Commit 60f907be by bachinger Committed by Oliver Woodman

Make FakeTimeline and FakeMediaSource provide a media item

FakeMediaSource and FakeTimeline should put a media item to the window just as other media sources and timelines do. This change provides a fake media item for both of them.

Further the MaskingMediaSource needs to provide a media item for when the real timeline of the masked media source is not available. This can be easily done by using mediaSource.getMediaItem() once available. For now a dummy is used to make ExoPlayerTest run green. This can be easily change to use mediaSource.getMediaSource as soon as this method is defined by the MediaSource interface.

PiperOrigin-RevId: 314897474
parent 08b0e08b
...@@ -44,6 +44,7 @@ import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; ...@@ -44,6 +44,7 @@ import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
import com.google.ads.interactivemedia.v3.api.player.AdMediaInfo; import com.google.ads.interactivemedia.v3.api.player.AdMediaInfo;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
...@@ -160,7 +161,7 @@ public final class ImaAdsLoaderTest { ...@@ -160,7 +161,7 @@ public final class ImaAdsLoaderTest {
@Test @Test
public void start_withPlaceholderContent_initializedAdsLoader() { public void start_withPlaceholderContent_initializedAdsLoader() {
Timeline placeholderTimeline = new DummyTimeline(/* tag= */ null); Timeline placeholderTimeline = new DummyTimeline(MediaItem.fromUri(Uri.EMPTY));
setupPlayback(placeholderTimeline, ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS); setupPlayback(placeholderTimeline, ADS_DURATIONS_US, PREROLL_CUE_POINTS_SECONDS);
imaAdsLoader.start(adsLoaderListener, adViewProvider); imaAdsLoader.start(adsLoaderListener, adViewProvider);
......
...@@ -15,10 +15,12 @@ ...@@ -15,10 +15,12 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import android.net.Uri;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window; import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
...@@ -66,7 +68,10 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -66,7 +68,10 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
initialTimeline, /* firstWindowUid= */ null, /* firstPeriodUid= */ null); initialTimeline, /* firstWindowUid= */ null, /* firstPeriodUid= */ null);
hasRealTimeline = true; hasRealTimeline = true;
} else { } else {
timeline = MaskingTimeline.createWithDummyTimeline(mediaSource.getTag()); // TODO(bachinger) Use mediasSource.getMediaItem() to provide the media item.
timeline =
MaskingTimeline.createWithDummyTimeline(
new MediaItem.Builder().setUri(Uri.EMPTY).setTag(mediaSource.getTag()).build());
} }
} }
...@@ -268,9 +273,9 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -268,9 +273,9 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
* *
* @param windowTag A window tag. * @param windowTag A window tag.
*/ */
public static MaskingTimeline createWithDummyTimeline(@Nullable Object windowTag) { public static MaskingTimeline createWithDummyTimeline(MediaItem mediaItem) {
return new MaskingTimeline( return new MaskingTimeline(
new DummyTimeline(windowTag), Window.SINGLE_WINDOW_UID, DUMMY_EXTERNAL_PERIOD_UID); new DummyTimeline(mediaItem), Window.SINGLE_WINDOW_UID, DUMMY_EXTERNAL_PERIOD_UID);
} }
/** /**
...@@ -348,10 +353,11 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -348,10 +353,11 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
@VisibleForTesting @VisibleForTesting
public static final class DummyTimeline extends Timeline { public static final class DummyTimeline extends Timeline {
@Nullable private final Object tag; private final MediaItem mediaItem;
public DummyTimeline(@Nullable Object tag) { /** Creates a new instance with the given media item. */
this.tag = tag; public DummyTimeline(MediaItem mediaItem) {
this.mediaItem = mediaItem;
} }
@Override @Override
...@@ -363,7 +369,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -363,7 +369,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
window.set( window.set(
Window.SINGLE_WINDOW_UID, Window.SINGLE_WINDOW_UID,
tag, mediaItem,
/* manifest= */ null, /* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
......
...@@ -126,7 +126,9 @@ public final class ExoPlayerTest { ...@@ -126,7 +126,9 @@ public final class ExoPlayerTest {
@Before @Before
public void setUp() { public void setUp() {
context = ApplicationProvider.getApplicationContext(); context = ApplicationProvider.getApplicationContext();
dummyTimeline = new MaskingMediaSource.DummyTimeline(/* tag= */ 0); dummyTimeline =
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(0).build());
} }
/** /**
...@@ -136,7 +138,8 @@ public final class ExoPlayerTest { ...@@ -136,7 +138,8 @@ public final class ExoPlayerTest {
@Test @Test
public void playEmptyTimeline() throws Exception { public void playEmptyTimeline() throws Exception {
Timeline timeline = Timeline.EMPTY; Timeline timeline = Timeline.EMPTY;
Timeline expectedMaskingTimeline = new MaskingMediaSource.DummyTimeline(/* tag= */ null); Timeline expectedMaskingTimeline =
new MaskingMediaSource.DummyTimeline(FakeTimeline.FAKE_MEDIA_ITEM);
FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_UNKNOWN); FakeRenderer renderer = new FakeRenderer(C.TRACK_TYPE_UNKNOWN);
ExoPlayerTestRunner testRunner = ExoPlayerTestRunner testRunner =
new ExoPlayerTestRunner.Builder(context) new ExoPlayerTestRunner.Builder(context)
...@@ -1226,13 +1229,15 @@ public final class ExoPlayerTest { ...@@ -1226,13 +1229,15 @@ public final class ExoPlayerTest {
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedMaskingTimeline = Timeline firstExpectedMaskingTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object(); Object secondWindowId = new Object();
Timeline secondTimeline = Timeline secondTimeline =
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedMaskingTimeline = Timeline secondExpectedMaskingTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline); MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong(); AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
...@@ -1278,13 +1283,15 @@ public final class ExoPlayerTest { ...@@ -1278,13 +1283,15 @@ public final class ExoPlayerTest {
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedDummyTimeline = Timeline firstExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object(); Object secondWindowId = new Object();
Timeline secondTimeline = Timeline secondTimeline =
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedDummyTimeline = Timeline secondExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline); MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong(); AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
...@@ -1330,13 +1337,15 @@ public final class ExoPlayerTest { ...@@ -1330,13 +1337,15 @@ public final class ExoPlayerTest {
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedDummyTimeline = Timeline firstExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object(); Object secondWindowId = new Object();
Timeline secondTimeline = Timeline secondTimeline =
new FakeTimeline( new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId)); new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedDummyTimeline = Timeline secondExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId); new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline); MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong(); AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
......
...@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.source; ...@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.source;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import android.net.Uri;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
...@@ -171,7 +173,7 @@ public final class ClippingMediaSourceTest { ...@@ -171,7 +173,7 @@ public final class ClippingMediaSourceTest {
// Timeline that's dynamic and not seekable. A child source might report such a timeline prior // Timeline that's dynamic and not seekable. A child source might report such a timeline prior
// to it having loaded sufficient data to establish its duration and seekability. Such timelines // to it having loaded sufficient data to establish its duration and seekability. Such timelines
// should not result in clipping failure. // should not result in clipping failure.
Timeline timeline = new DummyTimeline(/* tag= */ null); Timeline timeline = new DummyTimeline(MediaItem.fromUri(Uri.EMPTY));
Timeline clippedTimeline = Timeline clippedTimeline =
getClippedTimeline( getClippedTimeline(
......
...@@ -15,14 +15,15 @@ ...@@ -15,14 +15,15 @@
*/ */
package com.google.android.exoplayer2.testutil; package com.google.android.exoplayer2.testutil;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
...@@ -68,7 +69,12 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -68,7 +69,12 @@ public class FakeMediaSource extends BaseMediaSource {
} }
} }
private static final DataSpec FAKE_DATA_SPEC = new DataSpec(Uri.parse("http://manifest.uri")); /** The media item used by the fake media source. */
public static final MediaItem FAKE_MEDIA_ITEM =
new MediaItem.Builder().setUri("http://manifest.uri").build();
private static final DataSpec FAKE_DATA_SPEC =
new DataSpec(castNonNull(FAKE_MEDIA_ITEM.playbackProperties).uri);
private static final int MANIFEST_LOAD_BYTES = 100; private static final int MANIFEST_LOAD_BYTES = 100;
private final TrackGroupArray trackGroupArray; private final TrackGroupArray trackGroupArray;
...@@ -137,6 +143,14 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -137,6 +143,14 @@ public class FakeMediaSource extends BaseMediaSource {
return timeline.getWindow(0, new Timeline.Window()).tag; return timeline.getWindow(0, new Timeline.Window()).tag;
} }
// TODO(bachinger): add @Override annotation once the method is defined by MediaSource.
public MediaItem getMediaItem() {
if (timeline == null || timeline.isEmpty()) {
return FAKE_MEDIA_ITEM;
}
return timeline.getWindow(0, new Timeline.Window()).mediaItem;
}
@Override @Override
@Nullable @Nullable
public Timeline getInitialTimeline() { public Timeline getInitialTimeline() {
...@@ -172,7 +186,7 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -172,7 +186,7 @@ public class FakeMediaSource extends BaseMediaSource {
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(preparedSource).isTrue(); assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse(); assertThat(releasedSource).isFalse();
int periodIndex = Util.castNonNull(timeline).getIndexOfPeriod(id.periodUid); int periodIndex = castNonNull(timeline).getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET); Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period()); Period period = timeline.getPeriod(periodIndex, new Period());
EventDispatcher eventDispatcher = EventDispatcher eventDispatcher =
...@@ -202,7 +216,7 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -202,7 +216,7 @@ public class FakeMediaSource extends BaseMediaSource {
drmSessionManager.release(); drmSessionManager.release();
releasedSource = true; releasedSource = true;
preparedSource = false; preparedSource = false;
Util.castNonNull(sourceInfoRefreshHandler).removeCallbacksAndMessages(null); castNonNull(sourceInfoRefreshHandler).removeCallbacksAndMessages(null);
sourceInfoRefreshHandler = null; sourceInfoRefreshHandler = null;
} }
......
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
import android.net.Uri; import android.net.Uri;
import android.util.Pair; import android.util.Pair;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState; import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -41,6 +42,7 @@ public final class FakeTimeline extends Timeline { ...@@ -41,6 +42,7 @@ public final class FakeTimeline extends Timeline {
public final int periodCount; public final int periodCount;
public final Object id; public final Object id;
public final MediaItem mediaItem;
public final boolean isSeekable; public final boolean isSeekable;
public final boolean isDynamic; public final boolean isDynamic;
public final boolean isLive; public final boolean isLive;
...@@ -169,6 +171,7 @@ public final class FakeTimeline extends Timeline { ...@@ -169,6 +171,7 @@ public final class FakeTimeline extends Timeline {
Assertions.checkArgument(durationUs != C.TIME_UNSET || periodCount == 1); Assertions.checkArgument(durationUs != C.TIME_UNSET || periodCount == 1);
this.periodCount = periodCount; this.periodCount = periodCount;
this.id = id; this.id = id;
this.mediaItem = FAKE_MEDIA_ITEM.buildUpon().setTag(id).build();
this.isSeekable = isSeekable; this.isSeekable = isSeekable;
this.isDynamic = isDynamic; this.isDynamic = isDynamic;
this.isLive = isLive; this.isLive = isLive;
...@@ -180,6 +183,9 @@ public final class FakeTimeline extends Timeline { ...@@ -180,6 +183,9 @@ public final class FakeTimeline extends Timeline {
} }
} }
/** The fake media item used by the fake timeline. */
public static final MediaItem FAKE_MEDIA_ITEM = new MediaItem.Builder().setUri(Uri.EMPTY).build();
private static final long AD_DURATION_US = 10 * C.MICROS_PER_SECOND; private static final long AD_DURATION_US = 10 * C.MICROS_PER_SECOND;
private final TimelineWindowDefinition[] windowDefinitions; private final TimelineWindowDefinition[] windowDefinitions;
...@@ -262,7 +268,7 @@ public final class FakeTimeline extends Timeline { ...@@ -262,7 +268,7 @@ public final class FakeTimeline extends Timeline {
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex]; TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
window.set( window.set(
/* uid= */ windowDefinition.id, /* uid= */ windowDefinition.id,
/* tag= */ windowDefinition.id, windowDefinition.mediaItem,
manifests[windowIndex], manifests[windowIndex],
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment