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)
|
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 {
|
private void seekToCurrentPosition(boolean sendDiscontinuity) 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()) {
|
|
||||||
// Renderers may have read from a period that's been removed. Seek back to the current
|
// 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.
|
// position of the playing period to make sure none of the removed period is played.
|
||||||
MediaPeriodId periodId = queue.getPlayingPeriod().info.id;
|
MediaPeriodId periodId = queue.getPlayingPeriod().info.id;
|
||||||
long newPositionUs =
|
long newPositionUs =
|
||||||
seekToPeriodPosition(
|
seekToPeriodPosition(periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
||||||
periodId, playbackInfo.positionUs, /* forceDisableRenderers= */ true);
|
|
||||||
if (newPositionUs != playbackInfo.positionUs) {
|
if (newPositionUs != playbackInfo.positionUs) {
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
playbackInfo.fromNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
|
playbackInfo.fromNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs);
|
||||||
|
if (sendDiscontinuity) {
|
||||||
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
|||||||
* 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;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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. */
|
||||||
@ -286,17 +289,6 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||||||
length = 0;
|
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
|
* 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}.
|
||||||
@ -333,6 +325,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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user