Corregir archivo 3GP después de la transmisión desde Android Media Recorder

Estoy tratando de transmitir vídeo desde la cámara de Android a través de unix local socket y escribir archivo de corriente a sdcard. Todo funciona bien, excepto que el archivo no se puede reproducir con ningún reproductor. Es porque Android no llena algunas lagunas en el archivo porque socket no es buscable. Según tengo entendido, necesito hacer algunas modificaciones después de que la secuencia de video haya terminado. He leído varios artículos aquí , aquí y aquí , pero ninguno de ellos me ayudó. Estoy jugando con el editor hexadecimal para aprender a hacerlo manualmente, así que después será trivial hacer lo mismo en el código de Android.

Aquí está un ejemplo de archivo que se guardó de la secuencia: https://dl.dropbox.com/u/17510473/sample_not_playable.3gp

¿Puede alguien arreglar para que sea jugable y decir cómo lo hizo?

EDIT: borro el encabezado del archivo 3gp y escribo uno nuevo como sigue:

00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 00 00 00 

Luego encuentro la ubicación inicial de los átomos mdat y moov con el siguiente comando:

 grep -aobE "ftyp|mdat|moov" sample_not_playable.3gp 

Y me da la siguiente salida:

 4:ftyp 28:mdat 1414676:moov 

A continuación, haga 1414676 - 28 = 1,414,648 = 0x1595F8

Entonces escribo 0x1595F8 como 25-28 bytes, justo antes del átomo de mdat. Así que mi encabezado ahora se ve así:

 00 00 00 18 66 74 79 70 33 67 70 34 00 00 03 00 33 67 70 34 33 67 70 36 00 15 95 F8 

Y cuando intento jugarlo con mplayer consigo algún vídeo y salida audio dañados. He aquí una parte de la salida de mplayer:

 [amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file? [amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame [amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame [amrwb @ 0x7f72ad652380]Frame too small (33 bytes). Truncated file? [amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame [amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame [amrwb @ 0x7f72ad652380]Encountered a bad or corrupted frame A: 11.0 V: 1.4 AV: 9.650 ct: 0.023 0/ 0 10% 1% 1.6% 0 0 [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f72adeafc40]stream 1, offset 0x15e62b: partial file [h263 @ 0x7f72ad652380]Bad picture start code [h263 @ 0x7f72ad652380]header damaged Error while decoding frame! [h263 @ 0x7f72ad652380]Bad picture start code [h263 @ 0x7f72ad652380]header damaged Error while decoding frame! [h263 @ 0x7f72ad652380]Bad picture start code [h263 @ 0x7f72ad652380]header damaged Error while decoding frame! A: 11.1 V: 1.5 AV: 9.558 ct: 0.027 0/ 0 9% 1% 1.4% 0 0 [h263 @ 0x7f72ad652380]Bad picture start code [h263 @ 0x7f72ad652380]header damaged Error while decoding frame! 

¿Que estoy haciendo mal?

Lo que usted necesita entender es que mp4 no es un formato streamable en vivo . Por lo tanto no hay manera que usted será capaz de cortar de todos modos alrededor para que sea en directo streamable. La cabecera [moov atom] se escribe al final. Android crea una tabla en memoria de tamaños de trama y otros parámetros que luego escribe al principio del archivo al final de la grabación debido a que necesita la capacidad de búsqueda del manejador de archivo. [Que un socket no es]

Si está escribiendo contenido cifrado en el disco y desea hacerlo para que nadie pueda reproducir el archivo no tiene que cifrar todo el archivo. Sólo tiene que cifrar el encabezado y el archivo entero no puede reproducirse.

Si necesitas desesperadamente la codificación completa de archivos porque no estás convencido de mi anterior parámetro, entonces usa algo como ffmpeg para hacer la codificación. Modifíquelo le da salida cifrada sí mismo y la ahorra al disco duro otra vez – quita la pieza del zócalo otra vez.

No hay manera de que pueda hacer streaming en vivo de archivos mp4 en android. He visto toneladas de gente tratando en vano y si entiendes video / formatos no hay forma de que puedas hacerlo. Mp4 no está diseñado para transmisión en vivo. A menos que conozca los tamaños de su marco de antemano [que no lo hace] y la longitud exacta de la codificación [que probablemente no;] no se puede pre-crear el encabezado.

PD. Mp4 y 3gp son primos por lo que se aplica lo mismo.

Muchas personas confunden la transmisión en vivo con http pd y pseudo streaming. Live streaming significa que no tengo todo el archivo, que se está creando y también se está transmitiendo sobre la marcha. Http pd y pseudo streaming tienen lugar con archivos que están totalmente disponibles.

EDITAR:

Si su objetivo es cifrar el archivo grabado antes de almacenar en sdcard necesita soporte de codificador. Esto implica tener su propio codificador allí. Tome ffmpeg, recopilar cruzarlo a android. Escribe una pequeña interfaz JNI para tu aplicación. Consiga esto primero sin cifrado. Una vez hecho, donde ffmpeg escribe el flujo, agregue su módulo de cifrado. Lo mismo durante la decodificación. Y3ng creación. Esta es la manera más limpia de hacerlo.

EDIT 2: Vea spydroid para obtener algunas de las características para usted. Hay similares por ahí.

EDIT 3: Para mejorar la calidad de la respuesta estoy explicando una solución imperfecta también dada por otras respuestas:

Uno todavía puede transmitir el AV analizando el mp4 a medida que se genera y el envío de los flujos elementales por separado sobre un socket. El único problema que tendrá que afrontar es que no obtendrá una sincronización AV perfecta, ya que no conoce las marcas horarias exactas de la muestra AV. Sólo android sabe eso y escribe que en la cabecera mp4 al final. Así que no es bueno para ti. Usted tiene que estar haciendo una suposición sobre la tasa de muestreo perfecto de marcos de video y su audio tendrá que ser AMR para asumir 20ms paquetes. En otros casos de audio, empezarás a ver la deriva en largas tiradas [especialmente donde empiezas a tener escenas de alto movimiento]. Esto se debe a que cada paquete de audio generado no corresponde a una duración de tiempo fija [excepto para amr y otros codecs de voz]

En primer lugar, no es muy claro lo que está tratando de hacer.

¿Desea guardar un vídeo mediante programación en un archivo reproducible? Si es así, sólo tiene que usar descriptor de archivo en lugar de socket unix. Esta API de MediaRecord fue diseñada para trabajar con un archivo (no socket unix), precisamente por la razón de acceso aleatorio. Por lo tanto, mi primer consejo sería utilizar descriptor de archivo y obtendrá el archivo correcto al final de la grabación.

Puedes obtener ejemplos aquí: ¿Cómo puedo capturar una grabación de vídeo en Android?

En el caso, si usted está tratando de escribir una aplicación que transmite vídeo desde el dispositivo, tendrá que analizar el flujo en un realime, dividirlo por marcos y enviar marcos por separado. Y la parte más compleja es analizar el flujo (algunos códecs de vídeo, como el ejemplo H263 pueden ser analizados y otros no pueden ser, especialmente si los datos están entrelazados con el audio).

Creo que uno de estos dos proyectos implementa esta funcionalidad: http://sipdroid.org/ http://code.google.com/p/imsdroid/

  • InAppBrowser reproduce video de vimeo en el reproductor de video nativo automáticamente?
  • Reproducción de archivos .m3u8 a través de HTTPS en android 2.3
  • Se ha producido un error al cargar vídeo en html5 phonegap
  • Reproducir video en Android usando Xamarin
  • ¿Cómo puedo obtener los datos de ubicación de un video en Android?
  • La reproducción de vídeo proporciona pantalla en negro pero con sonido
  • Buffer de vídeo circular Android con sonido
  • Ver Android-Video en Pantalla Completa
  • Uso de JWplayer en Android para reproducir video en Phonegap
  • Reproducir video local en la vista web
  • Reproductor de vídeo en android (desarrollar)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.