mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add flag to SinglePeriodTimeline to suppress projection
Issue: #9037 #minor-release PiperOrigin-RevId: 385630065
This commit is contained in:
parent
e01838e036
commit
f8278da75d
5 changed files with 59 additions and 2 deletions
|
|
@ -39,6 +39,9 @@
|
||||||
([#9004](https://github.com/google/ExoPlayer/issues/9004)).
|
([#9004](https://github.com/google/ExoPlayer/issues/9004)).
|
||||||
* Forward the FRAME-RATE value from the master playlist to renditions.
|
* Forward the FRAME-RATE value from the master playlist to renditions.
|
||||||
([#8960](https://github.com/google/ExoPlayer/issues/8960)).
|
([#8960](https://github.com/google/ExoPlayer/issues/8960)).
|
||||||
|
* Fix issue where HLS events would start at positions greater than
|
||||||
|
specified by an `EXT-X-START` tag when placed in a playlist
|
||||||
|
([#9037](https://github.com/google/ExoPlayer/issues/9037)).
|
||||||
* Ad playback:
|
* Ad playback:
|
||||||
* Use the content URI when auto-generating an ad ID (in addition to the
|
* Use the content URI when auto-generating an ad ID (in addition to the
|
||||||
media ID and ad tag URI)
|
media ID and ad tag URI)
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
private final long windowDefaultStartPositionUs;
|
private final long windowDefaultStartPositionUs;
|
||||||
private final boolean isSeekable;
|
private final boolean isSeekable;
|
||||||
private final boolean isDynamic;
|
private final boolean isDynamic;
|
||||||
|
private final boolean suppressPositionProjection;
|
||||||
@Nullable private final Object manifest;
|
@Nullable private final Object manifest;
|
||||||
@Nullable private final MediaItem mediaItem;
|
@Nullable private final MediaItem mediaItem;
|
||||||
@Nullable private final MediaItem.LiveConfiguration liveConfiguration;
|
@Nullable private final MediaItem.LiveConfiguration liveConfiguration;
|
||||||
|
|
@ -169,6 +170,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
windowDefaultStartPositionUs,
|
windowDefaultStartPositionUs,
|
||||||
isSeekable,
|
isSeekable,
|
||||||
isDynamic,
|
isDynamic,
|
||||||
|
/* suppressPositionProjection= */ false,
|
||||||
manifest,
|
manifest,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
useLiveConfiguration ? mediaItem.liveConfiguration : null);
|
useLiveConfiguration ? mediaItem.liveConfiguration : null);
|
||||||
|
|
@ -176,7 +178,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link #SinglePeriodTimeline(long, long, long, long, long, long, long, boolean,
|
* @deprecated Use {@link #SinglePeriodTimeline(long, long, long, long, long, long, long, boolean,
|
||||||
* boolean, Object, MediaItem, MediaItem.LiveConfiguration)} instead.
|
* boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public SinglePeriodTimeline(
|
public SinglePeriodTimeline(
|
||||||
|
|
@ -202,11 +204,46 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
windowDefaultStartPositionUs,
|
windowDefaultStartPositionUs,
|
||||||
isSeekable,
|
isSeekable,
|
||||||
isDynamic,
|
isDynamic,
|
||||||
|
/* suppressPositionProjection= */ false,
|
||||||
manifest,
|
manifest,
|
||||||
MEDIA_ITEM.buildUpon().setTag(tag).build(),
|
MEDIA_ITEM.buildUpon().setTag(tag).build(),
|
||||||
isLive ? MEDIA_ITEM.liveConfiguration : null);
|
isLive ? MEDIA_ITEM.liveConfiguration : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #SinglePeriodTimeline(long, long, long, long, long, long, long, boolean,
|
||||||
|
* boolean, boolean, Object, MediaItem, MediaItem.LiveConfiguration)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public SinglePeriodTimeline(
|
||||||
|
long presentationStartTimeMs,
|
||||||
|
long windowStartTimeMs,
|
||||||
|
long elapsedRealtimeEpochOffsetMs,
|
||||||
|
long periodDurationUs,
|
||||||
|
long windowDurationUs,
|
||||||
|
long windowPositionInPeriodUs,
|
||||||
|
long windowDefaultStartPositionUs,
|
||||||
|
boolean isSeekable,
|
||||||
|
boolean isDynamic,
|
||||||
|
@Nullable Object manifest,
|
||||||
|
MediaItem mediaItem,
|
||||||
|
@Nullable MediaItem.LiveConfiguration liveConfiguration) {
|
||||||
|
this(
|
||||||
|
presentationStartTimeMs,
|
||||||
|
windowStartTimeMs,
|
||||||
|
elapsedRealtimeEpochOffsetMs,
|
||||||
|
periodDurationUs,
|
||||||
|
windowDurationUs,
|
||||||
|
windowPositionInPeriodUs,
|
||||||
|
windowDefaultStartPositionUs,
|
||||||
|
isSeekable,
|
||||||
|
isDynamic,
|
||||||
|
/* suppressPositionProjection= */ false,
|
||||||
|
manifest,
|
||||||
|
mediaItem,
|
||||||
|
liveConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a timeline with one period, and a window of known duration starting at a specified
|
* Creates a timeline with one period, and a window of known duration starting at a specified
|
||||||
* position in the period.
|
* position in the period.
|
||||||
|
|
@ -226,6 +263,9 @@ 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 suppressPositionProjection Whether {@link #getWindow(int, Window, long) position
|
||||||
|
* projection} in a playlist should be suppressed. This only applies for dynamic timelines and
|
||||||
|
* is ignored otherwise.
|
||||||
* @param manifest The manifest. May be {@code null}.
|
* @param manifest The manifest. May be {@code null}.
|
||||||
* @param mediaItem A media item used for {@link Timeline.Window#mediaItem}.
|
* @param mediaItem A media item used for {@link Timeline.Window#mediaItem}.
|
||||||
* @param liveConfiguration The configuration for live playback behaviour, or {@code null} if the
|
* @param liveConfiguration The configuration for live playback behaviour, or {@code null} if the
|
||||||
|
|
@ -241,6 +281,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
long windowDefaultStartPositionUs,
|
long windowDefaultStartPositionUs,
|
||||||
boolean isSeekable,
|
boolean isSeekable,
|
||||||
boolean isDynamic,
|
boolean isDynamic,
|
||||||
|
boolean suppressPositionProjection,
|
||||||
@Nullable Object manifest,
|
@Nullable Object manifest,
|
||||||
MediaItem mediaItem,
|
MediaItem mediaItem,
|
||||||
@Nullable MediaItem.LiveConfiguration liveConfiguration) {
|
@Nullable MediaItem.LiveConfiguration liveConfiguration) {
|
||||||
|
|
@ -253,6 +294,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.suppressPositionProjection = suppressPositionProjection;
|
||||||
this.manifest = manifest;
|
this.manifest = manifest;
|
||||||
this.mediaItem = checkNotNull(mediaItem);
|
this.mediaItem = checkNotNull(mediaItem);
|
||||||
this.liveConfiguration = liveConfiguration;
|
this.liveConfiguration = liveConfiguration;
|
||||||
|
|
@ -268,7 +310,7 @@ public final class SinglePeriodTimeline extends Timeline {
|
||||||
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
public Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {
|
||||||
Assertions.checkIndex(windowIndex, 0, 1);
|
Assertions.checkIndex(windowIndex, 0, 1);
|
||||||
long windowDefaultStartPositionUs = this.windowDefaultStartPositionUs;
|
long windowDefaultStartPositionUs = this.windowDefaultStartPositionUs;
|
||||||
if (isDynamic && defaultPositionProjectionUs != 0) {
|
if (isDynamic && !suppressPositionProjection && defaultPositionProjectionUs != 0) {
|
||||||
if (windowDurationUs == C.TIME_UNSET) {
|
if (windowDurationUs == C.TIME_UNSET) {
|
||||||
// Don't allow projection into a window that has an unknown duration.
|
// Don't allow projection into a window that has an unknown duration.
|
||||||
windowDefaultStartPositionUs = C.TIME_UNSET;
|
windowDefaultStartPositionUs = C.TIME_UNSET;
|
||||||
|
|
|
||||||
|
|
@ -9206,6 +9206,7 @@ public final class ExoPlayerTest {
|
||||||
/* windowDefaultStartPositionUs= */ 0,
|
/* windowDefaultStartPositionUs= */ 0,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ true,
|
/* isDynamic= */ true,
|
||||||
|
/* suppressPositionProjection= */ false,
|
||||||
/* manifest= */ null,
|
/* manifest= */ null,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
mediaItem.liveConfiguration);
|
mediaItem.liveConfiguration);
|
||||||
|
|
|
||||||
|
|
@ -559,6 +559,9 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
maybeUpdateLiveConfiguration(targetLiveOffsetUs);
|
maybeUpdateLiveConfiguration(targetLiveOffsetUs);
|
||||||
long windowDefaultStartPositionUs =
|
long windowDefaultStartPositionUs =
|
||||||
getLiveWindowDefaultStartPositionUs(playlist, liveEdgeOffsetUs);
|
getLiveWindowDefaultStartPositionUs(playlist, liveEdgeOffsetUs);
|
||||||
|
boolean suppressPositionProjection =
|
||||||
|
playlist.playlistType == HlsMediaPlaylist.PLAYLIST_TYPE_EVENT
|
||||||
|
&& playlist.hasPositiveStartOffset;
|
||||||
return new SinglePeriodTimeline(
|
return new SinglePeriodTimeline(
|
||||||
presentationStartTimeMs,
|
presentationStartTimeMs,
|
||||||
windowStartTimeMs,
|
windowStartTimeMs,
|
||||||
|
|
@ -569,6 +572,7 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
windowDefaultStartPositionUs,
|
windowDefaultStartPositionUs,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ !playlist.hasEndTag,
|
/* isDynamic= */ !playlist.hasEndTag,
|
||||||
|
suppressPositionProjection,
|
||||||
manifest,
|
manifest,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
liveConfiguration);
|
liveConfiguration);
|
||||||
|
|
@ -601,6 +605,7 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
windowDefaultStartPositionUs,
|
windowDefaultStartPositionUs,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ false,
|
/* isDynamic= */ false,
|
||||||
|
/* suppressPositionProjection= */ true,
|
||||||
manifest,
|
manifest,
|
||||||
mediaItem,
|
mediaItem,
|
||||||
/* liveConfiguration= */ null);
|
/* liveConfiguration= */ null);
|
||||||
|
|
|
||||||
|
|
@ -401,6 +401,11 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||||
* {@link #durationUs}, inclusive.
|
* {@link #durationUs}, inclusive.
|
||||||
*/
|
*/
|
||||||
public final long startOffsetUs;
|
public final long startOffsetUs;
|
||||||
|
/**
|
||||||
|
* Whether the {@link #startOffsetUs} was explicitly defined by #EXT-X-START as a positive value
|
||||||
|
* or zero.
|
||||||
|
*/
|
||||||
|
public final boolean hasPositiveStartOffset;
|
||||||
/** Whether the start position should be precise, as defined by #EXT-X-START. */
|
/** Whether the start position should be precise, as defined by #EXT-X-START. */
|
||||||
public final boolean preciseStart;
|
public final boolean preciseStart;
|
||||||
/**
|
/**
|
||||||
|
|
@ -537,6 +542,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||||
: startOffsetUs >= 0
|
: startOffsetUs >= 0
|
||||||
? min(durationUs, startOffsetUs)
|
? min(durationUs, startOffsetUs)
|
||||||
: max(0, durationUs + startOffsetUs);
|
: max(0, durationUs + startOffsetUs);
|
||||||
|
this.hasPositiveStartOffset = startOffsetUs >= 0;
|
||||||
this.serverControl = serverControl;
|
this.serverControl = serverControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue