diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java index 5ebba53527..e56cc041aa 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java @@ -125,11 +125,13 @@ import java.util.concurrent.atomic.AtomicInteger; } public long getBufferedPosition() { + long bufferedPositionUs = this.bufferedPositionUs; return bufferedPositionUs == C.UNKNOWN_TIME_US ? ExoPlayer.UNKNOWN_TIME : bufferedPositionUs / 1000; } public long getDuration() { + long durationUs = this.durationUs; return durationUs == C.UNKNOWN_TIME_US ? ExoPlayer.UNKNOWN_TIME : durationUs / 1000; } @@ -279,7 +281,6 @@ import java.util.concurrent.atomic.AtomicInteger; } durationUs = source.getDurationUs(); - bufferedPositionUs = source.getBufferedPositionUs(); selectTracksInternal(true); boolean allRenderersEnded = true; @@ -363,6 +364,13 @@ import java.util.concurrent.atomic.AtomicInteger; elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000; } + private void updateBufferedPositionUs() { + long sourceBufferedPositionUs = enabledRenderers.length > 0 ? source.getBufferedPositionUs() + : C.END_OF_SOURCE_US; + bufferedPositionUs = sourceBufferedPositionUs == C.END_OF_SOURCE_US + && durationUs != C.UNKNOWN_TIME_US ? durationUs : sourceBufferedPositionUs; + } + private void doSomeWork() throws ExoPlaybackException, IOException { TraceUtil.beginSection("doSomeWork"); long operationStartTimeMs = SystemClock.elapsedRealtime(); @@ -373,8 +381,10 @@ import java.util.concurrent.atomic.AtomicInteger; } updatePositionUs(); - bufferedPositionUs = source.getBufferedPositionUs(); - source.continueBuffering(positionUs); + updateBufferedPositionUs(); + if (enabledRenderers.length > 0) { + source.continueBuffering(positionUs); + } boolean allRenderersEnded = true; boolean allRenderersReadyOrEnded = true; @@ -444,13 +454,14 @@ import java.util.concurrent.atomic.AtomicInteger; return; } - for (TrackRenderer renderer : enabledRenderers) { - ensureStopped(renderer); - } - setState(ExoPlayer.STATE_BUFFERING); - source.seekToUs(positionUs); - for (TrackRenderer renderer : enabledRenderers) { - renderer.checkForReset(); + if (enabledRenderers != null) { + for (TrackRenderer renderer : enabledRenderers) { + ensureStopped(renderer); + } + source.seekToUs(positionUs); + for (TrackRenderer renderer : enabledRenderers) { + renderer.checkForReset(); + } } handler.sendEmptyMessage(MSG_DO_SOME_WORK); @@ -622,6 +633,7 @@ import java.util.concurrent.atomic.AtomicInteger; } source.endTrackSelection(positionUs); + updateBufferedPositionUs(); } private void reselectTracksInternal() throws ExoPlaybackException { diff --git a/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java b/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java index f6db3863b0..b5f15b0b5e 100644 --- a/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java @@ -20,6 +20,7 @@ import com.google.android.exoplayer.util.Assertions; import android.util.Pair; import java.io.IOException; +import java.util.Arrays; import java.util.IdentityHashMap; /** @@ -28,14 +29,17 @@ import java.util.IdentityHashMap; public final class MultiSampleSource implements SampleSource { private final SampleSource[] sources; + private final int[] sourceEnabledTrackCounts; private final IdentityHashMap trackStreamSourceIndices; private int state; private long durationUs; private TrackGroupArray trackGroups; + private SampleSource[] enabledSources; public MultiSampleSource(SampleSource... sources) { this.sources = sources; + sourceEnabledTrackCounts = new int[sources.length]; trackStreamSourceIndices = new IdentityHashMap<>(); state = STATE_UNPREPARED; } @@ -100,7 +104,9 @@ public final class MultiSampleSource implements SampleSource { Pair sourceAndGroup = getSourceAndTrackGroupIndices(selection.group); TrackStream trackStream = sources[sourceAndGroup.first].selectTrack( new TrackSelection(sourceAndGroup.second, selection.getTracks()), positionUs); - trackStreamSourceIndices.put(trackStream, sourceAndGroup.first); + int sourceIndex = sourceAndGroup.first; + sourceEnabledTrackCounts[sourceIndex]++; + trackStreamSourceIndices.put(trackStream, sourceIndex); return trackStream; } @@ -109,27 +115,34 @@ public final class MultiSampleSource implements SampleSource { Assertions.checkState(state == STATE_SELECTING_TRACKS); int sourceIndex = trackStreamSourceIndices.remove(trackStream); sources[sourceIndex].unselectTrack(trackStream); + sourceEnabledTrackCounts[sourceIndex]--; } @Override public void endTrackSelection(long positionUs) { Assertions.checkState(state == STATE_SELECTING_TRACKS); state = STATE_READING; - for (SampleSource source : sources) { - source.endTrackSelection(positionUs); + int newEnabledSourceCount = 0; + SampleSource[] newEnabledSources = new SampleSource[sources.length]; + for (int i = 0; i < sources.length; i++) { + sources[i].endTrackSelection(positionUs); + if (sourceEnabledTrackCounts[i] > 0) { + newEnabledSources[newEnabledSourceCount++] = sources[i]; + } } + enabledSources = Arrays.copyOf(newEnabledSources, newEnabledSourceCount); } @Override public void continueBuffering(long positionUs) { - for (SampleSource source : sources) { + for (SampleSource source : enabledSources) { source.continueBuffering(positionUs); } } @Override public void seekToUs(long positionUs) { - for (SampleSource source : sources) { + for (SampleSource source : enabledSources) { source.seekToUs(positionUs); } } @@ -142,7 +155,7 @@ public final class MultiSampleSource implements SampleSource { @Override public long getBufferedPositionUs() { long bufferedPositionUs = durationUs != C.UNKNOWN_TIME_US ? durationUs : Long.MAX_VALUE; - for (SampleSource source : sources) { + for (SampleSource source : enabledSources) { long rendererBufferedPositionUs = source.getBufferedPositionUs(); if (rendererBufferedPositionUs == C.UNKNOWN_TIME_US) { return C.UNKNOWN_TIME_US; diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSource.java b/library/src/main/java/com/google/android/exoplayer/SampleSource.java index 9a7931b10f..cf2259881c 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleSource.java @@ -132,7 +132,8 @@ public interface SampleSource { /** * Indicates to the source that it should continue buffering data for its enabled tracks. *

- * This method should only be called when the state is {@link #STATE_READING}. + * This method should only be called when the state is {@link #STATE_READING} and at least one + * track is selected. * * @param positionUs The current playback position. */ @@ -141,19 +142,20 @@ public interface SampleSource { /** * Returns an estimate of the position up to which data is buffered for the enabled tracks. *

- * This method should only be called when the state is {@link #STATE_READING}. + * This method should only be called when the state is {@link #STATE_READING} and at least one + * track is selected. * * @return An estimate of the absolute position in microseconds up to which data is buffered, * or {@link C#END_OF_SOURCE_US} if the track is fully buffered, or {@link C#UNKNOWN_TIME_US} - * if no estimate is available. If no tracks are enabled then {@link C#END_OF_SOURCE_US} is - * returned. + * if no estimate is available. */ long getBufferedPositionUs(); /** * Seeks to the specified time in microseconds. *

- * This method should only be called when the state is {@link #STATE_READING}. + * This method should only be called when the state is {@link #STATE_READING} and at least one + * track is selected. * * @param positionUs The seek position in microseconds. */ diff --git a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java index 0bd1e7734c..86992acfdd 100644 --- a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java @@ -220,7 +220,7 @@ public final class SingleSampleSource implements SampleSource, TrackStream, Load @Override public long getBufferedPositionUs() { - return streamState == STREAM_STATE_END_OF_STREAM || loadingFinished ? C.END_OF_SOURCE_US : 0; + return loadingFinished ? C.END_OF_SOURCE_US : 0; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index 0e071acf8f..3c7062a990 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -326,7 +326,7 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call @Override public long getBufferedPositionUs() { - if (!trackEnabled || loadingFinished) { + if (loadingFinished) { return C.END_OF_SOURCE_US; } else if (isPendingReset()) { return pendingResetPositionUs; diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java index 6d201b3d67..fb3a9f1334 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java @@ -423,9 +423,6 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu @Override public void continueBuffering(long playbackPositionUs) { - if (enabledTrackCount == 0) { - return; - } downstreamPositionUs = playbackPositionUs; discardSamplesForDisabledTracks(downstreamPositionUs); if (loadingFinished) { @@ -504,9 +501,6 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu @Override public void seekToUs(long positionUs) { - if (enabledTrackCount == 0) { - return; - } seekToInternal(positionUs); } @@ -529,7 +523,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu @Override public long getBufferedPositionUs() { - if (enabledTrackCount == 0 || loadingFinished) { + if (loadingFinished) { return C.END_OF_SOURCE_US; } else if (isPendingReset()) { return pendingResetPositionUs; diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index c7259c3385..8b19f1d9a4 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -258,9 +258,6 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback { @Override public void continueBuffering(long playbackPositionUs) { - if (enabledTrackCount == 0) { - return; - } downstreamPositionUs = playbackPositionUs; if (!extractors.isEmpty()) { discardSamplesForDisabledTracks(getCurrentExtractor(), downstreamPositionUs); @@ -360,17 +357,12 @@ public final class HlsSampleSource implements SampleSource, Loader.Callback { @Override public void seekToUs(long positionUs) { - if (enabledTrackCount == 0) { - return; - } seekToInternal(positionUs); } @Override public long getBufferedPositionUs() { - if (enabledTrackCount == 0) { - return C.END_OF_SOURCE_US; - } else if (isPendingReset()) { + if (isPendingReset()) { return pendingResetPositionUs; } else if (loadingFinished) { return C.END_OF_SOURCE_US;