Merge pull request #439 from videojs/fix-fetcher
Minor fixes to fetcher
Showing
3 changed files
with
83 additions
and
75 deletions
... | @@ -141,9 +141,7 @@ | ... | @@ -141,9 +141,7 @@ |
141 | // https://tools.ietf.org/html/draft-pantos-http-live-streaming-16#section-6.3.3 | 141 | // https://tools.ietf.org/html/draft-pantos-http-live-streaming-16#section-6.3.3 |
142 | start = intervalDuration(playlist, playlist.mediaSequence); | 142 | start = intervalDuration(playlist, playlist.mediaSequence); |
143 | end = intervalDuration(playlist, | 143 | end = intervalDuration(playlist, |
144 | playlist.mediaSequence + playlist.segments.length); | 144 | playlist.mediaSequence + Math.max(0, playlist.segments.length - 3)); |
145 | end -= (playlist.targetDuration || DEFAULT_TARGET_DURATION) * 3; | ||
146 | end = Math.max(0, end); | ||
147 | return videojs.createTimeRange(start, end); | 145 | return videojs.createTimeRange(start, end); |
148 | }; | 146 | }; |
149 | 147 | ... | ... |
... | @@ -9,14 +9,15 @@ | ... | @@ -9,14 +9,15 @@ |
9 | var | 9 | var |
10 | // a fudge factor to apply to advertised playlist bitrates to account for | 10 | // a fudge factor to apply to advertised playlist bitrates to account for |
11 | // temporary flucations in client bandwidth | 11 | // temporary flucations in client bandwidth |
12 | bandwidthVariance = 1.1, | 12 | bandwidthVariance = 1.2, |
13 | Component = videojs.getComponent('Component'), | 13 | Component = videojs.getComponent('Component'), |
14 | 14 | ||
15 | // the amount of time to wait between checking the state of the buffer | 15 | // the amount of time to wait between checking the state of the buffer |
16 | bufferCheckInterval = 500, | 16 | bufferCheckInterval = 500, |
17 | 17 | ||
18 | keyFailed, | 18 | keyFailed, |
19 | resolveUrl; | 19 | resolveUrl, |
20 | TIME_FUDGE_FACTOR = 1 / 60; | ||
20 | 21 | ||
21 | // returns true if a key has failed to download within a certain amount of retries | 22 | // returns true if a key has failed to download within a certain amount of retries |
22 | keyFailed = function(key) { | 23 | keyFailed = function(key) { |
... | @@ -396,72 +397,7 @@ videojs.HlsHandler.prototype.setupSourceBuffer_ = function() { | ... | @@ -396,72 +397,7 @@ videojs.HlsHandler.prototype.setupSourceBuffer_ = function() { |
396 | 397 | ||
397 | // transition the sourcebuffer to the ended state if we've hit the end of | 398 | // transition the sourcebuffer to the ended state if we've hit the end of |
398 | // the playlist | 399 | // the playlist |
399 | this.sourceBuffer.addEventListener('updateend', function() { | 400 | this.sourceBuffer.addEventListener('updateend', this.updateEndHandler_.bind(this)); |
400 | var | ||
401 | segmentInfo = this.pendingSegment_, | ||
402 | segment, | ||
403 | segments, | ||
404 | playlist, | ||
405 | currentMediaIndex, | ||
406 | currentBuffered, | ||
407 | timelineUpdates; | ||
408 | |||
409 | this.pendingSegment_ = null; | ||
410 | |||
411 | // stop here if the update errored or was aborted | ||
412 | if (!segmentInfo) { | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | playlist = this.playlists.media(); | ||
417 | segments = playlist.segments; | ||
418 | currentMediaIndex = segmentInfo.mediaIndex + (segmentInfo.mediaSequence - playlist.mediaSequence); | ||
419 | currentBuffered = this.findCurrentBuffered_(); | ||
420 | |||
421 | // if we switched renditions don't try to add segment timeline | ||
422 | // information to the playlist | ||
423 | if (segmentInfo.playlist.uri !== this.playlists.media().uri) { | ||
424 | return this.fillBuffer(); | ||
425 | } | ||
426 | |||
427 | // annotate the segment with any start and end time information | ||
428 | // added by the media processing | ||
429 | segment = playlist.segments[currentMediaIndex]; | ||
430 | |||
431 | timelineUpdates = videojs.Hls.bufferedAdditions_(segmentInfo.buffered, | ||
432 | this.tech_.buffered()); | ||
433 | |||
434 | timelineUpdates.forEach(function (update) { | ||
435 | if (segment) { | ||
436 | if (update.end !== undefined) { | ||
437 | segment.end = update.end; | ||
438 | } | ||
439 | } | ||
440 | }); | ||
441 | |||
442 | // if we've buffered to the end of the video, let the MediaSource know | ||
443 | if (this.playlists.media().endList && | ||
444 | currentBuffered.length && | ||
445 | segments[segments.length - 1].end <= currentBuffered.end(0) && | ||
446 | this.mediaSource.readyState === 'open') { | ||
447 | this.mediaSource.endOfStream(); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | if (timelineUpdates.length) { | ||
452 | this.updateDuration(playlist); | ||
453 | // check if it's time to download the next segment | ||
454 | this.fillBuffer(); | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | // the last segment append must have been entirely in the | ||
459 | // already buffered time ranges. just buffer forward until we | ||
460 | // find a segment that adds to the buffered time ranges and | ||
461 | // improves subsequent media index calculations. | ||
462 | this.fillBuffer(currentMediaIndex + 1); | ||
463 | return; | ||
464 | }.bind(this)); | ||
465 | }; | 401 | }; |
466 | 402 | ||
467 | /** | 403 | /** |
... | @@ -540,6 +476,11 @@ videojs.HlsHandler.prototype.setCurrentTime = function(currentTime) { | ... | @@ -540,6 +476,11 @@ videojs.HlsHandler.prototype.setCurrentTime = function(currentTime) { |
540 | return currentTime; | 476 | return currentTime; |
541 | } | 477 | } |
542 | 478 | ||
479 | // if we are in the middle of appending a segment, let it finish up | ||
480 | if (this.pendingSegment_ && this.pendingSegment_.buffered) { | ||
481 | return currentTime; | ||
482 | } | ||
483 | |||
543 | this.lastSegmentLoaded_ = null; | 484 | this.lastSegmentLoaded_ = null; |
544 | 485 | ||
545 | // cancel outstanding requests and buffer appends | 486 | // cancel outstanding requests and buffer appends |
... | @@ -640,6 +581,7 @@ videojs.HlsHandler.prototype.cancelSegmentXhr = function() { | ... | @@ -640,6 +581,7 @@ videojs.HlsHandler.prototype.cancelSegmentXhr = function() { |
640 | this.segmentXhr_.abort(); | 581 | this.segmentXhr_.abort(); |
641 | this.segmentXhr_ = null; | 582 | this.segmentXhr_ = null; |
642 | } | 583 | } |
584 | |||
643 | // clear out the segment being processed | 585 | // clear out the segment being processed |
644 | this.pendingSegment_ = null; | 586 | this.pendingSegment_ = null; |
645 | }; | 587 | }; |
... | @@ -828,8 +770,8 @@ videojs.HlsHandler.prototype.findCurrentBuffered_ = function() { | ... | @@ -828,8 +770,8 @@ videojs.HlsHandler.prototype.findCurrentBuffered_ = function() { |
828 | if (buffered && buffered.length) { | 770 | if (buffered && buffered.length) { |
829 | // Search for a range containing the play-head | 771 | // Search for a range containing the play-head |
830 | for (i = 0; i < buffered.length; i++) { | 772 | for (i = 0; i < buffered.length; i++) { |
831 | if (buffered.start(i) <= currentTime && | 773 | if (buffered.start(i) - TIME_FUDGE_FACTOR <= currentTime && |
832 | buffered.end(i) >= currentTime) { | 774 | buffered.end(i) + TIME_FUDGE_FACTOR >= currentTime) { |
833 | ranges = videojs.createTimeRanges(buffered.start(i), buffered.end(i)); | 775 | ranges = videojs.createTimeRanges(buffered.start(i), buffered.end(i)); |
834 | ranges.indexOf = i; | 776 | ranges.indexOf = i; |
835 | return ranges; | 777 | return ranges; |
... | @@ -1143,6 +1085,74 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) { | ... | @@ -1143,6 +1085,74 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) { |
1143 | this.sourceBuffer.appendBuffer(bytes); | 1085 | this.sourceBuffer.appendBuffer(bytes); |
1144 | }; | 1086 | }; |
1145 | 1087 | ||
1088 | videojs.HlsHandler.prototype.updateEndHandler_ = function () { | ||
1089 | var | ||
1090 | segmentInfo = this.pendingSegment_, | ||
1091 | segment, | ||
1092 | segments, | ||
1093 | playlist, | ||
1094 | currentMediaIndex, | ||
1095 | currentBuffered, | ||
1096 | timelineUpdates; | ||
1097 | |||
1098 | this.pendingSegment_ = null; | ||
1099 | |||
1100 | // stop here if the update errored or was aborted | ||
1101 | if (!segmentInfo) { | ||
1102 | return; | ||
1103 | } | ||
1104 | |||
1105 | playlist = this.playlists.media(); | ||
1106 | segments = playlist.segments; | ||
1107 | currentMediaIndex = segmentInfo.mediaIndex + (segmentInfo.mediaSequence - playlist.mediaSequence); | ||
1108 | currentBuffered = this.findCurrentBuffered_(); | ||
1109 | |||
1110 | // if we switched renditions don't try to add segment timeline | ||
1111 | // information to the playlist | ||
1112 | if (segmentInfo.playlist.uri !== this.playlists.media().uri) { | ||
1113 | return this.fillBuffer(); | ||
1114 | } | ||
1115 | |||
1116 | // annotate the segment with any start and end time information | ||
1117 | // added by the media processing | ||
1118 | segment = playlist.segments[currentMediaIndex]; | ||
1119 | |||
1120 | timelineUpdates = videojs.Hls.bufferedAdditions_(segmentInfo.buffered, | ||
1121 | this.tech_.buffered()); | ||
1122 | |||
1123 | timelineUpdates.forEach(function (update) { | ||
1124 | if (segment) { | ||
1125 | if (update.end !== undefined) { | ||
1126 | segment.end = update.end; | ||
1127 | } | ||
1128 | } | ||
1129 | }); | ||
1130 | |||
1131 | // if we've buffered to the end of the video, let the MediaSource know | ||
1132 | if (this.playlists.media().endList && | ||
1133 | currentBuffered.length && | ||
1134 | segments[segments.length - 1].end <= currentBuffered.end(0) && | ||
1135 | this.mediaSource.readyState === 'open') { | ||
1136 | this.mediaSource.endOfStream(); | ||
1137 | return; | ||
1138 | } | ||
1139 | |||
1140 | if (timelineUpdates.length || | ||
1141 | segmentInfo.buffered.length !== this.tech_.buffered().length) { | ||
1142 | this.updateDuration(playlist); | ||
1143 | // check if it's time to download the next segment | ||
1144 | this.fillBuffer(); | ||
1145 | return; | ||
1146 | } | ||
1147 | |||
1148 | // the last segment append must have been entirely in the | ||
1149 | // already buffered time ranges. just buffer forward until we | ||
1150 | // find a segment that adds to the buffered time ranges and | ||
1151 | // improves subsequent media index calculations. | ||
1152 | this.fillBuffer(currentMediaIndex + 1); | ||
1153 | return; | ||
1154 | }; | ||
1155 | |||
1146 | /** | 1156 | /** |
1147 | * Attempt to retrieve the key for a particular media segment. | 1157 | * Attempt to retrieve the key for a particular media segment. |
1148 | */ | 1158 | */ | ... | ... |
... | @@ -381,8 +381,8 @@ | ... | @@ -381,8 +381,8 @@ |
381 | }); | 381 | }); |
382 | equal(seekable.start(0), 0, 'starts at the earliest available segment'); | 382 | equal(seekable.start(0), 0, 'starts at the earliest available segment'); |
383 | equal(seekable.end(0), | 383 | equal(seekable.end(0), |
384 | 9 - (2 * 3), | 384 | 9 - (2 + 2 + 1), |
385 | 'allows seeking no further than three target durations from the end'); | 385 | 'allows seeking no further than three segments from the end'); |
386 | }); | 386 | }); |
387 | 387 | ||
388 | })(window, window.videojs); | 388 | })(window, window.videojs); | ... | ... |
-
Please register or sign in to post a comment