diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java index 0edd19bc09..95d5d96163 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -27,7 +27,6 @@ import com.google.android.exoplayer2.testutil.FakeMediaSource; import com.google.android.exoplayer2.testutil.FakeRenderer; import com.google.android.exoplayer2.testutil.FakeShuffleOrder; import com.google.android.exoplayer2.testutil.FakeTimeline; -import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition; import com.google.android.exoplayer2.testutil.FakeTrackSelection; import com.google.android.exoplayer2.testutil.FakeTrackSelector; import java.util.ArrayList; @@ -68,7 +67,7 @@ public final class ExoPlayerTest extends TestCase { * Tests playback of a source that exposes a single period. */ public void testPlaySinglePeriodTimeline() throws Exception { - Timeline timeline = new FakeTimeline(new TimelineWindowDefinition(false, false, 0)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 1); Object manifest = new Object(); FakeRenderer renderer = new FakeRenderer(Builder.VIDEO_FORMAT); ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder() @@ -87,10 +86,7 @@ public final class ExoPlayerTest extends TestCase { * Tests playback of a source that exposes three periods. */ public void testPlayMultiPeriodTimeline() throws Exception { - Timeline timeline = new FakeTimeline( - new TimelineWindowDefinition(false, false, 0), - new TimelineWindowDefinition(false, false, 0), - new TimelineWindowDefinition(false, false, 0)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 3); FakeRenderer renderer = new FakeRenderer(Builder.VIDEO_FORMAT); ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder() .setTimeline(timeline).setRenderers(renderer) @@ -107,10 +103,7 @@ public final class ExoPlayerTest extends TestCase { * source. */ public void testReadAheadToEndDoesNotResetRenderer() throws Exception { - Timeline timeline = new FakeTimeline( - new TimelineWindowDefinition(false, false, 10), - new TimelineWindowDefinition(false, false, 10), - new TimelineWindowDefinition(false, false, 10)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 3); final FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT); FakeMediaClockRenderer audioRenderer = new FakeMediaClockRenderer(Builder.AUDIO_FORMAT) { @@ -151,7 +144,7 @@ public final class ExoPlayerTest extends TestCase { } public void testRepreparationGivesFreshSourceInfo() throws Exception { - Timeline timeline = new FakeTimeline(new TimelineWindowDefinition(false, false, 0)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 1); FakeRenderer renderer = new FakeRenderer(Builder.VIDEO_FORMAT); Object firstSourceManifest = new Object(); MediaSource firstSource = new FakeMediaSource(timeline, firstSourceManifest, @@ -218,10 +211,7 @@ public final class ExoPlayerTest extends TestCase { } public void testRepeatModeChanges() throws Exception { - Timeline timeline = new FakeTimeline( - new TimelineWindowDefinition(true, false, 100000), - new TimelineWindowDefinition(true, false, 100000), - new TimelineWindowDefinition(true, false, 100000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 3); FakeRenderer renderer = new FakeRenderer(Builder.VIDEO_FORMAT); ActionSchedule actionSchedule = new ActionSchedule.Builder("testRepeatMode") // 0 -> 1 .waitForPositionDiscontinuity().setRepeatMode(Player.REPEAT_MODE_ONE) // 1 -> 1 @@ -241,7 +231,7 @@ public final class ExoPlayerTest extends TestCase { } public void testShuffleModeEnabledChanges() throws Exception { - Timeline fakeTimeline = new FakeTimeline(new TimelineWindowDefinition(true, false, 100000)); + Timeline fakeTimeline = new FakeTimeline(/* windowCount= */ 1); MediaSource[] fakeMediaSources = { new FakeMediaSource(fakeTimeline, null, Builder.VIDEO_FORMAT), new FakeMediaSource(fakeTimeline, null, Builder.VIDEO_FORMAT), @@ -264,7 +254,6 @@ public final class ExoPlayerTest extends TestCase { } public void testPeriodHoldersReleasedAfterSeekWithRepeatModeAll() throws Exception { - Timeline fakeTimeline = new FakeTimeline(new TimelineWindowDefinition(true, false, 100000)); FakeRenderer renderer = new FakeRenderer(Builder.VIDEO_FORMAT); ActionSchedule actionSchedule = new ActionSchedule.Builder("testPeriodHoldersReleased") .setRepeatMode(Player.REPEAT_MODE_ALL) @@ -274,15 +263,13 @@ public final class ExoPlayerTest extends TestCase { .setRepeatMode(Player.REPEAT_MODE_OFF) // Turn off repeat so that playback can finish. .build(); new ExoPlayerTestRunner.Builder() - .setTimeline(fakeTimeline).setRenderers(renderer).setActionSchedule(actionSchedule) + .setRenderers(renderer).setActionSchedule(actionSchedule) .build().start().blockUntilEnded(TIMEOUT_MS); assertTrue(renderer.isEnded); } public void testSeekProcessedCallback() throws Exception { - Timeline timeline = new FakeTimeline( - new TimelineWindowDefinition(true, false, 100000), - new TimelineWindowDefinition(true, false, 100000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 2); ActionSchedule actionSchedule = new ActionSchedule.Builder("testSeekProcessedCallback") // Initial seek before timeline preparation finished. .pause().seek(10).waitForPlaybackState(Player.STATE_READY) @@ -314,8 +301,7 @@ public final class ExoPlayerTest extends TestCase { } public void testAllActivatedTrackSelectionAreReleasedForSinglePeriod() throws Exception { - Timeline timeline = - new FakeTimeline(new TimelineWindowDefinition(false, false, /* durationUs= */ 500_000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 1); MediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT); FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT); @@ -343,9 +329,7 @@ public final class ExoPlayerTest extends TestCase { } public void testAllActivatedTrackSelectionAreReleasedForMultiPeriods() throws Exception { - Timeline timeline = - new FakeTimeline(new TimelineWindowDefinition(false, false, /* durationUs= */ 500_000), - new TimelineWindowDefinition(false, false, /* durationUs= */ 500_000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 2); MediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT); FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT); @@ -374,8 +358,7 @@ public final class ExoPlayerTest extends TestCase { public void testAllActivatedTrackSelectionAreReleasedWhenTrackSelectionsAreRemade() throws Exception { - Timeline timeline = - new FakeTimeline(new TimelineWindowDefinition(false, false, /* durationUs= */ 500_000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 1); MediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT); FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT); @@ -414,8 +397,7 @@ public final class ExoPlayerTest extends TestCase { public void testAllActivatedTrackSelectionAreReleasedWhenTrackSelectionsAreUsed() throws Exception { - Timeline timeline = - new FakeTimeline(new TimelineWindowDefinition(false, false, /* durationUs= */ 500_000)); + Timeline timeline = new FakeTimeline(/* windowCount= */ 1); MediaSource mediaSource = new FakeMediaSource(timeline, null, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT); FakeRenderer videoRenderer = new FakeRenderer(Builder.VIDEO_FORMAT); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java index a1f8fc7861..591e63dc5b 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java @@ -32,7 +32,6 @@ import com.google.android.exoplayer2.metadata.MetadataOutput; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.testutil.ExoPlayerTestRunner.Builder.PlayerFactory; -import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition; import com.google.android.exoplayer2.text.TextOutput; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; @@ -103,8 +102,9 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { /** * Sets a {@link Timeline} to be used by a {@link FakeMediaSource} in the test runner. The - * default value is a non-seekable, non-dynamic {@link FakeTimeline} with zero duration. Setting - * the timeline is not allowed after a call to {@link #setMediaSource(MediaSource)}. + * default value is a seekable, non-dynamic {@link FakeTimeline} with a duration of + * {@link FakeTimeline.TimelineWindowDefinition#DEFAULT_WINDOW_DURATION_US}. Setting the + * timeline is not allowed after a call to {@link #setMediaSource(MediaSource)}. * * @param timeline A {@link Timeline} to be used by a {@link FakeMediaSource} in the test * runner. @@ -294,7 +294,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { } if (mediaSource == null) { if (timeline == null) { - timeline = new FakeTimeline(new TimelineWindowDefinition(false, false, 0)); + timeline = new FakeTimeline(1); } mediaSource = new FakeMediaSource(timeline, manifest, supportedFormats); } 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 2937ee2770..4a9d79f906 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 @@ -30,7 +30,10 @@ public final class FakeTimeline extends Timeline { */ public static final class TimelineWindowDefinition { - private static final int WINDOW_DURATION_US = 100000; + /** + * Default test window duration in microseconds. + */ + public static final int DEFAULT_WINDOW_DURATION_US = 100_000; public final int periodCount; public final Object id; @@ -40,19 +43,65 @@ public final class FakeTimeline extends Timeline { public final int adGroupsPerPeriodCount; public final int adsPerAdGroupCount; - public TimelineWindowDefinition(int periodCount, Object id) { - this(periodCount, id, true, false, WINDOW_DURATION_US); + /** + * Creates a seekable, non-dynamic window definition with one period with a duration of + * {@link #DEFAULT_WINDOW_DURATION_US}. + */ + public TimelineWindowDefinition() { + this(1, 0, true, false, DEFAULT_WINDOW_DURATION_US); } + /** + * Creates a seekable, non-dynamic window definition with a duration of + * {@link #DEFAULT_WINDOW_DURATION_US}. + * + * @param periodCount The number of periods in the window. Each period get an equal slice of the + * total window duration. + * @param id The UID of the window. + */ + public TimelineWindowDefinition(int periodCount, Object id) { + this(periodCount, id, true, false, DEFAULT_WINDOW_DURATION_US); + } + + /** + * Creates a window definition with one period. + * + * @param isSeekable Whether the window is seekable. + * @param isDynamic Whether the window is dynamic. + * @param durationUs The duration of the window in microseconds. + */ public TimelineWindowDefinition(boolean isSeekable, boolean isDynamic, long durationUs) { this(1, 0, isSeekable, isDynamic, durationUs); } + /** + * Creates a window definition. + * + * @param periodCount The number of periods in the window. Each period get an equal slice of the + * total window duration. + * @param id The UID of the window. + * @param isSeekable Whether the window is seekable. + * @param isDynamic Whether the window is dynamic. + * @param durationUs The duration of the window in microseconds. + */ public TimelineWindowDefinition(int periodCount, Object id, boolean isSeekable, boolean isDynamic, long durationUs) { this(periodCount, id, isSeekable, isDynamic, durationUs, 0, 0); } + /** + * Creates a window definition with ad groups. + * + * @param periodCount The number of periods in the window. Each period get an equal slice of the + * total window duration. + * @param id The UID of the window. + * @param isSeekable Whether the window is seekable. + * @param isDynamic Whether the window is dynamic. + * @param durationUs The duration of the window in microseconds. + * @param adGroupsCountPerPeriod The number of ad groups in each period. The position of the ad + * groups is equally distributed in each period starting. + * @param adsPerAdGroupCount The number of ads in each ad group. + */ public TimelineWindowDefinition(int periodCount, Object id, boolean isSeekable, boolean isDynamic, long durationUs, int adGroupsCountPerPeriod, int adsPerAdGroupCount) { this.periodCount = periodCount; @@ -71,6 +120,21 @@ public final class FakeTimeline extends Timeline { private final TimelineWindowDefinition[] windowDefinitions; private final int[] periodOffsets; + /** + * Creates a fake timeline with the given number of seekable, non-dynamic windows with one period + * with a duration of {@link TimelineWindowDefinition#DEFAULT_WINDOW_DURATION_US} each. + * + * @param windowCount The number of windows. + */ + public FakeTimeline(int windowCount) { + this(createDefaultWindowDefinitions(windowCount)); + } + + /** + * Creates a fake timeline with the given window definitions. + * + * @param windowDefinitions A list of {@link TimelineWindowDefinition}s. + */ public FakeTimeline(TimelineWindowDefinition... windowDefinitions) { this.windowDefinitions = windowDefinitions; periodOffsets = new int[windowDefinitions.length + 1]; @@ -141,4 +205,10 @@ public final class FakeTimeline extends Timeline { return index >= 0 && index < getPeriodCount() ? index : C.INDEX_UNSET; } + private static TimelineWindowDefinition[] createDefaultWindowDefinitions(int windowCount) { + TimelineWindowDefinition[] windowDefinitions = new TimelineWindowDefinition[windowCount]; + Arrays.fill(windowDefinitions, new TimelineWindowDefinition()); + return windowDefinitions; + } + }