Commit 0d0ccadc by tonihei Committed by Oliver Woodman

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
parent 4e749e7a
...@@ -602,17 +602,16 @@ import java.util.Map; ...@@ -602,17 +602,16 @@ import java.util.Map;
} }
// Skip ads based on the start position as required. // Skip ads based on the start position as required.
long[] adGroupTimesUs = adPlaybackState.adGroupTimesUs;
int adGroupForPositionIndex = int adGroupForPositionIndex =
adPlaybackState.getAdGroupIndexForPositionUs( adPlaybackState.getAdGroupIndexForPositionUs(
C.msToUs(contentPositionMs), C.msToUs(contentDurationMs)); C.msToUs(contentPositionMs), C.msToUs(contentDurationMs));
if (adGroupForPositionIndex != C.INDEX_UNSET) { if (adGroupForPositionIndex != C.INDEX_UNSET) {
boolean playAdWhenStartingPlayback = boolean playAdWhenStartingPlayback =
configuration.playAdBeforeStartPosition adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs == C.msToUs(contentPositionMs)
|| adGroupTimesUs[adGroupForPositionIndex] == C.msToUs(contentPositionMs); || configuration.playAdBeforeStartPosition;
if (!playAdWhenStartingPlayback) { if (!playAdWhenStartingPlayback) {
adGroupForPositionIndex++; 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 // 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 // no midrolls, we are playing a preroll and any pending content position wouldn't be
// cleared. // cleared.
...@@ -622,13 +621,14 @@ import java.util.Map; ...@@ -622,13 +621,14 @@ import java.util.Map;
for (int i = 0; i < adGroupForPositionIndex; i++) { for (int i = 0; i < adGroupForPositionIndex; i++) {
adPlaybackState = adPlaybackState.withSkippedAdGroup(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 // 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. // ads, we signal that no ads will render so the caller can destroy the ads manager.
return null; return null;
} }
long adGroupForPositionTimeUs = adGroupTimesUs[adGroupForPositionIndex]; long adGroupForPositionTimeUs = adPlaybackState.getAdGroup(adGroupForPositionIndex).timeUs;
long adGroupBeforePositionTimeUs = adGroupTimesUs[adGroupForPositionIndex - 1]; long adGroupBeforePositionTimeUs =
adPlaybackState.getAdGroup(adGroupForPositionIndex - 1).timeUs;
if (adGroupForPositionTimeUs == C.TIME_END_OF_SOURCE) { if (adGroupForPositionTimeUs == C.TIME_END_OF_SOURCE) {
// Play the postroll by offsetting the start position just past the last non-postroll ad. // Play the postroll by offsetting the start position just past the last non-postroll ad.
adsRenderingSettings.setPlayAdsAfterTime( adsRenderingSettings.setPlayAdsAfterTime(
...@@ -786,14 +786,14 @@ import java.util.Map; ...@@ -786,14 +786,14 @@ import java.util.Map;
if (adGroupIndex == C.INDEX_UNSET) { if (adGroupIndex == C.INDEX_UNSET) {
return false; return false;
} }
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[adGroupIndex]; AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
if (adGroup.count != C.LENGTH_UNSET if (adGroup.count != C.LENGTH_UNSET
&& adGroup.count != 0 && adGroup.count != 0
&& adGroup.states[0] != AdPlaybackState.AD_STATE_UNAVAILABLE) { && adGroup.states[0] != AdPlaybackState.AD_STATE_UNAVAILABLE) {
// An ad is available already. // An ad is available already.
return false; return false;
} }
long adGroupTimeMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); long adGroupTimeMs = C.usToMs(adGroup.timeUs);
long contentPositionMs = getContentPeriodPositionMs(player, timeline, period); long contentPositionMs = getContentPeriodPositionMs(player, timeline, period);
long timeUntilAdMs = adGroupTimeMs - contentPositionMs; long timeUntilAdMs = adGroupTimeMs - contentPositionMs;
return timeUntilAdMs < configuration.adPreloadTimeoutMs; return timeUntilAdMs < configuration.adPreloadTimeoutMs;
...@@ -877,13 +877,13 @@ import java.util.Map; ...@@ -877,13 +877,13 @@ import java.util.Map;
} }
} }
if (!sentContentComplete && !wasPlayingAd && playingAd && imaAdState == IMA_AD_STATE_NONE) { if (!sentContentComplete && !wasPlayingAd && playingAd && imaAdState == IMA_AD_STATE_NONE) {
int adGroupIndex = player.getCurrentAdGroupIndex(); AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(player.getCurrentAdGroupIndex());
if (adPlaybackState.adGroupTimesUs[adGroupIndex] == C.TIME_END_OF_SOURCE) { if (adGroup.timeUs == C.TIME_END_OF_SOURCE) {
sendContentComplete(); sendContentComplete();
} else { } else {
// IMA hasn't called playAd yet, so fake the content position. // IMA hasn't called playAd yet, so fake the content position.
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime(); fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); fakeContentProgressOffsetMs = C.usToMs(adGroup.timeUs);
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) { if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
fakeContentProgressOffsetMs = contentDurationMs; fakeContentProgressOffsetMs = contentDurationMs;
} }
...@@ -919,11 +919,11 @@ import java.util.Map; ...@@ -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 // 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 // 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. // 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 =
adPlaybackState.withAdCount( adPlaybackState.withAdCount(
adInfo.adGroupIndex, max(adPodInfo.getTotalAds(), adGroup.states.length)); 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++) { for (int i = 0; i < adIndexInAdGroup; i++) {
// Any preceding ads that haven't loaded are not going to load. // Any preceding ads that haven't loaded are not going to load.
if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) { if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
...@@ -1062,10 +1062,10 @@ import java.util.Map; ...@@ -1062,10 +1062,10 @@ import java.util.Map;
private void markAdGroupInErrorStateAndClearPendingContentPosition(int adGroupIndex) { private void markAdGroupInErrorStateAndClearPendingContentPosition(int adGroupIndex) {
// Update the ad playback state so all ads in the ad group are in the error state. // 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) { if (adGroup.count == C.LENGTH_UNSET) {
adPlaybackState = adPlaybackState.withAdCount(adGroupIndex, max(1, adGroup.states.length)); 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++) { for (int i = 0; i < adGroup.count; i++) {
if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) { if (adGroup.states[i] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
...@@ -1094,7 +1094,7 @@ import java.util.Map; ...@@ -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 // 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. // we can notify that it failed to load.
fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime(); fakeContentProgressElapsedRealtimeMs = SystemClock.elapsedRealtime();
fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.adGroupTimesUs[adGroupIndex]); fakeContentProgressOffsetMs = C.usToMs(adPlaybackState.getAdGroup(adGroupIndex).timeUs);
if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) { if (fakeContentProgressOffsetMs == C.TIME_END_OF_SOURCE) {
fakeContentProgressOffsetMs = contentDurationMs; fakeContentProgressOffsetMs = contentDurationMs;
} }
...@@ -1109,7 +1109,7 @@ import java.util.Map; ...@@ -1109,7 +1109,7 @@ import java.util.Map;
adCallbacks.get(i).onEnded(adMediaInfo); adCallbacks.get(i).onEnded(adMediaInfo);
} }
} }
playingAdIndexInAdGroup = adPlaybackState.adGroups[adGroupIndex].getFirstAdIndexToPlay(); playingAdIndexInAdGroup = adPlaybackState.getAdGroup(adGroupIndex).getFirstAdIndexToPlay();
for (int i = 0; i < adCallbacks.size(); i++) { for (int i = 0; i < adCallbacks.size(); i++) {
adCallbacks.get(i).onError(checkNotNull(adMediaInfo)); adCallbacks.get(i).onError(checkNotNull(adMediaInfo));
} }
...@@ -1138,7 +1138,7 @@ import java.util.Map; ...@@ -1138,7 +1138,7 @@ import java.util.Map;
Log.d(TAG, "adsLoader.contentComplete"); Log.d(TAG, "adsLoader.contentComplete");
} }
for (int i = 0; i < adPlaybackState.adGroupCount; i++) { 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); adPlaybackState = adPlaybackState.withSkippedAdGroup(/* adGroupIndex= */ i);
} }
} }
...@@ -1213,7 +1213,7 @@ import java.util.Map; ...@@ -1213,7 +1213,7 @@ import java.util.Map;
float cuePointTimeSecondsFloat = (float) cuePointTimeSeconds; float cuePointTimeSecondsFloat = (float) cuePointTimeSeconds;
long adPodTimeUs = Math.round((double) cuePointTimeSecondsFloat * C.MICROS_PER_SECOND); long adPodTimeUs = Math.round((double) cuePointTimeSecondsFloat * C.MICROS_PER_SECOND);
for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) { 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 if (adGroupTimeUs != C.TIME_END_OF_SOURCE
&& Math.abs(adGroupTimeUs - adPodTimeUs) < THRESHOLD_AD_MATCH_US) { && Math.abs(adGroupTimeUs - adPodTimeUs) < THRESHOLD_AD_MATCH_US) {
return adGroupIndex; return adGroupIndex;
...@@ -1242,14 +1242,16 @@ import java.util.Map; ...@@ -1242,14 +1242,16 @@ import java.util.Map;
} }
} }
private static boolean hasMidrollAdGroups(long[] adGroupTimesUs) { private static boolean hasMidrollAdGroups(AdPlaybackState adPlaybackState) {
int count = adGroupTimesUs.length; int count = adPlaybackState.adGroupCount;
if (count == 1) { 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) { } 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 { } 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; return true;
} }
} }
......
...@@ -1413,7 +1413,8 @@ public final class ImaAdsLoaderTest { ...@@ -1413,7 +1413,8 @@ public final class ImaAdsLoaderTest {
public void onAdPlaybackState(AdPlaybackState adPlaybackState) { public void onAdPlaybackState(AdPlaybackState adPlaybackState) {
long[][] adDurationsUs = new long[adPlaybackState.adGroupCount][]; long[][] adDurationsUs = new long[adPlaybackState.adGroupCount][];
for (int adGroupIndex = 0; adGroupIndex < adPlaybackState.adGroupCount; adGroupIndex++) { 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); Arrays.fill(adDurationsUs[adGroupIndex], TEST_AD_DURATION_US);
} }
adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs); adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs);
......
...@@ -708,7 +708,7 @@ public abstract class Timeline implements Bundleable { ...@@ -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. * Period}, in microseconds, or {@link C#TIME_END_OF_SOURCE} for a post-roll ad group.
*/ */
public long getAdGroupTimeUs(int adGroupIndex) { public long getAdGroupTimeUs(int adGroupIndex) {
return adPlaybackState.adGroupTimesUs[adGroupIndex]; return adPlaybackState.getAdGroup(adGroupIndex).timeUs;
} }
/** /**
...@@ -720,7 +720,7 @@ public abstract class Timeline implements Bundleable { ...@@ -720,7 +720,7 @@ public abstract class Timeline implements Bundleable {
* if no ads should be played. * if no ads should be played.
*/ */
public int getFirstAdIndexToPlay(int adGroupIndex) { 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 { ...@@ -734,7 +734,7 @@ public abstract class Timeline implements Bundleable {
* if the ad group does not have any ads remaining to play. * if the ad group does not have any ads remaining to play.
*/ */
public int getNextAdIndexToPlay(int adGroupIndex, int lastPlayedAdIndex) { 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 { ...@@ -746,7 +746,7 @@ public abstract class Timeline implements Bundleable {
* skipped or failed. * skipped or failed.
*/ */
public boolean hasPlayedAdGroup(int adGroupIndex) { 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 { ...@@ -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. * @return The number of ads in the ad group, or {@link C#LENGTH_UNSET} if not yet known.
*/ */
public int getAdCountInAdGroup(int adGroupIndex) { 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 { ...@@ -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. * @return The duration of the ad, or {@link C#TIME_UNSET} if not yet known.
*/ */
public long getAdDurationUs(int adGroupIndex, int adIndexInAdGroup) { 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; return adGroup.count != C.LENGTH_UNSET ? adGroup.durationsUs[adIndexInAdGroup] : C.TIME_UNSET;
} }
...@@ -814,7 +814,7 @@ public abstract class Timeline implements Bundleable { ...@@ -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. * @return Whether this ad group is server-side inserted and part of the content stream.
*/ */
public boolean isServerSideInsertedAdGroup(int adGroupIndex) { 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 { ...@@ -825,7 +825,7 @@ public abstract class Timeline implements Bundleable {
* @return The offset that should be added to the content stream, in microseconds. * @return The offset that should be added to the content stream, in microseconds.
*/ */
public long getContentResumeOffsetUs(int adGroupIndex) { public long getContentResumeOffsetUs(int adGroupIndex) {
return adPlaybackState.adGroups[adGroupIndex].contentResumeOffsetUs; return adPlaybackState.getAdGroup(adGroupIndex).contentResumeOffsetUs;
} }
@Override @Override
......
...@@ -44,9 +44,9 @@ public class AdPlaybackStateTest { ...@@ -44,9 +44,9 @@ public class AdPlaybackStateTest {
@Test @Test
public void setAdCount() { 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); state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1);
assertThat(state.adGroups[0].count).isEqualTo(1); assertThat(state.getAdGroup(0).count).isEqualTo(1);
} }
@Test @Test
...@@ -54,10 +54,10 @@ public class AdPlaybackStateTest { ...@@ -54,10 +54,10 @@ public class AdPlaybackStateTest {
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI); state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1, TEST_URI);
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2); state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2);
assertThat(state.adGroups[0].uris[0]).isNull(); assertThat(state.getAdGroup(0).uris[0]).isNull();
assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); assertThat(state.getAdGroup(0).states[0]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
assertThat(state.adGroups[0].uris[1]).isSameInstanceAs(TEST_URI); assertThat(state.getAdGroup(0).uris[1]).isSameInstanceAs(TEST_URI);
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
} }
@Test @Test
...@@ -65,10 +65,10 @@ public class AdPlaybackStateTest { ...@@ -65,10 +65,10 @@ public class AdPlaybackStateTest {
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2); state = state.withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 2);
assertThat(state.adGroups[0].uris[0]).isNull(); assertThat(state.getAdGroup(0).uris[0]).isNull();
assertThat(state.adGroups[0].states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR); assertThat(state.getAdGroup(0).states[0]).isEqualTo(AdPlaybackState.AD_STATE_ERROR);
assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0)).isTrue(); 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(); assertThat(state.isAdInErrorState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1)).isFalse();
} }
...@@ -82,8 +82,8 @@ public class AdPlaybackStateTest { ...@@ -82,8 +82,8 @@ public class AdPlaybackStateTest {
.withAdGroupTimeUs(/* adGroupIndex= */ 1, 6_000); .withAdGroupTimeUs(/* adGroupIndex= */ 1, 6_000);
assertThat(state.adGroupCount).isEqualTo(2); assertThat(state.adGroupCount).isEqualTo(2);
assertThat(state.adGroupTimesUs[0]).isEqualTo(3_000); assertThat(state.getAdGroup(0).timeUs).isEqualTo(3_000);
assertThat(state.adGroupTimesUs[1]).isEqualTo(6_000); assertThat(state.getAdGroup(1).timeUs).isEqualTo(6_000);
} }
@Test @Test
...@@ -102,13 +102,13 @@ public class AdPlaybackStateTest { ...@@ -102,13 +102,13 @@ public class AdPlaybackStateTest {
.withNewAdGroup(/* adGroupIndex= */ 4, /* adGroupTimeUs= */ 8_000); .withNewAdGroup(/* adGroupIndex= */ 4, /* adGroupTimeUs= */ 8_000);
assertThat(state.adGroupCount).isEqualTo(5); assertThat(state.adGroupCount).isEqualTo(5);
assertThat(state.adGroups[0].count).isEqualTo(C.INDEX_UNSET); assertThat(state.getAdGroup(0).count).isEqualTo(C.INDEX_UNSET);
assertThat(state.adGroups[1].count).isEqualTo(2); assertThat(state.getAdGroup(1).count).isEqualTo(2);
assertThat(state.adGroups[1].uris[1]).isSameInstanceAs(TEST_URI); assertThat(state.getAdGroup(1).uris[1]).isSameInstanceAs(TEST_URI);
assertThat(state.adGroups[2].count).isEqualTo(C.INDEX_UNSET); assertThat(state.getAdGroup(2).count).isEqualTo(C.INDEX_UNSET);
assertThat(state.adGroups[3].count).isEqualTo(1); assertThat(state.getAdGroup(3).count).isEqualTo(1);
assertThat(state.adGroups[3].states[0]).isEqualTo(AdPlaybackState.AD_STATE_SKIPPED); assertThat(state.getAdGroup(3).states[0]).isEqualTo(AdPlaybackState.AD_STATE_SKIPPED);
assertThat(state.adGroups[4].count).isEqualTo(C.INDEX_UNSET); assertThat(state.getAdGroup(4).count).isEqualTo(C.INDEX_UNSET);
} }
@Test @Test
...@@ -121,10 +121,10 @@ public class AdPlaybackStateTest { ...@@ -121,10 +121,10 @@ public class AdPlaybackStateTest {
state = state.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 1_000, 2_000); state = state.withAdDurationsUs(/* adGroupIndex= */ 1, /* adDurationsUs...= */ 1_000, 2_000);
assertThat(state.adGroups[0].durationsUs[0]).isEqualTo(5_000); assertThat(state.getAdGroup(0).durationsUs[0]).isEqualTo(5_000);
assertThat(state.adGroups[0].durationsUs[1]).isEqualTo(6_000); assertThat(state.getAdGroup(0).durationsUs[1]).isEqualTo(6_000);
assertThat(state.adGroups[1].durationsUs[0]).isEqualTo(1_000); assertThat(state.getAdGroup(1).durationsUs[0]).isEqualTo(1_000);
assertThat(state.adGroups[1].durationsUs[1]).isEqualTo(2_000); assertThat(state.getAdGroup(1).durationsUs[1]).isEqualTo(2_000);
} }
@Test @Test
...@@ -133,7 +133,7 @@ public class AdPlaybackStateTest { ...@@ -133,7 +133,7 @@ public class AdPlaybackStateTest {
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI); state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, TEST_URI);
state = state.withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2, 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 @Test
...@@ -144,9 +144,9 @@ public class AdPlaybackStateTest { ...@@ -144,9 +144,9 @@ public class AdPlaybackStateTest {
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1); assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(1);
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); assertThat(state.getAdGroup(0).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
} }
@Test @Test
...@@ -157,9 +157,9 @@ public class AdPlaybackStateTest { ...@@ -157,9 +157,9 @@ public class AdPlaybackStateTest {
state = state.withSkippedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); state = state.withSkippedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(1); assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(1);
assertThat(state.adGroups[0].states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE); assertThat(state.getAdGroup(0).states[1]).isEqualTo(AdPlaybackState.AD_STATE_UNAVAILABLE);
assertThat(state.adGroups[0].states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE); assertThat(state.getAdGroup(0).states[2]).isEqualTo(AdPlaybackState.AD_STATE_AVAILABLE);
} }
@Test @Test
...@@ -171,7 +171,7 @@ public class AdPlaybackStateTest { ...@@ -171,7 +171,7 @@ public class AdPlaybackStateTest {
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1); state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(2); assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(2);
} }
@Test @Test
...@@ -181,7 +181,7 @@ public class AdPlaybackStateTest { ...@@ -181,7 +181,7 @@ public class AdPlaybackStateTest {
state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1); state = state.withAdLoadError(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
assertThat(state.adGroups[0].getNextAdIndexToPlay(0)).isEqualTo(2); assertThat(state.getAdGroup(0).getNextAdIndexToPlay(0)).isEqualTo(2);
} }
@Test @Test
...@@ -194,7 +194,7 @@ public class AdPlaybackStateTest { ...@@ -194,7 +194,7 @@ public class AdPlaybackStateTest {
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0);
assertThat(state.adGroups[0].getFirstAdIndexToPlay()).isEqualTo(0); assertThat(state.getAdGroup(0).getFirstAdIndexToPlay()).isEqualTo(0);
} }
@Test @Test
...@@ -209,8 +209,8 @@ public class AdPlaybackStateTest { ...@@ -209,8 +209,8 @@ public class AdPlaybackStateTest {
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 1);
state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2); state = state.withPlayedAd(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 2);
assertThat(state.adGroups[0].getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 0)).isEqualTo(1); assertThat(state.getAdGroup(0).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 0)).isEqualTo(1);
assertThat(state.adGroups[0].getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 1)).isEqualTo(2); assertThat(state.getAdGroup(0).getNextAdIndexToPlay(/* lastPlayedAdIndex= */ 1)).isEqualTo(2);
} }
@Test @Test
...@@ -229,8 +229,8 @@ public class AdPlaybackStateTest { ...@@ -229,8 +229,8 @@ public class AdPlaybackStateTest {
public void skipAllWithoutAdCount() { public void skipAllWithoutAdCount() {
state = state.withSkippedAdGroup(0); state = state.withSkippedAdGroup(0);
state = state.withSkippedAdGroup(1); state = state.withSkippedAdGroup(1);
assertThat(state.adGroups[0].count).isEqualTo(0); assertThat(state.getAdGroup(0).count).isEqualTo(0);
assertThat(state.adGroups[1].count).isEqualTo(0); assertThat(state.getAdGroup(1).count).isEqualTo(0);
} }
@Test @Test
...@@ -257,8 +257,9 @@ public class AdPlaybackStateTest { ...@@ -257,8 +257,9 @@ public class AdPlaybackStateTest {
assertThat(restoredState.adsId).isNull(); assertThat(restoredState.adsId).isNull();
assertThat(restoredState.adGroupCount).isEqualTo(originalState.adGroupCount); assertThat(restoredState.adGroupCount).isEqualTo(originalState.adGroupCount);
assertThat(restoredState.adGroupTimesUs).isEqualTo(originalState.adGroupTimesUs); for (int i = 0; i < restoredState.adGroupCount; i++) {
assertThat(restoredState.adGroups).isEqualTo(originalState.adGroups); assertThat(restoredState.getAdGroup(i)).isEqualTo(originalState.getAdGroup(i));
}
assertThat(restoredState.adResumePositionUs).isEqualTo(originalState.adResumePositionUs); assertThat(restoredState.adResumePositionUs).isEqualTo(originalState.adResumePositionUs);
assertThat(restoredState.contentDurationUs).isEqualTo(originalState.contentDurationUs); assertThat(restoredState.contentDurationUs).isEqualTo(originalState.contentDurationUs);
} }
...@@ -266,7 +267,7 @@ public class AdPlaybackStateTest { ...@@ -266,7 +267,7 @@ public class AdPlaybackStateTest {
@Test @Test
public void roundTripViaBundle_ofAdGroup_yieldsEqualInstance() { public void roundTripViaBundle_ofAdGroup_yieldsEqualInstance() {
AdPlaybackState.AdGroup adGroup = AdPlaybackState.AdGroup adGroup =
new AdPlaybackState.AdGroup() new AdPlaybackState.AdGroup(/* timeUs= */ 42)
.withAdCount(2) .withAdCount(2)
.withAdState(AD_STATE_AVAILABLE, /* index= */ 0) .withAdState(AD_STATE_AVAILABLE, /* index= */ 0)
.withAdState(AD_STATE_PLAYED, /* index= */ 1) .withAdState(AD_STATE_PLAYED, /* index= */ 1)
......
...@@ -50,7 +50,7 @@ public interface AdsLoader { ...@@ -50,7 +50,7 @@ public interface AdsLoader {
/** /**
* Called when the ad playback state has been updated. The number of {@link * 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. * @param adPlaybackState The new ad playback state.
*/ */
......
...@@ -305,11 +305,11 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -305,11 +305,11 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
@Nullable @Nullable
AdMediaSourceHolder adMediaSourceHolder = AdMediaSourceHolder adMediaSourceHolder =
this.adMediaSourceHolders[adGroupIndex][adIndexInAdGroup]; this.adMediaSourceHolders[adGroupIndex][adIndexInAdGroup];
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
if (adMediaSourceHolder != null if (adMediaSourceHolder != null
&& !adMediaSourceHolder.hasMediaSource() && !adMediaSourceHolder.hasMediaSource()
&& adPlaybackState.adGroups[adGroupIndex] != null && adIndexInAdGroup < adGroup.uris.length) {
&& adIndexInAdGroup < adPlaybackState.adGroups[adGroupIndex].uris.length) { @Nullable Uri adUri = adGroup.uris[adIndexInAdGroup];
@Nullable Uri adUri = adPlaybackState.adGroups[adGroupIndex].uris[adIndexInAdGroup];
if (adUri != null) { if (adUri != null) {
MediaItem.Builder adMediaItem = new MediaItem.Builder().setUri(adUri); MediaItem.Builder adMediaItem = new MediaItem.Builder().setUri(adUri);
// Propagate the content's DRM config into the ad media source. // Propagate the content's DRM config into the ad media source.
......
...@@ -122,13 +122,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource ...@@ -122,13 +122,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource
public void setAdPlaybackState(AdPlaybackState adPlaybackState) { public void setAdPlaybackState(AdPlaybackState adPlaybackState) {
checkArgument(adPlaybackState.adGroupCount >= this.adPlaybackState.adGroupCount); checkArgument(adPlaybackState.adGroupCount >= this.adPlaybackState.adGroupCount);
for (int i = 0; i < adPlaybackState.adGroupCount; i++) { 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) { if (i < this.adPlaybackState.adGroupCount) {
checkArgument( checkArgument(
getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i) getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i)
>= getAdCountInGroup(this.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); checkArgument(getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i) == 0);
} }
} }
...@@ -482,14 +483,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource ...@@ -482,14 +483,14 @@ public final class ServerSideInsertedAdsMediaSource extends BaseMediaSource
MediaPeriodImpl mediaPeriod, AdPlaybackState adPlaybackState) { MediaPeriodImpl mediaPeriod, AdPlaybackState adPlaybackState) {
MediaPeriodId id = mediaPeriod.mediaPeriodId; MediaPeriodId id = mediaPeriod.mediaPeriodId;
if (id.isAd()) { if (id.isAd()) {
return adPlaybackState.adGroups[id.adGroupIndex].count == C.LENGTH_UNSET AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(id.adGroupIndex);
? 0 return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.durationsUs[id.adIndexInAdGroup];
: adPlaybackState.adGroups[id.adGroupIndex].durationsUs[id.adIndexInAdGroup]; }
} if (id.nextAdGroupIndex == C.INDEX_UNSET) {
return id.nextAdGroupIndex == C.INDEX_UNSET return Long.MAX_VALUE;
|| adPlaybackState.adGroupTimesUs[id.nextAdGroupIndex] == C.TIME_END_OF_SOURCE }
? Long.MAX_VALUE AdPlaybackState.AdGroup nextAdGroup = adPlaybackState.getAdGroup(id.nextAdGroupIndex);
: adPlaybackState.adGroupTimesUs[id.nextAdGroupIndex]; return nextAdGroup.timeUs == C.TIME_END_OF_SOURCE ? Long.MAX_VALUE : nextAdGroup.timeUs;
} }
private static MediaLoadData correctMediaLoadData( private static MediaLoadData correctMediaLoadData(
......
...@@ -55,8 +55,8 @@ public final class ServerSideInsertedAdsUtil { ...@@ -55,8 +55,8 @@ public final class ServerSideInsertedAdsUtil {
fromPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState); fromPositionUs, /* nextAdGroupIndex= */ C.INDEX_UNSET, adPlaybackState);
int insertionIndex = 0; int insertionIndex = 0;
while (insertionIndex < adPlaybackState.adGroupCount while (insertionIndex < adPlaybackState.adGroupCount
&& adPlaybackState.adGroupTimesUs[insertionIndex] != C.TIME_END_OF_SOURCE && adPlaybackState.getAdGroup(insertionIndex).timeUs != C.TIME_END_OF_SOURCE
&& adPlaybackState.adGroupTimesUs[insertionIndex] <= adGroupInsertionPositionUs) { && adPlaybackState.getAdGroup(insertionIndex).timeUs <= adGroupInsertionPositionUs) {
insertionIndex++; insertionIndex++;
} }
long adDurationUs = toPositionUs - fromPositionUs; long adDurationUs = toPositionUs - fromPositionUs;
...@@ -69,11 +69,11 @@ public final class ServerSideInsertedAdsUtil { ...@@ -69,11 +69,11 @@ public final class ServerSideInsertedAdsUtil {
.withContentResumeOffsetUs(insertionIndex, contentResumeOffsetUs); .withContentResumeOffsetUs(insertionIndex, contentResumeOffsetUs);
long followingAdGroupTimeUsOffset = -adDurationUs + contentResumeOffsetUs; long followingAdGroupTimeUsOffset = -adDurationUs + contentResumeOffsetUs;
for (int i = insertionIndex + 1; i < adPlaybackState.adGroupCount; i++) { 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 =
adPlaybackState.withAdGroupTimeUs( adPlaybackState.withAdGroupTimeUs(
/* adGroupIndex= */ i, /* adGroupIndex= */ i, adGroupTimeUs + followingAdGroupTimeUsOffset);
adPlaybackState.adGroupTimesUs[i] + followingAdGroupTimeUsOffset);
} }
} }
return adPlaybackState; return adPlaybackState;
...@@ -182,16 +182,18 @@ public final class ServerSideInsertedAdsUtil { ...@@ -182,16 +182,18 @@ public final class ServerSideInsertedAdsUtil {
*/ */
public static long getStreamPositionUsForAd( public static long getStreamPositionUsForAd(
long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) { 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++) { for (int i = 0; i < adGroupIndex; i++) {
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { 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)) { if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) {
for (int i = 0; i < adIndexInAdGroup; i++) { for (int i = 0; i < adIndexInAdGroup; i++) {
positionUs += adPlaybackState.adGroups[adGroupIndex].durationsUs[i]; positionUs += currentAdGroup.durationsUs[i];
} }
} }
return positionUs; return positionUs;
...@@ -210,16 +212,18 @@ public final class ServerSideInsertedAdsUtil { ...@@ -210,16 +212,18 @@ public final class ServerSideInsertedAdsUtil {
*/ */
public static long getMediaPeriodPositionUsForAd( public static long getMediaPeriodPositionUsForAd(
long positionUs, int adGroupIndex, int adIndexInAdGroup, AdPlaybackState adPlaybackState) { 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++) { for (int i = 0; i < adGroupIndex; i++) {
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { 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)) { if (adIndexInAdGroup < getAdCountInGroup(adPlaybackState, adGroupIndex)) {
for (int i = 0; i < adIndexInAdGroup; i++) { for (int i = 0; i < adIndexInAdGroup; i++) {
positionUs -= adPlaybackState.adGroups[adGroupIndex].durationsUs[i]; positionUs -= currentAdGroup.durationsUs[i];
} }
} }
return positionUs; return positionUs;
...@@ -243,18 +247,16 @@ public final class ServerSideInsertedAdsUtil { ...@@ -243,18 +247,16 @@ public final class ServerSideInsertedAdsUtil {
nextAdGroupIndex = adPlaybackState.adGroupCount; nextAdGroupIndex = adPlaybackState.adGroupCount;
} }
for (int i = 0; i < nextAdGroupIndex; i++) { for (int i = 0; i < nextAdGroupIndex; i++) {
if (adPlaybackState.adGroupTimesUs[i] == C.TIME_END_OF_SOURCE AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|| adPlaybackState.adGroupTimesUs[i] > positionUs) { if (adGroup.timeUs == C.TIME_END_OF_SOURCE || adGroup.timeUs > positionUs) {
break; break;
} }
long adGroupStreamStartPositionUs = long adGroupStreamStartPositionUs = adGroup.timeUs + totalAdDurationBeforePositionUs;
adPlaybackState.adGroupTimesUs[i] + totalAdDurationBeforePositionUs;
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { 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; totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs;
long adGroupResumePositionUs = long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs;
adPlaybackState.adGroupTimesUs[i] + adPlaybackState.adGroups[i].contentResumeOffsetUs;
if (adGroupResumePositionUs > positionUs) { if (adGroupResumePositionUs > positionUs) {
// The position is inside the ad group. // The position is inside the ad group.
return max(adGroupStreamStartPositionUs, positionUs + totalAdDurationBeforePositionUs); return max(adGroupStreamStartPositionUs, positionUs + totalAdDurationBeforePositionUs);
...@@ -282,19 +284,19 @@ public final class ServerSideInsertedAdsUtil { ...@@ -282,19 +284,19 @@ public final class ServerSideInsertedAdsUtil {
nextAdGroupIndex = adPlaybackState.adGroupCount; nextAdGroupIndex = adPlaybackState.adGroupCount;
} }
for (int i = 0; i < nextAdGroupIndex; i++) { for (int i = 0; i < nextAdGroupIndex; i++) {
if (adPlaybackState.adGroupTimesUs[i] == C.TIME_END_OF_SOURCE AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|| adPlaybackState.adGroupTimesUs[i] > positionUs - totalAdDurationBeforePositionUs) { if (adGroup.timeUs == C.TIME_END_OF_SOURCE
|| adGroup.timeUs > positionUs - totalAdDurationBeforePositionUs) {
break; break;
} }
for (int j = 0; j < getAdCountInGroup(adPlaybackState, /* adGroupIndex= */ i); j++) { 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; totalAdDurationBeforePositionUs -= adGroup.contentResumeOffsetUs;
long adGroupResumePositionUs = long adGroupResumePositionUs = adGroup.timeUs + adGroup.contentResumeOffsetUs;
adPlaybackState.adGroupTimesUs[i] + adPlaybackState.adGroups[i].contentResumeOffsetUs;
if (adGroupResumePositionUs > positionUs - totalAdDurationBeforePositionUs) { if (adGroupResumePositionUs > positionUs - totalAdDurationBeforePositionUs) {
// The position is inside the ad group. // The position is inside the ad group.
return max(adPlaybackState.adGroupTimesUs[i], positionUs - totalAdDurationBeforePositionUs); return max(adGroup.timeUs, positionUs - totalAdDurationBeforePositionUs);
} }
} }
return positionUs - totalAdDurationBeforePositionUs; return positionUs - totalAdDurationBeforePositionUs;
...@@ -308,8 +310,7 @@ public final class ServerSideInsertedAdsUtil { ...@@ -308,8 +310,7 @@ public final class ServerSideInsertedAdsUtil {
* @return The number of ads in the ad group. * @return The number of ads in the ad group.
*/ */
public static int getAdCountInGroup(AdPlaybackState adPlaybackState, int adGroupIndex) { public static int getAdCountInGroup(AdPlaybackState adPlaybackState, int adGroupIndex) {
return adPlaybackState.adGroups[adGroupIndex].count == C.LENGTH_UNSET AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(adGroupIndex);
? 0 return adGroup.count == C.LENGTH_UNSET ? 0 : adGroup.count;
: adPlaybackState.adGroups[adGroupIndex].count;
} }
} }
...@@ -797,7 +797,9 @@ public final class MediaPeriodQueueTest { ...@@ -797,7 +797,9 @@ public final class MediaPeriodQueueTest {
long[][] newDurations = new long[adPlaybackState.adGroupCount][]; long[][] newDurations = new long[adPlaybackState.adGroupCount][];
for (int i = 0; i < adPlaybackState.adGroupCount; i++) { for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
newDurations[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 =
adPlaybackState adPlaybackState
...@@ -808,7 +810,7 @@ public final class MediaPeriodQueueTest { ...@@ -808,7 +810,7 @@ public final class MediaPeriodQueueTest {
} }
private void setAdGroupPlayed(int adGroupIndex) { 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); adPlaybackState = adPlaybackState.withPlayedAd(adGroupIndex, /* adIndexInAdGroup= */ i);
} }
updateTimeline(); updateTimeline();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment