擷取編碼樣本

MediaExtractorCompat 類別可直接取代平台的 MediaExtractor 類別,並提供相同的 API 和功能。可從資料來源擷取解多工的媒體資料 (通常是經過編碼)。

這項工具會將容器檔案 (例如 MP4 或 MKV) 分成個別,例如影片、音訊和字幕。擷取器接著會從這些軌讀取原始的編碼資料,做為一連串的樣本 (例如單一壓縮影片影格或音訊區塊),然後傳送至解碼器。

常見用途包括:

  • 轉碼重新封裝:從音軌讀取編碼樣本,然後變更轉碼器 (轉碼) 或將串流重新封裝到新的容器 (重新封裝),例如將 MP4 檔案轉換為 MKV。
  • 選擇性內容擷取:分離並儲存單一音軌,例如從影片檔案擷取音訊串流。
  • 低階偵錯:檢查個別樣本,偵錯檔案毀損、時間戳記問題或其他問題。
  • 建構自訂播放器:針對特定用途,建構可完全控制媒體管道的自訂播放器。

總覽

以下程式碼範例說明如何使用 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) {
    handleFailure(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) {
    handleFailure(e);
  } finally {
    // 3. Release the extractor
    extractor.release();
  }
}