Commit 7b82a3c8 by tonihei Committed by Oliver Woodman

Rollback of https://github.com/google/ExoPlayer/commit/5485133e5c7965f98d71da3cb92033b35f596c61

*** Original commit ***

Rollback of https://github.com/google/ExoPlayer/commit/949bbcfb2e98c5cb76ebb35d68fc9f0da4706f16

*** Original commit ***

Add masking for playWhenReady.

Masking is needed as soon as updates to a value can happen both in EPI
and EPII. PlayWhenReady is currently not masked because all updates
happen in EPI only. As soon as we allow pausing at certain times
(e.g. end of a stream), playWhenReady c...

***

PiperOrigin-RevId: 300330307
parent b46f64ab
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Player.PlaybackSuppressionReason;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...@@ -58,6 +59,10 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -58,6 +59,10 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public final TrackSelectorResult trackSelectorResult; public final TrackSelectorResult trackSelectorResult;
/** The {@link MediaPeriodId} of the currently loading media period in the {@link #timeline}. */ /** The {@link MediaPeriodId} of the currently loading media period in the {@link #timeline}. */
public final MediaPeriodId loadingMediaPeriodId; public final MediaPeriodId loadingMediaPeriodId;
/** Whether playback should proceed when {@link #playbackState} == {@link Player#STATE_READY}. */
public final boolean playWhenReady;
/** Reason why playback is suppressed even though {@link #playWhenReady} is {@code true}. */
@PlaybackSuppressionReason public final int playbackSuppressionReason;
/** /**
* Position up to which media is buffered in {@link #loadingMediaPeriodId) relative to the start * Position up to which media is buffered in {@link #loadingMediaPeriodId) relative to the start
...@@ -94,6 +99,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -94,6 +99,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
TrackGroupArray.EMPTY, TrackGroupArray.EMPTY,
emptyTrackSelectorResult, emptyTrackSelectorResult,
DUMMY_MEDIA_PERIOD_ID, DUMMY_MEDIA_PERIOD_ID,
/* playWhenReady= */ false,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
/* bufferedPositionUs= */ 0, /* bufferedPositionUs= */ 0,
/* totalBufferedDurationUs= */ 0, /* totalBufferedDurationUs= */ 0,
/* positionUs= */ 0); /* positionUs= */ 0);
...@@ -124,6 +131,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -124,6 +131,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
TrackGroupArray trackGroups, TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult, TrackSelectorResult trackSelectorResult,
MediaPeriodId loadingMediaPeriodId, MediaPeriodId loadingMediaPeriodId,
boolean playWhenReady,
@PlaybackSuppressionReason int playbackSuppressionReason,
long bufferedPositionUs, long bufferedPositionUs,
long totalBufferedDurationUs, long totalBufferedDurationUs,
long positionUs) { long positionUs) {
...@@ -136,6 +145,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -136,6 +145,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
this.trackGroups = trackGroups; this.trackGroups = trackGroups;
this.trackSelectorResult = trackSelectorResult; this.trackSelectorResult = trackSelectorResult;
this.loadingMediaPeriodId = loadingMediaPeriodId; this.loadingMediaPeriodId = loadingMediaPeriodId;
this.playWhenReady = playWhenReady;
this.playbackSuppressionReason = playbackSuppressionReason;
this.bufferedPositionUs = bufferedPositionUs; this.bufferedPositionUs = bufferedPositionUs;
this.totalBufferedDurationUs = totalBufferedDurationUs; this.totalBufferedDurationUs = totalBufferedDurationUs;
this.positionUs = positionUs; this.positionUs = positionUs;
...@@ -177,6 +188,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -177,6 +188,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
...@@ -200,6 +213,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -200,6 +213,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
...@@ -223,6 +238,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -223,6 +238,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
...@@ -246,6 +263,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -246,6 +263,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
...@@ -269,6 +288,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -269,6 +288,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
...@@ -292,6 +313,37 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -292,6 +313,37 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
trackGroups, trackGroups,
trackSelectorResult, trackSelectorResult,
loadingMediaPeriodId, loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs,
totalBufferedDurationUs,
positionUs);
}
/**
* Copies playback info with new information about whether playback should proceed when ready.
*
* @param playWhenReady Whether playback should proceed when {@link #playbackState} == {@link
* Player#STATE_READY}.
* @param playbackSuppressionReason Reason why playback is suppressed even though {@link
* #playWhenReady} is {@code true}.
* @return Copied playback info with new information.
*/
@CheckResult
public PlaybackInfo copyWithPlayWhenReady(
boolean playWhenReady, @PlaybackSuppressionReason int playbackSuppressionReason) {
return new PlaybackInfo(
timeline,
periodId,
requestedContentPositionUs,
playbackState,
playbackError,
isLoading,
trackGroups,
trackSelectorResult,
loadingMediaPeriodId,
playWhenReady,
playbackSuppressionReason,
bufferedPositionUs, bufferedPositionUs,
totalBufferedDurationUs, totalBufferedDurationUs,
positionUs); positionUs);
......
...@@ -548,6 +548,7 @@ public final class ExoPlayerTest { ...@@ -548,6 +548,7 @@ public final class ExoPlayerTest {
// only on seek processed callback). // only on seek processed callback).
.seek(5) .seek(5)
.seek(60) .seek(60)
.waitForSeekProcessed()
.play() .play()
.build(); .build();
final List<Integer> playbackStatesWhenSeekProcessed = new ArrayList<>(); final List<Integer> playbackStatesWhenSeekProcessed = new ArrayList<>();
...@@ -2790,6 +2791,7 @@ public final class ExoPlayerTest { ...@@ -2790,6 +2791,7 @@ public final class ExoPlayerTest {
.pause() .pause()
.waitForPlaybackState(Player.STATE_READY) .waitForPlaybackState(Player.STATE_READY)
.seek(/* windowIndex= */ 1, /* positionMs= */ 0) .seek(/* windowIndex= */ 1, /* positionMs= */ 0)
.waitForSeekProcessed()
.play() .play()
.build(); .build();
List<TrackGroupArray> trackGroupsList = new ArrayList<>(); List<TrackGroupArray> trackGroupsList = new ArrayList<>();
...@@ -4271,6 +4273,55 @@ public final class ExoPlayerTest { ...@@ -4271,6 +4273,55 @@ public final class ExoPlayerTest {
} }
@Test @Test
public void setPlayWhenReady_keepsCurrentPosition() throws Exception {
AtomicLong positionAfterSetPlayWhenReady = new AtomicLong(C.TIME_UNSET);
ActionSchedule actionSchedule =
new ActionSchedule.Builder(TAG)
.playUntilPosition(0, 5000)
.play()
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
positionAfterSetPlayWhenReady.set(player.getCurrentPosition());
}
})
.build();
new Builder()
.setActionSchedule(actionSchedule)
.build(context)
.start()
.blockUntilEnded(TIMEOUT_MS);
assertThat(positionAfterSetPlayWhenReady.get()).isAtLeast(5000);
}
@Test
public void setShuffleOrder_keepsCurrentPosition() throws Exception {
AtomicLong positionAfterSetShuffleOrder = new AtomicLong(C.TIME_UNSET);
ActionSchedule actionSchedule =
new ActionSchedule.Builder(TAG)
.playUntilPosition(0, 5000)
.setShuffleOrder(new FakeShuffleOrder(/* length= */ 1))
.executeRunnable(
new PlayerRunnable() {
@Override
public void run(SimpleExoPlayer player) {
positionAfterSetShuffleOrder.set(player.getCurrentPosition());
}
})
.play()
.build();
new Builder()
.setActionSchedule(actionSchedule)
.build(context)
.start()
.blockUntilEnded(TIMEOUT_MS);
assertThat(positionAfterSetShuffleOrder.get()).isAtLeast(5000);
}
@Test
public void setMediaSources_empty_whenEmpty_correctMaskingWindowIndex() throws Exception { public void setMediaSources_empty_whenEmpty_correctMaskingWindowIndex() throws Exception {
Timeline secondTimeline = new FakeTimeline(/* windowCount= */ 1); Timeline secondTimeline = new FakeTimeline(/* windowCount= */ 1);
MediaSource secondMediaSource = new FakeMediaSource(secondTimeline); MediaSource secondMediaSource = new FakeMediaSource(secondTimeline);
......
...@@ -421,6 +421,8 @@ public final class MediaPeriodQueueTest { ...@@ -421,6 +421,8 @@ public final class MediaPeriodQueueTest {
/* trackGroups= */ null, /* trackGroups= */ null,
/* trackSelectorResult= */ null, /* trackSelectorResult= */ null,
/* loadingMediaPeriodId= */ null, /* loadingMediaPeriodId= */ null,
/* playWhenReady= */ false,
Player.PLAYBACK_SUPPRESSION_REASON_NONE,
/* bufferedPositionUs= */ 0, /* bufferedPositionUs= */ 0,
/* totalBufferedDurationUs= */ 0, /* totalBufferedDurationUs= */ 0,
/* positionUs= */ 0); /* positionUs= */ 0);
......
...@@ -315,6 +315,7 @@ public final class AnalyticsCollectorTest { ...@@ -315,6 +315,7 @@ public final class AnalyticsCollectorTest {
.pause() .pause()
.waitForPlaybackState(Player.STATE_READY) .waitForPlaybackState(Player.STATE_READY)
.seek(/* windowIndex= */ 1, /* positionMs= */ 0) .seek(/* windowIndex= */ 1, /* positionMs= */ 0)
.waitForSeekProcessed()
.play() .play()
.build(); .build();
TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule); TestAnalyticsListener listener = runAnalyticsTest(mediaSource, actionSchedule);
...@@ -327,8 +328,8 @@ public final class AnalyticsCollectorTest { ...@@ -327,8 +328,8 @@ public final class AnalyticsCollectorTest {
WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* setPlayWhenReady=false */,
period0 /* READY */, period0 /* READY */,
period1 /* BUFFERING */, period1 /* BUFFERING */,
period1 /* READY */,
period1 /* setPlayWhenReady=true */, period1 /* setPlayWhenReady=true */,
period1 /* READY */,
period1 /* ENDED */); period1 /* ENDED */);
assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED))
.containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, period0 /* SOURCE_UPDATE */); .containsExactly(WINDOW_0 /* PLAYLIST_CHANGED */, period0 /* SOURCE_UPDATE */);
...@@ -466,6 +467,9 @@ public final class AnalyticsCollectorTest { ...@@ -466,6 +467,9 @@ public final class AnalyticsCollectorTest {
.pause() .pause()
.waitForPlaybackState(Player.STATE_READY) .waitForPlaybackState(Player.STATE_READY)
.setMediaSources(/* resetPosition= */ false, mediaSource2) .setMediaSources(/* resetPosition= */ false, mediaSource2)
.waitForTimelineChanged()
// Wait until loading started to prevent flakiness caused by loading finishing too fast.
.waitForIsLoading(true)
.play() .play()
.build(); .build();
TestAnalyticsListener listener = runAnalyticsTest(mediaSource1, actionSchedule); TestAnalyticsListener listener = runAnalyticsTest(mediaSource1, actionSchedule);
...@@ -486,7 +490,7 @@ public final class AnalyticsCollectorTest { ...@@ -486,7 +490,7 @@ public final class AnalyticsCollectorTest {
WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* setPlayWhenReady=false */,
period0Seq0 /* READY */, period0Seq0 /* READY */,
WINDOW_0 /* BUFFERING */, WINDOW_0 /* BUFFERING */,
WINDOW_0 /* setPlayWhenReady=true */, period0Seq1 /* setPlayWhenReady=true */,
period0Seq1 /* READY */, period0Seq1 /* READY */,
period0Seq1 /* ENDED */); period0Seq1 /* ENDED */);
assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED))
...@@ -545,6 +549,8 @@ public final class AnalyticsCollectorTest { ...@@ -545,6 +549,8 @@ public final class AnalyticsCollectorTest {
.waitForPlaybackState(Player.STATE_IDLE) .waitForPlaybackState(Player.STATE_IDLE)
.seek(/* positionMs= */ 0) .seek(/* positionMs= */ 0)
.prepare() .prepare()
// Wait until loading started to assert loading events without flakiness.
.waitForIsLoading(true)
.play() .play()
.waitForPlaybackState(Player.STATE_ENDED) .waitForPlaybackState(Player.STATE_ENDED)
.build(); .build();
...@@ -698,6 +704,8 @@ public final class AnalyticsCollectorTest { ...@@ -698,6 +704,8 @@ public final class AnalyticsCollectorTest {
.waitForIsLoading(true) .waitForIsLoading(true)
.waitForIsLoading(false) .waitForIsLoading(false)
.removeMediaItem(/* index= */ 0) .removeMediaItem(/* index= */ 0)
.waitForPlaybackState(Player.STATE_BUFFERING)
.waitForPlaybackState(Player.STATE_READY)
.play() .play()
.build(); .build();
TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule); TestAnalyticsListener listener = runAnalyticsTest(fakeMediaSource, actionSchedule);
...@@ -719,8 +727,8 @@ public final class AnalyticsCollectorTest { ...@@ -719,8 +727,8 @@ public final class AnalyticsCollectorTest {
WINDOW_0 /* BUFFERING */, WINDOW_0 /* BUFFERING */,
period0Seq0 /* READY */, period0Seq0 /* READY */,
period0Seq1 /* BUFFERING */, period0Seq1 /* BUFFERING */,
period0Seq1 /* setPlayWhenReady=true */,
period0Seq1 /* READY */, period0Seq1 /* READY */,
period0Seq1 /* setPlayWhenReady=true */,
period0Seq1 /* ENDED */); period0Seq1 /* ENDED */);
assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED))
.containsExactly( .containsExactly(
...@@ -815,6 +823,19 @@ public final class AnalyticsCollectorTest { ...@@ -815,6 +823,19 @@ public final class AnalyticsCollectorTest {
} }
}) })
.pause() .pause()
// Ensure everything is preloaded.
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForIsLoading(true)
.waitForIsLoading(false)
.waitForPlaybackState(Player.STATE_READY) .waitForPlaybackState(Player.STATE_READY)
// Wait in each content part to ensure previously triggered events get a chance to be // Wait in each content part to ensure previously triggered events get a chance to be
// delivered. This prevents flakiness caused by playback progressing too fast. // delivered. This prevents flakiness caused by playback progressing too fast.
...@@ -1018,6 +1039,8 @@ public final class AnalyticsCollectorTest { ...@@ -1018,6 +1039,8 @@ public final class AnalyticsCollectorTest {
.waitForIsLoading(false) .waitForIsLoading(false)
// Seek behind the midroll. // Seek behind the midroll.
.seek(6 * C.MICROS_PER_SECOND) .seek(6 * C.MICROS_PER_SECOND)
// Wait until loading started again to assert loading events without flakiness.
.waitForIsLoading(true)
.play() .play()
.waitForPlaybackState(Player.STATE_ENDED) .waitForPlaybackState(Player.STATE_ENDED)
.build(); .build();
...@@ -1047,8 +1070,8 @@ public final class AnalyticsCollectorTest { ...@@ -1047,8 +1070,8 @@ public final class AnalyticsCollectorTest {
WINDOW_0 /* setPlayWhenReady=false */, WINDOW_0 /* setPlayWhenReady=false */,
WINDOW_0 /* BUFFERING */, WINDOW_0 /* BUFFERING */,
contentBeforeMidroll /* READY */, contentBeforeMidroll /* READY */,
contentAfterMidroll /* setPlayWhenReady=true */,
midrollAd /* BUFFERING */, midrollAd /* BUFFERING */,
midrollAd /* setPlayWhenReady=true */,
midrollAd /* READY */, midrollAd /* READY */,
contentAfterMidroll /* ENDED */); contentAfterMidroll /* ENDED */);
assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED)) assertThat(listener.getEvents(EVENT_TIMELINE_CHANGED))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment