Извлечение закодированных образцов

Класс MediaExtractorCompat является прямой заменой классу MediaExtractor , используемому в платформе, и предоставляет идентичные API и функциональность. Он упрощает извлечение демультиплексированных, как правило, закодированных, медиаданных из источника данных.

Он разделяет файл-контейнер (например, MP4 или MKV) на отдельные дорожки , такие как видео, аудио и субтитры. Затем экстрактор считывает необработанные закодированные данные с этих дорожек в виде последовательности сэмплов (например, один сжатый видеокадр или блок аудио), прежде чем они будут отправлены декодеру.

К типичным сценариям использования относятся:

  • Транскодирование или ремуксирование : чтение закодированных сэмплов из трека для изменения кодека (транскодирование) или переупаковки потоков в новый контейнер (ремуксирование), например, преобразование файла MP4 в MKV.
  • Выборочное извлечение контента : выделение и сохранение отдельной дорожки, например, извлечение аудиопотока из видеофайла.
  • Низкоуровневая отладка : проверка отдельных образцов для выявления и устранения повреждений файлов, проблем с временными метками или других неполадок.
  • Создание пользовательских плееров : для нишевых сценариев использования — создание пользовательского плеера с полным контролем над потоком мультимедиа.

Обзор

Следующий пример кода демонстрирует использование MediaExtractorCompat :

Котлин

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();
    }
}