5a036701 by David LaPalomento

Merge pull request #89 from videojs/hotfix/bitrate-shifting

Hotfix/bitrate shifting
2 parents d8868f67 b65573ad
......@@ -250,8 +250,6 @@ module.exports = function(grunt) {
// Default task.
grunt.registerTask('default',
['clean',
'jshint',
'manifests-to-js',
'test',
'concat',
'uglify']);
......
......@@ -150,12 +150,21 @@
playlist = loader.master.playlists[playlist];
}
if (playlist.uri === media.uri) {
// switching to the currently active playlist is a no-op
// switch to fully loaded playlists immediately
if (loader.master.playlists[playlist.uri].endList) {
if (request) {
request.abort();
request = null;
}
loader.state = 'HAVE_METADATA';
media = playlist;
return;
}
// switching to the active playlist is a no-op
if (playlist.uri === media.uri) {
return;
}
loader.state = 'SWITCHING_MEDIA';
......
......@@ -348,9 +348,78 @@
'#EXT-X-ENDLIST\n');
loader.media('low.m3u8');
strictEqual(requests.length, 0, 'no requests is sent');
strictEqual(requests.length, 0, 'no requests are sent');
});
test('switching to the active live playlist is a no-op', function() {
var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
'low.m3u8\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=2\n' +
'high.m3u8\n');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n' +
'#EXTINF:10,\n' +
'low-0.ts\n');
loader.media('low.m3u8');
strictEqual(requests.length, 0, 'no requests are sent');
});
test('switches back to loaded playlists without re-requesting them', function() {
var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
'low.m3u8\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=2\n' +
'high.m3u8\n');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n' +
'#EXTINF:10,\n' +
'low-0.ts\n' +
'#EXT-X-ENDLIST\n');
loader.media('high.m3u8');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n' +
'#EXTINF:10,\n' +
'high-0.ts\n' +
'#EXT-X-ENDLIST\n');
loader.media('low.m3u8');
strictEqual(requests.length, 0, 'no outstanding requests');
strictEqual(loader.state, 'HAVE_METADATA', 'returned to loaded playlist');
});
test('aborts outstanding requests if switching back to an already loaded playlist', function() {
var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
'low.m3u8\n' +
'#EXT-X-STREAM-INF:BANDWIDTH=2\n' +
'high.m3u8\n');
requests.pop().respond(200, null,
'#EXTM3U\n' +
'#EXT-X-MEDIA-SEQUENCE:0\n' +
'#EXTINF:10,\n' +
'low-0.ts\n' +
'#EXT-X-ENDLIST\n');
loader.media('high.m3u8');
loader.media('low.m3u8');
strictEqual(requests.length, 1, 'requested high playlist');
ok(requests[0].aborted, 'aborted playlist request');
strictEqual(loader.state, 'HAVE_METADATA', 'returned to loaded playlist');
strictEqual(loader.media(), loader.master.playlists[0], 'switched to loaded playlist');
});
test('does not abort requests when the same playlist is re-requested', function() {
var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
requests.pop().respond(200, null,
......
......@@ -423,9 +423,8 @@ form label {
.line.bandwidth {
stroke: steelblue;
}
.line.buffered {
stroke: #2ca02c;
opacity: 0.25;
.line.effective-bandwidth {
stroke: #FF7F0E;
}
.line.bitrate {
stroke: #999;
......
......@@ -3,7 +3,7 @@
var segmentDuration = 9, // seconds
segmentCount = 100,
duration = segmentDuration * segmentCount,
propagationDelay = 1,
propagationDelay = 0.5,
runSimulation,
playlistResponse,
......@@ -86,6 +86,7 @@
runSimulation = function(options, done) {
var results = {
bandwidth: [],
effectiveBandwidth: [],
playlists: [],
buffered: [],
options: options
......@@ -207,6 +208,10 @@
request.status = 200;
request.response = new Uint8Array(segmentSize * 0.125);
request.setResponseBody('');
results.effectiveBandwidth.push({
time: Math.ceil(+new Date() * 0.001),
bandwidth: player.hls.bandwidth
});
}, ((remaining / value.bandwidth) + i) * 1000);
return false;
}
......@@ -266,7 +271,6 @@
displayTimeline = function(error, data) {
var x = d3.scale.linear().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y0 = d3.scale.linear().range([height, 0]),
timeAxis = d3.svg.axis().scale(x).orient('bottom'),
tickFormatter = d3.format(',.0f'),
......@@ -285,13 +289,13 @@
.y(function(data) {
return y(data.bandwidth);
}),
bufferedLine = d3.svg.line()
effectiveBandwidthLine = d3.svg.line()
.interpolate('basis')
.x(function(data) {
return x(data.time);
})
.y(function(data) {
return y0(data.buffered);
return y(data.bandwidth);
});
x.domain(d3.extent(data.bandwidth, function(data) {
......@@ -300,9 +304,6 @@
y.domain([0, Math.max(d3.max(data.bandwidth, function(data) {
return data.bandwidth;
}), d3.max(data.options.playlists))]);
y0.domain([0, d3.max(data.buffered, function(data) {
return data.buffered;
})]);
// time axis
svg.selectAll('.axis').remove();
......@@ -337,20 +338,22 @@
.datum(data.bandwidth)
.attr('class', 'line bandwidth')
.attr('d', bandwidthLine);
svg.selectAll('.effective-bandwidth').remove();
svg.append('path')
.datum(data.effectiveBandwidth)
.attr('class', 'line effective-bandwidth')
.attr('d', effectiveBandwidthLine);
svg.append('text')
.attr('class', 'bandwidth label')
.attr('transform', 'translate(' + x(x.range()[1]) + ', ' + y(data.bandwidth.slice(-1)[0].bandwidth) + ')')
.attr('dy', '1.35em')
.text('bandwidth');
// buffered line
svg.selectAll('.buffered').remove();
svg.append('path')
.datum(data.buffered)
.attr('class', 'line buffered')
.attr('y', 6)
.attr('d', bufferedLine);
svg.append('text')
.attr('class', 'bandwidth label')
.attr('transform', 'translate(' + x(x.range()[1]) + ', ' + y(data.effectiveBandwidth.slice(-1)[0].bandwidth) + ')')
.attr('dy', '1.35em')
.text('measured');
// segment bitrate dots
svg.selectAll('.segment-bitrate').remove();
......