Commit dc887070 by bachinger Committed by tonihei

Don't drop updates of the playing period for skipped SSI ads

Before this change ExpPlayerImplInternal dropped a change of the playing period when a change in the timeline occurred that actually changed the playing period but we don't want to update the period queue. This logic also dropped the update of a skipped server side inserted preroll ad for which we want the periodQueue to 'seek' to the stream position after the preroll ad and trigger a SKIP discontinuity.

This change now introduces an exception so that a skipped SSI ad is still causing an update in the period queue which leads to a 'seek' and a discontinuity of type SKIP.

PiperOrigin-RevId: 411607299
parent 039eef00
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.AdPlaybackState.AD_STATE_UNAVAILABLE;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.Math.max; import static java.lang.Math.max;
...@@ -820,6 +821,22 @@ public abstract class Timeline implements Bundleable { ...@@ -820,6 +821,22 @@ public abstract class Timeline implements Bundleable {
} }
/** /**
* Returns the state of the ad at index {@code adIndexInAdGroup} in the ad group at {@code
* adGroupIndex}, or {@link AdPlaybackState#AD_STATE_UNAVAILABLE} if not yet known.
*
* @param adGroupIndex The ad group index.
* @return The state of the ad, or {@link AdPlaybackState#AD_STATE_UNAVAILABLE} if not yet
* known.
*/
@UnstableApi
public int getAdState(int adGroupIndex, int adIndexInAdGroup) {
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
return adGroup.count != C.LENGTH_UNSET
? adGroup.states[adIndexInAdGroup]
: AD_STATE_UNAVAILABLE;
}
/**
* Returns the position offset in the first unplayed ad at which to begin playback, in * Returns the position offset in the first unplayed ad at which to begin playback, in
* microseconds. * microseconds.
*/ */
......
...@@ -28,6 +28,7 @@ import android.os.SystemClock; ...@@ -28,6 +28,7 @@ import android.os.SystemClock;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.AdPlaybackState;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.IllegalSeekPositionException; import androidx.media3.common.IllegalSeekPositionException;
...@@ -2656,15 +2657,14 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2656,15 +2657,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
&& earliestCuePointIsUnchangedOrLater; && earliestCuePointIsUnchangedOrLater;
// Drop update if the change is from/to server-side inserted ads at the same content position to // Drop update if the change is from/to server-side inserted ads at the same content position to
// avoid any unintentional renderer reset. // avoid any unintentional renderer reset.
timeline.getPeriodByUid(newPeriodUid, period);
boolean isInStreamAdChange = boolean isInStreamAdChange =
sameOldAndNewPeriodUid isIgnorableServerSideAdInsertionPeriodChange(
&& !isUsingPlaceholderPeriod isUsingPlaceholderPeriod,
&& oldContentPositionUs == newContentPositionUs oldPeriodId,
&& ((periodIdWithAds.isAd() oldContentPositionUs,
&& period.isServerSideInsertedAdGroup(periodIdWithAds.adGroupIndex)) periodIdWithAds,
|| (oldPeriodId.isAd() timeline.getPeriodByUid(newPeriodUid, period),
&& period.isServerSideInsertedAdGroup(oldPeriodId.adGroupIndex))); newContentPositionUs);
MediaPeriodId newPeriodId = MediaPeriodId newPeriodId =
onlyNextAdGroupIndexIncreased || isInStreamAdChange ? oldPeriodId : periodIdWithAds; onlyNextAdGroupIndexIncreased || isInStreamAdChange ? oldPeriodId : periodIdWithAds;
...@@ -2690,6 +2690,30 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -2690,6 +2690,30 @@ import java.util.concurrent.atomic.AtomicBoolean;
setTargetLiveOffset); setTargetLiveOffset);
} }
private static boolean isIgnorableServerSideAdInsertionPeriodChange(
boolean isUsingPlaceholderPeriod,
MediaPeriodId oldPeriodId,
long oldContentPositionUs,
MediaPeriodId newPeriodId,
Timeline.Period newPeriod,
long newContentPositionUs) {
if (isUsingPlaceholderPeriod
|| oldContentPositionUs != newContentPositionUs
|| !oldPeriodId.periodUid.equals(newPeriodId.periodUid)) {
// The period position changed.
return false;
}
if (oldPeriodId.isAd() && newPeriod.isServerSideInsertedAdGroup(oldPeriodId.adGroupIndex)) {
// Whether the old period was a server side ad that doesn't need skipping to the content.
return newPeriod.getAdState(oldPeriodId.adGroupIndex, oldPeriodId.adIndexInAdGroup)
!= AdPlaybackState.AD_STATE_ERROR
&& newPeriod.getAdState(oldPeriodId.adGroupIndex, oldPeriodId.adIndexInAdGroup)
!= AdPlaybackState.AD_STATE_SKIPPED;
}
// If the new period is a server side inserted ad, we can just continue playing.
return newPeriodId.isAd() && newPeriod.isServerSideInsertedAdGroup(newPeriodId.adGroupIndex);
}
private static boolean isUsingPlaceholderPeriod( private static boolean isUsingPlaceholderPeriod(
PlaybackInfo playbackInfo, Timeline.Period period) { PlaybackInfo playbackInfo, Timeline.Period period) {
MediaPeriodId periodId = playbackInfo.periodId; MediaPeriodId periodId = playbackInfo.periodId;
......
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