Add/fix tests related to segment annotation and fetching
Showing
4 changed files
with
101 additions
and
55 deletions
... | @@ -450,7 +450,7 @@ | ... | @@ -450,7 +450,7 @@ |
450 | break; | 450 | break; |
451 | } else { | 451 | } else { |
452 | knownStart = segment.end; | 452 | knownStart = segment.end; |
453 | startIndex = i; | 453 | startIndex = i + 1; |
454 | } | 454 | } |
455 | } | 455 | } |
456 | } | 456 | } |
... | @@ -494,9 +494,14 @@ | ... | @@ -494,9 +494,14 @@ |
494 | return i; | 494 | return i; |
495 | } | 495 | } |
496 | } | 496 | } |
497 | // We haven't found a segment so load the first one | 497 | |
498 | // We haven't found a segment so load the first one if time is zero | ||
499 | if (time === 0) { | ||
498 | return 0; | 500 | return 0; |
499 | } else { | 501 | } else { |
502 | return -1; | ||
503 | } | ||
504 | } else { | ||
500 | // We known nothing so walk from the front of the playlist, | 505 | // We known nothing so walk from the front of the playlist, |
501 | // subtracting durations until we find a segment that contains | 506 | // subtracting durations until we find a segment that contains |
502 | // time and return it | 507 | // time and return it | ... | ... |
... | @@ -10,8 +10,8 @@ var | ... | @@ -10,8 +10,8 @@ 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.2, | 12 | bandwidthVariance = 1.2, |
13 | blacklistDuration = 5 * 60 * 1000, // 2 minute blacklist | 13 | blacklistDuration = 5 * 60 * 1000, // 5 minute blacklist |
14 | TIME_FUDGE_FACTOR = 1 / 60, // Fudge factor to account for TimeRanges rounding | 14 | TIME_FUDGE_FACTOR = 1 / 30, // Fudge factor to account for TimeRanges rounding |
15 | Component = videojs.getComponent('Component'), | 15 | Component = videojs.getComponent('Component'), |
16 | 16 | ||
17 | // The amount of time to wait between checking the state of the buffer | 17 | // The amount of time to wait between checking the state of the buffer |
... | @@ -242,32 +242,52 @@ videojs.HlsHandler.prototype.handleSourceOpen = function() { | ... | @@ -242,32 +242,52 @@ videojs.HlsHandler.prototype.handleSourceOpen = function() { |
242 | } | 242 | } |
243 | }; | 243 | }; |
244 | 244 | ||
245 | // Search for any end-points in `update` that do not also exist | 245 | // Search for a likely end time for the segment that was just appened |
246 | // in `original`. | 246 | // based on the state of the `buffered` property before and after the |
247 | // append. | ||
247 | // If we found only one such uncommon end-point return it. | 248 | // If we found only one such uncommon end-point return it. |
248 | videojs.Hls.findSoleUncommonTimeRangesEnd_ = function(original, update) { | 249 | videojs.Hls.findSoleUncommonTimeRangesEnd_ = function(original, update) { |
249 | var result = [], originalEnds = []; | 250 | var |
250 | 251 | i, start, end, | |
251 | // if original or update are falsey, return an empty list of | 252 | result = [], |
252 | // additions | 253 | edges = [], |
253 | if (!original || !update) { | 254 | // In order to qualify as a possible candidate, the end point must: |
254 | return result; | 255 | // 1) Not have already existed in the `original` ranges |
255 | } | 256 | // 2) Not result from the shrinking of a range that already existed |
257 | // in the `original` ranges | ||
258 | // 3) Not be contained inside of a range that existed in `original` | ||
259 | checkEdges = function(span) { | ||
260 | return (span[0] <= end && span[1] > end) || span[1] === end; | ||
261 | }; | ||
256 | 262 | ||
257 | // Save all the end-points in the `original` TimeRanges object | 263 | if (original) { |
264 | // Save all the edges in the `original` TimeRanges object | ||
258 | for (i = 0; i < original.length; i++) { | 265 | for (i = 0; i < original.length; i++) { |
259 | originalEnds.push(original.end(i)); | 266 | start = original.start(i); |
267 | end = original.end(i); | ||
268 | |||
269 | edges.push([start, end]); | ||
270 | } | ||
260 | } | 271 | } |
261 | 272 | ||
273 | if (update) { | ||
262 | // Save any end-points in `update` that are not in the `original` | 274 | // Save any end-points in `update` that are not in the `original` |
263 | // TimeRanges object | 275 | // TimeRanges object |
264 | for (i = 0; i < update.length; i++) { | 276 | for (i = 0; i < update.length; i++) { |
265 | if (originalEnds.indexOf(update.end(i)) === -1) { | 277 | start = update.start(i); |
266 | result.push(update.end(i)); | 278 | end = update.end(i); |
279 | |||
280 | if (edges.some(checkEdges)) { | ||
281 | continue; | ||
282 | } | ||
283 | |||
284 | // at this point it must be a unique non-shrinking end edge | ||
285 | result.push(end); | ||
267 | } | 286 | } |
268 | } | 287 | } |
269 | 288 | ||
270 | // Return null if didn't find exactly one differing end-point | 289 | // we err on the side of caution and return null if didn't find |
290 | // exactly *one* differing end edge in the search above | ||
271 | if (result.length !== 1) { | 291 | if (result.length !== 1) { |
272 | return null; | 292 | return null; |
273 | } else { | 293 | } else { |
... | @@ -719,10 +739,6 @@ videojs.HlsHandler.prototype.checkBuffer_ = function() { | ... | @@ -719,10 +739,6 @@ videojs.HlsHandler.prototype.checkBuffer_ = function() { |
719 | * append bytes into the SourceBuffer. | 739 | * append bytes into the SourceBuffer. |
720 | */ | 740 | */ |
721 | videojs.HlsHandler.prototype.startCheckingBuffer_ = function() { | 741 | videojs.HlsHandler.prototype.startCheckingBuffer_ = function() { |
722 | // if the player ever stalls, check if there is video data available | ||
723 | // to append immediately | ||
724 | this.tech_.on('waiting', (this.drainBuffer).bind(this)); | ||
725 | |||
726 | this.checkBuffer_(); | 742 | this.checkBuffer_(); |
727 | }; | 743 | }; |
728 | 744 | ||
... | @@ -735,7 +751,6 @@ videojs.HlsHandler.prototype.stopCheckingBuffer_ = function() { | ... | @@ -735,7 +751,6 @@ videojs.HlsHandler.prototype.stopCheckingBuffer_ = function() { |
735 | window.clearTimeout(this.checkBufferTimeout_); | 751 | window.clearTimeout(this.checkBufferTimeout_); |
736 | this.checkBufferTimeout_ = null; | 752 | this.checkBufferTimeout_ = null; |
737 | } | 753 | } |
738 | this.tech_.off('waiting', this.drainBuffer); | ||
739 | }; | 754 | }; |
740 | 755 | ||
741 | var filterBufferedRanges = function(predicate) { | 756 | var filterBufferedRanges = function(predicate) { | ... | ... |
... | @@ -811,7 +811,7 @@ | ... | @@ -811,7 +811,7 @@ |
811 | '1001.ts\n' + | 811 | '1001.ts\n' + |
812 | '#EXTINF:5,\n' + | 812 | '#EXTINF:5,\n' + |
813 | '1002.ts\n'); | 813 | '1002.ts\n'); |
814 | loader.media().segments[0].start = 150; | 814 | loader.media().segments[0].end = 154; |
815 | 815 | ||
816 | equal(loader.getMediaIndexForTime_(0), -1, 'the lowest returned value is negative one'); | 816 | equal(loader.getMediaIndexForTime_(0), -1, 'the lowest returned value is negative one'); |
817 | equal(loader.getMediaIndexForTime_(45), -1, 'expired content returns negative one'); | 817 | equal(loader.getMediaIndexForTime_(45), -1, 'expired content returns negative one'); |
... | @@ -819,6 +819,7 @@ | ... | @@ -819,6 +819,7 @@ |
819 | equal(loader.getMediaIndexForTime_(50 + 100), 0, 'calculates the earliest available position'); | 819 | equal(loader.getMediaIndexForTime_(50 + 100), 0, 'calculates the earliest available position'); |
820 | equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment'); | 820 | equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment'); |
821 | equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment'); | 821 | equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment'); |
822 | equal(loader.getMediaIndexForTime_(50 + 100 + 4), 1, 'calculates within the second segment'); | ||
822 | equal(loader.getMediaIndexForTime_(50 + 100 + 4.5), 1, 'calculates within the second segment'); | 823 | equal(loader.getMediaIndexForTime_(50 + 100 + 4.5), 1, 'calculates within the second segment'); |
823 | equal(loader.getMediaIndexForTime_(50 + 100 + 6), 1, 'calculates within the second segment'); | 824 | equal(loader.getMediaIndexForTime_(50 + 100 + 6), 1, 'calculates within the second segment'); |
824 | }); | 825 | }); |
... | @@ -837,9 +838,9 @@ | ... | @@ -837,9 +838,9 @@ |
837 | loader.expired_ = 160; | 838 | loader.expired_ = 160; |
838 | // annotate the first segment with a start time | 839 | // annotate the first segment with a start time |
839 | // this number would be coming from the Source Buffer in practice | 840 | // this number would be coming from the Source Buffer in practice |
840 | loader.media().segments[0].start = 150; | 841 | loader.media().segments[0].end = 150; |
841 | 842 | ||
842 | equal(loader.getMediaIndexForTime_(151), 0, 'prefers the value on the first segment'); | 843 | equal(loader.getMediaIndexForTime_(149), 0, 'prefers the value on the first segment'); |
843 | 844 | ||
844 | clock.tick(10 * 1000); // trigger a playlist refresh | 845 | clock.tick(10 * 1000); // trigger a playlist refresh |
845 | requests.shift().respond(200, null, | 846 | requests.shift().respond(200, null, | ... | ... |
... | @@ -2745,47 +2745,72 @@ test('does not download segments if preload option set to none', function() { | ... | @@ -2745,47 +2745,72 @@ test('does not download segments if preload option set to none', function() { |
2745 | 2745 | ||
2746 | module('Buffer Inspection'); | 2746 | module('Buffer Inspection'); |
2747 | 2747 | ||
2748 | test('detects time range edges added by updates', function() { | 2748 | test('detects time range end-point changed by updates', function() { |
2749 | var edges; | 2749 | var edge; |
2750 | 2750 | ||
2751 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]), | 2751 | // Single-range changes |
2752 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]), | ||
2752 | videojs.createTimeRange([[0, 11]])); | 2753 | videojs.createTimeRange([[0, 11]])); |
2753 | deepEqual(edges, [{ end: 11 }], 'detected a forward addition'); | 2754 | strictEqual(edge, 11, 'detected a forward addition'); |
2754 | 2755 | ||
2755 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[5, 10]]), | 2756 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[5, 10]]), |
2756 | videojs.createTimeRange([[0, 10]])); | 2757 | videojs.createTimeRange([[0, 10]])); |
2757 | deepEqual(edges, [{ start: 0 }], 'detected a backward addition'); | 2758 | strictEqual(edge, null, 'ignores backward addition'); |
2758 | 2759 | ||
2759 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[5, 10]]), | 2760 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[5, 10]]), |
2760 | videojs.createTimeRange([[0, 11]])); | 2761 | videojs.createTimeRange([[0, 11]])); |
2761 | deepEqual(edges, [ | 2762 | strictEqual(edge, 11, 'detected a forward addition & ignores a backward addition'); |
2762 | { start: 0 }, { end: 11 } | ||
2763 | ], 'detected forward and backward additions'); | ||
2764 | 2763 | ||
2765 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]), | 2764 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]), |
2766 | videojs.createTimeRange([[0, 10]])); | 2765 | videojs.createTimeRange([[0, 9]])); |
2767 | deepEqual(edges, [], 'detected no addition'); | 2766 | strictEqual(edge, null, 'ignores a backwards addition resulting from a shrinking range'); |
2768 | 2767 | ||
2769 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([]), | 2768 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]), |
2770 | videojs.createTimeRange([[0, 10]])); | 2769 | videojs.createTimeRange([[2, 7]])); |
2771 | deepEqual(edges, [ | 2770 | strictEqual(edge, null, 'ignores a forward & backwards addition resulting from a shrinking range'); |
2772 | { start: 0 }, | ||
2773 | { end: 10 } | ||
2774 | ], 'detected an initial addition'); | ||
2775 | 2771 | ||
2776 | edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]), | 2772 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[2, 10]]), |
2777 | videojs.createTimeRange([[0, 10], [20, 30]])); | 2773 | videojs.createTimeRange([[0, 7]])); |
2778 | deepEqual(edges, [ | 2774 | strictEqual(edge, null, 'ignores a forward & backwards addition resulting from a range shifted backward'); |
2779 | { start: 20 }, | 2775 | |
2780 | { end: 30} | 2776 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[2, 10]]), |
2781 | ], 'detected a non-contiguous addition'); | 2777 | videojs.createTimeRange([[5, 15]])); |
2782 | }); | 2778 | strictEqual(edge, 15, 'detected a forwards addition resulting from a range shifted foward'); |
2779 | |||
2780 | // Multiple-range changes | ||
2781 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]), | ||
2782 | videojs.createTimeRange([[0, 11], [12, 15]])); | ||
2783 | strictEqual(edge, null, 'ignores multiple new forward additions'); | ||
2784 | |||
2785 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]), | ||
2786 | videojs.createTimeRange([[20, 50]])); | ||
2787 | strictEqual(edge, 50, 'detected a forward addition & ignores range removal'); | ||
2788 | |||
2789 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]), | ||
2790 | videojs.createTimeRange([[0, 50]])); | ||
2791 | strictEqual(edge, 50, 'detected a forward addition & ignores merges'); | ||
2792 | |||
2793 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]), | ||
2794 | videojs.createTimeRange([[0, 40]])); | ||
2795 | strictEqual(edge, null, 'ignores merges'); | ||
2796 | |||
2797 | // Empty input | ||
2798 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange(), | ||
2799 | videojs.createTimeRange([[0, 11]])); | ||
2800 | strictEqual(edge, 11, 'handle an empty original TimeRanges object'); | ||
2801 | |||
2802 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 11]]), | ||
2803 | videojs.createTimeRange()); | ||
2804 | strictEqual(edge, null, 'handle an empty update TimeRanges object'); | ||
2783 | 2805 | ||
2784 | test('treats null buffered ranges as no addition', function() { | 2806 | // Null input |
2785 | var edges = videojs.Hls.bufferedAdditions_(null, | 2807 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(null, |
2786 | videojs.createTimeRange([[0, 11]])); | 2808 | videojs.createTimeRange([[0, 11]])); |
2809 | strictEqual(edge, 11, 'treat null original buffer as an empty TimeRanges object'); | ||
2787 | 2810 | ||
2788 | equal(edges.length, 0, 'no additions'); | 2811 | edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 11]]), |
2812 | null); | ||
2813 | strictEqual(edge, null, 'treat null update buffer as an empty TimeRanges object'); | ||
2789 | }); | 2814 | }); |
2790 | 2815 | ||
2791 | })(window, window.videojs); | 2816 | })(window, window.videojs); | ... | ... |
-
Please register or sign in to post a comment