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.
- ¿Cómo acceder CORRECTAMENTE a datos de cámara LIVE en Android? ¿Cómo lo hace Skype?
- Cámara Android RTSP / RTP Stream?
- Cómo evitar el tiempo de espera de sesión en Android
- Cómo cambiar framerate cuando se utiliza clase MediaRecorder
- Problema con la transmisión de vídeo en android
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!
- ¿Cómo instalo Wowza Streaming Engine en Google Cloud?
- Android: Reproductor de video como la aplicación de Dailymotion
- Android 3.x / HLS cómo iniciar al final de la secuencia
- ANDROID: ¿Hay reproductor multimedia gratuito de terceros para streaming de vídeo MPEG4?
- Captura de la cámara IP Stream y publicar en mi sitio web
- Aplicación de chat de video para android
- Servidor para transmitir vídeo RTSP a Android
- Alternativas de comunicación en tiempo real nativas a WebRTC
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.
- Eclipse – Ningún proyecto visible en explorer
- MediaExtractor, MediaMetadataRetriever con archivo Raw / Asset