Make period durations of FakeMultiPeriodLiveTimeline configurable
PiperOrigin-RevId: 522046876
This commit is contained in:
parent
5442c33ac7
commit
e4194fc862
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.common;
|
package androidx.media3.common;
|
||||||
|
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_MS;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.PERIOD_DURATION_MS;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -436,10 +438,13 @@ public class TimelineTest {
|
|||||||
public void periodIsLivePostrollPlaceholder_recognizesLivePostrollPlaceholder() {
|
public void periodIsLivePostrollPlaceholder_recognizesLivePostrollPlaceholder() {
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000,
|
/* liveWindowDurationUs= */ 60_000_000,
|
||||||
/* nowUs= */ 60_000_000,
|
/* nowUs= */ 60_000_000,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
|
@ -15,8 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer;
|
package androidx.media3.exoplayer;
|
||||||
|
|
||||||
|
import static androidx.media3.common.util.Util.msToUs;
|
||||||
import static androidx.media3.test.utils.ExoPlayerTestRunner.AUDIO_FORMAT;
|
import static androidx.media3.test.utils.ExoPlayerTestRunner.AUDIO_FORMAT;
|
||||||
import static androidx.media3.test.utils.ExoPlayerTestRunner.VIDEO_FORMAT;
|
import static androidx.media3.test.utils.ExoPlayerTestRunner.VIDEO_FORMAT;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_MS;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.PERIOD_DURATION_MS;
|
||||||
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US;
|
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US;
|
||||||
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@ -430,15 +433,18 @@ public final class MediaPeriodQueueTest {
|
|||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void getNextMediaPeriodInfo_multiPeriodTimelineWithNoAdsAndNoPostrollPlaceholder() {
|
public void getNextMediaPeriodInfo_multiPeriodTimelineWithNoAdsAndNoPostrollPlaceholder() {
|
||||||
long contentPeriodDurationUs = FakeMultiPeriodLiveTimeline.PERIOD_DURATION_US;
|
long contentPeriodDurationUs = msToUs(PERIOD_DURATION_MS);
|
||||||
long adPeriodDurationUs = FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_US;
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Multi period timeline without ad playback state.
|
// Multi period timeline without ad playback state.
|
||||||
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000,
|
/* liveWindowDurationUs= */ 60_000_000,
|
||||||
/* nowUs= */ 110_000_000,
|
/* nowUs= */ 110_000_000,
|
||||||
new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -497,15 +503,18 @@ public final class MediaPeriodQueueTest {
|
|||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void getNextMediaPeriodInfo_multiPeriodTimelineWithPostrollPlaceHolder() {
|
public void getNextMediaPeriodInfo_multiPeriodTimelineWithPostrollPlaceHolder() {
|
||||||
long contentPeriodDurationUs = FakeMultiPeriodLiveTimeline.PERIOD_DURATION_US;
|
long contentPeriodDurationUs = msToUs(PERIOD_DURATION_MS);
|
||||||
long adPeriodDurationUs = FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_US;
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Multi period timeline without ad playback state.
|
// Multi period timeline without ad playback state.
|
||||||
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000,
|
/* liveWindowDurationUs= */ 60_000_000,
|
||||||
/* nowUs= */ 110_000_000,
|
/* nowUs= */ 110_000_000,
|
||||||
new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -564,14 +573,17 @@ public final class MediaPeriodQueueTest {
|
|||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void getNextMediaPeriodInfo_multiPeriodTimelineWithAdsAndWithPostRollPlaceHolder() {
|
public void getNextMediaPeriodInfo_multiPeriodTimelineWithAdsAndWithPostRollPlaceHolder() {
|
||||||
long contentPeriodDurationUs = FakeMultiPeriodLiveTimeline.PERIOD_DURATION_US;
|
long contentPeriodDurationUs = msToUs(PERIOD_DURATION_MS);
|
||||||
long adPeriodDurationUs = FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_US;
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000,
|
/* liveWindowDurationUs= */ 60_000_000,
|
||||||
/* nowUs= */ 110_000_000,
|
/* nowUs= */ 110_000_000,
|
||||||
new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -646,13 +658,16 @@ public final class MediaPeriodQueueTest {
|
|||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void getNextMediaPeriodInfo_multiPeriodTimelineWithPlayedAdsAndWithPostRollPlaceHolder() {
|
public void getNextMediaPeriodInfo_multiPeriodTimelineWithPlayedAdsAndWithPostRollPlaceHolder() {
|
||||||
long contentPeriodDurationUs = FakeMultiPeriodLiveTimeline.PERIOD_DURATION_US;
|
long contentPeriodDurationUs = msToUs(PERIOD_DURATION_MS);
|
||||||
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
FakeMultiPeriodLiveTimeline multiPeriodLiveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000,
|
/* liveWindowDurationUs= */ 60_000_000,
|
||||||
/* nowUs= */ 110_000_000,
|
/* nowUs= */ 110_000_000,
|
||||||
new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ true);
|
/* playedAds= */ true);
|
||||||
|
@ -20,6 +20,7 @@ import static androidx.media3.common.AdPlaybackState.AD_STATE_ERROR;
|
|||||||
import static androidx.media3.common.AdPlaybackState.AD_STATE_PLAYED;
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_PLAYED;
|
||||||
import static androidx.media3.common.AdPlaybackState.AD_STATE_SKIPPED;
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_SKIPPED;
|
||||||
import static androidx.media3.common.AdPlaybackState.AD_STATE_UNAVAILABLE;
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_UNAVAILABLE;
|
||||||
|
import static androidx.media3.common.util.Util.msToUs;
|
||||||
import static androidx.media3.exoplayer.ima.ImaUtil.addLiveAdBreak;
|
import static androidx.media3.exoplayer.ima.ImaUtil.addLiveAdBreak;
|
||||||
import static androidx.media3.exoplayer.ima.ImaUtil.getAdGroupAndIndexInLiveMultiPeriodTimeline;
|
import static androidx.media3.exoplayer.ima.ImaUtil.getAdGroupAndIndexInLiveMultiPeriodTimeline;
|
||||||
import static androidx.media3.exoplayer.ima.ImaUtil.getAdGroupAndIndexInVodMultiPeriodTimeline;
|
import static androidx.media3.exoplayer.ima.ImaUtil.getAdGroupAndIndexInVodMultiPeriodTimeline;
|
||||||
@ -28,7 +29,8 @@ import static androidx.media3.exoplayer.ima.ImaUtil.maybeCorrectPreviouslyUnknow
|
|||||||
import static androidx.media3.exoplayer.ima.ImaUtil.secToUsRounded;
|
import static androidx.media3.exoplayer.ima.ImaUtil.secToUsRounded;
|
||||||
import static androidx.media3.exoplayer.ima.ImaUtil.splitAdGroup;
|
import static androidx.media3.exoplayer.ima.ImaUtil.splitAdGroup;
|
||||||
import static androidx.media3.exoplayer.source.ads.ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState;
|
import static androidx.media3.exoplayer.source.ads.ServerSideAdInsertionUtil.addAdGroupToAdPlaybackState;
|
||||||
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_US;
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_MS;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.PERIOD_DURATION_MS;
|
||||||
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US;
|
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US;
|
||||||
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
import static androidx.media3.test.utils.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
@ -560,7 +562,7 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
splitAdPlaybackStateForPeriods_liveAdGroupStartedAndMovedOutOfWindow_splitCorrectly() {
|
splitAdPlaybackStateForPeriods_liveAdGroupStartedAndMovedOutOfWindow_splitCorrectly() {
|
||||||
long adPeriodDurationUs = AD_PERIOD_DURATION_US;
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
AdPlaybackState adPlaybackState =
|
AdPlaybackState adPlaybackState =
|
||||||
new AdPlaybackState(/* adsId= */ "adsId", C.TIME_END_OF_SOURCE)
|
new AdPlaybackState(/* adsId= */ "adsId", C.TIME_END_OF_SOURCE)
|
||||||
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
|
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
|
||||||
@ -568,10 +570,13 @@ public class ImaUtilTest {
|
|||||||
// Period durations: content=30_000_000, ad=10_000_000
|
// Period durations: content=30_000_000, ad=10_000_000
|
||||||
FakeMultiPeriodLiveTimeline liveTimeline =
|
FakeMultiPeriodLiveTimeline liveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 100_000_000,
|
/* liveWindowDurationUs= */ 100_000_000,
|
||||||
/* nowUs= */ 150_000_000,
|
/* nowUs= */ 150_000_000,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -851,6 +856,7 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
splitAdPlaybackStateForPeriods_fullAdGroupAtBeginOfWindow_adPeriodsCorrectlyDetected() {
|
splitAdPlaybackStateForPeriods_fullAdGroupAtBeginOfWindow_adPeriodsCorrectlyDetected() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
AdPlaybackState adPlaybackState =
|
AdPlaybackState adPlaybackState =
|
||||||
new AdPlaybackState(/* adsId= */ "adsId", C.TIME_END_OF_SOURCE)
|
new AdPlaybackState(/* adsId= */ "adsId", C.TIME_END_OF_SOURCE)
|
||||||
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
|
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
|
||||||
@ -858,10 +864,13 @@ public class ImaUtilTest {
|
|||||||
// Period durations: content=30_000_000, ad=10_000_000
|
// Period durations: content=30_000_000, ad=10_000_000
|
||||||
FakeMultiPeriodLiveTimeline liveTimeline =
|
FakeMultiPeriodLiveTimeline liveTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 30_000_000,
|
/* liveWindowDurationUs= */ 30_000_000,
|
||||||
/* nowUs= */ 59_999_999,
|
/* nowUs= */ 59_999_999,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -869,9 +878,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 30_000_000,
|
/* currentContentPeriodPositionUs= */ 30_000_000,
|
||||||
AD_PERIOD_DURATION_US,
|
adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 2 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 2 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 2,
|
/* totalAdsInAdPod= */ 2,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -968,9 +977,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 80_000_000,
|
/* currentContentPeriodPositionUs= */ 80_000_000,
|
||||||
AD_PERIOD_DURATION_US - 1000L, // SDK fallback duration.
|
adPeriodDurationUs - 1000L, // SDK fallback duration.
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 2 * AD_PERIOD_DURATION_US - 1001L,
|
/* totalAdDurationUs= */ 2 * adPeriodDurationUs - 1001L,
|
||||||
/* totalAdsInAdPod= */ 2,
|
/* totalAdsInAdPod= */ 2,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
splitAdPlaybackStates = ImaUtil.splitAdPlaybackStateForPeriods(adPlaybackState, liveTimeline);
|
splitAdPlaybackStates = ImaUtil.splitAdPlaybackStateForPeriods(adPlaybackState, liveTimeline);
|
||||||
@ -984,7 +993,7 @@ public class ImaUtilTest {
|
|||||||
AdPlaybackState.AdGroup actualAdGroup =
|
AdPlaybackState.AdGroup actualAdGroup =
|
||||||
splitAdPlaybackStates.get("uid-4[a]").getAdGroup(/* adGroupIndex= */ 0);
|
splitAdPlaybackStates.get("uid-4[a]").getAdGroup(/* adGroupIndex= */ 0);
|
||||||
assertThat(actualAdGroup.count).isEqualTo(1);
|
assertThat(actualAdGroup.count).isEqualTo(1);
|
||||||
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(AD_PERIOD_DURATION_US - 1000L);
|
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(adPeriodDurationUs - 1000L);
|
||||||
|
|
||||||
// Advance to make the window overlap 1 microsecond into the second ad period. Assert whether
|
// Advance to make the window overlap 1 microsecond into the second ad period. Assert whether
|
||||||
// both ad periods, including the last with unknown duration, are correctly marked as ad.
|
// both ad periods, including the last with unknown duration, are correctly marked as ad.
|
||||||
@ -999,11 +1008,11 @@ public class ImaUtilTest {
|
|||||||
assertThat(splitAdPlaybackStates.get("uid-4[a]").adGroupCount).isEqualTo(2);
|
assertThat(splitAdPlaybackStates.get("uid-4[a]").adGroupCount).isEqualTo(2);
|
||||||
actualAdGroup = splitAdPlaybackStates.get("uid-4[a]").getAdGroup(/* adGroupIndex= */ 0);
|
actualAdGroup = splitAdPlaybackStates.get("uid-4[a]").getAdGroup(/* adGroupIndex= */ 0);
|
||||||
assertThat(actualAdGroup.count).isEqualTo(1);
|
assertThat(actualAdGroup.count).isEqualTo(1);
|
||||||
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(AD_PERIOD_DURATION_US);
|
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(adPeriodDurationUs);
|
||||||
assertThat(splitAdPlaybackStates.get("uid-5[a]").adGroupCount).isEqualTo(2);
|
assertThat(splitAdPlaybackStates.get("uid-5[a]").adGroupCount).isEqualTo(2);
|
||||||
actualAdGroup = splitAdPlaybackStates.get("uid-5[a]").getAdGroup(/* adGroupIndex= */ 0);
|
actualAdGroup = splitAdPlaybackStates.get("uid-5[a]").getAdGroup(/* adGroupIndex= */ 0);
|
||||||
assertThat(actualAdGroup.count).isEqualTo(1);
|
assertThat(actualAdGroup.count).isEqualTo(1);
|
||||||
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(AD_PERIOD_DURATION_US - 1L); // SDK fallback.
|
assertThat(actualAdGroup.durationsUs[0]).isEqualTo(adPeriodDurationUs - 1L); // SDK fallback.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1033,6 +1042,7 @@ public class ImaUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void maybeCorrectPreviouslyUnknownAdDuration_singleAdInAdGroup_adDurationCorrected() {
|
public void maybeCorrectPreviouslyUnknownAdDuration_singleAdInAdGroup_adDurationCorrected() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
long liveWindowDurationUs = 60_000_000L;
|
long liveWindowDurationUs = 60_000_000L;
|
||||||
long nowUs = 110_234_567L;
|
long nowUs = 110_234_567L;
|
||||||
AdPlaybackState adPlaybackState =
|
AdPlaybackState adPlaybackState =
|
||||||
@ -1053,10 +1063,13 @@ public class ImaUtilTest {
|
|||||||
/* adDurationsUs...= */ 123);
|
/* adDurationsUs...= */ 123);
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1070,13 +1083,14 @@ public class ImaUtilTest {
|
|||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).timeUs).isEqualTo(90_000_000L);
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).timeUs).isEqualTo(90_000_000L);
|
||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).durationsUs)
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).durationsUs)
|
||||||
.asList()
|
.asList()
|
||||||
.containsExactly(AD_PERIOD_DURATION_US);
|
.containsExactly(adPeriodDurationUs);
|
||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).contentResumeOffsetUs)
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).contentResumeOffsetUs)
|
||||||
.isEqualTo(AD_PERIOD_DURATION_US);
|
.isEqualTo(adPeriodDurationUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void maybeCorrectPreviouslyUnknownAdDuration_multipleAdsInAdGroup_adDurationCorrected() {
|
public void maybeCorrectPreviouslyUnknownAdDuration_multipleAdsInAdGroup_adDurationCorrected() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
long liveWindowDurationUs = 60_000_000L;
|
long liveWindowDurationUs = 60_000_000L;
|
||||||
long nowUs = 110_234_567L;
|
long nowUs = 110_234_567L;
|
||||||
AdPlaybackState adPlaybackState =
|
AdPlaybackState adPlaybackState =
|
||||||
@ -1086,15 +1100,18 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState,
|
adPlaybackState,
|
||||||
/* fromPositionUs= */ 80_000_000L,
|
/* fromPositionUs= */ 80_000_000L,
|
||||||
/* contentResumeOffsetUs= */ 10_000_123L,
|
/* contentResumeOffsetUs= */ 10_000_123L,
|
||||||
/* adDurationsUs...= */ AD_PERIOD_DURATION_US,
|
/* adDurationsUs...= */ adPeriodDurationUs,
|
||||||
123L);
|
123L);
|
||||||
// Content timeline: [content, ad, ad, content]
|
// Content timeline: [content, ad, ad, content]
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1104,9 +1121,9 @@ public class ImaUtilTest {
|
|||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).timeUs).isEqualTo(80_000_000L);
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).timeUs).isEqualTo(80_000_000L);
|
||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).durationsUs)
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).durationsUs)
|
||||||
.asList()
|
.asList()
|
||||||
.containsExactly(AD_PERIOD_DURATION_US, AD_PERIOD_DURATION_US);
|
.containsExactly(adPeriodDurationUs, adPeriodDurationUs);
|
||||||
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).contentResumeOffsetUs)
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).contentResumeOffsetUs)
|
||||||
.isEqualTo(2 * AD_PERIOD_DURATION_US);
|
.isEqualTo(2 * adPeriodDurationUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1128,10 +1145,13 @@ public class ImaUtilTest {
|
|||||||
/* adDurationsUs...= */ 123);
|
/* adDurationsUs...= */ 123);
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 160_000_000L,
|
/* nowUs= */ 160_000_000L,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1150,10 +1170,17 @@ public class ImaUtilTest {
|
|||||||
// Content and ad period in window at the beginning: [c, a, a]
|
// Content and ad period in window at the beginning: [c, a, a]
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 50_000_000L,
|
/* liveWindowDurationUs= */ 50_000_000L,
|
||||||
/* nowUs= */ 50_000_000L,
|
/* nowUs= */ 50_000_000L,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1271,14 +1298,16 @@ public class ImaUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void maybeCorrectPreviouslyUnknownAdDuration_singleContentPeriodTimeline_doNothing() {
|
||||||
maybeCorrectPreviouslyUnknownAdDuration_singleContentPeriodTimeline_adPlaybackStateNotChanged() {
|
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 30_000_000L,
|
/* liveWindowDurationUs= */ 30_000_000L,
|
||||||
/* nowUs= */ 80_000_000L,
|
/* nowUs= */ 80_000_000L,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1308,10 +1337,13 @@ public class ImaUtilTest {
|
|||||||
maybeCorrectPreviouslyUnknownAdDuration_singleAdPeriodTimeline_doesNotOverrideWithTimeUnset() {
|
maybeCorrectPreviouslyUnknownAdDuration_singleAdPeriodTimeline_doesNotOverrideWithTimeUnset() {
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 10_000_000L,
|
/* liveWindowDurationUs= */ 10_000_000L,
|
||||||
/* nowUs= */ 90_000_000L,
|
/* nowUs= */ 90_000_000L,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1608,13 +1640,20 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getAdGroupAndIndexInLiveMultiPeriodTimeline_calledForPeriodsAfterUnplayedAdGroup_correctAdGroupIndexAndAdIndexInAdGroup() {
|
getAdGroupAndIndexInLiveMultiPeriodTimeline_calledForPeriodsAfterUnplayedAdGroup_correctAdGroupIndexAndAdIndexInAdGroup() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content live window with content and ad periods: c, [a, c, a, a, a, c, a], a, a
|
// Content live window with content and ad periods: c, [a, c, a, a, a, c, a], a, a
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 100_000_000,
|
/* liveWindowDurationUs= */ 100_000_000,
|
||||||
/* nowUs= */ 159_000_123,
|
/* nowUs= */ 159_000_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1623,9 +1662,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 50_000_000,
|
/* currentContentPeriodPositionUs= */ 50_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 1,
|
/* totalAdsInAdPod= */ 1,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -1642,25 +1681,25 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 90_000_000,
|
/* currentContentPeriodPositionUs= */ 90_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 100_000_000,
|
/* currentContentPeriodPositionUs= */ 100_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 110_000_000,
|
/* currentContentPeriodPositionUs= */ 110_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 3,
|
/* adPositionInAdPod= */ 3,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -1699,9 +1738,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 150_000_000,
|
/* currentContentPeriodPositionUs= */ 150_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -1717,13 +1756,20 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getAdGroupAndIndexInLiveMultiPeriodTimeline_calledForPeriodsBeforeUnplayedAdGroup_throwsWhenCalledForNonAdPeriods() {
|
getAdGroupAndIndexInLiveMultiPeriodTimeline_calledForPeriodsBeforeUnplayedAdGroup_throwsWhenCalledForNonAdPeriods() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content live window with content and ad periods: c, [a, c, a, a, a, c, a], a, a
|
// Content live window with content and ad periods: c, [a, c, a, a, a, c, a], a, a
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 100_000_000,
|
/* liveWindowDurationUs= */ 100_000_000,
|
||||||
/* nowUs= */ 159_000_123,
|
/* nowUs= */ 159_000_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1732,9 +1778,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 50_000_000,
|
/* currentContentPeriodPositionUs= */ 50_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 1,
|
/* totalAdsInAdPod= */ 1,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
@ -1742,25 +1788,25 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 90_000_000,
|
/* currentContentPeriodPositionUs= */ 90_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 100_000_000,
|
/* currentContentPeriodPositionUs= */ 100_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 110_000_000,
|
/* currentContentPeriodPositionUs= */ 110_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 3,
|
/* adPositionInAdPod= */ 3,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
AdPlaybackState finalAdPlaybackState = adPlaybackState;
|
AdPlaybackState finalAdPlaybackState = adPlaybackState;
|
||||||
@ -1783,9 +1829,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 150_000_000,
|
/* currentContentPeriodPositionUs= */ 150_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
AdPlaybackState anotherFinalAdPlaybackState = adPlaybackState;
|
AdPlaybackState anotherFinalAdPlaybackState = adPlaybackState;
|
||||||
@ -1803,13 +1849,20 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getAdGroupAndIndexInLiveMultiPeriodTimeline_partialAdGroupAtTimelineStart_correctAdGroupIndexAndAdIndexInAdGroup() {
|
getAdGroupAndIndexInLiveMultiPeriodTimeline_partialAdGroupAtTimelineStart_correctAdGroupIndexAndAdIndexInAdGroup() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content timeline with content and ad periods: c, a, a, [a, c, a, a, a, c]
|
// Content timeline with content and ad periods: c, a, a, [a, c, a, a, a, c]
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 100_000_000,
|
/* liveWindowDurationUs= */ 100_000_000,
|
||||||
/* nowUs= */ 151_000_123,
|
/* nowUs= */ 151_000_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1818,25 +1871,25 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 30_000_000,
|
/* currentContentPeriodPositionUs= */ 30_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 40_000_000,
|
/* currentContentPeriodPositionUs= */ 40_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 50_000_000,
|
/* currentContentPeriodPositionUs= */ 50_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 3,
|
/* adPositionInAdPod= */ 3,
|
||||||
/* totalAdDurationUs= */ 3 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 3 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 3,
|
/* totalAdsInAdPod= */ 3,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
@ -1856,14 +1909,24 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getAdGroupAndIndexInLiveMultiPeriodTimeline_onlyPartialAdGroupInWindow_correctAdGroupIndexAndAdIndexInAdGroup() {
|
getAdGroupAndIndexInLiveMultiPeriodTimeline_onlyPartialAdGroupInWindow_correctAdGroupIndexAndAdIndexInAdGroup() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content timeline with content and ad periods: c, a, [a, a, a, a], a, c
|
// Content timeline with content and ad periods: c, a, [a, a, a, a], a, c
|
||||||
// First three ad periods of the ad group already outside of the live window.
|
// First three ad periods of the ad group already outside of the live window.
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 30_000_000,
|
/* liveWindowDurationUs= */ 30_000_000,
|
||||||
/* nowUs= */ 71_000_123,
|
/* nowUs= */ 71_000_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1873,9 +1936,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 30_000_000,
|
/* currentContentPeriodPositionUs= */ 30_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 6 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 6 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 6,
|
/* totalAdsInAdPod= */ 6,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
@ -1883,9 +1946,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 40_000_000,
|
/* currentContentPeriodPositionUs= */ 40_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 6 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 6 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 6,
|
/* totalAdsInAdPod= */ 6,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -1903,9 +1966,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 50_000_000,
|
/* currentContentPeriodPositionUs= */ 50_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 3,
|
/* adPositionInAdPod= */ 3,
|
||||||
/* totalAdDurationUs= */ 6 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 6 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 6,
|
/* totalAdsInAdPod= */ 6,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -1941,13 +2004,23 @@ public class ImaUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handleAdPeriodRemovedFromTimeline_removalCorrectlyHandled() {
|
public void handleAdPeriodRemovedFromTimeline_removalCorrectlyHandled() {
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content timeline with content and ad periods: a,[c, a, a, a, a, a, a, c], a
|
// Content timeline with content and ad periods: a,[c, a, a, a, a, a, a, c], a
|
||||||
FakeMultiPeriodLiveTimeline contentTimeline =
|
FakeMultiPeriodLiveTimeline contentTimeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 70_000_123,
|
/* liveWindowDurationUs= */ 70_000_123,
|
||||||
/* nowUs= */ 189_453_123,
|
/* nowUs= */ 189_453_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true, true, true, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true, true, true, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -1957,9 +2030,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 120_000_000,
|
/* currentContentPeriodPositionUs= */ 120_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 1,
|
/* adPositionInAdPod= */ 1,
|
||||||
/* totalAdDurationUs= */ 6 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 6 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 6,
|
/* totalAdsInAdPod= */ 6,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
@ -1967,9 +2040,9 @@ public class ImaUtilTest {
|
|||||||
adPlaybackState =
|
adPlaybackState =
|
||||||
addLiveAdBreak(
|
addLiveAdBreak(
|
||||||
/* currentContentPeriodPositionUs= */ 130_000_000,
|
/* currentContentPeriodPositionUs= */ 130_000_000,
|
||||||
/* adDurationUs= */ AD_PERIOD_DURATION_US,
|
/* adDurationUs= */ adPeriodDurationUs,
|
||||||
/* adPositionInAdPod= */ 2,
|
/* adPositionInAdPod= */ 2,
|
||||||
/* totalAdDurationUs= */ 6 * AD_PERIOD_DURATION_US,
|
/* totalAdDurationUs= */ 6 * adPeriodDurationUs,
|
||||||
/* totalAdsInAdPod= */ 6,
|
/* totalAdsInAdPod= */ 6,
|
||||||
adPlaybackState);
|
adPlaybackState);
|
||||||
|
|
||||||
@ -2099,13 +2172,17 @@ public class ImaUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getAdGroupDurationUsForLiveAdPeriodIndex_allAdsInTimeline_correctAdGroupDuration() {
|
public void getAdGroupDurationUsForLiveAdPeriodIndex_allAdsInTimeline_correctAdGroupDuration() {
|
||||||
int adPodTotalAdCount = 2;
|
int adPodTotalAdCount = 2;
|
||||||
|
long adPeriodDurationUs = msToUs(AD_PERIOD_DURATION_MS);
|
||||||
// Content and ad periods in timeline: [c, a, a, c, a, a].
|
// Content and ad periods in timeline: [c, a, a, c, a, a].
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 75_007_123,
|
/* liveWindowDurationUs= */ 75_007_123,
|
||||||
/* nowUs= */ 99_321_457,
|
/* nowUs= */ 99_321_457,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -2121,11 +2198,11 @@ public class ImaUtilTest {
|
|||||||
assertThat(
|
assertThat(
|
||||||
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
||||||
timeline, firstAdPodInfo, /* adPeriodIndex= */ 1, new Window(), new Period()))
|
timeline, firstAdPodInfo, /* adPeriodIndex= */ 1, new Window(), new Period()))
|
||||||
.isEqualTo(2 * AD_PERIOD_DURATION_US);
|
.isEqualTo(2 * adPeriodDurationUs);
|
||||||
assertThat(
|
assertThat(
|
||||||
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
||||||
timeline, secondAdPodInfo, /* adPeriodIndex= */ 2, new Window(), new Period()))
|
timeline, secondAdPodInfo, /* adPeriodIndex= */ 2, new Window(), new Period()))
|
||||||
.isEqualTo(2 * AD_PERIOD_DURATION_US);
|
.isEqualTo(2 * adPeriodDurationUs);
|
||||||
// The second ad group has the last ad with an unknown duration.
|
// The second ad group has the last ad with an unknown duration.
|
||||||
assertThat(
|
assertThat(
|
||||||
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
ImaUtil.getAdGroupDurationUsForLiveAdPeriodIndex(
|
||||||
@ -2144,10 +2221,13 @@ public class ImaUtilTest {
|
|||||||
// Content and ad periods in timeline: [a, a, c]. First two ads not in window.
|
// Content and ad periods in timeline: [a, a, c]. First two ads not in window.
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0,
|
/* availabilityStartTimeMs= */ 0,
|
||||||
/* liveWindowDurationUs= */ 49_321_753,
|
/* liveWindowDurationUs= */ 49_321_753,
|
||||||
/* nowUs= */ 85_007_123,
|
/* nowUs= */ 85_007_123,
|
||||||
/* adSequencePattern= */ new boolean[] {false, true, true},
|
/* adSequencePattern= */ new boolean[] {false, true, true},
|
||||||
|
/* periodDurationMsPattern= */ new long[] {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
|
@ -17,6 +17,7 @@ package androidx.media3.test.utils;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Util.msToUs;
|
import static androidx.media3.common.util.Util.msToUs;
|
||||||
|
import static androidx.media3.common.util.Util.sum;
|
||||||
import static androidx.media3.common.util.Util.usToMs;
|
import static androidx.media3.common.util.Util.usToMs;
|
||||||
|
|
||||||
import androidx.media3.common.AdPlaybackState;
|
import androidx.media3.common.AdPlaybackState;
|
||||||
@ -42,14 +43,14 @@ import java.util.Arrays;
|
|||||||
*
|
*
|
||||||
* <p>Periods are either of type content or ad as defined by the ad sequence pattern. A period is an
|
* <p>Periods are either of type content or ad as defined by the ad sequence pattern. A period is an
|
||||||
* ad if {@code adSequencePattern[id % adSequencePattern.length]} evaluates to true. Ad periods have
|
* ad if {@code adSequencePattern[id % adSequencePattern.length]} evaluates to true. Ad periods have
|
||||||
* a duration of {@link #AD_PERIOD_DURATION_US} and content periods have a duration of {@link
|
* a duration of {@link #AD_PERIOD_DURATION_MS} and content periods have a duration of {@link
|
||||||
* #PERIOD_DURATION_US}.
|
* #PERIOD_DURATION_MS}.
|
||||||
*/
|
*/
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class FakeMultiPeriodLiveTimeline extends Timeline {
|
public class FakeMultiPeriodLiveTimeline extends Timeline {
|
||||||
|
|
||||||
public static final long AD_PERIOD_DURATION_US = 10_000_000L;
|
public static final long AD_PERIOD_DURATION_MS = 10_000L;
|
||||||
public static final long PERIOD_DURATION_US = 30_000_000L;
|
public static final long PERIOD_DURATION_MS = 30_000L;
|
||||||
|
|
||||||
private final boolean[] adSequencePattern;
|
private final boolean[] adSequencePattern;
|
||||||
private final MediaItem mediaItem;
|
private final MediaItem mediaItem;
|
||||||
@ -58,6 +59,7 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
private final boolean isContentTimeline;
|
private final boolean isContentTimeline;
|
||||||
private final boolean populateAds;
|
private final boolean populateAds;
|
||||||
private final boolean playedAds;
|
private final boolean playedAds;
|
||||||
|
private final long[] periodDurationUsPattern;
|
||||||
|
|
||||||
private long nowUs;
|
private long nowUs;
|
||||||
private ImmutableList<PeriodData> periods;
|
private ImmutableList<PeriodData> periods;
|
||||||
@ -65,53 +67,55 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
/**
|
/**
|
||||||
* Creates an instance.
|
* Creates an instance.
|
||||||
*
|
*
|
||||||
* @param availabilityStartTimeUs The start time of the available time range, in UNIX epoch.
|
* @param availabilityStartTimeMs The start time of the available time range, UNIX epoch in
|
||||||
|
* milliseconds.
|
||||||
* @param liveWindowDurationUs The duration of the live window.
|
* @param liveWindowDurationUs The duration of the live window.
|
||||||
* @param nowUs The current time that determines the end of the live window.
|
* @param nowUs The current time that determines the end of the live window.
|
||||||
* @param adSequencePattern The repeating pattern of periods starting at {@code
|
* @param adSequencePattern The repeating pattern of periods starting at {@code
|
||||||
* availabilityStartTimeUs}. True is an ad period, and false a content period.
|
* availabilityStartTimeMs}. True is an ad period, and false a content period.
|
||||||
|
* @param periodDurationMsPattern The repeating pattern of periods durations starting at {@code
|
||||||
|
* availabilityStartTimeMs}, in milliseconds. Must have the same length as {@code
|
||||||
|
* adSequencePattern}.
|
||||||
* @param isContentTimeline Whether the timeline is a content timeline without {@link
|
* @param isContentTimeline Whether the timeline is a content timeline without {@link
|
||||||
* AdPlaybackState}s.
|
* AdPlaybackState}s.
|
||||||
* @param populateAds Whether to populate ads in the same way if an ad event has been received.
|
* @param populateAds Whether to populate ads in the same way if an ad event has been received.
|
||||||
* @param playedAds Whether ads should be marked as played if populated.
|
* @param playedAds Whether ads should be marked as played if populated.
|
||||||
*/
|
*/
|
||||||
public FakeMultiPeriodLiveTimeline(
|
public FakeMultiPeriodLiveTimeline(
|
||||||
long availabilityStartTimeUs,
|
long availabilityStartTimeMs,
|
||||||
long liveWindowDurationUs,
|
long liveWindowDurationUs,
|
||||||
long nowUs,
|
long nowUs,
|
||||||
boolean[] adSequencePattern,
|
boolean[] adSequencePattern,
|
||||||
|
long[] periodDurationMsPattern,
|
||||||
boolean isContentTimeline,
|
boolean isContentTimeline,
|
||||||
boolean populateAds,
|
boolean populateAds,
|
||||||
boolean playedAds) {
|
boolean playedAds) {
|
||||||
checkArgument(nowUs - liveWindowDurationUs >= availabilityStartTimeUs);
|
checkArgument(nowUs - liveWindowDurationUs >= msToUs(availabilityStartTimeMs));
|
||||||
this.availabilityStartTimeUs = availabilityStartTimeUs;
|
checkArgument(adSequencePattern.length == periodDurationMsPattern.length);
|
||||||
|
this.availabilityStartTimeUs = msToUs(availabilityStartTimeMs);
|
||||||
this.liveWindowDurationUs = liveWindowDurationUs;
|
this.liveWindowDurationUs = liveWindowDurationUs;
|
||||||
this.nowUs = nowUs;
|
this.nowUs = nowUs;
|
||||||
this.adSequencePattern = Arrays.copyOf(adSequencePattern, adSequencePattern.length);
|
this.adSequencePattern = Arrays.copyOf(adSequencePattern, adSequencePattern.length);
|
||||||
|
periodDurationUsPattern = new long[periodDurationMsPattern.length];
|
||||||
|
for (int i = 0; i < periodDurationMsPattern.length; i++) {
|
||||||
|
periodDurationUsPattern[i] = msToUs(periodDurationMsPattern[i]);
|
||||||
|
}
|
||||||
this.isContentTimeline = isContentTimeline;
|
this.isContentTimeline = isContentTimeline;
|
||||||
this.populateAds = populateAds;
|
this.populateAds = populateAds;
|
||||||
this.playedAds = playedAds;
|
this.playedAds = playedAds;
|
||||||
mediaItem = new MediaItem.Builder().build();
|
mediaItem = new MediaItem.Builder().build();
|
||||||
periods =
|
periods =
|
||||||
invalidate(
|
invalidate(
|
||||||
availabilityStartTimeUs,
|
msToUs(availabilityStartTimeMs),
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationUsPattern,
|
||||||
isContentTimeline,
|
isContentTimeline,
|
||||||
populateAds,
|
populateAds,
|
||||||
playedAds);
|
playedAds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculates the total duration of the given ad period sequence. */
|
|
||||||
public static long calculateAdSequencePatternDurationUs(boolean[] adSequencePattern) {
|
|
||||||
long durationUs = 0;
|
|
||||||
for (boolean isAd : adSequencePattern) {
|
|
||||||
durationUs += (isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US);
|
|
||||||
}
|
|
||||||
return durationUs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Advances the live window by the given duration, in microseconds. */
|
/** Advances the live window by the given duration, in microseconds. */
|
||||||
public void advanceNowUs(long durationUs) {
|
public void advanceNowUs(long durationUs) {
|
||||||
nowUs += durationUs;
|
nowUs += durationUs;
|
||||||
@ -121,11 +125,35 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationUsPattern,
|
||||||
isContentTimeline,
|
isContentTimeline,
|
||||||
populateAds,
|
populateAds,
|
||||||
playedAds);
|
playedAds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The window's start time in microseconds since the Unix epoch, or {@link C#TIME_UNSET} if
|
||||||
|
* unknown or not applicable.
|
||||||
|
*/
|
||||||
|
public long getWindowStartTimeUs() {
|
||||||
|
Window window = getWindow(/* windowIndex= */ 0, new Window());
|
||||||
|
// Revert us/ms truncation introduced in `getWindow()`. This is identical to the truncation
|
||||||
|
// applied in the Media3 `DashMediaSource.DashTimeline` and can be reverted in the same way.
|
||||||
|
return window.windowStartTimeMs != C.TIME_UNSET
|
||||||
|
? msToUs(window.windowStartTimeMs) + (window.positionInFirstPeriodUs % 1000)
|
||||||
|
: C.TIME_UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the period start time since Unix epoch, in microseconds.
|
||||||
|
*
|
||||||
|
* <p>Note: The returned value has millisecond precision only, so the trailing 3 digits are always
|
||||||
|
* zeros.
|
||||||
|
*/
|
||||||
|
public long getPeriodStartTimeUs(int periodIndex) {
|
||||||
|
return msToUs(periods.get(periodIndex).periodStartTimeMs);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getWindowCount() {
|
public int getWindowCount() {
|
||||||
return 1;
|
return 1;
|
||||||
@ -136,12 +164,13 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
checkArgument(windowIndex == 0);
|
checkArgument(windowIndex == 0);
|
||||||
MediaItem.LiveConfiguration liveConfiguration =
|
MediaItem.LiveConfiguration liveConfiguration =
|
||||||
new MediaItem.LiveConfiguration.Builder().build();
|
new MediaItem.LiveConfiguration.Builder().build();
|
||||||
|
long positionInFirstPeriodUs = -periods.get(0).positionInWindowUs;
|
||||||
window.set(
|
window.set(
|
||||||
/* uid= */ "live-window",
|
/* uid= */ "live-window",
|
||||||
mediaItem,
|
mediaItem,
|
||||||
/* manifest= */ null,
|
/* manifest= */ null,
|
||||||
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
/* presentationStartTimeMs= */ C.TIME_UNSET,
|
||||||
/* windowStartTimeMs= */ usToMs(nowUs - liveWindowDurationUs),
|
/* windowStartTimeMs= */ periods.get(0).periodStartTimeMs + usToMs(positionInFirstPeriodUs),
|
||||||
/* elapsedRealtimeEpochOffsetMs= */ 0,
|
/* elapsedRealtimeEpochOffsetMs= */ 0,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ true,
|
/* isDynamic= */ true,
|
||||||
@ -150,7 +179,7 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
/* durationUs= */ liveWindowDurationUs,
|
/* durationUs= */ liveWindowDurationUs,
|
||||||
/* firstPeriodIndex= */ 0,
|
/* firstPeriodIndex= */ 0,
|
||||||
/* lastPeriodIndex= */ getPeriodCount() - 1,
|
/* lastPeriodIndex= */ getPeriodCount() - 1,
|
||||||
/* positionInFirstPeriodUs= */ -periods.get(0).positionInWindowUs);
|
positionInFirstPeriodUs);
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,24 +222,23 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
long liveWindowDurationUs,
|
long liveWindowDurationUs,
|
||||||
long now,
|
long now,
|
||||||
boolean[] adSequencePattern,
|
boolean[] adSequencePattern,
|
||||||
|
long[] periodDurationUsPattern,
|
||||||
boolean isContentTimeline,
|
boolean isContentTimeline,
|
||||||
boolean populateAds,
|
boolean populateAds,
|
||||||
boolean playedAds) {
|
boolean playedAds) {
|
||||||
long windowStartTimeUs = now - liveWindowDurationUs;
|
long windowStartTimeUs = now - liveWindowDurationUs;
|
||||||
int sequencePeriodCount = adSequencePattern.length;
|
int sequencePeriodCount = adSequencePattern.length;
|
||||||
long sequenceDurationUs = calculateAdSequencePatternDurationUs(adSequencePattern);
|
long sequenceDurationUs = sum(periodDurationUsPattern);
|
||||||
long skippedSequenceCount = (windowStartTimeUs - availabilityStartTimeUs) / sequenceDurationUs;
|
long skippedSequenceCount = (windowStartTimeUs - availabilityStartTimeUs) / sequenceDurationUs;
|
||||||
// Search the first period of the live window.
|
// Search the first period of the live window.
|
||||||
int firstPeriodIndex = (int) (skippedSequenceCount * sequencePeriodCount);
|
int firstPeriodIndex = (int) (skippedSequenceCount * sequencePeriodCount);
|
||||||
boolean isAd = adSequencePattern[firstPeriodIndex % sequencePeriodCount];
|
long firstPeriodDurationUs = periodDurationUsPattern[firstPeriodIndex % sequencePeriodCount];
|
||||||
long firstPeriodDurationUs = isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
|
||||||
long firstPeriodEndTimeUs =
|
long firstPeriodEndTimeUs =
|
||||||
availabilityStartTimeUs
|
availabilityStartTimeUs
|
||||||
+ (sequenceDurationUs * skippedSequenceCount)
|
+ (sequenceDurationUs * skippedSequenceCount)
|
||||||
+ firstPeriodDurationUs;
|
+ firstPeriodDurationUs;
|
||||||
while (firstPeriodEndTimeUs <= windowStartTimeUs) {
|
while (firstPeriodEndTimeUs <= windowStartTimeUs) {
|
||||||
isAd = adSequencePattern[++firstPeriodIndex % sequencePeriodCount];
|
firstPeriodDurationUs = periodDurationUsPattern[++firstPeriodIndex % sequencePeriodCount];
|
||||||
firstPeriodDurationUs = isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
|
||||||
firstPeriodEndTimeUs += firstPeriodDurationUs;
|
firstPeriodEndTimeUs += firstPeriodDurationUs;
|
||||||
}
|
}
|
||||||
ImmutableList.Builder<PeriodData> liveWindow = new ImmutableList.Builder<>();
|
ImmutableList.Builder<PeriodData> liveWindow = new ImmutableList.Builder<>();
|
||||||
@ -218,8 +246,8 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
int lastPeriodIndex = firstPeriodIndex;
|
int lastPeriodIndex = firstPeriodIndex;
|
||||||
// Add periods to the window from the first period until we find a period start after `now`.
|
// Add periods to the window from the first period until we find a period start after `now`.
|
||||||
while (lastPeriodStartTimeUs < now) {
|
while (lastPeriodStartTimeUs < now) {
|
||||||
isAd = adSequencePattern[lastPeriodIndex % sequencePeriodCount];
|
long periodDurationUs = periodDurationUsPattern[lastPeriodIndex % sequencePeriodCount];
|
||||||
long periodDurationUs = isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
boolean isAd = adSequencePattern[lastPeriodIndex % sequencePeriodCount];
|
||||||
AdPlaybackState adPlaybackState = AdPlaybackState.NONE;
|
AdPlaybackState adPlaybackState = AdPlaybackState.NONE;
|
||||||
if (!isContentTimeline) {
|
if (!isContentTimeline) {
|
||||||
adPlaybackState = new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended();
|
adPlaybackState = new AdPlaybackState("adsId").withLivePostrollPlaceholderAppended();
|
||||||
@ -244,6 +272,7 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
/* id= */ lastPeriodIndex++,
|
/* id= */ lastPeriodIndex++,
|
||||||
periodDurationUs,
|
periodDurationUs,
|
||||||
/* positionInWindowUs= */ lastPeriodStartTimeUs - windowStartTimeUs,
|
/* positionInWindowUs= */ lastPeriodStartTimeUs - windowStartTimeUs,
|
||||||
|
/* periodStartTimeMs= */ usToMs(lastPeriodStartTimeUs),
|
||||||
isAd,
|
isAd,
|
||||||
adPlaybackState));
|
adPlaybackState));
|
||||||
lastPeriodStartTimeUs += periodDurationUs;
|
lastPeriodStartTimeUs += periodDurationUs;
|
||||||
@ -257,6 +286,7 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
private final Object uid;
|
private final Object uid;
|
||||||
private final long durationUs;
|
private final long durationUs;
|
||||||
private final long positionInWindowUs;
|
private final long positionInWindowUs;
|
||||||
|
private final long periodStartTimeMs;
|
||||||
private final AdPlaybackState adPlaybackState;
|
private final AdPlaybackState adPlaybackState;
|
||||||
|
|
||||||
/** Creates an instance. */
|
/** Creates an instance. */
|
||||||
@ -264,9 +294,11 @@ public class FakeMultiPeriodLiveTimeline extends Timeline {
|
|||||||
int id,
|
int id,
|
||||||
long durationUs,
|
long durationUs,
|
||||||
long positionInWindowUs,
|
long positionInWindowUs,
|
||||||
|
long periodStartTimeMs,
|
||||||
boolean isAd,
|
boolean isAd,
|
||||||
AdPlaybackState adPlaybackState) {
|
AdPlaybackState adPlaybackState) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
this.periodStartTimeMs = periodStartTimeMs;
|
||||||
this.uid = "uid-" + id + "[" + (isAd ? "a" : "c") + "]";
|
this.uid = "uid-" + id + "[" + (isAd ? "a" : "c") + "]";
|
||||||
this.durationUs = durationUs;
|
this.durationUs = durationUs;
|
||||||
this.positionInWindowUs = positionInWindowUs;
|
this.positionInWindowUs = positionInWindowUs;
|
||||||
|
@ -15,14 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.test.utils;
|
package androidx.media3.test.utils;
|
||||||
|
|
||||||
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_US;
|
import static androidx.media3.common.util.Util.msToUs;
|
||||||
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.PERIOD_DURATION_US;
|
import static androidx.media3.common.util.Util.sum;
|
||||||
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.calculateAdSequencePatternDurationUs;
|
import static androidx.media3.common.util.Util.usToMs;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.AD_PERIOD_DURATION_MS;
|
||||||
|
import static androidx.media3.test.utils.FakeMultiPeriodLiveTimeline.PERIOD_DURATION_MS;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.util.Util;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -36,12 +37,16 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
@Test
|
@Test
|
||||||
public void newInstance_availabilitySinceStartOfUnixEpoch_correctLiveWindow() {
|
public void newInstance_availabilitySinceStartOfUnixEpoch_correctLiveWindow() {
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_000L,
|
/* nowUs= */ 60_000_000L,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -63,22 +68,28 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_000L,
|
/* nowUs= */ 60_000_000L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newInstance_timelineWithAdsPopulated_correctPlaybackStates() {
|
public void newInstance_timelineWithAdsPopulated_correctPlaybackStates() {
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 50_000_000L,
|
/* liveWindowDurationUs= */ 50_000_000L,
|
||||||
/* nowUs= */ 100_000_000L,
|
/* nowUs= */ 100_000_000L,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ true,
|
/* populateAds= */ true,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -123,22 +134,28 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 50_000_000L,
|
/* liveWindowDurationUs= */ 50_000_000L,
|
||||||
/* nowUs= */ 100_000_000L,
|
/* nowUs= */ 100_000_000L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newInstance_timelineWithAdsNotPopulated_correctPlaybackStates() {
|
public void newInstance_timelineWithAdsNotPopulated_correctPlaybackStates() {
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 50_000_000L,
|
/* liveWindowDurationUs= */ 50_000_000L,
|
||||||
/* nowUs= */ 100_000_000L,
|
/* nowUs= */ 100_000_000L,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ false,
|
/* isContentTimeline= */ false,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -175,22 +192,28 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 50_000_000L,
|
/* liveWindowDurationUs= */ 50_000_000L,
|
||||||
/* nowUs= */ 100_000_000L,
|
/* nowUs= */ 100_000_000L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void advanceTimeUs_availabilitySinceStartOfUnixEpoch_correctPeriodsInLiveWindow() {
|
public void advanceTimeUs_availabilitySinceStartOfUnixEpoch_correctPeriodsInLiveWindow() {
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_123L,
|
/* nowUs= */ 60_000_123L,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -209,11 +232,13 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_123L,
|
/* nowUs= */ 60_000_123L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
|
|
||||||
// Advance nowUs so that the window ends just 1us before the next period moves into the window.
|
// Advance nowUs so that the window ends just 1us before the next period moves into the window.
|
||||||
timeline.advanceNowUs(19999877L);
|
timeline.advanceNowUs(19999877L);
|
||||||
@ -231,11 +256,13 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_123L + 19999877L,
|
/* nowUs= */ 60_000_123L + 19999877L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
|
|
||||||
// Advance the window by 1us to add the next period at the end of the window.
|
// Advance the window by 1us to add the next period at the end of the window.
|
||||||
timeline.advanceNowUs(1L);
|
timeline.advanceNowUs(1L);
|
||||||
@ -254,110 +281,159 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 60_000_000L,
|
/* liveWindowDurationUs= */ 60_000_000L,
|
||||||
/* nowUs= */ 60_000_123L + 19999878L,
|
/* nowUs= */ 60_000_123L + 19999878L,
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newInstance_advancedAvailabilityStartTime_correctlyInterpolatedPeriodIds() {
|
public void newInstance_advancedAvailabilityStartTime_correctlyInterpolatedPeriodIds() {
|
||||||
Timeline.Period period = new Timeline.Period();
|
Timeline.Period period = new Timeline.Period();
|
||||||
long availabilityStartTimeUs = 0;
|
long availabilityStartTimeMs = 0;
|
||||||
long nowUs = 120_000_123;
|
long nowUs = 120_000_123;
|
||||||
long liveWindowDurationUs = 60_000_987L;
|
long liveWindowDurationUs = 60_000_987L;
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
long sequenceDurationUs = calculateAdSequencePatternDurationUs(adSequencePattern);
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
|
long sequenceDurationUs = 50_000_000L;
|
||||||
|
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
availabilityStartTimeUs,
|
availabilityStartTimeMs,
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ true);
|
/* playedAds= */ true);
|
||||||
|
|
||||||
assertThat(timeline.getWindow(0, new Timeline.Window()).windowStartTimeMs)
|
|
||||||
.isEqualTo(Util.usToMs(nowUs - liveWindowDurationUs));
|
|
||||||
assertThat(timeline.getPeriodCount()).isEqualTo(4);
|
assertThat(timeline.getPeriodCount()).isEqualTo(4);
|
||||||
|
long windowStartTimeUs = timeline.getWindowStartTimeUs();
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 0, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 0));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).id).isEqualTo(3);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).id).isEqualTo(3);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).uid).isEqualTo("uid-3[c]");
|
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).uid).isEqualTo("uid-3[c]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 1, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 1));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).id).isEqualTo(4);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).id).isEqualTo(4);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).uid).isEqualTo("uid-4[a]");
|
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).uid).isEqualTo("uid-4[a]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 2, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 2));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).id).isEqualTo(5);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).id).isEqualTo(5);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).uid).isEqualTo("uid-5[a]");
|
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).uid).isEqualTo("uid-5[a]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 3, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 3));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).id).isEqualTo(6);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).id).isEqualTo(6);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).uid).isEqualTo("uid-6[c]");
|
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).uid).isEqualTo("uid-6[c]");
|
||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
availabilityStartTimeUs, liveWindowDurationUs, nowUs, adSequencePattern),
|
availabilityStartTimeMs,
|
||||||
adSequencePattern);
|
liveWindowDurationUs,
|
||||||
|
nowUs,
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
|
|
||||||
timeline.advanceNowUs(sequenceDurationUs * 13);
|
timeline.advanceNowUs(sequenceDurationUs * 13);
|
||||||
|
windowStartTimeUs = timeline.getWindowStartTimeUs();
|
||||||
assertThat(timeline.getWindow(0, new Timeline.Window()).windowStartTimeMs)
|
assertThat(
|
||||||
.isEqualTo(Util.usToMs((nowUs + sequenceDurationUs * 13) - liveWindowDurationUs));
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 0, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 0));
|
||||||
assertThat(timeline.getPeriodCount()).isEqualTo(4);
|
assertThat(timeline.getPeriodCount()).isEqualTo(4);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).id).isEqualTo((13 * 3) + 3);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).id).isEqualTo((13 * 3) + 3);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).uid)
|
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period).uid)
|
||||||
.isEqualTo("uid-" + ((13 * 3) + 3) + "[c]");
|
.isEqualTo("uid-" + ((13 * 3) + 3) + "[c]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 1, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 1));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).id).isEqualTo((13 * 3) + 4);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).id).isEqualTo((13 * 3) + 4);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).uid)
|
assertThat(timeline.getPeriod(/* periodIndex= */ 1, period).uid)
|
||||||
.isEqualTo("uid-" + ((13 * 3) + 4) + "[a]");
|
.isEqualTo("uid-" + ((13 * 3) + 4) + "[a]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 2, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 2));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).id).isEqualTo((13 * 3) + 5);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).id).isEqualTo((13 * 3) + 5);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).uid)
|
assertThat(timeline.getPeriod(/* periodIndex= */ 2, period).uid)
|
||||||
.isEqualTo("uid-" + ((13 * 3) + 5) + "[a]");
|
.isEqualTo("uid-" + ((13 * 3) + 5) + "[a]");
|
||||||
|
assertThat(
|
||||||
|
windowStartTimeUs + timeline.getPeriod(/* periodIndex= */ 3, period).positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ 3));
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).id).isEqualTo((13 * 3) + 6);
|
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).id).isEqualTo((13 * 3) + 6);
|
||||||
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).uid)
|
assertThat(timeline.getPeriod(/* periodIndex= */ 3, period).uid)
|
||||||
.isEqualTo("uid-" + ((13 * 3) + 6) + "[c]");
|
.isEqualTo("uid-" + ((13 * 3) + 6) + "[c]");
|
||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
availabilityStartTimeUs,
|
availabilityStartTimeMs,
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
(nowUs + sequenceDurationUs * 13),
|
(nowUs + sequenceDurationUs * 13),
|
||||||
adSequencePattern),
|
adSequencePattern,
|
||||||
adSequencePattern);
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newInstance_availabilitySinceAWeekAfterStartOfUnixEpoch_correctLiveWindow() {
|
public void newInstance_availabilitySinceAWeekAfterStartOfUnixEpoch_correctLiveWindow() {
|
||||||
long availabilityStartTimeUs = 7 * A_DAY_US;
|
long availabilityStartTimeMs = usToMs(7 * A_DAY_US);
|
||||||
long nowUs = 18 * A_DAY_US + 135_000_000;
|
long nowUs = 18 * A_DAY_US + 135_000_000;
|
||||||
long liveWindowDurationUs = 60_000_000L;
|
long liveWindowDurationUs = 60_000_000L;
|
||||||
boolean[] adSequencePattern = {false, true, true};
|
boolean[] adSequencePattern = {false, true, true};
|
||||||
|
long[] periodDurationMsPattern = {
|
||||||
|
PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS, AD_PERIOD_DURATION_MS
|
||||||
|
};
|
||||||
|
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
availabilityStartTimeUs,
|
availabilityStartTimeMs,
|
||||||
liveWindowDurationUs,
|
liveWindowDurationUs,
|
||||||
nowUs,
|
nowUs,
|
||||||
adSequencePattern,
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
|
|
||||||
assertThat(timeline.getWindow(0, new Timeline.Window()).windowStartTimeMs)
|
assertThat(timeline.getWindow(0, new Timeline.Window()).windowStartTimeMs)
|
||||||
.isEqualTo(Util.usToMs(nowUs - liveWindowDurationUs));
|
.isEqualTo(usToMs(nowUs - liveWindowDurationUs));
|
||||||
assertExpectedWindow(
|
assertExpectedWindow(
|
||||||
timeline,
|
timeline,
|
||||||
calculateExpectedWindow(
|
calculateExpectedWindow(
|
||||||
availabilityStartTimeUs, liveWindowDurationUs, nowUs, adSequencePattern),
|
availabilityStartTimeMs,
|
||||||
adSequencePattern);
|
liveWindowDurationUs,
|
||||||
|
nowUs,
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern),
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void newInstance_adSequencePattern_correctPeriodTypesFromStartOfAvailability() {
|
public void newInstance_adSequencePattern_correctPeriodTypesFromStartOfAvailability() {
|
||||||
FakeMultiPeriodLiveTimeline timeline =
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 120_000_000L,
|
/* liveWindowDurationUs= */ 120_000_000L,
|
||||||
/* nowUs= */ 120_000_000L,
|
/* nowUs= */ 120_000_000L,
|
||||||
new boolean[] {false, true, true, true},
|
new boolean[] {false, true, true, true},
|
||||||
|
new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -392,10 +468,17 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
|
|
||||||
timeline =
|
timeline =
|
||||||
new FakeMultiPeriodLiveTimeline(
|
new FakeMultiPeriodLiveTimeline(
|
||||||
/* availabilityStartTimeUs= */ 0L,
|
/* availabilityStartTimeMs= */ 0L,
|
||||||
/* liveWindowDurationUs= */ 220_000_000L,
|
/* liveWindowDurationUs= */ 220_000_000L,
|
||||||
/* nowUs= */ 250_000_000L,
|
/* nowUs= */ 250_000_000L,
|
||||||
new boolean[] {false, true, false, true, false},
|
new boolean[] {false, true, false, true, false},
|
||||||
|
new long[] {
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
PERIOD_DURATION_MS,
|
||||||
|
AD_PERIOD_DURATION_MS,
|
||||||
|
PERIOD_DURATION_MS
|
||||||
|
},
|
||||||
/* isContentTimeline= */ true,
|
/* isContentTimeline= */ true,
|
||||||
/* populateAds= */ false,
|
/* populateAds= */ false,
|
||||||
/* playedAds= */ false);
|
/* playedAds= */ false);
|
||||||
@ -415,22 +498,62 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
assertThat(timeline.getPeriod(9, period).uid).isEqualTo("uid-10[c]");
|
assertThat(timeline.getPeriod(9, period).uid).isEqualTo("uid-10[c]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void advanceNowUs_calculatePeriodStartTimeUsFromWindowStartMs_correctPeriodStartTimeUs() {
|
||||||
|
long[] periodDurationMsPattern = {1, 7, 5, 3};
|
||||||
|
boolean[] adSequencePattern = {false, true, true, true};
|
||||||
|
long liveWindowDurationUs = 15_243L;
|
||||||
|
long nowUs = 29_000_123L;
|
||||||
|
long availabilityStartTimeMs = 1L;
|
||||||
|
FakeMultiPeriodLiveTimeline timeline =
|
||||||
|
new FakeMultiPeriodLiveTimeline(
|
||||||
|
availabilityStartTimeMs,
|
||||||
|
liveWindowDurationUs,
|
||||||
|
nowUs,
|
||||||
|
adSequencePattern,
|
||||||
|
periodDurationMsPattern,
|
||||||
|
/* isContentTimeline= */ true,
|
||||||
|
/* populateAds= */ false,
|
||||||
|
/* playedAds= */ false);
|
||||||
|
Timeline.Window window = new Timeline.Window();
|
||||||
|
Timeline.Period period = new Timeline.Period();
|
||||||
|
|
||||||
|
for (long i = 0; i < 50_000L; i++) {
|
||||||
|
timeline.getWindow(/* windowIndex= */ 0, window);
|
||||||
|
// Assert the DashMediaSource specific truncation can be reverted to calculate the period
|
||||||
|
// start time (See `FakeMultiPeriodLiveTimeline.getWindowStartImeUs()` also).
|
||||||
|
long windowStartTimeUs =
|
||||||
|
msToUs(window.windowStartTimeMs) + (window.positionInFirstPeriodUs % 1000);
|
||||||
|
for (int j = window.firstPeriodIndex; j <= window.lastPeriodIndex; j++) {
|
||||||
|
timeline.getPeriod(/* periodIndex= */ j, period);
|
||||||
|
assertThat(windowStartTimeUs + period.positionInWindowUs)
|
||||||
|
.isEqualTo(timeline.getPeriodStartTimeUs(/* periodIndex= */ j));
|
||||||
|
}
|
||||||
|
timeline.advanceNowUs(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ExpectedWindow calculateExpectedWindow(
|
private ExpectedWindow calculateExpectedWindow(
|
||||||
long availabilityStartTimeUs,
|
long availabilityStartTimeMs,
|
||||||
long liveWindowDurationUs,
|
long liveWindowDurationUs,
|
||||||
long nowUs,
|
long nowUs,
|
||||||
boolean[] adSequencePattern) {
|
boolean[] adSequencePattern,
|
||||||
|
long[] periodDurationMsPattern) {
|
||||||
|
long[] periodDurationUsPattern = new long[periodDurationMsPattern.length];
|
||||||
|
for (int i = 0; i < periodDurationMsPattern.length; i++) {
|
||||||
|
periodDurationUsPattern[i] = msToUs(periodDurationMsPattern[i]);
|
||||||
|
}
|
||||||
long windowStartTimeUs = nowUs - liveWindowDurationUs;
|
long windowStartTimeUs = nowUs - liveWindowDurationUs;
|
||||||
long sequenceDurationUs = calculateAdSequencePatternDurationUs(adSequencePattern);
|
long sequenceDurationUs = sum(periodDurationUsPattern);
|
||||||
long durationBeforeWindowStartUs = windowStartTimeUs - availabilityStartTimeUs;
|
long durationBeforeWindowStartUs = windowStartTimeUs - msToUs(availabilityStartTimeMs);
|
||||||
long skippedSequenceCount = durationBeforeWindowStartUs / sequenceDurationUs;
|
long skippedSequenceCount = durationBeforeWindowStartUs / sequenceDurationUs;
|
||||||
long remainingDurationBeforeWindowUs = durationBeforeWindowStartUs % sequenceDurationUs;
|
long remainingDurationBeforeWindowUs = durationBeforeWindowStartUs % sequenceDurationUs;
|
||||||
int idOfFirstPeriodInWindow = (int) (skippedSequenceCount * adSequencePattern.length);
|
int idOfFirstPeriodInWindow = (int) (skippedSequenceCount * adSequencePattern.length);
|
||||||
long lastSkippedPeriodDurationUs = 0L;
|
long lastSkippedPeriodDurationUs = 0L;
|
||||||
// Skip period by period until we reach the window start.
|
// Skip period by period until we reach the window start.
|
||||||
while (remainingDurationBeforeWindowUs > 0) {
|
while (remainingDurationBeforeWindowUs > 0) {
|
||||||
boolean isAd = adSequencePattern[idOfFirstPeriodInWindow++ % adSequencePattern.length];
|
lastSkippedPeriodDurationUs =
|
||||||
lastSkippedPeriodDurationUs = isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
periodDurationUsPattern[idOfFirstPeriodInWindow++ % adSequencePattern.length];
|
||||||
remainingDurationBeforeWindowUs -= lastSkippedPeriodDurationUs;
|
remainingDurationBeforeWindowUs -= lastSkippedPeriodDurationUs;
|
||||||
}
|
}
|
||||||
long positionOfFirstPeriodInWindowUs = 0;
|
long positionOfFirstPeriodInWindowUs = 0;
|
||||||
@ -442,24 +565,29 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
-(lastSkippedPeriodDurationUs + remainingDurationBeforeWindowUs);
|
-(lastSkippedPeriodDurationUs + remainingDurationBeforeWindowUs);
|
||||||
}
|
}
|
||||||
long durationOfFirstPeriodInWindowUs =
|
long durationOfFirstPeriodInWindowUs =
|
||||||
adSequencePattern[idOfFirstPeriodInWindow % adSequencePattern.length]
|
periodDurationUsPattern[idOfFirstPeriodInWindow % adSequencePattern.length];
|
||||||
? AD_PERIOD_DURATION_US
|
|
||||||
: PERIOD_DURATION_US;
|
|
||||||
long durationInWindowUs =
|
long durationInWindowUs =
|
||||||
remainingDurationBeforeWindowUs == 0
|
remainingDurationBeforeWindowUs == 0
|
||||||
? durationOfFirstPeriodInWindowUs
|
? durationOfFirstPeriodInWindowUs
|
||||||
: -remainingDurationBeforeWindowUs;
|
: -remainingDurationBeforeWindowUs;
|
||||||
int idOfLastPeriodInWindow = idOfFirstPeriodInWindow;
|
int idOfLastPeriodInWindow = idOfFirstPeriodInWindow;
|
||||||
while (durationInWindowUs < liveWindowDurationUs) {
|
while (durationInWindowUs < liveWindowDurationUs) {
|
||||||
boolean isAd = adSequencePattern[++idOfLastPeriodInWindow % adSequencePattern.length];
|
durationInWindowUs +=
|
||||||
durationInWindowUs += isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
periodDurationUsPattern[++idOfLastPeriodInWindow % adSequencePattern.length];
|
||||||
}
|
}
|
||||||
return new ExpectedWindow(
|
return new ExpectedWindow(
|
||||||
idOfFirstPeriodInWindow, idOfLastPeriodInWindow, positionOfFirstPeriodInWindowUs);
|
idOfFirstPeriodInWindow, idOfLastPeriodInWindow, positionOfFirstPeriodInWindowUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertExpectedWindow(
|
private void assertExpectedWindow(
|
||||||
Timeline timeline, ExpectedWindow expectedWindow, boolean[] adSequencePattern) {
|
Timeline timeline,
|
||||||
|
ExpectedWindow expectedWindow,
|
||||||
|
boolean[] adSequencePattern,
|
||||||
|
long[] periodDurationMsPattern) {
|
||||||
|
long[] periodDurationUsPattern = new long[periodDurationMsPattern.length];
|
||||||
|
for (int i = 0; i < periodDurationMsPattern.length; i++) {
|
||||||
|
periodDurationUsPattern[i] = msToUs(periodDurationMsPattern[i]);
|
||||||
|
}
|
||||||
Timeline.Period period = new Timeline.Period();
|
Timeline.Period period = new Timeline.Period();
|
||||||
assertThat(timeline.getPeriodCount())
|
assertThat(timeline.getPeriodCount())
|
||||||
.isEqualTo(expectedWindow.idOfLastPeriod - expectedWindow.idOfFirstPeriod + 1);
|
.isEqualTo(expectedWindow.idOfLastPeriod - expectedWindow.idOfFirstPeriod + 1);
|
||||||
@ -467,11 +595,12 @@ public class FakeMultiPeriodLiveTimelineTest {
|
|||||||
for (int i = 0; i < timeline.getPeriodCount(); i++) {
|
for (int i = 0; i < timeline.getPeriodCount(); i++) {
|
||||||
int id = expectedWindow.idOfFirstPeriod + i;
|
int id = expectedWindow.idOfFirstPeriod + i;
|
||||||
boolean isAd = adSequencePattern[id % adSequencePattern.length];
|
boolean isAd = adSequencePattern[id % adSequencePattern.length];
|
||||||
|
long durationUs = periodDurationUsPattern[id % periodDurationUsPattern.length];
|
||||||
assertThat(timeline.getPeriod(i, period).id).isEqualTo(id);
|
assertThat(timeline.getPeriod(i, period).id).isEqualTo(id);
|
||||||
assertThat(timeline.getPeriod(i, period).uid)
|
assertThat(timeline.getPeriod(i, period).uid)
|
||||||
.isEqualTo("uid-" + id + "[" + (isAd ? "a" : "c") + "]");
|
.isEqualTo("uid-" + id + "[" + (isAd ? "a" : "c") + "]");
|
||||||
assertThat(timeline.getPeriod(i, period).positionInWindowUs).isEqualTo(positionInWindowUs);
|
assertThat(timeline.getPeriod(i, period).positionInWindowUs).isEqualTo(positionInWindowUs);
|
||||||
positionInWindowUs += isAd ? AD_PERIOD_DURATION_US : PERIOD_DURATION_US;
|
positionInWindowUs += durationUs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user