mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Allow HlsSampleStreamWrapper to cancel partial media chunk loads
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=213439145
This commit is contained in:
parent
decbb33490
commit
db33b3bbd1
4 changed files with 35 additions and 23 deletions
|
|
@ -223,9 +223,6 @@ import java.util.List;
|
||||||
* started, the value will be the starting position in the period minus the duration of any
|
* started, the value will be the starting position in the period minus the duration of any
|
||||||
* media in previous periods still to be played.
|
* media in previous periods still to be played.
|
||||||
* @param loadPositionUs The current load position relative to the period start in microseconds.
|
* @param loadPositionUs The current load position relative to the period start in microseconds.
|
||||||
* If {@code queue} is empty, this is the starting position from which chunks should be
|
|
||||||
* provided. Else it's equal to {@link HlsMediaChunk#endTimeUs} of the last chunk in the
|
|
||||||
* {@code queue}.
|
|
||||||
* @param queue The queue of buffered {@link HlsMediaChunk}s.
|
* @param queue The queue of buffered {@link HlsMediaChunk}s.
|
||||||
* @param out A holder to populate.
|
* @param out A holder to populate.
|
||||||
*/
|
*/
|
||||||
|
|
@ -237,12 +234,12 @@ import java.util.List;
|
||||||
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
long bufferedDurationUs = loadPositionUs - playbackPositionUs;
|
||||||
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
|
long timeToLiveEdgeUs = resolveTimeToLiveEdgeUs(playbackPositionUs);
|
||||||
if (previous != null && !independentSegments) {
|
if (previous != null && !independentSegments) {
|
||||||
// Unless segments are known to be independent, switching variant will require downloading
|
// Unless segments are known to be independent, switching variant requires downloading
|
||||||
// overlapping segments. Hence we will subtract previous chunk's duration from buffered
|
// overlapping segments. Hence we subtract the previous segment's duration from the buffered
|
||||||
// duration.
|
// duration.
|
||||||
// This may affect the live-streaming adaptive track selection logic, when we are comparing
|
// This may affect the live-streaming adaptive track selection logic, when we compare the
|
||||||
// buffered duration to time to live edge to decide whether to switch. Therefore,
|
// buffered duration to time-to-live-edge to decide whether to switch. Therefore, we subtract
|
||||||
// we will subtract this same amount from timeToLiveEdgeUs as well.
|
// the duration of the last loaded segment from timeToLiveEdgeUs as well.
|
||||||
long subtractedDurationUs = previous.getDurationUs();
|
long subtractedDurationUs = previous.getDurationUs();
|
||||||
bufferedDurationUs = Math.max(0, bufferedDurationUs - subtractedDurationUs);
|
bufferedDurationUs = Math.max(0, bufferedDurationUs - subtractedDurationUs);
|
||||||
if (timeToLiveEdgeUs != C.TIME_UNSET) {
|
if (timeToLiveEdgeUs != C.TIME_UNSET) {
|
||||||
|
|
@ -420,7 +417,7 @@ import java.util.List;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns list of {@link MediaChunkIterator}s for upcoming media chunks.
|
* Returns an array of {@link MediaChunkIterator}s for upcoming media chunks.
|
||||||
*
|
*
|
||||||
* @param previous The previous media chunk. May be null.
|
* @param previous The previous media chunk. May be null.
|
||||||
* @param loadPositionUs The position at which the iterators will start.
|
* @param loadPositionUs The position at which the iterators will start.
|
||||||
|
|
@ -458,6 +455,18 @@ import java.util.List;
|
||||||
|
|
||||||
// Private methods.
|
// Private methods.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the media sequence number of the segment to load next in {@code mediaPlaylist}.
|
||||||
|
*
|
||||||
|
* @param previous The last (at least partially) loaded segment.
|
||||||
|
* @param switchingVariant Whether the segment to load is not preceded by a segment in the same
|
||||||
|
* variant.
|
||||||
|
* @param mediaPlaylist The media playlist to which the segment to load belongs.
|
||||||
|
* @param startOfPlaylistInPeriodUs The start of {@code mediaPlaylist} relative to the period
|
||||||
|
* start in microseconds.
|
||||||
|
* @param loadPositionUs The current load position relative to the period start in microseconds.
|
||||||
|
* @return The media sequence of the segment to load.
|
||||||
|
*/
|
||||||
private long getChunkMediaSequence(
|
private long getChunkMediaSequence(
|
||||||
@Nullable HlsMediaChunk previous,
|
@Nullable HlsMediaChunk previous,
|
||||||
boolean switchingVariant,
|
boolean switchingVariant,
|
||||||
|
|
@ -480,6 +489,8 @@ import java.util.List;
|
||||||
/* stayInBounds= */ !playlistTracker.isLive() || previous == null)
|
/* stayInBounds= */ !playlistTracker.isLive() || previous == null)
|
||||||
+ mediaPlaylist.mediaSequence;
|
+ mediaPlaylist.mediaSequence;
|
||||||
}
|
}
|
||||||
|
// We ignore the case of previous not having loaded completely, in which case we load the next
|
||||||
|
// segment.
|
||||||
return previous.getNextChunkIndex();
|
return previous.getNextChunkIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
if (previousChunk != null) {
|
if (previousChunk != null) {
|
||||||
id3Decoder = previousChunk.id3Decoder;
|
id3Decoder = previousChunk.id3Decoder;
|
||||||
id3Data = previousChunk.id3Data;
|
id3Data = previousChunk.id3Data;
|
||||||
shouldSpliceIn = previousChunk.hlsUrl != hlsUrl;
|
shouldSpliceIn = previousChunk.hlsUrl != hlsUrl || !previousChunk.loadCompleted;
|
||||||
previousExtractor = previousChunk.discontinuitySequenceNumber != discontinuitySequenceNumber
|
previousExtractor = previousChunk.discontinuitySequenceNumber != discontinuitySequenceNumber
|
||||||
|| shouldSpliceIn ? null : previousChunk.extractor;
|
|| shouldSpliceIn ? null : previousChunk.extractor;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -460,9 +460,7 @@ import java.util.List;
|
||||||
&& finishedReadingChunk(mediaChunks.get(discardToMediaChunkIndex))) {
|
&& finishedReadingChunk(mediaChunks.get(discardToMediaChunkIndex))) {
|
||||||
discardToMediaChunkIndex++;
|
discardToMediaChunkIndex++;
|
||||||
}
|
}
|
||||||
if (discardToMediaChunkIndex > 0) {
|
Util.removeRange(mediaChunks, 0, discardToMediaChunkIndex);
|
||||||
Util.removeRange(mediaChunks, 0, discardToMediaChunkIndex);
|
|
||||||
}
|
|
||||||
HlsMediaChunk currentChunk = mediaChunks.get(0);
|
HlsMediaChunk currentChunk = mediaChunks.get(0);
|
||||||
Format trackFormat = currentChunk.trackFormat;
|
Format trackFormat = currentChunk.trackFormat;
|
||||||
if (!trackFormat.equals(downstreamTrackFormat)) {
|
if (!trackFormat.equals(downstreamTrackFormat)) {
|
||||||
|
|
@ -554,7 +552,11 @@ import java.util.List;
|
||||||
loadPositionUs = pendingResetPositionUs;
|
loadPositionUs = pendingResetPositionUs;
|
||||||
} else {
|
} else {
|
||||||
chunkQueue = readOnlyMediaChunks;
|
chunkQueue = readOnlyMediaChunks;
|
||||||
loadPositionUs = getLastMediaChunk().endTimeUs;
|
HlsMediaChunk lastMediaChunk = getLastMediaChunk();
|
||||||
|
loadPositionUs =
|
||||||
|
lastMediaChunk.isLoadCompleted()
|
||||||
|
? lastMediaChunk.endTimeUs
|
||||||
|
: Math.max(lastSeekPositionUs, lastMediaChunk.startTimeUs);
|
||||||
}
|
}
|
||||||
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
chunkSource.getNextChunk(positionUs, loadPositionUs, chunkQueue, nextChunkHolder);
|
||||||
boolean endOfStream = nextChunkHolder.endOfStream;
|
boolean endOfStream = nextChunkHolder.endOfStream;
|
||||||
|
|
@ -666,17 +668,15 @@ import java.util.List;
|
||||||
boolean blacklistSucceeded = false;
|
boolean blacklistSucceeded = false;
|
||||||
LoadErrorAction loadErrorAction;
|
LoadErrorAction loadErrorAction;
|
||||||
|
|
||||||
if (!isMediaChunk || bytesLoaded == 0) {
|
long blacklistDurationMs =
|
||||||
long blacklistDurationMs =
|
loadErrorHandlingPolicy.getBlacklistDurationMsFor(
|
||||||
loadErrorHandlingPolicy.getBlacklistDurationMsFor(
|
loadable.type, loadDurationMs, error, errorCount);
|
||||||
loadable.type, loadDurationMs, error, errorCount);
|
if (blacklistDurationMs != C.TIME_UNSET) {
|
||||||
if (blacklistDurationMs != C.TIME_UNSET) {
|
blacklistSucceeded = chunkSource.maybeBlacklistTrack(loadable, blacklistDurationMs);
|
||||||
blacklistSucceeded = chunkSource.maybeBlacklistTrack(loadable, blacklistDurationMs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blacklistSucceeded) {
|
if (blacklistSucceeded) {
|
||||||
if (isMediaChunk) {
|
if (isMediaChunk && bytesLoaded == 0) {
|
||||||
HlsMediaChunk removed = mediaChunks.remove(mediaChunks.size() - 1);
|
HlsMediaChunk removed = mediaChunks.remove(mediaChunks.size() - 1);
|
||||||
Assertions.checkState(removed == loadable);
|
Assertions.checkState(removed == loadable);
|
||||||
if (mediaChunks.isEmpty()) {
|
if (mediaChunks.isEmpty()) {
|
||||||
|
|
@ -707,7 +707,7 @@ import java.util.List;
|
||||||
loadable.endTimeUs,
|
loadable.endTimeUs,
|
||||||
elapsedRealtimeMs,
|
elapsedRealtimeMs,
|
||||||
loadDurationMs,
|
loadDurationMs,
|
||||||
loadable.bytesLoaded(),
|
bytesLoaded,
|
||||||
error,
|
error,
|
||||||
/* wasCanceled= */ !loadErrorAction.isRetry());
|
/* wasCanceled= */ !loadErrorAction.isRetry());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
androidTestImplementation 'androidx.test:rules:' + testRunnerVersion
|
androidTestImplementation 'androidx.test:rules:' + testRunnerVersion
|
||||||
androidTestImplementation 'androidx.test:runner:' + testRunnerVersion
|
androidTestImplementation 'androidx.test:runner:' + testRunnerVersion
|
||||||
|
androidTestImplementation 'com.android.support:support-annotations:' + supportLibraryVersion
|
||||||
androidTestImplementation project(modulePrefix + 'library-core')
|
androidTestImplementation project(modulePrefix + 'library-core')
|
||||||
androidTestImplementation project(modulePrefix + 'library-dash')
|
androidTestImplementation project(modulePrefix + 'library-dash')
|
||||||
androidTestImplementation project(modulePrefix + 'library-hls')
|
androidTestImplementation project(modulePrefix + 'library-hls')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue