mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Prevent old playlist snapshots from being used on live HLS streams
This aims to replace InvalidCodeResponse's with BLWE's caused by trying to load chunks that have been removed from the server. Issue:#2344 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=145679171
This commit is contained in:
parent
25c18ca1b4
commit
c49d142981
@ -194,15 +194,16 @@ import java.util.Locale;
|
||||
|
||||
// Select the variant.
|
||||
trackSelection.updateSelectedTrack(bufferedDurationUs);
|
||||
int newVariantIndex = trackSelection.getSelectedIndexInTrackGroup();
|
||||
int selectedVariantIndex = trackSelection.getSelectedIndexInTrackGroup();
|
||||
|
||||
boolean switchingVariant = oldVariantIndex != newVariantIndex;
|
||||
HlsMediaPlaylist mediaPlaylist = playlistTracker.getPlaylistSnapshot(variants[newVariantIndex]);
|
||||
if (mediaPlaylist == null) {
|
||||
out.playlist = variants[newVariantIndex];
|
||||
boolean switchingVariant = oldVariantIndex != selectedVariantIndex;
|
||||
HlsUrl selectedUrl = variants[selectedVariantIndex];
|
||||
if (!playlistTracker.isSnapshotValid(selectedUrl)) {
|
||||
out.playlist = selectedUrl;
|
||||
// Retry when playlist is refreshed.
|
||||
return;
|
||||
}
|
||||
HlsMediaPlaylist mediaPlaylist = playlistTracker.getPlaylistSnapshot(selectedUrl);
|
||||
|
||||
// Select the chunk.
|
||||
int chunkMediaSequence;
|
||||
@ -218,8 +219,9 @@ import java.util.Locale;
|
||||
if (chunkMediaSequence < mediaPlaylist.mediaSequence && previous != null) {
|
||||
// We try getting the next chunk without adapting in case that's the reason for falling
|
||||
// behind the live window.
|
||||
newVariantIndex = oldVariantIndex;
|
||||
mediaPlaylist = playlistTracker.getPlaylistSnapshot(variants[newVariantIndex]);
|
||||
selectedVariantIndex = oldVariantIndex;
|
||||
selectedUrl = variants[selectedVariantIndex];
|
||||
mediaPlaylist = playlistTracker.getPlaylistSnapshot(selectedUrl);
|
||||
chunkMediaSequence = previous.getNextChunkIndex();
|
||||
}
|
||||
}
|
||||
@ -236,7 +238,7 @@ import java.util.Locale;
|
||||
if (mediaPlaylist.hasEndTag) {
|
||||
out.endOfStream = true;
|
||||
} else /* Live */ {
|
||||
out.playlist = variants[newVariantIndex];
|
||||
out.playlist = selectedUrl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -249,7 +251,7 @@ import java.util.Locale;
|
||||
Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.encryptionKeyUri);
|
||||
if (!keyUri.equals(encryptionKeyUri)) {
|
||||
// Encryption is specified and the key has changed.
|
||||
out.chunk = newEncryptionKeyChunk(keyUri, segment.encryptionIV, newVariantIndex,
|
||||
out.chunk = newEncryptionKeyChunk(keyUri, segment.encryptionIV, selectedVariantIndex,
|
||||
trackSelection.getSelectionReason(), trackSelection.getSelectionData());
|
||||
return;
|
||||
}
|
||||
@ -279,7 +281,7 @@ import java.util.Locale;
|
||||
Uri chunkUri = UriUtil.resolveToUri(mediaPlaylist.baseUri, segment.url);
|
||||
DataSpec dataSpec = new DataSpec(chunkUri, segment.byterangeOffset, segment.byterangeLength,
|
||||
null);
|
||||
out.chunk = new HlsMediaChunk(dataSource, dataSpec, initDataSpec, variants[newVariantIndex],
|
||||
out.chunk = new HlsMediaChunk(dataSource, dataSpec, initDataSpec, selectedUrl,
|
||||
trackSelection.getSelectionReason(), trackSelection.getSelectionData(),
|
||||
startTimeUs, startTimeUs + segment.durationUs, chunkMediaSequence, discontinuitySequence,
|
||||
isTimestampMaster, timestampAdjuster, previous, encryptionKey, encryptionIv);
|
||||
|
@ -166,8 +166,24 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
||||
* be null if no snapshot has been loaded yet.
|
||||
*/
|
||||
public HlsMediaPlaylist getPlaylistSnapshot(HlsUrl url) {
|
||||
HlsMediaPlaylist snapshot = playlistBundles.get(url).getPlaylistSnapshot();
|
||||
if (snapshot != null) {
|
||||
maybeSetPrimaryUrl(url);
|
||||
return playlistBundles.get(url).getPlaylistSnapshot();
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the snapshot of the playlist referenced by the provided {@link HlsUrl} is
|
||||
* valid, meaning all the segments referenced by the playlist are expected to be available. If the
|
||||
* playlist is not valid then some of the segments may no longer be available.
|
||||
|
||||
* @param url The {@link HlsUrl}.
|
||||
* @return Whether the snapshot of the playlist referenced by the provided {@link HlsUrl} is
|
||||
* valid.
|
||||
*/
|
||||
public boolean isSnapshotValid(HlsUrl url) {
|
||||
return playlistBundles.get(url).isSnapshotValid();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -412,6 +428,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
||||
private final ParsingLoadable<HlsPlaylist> mediaPlaylistLoadable;
|
||||
|
||||
private HlsMediaPlaylist playlistSnapshot;
|
||||
private long lastSnapshotLoadMs;
|
||||
private long lastSnapshotAccessTimeMs;
|
||||
private long blacklistUntilMs;
|
||||
|
||||
@ -429,6 +446,17 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
||||
return playlistSnapshot;
|
||||
}
|
||||
|
||||
public boolean isSnapshotValid() {
|
||||
if (playlistSnapshot == null) {
|
||||
return false;
|
||||
}
|
||||
// TODO: Return true for event playlists once playlist types are supported.
|
||||
long currentTimeMs = SystemClock.elapsedRealtime();
|
||||
long snapshotValidityDurationMs = Math.max(30000, C.usToMs(playlistSnapshot.durationUs));
|
||||
return playlistSnapshot.hasEndTag
|
||||
|| lastSnapshotLoadMs + snapshotValidityDurationMs > currentTimeMs;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mediaPlaylistLoader.release();
|
||||
}
|
||||
@ -488,6 +516,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
||||
|
||||
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist) {
|
||||
HlsMediaPlaylist oldPlaylist = playlistSnapshot;
|
||||
lastSnapshotLoadMs = SystemClock.elapsedRealtime();
|
||||
playlistSnapshot = getLatestPlaylistSnapshot(oldPlaylist, loadedPlaylist);
|
||||
long refreshDelayUs = C.TIME_UNSET;
|
||||
if (playlistSnapshot != oldPlaylist) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user