Commit 49a2e5a5 by bachinger Committed by Oliver Woodman

add manifest to Timeline.Window

- Remove manifest argument from callbacks of Player.EventListener and
  SourceInfoRefreshListener. Instead make it accessible through
  Player.getCurrentManifest() and Timeline.Window.manifest.
- Fix all MediaSource implementation to include the manifest in the
  Timeline instead of passing it to the SourceInfoRefreshListener.
- Refactor ExoPlayerTestRunner, FakeTimeline, FakeMediaSource to
  reflect these changes and make tests pass.

PiperOrigin-RevId: 257359662
parent 877923ce
Showing with 257 additions and 254 deletions
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
* Add VR player demo. * Add VR player demo.
* Wrap decoder exceptions in a new `DecoderException` class and report as * Wrap decoder exceptions in a new `DecoderException` class and report as
renderer error. renderer error.
* Do not pass the manifest to callbacks of Player.EventListener and
SourceInfoRefreshListener anymore. Instead make it accessible through
Player.getCurrentManifest() and Timeline.Window.manifest.
### 2.10.3 ### ### 2.10.3 ###
......
...@@ -264,8 +264,7 @@ import org.json.JSONObject; ...@@ -264,8 +264,7 @@ import org.json.JSONObject;
} }
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {
updateCurrentItemIndex(); updateCurrentItemIndex();
} }
......
...@@ -461,11 +461,6 @@ public final class CastPlayer extends BasePlayer { ...@@ -461,11 +461,6 @@ public final class CastPlayer extends BasePlayer {
} }
@Override @Override
@Nullable public Object getCurrentManifest() {
return null;
}
@Override
public int getCurrentPeriodIndex() { public int getCurrentPeriodIndex() {
return getCurrentWindowIndex(); return getCurrentWindowIndex();
} }
...@@ -592,8 +587,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -592,8 +587,7 @@ public final class CastPlayer extends BasePlayer {
waitingForInitialTimeline = false; waitingForInitialTimeline = false;
notificationsBatch.add( notificationsBatch.add(
new ListenerNotificationTask( new ListenerNotificationTask(
listener -> listener -> listener.onTimelineChanged(currentTimeline, reason)));
listener.onTimelineChanged(currentTimeline, /* manifest= */ null, reason)));
} }
} }
......
...@@ -117,6 +117,7 @@ import java.util.Arrays; ...@@ -117,6 +117,7 @@ import java.util.Arrays;
Object tag = setTag ? ids[windowIndex] : null; Object tag = setTag ? ids[windowIndex] : null;
return window.set( return window.set(
tag, tag,
/* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
/* isSeekable= */ !isDynamic, /* isSeekable= */ !isDynamic,
......
...@@ -946,8 +946,7 @@ public final class ImaAdsLoader ...@@ -946,8 +946,7 @@ public final class ImaAdsLoader
// Player.EventListener implementation. // Player.EventListener implementation.
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) {
if (timeline.isEmpty()) { if (timeline.isEmpty()) {
// The player is being reset or contains no media. // The player is being reset or contains no media.
return; return;
......
...@@ -51,9 +51,7 @@ import java.util.ArrayList; ...@@ -51,9 +51,7 @@ import java.util.ArrayList;
public void updateTimeline(Timeline timeline) { public void updateTimeline(Timeline timeline) {
for (Player.EventListener listener : listeners) { for (Player.EventListener listener : listeners) {
listener.onTimelineChanged( listener.onTimelineChanged(
timeline, timeline, prepared ? TIMELINE_CHANGE_REASON_DYNAMIC : TIMELINE_CHANGE_REASON_PREPARED);
null,
prepared ? TIMELINE_CHANGE_REASON_DYNAMIC : TIMELINE_CHANGE_REASON_PREPARED);
} }
prepared = true; prepared = true;
} }
......
...@@ -288,8 +288,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab ...@@ -288,8 +288,7 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter implements Runnab
} }
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {
Callback callback = getCallback(); Callback callback = getCallback();
callback.onDurationChanged(LeanbackPlayerAdapter.this); callback.onDurationChanged(LeanbackPlayerAdapter.this);
callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this); callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this);
......
...@@ -1020,8 +1020,7 @@ public final class MediaSessionConnector { ...@@ -1020,8 +1020,7 @@ public final class MediaSessionConnector {
// Player.EventListener implementation. // Player.EventListener implementation.
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) {
Player player = Assertions.checkNotNull(MediaSessionConnector.this.player); Player player = Assertions.checkNotNull(MediaSessionConnector.this.player);
int windowCount = player.getCurrentTimeline().getWindowCount(); int windowCount = player.getCurrentTimeline().getWindowCount();
int windowIndex = player.getCurrentWindowIndex(); int windowIndex = player.getCurrentWindowIndex();
......
...@@ -94,11 +94,19 @@ public abstract class BasePlayer implements Player { ...@@ -94,11 +94,19 @@ public abstract class BasePlayer implements Player {
@Override @Override
@Nullable @Nullable
public final Object getCurrentTag() { public final Object getCurrentTag() {
int windowIndex = getCurrentWindowIndex();
Timeline timeline = getCurrentTimeline(); Timeline timeline = getCurrentTimeline();
return windowIndex >= timeline.getWindowCount() return timeline.isEmpty()
? null
: timeline.getWindow(getCurrentWindowIndex(), window, /* setTag= */ true).tag;
}
@Override
@Nullable
public final Object getCurrentManifest() {
Timeline timeline = getCurrentTimeline();
return timeline.isEmpty()
? null ? null
: timeline.getWindow(windowIndex, window, /* setTag= */ true).tag; : timeline.getWindow(getCurrentWindowIndex(), window, /* setTag= */ false).manifest;
} }
@Override @Override
......
...@@ -547,11 +547,6 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -547,11 +547,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
return playbackInfo.timeline; return playbackInfo.timeline;
} }
@Override
public Object getCurrentManifest() {
return playbackInfo.manifest;
}
// Not private so it can be called from an inner class without going through a thunk method. // Not private so it can be called from an inner class without going through a thunk method.
/* package */ void handleEvent(Message msg) { /* package */ void handleEvent(Message msg) {
switch (msg.what) { switch (msg.what) {
...@@ -639,7 +634,6 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -639,7 +634,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
long contentPositionUs = resetPosition ? C.TIME_UNSET : playbackInfo.contentPositionUs; long contentPositionUs = resetPosition ? C.TIME_UNSET : playbackInfo.contentPositionUs;
return new PlaybackInfo( return new PlaybackInfo(
resetState ? Timeline.EMPTY : playbackInfo.timeline, resetState ? Timeline.EMPTY : playbackInfo.timeline,
resetState ? null : playbackInfo.manifest,
mediaPeriodId, mediaPeriodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -713,7 +707,7 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -713,7 +707,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
private final @Player.TimelineChangeReason int timelineChangeReason; private final @Player.TimelineChangeReason int timelineChangeReason;
private final boolean seekProcessed; private final boolean seekProcessed;
private final boolean playbackStateChanged; private final boolean playbackStateChanged;
private final boolean timelineOrManifestChanged; private final boolean timelineChanged;
private final boolean isLoadingChanged; private final boolean isLoadingChanged;
private final boolean trackSelectorResultChanged; private final boolean trackSelectorResultChanged;
private final boolean playWhenReady; private final boolean playWhenReady;
...@@ -737,9 +731,7 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -737,9 +731,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
this.seekProcessed = seekProcessed; this.seekProcessed = seekProcessed;
this.playWhenReady = playWhenReady; this.playWhenReady = playWhenReady;
playbackStateChanged = previousPlaybackInfo.playbackState != playbackInfo.playbackState; playbackStateChanged = previousPlaybackInfo.playbackState != playbackInfo.playbackState;
timelineOrManifestChanged = timelineChanged = previousPlaybackInfo.timeline != playbackInfo.timeline;
previousPlaybackInfo.timeline != playbackInfo.timeline
|| previousPlaybackInfo.manifest != playbackInfo.manifest;
isLoadingChanged = previousPlaybackInfo.isLoading != playbackInfo.isLoading; isLoadingChanged = previousPlaybackInfo.isLoading != playbackInfo.isLoading;
trackSelectorResultChanged = trackSelectorResultChanged =
previousPlaybackInfo.trackSelectorResult != playbackInfo.trackSelectorResult; previousPlaybackInfo.trackSelectorResult != playbackInfo.trackSelectorResult;
...@@ -747,12 +739,10 @@ import java.util.concurrent.CopyOnWriteArrayList; ...@@ -747,12 +739,10 @@ import java.util.concurrent.CopyOnWriteArrayList;
@Override @Override
public void run() { public void run() {
if (timelineOrManifestChanged || timelineChangeReason == TIMELINE_CHANGE_REASON_PREPARED) { if (timelineChanged || timelineChangeReason == TIMELINE_CHANGE_REASON_PREPARED) {
invokeAll( invokeAll(
listenerSnapshot, listenerSnapshot,
listener -> listener -> listener.onTimelineChanged(playbackInfo.timeline, timelineChangeReason));
listener.onTimelineChanged(
playbackInfo.timeline, playbackInfo.manifest, timelineChangeReason));
} }
if (positionDiscontinuity) { if (positionDiscontinuity) {
invokeAll( invokeAll(
......
...@@ -267,9 +267,10 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -267,9 +267,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
// MediaSource.SourceInfoRefreshListener implementation. // MediaSource.SourceInfoRefreshListener implementation.
@Override @Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline, Object manifest) { public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
handler.obtainMessage(MSG_REFRESH_SOURCE_INFO, handler
new MediaSourceRefreshInfo(source, timeline, manifest)).sendToTarget(); .obtainMessage(MSG_REFRESH_SOURCE_INFO, new MediaSourceRefreshInfo(source, timeline))
.sendToTarget();
} }
// MediaPeriod.Callback implementation. // MediaPeriod.Callback implementation.
...@@ -899,7 +900,6 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -899,7 +900,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
playbackInfo = playbackInfo =
new PlaybackInfo( new PlaybackInfo(
resetState ? Timeline.EMPTY : playbackInfo.timeline, resetState ? Timeline.EMPTY : playbackInfo.timeline,
resetState ? null : playbackInfo.manifest,
mediaPeriodId, mediaPeriodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -1276,9 +1276,8 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1276,9 +1276,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
Timeline oldTimeline = playbackInfo.timeline; Timeline oldTimeline = playbackInfo.timeline;
Timeline timeline = sourceRefreshInfo.timeline; Timeline timeline = sourceRefreshInfo.timeline;
Object manifest = sourceRefreshInfo.manifest;
queue.setTimeline(timeline); queue.setTimeline(timeline);
playbackInfo = playbackInfo.copyWithTimeline(timeline, manifest); playbackInfo = playbackInfo.copyWithTimeline(timeline);
resolvePendingMessagePositions(); resolvePendingMessagePositions();
MediaPeriodId newPeriodId = playbackInfo.periodId; MediaPeriodId newPeriodId = playbackInfo.periodId;
...@@ -1881,12 +1880,10 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -1881,12 +1880,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
public final MediaSource source; public final MediaSource source;
public final Timeline timeline; public final Timeline timeline;
public final Object manifest;
public MediaSourceRefreshInfo(MediaSource source, Timeline timeline, Object manifest) { public MediaSourceRefreshInfo(MediaSource source, Timeline timeline) {
this.source = source; this.source = source;
this.timeline = timeline; this.timeline = timeline;
this.manifest = manifest;
} }
} }
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
package com.google.android.exoplayer2; package com.google.android.exoplayer2;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectorResult; import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
...@@ -35,8 +34,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -35,8 +34,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
/** The current {@link Timeline}. */ /** The current {@link Timeline}. */
public final Timeline timeline; public final Timeline timeline;
/** The current manifest. */
@Nullable public final Object manifest;
/** The {@link MediaPeriodId} of the currently playing media period in the {@link #timeline}. */ /** The {@link MediaPeriodId} of the currently playing media period in the {@link #timeline}. */
public final MediaPeriodId periodId; public final MediaPeriodId periodId;
/** /**
...@@ -91,7 +88,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -91,7 +88,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
long startPositionUs, TrackSelectorResult emptyTrackSelectorResult) { long startPositionUs, TrackSelectorResult emptyTrackSelectorResult) {
return new PlaybackInfo( return new PlaybackInfo(
Timeline.EMPTY, Timeline.EMPTY,
/* manifest= */ null,
DUMMY_MEDIA_PERIOD_ID, DUMMY_MEDIA_PERIOD_ID,
startPositionUs, startPositionUs,
/* contentPositionUs= */ C.TIME_UNSET, /* contentPositionUs= */ C.TIME_UNSET,
...@@ -109,7 +105,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -109,7 +105,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
* Create playback info. * Create playback info.
* *
* @param timeline See {@link #timeline}. * @param timeline See {@link #timeline}.
* @param manifest See {@link #manifest}.
* @param periodId See {@link #periodId}. * @param periodId See {@link #periodId}.
* @param startPositionUs See {@link #startPositionUs}. * @param startPositionUs See {@link #startPositionUs}.
* @param contentPositionUs See {@link #contentPositionUs}. * @param contentPositionUs See {@link #contentPositionUs}.
...@@ -124,7 +119,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -124,7 +119,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
*/ */
public PlaybackInfo( public PlaybackInfo(
Timeline timeline, Timeline timeline,
@Nullable Object manifest,
MediaPeriodId periodId, MediaPeriodId periodId,
long startPositionUs, long startPositionUs,
long contentPositionUs, long contentPositionUs,
...@@ -137,7 +131,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -137,7 +131,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
long totalBufferedDurationUs, long totalBufferedDurationUs,
long positionUs) { long positionUs) {
this.timeline = timeline; this.timeline = timeline;
this.manifest = manifest;
this.periodId = periodId; this.periodId = periodId;
this.startPositionUs = startPositionUs; this.startPositionUs = startPositionUs;
this.contentPositionUs = contentPositionUs; this.contentPositionUs = contentPositionUs;
...@@ -187,7 +180,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -187,7 +180,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
long totalBufferedDurationUs) { long totalBufferedDurationUs) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
positionUs, positionUs,
periodId.isAd() ? contentPositionUs : C.TIME_UNSET, periodId.isAd() ? contentPositionUs : C.TIME_UNSET,
...@@ -202,17 +194,15 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -202,17 +194,15 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
} }
/** /**
* Copies playback info with new timeline and manifest. * Copies playback info with the new timeline.
* *
* @param timeline New timeline. See {@link #timeline}. * @param timeline New timeline. See {@link #timeline}.
* @param manifest New manifest. See {@link #manifest}. * @return Copied playback info with the new timeline.
* @return Copied playback info with new timeline and manifest.
*/ */
@CheckResult @CheckResult
public PlaybackInfo copyWithTimeline(Timeline timeline, Object manifest) { public PlaybackInfo copyWithTimeline(Timeline timeline) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -236,7 +226,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -236,7 +226,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public PlaybackInfo copyWithPlaybackState(int playbackState) { public PlaybackInfo copyWithPlaybackState(int playbackState) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -260,7 +249,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -260,7 +249,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public PlaybackInfo copyWithIsLoading(boolean isLoading) { public PlaybackInfo copyWithIsLoading(boolean isLoading) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -286,7 +274,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -286,7 +274,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
TrackGroupArray trackGroups, TrackSelectorResult trackSelectorResult) { TrackGroupArray trackGroups, TrackSelectorResult trackSelectorResult) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
...@@ -310,7 +297,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult; ...@@ -310,7 +297,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
public PlaybackInfo copyWithLoadingMediaPeriodId(MediaPeriodId loadingMediaPeriodId) { public PlaybackInfo copyWithLoadingMediaPeriodId(MediaPeriodId loadingMediaPeriodId) {
return new PlaybackInfo( return new PlaybackInfo(
timeline, timeline,
manifest,
periodId, periodId,
startPositionUs, startPositionUs,
contentPositionUs, contentPositionUs,
......
...@@ -325,6 +325,29 @@ public interface Player { ...@@ -325,6 +325,29 @@ public interface Player {
interface EventListener { interface EventListener {
/** /**
* Called when the timeline has been refreshed.
*
* <p>Note that if the timeline has changed then a position discontinuity may also have
* occurred. For example, the current period index may have changed as a result of periods being
* added or removed from the timeline. This will <em>not</em> be reported via a separate call to
* {@link #onPositionDiscontinuity(int)}.
*
* @param timeline The latest timeline. Never null, but may be empty.
* @param reason The {@link TimelineChangeReason} responsible for this timeline change.
*/
@SuppressWarnings("deprecation")
default void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
Object manifest = null;
if (timeline.getWindowCount() == 1) {
// Legacy behavior was to report the manifest for single window timelines only.
Timeline.Window window = new Timeline.Window();
manifest = timeline.getWindow(0, window).manifest;
}
// Call deprecated version.
onTimelineChanged(timeline, manifest, reason);
}
/**
* Called when the timeline and/or manifest has been refreshed. * Called when the timeline and/or manifest has been refreshed.
* *
* <p>Note that if the timeline has changed then a position discontinuity may also have * <p>Note that if the timeline has changed then a position discontinuity may also have
...@@ -335,7 +358,11 @@ public interface Player { ...@@ -335,7 +358,11 @@ public interface Player {
* @param timeline The latest timeline. Never null, but may be empty. * @param timeline The latest timeline. Never null, but may be empty.
* @param manifest The latest manifest. May be null. * @param manifest The latest manifest. May be null.
* @param reason The {@link TimelineChangeReason} responsible for this timeline change. * @param reason The {@link TimelineChangeReason} responsible for this timeline change.
* @deprecated Use {@link #onTimelineChanged(Timeline, int)} instead. The manifest can be
* accessed by using {@link #getCurrentManifest()} or {@code timeline.getWindow(windowIndex,
* window).manifest} for a given window index.
*/ */
@Deprecated
default void onTimelineChanged( default void onTimelineChanged(
Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {} Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {}
...@@ -396,8 +423,7 @@ public interface Player { ...@@ -396,8 +423,7 @@ public interface Player {
* when the source introduces a discontinuity internally). * when the source introduces a discontinuity internally).
* *
* <p>When a position discontinuity occurs as a result of a change to the timeline this method * <p>When a position discontinuity occurs as a result of a change to the timeline this method
* is <em>not</em> called. {@link #onTimelineChanged(Timeline, Object, int)} is called in this * is <em>not</em> called. {@link #onTimelineChanged(Timeline, int)} is called in this case.
* case.
* *
* @param reason The {@link DiscontinuityReason} responsible for the discontinuity. * @param reason The {@link DiscontinuityReason} responsible for the discontinuity.
*/ */
...@@ -430,13 +456,26 @@ public interface Player { ...@@ -430,13 +456,26 @@ public interface Player {
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public void onTimelineChanged(Timeline timeline, @TimelineChangeReason int reason) {
Object manifest = null;
if (timeline.getWindowCount() == 1) {
// Legacy behavior was to report the manifest for single window timelines only.
Timeline.Window window = new Timeline.Window();
manifest = timeline.getWindow(0, window).manifest;
}
// Call deprecated version.
onTimelineChanged(timeline, manifest, reason);
}
@Override
@SuppressWarnings("deprecation")
public void onTimelineChanged( public void onTimelineChanged(
Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) { Timeline timeline, @Nullable Object manifest, @TimelineChangeReason int reason) {
// Call deprecated version. Otherwise, do nothing. // Call deprecated version. Otherwise, do nothing.
onTimelineChanged(timeline, manifest); onTimelineChanged(timeline, manifest);
} }
/** @deprecated Use {@link EventListener#onTimelineChanged(Timeline, Object, int)} instead. */ /** @deprecated Use {@link EventListener#onTimelineChanged(Timeline, int)} instead. */
@Deprecated @Deprecated
public void onTimelineChanged(Timeline timeline, @Nullable Object manifest) { public void onTimelineChanged(Timeline timeline, @Nullable Object manifest) {
// Do nothing. // Do nothing.
......
...@@ -1071,13 +1071,6 @@ public class SimpleExoPlayer extends BasePlayer ...@@ -1071,13 +1071,6 @@ public class SimpleExoPlayer extends BasePlayer
} }
@Override @Override
@Nullable
public Object getCurrentManifest() {
verifyApplicationThread();
return player.getCurrentManifest();
}
@Override
public int getCurrentPeriodIndex() { public int getCurrentPeriodIndex() {
verifyApplicationThread(); verifyApplicationThread();
return player.getCurrentPeriodIndex(); return player.getCurrentPeriodIndex();
......
...@@ -122,6 +122,9 @@ public abstract class Timeline { ...@@ -122,6 +122,9 @@ public abstract class Timeline {
/** A tag for the window. Not necessarily unique. */ /** A tag for the window. Not necessarily unique. */
@Nullable public Object tag; @Nullable public Object tag;
/** The manifest of the window. May be {@code null}. */
@Nullable public Object manifest;
/** /**
* The start time of the presentation to which this window belongs in milliseconds since the * The start time of the presentation to which this window belongs in milliseconds since the
* epoch, or {@link C#TIME_UNSET} if unknown or not applicable. For informational purposes only. * epoch, or {@link C#TIME_UNSET} if unknown or not applicable. For informational purposes only.
...@@ -179,6 +182,7 @@ public abstract class Timeline { ...@@ -179,6 +182,7 @@ public abstract class Timeline {
/** Sets the data held by this window. */ /** Sets the data held by this window. */
public Window set( public Window set(
@Nullable Object tag, @Nullable Object tag,
@Nullable Object manifest,
long presentationStartTimeMs, long presentationStartTimeMs,
long windowStartTimeMs, long windowStartTimeMs,
boolean isSeekable, boolean isSeekable,
...@@ -189,6 +193,7 @@ public abstract class Timeline { ...@@ -189,6 +193,7 @@ public abstract class Timeline {
int lastPeriodIndex, int lastPeriodIndex,
long positionInFirstPeriodUs) { long positionInFirstPeriodUs) {
this.tag = tag; this.tag = tag;
this.manifest = manifest;
this.presentationStartTimeMs = presentationStartTimeMs; this.presentationStartTimeMs = presentationStartTimeMs;
this.windowStartTimeMs = windowStartTimeMs; this.windowStartTimeMs = windowStartTimeMs;
this.isSeekable = isSeekable; this.isSeekable = isSeekable;
......
...@@ -437,8 +437,7 @@ public class AnalyticsCollector ...@@ -437,8 +437,7 @@ public class AnalyticsCollector
// having slightly different real times. // having slightly different real times.
@Override @Override
public final void onTimelineChanged( public final void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) {
mediaPeriodQueueTracker.onTimelineChanged(timeline); mediaPeriodQueueTracker.onTimelineChanged(timeline);
EventTime eventTime = generatePlayingMediaPeriodEventTime(); EventTime eventTime = generatePlayingMediaPeriodEventTime();
for (AnalyticsListener listener : listeners) { for (AnalyticsListener listener : listeners) {
......
...@@ -335,6 +335,7 @@ public final class DownloadHelper { ...@@ -335,6 +335,7 @@ public final class DownloadHelper {
private final RendererCapabilities[] rendererCapabilities; private final RendererCapabilities[] rendererCapabilities;
private final SparseIntArray scratchSet; private final SparseIntArray scratchSet;
private final Handler callbackHandler; private final Handler callbackHandler;
private final Timeline.Window window;
private boolean isPreparedWithMedia; private boolean isPreparedWithMedia;
private @MonotonicNonNull Callback callback; private @MonotonicNonNull Callback callback;
...@@ -374,6 +375,7 @@ public final class DownloadHelper { ...@@ -374,6 +375,7 @@ public final class DownloadHelper {
trackSelector.setParameters(trackSelectorParameters); trackSelector.setParameters(trackSelectorParameters);
trackSelector.init(/* listener= */ () -> {}, new DummyBandwidthMeter()); trackSelector.init(/* listener= */ () -> {}, new DummyBandwidthMeter());
callbackHandler = new Handler(Util.getLooper()); callbackHandler = new Handler(Util.getLooper());
window = new Timeline.Window();
} }
/** /**
...@@ -409,7 +411,9 @@ public final class DownloadHelper { ...@@ -409,7 +411,9 @@ public final class DownloadHelper {
return null; return null;
} }
assertPreparedWithMedia(); assertPreparedWithMedia();
return mediaPreparer.manifest; return mediaPreparer.timeline.getWindowCount() > 0
? mediaPreparer.timeline.getWindow(/* windowIndex= */ 0, window).manifest
: null;
} }
/** /**
...@@ -814,7 +818,6 @@ public final class DownloadHelper { ...@@ -814,7 +818,6 @@ public final class DownloadHelper {
private final HandlerThread mediaSourceThread; private final HandlerThread mediaSourceThread;
private final Handler mediaSourceHandler; private final Handler mediaSourceHandler;
@Nullable public Object manifest;
public @MonotonicNonNull Timeline timeline; public @MonotonicNonNull Timeline timeline;
public MediaPeriod @MonotonicNonNull [] mediaPeriods; public MediaPeriod @MonotonicNonNull [] mediaPeriods;
...@@ -892,14 +895,12 @@ public final class DownloadHelper { ...@@ -892,14 +895,12 @@ public final class DownloadHelper {
// MediaSource.SourceInfoRefreshListener implementation. // MediaSource.SourceInfoRefreshListener implementation.
@Override @Override
public void onSourceInfoRefreshed( public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
MediaSource source, Timeline timeline, @Nullable Object manifest) {
if (this.timeline != null) { if (this.timeline != null) {
// Ignore dynamic updates. // Ignore dynamic updates.
return; return;
} }
this.timeline = timeline; this.timeline = timeline;
this.manifest = manifest;
mediaPeriods = new MediaPeriod[timeline.getPeriodCount()]; mediaPeriods = new MediaPeriod[timeline.getPeriodCount()];
for (int i = 0; i < mediaPeriods.length; i++) { for (int i = 0; i < mediaPeriods.length; i++) {
MediaPeriod mediaPeriod = MediaPeriod mediaPeriod =
......
...@@ -27,8 +27,8 @@ import java.util.ArrayList; ...@@ -27,8 +27,8 @@ import java.util.ArrayList;
* Base {@link MediaSource} implementation to handle parallel reuse and to keep a list of {@link * Base {@link MediaSource} implementation to handle parallel reuse and to keep a list of {@link
* MediaSourceEventListener}s. * MediaSourceEventListener}s.
* *
* <p>Whenever an implementing subclass needs to provide a new timeline and/or manifest, it must * <p>Whenever an implementing subclass needs to provide a new timeline, it must call {@link
* call {@link #refreshSourceInfo(Timeline, Object)} to notify all listeners. * #refreshSourceInfo(Timeline)} to notify all listeners.
*/ */
public abstract class BaseMediaSource implements MediaSource { public abstract class BaseMediaSource implements MediaSource {
...@@ -37,7 +37,6 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -37,7 +37,6 @@ public abstract class BaseMediaSource implements MediaSource {
@Nullable private Looper looper; @Nullable private Looper looper;
@Nullable private Timeline timeline; @Nullable private Timeline timeline;
@Nullable private Object manifest;
public BaseMediaSource() { public BaseMediaSource() {
sourceInfoListeners = new ArrayList<>(/* initialCapacity= */ 1); sourceInfoListeners = new ArrayList<>(/* initialCapacity= */ 1);
...@@ -65,13 +64,11 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -65,13 +64,11 @@ public abstract class BaseMediaSource implements MediaSource {
* Updates timeline and manifest and notifies all listeners of the update. * Updates timeline and manifest and notifies all listeners of the update.
* *
* @param timeline The new {@link Timeline}. * @param timeline The new {@link Timeline}.
* @param manifest The new manifest. May be null.
*/ */
protected final void refreshSourceInfo(Timeline timeline, @Nullable Object manifest) { protected final void refreshSourceInfo(Timeline timeline) {
this.timeline = timeline; this.timeline = timeline;
this.manifest = manifest;
for (SourceInfoRefreshListener listener : sourceInfoListeners) { for (SourceInfoRefreshListener listener : sourceInfoListeners) {
listener.onSourceInfoRefreshed(/* source= */ this, timeline, manifest); listener.onSourceInfoRefreshed(/* source= */ this, timeline);
} }
} }
...@@ -139,7 +136,7 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -139,7 +136,7 @@ public abstract class BaseMediaSource implements MediaSource {
this.looper = looper; this.looper = looper;
prepareSourceInternal(mediaTransferListener); prepareSourceInternal(mediaTransferListener);
} else if (timeline != null) { } else if (timeline != null) {
listener.onSourceInfoRefreshed(/* source= */ this, timeline, manifest); listener.onSourceInfoRefreshed(/* source= */ this, timeline);
} }
} }
...@@ -149,7 +146,6 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -149,7 +146,6 @@ public abstract class BaseMediaSource implements MediaSource {
if (sourceInfoListeners.isEmpty()) { if (sourceInfoListeners.isEmpty()) {
looper = null; looper = null;
timeline = null; timeline = null;
manifest = null;
releaseSourceInternal(); releaseSourceInternal();
} }
} }
......
...@@ -87,7 +87,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> { ...@@ -87,7 +87,6 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
private final ArrayList<ClippingMediaPeriod> mediaPeriods; private final ArrayList<ClippingMediaPeriod> mediaPeriods;
private final Timeline.Window window; private final Timeline.Window window;
@Nullable private Object manifest;
@Nullable private ClippingTimeline clippingTimeline; @Nullable private ClippingTimeline clippingTimeline;
@Nullable private IllegalClippingException clippingError; @Nullable private IllegalClippingException clippingError;
private long periodStartUs; private long periodStartUs;
...@@ -235,12 +234,10 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> { ...@@ -235,12 +234,10 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) {
Void id, MediaSource mediaSource, Timeline timeline, @Nullable Object manifest) {
if (clippingError != null) { if (clippingError != null) {
return; return;
} }
this.manifest = manifest;
refreshClippedTimeline(timeline); refreshClippedTimeline(timeline);
} }
...@@ -280,7 +277,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> { ...@@ -280,7 +277,7 @@ public final class ClippingMediaSource extends CompositeMediaSource<Void> {
clippingError = e; clippingError = e;
return; return;
} }
refreshSourceInfo(clippingTimeline, manifest); refreshSourceInfo(clippingTimeline);
} }
@Override @Override
......
...@@ -73,17 +73,15 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -73,17 +73,15 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
* @param id The unique id used to prepare the child source. * @param id The unique id used to prepare the child source.
* @param mediaSource The child source whose source info has been refreshed. * @param mediaSource The child source whose source info has been refreshed.
* @param timeline The timeline of the child source. * @param timeline The timeline of the child source.
* @param manifest The manifest of the child source.
*/ */
protected abstract void onChildSourceInfoRefreshed( protected abstract void onChildSourceInfoRefreshed(
T id, MediaSource mediaSource, Timeline timeline, @Nullable Object manifest); T id, MediaSource mediaSource, Timeline timeline);
/** /**
* Prepares a child source. * Prepares a child source.
* *
* <p>{@link #onChildSourceInfoRefreshed(Object, MediaSource, Timeline, Object)} will be called * <p>{@link #onChildSourceInfoRefreshed(Object, MediaSource, Timeline)} will be called when the
* when the child source updates its timeline and/or manifest with the same {@code id} passed to * child source updates its timeline with the same {@code id} passed to this method.
* this method.
* *
* <p>Any child sources that aren't explicitly released with {@link #releaseChildSource(Object)} * <p>Any child sources that aren't explicitly released with {@link #releaseChildSource(Object)}
* will be released in {@link #releaseSourceInternal()}. * will be released in {@link #releaseSourceInternal()}.
...@@ -94,7 +92,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -94,7 +92,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
protected final void prepareChildSource(final T id, MediaSource mediaSource) { protected final void prepareChildSource(final T id, MediaSource mediaSource) {
Assertions.checkArgument(!childSources.containsKey(id)); Assertions.checkArgument(!childSources.containsKey(id));
SourceInfoRefreshListener sourceListener = SourceInfoRefreshListener sourceListener =
(source, timeline, manifest) -> onChildSourceInfoRefreshed(id, source, timeline, manifest); new SourceInfoRefreshListener() {
@Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
onChildSourceInfoRefreshed(id, source, timeline);
}
};
MediaSourceEventListener eventListener = new ForwardingEventListener(id); MediaSourceEventListener eventListener = new ForwardingEventListener(id);
childSources.put(id, new MediaSourceAndListener(mediaSource, sourceListener, eventListener)); childSources.put(id, new MediaSourceAndListener(mediaSource, sourceListener, eventListener));
mediaSource.addEventListener(Assertions.checkNotNull(eventHandler), eventListener); mediaSource.addEventListener(Assertions.checkNotNull(eventHandler), eventListener);
......
...@@ -474,10 +474,7 @@ public final class ConcatenatingMediaSource extends CompositeMediaSource<MediaSo ...@@ -474,10 +474,7 @@ public final class ConcatenatingMediaSource extends CompositeMediaSource<MediaSo
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(
MediaSourceHolder mediaSourceHolder, MediaSourceHolder mediaSourceHolder, MediaSource mediaSource, Timeline timeline) {
MediaSource mediaSource,
Timeline timeline,
@Nullable Object manifest) {
updateMediaSourceInternal(mediaSourceHolder, timeline); updateMediaSourceInternal(mediaSourceHolder, timeline);
} }
...@@ -679,8 +676,7 @@ public final class ConcatenatingMediaSource extends CompositeMediaSource<MediaSo ...@@ -679,8 +676,7 @@ public final class ConcatenatingMediaSource extends CompositeMediaSource<MediaSo
timelineUpdateScheduled = false; timelineUpdateScheduled = false;
Set<HandlerAndRunnable> onCompletionActions = nextTimelineUpdateOnCompletionActions; Set<HandlerAndRunnable> onCompletionActions = nextTimelineUpdateOnCompletionActions;
nextTimelineUpdateOnCompletionActions = new HashSet<>(); nextTimelineUpdateOnCompletionActions = new HashSet<>();
refreshSourceInfo( refreshSourceInfo(new ConcatenatedTimeline(mediaSourceHolders, shuffleOrder, isAtomic));
new ConcatenatedTimeline(mediaSourceHolders, shuffleOrder, isAtomic), /* manifest= */ null);
getPlaybackThreadHandlerOnPlaybackThread() getPlaybackThreadHandlerOnPlaybackThread()
.obtainMessage(MSG_ON_COMPLETION, onCompletionActions) .obtainMessage(MSG_ON_COMPLETION, onCompletionActions)
.sendToTarget(); .sendToTarget();
......
...@@ -364,9 +364,8 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -364,9 +364,8 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
@Override @Override
public void onSourceInfoRefreshed( public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
MediaSource source, Timeline timeline, @Nullable Object manifest) { refreshSourceInfo(timeline);
refreshSourceInfo(timeline, manifest);
} }
@Deprecated @Deprecated
......
...@@ -100,13 +100,12 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> { ...@@ -100,13 +100,12 @@ public final class LoopingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(Void id, MediaSource mediaSource, Timeline timeline) {
Void id, MediaSource mediaSource, Timeline timeline, @Nullable Object manifest) {
Timeline loopingTimeline = Timeline loopingTimeline =
loopCount != Integer.MAX_VALUE loopCount != Integer.MAX_VALUE
? new LoopingTimeline(timeline, loopCount) ? new LoopingTimeline(timeline, loopCount)
: new InfinitelyLoopingTimeline(timeline); : new InfinitelyLoopingTimeline(timeline);
refreshSourceInfo(loopingTimeline, manifest); refreshSourceInfo(loopingTimeline);
} }
@Override @Override
......
...@@ -119,7 +119,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -119,7 +119,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(
Void id, MediaSource mediaSource, Timeline newTimeline, @Nullable Object manifest) { Void id, MediaSource mediaSource, Timeline newTimeline) {
if (isPrepared) { if (isPrepared) {
timeline = timeline.cloneWithUpdatedTimeline(newTimeline); timeline = timeline.cloneWithUpdatedTimeline(newTimeline);
} else if (newTimeline.isEmpty()) { } else if (newTimeline.isEmpty()) {
...@@ -162,7 +162,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -162,7 +162,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
} }
} }
isPrepared = true; isPrepared = true;
refreshSourceInfo(this.timeline, manifest); refreshSourceInfo(this.timeline);
} }
@Nullable @Nullable
...@@ -274,6 +274,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -274,6 +274,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
int windowIndex, Window window, boolean setTag, long defaultPositionProjectionUs) { int windowIndex, Window window, boolean setTag, long defaultPositionProjectionUs) {
return window.set( return window.set(
tag, tag,
/* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
/* isSeekable= */ false, /* isSeekable= */ false,
......
...@@ -58,8 +58,8 @@ public interface MediaPeriod extends SequenceableLoader { ...@@ -58,8 +58,8 @@ public interface MediaPeriod extends SequenceableLoader {
* *
* <p>If preparation succeeds and results in a source timeline change (e.g. the period duration * <p>If preparation succeeds and results in a source timeline change (e.g. the period duration
* becoming known), {@link * becoming known), {@link
* MediaSource.SourceInfoRefreshListener#onSourceInfoRefreshed(MediaSource, Timeline, Object)} * MediaSource.SourceInfoRefreshListener#onSourceInfoRefreshed(MediaSource, Timeline)} will be
* will be called before {@code callback.onPrepared}. * called before {@code callback.onPrepared}.
* *
* @param callback Callback to receive updates from this period, including being notified when * @param callback Callback to receive updates from this period, including being notified when
* preparation completes. * preparation completes.
......
...@@ -49,16 +49,16 @@ public interface MediaSource { ...@@ -49,16 +49,16 @@ public interface MediaSource {
interface SourceInfoRefreshListener { interface SourceInfoRefreshListener {
/** /**
* Called when manifest and/or timeline has been refreshed. * Called when the timeline has been refreshed.
* <p> *
* Called on the playback thread. * <p>Called on the playback thread.
* *
* @param source The {@link MediaSource} whose info has been refreshed. * @param source The {@link MediaSource} whose info has been refreshed.
* @param timeline The source's timeline. * @param timeline The source's timeline.
* @param manifest The loaded manifest. May be null.
*/ */
void onSourceInfoRefreshed(MediaSource source, Timeline timeline, @Nullable Object manifest); default void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
// Do nothing.
}
} }
/** /**
......
...@@ -71,7 +71,6 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> { ...@@ -71,7 +71,6 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
private final ArrayList<MediaSource> pendingTimelineSources; private final ArrayList<MediaSource> pendingTimelineSources;
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
@Nullable private Object primaryManifest;
private int periodCount; private int periodCount;
@Nullable private IllegalMergeException mergeError; @Nullable private IllegalMergeException mergeError;
...@@ -143,7 +142,6 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> { ...@@ -143,7 +142,6 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
protected void releaseSourceInternal() { protected void releaseSourceInternal() {
super.releaseSourceInternal(); super.releaseSourceInternal();
Arrays.fill(timelines, null); Arrays.fill(timelines, null);
primaryManifest = null;
periodCount = PERIOD_COUNT_UNSET; periodCount = PERIOD_COUNT_UNSET;
mergeError = null; mergeError = null;
pendingTimelineSources.clear(); pendingTimelineSources.clear();
...@@ -152,7 +150,7 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> { ...@@ -152,7 +150,7 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(
Integer id, MediaSource mediaSource, Timeline timeline, @Nullable Object manifest) { Integer id, MediaSource mediaSource, Timeline timeline) {
if (mergeError == null) { if (mergeError == null) {
mergeError = checkTimelineMerges(timeline); mergeError = checkTimelineMerges(timeline);
} }
...@@ -161,11 +159,8 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> { ...@@ -161,11 +159,8 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
} }
pendingTimelineSources.remove(mediaSource); pendingTimelineSources.remove(mediaSource);
timelines[id] = timeline; timelines[id] = timeline;
if (mediaSource == mediaSources[0]) {
primaryManifest = manifest;
}
if (pendingTimelineSources.isEmpty()) { if (pendingTimelineSources.isEmpty()) {
refreshSourceInfo(timelines[0], primaryManifest); refreshSourceInfo(timelines[0]);
} }
} }
......
...@@ -287,7 +287,10 @@ public final class ProgressiveMediaSource extends BaseMediaSource ...@@ -287,7 +287,10 @@ public final class ProgressiveMediaSource extends BaseMediaSource
// TODO: Make timeline dynamic until its duration is known. This is non-trivial. See b/69703223. // TODO: Make timeline dynamic until its duration is known. This is non-trivial. See b/69703223.
refreshSourceInfo( refreshSourceInfo(
new SinglePeriodTimeline( new SinglePeriodTimeline(
timelineDurationUs, timelineIsSeekable, /* isDynamic= */ false, tag), timelineDurationUs,
/* manifest= */ null); timelineIsSeekable,
/* isDynamic= */ false,
/* manifest= */ null,
tag));
} }
} }
...@@ -68,8 +68,7 @@ public final class SilenceMediaSource extends BaseMediaSource { ...@@ -68,8 +68,7 @@ public final class SilenceMediaSource extends BaseMediaSource {
@Override @Override
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
refreshSourceInfo( refreshSourceInfo(
new SinglePeriodTimeline(durationUs, /* isSeekable= */ true, /* isDynamic= */ false), new SinglePeriodTimeline(durationUs, /* isSeekable= */ true, /* isDynamic= */ false));
/* manifest= */ null);
} }
@Override @Override
......
...@@ -36,6 +36,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -36,6 +36,7 @@ public final class SinglePeriodTimeline extends Timeline {
private final boolean isSeekable; private final boolean isSeekable;
private final boolean isDynamic; private final boolean isDynamic;
@Nullable private final Object tag; @Nullable private final Object tag;
@Nullable private final Object manifest;
/** /**
* 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.
...@@ -45,7 +46,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -45,7 +46,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.
*/ */
public SinglePeriodTimeline(long durationUs, boolean isSeekable, boolean isDynamic) { public SinglePeriodTimeline(long durationUs, boolean isSeekable, boolean isDynamic) {
this(durationUs, isSeekable, isDynamic, /* tag= */ null); this(durationUs, isSeekable, isDynamic, /* manifest= */ null, /* tag= */ null);
} }
/** /**
...@@ -54,10 +55,15 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -54,10 +55,15 @@ public final class SinglePeriodTimeline extends Timeline {
* @param durationUs The duration of the period, in microseconds. * @param durationUs The duration of the period, in microseconds.
* @param isSeekable Whether seeking is supported within the period. * @param isSeekable Whether seeking is supported within the period.
* @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 tag A tag used for {@link Timeline.Window#tag}. * @param manifest The manifest. May be {@code null}.
* @param tag A tag used for {@link Window#tag}.
*/ */
public SinglePeriodTimeline( public SinglePeriodTimeline(
long durationUs, boolean isSeekable, boolean isDynamic, @Nullable Object tag) { long durationUs,
boolean isSeekable,
boolean isDynamic,
@Nullable Object manifest,
@Nullable Object tag) {
this( this(
durationUs, durationUs,
durationUs, durationUs,
...@@ -65,6 +71,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -65,6 +71,7 @@ public final class SinglePeriodTimeline extends Timeline {
/* windowDefaultStartPositionUs= */ 0, /* windowDefaultStartPositionUs= */ 0,
isSeekable, isSeekable,
isDynamic, isDynamic,
manifest,
tag); tag);
} }
...@@ -80,6 +87,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -80,6 +87,7 @@ public final class SinglePeriodTimeline extends Timeline {
* which to begin playback, in microseconds. * which to begin playback, in microseconds.
* @param isSeekable Whether seeking is supported within the window. * @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 manifest The manifest. May be (@code null}.
* @param tag A tag used for {@link Timeline.Window#tag}. * @param tag A tag used for {@link Timeline.Window#tag}.
*/ */
public SinglePeriodTimeline( public SinglePeriodTimeline(
...@@ -89,6 +97,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -89,6 +97,7 @@ public final class SinglePeriodTimeline extends Timeline {
long windowDefaultStartPositionUs, long windowDefaultStartPositionUs,
boolean isSeekable, boolean isSeekable,
boolean isDynamic, boolean isDynamic,
@Nullable Object manifest,
@Nullable Object tag) { @Nullable Object tag) {
this( this(
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
...@@ -99,6 +108,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -99,6 +108,7 @@ public final class SinglePeriodTimeline extends Timeline {
windowDefaultStartPositionUs, windowDefaultStartPositionUs,
isSeekable, isSeekable,
isDynamic, isDynamic,
manifest,
tag); tag);
} }
...@@ -117,6 +127,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -117,6 +127,7 @@ public final class SinglePeriodTimeline extends Timeline {
* which to begin playback, in microseconds. * which to begin playback, in microseconds.
* @param isSeekable Whether seeking is supported within the window. * @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 manifest The manifest. May be {@code null}.
* @param tag A tag used for {@link Timeline.Window#tag}. * @param tag A tag used for {@link Timeline.Window#tag}.
*/ */
public SinglePeriodTimeline( public SinglePeriodTimeline(
...@@ -128,6 +139,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -128,6 +139,7 @@ public final class SinglePeriodTimeline extends Timeline {
long windowDefaultStartPositionUs, long windowDefaultStartPositionUs,
boolean isSeekable, boolean isSeekable,
boolean isDynamic, boolean isDynamic,
@Nullable Object manifest,
@Nullable Object tag) { @Nullable Object tag) {
this.presentationStartTimeMs = presentationStartTimeMs; this.presentationStartTimeMs = presentationStartTimeMs;
this.windowStartTimeMs = windowStartTimeMs; this.windowStartTimeMs = windowStartTimeMs;
...@@ -137,6 +149,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -137,6 +149,7 @@ public final class SinglePeriodTimeline extends Timeline {
this.windowDefaultStartPositionUs = windowDefaultStartPositionUs; this.windowDefaultStartPositionUs = windowDefaultStartPositionUs;
this.isSeekable = isSeekable; this.isSeekable = isSeekable;
this.isDynamic = isDynamic; this.isDynamic = isDynamic;
this.manifest = manifest;
this.tag = tag; this.tag = tag;
} }
...@@ -165,6 +178,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -165,6 +178,7 @@ public final class SinglePeriodTimeline extends Timeline {
} }
return window.set( return window.set(
tag, tag,
manifest,
presentationStartTimeMs, presentationStartTimeMs,
windowStartTimeMs, windowStartTimeMs,
isSeekable, isSeekable,
......
...@@ -290,7 +290,8 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -290,7 +290,8 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
this.tag = tag; this.tag = tag;
dataSpec = new DataSpec(uri, DataSpec.FLAG_ALLOW_GZIP); dataSpec = new DataSpec(uri, DataSpec.FLAG_ALLOW_GZIP);
timeline = timeline =
new SinglePeriodTimeline(durationUs, /* isSeekable= */ true, /* isDynamic= */ false, tag); new SinglePeriodTimeline(
durationUs, /* isSeekable= */ true, /* isDynamic= */ false, /* manifest= */ null, tag);
} }
// MediaSource implementation. // MediaSource implementation.
...@@ -304,7 +305,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -304,7 +305,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
@Override @Override
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
transferListener = mediaTransferListener; transferListener = mediaTransferListener;
refreshSourceInfo(timeline, /* manifest= */ null); refreshSourceInfo(timeline);
} }
@Override @Override
......
...@@ -134,7 +134,6 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -134,7 +134,6 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
// Accessed on the player thread. // Accessed on the player thread.
@Nullable private ComponentListener componentListener; @Nullable private ComponentListener componentListener;
@Nullable private Timeline contentTimeline; @Nullable private Timeline contentTimeline;
@Nullable private Object contentManifest;
@Nullable private AdPlaybackState adPlaybackState; @Nullable private AdPlaybackState adPlaybackState;
private @NullableType MediaSource[][] adGroupMediaSources; private @NullableType MediaSource[][] adGroupMediaSources;
private @NullableType Timeline[][] adGroupTimelines; private @NullableType Timeline[][] adGroupTimelines;
...@@ -265,7 +264,6 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -265,7 +264,6 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
componentListener = null; componentListener = null;
maskingMediaPeriodByAdMediaSource.clear(); maskingMediaPeriodByAdMediaSource.clear();
contentTimeline = null; contentTimeline = null;
contentManifest = null;
adPlaybackState = null; adPlaybackState = null;
adGroupMediaSources = new MediaSource[0][]; adGroupMediaSources = new MediaSource[0][];
adGroupTimelines = new Timeline[0][]; adGroupTimelines = new Timeline[0][];
...@@ -274,16 +272,13 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -274,16 +272,13 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
@Override @Override
protected void onChildSourceInfoRefreshed( protected void onChildSourceInfoRefreshed(
MediaPeriodId mediaPeriodId, MediaPeriodId mediaPeriodId, MediaSource mediaSource, Timeline timeline) {
MediaSource mediaSource,
Timeline timeline,
@Nullable Object manifest) {
if (mediaPeriodId.isAd()) { if (mediaPeriodId.isAd()) {
int adGroupIndex = mediaPeriodId.adGroupIndex; int adGroupIndex = mediaPeriodId.adGroupIndex;
int adIndexInAdGroup = mediaPeriodId.adIndexInAdGroup; int adIndexInAdGroup = mediaPeriodId.adIndexInAdGroup;
onAdSourceInfoRefreshed(mediaSource, adGroupIndex, adIndexInAdGroup, timeline); onAdSourceInfoRefreshed(mediaSource, adGroupIndex, adIndexInAdGroup, timeline);
} else { } else {
onContentSourceInfoRefreshed(timeline, manifest); onContentSourceInfoRefreshed(timeline);
} }
} }
...@@ -308,10 +303,9 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -308,10 +303,9 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
maybeUpdateSourceInfo(); maybeUpdateSourceInfo();
} }
private void onContentSourceInfoRefreshed(Timeline timeline, @Nullable Object manifest) { private void onContentSourceInfoRefreshed(Timeline timeline) {
Assertions.checkArgument(timeline.getPeriodCount() == 1); Assertions.checkArgument(timeline.getPeriodCount() == 1);
contentTimeline = timeline; contentTimeline = timeline;
contentManifest = manifest;
maybeUpdateSourceInfo(); maybeUpdateSourceInfo();
} }
...@@ -340,7 +334,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -340,7 +334,7 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
adPlaybackState.adGroupCount == 0 adPlaybackState.adGroupCount == 0
? contentTimeline ? contentTimeline
: new SinglePeriodAdTimeline(contentTimeline, adPlaybackState); : new SinglePeriodAdTimeline(contentTimeline, adPlaybackState);
refreshSourceInfo(timeline, contentManifest); refreshSourceInfo(timeline);
} }
} }
......
...@@ -353,7 +353,6 @@ public final class MediaPeriodQueueTest { ...@@ -353,7 +353,6 @@ public final class MediaPeriodQueueTest {
playbackInfo = playbackInfo =
new PlaybackInfo( new PlaybackInfo(
timeline, timeline,
/* manifest= */ null,
mediaPeriodQueue.resolveMediaPeriodIdForAds(periodUid, initialPositionUs), mediaPeriodQueue.resolveMediaPeriodIdForAds(periodUid, initialPositionUs),
/* startPositionUs= */ 0, /* startPositionUs= */ 0,
/* contentPositionUs= */ 0, /* contentPositionUs= */ 0,
......
...@@ -125,7 +125,9 @@ public final class AnalyticsCollectorTest { ...@@ -125,7 +125,9 @@ public final class AnalyticsCollectorTest {
public void testEmptyTimeline() throws Exception { public void testEmptyTimeline() throws Exception {
FakeMediaSource mediaSource = FakeMediaSource mediaSource =
new FakeMediaSource( new FakeMediaSource(
Timeline.EMPTY, /* manifest= */ null, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT); Timeline.EMPTY,
ExoPlayerTestRunner.Builder.VIDEO_FORMAT,
ExoPlayerTestRunner.Builder.AUDIO_FORMAT);
TestAnalyticsListener listener = runAnalyticsTest(mediaSource); TestAnalyticsListener listener = runAnalyticsTest(mediaSource);
assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED)) assertThat(listener.getEvents(EVENT_PLAYER_STATE_CHANGED))
...@@ -140,7 +142,6 @@ public final class AnalyticsCollectorTest { ...@@ -140,7 +142,6 @@ public final class AnalyticsCollectorTest {
FakeMediaSource mediaSource = FakeMediaSource mediaSource =
new FakeMediaSource( new FakeMediaSource(
SINGLE_PERIOD_TIMELINE, SINGLE_PERIOD_TIMELINE,
/* manifest= */ null,
Builder.VIDEO_FORMAT, Builder.VIDEO_FORMAT,
Builder.AUDIO_FORMAT); Builder.AUDIO_FORMAT);
TestAnalyticsListener listener = runAnalyticsTest(mediaSource); TestAnalyticsListener listener = runAnalyticsTest(mediaSource);
...@@ -183,12 +184,10 @@ public final class AnalyticsCollectorTest { ...@@ -183,12 +184,10 @@ public final class AnalyticsCollectorTest {
new ConcatenatingMediaSource( new ConcatenatingMediaSource(
new FakeMediaSource( new FakeMediaSource(
SINGLE_PERIOD_TIMELINE, SINGLE_PERIOD_TIMELINE,
/* manifest= */ null,
Builder.VIDEO_FORMAT, Builder.VIDEO_FORMAT,
Builder.AUDIO_FORMAT), Builder.AUDIO_FORMAT),
new FakeMediaSource( new FakeMediaSource(
SINGLE_PERIOD_TIMELINE, SINGLE_PERIOD_TIMELINE,
/* manifest= */ null,
Builder.VIDEO_FORMAT, Builder.VIDEO_FORMAT,
Builder.AUDIO_FORMAT)); Builder.AUDIO_FORMAT));
TestAnalyticsListener listener = runAnalyticsTest(mediaSource); TestAnalyticsListener listener = runAnalyticsTest(mediaSource);
...@@ -242,9 +241,8 @@ public final class AnalyticsCollectorTest { ...@@ -242,9 +241,8 @@ public final class AnalyticsCollectorTest {
public void testPeriodTransitionWithRendererChange() throws Exception { public void testPeriodTransitionWithRendererChange() throws Exception {
MediaSource mediaSource = MediaSource mediaSource =
new ConcatenatingMediaSource( new ConcatenatingMediaSource(
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT),
new FakeMediaSource( new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.AUDIO_FORMAT));
SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.AUDIO_FORMAT));
TestAnalyticsListener listener = runAnalyticsTest(mediaSource); TestAnalyticsListener listener = runAnalyticsTest(mediaSource);
populateEventIds(listener.lastReportedTimeline); populateEventIds(listener.lastReportedTimeline);
...@@ -296,9 +294,8 @@ public final class AnalyticsCollectorTest { ...@@ -296,9 +294,8 @@ public final class AnalyticsCollectorTest {
public void testSeekToOtherPeriod() throws Exception { public void testSeekToOtherPeriod() throws Exception {
MediaSource mediaSource = MediaSource mediaSource =
new ConcatenatingMediaSource( new ConcatenatingMediaSource(
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT),
new FakeMediaSource( new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.AUDIO_FORMAT));
SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.AUDIO_FORMAT));
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
new ActionSchedule.Builder("AnalyticsCollectorTest") new ActionSchedule.Builder("AnalyticsCollectorTest")
.pause() .pause()
...@@ -361,12 +358,9 @@ public final class AnalyticsCollectorTest { ...@@ -361,12 +358,9 @@ public final class AnalyticsCollectorTest {
public void testSeekBackAfterReadingAhead() throws Exception { public void testSeekBackAfterReadingAhead() throws Exception {
MediaSource mediaSource = MediaSource mediaSource =
new ConcatenatingMediaSource( new ConcatenatingMediaSource(
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT), new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT),
new FakeMediaSource( new FakeMediaSource(
SINGLE_PERIOD_TIMELINE, SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT, Builder.AUDIO_FORMAT));
/* manifest= */ null,
Builder.VIDEO_FORMAT,
Builder.AUDIO_FORMAT));
long periodDurationMs = long periodDurationMs =
SINGLE_PERIOD_TIMELINE.getWindow(/* windowIndex= */ 0, new Window()).getDurationMs(); SINGLE_PERIOD_TIMELINE.getWindow(/* windowIndex= */ 0, new Window()).getDurationMs();
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
...@@ -443,10 +437,8 @@ public final class AnalyticsCollectorTest { ...@@ -443,10 +437,8 @@ public final class AnalyticsCollectorTest {
@Test @Test
public void testPrepareNewSource() throws Exception { public void testPrepareNewSource() throws Exception {
MediaSource mediaSource1 = MediaSource mediaSource1 = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT);
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT); MediaSource mediaSource2 = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT);
MediaSource mediaSource2 =
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT);
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
new ActionSchedule.Builder("AnalyticsCollectorTest") new ActionSchedule.Builder("AnalyticsCollectorTest")
.pause() .pause()
...@@ -507,8 +499,7 @@ public final class AnalyticsCollectorTest { ...@@ -507,8 +499,7 @@ public final class AnalyticsCollectorTest {
@Test @Test
public void testReprepareAfterError() throws Exception { public void testReprepareAfterError() throws Exception {
MediaSource mediaSource = MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT);
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT);
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
new ActionSchedule.Builder("AnalyticsCollectorTest") new ActionSchedule.Builder("AnalyticsCollectorTest")
.waitForPlaybackState(Player.STATE_READY) .waitForPlaybackState(Player.STATE_READY)
...@@ -570,7 +561,7 @@ public final class AnalyticsCollectorTest { ...@@ -570,7 +561,7 @@ public final class AnalyticsCollectorTest {
@Test @Test
public void testDynamicTimelineChange() throws Exception { public void testDynamicTimelineChange() throws Exception {
MediaSource childMediaSource = MediaSource childMediaSource =
new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null, Builder.VIDEO_FORMAT); new FakeMediaSource(SINGLE_PERIOD_TIMELINE, Builder.VIDEO_FORMAT);
final ConcatenatingMediaSource concatenatedMediaSource = final ConcatenatingMediaSource concatenatedMediaSource =
new ConcatenatingMediaSource(childMediaSource, childMediaSource); new ConcatenatingMediaSource(childMediaSource, childMediaSource);
long periodDurationMs = long periodDurationMs =
...@@ -639,7 +630,7 @@ public final class AnalyticsCollectorTest { ...@@ -639,7 +630,7 @@ public final class AnalyticsCollectorTest {
@Test @Test
public void testNotifyExternalEvents() throws Exception { public void testNotifyExternalEvents() throws Exception {
MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE, /* manifest= */ null); MediaSource mediaSource = new FakeMediaSource(SINGLE_PERIOD_TIMELINE);
ActionSchedule actionSchedule = ActionSchedule actionSchedule =
new ActionSchedule.Builder("AnalyticsCollectorTest") new ActionSchedule.Builder("AnalyticsCollectorTest")
.pause() .pause()
......
...@@ -60,9 +60,11 @@ public class DownloadHelperTest { ...@@ -60,9 +60,11 @@ public class DownloadHelperTest {
private static final String TEST_DOWNLOAD_TYPE = "downloadType"; private static final String TEST_DOWNLOAD_TYPE = "downloadType";
private static final String TEST_CACHE_KEY = "cacheKey"; private static final String TEST_CACHE_KEY = "cacheKey";
private static final Timeline TEST_TIMELINE =
new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ new Object()));
private static final Object TEST_MANIFEST = new Object(); private static final Object TEST_MANIFEST = new Object();
private static final Timeline TEST_TIMELINE =
new FakeTimeline(
new Object[] {TEST_MANIFEST},
new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ new Object()));
private static final Format VIDEO_FORMAT_LOW = createVideoFormat(/* bitrate= */ 200_000); private static final Format VIDEO_FORMAT_LOW = createVideoFormat(/* bitrate= */ 200_000);
private static final Format VIDEO_FORMAT_HIGH = createVideoFormat(/* bitrate= */ 800_000); private static final Format VIDEO_FORMAT_HIGH = createVideoFormat(/* bitrate= */ 800_000);
...@@ -491,7 +493,7 @@ public class DownloadHelperTest { ...@@ -491,7 +493,7 @@ public class DownloadHelperTest {
private static final class TestMediaSource extends FakeMediaSource { private static final class TestMediaSource extends FakeMediaSource {
public TestMediaSource() { public TestMediaSource() {
super(TEST_TIMELINE, TEST_MANIFEST); super(TEST_TIMELINE);
} }
@Override @Override
......
...@@ -185,6 +185,7 @@ public final class ClippingMediaSourceTest { ...@@ -185,6 +185,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline clippedTimeline = getClippedTimeline(timeline, /* durationUs= */ TEST_CLIP_AMOUNT_US); Timeline clippedTimeline = getClippedTimeline(timeline, /* durationUs= */ TEST_CLIP_AMOUNT_US);
...@@ -206,6 +207,7 @@ public final class ClippingMediaSourceTest { ...@@ -206,6 +207,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
...@@ -215,6 +217,7 @@ public final class ClippingMediaSourceTest { ...@@ -215,6 +217,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
...@@ -253,6 +256,7 @@ public final class ClippingMediaSourceTest { ...@@ -253,6 +256,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
...@@ -262,6 +266,7 @@ public final class ClippingMediaSourceTest { ...@@ -262,6 +266,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
...@@ -300,6 +305,7 @@ public final class ClippingMediaSourceTest { ...@@ -300,6 +305,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
...@@ -309,6 +315,7 @@ public final class ClippingMediaSourceTest { ...@@ -309,6 +315,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
...@@ -348,6 +355,7 @@ public final class ClippingMediaSourceTest { ...@@ -348,6 +355,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline timeline2 = Timeline timeline2 =
new SinglePeriodTimeline( new SinglePeriodTimeline(
...@@ -357,6 +365,7 @@ public final class ClippingMediaSourceTest { ...@@ -357,6 +365,7 @@ public final class ClippingMediaSourceTest {
/* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US, /* windowDefaultStartPositionUs= */ TEST_CLIP_AMOUNT_US,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Timeline[] clippedTimelines = Timeline[] clippedTimelines =
...@@ -473,7 +482,7 @@ public final class ClippingMediaSourceTest { ...@@ -473,7 +482,7 @@ public final class ClippingMediaSourceTest {
new SinglePeriodTimeline( new SinglePeriodTimeline(
TEST_PERIOD_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false); TEST_PERIOD_DURATION_US, /* isSeekable= */ true, /* isDynamic= */ false);
FakeMediaSource fakeMediaSource = FakeMediaSource fakeMediaSource =
new FakeMediaSource(timeline, /* manifest= */ null) { new FakeMediaSource(timeline) {
@Override @Override
protected FakeMediaPeriod createFakeMediaPeriod( protected FakeMediaPeriod createFakeMediaPeriod(
MediaPeriodId id, MediaPeriodId id,
...@@ -530,7 +539,7 @@ public final class ClippingMediaSourceTest { ...@@ -530,7 +539,7 @@ public final class ClippingMediaSourceTest {
*/ */
private static Timeline getClippedTimeline(Timeline timeline, long startUs, long endUs) private static Timeline getClippedTimeline(Timeline timeline, long startUs, long endUs)
throws IOException { throws IOException {
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline, /* manifest= */ null); FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, startUs, endUs); ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, startUs, endUs);
return getClippedTimelines(fakeMediaSource, mediaSource)[0]; return getClippedTimelines(fakeMediaSource, mediaSource)[0];
} }
...@@ -540,7 +549,7 @@ public final class ClippingMediaSourceTest { ...@@ -540,7 +549,7 @@ public final class ClippingMediaSourceTest {
*/ */
private static Timeline getClippedTimeline(Timeline timeline, long durationUs) private static Timeline getClippedTimeline(Timeline timeline, long durationUs)
throws IOException { throws IOException {
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline, /* manifest= */ null); FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, durationUs); ClippingMediaSource mediaSource = new ClippingMediaSource(fakeMediaSource, durationUs);
return getClippedTimelines(fakeMediaSource, mediaSource)[0]; return getClippedTimelines(fakeMediaSource, mediaSource)[0];
} }
...@@ -557,7 +566,7 @@ public final class ClippingMediaSourceTest { ...@@ -557,7 +566,7 @@ public final class ClippingMediaSourceTest {
Timeline firstTimeline, Timeline firstTimeline,
Timeline... additionalTimelines) Timeline... additionalTimelines)
throws IOException { throws IOException {
FakeMediaSource fakeMediaSource = new FakeMediaSource(firstTimeline, /* manifest= */ null); FakeMediaSource fakeMediaSource = new FakeMediaSource(firstTimeline);
ClippingMediaSource mediaSource = ClippingMediaSource mediaSource =
new ClippingMediaSource( new ClippingMediaSource(
fakeMediaSource, fakeMediaSource,
......
...@@ -226,7 +226,7 @@ public final class ConcatenatingMediaSourceTest { ...@@ -226,7 +226,7 @@ public final class ConcatenatingMediaSourceTest {
FakeMediaSource[] fastSources = createMediaSources(2); FakeMediaSource[] fastSources = createMediaSources(2);
final FakeMediaSource[] lazySources = new FakeMediaSource[4]; final FakeMediaSource[] lazySources = new FakeMediaSource[4];
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
lazySources[i] = new FakeMediaSource(null, null); lazySources[i] = new FakeMediaSource(null);
} }
// Add lazy sources and normal sources before preparation. Also remove one lazy source again // Add lazy sources and normal sources before preparation. Also remove one lazy source again
...@@ -307,16 +307,16 @@ public final class ConcatenatingMediaSourceTest { ...@@ -307,16 +307,16 @@ public final class ConcatenatingMediaSourceTest {
Timeline timeline = testRunner.prepareSource(); Timeline timeline = testRunner.prepareSource();
TimelineAsserts.assertEmpty(timeline); TimelineAsserts.assertEmpty(timeline);
mediaSource.addMediaSource(new FakeMediaSource(Timeline.EMPTY, null)); mediaSource.addMediaSource(new FakeMediaSource(Timeline.EMPTY));
timeline = testRunner.assertTimelineChangeBlocking(); timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertEmpty(timeline); TimelineAsserts.assertEmpty(timeline);
mediaSource.addMediaSources( mediaSource.addMediaSources(
Arrays.asList( Arrays.asList(
new MediaSource[] { new MediaSource[] {
new FakeMediaSource(Timeline.EMPTY, null), new FakeMediaSource(Timeline.EMPTY, null), new FakeMediaSource(Timeline.EMPTY), new FakeMediaSource(Timeline.EMPTY),
new FakeMediaSource(Timeline.EMPTY, null), new FakeMediaSource(Timeline.EMPTY, null), new FakeMediaSource(Timeline.EMPTY), new FakeMediaSource(Timeline.EMPTY),
new FakeMediaSource(Timeline.EMPTY, null), new FakeMediaSource(Timeline.EMPTY, null) new FakeMediaSource(Timeline.EMPTY), new FakeMediaSource(Timeline.EMPTY)
})); }));
timeline = testRunner.assertTimelineChangeBlocking(); timeline = testRunner.assertTimelineChangeBlocking();
TimelineAsserts.assertEmpty(timeline); TimelineAsserts.assertEmpty(timeline);
...@@ -362,9 +362,9 @@ public final class ConcatenatingMediaSourceTest { ...@@ -362,9 +362,9 @@ public final class ConcatenatingMediaSourceTest {
public void testDynamicChangeOfEmptyTimelines() throws IOException { public void testDynamicChangeOfEmptyTimelines() throws IOException {
FakeMediaSource[] childSources = FakeMediaSource[] childSources =
new FakeMediaSource[] { new FakeMediaSource[] {
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null), new FakeMediaSource(Timeline.EMPTY),
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null), new FakeMediaSource(Timeline.EMPTY),
new FakeMediaSource(Timeline.EMPTY, /* manifest= */ null), new FakeMediaSource(Timeline.EMPTY),
}; };
Timeline nonEmptyTimeline = new FakeTimeline(/* windowCount = */ 1); Timeline nonEmptyTimeline = new FakeTimeline(/* windowCount = */ 1);
...@@ -387,7 +387,7 @@ public final class ConcatenatingMediaSourceTest { ...@@ -387,7 +387,7 @@ public final class ConcatenatingMediaSourceTest {
@Test @Test
public void testIllegalArguments() { public void testIllegalArguments() {
MediaSource validSource = new FakeMediaSource(createFakeTimeline(1), null); MediaSource validSource = new FakeMediaSource(createFakeTimeline(1));
// Null sources. // Null sources.
try { try {
...@@ -660,8 +660,8 @@ public final class ConcatenatingMediaSourceTest { ...@@ -660,8 +660,8 @@ public final class ConcatenatingMediaSourceTest {
10 * C.MICROS_PER_SECOND, 10 * C.MICROS_PER_SECOND,
FakeTimeline.createAdPlaybackState( FakeTimeline.createAdPlaybackState(
/* adsPerAdGroup= */ 1, /* adGroupTimesUs= */ 0))); /* adsPerAdGroup= */ 1, /* adGroupTimesUs= */ 0)));
FakeMediaSource mediaSourceContentOnly = new FakeMediaSource(timelineContentOnly, null); FakeMediaSource mediaSourceContentOnly = new FakeMediaSource(timelineContentOnly);
FakeMediaSource mediaSourceWithAds = new FakeMediaSource(timelineWithAds, null); FakeMediaSource mediaSourceWithAds = new FakeMediaSource(timelineWithAds);
mediaSource.addMediaSource(mediaSourceContentOnly); mediaSource.addMediaSource(mediaSourceContentOnly);
mediaSource.addMediaSource(mediaSourceWithAds); mediaSource.addMediaSource(mediaSourceWithAds);
...@@ -807,7 +807,7 @@ public final class ConcatenatingMediaSourceTest { ...@@ -807,7 +807,7 @@ public final class ConcatenatingMediaSourceTest {
@Test @Test
public void testDuplicateMediaSources() throws IOException, InterruptedException { public void testDuplicateMediaSources() throws IOException, InterruptedException {
Timeline childTimeline = new FakeTimeline(/* windowCount= */ 2); Timeline childTimeline = new FakeTimeline(/* windowCount= */ 2);
FakeMediaSource childSource = new FakeMediaSource(childTimeline, /* manifest= */ null); FakeMediaSource childSource = new FakeMediaSource(childTimeline);
mediaSource.addMediaSource(childSource); mediaSource.addMediaSource(childSource);
mediaSource.addMediaSource(childSource); mediaSource.addMediaSource(childSource);
...@@ -840,7 +840,7 @@ public final class ConcatenatingMediaSourceTest { ...@@ -840,7 +840,7 @@ public final class ConcatenatingMediaSourceTest {
@Test @Test
public void testDuplicateNestedMediaSources() throws IOException, InterruptedException { public void testDuplicateNestedMediaSources() throws IOException, InterruptedException {
Timeline childTimeline = new FakeTimeline(/* windowCount= */ 1); Timeline childTimeline = new FakeTimeline(/* windowCount= */ 1);
FakeMediaSource childSource = new FakeMediaSource(childTimeline, /* manifest= */ null); FakeMediaSource childSource = new FakeMediaSource(childTimeline);
ConcatenatingMediaSource nestedConcatenation = new ConcatenatingMediaSource(); ConcatenatingMediaSource nestedConcatenation = new ConcatenatingMediaSource();
testRunner.prepareSource(); testRunner.prepareSource();
...@@ -874,8 +874,7 @@ public final class ConcatenatingMediaSourceTest { ...@@ -874,8 +874,7 @@ public final class ConcatenatingMediaSourceTest {
public void testClear() throws IOException { public void testClear() throws IOException {
DummyMainThread dummyMainThread = new DummyMainThread(); DummyMainThread dummyMainThread = new DummyMainThread();
final FakeMediaSource preparedChildSource = createFakeMediaSource(); final FakeMediaSource preparedChildSource = createFakeMediaSource();
final FakeMediaSource unpreparedChildSource = final FakeMediaSource unpreparedChildSource = new FakeMediaSource(/* timeline= */ null);
new FakeMediaSource(/* timeline= */ null, /* manifest= */ null);
dummyMainThread.runOnMainThread( dummyMainThread.runOnMainThread(
() -> { () -> {
mediaSource.addMediaSource(preparedChildSource); mediaSource.addMediaSource(preparedChildSource);
...@@ -1092,13 +1091,13 @@ public final class ConcatenatingMediaSourceTest { ...@@ -1092,13 +1091,13 @@ public final class ConcatenatingMediaSourceTest {
private static FakeMediaSource[] createMediaSources(int count) { private static FakeMediaSource[] createMediaSources(int count) {
FakeMediaSource[] sources = new FakeMediaSource[count]; FakeMediaSource[] sources = new FakeMediaSource[count];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
sources[i] = new FakeMediaSource(createFakeTimeline(i), null); sources[i] = new FakeMediaSource(createFakeTimeline(i));
} }
return sources; return sources;
} }
private static FakeMediaSource createFakeMediaSource() { private static FakeMediaSource createFakeMediaSource() {
return new FakeMediaSource(createFakeTimeline(/* index */ 0), null); return new FakeMediaSource(createFakeTimeline(/* index */ 0));
} }
private static FakeTimeline createFakeTimeline(int index) { private static FakeTimeline createFakeTimeline(int index) {
......
...@@ -135,7 +135,7 @@ public class LoopingMediaSourceTest { ...@@ -135,7 +135,7 @@ public class LoopingMediaSourceTest {
* Wraps the specified timeline in a {@link LoopingMediaSource} and returns the looping timeline. * Wraps the specified timeline in a {@link LoopingMediaSource} and returns the looping timeline.
*/ */
private static Timeline getLoopingTimeline(Timeline timeline, int loopCount) throws IOException { private static Timeline getLoopingTimeline(Timeline timeline, int loopCount) throws IOException {
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline, null); FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
LoopingMediaSource mediaSource = new LoopingMediaSource(fakeMediaSource, loopCount); LoopingMediaSource mediaSource = new LoopingMediaSource(fakeMediaSource, loopCount);
MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null); MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null);
try { try {
...@@ -153,7 +153,7 @@ public class LoopingMediaSourceTest { ...@@ -153,7 +153,7 @@ public class LoopingMediaSourceTest {
* the looping timeline can be created and prepared. * the looping timeline can be created and prepared.
*/ */
private static void testMediaPeriodCreation(Timeline timeline, int loopCount) throws Exception { private static void testMediaPeriodCreation(Timeline timeline, int loopCount) throws Exception {
FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline, null); FakeMediaSource fakeMediaSource = new FakeMediaSource(timeline);
LoopingMediaSource mediaSource = new LoopingMediaSource(fakeMediaSource, loopCount); LoopingMediaSource mediaSource = new LoopingMediaSource(fakeMediaSource, loopCount);
MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null); MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null);
try { try {
......
...@@ -68,8 +68,7 @@ public class MergingMediaSourceTest { ...@@ -68,8 +68,7 @@ public class MergingMediaSourceTest {
public void testMergingMediaSourcePeriodCreation() throws Exception { public void testMergingMediaSourcePeriodCreation() throws Exception {
FakeMediaSource[] mediaSources = new FakeMediaSource[2]; FakeMediaSource[] mediaSources = new FakeMediaSource[2];
for (int i = 0; i < mediaSources.length; i++) { for (int i = 0; i < mediaSources.length; i++) {
mediaSources[i] = mediaSources[i] = new FakeMediaSource(new FakeTimeline(/* windowCount= */ 2));
new FakeMediaSource(new FakeTimeline(/* windowCount= */ 2), /* manifest= */ null);
} }
MergingMediaSource mediaSource = new MergingMediaSource(mediaSources); MergingMediaSource mediaSource = new MergingMediaSource(mediaSources);
MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null); MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null);
...@@ -92,7 +91,7 @@ public class MergingMediaSourceTest { ...@@ -92,7 +91,7 @@ public class MergingMediaSourceTest {
private static void testMergingMediaSourcePrepare(Timeline... timelines) throws IOException { private static void testMergingMediaSourcePrepare(Timeline... timelines) throws IOException {
FakeMediaSource[] mediaSources = new FakeMediaSource[timelines.length]; FakeMediaSource[] mediaSources = new FakeMediaSource[timelines.length];
for (int i = 0; i < timelines.length; i++) { for (int i = 0; i < timelines.length; i++) {
mediaSources[i] = new FakeMediaSource(timelines[i], null); mediaSources[i] = new FakeMediaSource(timelines[i]);
} }
MergingMediaSource mergingMediaSource = new MergingMediaSource(mediaSources); MergingMediaSource mergingMediaSource = new MergingMediaSource(mediaSources);
MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mergingMediaSource, null); MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mergingMediaSource, null);
......
...@@ -62,6 +62,7 @@ public final class SinglePeriodTimelineTest { ...@@ -62,6 +62,7 @@ public final class SinglePeriodTimelineTest {
/* windowDefaultStartPositionUs= */ 0, /* windowDefaultStartPositionUs= */ 0,
/* isSeekable= */ false, /* isSeekable= */ false,
/* isDynamic= */ true, /* isDynamic= */ true,
/* manifest= */ null,
/* tag= */ null); /* tag= */ 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 =
...@@ -84,6 +85,7 @@ public final class SinglePeriodTimelineTest { ...@@ -84,6 +85,7 @@ public final class SinglePeriodTimelineTest {
/* durationUs= */ C.TIME_UNSET, /* durationUs= */ C.TIME_UNSET,
/* isSeekable= */ false, /* isSeekable= */ false,
/* isDynamic= */ false, /* isDynamic= */ false,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ false).tag).isNull(); assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ false).tag).isNull();
...@@ -100,7 +102,11 @@ public final class SinglePeriodTimelineTest { ...@@ -100,7 +102,11 @@ public final class SinglePeriodTimelineTest {
Object tag = new Object(); Object tag = new Object();
SinglePeriodTimeline timeline = SinglePeriodTimeline timeline =
new SinglePeriodTimeline( new SinglePeriodTimeline(
/* durationUs= */ C.TIME_UNSET, /* isSeekable= */ false, /* isDynamic= */ false, tag); /* durationUs= */ C.TIME_UNSET,
/* isSeekable= */ false,
/* isDynamic= */ false,
/* manifest= */ null,
tag);
assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ false).tag).isNull(); assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ false).tag).isNull();
assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ true).tag) assertThat(timeline.getWindow(/* windowIndex= */ 0, window, /* setTag= */ true).tag)
...@@ -114,6 +120,7 @@ public final class SinglePeriodTimelineTest { ...@@ -114,6 +120,7 @@ public final class SinglePeriodTimelineTest {
/* durationUs= */ C.TIME_UNSET, /* durationUs= */ C.TIME_UNSET,
/* isSeekable= */ false, /* isSeekable= */ false,
/* isDynamic= */ false, /* isDynamic= */ false,
/* manifest= */ null,
/* tag= */ null); /* tag= */ null);
Object uid = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid; Object uid = timeline.getPeriod(/* periodIndex= */ 0, period, /* setIds= */ true).uid;
......
...@@ -994,7 +994,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -994,7 +994,7 @@ public final class DashMediaSource extends BaseMediaSource {
windowDefaultStartPositionUs, windowDefaultStartPositionUs,
manifest, manifest,
tag); tag);
refreshSourceInfo(timeline, manifest); refreshSourceInfo(timeline);
if (!sideloadedManifest) { if (!sideloadedManifest) {
// Remove any pending simulated refresh. // Remove any pending simulated refresh.
...@@ -1193,6 +1193,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -1193,6 +1193,7 @@ public final class DashMediaSource extends BaseMediaSource {
&& manifest.durationMs == C.TIME_UNSET; && manifest.durationMs == C.TIME_UNSET;
return window.set( return window.set(
tag, tag,
manifest,
presentationStartTimeMs, presentationStartTimeMs,
windowStartTimeMs, windowStartTimeMs,
/* isSeekable= */ true, /* isSeekable= */ true,
......
...@@ -383,6 +383,7 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -383,6 +383,7 @@ public final class HlsMediaSource extends BaseMediaSource
? windowStartTimeMs ? windowStartTimeMs
: C.TIME_UNSET; : C.TIME_UNSET;
long windowDefaultStartPositionUs = playlist.startOffsetUs; long windowDefaultStartPositionUs = playlist.startOffsetUs;
HlsManifest manifest = new HlsManifest(playlistTracker.getMasterPlaylist(), playlist);
if (playlistTracker.isLive()) { if (playlistTracker.isLive()) {
long offsetFromInitialStartTimeUs = long offsetFromInitialStartTimeUs =
playlist.startTimeUs - playlistTracker.getInitialStartTimeUs(); playlist.startTimeUs - playlistTracker.getInitialStartTimeUs();
...@@ -403,6 +404,7 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -403,6 +404,7 @@ public final class HlsMediaSource extends BaseMediaSource
windowDefaultStartPositionUs, windowDefaultStartPositionUs,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ !playlist.hasEndTag, /* isDynamic= */ !playlist.hasEndTag,
manifest,
tag); tag);
} else /* not live */ { } else /* not live */ {
if (windowDefaultStartPositionUs == C.TIME_UNSET) { if (windowDefaultStartPositionUs == C.TIME_UNSET) {
...@@ -418,9 +420,10 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -418,9 +420,10 @@ public final class HlsMediaSource extends BaseMediaSource
windowDefaultStartPositionUs, windowDefaultStartPositionUs,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ false, /* isDynamic= */ false,
manifest,
tag); tag);
} }
refreshSourceInfo(timeline, new HlsManifest(playlistTracker.getMasterPlaylist(), playlist)); refreshSourceInfo(timeline);
} }
} }
...@@ -669,6 +669,7 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -669,6 +669,7 @@ public final class SsMediaSource extends BaseMediaSource
/* windowDefaultStartPositionUs= */ 0, /* windowDefaultStartPositionUs= */ 0,
/* isSeekable= */ true, /* isSeekable= */ true,
manifest.isLive, manifest.isLive,
manifest,
tag); tag);
} else if (manifest.isLive) { } else if (manifest.isLive) {
if (manifest.dvrWindowLengthUs != C.TIME_UNSET && manifest.dvrWindowLengthUs > 0) { if (manifest.dvrWindowLengthUs != C.TIME_UNSET && manifest.dvrWindowLengthUs > 0) {
...@@ -690,6 +691,7 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -690,6 +691,7 @@ public final class SsMediaSource extends BaseMediaSource
defaultStartPositionUs, defaultStartPositionUs,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ true, /* isDynamic= */ true,
manifest,
tag); tag);
} else { } else {
long durationUs = manifest.durationUs != C.TIME_UNSET ? manifest.durationUs long durationUs = manifest.durationUs != C.TIME_UNSET ? manifest.durationUs
...@@ -702,9 +704,10 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -702,9 +704,10 @@ public final class SsMediaSource extends BaseMediaSource
/* windowDefaultStartPositionUs= */ 0, /* windowDefaultStartPositionUs= */ 0,
/* isSeekable= */ true, /* isSeekable= */ true,
/* isDynamic= */ false, /* isDynamic= */ false,
manifest,
tag); tag);
} }
refreshSourceInfo(timeline, manifest); refreshSourceInfo(timeline);
} }
private void scheduleManifestRefresh() { private void scheduleManifestRefresh() {
......
...@@ -1212,8 +1212,7 @@ public class PlayerControlView extends FrameLayout { ...@@ -1212,8 +1212,7 @@ public class PlayerControlView extends FrameLayout {
} }
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) {
updateNavigation(); updateNavigation();
updateTimeline(); updateTimeline();
} }
......
...@@ -1286,7 +1286,7 @@ public class PlayerNotificationManager { ...@@ -1286,7 +1286,7 @@ public class PlayerNotificationManager {
} }
@Override @Override
public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) { public void onTimelineChanged(Timeline timeline, int reason) {
startOrUpdateNotification(); startOrUpdateNotification();
} }
......
...@@ -542,9 +542,7 @@ public abstract class Action { ...@@ -542,9 +542,7 @@ public abstract class Action {
} }
} }
/** /** Waits for {@link Player.EventListener#onTimelineChanged(Timeline, int)}. */
* Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)}.
*/
public static final class WaitForTimelineChanged extends Action { public static final class WaitForTimelineChanged extends Action {
@Nullable private final Timeline expectedTimeline; @Nullable private final Timeline expectedTimeline;
...@@ -575,9 +573,7 @@ public abstract class Action { ...@@ -575,9 +573,7 @@ public abstract class Action {
new Player.EventListener() { new Player.EventListener() {
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(
Timeline timeline, Timeline timeline, @Player.TimelineChangeReason int reason) {
@Nullable Object manifest,
@Player.TimelineChangeReason int reason) {
if (expectedTimeline == null || timeline.equals(expectedTimeline)) { if (expectedTimeline == null || timeline.equals(expectedTimeline)) {
player.removeListener(this); player.removeListener(this);
nextAction.schedule(player, trackSelector, surface, handler); nextAction.schedule(player, trackSelector, surface, handler);
......
...@@ -309,9 +309,9 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -309,9 +309,9 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
} }
if (mediaSource == null) { if (mediaSource == null) {
if (timeline == null) { if (timeline == null) {
timeline = new FakeTimeline(1); timeline = new FakeTimeline(/* windowCount= */ 1, manifest);
} }
mediaSource = new FakeMediaSource(timeline, manifest, supportedFormats); mediaSource = new FakeMediaSource(timeline, supportedFormats);
} }
if (expectedPlayerEndedCount == null) { if (expectedPlayerEndedCount == null) {
expectedPlayerEndedCount = 1; expectedPlayerEndedCount = 1;
...@@ -347,7 +347,6 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -347,7 +347,6 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
private final CountDownLatch endedCountDownLatch; private final CountDownLatch endedCountDownLatch;
private final CountDownLatch actionScheduleFinishedCountDownLatch; private final CountDownLatch actionScheduleFinishedCountDownLatch;
private final ArrayList<Timeline> timelines; private final ArrayList<Timeline> timelines;
private final ArrayList<Object> manifests;
private final ArrayList<Integer> timelineChangeReasons; private final ArrayList<Integer> timelineChangeReasons;
private final ArrayList<Integer> periodIndices; private final ArrayList<Integer> periodIndices;
private final ArrayList<Integer> discontinuityReasons; private final ArrayList<Integer> discontinuityReasons;
...@@ -380,7 +379,6 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -380,7 +379,6 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
this.eventListener = eventListener; this.eventListener = eventListener;
this.analyticsListener = analyticsListener; this.analyticsListener = analyticsListener;
this.timelines = new ArrayList<>(); this.timelines = new ArrayList<>();
this.manifests = new ArrayList<>();
this.timelineChangeReasons = new ArrayList<>(); this.timelineChangeReasons = new ArrayList<>();
this.periodIndices = new ArrayList<>(); this.periodIndices = new ArrayList<>();
this.discontinuityReasons = new ArrayList<>(); this.discontinuityReasons = new ArrayList<>();
...@@ -469,9 +467,8 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -469,9 +467,8 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
// Assertions called on the test thread after test finished. // Assertions called on the test thread after test finished.
/** /**
* Asserts that the timelines reported by * Asserts that the timelines reported by {@link Player.EventListener#onTimelineChanged(Timeline,
* {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)} are equal to the provided * int)} are equal to the provided timelines.
* timelines.
* *
* @param timelines A list of expected {@link Timeline}s. * @param timelines A list of expected {@link Timeline}s.
*/ */
...@@ -480,20 +477,9 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -480,20 +477,9 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
} }
/** /**
* Asserts that the manifests reported by
* {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)} are equal to the provided
* manifest.
*
* @param manifests A list of expected manifests.
*/
public void assertManifestsEqual(Object... manifests) {
assertThat(this.manifests).containsExactlyElementsIn(Arrays.asList(manifests)).inOrder();
}
/**
* Asserts that the timeline change reasons reported by {@link * Asserts that the timeline change reasons reported by {@link
* Player.EventListener#onTimelineChanged(Timeline, Object, int)} are equal to the provided * Player.EventListener#onTimelineChanged(Timeline, int)} are equal to the provided timeline
* timeline change reasons. * change reasons.
*/ */
public void assertTimelineChangeReasonsEqual(Integer... reasons) { public void assertTimelineChangeReasonsEqual(Integer... reasons) {
assertThat(timelineChangeReasons).containsExactlyElementsIn(Arrays.asList(reasons)).inOrder(); assertThat(timelineChangeReasons).containsExactlyElementsIn(Arrays.asList(reasons)).inOrder();
...@@ -573,10 +559,8 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -573,10 +559,8 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
// Player.EventListener // Player.EventListener
@Override @Override
public void onTimelineChanged( public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
Timeline timeline, @Nullable Object manifest, @Player.TimelineChangeReason int reason) {
timelines.add(timeline); timelines.add(timeline);
manifests.add(manifest);
timelineChangeReasons.add(reason); timelineChangeReasons.add(reason);
if (reason == Player.TIMELINE_CHANGE_REASON_PREPARED) { if (reason == Player.TIMELINE_CHANGE_REASON_PREPARED) {
periodIndices.add(player.getCurrentPeriodIndex()); periodIndices.add(player.getCurrentPeriodIndex());
......
...@@ -34,10 +34,9 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource { ...@@ -34,10 +34,9 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
public FakeAdaptiveMediaSource( public FakeAdaptiveMediaSource(
Timeline timeline, Timeline timeline,
Object manifest,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
FakeChunkSource.Factory chunkSourceFactory) { FakeChunkSource.Factory chunkSourceFactory) {
super(timeline, manifest, trackGroupArray); super(timeline, trackGroupArray);
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
} }
......
...@@ -56,7 +56,6 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -56,7 +56,6 @@ public class FakeMediaSource extends BaseMediaSource {
private final ArrayList<MediaPeriodId> createdMediaPeriods; private final ArrayList<MediaPeriodId> createdMediaPeriods;
protected Timeline timeline; protected Timeline timeline;
private Object manifest;
private boolean preparedSource; private boolean preparedSource;
private boolean releasedSource; private boolean releasedSource;
private Handler sourceInfoRefreshHandler; private Handler sourceInfoRefreshHandler;
...@@ -68,8 +67,8 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -68,8 +67,8 @@ public class FakeMediaSource extends BaseMediaSource {
* null to prevent an immediate source info refresh message when preparing the media source. It * null to prevent an immediate source info refresh message when preparing the media source. It
* can be manually set later using {@link #setNewSourceInfo(Timeline, Object)}. * can be manually set later using {@link #setNewSourceInfo(Timeline, Object)}.
*/ */
public FakeMediaSource(@Nullable Timeline timeline, Object manifest, Format... formats) { public FakeMediaSource(@Nullable Timeline timeline, Format... formats) {
this(timeline, manifest, buildTrackGroupArray(formats)); this(timeline, buildTrackGroupArray(formats));
} }
/** /**
...@@ -78,10 +77,8 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -78,10 +77,8 @@ public class FakeMediaSource extends BaseMediaSource {
* immediate source info refresh message when preparing the media source. It can be manually set * immediate source info refresh message when preparing the media source. It can be manually set
* later using {@link #setNewSourceInfo(Timeline, Object)}. * later using {@link #setNewSourceInfo(Timeline, Object)}.
*/ */
public FakeMediaSource(@Nullable Timeline timeline, Object manifest, public FakeMediaSource(@Nullable Timeline timeline, TrackGroupArray trackGroupArray) {
TrackGroupArray trackGroupArray) {
this.timeline = timeline; this.timeline = timeline;
this.manifest = manifest;
this.activeMediaPeriods = new ArrayList<>(); this.activeMediaPeriods = new ArrayList<>();
this.createdMediaPeriods = new ArrayList<>(); this.createdMediaPeriods = new ArrayList<>();
this.trackGroupArray = trackGroupArray; this.trackGroupArray = trackGroupArray;
...@@ -158,12 +155,10 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -158,12 +155,10 @@ public class FakeMediaSource extends BaseMediaSource {
assertThat(releasedSource).isFalse(); assertThat(releasedSource).isFalse();
assertThat(preparedSource).isTrue(); assertThat(preparedSource).isTrue();
timeline = newTimeline; timeline = newTimeline;
manifest = newManifest;
finishSourcePreparation(); finishSourcePreparation();
}); });
} else { } else {
timeline = newTimeline; timeline = newTimeline;
manifest = newManifest;
} }
} }
...@@ -212,7 +207,7 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -212,7 +207,7 @@ public class FakeMediaSource extends BaseMediaSource {
} }
private void finishSourcePreparation() { private void finishSourcePreparation() {
refreshSourceInfo(timeline, manifest); refreshSourceInfo(timeline);
if (!timeline.isEmpty()) { if (!timeline.isEmpty()) {
MediaLoadData mediaLoadData = MediaLoadData mediaLoadData =
new MediaLoadData( new MediaLoadData(
......
...@@ -112,6 +112,7 @@ public final class FakeTimeline extends Timeline { ...@@ -112,6 +112,7 @@ public final class FakeTimeline extends Timeline {
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;
private final Object[] manifests;
private final int[] periodOffsets; private final int[] periodOffsets;
/** /**
...@@ -140,9 +141,10 @@ public final class FakeTimeline extends Timeline { ...@@ -140,9 +141,10 @@ public final class FakeTimeline extends Timeline {
* with a duration of {@link TimelineWindowDefinition#DEFAULT_WINDOW_DURATION_US} each. * with a duration of {@link TimelineWindowDefinition#DEFAULT_WINDOW_DURATION_US} each.
* *
* @param windowCount The number of windows. * @param windowCount The number of windows.
* @param manifests The manifests of the windows.
*/ */
public FakeTimeline(int windowCount) { public FakeTimeline(int windowCount, Object... manifests) {
this(createDefaultWindowDefinitions(windowCount)); this(manifests, createDefaultWindowDefinitions(windowCount));
} }
/** /**
...@@ -151,6 +153,18 @@ public final class FakeTimeline extends Timeline { ...@@ -151,6 +153,18 @@ public final class FakeTimeline extends Timeline {
* @param windowDefinitions A list of {@link TimelineWindowDefinition}s. * @param windowDefinitions A list of {@link TimelineWindowDefinition}s.
*/ */
public FakeTimeline(TimelineWindowDefinition... windowDefinitions) { public FakeTimeline(TimelineWindowDefinition... windowDefinitions) {
this(new Object[0], windowDefinitions);
}
/**
* Creates a fake timeline with the given window definitions.
*
* @param windowDefinitions A list of {@link TimelineWindowDefinition}s.
*/
public FakeTimeline(Object[] manifests, TimelineWindowDefinition... windowDefinitions) {
this.manifests = new Object[windowDefinitions.length];
System.arraycopy(
manifests, 0, this.manifests, 0, Math.min(this.manifests.length, manifests.length));
this.windowDefinitions = windowDefinitions; this.windowDefinitions = windowDefinitions;
periodOffsets = new int[windowDefinitions.length + 1]; periodOffsets = new int[windowDefinitions.length + 1];
periodOffsets[0] = 0; periodOffsets[0] = 0;
...@@ -171,6 +185,7 @@ public final class FakeTimeline extends Timeline { ...@@ -171,6 +185,7 @@ public final class FakeTimeline extends Timeline {
Object tag = setTag ? windowDefinition.id : null; Object tag = setTag ? windowDefinition.id : null;
return window.set( return window.set(
tag, tag,
manifests[windowIndex],
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
/* windowStartTimeMs= */ C.TIME_UNSET, /* windowStartTimeMs= */ C.TIME_UNSET,
windowDefinition.isSeekable, windowDefinition.isSeekable,
......
...@@ -345,7 +345,7 @@ public class MediaSourceTestRunner { ...@@ -345,7 +345,7 @@ public class MediaSourceTestRunner {
// SourceInfoRefreshListener methods. // SourceInfoRefreshListener methods.
@Override @Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline, Object manifest) { public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); Assertions.checkState(Looper.myLooper() == playbackThread.getLooper());
timelines.addLast(timeline); timelines.addLast(timeline);
} }
......
...@@ -196,11 +196,6 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer { ...@@ -196,11 +196,6 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
} }
@Override @Override
public Object getCurrentManifest() {
throw new UnsupportedOperationException();
}
@Override
public Timeline getCurrentTimeline() { public Timeline getCurrentTimeline() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
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