mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Split ad playback state and recalculate window and period duriations
This change enables the ImaServerSideAdInsertionMediaSource for multi-period content. The global ad playback state is split into pieces for each period and the window and period durations are calculated accordingly in the ServerSideAdInsertionTimeline. For multi-period live content (DASH), the ad playback state is not set with this change. This is deferred to a follow up CL. Splitting is very tricky. For each timeline update the windowStartTimeUs may vary for some milliseconds relative to the start of the period.positionInWindowUs. This requires to either introduce some fuzzy logic or to choose a different approach than for multi-period VOD. Because mistakes within the playback states of subsequent moving live windows produces crashes, it seems sensible to defer this for now and keep this change in a separate future CL (unblock further work, easy to rollback). In this state, live DASH stream are working and the ad overlay is placed over the player correctly bu the SDK. However, ads are not reported by the position discontinuity event. Similarly, the player.isPlayingAd() does never returns true when a ad period is playing. PiperOrigin-RevId: 422539770
This commit is contained in:
parent
05d5937855
commit
05e23996fa
@ -994,7 +994,6 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
public ServerSideAdInsertionTimeline(
|
||||
Timeline contentTimeline, ImmutableMap<Object, AdPlaybackState> adPlaybackStates) {
|
||||
super(contentTimeline);
|
||||
checkState(contentTimeline.getPeriodCount() == 1);
|
||||
checkState(contentTimeline.getWindowCount() == 1);
|
||||
Period period = new Period();
|
||||
for (int i = 0; i < contentTimeline.getPeriodCount(); i++) {
|
||||
@ -1008,25 +1007,23 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
||||
super.getWindow(windowIndex, window, defaultPositionProjectionUs);
|
||||
Object firstPeriodUid =
|
||||
checkNotNull(getPeriod(/* periodIndex= */ 0, new Period(), /* setIds= */ true).uid);
|
||||
AdPlaybackState adPlaybackState = checkNotNull(adPlaybackStates.get(firstPeriodUid));
|
||||
checkNotNull(getPeriod(window.firstPeriodIndex, new Period(), /* setIds= */ true).uid);
|
||||
AdPlaybackState firstAdPlaybackState = checkNotNull(adPlaybackStates.get(firstPeriodUid));
|
||||
long positionInPeriodUs =
|
||||
getMediaPeriodPositionUsForContent(
|
||||
window.positionInFirstPeriodUs,
|
||||
/* nextAdGroupIndex= */ C.INDEX_UNSET,
|
||||
adPlaybackState);
|
||||
firstAdPlaybackState);
|
||||
if (window.durationUs == C.TIME_UNSET) {
|
||||
if (adPlaybackState.contentDurationUs != C.TIME_UNSET) {
|
||||
window.durationUs = adPlaybackState.contentDurationUs - positionInPeriodUs;
|
||||
if (firstAdPlaybackState.contentDurationUs != C.TIME_UNSET) {
|
||||
window.durationUs = firstAdPlaybackState.contentDurationUs - positionInPeriodUs;
|
||||
}
|
||||
} else {
|
||||
long actualWindowEndPositionInPeriodUs = window.positionInFirstPeriodUs + window.durationUs;
|
||||
long windowEndPositionInPeriodUs =
|
||||
getMediaPeriodPositionUsForContent(
|
||||
actualWindowEndPositionInPeriodUs,
|
||||
/* nextAdGroupIndex= */ C.INDEX_UNSET,
|
||||
adPlaybackState);
|
||||
window.durationUs = windowEndPositionInPeriodUs - positionInPeriodUs;
|
||||
Period lastPeriod = getPeriod(/* periodIndex= */ window.lastPeriodIndex, new Period());
|
||||
window.durationUs =
|
||||
lastPeriod.durationUs == C.TIME_UNSET
|
||||
? C.TIME_UNSET
|
||||
: lastPeriod.positionInWindowUs + lastPeriod.durationUs;
|
||||
}
|
||||
window.positionInFirstPeriodUs = positionInPeriodUs;
|
||||
return window;
|
||||
@ -1044,11 +1041,26 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
|
||||
getMediaPeriodPositionUsForContent(
|
||||
durationUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState);
|
||||
}
|
||||
long positionInWindowUs =
|
||||
-getMediaPeriodPositionUsForContent(
|
||||
-period.getPositionInWindowUs(),
|
||||
/* nextAdGroupIndex= */ C.INDEX_UNSET,
|
||||
adPlaybackState);
|
||||
long positionInWindowUs = 0;
|
||||
Period innerPeriod = new Period();
|
||||
for (int i = 0; i < periodIndex + 1; i++) {
|
||||
timeline.getPeriod(/* periodIndex= */ i, innerPeriod, /* setIds= */ true);
|
||||
AdPlaybackState innerAdPlaybackState = checkNotNull(adPlaybackStates.get(innerPeriod.uid));
|
||||
if (i == 0) {
|
||||
positionInWindowUs =
|
||||
-getMediaPeriodPositionUsForContent(
|
||||
-innerPeriod.getPositionInWindowUs(),
|
||||
/* nextAdGroupIndex= */ C.INDEX_UNSET,
|
||||
innerAdPlaybackState);
|
||||
}
|
||||
if (i != periodIndex) {
|
||||
positionInWindowUs +=
|
||||
getMediaPeriodPositionUsForContent(
|
||||
innerPeriod.durationUs,
|
||||
/* nextAdGroupIndex= */ C.INDEX_UNSET,
|
||||
innerAdPlaybackState);
|
||||
}
|
||||
}
|
||||
period.set(
|
||||
period.id,
|
||||
period.uid,
|
||||
|
@ -74,29 +74,6 @@ public final class ServerSideAdInsertionUtil {
|
||||
adPlaybackState, insertionIndex, adDurationUs, contentResumeOffsetUs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the duration of the underlying server-side inserted ads stream for the current {@link
|
||||
* Timeline.Period} in the {@link Player}.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param adPlaybackState The {@link AdPlaybackState} defining the ad groups.
|
||||
* @return The duration of the underlying server-side inserted ads stream, in microseconds, or
|
||||
* {@link C#TIME_UNSET} if it can't be determined.
|
||||
*/
|
||||
public static long getStreamDurationUs(Player player, AdPlaybackState adPlaybackState) {
|
||||
Timeline timeline = player.getCurrentTimeline();
|
||||
if (timeline.isEmpty()) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
Timeline.Period period =
|
||||
timeline.getPeriod(player.getCurrentPeriodIndex(), new Timeline.Period());
|
||||
if (period.durationUs == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
return getStreamPositionUsForContent(
|
||||
period.durationUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position in the underlying server-side inserted ads stream for the current playback
|
||||
* position in the {@link Player}.
|
||||
|
Loading…
x
Reference in New Issue
Block a user