UNPKG

videojs-contrib-hls

Version:

Play back HLS with video.js, even where it's not natively supported

208 lines (176 loc) 6.13 kB
import videojs from 'video.js'; import QUnit from 'qunit'; import { useFakeEnvironment, useFakeMediaSource, createPlayer, openMediaSource, standardXHRResponse } from './test-helpers.js'; import GapSkipper from '../src/gap-skipper'; QUnit.module('GapSkipper', { beforeEach() { this.env = useFakeEnvironment(); this.requests = this.env.requests; this.mse = useFakeMediaSource(); this.clock = this.env.clock; this.old = {}; // setup a player this.player = createPlayer(); }, afterEach() { this.env.restore(); this.mse.restore(); this.player.dispose(); } }); QUnit.test('skips over gap in firefox with waiting event', function() { this.player.autoplay(true); // create a buffer with a gap between 10 & 20 seconds this.player.tech_.buffered = function() { return videojs.createTimeRanges([[0, 10], [20, 30]]); }; // set an arbitrary source this.player.src({ src: 'master.m3u8', type: 'application/vnd.apple.mpegurl' }); // start playback normally this.player.tech_.triggerReady(); this.clock.tick(1); standardXHRResponse(this.requests.shift()); openMediaSource(this.player, this.clock); this.player.tech_.trigger('play'); this.player.tech_.trigger('playing'); this.clock.tick(1); // seek to 10 seconds and wait 12 seconds this.player.currentTime(10); this.player.tech_.trigger('waiting'); this.clock.tick(12000); // check that player jumped the gap QUnit.equal(Math.round(this.player.currentTime()), 20, 'Player seeked over gap after timer'); }); QUnit.test('skips over gap in chrome without waiting event', function() { this.player.autoplay(true); // create a buffer with a gap between 10 & 20 seconds this.player.tech_.buffered = function() { return videojs.createTimeRanges([[0, 10], [20, 30]]); }; // set an arbitrary source this.player.src({ src: 'master.m3u8', type: 'application/vnd.apple.mpegurl' }); // start playback normally this.player.tech_.triggerReady(); this.clock.tick(1); standardXHRResponse(this.requests.shift()); openMediaSource(this.player, this.clock); this.player.tech_.trigger('play'); this.player.tech_.trigger('playing'); this.clock.tick(1); // seek to 10 seconds & simulate chrome waiting event this.player.currentTime(10); for (let i = 0; i < 10; i++) { this.player.tech_.trigger('timeupdate'); } this.clock.tick(2000); // checks that player doesn't seek before timer expires QUnit.equal(this.player.currentTime(), 10, 'Player doesnt seek over gap pre-timer'); this.clock.tick(10000); // check that player jumped the gap QUnit.equal(Math.round(this.player.currentTime()), 20, 'Player seeked over gap after timer'); }); QUnit.test('skips over gap in Chrome due to video underflow', function() { this.player.autoplay(true); this.player.tech_.buffered = () => { return videojs.createTimeRanges([[0, 10], [10.1, 20]]); }; // set an arbitrary source this.player.src({ src: 'master.m3u8', type: 'application/vnd.apple.mpegurl' }); // start playback normally this.player.tech_.triggerReady(); this.clock.tick(1); standardXHRResponse(this.requests.shift()); openMediaSource(this.player, this.clock); this.player.tech_.trigger('play'); this.player.tech_.trigger('playing'); this.clock.tick(1); this.player.currentTime(13); let seeks = []; this.player.tech_.setCurrentTime = (time) => { seeks.push(time); }; for (let i = 0; i < 7; i++) { this.player.tech_.trigger('timeupdate'); } QUnit.equal(seeks.length, 1, 'one seek'); QUnit.equal(seeks[0], 13, 'player seeked to current time'); }); QUnit.module('GapSkipper isolated functions', { beforeEach() { this.gapSkipper = new GapSkipper({ tech: { on: () => {}, off: () => {} } }); } }); QUnit.test('skips gap from video underflow', function() { QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_(videojs.createTimeRanges(), 0), null, 'returns null when buffer is empty'); QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_(videojs.createTimeRanges([[0, 10]]), 13), null, 'returns null when there is only a previous buffer'); QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 15), null, 'returns null when gap is too far from current time'); QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 9.9), null, 'returns null when gap is after current time'); QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10.1], [10.2, 20]]), 12.1), null, 'returns null when time is less than or equal to 2 seconds ahead'); QUnit.equal( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 14.1), null, 'returns null when time is greater than or equal to 4 seconds ahead'); QUnit.deepEqual( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 12.2), {start: 10, end: 10.1}, 'returns gap when gap is small and time is greater than 2 seconds ahead in a buffer'); QUnit.deepEqual( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 13), {start: 10, end: 10.1}, 'returns gap when gap is small and time is 3 seconds ahead in a buffer'); QUnit.deepEqual( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 20]]), 13.9), {start: 10, end: 10.1}, 'returns gap when gap is small and time is less than 4 seconds ahead in a buffer'); // In a case where current time is outside of the buffered range, something odd must've // happened, but we should still allow the player to try to continue from that spot. QUnit.deepEqual( this.gapSkipper.gapFromVideoUnderflow_( videojs.createTimeRanges([[0, 10], [10.1, 12.9]]), 13), {start: 10, end: 10.1}, 'returns gap even when current time is not in buffered range'); });