Gradle dependencies
compile group: 'androidx.media3', name: 'media3-exoplayer-hls', version: '1.0.0-alpha03'
- groupId: androidx.media3
- artifactId: media3-exoplayer-hls
- version: 1.0.0-alpha03
Artifact androidx.media3:media3-exoplayer-hls:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)
Overview
Represents an HLS media playlist.
Summary
Fields |
---|
public final int | discontinuitySequence The discontinuity sequence number of the first media segment in the playlist, as defined by
#EXT-X-DISCONTINUITY-SEQUENCE. |
public final long | durationUs The total duration of the playlist in microseconds. |
public final boolean | hasDiscontinuitySequence Whether the playlist contains the #EXT-X-DISCONTINUITY-SEQUENCE tag. |
public final boolean | hasEndTag Whether the playlist contains the #EXT-X-ENDLIST tag. |
public final boolean | hasPositiveStartOffset Whether the HlsMediaPlaylist.startOffsetUs was explicitly defined by #EXT-X-START as a positive value
or zero. |
public final boolean | hasProgramDateTime Whether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag. |
public final long | mediaSequence The media sequence number of the first media segment in the playlist, as defined by
#EXT-X-MEDIA-SEQUENCE. |
public final long | partTargetDurationUs The target duration for segment parts, as defined by #EXT-X-PART-INF, or C.TIME_UNSET
if undefined. |
public static final int | PLAYLIST_TYPE_EVENT |
public static final int | PLAYLIST_TYPE_UNKNOWN |
public static final int | PLAYLIST_TYPE_VOD |
public final int | playlistType The type of the playlist. |
public final boolean | preciseStart Whether the start position should be precise, as defined by #EXT-X-START. |
public final DrmInitData | protectionSchemes Contains the CDM protection schemes used by segments in this playlist. |
public final java.util.Map<Uri, HlsMediaPlaylist.RenditionReport> | renditionReports The rendition reports of alternative rendition playlists. |
public final java.util.List<HlsMediaPlaylist.Segment> | segments The list of segments in the playlist. |
public final HlsMediaPlaylist.ServerControl | serverControl The attributes of the #EXT-X-SERVER-CONTROL header. |
public final long | startOffsetUs The start offset in microseconds from the beginning of the playlist, as defined by
#EXT-X-START, or C.TIME_UNSET if undefined. |
public final long | startTimeUs If HlsMediaPlaylist.hasProgramDateTime is true, contains the datetime as microseconds since epoch. |
public final long | targetDurationUs The target duration in microseconds, as defined by #EXT-X-TARGETDURATION. |
public final java.util.List<HlsMediaPlaylist.Part> | trailingParts The list of parts at the end of the playlist for which the segment is not in the playlist yet. |
public final int | version The compatibility version, as defined by #EXT-X-VERSION. |
from HlsPlaylist | baseUri, hasIndependentSegments, tags |
Constructors |
---|
public | HlsMediaPlaylist(int playlistType, java.lang.String baseUri, java.util.List<java.lang.String> tags, long startOffsetUs, boolean preciseStart, long startTimeUs, boolean hasDiscontinuitySequence, int discontinuitySequence, long mediaSequence, int version, long targetDurationUs, long partTargetDurationUs, boolean hasIndependentSegments, boolean hasEndTag, boolean hasProgramDateTime, DrmInitData protectionSchemes, java.util.List<HlsMediaPlaylist.Segment> segments, java.util.List<HlsMediaPlaylist.Part> trailingParts, HlsMediaPlaylist.ServerControl serverControl, java.util.Map<Uri, HlsMediaPlaylist.RenditionReport> renditionReports)
|
Methods |
---|
public HlsMediaPlaylist | copy(java.util.List<StreamKey> streamKeys)
|
public HlsMediaPlaylist | copyWith(long startTimeUs, int discontinuitySequence)
Returns a playlist identical to this one except for the start time, the discontinuity sequence
and hasDiscontinuitySequence values. |
public HlsMediaPlaylist | copyWithEndTag()
Returns a playlist identical to this one except that an end tag is added. |
public long | getEndTimeUs()
Returns the result of adding the duration of the playlist to its start time. |
public boolean | isNewerThan(HlsMediaPlaylist other)
Returns whether this playlist is newer than other. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Fields
public static final int
PLAYLIST_TYPE_UNKNOWNpublic static final int
PLAYLIST_TYPE_VODpublic static final int
PLAYLIST_TYPE_EVENTpublic final int
playlistTypeThe type of the playlist. See HlsMediaPlaylist.PlaylistType.
public final long
startOffsetUsThe start offset in microseconds from the beginning of the playlist, as defined by
#EXT-X-START, or C.TIME_UNSET if undefined. The value is guaranteed to be between 0 and
HlsMediaPlaylist.durationUs, inclusive.
public final boolean
hasPositiveStartOffsetWhether the HlsMediaPlaylist.startOffsetUs was explicitly defined by #EXT-X-START as a positive value
or zero.
public final boolean
preciseStartWhether the start position should be precise, as defined by #EXT-X-START.
public final long
startTimeUsIf HlsMediaPlaylist.hasProgramDateTime is true, contains the datetime as microseconds since epoch.
Otherwise, contains the aggregated duration of removed segments up to this snapshot of the
playlist.
public final boolean
hasDiscontinuitySequenceWhether the playlist contains the #EXT-X-DISCONTINUITY-SEQUENCE tag.
public final int
discontinuitySequenceThe discontinuity sequence number of the first media segment in the playlist, as defined by
#EXT-X-DISCONTINUITY-SEQUENCE.
public final long
mediaSequenceThe media sequence number of the first media segment in the playlist, as defined by
#EXT-X-MEDIA-SEQUENCE.
The compatibility version, as defined by #EXT-X-VERSION.
public final long
targetDurationUsThe target duration in microseconds, as defined by #EXT-X-TARGETDURATION.
public final long
partTargetDurationUsThe target duration for segment parts, as defined by #EXT-X-PART-INF, or C.TIME_UNSET
if undefined.
public final boolean
hasEndTagWhether the playlist contains the #EXT-X-ENDLIST tag.
public final boolean
hasProgramDateTimeWhether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag.
Contains the CDM protection schemes used by segments in this playlist. Does not contain any key
acquisition data. Null if none of the segments in the playlist is CDM-encrypted.
public final java.util.List<HlsMediaPlaylist.Segment>
segmentsThe list of segments in the playlist.
public final java.util.List<HlsMediaPlaylist.Part>
trailingPartsThe list of parts at the end of the playlist for which the segment is not in the playlist yet.
public final java.util.Map<Uri, HlsMediaPlaylist.RenditionReport>
renditionReportsThe rendition reports of alternative rendition playlists.
public final long
durationUsThe total duration of the playlist in microseconds.
The attributes of the #EXT-X-SERVER-CONTROL header.
Constructors
public
HlsMediaPlaylist(int playlistType, java.lang.String baseUri, java.util.List<java.lang.String> tags, long startOffsetUs, boolean preciseStart, long startTimeUs, boolean hasDiscontinuitySequence, int discontinuitySequence, long mediaSequence, int version, long targetDurationUs, long partTargetDurationUs, boolean hasIndependentSegments, boolean hasEndTag, boolean hasProgramDateTime,
DrmInitData protectionSchemes, java.util.List<HlsMediaPlaylist.Segment> segments, java.util.List<HlsMediaPlaylist.Part> trailingParts,
HlsMediaPlaylist.ServerControl serverControl, java.util.Map<Uri, HlsMediaPlaylist.RenditionReport> renditionReports)
Parameters:
playlistType: See HlsMediaPlaylist.playlistType.
baseUri: See HlsPlaylist.baseUri.
tags: See HlsPlaylist.tags.
startOffsetUs: See HlsMediaPlaylist.startOffsetUs.
startTimeUs: See HlsMediaPlaylist.startTimeUs.
hasDiscontinuitySequence: See HlsMediaPlaylist.hasDiscontinuitySequence.
discontinuitySequence: See HlsMediaPlaylist.discontinuitySequence.
mediaSequence: See HlsMediaPlaylist.mediaSequence.
version: See HlsMediaPlaylist.version.
targetDurationUs: See HlsMediaPlaylist.targetDurationUs.
hasIndependentSegments: See HlsPlaylist.hasIndependentSegments.
hasEndTag: See HlsMediaPlaylist.hasEndTag.
hasProgramDateTime: See HlsMediaPlaylist.hasProgramDateTime.
protectionSchemes: See HlsMediaPlaylist.protectionSchemes.
segments: See HlsMediaPlaylist.segments.
trailingParts: See HlsMediaPlaylist.trailingParts.
serverControl: See HlsMediaPlaylist.serverControl
renditionReports: See HlsMediaPlaylist.renditionReports.
Methods
Returns whether this playlist is newer than other.
Parameters:
other: The playlist to compare.
Returns:
Whether this playlist is newer than other.
public long
getEndTimeUs()
Returns the result of adding the duration of the playlist to its start time.
Returns a playlist identical to this one except for the start time, the discontinuity sequence
and hasDiscontinuitySequence values. The first two are set to the specified values,
hasDiscontinuitySequence is set to true.
Parameters:
startTimeUs: The start time for the returned playlist.
discontinuitySequence: The discontinuity sequence for the returned playlist.
Returns:
An identical playlist including the provided discontinuity and timing information.
Returns a playlist identical to this one except that an end tag is added. If an end tag is
already present then the playlist will return itself.
Source
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.exoplayer.hls.playlist;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.DrmInitData;
import androidx.media3.common.StreamKey;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/** Represents an HLS media playlist. */
@UnstableApi
public final class HlsMediaPlaylist extends HlsPlaylist {
/** Server control attributes. */
public static final class ServerControl {
/**
* The skip boundary for delta updates in microseconds, or {@link C#TIME_UNSET} if delta updates
* are not supported.
*/
public final long skipUntilUs;
/**
* Whether the playlist can produce delta updates that skip older #EXT-X-DATERANGE tags in
* addition to media segments.
*/
public final boolean canSkipDateRanges;
/**
* The server-recommended live offset in microseconds, or {@link C#TIME_UNSET} if none defined.
*/
public final long holdBackUs;
/**
* The server-recommended live offset in microseconds in low-latency mode, or {@link
* C#TIME_UNSET} if none defined.
*/
public final long partHoldBackUs;
/** Whether the server supports blocking playlist reload. */
public final boolean canBlockReload;
/**
* Creates a new instance.
*
* @param skipUntilUs See {@link #skipUntilUs}.
* @param canSkipDateRanges See {@link #canSkipDateRanges}.
* @param holdBackUs See {@link #holdBackUs}.
* @param partHoldBackUs See {@link #partHoldBackUs}.
* @param canBlockReload See {@link #canBlockReload}.
*/
public ServerControl(
long skipUntilUs,
boolean canSkipDateRanges,
long holdBackUs,
long partHoldBackUs,
boolean canBlockReload) {
this.skipUntilUs = skipUntilUs;
this.canSkipDateRanges = canSkipDateRanges;
this.holdBackUs = holdBackUs;
this.partHoldBackUs = partHoldBackUs;
this.canBlockReload = canBlockReload;
}
}
/** Media segment reference. */
@SuppressWarnings("ComparableType")
public static final class Segment extends SegmentBase {
/** The human readable title of the segment. */
public final String title;
/** The parts belonging to this segment. */
public final List<Part> parts;
/**
* Creates an instance to be used as init segment.
*
* @param uri See {@link #url}.
* @param byteRangeOffset See {@link #byteRangeOffset}.
* @param byteRangeLength See {@link #byteRangeLength}.
* @param fullSegmentEncryptionKeyUri See {@link #fullSegmentEncryptionKeyUri}.
* @param encryptionIV See {@link #encryptionIV}.
*/
public Segment(
String uri,
long byteRangeOffset,
long byteRangeLength,
@Nullable String fullSegmentEncryptionKeyUri,
@Nullable String encryptionIV) {
this(
uri,
/* initializationSegment= */ null,
/* title= */ "",
/* durationUs= */ 0,
/* relativeDiscontinuitySequence= */ -1,
/* relativeStartTimeUs= */ C.TIME_UNSET,
/* drmInitData= */ null,
fullSegmentEncryptionKeyUri,
encryptionIV,
byteRangeOffset,
byteRangeLength,
/* hasGapTag= */ false,
/* parts= */ ImmutableList.of());
}
/**
* Creates an instance.
*
* @param url See {@link #url}.
* @param initializationSegment See {@link #initializationSegment}.
* @param title See {@link #title}.
* @param durationUs See {@link #durationUs}.
* @param relativeDiscontinuitySequence See {@link #relativeDiscontinuitySequence}.
* @param relativeStartTimeUs See {@link #relativeStartTimeUs}.
* @param drmInitData See {@link #drmInitData}.
* @param fullSegmentEncryptionKeyUri See {@link #fullSegmentEncryptionKeyUri}.
* @param encryptionIV See {@link #encryptionIV}.
* @param byteRangeOffset See {@link #byteRangeOffset}.
* @param byteRangeLength See {@link #byteRangeLength}.
* @param hasGapTag See {@link #hasGapTag}.
* @param parts See {@link #parts}.
*/
public Segment(
String url,
@Nullable Segment initializationSegment,
String title,
long durationUs,
int relativeDiscontinuitySequence,
long relativeStartTimeUs,
@Nullable DrmInitData drmInitData,
@Nullable String fullSegmentEncryptionKeyUri,
@Nullable String encryptionIV,
long byteRangeOffset,
long byteRangeLength,
boolean hasGapTag,
List<Part> parts) {
super(
url,
initializationSegment,
durationUs,
relativeDiscontinuitySequence,
relativeStartTimeUs,
drmInitData,
fullSegmentEncryptionKeyUri,
encryptionIV,
byteRangeOffset,
byteRangeLength,
hasGapTag);
this.title = title;
this.parts = ImmutableList.copyOf(parts);
}
public Segment copyWith(long relativeStartTimeUs, int relativeDiscontinuitySequence) {
List<Part> updatedParts = new ArrayList<>();
long relativePartStartTimeUs = relativeStartTimeUs;
for (int i = 0; i < parts.size(); i++) {
Part part = parts.get(i);
updatedParts.add(part.copyWith(relativePartStartTimeUs, relativeDiscontinuitySequence));
relativePartStartTimeUs += part.durationUs;
}
return new Segment(
url,
initializationSegment,
title,
durationUs,
relativeDiscontinuitySequence,
relativeStartTimeUs,
drmInitData,
fullSegmentEncryptionKeyUri,
encryptionIV,
byteRangeOffset,
byteRangeLength,
hasGapTag,
updatedParts);
}
}
/** A media part. */
public static final class Part extends SegmentBase {
/** Whether the part is independent. */
public final boolean isIndependent;
/** Whether the part is a preloading part. */
public final boolean isPreload;
/**
* Creates an instance.
*
* @param url See {@link #url}.
* @param initializationSegment See {@link #initializationSegment}.
* @param durationUs See {@link #durationUs}.
* @param relativeDiscontinuitySequence See {@link #relativeDiscontinuitySequence}.
* @param relativeStartTimeUs See {@link #relativeStartTimeUs}.
* @param drmInitData See {@link #drmInitData}.
* @param fullSegmentEncryptionKeyUri See {@link #fullSegmentEncryptionKeyUri}.
* @param encryptionIV See {@link #encryptionIV}.
* @param byteRangeOffset See {@link #byteRangeOffset}.
* @param byteRangeLength See {@link #byteRangeLength}.
* @param hasGapTag See {@link #hasGapTag}.
* @param isIndependent See {@link #isIndependent}.
* @param isPreload See {@link #isPreload}.
*/
public Part(
String url,
@Nullable Segment initializationSegment,
long durationUs,
int relativeDiscontinuitySequence,
long relativeStartTimeUs,
@Nullable DrmInitData drmInitData,
@Nullable String fullSegmentEncryptionKeyUri,
@Nullable String encryptionIV,
long byteRangeOffset,
long byteRangeLength,
boolean hasGapTag,
boolean isIndependent,
boolean isPreload) {
super(
url,
initializationSegment,
durationUs,
relativeDiscontinuitySequence,
relativeStartTimeUs,
drmInitData,
fullSegmentEncryptionKeyUri,
encryptionIV,
byteRangeOffset,
byteRangeLength,
hasGapTag);
this.isIndependent = isIndependent;
this.isPreload = isPreload;
}
public Part copyWith(long relativeStartTimeUs, int relativeDiscontinuitySequence) {
return new Part(
url,
initializationSegment,
durationUs,
relativeDiscontinuitySequence,
relativeStartTimeUs,
drmInitData,
fullSegmentEncryptionKeyUri,
encryptionIV,
byteRangeOffset,
byteRangeLength,
hasGapTag,
isIndependent,
isPreload);
}
}
/** The base for a {@link Segment} or a {@link Part} required for playback. */
@SuppressWarnings("ComparableType")
public static class SegmentBase implements Comparable<Long> {
/** The url of the segment. */
public final String url;
/**
* The media initialization section for this segment, as defined by #EXT-X-MAP. May be null if
* the media playlist does not define a media initialization section for this segment. The same
* instance is used for all segments that share an EXT-X-MAP tag.
*/
@Nullable public final Segment initializationSegment;
/** The duration of the segment in microseconds, as defined by #EXTINF or #EXT-X-PART. */
public final long durationUs;
/** The number of #EXT-X-DISCONTINUITY tags in the playlist before the segment. */
public final int relativeDiscontinuitySequence;
/** The start time of the segment in microseconds, relative to the start of the playlist. */
public final long relativeStartTimeUs;
/**
* DRM initialization data for sample decryption, or null if the segment does not use CDM-DRM
* protection.
*/
@Nullable public final DrmInitData drmInitData;
/**
* The encryption identity key uri as defined by #EXT-X-KEY, or null if the segment does not use
* full segment encryption with identity key.
*/
@Nullable public final String fullSegmentEncryptionKeyUri;
/**
* The encryption initialization vector as defined by #EXT-X-KEY, or null if the segment is not
* encrypted.
*/
@Nullable public final String encryptionIV;
/**
* The segment's byte range offset, as defined by #EXT-X-BYTERANGE, #EXT-X-PART or
* #EXT-X-PRELOAD-HINT.
*/
public final long byteRangeOffset;
/**
* The segment's byte range length, as defined by #EXT-X-BYTERANGE, #EXT-X-PART or
* #EXT-X-PRELOAD-HINT, or {@link C#LENGTH_UNSET} if no byte range is specified or the byte
* range is open-ended.
*/
public final long byteRangeLength;
/** Whether the segment is marked as a gap. */
public final boolean hasGapTag;
private SegmentBase(
String url,
@Nullable Segment initializationSegment,
long durationUs,
int relativeDiscontinuitySequence,
long relativeStartTimeUs,
@Nullable DrmInitData drmInitData,
@Nullable String fullSegmentEncryptionKeyUri,
@Nullable String encryptionIV,
long byteRangeOffset,
long byteRangeLength,
boolean hasGapTag) {
this.url = url;
this.initializationSegment = initializationSegment;
this.durationUs = durationUs;
this.relativeDiscontinuitySequence = relativeDiscontinuitySequence;
this.relativeStartTimeUs = relativeStartTimeUs;
this.drmInitData = drmInitData;
this.fullSegmentEncryptionKeyUri = fullSegmentEncryptionKeyUri;
this.encryptionIV = encryptionIV;
this.byteRangeOffset = byteRangeOffset;
this.byteRangeLength = byteRangeLength;
this.hasGapTag = hasGapTag;
}
@Override
public int compareTo(Long relativeStartTimeUs) {
return this.relativeStartTimeUs > relativeStartTimeUs
? 1
: (this.relativeStartTimeUs < relativeStartTimeUs ? -1 : 0);
}
}
/**
* A rendition report for an alternative rendition defined in another media playlist.
*
* <p>See RFC 8216, section 4.4.5.1.4.
*/
public static final class RenditionReport {
/** The URI of the media playlist of the reported rendition. */
public final Uri playlistUri;
/** The last media sequence that is in the playlist of the reported rendition. */
public final long lastMediaSequence;
/**
* The last part index that is in the playlist of the reported rendition, or {@link
* C#INDEX_UNSET} if the rendition does not contain partial segments.
*/
public final int lastPartIndex;
/**
* Creates a new instance.
*
* @param playlistUri See {@link #playlistUri}.
* @param lastMediaSequence See {@link #lastMediaSequence}.
* @param lastPartIndex See {@link #lastPartIndex}.
*/
public RenditionReport(Uri playlistUri, long lastMediaSequence, int lastPartIndex) {
this.playlistUri = playlistUri;
this.lastMediaSequence = lastMediaSequence;
this.lastPartIndex = lastPartIndex;
}
}
/**
* Type of the playlist, as defined by #EXT-X-PLAYLIST-TYPE. One of {@link
* #PLAYLIST_TYPE_UNKNOWN}, {@link #PLAYLIST_TYPE_VOD} or {@link #PLAYLIST_TYPE_EVENT}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({PLAYLIST_TYPE_UNKNOWN, PLAYLIST_TYPE_VOD, PLAYLIST_TYPE_EVENT})
public @interface PlaylistType {}
public static final int PLAYLIST_TYPE_UNKNOWN = 0;
public static final int PLAYLIST_TYPE_VOD = 1;
public static final int PLAYLIST_TYPE_EVENT = 2;
/** The type of the playlist. See {@link PlaylistType}. */
public final @PlaylistType int playlistType;
/**
* The start offset in microseconds from the beginning of the playlist, as defined by
* #EXT-X-START, or {@link C#TIME_UNSET} if undefined. The value is guaranteed to be between 0 and
* {@link #durationUs}, inclusive.
*/
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. */
public final boolean preciseStart;
/**
* If {@link #hasProgramDateTime} is true, contains the datetime as microseconds since epoch.
* Otherwise, contains the aggregated duration of removed segments up to this snapshot of the
* playlist.
*/
public final long startTimeUs;
/** Whether the playlist contains the #EXT-X-DISCONTINUITY-SEQUENCE tag. */
public final boolean hasDiscontinuitySequence;
/**
* The discontinuity sequence number of the first media segment in the playlist, as defined by
* #EXT-X-DISCONTINUITY-SEQUENCE.
*/
public final int discontinuitySequence;
/**
* The media sequence number of the first media segment in the playlist, as defined by
* #EXT-X-MEDIA-SEQUENCE.
*/
public final long mediaSequence;
/** The compatibility version, as defined by #EXT-X-VERSION. */
public final int version;
/** The target duration in microseconds, as defined by #EXT-X-TARGETDURATION. */
public final long targetDurationUs;
/**
* The target duration for segment parts, as defined by #EXT-X-PART-INF, or {@link C#TIME_UNSET}
* if undefined.
*/
public final long partTargetDurationUs;
/** Whether the playlist contains the #EXT-X-ENDLIST tag. */
public final boolean hasEndTag;
/** Whether the playlist contains a #EXT-X-PROGRAM-DATE-TIME tag. */
public final boolean hasProgramDateTime;
/**
* Contains the CDM protection schemes used by segments in this playlist. Does not contain any key
* acquisition data. Null if none of the segments in the playlist is CDM-encrypted.
*/
@Nullable public final DrmInitData protectionSchemes;
/** The list of segments in the playlist. */
public final List<Segment> segments;
/**
* The list of parts at the end of the playlist for which the segment is not in the playlist yet.
*/
public final List<Part> trailingParts;
/** The rendition reports of alternative rendition playlists. */
public final Map<Uri, RenditionReport> renditionReports;
/** The total duration of the playlist in microseconds. */
public final long durationUs;
/** The attributes of the #EXT-X-SERVER-CONTROL header. */
public final ServerControl serverControl;
/**
* @param playlistType See {@link #playlistType}.
* @param baseUri See {@link #baseUri}.
* @param tags See {@link #tags}.
* @param startOffsetUs See {@link #startOffsetUs}.
* @param startTimeUs See {@link #startTimeUs}.
* @param hasDiscontinuitySequence See {@link #hasDiscontinuitySequence}.
* @param discontinuitySequence See {@link #discontinuitySequence}.
* @param mediaSequence See {@link #mediaSequence}.
* @param version See {@link #version}.
* @param targetDurationUs See {@link #targetDurationUs}.
* @param hasIndependentSegments See {@link #hasIndependentSegments}.
* @param hasEndTag See {@link #hasEndTag}.
* @param hasProgramDateTime See {@link #hasProgramDateTime}.
* @param protectionSchemes See {@link #protectionSchemes}.
* @param segments See {@link #segments}.
* @param trailingParts See {@link #trailingParts}.
* @param serverControl See {@link #serverControl}
* @param renditionReports See {@link #renditionReports}.
*/
public HlsMediaPlaylist(
@PlaylistType int playlistType,
String baseUri,
List<String> tags,
long startOffsetUs,
boolean preciseStart,
long startTimeUs,
boolean hasDiscontinuitySequence,
int discontinuitySequence,
long mediaSequence,
int version,
long targetDurationUs,
long partTargetDurationUs,
boolean hasIndependentSegments,
boolean hasEndTag,
boolean hasProgramDateTime,
@Nullable DrmInitData protectionSchemes,
List<Segment> segments,
List<Part> trailingParts,
ServerControl serverControl,
Map<Uri, RenditionReport> renditionReports) {
super(baseUri, tags, hasIndependentSegments);
this.playlistType = playlistType;
this.startTimeUs = startTimeUs;
this.preciseStart = preciseStart;
this.hasDiscontinuitySequence = hasDiscontinuitySequence;
this.discontinuitySequence = discontinuitySequence;
this.mediaSequence = mediaSequence;
this.version = version;
this.targetDurationUs = targetDurationUs;
this.partTargetDurationUs = partTargetDurationUs;
this.hasEndTag = hasEndTag;
this.hasProgramDateTime = hasProgramDateTime;
this.protectionSchemes = protectionSchemes;
this.segments = ImmutableList.copyOf(segments);
this.trailingParts = ImmutableList.copyOf(trailingParts);
this.renditionReports = ImmutableMap.copyOf(renditionReports);
if (!trailingParts.isEmpty()) {
Part lastPart = Iterables.getLast(trailingParts);
durationUs = lastPart.relativeStartTimeUs + lastPart.durationUs;
} else if (!segments.isEmpty()) {
Segment lastSegment = Iterables.getLast(segments);
durationUs = lastSegment.relativeStartTimeUs + lastSegment.durationUs;
} else {
durationUs = 0;
}
// From RFC 8216, section 4.4.2.2: If startOffsetUs is negative, it indicates the offset from
// the end of the playlist. If the absolute value exceeds the duration of the playlist, it
// indicates the beginning (if negative) or the end (if positive) of the playlist.
this.startOffsetUs =
startOffsetUs == C.TIME_UNSET
? C.TIME_UNSET
: startOffsetUs >= 0
? min(durationUs, startOffsetUs)
: max(0, durationUs + startOffsetUs);
this.hasPositiveStartOffset = startOffsetUs >= 0;
this.serverControl = serverControl;
}
@Override
public HlsMediaPlaylist copy(List<StreamKey> streamKeys) {
return this;
}
/**
* Returns whether this playlist is newer than {@code other}.
*
* @param other The playlist to compare.
* @return Whether this playlist is newer than {@code other}.
*/
public boolean isNewerThan(@Nullable HlsMediaPlaylist other) {
if (other == null || mediaSequence > other.mediaSequence) {
return true;
}
if (mediaSequence < other.mediaSequence) {
return false;
}
// The media sequences are equal.
int segmentCountDifference = segments.size() - other.segments.size();
if (segmentCountDifference != 0) {
return segmentCountDifference > 0;
}
int partCount = trailingParts.size();
int otherPartCount = other.trailingParts.size();
return partCount > otherPartCount
|| (partCount == otherPartCount && hasEndTag && !other.hasEndTag);
}
/** Returns the result of adding the duration of the playlist to its start time. */
public long getEndTimeUs() {
return startTimeUs + durationUs;
}
/**
* Returns a playlist identical to this one except for the start time, the discontinuity sequence
* and {@code hasDiscontinuitySequence} values. The first two are set to the specified values,
* {@code hasDiscontinuitySequence} is set to true.
*
* @param startTimeUs The start time for the returned playlist.
* @param discontinuitySequence The discontinuity sequence for the returned playlist.
* @return An identical playlist including the provided discontinuity and timing information.
*/
public HlsMediaPlaylist copyWith(long startTimeUs, int discontinuitySequence) {
return new HlsMediaPlaylist(
playlistType,
baseUri,
tags,
startOffsetUs,
preciseStart,
startTimeUs,
/* hasDiscontinuitySequence= */ true,
discontinuitySequence,
mediaSequence,
version,
targetDurationUs,
partTargetDurationUs,
hasIndependentSegments,
hasEndTag,
hasProgramDateTime,
protectionSchemes,
segments,
trailingParts,
serverControl,
renditionReports);
}
/**
* Returns a playlist identical to this one except that an end tag is added. If an end tag is
* already present then the playlist will return itself.
*/
public HlsMediaPlaylist copyWithEndTag() {
if (this.hasEndTag) {
return this;
}
return new HlsMediaPlaylist(
playlistType,
baseUri,
tags,
startOffsetUs,
preciseStart,
startTimeUs,
hasDiscontinuitySequence,
discontinuitySequence,
mediaSequence,
version,
targetDurationUs,
partTargetDurationUs,
hasIndependentSegments,
/* hasEndTag= */ true,
hasProgramDateTime,
protectionSchemes,
segments,
trailingParts,
serverControl,
renditionReports);
}
}