Utilizar MediaCodec para H264 streaming

Actualmente estoy intentando usar Android como punto final de Skype. En esta etapa, necesito codificar el vídeo en H.264 (puesto que es el único formato apoyado por Skype) y encapsularlo con RTP para hacer funcionar el streaming.

Aparentemente el MediaRecorder no es muy adecuado para esto por varias razones. Uno es porque agrega los encabezados MP4 o 3GP después de que haya terminado. Otra razón es que para reducir la latencia al mínimo, la aceleración del hardware puede resultar útil. Es por eso que me gustaría hacer uso de las recientes adiciones de bajo nivel al framework, siendo MediaCodec , MediaExtractor , etc.

Por el momento, planeo trabajar de la siguiente manera. La cámara escribe su vídeo en un búfer. MediaCodec codifica el vídeo con H264 y escribe el resultado en otro búfer. Este búfer es leído por un encapsulador RTP, que envía los datos de flujo al servidor. Aquí está mi primera pregunta: ¿este plan le parece factible?

Ahora ya estoy atascado con el primer paso. Dado que toda la documentación en Internet sobre el uso de la cámara hace uso de MediaRecorder , no puedo encontrar una manera de almacenar sus datos sin procesar en un búfer antes de la codificación. ¿ AddCallbackBuffer es adecuado para esto? ¿Alguien tiene un enlace con un ejemplo?

A continuación, no puedo encontrar una gran cantidad de documentación sobre MediaCodec (ya que es bastante nuevo). ¿Alguien que tiene un tutorial sólido?

Por último: ¿alguna recomendación sobre las bibliotecas RTP?

¡Muchas gracias por adelantado!

ACTUALIZAR
Finalmente pude crear paquetes adecuados de RTP de los marcos h264. Esto es lo que tienes que tener en cuenta (en realidad es bastante simple):

El codificador crea cabeceras NAL para cada trama. Pero devuelve cada fotograma como h264 bytestream . Esto significa que cada trama comienza con tres 0 bytes y un 1 byte. Todo lo que tienes que hacer es quitar los prefijos de inicio, y poner el marco en un paquete RTP (o dividirlos utilizando FU-As).

Ahora a sus preguntas:

No puedo encontrar una manera de almacenar sus datos sin procesar en un búfer antes de codificar. ¿AddCallbackBuffer es adecuado para esto?

Debería usar camera.setPreviewCallback (…) y agregar cada fotograma al codificador.

No puedo encontrar mucha documentación sobre MediaCodec (ya que es bastante nuevo). ¿Alguien que tiene un tutorial sólido?

Esta debe ser una buena introducción sobre cómo funciona el MediaCodec. http://dpsm.wordpress.com/2012/07/28/android-mediacodec-decoded/

Por último: ¿alguna recomendación sobre las bibliotecas RTP?

Estoy usando jlibrtp que consigue el trabajo hecho.

Todavía no sé nada sobre MediaCodec o MediaExtractor, pero estoy bastante familiarizado con MediaRecorder y he implementado con éxito un servidor RTSP, basado en SpyDroid, que captura la salida H264 / AMRNB de MediaRecorder. La idea básica es que el código crea un par de socket local y utiliza setOutputFile del MediaRecorder para escribir la salida a uno de los sockets del par. A continuación, el programa lee el flujo de vídeo o de audio del otro socket, lo analiza en paquetes y, a continuación, envuelve cada paquete en uno o más paquetes RTP que se envían a través de UDP.

Es cierto que MediaRecorder agrega los encabezados MOOV después de que haya terminado, pero eso no es un problema si está sirviendo video H264 en formato RTP. Básicamente, hay un encabezado "mdat" al inicio de la secuencia de vídeo. Tiene 4 bytes para la longitud del encabezado, seguido por los 4 bytes "mdat". Lea la longitud para averiguar cuánto tiempo es el encabezado, verifique que es el encabezado de mdat y omita el resto de los datos de encabezado. A partir de ahí, se obtiene una corriente de unidades NAL, que comienzan con 4 bytes para la longitud de la unidad. Las unidades NAL pequeñas se pueden enviar en un solo paquete RTP, y las unidades más grandes se dividen en paquetes FU. Para RTSP, también debe servir un encabezado SDP que describa el flujo. SpyDroid calcula la información en el encabezado SDP escribiendo una película muy corta en un archivo, y luego lee este archivo para extraer el encabezado MOOV desde el final. Mi aplicación siempre utiliza el mismo tamaño, formato y velocidad de bits, por lo que sólo sirve una cadena estática:

 public static final String SDP_STRING = "m=video 5006 RTP/AVP 96\n" + "b=RR:0\n" + "a=rtpmap:96 H264/90000\n" + "a=fmtp:96 packetization-mode=1;profile-level-id=428028;sprop-parameter-sets=Z0KAKJWgKA9E,aM48gA==;\n" + "a=control:trackID=0\n" + "m=audio 5004 RTP/AVP 96\n" + "b=AS:128\n" + "b=RR:0\n" + "a=rtpmap:96 AMR/8000\n" + "a=fmtp:96 octet-align=1;\n" + "a=control:trackID=1\n"; 

Ese es mi encabezado para 640x480x10fps, vídeo H264, con audio 8000/16/1 AMRNB.

Una cosa que puedo advertirle acerca de: Si está utilizando MediaRecorder, su devolución de llamada de vista previa nunca se llamará. Que sólo funciona en modo de cámara, no cuando se está grabando vídeo. No he podido encontrar ninguna manera de conseguir el acceso a la imagen de la inspección previo en el formato sin comprimir mientras que el vídeo está grabando.

Recomiendo mirar por encima del código de SpyDroid. Se necesita un poco de excavación alrededor, pero apuesto a que lo que quieres está allí ya.

Lo que usted planea es definitivamente factible. Puede registrar un Camera.PreviewCallback que toma los datos de la imagen y los coloca en el MediaCodec. Se lee la salida y se envía como RTP. En general, es fácil, pero hay varios escollos como espacios de color indocumentados y diferentes comportamientos de MediaCodec en diferentes dispositivos, pero es definitivamente posible.

  • Cómo obtener el ID de video de YouTube, incluidos los parámetros
  • Transmisión en directo desde la aplicación de Android a Youtube
  • Problemas de sincronización de Android MediaPlayer
  • Transmisión de vídeo mediante RTSP: Android
  • Android Streaming Video - Necesita la relación de aspecto
  • programatically leer buffer de trama / dev / graphics / fb0 en android
  • Cómo usar android exoplayer
  • Silenciar un video en un VideoView
  • UDP Video Streaming en Android
  • Android Dev - 3rd Party Media Player SDK u otras opciones?
  • Tipo de video mime de Android HLS
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.