diff --git a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java index 9751a61168..af97386ee8 100644 --- a/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java +++ b/extensions/ima/src/test/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoaderTest.java @@ -39,6 +39,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Timeline; +import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.source.ads.AdsLoader; import com.google.android.exoplayer2.source.ads.AdsMediaSource.AdLoadException; @@ -67,6 +68,8 @@ public class ImaAdsLoaderTest { new FakeTimeline( new TimelineWindowDefinition( /* isSeekable= */ true, /* isDynamic= */ false, CONTENT_DURATION_US)); + private static final long CONTENT_PERIOD_DURATION_US = + CONTENT_TIMELINE.getPeriod(/* periodIndex= */ 0, new Period()).durationUs; private static final Uri TEST_URI = Uri.EMPTY; private static final long TEST_AD_DURATION_US = 5 * C.MICROS_PER_SECOND; private static final long[][] PREROLL_ADS_DURATIONS_US = new long[][] {{TEST_AD_DURATION_US}}; @@ -147,7 +150,7 @@ public class ImaAdsLoaderTest { .isEqualTo( new AdPlaybackState(/* adGroupTimesUs...= */ 0) .withAdDurationsUs(PREROLL_ADS_DURATIONS_US) - .withContentDurationUs(CONTENT_DURATION_US)); + .withContentDurationUs(CONTENT_PERIOD_DURATION_US)); } @Test @@ -216,7 +219,7 @@ public class ImaAdsLoaderTest { assertThat(adsLoaderListener.adPlaybackState) .isEqualTo( new AdPlaybackState(/* adGroupTimesUs...= */ 0) - .withContentDurationUs(CONTENT_DURATION_US) + .withContentDurationUs(CONTENT_PERIOD_DURATION_US) .withAdCount(/* adGroupIndex= */ 0, /* adCount= */ 1) .withAdUri(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, /* uri= */ TEST_URI) .withAdDurationsUs(PREROLL_ADS_DURATIONS_US) diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java index 527b30bdeb..1be3e2f7fe 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -459,7 +459,9 @@ public final class ExoPlayerTest { public void adGroupWithLoadErrorIsSkipped() throws Exception { AdPlaybackState initialAdPlaybackState = FakeTimeline.createAdPlaybackState( - /* adsPerAdGroup= */ 1, /* adGroupTimesUs=... */ 5 * C.MICROS_PER_SECOND); + /* adsPerAdGroup= */ 1, /* adGroupTimesUs=... */ + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US + + 5 * C.MICROS_PER_SECOND); Timeline fakeTimeline = new FakeTimeline( new TimelineWindowDefinition( @@ -702,7 +704,8 @@ public final class ExoPlayerTest { EventDispatcher eventDispatcher, @Nullable TransferListener transferListener) { FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher); - mediaPeriod.setDiscontinuityPositionUs(0); + mediaPeriod.setDiscontinuityPositionUs( + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US); return mediaPeriod; } }; @@ -3064,6 +3067,7 @@ public final class ExoPlayerTest { /* isPlaceholder= */ false, /* durationUs= */ 10_000_000, /* defaultPositionUs= */ 5_000_000, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, adPlaybackState)); FakeMediaSource fakeMediaSource = new FakeMediaSource(/* timeline= */ null); AtomicReference playerReference = new AtomicReference<>(); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java index d45bc801fa..eb4f046e9b 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/MediaPeriodQueueTest.java @@ -231,7 +231,8 @@ public final class MediaPeriodQueueTest { /* startPositionUs= */ 0, /* requestedContentPositionUs= */ C.TIME_UNSET, /* endPositionUs= */ C.TIME_UNSET, - /* durationUs= */ CONTENT_DURATION_US, + /* durationUs= */ CONTENT_DURATION_US + + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, /* isLastInPeriod= */ true, /* isLastInWindow= */ false, /* nextAdGroupIndex= */ C.INDEX_UNSET); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java index 4593e0a261..0e31e473fc 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/AnalyticsCollectorTest.java @@ -762,7 +762,8 @@ public final class AnalyticsCollectorTest { FakeTimeline.createAdPlaybackState( /* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */ 0, - 5 * C.MICROS_PER_SECOND, + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US + + 5 * C.MICROS_PER_SECOND, C.TIME_END_OF_SOURCE)); AtomicInteger playedAdCount = new AtomicInteger(0); Timeline adTimeline = @@ -997,7 +998,9 @@ public final class AnalyticsCollectorTest { /* isDynamic= */ false, 10 * C.MICROS_PER_SECOND, FakeTimeline.createAdPlaybackState( - /* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */ 5 * C.MICROS_PER_SECOND))); + /* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */ + TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US + + 5 * C.MICROS_PER_SECOND))); FakeMediaSource fakeMediaSource = new FakeMediaSource(adTimeline, ExoPlayerTestRunner.Builder.VIDEO_FORMAT); ActionSchedule actionSchedule = diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java index 628d7b191d..19d172d0be 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeTimeline.java @@ -32,9 +32,13 @@ public final class FakeTimeline extends Timeline { */ public static final class TimelineWindowDefinition { - /** Default test window duration in microseconds. */ + /** Default window duration in microseconds. */ public static final long DEFAULT_WINDOW_DURATION_US = 10 * C.MICROS_PER_SECOND; + /** Default offset of a window in its first period in microseconds. */ + public static final long DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US = + 10_000 * C.MICROS_PER_SECOND; + public final int periodCount; public final Object id; public final boolean isSeekable; @@ -43,6 +47,7 @@ public final class FakeTimeline extends Timeline { public final boolean isPlaceholder; public final long durationUs; public final long defaultPositionUs; + public final long windowOffsetInFirstPeriodUs; public final AdPlaybackState adPlaybackState; /** @@ -61,6 +66,7 @@ public final class FakeTimeline extends Timeline { /* isPlaceholder= */ true, /* durationUs= */ C.TIME_UNSET, /* defaultPositionUs= */ 0, + /* windowOffsetInFirstPeriodUs= */ 0, AdPlaybackState.NONE); } @@ -129,6 +135,7 @@ public final class FakeTimeline extends Timeline { /* isPlaceholder= */ false, durationUs, /* defaultPositionUs= */ 0, + DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, adPlaybackState); } @@ -144,6 +151,8 @@ public final class FakeTimeline extends Timeline { * @param isPlaceholder Whether the window is a placeholder. * @param durationUs The duration of the window in microseconds. * @param defaultPositionUs The default position of the window in microseconds. + * @param windowOffsetInFirstPeriodUs The offset of the window in the first period, in + * microseconds. * @param adPlaybackState The ad playback state. */ public TimelineWindowDefinition( @@ -155,7 +164,9 @@ public final class FakeTimeline extends Timeline { boolean isPlaceholder, long durationUs, long defaultPositionUs, + long windowOffsetInFirstPeriodUs, AdPlaybackState adPlaybackState) { + Assertions.checkArgument(durationUs != C.TIME_UNSET || periodCount == 1); this.periodCount = periodCount; this.id = id; this.isSeekable = isSeekable; @@ -164,6 +175,7 @@ public final class FakeTimeline extends Timeline { this.isPlaceholder = isPlaceholder; this.durationUs = durationUs; this.defaultPositionUs = defaultPositionUs; + this.windowOffsetInFirstPeriodUs = windowOffsetInFirstPeriodUs; this.adPlaybackState = adPlaybackState; } } @@ -262,7 +274,7 @@ public final class FakeTimeline extends Timeline { windowDefinition.durationUs, periodOffsets[windowIndex], periodOffsets[windowIndex + 1] - 1, - /* positionInFirstPeriodUs= */ 0); + windowDefinition.windowOffsetInFirstPeriodUs); window.isPlaceholder = windowDefinition.isPlaceholder; return window; } @@ -279,8 +291,20 @@ public final class FakeTimeline extends Timeline { TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex]; Object id = setIds ? windowPeriodIndex : null; Object uid = setIds ? Pair.create(windowDefinition.id, windowPeriodIndex) : null; - long periodDurationUs = windowDefinition.durationUs / windowDefinition.periodCount; - long positionInWindowUs = periodDurationUs * windowPeriodIndex; + // Arbitrarily set period duration by distributing window duration equally among all periods. + long periodDurationUs = + windowDefinition.durationUs == C.TIME_UNSET + ? C.TIME_UNSET + : windowDefinition.durationUs / windowDefinition.periodCount; + long positionInWindowUs; + if (windowPeriodIndex == 0) { + if (windowDefinition.durationUs != C.TIME_UNSET) { + periodDurationUs += windowDefinition.windowOffsetInFirstPeriodUs; + } + positionInWindowUs = -windowDefinition.windowOffsetInFirstPeriodUs; + } else { + positionInWindowUs = periodDurationUs * windowPeriodIndex; + } return period.set( id, uid,