Cómo extraer muestras codificadas

La clase MediaExtractorCompat es un reemplazo directo para la clase MediaExtractor de la plataforma y proporciona APIs y funcionalidades idénticas. Facilita la extracción de datos multimedia demultiplexados, por lo general codificados, de una fuente de datos.

Separa un archivo contenedor (como MP4 o MKV) en sus pistas individuales, como video, audio y subtítulos. Luego, el extractor lee los datos codificados sin procesar de estos segmentos como una secuencia de muestras (por ejemplo, un solo fotograma de video comprimido o un bloque de audio) antes de que se envíen a un decodificador.

Los casos de uso comunes incluyen los siguientes:

  • Transcodificación o Remuxing: Lectura de muestras codificadas de una pista para cambiar el códec (transcodificación) o volver a empaquetar los flujos en un nuevo contenedor (remuxing), como convertir un archivo MP4 a MKV.
  • Extracción de contenido selectiva: Aislamiento y almacenamiento de una sola pista, como la extracción de una transmisión de audio de un archivo de video
  • Depuración de bajo nivel: Inspección de muestras individuales para depurar la corrupción de archivos, los problemas de marcas de tiempo o cualquier otro problema.
  • Creación de reproductores personalizados: Para casos de uso específicos, se puede crear un reproductor personalizado con control total sobre la canalización de medios.

Descripción general

En la siguiente muestra de código, se muestra cómo usar MediaExtractorCompat:

Kotlin

fun extractSamples(context: Context, mediaPath: String) {
    val extractor = MediaExtractorCompat(context)
    try {
        // 1. Setup the extractor
        extractor.setDataSource(mediaPath)

        // Find and select available tracks
        for (i in 0 until extractor.trackCount) {
            val format = extractor.getTrackFormat(i)
            extractor.selectTrack(i)
        }

        // 2. Process samples
        val buffer = ByteBuffer.allocate(10 * 1024 * 1024)
        while (true) {
            // Read an encoded sample into the buffer.
            val bytesRead = extractor.readSampleData(buffer, 0)
            if (bytesRead < 0) break

            // Access sample metadata
            val trackIndex = extractor.sampleTrackIndex
            val presentationTimeUs = extractor.sampleTime
            val sampleSize = extractor.sampleSize

            extractor.advance()
        }
    } catch (e: IOException) {
        throw RuntimeException(e)
    } finally {
        // 3. Release the extractor
        extractor.release()
    }
}

Java

public void extractSamples(Context context, String mediaPath) {
    MediaExtractorCompat extractor = new MediaExtractorCompat(context);
    try {
        // 1. Setup the extractor
        extractor.setDataSource(mediaPath);

        // Find and select available tracks
        for (int i = 0; i < extractor.getTrackCount(); i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            extractor.selectTrack(i);
        }

        // 2. Process samples
        ByteBuffer buffer = ByteBuffer.allocate(10 * 1024 * 1024);
        while (true) {
            // Read an encoded sample into the buffer.
            int bytesRead = extractor.readSampleData(buffer, 0);
            if (bytesRead < 0) break;

            // Access sample metadata
            int trackIndex = extractor.getSampleTrackIndex();
            long presentationTimeUs = extractor.getSampleTime();
            long sampleSize = extractor.getSampleSize();

            extractor.advance();
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        // 3. Release the extractor
        extractor.release();
    }
}