Commit a80b1675 by tonihei Committed by Tofunmi Adigun-Hameed

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 f898a7f17376d50c4de6cd8f67fe047410581527)
parent 9f6969bc
...@@ -648,16 +648,7 @@ import java.util.concurrent.TimeoutException; ...@@ -648,16 +648,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,
...@@ -680,7 +671,7 @@ import java.util.concurrent.TimeoutException; ...@@ -680,7 +671,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(
...@@ -714,7 +705,11 @@ import java.util.concurrent.TimeoutException; ...@@ -714,7 +705,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,
...@@ -1046,7 +1041,7 @@ import java.util.concurrent.TimeoutException; ...@@ -1046,7 +1041,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;
} }
...@@ -1106,17 +1101,7 @@ import java.util.concurrent.TimeoutException; ...@@ -1106,17 +1101,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
...@@ -1842,13 +1827,25 @@ import java.util.concurrent.TimeoutException; ...@@ -1842,13 +1827,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) {
...@@ -1863,10 +1860,9 @@ import java.util.concurrent.TimeoutException; ...@@ -1863,10 +1860,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) {
...@@ -2265,7 +2261,7 @@ import java.util.concurrent.TimeoutException; ...@@ -2265,7 +2261,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()) {
...@@ -2336,9 +2332,30 @@ import java.util.concurrent.TimeoutException; ...@@ -2336,9 +2332,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);
...@@ -2347,7 +2364,8 @@ import java.util.concurrent.TimeoutException; ...@@ -2347,7 +2364,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
...@@ -2376,7 +2394,9 @@ import java.util.concurrent.TimeoutException; ...@@ -2376,7 +2394,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);
...@@ -2404,7 +2424,7 @@ import java.util.concurrent.TimeoutException; ...@@ -2404,7 +2424,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();
...@@ -2480,20 +2500,21 @@ import java.util.concurrent.TimeoutException; ...@@ -2480,20 +2500,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.
...@@ -2545,7 +2566,7 @@ import java.util.concurrent.TimeoutException; ...@@ -2545,7 +2566,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,
......
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