mirror of
https://github.com/androidx/media.git
synced 2025-05-10 09:12:16 +08:00
Update message and seek positions using user intent
While the window in which a message or a seek position is resolved is still a placeholder, we need to re-resolve the position using the user intent (i.e. the window position) when the timeline updates. PiperOrigin-RevId: 293346360
This commit is contained in:
parent
da02bc73e8
commit
b99c6e0513
@ -1206,7 +1206,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
pendingMessages.add(new PendingMessageInfo(message));
|
pendingMessages.add(new PendingMessageInfo(message));
|
||||||
} else {
|
} else {
|
||||||
PendingMessageInfo pendingMessageInfo = new PendingMessageInfo(message);
|
PendingMessageInfo pendingMessageInfo = new PendingMessageInfo(message);
|
||||||
if (resolvePendingMessagePosition(pendingMessageInfo)) {
|
if (resolvePendingMessagePosition(
|
||||||
|
pendingMessageInfo,
|
||||||
|
/* newTimeline= */ playbackInfo.timeline,
|
||||||
|
/* previousTimeline= */ playbackInfo.timeline,
|
||||||
|
repeatMode,
|
||||||
|
shuffleModeEnabled,
|
||||||
|
window,
|
||||||
|
period)) {
|
||||||
pendingMessages.add(pendingMessageInfo);
|
pendingMessages.add(pendingMessageInfo);
|
||||||
// Ensure new message is inserted according to playback order.
|
// Ensure new message is inserted according to playback order.
|
||||||
Collections.sort(pendingMessages);
|
Collections.sort(pendingMessages);
|
||||||
@ -1258,9 +1265,20 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolvePendingMessagePositions() {
|
private void resolvePendingMessagePositions(Timeline newTimeline, Timeline previousTimeline) {
|
||||||
|
if (newTimeline.isEmpty() && previousTimeline.isEmpty()) {
|
||||||
|
// Keep all messages unresolved until we have a non-empty timeline.
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (int i = pendingMessages.size() - 1; i >= 0; i--) {
|
for (int i = pendingMessages.size() - 1; i >= 0; i--) {
|
||||||
if (!resolvePendingMessagePosition(pendingMessages.get(i))) {
|
if (!resolvePendingMessagePosition(
|
||||||
|
pendingMessages.get(i),
|
||||||
|
newTimeline,
|
||||||
|
previousTimeline,
|
||||||
|
repeatMode,
|
||||||
|
shuffleModeEnabled,
|
||||||
|
window,
|
||||||
|
period)) {
|
||||||
// Unable to resolve a new position for the message. Remove it.
|
// Unable to resolve a new position for the message. Remove it.
|
||||||
pendingMessages.get(i).message.markAsProcessed(/* isDelivered= */ false);
|
pendingMessages.get(i).message.markAsProcessed(/* isDelivered= */ false);
|
||||||
pendingMessages.remove(i);
|
pendingMessages.remove(i);
|
||||||
@ -1270,40 +1288,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
Collections.sort(pendingMessages);
|
Collections.sort(pendingMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean resolvePendingMessagePosition(PendingMessageInfo pendingMessageInfo) {
|
|
||||||
if (pendingMessageInfo.resolvedPeriodUid == null) {
|
|
||||||
// Position is still unresolved. Try to find window in current timeline.
|
|
||||||
@Nullable
|
|
||||||
Pair<Object, Long> periodPosition =
|
|
||||||
resolveSeekPosition(
|
|
||||||
playbackInfo.timeline,
|
|
||||||
new SeekPosition(
|
|
||||||
pendingMessageInfo.message.getTimeline(),
|
|
||||||
pendingMessageInfo.message.getWindowIndex(),
|
|
||||||
C.msToUs(pendingMessageInfo.message.getPositionMs())),
|
|
||||||
/* trySubsequentPeriods= */ false,
|
|
||||||
repeatMode,
|
|
||||||
shuffleModeEnabled,
|
|
||||||
window,
|
|
||||||
period);
|
|
||||||
if (periodPosition == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pendingMessageInfo.setResolvedPosition(
|
|
||||||
playbackInfo.timeline.getIndexOfPeriod(periodPosition.first),
|
|
||||||
periodPosition.second,
|
|
||||||
periodPosition.first);
|
|
||||||
} else {
|
|
||||||
// Position has been resolved for a previous timeline. Try to find the updated period index.
|
|
||||||
int index = playbackInfo.timeline.getIndexOfPeriod(pendingMessageInfo.resolvedPeriodUid);
|
|
||||||
if (index == C.INDEX_UNSET) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pendingMessageInfo.resolvedPeriodIndex = index;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeTriggerPendingMessages(long oldPeriodPositionUs, long newPeriodPositionUs)
|
private void maybeTriggerPendingMessages(long oldPeriodPositionUs, long newPeriodPositionUs)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
if (pendingMessages.isEmpty() || playbackInfo.periodId.isAd()) {
|
if (pendingMessages.isEmpty() || playbackInfo.periodId.isAd()) {
|
||||||
@ -1582,8 +1566,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfo =
|
playbackInfo =
|
||||||
copyWithNewPosition(newPeriodId, newPositionUs, newRequestedContentPositionUs);
|
copyWithNewPosition(newPeriodId, newPositionUs, newRequestedContentPositionUs);
|
||||||
}
|
}
|
||||||
|
resolvePendingMessagePositions(
|
||||||
|
/* newTimeline= */ timeline, /* previousTimeline= */ playbackInfo.timeline);
|
||||||
playbackInfo = playbackInfo.copyWithTimeline(timeline);
|
playbackInfo = playbackInfo.copyWithTimeline(timeline);
|
||||||
resolvePendingMessagePositions();
|
|
||||||
if (!timeline.isEmpty()) {
|
if (!timeline.isEmpty()) {
|
||||||
// Retain pending seek position only while the timeline is still empty.
|
// Retain pending seek position only while the timeline is still empty.
|
||||||
pendingInitialSeekPosition = null;
|
pendingInitialSeekPosition = null;
|
||||||
@ -2234,6 +2219,74 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
.isPlaceholder;
|
.isPlaceholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates pending message to a new timeline.
|
||||||
|
*
|
||||||
|
* @param pendingMessageInfo The pending message.
|
||||||
|
* @param newTimeline The new timeline.
|
||||||
|
* @param previousTimeline The previous timeline used to set the message positions.
|
||||||
|
* @param repeatMode The current repeat mode.
|
||||||
|
* @param shuffleModeEnabled The current shuffle mode.
|
||||||
|
* @param window A scratch window.
|
||||||
|
* @param period A scratch period.
|
||||||
|
* @return Whether the message position could be resolved to the current timeline.
|
||||||
|
*/
|
||||||
|
private static boolean resolvePendingMessagePosition(
|
||||||
|
PendingMessageInfo pendingMessageInfo,
|
||||||
|
Timeline newTimeline,
|
||||||
|
Timeline previousTimeline,
|
||||||
|
@Player.RepeatMode int repeatMode,
|
||||||
|
boolean shuffleModeEnabled,
|
||||||
|
Timeline.Window window,
|
||||||
|
Timeline.Period period) {
|
||||||
|
if (pendingMessageInfo.resolvedPeriodUid == null) {
|
||||||
|
// Position is still unresolved. Try to find window in new timeline.
|
||||||
|
@Nullable
|
||||||
|
Pair<Object, Long> periodPosition =
|
||||||
|
resolveSeekPosition(
|
||||||
|
newTimeline,
|
||||||
|
new SeekPosition(
|
||||||
|
pendingMessageInfo.message.getTimeline(),
|
||||||
|
pendingMessageInfo.message.getWindowIndex(),
|
||||||
|
C.msToUs(pendingMessageInfo.message.getPositionMs())),
|
||||||
|
/* trySubsequentPeriods= */ false,
|
||||||
|
repeatMode,
|
||||||
|
shuffleModeEnabled,
|
||||||
|
window,
|
||||||
|
period);
|
||||||
|
if (periodPosition == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pendingMessageInfo.setResolvedPosition(
|
||||||
|
/* periodIndex= */ newTimeline.getIndexOfPeriod(periodPosition.first),
|
||||||
|
/* periodTimeUs= */ periodPosition.second,
|
||||||
|
/* periodUid= */ periodPosition.first);
|
||||||
|
} else {
|
||||||
|
// Position has been resolved for a previous timeline. Try to find the updated period index.
|
||||||
|
int index = newTimeline.getIndexOfPeriod(pendingMessageInfo.resolvedPeriodUid);
|
||||||
|
if (index == C.INDEX_UNSET) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pendingMessageInfo.resolvedPeriodIndex = index;
|
||||||
|
previousTimeline.getPeriodByUid(pendingMessageInfo.resolvedPeriodUid, period);
|
||||||
|
if (previousTimeline.getWindow(period.windowIndex, window).isPlaceholder) {
|
||||||
|
// The position needs to be re-resolved because the window in the previous timeline wasn't
|
||||||
|
// fully prepared.
|
||||||
|
long windowPositionUs =
|
||||||
|
pendingMessageInfo.resolvedPeriodTimeUs + period.getPositionInWindowUs();
|
||||||
|
int windowIndex =
|
||||||
|
newTimeline.getPeriodByUid(pendingMessageInfo.resolvedPeriodUid, period).windowIndex;
|
||||||
|
Pair<Object, Long> periodPosition =
|
||||||
|
newTimeline.getPeriodPosition(window, period, windowIndex, windowPositionUs);
|
||||||
|
pendingMessageInfo.setResolvedPosition(
|
||||||
|
/* periodIndex= */ newTimeline.getIndexOfPeriod(periodPosition.first),
|
||||||
|
/* periodTimeUs= */ periodPosition.second,
|
||||||
|
/* periodUid= */ periodPosition.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a {@link SeekPosition} into the corresponding (periodUid, periodPositionUs) for the
|
* Converts a {@link SeekPosition} into the corresponding (periodUid, periodPositionUs) for the
|
||||||
* internal timeline.
|
* internal timeline.
|
||||||
@ -2282,6 +2335,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
int periodIndex = timeline.getIndexOfPeriod(periodPosition.first);
|
int periodIndex = timeline.getIndexOfPeriod(periodPosition.first);
|
||||||
if (periodIndex != C.INDEX_UNSET) {
|
if (periodIndex != C.INDEX_UNSET) {
|
||||||
// We successfully located the period in the internal timeline.
|
// We successfully located the period in the internal timeline.
|
||||||
|
seekTimeline.getPeriodByUid(periodPosition.first, period);
|
||||||
|
if (seekTimeline.getWindow(period.windowIndex, window).isPlaceholder) {
|
||||||
|
// The seek timeline was using a placeholder, so we need to re-resolve using the updated
|
||||||
|
// timeline in case the resolved position changed.
|
||||||
|
int newWindowIndex = timeline.getPeriodByUid(periodPosition.first, period).windowIndex;
|
||||||
|
periodPosition =
|
||||||
|
timeline.getPeriodPosition(
|
||||||
|
window, period, newWindowIndex, seekPosition.windowPositionUs);
|
||||||
|
}
|
||||||
return periodPosition;
|
return periodPosition;
|
||||||
}
|
}
|
||||||
if (trySubsequentPeriods) {
|
if (trySubsequentPeriods) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user