1598394f by David LaPalomento

Only download one segment at a time

Check if there is a request in flight and don't perform buffer checks until it completes.
1 parent f2be83ef
......@@ -25,6 +25,7 @@ var
player = this,
url,
segmentXhr,
fillBuffer,
selectPlaylist;
......@@ -64,11 +65,15 @@ var
var
buffered = player.buffered(),
bufferedTime = 0,
xhr = new window.XMLHttpRequest(),
segment = player.hls.currentPlaylist.segments[player.hls.currentMediaIndex],
segmentUri,
startTime;
// if there is a request already in flight, do nothing
if (segmentXhr) {
return;
}
// if the video has finished downloading, stop trying to buffer
if (!segment) {
return;
......@@ -77,10 +82,10 @@ var
if (buffered) {
// assuming a single, contiguous buffer region
bufferedTime = player.buffered().end(0) - player.currentTime();
console.log('buffered time:', bufferedTime);
}
// if there is plenty of content in the buffer, relax for awhile
console.log('bufferedTime:', bufferedTime);
if (bufferedTime >= goalBufferLength) {
return;
}
......@@ -92,26 +97,29 @@ var
}
// request the next segment
xhr.open('GET', segmentUri);
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
segmentXhr = new window.XMLHttpRequest();
segmentXhr.open('GET', segmentUri);
segmentXhr.responseType = 'arraybuffer';
segmentXhr.onreadystatechange = function() {
if (segmentXhr.readyState === 4) {
// calculate the download bandwidth
player.hls.segmentRequestTime = (+new Date()) - startTime;
player.hls.bandwidth = xhr.response.byteLength / player.hls.segmentRequestTime;
player.hls.segmentXhrTime = (+new Date()) - startTime;
player.hls.bandwidth = segmentXhr.response.byteLength / player.hls.segmentXhrTime;
// transmux the segment data from M2TS to FLV
segmentParser.parseSegmentBinaryData(new Uint8Array(xhr.response));
segmentParser.parseSegmentBinaryData(new Uint8Array(segmentXhr.response));
while (segmentParser.tagsAvailable()) {
player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes,
player);
}
console.log('finished downloading segment ' + player.hls.currentMediaIndex);
segmentXhr = null;
player.hls.currentMediaIndex++;
}
};
startTime = +new Date();
xhr.send(null);
segmentXhr.send(null);
};
player.on('loadedmetadata', fillBuffer);
player.on('timeupdate', fillBuffer);
......
......@@ -145,8 +145,8 @@ test('calculates the bandwidth after downloading a segment', function() {
ok(player.hls.bandwidth, 'bandwidth is calculated');
ok(player.hls.bandwidth > 0,
'bandwidth is positive: ' + player.hls.bandwidth);
ok(player.hls.segmentRequestTime >= 0,
'saves segment request time: ' + player.hls.segmentRequestTime + 's');
ok(player.hls.segmentXhrTime >= 0,
'saves segment request time: ' + player.hls.segmentXhrTime + 's');
});
test('does not download the next segment if the buffer is full', function() {
......@@ -196,6 +196,26 @@ test('stops downloading segments at the end of the playlist', function() {
strictEqual(xhrParams, null, 'no request is made');
});
test('only makes one segment request at a time', function() {
var openedXhrs = 0;
player.hls('manifest/media.m3u8');
videojs.mediaSources[player.currentSrc()].trigger({
type: 'sourceopen'
});
// mock out a long-running XHR
window.XMLHttpRequest = function() {
this.send = function() {};
this.open = function() {
openedXhrs++;
};
};
player.trigger('timeupdate');
strictEqual(1, openedXhrs, 'one XHR is made');
player.trigger('timeupdate');
strictEqual(1, openedXhrs, 'only one XHR is made');
});
module('segment controller', {
setup: function() {
segmentController = new window.videojs.hls.SegmentController();
......