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:
aquilescanta 2018-01-26 03:37:55 -08:00 committed by Oliver Woodman
parent bc9dbdb49e
commit 677fc291cf
11 changed files with 85 additions and 43 deletions

View File

@ -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

View File

@ -64,7 +64,7 @@ public class ContainerMediaChunk extends BaseMediaChunk {
}
@Override
public int getNextChunkIndex() {
public long getNextChunkIndex() {
return chunkIndex + chunkCount;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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));
}

View File

@ -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;
}
/**

View File

@ -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();

View File

@ -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 {