46460d84 by Gary Katsevman

Delay fillBuffer. Upshift if dl time less than 1s.

Only set up timeupdate and waiting event listeners for fillBuffer and
drainBuffer after we have upshifted. This is so that we would download
the first segment of the new playlist if the player is setup with
autoplay or a user clicks play too early.
Also, we should only upshift if our estimated download time for the new
segment is less than one second. This is done by estimating the duration
length of the segment of the new playlist with the duration of the
current segment in the current playlist.
1 parent 9d190d3e
...@@ -109,41 +109,40 @@ videojs.Hls.prototype.handleSourceOpen = function() { ...@@ -109,41 +109,40 @@ videojs.Hls.prototype.handleSourceOpen = function() {
109 this.playlists = new videojs.Hls.PlaylistLoader(this.src_, settings.withCredentials); 109 this.playlists = new videojs.Hls.PlaylistLoader(this.src_, settings.withCredentials);
110 110
111 this.playlists.on('loadedmetadata', videojs.bind(this, function() { 111 this.playlists.on('loadedmetadata', videojs.bind(this, function() {
112 var selectedPlaylist, loaderHandler; 112 var selectedPlaylist, loaderHandler, newBitrate, segmentDuration,
113 segmentDlTime, setupEvents;
113 114
114 oldMediaPlaylist = this.playlists.media(); 115 setupEvents = function() {
116 this.fillBuffer();
115 117
116 if (this.bandwidth !== this.playlists.bandwidth) { 118 // periodically check if new data needs to be downloaded or
117 if (this.bandwidth === undefined || this.bandwidth !== undefined && this.bandwidth < this.playlists.bandwidth) { 119 // buffered data should be appended to the source buffer
118 this.bandwidth = this.playlists.bandwidth; 120 player.on('timeupdate', videojs.bind(this, this.fillBuffer));
121 player.on('timeupdate', videojs.bind(this, this.drainBuffer));
122 player.on('waiting', videojs.bind(this, this.drainBuffer));
119 123
124 player.trigger('loadedmetadata');
125 };
126
127 oldMediaPlaylist = this.playlists.media();
128 this.bandwidth = this.playlists.bandwidth;
120 selectedPlaylist = this.selectPlaylist(); 129 selectedPlaylist = this.selectPlaylist();
121 if (selectedPlaylist === oldMediaPlaylist) { 130 newBitrate = selectedPlaylist.attributes && selectedPlaylist.attributes.BANDWIDTH;
122 this.fillBuffer(); 131 segmentDuration = oldMediaPlaylist.segments[this.mediaIndex].duration ||
123 } else { 132 oldMediaPlaylist.targetDuration;
133
134 segmentDlTime = (segmentDuration * newBitrate) / this.bandwidth;
135
136 if (segmentDlTime <= 1) {
124 this.playlists.media(selectedPlaylist); 137 this.playlists.media(selectedPlaylist);
125 loaderHandler = videojs.bind(this, function() { 138 loaderHandler = videojs.bind(this, function() {
126 this.fillBuffer(); 139 setupEvents.call(this);
127 this.playlists.off('loadedplaylist', loaderHandler); 140 this.playlists.off('loadedplaylist', loaderHandler);
128 }); 141 });
129 this.playlists.on('loadedplaylist', loaderHandler); 142 this.playlists.on('loadedplaylist', loaderHandler);
130 }
131 } else {
132 this.fillBuffer();
133 }
134 } else { 143 } else {
135 this.fillBuffer(); 144 setupEvents.call(this);
136 } 145 }
137
138 player.one('play', videojs.bind(this, this.fillBuffer));
139
140 // periodically check if new data needs to be downloaded or
141 // buffered data should be appended to the source buffer
142 player.on('timeupdate', videojs.bind(this, this.fillBuffer));
143 player.on('timeupdate', videojs.bind(this, this.drainBuffer));
144 player.on('waiting', videojs.bind(this, this.drainBuffer));
145
146 player.trigger('loadedmetadata');
147 })); 146 }));
148 147
149 this.playlists.on('error', videojs.bind(this, function() { 148 this.playlists.on('error', videojs.bind(this, function() {
......