Commit ed88f4f1 by kimvde Committed by kim-vde

Add possibility to update ExtractorOutput duration

PiperOrigin-RevId: 292912511
parent de387723
...@@ -653,8 +653,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -653,8 +653,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override @Override
public void seekMap(SeekMap seekMap) { public void seekMap(SeekMap seekMap) {
this.seekMap = icyHeaders == null ? seekMap : new Unseekable(/* durationUs */ C.TIME_UNSET); handler.post(() -> setSeekMap(seekMap));
handler.post(maybeFinishPrepareRunnable);
} }
// Icy metadata. Called by the loading thread. // Icy metadata. Called by the loading thread.
...@@ -691,6 +690,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -691,6 +690,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return trackOutput; return trackOutput;
} }
private void setSeekMap(SeekMap seekMap) {
this.seekMap = icyHeaders == null ? seekMap : new Unseekable(/* durationUs */ C.TIME_UNSET);
if (preparedState == null) {
maybeFinishPrepare();
} else {
preparedState =
new PreparedState(seekMap, preparedState.tracks, preparedState.trackIsAudioVideoFlags);
}
durationUs = seekMap.getDurationUs();
isLive = length == C.LENGTH_UNSET && seekMap.getDurationUs() == C.TIME_UNSET;
dataType = isLive ? C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE : C.DATA_TYPE_MEDIA;
listener.onSourceInfoRefreshed(durationUs, seekMap.isSeekable(), isLive);
}
private void maybeFinishPrepare() { private void maybeFinishPrepare() {
SeekMap seekMap = this.seekMap; SeekMap seekMap = this.seekMap;
if (released || preparedState != null || !sampleQueuesBuilt || seekMap == null) { if (released || preparedState != null || !sampleQueuesBuilt || seekMap == null) {
...@@ -705,7 +718,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -705,7 +718,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
int trackCount = sampleQueues.length; int trackCount = sampleQueues.length;
TrackGroup[] trackArray = new TrackGroup[trackCount]; TrackGroup[] trackArray = new TrackGroup[trackCount];
boolean[] trackIsAudioVideoFlags = new boolean[trackCount]; boolean[] trackIsAudioVideoFlags = new boolean[trackCount];
durationUs = seekMap.getDurationUs();
for (int i = 0; i < trackCount; i++) { for (int i = 0; i < trackCount; i++) {
Format trackFormat = sampleQueues[i].getUpstreamFormat(); Format trackFormat = sampleQueues[i].getUpstreamFormat();
String mimeType = trackFormat.sampleMimeType; String mimeType = trackFormat.sampleMimeType;
...@@ -731,11 +743,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -731,11 +743,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
trackArray[i] = new TrackGroup(trackFormat); trackArray[i] = new TrackGroup(trackFormat);
} }
isLive = length == C.LENGTH_UNSET && seekMap.getDurationUs() == C.TIME_UNSET;
dataType = isLive ? C.DATA_TYPE_MEDIA_PROGRESSIVE_LIVE : C.DATA_TYPE_MEDIA;
preparedState = preparedState =
new PreparedState(seekMap, new TrackGroupArray(trackArray), trackIsAudioVideoFlags); new PreparedState(seekMap, new TrackGroupArray(trackArray), trackIsAudioVideoFlags);
listener.onSourceInfoRefreshed(durationUs, seekMap.isSeekable(), isLive);
Assertions.checkNotNull(callback).onPrepared(this); Assertions.checkNotNull(callback).onPrepared(this);
} }
......
...@@ -27,11 +27,12 @@ import com.google.android.exoplayer2.util.Util; ...@@ -27,11 +27,12 @@ import com.google.android.exoplayer2.util.Util;
@VisibleForTesting @VisibleForTesting
/* package */ static final long MIN_TIME_BETWEEN_POINTS_US = C.MICROS_PER_SECOND / 10; /* package */ static final long MIN_TIME_BETWEEN_POINTS_US = C.MICROS_PER_SECOND / 10;
private final long durationUs;
private final long dataEndPosition; private final long dataEndPosition;
private final LongArray timesUs; private final LongArray timesUs;
private final LongArray positions; private final LongArray positions;
private long durationUs;
public IndexSeeker(long durationUs, long dataStartPosition, long dataEndPosition) { public IndexSeeker(long durationUs, long dataStartPosition, long dataEndPosition) {
this.durationUs = durationUs; this.durationUs = durationUs;
this.dataEndPosition = dataEndPosition; this.dataEndPosition = dataEndPosition;
...@@ -104,4 +105,8 @@ import com.google.android.exoplayer2.util.Util; ...@@ -104,4 +105,8 @@ import com.google.android.exoplayer2.util.Util;
long lastIndexedTimeUs = timesUs.get(timesUs.size() - 1); long lastIndexedTimeUs = timesUs.get(timesUs.size() - 1);
return timeUs - lastIndexedTimeUs < MIN_TIME_BETWEEN_POINTS_US; return timeUs - lastIndexedTimeUs < MIN_TIME_BETWEEN_POINTS_US;
} }
/* package */ void setDurationUs(long durationUs) {
this.durationUs = durationUs;
}
} }
...@@ -216,6 +216,31 @@ public final class Mp3Extractor implements Extractor { ...@@ -216,6 +216,31 @@ public final class Mp3Extractor implements Extractor {
public int read(ExtractorInput input, PositionHolder seekPosition) public int read(ExtractorInput input, PositionHolder seekPosition)
throws IOException, InterruptedException { throws IOException, InterruptedException {
assertInitialized(); assertInitialized();
int readResult = readInternal(input);
if (readResult == RESULT_END_OF_INPUT && seeker instanceof IndexSeeker) {
// Duration is exact when index seeker is used.
long durationUs = computeTimeUs(samplesRead);
if (seeker.getDurationUs() != durationUs) {
((IndexSeeker) seeker).setDurationUs(durationUs);
extractorOutput.seekMap(seeker);
}
}
return readResult;
}
/**
* Disables the extractor from being able to seek through the media.
*
* <p>Please note that this needs to be called before {@link #read}.
*/
public void disableSeeking() {
disableSeeking = true;
}
// Internal methods.
@RequiresNonNull({"extractorOutput", "currentTrackOutput", "realTrackOutput"})
private int readInternal(ExtractorInput input) throws IOException, InterruptedException {
if (synchronizedHeaderData == 0) { if (synchronizedHeaderData == 0) {
try { try {
synchronize(input, false); synchronize(input, false);
...@@ -254,17 +279,6 @@ public final class Mp3Extractor implements Extractor { ...@@ -254,17 +279,6 @@ public final class Mp3Extractor implements Extractor {
return readSample(input); return readSample(input);
} }
/**
* Disables the extractor from being able to seek through the media.
*
* <p>Please note that this needs to be called before {@link #read}.
*/
public void disableSeeking() {
disableSeeking = true;
}
// Internal methods.
@RequiresNonNull({"currentTrackOutput", "realTrackOutput", "seeker"}) @RequiresNonNull({"currentTrackOutput", "realTrackOutput", "seeker"})
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
if (sampleBytesRemaining == 0) { if (sampleBytesRemaining == 0) {
......
seekMap: seekMap:
isSeekable = true isSeekable = true
duration = UNSET TIME duration = 2808000
getPosition(0) = [[timeUs=0, position=224]] getPosition(0) = [[timeUs=0, position=224]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
......
seekMap: seekMap:
isSeekable = true isSeekable = true
duration = UNSET TIME duration = 2808000
getPosition(0) = [[timeUs=0, position=224]] getPosition(0) = [[timeUs=0, position=224]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
......
seekMap: seekMap:
isSeekable = true isSeekable = true
duration = UNSET TIME duration = 2808000
getPosition(0) = [[timeUs=0, position=224]] getPosition(0) = [[timeUs=0, position=224]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
......
seekMap: seekMap:
isSeekable = true isSeekable = true
duration = UNSET TIME duration = 2808000
getPosition(0) = [[timeUs=0, position=224]] getPosition(0) = [[timeUs=0, position=224]]
numberOfTracks = 1 numberOfTracks = 1
track 0: track 0:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment