From 04c28c6d7dcd49091578dcc1953c3e8eb14a4d84 Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 7 Sep 2016 12:44:28 -0700 Subject: [PATCH] Minimal change to fix seeking before prepare + finalize API - This change fixes seeking before the prepare (or more accurately, before the timeline is set). The fix a minimal one to fix the behavior. It's inefficient compared to posting the pending seek onto the playback thread, which will be the long term solution. - As of this change, I think we can call V2 "done". There are some loose ends to tie up, but the API is effectively finalized and the implementation is in a state where you can take it, use it and expect it to work. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=132468107 --- .../android/exoplayer2/demo/EventLogger.java | 4 +- .../exoplayer2/demo/PlayerActivity.java | 2 +- .../exoplayer2/ext/flac/FlacPlaybackTest.java | 2 +- .../exoplayer2/ext/opus/OpusPlaybackTest.java | 2 +- .../exoplayer2/ext/vp9/VpxPlaybackTest.java | 2 +- .../google/android/exoplayer2/ExoPlayer.java | 44 +++++++++---------- .../android/exoplayer2/ExoPlayerImpl.java | 38 +++++++++------- .../android/exoplayer2/SimpleExoPlayer.java | 5 +++ .../exoplayer2/ui/DebugTextViewHelper.java | 2 +- .../playbacktests/util/ExoHostedTest.java | 2 +- 10 files changed, 57 insertions(+), 46 deletions(-) diff --git a/demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java b/demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java index d52fc30cba..7fd32ddbe1 100644 --- a/demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java +++ b/demo/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java @@ -90,8 +90,8 @@ import java.util.Locale; } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { - Log.d(TAG, "discontinuity [" + periodIndex + ", " + positionMs + "]"); + public void onPositionDiscontinuity() { + Log.d(TAG, "positionDiscontinuity"); } @Override diff --git a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index 36f0110211..db0da6a4c9 100644 --- a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -427,7 +427,7 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { + public void onPositionDiscontinuity() { if (mediaController.isShowing()) { // The MediaController is visible, so force it to show the updated position immediately. mediaController.show(); diff --git a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java index ca3d1a0a65..5df912ace2 100644 --- a/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java +++ b/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacPlaybackTest.java @@ -91,7 +91,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase { } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { + public void onPositionDiscontinuity() { // Do nothing. } diff --git a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java index b094ed1f93..1f554cbebc 100644 --- a/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java +++ b/extensions/opus/src/androidTest/java/com/google/android/exoplayer2/ext/opus/OpusPlaybackTest.java @@ -91,7 +91,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase { } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { + public void onPositionDiscontinuity() { // Do nothing. } diff --git a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java index 7fd1294b01..553157605e 100644 --- a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java +++ b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer2/ext/vp9/VpxPlaybackTest.java @@ -110,7 +110,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase { } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { + public void onPositionDiscontinuity() { // Do nothing. } diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index b3408ff722..6ad687b87e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -144,15 +144,12 @@ public interface ExoPlayer { */ void onPlayerError(ExoPlaybackException error); - // TODO: Should be windowIndex and position in the window. /** - * Called when the player's position changes due to a discontinuity (i.e. due to seeking, - * playback transitioning to the next window, or a source induced discontinuity). - * - * @param periodIndex The index of the period being played. - * @param positionMs The playback position in that period, in milliseconds. + * Called when a position discontinuity occurs. Position discontinuities occur when seeks are + * performed, when playbacks transition from one period in the timeline to the next, and when + * the player introduces discontinuities internally. */ - void onPositionDiscontinuity(int periodIndex, long positionMs); + void onPositionDiscontinuity(); } @@ -309,17 +306,17 @@ public interface ExoPlayer { /** * Seeks to a position specified in milliseconds in the current window. * - * @param positionMs The seek position. + * @param windowPositionMs The seek position in the current window. */ - void seekTo(long positionMs); + void seekTo(long windowPositionMs); /** * Seeks to a position specified in milliseconds in the specified window. * * @param windowIndex The index of the window. - * @param positionMs The seek position relative to the start of the window. + * @param windowPositionMs The seek position in the specified window. */ - void seekTo(int windowIndex, long positionMs); + void seekTo(int windowIndex, long windowPositionMs); /** * Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention @@ -356,11 +353,6 @@ public interface ExoPlayer { */ void blockingSendMessages(ExoPlayerMessage... messages); - /** - * Returns the current {@link Timeline}, or {@code null} if there is no timeline. - */ - Timeline getCurrentTimeline(); - /** * Returns the current manifest. The type depends on the {@link MediaSource} passed to * {@link #prepare}. @@ -368,8 +360,17 @@ public interface ExoPlayer { Object getCurrentManifest(); /** - * Returns the index of the window associated with the current period, or {@link C#INDEX_UNSET} if - * the timeline is not set. + * Returns the current {@link Timeline}, or {@code null} if there is no timeline. + */ + Timeline getCurrentTimeline(); + + /** + * Returns the index of the period currently being played, or {@link C#INDEX_UNSET} if unknown. + */ + int getCurrentPeriodIndex(); + + /** + * Returns the index of the window currently being played. */ int getCurrentWindowIndex(); @@ -380,14 +381,13 @@ public interface ExoPlayer { long getDuration(); /** - * Returns the playback position in the current window, in milliseconds, or {@link C#TIME_UNSET} - * if the timeline is not set. + * Returns the playback position in the current window, in milliseconds. */ long getCurrentPosition(); /** - * Returns an estimate of the position in the current window up to which data is buffered, or - * {@link C#TIME_UNSET} if no estimate is available. + * Returns an estimate of the position in the current window up to which data is buffered, in + * milliseconds. */ long getBufferedPosition(); diff --git a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index 1203eab596..f4b21aac04 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -40,6 +40,7 @@ import java.util.concurrent.CopyOnWriteArraySet; private final Timeline.Window window; private final Timeline.Period period; + private boolean pendingInitialSeek; private boolean playWhenReady; private int playbackState; private int pendingSeekAcks; @@ -137,7 +138,9 @@ import java.util.concurrent.CopyOnWriteArraySet; @Override public void seekToDefaultPosition(int windowIndex) { if (timeline == null) { - // TODO: Handle seeks before the timeline is set. + maskingWindowIndex = windowIndex; + maskingWindowPositionMs = C.TIME_UNSET; + pendingInitialSeek = true; } else { Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount()); pendingSeekAcks++; @@ -157,7 +160,9 @@ import java.util.concurrent.CopyOnWriteArraySet; if (positionMs == C.TIME_UNSET) { seekToDefaultPosition(windowIndex); } else if (timeline == null) { - // TODO: Handle seeks before the timeline is set. + maskingWindowIndex = windowIndex; + maskingWindowPositionMs = positionMs; + pendingInitialSeek = true; } else { Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount()); pendingSeekAcks++; @@ -174,7 +179,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } internalPlayer.seekTo(periodIndex, C.msToUs(periodPositionMs)); for (EventListener listener : listeners) { - listener.onPositionDiscontinuity(periodIndex, periodPositionMs); + listener.onPositionDiscontinuity(); } } } @@ -200,11 +205,14 @@ import java.util.concurrent.CopyOnWriteArraySet; internalPlayer.blockingSendMessages(messages); } + @Override + public int getCurrentPeriodIndex() { + return playbackInfo.periodIndex; + } + @Override public int getCurrentWindowIndex() { - if (timeline == null) { - return C.INDEX_UNSET; - } else if (pendingSeekAcks > 0) { + if (timeline == null || pendingSeekAcks > 0) { return maskingWindowIndex; } else { return timeline.getPeriod(playbackInfo.periodIndex, period).windowIndex; @@ -221,9 +229,7 @@ import java.util.concurrent.CopyOnWriteArraySet; @Override public long getCurrentPosition() { - if (timeline == null) { - return C.TIME_UNSET; - } else if (pendingSeekAcks > 0) { + if (timeline == null || pendingSeekAcks > 0) { return maskingWindowPositionMs; } else { timeline.getPeriod(playbackInfo.periodIndex, period); @@ -234,9 +240,7 @@ import java.util.concurrent.CopyOnWriteArraySet; @Override public long getBufferedPosition() { // TODO - Implement this properly. - if (timeline == null) { - return C.TIME_UNSET; - } else if (pendingSeekAcks > 0) { + if (timeline == null || pendingSeekAcks > 0) { return maskingWindowPositionMs; } else { int periodIndex = playbackInfo.periodIndex; @@ -293,9 +297,8 @@ import java.util.concurrent.CopyOnWriteArraySet; case ExoPlayerImplInternal.MSG_SEEK_ACK: { if (--pendingSeekAcks == 0) { playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj; - long positionMs = C.usToMs(playbackInfo.startPositionUs); for (EventListener listener : listeners) { - listener.onPositionDiscontinuity(playbackInfo.periodIndex, positionMs); + listener.onPositionDiscontinuity(); } } break; @@ -303,9 +306,8 @@ import java.util.concurrent.CopyOnWriteArraySet; case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: { if (pendingSeekAcks == 0) { playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj; - long positionMs = C.usToMs(playbackInfo.startPositionUs); for (EventListener listener : listeners) { - listener.onPositionDiscontinuity(playbackInfo.periodIndex, positionMs); + listener.onPositionDiscontinuity(); } } break; @@ -315,6 +317,10 @@ import java.util.concurrent.CopyOnWriteArraySet; Pair timelineAndManifest = (Pair) msg.obj; timeline = timelineAndManifest.first; manifest = timelineAndManifest.second; + if (pendingInitialSeek) { + pendingInitialSeek = false; + seekTo(maskingWindowIndex, maskingWindowPositionMs); + } for (EventListener listener : listeners) { listener.onTimelineChanged(timeline, manifest); } diff --git a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 35c38771bf..721b3185d3 100644 --- a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -460,6 +460,11 @@ public final class SimpleExoPlayer implements ExoPlayer { player.blockingSendMessages(messages); } + @Override + public int getCurrentPeriodIndex() { + return player.getCurrentPeriodIndex(); + } + @Override public int getCurrentWindowIndex() { return player.getCurrentWindowIndex(); diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java b/library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java index 53e1dcee69..af38836fc9 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/DebugTextViewHelper.java @@ -84,7 +84,7 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe } @Override - public void onPositionDiscontinuity(int periodIndex, long positionMs) { + public void onPositionDiscontinuity() { updateAndPost(); } diff --git a/playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java b/playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java index 1b87dde852..692aa6366d 100644 --- a/playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java +++ b/playbacktests/src/main/java/com/google/android/exoplayer2/playbacktests/util/ExoHostedTest.java @@ -210,7 +210,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen } @Override - public final void onPositionDiscontinuity(int periodIndex, long positionMs) { + public final void onPositionDiscontinuity() { // Do nothing. }