9e12846d by David LaPalomento

Wait until the player is ready to set the source. Capture the target time during seeks.

Opening the media source before the player is fully initialized would result in loadstart happening too early and the big play button getting stuck over the player. The video element should report the desired currentTime while a seek is pending, so store this value when currentTime is set and return it until a seek completes successfully.
1 parent dc2fa763
...@@ -183,21 +183,31 @@ var ...@@ -183,21 +183,31 @@ var
183 initSource = function(player, mediaSource, srcUrl) { 183 initSource = function(player, mediaSource, srcUrl) {
184 var 184 var
185 segmentParser = new videojs.Hls.SegmentParser(), 185 segmentParser = new videojs.Hls.SegmentParser(),
186 settings = videojs.util.mergeOptions({}, player.options().hls),
186 187
188 lastSeekedTime,
187 segmentXhr, 189 segmentXhr,
188 settings = videojs.util.mergeOptions({}, player.options().hls),
189 fillBuffer, 190 fillBuffer,
190 updateDuration; 191 updateDuration;
191 192
192 193
193 player.hls.currentTime = function(currentTime) { 194 player.hls.currentTime = function() {
194 if (currentTime === undefined) { 195 if (lastSeekedTime) {
195 return this.el().vjs_getProperty('currentTime'); 196 return lastSeekedTime;
196 } 197 }
197 198 return this.el().vjs_getProperty('currentTime');
199 };
200 player.hls.setCurrentTime = function(currentTime) {
198 if (!(this.playlists && this.playlists.media())) { 201 if (!(this.playlists && this.playlists.media())) {
202 // return immediately if the metadata is not ready yet
199 return 0; 203 return 0;
200 } 204 }
205
206 // save the seek target so currentTime can report it correctly
207 // while the seek is pending
208 lastSeekedTime = currentTime;
209
210 // determine the requested segment
201 this.mediaIndex = 211 this.mediaIndex =
202 getMediaIndexByTime(this.playlists.media(), currentTime); 212 getMediaIndexByTime(this.playlists.media(), currentTime);
203 213
...@@ -330,8 +340,9 @@ var ...@@ -330,8 +340,9 @@ var
330 bufferedTime = player.buffered().end(0) - player.currentTime(); 340 bufferedTime = player.buffered().end(0) - player.currentTime();
331 } 341 }
332 342
333 // if there is plenty of content in the buffer, relax for awhile 343 // if there is plenty of content in the buffer and we're not
334 if (bufferedTime >= goalBufferLength) { 344 // seeking, relax for awhile
345 if (typeof offset !== 'number' && bufferedTime >= goalBufferLength) {
335 return; 346 return;
336 } 347 }
337 348
...@@ -382,10 +393,15 @@ var ...@@ -382,10 +393,15 @@ var
382 // if we're refilling the buffer after a seek, scan through the muxed 393 // if we're refilling the buffer after a seek, scan through the muxed
383 // FLV tags until we find the one that is closest to the desired 394 // FLV tags until we find the one that is closest to the desired
384 // playback time 395 // playback time
385 if (offset !== undefined && typeof offset === "number") { 396 if (typeof offset === 'number') {
386 while (segmentParser.getTags()[0].pts < offset) { 397 while (segmentParser.getTags()[0].pts < offset) {
387 segmentParser.getNextTag(); 398 segmentParser.getNextTag();
388 } 399 }
400
401 // tell the SWF where we will be seeking to
402 player.hls.el().vjs_setProperty('currentTime',
403 segmentParser.getTags()[0].pts * 0.001);
404 lastSeekedTime = null;
389 } 405 }
390 406
391 while (segmentParser.tagsAvailable()) { 407 while (segmentParser.tagsAvailable()) {
...@@ -473,6 +489,7 @@ videojs.Hls = videojs.Flash.extend({ ...@@ -473,6 +489,7 @@ videojs.Hls = videojs.Flash.extend({
473 videojs.Hls.prototype.src = function(src) { 489 videojs.Hls.prototype.src = function(src) {
474 var 490 var
475 player = this.player(), 491 player = this.player(),
492 self = this,
476 mediaSource, 493 mediaSource,
477 source; 494 source;
478 495
...@@ -484,8 +501,8 @@ videojs.Hls.prototype.src = function(src) { ...@@ -484,8 +501,8 @@ videojs.Hls.prototype.src = function(src) {
484 }; 501 };
485 this.mediaSource = mediaSource; 502 this.mediaSource = mediaSource;
486 initSource(player, mediaSource, src); 503 initSource(player, mediaSource, src);
487 this.ready(function() { 504 this.player().ready(function() {
488 this.el().vjs_src(source.src); 505 self.el().vjs_src(source.src);
489 }); 506 });
490 } 507 }
491 }; 508 };
......
...@@ -49,6 +49,7 @@ var ...@@ -49,6 +49,7 @@ var
49 49
50 tech = player.el().querySelector('.vjs-tech'); 50 tech = player.el().querySelector('.vjs-tech');
51 tech.vjs_getProperty = function() {}; 51 tech.vjs_getProperty = function() {};
52 tech.vjs_setProperty = function() {};
52 tech.vjs_src = function() {}; 53 tech.vjs_src = function() {};
53 videojs.Flash.onReady(tech.id); 54 videojs.Flash.onReady(tech.id);
54 55
...@@ -654,6 +655,7 @@ test('does not download the next segment if the buffer is full', function() { ...@@ -654,6 +655,7 @@ test('does not download the next segment if the buffer is full', function() {
654 655
655 player.trigger('timeupdate'); 656 player.trigger('timeupdate');
656 657
658 console.log(requests);
657 strictEqual(requests.length, 1, 'no segment request was made'); 659 strictEqual(requests.length, 1, 'no segment request was made');
658 }); 660 });
659 661
...@@ -754,7 +756,7 @@ test('cancels outstanding XHRs when seeking', function() { ...@@ -754,7 +756,7 @@ test('cancels outstanding XHRs when seeking', function() {
754 // trigger a segment download request 756 // trigger a segment download request
755 player.trigger('timeupdate'); 757 player.trigger('timeupdate');
756 // attempt to seek while the download is in progress 758 // attempt to seek while the download is in progress
757 player.hls.currentTime(7); 759 player.currentTime(7);
758 760
759 ok(requests[1].aborted, 'XHR aborted'); 761 ok(requests[1].aborted, 'XHR aborted');
760 strictEqual(requests.length, 3, 'opened new XHR'); 762 strictEqual(requests.length, 3, 'opened new XHR');
...@@ -830,7 +832,7 @@ test('drops tags before the target timestamp when seeking', function() { ...@@ -830,7 +832,7 @@ test('drops tags before the target timestamp when seeking', function() {
830 bytes: i 832 bytes: i
831 }); 833 });
832 } 834 }
833 player.hls.currentTime(7); 835 player.currentTime(7);
834 standardXHRResponse(requests[2]); 836 standardXHRResponse(requests[2]);
835 837
836 while (callbacks.length) { 838 while (callbacks.length) {
...@@ -876,7 +878,7 @@ test('clears pending buffer updates when seeking', function() { ...@@ -876,7 +878,7 @@ test('clears pending buffer updates when seeking', function() {
876 878
877 // seek to 7s 879 // seek to 7s
878 tags.push({ pts: 7000, bytes: 7 }); 880 tags.push({ pts: 7000, bytes: 7 });
879 player.hls.currentTime(7); 881 player.currentTime(7);
880 standardXHRResponse(requests[2]); 882 standardXHRResponse(requests[2]);
881 883
882 while (callbacks.length) { 884 while (callbacks.length) {
......