Description
Steps To Reproduce
Add this code to the demo PlayerActivity
:
private static boolean bug_triggered = false;
private class PlayerEventListener implements Player.Listener {
@Override
public void onPlaybackStateChanged(@Player.State int playbackState) {
Log.d(TAG, "onPlaybackStateChanged() - " + playbackState);
if (getIntent().getBooleanExtra("trigger_bug", false) && ! bug_triggered) {
playerView.setControllerAutoShow(false);
playerView.setControllerShowTimeoutMs(-1);
playerView.showController();
if (playbackState == Player.STATE_READY) {
bug_triggered = true;
DefaultTrackSelector.Parameters savedParameters = trackSelector.getParameters();
DefaultTrackSelector.Parameters disableTracksParameters =
savedParameters
.buildUpon()
.setMaxVideoBitrate(3000000 - 1)
.build();
trackSelector.setParameters(disableTracksParameters);
long pos = player.getCurrentPosition();
while (pos > 0) {
Log.d(TAG, "seekTo - " + pos);
player.seekTo(pos);
pos -= 600_000L;
android.os.SystemClock.sleep(500);
}
Log.d(TAG, "seekTo final to 0");
player.seekTo(0);
Log.d(TAG, "run track selection");
trackSelector.setParameters(savedParameters);
}
}
Run it sending the intent to the player:
adb shell am start -n com.google.android.exoplayer2.demo/.PlayerActivity -a com.google.android.exoplayer.demo.action.VIEW --ez trigger_bug true -d <live-url>
Issue Analysis
The MaskingMediaPeriod
forces position back to live start when TrackSelection is triggered following a seek to 0.
I believe this issue is related to issue #7975, specifically the code that handles changing the position, source here.
For the 2.12.x ExoPlayer this results in the player hangs in BUFFERING state but believing there is way more buffer then there is because position does not change. Changes since 2.12 (e.g. dynamic live edge) appear to have changed that behavior so now it simply jumps from position 0 (the expected position) to live edge. We will be fixing this for 2.12 (our current version) and will try to provide a forward port pull request for dev-v2
Plan is to only apply the override position on the initial playback start, not every track selection as it is done now.
Logging
08-27 15:50:44.165 16684 16684 D Demo : onPlaybackStateChanged() - 2
08-27 15:50:44.166 16684 16775 W MaskingMediaPeriod: () - 66568544 preparePositionUs: 0
08-27 15:50:45.584 16684 16775 D MaskingMediaPeriod: overridePreparePositionUs() - 66568544 preparePositionUs: 3571568, preparePositionOverrideUs: -9223372036854775807
08-27 15:50:45.584 16684 16775 D MaskingMediaPeriod: getPreparePositionWithOverride() - preparePositionMs: 0 preparePositionOverride: 3571568
08-27 15:50:47.272 16684 16684 D Demo : onPlaybackStateChanged() - 3
08-27 15:50:47.274 16684 16684 D Demo : seekTo - 3571600
08-27 15:50:47.781 16684 16684 D Demo : seekTo - 2971600
08-27 15:50:48.287 16684 16684 D Demo : seekTo - 2371600
08-27 15:50:48.793 16684 16684 D Demo : seekTo - 1771600
08-27 15:50:49.299 16684 16684 D Demo : seekTo - 1171600
08-27 15:50:49.807 16684 16684 D Demo : seekTo - 571600
08-27 15:50:50.311 16684 16684 D Demo : seekTo final to 0
08-27 15:50:50.316 16684 16684 D Demo : run track selection
08-27 15:50:50.336 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.22, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=3571600], PositionInfo:new [window=0, period=0, pos=3571600]]
08-27 15:50:50.346 16684 16684 D Demo : onPlaybackStateChanged() - 2
08-27 15:50:50.360 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.24, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=3571600], PositionInfo:new [window=0, period=0, pos=2971600]]
08-27 15:50:50.368 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.25, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=2971600], PositionInfo:new [window=0, period=0, pos=2371600]]
08-27 15:50:50.376 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.26, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=2371600], PositionInfo:new [window=0, period=0, pos=1771600]]
08-27 15:50:50.384 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.27, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=1771600], PositionInfo:new [window=0, period=0, pos=1171600]]
08-27 15:50:50.391 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.28, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=1171600], PositionInfo:new [window=0, period=0, pos=571600]]
08-27 15:50:50.399 16684 16684 D EventLogger: positionDiscontinuity [eventTime=6.28, mediaPos=0.00, window=0, period=0, reason=SEEK, PositionInfo:old [window=0, period=0, pos=571600], PositionInfo:new [window=0, period=0, pos=0]]
Here's where the error occurs, MMP overrides the position and returns it from selectTracks()
08-27 15:50:50.410 16684 16775 D MaskingMediaPeriod: selectTracks() - 66568544 override positionMs: 0 to preparePositionOverrideMs: 3571568, preparePositionMs: 0
08-27 15:50:51.128 16684 16684 D Demo : onPlaybackStateChanged() - 3
08-27 15:50:52.727 16684 16775 D MaskingMediaPeriod: overridePreparePositionUs() - 66568544 preparePositionUs: -9223372036854775807, preparePositionOverrideUs: -9223372036854775807