Skip to content

Commit

Permalink
Don't append over first fragment when next fragment aligns with playl…
Browse files Browse the repository at this point in the history
…ist within 1/200s tolerance

Fixes edge-case starting in v1.5 that causes #6441
  • Loading branch information
robwalch committed May 31, 2024
1 parent adf87aa commit 618e529
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/controller/base-stream-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ export default class BaseStreamController
let { fragPrevious } = this;
let { fragments, endSN } = levelDetails;
const { fragmentHint } = levelDetails;
const tolerance = config.maxFragLookUpTolerance;
const { maxFragLookUpTolerance } = config;
const partList = levelDetails.partList;

const loadingParts = !!(
Expand All @@ -1294,7 +1294,8 @@ export default class BaseStreamController

let frag;
if (bufferEnd < end) {
const lookupTolerance = bufferEnd > end - tolerance ? 0 : tolerance;
const lookupTolerance =
bufferEnd > end - maxFragLookUpTolerance ? 0 : maxFragLookUpTolerance;
// Remove the tolerance if it would put the bufferEnd past the actual end of stream
// Uses buffer and sequence number to calculate switch segment (required if using EXT-X-DISCONTINUITY-SEQUENCE)
frag = findFragmentByPTS(
Expand Down
37 changes: 34 additions & 3 deletions src/controller/fragment-finders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export function findFragmentByPTS(
fragments: Array<Fragment>,
bufferEnd: number = 0,
maxFragLookUpTolerance: number = 0,
nextFragLookupTolerance: number = 0.005,
): Fragment | null {
let fragNext: Fragment | null = null;
if (fragPrevious) {
Expand All @@ -76,9 +77,17 @@ export function findFragmentByPTS(
// Prefer the next fragment if it's within tolerance
if (
fragNext &&
(!fragPrevious || fragPrevious.level === fragNext.level) &&
fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext) ===
0
(((!fragPrevious || fragPrevious.level === fragNext.level) &&
fragmentWithinToleranceTest(
bufferEnd,
maxFragLookUpTolerance,
fragNext,
) === 0) ||
fragmentWithinFastStartSwitch(
fragNext,
fragPrevious,
Math.min(nextFragLookupTolerance, maxFragLookUpTolerance),
))
) {
return fragNext;
}
Expand All @@ -94,6 +103,28 @@ export function findFragmentByPTS(
return fragNext;
}

function fragmentWithinFastStartSwitch(
fragNext: Fragment,
fragPrevious: Fragment | null,
nextFragLookupTolerance: number,
): boolean {
if (
fragPrevious &&
fragPrevious.start === 0 &&
fragPrevious.level < fragNext.level &&
(fragPrevious.endPTS || 0) > 0
) {
const firstDuration = fragPrevious.tagList.reduce((duration, tag) => {
if (tag[0] === 'INF') {
duration += parseFloat(tag[1]);
}
return duration;
}, nextFragLookupTolerance);
return fragNext.start <= firstDuration;
}
return false;
}

/**
* The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.
* @param candidate - The fragment to test
Expand Down

0 comments on commit 618e529

Please sign in to comment.