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
This commit is contained in:
olly 2016-09-07 12:44:28 -07:00 committed by Santiago Seifert
parent 36df5bcd84
commit 04c28c6d7d
10 changed files with 57 additions and 46 deletions

View file

@ -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

View file

@ -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();

View file

@ -91,7 +91,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
public void onPositionDiscontinuity() {
// Do nothing.
}

View file

@ -91,7 +91,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
public void onPositionDiscontinuity() {
// Do nothing.
}

View file

@ -110,7 +110,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
public void onPositionDiscontinuity() {
// Do nothing.
}

View file

@ -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();

View file

@ -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<Timeline, Object> timelineAndManifest = (Pair<Timeline, Object>) msg.obj;
timeline = timelineAndManifest.first;
manifest = timelineAndManifest.second;
if (pendingInitialSeek) {
pendingInitialSeek = false;
seekTo(maskingWindowIndex, maskingWindowPositionMs);
}
for (EventListener listener : listeners) {
listener.onTimelineChanged(timeline, manifest);
}

View file

@ -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();

View file

@ -84,7 +84,7 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
}
@Override
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
public void onPositionDiscontinuity() {
updateAndPost();
}

View file

@ -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.
}