mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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:
parent
36df5bcd84
commit
04c28c6d7d
10 changed files with 57 additions and 46 deletions
|
|
@ -90,8 +90,8 @@ import java.util.Locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
Log.d(TAG, "discontinuity [" + periodIndex + ", " + positionMs + "]");
|
Log.d(TAG, "positionDiscontinuity");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -427,7 +427,7 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
if (mediaController.isShowing()) {
|
if (mediaController.isShowing()) {
|
||||||
// The MediaController is visible, so force it to show the updated position immediately.
|
// The MediaController is visible, so force it to show the updated position immediately.
|
||||||
mediaController.show();
|
mediaController.show();
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,15 +144,12 @@ public interface ExoPlayer {
|
||||||
*/
|
*/
|
||||||
void onPlayerError(ExoPlaybackException error);
|
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,
|
* Called when a position discontinuity occurs. Position discontinuities occur when seeks are
|
||||||
* playback transitioning to the next window, or a source induced discontinuity).
|
* performed, when playbacks transition from one period in the timeline to the next, and when
|
||||||
*
|
* the player introduces discontinuities internally.
|
||||||
* @param periodIndex The index of the period being played.
|
|
||||||
* @param positionMs The playback position in that period, in milliseconds.
|
|
||||||
*/
|
*/
|
||||||
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.
|
* 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.
|
* Seeks to a position specified in milliseconds in the specified window.
|
||||||
*
|
*
|
||||||
* @param windowIndex The index of the 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
|
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
|
||||||
|
|
@ -356,11 +353,6 @@ public interface ExoPlayer {
|
||||||
*/
|
*/
|
||||||
void blockingSendMessages(ExoPlayerMessage... messages);
|
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
|
* Returns the current manifest. The type depends on the {@link MediaSource} passed to
|
||||||
* {@link #prepare}.
|
* {@link #prepare}.
|
||||||
|
|
@ -368,8 +360,17 @@ public interface ExoPlayer {
|
||||||
Object getCurrentManifest();
|
Object getCurrentManifest();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of the window associated with the current period, or {@link C#INDEX_UNSET} if
|
* Returns the current {@link Timeline}, or {@code null} if there is no timeline.
|
||||||
* the timeline is not set.
|
*/
|
||||||
|
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();
|
int getCurrentWindowIndex();
|
||||||
|
|
||||||
|
|
@ -380,14 +381,13 @@ public interface ExoPlayer {
|
||||||
long getDuration();
|
long getDuration();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the playback position in the current window, in milliseconds, or {@link C#TIME_UNSET}
|
* Returns the playback position in the current window, in milliseconds.
|
||||||
* if the timeline is not set.
|
|
||||||
*/
|
*/
|
||||||
long getCurrentPosition();
|
long getCurrentPosition();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an estimate of the position in the current window up to which data is buffered, or
|
* Returns an estimate of the position in the current window up to which data is buffered, in
|
||||||
* {@link C#TIME_UNSET} if no estimate is available.
|
* milliseconds.
|
||||||
*/
|
*/
|
||||||
long getBufferedPosition();
|
long getBufferedPosition();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
private final Timeline.Window window;
|
private final Timeline.Window window;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
|
|
||||||
|
private boolean pendingInitialSeek;
|
||||||
private boolean playWhenReady;
|
private boolean playWhenReady;
|
||||||
private int playbackState;
|
private int playbackState;
|
||||||
private int pendingSeekAcks;
|
private int pendingSeekAcks;
|
||||||
|
|
@ -137,7 +138,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
@Override
|
@Override
|
||||||
public void seekToDefaultPosition(int windowIndex) {
|
public void seekToDefaultPosition(int windowIndex) {
|
||||||
if (timeline == null) {
|
if (timeline == null) {
|
||||||
// TODO: Handle seeks before the timeline is set.
|
maskingWindowIndex = windowIndex;
|
||||||
|
maskingWindowPositionMs = C.TIME_UNSET;
|
||||||
|
pendingInitialSeek = true;
|
||||||
} else {
|
} else {
|
||||||
Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount());
|
Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount());
|
||||||
pendingSeekAcks++;
|
pendingSeekAcks++;
|
||||||
|
|
@ -157,7 +160,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
if (positionMs == C.TIME_UNSET) {
|
if (positionMs == C.TIME_UNSET) {
|
||||||
seekToDefaultPosition(windowIndex);
|
seekToDefaultPosition(windowIndex);
|
||||||
} else if (timeline == null) {
|
} else if (timeline == null) {
|
||||||
// TODO: Handle seeks before the timeline is set.
|
maskingWindowIndex = windowIndex;
|
||||||
|
maskingWindowPositionMs = positionMs;
|
||||||
|
pendingInitialSeek = true;
|
||||||
} else {
|
} else {
|
||||||
Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount());
|
Assertions.checkIndex(windowIndex, 0, timeline.getWindowCount());
|
||||||
pendingSeekAcks++;
|
pendingSeekAcks++;
|
||||||
|
|
@ -174,7 +179,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
}
|
}
|
||||||
internalPlayer.seekTo(periodIndex, C.msToUs(periodPositionMs));
|
internalPlayer.seekTo(periodIndex, C.msToUs(periodPositionMs));
|
||||||
for (EventListener listener : listeners) {
|
for (EventListener listener : listeners) {
|
||||||
listener.onPositionDiscontinuity(periodIndex, periodPositionMs);
|
listener.onPositionDiscontinuity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -200,11 +205,14 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
internalPlayer.blockingSendMessages(messages);
|
internalPlayer.blockingSendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCurrentPeriodIndex() {
|
||||||
|
return playbackInfo.periodIndex;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCurrentWindowIndex() {
|
public int getCurrentWindowIndex() {
|
||||||
if (timeline == null) {
|
if (timeline == null || pendingSeekAcks > 0) {
|
||||||
return C.INDEX_UNSET;
|
|
||||||
} else if (pendingSeekAcks > 0) {
|
|
||||||
return maskingWindowIndex;
|
return maskingWindowIndex;
|
||||||
} else {
|
} else {
|
||||||
return timeline.getPeriod(playbackInfo.periodIndex, period).windowIndex;
|
return timeline.getPeriod(playbackInfo.periodIndex, period).windowIndex;
|
||||||
|
|
@ -221,9 +229,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getCurrentPosition() {
|
public long getCurrentPosition() {
|
||||||
if (timeline == null) {
|
if (timeline == null || pendingSeekAcks > 0) {
|
||||||
return C.TIME_UNSET;
|
|
||||||
} else if (pendingSeekAcks > 0) {
|
|
||||||
return maskingWindowPositionMs;
|
return maskingWindowPositionMs;
|
||||||
} else {
|
} else {
|
||||||
timeline.getPeriod(playbackInfo.periodIndex, period);
|
timeline.getPeriod(playbackInfo.periodIndex, period);
|
||||||
|
|
@ -234,9 +240,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPosition() {
|
public long getBufferedPosition() {
|
||||||
// TODO - Implement this properly.
|
// TODO - Implement this properly.
|
||||||
if (timeline == null) {
|
if (timeline == null || pendingSeekAcks > 0) {
|
||||||
return C.TIME_UNSET;
|
|
||||||
} else if (pendingSeekAcks > 0) {
|
|
||||||
return maskingWindowPositionMs;
|
return maskingWindowPositionMs;
|
||||||
} else {
|
} else {
|
||||||
int periodIndex = playbackInfo.periodIndex;
|
int periodIndex = playbackInfo.periodIndex;
|
||||||
|
|
@ -293,9 +297,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
||||||
if (--pendingSeekAcks == 0) {
|
if (--pendingSeekAcks == 0) {
|
||||||
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
||||||
long positionMs = C.usToMs(playbackInfo.startPositionUs);
|
|
||||||
for (EventListener listener : listeners) {
|
for (EventListener listener : listeners) {
|
||||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex, positionMs);
|
listener.onPositionDiscontinuity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -303,9 +306,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: {
|
case ExoPlayerImplInternal.MSG_POSITION_DISCONTINUITY: {
|
||||||
if (pendingSeekAcks == 0) {
|
if (pendingSeekAcks == 0) {
|
||||||
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
||||||
long positionMs = C.usToMs(playbackInfo.startPositionUs);
|
|
||||||
for (EventListener listener : listeners) {
|
for (EventListener listener : listeners) {
|
||||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex, positionMs);
|
listener.onPositionDiscontinuity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -315,6 +317,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
Pair<Timeline, Object> timelineAndManifest = (Pair<Timeline, Object>) msg.obj;
|
Pair<Timeline, Object> timelineAndManifest = (Pair<Timeline, Object>) msg.obj;
|
||||||
timeline = timelineAndManifest.first;
|
timeline = timelineAndManifest.first;
|
||||||
manifest = timelineAndManifest.second;
|
manifest = timelineAndManifest.second;
|
||||||
|
if (pendingInitialSeek) {
|
||||||
|
pendingInitialSeek = false;
|
||||||
|
seekTo(maskingWindowIndex, maskingWindowPositionMs);
|
||||||
|
}
|
||||||
for (EventListener listener : listeners) {
|
for (EventListener listener : listeners) {
|
||||||
listener.onTimelineChanged(timeline, manifest);
|
listener.onTimelineChanged(timeline, manifest);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -460,6 +460,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||||
player.blockingSendMessages(messages);
|
player.blockingSendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCurrentPeriodIndex() {
|
||||||
|
return player.getCurrentPeriodIndex();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCurrentWindowIndex() {
|
public int getCurrentWindowIndex() {
|
||||||
return player.getCurrentWindowIndex();
|
return player.getCurrentWindowIndex();
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public void onPositionDiscontinuity() {
|
||||||
updateAndPost();
|
updateAndPost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
public final void onPositionDiscontinuity() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue