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;
import com.google.ads.interactivemedia.v3.api.player.AdMediaInfo;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
......@@ -160,7 +161,7 @@ public final class ImaAdsLoaderTest {
@Test
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);
imaAdsLoader.start(adsLoaderListener, adViewProvider);
......
......@@ -15,10 +15,12 @@
*/
package com.google.android.exoplayer2.source;
import android.net.Uri;
import android.util.Pair;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
......@@ -66,7 +68,10 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
initialTimeline, /* firstWindowUid= */ null, /* firstPeriodUid= */ null);
hasRealTimeline = true;
} 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> {
*
* @param windowTag A window tag.
*/
public static MaskingTimeline createWithDummyTimeline(@Nullable Object windowTag) {
public static MaskingTimeline createWithDummyTimeline(MediaItem mediaItem) {
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> {
@VisibleForTesting
public static final class DummyTimeline extends Timeline {
@Nullable private final Object tag;
private final MediaItem mediaItem;
public DummyTimeline(@Nullable Object tag) {
this.tag = tag;
/** Creates a new instance with the given media item. */
public DummyTimeline(MediaItem mediaItem) {
this.mediaItem = mediaItem;
}
@Override
......@@ -363,7 +369,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
window.set(
Window.SINGLE_WINDOW_UID,
tag,
mediaItem,
/* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET,
......
......@@ -126,7 +126,9 @@ public final class ExoPlayerTest {
@Before
public void setUp() {
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 {
@Test
public void playEmptyTimeline() throws Exception {
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);
ExoPlayerTestRunner testRunner =
new ExoPlayerTestRunner.Builder(context)
......@@ -1226,13 +1229,15 @@ public final class ExoPlayerTest {
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedMaskingTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object();
Timeline secondTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedMaskingTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule =
......@@ -1278,13 +1283,15 @@ public final class ExoPlayerTest {
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object();
Timeline secondTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule =
......@@ -1330,13 +1337,15 @@ public final class ExoPlayerTest {
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ firstWindowId));
Timeline firstExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ firstWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(firstWindowId).build());
Object secondWindowId = new Object();
Timeline secondTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ secondWindowId));
Timeline secondExpectedDummyTimeline =
new MaskingMediaSource.DummyTimeline(/* tag= */ secondWindowId);
new MaskingMediaSource.DummyTimeline(
FakeTimeline.FAKE_MEDIA_ITEM.buildUpon().setTag(secondWindowId).build());
MediaSource secondSource = new FakeMediaSource(secondTimeline);
AtomicLong positionAfterReprepare = new AtomicLong();
ActionSchedule actionSchedule =
......
......@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.source;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
......@@ -171,7 +173,7 @@ public final class ClippingMediaSourceTest {
// 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
// should not result in clipping failure.
Timeline timeline = new DummyTimeline(/* tag= */ null);
Timeline timeline = new DummyTimeline(MediaItem.fromUri(Uri.EMPTY));
Timeline clippedTimeline =
getClippedTimeline(
......
......@@ -15,14 +15,15 @@
*/
package com.google.android.exoplayer2.testutil;
import static com.google.android.exoplayer2.util.Util.castNonNull;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.drm.DrmSessionManager;
......@@ -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 final TrackGroupArray trackGroupArray;
......@@ -137,6 +143,14 @@ public class FakeMediaSource extends BaseMediaSource {
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
@Nullable
public Timeline getInitialTimeline() {
......@@ -172,7 +186,7 @@ public class FakeMediaSource extends BaseMediaSource {
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
assertThat(preparedSource).isTrue();
assertThat(releasedSource).isFalse();
int periodIndex = Util.castNonNull(timeline).getIndexOfPeriod(id.periodUid);
int periodIndex = castNonNull(timeline).getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period());
EventDispatcher eventDispatcher =
......@@ -202,7 +216,7 @@ public class FakeMediaSource extends BaseMediaSource {
drmSessionManager.release();
releasedSource = true;
preparedSource = false;
Util.castNonNull(sourceInfoRefreshHandler).removeCallbacksAndMessages(null);
castNonNull(sourceInfoRefreshHandler).removeCallbacksAndMessages(null);
sourceInfoRefreshHandler = null;
}
......
......@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.testutil;
import android.net.Uri;
import android.util.Pair;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
import com.google.android.exoplayer2.util.Assertions;
......@@ -41,6 +42,7 @@ public final class FakeTimeline extends Timeline {
public final int periodCount;
public final Object id;
public final MediaItem mediaItem;
public final boolean isSeekable;
public final boolean isDynamic;
public final boolean isLive;
......@@ -169,6 +171,7 @@ public final class FakeTimeline extends Timeline {
Assertions.checkArgument(durationUs != C.TIME_UNSET || periodCount == 1);
this.periodCount = periodCount;
this.id = id;
this.mediaItem = FAKE_MEDIA_ITEM.buildUpon().setTag(id).build();
this.isSeekable = isSeekable;
this.isDynamic = isDynamic;
this.isLive = isLive;
......@@ -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 final TimelineWindowDefinition[] windowDefinitions;
......@@ -262,7 +268,7 @@ public final class FakeTimeline extends Timeline {
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
window.set(
/* uid= */ windowDefinition.id,
/* tag= */ windowDefinition.id,
windowDefinition.mediaItem,
manifests[windowIndex],
/* presentationStartTimeMs= */ 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