Commit 4dddad83 by tonihei Committed by Oliver Woodman

Keep requested content position even for content periods.

We currently only keep the requested next content start position while
we are playing ads. However, we should also keep at least before a content
period is fully prepared to not loose the information about the user intent.

PiperOrigin-RevId: 291705752
parent c0a3feee
...@@ -691,9 +691,9 @@ import java.util.concurrent.TimeoutException; ...@@ -691,9 +691,9 @@ import java.util.concurrent.TimeoutException;
public long getContentPosition() { public long getContentPosition() {
if (isPlayingAd()) { if (isPlayingAd()) {
playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period); playbackInfo.timeline.getPeriodByUid(playbackInfo.periodId.periodUid, period);
return playbackInfo.contentPositionUs == C.TIME_UNSET return playbackInfo.requestedContentPositionUs == C.TIME_UNSET
? playbackInfo.timeline.getWindow(getCurrentWindowIndex(), window).getDefaultPositionMs() ? playbackInfo.timeline.getWindow(getCurrentWindowIndex(), window).getDefaultPositionMs()
: period.getPositionInWindowMs() + C.usToMs(playbackInfo.contentPositionUs); : period.getPositionInWindowMs() + C.usToMs(playbackInfo.requestedContentPositionUs);
} else { } else {
return getCurrentPosition(); return getCurrentPosition();
} }
...@@ -824,18 +824,18 @@ import java.util.concurrent.TimeoutException; ...@@ -824,18 +824,18 @@ import java.util.concurrent.TimeoutException;
} }
Timeline timeline = playbackInfo.timeline; Timeline timeline = playbackInfo.timeline;
MediaPeriodId mediaPeriodId = playbackInfo.periodId; MediaPeriodId mediaPeriodId = playbackInfo.periodId;
long contentPositionUs = playbackInfo.contentPositionUs; long requestedContentPositionUs = playbackInfo.requestedContentPositionUs;
long positionUs = playbackInfo.positionUs; long positionUs = playbackInfo.positionUs;
if (clearPlaylist) { if (clearPlaylist) {
timeline = Timeline.EMPTY; timeline = Timeline.EMPTY;
mediaPeriodId = PlaybackInfo.getDummyPeriodForEmptyTimeline(); mediaPeriodId = PlaybackInfo.getDummyPeriodForEmptyTimeline();
contentPositionUs = C.TIME_UNSET; requestedContentPositionUs = C.TIME_UNSET;
positionUs = 0; positionUs = 0;
} }
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
mediaPeriodId, mediaPeriodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
resetError ? null : playbackInfo.playbackError, resetError ? null : playbackInfo.playbackError,
/* isLoading= */ false, /* isLoading= */ false,
......
...@@ -689,7 +689,8 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -689,7 +689,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* forceDisableRenderers= */ true, /* forceDisableRenderers= */ true,
/* forceBufferingState= */ false); /* forceBufferingState= */ false);
if (newPositionUs != playbackInfo.positionUs) { if (newPositionUs != playbackInfo.positionUs) {
playbackInfo = copyWithNewPosition(periodId, newPositionUs, playbackInfo.contentPositionUs); playbackInfo =
copyWithNewPosition(periodId, newPositionUs, playbackInfo.requestedContentPositionUs);
if (sendDiscontinuity) { if (sendDiscontinuity) {
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL); playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
} }
...@@ -729,7 +730,9 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -729,7 +730,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (discontinuityPositionUs != playbackInfo.positionUs) { if (discontinuityPositionUs != playbackInfo.positionUs) {
playbackInfo = playbackInfo =
copyWithNewPosition( copyWithNewPosition(
playbackInfo.periodId, discontinuityPositionUs, playbackInfo.contentPositionUs); playbackInfo.periodId,
discontinuityPositionUs,
playbackInfo.requestedContentPositionUs);
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL); playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
} }
} else { } else {
...@@ -863,7 +866,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -863,7 +866,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
MediaPeriodId periodId; MediaPeriodId periodId;
long periodPositionUs; long periodPositionUs;
long contentPositionUs; long requestedContentPosition;
boolean seekPositionAdjusted; boolean seekPositionAdjusted;
@Nullable @Nullable
Pair<Object, Long> resolvedSeekPosition = Pair<Object, Long> resolvedSeekPosition =
...@@ -878,17 +881,21 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -878,17 +881,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (resolvedSeekPosition == null) { if (resolvedSeekPosition == null) {
// The seek position was valid for the timeline that it was performed into, but the // The seek position was valid for the timeline that it was performed into, but the
// timeline has changed or is not ready and a suitable seek position could not be resolved. // timeline has changed or is not ready and a suitable seek position could not be resolved.
Pair<MediaPeriodId, Long> firstPeriodAndPosition = getDummyFirstMediaPeriodPosition(); Pair<MediaPeriodId, Long> firstPeriodAndPosition =
getDummyFirstMediaPeriodPosition(playbackInfo.timeline);
periodId = firstPeriodAndPosition.first; periodId = firstPeriodAndPosition.first;
periodPositionUs = firstPeriodAndPosition.second; periodPositionUs = firstPeriodAndPosition.second;
contentPositionUs = C.TIME_UNSET; requestedContentPosition = C.TIME_UNSET;
seekPositionAdjusted = true; seekPositionAdjusted = true;
} else { } else {
// Update the resolved seek position to take ads into account. // Update the resolved seek position to take ads into account.
Object periodUid = resolvedSeekPosition.first; Object periodUid = resolvedSeekPosition.first;
contentPositionUs = resolvedSeekPosition.second; long resolvedContentPosition = resolvedSeekPosition.second;
requestedContentPosition =
seekPosition.windowPositionUs == C.TIME_UNSET ? C.TIME_UNSET : resolvedContentPosition;
periodId = periodId =
queue.resolveMediaPeriodIdForAds(playbackInfo.timeline, periodUid, contentPositionUs); queue.resolveMediaPeriodIdForAds(
playbackInfo.timeline, periodUid, resolvedContentPosition);
if (periodId.isAd()) { if (periodId.isAd()) {
playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period); playbackInfo.timeline.getPeriodByUid(periodId.periodUid, period);
periodPositionUs = periodPositionUs =
...@@ -897,7 +904,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -897,7 +904,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
: 0; : 0;
seekPositionAdjusted = true; seekPositionAdjusted = true;
} else { } else {
periodPositionUs = resolvedSeekPosition.second; periodPositionUs = resolvedContentPosition;
seekPositionAdjusted = seekPosition.windowPositionUs == C.TIME_UNSET; seekPositionAdjusted = seekPosition.windowPositionUs == C.TIME_UNSET;
} }
} }
...@@ -942,7 +949,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -942,7 +949,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
periodPositionUs = newPeriodPositionUs; periodPositionUs = newPeriodPositionUs;
} }
} finally { } finally {
playbackInfo = copyWithNewPosition(periodId, periodPositionUs, contentPositionUs); playbackInfo = copyWithNewPosition(periodId, periodPositionUs, requestedContentPosition);
if (seekPositionAdjusted) { if (seekPositionAdjusted) {
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT); playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT);
} }
...@@ -1125,8 +1132,6 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1125,8 +1132,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
enabledRenderers = new Renderer[0]; enabledRenderers = new Renderer[0];
queue.clear();
shouldContinueLoading = false;
Timeline timeline = playbackInfo.timeline; Timeline timeline = playbackInfo.timeline;
if (clearPlaylist) { if (clearPlaylist) {
timeline = playlist.clear(/* shuffleOrder= */ null); timeline = playlist.clear(/* shuffleOrder= */ null);
...@@ -1135,26 +1140,34 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1135,26 +1140,34 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
pendingMessages.clear(); pendingMessages.clear();
nextPendingMessageIndex = 0; nextPendingMessageIndex = 0;
resetPosition = true;
} }
MediaPeriodId mediaPeriodId = playbackInfo.periodId; MediaPeriodId mediaPeriodId = playbackInfo.periodId;
long startPositionUs = playbackInfo.positionUs; long startPositionUs = playbackInfo.positionUs;
long contentPositionUs = playbackInfo.contentPositionUs; long requestedContentPositionUs =
shouldUseRequestedContentPosition(playbackInfo, period, window)
? playbackInfo.requestedContentPositionUs
: playbackInfo.positionUs;
boolean resetTrackInfo = clearPlaylist; boolean resetTrackInfo = clearPlaylist;
if (resetPosition) { if (resetPosition) {
pendingInitialSeekPosition = null; pendingInitialSeekPosition = null;
Pair<MediaPeriodId, Long> firstPeriodAndPosition = getDummyFirstMediaPeriodPosition(); Pair<MediaPeriodId, Long> firstPeriodAndPosition = getDummyFirstMediaPeriodPosition(timeline);
mediaPeriodId = firstPeriodAndPosition.first; mediaPeriodId = firstPeriodAndPosition.first;
startPositionUs = firstPeriodAndPosition.second; startPositionUs = firstPeriodAndPosition.second;
contentPositionUs = C.TIME_UNSET; requestedContentPositionUs = C.TIME_UNSET;
if (!mediaPeriodId.equals(playbackInfo.periodId)) { if (!mediaPeriodId.equals(playbackInfo.periodId)) {
resetTrackInfo = true; resetTrackInfo = true;
} }
} }
queue.clear();
shouldContinueLoading = false;
playbackInfo = playbackInfo =
new PlaybackInfo( new PlaybackInfo(
timeline, timeline,
mediaPeriodId, mediaPeriodId,
contentPositionUs, requestedContentPositionUs,
playbackInfo.playbackState, playbackInfo.playbackState,
resetError ? null : playbackInfo.playbackError, resetError ? null : playbackInfo.playbackError,
/* isLoading= */ false, /* isLoading= */ false,
...@@ -1169,21 +1182,21 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1169,21 +1182,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
} }
} }
private Pair<MediaPeriodId, Long> getDummyFirstMediaPeriodPosition() { private Pair<MediaPeriodId, Long> getDummyFirstMediaPeriodPosition(Timeline timeline) {
if (playbackInfo.timeline.isEmpty()) { if (timeline.isEmpty()) {
return Pair.create(PlaybackInfo.getDummyPeriodForEmptyTimeline(), 0L); return Pair.create(PlaybackInfo.getDummyPeriodForEmptyTimeline(), 0L);
} }
int firstWindowIndex = playbackInfo.timeline.getFirstWindowIndex(shuffleModeEnabled); int firstWindowIndex = timeline.getFirstWindowIndex(shuffleModeEnabled);
Pair<Object, Long> firstPeriodAndPosition = Pair<Object, Long> firstPeriodAndPosition =
playbackInfo.timeline.getPeriodPosition( timeline.getPeriodPosition(
window, period, firstWindowIndex, /* windowPositionUs= */ C.TIME_UNSET); window, period, firstWindowIndex, /* windowPositionUs= */ C.TIME_UNSET);
// Add ad metadata if any and propagate the window sequence number to new period id. // Add ad metadata if any and propagate the window sequence number to new period id.
MediaPeriodId firstPeriodId = MediaPeriodId firstPeriodId =
queue.resolveMediaPeriodIdForAds( queue.resolveMediaPeriodIdForAds(
playbackInfo.timeline, firstPeriodAndPosition.first, /* positionUs= */ 0); timeline, firstPeriodAndPosition.first, /* positionUs= */ 0);
long positionUs = firstPeriodAndPosition.second; long positionUs = firstPeriodAndPosition.second;
if (firstPeriodId.isAd()) { if (firstPeriodId.isAd()) {
playbackInfo.timeline.getPeriodByUid(firstPeriodId.periodUid, period); timeline.getPeriodByUid(firstPeriodId.periodUid, period);
positionUs = positionUs =
firstPeriodId.adIndexInAdGroup == period.getFirstAdIndexToPlay(firstPeriodId.adGroupIndex) firstPeriodId.adIndexInAdGroup == period.getFirstAdIndexToPlay(firstPeriodId.adGroupIndex)
? period.getAdResumePositionUs() ? period.getAdResumePositionUs()
...@@ -1408,7 +1421,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1408,7 +1421,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
newTrackSelectorResult, playbackInfo.positionUs, recreateStreams, streamResetFlags); newTrackSelectorResult, playbackInfo.positionUs, recreateStreams, streamResetFlags);
playbackInfo = playbackInfo =
copyWithNewPosition( copyWithNewPosition(
playbackInfo.periodId, periodPositionUs, playbackInfo.contentPositionUs); playbackInfo.periodId, periodPositionUs, playbackInfo.requestedContentPositionUs);
if (playbackInfo.playbackState != Player.STATE_ENDED if (playbackInfo.playbackState != Player.STATE_ENDED
&& periodPositionUs != playbackInfo.positionUs) { && periodPositionUs != playbackInfo.positionUs) {
playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL); playbackInfoUpdate.setPositionDiscontinuity(Player.DISCONTINUITY_REASON_INTERNAL);
...@@ -1533,11 +1546,11 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1533,11 +1546,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
window, window,
period); period);
MediaPeriodId newPeriodId = positionUpdate.periodId; MediaPeriodId newPeriodId = positionUpdate.periodId;
long newContentPositionUs = positionUpdate.contentPositionUs; long newRequestedContentPositionUs = positionUpdate.requestedContentPositionUs;
boolean forceBufferingState = positionUpdate.forceBufferingState; boolean forceBufferingState = positionUpdate.forceBufferingState;
long newPositionUs = positionUpdate.periodPositionUs; long newPositionUs = positionUpdate.periodPositionUs;
boolean isPlaybackPositionUnchanged = boolean periodPositionChanged =
playbackInfo.periodId.equals(newPeriodId) && newPositionUs == playbackInfo.positionUs; !playbackInfo.periodId.equals(newPeriodId) || newPositionUs != playbackInfo.positionUs;
try { try {
if (positionUpdate.endPlayback) { if (positionUpdate.endPlayback) {
...@@ -1551,7 +1564,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1551,7 +1564,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* clearPlaylist= */ false, /* clearPlaylist= */ false,
/* resetError= */ true); /* resetError= */ true);
} }
if (isPlaybackPositionUnchanged) { if (!periodPositionChanged) {
// We can keep the current playing period. Update the rest of the queued periods. // We can keep the current playing period. Update the rest of the queued periods.
if (!queue.updateQueuedPeriods( if (!queue.updateQueuedPeriods(
timeline, rendererPositionUs, getMaxRendererReadPositionUs())) { timeline, rendererPositionUs, getMaxRendererReadPositionUs())) {
...@@ -1572,8 +1585,10 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1572,8 +1585,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
newPositionUs = seekToPeriodPosition(newPeriodId, newPositionUs, forceBufferingState); newPositionUs = seekToPeriodPosition(newPeriodId, newPositionUs, forceBufferingState);
} }
} finally { } finally {
if (!isPlaybackPositionUnchanged) { if (periodPositionChanged
playbackInfo = copyWithNewPosition(newPeriodId, newPositionUs, newContentPositionUs); || newRequestedContentPositionUs != playbackInfo.requestedContentPositionUs) {
playbackInfo =
copyWithNewPosition(newPeriodId, newPositionUs, newRequestedContentPositionUs);
} }
playbackInfo = playbackInfo.copyWithTimeline(timeline); playbackInfo = playbackInfo.copyWithTimeline(timeline);
resolvePendingMessagePositions(); resolvePendingMessagePositions();
...@@ -1751,7 +1766,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1751,7 +1766,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
copyWithNewPosition( copyWithNewPosition(
newPlayingPeriodHolder.info.id, newPlayingPeriodHolder.info.id,
newPlayingPeriodHolder.info.startPositionUs, newPlayingPeriodHolder.info.startPositionUs,
newPlayingPeriodHolder.info.contentPositionUs); newPlayingPeriodHolder.info.requestedContentPositionUs);
int discontinuityReason = int discontinuityReason =
oldPlayingPeriodHolder.info.isLastInTimelinePeriod oldPlayingPeriodHolder.info.isLastInTimelinePeriod
? Player.DISCONTINUITY_REASON_PERIOD_TRANSITION ? Player.DISCONTINUITY_REASON_PERIOD_TRANSITION
...@@ -1823,7 +1838,9 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1823,7 +1838,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
enablePlayingPeriodRenderers(); enablePlayingPeriodRenderers();
playbackInfo = playbackInfo =
copyWithNewPosition( copyWithNewPosition(
playbackInfo.periodId, playbackInfo.positionUs, playbackInfo.contentPositionUs); playbackInfo.periodId,
playbackInfo.positionUs,
playbackInfo.requestedContentPositionUs);
} }
maybeContinueLoading(); maybeContinueLoading();
} }
...@@ -2076,14 +2093,18 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2076,14 +2093,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
return new PositionUpdateForPlaylistChange( return new PositionUpdateForPlaylistChange(
PlaybackInfo.getDummyPeriodForEmptyTimeline(), PlaybackInfo.getDummyPeriodForEmptyTimeline(),
/* periodPositionUs= */ 0, /* periodPositionUs= */ 0,
/* contentPositionUs= */ C.TIME_UNSET, /* requestedContentPositionUs= */ C.TIME_UNSET,
/* forceBufferingState= */ false, /* forceBufferingState= */ false,
/* endPlayback= */ true); /* endPlayback= */ true);
} }
MediaPeriodId oldPeriodId = playbackInfo.periodId; MediaPeriodId oldPeriodId = playbackInfo.periodId;
Object newPeriodUid = oldPeriodId.periodUid; Object newPeriodUid = oldPeriodId.periodUid;
boolean shouldUseRequestedContentPosition =
shouldUseRequestedContentPosition(playbackInfo, period, window);
long oldContentPositionUs = long oldContentPositionUs =
oldPeriodId.isAd() ? playbackInfo.contentPositionUs : playbackInfo.positionUs; shouldUseRequestedContentPosition
? playbackInfo.requestedContentPositionUs
: playbackInfo.positionUs;
long newContentPositionUs = oldContentPositionUs; long newContentPositionUs = oldContentPositionUs;
int startAtDefaultPositionWindowIndex = C.INDEX_UNSET; int startAtDefaultPositionWindowIndex = C.INDEX_UNSET;
boolean forceBufferingState = false; boolean forceBufferingState = false;
...@@ -2141,10 +2162,21 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2141,10 +2162,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
startAtDefaultPositionWindowIndex = startAtDefaultPositionWindowIndex =
timeline.getPeriodByUid(subsequentPeriodUid, period).windowIndex; timeline.getPeriodByUid(subsequentPeriodUid, period).windowIndex;
} }
} else if (oldContentPositionUs == C.TIME_UNSET) { } else if (shouldUseRequestedContentPosition) {
// We previously set the content position to be the default position of the current window. // We previously requested a content position, but haven't used it yet. Re-resolve the
// Re-resolve the period uid and position in case they changed since last time. // requested window position to the period uid and position in case they changed.
startAtDefaultPositionWindowIndex = timeline.getPeriodByUid(newPeriodUid, period).windowIndex; if (oldContentPositionUs == C.TIME_UNSET) {
startAtDefaultPositionWindowIndex =
timeline.getPeriodByUid(newPeriodUid, period).windowIndex;
} else {
playbackInfo.timeline.getPeriodByUid(oldPeriodId.periodUid, period);
long windowPositionUs = oldContentPositionUs + period.getPositionInWindowUs();
int windowIndex = timeline.getPeriodByUid(newPeriodUid, period).windowIndex;
Pair<Object, Long> periodPosition =
timeline.getPeriodPosition(window, period, windowIndex, windowPositionUs);
newPeriodUid = periodPosition.first;
newContentPositionUs = periodPosition.second;
}
} }
// Set period uid for default positions and resolve position for ad resolution. // Set period uid for default positions and resolve position for ad resolution.
...@@ -2158,15 +2190,12 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2158,15 +2190,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* windowPositionUs= */ C.TIME_UNSET); /* windowPositionUs= */ C.TIME_UNSET);
newPeriodUid = defaultPosition.first; newPeriodUid = defaultPosition.first;
contentPositionForAdResolutionUs = defaultPosition.second; contentPositionForAdResolutionUs = defaultPosition.second;
newContentPositionUs = C.TIME_UNSET;
} }
// Ensure ad insertion metadata is up to date. // Ensure ad insertion metadata is up to date.
MediaPeriodId periodIdWithAds = MediaPeriodId periodIdWithAds =
queue.resolveMediaPeriodIdForAds(timeline, newPeriodUid, contentPositionForAdResolutionUs); queue.resolveMediaPeriodIdForAds(timeline, newPeriodUid, contentPositionForAdResolutionUs);
if (!periodIdWithAds.isAd() && newContentPositionUs == C.TIME_UNSET) {
// We are not going to play an ad, so use resolved content position.
newContentPositionUs = contentPositionForAdResolutionUs;
}
boolean oldAndNewPeriodIdAreSame = boolean oldAndNewPeriodIdAreSame =
oldPeriodId.periodUid.equals(newPeriodUid) oldPeriodId.periodUid.equals(newPeriodUid)
&& !oldPeriodId.isAd() && !oldPeriodId.isAd()
...@@ -2193,6 +2222,19 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2193,6 +2222,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
newPeriodId, periodPositionUs, newContentPositionUs, forceBufferingState, endPlayback); newPeriodId, periodPositionUs, newContentPositionUs, forceBufferingState, endPlayback);
} }
private static boolean shouldUseRequestedContentPosition(
PlaybackInfo playbackInfo, Timeline.Period period, Timeline.Window window) {
// Only use the actual position as content position if it's not an ad and we already have
// prepared media information. Otherwise use the requested position.
MediaPeriodId periodId = playbackInfo.periodId;
Timeline timeline = playbackInfo.timeline;
return periodId.isAd()
|| timeline.isEmpty()
|| timeline.getWindow(
timeline.getPeriodByUid(periodId.periodUid, period).windowIndex, window)
.isPlaceholder;
}
/** /**
* 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.
...@@ -2332,19 +2374,19 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2332,19 +2374,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final class PositionUpdateForPlaylistChange { private static final class PositionUpdateForPlaylistChange {
public final MediaPeriodId periodId; public final MediaPeriodId periodId;
public final long periodPositionUs; public final long periodPositionUs;
public final long contentPositionUs; public final long requestedContentPositionUs;
public final boolean forceBufferingState; public final boolean forceBufferingState;
public final boolean endPlayback; public final boolean endPlayback;
public PositionUpdateForPlaylistChange( public PositionUpdateForPlaylistChange(
MediaPeriodId periodId, MediaPeriodId periodId,
long periodPositionUs, long periodPositionUs,
long contentPositionUs, long requestedContentPositionUs,
boolean forceBufferingState, boolean forceBufferingState,
boolean endPlayback) { boolean endPlayback) {
this.periodId = periodId; this.periodId = periodId;
this.periodPositionUs = periodPositionUs; this.periodPositionUs = periodPositionUs;
this.contentPositionUs = contentPositionUs; this.requestedContentPositionUs = requestedContentPositionUs;
this.forceBufferingState = forceBufferingState; this.forceBufferingState = forceBufferingState;
this.endPlayback = endPlayback; this.endPlayback = endPlayback;
} }
......
...@@ -28,11 +28,13 @@ import com.google.android.exoplayer2.util.Util; ...@@ -28,11 +28,13 @@ import com.google.android.exoplayer2.util.Util;
/** The start position of the media to play within the media period, in microseconds. */ /** The start position of the media to play within the media period, in microseconds. */
public final long startPositionUs; public final long startPositionUs;
/** /**
* If this is an ad, the position to play in the next content media period. {@link C#TIME_UNSET} * The requested next start position for the current timeline period, in microseconds, or {@link
* if this is not an ad or the next content media period should be played from its default * C#TIME_UNSET} if the period was requested to start at its default position.
* position. *
* <p>Note that if {@link #id} refers to an ad, this is the requested start position for the
* suspended content.
*/ */
public final long contentPositionUs; public final long requestedContentPositionUs;
/** /**
* The end position to which the media period's content is clipped in order to play a following ad * The end position to which the media period's content is clipped in order to play a following ad
* group, in microseconds, or {@link C#TIME_UNSET} if there is no following ad group or if this * group, in microseconds, or {@link C#TIME_UNSET} if there is no following ad group or if this
...@@ -60,14 +62,14 @@ import com.google.android.exoplayer2.util.Util; ...@@ -60,14 +62,14 @@ import com.google.android.exoplayer2.util.Util;
MediaPeriodInfo( MediaPeriodInfo(
MediaPeriodId id, MediaPeriodId id,
long startPositionUs, long startPositionUs,
long contentPositionUs, long requestedContentPositionUs,
long endPositionUs, long endPositionUs,
long durationUs, long durationUs,
boolean isLastInTimelinePeriod, boolean isLastInTimelinePeriod,
boolean isFinal) { boolean isFinal) {
this.id = id; this.id = id;
this.startPositionUs = startPositionUs; this.startPositionUs = startPositionUs;
this.contentPositionUs = contentPositionUs; this.requestedContentPositionUs = requestedContentPositionUs;
this.endPositionUs = endPositionUs; this.endPositionUs = endPositionUs;
this.durationUs = durationUs; this.durationUs = durationUs;
this.isLastInTimelinePeriod = isLastInTimelinePeriod; this.isLastInTimelinePeriod = isLastInTimelinePeriod;
...@@ -84,7 +86,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -84,7 +86,7 @@ import com.google.android.exoplayer2.util.Util;
: new MediaPeriodInfo( : new MediaPeriodInfo(
id, id,
startPositionUs, startPositionUs,
contentPositionUs, requestedContentPositionUs,
endPositionUs, endPositionUs,
durationUs, durationUs,
isLastInTimelinePeriod, isLastInTimelinePeriod,
...@@ -92,16 +94,16 @@ import com.google.android.exoplayer2.util.Util; ...@@ -92,16 +94,16 @@ import com.google.android.exoplayer2.util.Util;
} }
/** /**
* Returns a copy of this instance with the content position set to the specified value. May * Returns a copy of this instance with the requested content position set to the specified value.
* return the same instance if nothing changed. * May return the same instance if nothing changed.
*/ */
public MediaPeriodInfo copyWithContentPositionUs(long contentPositionUs) { public MediaPeriodInfo copyWithRequestedContentPositionUs(long requestedContentPositionUs) {
return contentPositionUs == this.contentPositionUs return requestedContentPositionUs == this.requestedContentPositionUs
? this ? this
: new MediaPeriodInfo( : new MediaPeriodInfo(
id, id,
startPositionUs, startPositionUs,
contentPositionUs, requestedContentPositionUs,
endPositionUs, endPositionUs,
durationUs, durationUs,
isLastInTimelinePeriod, isLastInTimelinePeriod,
...@@ -118,7 +120,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -118,7 +120,7 @@ import com.google.android.exoplayer2.util.Util;
} }
MediaPeriodInfo that = (MediaPeriodInfo) o; MediaPeriodInfo that = (MediaPeriodInfo) o;
return startPositionUs == that.startPositionUs return startPositionUs == that.startPositionUs
&& contentPositionUs == that.contentPositionUs && requestedContentPositionUs == that.requestedContentPositionUs
&& endPositionUs == that.endPositionUs && endPositionUs == that.endPositionUs
&& durationUs == that.durationUs && durationUs == that.durationUs
&& isLastInTimelinePeriod == that.isLastInTimelinePeriod && isLastInTimelinePeriod == that.isLastInTimelinePeriod
...@@ -131,7 +133,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -131,7 +133,7 @@ import com.google.android.exoplayer2.util.Util;
int result = 17; int result = 17;
result = 31 * result + id.hashCode(); result = 31 * result + id.hashCode();
result = 31 * result + (int) startPositionUs; result = 31 * result + (int) startPositionUs;
result = 31 * result + (int) contentPositionUs; result = 31 * result + (int) requestedContentPositionUs;
result = 31 * result + (int) endPositionUs; result = 31 * result + (int) endPositionUs;
result = 31 * result + (int) durationUs; result = 31 * result + (int) durationUs;
result = 31 * result + (isLastInTimelinePeriod ? 1 : 0); result = 31 * result + (isLastInTimelinePeriod ? 1 : 0);
......
...@@ -146,8 +146,8 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -146,8 +146,8 @@ import com.google.android.exoplayer2.util.Assertions;
TrackSelectorResult emptyTrackSelectorResult) { TrackSelectorResult emptyTrackSelectorResult) {
long rendererPositionOffsetUs = long rendererPositionOffsetUs =
loading == null loading == null
? (info.id.isAd() && info.contentPositionUs != C.TIME_UNSET ? (info.id.isAd() && info.requestedContentPositionUs != C.TIME_UNSET
? info.contentPositionUs ? info.requestedContentPositionUs
: 0) : 0)
: (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs); : (loading.getRendererOffset() + loading.info.durationUs - info.startPositionUs);
MediaPeriodHolder newPeriodHolder = MediaPeriodHolder newPeriodHolder =
...@@ -314,8 +314,11 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -314,8 +314,11 @@ import com.google.android.exoplayer2.util.Assertions;
} }
} }
// Use new period info, but keep old content position. // Use the new period info, but keep the old requested content position to avoid overriding it
periodHolder.info = newPeriodInfo.copyWithContentPositionUs(oldPeriodInfo.contentPositionUs); // by the default content position generated in getFollowingMediaPeriodInfo.
periodHolder.info =
newPeriodInfo.copyWithRequestedContentPositionUs(
oldPeriodInfo.requestedContentPositionUs);
if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) { if (!areDurationsCompatible(oldPeriodInfo.durationUs, newPeriodInfo.durationUs)) {
// The period duration changed. Remove all subsequent periods and check whether we read // The period duration changed. Remove all subsequent periods and check whether we read
...@@ -361,7 +364,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -361,7 +364,7 @@ import com.google.android.exoplayer2.util.Assertions;
return new MediaPeriodInfo( return new MediaPeriodInfo(
id, id,
info.startPositionUs, info.startPositionUs,
info.contentPositionUs, info.requestedContentPositionUs,
info.endPositionUs, info.endPositionUs,
durationUs, durationUs,
isLastInPeriod, isLastInPeriod,
...@@ -534,7 +537,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -534,7 +537,7 @@ import com.google.android.exoplayer2.util.Assertions;
return getMediaPeriodInfo( return getMediaPeriodInfo(
playbackInfo.timeline, playbackInfo.timeline,
playbackInfo.periodId, playbackInfo.periodId,
playbackInfo.contentPositionUs, playbackInfo.requestedContentPositionUs,
playbackInfo.positionUs); playbackInfo.positionUs);
} }
...@@ -631,11 +634,11 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -631,11 +634,11 @@ import com.google.android.exoplayer2.util.Assertions;
currentPeriodId.periodUid, currentPeriodId.periodUid,
adGroupIndex, adGroupIndex,
nextAdIndexInAdGroup, nextAdIndexInAdGroup,
mediaPeriodInfo.contentPositionUs, mediaPeriodInfo.requestedContentPositionUs,
currentPeriodId.windowSequenceNumber); currentPeriodId.windowSequenceNumber);
} else { } else {
// Play content from the ad group position. // Play content from the ad group position.
long startPositionUs = mediaPeriodInfo.contentPositionUs; long startPositionUs = mediaPeriodInfo.requestedContentPositionUs;
if (startPositionUs == C.TIME_UNSET) { if (startPositionUs == C.TIME_UNSET) {
// If we're transitioning from an ad group to content starting from its default position, // If we're transitioning from an ad group to content starting from its default position,
// project the start position forward as if this were a transition to a new window. // project the start position forward as if this were a transition to a new window.
...@@ -656,6 +659,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -656,6 +659,7 @@ import com.google.android.exoplayer2.util.Assertions;
timeline, timeline,
currentPeriodId.periodUid, currentPeriodId.periodUid,
startPositionUs, startPositionUs,
mediaPeriodInfo.requestedContentPositionUs,
currentPeriodId.windowSequenceNumber); currentPeriodId.windowSequenceNumber);
} }
} else { } else {
...@@ -667,6 +671,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -667,6 +671,7 @@ import com.google.android.exoplayer2.util.Assertions;
timeline, timeline,
currentPeriodId.periodUid, currentPeriodId.periodUid,
/* startPositionUs= */ mediaPeriodInfo.durationUs, /* startPositionUs= */ mediaPeriodInfo.durationUs,
/* requestedContentPositionUs= */ mediaPeriodInfo.durationUs,
currentPeriodId.windowSequenceNumber); currentPeriodId.windowSequenceNumber);
} }
int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex); int adIndexInAdGroup = period.getFirstAdIndexToPlay(nextAdGroupIndex);
...@@ -683,7 +688,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -683,7 +688,7 @@ import com.google.android.exoplayer2.util.Assertions;
} }
private MediaPeriodInfo getMediaPeriodInfo( private MediaPeriodInfo getMediaPeriodInfo(
Timeline timeline, MediaPeriodId id, long contentPositionUs, long startPositionUs) { Timeline timeline, MediaPeriodId id, long requestedContentPositionUs, long startPositionUs) {
timeline.getPeriodByUid(id.periodUid, period); timeline.getPeriodByUid(id.periodUid, period);
if (id.isAd()) { if (id.isAd()) {
if (!period.isAdAvailable(id.adGroupIndex, id.adIndexInAdGroup)) { if (!period.isAdAvailable(id.adGroupIndex, id.adIndexInAdGroup)) {
...@@ -694,11 +699,15 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -694,11 +699,15 @@ import com.google.android.exoplayer2.util.Assertions;
id.periodUid, id.periodUid,
id.adGroupIndex, id.adGroupIndex,
id.adIndexInAdGroup, id.adIndexInAdGroup,
contentPositionUs, requestedContentPositionUs,
id.windowSequenceNumber); id.windowSequenceNumber);
} else { } else {
return getMediaPeriodInfoForContent( return getMediaPeriodInfoForContent(
timeline, id.periodUid, startPositionUs, id.windowSequenceNumber); timeline,
id.periodUid,
startPositionUs,
requestedContentPositionUs,
id.windowSequenceNumber);
} }
} }
...@@ -730,7 +739,11 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -730,7 +739,11 @@ import com.google.android.exoplayer2.util.Assertions;
} }
private MediaPeriodInfo getMediaPeriodInfoForContent( private MediaPeriodInfo getMediaPeriodInfoForContent(
Timeline timeline, Object periodUid, long startPositionUs, long windowSequenceNumber) { Timeline timeline,
Object periodUid,
long startPositionUs,
long requestedContentPositionUs,
long windowSequenceNumber) {
int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs); int nextAdGroupIndex = period.getAdGroupIndexAfterPositionUs(startPositionUs);
MediaPeriodId id = new MediaPeriodId(periodUid, windowSequenceNumber, nextAdGroupIndex); MediaPeriodId id = new MediaPeriodId(periodUid, windowSequenceNumber, nextAdGroupIndex);
boolean isLastInPeriod = isLastInPeriod(id); boolean isLastInPeriod = isLastInPeriod(id);
...@@ -746,7 +759,7 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -746,7 +759,7 @@ import com.google.android.exoplayer2.util.Assertions;
return new MediaPeriodInfo( return new MediaPeriodInfo(
id, id,
startPositionUs, startPositionUs,
/* contentPositionUs= */ C.TIME_UNSET, requestedContentPositionUs,
endPositionUs, endPositionUs,
durationUs, durationUs,
isLastInPeriod, isLastInPeriod,
......
...@@ -38,12 +38,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -38,12 +38,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
/** The {@link MediaPeriodId} of the currently playing media period in the {@link #timeline}. */ /** The {@link MediaPeriodId} of the currently playing media period in the {@link #timeline}. */
public final MediaPeriodId periodId; public final MediaPeriodId periodId;
/** /**
* If {@link #periodId} refers to an ad, the position of the suspended content relative to the * The requested next start position for the current period in the {@link #timeline}, in
* start of the associated period in the {@link #timeline}, in microseconds. {@link C#TIME_UNSET} * microseconds, or {@link C#TIME_UNSET} if the period was requested to start at its default
* if {@link #periodId} does not refer to an ad or if the suspended content should be played from * position.
* its default position. *
* <p>Note that if {@link #periodId} refers to an ad, this is the requested start position for the
* suspended content.
*/ */
public final long contentPositionUs; public final long requestedContentPositionUs;
/** The current playback state. One of the {@link Player}.STATE_ constants. */ /** The current playback state. One of the {@link Player}.STATE_ constants. */
@Player.State public final int playbackState; @Player.State public final int playbackState;
/** The current playback error, or null if this is not an error state. */ /** The current playback error, or null if this is not an error state. */
...@@ -102,7 +104,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -102,7 +104,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* *
* @param timeline See {@link #timeline}. * @param timeline See {@link #timeline}.
* @param periodId See {@link #periodId}. * @param periodId See {@link #periodId}.
* @param contentPositionUs See {@link #contentPositionUs}. * @param requestedContentPositionUs See {@link #requestedContentPositionUs}.
* @param playbackState See {@link #playbackState}. * @param playbackState See {@link #playbackState}.
* @param isLoading See {@link #isLoading}. * @param isLoading See {@link #isLoading}.
* @param trackGroups See {@link #trackGroups}. * @param trackGroups See {@link #trackGroups}.
...@@ -115,7 +117,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -115,7 +117,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public PlaybackInfo( public PlaybackInfo(
Timeline timeline, Timeline timeline,
MediaPeriodId periodId, MediaPeriodId periodId,
long contentPositionUs, long requestedContentPositionUs,
@Player.State int playbackState, @Player.State int playbackState,
@Nullable ExoPlaybackException playbackError, @Nullable ExoPlaybackException playbackError,
boolean isLoading, boolean isLoading,
...@@ -127,7 +129,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -127,7 +129,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
long positionUs) { long positionUs) {
this.timeline = timeline; this.timeline = timeline;
this.periodId = periodId; this.periodId = periodId;
this.contentPositionUs = contentPositionUs; this.requestedContentPositionUs = requestedContentPositionUs;
this.playbackState = playbackState; this.playbackState = playbackState;
this.playbackError = playbackError; this.playbackError = playbackError;
this.isLoading = isLoading; this.isLoading = isLoading;
...@@ -149,8 +151,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -149,8 +151,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* *
* @param periodId New playing media period. See {@link #periodId}. * @param periodId New playing media period. See {@link #periodId}.
* @param positionUs New position. See {@link #positionUs}. * @param positionUs New position. See {@link #positionUs}.
* @param contentPositionUs New content position. See {@link #contentPositionUs}. Value is ignored * @param requestedContentPositionUs New requested content position. See {@link
* if {@code periodId.isAd()} is true. * #requestedContentPositionUs}.
* @param totalBufferedDurationUs New buffered duration. See {@link #totalBufferedDurationUs}. * @param totalBufferedDurationUs New buffered duration. See {@link #totalBufferedDurationUs}.
* @param trackGroups The track groups for the new position. See {@link #trackGroups}. * @param trackGroups The track groups for the new position. See {@link #trackGroups}.
* @param trackSelectorResult The track selector result for the new position. See {@link * @param trackSelectorResult The track selector result for the new position. See {@link
...@@ -161,14 +163,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -161,14 +163,14 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public PlaybackInfo copyWithNewPosition( public PlaybackInfo copyWithNewPosition(
MediaPeriodId periodId, MediaPeriodId periodId,
long positionUs, long positionUs,
long contentPositionUs, long requestedContentPositionUs,
long totalBufferedDurationUs, long totalBufferedDurationUs,
TrackGroupArray trackGroups, TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult) { TrackSelectorResult trackSelectorResult) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
periodId.isAd() ? contentPositionUs : C.TIME_UNSET, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
...@@ -191,7 +193,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -191,7 +193,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
...@@ -214,7 +216,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -214,7 +216,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
...@@ -237,7 +239,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -237,7 +239,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
...@@ -260,7 +262,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -260,7 +262,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
...@@ -283,7 +285,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -283,7 +285,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
periodId, periodId,
contentPositionUs, requestedContentPositionUs,
playbackState, playbackState,
playbackError, playbackError,
isLoading, isLoading,
......
...@@ -76,6 +76,7 @@ public final class MediaPeriodQueueTest { ...@@ -76,6 +76,7 @@ public final class MediaPeriodQueueTest {
setupTimeline(); setupTimeline();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* requestedContentPositionUs= */ C.TIME_UNSET,
/* endPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true, /* isLast= */ true,
...@@ -86,10 +87,11 @@ public final class MediaPeriodQueueTest { ...@@ -86,10 +87,11 @@ public final class MediaPeriodQueueTest {
public void getNextMediaPeriodInfo_withPrerollAd_returnsCorrectMediaPeriodInfos() { public void getNextMediaPeriodInfo_withPrerollAd_returnsCorrectMediaPeriodInfos() {
setupTimeline(/* adGroupTimesUs...= */ 0); setupTimeline(/* adGroupTimesUs...= */ 0);
setAdGroupLoaded(/* adGroupIndex= */ 0); setAdGroupLoaded(/* adGroupIndex= */ 0);
assertNextMediaPeriodInfoIsAd(/* adGroupIndex= */ 0, /* contentPositionUs= */ 0); assertNextMediaPeriodInfoIsAd(/* adGroupIndex= */ 0, /* contentPositionUs= */ C.TIME_UNSET);
advance(); advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* requestedContentPositionUs= */ C.TIME_UNSET,
/* endPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true, /* isLast= */ true,
...@@ -101,6 +103,7 @@ public final class MediaPeriodQueueTest { ...@@ -101,6 +103,7 @@ public final class MediaPeriodQueueTest {
setupTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US); setupTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, SECOND_AD_START_TIME_US);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* requestedContentPositionUs= */ C.TIME_UNSET,
/* endPositionUs= */ FIRST_AD_START_TIME_US, /* endPositionUs= */ FIRST_AD_START_TIME_US,
/* durationUs= */ FIRST_AD_START_TIME_US, /* durationUs= */ FIRST_AD_START_TIME_US,
/* isLast= */ false, /* isLast= */ false,
...@@ -114,6 +117,7 @@ public final class MediaPeriodQueueTest { ...@@ -114,6 +117,7 @@ public final class MediaPeriodQueueTest {
advance(); advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ FIRST_AD_START_TIME_US, /* startPositionUs= */ FIRST_AD_START_TIME_US,
/* requestedContentPositionUs= */ FIRST_AD_START_TIME_US,
/* endPositionUs= */ SECOND_AD_START_TIME_US, /* endPositionUs= */ SECOND_AD_START_TIME_US,
/* durationUs= */ SECOND_AD_START_TIME_US, /* durationUs= */ SECOND_AD_START_TIME_US,
/* isLast= */ false, /* isLast= */ false,
...@@ -125,6 +129,7 @@ public final class MediaPeriodQueueTest { ...@@ -125,6 +129,7 @@ public final class MediaPeriodQueueTest {
advance(); advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ SECOND_AD_START_TIME_US, /* startPositionUs= */ SECOND_AD_START_TIME_US,
/* requestedContentPositionUs= */ SECOND_AD_START_TIME_US,
/* endPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true, /* isLast= */ true,
...@@ -136,6 +141,7 @@ public final class MediaPeriodQueueTest { ...@@ -136,6 +141,7 @@ public final class MediaPeriodQueueTest {
setupTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, C.TIME_END_OF_SOURCE); setupTimeline(/* adGroupTimesUs...= */ FIRST_AD_START_TIME_US, C.TIME_END_OF_SOURCE);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* requestedContentPositionUs= */ C.TIME_UNSET,
/* endPositionUs= */ FIRST_AD_START_TIME_US, /* endPositionUs= */ FIRST_AD_START_TIME_US,
/* durationUs= */ FIRST_AD_START_TIME_US, /* durationUs= */ FIRST_AD_START_TIME_US,
/* isLast= */ false, /* isLast= */ false,
...@@ -147,6 +153,7 @@ public final class MediaPeriodQueueTest { ...@@ -147,6 +153,7 @@ public final class MediaPeriodQueueTest {
advance(); advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ FIRST_AD_START_TIME_US, /* startPositionUs= */ FIRST_AD_START_TIME_US,
/* requestedContentPositionUs= */ FIRST_AD_START_TIME_US,
/* endPositionUs= */ C.TIME_END_OF_SOURCE, /* endPositionUs= */ C.TIME_END_OF_SOURCE,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ false, /* isLast= */ false,
...@@ -158,6 +165,7 @@ public final class MediaPeriodQueueTest { ...@@ -158,6 +165,7 @@ public final class MediaPeriodQueueTest {
advance(); advance();
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ CONTENT_DURATION_US, /* startPositionUs= */ CONTENT_DURATION_US,
/* requestedContentPositionUs= */ CONTENT_DURATION_US,
/* endPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true, /* isLast= */ true,
...@@ -169,6 +177,7 @@ public final class MediaPeriodQueueTest { ...@@ -169,6 +177,7 @@ public final class MediaPeriodQueueTest {
setupTimeline(/* adGroupTimesUs...= */ C.TIME_END_OF_SOURCE); setupTimeline(/* adGroupTimesUs...= */ C.TIME_END_OF_SOURCE);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* requestedContentPositionUs= */ C.TIME_UNSET,
/* endPositionUs= */ C.TIME_END_OF_SOURCE, /* endPositionUs= */ C.TIME_END_OF_SOURCE,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ false, /* isLast= */ false,
...@@ -177,6 +186,7 @@ public final class MediaPeriodQueueTest { ...@@ -177,6 +186,7 @@ public final class MediaPeriodQueueTest {
setAdGroupFailedToLoad(/* adGroupIndex= */ 0); setAdGroupFailedToLoad(/* adGroupIndex= */ 0);
assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
/* startPositionUs= */ CONTENT_DURATION_US, /* startPositionUs= */ CONTENT_DURATION_US,
/* requestedContentPositionUs= */ CONTENT_DURATION_US,
/* endPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET,
/* durationUs= */ CONTENT_DURATION_US, /* durationUs= */ CONTENT_DURATION_US,
/* isLast= */ true, /* isLast= */ true,
...@@ -343,7 +353,7 @@ public final class MediaPeriodQueueTest { ...@@ -343,7 +353,7 @@ public final class MediaPeriodQueueTest {
new PlaybackInfo( new PlaybackInfo(
timeline, timeline,
mediaPeriodQueue.resolveMediaPeriodIdForAds(timeline, periodUid, /* positionUs= */ 0), mediaPeriodQueue.resolveMediaPeriodIdForAds(timeline, periodUid, /* positionUs= */ 0),
/* contentPositionUs= */ 0, /* requestedContentPositionUs= */ C.TIME_UNSET,
Player.STATE_READY, Player.STATE_READY,
/* playbackError= */ null, /* playbackError= */ null,
/* isLoading= */ false, /* isLoading= */ false,
...@@ -428,6 +438,7 @@ public final class MediaPeriodQueueTest { ...@@ -428,6 +438,7 @@ public final class MediaPeriodQueueTest {
private void assertGetNextMediaPeriodInfoReturnsContentMediaPeriod( private void assertGetNextMediaPeriodInfoReturnsContentMediaPeriod(
long startPositionUs, long startPositionUs,
long requestedContentPositionUs,
long endPositionUs, long endPositionUs,
long durationUs, long durationUs,
boolean isLast, boolean isLast,
...@@ -437,7 +448,7 @@ public final class MediaPeriodQueueTest { ...@@ -437,7 +448,7 @@ public final class MediaPeriodQueueTest {
new MediaPeriodInfo( new MediaPeriodInfo(
new MediaPeriodId(periodUid, /* windowSequenceNumber= */ 0, nextAdGroupIndex), new MediaPeriodId(periodUid, /* windowSequenceNumber= */ 0, nextAdGroupIndex),
startPositionUs, startPositionUs,
/* contentPositionUs= */ C.TIME_UNSET, requestedContentPositionUs,
endPositionUs, endPositionUs,
durationUs, durationUs,
/* isLastInTimelinePeriod= */ isLast, /* isLastInTimelinePeriod= */ isLast,
......
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