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:
aquilescanta 2016-12-13 13:41:18 -08:00 committed by Oliver Woodman
parent 48072f2155
commit 8a7628cb26
3 changed files with 7 additions and 62 deletions

View File

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

View File

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

View File

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