Multi period content support for AdsMediaSource#3126
Multi period content support for AdsMediaSource#3126kotucz wants to merge 12 commits intoandroidx:mainfrom
Conversation
Because of commit: Don't enqueue ad periods that start after the end of the period Issue: androidx#2215 PiperOrigin-RevId: 747376615
|
Thanks for the pull request (and rebasing your earlier attempt from #2501)! I'll leave some comment for discussion, but overall looks like the right approach. |
| boolean sameOldAndNewPeriodUid = oldPeriodId.periodUid.equals(newPeriodUid); | ||
| boolean onlyNextAdGroupIndexIncreased = | ||
| sameOldAndNewPeriodUid | ||
| && samePeriodCount |
There was a problem hiding this comment.
This specific condition about the having the same number of periods is probably too restrictive overall (imagine using the AdsMediaSource in a playlist with other items).
Is it possible to check for Timeline.Period.isPlaceholder in this condition to not apply this check when we go from placeholder to non-placeholder? This would of course only work if the isPlaceholder flag is changing at the right moment too. Alternatively, I wonder if we need additional checks for this logic to verify that the time of the ad group hasn't changed or is within the period duration. As you can see from the comment, the purpose of this check has really nothing to do with the multi-period ads, but with failed future ads that are not supposed to interrupt playback immediately.
| adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurationsUs()); | ||
| refreshSourceInfo(new SinglePeriodAdTimeline(contentTimeline, adPlaybackState)); | ||
| if (contentTimeline.getPeriodCount() == 1) { | ||
| refreshSourceInfo(new SinglePeriodAdTimeline(contentTimeline, adPlaybackState)); |
There was a problem hiding this comment.
The SinglePeriodAdTimeline now sounds like a subset of the MultiPeriodAdTimelime - could this just be changed to be simply an AdTimeline? We likely need to keep SinglePeriodAdTimeline as deprecated to avoid breakages, but otherwise it looks like the new class can be just be used instead of the old one.
| * <ul> | ||
| * <li> ad group time is offset relative to period start time </li> | ||
| * <li> post-roll ad group is kept only for last period </li> | ||
| * <li> ad group count and indices are kept unchanged </li> |
There was a problem hiding this comment.
This part is surprising to me because it sounds like we would play all ads repeatedly for all periods. I assume some of the internal player logic prevents that from happening, but it would be much cleaner if we could actually split the AdPlaybackState fully into the individual ads for each period.
There was a problem hiding this comment.
Second note: When looking for other adjustments that might be needed in AdsMediaSource, I realized you avoided making these adjustments by keeping the adGroupIndex stable across all periods. So if you follow my suggestion here to split the AdPlaybackState properly, the logic in AdsMediaSource.createPeriod/releasePeriod/onChildSourceInfoRefreshed and potentially other places would need to change to reverse the mapping from adGroupIndex in a period to adGroupIndex in the 'global' AdPlaybackState.
Given all that, I think your approach of keeping the indices stable without further mapping is actually quite useful. I'm curious to hear whether you tried the other idea of splitting the state further still.
| } else { | ||
| // start time relative to period start | ||
| adPlaybackState = adPlaybackState.withAdGroupTimeUs(adGroupIndex, | ||
| adGroupTimeUs - periodStartOffsetUs); |
There was a problem hiding this comment.
If this is negative or beyond the period duration, should it also be marked as "skipped" to more clearly signal that this ad group should not be played for this period?
| @@ -0,0 +1,101 @@ | |||
| /* | |||
| * Copyright (C) 2017 The Android Open Source Project | |||
|
Re-reading the discussion of #1642 (comment), I also wonder if you thought about adjustments needed in |
Multi period DASH content ads support inspired by #1642 (comment)
Reopens: #2501
At Timeline level, the original
AdPlaybackStateis divided and adjusted for each of the periods.Removing single period assertions from
AdsMediaSource.Providing
MultiPeriodAdTimelineas an alternative to currentSinglePeriodAdTimeline.From input
AdPlaybackState, new modifiedAdPlaybackStateis created - one for each period:The streaming continues beyond the duration if VMAP has scheduled advertises after duration itself #2215)
More detail is also here:
https://blog.hotstar.com/monetisation-multi-period-dash-x-exoplayer-db8e8c00e521
We have encountered an issue, which is also handled in this PR:
Player is using
MaskingMediaSourceto reduce start lag. This means preroll ads are loaded in parallel to resolving content manifest. Meanwhile placeholder manifest is used for content temporarily having single period.Ads are initialized as follows:
After the content manifest (MPD) is resolved content will have multiple periods.
For each period we will create an adjusted copy the main
AdPlaybackStateto have specific config of ads.Preroll will stay unchange (no fill), while midrolls for period 0 (bumper/disclaimer) will be marked as SKIPPED as these should not be played in this period.
Note: if preroll is available it refreshes the timeline when it is done playing at this moment real timeline with periods is available and
AdPlaybackStates are reflected as expectedExoPlayer has evaluates this update can be ignored. (Placeholder and real timeline have same Id and are not distinguished)
Player plays until the ad group is reached. But since the ad group is only some time after the period end, player is stuck in the end of period 0, waiting for the midroll to be played.
Note: Seekbar or fast forward button can be used to unstuck the player (forcing Timeline update).
FIX: Player timeline will be recreated when period count is changed
Example:
What happens:
Midroll is not in period 0, but this change is not reflected in the Timeline on the placeholder timeline -> multiperiod timeline transition