Commit 77ed9302 by tonihei Committed by Oliver Woodman

Add Timeline.Window.uid.

This allows to uniquely identify a window within a Timeline. The value is set
correctly for all Window instances, but is not used anywhere yet.

PiperOrigin-RevId: 267556516
parent de915bd6
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
[#4337](https://github.com/google/ExoPlayer/issues/4337)). [#4337](https://github.com/google/ExoPlayer/issues/4337)).
* Publish `testutils` module to simplify unit testing with ExoPlayer * Publish `testutils` module to simplify unit testing with ExoPlayer
([#6267](https://github.com/google/ExoPlayer/issues/6267)). ([#6267](https://github.com/google/ExoPlayer/issues/6267)).
* Add `uid` to `Timeline.Window` to uniquely identify window instances.
### 2.10.4 ### ### 2.10.4 ###
......
...@@ -114,6 +114,7 @@ import java.util.Arrays; ...@@ -114,6 +114,7 @@ import java.util.Arrays;
long durationUs = durationsUs[windowIndex]; long durationUs = durationsUs[windowIndex];
boolean isDynamic = durationUs == C.TIME_UNSET; boolean isDynamic = durationUs == C.TIME_UNSET;
return window.set( return window.set(
/* uid= */ ids[windowIndex],
/* tag= */ ids[windowIndex], /* tag= */ ids[windowIndex],
/* manifest= */ null, /* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
......
...@@ -115,6 +115,17 @@ public abstract class Timeline { ...@@ -115,6 +115,17 @@ public abstract class Timeline {
*/ */
public static final class Window { public static final class Window {
/**
* A {@link #uid} for a window that must be used for single-window {@link Timeline Timelines}.
*/
public static final Object SINGLE_WINDOW_UID = new Object();
/**
* A unique identifier for the window. Single-window {@link Timeline Timelines} must use {@link
* #SINGLE_WINDOW_UID}.
*/
public Object uid;
/** A tag for the window. Not necessarily unique. */ /** A tag for the window. Not necessarily unique. */
@Nullable public Object tag; @Nullable public Object tag;
...@@ -175,8 +186,14 @@ public abstract class Timeline { ...@@ -175,8 +186,14 @@ public abstract class Timeline {
*/ */
public long positionInFirstPeriodUs; public long positionInFirstPeriodUs;
/** Creates window. */
public Window() {
uid = SINGLE_WINDOW_UID;
}
/** Sets the data held by this window. */ /** Sets the data held by this window. */
public Window set( public Window set(
Object uid,
@Nullable Object tag, @Nullable Object tag,
@Nullable Object manifest, @Nullable Object manifest,
long presentationStartTimeMs, long presentationStartTimeMs,
...@@ -188,6 +205,7 @@ public abstract class Timeline { ...@@ -188,6 +205,7 @@ public abstract class Timeline {
int firstPeriodIndex, int firstPeriodIndex,
int lastPeriodIndex, int lastPeriodIndex,
long positionInFirstPeriodUs) { long positionInFirstPeriodUs) {
this.uid = uid;
this.tag = tag; this.tag = tag;
this.manifest = manifest; this.manifest = manifest;
this.presentationStartTimeMs = presentationStartTimeMs; this.presentationStartTimeMs = presentationStartTimeMs;
...@@ -793,8 +811,8 @@ public abstract class Timeline { ...@@ -793,8 +811,8 @@ public abstract class Timeline {
public abstract Period getPeriod(int periodIndex, Period period, boolean setIds); public abstract Period getPeriod(int periodIndex, Period period, boolean setIds);
/** /**
* Returns the index of the period identified by its unique {@code id}, or {@link C#INDEX_UNSET} * Returns the index of the period identified by its unique {@link Period#uid}, or {@link
* if the period is not in the timeline. * C#INDEX_UNSET} if the period is not in the timeline.
* *
* @param uid A unique identifier for a period. * @param uid A unique identifier for a period.
* @return The index of the period, or {@link C#INDEX_UNSET} if the period was not found. * @return The index of the period, or {@link C#INDEX_UNSET} if the period was not found.
......
...@@ -53,14 +53,14 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -53,14 +53,14 @@ import com.google.android.exoplayer2.util.Assertions;
} }
/** /**
* Returns concatenated UID for a period in a child timeline. * Returns a concatenated UID for a period or window in a child timeline.
* *
* @param childTimelineUid UID of the child timeline this period belongs to. * @param childTimelineUid UID of the child timeline this period or window belongs to.
* @param childPeriodUid UID of the period in the child timeline. * @param childPeriodOrWindowUid UID of the period or window in the child timeline.
* @return UID of the period in the concatenated timeline. * @return UID of the period or window in the concatenated timeline.
*/ */
public static Object getConcatenatedUid(Object childTimelineUid, Object childPeriodUid) { public static Object getConcatenatedUid(Object childTimelineUid, Object childPeriodOrWindowUid) {
return Pair.create(childTimelineUid, childPeriodUid); return Pair.create(childTimelineUid, childPeriodOrWindowUid);
} }
/** /**
...@@ -195,6 +195,12 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -195,6 +195,12 @@ import com.google.android.exoplayer2.util.Assertions;
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex); int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
getTimelineByChildIndex(childIndex) getTimelineByChildIndex(childIndex)
.getWindow(windowIndex - firstWindowIndexInChild, window, defaultPositionProjectionUs); .getWindow(windowIndex - firstWindowIndexInChild, window, defaultPositionProjectionUs);
Object childUid = getChildUidByChildIndex(childIndex);
// Don't create new objects if the child is using SINGLE_WINDOW_UID.
window.uid =
Window.SINGLE_WINDOW_UID.equals(window.uid)
? childUid
: getConcatenatedUid(childUid, window.uid);
window.firstPeriodIndex += firstPeriodIndexInChild; window.firstPeriodIndex += firstPeriodIndexInChild;
window.lastPeriodIndex += firstPeriodIndexInChild; window.lastPeriodIndex += firstPeriodIndexInChild;
return window; return window;
......
...@@ -19,6 +19,7 @@ import android.util.Pair; ...@@ -19,6 +19,7 @@ import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
...@@ -134,7 +135,8 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -134,7 +135,8 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
timeline = timeline.cloneWithUpdatedTimeline(newTimeline); timeline = timeline.cloneWithUpdatedTimeline(newTimeline);
} else if (newTimeline.isEmpty()) { } else if (newTimeline.isEmpty()) {
timeline = timeline =
MaskingTimeline.createWithRealTimeline(newTimeline, MaskingTimeline.DUMMY_EXTERNAL_ID); MaskingTimeline.createWithRealTimeline(
newTimeline, Window.SINGLE_WINDOW_UID, MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID);
} else { } else {
// Determine first period and the start position. // Determine first period and the start position.
// This will be: // This will be:
...@@ -156,12 +158,13 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -156,12 +158,13 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
windowStartPositionUs = periodPreparePositionUs; windowStartPositionUs = periodPreparePositionUs;
} }
} }
Object windowUid = window.uid;
Pair<Object, Long> periodPosition = Pair<Object, Long> periodPosition =
newTimeline.getPeriodPosition( newTimeline.getPeriodPosition(
window, period, /* windowIndex= */ 0, windowStartPositionUs); window, period, /* windowIndex= */ 0, windowStartPositionUs);
Object periodUid = periodPosition.first; Object periodUid = periodPosition.first;
long periodPositionUs = periodPosition.second; long periodPositionUs = periodPosition.second;
timeline = MaskingTimeline.createWithRealTimeline(newTimeline, periodUid); timeline = MaskingTimeline.createWithRealTimeline(newTimeline, windowUid, periodUid);
if (unpreparedMaskingMediaPeriod != null) { if (unpreparedMaskingMediaPeriod != null) {
MaskingMediaPeriod maskingPeriod = unpreparedMaskingMediaPeriod; MaskingMediaPeriod maskingPeriod = unpreparedMaskingMediaPeriod;
maskingPeriod.overridePreparePositionUs(periodPositionUs); maskingPeriod.overridePreparePositionUs(periodPositionUs);
...@@ -190,14 +193,14 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -190,14 +193,14 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
} }
private Object getInternalPeriodUid(Object externalPeriodUid) { private Object getInternalPeriodUid(Object externalPeriodUid) {
return externalPeriodUid.equals(MaskingTimeline.DUMMY_EXTERNAL_ID) return externalPeriodUid.equals(MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID)
? timeline.replacedInternalId ? timeline.replacedInternalPeriodUid
: externalPeriodUid; : externalPeriodUid;
} }
private Object getExternalPeriodUid(Object internalPeriodUid) { private Object getExternalPeriodUid(Object internalPeriodUid) {
return timeline.replacedInternalId.equals(internalPeriodUid) return timeline.replacedInternalPeriodUid.equals(internalPeriodUid)
? MaskingTimeline.DUMMY_EXTERNAL_ID ? MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID
: internalPeriodUid; : internalPeriodUid;
} }
...@@ -207,9 +210,10 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -207,9 +210,10 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
*/ */
private static final class MaskingTimeline extends ForwardingTimeline { private static final class MaskingTimeline extends ForwardingTimeline {
public static final Object DUMMY_EXTERNAL_ID = new Object(); public static final Object DUMMY_EXTERNAL_PERIOD_UID = new Object();
private final Object replacedInternalId; private final Object replacedInternalWindowUid;
private final Object replacedInternalPeriodUid;
/** /**
* Returns an instance with a dummy timeline using the provided window tag. * Returns an instance with a dummy timeline using the provided window tag.
...@@ -217,7 +221,8 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -217,7 +221,8 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
* @param windowTag A window tag. * @param windowTag A window tag.
*/ */
public static MaskingTimeline createWithDummyTimeline(@Nullable Object windowTag) { public static MaskingTimeline createWithDummyTimeline(@Nullable Object windowTag) {
return new MaskingTimeline(new DummyTimeline(windowTag), DUMMY_EXTERNAL_ID); return new MaskingTimeline(
new DummyTimeline(windowTag), Window.SINGLE_WINDOW_UID, DUMMY_EXTERNAL_PERIOD_UID);
} }
/** /**
...@@ -225,16 +230,21 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -225,16 +230,21 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
* assigned dummy period ID. * assigned dummy period ID.
* *
* @param timeline The real timeline. * @param timeline The real timeline.
* @param firstWindowUid The window UID in the timeline which will be replaced by the already
* assigned {@link Window#SINGLE_WINDOW_UID}.
* @param firstPeriodUid The period UID in the timeline which will be replaced by the already * @param firstPeriodUid The period UID in the timeline which will be replaced by the already
* assigned dummy period UID. * assigned {@link #DUMMY_EXTERNAL_PERIOD_UID}.
*/ */
public static MaskingTimeline createWithRealTimeline(Timeline timeline, Object firstPeriodUid) { public static MaskingTimeline createWithRealTimeline(
return new MaskingTimeline(timeline, firstPeriodUid); Timeline timeline, Object firstWindowUid, Object firstPeriodUid) {
return new MaskingTimeline(timeline, firstWindowUid, firstPeriodUid);
} }
private MaskingTimeline(Timeline timeline, Object replacedInternalId) { private MaskingTimeline(
Timeline timeline, Object replacedInternalWindowUid, Object replacedInternalPeriodUid) {
super(timeline); super(timeline);
this.replacedInternalId = replacedInternalId; this.replacedInternalWindowUid = replacedInternalWindowUid;
this.replacedInternalPeriodUid = replacedInternalPeriodUid;
} }
/** /**
...@@ -243,7 +253,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -243,7 +253,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
* @param timeline The new timeline. * @param timeline The new timeline.
*/ */
public MaskingTimeline cloneWithUpdatedTimeline(Timeline timeline) { public MaskingTimeline cloneWithUpdatedTimeline(Timeline timeline) {
return new MaskingTimeline(timeline, replacedInternalId); return new MaskingTimeline(timeline, replacedInternalWindowUid, replacedInternalPeriodUid);
} }
/** Returns the wrapped timeline. */ /** Returns the wrapped timeline. */
...@@ -252,23 +262,33 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -252,23 +262,33 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
} }
@Override @Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
timeline.getWindow(windowIndex, window, defaultPositionProjectionUs);
if (Util.areEqual(window.uid, replacedInternalWindowUid)) {
window.uid = Window.SINGLE_WINDOW_UID;
}
return window;
}
@Override
public Period getPeriod(int periodIndex, Period period, boolean setIds) { public Period getPeriod(int periodIndex, Period period, boolean setIds) {
timeline.getPeriod(periodIndex, period, setIds); timeline.getPeriod(periodIndex, period, setIds);
if (Util.areEqual(period.uid, replacedInternalId)) { if (Util.areEqual(period.uid, replacedInternalPeriodUid)) {
period.uid = DUMMY_EXTERNAL_ID; period.uid = DUMMY_EXTERNAL_PERIOD_UID;
} }
return period; return period;
} }
@Override @Override
public int getIndexOfPeriod(Object uid) { public int getIndexOfPeriod(Object uid) {
return timeline.getIndexOfPeriod(DUMMY_EXTERNAL_ID.equals(uid) ? replacedInternalId : uid); return timeline.getIndexOfPeriod(
DUMMY_EXTERNAL_PERIOD_UID.equals(uid) ? replacedInternalPeriodUid : uid);
} }
@Override @Override
public Object getUidOfPeriod(int periodIndex) { public Object getUidOfPeriod(int periodIndex) {
Object uid = timeline.getUidOfPeriod(periodIndex); Object uid = timeline.getUidOfPeriod(periodIndex);
return Util.areEqual(uid, replacedInternalId) ? DUMMY_EXTERNAL_ID : uid; return Util.areEqual(uid, replacedInternalPeriodUid) ? DUMMY_EXTERNAL_PERIOD_UID : uid;
} }
} }
...@@ -289,6 +309,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -289,6 +309,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
@Override @Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
return window.set( return window.set(
Window.SINGLE_WINDOW_UID,
tag, tag,
/* manifest= */ null, /* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
...@@ -312,7 +333,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -312,7 +333,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
public Period getPeriod(int periodIndex, Period period, boolean setIds) { public Period getPeriod(int periodIndex, Period period, boolean setIds) {
return period.set( return period.set(
/* id= */ 0, /* id= */ 0,
/* uid= */ MaskingTimeline.DUMMY_EXTERNAL_ID, /* uid= */ MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID,
/* windowIndex= */ 0, /* windowIndex= */ 0,
/* durationUs = */ C.TIME_UNSET, /* durationUs = */ C.TIME_UNSET,
/* positionInWindowUs= */ 0); /* positionInWindowUs= */ 0);
...@@ -320,12 +341,12 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> { ...@@ -320,12 +341,12 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
@Override @Override
public int getIndexOfPeriod(Object uid) { public int getIndexOfPeriod(Object uid) {
return uid == MaskingTimeline.DUMMY_EXTERNAL_ID ? 0 : C.INDEX_UNSET; return uid == MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID ? 0 : C.INDEX_UNSET;
} }
@Override @Override
public Object getUidOfPeriod(int periodIndex) { public Object getUidOfPeriod(int periodIndex) {
return MaskingTimeline.DUMMY_EXTERNAL_ID; return MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID;
} }
} }
} }
...@@ -175,6 +175,7 @@ public final class SinglePeriodTimeline extends Timeline { ...@@ -175,6 +175,7 @@ public final class SinglePeriodTimeline extends Timeline {
} }
} }
return window.set( return window.set(
Window.SINGLE_WINDOW_UID,
tag, tag,
manifest, manifest,
presentationStartTimeMs, presentationStartTimeMs,
......
...@@ -1216,6 +1216,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -1216,6 +1216,7 @@ public final class DashMediaSource extends BaseMediaSource {
&& manifest.minUpdatePeriodMs != C.TIME_UNSET && manifest.minUpdatePeriodMs != C.TIME_UNSET
&& manifest.durationMs == C.TIME_UNSET; && manifest.durationMs == C.TIME_UNSET;
return window.set( return window.set(
Window.SINGLE_WINDOW_UID,
windowTag, windowTag,
manifest, manifest,
presentationStartTimeMs, presentationStartTimeMs,
......
...@@ -182,6 +182,7 @@ public final class FakeTimeline extends Timeline { ...@@ -182,6 +182,7 @@ public final class FakeTimeline extends Timeline {
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) { public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex]; TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
return window.set( return window.set(
/* uid= */ windowDefinition.id,
/* tag= */ windowDefinition.id, /* tag= */ windowDefinition.id,
manifests[windowIndex], manifests[windowIndex],
/* presentationStartTimeMs= */ C.TIME_UNSET, /* presentationStartTimeMs= */ C.TIME_UNSET,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment