Commit 66a5c96c by andrewlewis Committed by Oliver Woodman

Calculate ExtractorSampleSource duration if unknown (playlists #4).

When buffering playlist items after the currently-playing one,
continueBuffering should take a position that is negative because the playback
position is before the start of the source being buffered. This change makes
sure that ExtractorSampleSources always have a known duration when they are
fully buffered, which means that the correct (negative) source-relative
position can be calculated.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=124949409
parent e6267cd2
...@@ -37,7 +37,10 @@ public interface SampleSource { ...@@ -37,7 +37,10 @@ public interface SampleSource {
boolean prepare(long positionUs) throws IOException; boolean prepare(long positionUs) throws IOException;
/** /**
* Returns the duration of the source. * Returns the duration of the source in microseconds, or {@link C#UNSET_TIME_US} if not known.
* <p>
* If {@link #getBufferedPositionUs()} returns {@link C#END_OF_SOURCE_US}, the duration is
* guaranteed to be known.
* <p> * <p>
* This method should only be called after the source has been prepared. * This method should only be called after the source has been prepared.
* *
......
...@@ -109,7 +109,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent { ...@@ -109,7 +109,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
private int state; private int state;
private TrackStream stream; private TrackStream stream;
private long streamOffsetUs; private long streamOffsetUs;
private long maximumTimeUs;
private boolean readEndOfStream; private boolean readEndOfStream;
private boolean streamIsFinal; private boolean streamIsFinal;
...@@ -235,7 +234,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent { ...@@ -235,7 +234,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
*/ */
/* package */ final void reset(long positionUs) throws ExoPlaybackException { /* package */ final void reset(long positionUs) throws ExoPlaybackException {
streamIsFinal = false; streamIsFinal = false;
maximumTimeUs = C.UNSET_TIME_US;
onReset(positionUs, false); onReset(positionUs, false);
} }
...@@ -261,14 +259,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent { ...@@ -261,14 +259,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
} }
/** /**
* Returns the maximum buffer timestamp read from the stream since the last reset, or
* {@link C#UNSET_TIME_US} if no buffers have been read.
*/
/* package */ final long getMaximumTimeUs() {
return maximumTimeUs;
}
/**
* Signals to the renderer that the current {@link TrackStream} will be the final one supplied * Signals to the renderer that the current {@link TrackStream} will be the final one supplied
* before it is next disabled or reset. * before it is next disabled or reset.
*/ */
...@@ -372,9 +362,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent { ...@@ -372,9 +362,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
return streamIsFinal ? TrackStream.BUFFER_READ : TrackStream.NOTHING_READ; return streamIsFinal ? TrackStream.BUFFER_READ : TrackStream.NOTHING_READ;
} }
buffer.timeUs += streamOffsetUs; buffer.timeUs += streamOffsetUs;
if (buffer.timeUs > maximumTimeUs) {
maximumTimeUs = buffer.timeUs;
}
} }
return result; return result;
} }
......
...@@ -111,6 +111,12 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu ...@@ -111,6 +111,12 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
private static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1; private static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1;
/**
* When the source's duration is unknown, it is calculated by adding this value to the largest
* sample timestamp seen when buffering completes.
*/
private static final long DEFAULT_LAST_SAMPLE_DURATION_US = 10000;
// Lazily initialized default extractor classes in priority order. // Lazily initialized default extractor classes in priority order.
private static List<Class<? extends Extractor>> defaultExtractorClasses; private static List<Class<? extends Extractor>> defaultExtractorClasses;
...@@ -397,11 +403,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu ...@@ -397,11 +403,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
} else if (isPendingReset()) { } else if (isPendingReset()) {
return pendingResetPositionUs; return pendingResetPositionUs;
} else { } else {
long largestQueuedTimestampUs = Long.MIN_VALUE; long largestQueuedTimestampUs = getLargestQueuedTimestampUs();
for (DefaultTrackOutput sampleQueue : sampleQueues) {
largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs,
sampleQueue.getLargestQueuedTimestampUs());
}
return largestQueuedTimestampUs == Long.MIN_VALUE ? lastSeekPositionUs return largestQueuedTimestampUs == Long.MIN_VALUE ? lastSeekPositionUs
: largestQueuedTimestampUs; : largestQueuedTimestampUs;
} }
...@@ -459,6 +461,11 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu ...@@ -459,6 +461,11 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
long loadDurationMs) { long loadDurationMs) {
copyLengthFromLoader(loadable); copyLengthFromLoader(loadable);
loadingFinished = true; loadingFinished = true;
if (durationUs == C.UNSET_TIME_US) {
long largestQueuedTimestampUs = getLargestQueuedTimestampUs();
durationUs = largestQueuedTimestampUs == Long.MIN_VALUE ? 0
: largestQueuedTimestampUs + DEFAULT_LAST_SAMPLE_DURATION_US;
}
} }
@Override @Override
...@@ -579,6 +586,15 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu ...@@ -579,6 +586,15 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
return extractedSamplesCount; return extractedSamplesCount;
} }
private long getLargestQueuedTimestampUs() {
long largestQueuedTimestampUs = Long.MIN_VALUE;
for (DefaultTrackOutput sampleQueue : sampleQueues) {
largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs,
sampleQueue.getLargestQueuedTimestampUs());
}
return largestQueuedTimestampUs;
}
private boolean haveFormatsForAllTracks() { private boolean haveFormatsForAllTracks() {
for (DefaultTrackOutput sampleQueue : sampleQueues) { for (DefaultTrackOutput sampleQueue : sampleQueues) {
if (sampleQueue.getUpstreamFormat() == null) { if (sampleQueue.getUpstreamFormat() == null) {
......
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