Make IndexSeekMap dynamic, allowing seek points to be added later

PiperOrigin-RevId: 660324829
This commit is contained in:
rohks 2024-08-07 03:55:31 -07:00 committed by Copybara-Service
parent 5dac58995a
commit a087f82fa8
2 changed files with 51 additions and 16 deletions

View File

@ -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.
*

View File

@ -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.
*
* <p>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);
}
}