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
This commit is contained in:
parent
a075b23893
commit
10033623e7
@ -416,54 +416,29 @@ import java.util.Collections;
|
||||
private void setRepeatModeInternal(@Player.RepeatMode int repeatMode)
|
||||
throws ExoPlaybackException {
|
||||
this.repeatMode = repeatMode;
|
||||
queue.setRepeatMode(repeatMode);
|
||||
validateExistingPeriodHolders();
|
||||
if (!queue.updateRepeatMode(repeatMode)) {
|
||||
seekToCurrentPosition(/* sendDiscontinuity= */ true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setShuffleModeEnabledInternal(boolean shuffleModeEnabled)
|
||||
throws ExoPlaybackException {
|
||||
this.shuffleModeEnabled = shuffleModeEnabled;
|
||||
queue.setShuffleModeEnabled(shuffleModeEnabled);
|
||||
validateExistingPeriodHolders();
|
||||
if (!queue.updateShuffleModeEnabled(shuffleModeEnabled)) {
|
||||
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.
|
||||
boolean readingPeriodRemoved = queue.removeAfter(lastValidPeriodHolder);
|
||||
|
||||
// Update the period info for the last holder, as it may now be the last period in the timeline.
|
||||
lastValidPeriodHolder.info = queue.getUpdatedMediaPeriodInfo(lastValidPeriodHolder.info);
|
||||
|
||||
if (readingPeriodRemoved && queue.hasPlayingPeriod()) {
|
||||
private void seekToCurrentPosition(boolean sendDiscontinuity) throws ExoPlaybackException {
|
||||
// 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.
|
||||
MediaPeriodId periodId = queue.getPlayingPeriod().info.id;
|
||||
long newPositionUs =
|
||||
seekToPeriodPosition(
|
||||
periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
||||
seekToPeriodPosition(periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
||||
if (newPositionUs != playbackInfo.positionUs) {
|
||||
playbackInfo =
|
||||
playbackInfo.fromNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
|
||||
if (sendDiscontinuity) {
|
||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||
}
|
||||
}
|
||||
@ -1271,13 +1246,7 @@ import java.util.Collections;
|
||||
// The holder is inconsistent with the new timeline.
|
||||
boolean readingPeriodRemoved = queue.removeAfter(previousPeriodHolder);
|
||||
if (readingPeriodRemoved) {
|
||||
// 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.
|
||||
MediaPeriodId id = queue.getPlayingPeriod().info.id;
|
||||
long newPositionUs =
|
||||
seekToPeriodPosition(id, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
||||
playbackInfo =
|
||||
playbackInfo.fromNewPosition(id, newPositionUs, playbackInfo.contentPositionUs);
|
||||
seekToCurrentPosition(/* sendDiscontinuity= */ false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -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
|
||||
* the queue. Also has a reference to the media period currently being read.
|
||||
*/
|
||||
@SuppressWarnings("UngroupedOverloads")
|
||||
/* package */ final class MediaPeriodQueue {
|
||||
|
||||
/**
|
||||
@ -66,19 +67,21 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RepeatMode}. Call {@link #getUpdatedMediaPeriodInfo} to update period
|
||||
* information taking into account the new repeat mode.
|
||||
* Sets the {@link RepeatMode} and returns whether the repeat mode change has been fully handled.
|
||||
* 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;
|
||||
return updateForPlaybackModeChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether shuffling is enabled. Call {@link #getUpdatedMediaPeriodInfo} to update period
|
||||
* information taking into account the shuffle mode.
|
||||
* Sets whether shuffling is enabled and returns whether the shuffle mode change has been fully
|
||||
* 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;
|
||||
return updateForPlaybackModeChange();
|
||||
}
|
||||
|
||||
/** Returns whether {@code mediaPeriod} is the current loading media period. */
|
||||
@ -286,17 +289,6 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
@ -333,6 +325,47 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
|
||||
// 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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user