android ffmpeg h.264 rtsp decoding

¿Decodificación de la corriente Raw H264 en Android?



ffmpeg h.264 (3)

Desafortunadamente, no puedo proporcionar ningún código para esto, pero haré todo lo posible para explicarlo en función de cómo lo hice funcionar.

Así que esta es mi descripción general de cómo obtuve el video con codificación H.264 sin procesar para trabajar usando la clase MediaCodec ( http://developer.android.com/reference/android/media/MediaCodec.html ).

Usando el enlace de arriba hay un ejemplo de cómo configurar el decodificador y cómo usarlo, deberá configurarlo para decodificar H264 AVC.

El formato de H.264 es que está formado por NAL Units, cada uno comenzando con un prefijo de inicio de tres bytes con los valores 0x00, 0x00, 0x01 y cada unidad tiene un tipo diferente según el valor del 4to byte justo después de estos. 3 bytes iniciales Una unidad NAL NO ES un cuadro en el video, cada cuadro está compuesto por un número de Unidades NAL.

Básicamente, escribí un método que encuentra cada unidad individual y la pasa al decodificador (una unidad NAL es el prefijo inicial y cualquier byte allí después hasta el próximo prefijo inicial).

Ahora, si tiene la configuración del decodificador para decodificar H.264 AVC y tiene un InputBuffer desde el decodificador, entonces está listo para comenzar. Debe llenar este InputBuffer con una unidad NAL y pasarlo de nuevo al decodificador y continuar haciéndolo durante la duración de la transmisión. Pero, para que esto funcione, primero tuve que pasar el decodificador a una unidad NAL SPS (Sequence Parameter Set). Esta unidad tiene un valor de byte de 0x67 después del prefijo inicial (el 4º byte), en algunos dispositivos el decodificador se colgaría a menos que primero recibiera esta unidad. Básicamente, hasta que encuentre esta unidad, ignore todas las demás Unidades NAL y siga analizando la secuencia hasta que obtenga esta unidad, luego puede pasar todas las demás unidades al decodificador.

Algunos dispositivos no necesitaban el SPS primero y otros sí, pero es mejor que lo pases primero.

Ahora, si tenía una superficie que pasó al decodificador cuando la configuró, una vez que obtiene suficientes unidades NAL para un cuadro, debería mostrarla en la superficie.

Tengo un proyecto en el que me pidieron que muestre una transmisión de video en Android, la transmisión es H.264 en crudo y me estoy conectando a un servidor y recibiré una transmisión de bytes desde el servidor.

Básicamente, me pregunto si hay alguna forma de enviar bytes sin formato a un decodificador en Android y mostrarlo en una superficie.

He logrado decodificar H264 envuelto en un contenedor mp4 utilizando la nueva API MediaCodec y MediaExtractor en Android 4.1. Desafortunadamente, no he encontrado una forma de decodificar un archivo H264 sin procesar con estas API.

Entiendo que una forma es compilar y usar FFmpeg, pero prefiero utilizar un método integrado que pueda usar la aceleración HW. También entiendo que la transmisión RTSP es compatible con Android, pero esta no es una opción. La versión de Android no es un problema.


Estos son los recursos que he encontrado útiles en un proyecto similar:

  1. Este video ha sido muy útil para comprender cómo MediaCodec maneja las transmisiones h.264 en bruto a un alto nivel.
  2. Este hilo entra en un poco más de detalle en cuanto al manejo de los NALU SPS / PPS específicamente. Como se mencionó anteriormente, debe separar las unidades NAL individuales utilizando el prefijo de inicio, y luego entregar los datos restantes a MediaCodec.
  3. Este repositorio (libstreaming) es un gran ejemplo de decodificación de una transmisión H264 en Android utilizando RTSP / RTP para la transmisión.

Puede descargar el H.264 sin procesar del servidor, luego ofrecerlo a través de un servidor HTTP local que se ejecuta en el teléfono y luego dejar que VLC para Android reproduzca desde ese servidor HTTP. Debería usar el esquema http / h264: // de VLC para forzar el demuxer a H.264 sin procesar (si no fuerza el demuxer VLC puede no ser capaz de reconocer la transmisión, incluso cuando el tipo MIME devuelto por el servidor HTTP es establecer correctamente). Ver

https://github.com/rauljim/tgs-android/blob/integrate_record/src/com/tudelft/triblerdroid/first/VideoPlayerActivity.java#L211

para un ejemplo sobre cómo crear un Intento que lanzará VLC.

Nota: Raw H.264 aparentemente no tiene información de sincronización, por lo que VLC se reproducirá lo más rápido posible. Primero incrustarlo en MPEGTS será mejor. No he encontrado una lib de Android que lo haga aún.