Add client side post roll placeholder

PiperOrigin-RevId: 707142019
This commit is contained in:
bachinger 2024-12-17 09:56:15 -08:00 committed by Copybara-Service
parent 32ab258c43
commit aa2ee8f702
7 changed files with 349 additions and 82 deletions

View file

@ -35,6 +35,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.media3.common.util.NullableType; import androidx.media3.common.util.NullableType;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import com.google.errorprone.annotations.InlineMe;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -71,7 +72,7 @@ public final class AdPlaybackState {
/** /**
* The original number of ads in the ad group in case the ad group is only partially available, * The original number of ads in the ad group in case the ad group is only partially available,
* or {@link C#LENGTH_UNSET} if unknown. An ad can be partially available when a server side * or {@link C#LENGTH_UNSET} if unknown. An ad can be partially available when a server-side
* inserted ad live stream is joined while an ad is already playing and some ad information is * inserted ad live stream is joined while an ad is already playing and some ad information is
* missing. * missing.
*/ */
@ -103,6 +104,9 @@ public final class AdPlaybackState {
/** Whether this ad group is server-side inserted and part of the content stream. */ /** Whether this ad group is server-side inserted and part of the content stream. */
public final boolean isServerSideInserted; public final boolean isServerSideInserted;
/** Whether this is an ignorable placeholder that must not be attempted to be played. */
public final boolean isPlaceholder;
/** /**
* Creates a new ad group with an unspecified number of ads. * Creates a new ad group with an unspecified number of ads.
* *
@ -119,7 +123,8 @@ public final class AdPlaybackState {
/* durationsUs= */ new long[0], /* durationsUs= */ new long[0],
/* contentResumeOffsetUs= */ 0, /* contentResumeOffsetUs= */ 0,
/* isServerSideInserted= */ false, /* isServerSideInserted= */ false,
/* ids= */ new String[0]); /* ids= */ new String[0],
/* isPlaceholder= */ false);
} }
@SuppressWarnings("deprecation") // Intentionally assigning deprecated field @SuppressWarnings("deprecation") // Intentionally assigning deprecated field
@ -132,7 +137,8 @@ public final class AdPlaybackState {
long[] durationsUs, long[] durationsUs,
long contentResumeOffsetUs, long contentResumeOffsetUs,
boolean isServerSideInserted, boolean isServerSideInserted,
@NullableType String[] ids) { @NullableType String[] ids,
boolean isPlaceholder) {
checkArgument(states.length == mediaItems.length); checkArgument(states.length == mediaItems.length);
this.timeUs = timeUs; this.timeUs = timeUs;
this.count = count; this.count = count;
@ -147,6 +153,7 @@ public final class AdPlaybackState {
uris[i] = mediaItems[i] == null ? null : checkNotNull(mediaItems[i].localConfiguration).uri; uris[i] = mediaItems[i] == null ? null : checkNotNull(mediaItems[i].localConfiguration).uri;
} }
this.ids = ids; this.ids = ids;
this.isPlaceholder = isPlaceholder;
} }
/** /**
@ -162,7 +169,7 @@ public final class AdPlaybackState {
* lastPlayedAdIndex}, or {@link #count} if no later ads should be played. If no ads have been * lastPlayedAdIndex}, or {@link #count} if no later ads should be played. If no ads have been
* played, pass -1 to get the index of the first ad to play. * played, pass -1 to get the index of the first ad to play.
* *
* <p>Note: {@linkplain #isServerSideInserted Server side inserted ads} are always considered * <p>Note: {@linkplain #isServerSideInserted server-side inserted ads} are always considered
* playable. * playable.
*/ */
public int getNextAdIndexToPlay(@IntRange(from = -1) int lastPlayedAdIndex) { public int getNextAdIndexToPlay(@IntRange(from = -1) int lastPlayedAdIndex) {
@ -198,8 +205,24 @@ public final class AdPlaybackState {
return false; return false;
} }
private boolean isLivePostrollPlaceholder() { /**
return isServerSideInserted && timeUs == C.TIME_END_OF_SOURCE && count == C.LENGTH_UNSET; * Returns whether this is a is a placeholder ad group.
*
* @param isServerSideInserted Whether the postroll placeholder must be server-side inserted.
* @return true only if this ad group has a matching {@link #isServerSideInserted} flag.
*/
public boolean isLivePostrollPlaceholder(boolean isServerSideInserted) {
return (this.isServerSideInserted == isServerSideInserted) && isLivePostrollPlaceholder();
}
/**
* Returns whether this is a placeholder ad group. It can be server-side inserted or not. Use
* {@link #isLivePostrollPlaceholder(boolean)} if you want to differentiate.
*
* @return true only if this is a live postroll placeholder.
*/
public boolean isLivePostrollPlaceholder() {
return isPlaceholder && timeUs == C.TIME_END_OF_SOURCE && count == C.LENGTH_UNSET;
} }
@Override @Override
@ -219,7 +242,8 @@ public final class AdPlaybackState {
&& Arrays.equals(durationsUs, adGroup.durationsUs) && Arrays.equals(durationsUs, adGroup.durationsUs)
&& contentResumeOffsetUs == adGroup.contentResumeOffsetUs && contentResumeOffsetUs == adGroup.contentResumeOffsetUs
&& isServerSideInserted == adGroup.isServerSideInserted && isServerSideInserted == adGroup.isServerSideInserted
&& Arrays.equals(ids, adGroup.ids); && Arrays.equals(ids, adGroup.ids)
&& isPlaceholder == adGroup.isPlaceholder;
} }
@Override @Override
@ -233,6 +257,7 @@ public final class AdPlaybackState {
result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32)); result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32));
result = 31 * result + (isServerSideInserted ? 1 : 0); result = 31 * result + (isServerSideInserted ? 1 : 0);
result = 31 * result + Arrays.hashCode(ids); result = 31 * result + Arrays.hashCode(ids);
result = 31 * result + (isPlaceholder ? 1 : 0);
return result; return result;
} }
@ -248,7 +273,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns a new instance with the ad count set to {@code count}. */ /** Returns a new instance with the ad count set to {@code count}. */
@ -267,7 +293,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** /**
@ -305,7 +332,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** /**
@ -346,7 +374,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns a new instance with the specified ad durations, in microseconds. */ /** Returns a new instance with the specified ad durations, in microseconds. */
@ -366,7 +395,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns a new instance with the specified ID for the given ad index. */ /** Returns a new instance with the specified ID for the given ad index. */
@ -395,7 +425,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns an instance with the specified {@link #contentResumeOffsetUs}. */ /** Returns an instance with the specified {@link #contentResumeOffsetUs}. */
@ -410,7 +441,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns an instance with the specified value for {@link #isServerSideInserted}. */ /** Returns an instance with the specified value for {@link #isServerSideInserted}. */
@ -425,7 +457,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Returns an instance with the specified value for {@link #originalCount}. */ /** Returns an instance with the specified value for {@link #originalCount}. */
@ -439,7 +472,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** Removes the last ad from the ad group. */ /** Removes the last ad from the ad group. */
@ -461,7 +495,8 @@ public final class AdPlaybackState {
newDurationsUs, newDurationsUs,
/* contentResumeOffsetUs= */ Util.sum(newDurationsUs), /* contentResumeOffsetUs= */ Util.sum(newDurationsUs),
isServerSideInserted, isServerSideInserted,
newIds); newIds,
isPlaceholder);
} }
/** /**
@ -480,7 +515,8 @@ public final class AdPlaybackState {
/* durationsUs= */ new long[0], /* durationsUs= */ new long[0],
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
int count = this.states.length; int count = this.states.length;
@AdState int[] states = Arrays.copyOf(this.states, count); @AdState int[] states = Arrays.copyOf(this.states, count);
@ -498,7 +534,8 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
} }
/** /**
@ -528,7 +565,22 @@ public final class AdPlaybackState {
durationsUs, durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids); ids,
isPlaceholder);
}
private AdGroup withIsPlaceholder(boolean isPlaceholder, boolean isServerSideInserted) {
return new AdGroup(
timeUs,
count,
originalCount,
states,
mediaItems,
durationsUs,
contentResumeOffsetUs,
isServerSideInserted,
ids,
isPlaceholder);
} }
/** /**
@ -572,6 +624,7 @@ public final class AdPlaybackState {
private static final String FIELD_ORIGINAL_COUNT = Util.intToStringMaxRadix(7); private static final String FIELD_ORIGINAL_COUNT = Util.intToStringMaxRadix(7);
@VisibleForTesting static final String FIELD_MEDIA_ITEMS = Util.intToStringMaxRadix(8); @VisibleForTesting static final String FIELD_MEDIA_ITEMS = Util.intToStringMaxRadix(8);
static final String FIELD_IDS = Util.intToStringMaxRadix(9); static final String FIELD_IDS = Util.intToStringMaxRadix(9);
static final String FIELD_IS_PLACEHOLDER = Util.intToStringMaxRadix(10);
// Intentionally assigning deprecated field. // Intentionally assigning deprecated field.
// putParcelableArrayList actually supports null elements. // putParcelableArrayList actually supports null elements.
@ -589,6 +642,7 @@ public final class AdPlaybackState {
bundle.putLong(FIELD_CONTENT_RESUME_OFFSET_US, contentResumeOffsetUs); bundle.putLong(FIELD_CONTENT_RESUME_OFFSET_US, contentResumeOffsetUs);
bundle.putBoolean(FIELD_IS_SERVER_SIDE_INSERTED, isServerSideInserted); bundle.putBoolean(FIELD_IS_SERVER_SIDE_INSERTED, isServerSideInserted);
bundle.putStringArrayList(FIELD_IDS, new ArrayList<>(Arrays.asList(ids))); bundle.putStringArrayList(FIELD_IDS, new ArrayList<>(Arrays.asList(ids)));
bundle.putBoolean(FIELD_IS_PLACEHOLDER, isPlaceholder);
return bundle; return bundle;
} }
@ -610,6 +664,7 @@ public final class AdPlaybackState {
long contentResumeOffsetUs = bundle.getLong(FIELD_CONTENT_RESUME_OFFSET_US); long contentResumeOffsetUs = bundle.getLong(FIELD_CONTENT_RESUME_OFFSET_US);
boolean isServerSideInserted = bundle.getBoolean(FIELD_IS_SERVER_SIDE_INSERTED); boolean isServerSideInserted = bundle.getBoolean(FIELD_IS_SERVER_SIDE_INSERTED);
@Nullable ArrayList<String> ids = bundle.getStringArrayList(FIELD_IDS); @Nullable ArrayList<String> ids = bundle.getStringArrayList(FIELD_IDS);
boolean isPlaceholder = bundle.getBoolean(FIELD_IS_PLACEHOLDER);
return new AdGroup( return new AdGroup(
timeUs, timeUs,
count, count,
@ -619,7 +674,8 @@ public final class AdPlaybackState {
durationsUs == null ? new long[0] : durationsUs, durationsUs == null ? new long[0] : durationsUs,
contentResumeOffsetUs, contentResumeOffsetUs,
isServerSideInserted, isServerSideInserted,
ids == null ? new String[0] : ids.toArray(new String[0])); ids == null ? new String[0] : ids.toArray(new String[0]),
isPlaceholder);
} }
private ArrayList<@NullableType Bundle> getMediaItemsArrayBundles() { private ArrayList<@NullableType Bundle> getMediaItemsArrayBundles() {
@ -929,11 +985,11 @@ public final class AdPlaybackState {
/** /**
* Returns an instance with the specified ad marked as {@linkplain #AD_STATE_AVAILABLE available}. * Returns an instance with the specified ad marked as {@linkplain #AD_STATE_AVAILABLE available}.
* *
* <p>Must not be called with client side inserted ad groups. Client side inserted ads should use * <p>Must not be called with client-side inserted ad groups. Client-side inserted ads should use
* {@link #withAvailableAdMediaItem}. * {@link #withAvailableAdMediaItem}.
* *
* @throws IllegalStateException in case this methods is called on an ad group that {@linkplain * @throws IllegalStateException in case this methods is called on an ad group that {@linkplain
* AdGroup#isServerSideInserted is not server side inserted}. * AdGroup#isServerSideInserted is not server-side inserted}.
*/ */
@CheckResult @CheckResult
public AdPlaybackState withAvailableAd( public AdPlaybackState withAvailableAd(
@ -1160,24 +1216,55 @@ public final class AdPlaybackState {
} }
/** /**
* Appends a live post roll placeholder ad group to the ad playback state. * @deprecated Use {@link #withLivePostrollPlaceholderAppended(boolean)} and pass {@code true}
* instead.
*/
@InlineMe(replacement = "this.withLivePostrollPlaceholderAppended(true)")
@Deprecated
public AdPlaybackState withLivePostrollPlaceholderAppended() {
return withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
}
/**
* Appends a live postroll placeholder ad group to the ad playback state.
* *
* <p>Adding such a placeholder is only required for periods of server side ad insertion live * <p>Adding such a placeholder is only required for periods of live streams. A player is not
* streams. A player is not expected to play this placeholder. It is only used to indicate that * expected to play this placeholder. It is only used to indicate that another ad group with this
* another ad group with this ad group index will be inserted in the future. * ad group index will be inserted in the future.
* *
* <p>See {@link #endsWithLivePostrollPlaceHolder()} also. * <p>See {@link #endsWithLivePostrollPlaceHolder()} and {@link
* #endsWithLivePostrollPlaceHolder(boolean)} also.
* *
* @param isServerSideInserted Whether this is a server-side inserted ad (single stream).
* @return The new ad playback state instance ending with a live postroll placeholder. * @return The new ad playback state instance ending with a live postroll placeholder.
*/ */
public AdPlaybackState withLivePostrollPlaceholderAppended() { public AdPlaybackState withLivePostrollPlaceholderAppended(boolean isServerSideInserted) {
return withNewAdGroup(adGroupCount, /* adGroupTimeUs= */ C.TIME_END_OF_SOURCE) return withNewAdGroup(adGroupCount, /* adGroupTimeUs= */ C.TIME_END_OF_SOURCE)
.withIsServerSideInserted(adGroupCount, true); .withIsPlaceholder(adGroupCount, /* isPlaceholder= */ true, isServerSideInserted);
}
@VisibleForTesting
/* package */ AdPlaybackState withIsPlaceholder(
int adGroupIndex, boolean isPlaceholder, boolean isServerSideInserted) {
int adjustedIndex = adGroupIndex - removedAdGroupCount;
if (adGroups[adjustedIndex].isPlaceholder == isPlaceholder
&& adGroups[adjustedIndex].isServerSideInserted == isServerSideInserted) {
return this;
}
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
adGroups[adjustedIndex] =
adGroups[adjustedIndex].withIsPlaceholder(isPlaceholder, isServerSideInserted);
return new AdPlaybackState(
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
} }
/** /**
* Returns whether the last ad group is a live postroll placeholder as inserted by {@link * Returns whether the last ad group is a live postroll placeholder as inserted by {@link
* #withLivePostrollPlaceholderAppended()}. * #withLivePostrollPlaceholderAppended(boolean)}.
*
* <p>Note: That either server-side or client-side inserted placeholders are considered. Use
* {@link #endsWithLivePostrollPlaceHolder(boolean)} if you want to test for one or the other
* only.
* *
* @return Whether the ad playback state ends with a live postroll placeholder. * @return Whether the ad playback state ends with a live postroll placeholder.
*/ */
@ -1187,7 +1274,22 @@ public final class AdPlaybackState {
} }
/** /**
* Whether the {@link AdGroup} at the given ad group index is a live postroll placeholder. * Returns whether the last ad group is a live postroll placeholder as inserted by {@link
* #withLivePostrollPlaceholderAppended(boolean)} .
*
* @param isServerSideInserted Whether the trailing placeholder is server-side inserted.
* @return Whether the ad playback state ends with a live postroll placeholder.
*/
public boolean endsWithLivePostrollPlaceHolder(boolean isServerSideInserted) {
int adGroupIndex = adGroupCount - 1;
return adGroupIndex >= 0 && isLivePostrollPlaceholder(adGroupIndex, isServerSideInserted);
}
/**
* Returns whether the {@link AdGroup} at the given ad group index is a live postroll placeholder.
*
* <p>Note: That either server-side or client-side inserted placeholders return true. Use {@link
* #isLivePostrollPlaceholder(int, boolean)} if you want to test for one or the other only.
* *
* @param adGroupIndex The ad group index. * @param adGroupIndex The ad group index.
* @return True if the ad group at the given index is a live postroll placeholder, false if not. * @return True if the ad group at the given index is a live postroll placeholder, false if not.
@ -1196,6 +1298,19 @@ public final class AdPlaybackState {
return adGroupIndex == adGroupCount - 1 && getAdGroup(adGroupIndex).isLivePostrollPlaceholder(); return adGroupIndex == adGroupCount - 1 && getAdGroup(adGroupIndex).isLivePostrollPlaceholder();
} }
/**
* Returns whether the {@link AdGroup} at the given ad group index is a live postroll placeholder
* and either server or client-side inserted.
*
* @param adGroupIndex The ad group index.
* @param isServerSideInserted Whether the placeholder is server-side inserted.
* @return True if the ad group at the given index is a live postroll placeholder, false if not.
*/
public boolean isLivePostrollPlaceholder(int adGroupIndex, boolean isServerSideInserted) {
return adGroupIndex == adGroupCount - 1
&& getAdGroup(adGroupIndex).isLivePostrollPlaceholder(isServerSideInserted);
}
/** /**
* Returns the index of the ad with the given ad ID in the given ad group, or {@link * Returns the index of the ad with the given ad ID in the given ad group, or {@link
* C#INDEX_UNSET} if the ad ID can't be found. * C#INDEX_UNSET} if the ad ID can't be found.
@ -1230,7 +1345,8 @@ public final class AdPlaybackState {
Arrays.copyOf(adGroup.durationsUs, adGroup.durationsUs.length), Arrays.copyOf(adGroup.durationsUs, adGroup.durationsUs.length),
adGroup.contentResumeOffsetUs, adGroup.contentResumeOffsetUs,
adGroup.isServerSideInserted, adGroup.isServerSideInserted,
adGroup.ids); adGroup.ids,
adGroup.isPlaceholder);
} }
return new AdPlaybackState( return new AdPlaybackState(
adsId, adsId,
@ -1332,7 +1448,7 @@ public final class AdPlaybackState {
// placeholder in a period of a multi-period live window, or when c) the position actually is // placeholder in a period of a multi-period live window, or when c) the position actually is
// before the given period duration. // before the given period duration.
return periodDurationUs == C.TIME_UNSET return periodDurationUs == C.TIME_UNSET
|| (adGroup.isServerSideInserted && adGroup.count == C.LENGTH_UNSET) || adGroup.isLivePostrollPlaceholder()
|| positionUs < periodDurationUs; || positionUs < periodDurationUs;
} }
return positionUs < adGroupPositionUs; return positionUs < adGroupPositionUs;

View file

@ -568,18 +568,66 @@ public class AdPlaybackStateTest {
assertThat(AdPlaybackState.AdGroup.fromBundle(bundle)).isEqualTo(adGroup); assertThat(AdPlaybackState.AdGroup.fromBundle(bundle)).isEqualTo(adGroup);
} }
@SuppressWarnings({"deprecation", "InlineMeInliner"}) // testing deprecated API
@Test @Test
public void withLivePostrollPlaceholderAppended_emptyAdPlaybackState_insertsPlaceholder() { public void withLivePostrollPlaceholderAppended_emptyAdPlaybackState_insertsPlaceholder() {
AdPlaybackState adPlaybackState = AdPlaybackState emptyAdPlaybackState = new AdPlaybackState("adsId");
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended();
assertThat(adPlaybackState.adGroupCount).isEqualTo(1); assertThat(
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).timeUs) emptyAdPlaybackState.withLivePostrollPlaceholderAppended(
.isEqualTo(C.TIME_END_OF_SOURCE); /* isServerSideInserted= */ true))
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).count).isEqualTo(C.LENGTH_UNSET); .isEqualTo(
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).isServerSideInserted).isTrue(); new AdPlaybackState("adsId", C.TIME_END_OF_SOURCE)
.withIsPlaceholder(
/* adGroupIndex= */ 0,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ true));
assertThat(emptyAdPlaybackState.withLivePostrollPlaceholderAppended())
.isEqualTo(
new AdPlaybackState("adsId", C.TIME_END_OF_SOURCE)
.withIsPlaceholder(
/* adGroupIndex= */ 0,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ true));
assertThat(
emptyAdPlaybackState.withLivePostrollPlaceholderAppended(
/* isServerSideInserted= */ false))
.isEqualTo(
new AdPlaybackState("adsId", C.TIME_END_OF_SOURCE)
.withIsPlaceholder(
/* adGroupIndex= */ 0,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ false));
} }
@SuppressWarnings({"deprecation", "InlineMeInliner"}) // testing deprecated API
@Test
public void endsWithLivePostrollPlaceHolder_emptyAdPlaybackState_insertsPlaceholder() {
AdPlaybackState emptyAdPlaybackState = new AdPlaybackState("adsId");
assertThat(
emptyAdPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true)
.endsWithLivePostrollPlaceHolder())
.isTrue();
assertThat(
emptyAdPlaybackState
.withLivePostrollPlaceholderAppended()
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ true))
.isTrue();
assertThat(
emptyAdPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false)
.endsWithLivePostrollPlaceHolder())
.isTrue();
assertThat(
emptyAdPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false)
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ false))
.isTrue();
}
@SuppressWarnings({"deprecation", "InlineMeInliner"}) // testing deprecated API
@Test @Test
public void withLivePostrollPlaceholderAppended_withExistingAdGroups_appendsPlaceholder() { public void withLivePostrollPlaceholderAppended_withExistingAdGroups_appendsPlaceholder() {
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
@ -591,13 +639,32 @@ public class AdPlaybackStateTest {
.withAdDurationsUs(/* adGroupIndex= */ 0, /* adDurationsUs...= */ 10_000_000L) .withAdDurationsUs(/* adGroupIndex= */ 0, /* adDurationsUs...= */ 10_000_000L)
.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 5_000_000L); .withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 5_000_000L);
adPlaybackState = adPlaybackState.withLivePostrollPlaceholderAppended(); assertThat(
adPlaybackState.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true))
assertThat(adPlaybackState.adGroupCount).isEqualTo(3); .isEqualTo(
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).timeUs) adPlaybackState
.isEqualTo(C.TIME_END_OF_SOURCE); .withNewAdGroup(/* adGroupIndex= */ 2, C.TIME_END_OF_SOURCE)
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).count).isEqualTo(C.LENGTH_UNSET); .withIsPlaceholder(
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).isServerSideInserted).isTrue(); /* adGroupIndex= */ 2,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ true));
assertThat(adPlaybackState.withLivePostrollPlaceholderAppended())
.isEqualTo(
adPlaybackState
.withNewAdGroup(/* adGroupIndex= */ 2, C.TIME_END_OF_SOURCE)
.withIsPlaceholder(
/* adGroupIndex= */ 2,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ true));
assertThat(
adPlaybackState.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false))
.isEqualTo(
adPlaybackState
.withNewAdGroup(/* adGroupIndex= */ 2, C.TIME_END_OF_SOURCE)
.withIsPlaceholder(
/* adGroupIndex= */ 2,
/* isPlaceholder= */ true,
/* isServerSideInserted= */ false));
} }
@Test @Test
@ -611,14 +678,37 @@ public class AdPlaybackStateTest {
.withAdDurationsUs(/* adGroupIndex= */ 0, /* adDurationsUs...= */ 10_000_000L) .withAdDurationsUs(/* adGroupIndex= */ 0, /* adDurationsUs...= */ 10_000_000L)
.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 5_000_000L); .withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 5_000_000L);
boolean endsWithLivePostrollPlaceHolder = adPlaybackState.endsWithLivePostrollPlaceHolder(); assertThat(
adPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true)
.endsWithLivePostrollPlaceHolder())
.isTrue();
assertThat(
adPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true)
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ true))
.isTrue();
assertThat(
adPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true)
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ false))
.isFalse();
assertThat(endsWithLivePostrollPlaceHolder).isFalse(); assertThat(
adPlaybackState
adPlaybackState = adPlaybackState.withLivePostrollPlaceholderAppended(); .withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false)
endsWithLivePostrollPlaceHolder = adPlaybackState.endsWithLivePostrollPlaceHolder(); .endsWithLivePostrollPlaceHolder())
.isTrue();
assertThat(endsWithLivePostrollPlaceHolder).isTrue(); assertThat(
adPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false)
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ false))
.isTrue();
assertThat(
adPlaybackState
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false)
.endsWithLivePostrollPlaceHolder(/* isServerSideInserted= */ true))
.isFalse();
} }
@Test @Test
@ -783,7 +873,7 @@ public class AdPlaybackStateTest {
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true)
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0) .withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)
.withLivePostrollPlaceholderAppended(); .withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
assertThat( assertThat(
state.getAdGroupIndexAfterPositionUs( state.getAdGroupIndexAfterPositionUs(
@ -811,13 +901,51 @@ public class AdPlaybackStateTest {
public void public void
getAdGroupIndexForPositionUs_withServerSidePostrollPlaceholderForLive_ignoresPlaceholder() { getAdGroupIndexForPositionUs_withServerSidePostrollPlaceholderForLive_ignoresPlaceholder() {
AdPlaybackState state = AdPlaybackState state =
new AdPlaybackState("adsId", /* adGroupTimesUs...= */ 0L, 5_000_000L, C.TIME_END_OF_SOURCE) new AdPlaybackState("adsId", /* adGroupTimesUs...= */ 0L, 5_000_000L)
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true) .withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true)
.withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true) .withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true)
.withIsServerSideInserted(/* adGroupIndex= */ 2, /* isServerSideInserted= */ true)
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1) .withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1)
.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); .withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ 4_999_999L, /* periodDurationUs= */ 10_000_000L))
.isEqualTo(C.INDEX_UNSET);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ 4_999_999L, /* periodDurationUs= */ C.TIME_UNSET))
.isEqualTo(C.INDEX_UNSET);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ 5_000_000L, /* periodDurationUs= */ 10_000_000L))
.isEqualTo(1);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ 5_000_000L, /* periodDurationUs= */ C.TIME_UNSET))
.isEqualTo(1);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ 10_000_000L))
.isEqualTo(1);
assertThat(
state.getAdGroupIndexForPositionUs(
/* positionUs= */ C.TIME_END_OF_SOURCE, /* periodDurationUs= */ C.TIME_UNSET))
.isEqualTo(1);
}
@Test
public void
getAdGroupIndexForPositionUs_withClientSidePostrollPlaceholderForLive_ignoresPlaceholder() {
AdPlaybackState state =
new AdPlaybackState("adsId", /* adGroupTimesUs...= */ 0L, 5_000_000L)
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true)
.withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true)
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1)
.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 1)
.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ false);
assertThat( assertThat(
state.getAdGroupIndexForPositionUs( state.getAdGroupIndexForPositionUs(
@ -849,8 +977,8 @@ public class AdPlaybackStateTest {
public void public void
getAdGroupIndexForPositionUs_withOnlyServerSidePostrollPlaceholderForLive_ignoresPlaceholder() { getAdGroupIndexForPositionUs_withOnlyServerSidePostrollPlaceholderForLive_ignoresPlaceholder() {
AdPlaybackState state = AdPlaybackState state =
new AdPlaybackState("adsId", /* adGroupTimesUs...= */ C.TIME_END_OF_SOURCE) new AdPlaybackState("adsId")
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true); .withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
assertThat( assertThat(
state.getAdGroupIndexForPositionUs( state.getAdGroupIndexForPositionUs(

View file

@ -198,7 +198,8 @@ public final class ServerSideAdInsertionMediaSourceTest {
public void onContinueLoadingRequested(MediaPeriod source) {} public void onContinueLoadingRequested(MediaPeriod source) {}
}; };
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
FakeTimeline wrappedTimeline = FakeTimeline wrappedTimeline =
new FakeTimeline( new FakeTimeline(
new FakeTimeline.TimelineWindowDefinition( new FakeTimeline.TimelineWindowDefinition(

View file

@ -861,7 +861,8 @@ public final class ImaServerSideAdInsertionMediaSource extends CompositeMediaSou
mainHandler.post( mainHandler.post(
() -> () ->
setAdPlaybackState( setAdPlaybackState(
new AdPlaybackState(adsId).withLivePostrollPlaceholderAppended())); new AdPlaybackState(adsId)
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true)));
} }
prepareChildSource(/* id= */ null, serverSideAdInsertionMediaSource); prepareChildSource(/* id= */ null, serverSideAdInsertionMediaSource);
} }

View file

@ -425,7 +425,9 @@ import java.util.Set;
long windowStartTimeUs = long windowStartTimeUs =
getWindowStartTimeUs(window.windowStartTimeMs, window.positionInFirstPeriodUs); getWindowStartTimeUs(window.windowStartTimeMs, window.positionInFirstPeriodUs);
totalElapsedContentDurationUs = windowStartTimeUs - window.positionInFirstPeriodUs; totalElapsedContentDurationUs = windowStartTimeUs - window.positionInFirstPeriodUs;
contentOnlyAdPlaybackState = contentOnlyAdPlaybackState.withLivePostrollPlaceholderAppended(); contentOnlyAdPlaybackState =
contentOnlyAdPlaybackState.withLivePostrollPlaceholderAppended(
/* isServerSideInserted= */ true);
} }
Map<Object, AdPlaybackState> adPlaybackStates = new HashMap<>(); Map<Object, AdPlaybackState> adPlaybackStates = new HashMap<>();
for (int i = adPlaybackState.removedAdGroupCount; i < adPlaybackState.adGroupCount; i++) { for (int i = adPlaybackState.removedAdGroupCount; i < adPlaybackState.adGroupCount; i++) {
@ -505,7 +507,8 @@ import java.util.Set;
.withIsServerSideInserted(/* adGroupIndex= */ 0, true) .withIsServerSideInserted(/* adGroupIndex= */ 0, true)
.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1); .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1);
if (isLiveStream) { if (isLiveStream) {
adPlaybackState = adPlaybackState.withLivePostrollPlaceholderAppended(); adPlaybackState =
adPlaybackState.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
} }
long adGroupDurationUs = 0; long adGroupDurationUs = 0;
for (int i = 0; i < adGroup.count; i++) { for (int i = 0; i < adGroup.count; i++) {

View file

@ -1086,7 +1086,8 @@ public class ImaUtilTest {
long liveWindowDurationUs = 60_000_000L; long liveWindowDurationUs = 60_000_000L;
long nowUs = 110_234_567L; long nowUs = 110_234_567L;
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addAdGroupToAdPlaybackState( addAdGroupToAdPlaybackState(
adPlaybackState, adPlaybackState,
@ -1134,7 +1135,8 @@ public class ImaUtilTest {
long liveWindowDurationUs = 60_000_000L; long liveWindowDurationUs = 60_000_000L;
long nowUs = 110_234_567L; long nowUs = 110_234_567L;
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addAdGroupToAdPlaybackState( addAdGroupToAdPlaybackState(
adPlaybackState, adPlaybackState,
@ -1170,7 +1172,8 @@ public class ImaUtilTest {
public void public void
maybeCorrectPreviouslyUnknownAdDuration_windowPastAdGroups_adPlaybackStateNotChanged() { maybeCorrectPreviouslyUnknownAdDuration_windowPastAdGroups_adPlaybackStateNotChanged() {
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addAdGroupToAdPlaybackState( addAdGroupToAdPlaybackState(
adPlaybackState, adPlaybackState,
@ -1219,7 +1222,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Insert first ad resulting in group [10_000_000, 29_000_123, 0, 0] // Insert first ad resulting in group [10_000_000, 29_000_123, 0, 0]
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
@ -1322,7 +1326,8 @@ public class ImaUtilTest {
public void public void
maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForward_adDurationCorrected() { maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForward_adDurationCorrected() {
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Timeline window to start with: c, a, a, a, [a, c, a], a, a, a // Timeline window to start with: c, a, a, a, [a, c, a], a, a, a
FakeMultiPeriodLiveTimeline contentTimeline = FakeMultiPeriodLiveTimeline contentTimeline =
new FakeMultiPeriodLiveTimeline( new FakeMultiPeriodLiveTimeline(
@ -1402,7 +1407,8 @@ public class ImaUtilTest {
windowStartTimeUs windowStartTimeUs
+ contentTimeline.getPeriod(/* periodIndex= */ 1, new Period()).positionInWindowUs; + contentTimeline.getPeriod(/* periodIndex= */ 1, new Period()).positionInWindowUs;
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
/* currentContentPeriodPositionUs= */ firstAdPeriodStartTimeUs, /* currentContentPeriodPositionUs= */ firstAdPeriodStartTimeUs,
@ -1438,7 +1444,8 @@ public class ImaUtilTest {
public void public void
maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForwardStartOfAdGroupNotInWindow_adDurationCorrected() { maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForwardStartOfAdGroupNotInWindow_adDurationCorrected() {
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Window with content and ad periods: c, a, a, a, a, [c, a, a], a, a, c // Window with content and ad periods: c, a, a, a, a, [c, a, a], a, a, c
// Supposed insertion of ad for period with unknown duration. // Supposed insertion of ad for period with unknown duration.
// durationsUs: [10_000_000L, 28_000_000L, 0L, 0L] // durationsUs: [10_000_000L, 28_000_000L, 0L, 0L]
@ -1496,7 +1503,8 @@ public class ImaUtilTest {
public void public void
maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForwardWithinAdOnlyWindow_adDurationCorrected() { maybeCorrectPreviouslyUnknownAdDuration_timelineMovesMultiplePeriodsForwardWithinAdOnlyWindow_adDurationCorrected() {
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Supposed window when inserting ads: c, a, a, [a, a, a], a, a, a, c // Supposed window when inserting ads: c, a, a, [a, a, a], a, a, a, c
// durationsUs: [10_000_000L, 10_000_000L, 10_000_000L, 10_000_000L, 123L, 0, 0, 0] // durationsUs: [10_000_000L, 10_000_000L, 10_000_000L, 10_000_000L, 123L, 0, 0, 0]
adPlaybackState = adPlaybackState =
@ -1619,7 +1627,8 @@ public class ImaUtilTest {
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS); long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
long periodDurationUs = msToUs(PERIOD_DURATION_MS); long periodDurationUs = msToUs(PERIOD_DURATION_MS);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Window with content and ad periods: c, a, a, a, a, [c, a, a], a, a, c // Window with content and ad periods: c, a, a, a, a, [c, a, a], a, a, c
// Supposed insertion of ad for period with unknown duration. PLaying first ad. // Supposed insertion of ad for period with unknown duration. PLaying first ad.
// durationsUs: [10_000_000L, 28_000_000L, 0L, 0L] // durationsUs: [10_000_000L, 28_000_000L, 0L, 0L]
@ -1688,7 +1697,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addAdGroupToAdPlaybackState( addAdGroupToAdPlaybackState(
adPlaybackState, adPlaybackState,
@ -1724,7 +1734,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState(/* adsId= */ "adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState(/* adsId= */ "adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addAdGroupToAdPlaybackState( addAdGroupToAdPlaybackState(
adPlaybackState, adPlaybackState,
@ -2034,7 +2045,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
/* currentContentPeriodPositionUs= */ 50_000_000, /* currentContentPeriodPositionUs= */ 50_000_000,
@ -2135,7 +2147,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
/* currentContentPeriodPositionUs= */ 50_000_000, /* currentContentPeriodPositionUs= */ 50_000_000,
@ -2222,7 +2235,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
/* currentContentPeriodPositionUs= */ 30_000_000, /* currentContentPeriodPositionUs= */ 30_000_000,
@ -2283,7 +2297,8 @@ public class ImaUtilTest {
/* populateAds= */ false, /* populateAds= */ false,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Ad events of the first two ads of the group have arrived (the first of the window). // Ad events of the first two ads of the group have arrived (the first of the window).
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(
@ -2365,7 +2380,8 @@ public class ImaUtilTest {
/* populateAds= */ true, /* populateAds= */ true,
/* playedAds= */ false); /* playedAds= */ false);
AdPlaybackState adPlaybackState = AdPlaybackState adPlaybackState =
new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
// Ad events of the first two ads of the group have arrived (the first of the window). // Ad events of the first two ads of the group have arrived (the first of the window).
adPlaybackState = adPlaybackState =
addLiveAdBreak( addLiveAdBreak(

View file

@ -250,7 +250,9 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
boolean isAd = adSequencePattern[lastPeriodIndex % sequencePeriodCount]; boolean isAd = adSequencePattern[lastPeriodIndex % sequencePeriodCount];
AdPlaybackState adPlaybackState = AdPlaybackState.NONE; AdPlaybackState adPlaybackState = AdPlaybackState.NONE;
if (!isContentTimeline) { if (!isContentTimeline) {
adPlaybackState = new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended(); adPlaybackState =
new AdPlaybackState("adsId")
.withLivePostrollPlaceholderAppended(/* isServerSideInserted= */ true);
if (isAd && populateAds) { if (isAd && populateAds) {
adPlaybackState = adPlaybackState =
adPlaybackState adPlaybackState