MediaCodec y cámara: los espacios de colores no coinciden

He estado tratando de hacer que la codificación H264 funcione con la entrada capturada por la cámara en una tableta Android utilizando el nuevo nivel bajoMediaCodec. He tenido algunas dificultades con esto, ya que el MediaCodecAPI está mal documentado, pero por fin he conseguido que algo funcione.

Estoy configurando la cámara de la siguiente manera:

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

Para la parte de codificación, estoy creando una instancia del objeto MediaCodec de la siguiente manera:

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

El objetivo final es crear un flujo RTP (y corresponder con Skype), pero hasta ahora solo estoy transmitiendo el H264 en bruto directamente a mi escritorio. Allí utilizo el siguiente GStreamer-pipeline para mostrar el resultado:

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

Todo funciona bien, excepto los colores. Necesito configurar 2 formatos de color en la computadora: uno para la vista previa de la cámara (línea etiquetada con<1>) y uno para el objeto MediaCodec (etiquetado con<2>)

Determinar los valores aceptables para las líneas.<1> solíaparameters.getSupportedPreviewFormats(). Por esto, sé que los únicos formatos soportados en la cámara sonImageFormat.NV21 yImageFormat.YV2.

por<2>, Recuperé elMediaCodecInfo.CodecCapabilities-objeto por tipovideo / avc, siendo los valores enteros 19 (correspondientes aMediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar y 2130708361 (que no corresponde con ningún valor deMediaCodecInfo.CodecCapabilities).

Cualquier otro valor que el anterior resulta en una caída.

La combinación de estos ajustes da diferentes resultados, que se muestran a continuación. Aquí está la captura de pantalla en Android (es decir, los colores "reales"): Aquí están los resultados mostrados por Gstreamer:

<1> = NV21,<2> = COLOR_FormatYUV420Planar

<1> = NV21,<2> = 2130708361

<1> = YV2,<2> = COLOR_FormatYUV420Planar

<1> = YV2,<2> = 2130708361

Como se puede ver, ninguno de estos son satisfactorios. El espacio de color YV2 parece el más prometedor, pero parece que el rojo (Cr) y el azul (Cb) están invertidos. El NV21 parece entrelazado, supongo (sin embargo, no soy un experto en este campo).

Dado que el propósito es comunicarse con Skype, asumo que no debería cambiar el decodificador (es decir, el comando Gstreamer), ¿verdad? ¿Esto se solucionará en Android? En caso afirmativo, ¿cómo? ¿O esto se puede resolver agregando cierta información de carga útil de RTP? ¿Alguna otra sugerencia?

Respuestas a la pregunta(4)

Su respuesta a la pregunta