MediaCodec e Camera: os espaços de cores não correspondem

Eu tenho tentado obter codificação H264 para trabalhar com entrada capturada pela câmera em um tablet Android usando o novo nível baixoMediaCodec. Eu passei por algumas dificuldades com isso, já que o MediaCodecAPI está mal documentado, mas eu consegui algo para trabalhar no passado.

Estou configurando a câmera da seguinte maneira:

        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewFormat(ImageFormat.YV12); // <1>
        parameters.setPreviewFpsRange(4000,60000);
        parameters.setPreviewSize(640, 480);            
        mCamera.setParameters(parameters);

Para a parte de codificação, estou instanciando o objeto MediaCodec da seguinte maneira:

    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();

O objetivo final é criar um fluxo RTP (e corresponder ao Skype), mas até agora só estou transmitindo o H264 bruto diretamente para o meu desktop. Lá eu uso o seguinte GStreamer-pipeline para mostrar o resultado:

gst-launch udpsrc port=5555 ! video/x-h264,width=640,height=480,framerate=15/1 ! ffdec_h264 ! autovideosink

Tudo funciona bem, exceto pelas cores. Preciso definir 2 formatos de cores no computador: um para a visualização da câmera (linha marcada com<1>) e um para o objeto MediaCodec (marcado com<2>)

Para determinar os valores aceitáveis ​​para as linhas<1> eu useiparameters.getSupportedPreviewFormats(). A partir disso, sei que os únicos formatos suportados na câmera sãoImageFormat.NV21 eImageFormat.YV2.

Para<2>, Eu recuperei oMediaCodecInfo.CodecCapabilities-objeto por tipovideo / avc, sendo os valores inteiros 19 (correspondentesMediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar e 2130708361 (que não corresponde a nenhum valor deMediaCodecInfo.CodecCapabilities).

Qualquer outro valor que não seja o acima, resulta em uma falha.

A combinação dessas configurações gera resultados diferentes, que serão mostrados abaixo. Aqui está a captura de tela no Android (ou seja, as cores "reais"): Aqui estão os resultados como mostrado por Gstreamer:

<1> = NV21,<2> = COLOR_FormatYUV420Planar

<1> = NV21,<2> = 2130708361

<1> = YV2<2> = COLOR_FormatYUV420Planar

<1> = YV2<2> = 2130708361

Como pode ser visto, nenhum destes é satisfatório. O espaço de cores YV2 parece o mais promissor, mas parece que vermelho (Cr) e azul (Cb) estão invertidos. O NV21 parece entrelaçado, eu acho (no entanto, eu não sou especialista neste campo).

Como o objetivo é comunicar com o Skype, suponho que não deva alterar o decodificador (ou seja, o comando Gstreamer), certo? Isso é para ser resolvido no Android e em caso afirmativo: como? Ou isso pode ser resolvido adicionando certas informações de carga útil do RTP? Alguma outra sugestão?

questionAnswers(4)

yourAnswerToTheQuestion