mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Allow ad groups to be marked as server-side inserted.
This helps both player the logic and clients like UI or analytics to detect SSAI ads. PiperOrigin-RevId: 373540754
This commit is contained in:
parent
bec7b0041e
commit
954a6730d5
3 changed files with 67 additions and 12 deletions
|
|
@ -804,6 +804,17 @@ public abstract class Timeline implements Bundleable {
|
||||||
return adPlaybackState.adResumePositionUs;
|
return adPlaybackState.adResumePositionUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the ad group at index {@code adGroupIndex} is server-side inserted and part
|
||||||
|
* of the content stream.
|
||||||
|
*
|
||||||
|
* @param adGroupIndex The ad group index.
|
||||||
|
* @return Whether this ad group is server-side inserted and part of the content stream.
|
||||||
|
*/
|
||||||
|
public boolean isServerSideInsertedAdGroup(int adGroupIndex) {
|
||||||
|
return adPlaybackState.adGroups[adGroupIndex].isServerSideInserted;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the offset in microseconds which should be added to the content stream when resuming
|
* Returns the offset in microseconds which should be added to the content stream when resuming
|
||||||
* playback after the specified ad group.
|
* playback after the specified ad group.
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
* after the ad group.
|
* after the ad group.
|
||||||
*/
|
*/
|
||||||
public final long contentResumeOffsetUs;
|
public final long contentResumeOffsetUs;
|
||||||
|
/** Whether this ad group is server-side inserted and part of the content stream. */
|
||||||
|
public final boolean isServerSideInserted;
|
||||||
|
|
||||||
/** Creates a new ad group with an unspecified number of ads. */
|
/** Creates a new ad group with an unspecified number of ads. */
|
||||||
public AdGroup() {
|
public AdGroup() {
|
||||||
|
|
@ -71,7 +73,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
/* states= */ new int[0],
|
/* states= */ new int[0],
|
||||||
/* uris= */ new Uri[0],
|
/* uris= */ new Uri[0],
|
||||||
/* durationsUs= */ new long[0],
|
/* durationsUs= */ new long[0],
|
||||||
/* contentResumeOffsetUs= */ 0);
|
/* contentResumeOffsetUs= */ 0,
|
||||||
|
/* isServerSideInserted= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AdGroup(
|
private AdGroup(
|
||||||
|
|
@ -79,13 +82,15 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
@AdState int[] states,
|
@AdState int[] states,
|
||||||
@NullableType Uri[] uris,
|
@NullableType Uri[] uris,
|
||||||
long[] durationsUs,
|
long[] durationsUs,
|
||||||
long contentResumeOffsetUs) {
|
long contentResumeOffsetUs,
|
||||||
|
boolean isServerSideInserted) {
|
||||||
checkArgument(states.length == uris.length);
|
checkArgument(states.length == uris.length);
|
||||||
this.count = count;
|
this.count = count;
|
||||||
this.states = states;
|
this.states = states;
|
||||||
this.uris = uris;
|
this.uris = uris;
|
||||||
this.durationsUs = durationsUs;
|
this.durationsUs = durationsUs;
|
||||||
this.contentResumeOffsetUs = contentResumeOffsetUs;
|
this.contentResumeOffsetUs = contentResumeOffsetUs;
|
||||||
|
this.isServerSideInserted = isServerSideInserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -130,7 +135,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
&& Arrays.equals(uris, adGroup.uris)
|
&& Arrays.equals(uris, adGroup.uris)
|
||||||
&& Arrays.equals(states, adGroup.states)
|
&& Arrays.equals(states, adGroup.states)
|
||||||
&& Arrays.equals(durationsUs, adGroup.durationsUs)
|
&& Arrays.equals(durationsUs, adGroup.durationsUs)
|
||||||
&& contentResumeOffsetUs == adGroup.contentResumeOffsetUs;
|
&& contentResumeOffsetUs == adGroup.contentResumeOffsetUs
|
||||||
|
&& isServerSideInserted == adGroup.isServerSideInserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -140,6 +146,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
result = 31 * result + Arrays.hashCode(states);
|
result = 31 * result + Arrays.hashCode(states);
|
||||||
result = 31 * result + Arrays.hashCode(durationsUs);
|
result = 31 * result + Arrays.hashCode(durationsUs);
|
||||||
result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32));
|
result = 31 * result + (int) (contentResumeOffsetUs ^ (contentResumeOffsetUs >>> 32));
|
||||||
|
result = 31 * result + (isServerSideInserted ? 1 : 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,7 +156,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count);
|
@AdState int[] states = copyStatesWithSpaceForAdCount(this.states, count);
|
||||||
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
||||||
@NullableType Uri[] uris = Arrays.copyOf(this.uris, count);
|
@NullableType Uri[] uris = Arrays.copyOf(this.uris, count);
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -166,7 +174,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
@NullableType Uri[] uris = Arrays.copyOf(this.uris, states.length);
|
@NullableType Uri[] uris = Arrays.copyOf(this.uris, states.length);
|
||||||
uris[index] = uri;
|
uris[index] = uri;
|
||||||
states[index] = AD_STATE_AVAILABLE;
|
states[index] = AD_STATE_AVAILABLE;
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -193,7 +202,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
Uri[] uris =
|
Uri[] uris =
|
||||||
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
||||||
states[index] = state;
|
states[index] = state;
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a new instance with the specified ad durations, in microseconds. */
|
/** Returns a new instance with the specified ad durations, in microseconds. */
|
||||||
|
|
@ -204,13 +214,22 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
} else if (count != C.LENGTH_UNSET && durationsUs.length > uris.length) {
|
} else if (count != C.LENGTH_UNSET && durationsUs.length > uris.length) {
|
||||||
durationsUs = Arrays.copyOf(durationsUs, uris.length);
|
durationsUs = Arrays.copyOf(durationsUs, uris.length);
|
||||||
}
|
}
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an instance with the specified {@link #contentResumeOffsetUs}. */
|
/** Returns an instance with the specified {@link #contentResumeOffsetUs}. */
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdGroup withContentResumeOffsetUs(long contentResumeOffsetUs) {
|
public AdGroup withContentResumeOffsetUs(long contentResumeOffsetUs) {
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns an instance with the specified value for {@link #isServerSideInserted}. */
|
||||||
|
@CheckResult
|
||||||
|
public AdGroup withIsServerSideInserted(boolean isServerSideInserted) {
|
||||||
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -225,7 +244,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
/* states= */ new int[0],
|
/* states= */ new int[0],
|
||||||
/* uris= */ new Uri[0],
|
/* uris= */ new Uri[0],
|
||||||
/* durationsUs= */ new long[0],
|
/* durationsUs= */ new long[0],
|
||||||
contentResumeOffsetUs);
|
contentResumeOffsetUs,
|
||||||
|
isServerSideInserted);
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|
@ -234,7 +254,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
states[i] = AD_STATE_SKIPPED;
|
states[i] = AD_STATE_SKIPPED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new AdGroup(count, states, uris, durationsUs, contentResumeOffsetUs);
|
return new AdGroup(
|
||||||
|
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@CheckResult
|
@CheckResult
|
||||||
|
|
@ -265,6 +286,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
FIELD_STATES,
|
FIELD_STATES,
|
||||||
FIELD_DURATIONS_US,
|
FIELD_DURATIONS_US,
|
||||||
FIELD_CONTENT_RESUME_OFFSET_US,
|
FIELD_CONTENT_RESUME_OFFSET_US,
|
||||||
|
FIELD_IS_SERVER_SIDE_INSERTED,
|
||||||
})
|
})
|
||||||
private @interface FieldNumber {}
|
private @interface FieldNumber {}
|
||||||
|
|
||||||
|
|
@ -273,6 +295,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
private static final int FIELD_STATES = 2;
|
private static final int FIELD_STATES = 2;
|
||||||
private static final int FIELD_DURATIONS_US = 3;
|
private static final int FIELD_DURATIONS_US = 3;
|
||||||
private static final int FIELD_CONTENT_RESUME_OFFSET_US = 4;
|
private static final int FIELD_CONTENT_RESUME_OFFSET_US = 4;
|
||||||
|
private static final int FIELD_IS_SERVER_SIDE_INSERTED = 5;
|
||||||
|
|
||||||
// putParcelableArrayList actually supports null elements.
|
// putParcelableArrayList actually supports null elements.
|
||||||
@SuppressWarnings("nullness:argument.type.incompatible")
|
@SuppressWarnings("nullness:argument.type.incompatible")
|
||||||
|
|
@ -285,6 +308,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
bundle.putIntArray(keyForField(FIELD_STATES), states);
|
bundle.putIntArray(keyForField(FIELD_STATES), states);
|
||||||
bundle.putLongArray(keyForField(FIELD_DURATIONS_US), durationsUs);
|
bundle.putLongArray(keyForField(FIELD_DURATIONS_US), durationsUs);
|
||||||
bundle.putLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US), contentResumeOffsetUs);
|
bundle.putLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US), contentResumeOffsetUs);
|
||||||
|
bundle.putBoolean(keyForField(FIELD_IS_SERVER_SIDE_INSERTED), isServerSideInserted);
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,12 +326,14 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
int[] states = bundle.getIntArray(keyForField(FIELD_STATES));
|
int[] states = bundle.getIntArray(keyForField(FIELD_STATES));
|
||||||
@Nullable long[] durationsUs = bundle.getLongArray(keyForField(FIELD_DURATIONS_US));
|
@Nullable long[] durationsUs = bundle.getLongArray(keyForField(FIELD_DURATIONS_US));
|
||||||
long contentResumeOffsetUs = bundle.getLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US));
|
long contentResumeOffsetUs = bundle.getLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US));
|
||||||
|
boolean isServerSideInserted = bundle.getBoolean(keyForField(FIELD_IS_SERVER_SIDE_INSERTED));
|
||||||
return new AdGroup(
|
return new AdGroup(
|
||||||
count,
|
count,
|
||||||
states == null ? new int[0] : states,
|
states == null ? new int[0] : states,
|
||||||
uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]),
|
uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]),
|
||||||
durationsUs == null ? new long[0] : durationsUs,
|
durationsUs == null ? new long[0] : durationsUs,
|
||||||
contentResumeOffsetUs);
|
contentResumeOffsetUs,
|
||||||
|
isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String keyForField(@AdGroup.FieldNumber int field) {
|
private static String keyForField(@AdGroup.FieldNumber int field) {
|
||||||
|
|
@ -605,6 +631,21 @@ public final class AdPlaybackState implements Bundleable {
|
||||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance with the specified value for {@link AdGroup#isServerSideInserted} in the
|
||||||
|
* specified ad group.
|
||||||
|
*/
|
||||||
|
@CheckResult
|
||||||
|
public AdPlaybackState withIsServerSideInserted(int adGroupIndex, boolean isServerSideInserted) {
|
||||||
|
if (adGroups[adGroupIndex].isServerSideInserted == isServerSideInserted) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
|
adGroups[adGroupIndex] = adGroups[adGroupIndex].withIsServerSideInserted(isServerSideInserted);
|
||||||
|
return new AdPlaybackState(
|
||||||
|
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object o) {
|
public boolean equals(@Nullable Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,8 @@ public class AdPlaybackStateTest {
|
||||||
.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI)
|
.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, TEST_URI)
|
||||||
.withContentResumeOffsetUs(/* adGroupIndex= */ 0, /* contentResumeOffsetUs= */ 4444)
|
.withContentResumeOffsetUs(/* adGroupIndex= */ 0, /* contentResumeOffsetUs= */ 4444)
|
||||||
.withContentResumeOffsetUs(/* adGroupIndex= */ 1, /* contentResumeOffsetUs= */ 3333)
|
.withContentResumeOffsetUs(/* adGroupIndex= */ 1, /* contentResumeOffsetUs= */ 3333)
|
||||||
|
.withIsServerSideInserted(/* adGroupIndex= */ 0, /* isServerSideInserted= */ true)
|
||||||
|
.withIsServerSideInserted(/* adGroupIndex= */ 1, /* isServerSideInserted= */ true)
|
||||||
.withAdDurationsUs(new long[][] {{12}, {34, 56}})
|
.withAdDurationsUs(new long[][] {{12}, {34, 56}})
|
||||||
.withAdResumePositionUs(123)
|
.withAdResumePositionUs(123)
|
||||||
.withContentDurationUs(456);
|
.withContentDurationUs(456);
|
||||||
|
|
@ -219,7 +221,8 @@ public class AdPlaybackStateTest {
|
||||||
.withAdUri(Uri.parse("https://www.google.com"), /* index= */ 0)
|
.withAdUri(Uri.parse("https://www.google.com"), /* index= */ 0)
|
||||||
.withAdUri(Uri.EMPTY, /* index= */ 1)
|
.withAdUri(Uri.EMPTY, /* index= */ 1)
|
||||||
.withAdDurationsUs(new long[] {1234, 5678})
|
.withAdDurationsUs(new long[] {1234, 5678})
|
||||||
.withContentResumeOffsetUs(4444);
|
.withContentResumeOffsetUs(4444)
|
||||||
|
.withIsServerSideInserted(true);
|
||||||
|
|
||||||
assertThat(AdPlaybackState.AdGroup.CREATOR.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
assertThat(AdPlaybackState.AdGroup.CREATOR.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue