From 8ba3335145755d5af0173970a75d5173f4ac85f4 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Fri, 26 Jan 2018 07:56:29 -0800 Subject: [PATCH] Use long segment indices for DASH ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=183389701 --- .../source/chunk/BaseMediaChunk.java | 12 ++- .../source/chunk/ContainerMediaChunk.java | 15 ++- .../source/chunk/SingleSampleMediaChunk.java | 14 ++- .../dash/manifest/DashManifestParserTest.java | 2 +- .../source/dash/DashMediaSource.java | 6 +- .../source/dash/DashSegmentIndex.java | 18 ++-- .../source/dash/DashWrappingSegmentIndex.java | 17 ++-- .../source/dash/DefaultDashChunkSource.java | 47 +++++---- .../dash/manifest/DashManifestParser.java | 26 +++-- .../source/dash/manifest/Representation.java | 10 +- .../source/dash/manifest/SegmentBase.java | 99 ++++++++++--------- .../dash/manifest/SingleSegmentIndex.java | 10 +- .../source/dash/manifest/UrlTemplate.java | 6 +- .../source/dash/offline/DashDownloader.java | 6 +- .../hls/playlist/HlsPlaylistTracker.java | 6 +- 15 files changed, 171 insertions(+), 123 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java index 62c07ee248..c8ebc02434 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/BaseMediaChunk.java @@ -37,9 +37,15 @@ public abstract class BaseMediaChunk extends MediaChunk { * @param endTimeUs The end time of the media contained by the chunk, in microseconds. * @param chunkIndex The index of the chunk. */ - public BaseMediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs, - int chunkIndex) { + public BaseMediaChunk( + DataSource dataSource, + DataSpec dataSpec, + Format trackFormat, + int trackSelectionReason, + Object trackSelectionData, + long startTimeUs, + long endTimeUs, + long chunkIndex) { super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java index 4daa4041fe..b43c69b63a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ContainerMediaChunk.java @@ -53,9 +53,18 @@ public class ContainerMediaChunk extends BaseMediaChunk { * @param sampleOffsetUs An offset to add to the sample timestamps parsed by the extractor. * @param extractorWrapper A wrapped extractor to use for parsing the data. */ - public ContainerMediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs, - int chunkIndex, int chunkCount, long sampleOffsetUs, ChunkExtractorWrapper extractorWrapper) { + public ContainerMediaChunk( + DataSource dataSource, + DataSpec dataSpec, + Format trackFormat, + int trackSelectionReason, + Object trackSelectionData, + long startTimeUs, + long endTimeUs, + long chunkIndex, + int chunkCount, + long sampleOffsetUs, + ChunkExtractorWrapper extractorWrapper) { super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex); this.chunkCount = chunkCount; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java index 02cf7dfd55..87a90bc285 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/SingleSampleMediaChunk.java @@ -50,9 +50,17 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk { * constants. * @param sampleFormat The {@link Format} of the sample in the chunk. */ - public SingleSampleMediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs, - int chunkIndex, int trackType, Format sampleFormat) { + public SingleSampleMediaChunk( + DataSource dataSource, + DataSpec dataSpec, + Format trackFormat, + int trackSelectionReason, + Object trackSelectionData, + long startTimeUs, + long endTimeUs, + long chunkIndex, + int trackType, + Format sampleFormat) { super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, endTimeUs, chunkIndex); this.trackType = trackType; diff --git a/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java b/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java index c697e12471..3b7982592d 100644 --- a/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java +++ b/library/dash/src/androidTest/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParserTest.java @@ -64,7 +64,7 @@ public class DashManifestParserTest extends InstrumentationTestCase { if (representation instanceof Representation.MultiSegmentRepresentation) { Representation.MultiSegmentRepresentation multiSegmentRepresentation = (Representation.MultiSegmentRepresentation) representation; - int firstSegmentIndex = multiSegmentRepresentation.getFirstSegmentNum(); + long firstSegmentIndex = multiSegmentRepresentation.getFirstSegmentNum(); RangedUri uri = multiSegmentRepresentation.getSegmentUrl(firstSegmentIndex); assertThat( uri.resolveUriString(representation.baseUrl) diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index f609498656..eb9b18512c 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -898,11 +898,11 @@ public final class DashMediaSource implements MediaSource { availableStartTimeUs = 0; availableEndTimeUs = 0; } else if (!seenEmptyIndex) { - int firstSegmentNum = index.getFirstSegmentNum(); + long firstSegmentNum = index.getFirstSegmentNum(); long adaptationSetAvailableStartTimeUs = index.getTimeUs(firstSegmentNum); availableStartTimeUs = Math.max(availableStartTimeUs, adaptationSetAvailableStartTimeUs); if (segmentCount != DashSegmentIndex.INDEX_UNBOUNDED) { - int lastSegmentNum = firstSegmentNum + segmentCount - 1; + long lastSegmentNum = firstSegmentNum + segmentCount - 1; long adaptationSetAvailableEndTimeUs = index.getTimeUs(lastSegmentNum) + index.getDurationUs(lastSegmentNum, durationUs); availableEndTimeUs = Math.min(availableEndTimeUs, adaptationSetAvailableEndTimeUs); @@ -1027,7 +1027,7 @@ public final class DashMediaSource implements MediaSource { // Video adaptation set does not include a non-empty index for snapping. return windowDefaultStartPositionUs; } - int segmentNum = snapIndex.getSegmentNum(defaultStartPositionInPeriodUs, periodDurationUs); + long segmentNum = snapIndex.getSegmentNum(defaultStartPositionInPeriodUs, periodDurationUs); return windowDefaultStartPositionUs + snapIndex.getTimeUs(segmentNum) - defaultStartPositionInPeriodUs; } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashSegmentIndex.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashSegmentIndex.java index 2ddc7f4f80..9d45bc726e 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashSegmentIndex.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashSegmentIndex.java @@ -32,11 +32,11 @@ public interface DashSegmentIndex { * Otherwise, returns the segment number of the segment containing the given media time. * * @param timeUs The time in microseconds. - * @param periodDurationUs The duration of the enclosing period in microseconds, or - * {@link C#TIME_UNSET} if the period's duration is not yet known. + * @param periodDurationUs The duration of the enclosing period in microseconds, or {@link + * C#TIME_UNSET} if the period's duration is not yet known. * @return The segment number of the corresponding segment. */ - int getSegmentNum(long timeUs, long periodDurationUs); + long getSegmentNum(long timeUs, long periodDurationUs); /** * Returns the start time of a segment. @@ -44,17 +44,17 @@ public interface DashSegmentIndex { * @param segmentNum The segment number. * @return The corresponding start time in microseconds. */ - long getTimeUs(int segmentNum); + long getTimeUs(long segmentNum); /** * Returns the duration of a segment. * * @param segmentNum The segment number. - * @param periodDurationUs The duration of the enclosing period in microseconds, or - * {@link C#TIME_UNSET} if the period's duration is not yet known. + * @param periodDurationUs The duration of the enclosing period in microseconds, or {@link + * C#TIME_UNSET} if the period's duration is not yet known. * @return The duration of the segment, in microseconds. */ - long getDurationUs(int segmentNum, long periodDurationUs); + long getDurationUs(long segmentNum, long periodDurationUs); /** * Returns a {@link RangedUri} defining the location of a segment. @@ -62,14 +62,14 @@ public interface DashSegmentIndex { * @param segmentNum The segment number. * @return The {@link RangedUri} defining the location of the data. */ - RangedUri getSegmentUrl(int segmentNum); + RangedUri getSegmentUrl(long segmentNum); /** * Returns the segment number of the first segment. * * @return The segment number of the first segment. */ - int getFirstSegmentNum(); + long getFirstSegmentNum(); /** * Returns the number of segments in the index, or {@link #INDEX_UNBOUNDED}. diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java index 8cd5018dc7..078305a687 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashWrappingSegmentIndex.java @@ -34,7 +34,7 @@ public final class DashWrappingSegmentIndex implements DashSegmentIndex { } @Override - public int getFirstSegmentNum() { + public long getFirstSegmentNum() { return 0; } @@ -44,22 +44,23 @@ public final class DashWrappingSegmentIndex implements DashSegmentIndex { } @Override - public long getTimeUs(int segmentNum) { - return chunkIndex.timesUs[segmentNum]; + public long getTimeUs(long segmentNum) { + return chunkIndex.timesUs[(int) segmentNum]; } @Override - public long getDurationUs(int segmentNum, long periodDurationUs) { - return chunkIndex.durationsUs[segmentNum]; + public long getDurationUs(long segmentNum, long periodDurationUs) { + return chunkIndex.durationsUs[(int) segmentNum]; } @Override - public RangedUri getSegmentUrl(int segmentNum) { - return new RangedUri(null, chunkIndex.offsets[segmentNum], chunkIndex.sizes[segmentNum]); + public RangedUri getSegmentUrl(long segmentNum) { + return new RangedUri( + null, chunkIndex.offsets[(int) segmentNum], chunkIndex.sizes[(int) segmentNum]); } @Override - public int getSegmentNum(long timeUs, long periodDurationUs) { + public long getSegmentNum(long timeUs, long periodDurationUs) { return chunkIndex.getChunkIndex(timeUs); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index beede59b8d..a76349adac 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -187,7 +187,7 @@ public class DefaultDashChunkSource implements DashChunkSource { // Segments are aligned across representations, so any segment index will do. for (RepresentationHolder representationHolder : representationHolders) { if (representationHolder.segmentIndex != null) { - int segmentNum = representationHolder.getSegmentNum(positionUs); + long segmentNum = representationHolder.getSegmentNum(positionUs); long firstSyncUs = representationHolder.getSegmentStartTimeUs(segmentNum); long secondSyncUs = firstSyncUs < positionUs && segmentNum < representationHolder.getSegmentCount() - 1 @@ -284,8 +284,8 @@ public class DefaultDashChunkSource implements DashChunkSource { return; } - int firstAvailableSegmentNum = representationHolder.getFirstSegmentNum(); - int lastAvailableSegmentNum; + long firstAvailableSegmentNum = representationHolder.getFirstSegmentNum(); + long lastAvailableSegmentNum; if (availableSegmentCount == DashSegmentIndex.INDEX_UNBOUNDED) { // The index is itself unbounded. We need to use the current time to calculate the range of // available segments. @@ -306,12 +306,12 @@ public class DefaultDashChunkSource implements DashChunkSource { updateLiveEdgeTimeUs(representationHolder, lastAvailableSegmentNum); - int segmentNum; + long segmentNum; if (previous == null) { segmentNum = Util.constrainValue(representationHolder.getSegmentNum(loadPositionUs), firstAvailableSegmentNum, lastAvailableSegmentNum); } else { - segmentNum = (int) previous.getNextChunkIndex(); + segmentNum = previous.getNextChunkIndex(); if (segmentNum < firstAvailableSegmentNum) { // This is before the first chunk in the current manifest. fatalError = new BehindLiveWindowException(); @@ -326,7 +326,8 @@ public class DefaultDashChunkSource implements DashChunkSource { return; } - int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1); + int maxSegmentCount = + (int) Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1); out.chunk = newMediaChunk(representationHolder, dataSource, trackType, trackSelection.getSelectedFormat(), trackSelection.getSelectionReason(), trackSelection.getSelectionData(), segmentNum, maxSegmentCount); @@ -370,7 +371,7 @@ public class DefaultDashChunkSource implements DashChunkSource { representationHolders[trackSelection.indexOf(chunk.trackFormat)]; int segmentCount = representationHolder.getSegmentCount(); if (segmentCount != DashSegmentIndex.INDEX_UNBOUNDED && segmentCount != 0) { - int lastAvailableSegmentNum = representationHolder.getFirstSegmentNum() + segmentCount - 1; + long lastAvailableSegmentNum = representationHolder.getFirstSegmentNum() + segmentCount - 1; if (((MediaChunk) chunk).getNextChunkIndex() > lastAvailableSegmentNum) { missingLastSegment = true; return true; @@ -393,8 +394,8 @@ public class DefaultDashChunkSource implements DashChunkSource { return representations; } - private void updateLiveEdgeTimeUs(RepresentationHolder representationHolder, - int lastAvailableSegmentNum) { + private void updateLiveEdgeTimeUs( + RepresentationHolder representationHolder, long lastAvailableSegmentNum) { liveEdgeTimeUs = manifest.dynamic ? representationHolder.getSegmentEndTimeUs(lastAvailableSegmentNum) : C.TIME_UNSET; } @@ -433,9 +434,15 @@ public class DefaultDashChunkSource implements DashChunkSource { trackSelectionReason, trackSelectionData, representationHolder.extractorWrapper); } - protected static Chunk newMediaChunk(RepresentationHolder representationHolder, - DataSource dataSource, int trackType, Format trackFormat, int trackSelectionReason, - Object trackSelectionData, int firstSegmentNum, int maxSegmentCount) { + protected static Chunk newMediaChunk( + RepresentationHolder representationHolder, + DataSource dataSource, + int trackType, + Format trackFormat, + int trackSelectionReason, + Object trackSelectionData, + long firstSegmentNum, + int maxSegmentCount) { Representation representation = representationHolder.representation; long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum); RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum); @@ -481,7 +488,7 @@ public class DefaultDashChunkSource implements DashChunkSource { public DashSegmentIndex segmentIndex; private long periodDurationUs; - private int segmentNumShift; + private long segmentNumShift; /* package */ RepresentationHolder( long periodDurationUs, @@ -547,10 +554,10 @@ public class DefaultDashChunkSource implements DashChunkSource { return; } - int oldIndexLastSegmentNum = oldIndex.getFirstSegmentNum() + oldIndexSegmentCount - 1; + long oldIndexLastSegmentNum = oldIndex.getFirstSegmentNum() + oldIndexSegmentCount - 1; long oldIndexEndTimeUs = oldIndex.getTimeUs(oldIndexLastSegmentNum) + oldIndex.getDurationUs(oldIndexLastSegmentNum, periodDurationUs); - int newIndexFirstSegmentNum = newIndex.getFirstSegmentNum(); + long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum(); long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum); if (oldIndexEndTimeUs == newIndexStartTimeUs) { // The new index continues where the old one ended, with no overlap. @@ -566,7 +573,7 @@ public class DefaultDashChunkSource implements DashChunkSource { } } - public int getFirstSegmentNum() { + public long getFirstSegmentNum() { return segmentIndex.getFirstSegmentNum() + segmentNumShift; } @@ -574,20 +581,20 @@ public class DefaultDashChunkSource implements DashChunkSource { return segmentIndex.getSegmentCount(periodDurationUs); } - public long getSegmentStartTimeUs(int segmentNum) { + public long getSegmentStartTimeUs(long segmentNum) { return segmentIndex.getTimeUs(segmentNum - segmentNumShift); } - public long getSegmentEndTimeUs(int segmentNum) { + public long getSegmentEndTimeUs(long segmentNum) { return getSegmentStartTimeUs(segmentNum) + segmentIndex.getDurationUs(segmentNum - segmentNumShift, periodDurationUs); } - public int getSegmentNum(long positionUs) { + public long getSegmentNum(long positionUs) { return segmentIndex.getSegmentNum(positionUs, periodDurationUs) + segmentNumShift; } - public RangedUri getSegmentUrl(int segmentNum) { + public RangedUri getSegmentUrl(long segmentNum) { return segmentIndex.getSegmentUrl(segmentNum - segmentNumShift); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java index bda2a1fb85..1b1e24005b 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java @@ -602,7 +602,7 @@ public class DashManifestParser extends DefaultHandler long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", parent != null ? parent.presentationTimeOffset : 0); long duration = parseLong(xpp, "duration", parent != null ? parent.duration : C.TIME_UNSET); - int startNumber = parseInt(xpp, "startNumber", parent != null ? parent.startNumber : 1); + long startNumber = parseLong(xpp, "startNumber", parent != null ? parent.startNumber : 1); RangedUri initialization = null; List timeline = null; @@ -632,9 +632,14 @@ public class DashManifestParser extends DefaultHandler startNumber, duration, timeline, segments); } - protected SegmentList buildSegmentList(RangedUri initialization, long timescale, - long presentationTimeOffset, int startNumber, long duration, - List timeline, List segments) { + protected SegmentList buildSegmentList( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long startNumber, + long duration, + List timeline, + List segments) { return new SegmentList(initialization, timescale, presentationTimeOffset, startNumber, duration, timeline, segments); } @@ -645,7 +650,7 @@ public class DashManifestParser extends DefaultHandler long presentationTimeOffset = parseLong(xpp, "presentationTimeOffset", parent != null ? parent.presentationTimeOffset : 0); long duration = parseLong(xpp, "duration", parent != null ? parent.duration : C.TIME_UNSET); - int startNumber = parseInt(xpp, "startNumber", parent != null ? parent.startNumber : 1); + long startNumber = parseLong(xpp, "startNumber", parent != null ? parent.startNumber : 1); UrlTemplate mediaTemplate = parseUrlTemplate(xpp, "media", parent != null ? parent.mediaTemplate : null); UrlTemplate initializationTemplate = parseUrlTemplate(xpp, "initialization", @@ -672,9 +677,14 @@ public class DashManifestParser extends DefaultHandler startNumber, duration, timeline, initializationTemplate, mediaTemplate); } - protected SegmentTemplate buildSegmentTemplate(RangedUri initialization, long timescale, - long presentationTimeOffset, int startNumber, long duration, - List timeline, UrlTemplate initializationTemplate, + protected SegmentTemplate buildSegmentTemplate( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long startNumber, + long duration, + List timeline, + UrlTemplate initializationTemplate, UrlTemplate mediaTemplate) { return new SegmentTemplate(initialization, timescale, presentationTimeOffset, startNumber, duration, timeline, initializationTemplate, mediaTemplate); diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java index 81e4602c1d..71a3a0122c 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/Representation.java @@ -292,27 +292,27 @@ public abstract class Representation { // DashSegmentIndex implementation. @Override - public RangedUri getSegmentUrl(int segmentIndex) { + public RangedUri getSegmentUrl(long segmentIndex) { return segmentBase.getSegmentUrl(this, segmentIndex); } @Override - public int getSegmentNum(long timeUs, long periodDurationUs) { + public long getSegmentNum(long timeUs, long periodDurationUs) { return segmentBase.getSegmentNum(timeUs, periodDurationUs); } @Override - public long getTimeUs(int segmentIndex) { + public long getTimeUs(long segmentIndex) { return segmentBase.getSegmentTimeUs(segmentIndex); } @Override - public long getDurationUs(int segmentIndex, long periodDurationUs) { + public long getDurationUs(long segmentIndex, long periodDurationUs) { return segmentBase.getSegmentDurationUs(segmentIndex, periodDurationUs); } @Override - public int getFirstSegmentNum() { + public long getFirstSegmentNum() { return segmentBase.getFirstSegmentNum(); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java index 4f7dc81fc5..f033232590 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SegmentBase.java @@ -99,7 +99,7 @@ public abstract class SegmentBase { */ public abstract static class MultiSegmentBase extends SegmentBase { - /* package */ final int startNumber; + /* package */ final long startNumber; /* package */ final long duration; /* package */ final List segmentTimeline; @@ -111,43 +111,46 @@ public abstract class SegmentBase { * division of this value and {@code timescale}. * @param startNumber The sequence number of the first segment. * @param duration The duration of each segment in the case of fixed duration segments. The - * value in seconds is the division of this value and {@code timescale}. If - * {@code segmentTimeline} is non-null then this parameter is ignored. + * value in seconds is the division of this value and {@code timescale}. If {@code + * segmentTimeline} is non-null then this parameter is ignored. * @param segmentTimeline A segment timeline corresponding to the segments. If null, then * segments are assumed to be of fixed duration as specified by the {@code duration} * parameter. */ - public MultiSegmentBase(RangedUri initialization, long timescale, long presentationTimeOffset, - int startNumber, long duration, List segmentTimeline) { + public MultiSegmentBase( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long startNumber, + long duration, + List segmentTimeline) { super(initialization, timescale, presentationTimeOffset); this.startNumber = startNumber; this.duration = duration; this.segmentTimeline = segmentTimeline; } - /** - * @see DashSegmentIndex#getSegmentNum(long, long) - */ - public int getSegmentNum(long timeUs, long periodDurationUs) { - final int firstSegmentNum = getFirstSegmentNum(); - final int segmentCount = getSegmentCount(periodDurationUs); + /** @see DashSegmentIndex#getSegmentNum(long, long) */ + public long getSegmentNum(long timeUs, long periodDurationUs) { + final long firstSegmentNum = getFirstSegmentNum(); + final long segmentCount = getSegmentCount(periodDurationUs); if (segmentCount == 0) { return firstSegmentNum; } if (segmentTimeline == null) { // All segments are of equal duration (with the possible exception of the last one). long durationUs = (duration * C.MICROS_PER_SECOND) / timescale; - int segmentNum = startNumber + (int) (timeUs / durationUs); + long segmentNum = startNumber + timeUs / durationUs; // Ensure we stay within bounds. return segmentNum < firstSegmentNum ? firstSegmentNum : segmentCount == DashSegmentIndex.INDEX_UNBOUNDED ? segmentNum : Math.min(segmentNum, firstSegmentNum + segmentCount - 1); } else { // The index cannot be unbounded. Identify the segment using binary search. - int lowIndex = firstSegmentNum; - int highIndex = firstSegmentNum + segmentCount - 1; + long lowIndex = firstSegmentNum; + long highIndex = firstSegmentNum + segmentCount - 1; while (lowIndex <= highIndex) { - int midIndex = lowIndex + (highIndex - lowIndex) / 2; + long midIndex = lowIndex + (highIndex - lowIndex) / 2; long midTimeUs = getSegmentTimeUs(midIndex); if (midTimeUs < timeUs) { lowIndex = midIndex + 1; @@ -161,12 +164,10 @@ public abstract class SegmentBase { } } - /** - * @see DashSegmentIndex#getDurationUs(int, long) - */ - public final long getSegmentDurationUs(int sequenceNumber, long periodDurationUs) { + /** @see DashSegmentIndex#getDurationUs(long, long) */ + public final long getSegmentDurationUs(long sequenceNumber, long periodDurationUs) { if (segmentTimeline != null) { - long duration = segmentTimeline.get(sequenceNumber - startNumber).duration; + long duration = segmentTimeline.get((int) (sequenceNumber - startNumber)).duration; return (duration * C.MICROS_PER_SECOND) / timescale; } else { int segmentCount = getSegmentCount(periodDurationUs); @@ -177,14 +178,13 @@ public abstract class SegmentBase { } } - /** - * @see DashSegmentIndex#getTimeUs(int) - */ - public final long getSegmentTimeUs(int sequenceNumber) { + /** @see DashSegmentIndex#getTimeUs(long) */ + public final long getSegmentTimeUs(long sequenceNumber) { long unscaledSegmentTime; if (segmentTimeline != null) { - unscaledSegmentTime = segmentTimeline.get(sequenceNumber - startNumber).startTime - - presentationTimeOffset; + unscaledSegmentTime = + segmentTimeline.get((int) (sequenceNumber - startNumber)).startTime + - presentationTimeOffset; } else { unscaledSegmentTime = (sequenceNumber - startNumber) * duration; } @@ -195,14 +195,12 @@ public abstract class SegmentBase { * Returns a {@link RangedUri} defining the location of a segment for the given index in the * given representation. * - * @see DashSegmentIndex#getSegmentUrl(int) + * @see DashSegmentIndex#getSegmentUrl(long) */ - public abstract RangedUri getSegmentUrl(Representation representation, int index); + public abstract RangedUri getSegmentUrl(Representation representation, long index); - /** - * @see DashSegmentIndex#getFirstSegmentNum() - */ - public int getFirstSegmentNum() { + /** @see DashSegmentIndex#getFirstSegmentNum() */ + public long getFirstSegmentNum() { return startNumber; } @@ -235,15 +233,20 @@ public abstract class SegmentBase { * division of this value and {@code timescale}. * @param startNumber The sequence number of the first segment. * @param duration The duration of each segment in the case of fixed duration segments. The - * value in seconds is the division of this value and {@code timescale}. If - * {@code segmentTimeline} is non-null then this parameter is ignored. + * value in seconds is the division of this value and {@code timescale}. If {@code + * segmentTimeline} is non-null then this parameter is ignored. * @param segmentTimeline A segment timeline corresponding to the segments. If null, then * segments are assumed to be of fixed duration as specified by the {@code duration} * parameter. * @param mediaSegments A list of {@link RangedUri}s indicating the locations of the segments. */ - public SegmentList(RangedUri initialization, long timescale, long presentationTimeOffset, - int startNumber, long duration, List segmentTimeline, + public SegmentList( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long startNumber, + long duration, + List segmentTimeline, List mediaSegments) { super(initialization, timescale, presentationTimeOffset, startNumber, duration, segmentTimeline); @@ -251,8 +254,8 @@ public abstract class SegmentBase { } @Override - public RangedUri getSegmentUrl(Representation representation, int sequenceNumber) { - return mediaSegments.get(sequenceNumber - startNumber); + public RangedUri getSegmentUrl(Representation representation, long sequenceNumber) { + return mediaSegments.get((int) (sequenceNumber - startNumber)); } @Override @@ -284,8 +287,8 @@ public abstract class SegmentBase { * division of this value and {@code timescale}. * @param startNumber The sequence number of the first segment. * @param duration The duration of each segment in the case of fixed duration segments. The - * value in seconds is the division of this value and {@code timescale}. If - * {@code segmentTimeline} is non-null then this parameter is ignored. + * value in seconds is the division of this value and {@code timescale}. If {@code + * segmentTimeline} is non-null then this parameter is ignored. * @param segmentTimeline A segment timeline corresponding to the segments. If null, then * segments are assumed to be of fixed duration as specified by the {@code duration} * parameter. @@ -294,9 +297,15 @@ public abstract class SegmentBase { * null then {@code initialization} will be used. * @param mediaTemplate A template defining the location of each media segment. */ - public SegmentTemplate(RangedUri initialization, long timescale, long presentationTimeOffset, - int startNumber, long duration, List segmentTimeline, - UrlTemplate initializationTemplate, UrlTemplate mediaTemplate) { + public SegmentTemplate( + RangedUri initialization, + long timescale, + long presentationTimeOffset, + long startNumber, + long duration, + List segmentTimeline, + UrlTemplate initializationTemplate, + UrlTemplate mediaTemplate) { super(initialization, timescale, presentationTimeOffset, startNumber, duration, segmentTimeline); this.initializationTemplate = initializationTemplate; @@ -315,10 +324,10 @@ public abstract class SegmentBase { } @Override - public RangedUri getSegmentUrl(Representation representation, int sequenceNumber) { + public RangedUri getSegmentUrl(Representation representation, long sequenceNumber) { long time; if (segmentTimeline != null) { - time = segmentTimeline.get(sequenceNumber - startNumber).startTime; + time = segmentTimeline.get((int) (sequenceNumber - startNumber)).startTime; } else { time = (sequenceNumber - startNumber) * duration; } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java index 4ce49c5ffe..a56a11fe50 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/SingleSegmentIndex.java @@ -32,27 +32,27 @@ import com.google.android.exoplayer2.source.dash.DashSegmentIndex; } @Override - public int getSegmentNum(long timeUs, long periodDurationUs) { + public long getSegmentNum(long timeUs, long periodDurationUs) { return 0; } @Override - public long getTimeUs(int segmentNum) { + public long getTimeUs(long segmentNum) { return 0; } @Override - public long getDurationUs(int segmentNum, long periodDurationUs) { + public long getDurationUs(long segmentNum, long periodDurationUs) { return periodDurationUs; } @Override - public RangedUri getSegmentUrl(int segmentNum) { + public RangedUri getSegmentUrl(long segmentNum) { return uri; } @Override - public int getFirstSegmentNum() { + public long getFirstSegmentNum() { return 0; } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java index c47eec90a1..a7ce7eb9a0 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/UrlTemplate.java @@ -71,8 +71,8 @@ public final class UrlTemplate { /** * Constructs a Uri from the template, substituting in the provided arguments. - *

- * Arguments whose corresponding identifiers are not present in the template will be ignored. + * + *

Arguments whose corresponding identifiers are not present in the template will be ignored. * * @param representationId The representation identifier. * @param segmentNumber The segment number. @@ -80,7 +80,7 @@ public final class UrlTemplate { * @param time The time as specified by the segment timeline. * @return The built Uri. */ - public String buildUri(String representationId, int segmentNumber, int bandwidth, long time) { + public String buildUri(String representationId, long segmentNumber, int bandwidth, long time) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < identifierCount; i++) { builder.append(urlPieces[i]); diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java index 4c07e4874e..467f60fb0e 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/offline/DashDownloader.java @@ -138,9 +138,9 @@ public final class DashDownloader extends SegmentDownloader oldSegments = oldPlaylist.segments; - return mediaSequenceOffset < oldSegments.size() - ? oldSegments.get((int) mediaSequenceOffset) - : null; + return mediaSequenceOffset < oldSegments.size() ? oldSegments.get(mediaSequenceOffset) : null; } /** -- GitLab