64bbbe93 by David LaPalomento

@dmlap quicker quality switches when bandwidth changes. Closes #285.

2 parents 93d4e050 54977aa4
......@@ -10,6 +10,7 @@ CHANGELOG
* @mikrohard: Trim whitespace in playlist. ([view](https://github.com/videojs/videojs-contrib-hls/pull/282))
* @dmlap add a contrib option to merge PRs without squashing ([view](https://github.com/videojs/videojs-contrib-hls/pull/287))
* @mikrohard allow playback of TS files with NITs. Don't warn about PCR PIDs. ([view](https://github.com/videojs/videojs-contrib-hls/pull/284))
* @dmlap quicker quality switches when bandwidth changes. ([view](https://github.com/videojs/videojs-contrib-hls/pull/285))
--------------------
......
......@@ -315,6 +315,12 @@ videojs.Hls.prototype.setCurrentTime = function(currentTime) {
return 0;
}
// it's clearly an edge-case but don't thrown an error if asked to
// seek within an empty playlist
if (!this.playlists.media().segments) {
return 0;
}
// save the seek target so currentTime can report it correctly
// while the seek is pending
this.lastSeekedTime_ = currentTime;
......@@ -578,6 +584,11 @@ videojs.Hls.prototype.fillBuffer = function(offset) {
return;
}
// if a playlist switch is in progress, wait for it to finish
if (this.playlists.state === 'SWITCHING_MEDIA') {
return;
}
// if the video has finished downloading, stop trying to buffer
segment = this.playlists.media().segments[this.mediaIndex];
if (!segment) {
......
......@@ -976,6 +976,35 @@ test('only appends one segment at a time', function() {
equal(appends, 0, 'did not append while updating');
});
test('waits to download new segments until the media playlist is stable', function() {
var media;
player.src({
src: 'manifest/master.m3u8',
type: 'application/vnd.apple.mpegurl'
});
openMediaSource(player);
standardXHRResponse(requests.shift()); // master
player.hls.bandwidth = 1; // make sure we stay on the lowest variant
standardXHRResponse(requests.shift()); // media
// mock a playlist switch
media = player.hls.playlists.media();
player.hls.playlists.media = function() {
return media;
};
player.hls.playlists.state = 'SWITCHING_MEDIA';
standardXHRResponse(requests.shift()); // segment 0
equal(requests.length, 0, 'no requests outstanding');
player.hls.checkBuffer_();
equal(requests.length, 0, 'delays segment fetching');
player.hls.playlists.state = 'LOADED_METADATA';
player.hls.checkBuffer_();
equal(requests.length, 1, 'resumes segment fetching');
});
test('cancels outstanding XHRs when seeking', function() {
player.src({
src: 'manifest/media.m3u8',
......@@ -1321,6 +1350,19 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () {
equal(4, player.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_ABORTED');
});
test('seeking in an empty playlist is a non-erroring noop', function() {
player.src({
src: 'manifest/empty-live.m3u8',
type: 'application/vnd.apple.mpegurl'
});
openMediaSource(player);
requests.shift().respond(200, null, '#EXTM3U\n');
player.currentTime(183);
equal(player.currentTime(), 0, 'remains at time zero');
});
test('duration is Infinity for live playlists', function() {
player.src({
src: 'http://example.com/manifest/missingEndlist.m3u8',
......