Commit 10033623 by andrewlewis Committed by Andrew Lewis

Handle repeat mode/shuffle mode changes in MediaPeriodQueue

This should be a no-op change.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=184150266
parent a075b238
...@@ -416,54 +416,29 @@ import java.util.Collections; ...@@ -416,54 +416,29 @@ import java.util.Collections;
private void setRepeatModeInternal(@Player.RepeatMode int repeatMode) private void setRepeatModeInternal(@Player.RepeatMode int repeatMode)
throws ExoPlaybackException { throws ExoPlaybackException {
this.repeatMode = repeatMode; this.repeatMode = repeatMode;
queue.setRepeatMode(repeatMode); if (!queue.updateRepeatMode(repeatMode)) {
validateExistingPeriodHolders(); seekToCurrentPosition(/* sendDiscontinuity= */ true);
}
} }
private void setShuffleModeEnabledInternal(boolean shuffleModeEnabled) private void setShuffleModeEnabledInternal(boolean shuffleModeEnabled)
throws ExoPlaybackException { throws ExoPlaybackException {
this.shuffleModeEnabled = shuffleModeEnabled; this.shuffleModeEnabled = shuffleModeEnabled;
queue.setShuffleModeEnabled(shuffleModeEnabled); if (!queue.updateShuffleModeEnabled(shuffleModeEnabled)) {
validateExistingPeriodHolders(); seekToCurrentPosition(/* sendDiscontinuity= */ true);
}
private void validateExistingPeriodHolders() throws ExoPlaybackException {
// Find the last existing period holder that matches the new period order.
MediaPeriodHolder lastValidPeriodHolder = queue.getFrontPeriod();
if (lastValidPeriodHolder == null) {
return;
}
while (true) {
int nextPeriodIndex = playbackInfo.timeline.getNextPeriodIndex(
lastValidPeriodHolder.info.id.periodIndex, period, window, repeatMode,
shuffleModeEnabled);
while (lastValidPeriodHolder.next != null
&& !lastValidPeriodHolder.info.isLastInTimelinePeriod) {
lastValidPeriodHolder = lastValidPeriodHolder.next;
}
if (nextPeriodIndex == C.INDEX_UNSET || lastValidPeriodHolder.next == null
|| lastValidPeriodHolder.next.info.id.periodIndex != nextPeriodIndex) {
break;
}
lastValidPeriodHolder = lastValidPeriodHolder.next;
} }
}
// Release any period holders that don't match the new period order. private void seekToCurrentPosition(boolean sendDiscontinuity) throws ExoPlaybackException {
boolean readingPeriodRemoved = queue.removeAfter(lastValidPeriodHolder); // Renderers may have read from a period that's been removed. Seek back to the current
// position of the playing period to make sure none of the removed period is played.
// Update the period info for the last holder, as it may now be the last period in the timeline. MediaPeriodId periodId = queue.getPlayingPeriod().info.id;
lastValidPeriodHolder.info = queue.getUpdatedMediaPeriodInfo(lastValidPeriodHolder.info); long newPositionUs =
seekToPeriodPosition(periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
if (readingPeriodRemoved && queue.hasPlayingPeriod()) { if (newPositionUs != playbackInfo.positionUs) {
// Renderers may have read from a period that's been removed. Seek back to the current playbackInfo =
// position of the playing period to make sure none of the removed period is played. playbackInfo.fromNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
MediaPeriodId periodId = queue.getPlayingPeriod().info.id; if (sendDiscontinuity) {
long newPositionUs =
seekToPeriodPosition(
periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
if (newPositionUs != playbackInfo.positionUs) {
playbackInfo =
playbackInfo.fromNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL); playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
} }
} }
...@@ -1271,13 +1246,7 @@ import java.util.Collections; ...@@ -1271,13 +1246,7 @@ import java.util.Collections;
// The holder is inconsistent with the new timeline. // The holder is inconsistent with the new timeline.
boolean readingPeriodRemoved = queue.removeAfter(previousPeriodHolder); boolean readingPeriodRemoved = queue.removeAfter(previousPeriodHolder);
if (readingPeriodRemoved) { if (readingPeriodRemoved) {
// Renderers may have read from a period that's been removed. Seek back to the current seekToCurrentPosition(/* sendDiscontinuity= */ false);
// position of the playing period to make sure none of the removed period is played.
MediaPeriodId id = queue.getPlayingPeriod().info.id;
long newPositionUs =
seekToPeriodPosition(id, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
playbackInfo =
playbackInfo.fromNewPosition(id, newPositionUs, playbackInfo.contentPositionUs);
} }
break; break;
} }
......
...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.util.Assertions;
* loading media period at the end of the queue, with methods for controlling loading and updating * loading media period at the end of the queue, with methods for controlling loading and updating
* the queue. Also has a reference to the media period currently being read. * the queue. Also has a reference to the media period currently being read.
*/ */
@SuppressWarnings("UngroupedOverloads")
/* package */ final class MediaPeriodQueue { /* package */ final class MediaPeriodQueue {
/** /**
...@@ -66,19 +67,21 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -66,19 +67,21 @@ import com.google.android.exoplayer2.util.Assertions;
} }
/** /**
* Sets the {@link RepeatMode}. Call {@link #getUpdatedMediaPeriodInfo} to update period * Sets the {@link RepeatMode} and returns whether the repeat mode change has been fully handled.
* information taking into account the new repeat mode. * If not, it is necessary to seek to the current playback position.
*/ */
public void setRepeatMode(@RepeatMode int repeatMode) { public boolean updateRepeatMode(@RepeatMode int repeatMode) {
this.repeatMode = repeatMode; this.repeatMode = repeatMode;
return updateForPlaybackModeChange();
} }
/** /**
* Sets whether shuffling is enabled. Call {@link #getUpdatedMediaPeriodInfo} to update period * Sets whether shuffling is enabled and returns whether the shuffle mode change has been fully
* information taking into account the shuffle mode. * handled. If not, it is necessary to seek to the current playback position.
*/ */
public void setShuffleModeEnabled(boolean shuffleModeEnabled) { public boolean updateShuffleModeEnabled(boolean shuffleModeEnabled) {
this.shuffleModeEnabled = shuffleModeEnabled; this.shuffleModeEnabled = shuffleModeEnabled;
return updateForPlaybackModeChange();
} }
/** Returns whether {@code mediaPeriod} is the current loading media period. */ /** Returns whether {@code mediaPeriod} is the current loading media period. */
...@@ -288,17 +291,6 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -288,17 +291,6 @@ import com.google.android.exoplayer2.util.Assertions;
/** /**
* Returns new media period info based on specified {@code mediaPeriodInfo} but taking into * Returns new media period info based on specified {@code mediaPeriodInfo} but taking into
* account the current timeline.
*
* @param mediaPeriodInfo Media period info for a media period based on an old timeline.
* @return The updated media period info for the current timeline.
*/
public MediaPeriodInfo getUpdatedMediaPeriodInfo(MediaPeriodInfo mediaPeriodInfo) {
return getUpdatedMediaPeriodInfo(mediaPeriodInfo, mediaPeriodInfo.id);
}
/**
* Returns new media period info based on specified {@code mediaPeriodInfo} but taking into
* account the current timeline, and with the period index updated to {@code newPeriodIndex}. * account the current timeline, and with the period index updated to {@code newPeriodIndex}.
* *
* @param mediaPeriodInfo Media period info for a media period based on an old timeline. * @param mediaPeriodInfo Media period info for a media period based on an old timeline.
...@@ -334,6 +326,47 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -334,6 +326,47 @@ import com.google.android.exoplayer2.util.Assertions;
// Internal methods. // Internal methods.
/** /**
* Updates the queue for any playback mode change, and returns whether the change was fully
* handled. If not, it is necessary to seek to the current playback position.
*/
private boolean updateForPlaybackModeChange() {
// Find the last existing period holder that matches the new period order.
MediaPeriodHolder lastValidPeriodHolder = getFrontPeriod();
if (lastValidPeriodHolder == null) {
return true;
}
while (true) {
int nextPeriodIndex =
timeline.getNextPeriodIndex(
lastValidPeriodHolder.info.id.periodIndex,
period,
window,
repeatMode,
shuffleModeEnabled);
while (lastValidPeriodHolder.next != null
&& !lastValidPeriodHolder.info.isLastInTimelinePeriod) {
lastValidPeriodHolder = lastValidPeriodHolder.next;
}
if (nextPeriodIndex == C.INDEX_UNSET
|| lastValidPeriodHolder.next == null
|| lastValidPeriodHolder.next.info.id.periodIndex != nextPeriodIndex) {
break;
}
lastValidPeriodHolder = lastValidPeriodHolder.next;
}
// Release any period holders that don't match the new period order.
boolean readingPeriodRemoved = removeAfter(lastValidPeriodHolder);
// Update the period info for the last holder, as it may now be the last period in the timeline.
lastValidPeriodHolder.info =
getUpdatedMediaPeriodInfo(lastValidPeriodHolder.info, lastValidPeriodHolder.info.id);
// If renderers may have read from a period that's been removed, it is necessary to restart.
return !readingPeriodRemoved || !hasPlayingPeriod();
}
/**
* Returns the first {@link MediaPeriodInfo} to play, based on the specified playback position. * Returns the first {@link MediaPeriodInfo} to play, based on the specified playback position.
*/ */
private MediaPeriodInfo getFirstMediaPeriodInfo(PlaybackInfo playbackInfo) { private MediaPeriodInfo getFirstMediaPeriodInfo(PlaybackInfo playbackInfo) {
......
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