MediaCodec и Camera: цветовые пространства не совпадают
Я пытался заставить кодирование 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-pipe, чтобы показать результат:
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-объект для типавидео / АВК, являясь целочисленными значениями 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? Любое другое предложение?