mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add getter for ad groups in AdPlaybackState.
This allows to decouple the data structure from the access. In a future change, this allows to completely remove old ad groups (e.g. for live streams where the number of groups would otherwise grow forever). Also move the time into the group itself for better encapsulation. PiperOrigin-RevId: 376170408
This commit is contained in:
parent
4e749e7afe
commit
0d0ccadc83
@ -602,17 +602,16 @@ import java.util.Map;
|
||||
}
|
||||
|
||||
// Skip ads based on the start position as required.
|
||||
long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs;
|
||||
int adGroupForPositionIndex =
|
||||
adPlaybackState.getAdGroupIndexForPositionUs(
|
||||
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
|
||||
if (adGroupForPositionIndex != C.INDEX_UNSET) {
|
||||
boolean playAdWhenStartingPlayback =
|
||||
configuration.playAdBeforeStartPosition
|
||||
|| adGroupTimesUs[adGroupForPositionIndex] == C.msToUs(contentPositionMs);
|
||||
adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs == C.msToUs(contentPositionMs)
|
||||
|| configuration.playAdBeforeStartPosition;
|
||||
if (!playAdWhenStartingPlayback) {
|
||||
adGroupForPositionIndex++;
|
||||
} else if (hasMidrollAdGroups(adGroupTimesUs)) {
|
||||
} else if (hasMidrollAdGroups(adPlaybackState)) {
|
||||
// Provide the player's initial position to trigger loading and playing the ad. If there are
|
||||
// no midrolls, we are playing a preroll and any pending content position wouldn't be
|
||||
// cleared.
|
||||
@ -622,13 +621,14 @@ import java.util.Map;
|
||||
for (int i = 0; i < adGroupForPositionIndex; i++) {
|
||||
adPlaybackState = adPlaybackState.withSkippedAdGroup(i);
|
||||
}
|
||||
if (adGroupForPositionIndex == adGroupTimesUs.length) {
|
||||
if (adGroupForPositionIndex == adPlaybackState.adGroupCount) {
|
||||
// We don't need to play any ads. Because setPlayAdsAfterTime does not discard non-VMAP
|
||||
// ads, we signal that no ads will render so the caller can destroy the ads manager.
|
||||
return null;
|
||||
}
|
||||
long adGroupForPositionTimeUs = adGroupTimesUs[adGroupForPositionIndex];
|
||||
long adGroupBeforePositionTimeUs = adGroupTimesUs[adGroupForPositionIndex - 1];
|
||||
long adGroupForPositionTimeUs = adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs;
|
||||
long adGroupBeforePositionTimeUs =
|
||||
adPlaybackState.getAdGroup(adGroupForPositionIndex - 1).timeUs;
|
||||
if (adGroupForPositionTimeUs == C.TIME_END_OF_SOURCE) {
|
||||
// Play the postroll by offsetting the start position just past the last non-postroll ad.
|
||||
adsRenderingSettings.setPlayAdsAfterTime(
|
||||
@ -786,14 +786,14 @@ import java.util.Map;
|
||||
if (adGroupIndex == C.INDEX_UNSET) {
|
||||
return false;
|
||||
}
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
if (adGroup.count != C.LENGTH_UNSET
|
||||
&& adGroup.count != 0
|
||||
&& adGroup.states[0] != AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
||||
// An ad is available already.
|
||||
return false;
|
||||
}
|
||||
long adGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]);
|
||||
long adGroupTimeMs = C.usToMs(adGroup.timeUs);
|
||||
long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
|
||||
long timeUntilAdMs = adGroupTimeMs - contentPositionMs;
|
||||
return timeUntilAdMs < configuration.adPreloadTimeoutMs;
|
||||
@ -877,13 +877,13 @@ import java.util.Map;
|
||||
}
|
||||
}
|
||||
if (!sentContentComplete && !wasPlayingAd && playingAd && imaAdState == IMA_AD_STATE_NONE) {
|
||||
int adGroupIndex = player.getCurrentAdGroupIndex();
|
||||
if (adPlaybackState.adGroupTimesUs[adGroupIndex] == C.TIME_END_OF_SOURCE) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(player.getCurrentAdGroupIndex());
|
||||
if (adGroup.timeUs == C.TIME_END_OF_SOURCE) {
|
||||
sendContentComplete();
|
||||
} else {
|
||||
// IMA hasn't called playAd yet, so fake the content position.
|
||||
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
||||
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]);
|
||||
fakeContentProgressOffsetMs = C.usToMs(adGroup.timeUs);
|
||||
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
|
||||
fakeContentProgressOffsetMs = contentDurationMs;
|
||||
}
|
||||
@ -919,11 +919,11 @@ import java.util.Map;
|
||||
// The ad count may increase on successive loads of ads in the same ad pod, for example, due to
|
||||
// separate requests for ad tags with multiple ads within the ad pod completing after an earlier
|
||||
// ad has loaded. See also https://github.com/google/ExoPlayer/issues/7477.
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex);
|
||||
adPlaybackState =
|
||||
adPlaybackState.withAdCount(
|
||||
adInfo.adGroupIndex, max(adPodInfo.getTotalAds(), adGroup.states.length));
|
||||
adGroup = adPlaybackState.adGroups[adInfo.adGroupIndex];
|
||||
adGroup = adPlaybackState.getAdGroup(adInfo.adGroupIndex);
|
||||
for (int i = 0; i < adIndexInAdGroup; i++) {
|
||||
// Any preceding ads that haven't loaded are not going to load.
|
||||
if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
||||
@ -1062,10 +1062,10 @@ import java.util.Map;
|
||||
|
||||
private void markAdGroupInErrorStateAndClearPendingContentPosition(int adGroupIndex) {
|
||||
// Update the ad playback state so all ads in the ad group are in the error state.
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
if (adGroup.count == C.LENGTH_UNSET) {
|
||||
adPlaybackState = adPlaybackState.withAdCount(adGroupIndex, max(1, adGroup.states.length));
|
||||
adGroup = adPlaybackState.adGroups[adGroupIndex];
|
||||
adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
}
|
||||
for (int i = 0; i < adGroup.count; i++) {
|
||||
if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
||||
@ -1094,7 +1094,7 @@ import java.util.Map;
|
||||
// Send IMA a content position at the ad group so that it will try to play it, at which point
|
||||
// we can notify that it failed to load.
|
||||
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
|
||||
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]);
|
||||
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.getAdGroup(adGroupIndex).timeUs);
|
||||
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
|
||||
fakeContentProgressOffsetMs = contentDurationMs;
|
||||
}
|
||||
@ -1109,7 +1109,7 @@ import java.util.Map;
|
||||
adCallbacks.get(i).onEnded(adMediaInfo);
|
||||
}
|
||||
}
|
||||
playingAdIndexInAdGroup = adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay();
|
||||
playingAdIndexInAdGroup = adPlaybackState.getAdGroup(adGroupIndex).getFirstAdIndexToPlay();
|
||||
for (int i = 0; i < adCallbacks.size(); i++) {
|
||||
adCallbacks.get(i).onError(checkNotNull(adMediaInfo));
|
||||
}
|
||||
@ -1138,7 +1138,7 @@ import java.util.Map;
|
||||
Log.d(TAG, "adsLoader.contentComplete");
|
||||
}
|
||||
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
||||
if (adPlaybackState.adGroupTimesUs[i] != C.TIME_END_OF_SOURCE) {
|
||||
if (adPlaybackState.getAdGroup(i).timeUs != C.TIME_END_OF_SOURCE) {
|
||||
adPlaybackState = adPlaybackState.withSkippedAdGroup(/* adGroupIndex= */ i);
|
||||
}
|
||||
}
|
||||
@ -1213,7 +1213,7 @@ import java.util.Map;
|
||||
float cuePointTimeSecondsFloat = (float) cuePointTimeSeconds;
|
||||
long adPodTimeUs = Math.round((double) cuePointTimeSecondsFloat * C.MICROS_PER_SECOND);
|
||||
for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) {
|
||||
long adGroupTimeUs = adPlaybackState.adGroupTimesUs[adGroupIndex];
|
||||
long adGroupTimeUs = adPlaybackState.getAdGroup(adGroupIndex).timeUs;
|
||||
if (adGroupTimeUs != C.TIME_END_OF_SOURCE
|
||||
&& Math.abs(adGroupTimeUs - adPodTimeUs) < THRESHOLD_AD_MATCH_US) {
|
||||
return adGroupIndex;
|
||||
@ -1242,14 +1242,16 @@ import java.util.Map;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) {
|
||||
int count = adGroupTimesUs.length;
|
||||
private static boolean hasMidrollAdGroups(AdPlaybackState adPlaybackState) {
|
||||
int count = adPlaybackState.adGroupCount;
|
||||
if (count == 1) {
|
||||
return adGroupTimesUs[0] != 0 && adGroupTimesUs[0] != C.TIME_END_OF_SOURCE;
|
||||
long adGroupTimeUs = adPlaybackState.getAdGroup(0).timeUs;
|
||||
return adGroupTimeUs != 0 && adGroupTimeUs != C.TIME_END_OF_SOURCE;
|
||||
} else if (count == 2) {
|
||||
return adGroupTimesUs[0] != 0 || adGroupTimesUs[1] != C.TIME_END_OF_SOURCE;
|
||||
return adPlaybackState.getAdGroup(0).timeUs != 0
|
||||
|| adPlaybackState.getAdGroup(1).timeUs != C.TIME_END_OF_SOURCE;
|
||||
} else {
|
||||
// There's at least one midroll ad group, as adGroupTimesUs is never empty.
|
||||
// There's at least one midroll ad group, as adPlaybackState is never empty.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1413,7 +1413,8 @@ public final class ImaAdsLoaderTest {
|
||||
public void onAdPlaybackState(AdPlaybackState adPlaybackState) {
|
||||
long[][] adDurationsUs = new long[adPlaybackState.adGroupCount][];
|
||||
for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) {
|
||||
adDurationsUs[adGroupIndex] = new long[adPlaybackState.adGroups[adGroupIndex].uris.length];
|
||||
adDurationsUs[adGroupIndex] =
|
||||
new long[adPlaybackState.getAdGroup(adGroupIndex).uris.length];
|
||||
Arrays.fill(adDurationsUs[adGroupIndex], TEST_AD_DURATION_US);
|
||||
}
|
||||
adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs);
|
||||
|
@ -708,7 +708,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* Period}, in microseconds, or {@link C#TIME_END_OF_SOURCE} for a post-roll ad group.
|
||||
*/
|
||||
public long getAdGroupTimeUs(int adGroupIndex) {
|
||||
return adPlaybackState.adGroupTimesUs[adGroupIndex];
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).timeUs;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -720,7 +720,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* if no ads should be played.
|
||||
*/
|
||||
public int getFirstAdIndexToPlay(int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay();
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).getFirstAdIndexToPlay();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -734,7 +734,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* if the ad group does not have any ads remaining to play.
|
||||
*/
|
||||
public int getNextAdIndexToPlay(int adGroupIndex, int lastPlayedAdIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].getNextAdIndexToPlay(lastPlayedAdIndex);
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).getNextAdIndexToPlay(lastPlayedAdIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -746,7 +746,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* skipped or failed.
|
||||
*/
|
||||
public boolean hasPlayedAdGroup(int adGroupIndex) {
|
||||
return !adPlaybackState.adGroups[adGroupIndex].hasUnplayedAds();
|
||||
return !adPlaybackState.getAdGroup(adGroupIndex).hasUnplayedAds();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -782,7 +782,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* @return The number of ads in the ad group, or {@link C#LENGTH_UNSET} if not yet known.
|
||||
*/
|
||||
public int getAdCountInAdGroup(int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].count;
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).count;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -794,7 +794,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* @return The duration of the ad, or {@link C#TIME_UNSET} if not yet known.
|
||||
*/
|
||||
public long getAdDurationUs(int adGroupIndex, int adIndexInAdGroup) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
return adGroup.count != C.LENGTH_UNSET ? adGroup.durationsUs[adIndexInAdGroup] : C.TIME_UNSET;
|
||||
}
|
||||
|
||||
@ -814,7 +814,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* @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;
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).isServerSideInserted;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -825,7 +825,7 @@ public abstract class Timeline implements Bundleable {
|
||||
* @return The offset that should be added to the content stream, in microseconds.
|
||||
*/
|
||||
public long getContentResumeOffsetUs(int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].contentResumeOffsetUs;
|
||||
return adPlaybackState.getAdGroup(adGroupIndex).contentResumeOffsetUs;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,6 +49,11 @@ public final class AdPlaybackState implements Bundleable {
|
||||
*/
|
||||
public static final class AdGroup implements Bundleable {
|
||||
|
||||
/**
|
||||
* The time of the ad group in the {@link com.google.android.exoplayer2.Timeline.Period}, in
|
||||
* microseconds, or {@link C#TIME_END_OF_SOURCE} to indicate a postroll ad.
|
||||
*/
|
||||
public final long timeUs;
|
||||
/** The number of ads in the ad group, or {@link C#LENGTH_UNSET} if unknown. */
|
||||
public final int count;
|
||||
/** The URI of each ad in the ad group. */
|
||||
@ -65,9 +70,16 @@ public final class AdPlaybackState implements Bundleable {
|
||||
/** 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. */
|
||||
public AdGroup() {
|
||||
/**
|
||||
* Creates a new ad group with an unspecified number of ads.
|
||||
*
|
||||
* @param timeUs The time of the ad group in the {@link
|
||||
* com.google.android.exoplayer2.Timeline.Period}, in microseconds, or {@link
|
||||
* C#TIME_END_OF_SOURCE} to indicate a postroll ad.
|
||||
*/
|
||||
public AdGroup(long timeUs) {
|
||||
this(
|
||||
timeUs,
|
||||
/* count= */ C.LENGTH_UNSET,
|
||||
/* states= */ new int[0],
|
||||
/* uris= */ new Uri[0],
|
||||
@ -77,6 +89,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
}
|
||||
|
||||
private AdGroup(
|
||||
long timeUs,
|
||||
int count,
|
||||
@AdState int[] states,
|
||||
@NullableType Uri[] uris,
|
||||
@ -84,6 +97,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
long contentResumeOffsetUs,
|
||||
boolean isServerSideInserted) {
|
||||
checkArgument(states.length == uris.length);
|
||||
this.timeUs = timeUs;
|
||||
this.count = count;
|
||||
this.states = states;
|
||||
this.uris = uris;
|
||||
@ -146,7 +160,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||
return false;
|
||||
}
|
||||
AdGroup adGroup = (AdGroup) o;
|
||||
return count == adGroup.count
|
||||
return timeUs == adGroup.timeUs
|
||||
&& count == adGroup.count
|
||||
&& Arrays.equals(uris, adGroup.uris)
|
||||
&& Arrays.equals(states, adGroup.states)
|
||||
&& Arrays.equals(durationsUs, adGroup.durationsUs)
|
||||
@ -157,6 +172,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = count;
|
||||
result = 31 * result + (int) (timeUs ^ (timeUs >>> 32));
|
||||
result = 31 * result + Arrays.hashCode(uris);
|
||||
result = 31 * result + Arrays.hashCode(states);
|
||||
result = 31 * result + Arrays.hashCode(durationsUs);
|
||||
@ -165,6 +181,13 @@ public final class AdPlaybackState implements Bundleable {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns a new instance with the {@link #timeUs} set to the specified value. */
|
||||
@CheckResult
|
||||
public AdGroup withTimeUs(long timeUs) {
|
||||
return new AdGroup(
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/** Returns a new instance with the ad count set to {@code count}. */
|
||||
@CheckResult
|
||||
public AdGroup withAdCount(int count) {
|
||||
@ -172,7 +195,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
long[] durationsUs = copyDurationsUsWithSpaceForAdCount(this.durationsUs, count);
|
||||
@NullableType Uri[] uris = Arrays.copyOf(this.uris, count);
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,7 +213,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
uris[index] = uri;
|
||||
states[index] = AD_STATE_AVAILABLE;
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,7 +241,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
this.uris.length == states.length ? this.uris : Arrays.copyOf(this.uris, states.length);
|
||||
states[index] = state;
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/** Returns a new instance with the specified ad durations, in microseconds. */
|
||||
@ -230,21 +253,21 @@ public final class AdPlaybackState implements Bundleable {
|
||||
durationsUs = Arrays.copyOf(durationsUs, uris.length);
|
||||
}
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified {@link #contentResumeOffsetUs}. */
|
||||
@CheckResult
|
||||
public AdGroup withContentResumeOffsetUs(long contentResumeOffsetUs) {
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, 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);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,6 +278,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdGroup withAllAdsSkipped() {
|
||||
if (count == C.LENGTH_UNSET) {
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
/* count= */ 0,
|
||||
/* states= */ new int[0],
|
||||
/* uris= */ new Uri[0],
|
||||
@ -270,7 +294,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
}
|
||||
}
|
||||
return new AdGroup(
|
||||
count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@ -296,6 +320,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
FIELD_TIME_US,
|
||||
FIELD_COUNT,
|
||||
FIELD_URIS,
|
||||
FIELD_STATES,
|
||||
@ -305,18 +330,20 @@ public final class AdPlaybackState implements Bundleable {
|
||||
})
|
||||
private @interface FieldNumber {}
|
||||
|
||||
private static final int FIELD_COUNT = 0;
|
||||
private static final int FIELD_URIS = 1;
|
||||
private static final int FIELD_STATES = 2;
|
||||
private static final int FIELD_DURATIONS_US = 3;
|
||||
private static final int FIELD_CONTENT_RESUME_OFFSET_US = 4;
|
||||
private static final int FIELD_IS_SERVER_SIDE_INSERTED = 5;
|
||||
private static final int FIELD_TIME_US = 0;
|
||||
private static final int FIELD_COUNT = 1;
|
||||
private static final int FIELD_URIS = 2;
|
||||
private static final int FIELD_STATES = 3;
|
||||
private static final int FIELD_DURATIONS_US = 4;
|
||||
private static final int FIELD_CONTENT_RESUME_OFFSET_US = 5;
|
||||
private static final int FIELD_IS_SERVER_SIDE_INSERTED = 6;
|
||||
|
||||
// putParcelableArrayList actually supports null elements.
|
||||
@SuppressWarnings("nullness:argument.type.incompatible")
|
||||
@Override
|
||||
public Bundle toBundle() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(keyForField(FIELD_TIME_US), timeUs);
|
||||
bundle.putInt(keyForField(FIELD_COUNT), count);
|
||||
bundle.putParcelableArrayList(
|
||||
keyForField(FIELD_URIS), new ArrayList<@NullableType Uri>(Arrays.asList(uris)));
|
||||
@ -333,6 +360,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
// getParcelableArrayList may have null elements.
|
||||
@SuppressWarnings("nullness:type.argument.type.incompatible")
|
||||
private static AdGroup fromBundle(Bundle bundle) {
|
||||
long timeUs = bundle.getLong(keyForField(FIELD_TIME_US));
|
||||
int count = bundle.getInt(keyForField(FIELD_COUNT), /* defaultValue= */ C.LENGTH_UNSET);
|
||||
@Nullable
|
||||
ArrayList<@NullableType Uri> uriList = bundle.getParcelableArrayList(keyForField(FIELD_URIS));
|
||||
@ -343,6 +371,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
long contentResumeOffsetUs = bundle.getLong(keyForField(FIELD_CONTENT_RESUME_OFFSET_US));
|
||||
boolean isServerSideInserted = bundle.getBoolean(keyForField(FIELD_IS_SERVER_SIDE_INSERTED));
|
||||
return new AdGroup(
|
||||
timeUs,
|
||||
count,
|
||||
states == null ? new int[0] : states,
|
||||
uriList == null ? new Uri[0] : uriList.toArray(new Uri[0]),
|
||||
@ -386,7 +415,6 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public static final AdPlaybackState NONE =
|
||||
new AdPlaybackState(
|
||||
/* adsId= */ null,
|
||||
/* adGroupTimesUs= */ new long[0],
|
||||
/* adGroups= */ new AdGroup[0],
|
||||
/* adResumePositionUs= */ 0L,
|
||||
/* contentDurationUs= */ C.TIME_UNSET);
|
||||
@ -398,14 +426,6 @@ public final class AdPlaybackState implements Bundleable {
|
||||
|
||||
/** The number of ad groups. */
|
||||
public final int adGroupCount;
|
||||
/**
|
||||
* The times of ad groups, in microseconds, relative to the start of the {@link
|
||||
* com.google.android.exoplayer2.Timeline.Period} they belong to. A final element with the value
|
||||
* {@link C#TIME_END_OF_SOURCE} indicates a postroll ad.
|
||||
*/
|
||||
public final long[] adGroupTimesUs;
|
||||
/** The ad groups. */
|
||||
public final AdGroup[] adGroups;
|
||||
/** The position offset in the first unplayed ad at which to begin playback, in microseconds. */
|
||||
public final long adResumePositionUs;
|
||||
/**
|
||||
@ -413,6 +433,8 @@ public final class AdPlaybackState implements Bundleable {
|
||||
*/
|
||||
public final long contentDurationUs;
|
||||
|
||||
private final AdGroup[] adGroups;
|
||||
|
||||
/**
|
||||
* Creates a new ad playback state with the specified ad group times.
|
||||
*
|
||||
@ -424,27 +446,25 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState(Object adsId, long... adGroupTimesUs) {
|
||||
this(
|
||||
adsId,
|
||||
adGroupTimesUs,
|
||||
createEmptyAdGroups(adGroupTimesUs.length),
|
||||
createEmptyAdGroups(adGroupTimesUs),
|
||||
/* adResumePositionUs= */ 0,
|
||||
/* contentDurationUs= */ C.TIME_UNSET);
|
||||
}
|
||||
|
||||
private AdPlaybackState(
|
||||
@Nullable Object adsId,
|
||||
long[] adGroupTimesUs,
|
||||
AdGroup[] adGroups,
|
||||
long adResumePositionUs,
|
||||
long contentDurationUs) {
|
||||
checkArgument(adGroups.length == adGroupTimesUs.length);
|
||||
@Nullable Object adsId, AdGroup[] adGroups, long adResumePositionUs, long contentDurationUs) {
|
||||
this.adsId = adsId;
|
||||
this.adGroupTimesUs = adGroupTimesUs;
|
||||
this.adResumePositionUs = adResumePositionUs;
|
||||
this.contentDurationUs = contentDurationUs;
|
||||
adGroupCount = adGroupTimesUs.length;
|
||||
adGroupCount = adGroups.length;
|
||||
this.adGroups = adGroups;
|
||||
}
|
||||
|
||||
/** Returns the specified {@link AdGroup}. */
|
||||
public AdGroup getAdGroup(int adGroupIndex) {
|
||||
return adGroups[adGroupIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the ad group at or before {@code positionUs} that should be played before
|
||||
* the content at {@code positionUs}. Returns {@link C#INDEX_UNSET} if the ad group at or before
|
||||
@ -460,7 +480,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public int getAdGroupIndexForPositionUs(long positionUs, long periodDurationUs) {
|
||||
// Use a linear search as the array elements may not be increasing due to TIME_END_OF_SOURCE.
|
||||
// In practice we expect there to be few ad groups so the search shouldn't be expensive.
|
||||
int index = adGroupTimesUs.length - 1;
|
||||
int index = adGroups.length - 1;
|
||||
while (index >= 0 && isPositionBeforeAdGroup(positionUs, periodDurationUs, index)) {
|
||||
index--;
|
||||
}
|
||||
@ -486,12 +506,12 @@ public final class AdPlaybackState implements Bundleable {
|
||||
// Use a linear search as the array elements may not be increasing due to TIME_END_OF_SOURCE.
|
||||
// In practice we expect there to be few ad groups so the search shouldn't be expensive.
|
||||
int index = 0;
|
||||
while (index < adGroupTimesUs.length
|
||||
&& ((adGroupTimesUs[index] != C.TIME_END_OF_SOURCE && adGroupTimesUs[index] <= positionUs)
|
||||
while (index < adGroups.length
|
||||
&& ((adGroups[index].timeUs != C.TIME_END_OF_SOURCE && adGroups[index].timeUs <= positionUs)
|
||||
|| !adGroups[index].shouldPlayAdGroup())) {
|
||||
index++;
|
||||
}
|
||||
return index < adGroupTimesUs.length ? index : C.INDEX_UNSET;
|
||||
return index < adGroups.length ? index : C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
/** Returns whether the specified ad has been marked as in {@link #AD_STATE_ERROR}. */
|
||||
@ -516,10 +536,9 @@ public final class AdPlaybackState implements Bundleable {
|
||||
*/
|
||||
@CheckResult
|
||||
public AdPlaybackState withAdGroupTimeUs(int adGroupIndex, long adGroupTimeUs) {
|
||||
long[] adGroupTimesUs = Arrays.copyOf(this.adGroupTimesUs, this.adGroupCount);
|
||||
adGroupTimesUs[adGroupIndex] = adGroupTimeUs;
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = this.adGroups[adGroupIndex].withTimeUs(adGroupTimeUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -532,7 +551,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
*/
|
||||
@CheckResult
|
||||
public AdPlaybackState withNewAdGroup(int adGroupIndex, long adGroupTimeUs) {
|
||||
AdGroup newAdGroup = new AdGroup();
|
||||
AdGroup newAdGroup = new AdGroup(adGroupTimeUs);
|
||||
AdGroup[] adGroups = Util.nullSafeArrayAppend(this.adGroups, newAdGroup);
|
||||
System.arraycopy(
|
||||
/* src= */ adGroups,
|
||||
@ -541,16 +560,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
/* destPos= */ adGroupIndex + 1,
|
||||
/* length= */ adGroupCount - adGroupIndex);
|
||||
adGroups[adGroupIndex] = newAdGroup;
|
||||
long[] adGroupTimesUs = Arrays.copyOf(this.adGroupTimesUs, adGroupCount + 1);
|
||||
System.arraycopy(
|
||||
/* src= */ adGroupTimesUs,
|
||||
/* srcPos= */ adGroupIndex,
|
||||
/* dest= */ adGroupTimesUs,
|
||||
/* destPos= */ adGroupIndex + 1,
|
||||
/* length= */ adGroupCount - adGroupIndex);
|
||||
adGroupTimesUs[adGroupIndex] = adGroupTimeUs;
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -565,8 +575,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
}
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = this.adGroups[adGroupIndex].withAdCount(adCount);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad URI. */
|
||||
@ -574,8 +583,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withAdUri(int adGroupIndex, int adIndexInAdGroup, Uri uri) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdUri(uri, adIndexInAdGroup);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad marked as played. */
|
||||
@ -583,8 +591,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withPlayedAd(int adGroupIndex, int adIndexInAdGroup) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_PLAYED, adIndexInAdGroup);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad marked as skipped. */
|
||||
@ -592,8 +599,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withSkippedAd(int adGroupIndex, int adIndexInAdGroup) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_SKIPPED, adIndexInAdGroup);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad marked as having a load error. */
|
||||
@ -601,8 +607,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withAdLoadError(int adGroupIndex, int adIndexInAdGroup) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdState(AD_STATE_ERROR, adIndexInAdGroup);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -613,8 +618,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withSkippedAdGroup(int adGroupIndex) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAllAdsSkipped();
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/** Returns an instance with the specified ad durations, in microseconds. */
|
||||
@ -624,8 +628,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
for (int adGroupIndex = 0; adGroupIndex < adGroupCount; adGroupIndex++) {
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]);
|
||||
}
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -636,8 +639,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public AdPlaybackState withAdDurationsUs(int adGroupIndex, long... adDurationsUs) {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationsUs);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -649,8 +651,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
if (this.adResumePositionUs == adResumePositionUs) {
|
||||
return this;
|
||||
} else {
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -660,8 +661,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
if (this.contentDurationUs == contentDurationUs) {
|
||||
return this;
|
||||
} else {
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -677,8 +677,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] =
|
||||
adGroups[adGroupIndex].withContentResumeOffsetUs(contentResumeOffsetUs);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,8 +691,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
}
|
||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withIsServerSideInserted(isServerSideInserted);
|
||||
return new AdPlaybackState(
|
||||
adsId, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(adsId, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -709,7 +707,6 @@ public final class AdPlaybackState implements Bundleable {
|
||||
&& adGroupCount == that.adGroupCount
|
||||
&& adResumePositionUs == that.adResumePositionUs
|
||||
&& contentDurationUs == that.contentDurationUs
|
||||
&& Arrays.equals(adGroupTimesUs, that.adGroupTimesUs)
|
||||
&& Arrays.equals(adGroups, that.adGroups);
|
||||
}
|
||||
|
||||
@ -719,7 +716,6 @@ public final class AdPlaybackState implements Bundleable {
|
||||
result = 31 * result + (adsId == null ? 0 : adsId.hashCode());
|
||||
result = 31 * result + (int) adResumePositionUs;
|
||||
result = 31 * result + (int) contentDurationUs;
|
||||
result = 31 * result + Arrays.hashCode(adGroupTimesUs);
|
||||
result = 31 * result + Arrays.hashCode(adGroups);
|
||||
return result;
|
||||
}
|
||||
@ -734,7 +730,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
sb.append(", adGroups=[");
|
||||
for (int i = 0; i < adGroups.length; i++) {
|
||||
sb.append("adGroup(timeUs=");
|
||||
sb.append(adGroupTimesUs[i]);
|
||||
sb.append(adGroups[i].timeUs);
|
||||
sb.append(", ads=[");
|
||||
for (int j = 0; j < adGroups[i].states.length; j++) {
|
||||
sb.append("ad(state=");
|
||||
@ -780,7 +776,7 @@ public final class AdPlaybackState implements Bundleable {
|
||||
// The end of the content is at (but not before) any postroll ad, and after any other ads.
|
||||
return false;
|
||||
}
|
||||
long adGroupPositionUs = adGroupTimesUs[adGroupIndex];
|
||||
long adGroupPositionUs = adGroups[adGroupIndex].timeUs;
|
||||
if (adGroupPositionUs == C.TIME_END_OF_SOURCE) {
|
||||
return periodDurationUs == C.TIME_UNSET || positionUs < periodDurationUs;
|
||||
} else {
|
||||
@ -792,18 +788,12 @@ public final class AdPlaybackState implements Bundleable {
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
FIELD_AD_GROUP_TIMES_US,
|
||||
FIELD_AD_GROUPS,
|
||||
FIELD_AD_RESUME_POSITION_US,
|
||||
FIELD_CONTENT_DURATION_US
|
||||
})
|
||||
@IntDef({FIELD_AD_GROUPS, FIELD_AD_RESUME_POSITION_US, FIELD_CONTENT_DURATION_US})
|
||||
private @interface FieldNumber {}
|
||||
|
||||
private static final int FIELD_AD_GROUP_TIMES_US = 1;
|
||||
private static final int FIELD_AD_GROUPS = 2;
|
||||
private static final int FIELD_AD_RESUME_POSITION_US = 3;
|
||||
private static final int FIELD_CONTENT_DURATION_US = 4;
|
||||
private static final int FIELD_AD_GROUPS = 1;
|
||||
private static final int FIELD_AD_RESUME_POSITION_US = 2;
|
||||
private static final int FIELD_CONTENT_DURATION_US = 3;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -815,7 +805,6 @@ public final class AdPlaybackState implements Bundleable {
|
||||
@Override
|
||||
public Bundle toBundle() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLongArray(keyForField(FIELD_AD_GROUP_TIMES_US), adGroupTimesUs);
|
||||
ArrayList<Bundle> adGroupBundleList = new ArrayList<>();
|
||||
for (AdGroup adGroup : adGroups) {
|
||||
adGroupBundleList.add(adGroup.toBundle());
|
||||
@ -834,16 +823,12 @@ public final class AdPlaybackState implements Bundleable {
|
||||
public static final Bundleable.Creator<AdPlaybackState> CREATOR = AdPlaybackState::fromBundle;
|
||||
|
||||
private static AdPlaybackState fromBundle(Bundle bundle) {
|
||||
@Nullable long[] adGroupTimesUs = bundle.getLongArray(keyForField(FIELD_AD_GROUP_TIMES_US));
|
||||
if (adGroupTimesUs == null) {
|
||||
adGroupTimesUs = new long[0];
|
||||
}
|
||||
@Nullable
|
||||
ArrayList<Bundle> adGroupBundleList =
|
||||
bundle.getParcelableArrayList(keyForField(FIELD_AD_GROUPS));
|
||||
@Nullable AdGroup[] adGroups;
|
||||
if (adGroupBundleList == null) {
|
||||
adGroups = createEmptyAdGroups(adGroupTimesUs.length);
|
||||
adGroups = new AdGroup[0];
|
||||
} else {
|
||||
adGroups = new AdGroup[adGroupBundleList.size()];
|
||||
for (int i = 0; i < adGroupBundleList.size(); i++) {
|
||||
@ -854,18 +839,17 @@ public final class AdPlaybackState implements Bundleable {
|
||||
bundle.getLong(keyForField(FIELD_AD_RESUME_POSITION_US), /* defaultValue= */ 0);
|
||||
long contentDurationUs =
|
||||
bundle.getLong(keyForField(FIELD_CONTENT_DURATION_US), /* defaultValue= */ C.TIME_UNSET);
|
||||
return new AdPlaybackState(
|
||||
/* adsId= */ null, adGroupTimesUs, adGroups, adResumePositionUs, contentDurationUs);
|
||||
return new AdPlaybackState(/* adsId= */ null, adGroups, adResumePositionUs, contentDurationUs);
|
||||
}
|
||||
|
||||
private static String keyForField(@FieldNumber int field) {
|
||||
return Integer.toString(field, Character.MAX_RADIX);
|
||||
}
|
||||
|
||||
private static AdGroup[] createEmptyAdGroups(int count) {
|
||||
AdGroup[] adGroups = new AdGroup[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
adGroups[i] = new AdGroup();
|
||||
private static AdGroup[] createEmptyAdGroups(long[] adGroupTimesUs) {
|
||||
AdGroup[] adGroups = new AdGroup[adGroupTimesUs.length];
|
||||
for (int i = 0; i < adGroups.length; i++) {
|
||||
adGroups[i] = new AdGroup(adGroupTimesUs[i]);
|
||||
}
|
||||
return adGroups;
|
||||
}
|
||||
|
@ -44,9 +44,9 @@ public class AdPlaybackStateTest {
|
||||
|
||||
@Test
|
||||
public void setAdCount() {
|
||||
assertThat(state.adGroups[0].count).isEqualTo(C.LENGTH_UNSET);
|
||||
assertThat(state.getAdGroup(0).count).isEqualTo(C.LENGTH_UNSET);
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1);
|
||||
assertThat(state.adGroups[0].count).isEqualTo(1);
|
||||
assertThat(state.getAdGroup(0).count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -54,10 +54,10 @@ public class AdPlaybackStateTest {
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI);
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2);
|
||||
|
||||
assertThat(state.adGroups[0].uris[0]).isNull();
|
||||
assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.adGroups[0].uris[1]).isSameInstanceAs(TEST_URI);
|
||||
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
assertThat(state.getAdGroup(0).uris[0]).isNull();
|
||||
assertThat(state.getAdGroup(0).states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.getAdGroup(0).uris[1]).isSameInstanceAs(TEST_URI);
|
||||
assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -65,10 +65,10 @@ public class AdPlaybackStateTest {
|
||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2);
|
||||
|
||||
assertThat(state.adGroups[0].uris[0]).isNull();
|
||||
assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR);
|
||||
assertThat(state.getAdGroup(0).uris[0]).isNull();
|
||||
assertThat(state.getAdGroup(0).states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR);
|
||||
assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)).isTrue();
|
||||
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1)).isFalse();
|
||||
}
|
||||
|
||||
@ -82,8 +82,8 @@ public class AdPlaybackStateTest {
|
||||
.withAdGroupTimeUs(/* adGroupIndex= */ 1, 6_000);
|
||||
|
||||
assertThat(state.adGroupCount).isEqualTo(2);
|
||||
assertThat(state.adGroupTimesUs[0]).isEqualTo(3_000);
|
||||
assertThat(state.adGroupTimesUs[1]).isEqualTo(6_000);
|
||||
assertThat(state.getAdGroup(0).timeUs).isEqualTo(3_000);
|
||||
assertThat(state.getAdGroup(1).timeUs).isEqualTo(6_000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -102,13 +102,13 @@ public class AdPlaybackStateTest {
|
||||
.withNewAdGroup(/* adGroupIndex= */ 4, /* adGroupTimeUs= */ 8_000);
|
||||
|
||||
assertThat(state.adGroupCount).isEqualTo(5);
|
||||
assertThat(state.adGroups[0].count).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.adGroups[1].count).isEqualTo(2);
|
||||
assertThat(state.adGroups[1].uris[1]).isSameInstanceAs(TEST_URI);
|
||||
assertThat(state.adGroups[2].count).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.adGroups[3].count).isEqualTo(1);
|
||||
assertThat(state.adGroups[3].states[0]).isEqualTo(AdPlaybackState.AD_STATE_SKIPPED);
|
||||
assertThat(state.adGroups[4].count).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.getAdGroup(0).count).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.getAdGroup(1).count).isEqualTo(2);
|
||||
assertThat(state.getAdGroup(1).uris[1]).isSameInstanceAs(TEST_URI);
|
||||
assertThat(state.getAdGroup(2).count).isEqualTo(C.INDEX_UNSET);
|
||||
assertThat(state.getAdGroup(3).count).isEqualTo(1);
|
||||
assertThat(state.getAdGroup(3).states[0]).isEqualTo(AdPlaybackState.AD_STATE_SKIPPED);
|
||||
assertThat(state.getAdGroup(4).count).isEqualTo(C.INDEX_UNSET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -121,10 +121,10 @@ public class AdPlaybackStateTest {
|
||||
|
||||
state = state.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 1_000, 2_000);
|
||||
|
||||
assertThat(state.adGroups[0].durationsUs[0]).isEqualTo(5_000);
|
||||
assertThat(state.adGroups[0].durationsUs[1]).isEqualTo(6_000);
|
||||
assertThat(state.adGroups[1].durationsUs[0]).isEqualTo(1_000);
|
||||
assertThat(state.adGroups[1].durationsUs[1]).isEqualTo(2_000);
|
||||
assertThat(state.getAdGroup(0).durationsUs[0]).isEqualTo(5_000);
|
||||
assertThat(state.getAdGroup(0).durationsUs[1]).isEqualTo(6_000);
|
||||
assertThat(state.getAdGroup(1).durationsUs[0]).isEqualTo(1_000);
|
||||
assertThat(state.getAdGroup(1).durationsUs[1]).isEqualTo(2_000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -133,7 +133,7 @@ public class AdPlaybackStateTest {
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
|
||||
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, TEST_URI);
|
||||
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(0);
|
||||
assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -144,9 +144,9 @@ public class AdPlaybackStateTest {
|
||||
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1);
|
||||
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(1);
|
||||
assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.getAdGroup(0).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -157,9 +157,9 @@ public class AdPlaybackStateTest {
|
||||
|
||||
state = state.withSkippedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1);
|
||||
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(1);
|
||||
assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
|
||||
assertThat(state.getAdGroup(0).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -171,7 +171,7 @@ public class AdPlaybackStateTest {
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
||||
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(2);
|
||||
assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -181,7 +181,7 @@ public class AdPlaybackStateTest {
|
||||
|
||||
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
||||
|
||||
assertThat(state.adGroups[0].getNextAdIndexToPlay(0)).isEqualTo(2);
|
||||
assertThat(state.getAdGroup(0).getNextAdIndexToPlay(0)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -194,7 +194,7 @@ public class AdPlaybackStateTest {
|
||||
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
|
||||
|
||||
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(0);
|
||||
assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -209,8 +209,8 @@ public class AdPlaybackStateTest {
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
|
||||
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2);
|
||||
|
||||
assertThat(state.adGroups[0].getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 0)).isEqualTo(1);
|
||||
assertThat(state.adGroups[0].getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 1)).isEqualTo(2);
|
||||
assertThat(state.getAdGroup(0).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 0)).isEqualTo(1);
|
||||
assertThat(state.getAdGroup(0).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 1)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -229,8 +229,8 @@ public class AdPlaybackStateTest {
|
||||
public void skipAllWithoutAdCount() {
|
||||
state = state.withSkippedAdGroup(0);
|
||||
state = state.withSkippedAdGroup(1);
|
||||
assertThat(state.adGroups[0].count).isEqualTo(0);
|
||||
assertThat(state.adGroups[1].count).isEqualTo(0);
|
||||
assertThat(state.getAdGroup(0).count).isEqualTo(0);
|
||||
assertThat(state.getAdGroup(1).count).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -257,8 +257,9 @@ public class AdPlaybackStateTest {
|
||||
|
||||
assertThat(restoredState.adsId).isNull();
|
||||
assertThat(restoredState.adGroupCount).isEqualTo(originalState.adGroupCount);
|
||||
assertThat(restoredState.adGroupTimesUs).isEqualTo(originalState.adGroupTimesUs);
|
||||
assertThat(restoredState.adGroups).isEqualTo(originalState.adGroups);
|
||||
for (int i = 0; i < restoredState.adGroupCount; i++) {
|
||||
assertThat(restoredState.getAdGroup(i)).isEqualTo(originalState.getAdGroup(i));
|
||||
}
|
||||
assertThat(restoredState.adResumePositionUs).isEqualTo(originalState.adResumePositionUs);
|
||||
assertThat(restoredState.contentDurationUs).isEqualTo(originalState.contentDurationUs);
|
||||
}
|
||||
@ -266,7 +267,7 @@ public class AdPlaybackStateTest {
|
||||
@Test
|
||||
public void roundTripViaBundle_ofAdGroup_yieldsEqualInstance() {
|
||||
AdPlaybackState.AdGroup adGroup =
|
||||
new AdPlaybackState.AdGroup()
|
||||
new AdPlaybackState.AdGroup(/* timeUs= */ 42)
|
||||
.withAdCount(2)
|
||||
.withAdState(AD_STATE_AVAILABLE, /* index= */ 0)
|
||||
.withAdState(AD_STATE_PLAYED, /* index= */ 1)
|
||||
|
@ -50,7 +50,7 @@ public interface AdsLoader {
|
||||
|
||||
/**
|
||||
* Called when the ad playback state has been updated. The number of {@link
|
||||
* AdPlaybackState#adGroups ad groups} may not change after the first call.
|
||||
* AdPlaybackState#adGroupCount ad groups} may not change after the first call.
|
||||
*
|
||||
* @param adPlaybackState The new ad playback state.
|
||||
*/
|
||||
|
@ -305,11 +305,11 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
|
||||
@Nullable
|
||||
AdMediaSourceHolder adMediaSourceHolder =
|
||||
this.adMediaSourceHolders[adGroupIndex][adIndexInAdGroup];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
if (adMediaSourceHolder != null
|
||||
&& !adMediaSourceHolder.hasMediaSource()
|
||||
&& adPlaybackState.adGroups[adGroupIndex] != null
|
||||
&& adIndexInAdGroup < adPlaybackState.adGroups[adGroupIndex].uris.length) {
|
||||
@Nullable Uri adUri = adPlaybackState.adGroups[adGroupIndex].uris[adIndexInAdGroup];
|
||||
&& adIndexInAdGroup < adGroup.uris.length) {
|
||||
@Nullable Uri adUri = adGroup.uris[adIndexInAdGroup];
|
||||
if (adUri != null) {
|
||||
MediaItem.Builder adMediaItem = new MediaItem.Builder().setUri(adUri);
|
||||
// Propagate the content's DRM config into the ad media source.
|
||||
|
@ -122,13 +122,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource
|
||||
public void setAdPlaybackState(AdPlaybackState adPlaybackState) {
|
||||
checkArgument(adPlaybackState.adGroupCount >= this.adPlaybackState.adGroupCount);
|
||||
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
||||
checkArgument(adPlaybackState.adGroups[i].isServerSideInserted);
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
checkArgument(adGroup.isServerSideInserted);
|
||||
if (i < this.adPlaybackState.adGroupCount) {
|
||||
checkArgument(
|
||||
getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i)
|
||||
>= getAdCountInGroup(this.adPlaybackState, /* adGroupIndex= */ i));
|
||||
}
|
||||
if (adPlaybackState.adGroupTimesUs[i] == C.TIME_END_OF_SOURCE) {
|
||||
if (adGroup.timeUs == C.TIME_END_OF_SOURCE) {
|
||||
checkArgument(getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i) == 0);
|
||||
}
|
||||
}
|
||||
@ -482,14 +483,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource
|
||||
MediaPeriodImpl mediaPeriod, AdPlaybackState adPlaybackState) {
|
||||
MediaPeriodId id = mediaPeriod.mediaPeriodId;
|
||||
if (id.isAd()) {
|
||||
return adPlaybackState.adGroups[id.adGroupIndex].count == C.LENGTH_UNSET
|
||||
? 0
|
||||
: adPlaybackState.adGroups[id.adGroupIndex].durationsUs[id.adIndexInAdGroup];
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(id.adGroupIndex);
|
||||
return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.durationsUs[id.adIndexInAdGroup];
|
||||
}
|
||||
return id.nextAdGroupIndex == C.INDEX_UNSET
|
||||
|| adPlaybackState.adGroupTimesUs[id.nextAdGroupIndex] == C.TIME_END_OF_SOURCE
|
||||
? Long.MAX_VALUE
|
||||
: adPlaybackState.adGroupTimesUs[id.nextAdGroupIndex];
|
||||
if (id.nextAdGroupIndex == C.INDEX_UNSET) {
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
AdPlaybackState.AdGroup nextAdGroup = adPlaybackState.getAdGroup(id.nextAdGroupIndex);
|
||||
return nextAdGroup.timeUs == C.TIME_END_OF_SOURCE ? Long.MAX_VALUE : nextAdGroup.timeUs;
|
||||
}
|
||||
|
||||
private static MediaLoadData correctMediaLoadData(
|
||||
|
@ -55,8 +55,8 @@ public final class ServerSideInsertedAdsUtil {
|
||||
fromPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState);
|
||||
int insertionIndex = 0;
|
||||
while (insertionIndex < adPlaybackState.adGroupCount
|
||||
&& adPlaybackState.adGroupTimesUs[insertionIndex] != C.TIME_END_OF_SOURCE
|
||||
&& adPlaybackState.adGroupTimesUs[insertionIndex] <= adGroupInsertionPositionUs) {
|
||||
&& adPlaybackState.getAdGroup(insertionIndex).timeUs != C.TIME_END_OF_SOURCE
|
||||
&& adPlaybackState.getAdGroup(insertionIndex).timeUs <= adGroupInsertionPositionUs) {
|
||||
insertionIndex++;
|
||||
}
|
||||
long adDurationUs = toPositionUs - fromPositionUs;
|
||||
@ -69,11 +69,11 @@ public final class ServerSideInsertedAdsUtil {
|
||||
.withContentResumeOffsetUs(insertionIndex, contentResumeOffsetUs);
|
||||
long followingAdGroupTimeUsOffset = -adDurationUs + contentResumeOffsetUs;
|
||||
for (int i = insertionIndex + 1; i < adPlaybackState.adGroupCount; i++) {
|
||||
if (adPlaybackState.adGroupTimesUs[i] != C.TIME_END_OF_SOURCE) {
|
||||
long adGroupTimeUs = adPlaybackState.getAdGroup(i).timeUs;
|
||||
if (adGroupTimeUs != C.TIME_END_OF_SOURCE) {
|
||||
adPlaybackState =
|
||||
adPlaybackState.withAdGroupTimeUs(
|
||||
/* adGroupIndex= */ i,
|
||||
adPlaybackState.adGroupTimesUs[i] + followingAdGroupTimeUsOffset);
|
||||
/* adGroupIndex= */ i, adGroupTimeUs + followingAdGroupTimeUsOffset);
|
||||
}
|
||||
}
|
||||
return adPlaybackState;
|
||||
@ -182,16 +182,18 @@ public final class ServerSideInsertedAdsUtil {
|
||||
*/
|
||||
public static long getStreamPositionUsForAd(
|
||||
long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) {
|
||||
positionUs += adPlaybackState.adGroupTimesUs[adGroupIndex];
|
||||
AdPlaybackState.AdGroup currentAdGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
positionUs += currentAdGroup.timeUs;
|
||||
for (int i = 0; i < adGroupIndex; i++) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) {
|
||||
positionUs += adPlaybackState.adGroups[i].durationsUs[j];
|
||||
positionUs += adGroup.durationsUs[j];
|
||||
}
|
||||
positionUs -= adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
positionUs -= adGroup.contentResumeOffsetUs;
|
||||
}
|
||||
if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) {
|
||||
for (int i = 0; i < adIndexInAdGroup; i++) {
|
||||
positionUs += adPlaybackState.adGroups[adGroupIndex].durationsUs[i];
|
||||
positionUs += currentAdGroup.durationsUs[i];
|
||||
}
|
||||
}
|
||||
return positionUs;
|
||||
@ -210,16 +212,18 @@ public final class ServerSideInsertedAdsUtil {
|
||||
*/
|
||||
public static long getMediaPeriodPositionUsForAd(
|
||||
long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) {
|
||||
positionUs -= adPlaybackState.adGroupTimesUs[adGroupIndex];
|
||||
AdPlaybackState.AdGroup currentAdGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
positionUs -= currentAdGroup.timeUs;
|
||||
for (int i = 0; i < adGroupIndex; i++) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) {
|
||||
positionUs -= adPlaybackState.adGroups[i].durationsUs[j];
|
||||
positionUs -= adGroup.durationsUs[j];
|
||||
}
|
||||
positionUs += adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
positionUs += adGroup.contentResumeOffsetUs;
|
||||
}
|
||||
if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) {
|
||||
for (int i = 0; i < adIndexInAdGroup; i++) {
|
||||
positionUs -= adPlaybackState.adGroups[adGroupIndex].durationsUs[i];
|
||||
positionUs -= currentAdGroup.durationsUs[i];
|
||||
}
|
||||
}
|
||||
return positionUs;
|
||||
@ -243,18 +247,16 @@ public final class ServerSideInsertedAdsUtil {
|
||||
nextAdGroupIndex = adPlaybackState.adGroupCount;
|
||||
}
|
||||
for (int i = 0; i < nextAdGroupIndex; i++) {
|
||||
if (adPlaybackState.adGroupTimesUs[i] == C.TIME_END_OF_SOURCE
|
||||
|| adPlaybackState.adGroupTimesUs[i] > positionUs) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
if (adGroup.timeUs == C.TIME_END_OF_SOURCE || adGroup.timeUs > positionUs) {
|
||||
break;
|
||||
}
|
||||
long adGroupStreamStartPositionUs =
|
||||
adPlaybackState.adGroupTimesUs[i] + totalAdDurationBeforePositionUs;
|
||||
long adGroupStreamStartPositionUs = adGroup.timeUs + totalAdDurationBeforePositionUs;
|
||||
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) {
|
||||
totalAdDurationBeforePositionUs += adPlaybackState.adGroups[i].durationsUs[j];
|
||||
totalAdDurationBeforePositionUs += adGroup.durationsUs[j];
|
||||
}
|
||||
totalAdDurationBeforePositionUs -= adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
long adGroupResumePositionUs =
|
||||
adPlaybackState.adGroupTimesUs[i] + adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs;
|
||||
long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs;
|
||||
if (adGroupResumePositionUs > positionUs) {
|
||||
// The position is inside the ad group.
|
||||
return max(adGroupStreamStartPositionUs, positionUs + totalAdDurationBeforePositionUs);
|
||||
@ -282,19 +284,19 @@ public final class ServerSideInsertedAdsUtil {
|
||||
nextAdGroupIndex = adPlaybackState.adGroupCount;
|
||||
}
|
||||
for (int i = 0; i < nextAdGroupIndex; i++) {
|
||||
if (adPlaybackState.adGroupTimesUs[i] == C.TIME_END_OF_SOURCE
|
||||
|| adPlaybackState.adGroupTimesUs[i] > positionUs - totalAdDurationBeforePositionUs) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
if (adGroup.timeUs == C.TIME_END_OF_SOURCE
|
||||
|| adGroup.timeUs > positionUs - totalAdDurationBeforePositionUs) {
|
||||
break;
|
||||
}
|
||||
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) {
|
||||
totalAdDurationBeforePositionUs += adPlaybackState.adGroups[i].durationsUs[j];
|
||||
totalAdDurationBeforePositionUs += adGroup.durationsUs[j];
|
||||
}
|
||||
totalAdDurationBeforePositionUs -= adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
long adGroupResumePositionUs =
|
||||
adPlaybackState.adGroupTimesUs[i] + adPlaybackState.adGroups[i].contentResumeOffsetUs;
|
||||
totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs;
|
||||
long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs;
|
||||
if (adGroupResumePositionUs > positionUs - totalAdDurationBeforePositionUs) {
|
||||
// The position is inside the ad group.
|
||||
return max(adPlaybackState.adGroupTimesUs[i], positionUs - totalAdDurationBeforePositionUs);
|
||||
return max(adGroup.timeUs, positionUs - totalAdDurationBeforePositionUs);
|
||||
}
|
||||
}
|
||||
return positionUs - totalAdDurationBeforePositionUs;
|
||||
@ -308,8 +310,7 @@ public final class ServerSideInsertedAdsUtil {
|
||||
* @return The number of ads in the ad group.
|
||||
*/
|
||||
public static int getAdCountInGroup(AdPlaybackState adPlaybackState, int adGroupIndex) {
|
||||
return adPlaybackState.adGroups[adGroupIndex].count == C.LENGTH_UNSET
|
||||
? 0
|
||||
: adPlaybackState.adGroups[adGroupIndex].count;
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
|
||||
return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.count;
|
||||
}
|
||||
}
|
||||
|
@ -797,7 +797,9 @@ public final class MediaPeriodQueueTest {
|
||||
long[][] newDurations = new long[adPlaybackState.adGroupCount][];
|
||||
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
||||
newDurations[i] =
|
||||
i == adGroupIndex ? new long[] {AD_DURATION_US} : adPlaybackState.adGroups[i].durationsUs;
|
||||
i == adGroupIndex
|
||||
? new long[] {AD_DURATION_US}
|
||||
: adPlaybackState.getAdGroup(i).durationsUs;
|
||||
}
|
||||
adPlaybackState =
|
||||
adPlaybackState
|
||||
@ -808,7 +810,7 @@ public final class MediaPeriodQueueTest {
|
||||
}
|
||||
|
||||
private void setAdGroupPlayed(int adGroupIndex) {
|
||||
for (int i = 0; i < adPlaybackState.adGroups[adGroupIndex].count; i++) {
|
||||
for (int i = 0; i < adPlaybackState.getAdGroup(adGroupIndex).count; i++) {
|
||||
adPlaybackState = adPlaybackState.withPlayedAd(adGroupIndex, /* adIndexInAdGroup= */ i);
|
||||
}
|
||||
updateTimeline();
|
||||
|
Loading…
x
Reference in New Issue
Block a user