android h.264 stagefright mediacodec transport-stream

android - Cómo usar MediaCodec sin MediaExtractor para H264



h.264 stagefright (2)

Para su última pregunta, es decir, cómo puede obtener los valores de SPS y PPS , debe tener un mecanismo para leer lo mismo del archivo.

Si tiene un archivo de elementary stream , deberá analizar el archivo, identificar los encabezados de NALU y extraer el contenido.

Si tiene container formato de container , deberá tener un mecanismo para leer el file format de file format del tipo de container y extraer la información.

Si tiene una entrada de streaming , entonces puede recibir el contenido de la información SDP entrante.

En cuanto a su código actual, recomendaría concatenar tanto SPS como PPS en un búfer y proporcionar lo mismo al codec subyacente como se muestra a continuación.

byte[] csd_info = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108, 0, 0, 0, 1, 104, -18, 60, -128 }; format.setByteBuffer("csd-0", ByteBuffer.wrap(csd_info)); format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080); format.setInteger("durationUs", 63446722);

Necesito usar MediaCodec sin el MediaExtractor y estoy leyendo el archivo usando FileInputStream. Actualmente no está funcionando, está mostrando una imagen revuelta verdosa en la pantalla.

Este es el código fuente completo:

FileInputStream in = new FileInputStream("/sdcard/sample.ts"); String mimeType = "video/avc"; MediaCodec decoder = MediaCodec.createDecoderByType(mimeType); MediaFormat format = MediaFormat.createVideoFormat(mimeType, 1920, 1080); byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 }; byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 }; format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps)); format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps)); format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080); format.setInteger("durationUs", 63446722); decoder.configure(format, surface, null, 0); decoder.start(); ByteBuffer[] inputBuffers = decoder.getInputBuffers(); ByteBuffer[] outputBuffers = decoder.getOutputBuffers(); BufferInfo info = new BufferInfo(); boolean isEOS = false; long startMs = System.currentTimeMillis(); while (!Thread.interrupted()) { if (!isEOS) { int inIndex = decoder.dequeueInputBuffer(1000); if (inIndex >= 0) { byte buffer2[] = new byte[18800 * 8 * 8 * 8]; ByteBuffer buffer = inputBuffers[inIndex]; int sampleSize; sampleSize = in.read(buffer2, 0, 18800 * 4); buffer.clear(); buffer.put(buffer2, 0, sampleSize); buffer.clear(); if (sampleSize < 0) { decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); isEOS = true; } else { decoder.queueInputBuffer(inIndex, 0, sampleSize, 0, 0); } } } int outIndex = decoder.dequeueOutputBuffer(info, 10000); switch (outIndex) { case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED"); outputBuffers = decoder.getOutputBuffers(); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: Log.d("DecodeActivity", "New format " + decoder.getOutputFormat()); break; case MediaCodec.INFO_TRY_AGAIN_LATER: Log.d("DecodeActivity", "dequeueOutputBuffer timed out! " + info); break; default: ByteBuffer buffer = outputBuffers[outIndex]; Log.v("DecodeActivity", "We can''t use this buffer but render it due to the API limit, " + buffer); while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); break; } } decoder.releaseOutputBuffer(outIndex, true); break; } if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM"); break; } } decoder.stop(); decoder.release();

Si uso el MediaExtractor, todo funciona bien. Obtuve los valores de SPS / PPS mirando el MediaFormat cuando uso MediaExtractor. Si elimino la sección de abajo, nada se muestra en la pantalla.

byte[] header_sps = { 0, 0, 0, 1, 103, 100, 0, 40, -84, 52, -59, 1, -32, 17, 31, 120, 11, 80, 16, 16, 31, 0, 0, 3, 3, -23, 0, 0, -22, 96, -108 }; byte[] header_pps = { 0, 0, 0, 1, 104, -18, 60, -128 }; format.setByteBuffer("csd-0", ByteBuffer.wrap(header_sps)); format.setByteBuffer("csd-1", ByteBuffer.wrap(header_pps)); format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 1920 * 1080); format.setInteger("durationUs", 63446722);

¿Qué me estoy perdiendo? ¿Cómo puedo obtener los valores de SPS / PPS programáticamente sin MediaExtractor?


Supongo que está leyendo un flujo elemental H.264 sin formato y no un archivo MP4.

Parece que estás suministrando bloques de datos de tamaño fijo al decodificador. Eso no funciona. Es necesario poner una sola unidad de acceso en cada búfer.