diff --git a/src/controller/fragment-finders.ts b/src/controller/fragment-finders.ts index 995352fc944..6dd7445a1a1 100644 --- a/src/controller/fragment-finders.ts +++ b/src/controller/fragment-finders.ts @@ -82,7 +82,7 @@ export function findFragmentByPTS( fragments, fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance) ); - if (foundFragment) { + if (foundFragment && (foundFragment !== fragPrevious || !fragNext)) { return foundFragment; } // If no match was found return the next fragment after fragPrevious, or null @@ -101,6 +101,13 @@ export function fragmentWithinToleranceTest( maxFragLookUpTolerance = 0, candidate: Fragment ) { + // eagerly accept an accurate match (no tolerance) + if ( + candidate.start <= bufferEnd && + candidate.start + candidate.duration > bufferEnd + ) { + return 0; + } // offset should be within fragment boundary - config.maxFragLookUpTolerance // this is to cope with situations like // bufferEnd = 9.991 diff --git a/tests/unit/controller/fragment-finders.js b/tests/unit/controller/fragment-finders.js index d695959e2f2..efc10774bd2 100644 --- a/tests/unit/controller/fragment-finders.js +++ b/tests/unit/controller/fragment-finders.js @@ -192,7 +192,7 @@ describe('Fragment finders', function () { expect(actual).to.equal(-1); }); - it('does not skip very small fragments', function () { + it('does not skip very small fragments at the start', function () { const frag = { start: 0.2, duration: 0.1, @@ -201,6 +201,31 @@ describe('Fragment finders', function () { const actual = fragmentWithinToleranceTest(0, tolerance, frag); expect(actual).to.equal(0); }); + it('does not skip very small fragments', function () { + const frag = { + start: 5, + duration: 0.1, + deltaPTS: 0.1, + }; + const actual = fragmentWithinToleranceTest(5, tolerance, frag); + expect(actual).to.equal(0); + }); + it('does not skip very small fragments without deltaPTS', function () { + const frag = { + start: 5, + duration: 0.1, + }; + const actual = fragmentWithinToleranceTest(5, tolerance, frag); + expect(actual).to.equal(0); + }); + it('does not skip fragments when searching near boundaries', function () { + const frag = { + start: 19.96916, + duration: 9.98458, + }; + const actual = fragmentWithinToleranceTest(29, 0.25, frag); + expect(actual).to.equal(0); + }); }); describe('findFragmentByPDT', function () {