Skip to content

Commit

Permalink
Fixes early transiton to Player.STATE_ENDED with MPD transition dyn…
Browse files Browse the repository at this point in the history
…amic to static

This checkin fixes Issue androidx#1441 where the player transitons to `Player.STATE_ENDED` once
the buffer runs out on a DASH start-over playlist that has transitioned from dynamic to static.

The fix detects the DASH Period has changed offset to the window, which occurs when the
origin vendor follows the DASH-IF recommendations in
*Section 4.6.4. Transition Phase between Live and On-Demand* ,  summerized as:

-	adds the attribute `MPD@mediaPresentationDuration`
-	removes the attribute `MPD@minimumUpdatePeriod`
-	`Period@start` is removed (if it was present)
-	`Period@duration` is added (in case more than 1 period is present)
-	`Adaptationset .SegmentTemplate@presentationTimeOffset` is set to earliest presentation time of a segment in the Adaptationset

The MPD change does not affect the render position or the segment timeline at all, however
the cleanest way to implement this was to report a `PositionUpdateForPlaylistChange`
which triggers a seek and flushes the current buffered content.
  • Loading branch information
stevemayhew committed Jun 12, 2024
1 parent ca51ed6 commit a9f57d4
Showing 1 changed file with 21 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3030,6 +3030,11 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange(
}
}

long periodPositionDeltaUs = checkPlayingPeriodPositionChanged(timeline, playbackInfo, period.windowIndex);
if (periodPositionDeltaUs > 0) {
periodPositionUs = periodPositionUs - periodPositionDeltaUs;
}

return new PositionUpdateForPlaylistChange(
newPeriodId,
periodPositionUs,
Expand All @@ -3039,6 +3044,22 @@ private static PositionUpdateForPlaylistChange resolvePositionForPlaylistChange(
setTargetLiveOffset);
}

private static long checkPlayingPeriodPositionChanged(Timeline timeline, PlaybackInfo playbackInfo, int currentWindowIndex) {
long periodPositionDeltaUs = C.TIME_UNSET;
if (!playbackInfo.timeline.isEmpty() && !timeline.isEmpty() && !playbackInfo.periodId.isAd()) {
Timeline.Window newWindow = timeline.getWindow(currentWindowIndex, new Timeline.Window());
Timeline.Window oldWindow = playbackInfo.timeline.getWindow(currentWindowIndex, new Timeline.Window());
if (oldWindow.isDynamic && ! newWindow.isDynamic) {
Timeline.Period newPeriod = timeline.getPeriodByUid(playbackInfo.periodId.periodUid, new Timeline.Period());
int windowIndex = newPeriod.windowIndex;
Pair<Object, Long> oldPositionZero = playbackInfo.timeline.getPeriodPosition(oldWindow, new Timeline.Period(), windowIndex, 0);
Pair<Object, Long> newPositionZero = timeline.getPeriodPosition(newWindow, new Timeline.Period(), windowIndex, 0);
periodPositionDeltaUs = oldPositionZero.second - newPositionZero.second;
}
}
return periodPositionDeltaUs;
}

private static boolean isIgnorableServerSideAdInsertionPeriodChange(
boolean isUsingPlaceholderPeriod,
MediaPeriodId oldPeriodId,
Expand Down

0 comments on commit a9f57d4

Please sign in to comment.