Make use of MediaItem in ProgressiveMediaSource

PiperOrigin-RevId: 310889726
This commit is contained in:
bachinger 2020-05-11 12:58:27 +01:00 committed by Oliver Woodman
parent 1241c8c321
commit 19d639eb9a
5 changed files with 253 additions and 60 deletions

View File

@ -321,14 +321,16 @@ public final class ExtractorMediaSource extends CompositeMediaSource<Void> {
@Nullable Object tag) { @Nullable Object tag) {
progressiveMediaSource = progressiveMediaSource =
new ProgressiveMediaSource( new ProgressiveMediaSource(
uri, new MediaItem.Builder()
.setUri(uri)
.setCustomCacheKey(customCacheKey)
.setTag(tag)
.build(),
dataSourceFactory, dataSourceFactory,
extractorsFactory, extractorsFactory,
DrmSessionManager.getDummyDrmSessionManager(), DrmSessionManager.getDummyDrmSessionManager(),
loadableLoadErrorHandlingPolicy, loadableLoadErrorHandlingPolicy,
customCacheKey, continueLoadingCheckIntervalBytes);
continueLoadingCheckIntervalBytes,
tag);
} }
@Override @Override

View File

@ -15,6 +15,8 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
@ -30,7 +32,6 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;
/** /**
* Provides one period that loads data from a {@link Uri} and extracted using an {@link Extractor}. * Provides one period that loads data from a {@link Uri} and extracted using an {@link Extractor}.
@ -178,18 +179,21 @@ public final class ProgressiveMediaSource extends BaseMediaSource
*/ */
@Override @Override
public ProgressiveMediaSource createMediaSource(MediaItem mediaItem) { public ProgressiveMediaSource createMediaSource(MediaItem mediaItem) {
Assertions.checkNotNull(mediaItem.playbackProperties); checkNotNull(mediaItem.playbackProperties);
MediaItem.Builder builder = mediaItem.buildUpon();
if (mediaItem.playbackProperties.tag == null) {
builder.setTag(tag);
}
if (mediaItem.playbackProperties.customCacheKey == null) {
builder.setCustomCacheKey(customCacheKey);
}
return new ProgressiveMediaSource( return new ProgressiveMediaSource(
mediaItem.playbackProperties.uri, builder.build(),
dataSourceFactory, dataSourceFactory,
extractorsFactory, extractorsFactory,
drmSessionManager, drmSessionManager,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
mediaItem.playbackProperties.customCacheKey != null continueLoadingCheckIntervalBytes);
? mediaItem.playbackProperties.customCacheKey
: customCacheKey,
continueLoadingCheckIntervalBytes,
mediaItem.playbackProperties.tag != null ? mediaItem.playbackProperties.tag : tag);
} }
@Override @Override
@ -204,14 +208,13 @@ public final class ProgressiveMediaSource extends BaseMediaSource
*/ */
public static final int DEFAULT_LOADING_CHECK_INTERVAL_BYTES = 1024 * 1024; public static final int DEFAULT_LOADING_CHECK_INTERVAL_BYTES = 1024 * 1024;
private final Uri uri; private final MediaItem mediaItem;
private final MediaItem.PlaybackProperties playbackProperties;
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private final ExtractorsFactory extractorsFactory; private final ExtractorsFactory extractorsFactory;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy;
@Nullable private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes; private final int continueLoadingCheckIntervalBytes;
@Nullable private final Object tag;
private boolean timelineIsPlaceholder; private boolean timelineIsPlaceholder;
private long timelineDurationUs; private long timelineDurationUs;
@ -221,30 +224,32 @@ public final class ProgressiveMediaSource extends BaseMediaSource
// TODO: Make private when ExtractorMediaSource is deleted. // TODO: Make private when ExtractorMediaSource is deleted.
/* package */ ProgressiveMediaSource( /* package */ ProgressiveMediaSource(
Uri uri, MediaItem mediaItem,
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, ExtractorsFactory extractorsFactory,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy, LoadErrorHandlingPolicy loadableLoadErrorHandlingPolicy,
@Nullable String customCacheKey, int continueLoadingCheckIntervalBytes) {
int continueLoadingCheckIntervalBytes, this.playbackProperties = checkNotNull(mediaItem.playbackProperties);
@Nullable Object tag) { this.mediaItem = mediaItem;
this.uri = uri;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.extractorsFactory = extractorsFactory; this.extractorsFactory = extractorsFactory;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.loadableLoadErrorHandlingPolicy = loadableLoadErrorHandlingPolicy; this.loadableLoadErrorHandlingPolicy = loadableLoadErrorHandlingPolicy;
this.customCacheKey = customCacheKey;
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
this.timelineIsPlaceholder = true; this.timelineIsPlaceholder = true;
this.timelineDurationUs = C.TIME_UNSET; this.timelineDurationUs = C.TIME_UNSET;
this.tag = tag;
} }
@Override @Override
@Nullable @Nullable
public Object getTag() { public Object getTag() {
return tag; return playbackProperties.tag;
}
@Nullable
public Object getMediaItem() {
return mediaItem;
} }
@Override @Override
@ -266,7 +271,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource
dataSource.addTransferListener(transferListener); dataSource.addTransferListener(transferListener);
} }
return new ProgressiveMediaPeriod( return new ProgressiveMediaPeriod(
uri, playbackProperties.uri,
dataSource, dataSource,
extractorsFactory.createExtractors(), extractorsFactory.createExtractors(),
drmSessionManager, drmSessionManager,
@ -274,7 +279,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource
createEventDispatcher(id), createEventDispatcher(id),
this, this,
allocator, allocator,
customCacheKey, playbackProperties.customCacheKey,
continueLoadingCheckIntervalBytes); continueLoadingCheckIntervalBytes);
} }
@ -320,7 +325,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource
/* isDynamic= */ false, /* isDynamic= */ false,
/* isLive= */ timelineIsLive, /* isLive= */ timelineIsLive,
/* manifest= */ null, /* manifest= */ null,
tag); mediaItem);
if (timelineIsPlaceholder) { if (timelineIsPlaceholder) {
// TODO: Actually prepare the extractors during prepatation so that we don't need a // TODO: Actually prepare the extractors during prepatation so that we don't need a
// placeholder. See https://github.com/google/ExoPlayer/issues/4727. // placeholder. See https://github.com/google/ExoPlayer/issues/4727.

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
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.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
@ -39,6 +40,7 @@ public final class SinglePeriodTimeline extends Timeline {
private final boolean isLive; private final boolean isLive;
@Nullable private final Object tag; @Nullable private final Object tag;
@Nullable private final Object manifest; @Nullable private final Object manifest;
@Nullable private final MediaItem mediaItem;
/** /**
* Creates a timeline containing a single period and a window that spans it. * Creates a timeline containing a single period and a window that spans it.
@ -50,19 +52,16 @@ public final class SinglePeriodTimeline extends Timeline {
*/ */
public SinglePeriodTimeline( public SinglePeriodTimeline(
long durationUs, boolean isSeekable, boolean isDynamic, boolean isLive) { long durationUs, boolean isSeekable, boolean isDynamic, boolean isLive) {
this(durationUs, isSeekable, isDynamic, isLive, /* manifest= */ null, /* tag= */ null); this(durationUs, isSeekable, isDynamic, isLive, /* manifest= */ null, /* mediaItem= */ null);
} }
/** /**
* Creates a timeline containing a single period and a window that spans it. * @deprecated Use {@link #SinglePeriodTimeline(long, boolean, boolean, boolean, Object,
* * MediaItem)} instead.
* @param durationUs The duration of the period, in microseconds.
* @param isSeekable Whether seeking is supported within the period.
* @param isDynamic Whether the window may change when the timeline is updated.
* @param isLive Whether the window is live.
* @param manifest The manifest. May be {@code null}.
* @param tag A tag used for {@link Window#tag}.
*/ */
// Provide backwards compatibility.
@SuppressWarnings("deprecation")
@Deprecated
public SinglePeriodTimeline( public SinglePeriodTimeline(
long durationUs, long durationUs,
boolean isSeekable, boolean isSeekable,
@ -83,21 +82,41 @@ public final class SinglePeriodTimeline extends Timeline {
} }
/** /**
* Creates a timeline with one period, and a window of known duration starting at a specified * Creates a timeline containing a single period and a window that spans it.
* position in the period.
* *
* @param periodDurationUs The duration of the period in microseconds. * @param durationUs The duration of the period, in microseconds.
* @param windowDurationUs The duration of the window in microseconds. * @param isSeekable Whether seeking is supported within the period.
* @param windowPositionInPeriodUs The position of the start of the window in the period, in
* microseconds.
* @param windowDefaultStartPositionUs The default position relative to the start of the window at
* which to begin playback, in microseconds.
* @param isSeekable Whether seeking is supported within the window.
* @param isDynamic Whether the window may change when the timeline is updated. * @param isDynamic Whether the window may change when the timeline is updated.
* @param isLive Whether the window is live. * @param isLive Whether the window is live.
* @param manifest The manifest. May be (@code null}. * @param manifest The manifest. May be {@code null}.
* @param tag A tag used for {@link Timeline.Window#tag}. * @param mediaItem A media item used for {@link Window#mediaItem}.
*/ */
public SinglePeriodTimeline(
long durationUs,
boolean isSeekable,
boolean isDynamic,
boolean isLive,
@Nullable Object manifest,
@Nullable MediaItem mediaItem) {
this(
durationUs,
durationUs,
/* windowPositionInPeriodUs= */ 0,
/* windowDefaultStartPositionUs= */ 0,
isSeekable,
isDynamic,
isLive,
manifest,
mediaItem);
}
/**
* @deprecated Use {@link #SinglePeriodTimeline(long, long, long, long, boolean, boolean, boolean,
* Object, MediaItem)} instead.
*/
// Provide backwards compatibility.
@SuppressWarnings("deprecation")
@Deprecated
public SinglePeriodTimeline( public SinglePeriodTimeline(
long periodDurationUs, long periodDurationUs,
long windowDurationUs, long windowDurationUs,
@ -123,6 +142,81 @@ public final class SinglePeriodTimeline extends Timeline {
tag); tag);
} }
/**
* Creates a timeline with one period, and a window of known duration starting at a specified
* position in the period.
*
* @param periodDurationUs The duration of the period in microseconds.
* @param windowDurationUs The duration of the window in microseconds.
* @param windowPositionInPeriodUs The position of the start of the window in the period, in
* microseconds.
* @param windowDefaultStartPositionUs The default position relative to the start of the window at
* which to begin playback, in microseconds.
* @param isSeekable Whether seeking is supported within the window.
* @param isDynamic Whether the window may change when the timeline is updated.
* @param isLive Whether the window is live.
* @param manifest The manifest. May be (@code null}.
* @param mediaItem A media item used for {@link Timeline.Window#mediaItem}.
*/
public SinglePeriodTimeline(
long periodDurationUs,
long windowDurationUs,
long windowPositionInPeriodUs,
long windowDefaultStartPositionUs,
boolean isSeekable,
boolean isDynamic,
boolean isLive,
@Nullable Object manifest,
@Nullable MediaItem mediaItem) {
this(
/* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET,
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
periodDurationUs,
windowDurationUs,
windowPositionInPeriodUs,
windowDefaultStartPositionUs,
isSeekable,
isDynamic,
isLive,
manifest,
mediaItem);
}
/**
* @deprecated Use {@link #SinglePeriodTimeline(long, long, long, long, long, long, long, boolean,
* boolean, boolean, Object, MediaItem)} instead.
*/
@Deprecated
public SinglePeriodTimeline(
long presentationStartTimeMs,
long windowStartTimeMs,
long elapsedRealtimeEpochOffsetMs,
long periodDurationUs,
long windowDurationUs,
long windowPositionInPeriodUs,
long windowDefaultStartPositionUs,
boolean isSeekable,
boolean isDynamic,
boolean isLive,
@Nullable Object manifest,
@Nullable Object tag) {
this(
presentationStartTimeMs,
windowStartTimeMs,
elapsedRealtimeEpochOffsetMs,
periodDurationUs,
windowDurationUs,
windowPositionInPeriodUs,
windowDefaultStartPositionUs,
isSeekable,
isDynamic,
isLive,
manifest,
/* mediaItem= */ null,
tag);
}
/** /**
* Creates a timeline with one period, and a window of known duration starting at a specified * Creates a timeline with one period, and a window of known duration starting at a specified
* position in the period. * position in the period.
@ -144,7 +238,7 @@ public final class SinglePeriodTimeline extends Timeline {
* @param isDynamic Whether the window may change when the timeline is updated. * @param isDynamic Whether the window may change when the timeline is updated.
* @param isLive Whether the window is live. * @param isLive Whether the window is live.
* @param manifest The manifest. May be {@code null}. * @param manifest The manifest. May be {@code null}.
* @param tag A tag used for {@link Timeline.Window#tag}. * @param mediaItem A media item used for {@link Timeline.Window#mediaItem}.
*/ */
public SinglePeriodTimeline( public SinglePeriodTimeline(
long presentationStartTimeMs, long presentationStartTimeMs,
@ -158,6 +252,36 @@ public final class SinglePeriodTimeline extends Timeline {
boolean isDynamic, boolean isDynamic,
boolean isLive, boolean isLive,
@Nullable Object manifest, @Nullable Object manifest,
@Nullable MediaItem mediaItem) {
this(
presentationStartTimeMs,
windowStartTimeMs,
elapsedRealtimeEpochOffsetMs,
periodDurationUs,
windowDurationUs,
windowPositionInPeriodUs,
windowDefaultStartPositionUs,
isSeekable,
isDynamic,
isLive,
manifest,
mediaItem,
/* tag= */ null);
}
private SinglePeriodTimeline(
long presentationStartTimeMs,
long windowStartTimeMs,
long elapsedRealtimeEpochOffsetMs,
long periodDurationUs,
long windowDurationUs,
long windowPositionInPeriodUs,
long windowDefaultStartPositionUs,
boolean isSeekable,
boolean isDynamic,
boolean isLive,
@Nullable Object manifest,
@Nullable MediaItem mediaItem,
@Nullable Object tag) { @Nullable Object tag) {
this.presentationStartTimeMs = presentationStartTimeMs; this.presentationStartTimeMs = presentationStartTimeMs;
this.windowStartTimeMs = windowStartTimeMs; this.windowStartTimeMs = windowStartTimeMs;
@ -170,6 +294,7 @@ public final class SinglePeriodTimeline extends Timeline {
this.isDynamic = isDynamic; this.isDynamic = isDynamic;
this.isLive = isLive; this.isLive = isLive;
this.manifest = manifest; this.manifest = manifest;
this.mediaItem = mediaItem;
this.tag = tag; this.tag = tag;
} }
@ -178,6 +303,8 @@ public final class SinglePeriodTimeline extends Timeline {
return 1; return 1;
} }
// Provide backwards compatibility.
@SuppressWarnings("deprecation")
@Override @Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
Assertions.checkIndex(windowIndex, 0, 1); Assertions.checkIndex(windowIndex, 0, 1);
@ -194,9 +321,27 @@ public final class SinglePeriodTimeline extends Timeline {
} }
} }
} }
if (tag != null) {
// Support deprecated constructors.
return window.set(
Window.SINGLE_WINDOW_UID,
tag,
manifest,
presentationStartTimeMs,
windowStartTimeMs,
elapsedRealtimeEpochOffsetMs,
isSeekable,
isDynamic,
isLive,
windowDefaultStartPositionUs,
windowDurationUs,
/* firstPeriodIndex= */ 0,
/* lastPeriodIndex= */ 0,
windowPositionInPeriodUs);
}
return window.set( return window.set(
Window.SINGLE_WINDOW_UID, Window.SINGLE_WINDOW_UID,
tag, mediaItem,
manifest, manifest,
presentationStartTimeMs, presentationStartTimeMs,
windowStartTimeMs, windowStartTimeMs,

View File

@ -235,7 +235,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline clippedTimeline = getClippedTimeline(timeline, /* durationUs= */ TEST_CLIP_AMOUNT_US); Timeline clippedTimeline = getClippedTimeline(timeline, /* durationUs= */ TEST_CLIP_AMOUNT_US);
assertThat(clippedTimeline.getWindow(0, window).getDurationUs()).isEqualTo(TEST_CLIP_AMOUNT_US); assertThat(clippedTimeline.getWindow(0, window).getDurationUs()).isEqualTo(TEST_CLIP_AMOUNT_US);
@ -258,7 +258,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
/* periodDurationUs= */ 3 * TEST_PERIOD_DURATION_US, /* periodDurationUs= */ 3 * TEST_PERIOD_DURATION_US,
@ -269,7 +269,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
getClippedTimelines( getClippedTimelines(
@ -309,7 +309,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
/* periodDurationUs= */ 4 * TEST_PERIOD_DURATION_US, /* periodDurationUs= */ 4 * TEST_PERIOD_DURATION_US,
@ -320,7 +320,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
getClippedTimelines( getClippedTimelines(
@ -360,7 +360,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
/* periodDurationUs= */ 3 * TEST_PERIOD_DURATION_US, /* periodDurationUs= */ 3 * TEST_PERIOD_DURATION_US,
@ -371,7 +371,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
getClippedTimelines( getClippedTimelines(
@ -412,7 +412,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
/* periodDurationUs= */ 4 * TEST_PERIOD_DURATION_US, /* periodDurationUs= */ 4 * TEST_PERIOD_DURATION_US,
@ -423,7 +423,7 @@ public final class ClippingMediaSourceTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
getClippedTimelines( getClippedTimelines(

View File

@ -17,9 +17,11 @@ package com.google.android.exoplayer2.source;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import android.util.Pair; import android.util.Pair;
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.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.Timeline.Window; import com.google.android.exoplayer2.Timeline.Window;
import org.junit.Before; import org.junit.Before;
@ -66,7 +68,7 @@ public final class SinglePeriodTimelineTest {
/* isDynamic= */ true, /* isDynamic= */ true,
/* isLive= */ true, /* isLive= */ true,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
// Should return null with a positive position projection beyond window duration. // Should return null with a positive position projection beyond window duration.
Pair<Object, Long> position = Pair<Object, Long> position =
timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, windowDurationUs + 1); timeline.getPeriodPosition(window, period, 0, C.TIME_UNSET, windowDurationUs + 1);
@ -90,7 +92,7 @@ public final class SinglePeriodTimelineTest {
/* isDynamic= */ false, /* isDynamic= */ false,
/* isLive= */ false, /* isLive= */ false,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* tag= */ (Object) null);
assertThat(timeline.getWindow(/* windowIndex= */ 0, window).tag).isNull(); assertThat(timeline.getWindow(/* windowIndex= */ 0, window).tag).isNull();
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ false).id).isNull(); assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ false).id).isNull();
@ -100,6 +102,25 @@ public final class SinglePeriodTimelineTest {
.isNotNull(); .isNotNull();
} }
@Test
public void setNullMediaItem_returnsNullMediaItem_butUsesDefaultUid() {
SinglePeriodTimeline timeline =
new SinglePeriodTimeline(
/* durationUs= */ C.TIME_UNSET,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* isLive= */ false,
/* manifest= */ null,
/* mediaItem= */ null);
assertThat(timeline.getWindow(/* windowIndex= */ 0, window).mediaItem).isNull();
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ false).id).isNull();
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).id).isNull();
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ false).uid).isNull();
assertThat(timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid)
.isNotNull();
}
@Test @Test
public void getWindow_setsTag() { public void getWindow_setsTag() {
Object tag = new Object(); Object tag = new Object();
@ -115,6 +136,26 @@ public final class SinglePeriodTimelineTest {
assertThat(timeline.getWindow(/* windowIndex= */ 0, window).tag).isEqualTo(tag); assertThat(timeline.getWindow(/* windowIndex= */ 0, window).tag).isEqualTo(tag);
} }
// Tests backward compatibility.
@SuppressWarnings("deprecation")
@Test
public void getWindow_setsMediaItemAndTag() {
MediaItem mediaItem = new MediaItem.Builder().setUri(Uri.EMPTY).setTag(new Object()).build();
SinglePeriodTimeline timeline =
new SinglePeriodTimeline(
/* durationUs= */ C.TIME_UNSET,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* isLive= */ false,
/* manifest= */ null,
mediaItem);
Window window = timeline.getWindow(/* windowIndex= */ 0, this.window);
assertThat(window.mediaItem).isEqualTo(mediaItem);
assertThat(window.tag).isEqualTo(mediaItem.playbackProperties.tag);
}
@Test @Test
public void getIndexOfPeriod_returnsPeriod() { public void getIndexOfPeriod_returnsPeriod() {
SinglePeriodTimeline timeline = SinglePeriodTimeline timeline =
@ -124,7 +165,7 @@ public final class SinglePeriodTimelineTest {
/* isDynamic= */ false, /* isDynamic= */ false,
/* isLive= */ false, /* isLive= */ false,
/* manifest= */ null, /* manifest= */ null,
/* tag= */ null); /* mediaItem= */ null);
Object uid = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid; Object uid = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid;
assertThat(timeline.getIndexOfPeriod(uid)).isEqualTo(0); assertThat(timeline.getIndexOfPeriod(uid)).isEqualTo(0);