diff --git a/libraries/common/src/main/java/androidx/media3/common/util/LongArray.java b/libraries/common/src/main/java/androidx/media3/common/util/LongArray.java index bca5d9bfb2..5a8a34cb52 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/LongArray.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/LongArray.java @@ -15,6 +15,8 @@ */ package androidx.media3.common.util; +import static java.lang.Math.max; + import java.util.Arrays; /** An append-only, auto-growing {@code long[]}. */ @@ -49,6 +51,20 @@ public final class LongArray { values[size++] = value; } + /** + * Appends all elements of the specified array. + * + * @param values The array whose elements are to be added. + */ + public void addAll(long[] values) { + int newSize = size + values.length; + if (newSize > this.values.length) { + this.values = Arrays.copyOf(this.values, max(this.values.length * 2, newSize)); + } + System.arraycopy(values, 0, this.values, size, values.length); + size = newSize; + } + /** * Returns the value at a specified index. * diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/IndexSeekMap.java b/libraries/extractor/src/main/java/androidx/media3/extractor/IndexSeekMap.java index de0bb5eff8..5068052d85 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/IndexSeekMap.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/IndexSeekMap.java @@ -19,6 +19,7 @@ package androidx.media3.extractor; import static androidx.media3.common.util.Assertions.checkArgument; import androidx.media3.common.C; +import androidx.media3.common.util.LongArray; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; @@ -29,10 +30,9 @@ import androidx.media3.common.util.Util; @UnstableApi public final class IndexSeekMap implements SeekMap { - private final long[] positions; - private final long[] timesUs; + private final LongArray positions; + private final LongArray timesUs; private final long durationUs; - private final boolean isSeekable; /** * Creates an instance. @@ -44,23 +44,24 @@ public final class IndexSeekMap implements SeekMap { public IndexSeekMap(long[] positions, long[] timesUs, long durationUs) { checkArgument(positions.length == timesUs.length); int length = timesUs.length; - isSeekable = length > 0; - if (isSeekable && timesUs[0] > 0) { + if (length > 0 && timesUs[0] > 0) { // Add (position = 0, timeUs = 0) as first entry. - this.positions = new long[length + 1]; - this.timesUs = new long[length + 1]; - System.arraycopy(positions, 0, this.positions, 1, length); - System.arraycopy(timesUs, 0, this.timesUs, 1, length); + this.positions = new LongArray(length + 1); + this.timesUs = new LongArray(length + 1); + this.positions.add(0L); + this.timesUs.add(0L); } else { - this.positions = positions; - this.timesUs = timesUs; + this.positions = new LongArray(length); + this.timesUs = new LongArray(length); } + this.positions.addAll(positions); + this.timesUs.addAll(timesUs); this.durationUs = durationUs; } @Override public boolean isSeekable() { - return isSeekable; + return timesUs.size() > 0; } @Override @@ -70,18 +71,36 @@ public final class IndexSeekMap implements SeekMap { @Override public SeekMap.SeekPoints getSeekPoints(long timeUs) { - if (!isSeekable) { + if (timesUs.size() == 0) { return new SeekMap.SeekPoints(SeekPoint.START); } int targetIndex = Util.binarySearchFloor(timesUs, timeUs, /* inclusive= */ true, /* stayInBounds= */ true); - SeekPoint leftSeekPoint = new SeekPoint(timesUs[targetIndex], positions[targetIndex]); - if (leftSeekPoint.timeUs == timeUs || targetIndex == timesUs.length - 1) { + SeekPoint leftSeekPoint = new SeekPoint(timesUs.get(targetIndex), positions.get(targetIndex)); + if (leftSeekPoint.timeUs == timeUs || targetIndex == timesUs.size() - 1) { return new SeekMap.SeekPoints(leftSeekPoint); } else { SeekPoint rightSeekPoint = - new SeekPoint(timesUs[targetIndex + 1], positions[targetIndex + 1]); + new SeekPoint(timesUs.get(targetIndex + 1), positions.get(targetIndex + 1)); return new SeekMap.SeekPoints(leftSeekPoint, rightSeekPoint); } } + + /** + * Adds a seek point to the index. + * + *

Seek points must be added in order. + * + * @param timeUs The time of the seek point in microseconds. + * @param position The position in the stream corresponding to the seek point, in bytes. + */ + public void addSeekPoint(long timeUs, long position) { + if (timesUs.size() == 0 && timeUs > 0) { + // Add (position = 0, timeUs = 0) as first entry. + this.positions.add(0L); + this.timesUs.add(0L); + } + positions.add(position); + timesUs.add(timeUs); + } }