Use long for HLS media sequences
Issue:#3747 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=183366339
This commit is contained in:
parent
bc9dbdb49e
commit
677fc291cf
@ -67,6 +67,8 @@
|
||||
([#3653](https://github.com/google/ExoPlayer/issues/3653)).
|
||||
* Fix ID3 context reuse across segment format changes
|
||||
([#3622](https://github.com/google/ExoPlayer/issues/3622)).
|
||||
* Use long for media sequence numbers
|
||||
([#3747](https://github.com/google/ExoPlayer/issues/3747))
|
||||
* New Cast extension: Simplifies toggling between local and Cast playbacks.
|
||||
* Audio:
|
||||
* Support TrueHD passthrough for rechunked samples in Matroska files
|
||||
|
@ -64,7 +64,7 @@ public class ContainerMediaChunk extends BaseMediaChunk {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextChunkIndex() {
|
||||
public long getNextChunkIndex() {
|
||||
return chunkIndex + chunkCount;
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,8 @@ import com.google.android.exoplayer2.util.Assertions;
|
||||
*/
|
||||
public abstract class MediaChunk extends Chunk {
|
||||
|
||||
/**
|
||||
* The chunk index.
|
||||
*/
|
||||
public final int chunkIndex;
|
||||
/** The chunk index. */
|
||||
public final long chunkIndex;
|
||||
|
||||
/**
|
||||
* @param dataSource The source from which the data should be loaded.
|
||||
@ -41,19 +39,23 @@ public abstract class MediaChunk extends Chunk {
|
||||
* @param endTimeUs The end time of the media contained by the chunk, in microseconds.
|
||||
* @param chunkIndex The index of the chunk.
|
||||
*/
|
||||
public MediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat,
|
||||
int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs,
|
||||
int chunkIndex) {
|
||||
public MediaChunk(
|
||||
DataSource dataSource,
|
||||
DataSpec dataSpec,
|
||||
Format trackFormat,
|
||||
int trackSelectionReason,
|
||||
Object trackSelectionData,
|
||||
long startTimeUs,
|
||||
long endTimeUs,
|
||||
long chunkIndex) {
|
||||
super(dataSource, dataSpec, C.DATA_TYPE_MEDIA, trackFormat, trackSelectionReason,
|
||||
trackSelectionData, startTimeUs, endTimeUs);
|
||||
Assertions.checkNotNull(trackFormat);
|
||||
this.chunkIndex = chunkIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next chunk index.
|
||||
*/
|
||||
public int getNextChunkIndex() {
|
||||
/** Returns the next chunk index. */
|
||||
public long getNextChunkIndex() {
|
||||
return chunkIndex + 1;
|
||||
}
|
||||
|
||||
|
@ -311,7 +311,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
segmentNum = Util.constrainValue(representationHolder.getSegmentNum(loadPositionUs),
|
||||
firstAvailableSegmentNum, lastAvailableSegmentNum);
|
||||
} else {
|
||||
segmentNum = previous.getNextChunkIndex();
|
||||
segmentNum = (int) previous.getNextChunkIndex();
|
||||
if (segmentNum < firstAvailableSegmentNum) {
|
||||
// This is before the first chunk in the current manifest.
|
||||
fatalError = new BehindLiveWindowException();
|
||||
|
@ -253,7 +253,7 @@ import java.util.List;
|
||||
updateLiveEdgeTimeUs(mediaPlaylist);
|
||||
|
||||
// Select the chunk.
|
||||
int chunkMediaSequence;
|
||||
long chunkMediaSequence;
|
||||
if (previous == null || switchingVariant) {
|
||||
long targetPositionUs = (previous == null || independentSegments) ? loadPositionUs
|
||||
: previous.startTimeUs;
|
||||
@ -281,7 +281,7 @@ import java.util.List;
|
||||
return;
|
||||
}
|
||||
|
||||
int chunkIndex = chunkMediaSequence - mediaPlaylist.mediaSequence;
|
||||
int chunkIndex = (int) (chunkMediaSequence - mediaPlaylist.mediaSequence);
|
||||
if (chunkIndex >= mediaPlaylist.segments.size()) {
|
||||
if (mediaPlaylist.hasEndTag) {
|
||||
out.endOfStream = true;
|
||||
|
@ -83,8 +83,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
private volatile boolean loadCompleted;
|
||||
|
||||
/**
|
||||
* @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk
|
||||
* extractor is obtained.
|
||||
* @param extractorFactory A {@link HlsExtractorFactory} from which the HLS media chunk extractor
|
||||
* is obtained.
|
||||
* @param dataSource The source from which the data should be loaded.
|
||||
* @param dataSpec Defines the data to be loaded.
|
||||
* @param initDataSpec Defines the initialization data to be fed to new extractors. May be null.
|
||||
@ -95,7 +95,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @param trackSelectionData See {@link #trackSelectionData}.
|
||||
* @param startTimeUs The start time of the chunk in microseconds.
|
||||
* @param endTimeUs The end time of the chunk in microseconds.
|
||||
* @param chunkIndex The media sequence number of the chunk.
|
||||
* @param chunkMediaSequence The media sequence number of the chunk.
|
||||
* @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
|
||||
* @param isMasterTimestampSource True if the chunk can initialize the timestamp adjuster.
|
||||
* @param timestampAdjuster Adjuster corresponding to the provided discontinuity sequence number.
|
||||
@ -106,15 +106,34 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @param encryptionIv The AES initialization vector, or null if the segment is not fully
|
||||
* encrypted.
|
||||
*/
|
||||
public HlsMediaChunk(HlsExtractorFactory extractorFactory, DataSource dataSource,
|
||||
DataSpec dataSpec, DataSpec initDataSpec, HlsUrl hlsUrl, List<Format> muxedCaptionFormats,
|
||||
int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs,
|
||||
int chunkIndex, int discontinuitySequenceNumber, boolean isMasterTimestampSource,
|
||||
TimestampAdjuster timestampAdjuster, HlsMediaChunk previousChunk, DrmInitData drmInitData,
|
||||
byte[] fullSegmentEncryptionKey, byte[] encryptionIv) {
|
||||
super(buildDataSource(dataSource, fullSegmentEncryptionKey, encryptionIv), dataSpec,
|
||||
hlsUrl.format, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs,
|
||||
chunkIndex);
|
||||
public HlsMediaChunk(
|
||||
HlsExtractorFactory extractorFactory,
|
||||
DataSource dataSource,
|
||||
DataSpec dataSpec,
|
||||
DataSpec initDataSpec,
|
||||
HlsUrl hlsUrl,
|
||||
List<Format> muxedCaptionFormats,
|
||||
int trackSelectionReason,
|
||||
Object trackSelectionData,
|
||||
long startTimeUs,
|
||||
long endTimeUs,
|
||||
long chunkMediaSequence,
|
||||
int discontinuitySequenceNumber,
|
||||
boolean isMasterTimestampSource,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
HlsMediaChunk previousChunk,
|
||||
DrmInitData drmInitData,
|
||||
byte[] fullSegmentEncryptionKey,
|
||||
byte[] encryptionIv) {
|
||||
super(
|
||||
buildDataSource(dataSource, fullSegmentEncryptionKey, encryptionIv),
|
||||
dataSpec,
|
||||
hlsUrl.format,
|
||||
trackSelectionReason,
|
||||
trackSelectionData,
|
||||
startTimeUs,
|
||||
endTimeUs,
|
||||
chunkMediaSequence);
|
||||
this.discontinuitySequenceNumber = discontinuitySequenceNumber;
|
||||
this.initDataSpec = initDataSpec;
|
||||
this.hlsUrl = hlsUrl;
|
||||
|
@ -139,7 +139,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* The media sequence number of the first media segment in the playlist, as defined by
|
||||
* #EXT-X-MEDIA-SEQUENCE.
|
||||
*/
|
||||
public final int mediaSequence;
|
||||
public final long mediaSequence;
|
||||
/**
|
||||
* The compatibility version, as defined by #EXT-X-VERSION.
|
||||
*/
|
||||
@ -196,11 +196,23 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||
* @param initializationSegment See {@link #initializationSegment}.
|
||||
* @param segments See {@link #segments}.
|
||||
*/
|
||||
public HlsMediaPlaylist(@PlaylistType int playlistType, String baseUri, List<String> tags,
|
||||
long startOffsetUs, long startTimeUs, boolean hasDiscontinuitySequence,
|
||||
int discontinuitySequence, int mediaSequence, int version, long targetDurationUs,
|
||||
boolean hasIndependentSegmentsTag, boolean hasEndTag, boolean hasProgramDateTime,
|
||||
DrmInitData drmInitData, Segment initializationSegment, List<Segment> segments) {
|
||||
public HlsMediaPlaylist(
|
||||
@PlaylistType int playlistType,
|
||||
String baseUri,
|
||||
List<String> tags,
|
||||
long startOffsetUs,
|
||||
long startTimeUs,
|
||||
boolean hasDiscontinuitySequence,
|
||||
int discontinuitySequence,
|
||||
long mediaSequence,
|
||||
int version,
|
||||
long targetDurationUs,
|
||||
boolean hasIndependentSegmentsTag,
|
||||
boolean hasEndTag,
|
||||
boolean hasProgramDateTime,
|
||||
DrmInitData drmInitData,
|
||||
Segment initializationSegment,
|
||||
List<Segment> segments) {
|
||||
super(baseUri, tags);
|
||||
this.playlistType = playlistType;
|
||||
this.startTimeUs = startTimeUs;
|
||||
|
@ -339,7 +339,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
throws IOException {
|
||||
@HlsMediaPlaylist.PlaylistType int playlistType = HlsMediaPlaylist.PLAYLIST_TYPE_UNKNOWN;
|
||||
long startOffsetUs = C.TIME_UNSET;
|
||||
int mediaSequence = 0;
|
||||
long mediaSequence = 0;
|
||||
int version = 1; // Default version == 1.
|
||||
long targetDurationUs = C.TIME_UNSET;
|
||||
boolean hasIndependentSegmentsTag = false;
|
||||
@ -356,7 +356,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
long segmentStartTimeUs = 0;
|
||||
long segmentByteRangeOffset = 0;
|
||||
long segmentByteRangeLength = C.LENGTH_UNSET;
|
||||
int segmentMediaSequence = 0;
|
||||
long segmentMediaSequence = 0;
|
||||
|
||||
String encryptionKeyUri = null;
|
||||
String encryptionIV = null;
|
||||
@ -396,7 +396,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
} else if (line.startsWith(TAG_TARGET_DURATION)) {
|
||||
targetDurationUs = parseIntAttr(line, REGEX_TARGET_DURATION) * C.MICROS_PER_SECOND;
|
||||
} else if (line.startsWith(TAG_MEDIA_SEQUENCE)) {
|
||||
mediaSequence = parseIntAttr(line, REGEX_MEDIA_SEQUENCE);
|
||||
mediaSequence = parseLongAttr(line, REGEX_MEDIA_SEQUENCE);
|
||||
segmentMediaSequence = mediaSequence;
|
||||
} else if (line.startsWith(TAG_VERSION)) {
|
||||
version = parseIntAttr(line, REGEX_VERSION);
|
||||
@ -456,7 +456,7 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
} else if (encryptionIV != null) {
|
||||
segmentEncryptionIV = encryptionIV;
|
||||
} else {
|
||||
segmentEncryptionIV = Integer.toHexString(segmentMediaSequence);
|
||||
segmentEncryptionIV = Long.toHexString(segmentMediaSequence);
|
||||
}
|
||||
segmentMediaSequence++;
|
||||
if (segmentByteRangeLength == C.LENGTH_UNSET) {
|
||||
@ -504,6 +504,10 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||
return Integer.parseInt(parseStringAttr(line, pattern));
|
||||
}
|
||||
|
||||
private static long parseLongAttr(String line, Pattern pattern) throws ParserException {
|
||||
return Long.parseLong(parseStringAttr(line, pattern));
|
||||
}
|
||||
|
||||
private static double parseDoubleAttr(String line, Pattern pattern) throws ParserException {
|
||||
return Double.parseDouble(parseStringAttr(line, pattern));
|
||||
}
|
||||
|
@ -450,9 +450,11 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
||||
|
||||
private static Segment getFirstOldOverlappingSegment(HlsMediaPlaylist oldPlaylist,
|
||||
HlsMediaPlaylist loadedPlaylist) {
|
||||
int mediaSequenceOffset = loadedPlaylist.mediaSequence - oldPlaylist.mediaSequence;
|
||||
long mediaSequenceOffset = loadedPlaylist.mediaSequence - oldPlaylist.mediaSequence;
|
||||
List<Segment> oldSegments = oldPlaylist.segments;
|
||||
return mediaSequenceOffset < oldSegments.size() ? oldSegments.get(mediaSequenceOffset) : null;
|
||||
return mediaSequenceOffset < oldSegments.size()
|
||||
? oldSegments.get((int) mediaSequenceOffset)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,7 +183,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
|
||||
if (previous == null) {
|
||||
chunkIndex = streamElement.getChunkIndex(loadPositionUs);
|
||||
} else {
|
||||
chunkIndex = previous.getNextChunkIndex() - currentManifestChunkOffset;
|
||||
chunkIndex = (int) (previous.getNextChunkIndex() - currentManifestChunkOffset);
|
||||
if (chunkIndex < 0) {
|
||||
// This is before the first chunk in the current manifest.
|
||||
fatalError = new BehindLiveWindowException();
|
||||
|
@ -30,7 +30,6 @@ import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@ -100,8 +99,10 @@ public final class FakeChunkSource implements ChunkSource {
|
||||
ChunkHolder out) {
|
||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||
trackSelection.updateSelectedTrack(playbackPositionUs, bufferedDurationUs, C.TIME_UNSET);
|
||||
int chunkIndex = previous == null ? dataSet.getChunkIndexByPosition(playbackPositionUs)
|
||||
: previous.getNextChunkIndex();
|
||||
int chunkIndex =
|
||||
previous == null
|
||||
? dataSet.getChunkIndexByPosition(playbackPositionUs)
|
||||
: (int) previous.getNextChunkIndex();
|
||||
if (chunkIndex >= dataSet.getChunkCount()) {
|
||||
out.endOfStream = true;
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user