mirror of
https://github.com/androidx/media.git
synced 2025-05-15 19:49:50 +08:00
Remove playlist adjustment on chunk loads
This is particularly problematic for subtitle tracks where adjustment can be broken. Now, the primary url can change when clients ask for a variant snapshot, instead of happening on chunk load as before. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=141933689
This commit is contained in:
parent
48072f2155
commit
8a7628cb26
@ -190,7 +190,7 @@ import java.util.Locale;
|
|||||||
// Use start time of the previous chunk rather than its end time because switching format will
|
// Use start time of the previous chunk rather than its end time because switching format will
|
||||||
// require downloading overlapping segments.
|
// require downloading overlapping segments.
|
||||||
long bufferedDurationUs = previous == null ? 0
|
long bufferedDurationUs = previous == null ? 0
|
||||||
: Math.max(0, previous.getAdjustedStartTimeUs() - playbackPositionUs);
|
: Math.max(0, previous.startTimeUs - playbackPositionUs);
|
||||||
|
|
||||||
// Select the variant.
|
// Select the variant.
|
||||||
trackSelection.updateSelectedTrack(bufferedDurationUs);
|
trackSelection.updateSelectedTrack(bufferedDurationUs);
|
||||||
@ -291,11 +291,7 @@ import java.util.Locale;
|
|||||||
* @param chunk The chunk whose load has been completed.
|
* @param chunk The chunk whose load has been completed.
|
||||||
*/
|
*/
|
||||||
public void onChunkLoadCompleted(Chunk chunk) {
|
public void onChunkLoadCompleted(Chunk chunk) {
|
||||||
if (chunk instanceof HlsMediaChunk) {
|
if (chunk instanceof EncryptionKeyChunk) {
|
||||||
HlsMediaChunk mediaChunk = (HlsMediaChunk) chunk;
|
|
||||||
playlistTracker.onChunkLoaded(mediaChunk.hlsUrl, mediaChunk.chunkIndex,
|
|
||||||
mediaChunk.getAdjustedStartTimeUs());
|
|
||||||
} else if (chunk instanceof EncryptionKeyChunk) {
|
|
||||||
EncryptionKeyChunk encryptionKeyChunk = (EncryptionKeyChunk) chunk;
|
EncryptionKeyChunk encryptionKeyChunk = (EncryptionKeyChunk) chunk;
|
||||||
scratchSpace = encryptionKeyChunk.getDataHolder();
|
scratchSpace = encryptionKeyChunk.getDataHolder();
|
||||||
setEncryptionData(encryptionKeyChunk.dataSpec.uri, encryptionKeyChunk.iv,
|
setEncryptionData(encryptionKeyChunk.dataSpec.uri, encryptionKeyChunk.iv,
|
||||||
|
@ -91,7 +91,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private int bytesLoaded;
|
private int bytesLoaded;
|
||||||
private boolean initLoadCompleted;
|
private boolean initLoadCompleted;
|
||||||
private HlsSampleStreamWrapper extractorOutput;
|
private HlsSampleStreamWrapper extractorOutput;
|
||||||
private long adjustedEndTimeUs;
|
|
||||||
private volatile boolean loadCanceled;
|
private volatile boolean loadCanceled;
|
||||||
private volatile boolean loadCompleted;
|
private volatile boolean loadCompleted;
|
||||||
|
|
||||||
@ -141,7 +140,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
id3Data = null;
|
id3Data = null;
|
||||||
}
|
}
|
||||||
initDataSource = dataSource;
|
initDataSource = dataSource;
|
||||||
adjustedEndTimeUs = endTimeUs;
|
|
||||||
uid = UID_SOURCE.getAndIncrement();
|
uid = UID_SOURCE.getAndIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,20 +154,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
output.init(uid, previousChunk != null && previousChunk.hlsUrl != hlsUrl);
|
output.init(uid, previousChunk != null && previousChunk.hlsUrl != hlsUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the presentation time in microseconds of the first sample in the chunk.
|
|
||||||
*/
|
|
||||||
public long getAdjustedStartTimeUs() {
|
|
||||||
return adjustedEndTimeUs - getDurationUs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the presentation time in microseconds of the last sample in the chunk.
|
|
||||||
*/
|
|
||||||
public long getAdjustedEndTimeUs() {
|
|
||||||
return adjustedEndTimeUs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLoadCompleted() {
|
public boolean isLoadCompleted() {
|
||||||
return loadCompleted;
|
return loadCompleted;
|
||||||
@ -265,10 +249,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
while (result == Extractor.RESULT_CONTINUE && !loadCanceled) {
|
||||||
result = extractor.read(input, null);
|
result = extractor.read(input, null);
|
||||||
}
|
}
|
||||||
long adjustedEndTimeUs = extractorOutput.getLargestQueuedTimestampUs();
|
|
||||||
if (adjustedEndTimeUs != Long.MIN_VALUE) {
|
|
||||||
this.adjustedEndTimeUs = adjustedEndTimeUs;
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
|
bytesLoaded = (int) (input.getPosition() - dataSpec.absoluteStreamPosition);
|
||||||
}
|
}
|
||||||
|
@ -74,12 +74,6 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The minimum number of milliseconds by which a media playlist segment's start time has to drift
|
|
||||||
* from the actual start time of the chunk it refers to for it to be adjusted.
|
|
||||||
*/
|
|
||||||
private static final long TIMESTAMP_ADJUSTMENT_THRESHOLD_US = 500000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum number of milliseconds that a url is kept as primary url, if no
|
* The minimum number of milliseconds that a url is kept as primary url, if no
|
||||||
* {@link #getPlaylistSnapshot} call is made for that url.
|
* {@link #getPlaylistSnapshot} call is made for that url.
|
||||||
@ -172,6 +166,7 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
|||||||
* be null if no snapshot has been loaded yet.
|
* be null if no snapshot has been loaded yet.
|
||||||
*/
|
*/
|
||||||
public HlsMediaPlaylist getPlaylistSnapshot(HlsUrl url) {
|
public HlsMediaPlaylist getPlaylistSnapshot(HlsUrl url) {
|
||||||
|
maybeSetPrimaryUrl(url);
|
||||||
return playlistBundles.get(url).getPlaylistSnapshot();
|
return playlistBundles.get(url).getPlaylistSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,18 +213,6 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
|||||||
return isLive;
|
return isLive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a chunk from a media playlist is loaded.
|
|
||||||
*
|
|
||||||
* @param hlsUrl The url of the playlist from which the chunk was obtained.
|
|
||||||
* @param chunkMediaSequence The media sequence number of the loaded chunk.
|
|
||||||
* @param adjustedStartTimeUs The adjusted start time of the loaded chunk.
|
|
||||||
*/
|
|
||||||
public void onChunkLoaded(HlsUrl hlsUrl, int chunkMediaSequence, long adjustedStartTimeUs) {
|
|
||||||
playlistBundles.get(hlsUrl).adjustTimestampsOfPlaylist(chunkMediaSequence, adjustedStartTimeUs);
|
|
||||||
maybeSetPrimaryUrl(hlsUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loader.Callback implementation.
|
// Loader.Callback implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -295,8 +278,10 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maybeSetPrimaryUrl(HlsUrl url) {
|
private void maybeSetPrimaryUrl(HlsUrl url) {
|
||||||
if (!masterPlaylist.variants.contains(url)) {
|
if (!masterPlaylist.variants.contains(url)
|
||||||
// Only allow variant urls to be chosen as primary.
|
|| (primaryUrlSnapshot != null && primaryUrlSnapshot.hasEndTag)) {
|
||||||
|
// Only allow variant urls to be chosen as primary. Also prevent changing the primary url if
|
||||||
|
// the last primary snapshot contains an end tag.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MediaPlaylistBundle currentPrimaryBundle = playlistBundles.get(primaryHlsUrl);
|
MediaPlaylistBundle currentPrimaryBundle = playlistBundles.get(primaryHlsUrl);
|
||||||
@ -429,22 +414,6 @@ public final class HlsPlaylistTracker implements Loader.Callback<ParsingLoadable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void adjustTimestampsOfPlaylist(int chunkMediaSequence, long adjustedChunkStartTimeUs) {
|
|
||||||
int indexOfChunk = chunkMediaSequence - playlistSnapshot.mediaSequence;
|
|
||||||
if (playlistSnapshot.hasProgramDateTime || indexOfChunk < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Segment actualSegment = playlistSnapshot.segments.get(indexOfChunk);
|
|
||||||
long segmentAbsoluteStartTimeUs =
|
|
||||||
actualSegment.relativeStartTimeUs + playlistSnapshot.startTimeUs;
|
|
||||||
long timestampDriftUs = Math.abs(segmentAbsoluteStartTimeUs - adjustedChunkStartTimeUs);
|
|
||||||
if (timestampDriftUs < TIMESTAMP_ADJUSTMENT_THRESHOLD_US) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
playlistSnapshot = playlistSnapshot.copyWithStartTimeUs(
|
|
||||||
adjustedChunkStartTimeUs - actualSegment.relativeStartTimeUs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loader.Callback implementation.
|
// Loader.Callback implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user