Add window.isPlaceHolder flag
There are existing bugs that need this flag to know whether the current information in the window is still a placeholder or can already be relied on for further calculation. This flag will probably only ever be set in DummyTimeline, so it's not added to the window.set method to avoid updating all clients. Issue:#5924 PiperOrigin-RevId: 291705637
This commit is contained in:
parent
5a6cffcf6f
commit
c0a3feee00
@ -176,6 +176,12 @@ public abstract class Timeline {
|
||||
*/
|
||||
public boolean isLive;
|
||||
|
||||
/**
|
||||
* Whether the information in this window is used as a placeholder for as long as the media
|
||||
* hasn't provided the real information.
|
||||
*/
|
||||
public boolean isPlaceholder;
|
||||
|
||||
/** The index of the first period that belongs to this window. */
|
||||
public int firstPeriodIndex;
|
||||
|
||||
@ -238,6 +244,7 @@ public abstract class Timeline {
|
||||
this.firstPeriodIndex = firstPeriodIndex;
|
||||
this.lastPeriodIndex = lastPeriodIndex;
|
||||
this.positionInFirstPeriodUs = positionInFirstPeriodUs;
|
||||
this.isPlaceholder = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -319,6 +326,7 @@ public abstract class Timeline {
|
||||
&& isSeekable == that.isSeekable
|
||||
&& isDynamic == that.isDynamic
|
||||
&& isLive == that.isLive
|
||||
&& isPlaceholder == that.isPlaceholder
|
||||
&& defaultPositionUs == that.defaultPositionUs
|
||||
&& durationUs == that.durationUs
|
||||
&& firstPeriodIndex == that.firstPeriodIndex
|
||||
@ -340,6 +348,7 @@ public abstract class Timeline {
|
||||
result = 31 * result + (isSeekable ? 1 : 0);
|
||||
result = 31 * result + (isDynamic ? 1 : 0);
|
||||
result = 31 * result + (isLive ? 1 : 0);
|
||||
result = 31 * result + (isPlaceholder ? 1 : 0);
|
||||
result = 31 * result + (int) (defaultPositionUs ^ (defaultPositionUs >>> 32));
|
||||
result = 31 * result + (int) (durationUs ^ (durationUs >>> 32));
|
||||
result = 31 * result + firstPeriodIndex;
|
||||
|
@ -331,7 +331,7 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
||||
return window.set(
|
||||
window.set(
|
||||
Window.SINGLE_WINDOW_UID,
|
||||
tag,
|
||||
/* manifest= */ null,
|
||||
@ -347,6 +347,8 @@ public final class MaskingMediaSource extends CompositeMediaSource<Void> {
|
||||
/* firstPeriodIndex= */ 0,
|
||||
/* lastPeriodIndex= */ 0,
|
||||
/* positionInFirstPeriodUs= */ 0);
|
||||
window.isPlaceholder = true;
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3486,22 +3486,8 @@ public final class ExoPlayerTest {
|
||||
MediaSource mediaSource2 = new FakeMediaSource(timeline2);
|
||||
Timeline expectedDummyTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 1,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 2,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE));
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 1),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 2));
|
||||
ActionSchedule actionSchedule =
|
||||
new ActionSchedule.Builder("testMoveMediaItem")
|
||||
.waitForTimelineChanged(
|
||||
@ -3573,30 +3559,9 @@ public final class ExoPlayerTest {
|
||||
|
||||
Timeline expectedDummyTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 1,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 2,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 3,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE));
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 1),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 2),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 3));
|
||||
Timeline expectedRealTimeline =
|
||||
new FakeTimeline(firstWindowDefinition, secondWindowDefinition, thirdWindowDefinition);
|
||||
Timeline expectedRealTimelineAfterRemove =
|
||||
@ -3654,30 +3619,9 @@ public final class ExoPlayerTest {
|
||||
|
||||
Timeline expectedDummyTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 1,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 2,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 3,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE));
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 1),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 2),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 3));
|
||||
Timeline expectedRealTimeline =
|
||||
new FakeTimeline(firstWindowDefinition, secondWindowDefinition, thirdWindowDefinition);
|
||||
Timeline expectedRealTimelineAfterRemove = new FakeTimeline(firstWindowDefinition);
|
||||
@ -3819,22 +3763,8 @@ public final class ExoPlayerTest {
|
||||
Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE /* source update after prepare */);
|
||||
Timeline expectedSecondDummyTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 0,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE),
|
||||
new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ 0,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE));
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 0),
|
||||
TimelineWindowDefinition.createDummy(/* tag= */ 0));
|
||||
Timeline expectedSecondRealTimeline =
|
||||
new FakeTimeline(
|
||||
new TimelineWindowDefinition(
|
||||
|
@ -94,6 +94,10 @@ public class TimelineTest {
|
||||
otherWindow.isLive = true;
|
||||
assertThat(window).isNotEqualTo(otherWindow);
|
||||
|
||||
otherWindow = new Timeline.Window();
|
||||
otherWindow.isPlaceholder = true;
|
||||
assertThat(window).isNotEqualTo(otherWindow);
|
||||
|
||||
otherWindow = new Timeline.Window();
|
||||
otherWindow.defaultPositionUs = C.TIME_UNSET;
|
||||
assertThat(window).isNotEqualTo(otherWindow);
|
||||
|
@ -42,12 +42,31 @@ public final class FakeTimeline extends Timeline {
|
||||
public final boolean isSeekable;
|
||||
public final boolean isDynamic;
|
||||
public final boolean isLive;
|
||||
public final boolean isPlaceholder;
|
||||
public final long durationUs;
|
||||
public final AdPlaybackState adPlaybackState;
|
||||
|
||||
/**
|
||||
* Creates a seekable, non-dynamic window definition with a duration of
|
||||
* {@link #DEFAULT_WINDOW_DURATION_US}.
|
||||
* Creates a window definition that corresponds to a dummy placeholder timeline using the given
|
||||
* tag.
|
||||
*
|
||||
* @param tag The tag to use in the timeline.
|
||||
*/
|
||||
public static TimelineWindowDefinition createDummy(Object tag) {
|
||||
return new TimelineWindowDefinition(
|
||||
/* periodCount= */ 1,
|
||||
/* id= */ tag,
|
||||
/* isSeekable= */ false,
|
||||
/* isDynamic= */ true,
|
||||
/* isLive= */ false,
|
||||
/* isPlaceholder= */ true,
|
||||
/* durationUs= */ C.TIME_UNSET,
|
||||
AdPlaybackState.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a seekable, non-dynamic window definition with a duration of {@link
|
||||
* #DEFAULT_WINDOW_DURATION_US}.
|
||||
*
|
||||
* @param periodCount The number of periods in the window. Each period get an equal slice of the
|
||||
* total window duration.
|
||||
@ -107,6 +126,7 @@ public final class FakeTimeline extends Timeline {
|
||||
isSeekable,
|
||||
isDynamic,
|
||||
/* isLive= */ isDynamic,
|
||||
/* isPlaceholder= */ false,
|
||||
durationUs,
|
||||
adPlaybackState);
|
||||
}
|
||||
@ -120,6 +140,7 @@ public final class FakeTimeline extends Timeline {
|
||||
* @param isSeekable Whether the window is seekable.
|
||||
* @param isDynamic Whether the window is dynamic.
|
||||
* @param isLive Whether the window is live.
|
||||
* @param isPlaceholder Whether the window is a placeholder.
|
||||
* @param durationUs The duration of the window in microseconds.
|
||||
* @param adPlaybackState The ad playback state.
|
||||
*/
|
||||
@ -129,6 +150,7 @@ public final class FakeTimeline extends Timeline {
|
||||
boolean isSeekable,
|
||||
boolean isDynamic,
|
||||
boolean isLive,
|
||||
boolean isPlaceholder,
|
||||
long durationUs,
|
||||
AdPlaybackState adPlaybackState) {
|
||||
this.periodCount = periodCount;
|
||||
@ -136,10 +158,10 @@ public final class FakeTimeline extends Timeline {
|
||||
this.isSeekable = isSeekable;
|
||||
this.isDynamic = isDynamic;
|
||||
this.isLive = isLive;
|
||||
this.isPlaceholder = isPlaceholder;
|
||||
this.durationUs = durationUs;
|
||||
this.adPlaybackState = adPlaybackState;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final long AD_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
||||
@ -222,7 +244,7 @@ public final class FakeTimeline extends Timeline {
|
||||
@Override
|
||||
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
||||
TimelineWindowDefinition windowDefinition = windowDefinitions[windowIndex];
|
||||
return window.set(
|
||||
window.set(
|
||||
/* uid= */ windowDefinition.id,
|
||||
/* tag= */ windowDefinition.id,
|
||||
manifests[windowIndex],
|
||||
@ -237,6 +259,8 @@ public final class FakeTimeline extends Timeline {
|
||||
periodOffsets[windowIndex],
|
||||
periodOffsets[windowIndex + 1] - 1,
|
||||
/* positionInFirstPeriodUs= */ 0);
|
||||
window.isPlaceholder = windowDefinition.isPlaceholder;
|
||||
return window;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user