mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Untangle PlayerInfo/PlaybackInfo updates
The methods in ExoPlayerImpl and MediaControllerImplBase that determine the new PlayerInfo/PlaybackInfo currently have a hard-to-reason-about setup where the method generating the new info accesses other methods that rely on the existing class field instead of working with the passed in PlayerInfo/PlaybackInfo. This prevents reuse of the util methods (e.g. for replaceMediaItems) because they access potentially stale state. This change untangles these methods a bit by making the util methods either static or at least ensure that they don't rely on existing class fields of PlayerInfo/PlaybackInfo. Overall, the change is a complete no-op. #minor-release PiperOrigin-RevId: 534036633 (cherry picked from commit 1fa790348e7e90c987d3385a79a2c7c150cd6824)
This commit is contained in:
parent
44ffea2477
commit
1b007deca0
@ -659,16 +659,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
setMediaSources(mediaSources, /* resetPosition= */ maskingWindowIndex == C.INDEX_UNSET);
|
setMediaSources(mediaSources, /* resetPosition= */ maskingWindowIndex == C.INDEX_UNSET);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Timeline oldTimeline = getCurrentTimeline();
|
PlaybackInfo newPlaybackInfo = addMediaSourcesInternal(playbackInfo, index, mediaSources);
|
||||||
pendingOperationAcks++;
|
|
||||||
List<MediaSourceList.MediaSourceHolder> holders = addMediaSourceHolders(index, mediaSources);
|
|
||||||
Timeline newTimeline = createMaskingTimeline();
|
|
||||||
PlaybackInfo newPlaybackInfo =
|
|
||||||
maskTimelineAndPosition(
|
|
||||||
playbackInfo,
|
|
||||||
newTimeline,
|
|
||||||
getPeriodPositionUsAfterTimelineChanged(oldTimeline, newTimeline));
|
|
||||||
internalPlayer.addMediaSources(index, holders, shuffleOrder);
|
|
||||||
updatePlaybackInfo(
|
updatePlaybackInfo(
|
||||||
newPlaybackInfo,
|
newPlaybackInfo,
|
||||||
/* timelineChangeReason= */ TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
/* timelineChangeReason= */ TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
||||||
@ -691,7 +682,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
// Do nothing.
|
// Do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PlaybackInfo newPlaybackInfo = removeMediaItemsInternal(fromIndex, toIndex);
|
PlaybackInfo newPlaybackInfo = removeMediaItemsInternal(playbackInfo, fromIndex, toIndex);
|
||||||
boolean positionDiscontinuity =
|
boolean positionDiscontinuity =
|
||||||
!newPlaybackInfo.periodId.periodUid.equals(playbackInfo.periodId.periodUid);
|
!newPlaybackInfo.periodId.periodUid.equals(playbackInfo.periodId.periodUid);
|
||||||
updatePlaybackInfo(
|
updatePlaybackInfo(
|
||||||
@ -725,7 +716,11 @@ import java.util.concurrent.TimeoutException;
|
|||||||
maskTimelineAndPosition(
|
maskTimelineAndPosition(
|
||||||
playbackInfo,
|
playbackInfo,
|
||||||
newTimeline,
|
newTimeline,
|
||||||
getPeriodPositionUsAfterTimelineChanged(oldTimeline, newTimeline));
|
getPeriodPositionUsAfterTimelineChanged(
|
||||||
|
oldTimeline,
|
||||||
|
newTimeline,
|
||||||
|
getCurrentWindowIndexInternal(playbackInfo),
|
||||||
|
getContentPositionInternal(playbackInfo)));
|
||||||
internalPlayer.moveMediaSources(fromIndex, toIndex, newFromIndex, shuffleOrder);
|
internalPlayer.moveMediaSources(fromIndex, toIndex, newFromIndex, shuffleOrder);
|
||||||
updatePlaybackInfo(
|
updatePlaybackInfo(
|
||||||
newPlaybackInfo,
|
newPlaybackInfo,
|
||||||
@ -1057,7 +1052,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public int getCurrentMediaItemIndex() {
|
public int getCurrentMediaItemIndex() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
int currentWindowIndex = getCurrentWindowIndexInternal();
|
int currentWindowIndex = getCurrentWindowIndexInternal(playbackInfo);
|
||||||
return currentWindowIndex == C.INDEX_UNSET ? 0 : currentWindowIndex;
|
return currentWindowIndex == C.INDEX_UNSET ? 0 : currentWindowIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,17 +1112,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
@Override
|
@Override
|
||||||
public long getContentPosition() {
|
public long getContentPosition() {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
if (isPlayingAd()) {
|
return getContentPositionInternal(playbackInfo);
|
||||||
playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period);
|
|
||||||
return playbackInfo.requestedContentPositionUs == C.TIME_UNSET
|
|
||||||
? playbackInfo
|
|
||||||
.timeline
|
|
||||||
.getWindow(getCurrentMediaItemIndex(), window)
|
|
||||||
.getDefaultPositionMs()
|
|
||||||
: period.getPositionInWindowMs() + Util.usToMs(playbackInfo.requestedContentPositionUs);
|
|
||||||
} else {
|
|
||||||
return getCurrentPosition();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1853,13 +1838,25 @@ import java.util.concurrent.TimeoutException;
|
|||||||
/* repeatCurrentMediaItem= */ false);
|
/* repeatCurrentMediaItem= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentWindowIndexInternal() {
|
private int getCurrentWindowIndexInternal(PlaybackInfo playbackInfo) {
|
||||||
if (playbackInfo.timeline.isEmpty()) {
|
if (playbackInfo.timeline.isEmpty()) {
|
||||||
return maskingWindowIndex;
|
return maskingWindowIndex;
|
||||||
} else {
|
|
||||||
return playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period)
|
|
||||||
.windowIndex;
|
|
||||||
}
|
}
|
||||||
|
return playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period)
|
||||||
|
.windowIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getContentPositionInternal(PlaybackInfo playbackInfo) {
|
||||||
|
if (playbackInfo.periodId.isAd()) {
|
||||||
|
playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period);
|
||||||
|
return playbackInfo.requestedContentPositionUs == C.TIME_UNSET
|
||||||
|
? playbackInfo
|
||||||
|
.timeline
|
||||||
|
.getWindow(getCurrentWindowIndexInternal(playbackInfo), window)
|
||||||
|
.getDefaultPositionMs()
|
||||||
|
: period.getPositionInWindowMs() + Util.usToMs(playbackInfo.requestedContentPositionUs);
|
||||||
|
}
|
||||||
|
return Util.usToMs(getCurrentPositionUsInternal(playbackInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getCurrentPositionUsInternal(PlaybackInfo playbackInfo) {
|
private long getCurrentPositionUsInternal(PlaybackInfo playbackInfo) {
|
||||||
@ -1874,10 +1871,9 @@ import java.util.concurrent.TimeoutException;
|
|||||||
|
|
||||||
if (playbackInfo.periodId.isAd()) {
|
if (playbackInfo.periodId.isAd()) {
|
||||||
return positionUs;
|
return positionUs;
|
||||||
} else {
|
|
||||||
return periodPositionUsToWindowPositionUs(
|
|
||||||
playbackInfo.timeline, playbackInfo.periodId, positionUs);
|
|
||||||
}
|
}
|
||||||
|
return periodPositionUsToWindowPositionUs(
|
||||||
|
playbackInfo.timeline, playbackInfo.periodId, positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MediaSource> createMediaSources(List<MediaItem> mediaItems) {
|
private List<MediaSource> createMediaSources(List<MediaItem> mediaItems) {
|
||||||
@ -2276,7 +2272,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
int startWindowIndex,
|
int startWindowIndex,
|
||||||
long startPositionMs,
|
long startPositionMs,
|
||||||
boolean resetToDefaultPosition) {
|
boolean resetToDefaultPosition) {
|
||||||
int currentWindowIndex = getCurrentWindowIndexInternal();
|
int currentWindowIndex = getCurrentWindowIndexInternal(playbackInfo);
|
||||||
long currentPositionMs = getCurrentPosition();
|
long currentPositionMs = getCurrentPosition();
|
||||||
pendingOperationAcks++;
|
pendingOperationAcks++;
|
||||||
if (!mediaSourceHolderSnapshots.isEmpty()) {
|
if (!mediaSourceHolderSnapshots.isEmpty()) {
|
||||||
@ -2347,9 +2343,30 @@ import java.util.concurrent.TimeoutException;
|
|||||||
return holders;
|
return holders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaybackInfo removeMediaItemsInternal(int fromIndex, int toIndex) {
|
private PlaybackInfo addMediaSourcesInternal(
|
||||||
int currentIndex = getCurrentMediaItemIndex();
|
PlaybackInfo playbackInfo, int index, List<MediaSource> mediaSources) {
|
||||||
Timeline oldTimeline = getCurrentTimeline();
|
Timeline oldTimeline = playbackInfo.timeline;
|
||||||
|
pendingOperationAcks++;
|
||||||
|
List<MediaSourceList.MediaSourceHolder> holders = addMediaSourceHolders(index, mediaSources);
|
||||||
|
Timeline newTimeline = createMaskingTimeline();
|
||||||
|
PlaybackInfo newPlaybackInfo =
|
||||||
|
maskTimelineAndPosition(
|
||||||
|
playbackInfo,
|
||||||
|
newTimeline,
|
||||||
|
getPeriodPositionUsAfterTimelineChanged(
|
||||||
|
oldTimeline,
|
||||||
|
newTimeline,
|
||||||
|
getCurrentWindowIndexInternal(playbackInfo),
|
||||||
|
getContentPositionInternal(playbackInfo)));
|
||||||
|
internalPlayer.addMediaSources(index, holders, shuffleOrder);
|
||||||
|
return newPlaybackInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlaybackInfo removeMediaItemsInternal(
|
||||||
|
PlaybackInfo playbackInfo, int fromIndex, int toIndex) {
|
||||||
|
int currentIndex = getCurrentWindowIndexInternal(playbackInfo);
|
||||||
|
long contentPositionMs = getContentPositionInternal(playbackInfo);
|
||||||
|
Timeline oldTimeline = playbackInfo.timeline;
|
||||||
int currentMediaSourceCount = mediaSourceHolderSnapshots.size();
|
int currentMediaSourceCount = mediaSourceHolderSnapshots.size();
|
||||||
pendingOperationAcks++;
|
pendingOperationAcks++;
|
||||||
removeMediaSourceHolders(fromIndex, /* toIndexExclusive= */ toIndex);
|
removeMediaSourceHolders(fromIndex, /* toIndexExclusive= */ toIndex);
|
||||||
@ -2358,7 +2375,8 @@ import java.util.concurrent.TimeoutException;
|
|||||||
maskTimelineAndPosition(
|
maskTimelineAndPosition(
|
||||||
playbackInfo,
|
playbackInfo,
|
||||||
newTimeline,
|
newTimeline,
|
||||||
getPeriodPositionUsAfterTimelineChanged(oldTimeline, newTimeline));
|
getPeriodPositionUsAfterTimelineChanged(
|
||||||
|
oldTimeline, newTimeline, currentIndex, contentPositionMs));
|
||||||
// Player transitions to STATE_ENDED if the current index is part of the removed tail.
|
// Player transitions to STATE_ENDED if the current index is part of the removed tail.
|
||||||
final boolean transitionsToEnded =
|
final boolean transitionsToEnded =
|
||||||
newPlaybackInfo.playbackState != STATE_IDLE
|
newPlaybackInfo.playbackState != STATE_IDLE
|
||||||
@ -2387,7 +2405,9 @@ import java.util.concurrent.TimeoutException;
|
|||||||
private PlaybackInfo maskTimelineAndPosition(
|
private PlaybackInfo maskTimelineAndPosition(
|
||||||
PlaybackInfo playbackInfo, Timeline timeline, @Nullable Pair<Object, Long> periodPositionUs) {
|
PlaybackInfo playbackInfo, Timeline timeline, @Nullable Pair<Object, Long> periodPositionUs) {
|
||||||
checkArgument(timeline.isEmpty() || periodPositionUs != null);
|
checkArgument(timeline.isEmpty() || periodPositionUs != null);
|
||||||
|
// Get the old timeline and position before updating playbackInfo.
|
||||||
Timeline oldTimeline = playbackInfo.timeline;
|
Timeline oldTimeline = playbackInfo.timeline;
|
||||||
|
long oldContentPositionMs = getContentPositionInternal(playbackInfo);
|
||||||
// Mask the timeline.
|
// Mask the timeline.
|
||||||
playbackInfo = playbackInfo.copyWithTimeline(timeline);
|
playbackInfo = playbackInfo.copyWithTimeline(timeline);
|
||||||
|
|
||||||
@ -2415,7 +2435,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
MediaPeriodId newPeriodId =
|
MediaPeriodId newPeriodId =
|
||||||
playingPeriodChanged ? new MediaPeriodId(periodPositionUs.first) : playbackInfo.periodId;
|
playingPeriodChanged ? new MediaPeriodId(periodPositionUs.first) : playbackInfo.periodId;
|
||||||
long newContentPositionUs = periodPositionUs.second;
|
long newContentPositionUs = periodPositionUs.second;
|
||||||
long oldContentPositionUs = Util.msToUs(getContentPosition());
|
long oldContentPositionUs = Util.msToUs(oldContentPositionMs);
|
||||||
if (!oldTimeline.isEmpty()) {
|
if (!oldTimeline.isEmpty()) {
|
||||||
oldContentPositionUs -=
|
oldContentPositionUs -=
|
||||||
oldTimeline.getPeriodByUid(oldPeriodUid, period).getPositionInWindowUs();
|
oldTimeline.getPeriodByUid(oldPeriodUid, period).getPositionInWindowUs();
|
||||||
@ -2491,20 +2511,21 @@ import java.util.concurrent.TimeoutException;
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Pair<Object, Long> getPeriodPositionUsAfterTimelineChanged(
|
private Pair<Object, Long> getPeriodPositionUsAfterTimelineChanged(
|
||||||
Timeline oldTimeline, Timeline newTimeline) {
|
Timeline oldTimeline,
|
||||||
long currentPositionMs = getContentPosition();
|
Timeline newTimeline,
|
||||||
|
int currentWindowIndexInternal,
|
||||||
|
long contentPositionMs) {
|
||||||
if (oldTimeline.isEmpty() || newTimeline.isEmpty()) {
|
if (oldTimeline.isEmpty() || newTimeline.isEmpty()) {
|
||||||
boolean isCleared = !oldTimeline.isEmpty() && newTimeline.isEmpty();
|
boolean isCleared = !oldTimeline.isEmpty() && newTimeline.isEmpty();
|
||||||
return maskWindowPositionMsOrGetPeriodPositionUs(
|
return maskWindowPositionMsOrGetPeriodPositionUs(
|
||||||
newTimeline,
|
newTimeline,
|
||||||
isCleared ? C.INDEX_UNSET : getCurrentWindowIndexInternal(),
|
isCleared ? C.INDEX_UNSET : currentWindowIndexInternal,
|
||||||
isCleared ? C.TIME_UNSET : currentPositionMs);
|
isCleared ? C.TIME_UNSET : contentPositionMs);
|
||||||
}
|
}
|
||||||
int currentMediaItemIndex = getCurrentMediaItemIndex();
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Pair<Object, Long> oldPeriodPositionUs =
|
Pair<Object, Long> oldPeriodPositionUs =
|
||||||
oldTimeline.getPeriodPositionUs(
|
oldTimeline.getPeriodPositionUs(
|
||||||
window, period, currentMediaItemIndex, Util.msToUs(currentPositionMs));
|
window, period, currentWindowIndexInternal, Util.msToUs(contentPositionMs));
|
||||||
Object periodUid = castNonNull(oldPeriodPositionUs).first;
|
Object periodUid = castNonNull(oldPeriodPositionUs).first;
|
||||||
if (newTimeline.getIndexOfPeriod(periodUid) != C.INDEX_UNSET) {
|
if (newTimeline.getIndexOfPeriod(periodUid) != C.INDEX_UNSET) {
|
||||||
// The old period position is still available in the new timeline.
|
// The old period position is still available in the new timeline.
|
||||||
@ -2556,7 +2577,7 @@ import java.util.concurrent.TimeoutException;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PlayerMessage createMessageInternal(Target target) {
|
private PlayerMessage createMessageInternal(Target target) {
|
||||||
int currentWindowIndex = getCurrentWindowIndexInternal();
|
int currentWindowIndex = getCurrentWindowIndexInternal(playbackInfo);
|
||||||
return new PlayerMessage(
|
return new PlayerMessage(
|
||||||
internalPlayer,
|
internalPlayer,
|
||||||
target,
|
target,
|
||||||
|
@ -920,7 +920,19 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
}
|
}
|
||||||
// Add media items to the end of the timeline if the index exceeds the window count.
|
// Add media items to the end of the timeline if the index exceeds the window count.
|
||||||
index = min(index, playerInfo.timeline.getWindowCount());
|
index = min(index, playerInfo.timeline.getWindowCount());
|
||||||
|
PlayerInfo newPlayerInfo = maskPlaybackInfoForAddedItems(playerInfo, index, mediaItems);
|
||||||
|
updatePlayerInfo(
|
||||||
|
newPlayerInfo,
|
||||||
|
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
||||||
|
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
||||||
|
/* positionDiscontinuity= */ false,
|
||||||
|
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
|
||||||
|
/* mediaItemTransition= */ playerInfo.timeline.isEmpty(),
|
||||||
|
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlayerInfo maskPlaybackInfoForAddedItems(
|
||||||
|
PlayerInfo playerInfo, int index, List<MediaItem> mediaItems) {
|
||||||
Timeline oldTimeline = playerInfo.timeline;
|
Timeline oldTimeline = playerInfo.timeline;
|
||||||
List<Window> newWindows = new ArrayList<>();
|
List<Window> newWindows = new ArrayList<>();
|
||||||
List<Period> newPeriods = new ArrayList<>();
|
List<Period> newPeriods = new ArrayList<>();
|
||||||
@ -948,21 +960,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
? playerInfo.sessionPositionInfo.positionInfo.periodIndex + mediaItems.size()
|
? playerInfo.sessionPositionInfo.positionInfo.periodIndex + mediaItems.size()
|
||||||
: playerInfo.sessionPositionInfo.positionInfo.periodIndex;
|
: playerInfo.sessionPositionInfo.positionInfo.periodIndex;
|
||||||
}
|
}
|
||||||
PlayerInfo newPlayerInfo =
|
return maskTimelineAndPositionInfo(
|
||||||
maskTimelineAndPositionInfo(
|
playerInfo,
|
||||||
playerInfo,
|
newTimeline,
|
||||||
newTimeline,
|
newMediaItemIndex,
|
||||||
newMediaItemIndex,
|
newPeriodIndex,
|
||||||
newPeriodIndex,
|
Player.DISCONTINUITY_REASON_INTERNAL);
|
||||||
Player.DISCONTINUITY_REASON_INTERNAL);
|
|
||||||
updatePlayerInfo(
|
|
||||||
newPlayerInfo,
|
|
||||||
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
|
||||||
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
|
||||||
/* positionDiscontinuity= */ false,
|
|
||||||
/* ignored */ Player.DISCONTINUITY_REASON_INTERNAL,
|
|
||||||
/* mediaItemTransition= */ oldTimeline.isEmpty(),
|
|
||||||
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1004,13 +1007,29 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeMediaItemsInternal(int fromIndex, int toIndex) {
|
private void removeMediaItemsInternal(int fromIndex, int toIndex) {
|
||||||
Timeline oldTimeline = playerInfo.timeline;
|
|
||||||
int playlistSize = playerInfo.timeline.getWindowCount();
|
int playlistSize = playerInfo.timeline.getWindowCount();
|
||||||
toIndex = min(toIndex, playlistSize);
|
toIndex = min(toIndex, playlistSize);
|
||||||
if (fromIndex >= playlistSize || fromIndex == toIndex) {
|
if (fromIndex >= playlistSize || fromIndex == toIndex || playlistSize == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
boolean currentItemRemoved =
|
||||||
|
getCurrentMediaItemIndex() >= fromIndex && getCurrentMediaItemIndex() < toIndex;
|
||||||
|
PlayerInfo newPlayerInfo = maskPlayerInfoForRemovedItems(playerInfo, fromIndex, toIndex);
|
||||||
|
updatePlayerInfo(
|
||||||
|
newPlayerInfo,
|
||||||
|
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
||||||
|
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
||||||
|
/* positionDiscontinuity= */ currentItemRemoved,
|
||||||
|
Player.DISCONTINUITY_REASON_REMOVE,
|
||||||
|
/* mediaItemTransition= */ playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex
|
||||||
|
>= fromIndex
|
||||||
|
&& playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex < toIndex,
|
||||||
|
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlayerInfo maskPlayerInfoForRemovedItems(
|
||||||
|
PlayerInfo playerInfo, int fromIndex, int toIndex) {
|
||||||
|
Timeline oldTimeline = playerInfo.timeline;
|
||||||
List<Window> newWindows = new ArrayList<>();
|
List<Window> newWindows = new ArrayList<>();
|
||||||
List<Period> newPeriods = new ArrayList<>();
|
List<Period> newPeriods = new ArrayList<>();
|
||||||
for (int i = 0; i < oldTimeline.getWindowCount(); i++) {
|
for (int i = 0; i < oldTimeline.getWindowCount(); i++) {
|
||||||
@ -1021,124 +1040,109 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
rebuildPeriods(oldTimeline, newWindows, newPeriods);
|
rebuildPeriods(oldTimeline, newWindows, newPeriods);
|
||||||
Timeline newTimeline = createMaskingTimeline(newWindows, newPeriods);
|
Timeline newTimeline = createMaskingTimeline(newWindows, newPeriods);
|
||||||
|
|
||||||
int oldMediaItemIndex = getCurrentMediaItemIndex();
|
int oldMediaItemIndex = getCurrentMediaItemIndexInternal(playerInfo);
|
||||||
int newMediaItemIndex = oldMediaItemIndex;
|
int newMediaItemIndex = oldMediaItemIndex;
|
||||||
int oldPeriodIndex = playerInfo.sessionPositionInfo.positionInfo.periodIndex;
|
int oldPeriodIndex = playerInfo.sessionPositionInfo.positionInfo.periodIndex;
|
||||||
int newPeriodIndex = oldPeriodIndex;
|
int newPeriodIndex = oldPeriodIndex;
|
||||||
boolean currentItemRemoved =
|
|
||||||
getCurrentMediaItemIndex() >= fromIndex && getCurrentMediaItemIndex() < toIndex;
|
|
||||||
Window window = new Window();
|
Window window = new Window();
|
||||||
if (oldTimeline.isEmpty()) {
|
boolean currentItemRemoved = oldMediaItemIndex >= fromIndex && oldMediaItemIndex < toIndex;
|
||||||
// No masking required. Just forwarding command to session.
|
if (newTimeline.isEmpty()) {
|
||||||
|
newMediaItemIndex = C.INDEX_UNSET;
|
||||||
|
newPeriodIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
if (newTimeline.isEmpty()) {
|
|
||||||
newMediaItemIndex = C.INDEX_UNSET;
|
|
||||||
newPeriodIndex = 0;
|
|
||||||
} else {
|
|
||||||
if (currentItemRemoved) {
|
|
||||||
int oldNextMediaItemIndex =
|
|
||||||
resolveSubsequentMediaItemIndex(
|
|
||||||
getRepeatMode(),
|
|
||||||
getShuffleModeEnabled(),
|
|
||||||
oldMediaItemIndex,
|
|
||||||
oldTimeline,
|
|
||||||
fromIndex,
|
|
||||||
toIndex);
|
|
||||||
if (oldNextMediaItemIndex == C.INDEX_UNSET) {
|
|
||||||
newMediaItemIndex = newTimeline.getFirstWindowIndex(getShuffleModeEnabled());
|
|
||||||
} else if (oldNextMediaItemIndex >= toIndex) {
|
|
||||||
newMediaItemIndex = oldNextMediaItemIndex - (toIndex - fromIndex);
|
|
||||||
} else {
|
|
||||||
newMediaItemIndex = oldNextMediaItemIndex;
|
|
||||||
}
|
|
||||||
newPeriodIndex = newTimeline.getWindow(newMediaItemIndex, window).firstPeriodIndex;
|
|
||||||
} else if (oldMediaItemIndex >= toIndex) {
|
|
||||||
newMediaItemIndex -= (toIndex - fromIndex);
|
|
||||||
newPeriodIndex =
|
|
||||||
getNewPeriodIndexWithoutRemovedPeriods(
|
|
||||||
oldTimeline, oldPeriodIndex, fromIndex, toIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerInfo newPlayerInfo;
|
|
||||||
if (currentItemRemoved) {
|
if (currentItemRemoved) {
|
||||||
PositionInfo newPositionInfo;
|
int oldNextMediaItemIndex =
|
||||||
if (newMediaItemIndex == C.INDEX_UNSET) {
|
resolveSubsequentMediaItemIndex(
|
||||||
newPositionInfo = SessionPositionInfo.DEFAULT_POSITION_INFO;
|
playerInfo.repeatMode,
|
||||||
newPlayerInfo =
|
playerInfo.shuffleModeEnabled,
|
||||||
maskTimelineAndPositionInfo(
|
oldMediaItemIndex,
|
||||||
playerInfo,
|
oldTimeline,
|
||||||
newTimeline,
|
fromIndex,
|
||||||
newPositionInfo,
|
toIndex);
|
||||||
SessionPositionInfo.DEFAULT,
|
if (oldNextMediaItemIndex == C.INDEX_UNSET) {
|
||||||
Player.DISCONTINUITY_REASON_REMOVE);
|
newMediaItemIndex = newTimeline.getFirstWindowIndex(playerInfo.shuffleModeEnabled);
|
||||||
|
} else if (oldNextMediaItemIndex >= toIndex) {
|
||||||
|
newMediaItemIndex = oldNextMediaItemIndex - (toIndex - fromIndex);
|
||||||
} else {
|
} else {
|
||||||
Window newWindow = newTimeline.getWindow(newMediaItemIndex, new Window());
|
newMediaItemIndex = oldNextMediaItemIndex;
|
||||||
long defaultPositionMs = newWindow.getDefaultPositionMs();
|
|
||||||
long durationMs = newWindow.getDurationMs();
|
|
||||||
newPositionInfo =
|
|
||||||
new PositionInfo(
|
|
||||||
/* windowUid= */ null,
|
|
||||||
newMediaItemIndex,
|
|
||||||
newWindow.mediaItem,
|
|
||||||
/* periodUid= */ null,
|
|
||||||
newPeriodIndex,
|
|
||||||
/* positionMs= */ defaultPositionMs,
|
|
||||||
/* contentPositionMs= */ defaultPositionMs,
|
|
||||||
/* adGroupIndex= */ C.INDEX_UNSET,
|
|
||||||
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
|
||||||
newPlayerInfo =
|
|
||||||
maskTimelineAndPositionInfo(
|
|
||||||
playerInfo,
|
|
||||||
newTimeline,
|
|
||||||
newPositionInfo,
|
|
||||||
new SessionPositionInfo(
|
|
||||||
newPositionInfo,
|
|
||||||
/* isPlayingAd= */ false,
|
|
||||||
/* eventTimeMs= */ SystemClock.elapsedRealtime(),
|
|
||||||
/* durationMs= */ durationMs,
|
|
||||||
/* bufferedPositionMs= */ defaultPositionMs,
|
|
||||||
/* bufferedPercentage= */ calculateBufferedPercentage(
|
|
||||||
defaultPositionMs, durationMs),
|
|
||||||
/* totalBufferedDurationMs= */ 0,
|
|
||||||
/* currentLiveOffsetMs= */ C.TIME_UNSET,
|
|
||||||
/* contentDurationMs= */ durationMs,
|
|
||||||
/* contentBufferedPositionMs= */ defaultPositionMs),
|
|
||||||
Player.DISCONTINUITY_REASON_REMOVE);
|
|
||||||
}
|
}
|
||||||
} else {
|
newPeriodIndex = newTimeline.getWindow(newMediaItemIndex, window).firstPeriodIndex;
|
||||||
|
} else if (oldMediaItemIndex >= toIndex) {
|
||||||
|
newMediaItemIndex -= (toIndex - fromIndex);
|
||||||
|
newPeriodIndex =
|
||||||
|
getNewPeriodIndexWithoutRemovedPeriods(oldTimeline, oldPeriodIndex, fromIndex, toIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerInfo newPlayerInfo;
|
||||||
|
if (currentItemRemoved) {
|
||||||
|
PositionInfo newPositionInfo;
|
||||||
|
if (newMediaItemIndex == C.INDEX_UNSET) {
|
||||||
|
newPositionInfo = SessionPositionInfo.DEFAULT_POSITION_INFO;
|
||||||
newPlayerInfo =
|
newPlayerInfo =
|
||||||
maskTimelineAndPositionInfo(
|
maskTimelineAndPositionInfo(
|
||||||
playerInfo,
|
playerInfo,
|
||||||
newTimeline,
|
newTimeline,
|
||||||
|
newPositionInfo,
|
||||||
|
SessionPositionInfo.DEFAULT,
|
||||||
|
Player.DISCONTINUITY_REASON_REMOVE);
|
||||||
|
} else {
|
||||||
|
Window newWindow = newTimeline.getWindow(newMediaItemIndex, new Window());
|
||||||
|
long defaultPositionMs = newWindow.getDefaultPositionMs();
|
||||||
|
long durationMs = newWindow.getDurationMs();
|
||||||
|
newPositionInfo =
|
||||||
|
new PositionInfo(
|
||||||
|
/* windowUid= */ null,
|
||||||
newMediaItemIndex,
|
newMediaItemIndex,
|
||||||
|
newWindow.mediaItem,
|
||||||
|
/* periodUid= */ null,
|
||||||
newPeriodIndex,
|
newPeriodIndex,
|
||||||
|
/* positionMs= */ defaultPositionMs,
|
||||||
|
/* contentPositionMs= */ defaultPositionMs,
|
||||||
|
/* adGroupIndex= */ C.INDEX_UNSET,
|
||||||
|
/* adIndexInAdGroup= */ C.INDEX_UNSET);
|
||||||
|
newPlayerInfo =
|
||||||
|
maskTimelineAndPositionInfo(
|
||||||
|
playerInfo,
|
||||||
|
newTimeline,
|
||||||
|
newPositionInfo,
|
||||||
|
new SessionPositionInfo(
|
||||||
|
newPositionInfo,
|
||||||
|
/* isPlayingAd= */ false,
|
||||||
|
/* eventTimeMs= */ SystemClock.elapsedRealtime(),
|
||||||
|
/* durationMs= */ durationMs,
|
||||||
|
/* bufferedPositionMs= */ defaultPositionMs,
|
||||||
|
/* bufferedPercentage= */ calculateBufferedPercentage(
|
||||||
|
defaultPositionMs, durationMs),
|
||||||
|
/* totalBufferedDurationMs= */ 0,
|
||||||
|
/* currentLiveOffsetMs= */ C.TIME_UNSET,
|
||||||
|
/* contentDurationMs= */ durationMs,
|
||||||
|
/* contentBufferedPositionMs= */ defaultPositionMs),
|
||||||
Player.DISCONTINUITY_REASON_REMOVE);
|
Player.DISCONTINUITY_REASON_REMOVE);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// Player transitions to Player.STATE_ENDED if the current index is part of the removed tail.
|
newPlayerInfo =
|
||||||
final boolean transitionsToEnded =
|
maskTimelineAndPositionInfo(
|
||||||
newPlayerInfo.playbackState != Player.STATE_IDLE
|
playerInfo,
|
||||||
&& newPlayerInfo.playbackState != Player.STATE_ENDED
|
newTimeline,
|
||||||
&& fromIndex < toIndex
|
newMediaItemIndex,
|
||||||
&& toIndex == oldTimeline.getWindowCount()
|
newPeriodIndex,
|
||||||
&& getCurrentMediaItemIndex() >= fromIndex;
|
Player.DISCONTINUITY_REASON_REMOVE);
|
||||||
if (transitionsToEnded) {
|
|
||||||
newPlayerInfo =
|
|
||||||
newPlayerInfo.copyWithPlaybackState(Player.STATE_ENDED, /* playerError= */ null);
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePlayerInfo(
|
|
||||||
newPlayerInfo,
|
|
||||||
/* timelineChangeReason= */ Player.TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED,
|
|
||||||
/* ignored */ Player.PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST,
|
|
||||||
/* positionDiscontinuity= */ currentItemRemoved,
|
|
||||||
Player.DISCONTINUITY_REASON_REMOVE,
|
|
||||||
/* mediaItemTransition= */ playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex
|
|
||||||
>= fromIndex
|
|
||||||
&& playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex < toIndex,
|
|
||||||
Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Player transitions to Player.STATE_ENDED if the current index is part of the removed tail.
|
||||||
|
final boolean transitionsToEnded =
|
||||||
|
newPlayerInfo.playbackState != Player.STATE_IDLE
|
||||||
|
&& newPlayerInfo.playbackState != Player.STATE_ENDED
|
||||||
|
&& fromIndex < toIndex
|
||||||
|
&& toIndex == oldTimeline.getWindowCount()
|
||||||
|
&& oldMediaItemIndex >= fromIndex;
|
||||||
|
if (transitionsToEnded) {
|
||||||
|
newPlayerInfo =
|
||||||
|
newPlayerInfo.copyWithPlaybackState(Player.STATE_ENDED, /* playerError= */ null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPlayerInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1176,9 +1180,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCurrentMediaItemIndex() {
|
public int getCurrentMediaItemIndex() {
|
||||||
return playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex == C.INDEX_UNSET
|
return getCurrentMediaItemIndexInternal(playerInfo);
|
||||||
? 0
|
|
||||||
: playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/184479406): Get the index directly from Player rather than Timeline.
|
// TODO(b/184479406): Get the index directly from Player rather than Timeline.
|
||||||
@ -1773,7 +1775,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Timeline createMaskingTimeline(List<Window> windows, List<Period> periods) {
|
private static Timeline createMaskingTimeline(List<Window> windows, List<Period> periods) {
|
||||||
return new RemotableTimeline(
|
return new RemotableTimeline(
|
||||||
new ImmutableList.Builder<Window>().addAll(windows).build(),
|
new ImmutableList.Builder<Window>().addAll(windows).build(),
|
||||||
new ImmutableList.Builder<Period>().addAll(periods).build(),
|
new ImmutableList.Builder<Period>().addAll(periods).build(),
|
||||||
@ -2751,7 +2753,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PeriodInfo getPeriodInfo(
|
private static PeriodInfo getPeriodInfo(
|
||||||
Timeline timeline, Window window, Period period, int windowIndex, long windowPositionUs) {
|
Timeline timeline, Window window, Period period, int windowIndex, long windowPositionUs) {
|
||||||
checkIndex(windowIndex, 0, timeline.getWindowCount());
|
checkIndex(windowIndex, 0, timeline.getWindowCount());
|
||||||
timeline.getWindow(windowIndex, window);
|
timeline.getWindow(windowIndex, window);
|
||||||
@ -2773,7 +2775,13 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
return new PeriodInfo(periodIndex, periodPositionUs);
|
return new PeriodInfo(periodIndex, periodPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerInfo maskTimelineAndPositionInfo(
|
private static int getCurrentMediaItemIndexInternal(PlayerInfo playerInfo) {
|
||||||
|
return playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex == C.INDEX_UNSET
|
||||||
|
? 0
|
||||||
|
: playerInfo.sessionPositionInfo.positionInfo.mediaItemIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlayerInfo maskTimelineAndPositionInfo(
|
||||||
PlayerInfo playerInfo,
|
PlayerInfo playerInfo,
|
||||||
Timeline timeline,
|
Timeline timeline,
|
||||||
int newMediaItemIndex,
|
int newMediaItemIndex,
|
||||||
@ -2808,7 +2816,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
discontinuityReason);
|
discontinuityReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerInfo maskTimelineAndPositionInfo(
|
private static PlayerInfo maskTimelineAndPositionInfo(
|
||||||
PlayerInfo playerInfo,
|
PlayerInfo playerInfo,
|
||||||
Timeline timeline,
|
Timeline timeline,
|
||||||
PositionInfo newPositionInfo,
|
PositionInfo newPositionInfo,
|
||||||
@ -2853,14 +2861,15 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
currentPositionMs = estimatedPositionMs;
|
currentPositionMs = estimatedPositionMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Period getPeriodWithNewWindowIndex(Timeline timeline, int periodIndex, int windowIndex) {
|
private static Period getPeriodWithNewWindowIndex(
|
||||||
|
Timeline timeline, int periodIndex, int windowIndex) {
|
||||||
Period period = new Period();
|
Period period = new Period();
|
||||||
timeline.getPeriod(periodIndex, period);
|
timeline.getPeriod(periodIndex, period);
|
||||||
period.windowIndex = windowIndex;
|
period.windowIndex = windowIndex;
|
||||||
return period;
|
return period;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getNewPeriodIndexWithoutRemovedPeriods(
|
private static int getNewPeriodIndexWithoutRemovedPeriods(
|
||||||
Timeline timeline, int oldPeriodIndex, int fromIndex, int toIndex) {
|
Timeline timeline, int oldPeriodIndex, int fromIndex, int toIndex) {
|
||||||
if (oldPeriodIndex == C.INDEX_UNSET) {
|
if (oldPeriodIndex == C.INDEX_UNSET) {
|
||||||
return oldPeriodIndex;
|
return oldPeriodIndex;
|
||||||
@ -2906,7 +2915,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
/* isPlaceholder= */ true);
|
/* isPlaceholder= */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rebuildPeriods(
|
private static void rebuildPeriods(
|
||||||
Timeline oldTimeline, List<Window> newWindows, List<Period> newPeriods) {
|
Timeline oldTimeline, List<Window> newWindows, List<Period> newPeriods) {
|
||||||
for (int i = 0; i < newWindows.size(); i++) {
|
for (int i = 0; i < newWindows.size(); i++) {
|
||||||
Window window = newWindows.get(i);
|
Window window = newWindows.get(i);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user