From f9fa54cd5dd1c90da2ae1db95b78c4a4b222dd83 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 21 Jun 2016 11:43:51 -0700 Subject: [PATCH] Have seekTo return new position directly. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=125476407 --- .../exoplayer/ExoPlayerImplInternal.java | 42 ++++++++++--------- .../android/exoplayer/MultiSampleSource.java | 24 ++++++----- .../android/exoplayer/SampleSource.java | 19 ++++++--- .../android/exoplayer/SingleSampleSource.java | 12 ++---- .../exoplayer/dash/DashSampleSource.java | 17 ++------ .../extractor/ExtractorSampleSource.java | 5 ++- .../exoplayer/hls/HlsSampleSource.java | 17 ++------ .../SmoothStreamingSampleSource.java | 17 ++------ 8 files changed, 64 insertions(+), 89 deletions(-) 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 f18bfe1463..af2f85b003 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java @@ -377,8 +377,8 @@ import java.util.concurrent.atomic.AtomicInteger; TraceUtil.beginSection("doSomeWork"); if (enabledRenderers.length > 0) { - // Process reset if there is one, else update the position. - if (!checkForSourceResetInternal()) { + // Process a source discontinuity if there is one, else update the position. + if (!checkForSourceDiscontinuityInternal()) { updatePositionUs(); sampleSource = timeline.getSampleSource(); } @@ -442,21 +442,21 @@ import java.util.concurrent.atomic.AtomicInteger; } } - private void seekToInternal(int sourceIndex, long positionMs) throws ExoPlaybackException { + private void seekToInternal(int sourceIndex, long seekPositionMs) throws ExoPlaybackException { try { - if (positionMs == (positionUs / 1000)) { + if (seekPositionMs == (positionUs / 1000)) { // Seek is to the current position. Do nothing. return; } + long seekPositionUs = seekPositionMs * 1000; rebuffering = false; - positionUs = positionMs * 1000; - internalPositionUs = sourceOffsetUs + positionUs; standaloneMediaClock.stop(); - standaloneMediaClock.setPositionUs(internalPositionUs); - sampleSource = timeline.seekTo(sourceIndex, positionUs); + + sampleSource = timeline.seekToSource(sourceIndex); if (sampleSource == null) { // The source isn't prepared. + setNewSourcePositionInternal(seekPositionUs); return; } @@ -464,9 +464,10 @@ import java.util.concurrent.atomic.AtomicInteger; for (TrackRenderer renderer : enabledRenderers) { ensureStopped(renderer); } - checkForSourceResetInternal(); + seekPositionUs = sampleSource.seekToUs(seekPositionUs); } + setNewSourcePositionInternal(seekPositionUs); resumeInternal(); } finally { pendingSeekCount.decrementAndGet(); @@ -496,17 +497,22 @@ import java.util.concurrent.atomic.AtomicInteger; handler.sendEmptyMessage(MSG_DO_SOME_WORK); } - private boolean checkForSourceResetInternal() throws ExoPlaybackException { - long resetPositionUs = sampleSource.readReset(); - if (resetPositionUs == C.UNSET_TIME_US) { + private boolean checkForSourceDiscontinuityInternal() throws ExoPlaybackException { + long newSourcePositionUs = sampleSource.readDiscontinuity(); + if (newSourcePositionUs == C.UNSET_TIME_US) { return false; } - internalPositionUs = sourceOffsetUs + resetPositionUs; + setNewSourcePositionInternal(newSourcePositionUs); + return true; + } + + private void setNewSourcePositionInternal(long sourcePositionUs) throws ExoPlaybackException { + positionUs = sourcePositionUs; + internalPositionUs = sourceOffsetUs + sourcePositionUs; standaloneMediaClock.setPositionUs(internalPositionUs); for (TrackRenderer renderer : enabledRenderers) { renderer.reset(internalPositionUs); } - return true; } private void stopInternal() { @@ -672,8 +678,6 @@ import java.util.concurrent.atomic.AtomicInteger; playingSourceEndPositionUs = C.UNSET_TIME_US; } else if (playingSource.nextSource != null && playingSource.nextSource.prepared) { readingSource = playingSource.nextSource; - // Suppress reading a reset so that the transition can be seamless. - readingSource.sampleSource.readReset(); // Replace enabled renderers' TrackStreams if they will continue to be enabled when the // new source starts playing, so that the transition can be seamless. TrackSelectionArray newTrackSelections = readingSource.trackSelections; @@ -711,7 +715,7 @@ import java.util.concurrent.atomic.AtomicInteger; return playingSource.sampleSource; } - public SampleSource seekTo(int sourceIndex, long sourcePositionUs) throws ExoPlaybackException { + public SampleSource seekToSource(int sourceIndex) throws ExoPlaybackException { // Clear the timeline, but keep the requested source if it is already prepared. Source source = playingSource; Source newPlayingSource = null; @@ -729,10 +733,8 @@ import java.util.concurrent.atomic.AtomicInteger; setPlayingSource(newPlayingSource, sourceOffsetUs); bufferingSource = playingSource; bufferingSourceOffsetUs = sourceOffsetUs; - if (playingSource.hasEnabledTracks) { - sampleSource.seekToUs(sourcePositionUs); - } } else { + // TODO[REFACTOR]: Presumably we need to disable the renderers somewhere in here? playingSource = null; readingSource = null; bufferingSource = null; 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 bcd4b31a1c..234fb37258 100644 --- a/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/MultiSampleSource.java @@ -124,17 +124,14 @@ public final class MultiSampleSource implements SampleSource { } @Override - public long readReset() { - long resetPositionUs = C.UNSET_TIME_US; + public long readDiscontinuity() { for (SampleSource source : enabledSources) { - long childResetPositionUs = source.readReset(); - if (resetPositionUs == C.UNSET_TIME_US) { - resetPositionUs = childResetPositionUs; - } else if (childResetPositionUs != C.UNSET_TIME_US) { - resetPositionUs = Math.min(resetPositionUs, childResetPositionUs); + if (source.readDiscontinuity() != C.UNSET_TIME_US) { + // Children are not allowed to report discontinuities. + throw new IllegalStateException("Child reported discontinuity"); } } - return resetPositionUs; + return C.UNSET_TIME_US; } @Override @@ -150,10 +147,15 @@ public final class MultiSampleSource implements SampleSource { } @Override - public void seekToUs(long positionUs) { - for (SampleSource source : enabledSources) { - source.seekToUs(positionUs); + public long seekToUs(long positionUs) { + positionUs = enabledSources[0].seekToUs(positionUs); + for (int i = 1; i < enabledSources.length; i++) { + // Additional sources must seek to the same position. + if (enabledSources[i].seekToUs(positionUs) != positionUs) { + throw new IllegalStateException("Children seeked to different positions"); + } } + return positionUs; } @Override 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 51577ec4dd..c8ed5334ac 100644 --- a/library/src/main/java/com/google/android/exoplayer/SampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SampleSource.java @@ -88,12 +88,15 @@ public interface SampleSource { void continueBuffering(long positionUs); /** - * Attempts to read a pending reset. + * Attempts to read a discontinuity. + *

+ * After this method has returned a value other than {@link C#UNSET_TIME_US}, all + * {@link TrackStream}s provided by the source are guaranteed to start from a key frame. * - * @return If a reset was read then the playback position in microseconds after the reset. Else - * {@link C#UNSET_TIME_US}. + * @return If a discontinuity was read then the playback position in microseconds after the + * discontinuity. Else {@link C#UNSET_TIME_US}. */ - long readReset(); + long readDiscontinuity(); /** * Returns an estimate of the position up to which data is buffered for the enabled tracks. @@ -106,13 +109,17 @@ public interface SampleSource { long getBufferedPositionUs(); /** - * Seeks to the specified position in microseconds. + * Attempts to seek to the specified position in microseconds. + *

+ * After this method has been called, all {@link TrackStream}s provided by the source are + * guaranteed to start from a key frame. *

* This method should only be called when at least one track is selected. * * @param positionUs The seek position in microseconds. + * @return The actual position to which the source was seeked, in microseconds. */ - void seekToUs(long positionUs); + long seekToUs(long positionUs); /** * Releases the source. 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 1543fb7ea5..4f228724bc 100644 --- a/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/SingleSampleSource.java @@ -74,7 +74,6 @@ public final class SingleSampleSource implements SampleSource, TrackStream, private final EventListener eventListener; private final int eventSourceId; - private long pendingResetPositionUs; private boolean loadingFinished; private int streamState; @@ -140,7 +139,6 @@ public final class SingleSampleSource implements SampleSource, TrackStream, if (!newSelections.isEmpty()) { newStreams[0] = this; streamState = STREAM_STATE_SEND_FORMAT; - pendingResetPositionUs = C.UNSET_TIME_US; maybeStartLoading(); } return newStreams; @@ -157,11 +155,11 @@ public final class SingleSampleSource implements SampleSource, TrackStream, } @Override - public void seekToUs(long positionUs) { + public long seekToUs(long positionUs) { if (streamState == STREAM_STATE_END_OF_STREAM) { - pendingResetPositionUs = positionUs; streamState = STREAM_STATE_SEND_SAMPLE; } + return positionUs; } @Override @@ -182,10 +180,8 @@ public final class SingleSampleSource implements SampleSource, TrackStream, } @Override - public long readReset() { - long resetPositionUs = pendingResetPositionUs; - pendingResetPositionUs = C.UNSET_TIME_US; - return resetPositionUs; + public long readDiscontinuity() { + return C.UNSET_TIME_US; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java b/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java index c30e56bb64..ad80a9b15e 100644 --- a/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/dash/DashSampleSource.java @@ -92,8 +92,6 @@ public final class DashSampleSource implements SampleSource { private long elapsedRealtimeOffset; private TrackGroupArray trackGroups; private int[] trackGroupAdaptationSetIndices; - private boolean pendingReset; - private long lastSeekPositionUs; private ChunkTrackStream[] trackStreams; public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory, @@ -184,14 +182,7 @@ public final class DashSampleSource implements SampleSource { } @Override - public long readReset() { - if (pendingReset) { - pendingReset = false; - for (ChunkTrackStream trackStream : trackStreams) { - trackStream.setReadingEnabled(true); - } - return lastSeekPositionUs; - } + public long readDiscontinuity() { return C.UNSET_TIME_US; } @@ -208,13 +199,11 @@ public final class DashSampleSource implements SampleSource { } @Override - public void seekToUs(long positionUs) { - lastSeekPositionUs = positionUs; - pendingReset = true; + public long seekToUs(long positionUs) { for (ChunkTrackStream trackStream : trackStreams) { - trackStream.setReadingEnabled(false); trackStream.seekToUs(positionUs); } + return positionUs; } @Override 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 a6cd21b728..b2b856a363 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 @@ -388,7 +388,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu } @Override - public long readReset() { + public long readDiscontinuity() { if (notifyReset) { notifyReset = false; return lastSeekPositionUs; @@ -410,7 +410,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu } @Override - public void seekToUs(long positionUs) { + public long seekToUs(long positionUs) { // Treat all seeks into non-seekable media as being to t=0. positionUs = seekMap.isSeekable() ? positionUs : 0; lastSeekPositionUs = positionUs; @@ -426,6 +426,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu if (!seekInsideBuffer) { restartFrom(positionUs); } + return positionUs; } @Override 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 54b8ca3e9f..bf71747171 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 @@ -80,8 +80,6 @@ public final class HlsSampleSource implements SampleSource, private int[] selectedTrackCounts; private HlsTrackStreamWrapper[] trackStreamWrappers; private HlsTrackStreamWrapper[] enabledTrackStreamWrappers; - private boolean pendingReset; - private long lastSeekPositionUs; public HlsSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter, Handler eventHandler, @@ -192,14 +190,7 @@ public final class HlsSampleSource implements SampleSource, } @Override - public long readReset() { - if (pendingReset) { - pendingReset = false; - for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) { - trackStreamWrapper.setReadingEnabled(true); - } - return lastSeekPositionUs; - } + public long readDiscontinuity() { return C.UNSET_TIME_US; } @@ -216,16 +207,14 @@ public final class HlsSampleSource implements SampleSource, } @Override - public void seekToUs(long positionUs) { + public long seekToUs(long positionUs) { // Treat all seeks into non-seekable media as being to t=0. positionUs = isLive ? 0 : positionUs; - lastSeekPositionUs = positionUs; - pendingReset = true; timestampAdjusterProvider.reset(); for (HlsTrackStreamWrapper trackStreamWrapper : enabledTrackStreamWrappers) { - trackStreamWrapper.setReadingEnabled(false); trackStreamWrapper.restartFrom(positionUs); } + return positionUs; } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java index 2f1b33748c..2b4f3fada1 100644 --- a/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/smoothstreaming/SmoothStreamingSampleSource.java @@ -81,8 +81,6 @@ public final class SmoothStreamingSampleSource implements SampleSource, private TrackEncryptionBox[] trackEncryptionBoxes; private TrackGroupArray trackGroups; private int[] trackGroupElementIndices; - private boolean pendingReset; - private long lastSeekPositionUs; private ChunkTrackStream[] trackStreams; @@ -171,14 +169,7 @@ public final class SmoothStreamingSampleSource implements SampleSource, } @Override - public long readReset() { - if (pendingReset) { - pendingReset = false; - for (ChunkTrackStream trackStream : trackStreams) { - trackStream.setReadingEnabled(true); - } - return lastSeekPositionUs; - } + public long readDiscontinuity() { return C.UNSET_TIME_US; } @@ -195,13 +186,11 @@ public final class SmoothStreamingSampleSource implements SampleSource, } @Override - public void seekToUs(long positionUs) { - lastSeekPositionUs = positionUs; - pendingReset = true; + public long seekToUs(long positionUs) { for (ChunkTrackStream trackStream : trackStreams) { - trackStream.setReadingEnabled(false); trackStream.seekToUs(positionUs); } + return positionUs; } @Override