Skip to content

Commit

Permalink
WIP(HLS): Fix duplicate hinted segments (alternate fix)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyparrish committed May 26, 2022
1 parent a6b7148 commit adf3b77
Showing 1 changed file with 32 additions and 5 deletions.
37 changes: 32 additions & 5 deletions lib/media/streaming_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -1123,16 +1123,39 @@ shaka.media.StreamingEngine = class {
mediaState.stream.segmentIndex,
'segment index should have been generated already');

// This scenario requires special handling. In LL-HLS and sequence mode, we
// need to be careful with preload-hinted partial segments, which don't have
// a known duration at the time we append them. If we aren't careful, we
// can end up appending the same partial segment twice, since based on the
// last segment reference alone, we might think we need the same timestamp
// again. If we make that mistake in sequence mode, we end up with repeated
// content and possible A/V desync.
// https://github.com/shaka-project/shaka-player/issues/4223#issuecomment-1138910167
const lastReference = mediaState.lastSegmentReference;
const lastReferenceHadUnknownDuration =
lastReference &&
lastReference.startTime == lastReference.endTime;

const isRepeatedSegment = (ref) => {
// Sometimes, the new ref's start time is a fraction of a second earlier,
// due to rounding errors. We should still detect that as a repeat.
return ref &&
ref.startTime <= lastReference.startTime;
};

if (mediaState.segmentIterator) {
// Something is buffered from the same Stream. Use the current position
// in the segment index. This is updated via next() after each segment is
// appended.
return mediaState.segmentIterator.current();
} else if (mediaState.lastSegmentReference || bufferEnd) {
const currentRef = mediaState.segmentIterator.current();
if (lastReferenceHadUnknownDuration && isRepeatedSegment(currentRef)) {
// Advance one more time.
return mediaState.segmentIterator.next().value;
}
return currentRef;
} else if (lastReference || bufferEnd) {
// Something is buffered from another Stream.
const time = mediaState.lastSegmentReference ?
mediaState.lastSegmentReference.endTime :
bufferEnd;
const time = lastReference ? lastReference.endTime : bufferEnd;
goog.asserts.assert(time != null, 'Should have a time to search');
shaka.log.v1(
logPrefix, 'looking up segment from new stream endTime:', time);
Expand All @@ -1144,6 +1167,10 @@ shaka.media.StreamingEngine = class {
if (ref == null) {
shaka.log.warning(logPrefix, 'cannot find segment', 'endTime:', time);
}
if (lastReferenceHadUnknownDuration && isRepeatedSegment(ref)) {
// Advance one more time.
return mediaState.segmentIterator.next().value;
}
return ref;
} else {
// Nothing is buffered. Start at the playhead time.
Expand Down

0 comments on commit adf3b77

Please sign in to comment.