Decodificación h264 ByteStream en Android

Quiero decodificar y mostrar un flujo de bytes de vídeo h264 sin procesar en Android y, por lo tanto, estoy utilizando las clases de MediaCodec/Format . Adquiero los datos del marco vía Udp de un servidor. Pero, por desgracia, no se muestra nada en este momento.

Esto es lo que tengo hasta ahora.

Inicialización de la clase MediaCodec:

 codec = MediaCodec.createDecoderByType("video/avc"); MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, "video/avc"); format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 100000); format.setInteger(MediaFormat.KEY_WIDTH, 800); format.setInteger(MediaFormat.KEY_HEIGHT, 600); format.setInteger("max-width", 800); format.setInteger("max-height", 600); format.setInteger("push-blank-buffers-on-shutdown", 1); codec.configure(format, surface, null, 0); 

Uso del Decodificador:

 int inIndex = codec.dequeueInputBuffer(10000); if(inIndex >= 0) { ByteBuffer inputBuffer = codecInputBuffers[inIndex]; inputBuffer.clear(); inputBuffer.put(frameData); codec.queueInputBuffer(inIndex, 0, frameSize, 33, 0); } int outIndex = codec.dequeueOutputBuffer(null, 10000); switch(outIndex) { case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: codecOutputBuffers = codec.getOutputBuffers(); System.out.println("OB Changed"); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: System.out.println("OF Changed"); break; case MediaCodec.INFO_TRY_AGAIN_LATER: System.out.println("l8r"); break; default: ByteBuffer buffer = codecOutputBuffers[outIndex]; codec.releaseOutputBuffer(outIndex, true); } 

El dispositivo en el que estoy probando este código es Google Nexus 5. Cuando ejecuto esto, el outIndex es igual a MediaCodec.INFO_TRY_AGAIN_LATER todo el tiempo.

He escrito previamente un cliente para los cuadernos, que trabaja muy bien, así que supongo que la corriente de h264 del servidor debe ser ACEPTABLE.

Gracias por tu ayuda

Editar: En caso de que alguien está encontrando el mismo problema, la enmienda propuesta (1) de fadden resuelto el problema. He corregido el código anterior. Está funcionando ahora. Otro error de mi ejemplo mostrado era, que usted no puede pasar null a .dequeueOutputBuffers (…) ;. Tienes que hacer algo como

  BufferInfo buffInfo = new MediaCodec.BufferInfo(); int outIndex = codec.dequeueOutputBuffer(buffInfo, 10000); 

Incluso si no estás interessted en ella. 😉

Veo algunos problemas …

(1) Está intentando reemplazar un búfer en la matriz de búfer de entrada. MediaCodec no funciona de esta manera – el marco proporciona los búferes, y se copian los datos en ellos. La idea es que al permitir que el marco de trabajo realice la asignación, puede evitar copiar los datos posteriormente.

Necesita obtener la matriz de búferes de entrada de decoder.getInputBuffers() , y usarlos. Asegúrese de clear() el ByteBuffer para restablecer la posición y limitar cada vez.

(2) Estás escribiendo un solo paquete de datos y esperando un marco de datos de salida. En la práctica, es posible que deba proporcionar varios almacenamientos intermedios de datos antes de que se genere el primer marco. Vea este post como ejemplo. En algunos perfiles, el codificador puede reordenar las tramas, por lo que incluso después de que el decodificador comience a funcionar, no puede simplemente alimentar un marco y esperar a que los datos decodificados salten por el otro lado.

(3) El decodificador AVC necesita los datos SPS / PPS , que puede proporcionar a través de un búfer con el BUFFER_FLAG_CODEC_CONFIG indicadores BUFFER_FLAG_CODEC_CONFIG o añadiendo los datos con las teclas "csd-0" / "csd-1" al MediaFormat utilizando MediaFormat#setByteBuffer() . Ejemplos de ambos enfoques se pueden encontrar en EncodeDecodeTest .

Hay varios ejemplos de decodificación AVC en bigflake , pero la fuente de datos es el codificador de MediaCodec , por lo que generalmente obtienen el punto # 3 de forma gratuita.

Esta publicación puede ser útil para usted.

Para visualizar los marcos, puede ver diferentes enfoques en Grafika (que generalmente funciona con archivos .mp4, por lo que la implementación de codificar / decodificar no es tan relevante).

  • YouTubeAndroidPlayerAPI no puede reproducir algunos videos
  • El teléfono giratorio reinicia el video en android
  • Android MediaPlayer parpadea al reproducir vídeos en Android 4.2.2
  • Capturar vídeo con proporción de aspecto 1: 1 en Android
  • En Android, usando exoplayer, ¿cómo rellenar surfaceview con un video que no tiene la misma relación de aspecto con el dispositivo?
  • Resample / upsample sonidos de 8Khz a 48Khz (Java / Android)
  • Video vía phonegap en android
  • Cómo fusionar archivos de audio y video en Android
  • Reproducción de un video local de aplicación (.mp4) en una vista web
  • Corregir archivo 3GP después de la transmisión desde Android Media Recorder
  • Reproducir vídeo Mp4 desde el servidor android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.