Я пытаюсь получить кодировку H264 для работы с вводом, захваченным камерой на планшете Android, с использованием нового низкоуровневого MediaCodec. С этим я столкнулся с некоторыми трудностями, поскольку MediaCodecAPI плохо документирован, но у меня наконец-то появилось что-то.
Я настраиваю камеру следующим образом:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewFormat(ImageFormat.YV12); // <1>
parameters.setPreviewFpsRange(4000,60000);
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
Для части кодирования я создаю объект MediaCodec следующим образом:
mediaCodec = MediaCodec.createEncoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 500000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); // <2>
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
Конечная цель - создать RTP-поток (и соответствовать Skype), но до сих пор я просто передавал необработанный H264 прямо на мой рабочий стол. Там я использую следующий конвейер GStreamer, чтобы показать результат:
gst-launch udpsrc port=5555 ! video/x-h264,width=640,height=480,framerate=15/1 ! ffdec_h264 ! autovideosink
Все работает хорошо, за исключением цветов. Мне нужно установить 2 цветовыхформата на компьютере: один для предварительного просмотра камеры (строка с тегами <1>
) и одна для объекта MediaCodec (с тегами <2>
)
Чтобы определить допустимые значения для строк <1>
, я использовал parameters.getSupportedPreviewFormats()
. Из этого я знаю, что только поддерживаемые форматы на камере ImageFormat.NV21 и ImageFormat.YV2.
В <2>
я получил MediaCodecInfo.CodecCapabilities -объект для типа video/avc, являющийся целыми значениями 19 (соответствует MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar и 2130708361 (который не соответствует ни одному значению MediaCodecInfo.CodecCapabilities).
Любое другое значение, чем приведенное выше, приводит к сбою.
Объединение этих настроек дает разные результаты, которые я покажу ниже. Вот скриншот на Android (т.е. "Настоящие" цвета): Вот результаты, показанные Gstreamer:
<1>
= NV21, <2>
= COLOR_FormatYUV420Planar
<1>
= NV21, <2>
= 2130708361
<1>
= YV2, <2>
= COLOR_FormatYUV420Planar
<1>
= YV2, <2>
= 2130708361
Как видно, ни одно из них не удовлетворяет. Цветовое пространство YV2 выглядит наиболее перспективным, но похоже, что красный (Cr) и синий (Cb) инвертированы. NV21 выглядит чересстрочным, я думаю (однако, я не эксперт в этой области).
Поскольку целью является общение со Skype, я предполагаю, что я не должен менять декодер (т.е. команду Gstreamer), правильно? Это нужно решить в Android, и если да: как? Или это можно решить, добавив определенную информацию полезной нагрузки RTP? Любое другое предложение?