인코딩된 샘플 추출

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