Browse Source
Yield control to the browser between appending FLV tags
Yield control to the browser between appending FLV tags
Pushing an entire segment worth of FLV tags into the source buffer at once caused noticeable delays with high-bitrate segments. Instead, wrap each call to appendBuffer in a setTimeout of zero so that the browser has a chance to render frames while the segment is being transferred to the SWF. Make sure that appends-in-progress are cleared if a seek is initiated.pull/80/head

7 changed files with 217 additions and 32 deletions
-
4Gruntfile.js
-
1example.html
-
37src/async-queue.js
-
24src/videojs-hls.js
-
69test/async-queue_test.js
-
4test/videojs-hls.html
-
110test/videojs-hls_test.js
@ -0,0 +1,37 @@ |
|||
(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); |
@ -0,0 +1,69 @@ |
|||
(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'); |
|||
}); |
|||
|
|||
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); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue