MediaCodec and Camera: przestrzenie kolorów się nie zgadzają
Starałem się, aby kodowanie H264 działało z wejściem przechwyconym przez kamerę na tablecie z Androidem przy użyciu nowego niskiego poziomuMediaCodec. Przeżyłem z tym pewne trudności, ponieważ MediaCodecAPI jest słabo udokumentowany, ale w końcu mam coś do roboty.
Konfiguruję kamerę w następujący sposób:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewFormat(ImageFormat.YV12); // <1>
parameters.setPreviewFpsRange(4000,60000);
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
Dla części kodującej tworzę instancję obiektu MediaCodec w następujący sposób:
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();
Ostatecznym celem jest stworzenie strumienia RTP (i korespondowanie ze Skype), ale jak dotąd przesyłam strumieniowo surowy H264 bezpośrednio na mój pulpit. Korzystam z następującego potoku GStreamer, aby pokazać wynik:
gst-launch udpsrc port=5555 ! video/x-h264,width=640,height=480,framerate=15/1 ! ffdec_h264 ! autovideosink
Wszystko działa dobrze, z wyjątkiem kolorów. Muszę ustawić 2 formaty kolorów w komputerze: jeden dla podglądu kamery (linia oznaczona za pomocą<1>
) i jeden dla obiektu MediaCodec (oznaczonego tagiem<2>
)
Aby określić dopuszczalne wartości dla linii<1>
użyłemparameters.getSupportedPreviewFormats()
. Z tego wiem, że jedynymi obsługiwanymi formatami w aparacie sąImageFormat.NV21 iImageFormat.YV2.
Dla<2>
, OdzyskałemMediaCodecInfo.CodecCapabilities-obiekt dla typuwideo / avc, będące wartościami całkowitymi 19 (odpowiadająceMediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar i 2130708361 (co nie odpowiada żadnej wartościMediaCodecInfo.CodecCapabilities).
Każda inna wartość niż powyższa powoduje awarię.
Połączenie tych ustawień daje różne wyniki, które pokażę poniżej. Oto zrzut ekranu na Androida (tzn. „Prawdziwe” kolory): Oto wyniki pokazane przez Gstreamer:
<1>
= NV21,<2>
= COLOR_FormatYUV420Planar
<1>
= NV21,<2>
= 2130708361
<1>
= YV2,<2>
= COLOR_FormatYUV420Planar
<1>
= YV2,<2>
= 2130708361
Jak widać, żaden z nich nie jest zadowalający. Przestrzeń kolorów YV2 wygląda najbardziej obiecująco, ale wygląda na to, że czerwony (Cr) i niebieski (Cb) są odwrócone. Wygląda na to, że NV21 przeplata się (jednak nie jestem ekspertem w tej dziedzinie).
Ponieważ celem jest komunikowanie się ze Skype, zakładam, że nie powinienem zmieniać dekodera (tj. Polecenia Gstreamer), prawda? Czy to ma być rozwiązane w Androidzie, a jeśli tak, to w jaki sposób? Czy można to rozwiązać, dodając pewne informacje o ładunku RTP? Jakieś inne sugestie?