faaa60ef by David LaPalomento

Merge pull request #46 from videojs/hotfix/mse-upgrade

Update to vjs-MSE 0.2.0
2 parents 84ea0e16 7f3f609b
......@@ -10,11 +10,10 @@
<script src="node_modules/video.js/dist/video-js/video.js"></script>
<!-- Media Sources plugin -->
<script src="node_modules/videojs-contrib-media-sources/videojs-media-sources.js"></script>
<script src="node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script>
<!-- HLS plugin -->
<script src="src/videojs-hls.js"></script>
<script src="src/async-queue.js"></script>
<!-- segment handling -->
<script src="src/flv-tag.js"></script>
......
......@@ -40,6 +40,6 @@
"video.js": "^4.5"
},
"dependencies": {
"videojs-contrib-media-sources": "git+https://github.com/videojs/videojs-contrib-media-sources.git"
"videojs-contrib-media-sources": "^0.2"
}
}
......
(function(window, videojs, undefined) {
'use strict';
/**
* A queue object that manages tasks that should be processed
* serially but asynchronously. Loosely adapted from
* https://github.com/caolan/async#queue.
* @param worker {function} the callback to invoke with each value
* pushed onto the queue
* @return {object} an object with an array of `tasks` that remain to
* be processed and function `push` to add new tasks
*/
videojs.hls.queue = function(worker) {
var
q = {
tasks: [],
running: false,
push: function(task) {
q.tasks.push(task);
if (!q.running) {
window.setTimeout(process, 0);
q.running = true;
}
}
},
process = function() {
var task;
if (q.tasks.length) {
task = q.tasks.shift();
worker.call(this, task);
window.setTimeout(process, 0);
} else {
q.running = false;
}
};
return q;
};
})(window, window.videojs);
......@@ -272,15 +272,6 @@ var
mediaSource = new videojs.MediaSource(),
segmentParser = new videojs.hls.SegmentParser(),
player = this,
// async queue of Uint8Arrays to be appended to the SourceBuffer
tags = videojs.hls.queue(function(tag) {
player.hls.sourceBuffer.appendBuffer(tag, player);
if (player.hls.mediaIndex === player.hls.media.segments.length) {
mediaSource.endOfStream();
}
}),
srcUrl,
playlistXhr,
......@@ -366,11 +357,13 @@ var
var currentTime = player.currentTime();
player.hls.mediaIndex = getMediaIndexByTime(player.hls.media, currentTime);
// abort any segments still being decoded
player.hls.sourceBuffer.abort();
// cancel outstanding requests and buffer appends
if (segmentXhr) {
segmentXhr.abort();
}
tags.tasks = [];
// begin filling the buffer at the new position
fillBuffer(currentTime * 1000);
......@@ -686,11 +679,18 @@ var
// queue up the bytes to be appended to the SourceBuffer
// the queue gives control back to the browser between tags
// so that large segments don't cause a "hiccup" in playback
tags.push(segmentParser.getNextTag().bytes);
player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes,
player);
}
player.hls.mediaIndex++;
if (player.hls.mediaIndex === player.hls.media.segments.length) {
mediaSource.endOfStream();
}
// figure out what stream the next segment should be downloaded from
// with the updated bandwidth information
updateCurrentPlaylist();
......
(function(window, queue, undefined) {
var
oldSetTimeout,
callbacks;
module('async queue', {
setup: function() {
oldSetTimeout = window.setTimeout;
callbacks = [];
window.setTimeout = function(callback) {
callbacks.push(callback);
};
},
teardown: function() {
window.setTimeout = oldSetTimeout;
}
});
test('runs tasks asynchronously', function() {
var
run = false,
q = queue(function() {
run = true;
});
q.push(1);
ok(!run, 'tasks are not run immediately');
callbacks[0]();
ok(run, 'tasks are run asynchronously');
});
test('runs one task at a time', function() {
var q = queue(function() {});
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
strictEqual(q.tasks.length, 5, 'all tasks are queued');
strictEqual(1, callbacks.length, 'one callback is registered');
});
test('tasks are scheduled until the queue is empty', function() {
var q = queue(function() {});
q.push(1);
q.push(2);
callbacks.shift()();
strictEqual(1, callbacks.length, 'the next task is scheduled');
callbacks.shift()();
strictEqual(1, callbacks.length, 'nothing is scheduled on an empty queue');
});
test('can be emptied at any time', function() {
var
runs = 0,
q = queue(function() {
runs++;
});
q.push(1);
q.push(2);
callbacks.shift()();
strictEqual(1, runs, 'task one is run');
q.tasks = [];
callbacks.shift()();
strictEqual(1, runs, 'the remaining tasks are cancelled');
});
})(window, window.videojs.hls.queue);
......@@ -40,7 +40,7 @@ module.exports = function(config) {
files: [
'../node_modules/video.js/dist/video-js/video.js',
'../node_modules/videojs-contrib-media-sources/videojs-media-sources.js',
'../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js',
'../test/karma-qunit-shim.js',
"../src/videojs-hls.js",
"../src/flv-tag.js",
......
......@@ -35,7 +35,7 @@ module.exports = function(config) {
files: [
'../node_modules/video.js/dist/video-js/video.js',
'../node_modules/videojs-contrib-media-sources/videojs-media-sources.js',
'../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js',
'../test/karma-qunit-shim.js',
"../src/videojs-hls.js",
"../src/flv-tag.js",
......
......@@ -9,7 +9,7 @@
<!-- video.js -->
<script src="../node_modules/video.js/dist/video-js/video.js"></script>
<script src="../node_modules/videojs-contrib-media-sources/videojs-media-sources.js"></script>
<script src="../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script>
<!-- HLS plugin -->
<script src="../src/videojs-hls.js"></script>
......@@ -31,9 +31,6 @@
<script src="tsSegment-bc.js"></script>
<script src="../src/bin-utils.js"></script>
<!-- async queue -->
<script src="../src/async-queue.js"></script>
<!-- Test cases -->
<script>
module('environment');
......@@ -48,7 +45,6 @@
<script src="exp-golomb_test.js"></script>
<script src="flv-tag_test.js"></script>
<script src="m3u8_test.js"></script>
<script src="async-queue_test.js"></script>
</head>
<body>
<div id="qunit"></div>
......
......@@ -63,6 +63,7 @@ module('HLS', {
oldSourceBuffer = window.videojs.SourceBuffer;
window.videojs.SourceBuffer = function() {
this.appendBuffer = function() {};
this.abort = function() {};
};
// force native HLS to be ignored
......@@ -714,6 +715,7 @@ test('drops tags before the target timestamp when seeking', function() {
this.appendBuffer = function(chunk) {
bytes.push(chunk);
};
this.abort = function() {};
};
// capture timeouts
window.setTimeout = function(callback) {
......@@ -755,6 +757,7 @@ test('clears pending buffer updates when seeking', function() {
var
bytes = [],
callbacks = [],
aborts = 0,
tags = [{ pts: 0, bytes: 0 }];
// mock out the parser and source buffer
videojs.hls.SegmentParser = mockSegmentParser(tags);
......@@ -762,6 +765,9 @@ test('clears pending buffer updates when seeking', function() {
this.appendBuffer = function(chunk) {
bytes.push(chunk);
};
this.abort = function() {
aborts++;
};
};
// capture timeouts
window.setTimeout = function(callback) {
......@@ -785,7 +791,7 @@ test('clears pending buffer updates when seeking', function() {
callbacks.shift()();
}
deepEqual(bytes, ['flv', 7], 'tags queued to be appended should be cancelled');
strictEqual(1, aborts, 'aborted pending buffer');
});
test('playlist 404 should trigger MEDIA_ERR_NETWORK', function() {
......@@ -1067,6 +1073,7 @@ test('only reloads the active media playlist', function() {
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
});
videojs.mediaSources[player.currentSrc()].endOfStream = function() {};
window.XMLHttpRequest = function() {
this.open = function(method, url) {
......