public final class

FlacSeekTableSeekMap

extends java.lang.Object

implements SeekMap

 java.lang.Object

↳androidx.media3.extractor.FlacSeekTableSeekMap

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-extractor', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-extractor
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-extractor:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

A SeekMap implementation for FLAC streams that contain a seek table.

Summary

Constructors
publicFlacSeekTableSeekMap(FlacStreamMetadata flacStreamMetadata, long firstFrameOffset)

Creates a seek map from the FLAC stream seek table.

Methods
public longgetDurationUs()

public SeekMap.SeekPointsgetSeekPoints(long timeUs)

public booleanisSeekable()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructors

public FlacSeekTableSeekMap(FlacStreamMetadata flacStreamMetadata, long firstFrameOffset)

Creates a seek map from the FLAC stream seek table.

Parameters:

flacStreamMetadata: The stream metadata.
firstFrameOffset: The byte offset of the first frame in the stream.

Methods

public boolean isSeekable()

public long getDurationUs()

public SeekMap.SeekPoints getSeekPoints(long timeUs)

Source

/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package androidx.media3.extractor;

import androidx.media3.common.C;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;

/**
 * A {@link SeekMap} implementation for FLAC streams that contain a <a
 * href="https://xiph.org/flac/format.html#metadata_block_seektable">seek table</a>.
 */
@UnstableApi
public final class FlacSeekTableSeekMap implements SeekMap {

  private final FlacStreamMetadata flacStreamMetadata;
  private final long firstFrameOffset;

  /**
   * Creates a seek map from the FLAC stream seek table.
   *
   * @param flacStreamMetadata The stream metadata.
   * @param firstFrameOffset The byte offset of the first frame in the stream.
   */
  public FlacSeekTableSeekMap(FlacStreamMetadata flacStreamMetadata, long firstFrameOffset) {
    this.flacStreamMetadata = flacStreamMetadata;
    this.firstFrameOffset = firstFrameOffset;
  }

  @Override
  public boolean isSeekable() {
    return true;
  }

  @Override
  public long getDurationUs() {
    return flacStreamMetadata.getDurationUs();
  }

  @Override
  public SeekPoints getSeekPoints(long timeUs) {
    Assertions.checkStateNotNull(flacStreamMetadata.seekTable);
    long[] pointSampleNumbers = flacStreamMetadata.seekTable.pointSampleNumbers;
    long[] pointOffsets = flacStreamMetadata.seekTable.pointOffsets;

    long targetSampleNumber = flacStreamMetadata.getSampleNumber(timeUs);
    int index =
        Util.binarySearchFloor(
            pointSampleNumbers,
            targetSampleNumber,
            /* inclusive= */ true,
            /* stayInBounds= */ false);

    long seekPointSampleNumber = index == -1 ? 0 : pointSampleNumbers[index];
    long seekPointOffsetFromFirstFrame = index == -1 ? 0 : pointOffsets[index];
    SeekPoint seekPoint = getSeekPoint(seekPointSampleNumber, seekPointOffsetFromFirstFrame);
    if (seekPoint.timeUs == timeUs || index == pointSampleNumbers.length - 1) {
      return new SeekPoints(seekPoint);
    } else {
      SeekPoint secondSeekPoint =
          getSeekPoint(pointSampleNumbers[index + 1], pointOffsets[index + 1]);
      return new SeekPoints(seekPoint, secondSeekPoint);
    }
  }

  private SeekPoint getSeekPoint(long sampleNumber, long offsetFromFirstFrame) {
    long seekTimeUs = sampleNumber * C.MICROS_PER_SECOND / flacStreamMetadata.sampleRate;
    long seekPosition = firstFrameOffset + offsetFromFirstFrame;
    return new SeekPoint(seekTimeUs, seekPosition);
  }
}