Browse Source

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.
pull/80/head
David LaPalomento 12 years ago
parent
commit
5279941369
  1. 26
      src/videojs-hls.js
  2. 25
      test/videojs-hls_test.js

26
src/videojs-hls.js

@ -10,7 +10,7 @@
videojs.hls = {}; videojs.hls = {};
videojs.plugin('hls', function(options) {
var init = function(options) {
var var
mediaSource = new videojs.MediaSource(), mediaSource = new videojs.MediaSource(),
segmentParser = new videojs.hls.SegmentParser(), segmentParser = new videojs.hls.SegmentParser(),
@ -53,7 +53,8 @@ videojs.plugin('hls', function(options) {
var var
xhr = new window.XMLHttpRequest(), xhr = new window.XMLHttpRequest(),
segment = player.hls.currentPlaylist.segments[player.hls.currentMediaIndex], segment = player.hls.currentPlaylist.segments[player.hls.currentMediaIndex],
segmentUri = segment.uri;
segmentUri = segment.uri,
startTime;
if (!(/^([A-z]*:)?\/\//).test(segmentUri)) { if (!(/^([A-z]*:)?\/\//).test(segmentUri)) {
// the segment URI is relative to the manifest // the segment URI is relative to the manifest
segmentUri = url.split('/').slice(0, -1).concat(segmentUri).join('/'); segmentUri = url.split('/').slice(0, -1).concat(segmentUri).join('/');
@ -61,15 +62,24 @@ videojs.plugin('hls', function(options) {
xhr.open('GET', segmentUri); xhr.open('GET', segmentUri);
xhr.responseType = 'arraybuffer'; xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function() { xhr.onreadystatechange = function() {
var elapsed;
if (xhr.readyState === 4) { 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)); segmentParser.parseSegmentBinaryData(new Uint8Array(xhr.response));
while (segmentParser.tagsAvailable()) { while (segmentParser.tagsAvailable()) {
player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes, player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes,
player); player);
} }
// update the segment index
player.hls.currentMediaIndex++;
} }
}; };
startTime = +new Date();
xhr.send(null); xhr.send(null);
}; };
player.on('loadedmetadata', fillBuffer); player.on('loadedmetadata', fillBuffer);
@ -102,6 +112,16 @@ videojs.plugin('hls', function(options) {
src: videojs.URL.createObjectURL(mediaSource), src: videojs.URL.createObjectURL(mediaSource),
type: "video/flv" 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); })(window, window.videojs);

25
test/videojs-hls_test.js

@ -42,6 +42,7 @@ module('HLS', {
manifestName = manifestName[1]; manifestName = manifestName[1];
} }
this.responseText = window.manifests[manifestName || xhrParams[1]]; this.responseText = window.manifests[manifestName || xhrParams[1]];
this.response = new Uint8Array([1]).buffer;
this.readyState = 4; this.readyState = 4;
this.onreadystatechange(); 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'); 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'); player.hls('manifest/absoluteUris.m3u8');
videojs.mediaSources[player.currentSrc()].trigger({ videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen' type: 'sourceopen'
@ -104,6 +105,28 @@ test('recognizes absolute URIs and uses them umnodified', function() {
'the first segment is requested'); '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', { module('segment controller', {
setup: function() { setup: function() {
segmentController = new window.videojs.hls.SegmentController(); segmentController = new window.videojs.hls.SegmentController();

Loading…
Cancel
Save