Skip to content

Commit

Permalink
Add Timeline.Window.uid.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tonihei authored and ojw28 committed Sep 10, 2019
1 parent de915bd commit 77ed930
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 30 deletions.
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
[#4337](https://github.com/google/ExoPlayer/issues/4337)).
* Publish `testutils` module to simplify unit testing with ExoPlayer
([#6267](https://github.com/google/ExoPlayer/issues/6267)).
* Add `uid` to `Timeline.Window` to uniquely identify window instances.

### 2.10.4 ###

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public Window getWindow(int windowIndex, Window window, long defaultPositionProj
long durationUs = durationsUs[windowIndex];
boolean isDynamic = durationUs == C.TIME_UNSET;
return window.set(
/* uid= */ ids[windowIndex],
/* tag= */ ids[windowIndex],
/* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,17 @@ public abstract class Timeline {
*/
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. */
@Nullable public Object tag;

Expand Down Expand Up @@ -175,8 +186,14 @@ public static final class Window {
*/
public long positionInFirstPeriodUs;

/** Creates window. */
public Window() {
uid = SINGLE_WINDOW_UID;
}

/** Sets the data held by this window. */
public Window set(
Object uid,
@Nullable Object tag,
@Nullable Object manifest,
long presentationStartTimeMs,
Expand All @@ -188,6 +205,7 @@ public Window set(
int firstPeriodIndex,
int lastPeriodIndex,
long positionInFirstPeriodUs) {
this.uid = uid;
this.tag = tag;
this.manifest = manifest;
this.presentationStartTimeMs = presentationStartTimeMs;
Expand Down Expand Up @@ -793,8 +811,8 @@ public final Period getPeriod(int periodIndex, Period period) {
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}
* if the period is not in the timeline.
* Returns the index of the period identified by its unique {@link Period#uid}, or {@link
* C#INDEX_UNSET} if the period is not in the timeline.
*
* @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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ public static Object getChildPeriodUidFromConcatenatedUid(Object concatenatedUid
}

/**
* 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 childPeriodUid UID of the period in the child timeline.
* @return UID of the period in the concatenated timeline.
* @param childTimelineUid UID of the child timeline this period or window belongs to.
* @param childPeriodOrWindowUid UID of the period or window in the child timeline.
* @return UID of the period or window in the concatenated timeline.
*/
public static Object getConcatenatedUid(Object childTimelineUid, Object childPeriodUid) {
return Pair.create(childTimelineUid, childPeriodUid);
public static Object getConcatenatedUid(Object childTimelineUid, Object childPeriodOrWindowUid) {
return Pair.create(childTimelineUid, childPeriodOrWindowUid);
}

/**
Expand Down Expand Up @@ -195,6 +195,12 @@ public final Window getWindow(int windowIndex, Window window, long defaultPositi
int firstPeriodIndexInChild = getFirstPeriodIndexByChildIndex(childIndex);
getTimelineByChildIndex(childIndex)
.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.lastPeriodIndex += firstPeriodIndexInChild;
return window;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
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.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
Expand Down Expand Up @@ -134,7 +135,8 @@ protected void onChildSourceInfoRefreshed(
timeline = timeline.cloneWithUpdatedTimeline(newTimeline);
} else if (newTimeline.isEmpty()) {
timeline =
MaskingTimeline.createWithRealTimeline(newTimeline, MaskingTimeline.DUMMY_EXTERNAL_ID);
MaskingTimeline.createWithRealTimeline(
newTimeline, Window.SINGLE_WINDOW_UID, MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID);
} else {
// Determine first period and the start position.
// This will be:
Expand All @@ -156,12 +158,13 @@ protected void onChildSourceInfoRefreshed(
windowStartPositionUs = periodPreparePositionUs;
}
}
Object windowUid = window.uid;
Pair<Object, Long> periodPosition =
newTimeline.getPeriodPosition(
window, period, /* windowIndex= */ 0, windowStartPositionUs);
Object periodUid = periodPosition.first;
long periodPositionUs = periodPosition.second;
timeline = MaskingTimeline.createWithRealTimeline(newTimeline, periodUid);
timeline = MaskingTimeline.createWithRealTimeline(newTimeline, windowUid, periodUid);
if (unpreparedMaskingMediaPeriod != null) {
MaskingMediaPeriod maskingPeriod = unpreparedMaskingMediaPeriod;
maskingPeriod.overridePreparePositionUs(periodPositionUs);
Expand Down Expand Up @@ -190,14 +193,14 @@ protected boolean shouldDispatchCreateOrReleaseEvent(MediaPeriodId mediaPeriodId
}

private Object getInternalPeriodUid(Object externalPeriodUid) {
return externalPeriodUid.equals(MaskingTimeline.DUMMY_EXTERNAL_ID)
? timeline.replacedInternalId
return externalPeriodUid.equals(MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID)
? timeline.replacedInternalPeriodUid
: externalPeriodUid;
}

private Object getExternalPeriodUid(Object internalPeriodUid) {
return timeline.replacedInternalId.equals(internalPeriodUid)
? MaskingTimeline.DUMMY_EXTERNAL_ID
return timeline.replacedInternalPeriodUid.equals(internalPeriodUid)
? MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID
: internalPeriodUid;
}

Expand All @@ -207,34 +210,41 @@ private Object getExternalPeriodUid(Object internalPeriodUid) {
*/
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.
*
* @param windowTag A window tag.
*/
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);
}

/**
* Returns an instance with a real timeline, replacing the provided period ID with the already
* assigned dummy period ID.
*
* @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
* assigned dummy period UID.
* assigned {@link #DUMMY_EXTERNAL_PERIOD_UID}.
*/
public static MaskingTimeline createWithRealTimeline(Timeline timeline, Object firstPeriodUid) {
return new MaskingTimeline(timeline, firstPeriodUid);
public static MaskingTimeline createWithRealTimeline(
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);
this.replacedInternalId = replacedInternalId;
this.replacedInternalWindowUid = replacedInternalWindowUid;
this.replacedInternalPeriodUid = replacedInternalPeriodUid;
}

/**
Expand All @@ -243,32 +253,42 @@ private MaskingTimeline(Timeline timeline, Object replacedInternalId) {
* @param timeline The new timeline.
*/
public MaskingTimeline cloneWithUpdatedTimeline(Timeline timeline) {
return new MaskingTimeline(timeline, replacedInternalId);
return new MaskingTimeline(timeline, replacedInternalWindowUid, replacedInternalPeriodUid);
}

/** Returns the wrapped timeline. */
public Timeline getTimeline() {
return timeline;
}

@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) {
timeline.getPeriod(periodIndex, period, setIds);
if (Util.areEqual(period.uid, replacedInternalId)) {
period.uid = DUMMY_EXTERNAL_ID;
if (Util.areEqual(period.uid, replacedInternalPeriodUid)) {
period.uid = DUMMY_EXTERNAL_PERIOD_UID;
}
return period;
}

@Override
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
public Object getUidOfPeriod(int 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;
}
}

Expand All @@ -289,6 +309,7 @@ public int getWindowCount() {
@Override
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
return window.set(
Window.SINGLE_WINDOW_UID,
tag,
/* manifest= */ null,
/* presentationStartTimeMs= */ C.TIME_UNSET,
Expand All @@ -312,20 +333,20 @@ public int getPeriodCount() {
public Period getPeriod(int periodIndex, Period period, boolean setIds) {
return period.set(
/* id= */ 0,
/* uid= */ MaskingTimeline.DUMMY_EXTERNAL_ID,
/* uid= */ MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID,
/* windowIndex= */ 0,
/* durationUs = */ C.TIME_UNSET,
/* positionInWindowUs= */ 0);
}

@Override
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
public Object getUidOfPeriod(int periodIndex) {
return MaskingTimeline.DUMMY_EXTERNAL_ID;
return MaskingTimeline.DUMMY_EXTERNAL_PERIOD_UID;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ public Window getWindow(int windowIndex, Window window, long defaultPositionProj
}
}
return window.set(
Window.SINGLE_WINDOW_UID,
tag,
manifest,
presentationStartTimeMs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ public Window getWindow(int windowIndex, Window window, long defaultPositionProj
&& manifest.minUpdatePeriodMs != C.TIME_UNSET
&& manifest.durationMs == C.TIME_UNSET;
return window.set(
Window.SINGLE_WINDOW_UID,
windowTag,
manifest,
presentationStartTimeMs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ public int getWindowCount() {
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
return window.set(
/* uid= */ windowDefinition.id,
/* tag= */ windowDefinition.id,
manifests[windowIndex],
/* presentationStartTimeMs= */ C.TIME_UNSET,
Expand Down

0 comments on commit 77ed930

Please sign in to comment.