52799413 by David LaPalomento

Calculate bandwidth when downloading segments

Track the XHR duration and use that to figure out bandwidth when downloading segments. Ensure a fresh instance is assigned to player.hls on each plugin invocation so that state attached to the plugin object is not retained across loads.
1 parent 23f8e047
......@@ -10,7 +10,7 @@
videojs.hls = {};
videojs.plugin('hls', function(options) {
var init = function(options) {
var
mediaSource = new videojs.MediaSource(),
segmentParser = new videojs.hls.SegmentParser(),
......@@ -53,7 +53,8 @@ videojs.plugin('hls', function(options) {
var
xhr = new window.XMLHttpRequest(),
segment = player.hls.currentPlaylist.segments[player.hls.currentMediaIndex],
segmentUri = segment.uri;
segmentUri = segment.uri,
startTime;
if (!(/^([A-z]*:)?\/\//).test(segmentUri)) {
// the segment URI is relative to the manifest
segmentUri = url.split('/').slice(0, -1).concat(segmentUri).join('/');
......@@ -61,15 +62,24 @@ videojs.plugin('hls', function(options) {
xhr.open('GET', segmentUri);
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function() {
var elapsed;
if (xhr.readyState === 4) {
player.hls.currentMediaIndex++;
// calculate the download bandwidth
elapsed = ((+new Date()) - startTime) * 1000;
player.hls.bandwidth = xhr.response.byteLength / elapsed;
// transmux the segment data from M2TS to FLV
segmentParser.parseSegmentBinaryData(new Uint8Array(xhr.response));
while (segmentParser.tagsAvailable()) {
player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes,
player);
}
// update the segment index
player.hls.currentMediaIndex++;
}
};
startTime = +new Date();
xhr.send(null);
};
player.on('loadedmetadata', fillBuffer);
......@@ -102,6 +112,16 @@ videojs.plugin('hls', function(options) {
src: videojs.URL.createObjectURL(mediaSource),
type: "video/flv"
});
};
videojs.plugin('hls', function() {
var initialize = function() {
return function() {
this.hls = initialize();
init.apply(this, arguments);
};
};
initialize().apply(this, arguments);
});
})(window, window.videojs);
......
......@@ -42,6 +42,7 @@ module('HLS', {
manifestName = manifestName[1];
}
this.responseText = window.manifests[manifestName || xhrParams[1]];
this.response = new Uint8Array([1]).buffer;
this.readyState = 4;
this.onreadystatechange();
......@@ -93,7 +94,7 @@ test('starts downloading a segment on loadedmetadata', function() {
strictEqual(xhrParams[1], 'manifest/00001.ts', 'the first segment is requested');
});
test('recognizes absolute URIs and uses them umnodified', function() {
test('recognizes absolute URIs and requests them unmodified', function() {
player.hls('manifest/absoluteUris.m3u8');
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
......@@ -104,6 +105,28 @@ test('recognizes absolute URIs and uses them umnodified', function() {
'the first segment is requested');
});
test('re-initializes the plugin for each source', function() {
var firstInit, secondInit;
player.hls('manifest/master.m3u8');
firstInit = player.hls;
player.hls('manifest/master.m3u8');
secondInit = player.hls;
notStrictEqual(firstInit, secondInit, 'the plugin object is replaced');
});
test('calculates the bandwidth after downloading a segment', function() {
player.hls('manifest/media.m3u8');
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
});
ok(player.hls.bandwidth, 'bandwidth is calculated');
ok(player.hls.bandwidth > 0,
'bandwidth is positive: ' + player.hls.bandwidth);
});
module('segment controller', {
setup: function() {
segmentController = new window.videojs.hls.SegmentController();
......