forked from video-dev/hls.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor live backbuffer eviction to fit more closely to design goals (…
- Loading branch information
1 parent
3e6651d
commit 1671c91
Showing
3 changed files
with
122 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,80 +1,120 @@ | ||
import assert from 'assert'; | ||
import { stub } from 'sinon'; | ||
import sinon from 'sinon'; | ||
import Hls from '../../../src/hls'; | ||
import BufferController from '../../../src/controller/buffer-controller'; | ||
|
||
describe('BufferController tests', function () { | ||
let hls; | ||
let bufferController; | ||
let flushSpy; | ||
let removeStub; | ||
const sandbox = sinon.sandbox.create(); | ||
|
||
beforeEach(function () { | ||
hls = new Hls({}); | ||
|
||
bufferController = new BufferController(hls); | ||
flushSpy = sandbox.spy(bufferController, 'flushLiveBackBuffer'); | ||
removeStub = sandbox.stub(bufferController, 'removeBufferRange'); | ||
}); | ||
|
||
describe('Live back buffer enforcement', () => { | ||
it('should trigger clean back buffer when there are no pending appends', () => { | ||
bufferController.parent = {}; | ||
bufferController.segments = [{ parent: bufferController.parent }]; | ||
|
||
let clearStub = stub(bufferController, 'clearLiveBackBuffer'); | ||
stub(bufferController, 'doAppending'); | ||
|
||
bufferController.onSBUpdateEnd(); | ||
|
||
assert(clearStub.notCalled, 'clear live back buffer was called'); | ||
|
||
bufferController.segments = []; | ||
bufferController.onSBUpdateEnd(); | ||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
|
||
assert(clearStub.calledOnce, 'clear live back buffer was not called once'); | ||
}); | ||
describe('Live back buffer enforcement', function () { | ||
let mockMedia; | ||
let mockSourceBuffer; | ||
let bufStart; | ||
|
||
it('should trigger buffer removal with valid range for live', () => { | ||
bufferController.media = { currentTime: 360 }; | ||
hls.config.liveBackBufferLength = 60; | ||
bufferController.sourceBuffer = { | ||
beforeEach(function () { | ||
bufStart = 0; | ||
bufferController._levelTargetDuration = 10; | ||
bufferController.media = mockMedia = { | ||
currentTime: 0 | ||
}; | ||
bufferController.sourceBuffer = mockSourceBuffer = { | ||
video: { | ||
buffered: { | ||
start: stub().withArgs(0).returns(120), | ||
start () { | ||
return bufStart; | ||
}, | ||
length: 1 | ||
} | ||
} | ||
}; | ||
bufferController._live = true; | ||
hls.config.liveBackBufferLength = 10; | ||
}); | ||
|
||
let removeBufferRangeStub = stub(bufferController, 'removeBufferRange'); | ||
it('exits early if not live', function () { | ||
bufferController.flushLiveBackBuffer(); | ||
assert(removeStub.notCalled); | ||
}); | ||
|
||
bufferController._live = false; | ||
bufferController.clearLiveBackBuffer(); | ||
assert(removeBufferRangeStub.notCalled, 'remove buffer range was called for non-live'); | ||
it('exits early if liveBackBufferLength is not a finite number, or is less than 0', function () { | ||
hls.config.liveBackBufferLength = 'foo'; | ||
bufferController.flushLiveBackBuffer(); | ||
|
||
bufferController._live = true; | ||
bufferController.clearLiveBackBuffer(); | ||
assert(removeBufferRangeStub.calledOnce, 'remove buffer range was not called once'); | ||
|
||
assert( | ||
removeBufferRangeStub.calledWith( | ||
'video', | ||
bufferController.sourceBuffer.video, | ||
0, | ||
bufferController.media.currentTime - hls.config.liveBackBufferLength | ||
), | ||
'remove buffer range was not requested with valid data from liveBackBufferLength' | ||
); | ||
hls.config.liveBackBufferLength = -1; | ||
bufferController.flushLiveBackBuffer(); | ||
|
||
assert(removeStub.notCalled); | ||
}); | ||
|
||
it('does not flush if nothing is buffered', function () { | ||
delete mockSourceBuffer.buffered; | ||
bufferController.flushLiveBackBuffer(); | ||
|
||
mockSourceBuffer = null; | ||
bufferController.flushLiveBackBuffer(); | ||
|
||
assert(removeStub.notCalled); | ||
}); | ||
|
||
it('does not flush if no buffered range intersects with back buffer limit', function () { | ||
bufStart = 5; | ||
mockMedia.currentTime = 10; | ||
bufferController.flushLiveBackBuffer(); | ||
assert(removeStub.notCalled); | ||
}); | ||
|
||
it('does not flush if the liveBackBufferLength is Infinity', function () { | ||
hls.config.liveBackBufferLength = Infinity; | ||
mockMedia.currentTime = 15; | ||
bufferController.flushLiveBackBuffer(); | ||
assert(removeStub.notCalled); | ||
}); | ||
|
||
it('flushes up to the back buffer limit if the buffer intersects with that point', function () { | ||
mockMedia.currentTime = 15; | ||
bufferController.flushLiveBackBuffer(); | ||
assert(removeStub.calledOnce); | ||
assert(!bufferController.flushBufferCounter, 'Should reset the flushBufferCounter'); | ||
assert(removeStub.calledWith('video', mockSourceBuffer.video, 0, 5)); | ||
}); | ||
|
||
it('flushes to a max of one targetDuration from currentTime, regardless of liveBackBufferLength', function () { | ||
mockMedia.currentTime = 15; | ||
bufferController._levelTargetDuration = 5; | ||
hls.config.liveBackBufferLength = 0; | ||
bufferController._levelTargetDuration = 10; | ||
bufferController.clearLiveBackBuffer(); | ||
assert( | ||
removeBufferRangeStub.calledWith( | ||
'video', | ||
bufferController.sourceBuffer.video, | ||
0, | ||
bufferController.media.currentTime - bufferController._levelTargetDuration | ||
), | ||
'remove buffer range was not requested with valid data from _levelTargetDuration' | ||
); | ||
bufferController.flushLiveBackBuffer(); | ||
assert(removeStub.calledWith('video', mockSourceBuffer.video, 0, 10)); | ||
}); | ||
|
||
it('should trigger clean back buffer when there are no pending appends', function () { | ||
bufferController.parent = {}; | ||
bufferController.segments = [{ parent: bufferController.parent }]; | ||
|
||
sandbox.stub(bufferController, 'doAppending'); | ||
|
||
bufferController.onSBUpdateEnd(); | ||
|
||
assert(flushSpy.notCalled, 'clear live back buffer was called'); | ||
|
||
bufferController.segments = []; | ||
bufferController.onSBUpdateEnd(); | ||
|
||
assert(flushSpy.calledOnce, 'clear live back buffer was not called once'); | ||
}); | ||
}); | ||
}); |