Merge pull request #389 from videojs/discontinuity
Discontinuity
Showing
5 changed files
with
466 additions
and
289 deletions
... | @@ -44,11 +44,11 @@ | ... | @@ -44,11 +44,11 @@ |
44 | "karma-sauce-launcher": "~0.1.8", | 44 | "karma-sauce-launcher": "~0.1.8", |
45 | "qunitjs": "^1.18.0", | 45 | "qunitjs": "^1.18.0", |
46 | "sinon": "1.10.2", | 46 | "sinon": "1.10.2", |
47 | "video.js": "^5.0.0-rc.51" | 47 | "video.js": "^5.0.0-rc.96" |
48 | }, | 48 | }, |
49 | "dependencies": { | 49 | "dependencies": { |
50 | "pkcs7": "^0.2.2", | 50 | "pkcs7": "^0.2.2", |
51 | "videojs-contrib-media-sources": "videojs/videojs-contrib-media-sources.git#mse-mp2t-polyfill", | 51 | "videojs-contrib-media-sources": "videojs/videojs-contrib-media-sources.git#mse-mp2t-polyfill", |
52 | "videojs-swf": "5.0.0-rc0" | 52 | "videojs-swf": "5.0.0-rc1" |
53 | } | 53 | } |
54 | } | 54 | } | ... | ... |
... | @@ -24,8 +24,8 @@ keyFailed = function(key) { | ... | @@ -24,8 +24,8 @@ keyFailed = function(key) { |
24 | return key.retries && key.retries >= 2; | 24 | return key.retries && key.retries >= 2; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | videojs.Hls = videojs.extends(Component, { | 27 | videojs.Hls = videojs.extend(Component, { |
28 | constructor: function(tech, source) { | 28 | constructor: function(tech, options) { |
29 | var self = this, _player; | 29 | var self = this, _player; |
30 | 30 | ||
31 | Component.call(this, tech); | 31 | Component.call(this, tech); |
... | @@ -44,7 +44,8 @@ videojs.Hls = videojs.extends(Component, { | ... | @@ -44,7 +44,8 @@ videojs.Hls = videojs.extends(Component, { |
44 | } | 44 | } |
45 | } | 45 | } |
46 | this.tech_ = tech; | 46 | this.tech_ = tech; |
47 | this.source_ = source; | 47 | this.source_ = options.source; |
48 | this.mode_ = options.mode; | ||
48 | this.bytesReceived = 0; | 49 | this.bytesReceived = 0; |
49 | 50 | ||
50 | // loadingState_ tracks how far along the buffering process we | 51 | // loadingState_ tracks how far along the buffering process we |
... | @@ -87,7 +88,8 @@ videojs.Hls.canPlaySource = function() { | ... | @@ -87,7 +88,8 @@ videojs.Hls.canPlaySource = function() { |
87 | * the browser it is running in. It is not necessary to use or modify | 88 | * the browser it is running in. It is not necessary to use or modify |
88 | * this object in normal usage. | 89 | * this object in normal usage. |
89 | */ | 90 | */ |
90 | videojs.HlsSourceHandler = { | 91 | videojs.HlsSourceHandler = function(mode) { |
92 | return { | ||
91 | canHandleSource: function(srcObj) { | 93 | canHandleSource: function(srcObj) { |
92 | var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i; | 94 | var mpegurlRE = /^application\/(?:x-|vnd\.apple\.)mpegurl/i; |
93 | 95 | ||
... | @@ -98,17 +100,21 @@ videojs.HlsSourceHandler = { | ... | @@ -98,17 +100,21 @@ videojs.HlsSourceHandler = { |
98 | return mpegurlRE.test(srcObj.type); | 100 | return mpegurlRE.test(srcObj.type); |
99 | }, | 101 | }, |
100 | handleSource: function(source, tech) { | 102 | handleSource: function(source, tech) { |
101 | tech.hls = new videojs.Hls(tech, source); | 103 | tech.hls = new videojs.Hls(tech, { |
104 | source: source, | ||
105 | mode: mode | ||
106 | }); | ||
102 | tech.hls.src(source.src); | 107 | tech.hls.src(source.src); |
103 | return tech.hls; | 108 | return tech.hls; |
104 | } | 109 | } |
110 | }; | ||
105 | }; | 111 | }; |
106 | // register with the appropriate tech | 112 | |
113 | // register source handlers with the appropriate techs | ||
107 | if (videojs.MediaSource.supportsNativeMediaSources()) { | 114 | if (videojs.MediaSource.supportsNativeMediaSources()) { |
108 | videojs.getComponent('Html5').registerSourceHandler(videojs.HlsSourceHandler); | 115 | videojs.getComponent('Html5').registerSourceHandler(videojs.HlsSourceHandler('html5')); |
109 | } else { | ||
110 | videojs.getComponent('Flash').registerSourceHandler(videojs.HlsSourceHandler); | ||
111 | } | 116 | } |
117 | videojs.getComponent('Flash').registerSourceHandler(videojs.HlsSourceHandler('flash')); | ||
112 | 118 | ||
113 | // the desired length of video to maintain in the buffer, in seconds | 119 | // the desired length of video to maintain in the buffer, in seconds |
114 | videojs.Hls.GOAL_BUFFER_LENGTH = 30; | 120 | videojs.Hls.GOAL_BUFFER_LENGTH = 30; |
... | @@ -121,7 +127,7 @@ videojs.Hls.prototype.src = function(src) { | ... | @@ -121,7 +127,7 @@ videojs.Hls.prototype.src = function(src) { |
121 | return; | 127 | return; |
122 | } | 128 | } |
123 | 129 | ||
124 | this.mediaSource = new videojs.MediaSource(); | 130 | this.mediaSource = new videojs.MediaSource({ mode: this.mode_ }); |
125 | this.segmentBuffer_ = []; | 131 | this.segmentBuffer_ = []; |
126 | 132 | ||
127 | // if the stream contains ID3 metadata, expose that as a metadata | 133 | // if the stream contains ID3 metadata, expose that as a metadata |
... | @@ -739,6 +745,31 @@ videojs.Hls.prototype.stopCheckingBuffer_ = function() { | ... | @@ -739,6 +745,31 @@ videojs.Hls.prototype.stopCheckingBuffer_ = function() { |
739 | }; | 745 | }; |
740 | 746 | ||
741 | /** | 747 | /** |
748 | * Attempts to find the buffered TimeRange where playback is currently | ||
749 | * happening. Returns a new TimeRange with one or zero ranges. | ||
750 | */ | ||
751 | videojs.Hls.prototype.findCurrentBuffered_ = function() { | ||
752 | var | ||
753 | tech = this.tech_, | ||
754 | currentTime = tech.currentTime(), | ||
755 | buffered = this.tech_.buffered(), | ||
756 | i; | ||
757 | |||
758 | if (buffered && buffered.length) { | ||
759 | // Search for a range containing the play-head | ||
760 | for (i = 0;i < buffered.length; i++) { | ||
761 | if (buffered.start(i) <= currentTime && | ||
762 | buffered.end(i) >= currentTime) { | ||
763 | return videojs.createTimeRange(buffered.start(i), buffered.end(i)); | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | |||
768 | // Return an empty range if no ranges exist | ||
769 | return videojs.createTimeRange(); | ||
770 | }; | ||
771 | |||
772 | /** | ||
742 | * Determines whether there is enough video data currently in the buffer | 773 | * Determines whether there is enough video data currently in the buffer |
743 | * and downloads a new segment if the buffered time is less than the goal. | 774 | * and downloads a new segment if the buffered time is less than the goal. |
744 | * @param offset (optional) {number} the offset into the downloaded segment | 775 | * @param offset (optional) {number} the offset into the downloaded segment |
... | @@ -747,7 +778,8 @@ videojs.Hls.prototype.stopCheckingBuffer_ = function() { | ... | @@ -747,7 +778,8 @@ videojs.Hls.prototype.stopCheckingBuffer_ = function() { |
747 | videojs.Hls.prototype.fillBuffer = function(offset) { | 778 | videojs.Hls.prototype.fillBuffer = function(offset) { |
748 | var | 779 | var |
749 | tech = this.tech_, | 780 | tech = this.tech_, |
750 | buffered = this.tech_.buffered(), | 781 | currentTime = tech.currentTime(), |
782 | buffered = this.findCurrentBuffered_(), | ||
751 | bufferedTime = 0, | 783 | bufferedTime = 0, |
752 | segment, | 784 | segment, |
753 | segmentUri; | 785 | segmentUri; |
... | @@ -785,9 +817,10 @@ videojs.Hls.prototype.fillBuffer = function(offset) { | ... | @@ -785,9 +817,10 @@ videojs.Hls.prototype.fillBuffer = function(offset) { |
785 | return; | 817 | return; |
786 | } | 818 | } |
787 | 819 | ||
820 | // To determine how much is buffered, we need to find the buffered region we | ||
821 | // are currently playing in and measure it's length | ||
788 | if (buffered && buffered.length) { | 822 | if (buffered && buffered.length) { |
789 | // assuming a single, contiguous buffer region | 823 | bufferedTime = Math.max(0, buffered.end(0) - currentTime); |
790 | bufferedTime = tech.buffered().end(0) - tech.currentTime(); | ||
791 | } | 824 | } |
792 | 825 | ||
793 | // if there is plenty of content in the buffer and we're not | 826 | // if there is plenty of content in the buffer and we're not |
... | @@ -844,12 +877,13 @@ videojs.Hls.prototype.loadSegment = function(segmentUri, offset) { | ... | @@ -844,12 +877,13 @@ videojs.Hls.prototype.loadSegment = function(segmentUri, offset) { |
844 | // the segment request is no longer outstanding | 877 | // the segment request is no longer outstanding |
845 | self.segmentXhr_ = null; | 878 | self.segmentXhr_ = null; |
846 | 879 | ||
847 | if (error) { | ||
848 | // if a segment request times out, we may have better luck with another playlist | 880 | // if a segment request times out, we may have better luck with another playlist |
849 | if (request.timedout) { | 881 | if (request.timedout) { |
850 | self.bandwidth = 1; | 882 | self.bandwidth = 1; |
851 | return self.playlists.media(self.selectPlaylist()); | 883 | return self.playlists.media(self.selectPlaylist()); |
852 | } | 884 | } |
885 | |||
886 | if (!request.aborted && error) { | ||
853 | // otherwise, try jumping ahead to the next segment | 887 | // otherwise, try jumping ahead to the next segment |
854 | self.error = { | 888 | self.error = { |
855 | status: request.status, | 889 | status: request.status, |
... | @@ -914,7 +948,6 @@ videojs.Hls.prototype.drainBuffer = function(event) { | ... | @@ -914,7 +948,6 @@ videojs.Hls.prototype.drainBuffer = function(event) { |
914 | segment, | 948 | segment, |
915 | decrypter, | 949 | decrypter, |
916 | segIv, | 950 | segIv, |
917 | segmentOffset = 0, | ||
918 | // ptsTime, | 951 | // ptsTime, |
919 | segmentBuffer = this.segmentBuffer_; | 952 | segmentBuffer = this.segmentBuffer_; |
920 | 953 | ||
... | @@ -999,11 +1032,9 @@ videojs.Hls.prototype.drainBuffer = function(event) { | ... | @@ -999,11 +1032,9 @@ videojs.Hls.prototype.drainBuffer = function(event) { |
999 | // this.tech_.el().vjs_discontinuity(); | 1032 | // this.tech_.el().vjs_discontinuity(); |
1000 | // } | 1033 | // } |
1001 | 1034 | ||
1002 | // determine the timestamp offset for the start of this segment | 1035 | if (segment.discontinuity) { |
1003 | segmentOffset = this.playlists.expiredPostDiscontinuity_ + this.playlists.expiredPreDiscontinuity_; | 1036 | this.sourceBuffer.timestampOffset = this.findCurrentBuffered_().end(0); |
1004 | segmentOffset += videojs.Hls.Playlist.duration(playlist, | 1037 | } |
1005 | playlist.mediaSequence, | ||
1006 | playlist.mediaSequence + mediaIndex); | ||
1007 | 1038 | ||
1008 | this.sourceBuffer.appendBuffer(bytes); | 1039 | this.sourceBuffer.appendBuffer(bytes); |
1009 | 1040 | ... | ... |
... | @@ -5,13 +5,35 @@ | ... | @@ -5,13 +5,35 @@ |
5 | * A wrapper for videojs.xhr that tracks bandwidth. | 5 | * A wrapper for videojs.xhr that tracks bandwidth. |
6 | */ | 6 | */ |
7 | videojs.Hls.xhr = function(options, callback) { | 7 | videojs.Hls.xhr = function(options, callback) { |
8 | var request = videojs.xhr(options, function(error, request) { | 8 | // Add a default timeout for all hls requests |
9 | if (request.response) { | 9 | options = videojs.mergeOptions({ |
10 | timeout: 45e3 | ||
11 | }, options); | ||
12 | |||
13 | var request = videojs.xhr(options, function(error, response) { | ||
14 | if (!error && request.response) { | ||
10 | request.responseTime = (new Date()).getTime(); | 15 | request.responseTime = (new Date()).getTime(); |
11 | request.roundTripTime = request.responseTime - request.requestTime; | 16 | request.roundTripTime = request.responseTime - request.requestTime; |
12 | request.bytesReceived = request.response.byteLength || request.response.length; | 17 | request.bytesReceived = request.response.byteLength || request.response.length; |
18 | if (!request.bandwidth) { | ||
13 | request.bandwidth = Math.floor((request.bytesReceived / request.roundTripTime) * 8 * 1000); | 19 | request.bandwidth = Math.floor((request.bytesReceived / request.roundTripTime) * 8 * 1000); |
14 | } | 20 | } |
21 | } | ||
22 | |||
23 | // videojs.xhr now uses a specific code on the error object to signal that a request has | ||
24 | // timed out errors of setting a boolean on the request object | ||
25 | if (error || request.timedout) { | ||
26 | request.timedout = request.timedout || (error.code === 'ETIMEDOUT'); | ||
27 | } else { | ||
28 | request.timedout = false; | ||
29 | } | ||
30 | |||
31 | // videojs.xhr no longer consider status codes outside of 200 and 0 (for file uris) to be | ||
32 | // errors but the old XHR did so emulate that behavior | ||
33 | if (!error && response.statusCode !== 200 && response.statusCode !== 0) { | ||
34 | error = new Error('XHR Failed with a response of: ' + | ||
35 | (request && (request.response || request.responseText))); | ||
36 | } | ||
15 | 37 | ||
16 | callback(error, request); | 38 | callback(error, request); |
17 | }); | 39 | }); | ... | ... |
... | @@ -20,6 +20,8 @@ | ... | @@ -20,6 +20,8 @@ |
20 | setup: function() { | 20 | setup: function() { |
21 | // fake XHRs | 21 | // fake XHRs |
22 | sinonXhr = sinon.useFakeXMLHttpRequest(); | 22 | sinonXhr = sinon.useFakeXMLHttpRequest(); |
23 | videojs.xhr.XMLHttpRequest = sinonXhr; | ||
24 | |||
23 | requests = []; | 25 | requests = []; |
24 | sinonXhr.onCreate = function(xhr) { | 26 | sinonXhr.onCreate = function(xhr) { |
25 | // force the XHR2 timeout polyfill | 27 | // force the XHR2 timeout polyfill |
... | @@ -32,6 +34,7 @@ | ... | @@ -32,6 +34,7 @@ |
32 | }, | 34 | }, |
33 | teardown: function() { | 35 | teardown: function() { |
34 | sinonXhr.restore(); | 36 | sinonXhr.restore(); |
37 | videojs.xhr.XMLHttpRequest = window.XMLHttpRequest; | ||
35 | clock.restore(); | 38 | clock.restore(); |
36 | } | 39 | } |
37 | }); | 40 | }); | ... | ... |
... | @@ -87,24 +87,24 @@ var | ... | @@ -87,24 +87,24 @@ var |
87 | player.buffered = function() { | 87 | player.buffered = function() { |
88 | return videojs.createTimeRange(0, 0); | 88 | return videojs.createTimeRange(0, 0); |
89 | }; | 89 | }; |
90 | mockTech(player.tech); | 90 | mockTech(player.tech_); |
91 | 91 | ||
92 | return player; | 92 | return player; |
93 | }, | 93 | }, |
94 | openMediaSource = function(player) { | 94 | openMediaSource = function(player) { |
95 | // ensure the Flash tech is ready | 95 | // ensure the Flash tech is ready |
96 | player.tech.triggerReady(); | 96 | player.tech_.triggerReady(); |
97 | clock.tick(1); | 97 | clock.tick(1); |
98 | 98 | ||
99 | // simulate the sourceopen event | 99 | // simulate the sourceopen event |
100 | player.tech.hls.mediaSource.readyState = 'open'; | 100 | player.tech_.hls.mediaSource.readyState = 'open'; |
101 | player.tech.hls.mediaSource.dispatchEvent({ | 101 | player.tech_.hls.mediaSource.dispatchEvent({ |
102 | type: 'sourceopen', | 102 | type: 'sourceopen', |
103 | swfId: player.tech.el().id | 103 | swfId: player.tech_.el().id |
104 | }); | 104 | }); |
105 | 105 | ||
106 | // endOfStream triggers an exception if flash isn't available | 106 | // endOfStream triggers an exception if flash isn't available |
107 | player.tech.hls.mediaSource.endOfStream = function(error) { | 107 | player.tech_.hls.mediaSource.endOfStream = function(error) { |
108 | this.error_ = error; | 108 | this.error_ = error; |
109 | }; | 109 | }; |
110 | }, | 110 | }, |
... | @@ -190,10 +190,10 @@ var | ... | @@ -190,10 +190,10 @@ var |
190 | }, | 190 | }, |
191 | 191 | ||
192 | // a no-op MediaSource implementation to allow synchronous testing | 192 | // a no-op MediaSource implementation to allow synchronous testing |
193 | MockMediaSource = videojs.extends(videojs.EventTarget, { | 193 | MockMediaSource = videojs.extend(videojs.EventTarget, { |
194 | constructor: function() {}, | 194 | constructor: function() {}, |
195 | addSourceBuffer: function() { | 195 | addSourceBuffer: function() { |
196 | return new (videojs.extends(videojs.EventTarget, { | 196 | return new (videojs.extend(videojs.EventTarget, { |
197 | constructor: function() {}, | 197 | constructor: function() {}, |
198 | abort: function() {}, | 198 | abort: function() {}, |
199 | buffered: videojs.createTimeRange(), | 199 | buffered: videojs.createTimeRange(), |
... | @@ -287,6 +287,7 @@ module('HLS', { | ... | @@ -287,6 +287,7 @@ module('HLS', { |
287 | 287 | ||
288 | // fake XHRs | 288 | // fake XHRs |
289 | xhr = sinon.useFakeXMLHttpRequest(); | 289 | xhr = sinon.useFakeXMLHttpRequest(); |
290 | videojs.xhr.XMLHttpRequest = xhr; | ||
290 | requests = []; | 291 | requests = []; |
291 | xhr.onCreate = function(xhr) { | 292 | xhr.onCreate = function(xhr) { |
292 | requests.push(xhr); | 293 | requests.push(xhr); |
... | @@ -314,6 +315,7 @@ module('HLS', { | ... | @@ -314,6 +315,7 @@ module('HLS', { |
314 | 315 | ||
315 | player.dispose(); | 316 | player.dispose(); |
316 | xhr.restore(); | 317 | xhr.restore(); |
318 | videojs.xhr.XMLHttpRequest = window.XMLHttpRequest; | ||
317 | clock.restore(); | 319 | clock.restore(); |
318 | } | 320 | } |
319 | }); | 321 | }); |
... | @@ -326,10 +328,10 @@ test('starts playing if autoplay is specified', function() { | ... | @@ -326,10 +328,10 @@ test('starts playing if autoplay is specified', function() { |
326 | type: 'application/vnd.apple.mpegurl' | 328 | type: 'application/vnd.apple.mpegurl' |
327 | }); | 329 | }); |
328 | // REMOVEME workaround https://github.com/videojs/video.js/issues/2326 | 330 | // REMOVEME workaround https://github.com/videojs/video.js/issues/2326 |
329 | player.tech.triggerReady(); | 331 | player.tech_.triggerReady(); |
330 | clock.tick(1); | 332 | clock.tick(1); |
331 | // make sure play() is called *after* the media source opens | 333 | // make sure play() is called *after* the media source opens |
332 | player.tech.hls.play = function() { | 334 | player.tech_.hls.play = function() { |
333 | plays++; | 335 | plays++; |
334 | }; | 336 | }; |
335 | openMediaSource(player); | 337 | openMediaSource(player); |
... | @@ -365,7 +367,7 @@ test('autoplay seeks to the live point after media source open', function() { | ... | @@ -365,7 +367,7 @@ test('autoplay seeks to the live point after media source open', function() { |
365 | src: 'liveStart30sBefore.m3u8', | 367 | src: 'liveStart30sBefore.m3u8', |
366 | type: 'application/vnd.apple.mpegurl' | 368 | type: 'application/vnd.apple.mpegurl' |
367 | }); | 369 | }); |
368 | player.tech.triggerReady(); | 370 | player.tech_.triggerReady(); |
369 | clock.tick(1); | 371 | clock.tick(1); |
370 | standardXHRResponse(requests.shift()); | 372 | standardXHRResponse(requests.shift()); |
371 | openMediaSource(player); | 373 | openMediaSource(player); |
... | @@ -379,12 +381,12 @@ test('duration is set when the source opens after the playlist is loaded', funct | ... | @@ -379,12 +381,12 @@ test('duration is set when the source opens after the playlist is loaded', funct |
379 | src: 'media.m3u8', | 381 | src: 'media.m3u8', |
380 | type: 'application/vnd.apple.mpegurl' | 382 | type: 'application/vnd.apple.mpegurl' |
381 | }); | 383 | }); |
382 | player.tech.triggerReady(); | 384 | player.tech_.triggerReady(); |
383 | clock.tick(1); | 385 | clock.tick(1); |
384 | standardXHRResponse(requests.shift()); | 386 | standardXHRResponse(requests.shift()); |
385 | openMediaSource(player); | 387 | openMediaSource(player); |
386 | 388 | ||
387 | equal(player.tech.hls.mediaSource.duration , 40, 'set the duration'); | 389 | equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration'); |
388 | }); | 390 | }); |
389 | 391 | ||
390 | test('codecs are passed to the source buffer', function() { | 392 | test('codecs are passed to the source buffer', function() { |
... | @@ -394,7 +396,7 @@ test('codecs are passed to the source buffer', function() { | ... | @@ -394,7 +396,7 @@ test('codecs are passed to the source buffer', function() { |
394 | type: 'application/vnd.apple.mpegurl' | 396 | type: 'application/vnd.apple.mpegurl' |
395 | }); | 397 | }); |
396 | openMediaSource(player); | 398 | openMediaSource(player); |
397 | player.tech.hls.mediaSource.addSourceBuffer = function(codec) { | 399 | player.tech_.hls.mediaSource.addSourceBuffer = function(codec) { |
398 | codecs.push(codec); | 400 | codecs.push(codec); |
399 | }; | 401 | }; |
400 | 402 | ||
... | @@ -420,7 +422,7 @@ test('creates a PlaylistLoader on init', function() { | ... | @@ -420,7 +422,7 @@ test('creates a PlaylistLoader on init', function() { |
420 | src: 'manifest/playlist.m3u8', | 422 | src: 'manifest/playlist.m3u8', |
421 | type: 'application/vnd.apple.mpegurl' | 423 | type: 'application/vnd.apple.mpegurl' |
422 | }); | 424 | }); |
423 | 425 | openMediaSource(player); | |
424 | player.src({ | 426 | player.src({ |
425 | src:'manifest/playlist.m3u8', | 427 | src:'manifest/playlist.m3u8', |
426 | type: 'application/vnd.apple.mpegurl' | 428 | type: 'application/vnd.apple.mpegurl' |
... | @@ -429,11 +431,11 @@ test('creates a PlaylistLoader on init', function() { | ... | @@ -429,11 +431,11 @@ test('creates a PlaylistLoader on init', function() { |
429 | 431 | ||
430 | equal(requests[0].aborted, true, 'aborted previous src'); | 432 | equal(requests[0].aborted, true, 'aborted previous src'); |
431 | standardXHRResponse(requests[1]); | 433 | standardXHRResponse(requests[1]); |
432 | ok(player.tech.hls.playlists.master, 'set the master playlist'); | 434 | ok(player.tech_.hls.playlists.master, 'set the master playlist'); |
433 | ok(player.tech.hls.playlists.media(), 'set the media playlist'); | 435 | ok(player.tech_.hls.playlists.media(), 'set the media playlist'); |
434 | ok(player.tech.hls.playlists.media().segments, 'the segment entries are parsed'); | 436 | ok(player.tech_.hls.playlists.media().segments, 'the segment entries are parsed'); |
435 | strictEqual(player.tech.hls.playlists.master.playlists[0], | 437 | strictEqual(player.tech_.hls.playlists.master.playlists[0], |
436 | player.tech.hls.playlists.media(), | 438 | player.tech_.hls.playlists.media(), |
437 | 'the playlist is selected'); | 439 | 'the playlist is selected'); |
438 | }); | 440 | }); |
439 | 441 | ||
... | @@ -455,14 +457,14 @@ test('re-initializes the playlist loader when switching sources', function() { | ... | @@ -455,14 +457,14 @@ test('re-initializes the playlist loader when switching sources', function() { |
455 | }); | 457 | }); |
456 | // maybe not needed if https://github.com/videojs/video.js/issues/2326 gets fixed | 458 | // maybe not needed if https://github.com/videojs/video.js/issues/2326 gets fixed |
457 | clock.tick(1); | 459 | clock.tick(1); |
458 | ok(!player.tech.hls.playlists.media(), 'no media playlist'); | 460 | ok(!player.tech_.hls.playlists.media(), 'no media playlist'); |
459 | equal(player.tech.hls.playlists.state, | 461 | equal(player.tech_.hls.playlists.state, |
460 | 'HAVE_NOTHING', | 462 | 'HAVE_NOTHING', |
461 | 'reset the playlist loader state'); | 463 | 'reset the playlist loader state'); |
462 | equal(requests.length, 1, 'requested the new src'); | 464 | equal(requests.length, 1, 'requested the new src'); |
463 | 465 | ||
464 | // buffer check | 466 | // buffer check |
465 | player.tech.hls.checkBuffer_(); | 467 | player.tech_.hls.checkBuffer_(); |
466 | equal(requests.length, 1, 'did not request a stale segment'); | 468 | equal(requests.length, 1, 'did not request a stale segment'); |
467 | 469 | ||
468 | // sourceopen | 470 | // sourceopen |
... | @@ -479,12 +481,12 @@ test('sets the duration if one is available on the playlist', function() { | ... | @@ -479,12 +481,12 @@ test('sets the duration if one is available on the playlist', function() { |
479 | type: 'application/vnd.apple.mpegurl' | 481 | type: 'application/vnd.apple.mpegurl' |
480 | }); | 482 | }); |
481 | openMediaSource(player); | 483 | openMediaSource(player); |
482 | player.tech.on('durationchange', function() { | 484 | player.tech_.on('durationchange', function() { |
483 | events++; | 485 | events++; |
484 | }); | 486 | }); |
485 | 487 | ||
486 | standardXHRResponse(requests[0]); | 488 | standardXHRResponse(requests[0]); |
487 | equal(player.tech.hls.mediaSource.duration, 40, 'set the duration'); | 489 | equal(player.tech_.hls.mediaSource.duration, 40, 'set the duration'); |
488 | equal(events, 1, 'durationchange is fired'); | 490 | equal(events, 1, 'durationchange is fired'); |
489 | }); | 491 | }); |
490 | 492 | ||
... | @@ -495,14 +497,14 @@ QUnit.skip('calculates the duration if needed', function() { | ... | @@ -495,14 +497,14 @@ QUnit.skip('calculates the duration if needed', function() { |
495 | type: 'application/vnd.apple.mpegurl' | 497 | type: 'application/vnd.apple.mpegurl' |
496 | }); | 498 | }); |
497 | openMediaSource(player); | 499 | openMediaSource(player); |
498 | player.tech.hls.mediaSource.duration = NaN; | 500 | player.tech_.hls.mediaSource.duration = NaN; |
499 | player.on('durationchange', function() { | 501 | player.on('durationchange', function() { |
500 | changes++; | 502 | changes++; |
501 | }); | 503 | }); |
502 | 504 | ||
503 | standardXHRResponse(requests[0]); | 505 | standardXHRResponse(requests[0]); |
504 | strictEqual(player.tech.hls.mediaSource.duration, | 506 | strictEqual(player.tech_.hls.mediaSource.duration, |
505 | player.tech.hls.playlists.media().segments.length * 10, | 507 | player.tech_.hls.playlists.media().segments.length * 10, |
506 | 'duration is updated'); | 508 | 'duration is updated'); |
507 | strictEqual(changes, 1, 'one durationchange fired'); | 509 | strictEqual(changes, 1, 'one durationchange fired'); |
508 | }); | 510 | }); |
... | @@ -549,6 +551,28 @@ test('starts downloading a segment on loadedmetadata', function() { | ... | @@ -549,6 +551,28 @@ test('starts downloading a segment on loadedmetadata', function() { |
549 | 'the first segment is requested'); | 551 | 'the first segment is requested'); |
550 | }); | 552 | }); |
551 | 553 | ||
554 | test('finds the correct buffered region based on currentTime', function() { | ||
555 | player.src({ | ||
556 | src: 'manifest/media.m3u8', | ||
557 | type: 'application/vnd.apple.mpegurl' | ||
558 | }); | ||
559 | player.tech_.buffered = function() { | ||
560 | return videojs.createTimeRanges([[0, 5], [6, 12]]); | ||
561 | }; | ||
562 | openMediaSource(player); | ||
563 | |||
564 | standardXHRResponse(requests[0]); | ||
565 | standardXHRResponse(requests[1]); | ||
566 | player.currentTime(3); | ||
567 | clock.tick(1); | ||
568 | equal(player.tech_.hls.findCurrentBuffered_().end(0), | ||
569 | 5, 'inside the first buffered region'); | ||
570 | player.currentTime(6); | ||
571 | clock.tick(1); | ||
572 | equal(player.tech_.hls.findCurrentBuffered_().end(0), | ||
573 | 12, 'inside the second buffered region'); | ||
574 | }); | ||
575 | |||
552 | test('recognizes absolute URIs and requests them unmodified', function() { | 576 | test('recognizes absolute URIs and requests them unmodified', function() { |
553 | player.src({ | 577 | player.src({ |
554 | src: 'manifest/absoluteUris.m3u8', | 578 | src: 'manifest/absoluteUris.m3u8', |
... | @@ -588,11 +612,11 @@ test('re-initializes the handler for each source', function() { | ... | @@ -588,11 +612,11 @@ test('re-initializes the handler for each source', function() { |
588 | type: 'application/vnd.apple.mpegurl' | 612 | type: 'application/vnd.apple.mpegurl' |
589 | }); | 613 | }); |
590 | openMediaSource(player); | 614 | openMediaSource(player); |
591 | firstPlaylists = player.tech.hls.playlists; | 615 | firstPlaylists = player.tech_.hls.playlists; |
592 | firstMSE = player.tech.hls.mediaSource; | 616 | firstMSE = player.tech_.hls.mediaSource; |
593 | standardXHRResponse(requests.shift()); | 617 | standardXHRResponse(requests.shift()); |
594 | standardXHRResponse(requests.shift()); | 618 | standardXHRResponse(requests.shift()); |
595 | player.tech.hls.sourceBuffer.abort = function() { | 619 | player.tech_.hls.sourceBuffer.abort = function() { |
596 | aborts++; | 620 | aborts++; |
597 | }; | 621 | }; |
598 | 622 | ||
... | @@ -601,8 +625,8 @@ test('re-initializes the handler for each source', function() { | ... | @@ -601,8 +625,8 @@ test('re-initializes the handler for each source', function() { |
601 | type: 'application/vnd.apple.mpegurl' | 625 | type: 'application/vnd.apple.mpegurl' |
602 | }); | 626 | }); |
603 | openMediaSource(player); | 627 | openMediaSource(player); |
604 | secondPlaylists = player.tech.hls.playlists; | 628 | secondPlaylists = player.tech_.hls.playlists; |
605 | secondMSE = player.tech.hls.mediaSource; | 629 | secondMSE = player.tech_.hls.mediaSource; |
606 | 630 | ||
607 | equal(1, aborts, 'aborted the old source buffer'); | 631 | equal(1, aborts, 'aborted the old source buffer'); |
608 | ok(requests[0].aborted, 'aborted the old segment request'); | 632 | ok(requests[0].aborted, 'aborted the old segment request'); |
... | @@ -618,7 +642,7 @@ test('triggers an error when a master playlist request errors', function() { | ... | @@ -618,7 +642,7 @@ test('triggers an error when a master playlist request errors', function() { |
618 | openMediaSource(player); | 642 | openMediaSource(player); |
619 | requests.pop().respond(500); | 643 | requests.pop().respond(500); |
620 | 644 | ||
621 | equal(player.tech.hls.mediaSource.error_, 'network', 'a network error is triggered'); | 645 | equal(player.tech_.hls.mediaSource.error_, 'network', 'a network error is triggered'); |
622 | }); | 646 | }); |
623 | 647 | ||
624 | test('downloads media playlists after loading the master', function() { | 648 | test('downloads media playlists after loading the master', function() { |
... | @@ -629,7 +653,7 @@ test('downloads media playlists after loading the master', function() { | ... | @@ -629,7 +653,7 @@ test('downloads media playlists after loading the master', function() { |
629 | openMediaSource(player); | 653 | openMediaSource(player); |
630 | 654 | ||
631 | // set bandwidth to an appropriate number so we don't switch | 655 | // set bandwidth to an appropriate number so we don't switch |
632 | player.tech.hls.bandwidth = 200000; | 656 | player.tech_.hls.bandwidth = 200000; |
633 | standardXHRResponse(requests[0]); | 657 | standardXHRResponse(requests[0]); |
634 | standardXHRResponse(requests[1]); | 658 | standardXHRResponse(requests[1]); |
635 | standardXHRResponse(requests[2]); | 659 | standardXHRResponse(requests[2]); |
... | @@ -652,8 +676,8 @@ test('upshift if initial bandwidth is high', function() { | ... | @@ -652,8 +676,8 @@ test('upshift if initial bandwidth is high', function() { |
652 | 676 | ||
653 | standardXHRResponse(requests[0]); | 677 | standardXHRResponse(requests[0]); |
654 | 678 | ||
655 | player.tech.hls.playlists.setBandwidth = function() { | 679 | player.tech_.hls.playlists.setBandwidth = function() { |
656 | player.tech.hls.playlists.bandwidth = 1000000000; | 680 | player.tech_.hls.playlists.bandwidth = 1000000000; |
657 | }; | 681 | }; |
658 | 682 | ||
659 | standardXHRResponse(requests[1]); | 683 | standardXHRResponse(requests[1]); |
... | @@ -682,8 +706,8 @@ test('dont downshift if bandwidth is low', function() { | ... | @@ -682,8 +706,8 @@ test('dont downshift if bandwidth is low', function() { |
682 | 706 | ||
683 | standardXHRResponse(requests[0]); | 707 | standardXHRResponse(requests[0]); |
684 | 708 | ||
685 | player.tech.hls.playlists.setBandwidth = function() { | 709 | player.tech_.hls.playlists.setBandwidth = function() { |
686 | player.tech.hls.playlists.bandwidth = 100; | 710 | player.tech_.hls.playlists.bandwidth = 100; |
687 | }; | 711 | }; |
688 | 712 | ||
689 | standardXHRResponse(requests[1]); | 713 | standardXHRResponse(requests[1]); |
... | @@ -710,10 +734,10 @@ test('starts checking the buffer on init', function() { | ... | @@ -710,10 +734,10 @@ test('starts checking the buffer on init', function() { |
710 | 734 | ||
711 | // wait long enough for the buffer check interval to expire and | 735 | // wait long enough for the buffer check interval to expire and |
712 | // trigger fill/drainBuffer | 736 | // trigger fill/drainBuffer |
713 | player.tech.hls.fillBuffer = function() { | 737 | player.tech_.hls.fillBuffer = function() { |
714 | fills++; | 738 | fills++; |
715 | }; | 739 | }; |
716 | player.tech.hls.drainBuffer = function() { | 740 | player.tech_.hls.drainBuffer = function() { |
717 | drains++; | 741 | drains++; |
718 | }; | 742 | }; |
719 | clock.tick(500); | 743 | clock.tick(500); |
... | @@ -732,7 +756,7 @@ test('buffer checks are noops until a media playlist is ready', function() { | ... | @@ -732,7 +756,7 @@ test('buffer checks are noops until a media playlist is ready', function() { |
732 | type: 'application/vnd.apple.mpegurl' | 756 | type: 'application/vnd.apple.mpegurl' |
733 | }); | 757 | }); |
734 | openMediaSource(player); | 758 | openMediaSource(player); |
735 | player.tech.hls.checkBuffer_(); | 759 | player.tech_.hls.checkBuffer_(); |
736 | 760 | ||
737 | strictEqual(1, requests.length, 'one request was made'); | 761 | strictEqual(1, requests.length, 'one request was made'); |
738 | strictEqual(requests[0].url, 'manifest/media.m3u8', 'media playlist requested'); | 762 | strictEqual(requests[0].url, 'manifest/media.m3u8', 'media playlist requested'); |
... | @@ -760,7 +784,7 @@ test('buffer checks are noops when only the master is ready', function() { | ... | @@ -760,7 +784,7 @@ test('buffer checks are noops when only the master is ready', function() { |
760 | // respond with the master playlist but don't send the media playlist yet | 784 | // respond with the master playlist but don't send the media playlist yet |
761 | standardXHRResponse(requests.shift()); | 785 | standardXHRResponse(requests.shift()); |
762 | // trigger fillBuffer() | 786 | // trigger fillBuffer() |
763 | player.tech.hls.checkBuffer_(); | 787 | player.tech_.hls.checkBuffer_(); |
764 | 788 | ||
765 | strictEqual(1, requests.length, 'one request was made'); | 789 | strictEqual(1, requests.length, 'one request was made'); |
766 | strictEqual(requests[0].url, | 790 | strictEqual(requests[0].url, |
... | @@ -782,11 +806,11 @@ test('calculates the bandwidth after downloading a segment', function() { | ... | @@ -782,11 +806,11 @@ test('calculates the bandwidth after downloading a segment', function() { |
782 | 806 | ||
783 | standardXHRResponse(requests[1]); | 807 | standardXHRResponse(requests[1]); |
784 | 808 | ||
785 | ok(player.tech.hls.bandwidth, 'bandwidth is calculated'); | 809 | ok(player.tech_.hls.bandwidth, 'bandwidth is calculated'); |
786 | ok(player.tech.hls.bandwidth > 0, | 810 | ok(player.tech_.hls.bandwidth > 0, |
787 | 'bandwidth is positive: ' + player.tech.hls.bandwidth); | 811 | 'bandwidth is positive: ' + player.tech_.hls.bandwidth); |
788 | ok(player.tech.hls.segmentXhrTime >= 0, | 812 | ok(player.tech_.hls.segmentXhrTime >= 0, |
789 | 'saves segment request time: ' + player.tech.hls.segmentXhrTime + 's'); | 813 | 'saves segment request time: ' + player.tech_.hls.segmentXhrTime + 's'); |
790 | }); | 814 | }); |
791 | 815 | ||
792 | test('fires a progress event after downloading a segment', function() { | 816 | test('fires a progress event after downloading a segment', function() { |
... | @@ -813,14 +837,14 @@ test('selects a playlist after segment downloads', function() { | ... | @@ -813,14 +837,14 @@ test('selects a playlist after segment downloads', function() { |
813 | type: 'application/vnd.apple.mpegurl' | 837 | type: 'application/vnd.apple.mpegurl' |
814 | }); | 838 | }); |
815 | openMediaSource(player); | 839 | openMediaSource(player); |
816 | player.tech.hls.selectPlaylist = function() { | 840 | player.tech_.hls.selectPlaylist = function() { |
817 | calls++; | 841 | calls++; |
818 | return player.tech.hls.playlists.master.playlists[0]; | 842 | return player.tech_.hls.playlists.master.playlists[0]; |
819 | }; | 843 | }; |
820 | 844 | ||
821 | standardXHRResponse(requests[0]); | 845 | standardXHRResponse(requests[0]); |
822 | 846 | ||
823 | player.tech.hls.bandwidth = 3000000; | 847 | player.tech_.hls.bandwidth = 3000000; |
824 | standardXHRResponse(requests[1]); | 848 | standardXHRResponse(requests[1]); |
825 | standardXHRResponse(requests[2]); | 849 | standardXHRResponse(requests[2]); |
826 | 850 | ||
... | @@ -831,7 +855,7 @@ test('selects a playlist after segment downloads', function() { | ... | @@ -831,7 +855,7 @@ test('selects a playlist after segment downloads', function() { |
831 | player.buffered = function() { | 855 | player.buffered = function() { |
832 | return videojs.createTimeRange(0, 2); | 856 | return videojs.createTimeRange(0, 2); |
833 | }; | 857 | }; |
834 | player.tech.hls.checkBuffer_(); | 858 | player.tech_.hls.checkBuffer_(); |
835 | 859 | ||
836 | standardXHRResponse(requests[3]); | 860 | standardXHRResponse(requests[3]); |
837 | 861 | ||
... | @@ -847,15 +871,15 @@ test('moves to the next segment if there is a network error', function() { | ... | @@ -847,15 +871,15 @@ test('moves to the next segment if there is a network error', function() { |
847 | }); | 871 | }); |
848 | openMediaSource(player); | 872 | openMediaSource(player); |
849 | 873 | ||
850 | player.tech.hls.bandwidth = 20000; | 874 | player.tech_.hls.bandwidth = 20000; |
851 | standardXHRResponse(requests[0]); | 875 | standardXHRResponse(requests[0]); |
852 | standardXHRResponse(requests[1]); | 876 | standardXHRResponse(requests[1]); |
853 | 877 | ||
854 | mediaIndex = player.tech.hls.mediaIndex; | 878 | mediaIndex = player.tech_.hls.mediaIndex; |
855 | player.trigger('timeupdate'); | 879 | player.trigger('timeupdate'); |
856 | 880 | ||
857 | requests[2].respond(400); | 881 | requests[2].respond(400); |
858 | strictEqual(mediaIndex + 1, player.tech.hls.mediaIndex, 'media index is incremented'); | 882 | strictEqual(mediaIndex + 1, player.tech_.hls.mediaIndex, 'media index is incremented'); |
859 | }); | 883 | }); |
860 | 884 | ||
861 | test('updates the duration after switching playlists', function() { | 885 | test('updates the duration after switching playlists', function() { |
... | @@ -865,13 +889,13 @@ test('updates the duration after switching playlists', function() { | ... | @@ -865,13 +889,13 @@ test('updates the duration after switching playlists', function() { |
865 | type: 'application/vnd.apple.mpegurl' | 889 | type: 'application/vnd.apple.mpegurl' |
866 | }); | 890 | }); |
867 | openMediaSource(player); | 891 | openMediaSource(player); |
868 | player.tech.hls.selectPlaylist = function() { | 892 | player.tech_.hls.selectPlaylist = function() { |
869 | selectedPlaylist = true; | 893 | selectedPlaylist = true; |
870 | 894 | ||
871 | // this duraiton should be overwritten by the playlist change | 895 | // this duraiton should be overwritten by the playlist change |
872 | player.tech.hls.mediaSource.duration = -Infinity; | 896 | player.tech_.hls.mediaSource.duration = -Infinity; |
873 | 897 | ||
874 | return player.tech.hls.playlists.master.playlists[1]; | 898 | return player.tech_.hls.playlists.master.playlists[1]; |
875 | }; | 899 | }; |
876 | 900 | ||
877 | standardXHRResponse(requests[0]); | 901 | standardXHRResponse(requests[0]); |
... | @@ -879,7 +903,7 @@ test('updates the duration after switching playlists', function() { | ... | @@ -879,7 +903,7 @@ test('updates the duration after switching playlists', function() { |
879 | standardXHRResponse(requests[2]); | 903 | standardXHRResponse(requests[2]); |
880 | standardXHRResponse(requests[3]); | 904 | standardXHRResponse(requests[3]); |
881 | ok(selectedPlaylist, 'selected playlist'); | 905 | ok(selectedPlaylist, 'selected playlist'); |
882 | ok(player.tech.hls.mediaSource.duration !== -Infinity, 'updates the duration'); | 906 | ok(player.tech_.hls.mediaSource.duration !== -Infinity, 'updates the duration'); |
883 | }); | 907 | }); |
884 | 908 | ||
885 | test('downloads additional playlists if required', function() { | 909 | test('downloads additional playlists if required', function() { |
... | @@ -894,12 +918,12 @@ test('downloads additional playlists if required', function() { | ... | @@ -894,12 +918,12 @@ test('downloads additional playlists if required', function() { |
894 | }); | 918 | }); |
895 | openMediaSource(player); | 919 | openMediaSource(player); |
896 | 920 | ||
897 | player.tech.hls.bandwidth = 20000; | 921 | player.tech_.hls.bandwidth = 20000; |
898 | standardXHRResponse(requests[0]); | 922 | standardXHRResponse(requests[0]); |
899 | 923 | ||
900 | standardXHRResponse(requests[1]); | 924 | standardXHRResponse(requests[1]); |
901 | // before an m3u8 is downloaded, no segments are available | 925 | // before an m3u8 is downloaded, no segments are available |
902 | player.tech.hls.selectPlaylist = function() { | 926 | player.tech_.hls.selectPlaylist = function() { |
903 | if (!called) { | 927 | if (!called) { |
904 | called = true; | 928 | called = true; |
905 | return playlist; | 929 | return playlist; |
... | @@ -921,9 +945,9 @@ test('downloads additional playlists if required', function() { | ... | @@ -921,9 +945,9 @@ test('downloads additional playlists if required', function() { |
921 | absoluteUrl('manifest/' + playlist.uri), | 945 | absoluteUrl('manifest/' + playlist.uri), |
922 | 'made playlist request'); | 946 | 'made playlist request'); |
923 | strictEqual(playlist.uri, | 947 | strictEqual(playlist.uri, |
924 | player.tech.hls.playlists.media().uri, | 948 | player.tech_.hls.playlists.media().uri, |
925 | 'a new playlists was selected'); | 949 | 'a new playlists was selected'); |
926 | ok(player.tech.hls.playlists.media().segments, 'segments are now available'); | 950 | ok(player.tech_.hls.playlists.media().segments, 'segments are now available'); |
927 | }); | 951 | }); |
928 | 952 | ||
929 | test('selects a playlist below the current bandwidth', function() { | 953 | test('selects a playlist below the current bandwidth', function() { |
... | @@ -937,15 +961,15 @@ test('selects a playlist below the current bandwidth', function() { | ... | @@ -937,15 +961,15 @@ test('selects a playlist below the current bandwidth', function() { |
937 | standardXHRResponse(requests[0]); | 961 | standardXHRResponse(requests[0]); |
938 | 962 | ||
939 | // the default playlist has a really high bitrate | 963 | // the default playlist has a really high bitrate |
940 | player.tech.hls.playlists.master.playlists[0].attributes.BANDWIDTH = 9e10; | 964 | player.tech_.hls.playlists.master.playlists[0].attributes.BANDWIDTH = 9e10; |
941 | // playlist 1 has a very low bitrate | 965 | // playlist 1 has a very low bitrate |
942 | player.tech.hls.playlists.master.playlists[1].attributes.BANDWIDTH = 1; | 966 | player.tech_.hls.playlists.master.playlists[1].attributes.BANDWIDTH = 1; |
943 | // but the detected client bandwidth is really low | 967 | // but the detected client bandwidth is really low |
944 | player.tech.hls.bandwidth = 10; | 968 | player.tech_.hls.bandwidth = 10; |
945 | 969 | ||
946 | playlist = player.tech.hls.selectPlaylist(); | 970 | playlist = player.tech_.hls.selectPlaylist(); |
947 | strictEqual(playlist, | 971 | strictEqual(playlist, |
948 | player.tech.hls.playlists.master.playlists[1], | 972 | player.tech_.hls.playlists.master.playlists[1], |
949 | 'the low bitrate stream is selected'); | 973 | 'the low bitrate stream is selected'); |
950 | }); | 974 | }); |
951 | 975 | ||
... | @@ -961,7 +985,7 @@ test('scales the bandwidth estimate for the first segment', function() { | ... | @@ -961,7 +985,7 @@ test('scales the bandwidth estimate for the first segment', function() { |
961 | '#EXTM3U\n' + | 985 | '#EXTM3U\n' + |
962 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | 986 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + |
963 | '#EXT-X-TARGETDURATION:10\n'); | 987 | '#EXT-X-TARGETDURATION:10\n'); |
964 | equal(player.tech.hls.bandwidth, 500 * 5, 'scaled the bandwidth estimate by 5'); | 988 | equal(player.tech_.hls.bandwidth, 500 * 5, 'scaled the bandwidth estimate by 5'); |
965 | }); | 989 | }); |
966 | 990 | ||
967 | test('allows initial bandwidth to be provided', function() { | 991 | test('allows initial bandwidth to be provided', function() { |
... | @@ -970,14 +994,14 @@ test('allows initial bandwidth to be provided', function() { | ... | @@ -970,14 +994,14 @@ test('allows initial bandwidth to be provided', function() { |
970 | type: 'application/vnd.apple.mpegurl' | 994 | type: 'application/vnd.apple.mpegurl' |
971 | }); | 995 | }); |
972 | openMediaSource(player); | 996 | openMediaSource(player); |
973 | player.tech.hls.bandwidth = 500; | 997 | player.tech_.hls.bandwidth = 500; |
974 | 998 | ||
975 | requests[0].bandwidth = 1; | 999 | requests[0].bandwidth = 1; |
976 | requests.shift().respond(200, null, | 1000 | requests.shift().respond(200, null, |
977 | '#EXTM3U\n' + | 1001 | '#EXTM3U\n' + |
978 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | 1002 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + |
979 | '#EXT-X-TARGETDURATION:10\n'); | 1003 | '#EXT-X-TARGETDURATION:10\n'); |
980 | equal(player.tech.hls.bandwidth, 500, 'prefers user-specified intial bandwidth'); | 1004 | equal(player.tech_.hls.bandwidth, 500, 'prefers user-specified intial bandwidth'); |
981 | }); | 1005 | }); |
982 | 1006 | ||
983 | test('raises the minimum bitrate for a stream proportionially', function() { | 1007 | test('raises the minimum bitrate for a stream proportionially', function() { |
... | @@ -991,15 +1015,15 @@ test('raises the minimum bitrate for a stream proportionially', function() { | ... | @@ -991,15 +1015,15 @@ test('raises the minimum bitrate for a stream proportionially', function() { |
991 | standardXHRResponse(requests[0]); | 1015 | standardXHRResponse(requests[0]); |
992 | 1016 | ||
993 | // the default playlist's bandwidth + 10% is equal to the current bandwidth | 1017 | // the default playlist's bandwidth + 10% is equal to the current bandwidth |
994 | player.tech.hls.playlists.master.playlists[0].attributes.BANDWIDTH = 10; | 1018 | player.tech_.hls.playlists.master.playlists[0].attributes.BANDWIDTH = 10; |
995 | player.tech.hls.bandwidth = 11; | 1019 | player.tech_.hls.bandwidth = 11; |
996 | 1020 | ||
997 | // 9.9 * 1.1 < 11 | 1021 | // 9.9 * 1.1 < 11 |
998 | player.tech.hls.playlists.master.playlists[1].attributes.BANDWIDTH = 9.9; | 1022 | player.tech_.hls.playlists.master.playlists[1].attributes.BANDWIDTH = 9.9; |
999 | playlist = player.tech.hls.selectPlaylist(); | 1023 | playlist = player.tech_.hls.selectPlaylist(); |
1000 | 1024 | ||
1001 | strictEqual(playlist, | 1025 | strictEqual(playlist, |
1002 | player.tech.hls.playlists.master.playlists[1], | 1026 | player.tech_.hls.playlists.master.playlists[1], |
1003 | 'a lower bitrate stream is selected'); | 1027 | 'a lower bitrate stream is selected'); |
1004 | }); | 1028 | }); |
1005 | 1029 | ||
... | @@ -1014,12 +1038,12 @@ test('uses the lowest bitrate if no other is suitable', function() { | ... | @@ -1014,12 +1038,12 @@ test('uses the lowest bitrate if no other is suitable', function() { |
1014 | standardXHRResponse(requests[0]); | 1038 | standardXHRResponse(requests[0]); |
1015 | 1039 | ||
1016 | // the lowest bitrate playlist is much greater than 1b/s | 1040 | // the lowest bitrate playlist is much greater than 1b/s |
1017 | player.tech.hls.bandwidth = 1; | 1041 | player.tech_.hls.bandwidth = 1; |
1018 | playlist = player.tech.hls.selectPlaylist(); | 1042 | playlist = player.tech_.hls.selectPlaylist(); |
1019 | 1043 | ||
1020 | // playlist 1 has the lowest advertised bitrate | 1044 | // playlist 1 has the lowest advertised bitrate |
1021 | strictEqual(playlist, | 1045 | strictEqual(playlist, |
1022 | player.tech.hls.playlists.master.playlists[1], | 1046 | player.tech_.hls.playlists.master.playlists[1], |
1023 | 'the lowest bitrate stream is selected'); | 1047 | 'the lowest bitrate stream is selected'); |
1024 | }); | 1048 | }); |
1025 | 1049 | ||
... | @@ -1037,18 +1061,18 @@ test('uses the lowest bitrate if no other is suitable', function() { | ... | @@ -1037,18 +1061,18 @@ test('uses the lowest bitrate if no other is suitable', function() { |
1037 | 1061 | ||
1038 | player.width(640); | 1062 | player.width(640); |
1039 | player.height(360); | 1063 | player.height(360); |
1040 | player.tech.hls.bandwidth = 3000000; | 1064 | player.tech_.hls.bandwidth = 3000000; |
1041 | 1065 | ||
1042 | playlist = player.tech.hls.selectPlaylist(); | 1066 | playlist = player.tech_.hls.selectPlaylist(); |
1043 | 1067 | ||
1044 | deepEqual(playlist.attributes.RESOLUTION, {width:960,height:540},'should return the correct resolution by player dimensions'); | 1068 | deepEqual(playlist.attributes.RESOLUTION, {width:960,height:540},'should return the correct resolution by player dimensions'); |
1045 | equal(playlist.attributes.BANDWIDTH, 1928000, 'should have the expected bandwidth in case of multiple'); | 1069 | equal(playlist.attributes.BANDWIDTH, 1928000, 'should have the expected bandwidth in case of multiple'); |
1046 | 1070 | ||
1047 | player.width(1920); | 1071 | player.width(1920); |
1048 | player.height(1080); | 1072 | player.height(1080); |
1049 | player.tech.hls.bandwidth = 3000000; | 1073 | player.tech_.hls.bandwidth = 3000000; |
1050 | 1074 | ||
1051 | playlist = player.tech.hls.selectPlaylist(); | 1075 | playlist = player.tech_.hls.selectPlaylist(); |
1052 | 1076 | ||
1053 | deepEqual(playlist.attributes.RESOLUTION, { | 1077 | deepEqual(playlist.attributes.RESOLUTION, { |
1054 | width:960, | 1078 | width:960, |
... | @@ -1058,7 +1082,7 @@ test('uses the lowest bitrate if no other is suitable', function() { | ... | @@ -1058,7 +1082,7 @@ test('uses the lowest bitrate if no other is suitable', function() { |
1058 | 1082 | ||
1059 | player.width(396); | 1083 | player.width(396); |
1060 | player.height(224); | 1084 | player.height(224); |
1061 | playlist = player.tech.hls.selectPlaylist(); | 1085 | playlist = player.tech_.hls.selectPlaylist(); |
1062 | 1086 | ||
1063 | deepEqual(playlist.attributes.RESOLUTION, { | 1087 | deepEqual(playlist.attributes.RESOLUTION, { |
1064 | width:396, | 1088 | width:396, |
... | @@ -1083,12 +1107,12 @@ test('selects the highest bitrate playlist when the player dimensions are ' + | ... | @@ -1083,12 +1107,12 @@ test('selects the highest bitrate playlist when the player dimensions are ' + |
1083 | '#EXT-X-STREAM-INF:BANDWIDTH=1,RESOLUTION=1x1\n' + | 1107 | '#EXT-X-STREAM-INF:BANDWIDTH=1,RESOLUTION=1x1\n' + |
1084 | 'media1.m3u8\n'); // master | 1108 | 'media1.m3u8\n'); // master |
1085 | standardXHRResponse(requests.shift()); // media | 1109 | standardXHRResponse(requests.shift()); // media |
1086 | player.tech.hls.bandwidth = 1e10; | 1110 | player.tech_.hls.bandwidth = 1e10; |
1087 | 1111 | ||
1088 | player.width(1024); | 1112 | player.width(1024); |
1089 | player.height(768); | 1113 | player.height(768); |
1090 | 1114 | ||
1091 | playlist = player.tech.hls.selectPlaylist(); | 1115 | playlist = player.tech_.hls.selectPlaylist(); |
1092 | 1116 | ||
1093 | equal(playlist.attributes.BANDWIDTH, | 1117 | equal(playlist.attributes.BANDWIDTH, |
1094 | 1000, | 1118 | 1000, |
... | @@ -1101,10 +1125,10 @@ test('does not download the next segment if the buffer is full', function() { | ... | @@ -1101,10 +1125,10 @@ test('does not download the next segment if the buffer is full', function() { |
1101 | src: 'manifest/media.m3u8', | 1125 | src: 'manifest/media.m3u8', |
1102 | type: 'application/vnd.apple.mpegurl' | 1126 | type: 'application/vnd.apple.mpegurl' |
1103 | }); | 1127 | }); |
1104 | player.tech.currentTime = function() { | 1128 | player.tech_.currentTime = function() { |
1105 | return currentTime; | 1129 | return currentTime; |
1106 | }; | 1130 | }; |
1107 | player.tech.buffered = function() { | 1131 | player.tech_.buffered = function() { |
1108 | return videojs.createTimeRange(0, currentTime + videojs.Hls.GOAL_BUFFER_LENGTH); | 1132 | return videojs.createTimeRange(0, currentTime + videojs.Hls.GOAL_BUFFER_LENGTH); |
1109 | }; | 1133 | }; |
1110 | openMediaSource(player); | 1134 | openMediaSource(player); |
... | @@ -1126,14 +1150,14 @@ test('downloads the next segment if the buffer is getting low', function() { | ... | @@ -1126,14 +1150,14 @@ test('downloads the next segment if the buffer is getting low', function() { |
1126 | standardXHRResponse(requests[0]); | 1150 | standardXHRResponse(requests[0]); |
1127 | standardXHRResponse(requests[1]); | 1151 | standardXHRResponse(requests[1]); |
1128 | 1152 | ||
1129 | strictEqual(requests.length, 2, 'did not make a request'); | 1153 | strictEqual(requests.length, 2, 'made two requests'); |
1130 | player.currentTime = function() { | 1154 | player.tech_.currentTime = function() { |
1131 | return 15; | 1155 | return 15; |
1132 | }; | 1156 | }; |
1133 | player.buffered = function() { | 1157 | player.tech_.buffered = function() { |
1134 | return videojs.createTimeRange(0, 19.999); | 1158 | return videojs.createTimeRange(0, 19.999); |
1135 | }; | 1159 | }; |
1136 | player.tech.hls.checkBuffer_(); | 1160 | player.tech_.hls.checkBuffer_(); |
1137 | 1161 | ||
1138 | standardXHRResponse(requests[2]); | 1162 | standardXHRResponse(requests[2]); |
1139 | 1163 | ||
... | @@ -1143,6 +1167,69 @@ test('downloads the next segment if the buffer is getting low', function() { | ... | @@ -1143,6 +1167,69 @@ test('downloads the next segment if the buffer is getting low', function() { |
1143 | 'made segment request'); | 1167 | 'made segment request'); |
1144 | }); | 1168 | }); |
1145 | 1169 | ||
1170 | test('buffers based on the correct TimeRange if multiple ranges exist', function() { | ||
1171 | player.tech_.currentTime = function() { | ||
1172 | return 8; | ||
1173 | }; | ||
1174 | |||
1175 | player.tech_.buffered = function() { | ||
1176 | return { | ||
1177 | start: function(num) { | ||
1178 | switch (num) { | ||
1179 | case 0: | ||
1180 | return 0; | ||
1181 | case 1: | ||
1182 | return 50; | ||
1183 | } | ||
1184 | }, | ||
1185 | end: function(num) { | ||
1186 | switch (num) { | ||
1187 | case 0: | ||
1188 | return 10; | ||
1189 | case 1: | ||
1190 | return 160; | ||
1191 | } | ||
1192 | }, | ||
1193 | length: 2 | ||
1194 | }; | ||
1195 | }; | ||
1196 | |||
1197 | player.src({ | ||
1198 | src: 'manifest/media.m3u8', | ||
1199 | type: 'application/vnd.apple.mpegurl' | ||
1200 | }); | ||
1201 | openMediaSource(player); | ||
1202 | |||
1203 | standardXHRResponse(requests[0]); | ||
1204 | standardXHRResponse(requests[1]); | ||
1205 | |||
1206 | strictEqual(requests.length, 2, 'made two requests'); | ||
1207 | strictEqual(requests[1].url, | ||
1208 | absoluteUrl('manifest/media-00001.ts'), | ||
1209 | 'made segment request'); | ||
1210 | |||
1211 | player.tech_.currentTime = function() { | ||
1212 | return 55; | ||
1213 | }; | ||
1214 | |||
1215 | player.tech_.hls.checkBuffer_(); | ||
1216 | |||
1217 | strictEqual(requests.length, 2, 'made no additional requests'); | ||
1218 | |||
1219 | player.tech_.currentTime = function() { | ||
1220 | return 134; | ||
1221 | }; | ||
1222 | |||
1223 | player.tech_.hls.checkBuffer_(); | ||
1224 | standardXHRResponse(requests[2]); | ||
1225 | |||
1226 | strictEqual(requests.length, 3, 'made three requests'); | ||
1227 | |||
1228 | strictEqual(requests[2].url, | ||
1229 | absoluteUrl('manifest/media-00002.ts'), | ||
1230 | 'made segment request'); | ||
1231 | }); | ||
1232 | |||
1146 | test('stops downloading segments at the end of the playlist', function() { | 1233 | test('stops downloading segments at the end of the playlist', function() { |
1147 | player.src({ | 1234 | player.src({ |
1148 | src: 'manifest/media.m3u8', | 1235 | src: 'manifest/media.m3u8', |
... | @@ -1151,7 +1238,7 @@ test('stops downloading segments at the end of the playlist', function() { | ... | @@ -1151,7 +1238,7 @@ test('stops downloading segments at the end of the playlist', function() { |
1151 | openMediaSource(player); | 1238 | openMediaSource(player); |
1152 | standardXHRResponse(requests[0]); | 1239 | standardXHRResponse(requests[0]); |
1153 | requests = []; | 1240 | requests = []; |
1154 | player.tech.hls.mediaIndex = 4; | 1241 | player.tech_.hls.mediaIndex = 4; |
1155 | player.trigger('timeupdate'); | 1242 | player.trigger('timeupdate'); |
1156 | 1243 | ||
1157 | strictEqual(requests.length, 0, 'no request is made'); | 1244 | strictEqual(requests.length, 0, 'no request is made'); |
... | @@ -1181,14 +1268,14 @@ test('only appends one segment at a time', function() { | ... | @@ -1181,14 +1268,14 @@ test('only appends one segment at a time', function() { |
1181 | standardXHRResponse(requests.pop()); // media.m3u8 | 1268 | standardXHRResponse(requests.pop()); // media.m3u8 |
1182 | standardXHRResponse(requests.pop()); // segment 0 | 1269 | standardXHRResponse(requests.pop()); // segment 0 |
1183 | 1270 | ||
1184 | player.tech.hls.sourceBuffer.updating = true; | 1271 | player.tech_.hls.sourceBuffer.updating = true; |
1185 | player.tech.hls.sourceBuffer.appendBuffer = function() { | 1272 | player.tech_.hls.sourceBuffer.appendBuffer = function() { |
1186 | appends++; | 1273 | appends++; |
1187 | }; | 1274 | }; |
1188 | 1275 | ||
1189 | player.tech.hls.checkBuffer_(); | 1276 | player.tech_.hls.checkBuffer_(); |
1190 | standardXHRResponse(requests.pop()); // segment 1 | 1277 | standardXHRResponse(requests.pop()); // segment 1 |
1191 | player.tech.hls.checkBuffer_(); // should be a no-op | 1278 | player.tech_.hls.checkBuffer_(); // should be a no-op |
1192 | equal(appends, 0, 'did not append while updating'); | 1279 | equal(appends, 0, 'did not append while updating'); |
1193 | }); | 1280 | }); |
1194 | 1281 | ||
... | @@ -1206,10 +1293,10 @@ QUnit.skip('records the min and max PTS values for a segment', function() { | ... | @@ -1206,10 +1293,10 @@ QUnit.skip('records the min and max PTS values for a segment', function() { |
1206 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); | 1293 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); |
1207 | standardXHRResponse(requests.pop()); // segment 0 | 1294 | standardXHRResponse(requests.pop()); // segment 0 |
1208 | 1295 | ||
1209 | equal(player.tech.hls.playlists.media().segments[0].minVideoPts, 0, 'recorded min video pts'); | 1296 | equal(player.tech_.hls.playlists.media().segments[0].minVideoPts, 0, 'recorded min video pts'); |
1210 | equal(player.tech.hls.playlists.media().segments[0].maxVideoPts, 10, 'recorded max video pts'); | 1297 | equal(player.tech_.hls.playlists.media().segments[0].maxVideoPts, 10, 'recorded max video pts'); |
1211 | equal(player.tech.hls.playlists.media().segments[0].minAudioPts, 0, 'recorded min audio pts'); | 1298 | equal(player.tech_.hls.playlists.media().segments[0].minAudioPts, 0, 'recorded min audio pts'); |
1212 | equal(player.tech.hls.playlists.media().segments[0].maxAudioPts, 10, 'recorded max audio pts'); | 1299 | equal(player.tech_.hls.playlists.media().segments[0].maxAudioPts, 10, 'recorded max audio pts'); |
1213 | }); | 1300 | }); |
1214 | 1301 | ||
1215 | QUnit.skip('records PTS values for video-only segments', function() { | 1302 | QUnit.skip('records PTS values for video-only segments', function() { |
... | @@ -1222,23 +1309,23 @@ QUnit.skip('records PTS values for video-only segments', function() { | ... | @@ -1222,23 +1309,23 @@ QUnit.skip('records PTS values for video-only segments', function() { |
1222 | openMediaSource(player); | 1309 | openMediaSource(player); |
1223 | standardXHRResponse(requests.pop()); // media.m3u8 | 1310 | standardXHRResponse(requests.pop()); // media.m3u8 |
1224 | 1311 | ||
1225 | player.tech.hls.segmentParser_.stats.aacTags = function() { | 1312 | player.tech_.hls.segmentParser_.stats.aacTags = function() { |
1226 | return 0; | 1313 | return 0; |
1227 | }; | 1314 | }; |
1228 | player.tech.hls.segmentParser_.stats.minAudioPts = function() { | 1315 | player.tech_.hls.segmentParser_.stats.minAudioPts = function() { |
1229 | throw new Error('No audio tags'); | 1316 | throw new Error('No audio tags'); |
1230 | }; | 1317 | }; |
1231 | player.tech.hls.segmentParser_.stats.maxAudioPts = function() { | 1318 | player.tech_.hls.segmentParser_.stats.maxAudioPts = function() { |
1232 | throw new Error('No audio tags'); | 1319 | throw new Error('No audio tags'); |
1233 | }; | 1320 | }; |
1234 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); | 1321 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); |
1235 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); | 1322 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); |
1236 | standardXHRResponse(requests.pop()); // segment 0 | 1323 | standardXHRResponse(requests.pop()); // segment 0 |
1237 | 1324 | ||
1238 | equal(player.tech.hls.playlists.media().segments[0].minVideoPts, 0, 'recorded min video pts'); | 1325 | equal(player.tech_.hls.playlists.media().segments[0].minVideoPts, 0, 'recorded min video pts'); |
1239 | equal(player.tech.hls.playlists.media().segments[0].maxVideoPts, 10, 'recorded max video pts'); | 1326 | equal(player.tech_.hls.playlists.media().segments[0].maxVideoPts, 10, 'recorded max video pts'); |
1240 | strictEqual(player.tech.hls.playlists.media().segments[0].minAudioPts, undefined, 'min audio pts is undefined'); | 1327 | strictEqual(player.tech_.hls.playlists.media().segments[0].minAudioPts, undefined, 'min audio pts is undefined'); |
1241 | strictEqual(player.tech.hls.playlists.media().segments[0].maxAudioPts, undefined, 'max audio pts is undefined'); | 1328 | strictEqual(player.tech_.hls.playlists.media().segments[0].maxAudioPts, undefined, 'max audio pts is undefined'); |
1242 | }); | 1329 | }); |
1243 | 1330 | ||
1244 | QUnit.skip('records PTS values for audio-only segments', function() { | 1331 | QUnit.skip('records PTS values for audio-only segments', function() { |
... | @@ -1251,23 +1338,23 @@ QUnit.skip('records PTS values for audio-only segments', function() { | ... | @@ -1251,23 +1338,23 @@ QUnit.skip('records PTS values for audio-only segments', function() { |
1251 | openMediaSource(player); | 1338 | openMediaSource(player); |
1252 | standardXHRResponse(requests.pop()); // media.m3u8 | 1339 | standardXHRResponse(requests.pop()); // media.m3u8 |
1253 | 1340 | ||
1254 | player.tech.hls.segmentParser_.stats.h264Tags = function() { | 1341 | player.tech_.hls.segmentParser_.stats.h264Tags = function() { |
1255 | return 0; | 1342 | return 0; |
1256 | }; | 1343 | }; |
1257 | player.tech.hls.segmentParser_.stats.minVideoPts = function() { | 1344 | player.tech_.hls.segmentParser_.stats.minVideoPts = function() { |
1258 | throw new Error('No video tags'); | 1345 | throw new Error('No video tags'); |
1259 | }; | 1346 | }; |
1260 | player.tech.hls.segmentParser_.stats.maxVideoPts = function() { | 1347 | player.tech_.hls.segmentParser_.stats.maxVideoPts = function() { |
1261 | throw new Error('No video tags'); | 1348 | throw new Error('No video tags'); |
1262 | }; | 1349 | }; |
1263 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); | 1350 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); |
1264 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); | 1351 | tags.push({ pts: 10, bytes: new Uint8Array(1) }); |
1265 | standardXHRResponse(requests.pop()); // segment 0 | 1352 | standardXHRResponse(requests.pop()); // segment 0 |
1266 | 1353 | ||
1267 | equal(player.tech.hls.playlists.media().segments[0].minAudioPts, 0, 'recorded min audio pts'); | 1354 | equal(player.tech_.hls.playlists.media().segments[0].minAudioPts, 0, 'recorded min audio pts'); |
1268 | equal(player.tech.hls.playlists.media().segments[0].maxAudioPts, 10, 'recorded max audio pts'); | 1355 | equal(player.tech_.hls.playlists.media().segments[0].maxAudioPts, 10, 'recorded max audio pts'); |
1269 | strictEqual(player.tech.hls.playlists.media().segments[0].minVideoPts, undefined, 'min video pts is undefined'); | 1356 | strictEqual(player.tech_.hls.playlists.media().segments[0].minVideoPts, undefined, 'min video pts is undefined'); |
1270 | strictEqual(player.tech.hls.playlists.media().segments[0].maxVideoPts, undefined, 'max video pts is undefined'); | 1357 | strictEqual(player.tech_.hls.playlists.media().segments[0].maxVideoPts, undefined, 'max video pts is undefined'); |
1271 | }); | 1358 | }); |
1272 | 1359 | ||
1273 | test('waits to download new segments until the media playlist is stable', function() { | 1360 | test('waits to download new segments until the media playlist is stable', function() { |
... | @@ -1278,24 +1365,24 @@ test('waits to download new segments until the media playlist is stable', functi | ... | @@ -1278,24 +1365,24 @@ test('waits to download new segments until the media playlist is stable', functi |
1278 | }); | 1365 | }); |
1279 | openMediaSource(player); | 1366 | openMediaSource(player); |
1280 | standardXHRResponse(requests.shift()); // master | 1367 | standardXHRResponse(requests.shift()); // master |
1281 | player.tech.hls.bandwidth = 1; // make sure we stay on the lowest variant | 1368 | player.tech_.hls.bandwidth = 1; // make sure we stay on the lowest variant |
1282 | standardXHRResponse(requests.shift()); // media | 1369 | standardXHRResponse(requests.shift()); // media |
1283 | 1370 | ||
1284 | // mock a playlist switch | 1371 | // mock a playlist switch |
1285 | media = player.tech.hls.playlists.media(); | 1372 | media = player.tech_.hls.playlists.media(); |
1286 | player.tech.hls.playlists.media = function() { | 1373 | player.tech_.hls.playlists.media = function() { |
1287 | return media; | 1374 | return media; |
1288 | }; | 1375 | }; |
1289 | player.tech.hls.playlists.state = 'SWITCHING_MEDIA'; | 1376 | player.tech_.hls.playlists.state = 'SWITCHING_MEDIA'; |
1290 | 1377 | ||
1291 | standardXHRResponse(requests.shift()); // segment 0 | 1378 | standardXHRResponse(requests.shift()); // segment 0 |
1292 | 1379 | ||
1293 | equal(requests.length, 0, 'no requests outstanding'); | 1380 | equal(requests.length, 0, 'no requests outstanding'); |
1294 | player.tech.hls.checkBuffer_(); | 1381 | player.tech_.hls.checkBuffer_(); |
1295 | equal(requests.length, 0, 'delays segment fetching'); | 1382 | equal(requests.length, 0, 'delays segment fetching'); |
1296 | 1383 | ||
1297 | player.tech.hls.playlists.state = 'LOADED_METADATA'; | 1384 | player.tech_.hls.playlists.state = 'LOADED_METADATA'; |
1298 | player.tech.hls.checkBuffer_(); | 1385 | player.tech_.hls.checkBuffer_(); |
1299 | equal(requests.length, 1, 'resumes segment fetching'); | 1386 | equal(requests.length, 1, 'resumes segment fetching'); |
1300 | }); | 1387 | }); |
1301 | 1388 | ||
... | @@ -1306,7 +1393,7 @@ test('cancels outstanding XHRs when seeking', function() { | ... | @@ -1306,7 +1393,7 @@ test('cancels outstanding XHRs when seeking', function() { |
1306 | }); | 1393 | }); |
1307 | openMediaSource(player); | 1394 | openMediaSource(player); |
1308 | standardXHRResponse(requests[0]); | 1395 | standardXHRResponse(requests[0]); |
1309 | player.tech.hls.media = { | 1396 | player.tech_.hls.media = { |
1310 | segments: [{ | 1397 | segments: [{ |
1311 | uri: '0.ts', | 1398 | uri: '0.ts', |
1312 | duration: 10 | 1399 | duration: 10 |
... | @@ -1337,7 +1424,7 @@ test('when outstanding XHRs are cancelled, they get aborted properly', function( | ... | @@ -1337,7 +1424,7 @@ test('when outstanding XHRs are cancelled, they get aborted properly', function( |
1337 | // trigger a segment download request | 1424 | // trigger a segment download request |
1338 | player.trigger('timeupdate'); | 1425 | player.trigger('timeupdate'); |
1339 | 1426 | ||
1340 | player.tech.hls.segmentXhr_.onreadystatechange = function() { | 1427 | player.tech_.hls.segmentXhr_.onreadystatechange = function() { |
1341 | readystatechanges++; | 1428 | readystatechanges++; |
1342 | }; | 1429 | }; |
1343 | 1430 | ||
... | @@ -1347,7 +1434,7 @@ test('when outstanding XHRs are cancelled, they get aborted properly', function( | ... | @@ -1347,7 +1434,7 @@ test('when outstanding XHRs are cancelled, they get aborted properly', function( |
1347 | 1434 | ||
1348 | ok(requests[1].aborted, 'XHR aborted'); | 1435 | ok(requests[1].aborted, 'XHR aborted'); |
1349 | strictEqual(requests.length, 3, 'opened new XHR'); | 1436 | strictEqual(requests.length, 3, 'opened new XHR'); |
1350 | notEqual(player.tech.hls.segmentXhr_.url, requests[1].url, 'a new segment is request that is not the aborted one'); | 1437 | notEqual(player.tech_.hls.segmentXhr_.url, requests[1].url, 'a new segment is request that is not the aborted one'); |
1351 | strictEqual(readystatechanges, 0, 'onreadystatechange was not called'); | 1438 | strictEqual(readystatechanges, 0, 'onreadystatechange was not called'); |
1352 | }); | 1439 | }); |
1353 | 1440 | ||
... | @@ -1369,15 +1456,15 @@ test('segmentXhr is properly nulled out when dispose is called', function() { | ... | @@ -1369,15 +1456,15 @@ test('segmentXhr is properly nulled out when dispose is called', function() { |
1369 | // trigger a segment download request | 1456 | // trigger a segment download request |
1370 | player.trigger('timeupdate'); | 1457 | player.trigger('timeupdate'); |
1371 | 1458 | ||
1372 | player.tech.hls.segmentXhr_.onreadystatechange = function() { | 1459 | player.tech_.hls.segmentXhr_.onreadystatechange = function() { |
1373 | readystatechanges++; | 1460 | readystatechanges++; |
1374 | }; | 1461 | }; |
1375 | 1462 | ||
1376 | player.tech.hls.dispose(); | 1463 | player.tech_.hls.dispose(); |
1377 | 1464 | ||
1378 | ok(requests[1].aborted, 'XHR aborted'); | 1465 | ok(requests[1].aborted, 'XHR aborted'); |
1379 | strictEqual(requests.length, 2, 'did not open a new XHR'); | 1466 | strictEqual(requests.length, 2, 'did not open a new XHR'); |
1380 | equal(player.tech.hls.segmentXhr_, null, 'the segment xhr is nulled out'); | 1467 | equal(player.tech_.hls.segmentXhr_, null, 'the segment xhr is nulled out'); |
1381 | strictEqual(readystatechanges, 0, 'onreadystatechange was not called'); | 1468 | strictEqual(readystatechanges, 0, 'onreadystatechange was not called'); |
1382 | 1469 | ||
1383 | Flash.prototype.dispose = oldDispose; | 1470 | Flash.prototype.dispose = oldDispose; |
... | @@ -1392,9 +1479,9 @@ QUnit.skip('exposes in-band metadata events as cues', function() { | ... | @@ -1392,9 +1479,9 @@ QUnit.skip('exposes in-band metadata events as cues', function() { |
1392 | }); | 1479 | }); |
1393 | openMediaSource(player); | 1480 | openMediaSource(player); |
1394 | 1481 | ||
1395 | player.tech.hls.segmentParser_.parseSegmentBinaryData = function() { | 1482 | player.tech_.hls.segmentParser_.parseSegmentBinaryData = function() { |
1396 | // trigger a metadata event | 1483 | // trigger a metadata event |
1397 | player.tech.hls.segmentParser_.metadataStream.trigger('data', { | 1484 | player.tech_.hls.segmentParser_.metadataStream.trigger('data', { |
1398 | pts: 2000, | 1485 | pts: 2000, |
1399 | data: new Uint8Array([]), | 1486 | data: new Uint8Array([]), |
1400 | frames: [{ | 1487 | frames: [{ |
... | @@ -1448,9 +1535,9 @@ QUnit.skip('only adds in-band cues the first time they are encountered', functio | ... | @@ -1448,9 +1535,9 @@ QUnit.skip('only adds in-band cues the first time they are encountered', functio |
1448 | }); | 1535 | }); |
1449 | openMediaSource(player); | 1536 | openMediaSource(player); |
1450 | 1537 | ||
1451 | player.tech.hls.segmentParser_.parseSegmentBinaryData = function() { | 1538 | player.tech_.hls.segmentParser_.parseSegmentBinaryData = function() { |
1452 | // trigger a metadata event | 1539 | // trigger a metadata event |
1453 | player.tech.hls.segmentParser_.metadataStream.trigger('data', { | 1540 | player.tech_.hls.segmentParser_.metadataStream.trigger('data', { |
1454 | pts: 2000, | 1541 | pts: 2000, |
1455 | data: new Uint8Array([]), | 1542 | data: new Uint8Array([]), |
1456 | frames: [{ | 1543 | frames: [{ |
... | @@ -1463,7 +1550,7 @@ QUnit.skip('only adds in-band cues the first time they are encountered', functio | ... | @@ -1463,7 +1550,7 @@ QUnit.skip('only adds in-band cues the first time they are encountered', functio |
1463 | standardXHRResponse(requests.shift()); | 1550 | standardXHRResponse(requests.shift()); |
1464 | // seek back to the first segment | 1551 | // seek back to the first segment |
1465 | player.currentTime(0); | 1552 | player.currentTime(0); |
1466 | player.tech.hls.trigger('seeking'); | 1553 | player.tech_.hls.trigger('seeking'); |
1467 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); | 1554 | tags.push({ pts: 0, bytes: new Uint8Array(1) }); |
1468 | standardXHRResponse(requests.shift()); | 1555 | standardXHRResponse(requests.shift()); |
1469 | 1556 | ||
... | @@ -1483,10 +1570,10 @@ QUnit.skip('clears in-band cues ahead of current time on seek', function() { | ... | @@ -1483,10 +1570,10 @@ QUnit.skip('clears in-band cues ahead of current time on seek', function() { |
1483 | }); | 1570 | }); |
1484 | openMediaSource(player); | 1571 | openMediaSource(player); |
1485 | 1572 | ||
1486 | player.tech.hls.segmentParser_.parseSegmentBinaryData = function() { | 1573 | player.tech_.hls.segmentParser_.parseSegmentBinaryData = function() { |
1487 | // trigger a metadata event | 1574 | // trigger a metadata event |
1488 | while (events.length) { | 1575 | while (events.length) { |
1489 | player.tech.hls.segmentParser_.metadataStream.trigger('data', events.shift()); | 1576 | player.tech_.hls.segmentParser_.metadataStream.trigger('data', events.shift()); |
1490 | } | 1577 | } |
1491 | }; | 1578 | }; |
1492 | standardXHRResponse(requests.shift()); // media | 1579 | standardXHRResponse(requests.shift()); // media |
... | @@ -1519,7 +1606,7 @@ QUnit.skip('clears in-band cues ahead of current time on seek', function() { | ... | @@ -1519,7 +1606,7 @@ QUnit.skip('clears in-band cues ahead of current time on seek', function() { |
1519 | value: 'cue 2' | 1606 | value: 'cue 2' |
1520 | }] | 1607 | }] |
1521 | }); | 1608 | }); |
1522 | player.tech.hls.checkBuffer_(); | 1609 | player.tech_.hls.checkBuffer_(); |
1523 | standardXHRResponse(requests.shift()); // segment 1 | 1610 | standardXHRResponse(requests.shift()); // segment 1 |
1524 | 1611 | ||
1525 | track = player.textTracks()[0]; | 1612 | track = player.textTracks()[0]; |
... | @@ -1541,9 +1628,9 @@ QUnit.skip('translates ID3 PTS values to cue media timeline positions', function | ... | @@ -1541,9 +1628,9 @@ QUnit.skip('translates ID3 PTS values to cue media timeline positions', function |
1541 | }); | 1628 | }); |
1542 | openMediaSource(player); | 1629 | openMediaSource(player); |
1543 | 1630 | ||
1544 | player.tech.hls.segmentParser_.parseSegmentBinaryData = function() { | 1631 | player.tech_.hls.segmentParser_.parseSegmentBinaryData = function() { |
1545 | // trigger a metadata event | 1632 | // trigger a metadata event |
1546 | player.tech.hls.segmentParser_.metadataStream.trigger('data', { | 1633 | player.tech_.hls.segmentParser_.metadataStream.trigger('data', { |
1547 | pts: 5 * 1000, | 1634 | pts: 5 * 1000, |
1548 | data: new Uint8Array([]), | 1635 | data: new Uint8Array([]), |
1549 | frames: [{ | 1636 | frames: [{ |
... | @@ -1636,10 +1723,10 @@ QUnit.skip('translates ID3 PTS values across discontinuities', function() { | ... | @@ -1636,10 +1723,10 @@ QUnit.skip('translates ID3 PTS values across discontinuities', function() { |
1636 | }); | 1723 | }); |
1637 | openMediaSource(player); | 1724 | openMediaSource(player); |
1638 | 1725 | ||
1639 | player.tech.hls.segmentParser_.parseSegmentBinaryData = function() { | 1726 | player.tech_.hls.segmentParser_.parseSegmentBinaryData = function() { |
1640 | // trigger a metadata event | 1727 | // trigger a metadata event |
1641 | if (events.length) { | 1728 | if (events.length) { |
1642 | player.tech.hls.segmentParser_.metadataStream.trigger('data', events.shift()); | 1729 | player.tech_.hls.segmentParser_.metadataStream.trigger('data', events.shift()); |
1643 | } | 1730 | } |
1644 | }; | 1731 | }; |
1645 | 1732 | ||
... | @@ -1677,7 +1764,7 @@ QUnit.skip('translates ID3 PTS values across discontinuities', function() { | ... | @@ -1677,7 +1764,7 @@ QUnit.skip('translates ID3 PTS values across discontinuities', function() { |
1677 | value: 'cue 1' | 1764 | value: 'cue 1' |
1678 | }] | 1765 | }] |
1679 | }); | 1766 | }); |
1680 | player.tech.hls.checkBuffer_(); | 1767 | player.tech_.hls.checkBuffer_(); |
1681 | standardXHRResponse(requests.shift()); | 1768 | standardXHRResponse(requests.shift()); |
1682 | 1769 | ||
1683 | track = player.textTracks()[0]; | 1770 | track = player.textTracks()[0]; |
... | @@ -1734,16 +1821,16 @@ test('adjusts the segment offsets for out-of-buffer seeking', function() { | ... | @@ -1734,16 +1821,16 @@ test('adjusts the segment offsets for out-of-buffer seeking', function() { |
1734 | }); | 1821 | }); |
1735 | openMediaSource(player); | 1822 | openMediaSource(player); |
1736 | standardXHRResponse(requests.shift()); // media | 1823 | standardXHRResponse(requests.shift()); // media |
1737 | player.tech.hls.sourceBuffer.buffered = function() { | 1824 | player.tech_.hls.sourceBuffer.buffered = function() { |
1738 | return videojs.createTimeRange(0, 20); | 1825 | return videojs.createTimeRange(0, 20); |
1739 | }; | 1826 | }; |
1740 | equal(player.tech.hls.mediaIndex, 0, 'starts at zero'); | 1827 | equal(player.tech_.hls.mediaIndex, 0, 'starts at zero'); |
1741 | 1828 | ||
1742 | player.tech.setCurrentTime(35); | 1829 | player.tech_.setCurrentTime(35); |
1743 | clock.tick(1); | 1830 | clock.tick(1); |
1744 | // drop the aborted segment | 1831 | // drop the aborted segment |
1745 | requests.shift(); | 1832 | requests.shift(); |
1746 | equal(player.tech.hls.mediaIndex, 3, 'moved the mediaIndex'); | 1833 | equal(player.tech_.hls.mediaIndex, 3, 'moved the mediaIndex'); |
1747 | standardXHRResponse(requests.shift()); | 1834 | standardXHRResponse(requests.shift()); |
1748 | }); | 1835 | }); |
1749 | 1836 | ||
... | @@ -1754,7 +1841,7 @@ test('seeks between buffered time ranges', function() { | ... | @@ -1754,7 +1841,7 @@ test('seeks between buffered time ranges', function() { |
1754 | }); | 1841 | }); |
1755 | openMediaSource(player); | 1842 | openMediaSource(player); |
1756 | standardXHRResponse(requests.shift()); // media | 1843 | standardXHRResponse(requests.shift()); // media |
1757 | player.tech.buffered = function() { | 1844 | player.tech_.buffered = function() { |
1758 | return { | 1845 | return { |
1759 | length: 2, | 1846 | length: 2, |
1760 | ranges_: [[0, 10], [20, 30]], | 1847 | ranges_: [[0, 10], [20, 30]], |
... | @@ -1767,11 +1854,11 @@ test('seeks between buffered time ranges', function() { | ... | @@ -1767,11 +1854,11 @@ test('seeks between buffered time ranges', function() { |
1767 | }; | 1854 | }; |
1768 | }; | 1855 | }; |
1769 | 1856 | ||
1770 | player.tech.setCurrentTime(15); | 1857 | player.tech_.setCurrentTime(15); |
1771 | clock.tick(1); | 1858 | clock.tick(1); |
1772 | // drop the aborted segment | 1859 | // drop the aborted segment |
1773 | requests.shift(); | 1860 | requests.shift(); |
1774 | equal(player.tech.hls.mediaIndex, 1, 'updated the mediaIndex'); | 1861 | equal(player.tech_.hls.mediaIndex, 1, 'updated the mediaIndex'); |
1775 | standardXHRResponse(requests.shift()); | 1862 | standardXHRResponse(requests.shift()); |
1776 | }); | 1863 | }); |
1777 | 1864 | ||
... | @@ -1783,14 +1870,14 @@ test('does not modify the media index for in-buffer seeking', function() { | ... | @@ -1783,14 +1870,14 @@ test('does not modify the media index for in-buffer seeking', function() { |
1783 | }); | 1870 | }); |
1784 | openMediaSource(player); | 1871 | openMediaSource(player); |
1785 | standardXHRResponse(requests.shift()); | 1872 | standardXHRResponse(requests.shift()); |
1786 | player.tech.buffered = function() { | 1873 | player.tech_.buffered = function() { |
1787 | return videojs.createTimeRange(0, 20); | 1874 | return videojs.createTimeRange(0, 20); |
1788 | }; | 1875 | }; |
1789 | mediaIndex = player.tech.hls.mediaIndex; | 1876 | mediaIndex = player.tech_.hls.mediaIndex; |
1790 | 1877 | ||
1791 | player.tech.setCurrentTime(11); | 1878 | player.tech_.setCurrentTime(11); |
1792 | clock.tick(1); | 1879 | clock.tick(1); |
1793 | equal(player.tech.hls.mediaIndex, mediaIndex, 'did not interrupt buffering'); | 1880 | equal(player.tech_.hls.mediaIndex, mediaIndex, 'did not interrupt buffering'); |
1794 | equal(requests.length, 1, 'did not abort the outstanding request'); | 1881 | equal(requests.length, 1, 'did not abort the outstanding request'); |
1795 | }); | 1882 | }); |
1796 | 1883 | ||
... | @@ -1802,7 +1889,7 @@ test('playlist 404 should end stream with a network error', function() { | ... | @@ -1802,7 +1889,7 @@ test('playlist 404 should end stream with a network error', function() { |
1802 | openMediaSource(player); | 1889 | openMediaSource(player); |
1803 | requests.pop().respond(404); | 1890 | requests.pop().respond(404); |
1804 | 1891 | ||
1805 | equal(player.tech.hls.mediaSource.error_, 'network', 'set a network error'); | 1892 | equal(player.tech_.hls.mediaSource.error_, 'network', 'set a network error'); |
1806 | }); | 1893 | }); |
1807 | 1894 | ||
1808 | test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { | 1895 | test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { |
... | @@ -1815,8 +1902,8 @@ test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { | ... | @@ -1815,8 +1902,8 @@ test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { |
1815 | 1902 | ||
1816 | standardXHRResponse(requests[0]); | 1903 | standardXHRResponse(requests[0]); |
1817 | requests[1].respond(404); | 1904 | requests[1].respond(404); |
1818 | ok(player.tech.hls.error.message, 'an error message is available'); | 1905 | ok(player.tech_.hls.error.message, 'an error message is available'); |
1819 | equal(2, player.tech.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_NETWORK'); | 1906 | equal(2, player.tech_.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_NETWORK'); |
1820 | }); | 1907 | }); |
1821 | 1908 | ||
1822 | test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { | 1909 | test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { |
... | @@ -1829,8 +1916,8 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { | ... | @@ -1829,8 +1916,8 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { |
1829 | 1916 | ||
1830 | standardXHRResponse(requests[0]); | 1917 | standardXHRResponse(requests[0]); |
1831 | requests[1].respond(500); | 1918 | requests[1].respond(500); |
1832 | ok(player.tech.hls.error.message, 'an error message is available'); | 1919 | ok(player.tech_.hls.error.message, 'an error message is available'); |
1833 | equal(4, player.tech.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_ABORTED'); | 1920 | equal(4, player.tech_.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_ABORTED'); |
1834 | }); | 1921 | }); |
1835 | 1922 | ||
1836 | test('seeking in an empty playlist is a non-erroring noop', function() { | 1923 | test('seeking in an empty playlist is a non-erroring noop', function() { |
... | @@ -1845,7 +1932,7 @@ test('seeking in an empty playlist is a non-erroring noop', function() { | ... | @@ -1845,7 +1932,7 @@ test('seeking in an empty playlist is a non-erroring noop', function() { |
1845 | requests.shift().respond(200, null, '#EXTM3U\n'); | 1932 | requests.shift().respond(200, null, '#EXTM3U\n'); |
1846 | 1933 | ||
1847 | requestsLength = requests.length; | 1934 | requestsLength = requests.length; |
1848 | player.tech.setCurrentTime(183); | 1935 | player.tech_.setCurrentTime(183); |
1849 | clock.tick(1); | 1936 | clock.tick(1); |
1850 | 1937 | ||
1851 | equal(requests.length, requestsLength, 'made no additional requests'); | 1938 | equal(requests.length, requestsLength, 'made no additional requests'); |
... | @@ -1860,7 +1947,7 @@ test('duration is Infinity for live playlists', function() { | ... | @@ -1860,7 +1947,7 @@ test('duration is Infinity for live playlists', function() { |
1860 | 1947 | ||
1861 | standardXHRResponse(requests[0]); | 1948 | standardXHRResponse(requests[0]); |
1862 | 1949 | ||
1863 | strictEqual(player.tech.hls.mediaSource.duration, | 1950 | strictEqual(player.tech_.hls.mediaSource.duration, |
1864 | Infinity, | 1951 | Infinity, |
1865 | 'duration is infinity'); | 1952 | 'duration is infinity'); |
1866 | }); | 1953 | }); |
... | @@ -1871,7 +1958,7 @@ test('updates the media index when a playlist reloads', function() { | ... | @@ -1871,7 +1958,7 @@ test('updates the media index when a playlist reloads', function() { |
1871 | type: 'application/vnd.apple.mpegurl' | 1958 | type: 'application/vnd.apple.mpegurl' |
1872 | }); | 1959 | }); |
1873 | openMediaSource(player); | 1960 | openMediaSource(player); |
1874 | player.tech.trigger('play'); | 1961 | player.tech_.trigger('play'); |
1875 | 1962 | ||
1876 | requests[0].respond(200, null, | 1963 | requests[0].respond(200, null, |
1877 | '#EXTM3U\n' + | 1964 | '#EXTM3U\n' + |
... | @@ -1883,9 +1970,9 @@ test('updates the media index when a playlist reloads', function() { | ... | @@ -1883,9 +1970,9 @@ test('updates the media index when a playlist reloads', function() { |
1883 | '2.ts\n'); | 1970 | '2.ts\n'); |
1884 | standardXHRResponse(requests[1]); | 1971 | standardXHRResponse(requests[1]); |
1885 | // play the stream until 2.ts is playing | 1972 | // play the stream until 2.ts is playing |
1886 | player.tech.hls.mediaIndex = 3; | 1973 | player.tech_.hls.mediaIndex = 3; |
1887 | // trigger a playlist refresh | 1974 | // trigger a playlist refresh |
1888 | player.tech.hls.playlists.trigger('mediaupdatetimeout'); | 1975 | player.tech_.hls.playlists.trigger('mediaupdatetimeout'); |
1889 | requests[2].respond(200, null, | 1976 | requests[2].respond(200, null, |
1890 | '#EXTM3U\n' + | 1977 | '#EXTM3U\n' + |
1891 | '#EXT-X-MEDIA-SEQUENCE:1\n' + | 1978 | '#EXT-X-MEDIA-SEQUENCE:1\n' + |
... | @@ -1896,7 +1983,7 @@ test('updates the media index when a playlist reloads', function() { | ... | @@ -1896,7 +1983,7 @@ test('updates the media index when a playlist reloads', function() { |
1896 | '#EXTINF:10,\n' + | 1983 | '#EXTINF:10,\n' + |
1897 | '3.ts\n'); | 1984 | '3.ts\n'); |
1898 | 1985 | ||
1899 | strictEqual(player.tech.hls.mediaIndex, 2, 'mediaIndex is updated after the reload'); | 1986 | strictEqual(player.tech_.hls.mediaIndex, 2, 'mediaIndex is updated after the reload'); |
1900 | }); | 1987 | }); |
1901 | 1988 | ||
1902 | test('live playlist starts three target durations before live', function() { | 1989 | test('live playlist starts three target durations before live', function() { |
... | @@ -1922,12 +2009,12 @@ test('live playlist starts three target durations before live', function() { | ... | @@ -1922,12 +2009,12 @@ test('live playlist starts three target durations before live', function() { |
1922 | 2009 | ||
1923 | equal(requests.length, 0, 'no outstanding segment request'); | 2010 | equal(requests.length, 0, 'no outstanding segment request'); |
1924 | 2011 | ||
1925 | player.tech.paused = function() { return false; }; | 2012 | player.tech_.paused = function() { return false; }; |
1926 | player.tech.trigger('play'); | 2013 | player.tech_.trigger('play'); |
1927 | clock.tick(1); | 2014 | clock.tick(1); |
1928 | mediaPlaylist = player.tech.hls.playlists.media(); | 2015 | mediaPlaylist = player.tech_.hls.playlists.media(); |
1929 | equal(player.tech.hls.mediaIndex, 1, 'mediaIndex is updated at play'); | 2016 | equal(player.tech_.hls.mediaIndex, 1, 'mediaIndex is updated at play'); |
1930 | equal(player.currentTime(), player.tech.hls.seekable().end(0), 'seeked to the seekable end'); | 2017 | equal(player.currentTime(), player.tech_.hls.seekable().end(0), 'seeked to the seekable end'); |
1931 | 2018 | ||
1932 | equal(requests.length, 1, 'begins buffering'); | 2019 | equal(requests.length, 1, 'begins buffering'); |
1933 | }); | 2020 | }); |
... | @@ -1959,14 +2046,14 @@ test('live playlist starts with correct currentTime value', function() { | ... | @@ -1959,14 +2046,14 @@ test('live playlist starts with correct currentTime value', function() { |
1959 | 2046 | ||
1960 | standardXHRResponse(requests[0]); | 2047 | standardXHRResponse(requests[0]); |
1961 | 2048 | ||
1962 | player.tech.hls.playlists.trigger('loadedmetadata'); | 2049 | player.tech_.hls.playlists.trigger('loadedmetadata'); |
1963 | 2050 | ||
1964 | player.tech.paused = function() { return false; }; | 2051 | player.tech_.paused = function() { return false; }; |
1965 | player.tech.trigger('play'); | 2052 | player.tech_.trigger('play'); |
1966 | clock.tick(1); | 2053 | clock.tick(1); |
1967 | 2054 | ||
1968 | strictEqual(player.currentTime(), | 2055 | strictEqual(player.currentTime(), |
1969 | videojs.Hls.Playlist.seekable(player.tech.hls.playlists.media()).end(0), | 2056 | videojs.Hls.Playlist.seekable(player.tech_.hls.playlists.media()).end(0), |
1970 | 'currentTime is updated at playback'); | 2057 | 'currentTime is updated at playback'); |
1971 | }); | 2058 | }); |
1972 | 2059 | ||
... | @@ -1985,22 +2072,22 @@ test('resets the time to a seekable position when resuming a live stream ' + | ... | @@ -1985,22 +2072,22 @@ test('resets the time to a seekable position when resuming a live stream ' + |
1985 | '16.ts\n'); | 2072 | '16.ts\n'); |
1986 | // mock out the player to simulate a live stream that has been | 2073 | // mock out the player to simulate a live stream that has been |
1987 | // playing for awhile | 2074 | // playing for awhile |
1988 | player.tech.hls.seekable = function() { | 2075 | player.tech_.hls.seekable = function() { |
1989 | return videojs.createTimeRange(160, 170); | 2076 | return videojs.createTimeRange(160, 170); |
1990 | }; | 2077 | }; |
1991 | player.tech.setCurrentTime = function(time) { | 2078 | player.tech_.setCurrentTime = function(time) { |
1992 | if (time !== undefined) { | 2079 | if (time !== undefined) { |
1993 | seekTarget = time; | 2080 | seekTarget = time; |
1994 | } | 2081 | } |
1995 | }; | 2082 | }; |
1996 | player.tech.played = function() { | 2083 | player.tech_.played = function() { |
1997 | return videojs.createTimeRange(120, 170); | 2084 | return videojs.createTimeRange(120, 170); |
1998 | }; | 2085 | }; |
1999 | player.tech.trigger('playing'); | 2086 | player.tech_.trigger('playing'); |
2000 | 2087 | ||
2001 | player.tech.trigger('play'); | 2088 | player.tech_.trigger('play'); |
2002 | equal(seekTarget, player.seekable().start(0), 'seeked to the start of seekable'); | 2089 | equal(seekTarget, player.seekable().start(0), 'seeked to the start of seekable'); |
2003 | player.tech.trigger('seeked'); | 2090 | player.tech_.trigger('seeked'); |
2004 | }); | 2091 | }); |
2005 | 2092 | ||
2006 | test('mediaIndex is zero before the first segment loads', function() { | 2093 | test('mediaIndex is zero before the first segment loads', function() { |
... | @@ -2014,7 +2101,7 @@ test('mediaIndex is zero before the first segment loads', function() { | ... | @@ -2014,7 +2101,7 @@ test('mediaIndex is zero before the first segment loads', function() { |
2014 | }); | 2101 | }); |
2015 | openMediaSource(player); | 2102 | openMediaSource(player); |
2016 | 2103 | ||
2017 | strictEqual(player.tech.hls.mediaIndex, 0, 'mediaIndex is zero'); | 2104 | strictEqual(player.tech_.hls.mediaIndex, 0, 'mediaIndex is zero'); |
2018 | }); | 2105 | }); |
2019 | 2106 | ||
2020 | test('mediaIndex returns correctly at playlist boundaries', function() { | 2107 | test('mediaIndex returns correctly at playlist boundaries', function() { |
... | @@ -2027,13 +2114,13 @@ test('mediaIndex returns correctly at playlist boundaries', function() { | ... | @@ -2027,13 +2114,13 @@ test('mediaIndex returns correctly at playlist boundaries', function() { |
2027 | standardXHRResponse(requests.shift()); // master | 2114 | standardXHRResponse(requests.shift()); // master |
2028 | standardXHRResponse(requests.shift()); // media | 2115 | standardXHRResponse(requests.shift()); // media |
2029 | 2116 | ||
2030 | strictEqual(player.tech.hls.mediaIndex, 0, 'mediaIndex is zero at first segment'); | 2117 | strictEqual(player.tech_.hls.mediaIndex, 0, 'mediaIndex is zero at first segment'); |
2031 | 2118 | ||
2032 | // seek to end | 2119 | // seek to end |
2033 | player.tech.setCurrentTime(40); | 2120 | player.tech_.setCurrentTime(40); |
2034 | clock.tick(1); | 2121 | clock.tick(1); |
2035 | 2122 | ||
2036 | strictEqual(player.tech.hls.mediaIndex, 3, 'mediaIndex is 3 at last segment'); | 2123 | strictEqual(player.tech_.hls.mediaIndex, 3, 'mediaIndex is 3 at last segment'); |
2037 | }); | 2124 | }); |
2038 | 2125 | ||
2039 | test('reloads out-of-date live playlists when switching variants', function() { | 2126 | test('reloads out-of-date live playlists when switching variants', function() { |
... | @@ -2043,7 +2130,7 @@ test('reloads out-of-date live playlists when switching variants', function() { | ... | @@ -2043,7 +2130,7 @@ test('reloads out-of-date live playlists when switching variants', function() { |
2043 | }); | 2130 | }); |
2044 | openMediaSource(player); | 2131 | openMediaSource(player); |
2045 | 2132 | ||
2046 | player.tech.hls.master = { | 2133 | player.tech_.hls.master = { |
2047 | playlists: [{ | 2134 | playlists: [{ |
2048 | mediaSequence: 15, | 2135 | mediaSequence: 15, |
2049 | segments: [1, 1, 1] | 2136 | segments: [1, 1, 1] |
... | @@ -2054,7 +2141,7 @@ test('reloads out-of-date live playlists when switching variants', function() { | ... | @@ -2054,7 +2141,7 @@ test('reloads out-of-date live playlists when switching variants', function() { |
2054 | }] | 2141 | }] |
2055 | }; | 2142 | }; |
2056 | // playing segment 15 on playlist zero | 2143 | // playing segment 15 on playlist zero |
2057 | player.tech.hls.media = player.tech.hls.master.playlists[0]; | 2144 | player.tech_.hls.media = player.tech_.hls.master.playlists[0]; |
2058 | player.mediaIndex = 1; | 2145 | player.mediaIndex = 1; |
2059 | window.manifests['variant-update'] = '#EXTM3U\n' + | 2146 | window.manifests['variant-update'] = '#EXTM3U\n' + |
2060 | '#EXT-X-MEDIA-SEQUENCE:16\n' + | 2147 | '#EXT-X-MEDIA-SEQUENCE:16\n' + |
... | @@ -2064,8 +2151,8 @@ test('reloads out-of-date live playlists when switching variants', function() { | ... | @@ -2064,8 +2151,8 @@ test('reloads out-of-date live playlists when switching variants', function() { |
2064 | '17.ts\n'; | 2151 | '17.ts\n'; |
2065 | 2152 | ||
2066 | // switch playlists | 2153 | // switch playlists |
2067 | player.tech.hls.selectPlaylist = function() { | 2154 | player.tech_.hls.selectPlaylist = function() { |
2068 | return player.tech.hls.master.playlists[1]; | 2155 | return player.tech_.hls.master.playlists[1]; |
2069 | }; | 2156 | }; |
2070 | // timeupdate downloads segment 16 then switches playlists | 2157 | // timeupdate downloads segment 16 then switches playlists |
2071 | player.trigger('timeupdate'); | 2158 | player.trigger('timeupdate'); |
... | @@ -2149,7 +2236,7 @@ test('clears the segment buffer on seek', function() { | ... | @@ -2149,7 +2236,7 @@ test('clears the segment buffer on seek', function() { |
2149 | } | 2236 | } |
2150 | return currentTime; | 2237 | return currentTime; |
2151 | }; | 2238 | }; |
2152 | player.tech.buffered = function() { | 2239 | player.tech_.buffered = function() { |
2153 | return videojs.createTimeRange(); | 2240 | return videojs.createTimeRange(); |
2154 | }; | 2241 | }; |
2155 | 2242 | ||
... | @@ -2169,20 +2256,52 @@ test('clears the segment buffer on seek', function() { | ... | @@ -2169,20 +2256,52 @@ test('clears the segment buffer on seek', function() { |
2169 | clock.tick(6000); | 2256 | clock.tick(6000); |
2170 | 2257 | ||
2171 | standardXHRResponse(requests.pop()); // 2.ts | 2258 | standardXHRResponse(requests.pop()); // 2.ts |
2172 | equal(player.tech.hls.segmentBuffer_.length, 2, 'started fetching segments'); | 2259 | equal(player.tech_.hls.segmentBuffer_.length, 2, 'started fetching segments'); |
2173 | 2260 | ||
2174 | // seek back to the beginning | 2261 | // seek back to the beginning |
2175 | player.currentTime(0); | 2262 | player.currentTime(0); |
2176 | clock.tick(1); | 2263 | clock.tick(1); |
2177 | equal(player.tech.hls.segmentBuffer_.length, 0, 'cleared the segment buffer'); | 2264 | equal(player.tech_.hls.segmentBuffer_.length, 0, 'cleared the segment buffer'); |
2265 | }); | ||
2266 | |||
2267 | test('calls mediaSource\'s timestampOffset on discontinuity', function() { | ||
2268 | player.src({ | ||
2269 | src: 'discontinuity.m3u8', | ||
2270 | type: 'application/vnd.apple.mpegurl' | ||
2271 | }); | ||
2272 | openMediaSource(player); | ||
2273 | player.play(); | ||
2274 | player.tech_.buffered = function() { | ||
2275 | return videojs.createTimeRange(0, 10); | ||
2276 | }; | ||
2277 | |||
2278 | requests.pop().respond(200, null, | ||
2279 | '#EXTM3U\n' + | ||
2280 | '#EXTINF:10,0\n' + | ||
2281 | '1.ts\n' + | ||
2282 | '#EXT-X-DISCONTINUITY\n' + | ||
2283 | '#EXTINF:10,0\n' + | ||
2284 | '2.ts\n' + | ||
2285 | '#EXT-X-ENDLIST\n'); | ||
2286 | standardXHRResponse(requests.pop()); // 1.ts | ||
2287 | player.tech_.hls.sourceBuffer.timestampOffset = 0; | ||
2288 | |||
2289 | equal(player.tech_.hls.sourceBuffer.timestampOffset, 0, 'timestampOffset starts at zero'); | ||
2290 | |||
2291 | // play to 6s to trigger the next segment request | ||
2292 | clock.tick(6000); | ||
2293 | |||
2294 | standardXHRResponse(requests.pop()); // 2.ts | ||
2295 | equal(player.tech_.hls.sourceBuffer.timestampOffset, 10, 'timestampOffset set after discontinuity'); | ||
2178 | }); | 2296 | }); |
2179 | 2297 | ||
2298 | |||
2180 | test('can seek before the source buffer opens', function() { | 2299 | test('can seek before the source buffer opens', function() { |
2181 | player.src({ | 2300 | player.src({ |
2182 | src: 'media.m3u8', | 2301 | src: 'media.m3u8', |
2183 | type: 'application/vnd.apple.mpegurl' | 2302 | type: 'application/vnd.apple.mpegurl' |
2184 | }); | 2303 | }); |
2185 | player.tech.triggerReady(); | 2304 | player.tech_.triggerReady(); |
2186 | clock.tick(1); | 2305 | clock.tick(1); |
2187 | standardXHRResponse(requests.shift()); | 2306 | standardXHRResponse(requests.shift()); |
2188 | player.triggerReady(); | 2307 | player.triggerReady(); |
... | @@ -2191,7 +2310,6 @@ test('can seek before the source buffer opens', function() { | ... | @@ -2191,7 +2310,6 @@ test('can seek before the source buffer opens', function() { |
2191 | equal(player.currentTime(), 1, 'seeked'); | 2310 | equal(player.currentTime(), 1, 'seeked'); |
2192 | }); | 2311 | }); |
2193 | 2312 | ||
2194 | // TODO: Decide on proper discontinuity behavior | ||
2195 | QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() { | 2313 | QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() { |
2196 | var bufferEnd; | 2314 | var bufferEnd; |
2197 | player.src({ | 2315 | player.src({ |
... | @@ -2199,7 +2317,7 @@ QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() | ... | @@ -2199,7 +2317,7 @@ QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() |
2199 | type: 'application/vnd.apple.mpegurl' | 2317 | type: 'application/vnd.apple.mpegurl' |
2200 | }); | 2318 | }); |
2201 | openMediaSource(player); | 2319 | openMediaSource(player); |
2202 | player.tech.buffered = function() { | 2320 | player.tech_.buffered = function() { |
2203 | return videojs.createTimeRange(0, bufferEnd); | 2321 | return videojs.createTimeRange(0, bufferEnd); |
2204 | }; | 2322 | }; |
2205 | 2323 | ||
... | @@ -2214,14 +2332,14 @@ QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() | ... | @@ -2214,14 +2332,14 @@ QUnit.skip('sets the timestampOffset after seeking to discontinuity', function() |
2214 | standardXHRResponse(requests.pop()); // 1.ts | 2332 | standardXHRResponse(requests.pop()); // 1.ts |
2215 | 2333 | ||
2216 | // seek to a discontinuity | 2334 | // seek to a discontinuity |
2217 | player.tech.setCurrentTime(10); | 2335 | player.tech_.setCurrentTime(10); |
2218 | bufferEnd = 9.9; | 2336 | bufferEnd = 9.9; |
2219 | clock.tick(1); | 2337 | clock.tick(1); |
2220 | standardXHRResponse(requests.pop()); // 1.ts | 2338 | standardXHRResponse(requests.pop()); // 1.ts, again |
2221 | player.tech.hls.checkBuffer_(); | 2339 | player.tech_.hls.checkBuffer_(); |
2222 | standardXHRResponse(requests.pop()); // 2.ts, again | 2340 | standardXHRResponse(requests.pop()); // 2.ts |
2223 | equal(player.tech.hls.sourceBuffer.timestampOffset, | 2341 | equal(player.tech_.hls.sourceBuffer.timestampOffset, |
2224 | 10, | 2342 | 9.9, |
2225 | 'set the timestamp offset'); | 2343 | 'set the timestamp offset'); |
2226 | }); | 2344 | }); |
2227 | 2345 | ||
... | @@ -2234,7 +2352,7 @@ QUnit.skip('tracks segment end times as they are buffered', function() { | ... | @@ -2234,7 +2352,7 @@ QUnit.skip('tracks segment end times as they are buffered', function() { |
2234 | openMediaSource(player); | 2352 | openMediaSource(player); |
2235 | 2353 | ||
2236 | // as new segments are downloaded, the buffer end is updated | 2354 | // as new segments are downloaded, the buffer end is updated |
2237 | player.tech.buffered = function() { | 2355 | player.tech_.buffered = function() { |
2238 | return videojs.createTimeRange(0, bufferEnd); | 2356 | return videojs.createTimeRange(0, bufferEnd); |
2239 | }; | 2357 | }; |
2240 | requests.shift().respond(200, null, | 2358 | requests.shift().respond(200, null, |
... | @@ -2247,13 +2365,13 @@ QUnit.skip('tracks segment end times as they are buffered', function() { | ... | @@ -2247,13 +2365,13 @@ QUnit.skip('tracks segment end times as they are buffered', function() { |
2247 | 2365 | ||
2248 | // 0.ts is shorter than advertised | 2366 | // 0.ts is shorter than advertised |
2249 | standardXHRResponse(requests.shift()); | 2367 | standardXHRResponse(requests.shift()); |
2250 | equal(player.tech.hls.mediaSource.duration, 20, 'original duration is from the m3u8'); | 2368 | equal(player.tech_.hls.mediaSource.duration, 20, 'original duration is from the m3u8'); |
2251 | 2369 | ||
2252 | bufferEnd = 9.5; | 2370 | bufferEnd = 9.5; |
2253 | player.tech.hls.sourceBuffer.trigger('update'); | 2371 | player.tech_.hls.sourceBuffer.trigger('update'); |
2254 | player.tech.hls.sourceBuffer.trigger('updateend'); | 2372 | player.tech_.hls.sourceBuffer.trigger('updateend'); |
2255 | equal(player.tech.duration(), 10 + 9.5, 'updated duration'); | 2373 | equal(player.tech_.duration(), 10 + 9.5, 'updated duration'); |
2256 | equal(player.tech.hls.appendingSegmentInfo_, null, 'cleared the appending segment'); | 2374 | equal(player.tech_.hls.appendingSegmentInfo_, null, 'cleared the appending segment'); |
2257 | }); | 2375 | }); |
2258 | 2376 | ||
2259 | QUnit.skip('seeking does not fail when targeted between segments', function() { | 2377 | QUnit.skip('seeking does not fail when targeted between segments', function() { |
... | @@ -2265,12 +2383,12 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { | ... | @@ -2265,12 +2383,12 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { |
2265 | openMediaSource(player); | 2383 | openMediaSource(player); |
2266 | 2384 | ||
2267 | // mock out the currentTime callbacks | 2385 | // mock out the currentTime callbacks |
2268 | player.tech.el().vjs_setProperty = function(property, value) { | 2386 | player.tech_.el().vjs_setProperty = function(property, value) { |
2269 | if (property === 'currentTime') { | 2387 | if (property === 'currentTime') { |
2270 | currentTime = value; | 2388 | currentTime = value; |
2271 | } | 2389 | } |
2272 | }; | 2390 | }; |
2273 | player.tech.el().vjs_getProperty = function(property) { | 2391 | player.tech_.el().vjs_getProperty = function(property) { |
2274 | if (property === 'currentTime') { | 2392 | if (property === 'currentTime') { |
2275 | return currentTime; | 2393 | return currentTime; |
2276 | } | 2394 | } |
... | @@ -2278,7 +2396,7 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { | ... | @@ -2278,7 +2396,7 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { |
2278 | 2396 | ||
2279 | standardXHRResponse(requests.shift()); // media | 2397 | standardXHRResponse(requests.shift()); // media |
2280 | standardXHRResponse(requests.shift()); // segment 0 | 2398 | standardXHRResponse(requests.shift()); // segment 0 |
2281 | player.tech.hls.checkBuffer_(); | 2399 | player.tech_.hls.checkBuffer_(); |
2282 | segmentUrl = requests[0].url; | 2400 | segmentUrl = requests[0].url; |
2283 | standardXHRResponse(requests.shift()); // segment 1 | 2401 | standardXHRResponse(requests.shift()); // segment 1 |
2284 | 2402 | ||
... | @@ -2286,12 +2404,12 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { | ... | @@ -2286,12 +2404,12 @@ QUnit.skip('seeking does not fail when targeted between segments', function() { |
2286 | // less than the first in segment 1 | 2404 | // less than the first in segment 1 |
2287 | // FIXME: it's not possible to seek here without timestamp-based | 2405 | // FIXME: it's not possible to seek here without timestamp-based |
2288 | // segment durations | 2406 | // segment durations |
2289 | player.tech.setCurrentTime(9.4); | 2407 | player.tech_.setCurrentTime(9.4); |
2290 | clock.tick(1); | 2408 | clock.tick(1); |
2291 | equal(requests[0].url, segmentUrl, 'requested the later segment'); | 2409 | equal(requests[0].url, segmentUrl, 'requested the later segment'); |
2292 | 2410 | ||
2293 | standardXHRResponse(requests.shift()); // segment 1 | 2411 | standardXHRResponse(requests.shift()); // segment 1 |
2294 | player.tech.trigger('seeked'); | 2412 | player.tech_.trigger('seeked'); |
2295 | equal(player.currentTime(), 9.5, 'seeked to the later time'); | 2413 | equal(player.currentTime(), 9.5, 'seeked to the later time'); |
2296 | }); | 2414 | }); |
2297 | 2415 | ||
... | @@ -2301,7 +2419,7 @@ test('resets the switching algorithm if a request times out', function() { | ... | @@ -2301,7 +2419,7 @@ test('resets the switching algorithm if a request times out', function() { |
2301 | type: 'application/vnd.apple.mpegurl' | 2419 | type: 'application/vnd.apple.mpegurl' |
2302 | }); | 2420 | }); |
2303 | openMediaSource(player); | 2421 | openMediaSource(player); |
2304 | player.tech.hls.bandwidth = 20000; | 2422 | player.tech_.hls.bandwidth = 20000; |
2305 | 2423 | ||
2306 | standardXHRResponse(requests.shift()); // master | 2424 | standardXHRResponse(requests.shift()); // master |
2307 | standardXHRResponse(requests.shift()); // media.m3u8 | 2425 | standardXHRResponse(requests.shift()); // media.m3u8 |
... | @@ -2311,8 +2429,8 @@ test('resets the switching algorithm if a request times out', function() { | ... | @@ -2311,8 +2429,8 @@ test('resets the switching algorithm if a request times out', function() { |
2311 | 2429 | ||
2312 | standardXHRResponse(requests.shift()); | 2430 | standardXHRResponse(requests.shift()); |
2313 | 2431 | ||
2314 | strictEqual(player.tech.hls.playlists.media(), | 2432 | strictEqual(player.tech_.hls.playlists.media(), |
2315 | player.tech.hls.playlists.master.playlists[1], | 2433 | player.tech_.hls.playlists.master.playlists[1], |
2316 | 'reset to the lowest bitrate playlist'); | 2434 | 'reset to the lowest bitrate playlist'); |
2317 | }); | 2435 | }); |
2318 | 2436 | ||
... | @@ -2324,10 +2442,10 @@ test('disposes the playlist loader', function() { | ... | @@ -2324,10 +2442,10 @@ test('disposes the playlist loader', function() { |
2324 | type: 'application/vnd.apple.mpegurl' | 2442 | type: 'application/vnd.apple.mpegurl' |
2325 | }); | 2443 | }); |
2326 | openMediaSource(player); | 2444 | openMediaSource(player); |
2327 | loaderDispose = player.tech.hls.playlists.dispose; | 2445 | loaderDispose = player.tech_.hls.playlists.dispose; |
2328 | player.tech.hls.playlists.dispose = function() { | 2446 | player.tech_.hls.playlists.dispose = function() { |
2329 | disposes++; | 2447 | disposes++; |
2330 | loaderDispose.call(player.tech.hls.playlists); | 2448 | loaderDispose.call(player.tech_.hls.playlists); |
2331 | }; | 2449 | }; |
2332 | 2450 | ||
2333 | player.dispose(); | 2451 | player.dispose(); |
... | @@ -2383,7 +2501,7 @@ test('aborts the source buffer on disposal', function() { | ... | @@ -2383,7 +2501,7 @@ test('aborts the source buffer on disposal', function() { |
2383 | }); | 2501 | }); |
2384 | openMediaSource(player); | 2502 | openMediaSource(player); |
2385 | standardXHRResponse(requests.shift()); | 2503 | standardXHRResponse(requests.shift()); |
2386 | player.tech.hls.sourceBuffer.abort = function() { | 2504 | player.tech_.hls.sourceBuffer.abort = function() { |
2387 | aborts++; | 2505 | aborts++; |
2388 | }; | 2506 | }; |
2389 | 2507 | ||
... | @@ -2392,19 +2510,21 @@ test('aborts the source buffer on disposal', function() { | ... | @@ -2392,19 +2510,21 @@ test('aborts the source buffer on disposal', function() { |
2392 | }); | 2510 | }); |
2393 | 2511 | ||
2394 | test('the source handler supports HLS mime types', function() { | 2512 | test('the source handler supports HLS mime types', function() { |
2395 | ok(videojs.HlsSourceHandler.canHandleSource({ | 2513 | ['html5', 'flash'].forEach(function(techName) { |
2514 | ok(videojs.HlsSourceHandler(techName).canHandleSource({ | ||
2396 | type: 'aPplicatiOn/x-MPegUrl' | 2515 | type: 'aPplicatiOn/x-MPegUrl' |
2397 | }), 'supports x-mpegurl'); | 2516 | }), 'supports x-mpegurl'); |
2398 | ok(videojs.HlsSourceHandler.canHandleSource({ | 2517 | ok(videojs.HlsSourceHandler(techName).canHandleSource({ |
2399 | type: 'aPplicatiOn/VnD.aPPle.MpEgUrL' | 2518 | type: 'aPplicatiOn/VnD.aPPle.MpEgUrL' |
2400 | }), 'supports vnd.apple.mpegurl'); | 2519 | }), 'supports vnd.apple.mpegurl'); |
2401 | 2520 | ||
2402 | ok(!(videojs.HlsSourceHandler.canHandleSource({ | 2521 | ok(!(videojs.HlsSourceHandler(techName).canHandleSource({ |
2403 | type: 'video/mp4' | 2522 | type: 'video/mp4' |
2404 | }) instanceof videojs.Hls), 'does not support mp4'); | 2523 | }) instanceof videojs.Hls), 'does not support mp4'); |
2405 | ok(!(videojs.HlsSourceHandler.canHandleSource({ | 2524 | ok(!(videojs.HlsSourceHandler(techName).canHandleSource({ |
2406 | type: 'video/x-flv' | 2525 | type: 'video/x-flv' |
2407 | }) instanceof videojs.Hls), 'does not support flv'); | 2526 | }) instanceof videojs.Hls), 'does not support flv'); |
2527 | }); | ||
2408 | }); | 2528 | }); |
2409 | 2529 | ||
2410 | test('has no effect if native HLS is available', function() { | 2530 | test('has no effect if native HLS is available', function() { |
... | @@ -2416,7 +2536,7 @@ test('has no effect if native HLS is available', function() { | ... | @@ -2416,7 +2536,7 @@ test('has no effect if native HLS is available', function() { |
2416 | type: 'application/x-mpegURL' | 2536 | type: 'application/x-mpegURL' |
2417 | }); | 2537 | }); |
2418 | 2538 | ||
2419 | ok(!player.tech.hls, 'did not load hls tech'); | 2539 | ok(!player.tech_.hls, 'did not load hls tech'); |
2420 | player.dispose(); | 2540 | player.dispose(); |
2421 | }); | 2541 | }); |
2422 | 2542 | ||
... | @@ -2436,7 +2556,7 @@ test('tracks the bytes downloaded', function() { | ... | @@ -2436,7 +2556,7 @@ test('tracks the bytes downloaded', function() { |
2436 | }); | 2556 | }); |
2437 | openMediaSource(player); | 2557 | openMediaSource(player); |
2438 | 2558 | ||
2439 | strictEqual(player.tech.hls.bytesReceived, 0, 'no bytes received'); | 2559 | strictEqual(player.tech_.hls.bytesReceived, 0, 'no bytes received'); |
2440 | 2560 | ||
2441 | requests.shift().respond(200, null, | 2561 | requests.shift().respond(200, null, |
2442 | '#EXTM3U\n' + | 2562 | '#EXTM3U\n' + |
... | @@ -2449,15 +2569,15 @@ test('tracks the bytes downloaded', function() { | ... | @@ -2449,15 +2569,15 @@ test('tracks the bytes downloaded', function() { |
2449 | requests[0].response = new ArrayBuffer(17); | 2569 | requests[0].response = new ArrayBuffer(17); |
2450 | requests.shift().respond(200, null, ''); | 2570 | requests.shift().respond(200, null, ''); |
2451 | 2571 | ||
2452 | strictEqual(player.tech.hls.bytesReceived, 17, 'tracked bytes received'); | 2572 | strictEqual(player.tech_.hls.bytesReceived, 17, 'tracked bytes received'); |
2453 | 2573 | ||
2454 | player.tech.hls.checkBuffer_(); | 2574 | player.tech_.hls.checkBuffer_(); |
2455 | 2575 | ||
2456 | // transmit some more | 2576 | // transmit some more |
2457 | requests[0].response = new ArrayBuffer(5); | 2577 | requests[0].response = new ArrayBuffer(5); |
2458 | requests.shift().respond(200, null, ''); | 2578 | requests.shift().respond(200, null, ''); |
2459 | 2579 | ||
2460 | strictEqual(player.tech.hls.bytesReceived, 22, 'tracked more bytes'); | 2580 | strictEqual(player.tech_.hls.bytesReceived, 22, 'tracked more bytes'); |
2461 | }); | 2581 | }); |
2462 | 2582 | ||
2463 | test('re-emits mediachange events', function() { | 2583 | test('re-emits mediachange events', function() { |
... | @@ -2472,12 +2592,12 @@ test('re-emits mediachange events', function() { | ... | @@ -2472,12 +2592,12 @@ test('re-emits mediachange events', function() { |
2472 | }); | 2592 | }); |
2473 | openMediaSource(player); | 2593 | openMediaSource(player); |
2474 | 2594 | ||
2475 | player.tech.hls.playlists.trigger('mediachange'); | 2595 | player.tech_.hls.playlists.trigger('mediachange'); |
2476 | strictEqual(mediaChanges, 1, 'fired mediachange'); | 2596 | strictEqual(mediaChanges, 1, 'fired mediachange'); |
2477 | }); | 2597 | }); |
2478 | 2598 | ||
2479 | test('can be disposed before finishing initialization', function() { | 2599 | test('can be disposed before finishing initialization', function() { |
2480 | var player = createPlayer(), readyHandlers = []; | 2600 | var readyHandlers = []; |
2481 | player.ready = function(callback) { | 2601 | player.ready = function(callback) { |
2482 | readyHandlers.push(callback); | 2602 | readyHandlers.push(callback); |
2483 | }; | 2603 | }; |
... | @@ -2493,6 +2613,7 @@ test('can be disposed before finishing initialization', function() { | ... | @@ -2493,6 +2613,7 @@ test('can be disposed before finishing initialization', function() { |
2493 | try { | 2613 | try { |
2494 | while (readyHandlers.length) { | 2614 | while (readyHandlers.length) { |
2495 | readyHandlers.shift().call(player); | 2615 | readyHandlers.shift().call(player); |
2616 | openMediaSource(player); | ||
2496 | } | 2617 | } |
2497 | ok(true, 'did not throw an exception'); | 2618 | ok(true, 'did not throw an exception'); |
2498 | } catch (e) { | 2619 | } catch (e) { |
... | @@ -2507,7 +2628,7 @@ test('calls ended() on the media source at the end of a playlist', function() { | ... | @@ -2507,7 +2628,7 @@ test('calls ended() on the media source at the end of a playlist', function() { |
2507 | type: 'application/vnd.apple.mpegurl' | 2628 | type: 'application/vnd.apple.mpegurl' |
2508 | }); | 2629 | }); |
2509 | openMediaSource(player); | 2630 | openMediaSource(player); |
2510 | player.tech.hls.mediaSource.endOfStream = function() { | 2631 | player.tech_.hls.mediaSource.endOfStream = function() { |
2511 | endOfStreams++; | 2632 | endOfStreams++; |
2512 | }; | 2633 | }; |
2513 | // playlist response | 2634 | // playlist response |
... | @@ -2521,7 +2642,7 @@ test('calls ended() on the media source at the end of a playlist', function() { | ... | @@ -2521,7 +2642,7 @@ test('calls ended() on the media source at the end of a playlist', function() { |
2521 | requests.shift().respond(200, null, ''); | 2642 | requests.shift().respond(200, null, ''); |
2522 | strictEqual(endOfStreams, 0, 'waits for the buffer update to finish'); | 2643 | strictEqual(endOfStreams, 0, 'waits for the buffer update to finish'); |
2523 | 2644 | ||
2524 | player.tech.hls.sourceBuffer.trigger('updateend'); | 2645 | player.tech_.hls.sourceBuffer.trigger('updateend'); |
2525 | strictEqual(endOfStreams, 1, 'ended media source'); | 2646 | strictEqual(endOfStreams, 1, 'ended media source'); |
2526 | }); | 2647 | }); |
2527 | 2648 | ||
... | @@ -2538,13 +2659,13 @@ test('calling play() at the end of a video resets the media index', function() { | ... | @@ -2538,13 +2659,13 @@ test('calling play() at the end of a video resets the media index', function() { |
2538 | '#EXT-X-ENDLIST\n'); | 2659 | '#EXT-X-ENDLIST\n'); |
2539 | standardXHRResponse(requests.shift()); | 2660 | standardXHRResponse(requests.shift()); |
2540 | 2661 | ||
2541 | strictEqual(player.tech.hls.mediaIndex, 1, 'index is 1 after the first segment'); | 2662 | strictEqual(player.tech_.hls.mediaIndex, 1, 'index is 1 after the first segment'); |
2542 | player.tech.ended = function() { | 2663 | player.tech_.ended = function() { |
2543 | return true; | 2664 | return true; |
2544 | }; | 2665 | }; |
2545 | 2666 | ||
2546 | player.tech.trigger('play'); | 2667 | player.tech_.trigger('play'); |
2547 | strictEqual(player.tech.hls.mediaIndex, 0, 'index is 0 after the first segment'); | 2668 | strictEqual(player.tech_.hls.mediaIndex, 0, 'index is 0 after the first segment'); |
2548 | }); | 2669 | }); |
2549 | 2670 | ||
2550 | test('drainBuffer will not proceed with empty source buffer', function() { | 2671 | test('drainBuffer will not proceed with empty source buffer', function() { |
... | @@ -2555,7 +2676,7 @@ test('drainBuffer will not proceed with empty source buffer', function() { | ... | @@ -2555,7 +2676,7 @@ test('drainBuffer will not proceed with empty source buffer', function() { |
2555 | }); | 2676 | }); |
2556 | openMediaSource(player); | 2677 | openMediaSource(player); |
2557 | 2678 | ||
2558 | oldMedia = player.tech.hls.playlists.media; | 2679 | oldMedia = player.tech_.hls.playlists.media; |
2559 | newMedia = {segments: [{ | 2680 | newMedia = {segments: [{ |
2560 | key: { | 2681 | key: { |
2561 | 'retries': 5 | 2682 | 'retries': 5 |
... | @@ -2568,23 +2689,23 @@ test('drainBuffer will not proceed with empty source buffer', function() { | ... | @@ -2568,23 +2689,23 @@ test('drainBuffer will not proceed with empty source buffer', function() { |
2568 | }, | 2689 | }, |
2569 | uri: 'http://media.example.com/fileSequence53-B.ts' | 2690 | uri: 'http://media.example.com/fileSequence53-B.ts' |
2570 | }]}; | 2691 | }]}; |
2571 | player.tech.hls.playlists.media = function() { | 2692 | player.tech_.hls.playlists.media = function() { |
2572 | return newMedia; | 2693 | return newMedia; |
2573 | }; | 2694 | }; |
2574 | 2695 | ||
2575 | player.tech.hls.sourceBuffer = undefined; | 2696 | player.tech_.hls.sourceBuffer = undefined; |
2576 | compareBuffer = [{mediaIndex: 0, playlist: newMedia, offset: 0, bytes: new Uint8Array(3)}]; | 2697 | compareBuffer = [{mediaIndex: 0, playlist: newMedia, offset: 0, bytes: new Uint8Array(3)}]; |
2577 | player.tech.hls.segmentBuffer_ = [{mediaIndex: 0, playlist: newMedia, offset: 0, bytes: new Uint8Array(3)}]; | 2698 | player.tech_.hls.segmentBuffer_ = [{mediaIndex: 0, playlist: newMedia, offset: 0, bytes: new Uint8Array(3)}]; |
2578 | 2699 | ||
2579 | player.tech.hls.drainBuffer(); | 2700 | player.tech_.hls.drainBuffer(); |
2580 | 2701 | ||
2581 | /* Normally, drainBuffer() calls segmentBuffer.shift(), removing a segment from the stack. | 2702 | /* Normally, drainBuffer() calls segmentBuffer.shift(), removing a segment from the stack. |
2582 | * Comparing two buffers to ensure no segment was popped verifies that we returned early | 2703 | * Comparing two buffers to ensure no segment was popped verifies that we returned early |
2583 | * from drainBuffer() because sourceBuffer was empty. | 2704 | * from drainBuffer() because sourceBuffer was empty. |
2584 | */ | 2705 | */ |
2585 | deepEqual(player.tech.hls.segmentBuffer_, compareBuffer, 'playlist remains unchanged'); | 2706 | deepEqual(player.tech_.hls.segmentBuffer_, compareBuffer, 'playlist remains unchanged'); |
2586 | 2707 | ||
2587 | player.tech.hls.playlists.media = oldMedia; | 2708 | player.tech_.hls.playlists.media = oldMedia; |
2588 | }); | 2709 | }); |
2589 | 2710 | ||
2590 | test('keys are requested when an encrypted segment is loaded', function() { | 2711 | test('keys are requested when an encrypted segment is loaded', function() { |
... | @@ -2593,13 +2714,13 @@ test('keys are requested when an encrypted segment is loaded', function() { | ... | @@ -2593,13 +2714,13 @@ test('keys are requested when an encrypted segment is loaded', function() { |
2593 | type: 'application/vnd.apple.mpegurl' | 2714 | type: 'application/vnd.apple.mpegurl' |
2594 | }); | 2715 | }); |
2595 | openMediaSource(player); | 2716 | openMediaSource(player); |
2596 | player.tech.trigger('play'); | 2717 | player.tech_.trigger('play'); |
2597 | standardXHRResponse(requests.shift()); // playlist | 2718 | standardXHRResponse(requests.shift()); // playlist |
2598 | standardXHRResponse(requests.shift()); // first segment | 2719 | standardXHRResponse(requests.shift()); // first segment |
2599 | 2720 | ||
2600 | strictEqual(requests.length, 1, 'a key XHR is created'); | 2721 | strictEqual(requests.length, 1, 'a key XHR is created'); |
2601 | strictEqual(requests[0].url, | 2722 | strictEqual(requests[0].url, |
2602 | player.tech.hls.playlists.media().segments[0].key.uri, | 2723 | player.tech_.hls.playlists.media().segments[0].key.uri, |
2603 | 'a key XHR is created with correct uri'); | 2724 | 'a key XHR is created with correct uri'); |
2604 | }); | 2725 | }); |
2605 | 2726 | ||
... | @@ -2667,15 +2788,15 @@ test('a new key XHR is created when a the segment is received', function() { | ... | @@ -2667,15 +2788,15 @@ test('a new key XHR is created when a the segment is received', function() { |
2667 | standardXHRResponse(requests.shift()); // segment 1 | 2788 | standardXHRResponse(requests.shift()); // segment 1 |
2668 | standardXHRResponse(requests.shift()); // key 1 | 2789 | standardXHRResponse(requests.shift()); // key 1 |
2669 | // "finish" decrypting segment 1 | 2790 | // "finish" decrypting segment 1 |
2670 | player.tech.hls.segmentBuffer_[0].bytes = new Uint8Array(16); | 2791 | player.tech_.hls.segmentBuffer_[0].bytes = new Uint8Array(16); |
2671 | player.tech.hls.checkBuffer_(); | 2792 | player.tech_.hls.checkBuffer_(); |
2672 | 2793 | ||
2673 | standardXHRResponse(requests.shift()); // segment 2 | 2794 | standardXHRResponse(requests.shift()); // segment 2 |
2674 | 2795 | ||
2675 | strictEqual(requests.length, 1, 'a key XHR is created'); | 2796 | strictEqual(requests.length, 1, 'a key XHR is created'); |
2676 | strictEqual(requests[0].url, | 2797 | strictEqual(requests[0].url, |
2677 | 'https://example.com/' + | 2798 | 'https://example.com/' + |
2678 | player.tech.hls.playlists.media().segments[1].key.uri, | 2799 | player.tech_.hls.playlists.media().segments[1].key.uri, |
2679 | 'a key XHR is created with the correct uri'); | 2800 | 'a key XHR is created with the correct uri'); |
2680 | }); | 2801 | }); |
2681 | 2802 | ||
... | @@ -2708,7 +2829,7 @@ test('seeking should abort an outstanding key request and create a new one', fun | ... | @@ -2708,7 +2829,7 @@ test('seeking should abort an outstanding key request and create a new one', fun |
2708 | equal(requests.length, 1, 'requested the new key'); | 2829 | equal(requests.length, 1, 'requested the new key'); |
2709 | equal(requests[0].url, | 2830 | equal(requests[0].url, |
2710 | 'https://example.com/' + | 2831 | 'https://example.com/' + |
2711 | player.tech.hls.playlists.media().segments[1].key.uri, | 2832 | player.tech_.hls.playlists.media().segments[1].key.uri, |
2712 | 'urls should match'); | 2833 | 'urls should match'); |
2713 | }); | 2834 | }); |
2714 | 2835 | ||
... | @@ -2718,7 +2839,7 @@ test('retries key requests once upon failure', function() { | ... | @@ -2718,7 +2839,7 @@ test('retries key requests once upon failure', function() { |
2718 | type: 'application/vnd.apple.mpegurl' | 2839 | type: 'application/vnd.apple.mpegurl' |
2719 | }); | 2840 | }); |
2720 | openMediaSource(player); | 2841 | openMediaSource(player); |
2721 | player.tech.trigger('play'); | 2842 | player.tech_.trigger('play'); |
2722 | 2843 | ||
2723 | requests.shift().respond(200, null, | 2844 | requests.shift().respond(200, null, |
2724 | '#EXTM3U\n' + | 2845 | '#EXTM3U\n' + |
... | @@ -2745,7 +2866,7 @@ test('skip segments if key requests fail more than once', function() { | ... | @@ -2745,7 +2866,7 @@ test('skip segments if key requests fail more than once', function() { |
2745 | type: 'application/vnd.apple.mpegurl' | 2866 | type: 'application/vnd.apple.mpegurl' |
2746 | }); | 2867 | }); |
2747 | openMediaSource(player); | 2868 | openMediaSource(player); |
2748 | player.tech.trigger('play'); | 2869 | player.tech_.trigger('play'); |
2749 | 2870 | ||
2750 | requests.shift().respond(200, null, | 2871 | requests.shift().respond(200, null, |
2751 | '#EXTM3U\n' + | 2872 | '#EXTM3U\n' + |
... | @@ -2755,14 +2876,14 @@ test('skip segments if key requests fail more than once', function() { | ... | @@ -2755,14 +2876,14 @@ test('skip segments if key requests fail more than once', function() { |
2755 | '#EXT-X-KEY:METHOD=AES-128,URI="htts://priv.example.com/key.php?r=53"\n' + | 2876 | '#EXT-X-KEY:METHOD=AES-128,URI="htts://priv.example.com/key.php?r=53"\n' + |
2756 | '#EXTINF:15.0,\n' + | 2877 | '#EXTINF:15.0,\n' + |
2757 | 'http://media.example.com/fileSequence53-A.ts\n'); | 2878 | 'http://media.example.com/fileSequence53-A.ts\n'); |
2758 | player.tech.hls.sourceBuffer.appendBuffer = function(chunk) { | 2879 | player.tech_.hls.sourceBuffer.appendBuffer = function(chunk) { |
2759 | bytes.push(chunk); | 2880 | bytes.push(chunk); |
2760 | }; | 2881 | }; |
2761 | standardXHRResponse(requests.shift()); // segment 1 | 2882 | standardXHRResponse(requests.shift()); // segment 1 |
2762 | requests.shift().respond(404); // fail key | 2883 | requests.shift().respond(404); // fail key |
2763 | requests.shift().respond(404); // fail key, again | 2884 | requests.shift().respond(404); // fail key, again |
2764 | 2885 | ||
2765 | player.tech.hls.checkBuffer_(); | 2886 | player.tech_.hls.checkBuffer_(); |
2766 | standardXHRResponse(requests.shift()); // segment 2 | 2887 | standardXHRResponse(requests.shift()); // segment 2 |
2767 | equal(bytes.length, 0, 'did not append encrypted bytes'); | 2888 | equal(bytes.length, 0, 'did not append encrypted bytes'); |
2768 | 2889 | ||
... | @@ -2770,8 +2891,8 @@ test('skip segments if key requests fail more than once', function() { | ... | @@ -2770,8 +2891,8 @@ test('skip segments if key requests fail more than once', function() { |
2770 | requests[0].response = new Uint32Array([0,0,0,0]).buffer; | 2891 | requests[0].response = new Uint32Array([0,0,0,0]).buffer; |
2771 | requests.shift().respond(200, null, ''); | 2892 | requests.shift().respond(200, null, ''); |
2772 | // "finish" decryption | 2893 | // "finish" decryption |
2773 | player.tech.hls.segmentBuffer_[0].bytes = new Uint8Array(16); | 2894 | player.tech_.hls.segmentBuffer_[0].bytes = new Uint8Array(16); |
2774 | player.tech.hls.checkBuffer_(); | 2895 | player.tech_.hls.checkBuffer_(); |
2775 | 2896 | ||
2776 | equal(bytes.length, 1, 'appended cleartext bytes from the second segment'); | 2897 | equal(bytes.length, 1, 'appended cleartext bytes from the second segment'); |
2777 | deepEqual(bytes[0], new Uint8Array(16), 'appended bytes from the second segment, not the first'); | 2898 | deepEqual(bytes[0], new Uint8Array(16), 'appended bytes from the second segment, not the first'); |
... | @@ -2785,7 +2906,7 @@ test('the key is supplied to the decrypter in the correct format', function() { | ... | @@ -2785,7 +2906,7 @@ test('the key is supplied to the decrypter in the correct format', function() { |
2785 | type: 'application/vnd.apple.mpegurl' | 2906 | type: 'application/vnd.apple.mpegurl' |
2786 | }); | 2907 | }); |
2787 | openMediaSource(player); | 2908 | openMediaSource(player); |
2788 | player.tech.trigger('play'); | 2909 | player.tech_.trigger('play'); |
2789 | 2910 | ||
2790 | requests.pop().respond(200, null, | 2911 | requests.pop().respond(200, null, |
2791 | '#EXTM3U\n' + | 2912 | '#EXTM3U\n' + |
... | @@ -2820,7 +2941,7 @@ test('supplies the media sequence of current segment as the IV by default, if no | ... | @@ -2820,7 +2941,7 @@ test('supplies the media sequence of current segment as the IV by default, if no |
2820 | type: 'application/vnd.apple.mpegurl' | 2941 | type: 'application/vnd.apple.mpegurl' |
2821 | }); | 2942 | }); |
2822 | openMediaSource(player); | 2943 | openMediaSource(player); |
2823 | player.tech.trigger('play'); | 2944 | player.tech_.trigger('play'); |
2824 | 2945 | ||
2825 | requests.pop().respond(200, null, | 2946 | requests.pop().respond(200, null, |
2826 | '#EXTM3U\n' + | 2947 | '#EXTM3U\n' + |
... | @@ -2860,15 +2981,15 @@ test('switching playlists with an outstanding key request does not stall playbac | ... | @@ -2860,15 +2981,15 @@ test('switching playlists with an outstanding key request does not stall playbac |
2860 | type: 'application/vnd.apple.mpegurl' | 2981 | type: 'application/vnd.apple.mpegurl' |
2861 | }); | 2982 | }); |
2862 | openMediaSource(player); | 2983 | openMediaSource(player); |
2863 | player.tech.trigger('play'); | 2984 | player.tech_.trigger('play'); |
2864 | 2985 | ||
2865 | // master playlist | 2986 | // master playlist |
2866 | standardXHRResponse(requests.shift()); | 2987 | standardXHRResponse(requests.shift()); |
2867 | // media playlist | 2988 | // media playlist |
2868 | requests.shift().respond(200, null, media); | 2989 | requests.shift().respond(200, null, media); |
2869 | // mock out media switching from this point on | 2990 | // mock out media switching from this point on |
2870 | player.tech.hls.playlists.media = function() { | 2991 | player.tech_.hls.playlists.media = function() { |
2871 | return player.tech.hls.playlists.master.playlists[0]; | 2992 | return player.tech_.hls.playlists.master.playlists[0]; |
2872 | }; | 2993 | }; |
2873 | // first segment of the original media playlist | 2994 | // first segment of the original media playlist |
2874 | standardXHRResponse(requests.shift()); | 2995 | standardXHRResponse(requests.shift()); |
... | @@ -2876,9 +2997,9 @@ test('switching playlists with an outstanding key request does not stall playbac | ... | @@ -2876,9 +2997,9 @@ test('switching playlists with an outstanding key request does not stall playbac |
2876 | requests.shift(); | 2997 | requests.shift(); |
2877 | 2998 | ||
2878 | // "switch" media | 2999 | // "switch" media |
2879 | player.tech.hls.playlists.trigger('mediachange'); | 3000 | player.tech_.hls.playlists.trigger('mediachange'); |
2880 | 3001 | ||
2881 | player.tech.hls.checkBuffer_(); | 3002 | player.tech_.hls.checkBuffer_(); |
2882 | 3003 | ||
2883 | ok(requests.length, 'made a request'); | 3004 | ok(requests.length, 'made a request'); |
2884 | equal(requests[0].url, | 3005 | equal(requests[0].url, |
... | @@ -2915,7 +3036,7 @@ test('treats invalid keys as a key request failure', function() { | ... | @@ -2915,7 +3036,7 @@ test('treats invalid keys as a key request failure', function() { |
2915 | type: 'application/vnd.apple.mpegurl' | 3036 | type: 'application/vnd.apple.mpegurl' |
2916 | }); | 3037 | }); |
2917 | openMediaSource(player); | 3038 | openMediaSource(player); |
2918 | player.tech.trigger('play'); | 3039 | player.tech_.trigger('play'); |
2919 | requests.shift().respond(200, null, | 3040 | requests.shift().respond(200, null, |
2920 | '#EXTM3U\n' + | 3041 | '#EXTM3U\n' + |
2921 | '#EXT-X-MEDIA-SEQUENCE:5\n' + | 3042 | '#EXT-X-MEDIA-SEQUENCE:5\n' + |
... | @@ -2925,7 +3046,7 @@ test('treats invalid keys as a key request failure', function() { | ... | @@ -2925,7 +3046,7 @@ test('treats invalid keys as a key request failure', function() { |
2925 | '#EXT-X-KEY:METHOD=NONE\n' + | 3046 | '#EXT-X-KEY:METHOD=NONE\n' + |
2926 | '#EXTINF:15.0,\n' + | 3047 | '#EXTINF:15.0,\n' + |
2927 | 'http://media.example.com/fileSequence52-B.ts\n'); | 3048 | 'http://media.example.com/fileSequence52-B.ts\n'); |
2928 | player.tech.hls.sourceBuffer.appendBuffer = function(chunk) { | 3049 | player.tech_.hls.sourceBuffer.appendBuffer = function(chunk) { |
2929 | bytes.push(chunk); | 3050 | bytes.push(chunk); |
2930 | }; | 3051 | }; |
2931 | // segment request | 3052 | // segment request |
... | @@ -2941,7 +3062,7 @@ test('treats invalid keys as a key request failure', function() { | ... | @@ -2941,7 +3062,7 @@ test('treats invalid keys as a key request failure', function() { |
2941 | requests.shift().respond(200, null, ''); | 3062 | requests.shift().respond(200, null, ''); |
2942 | 3063 | ||
2943 | // the first segment should be dropped and playback moves on | 3064 | // the first segment should be dropped and playback moves on |
2944 | player.tech.hls.checkBuffer_(); | 3065 | player.tech_.hls.checkBuffer_(); |
2945 | equal(bytes.length, 0, 'did not append bytes'); | 3066 | equal(bytes.length, 0, 'did not append bytes'); |
2946 | 3067 | ||
2947 | // second segment request | 3068 | // second segment request |
... | @@ -2958,7 +3079,7 @@ test('live stream should not call endOfStream', function(){ | ... | @@ -2958,7 +3079,7 @@ test('live stream should not call endOfStream', function(){ |
2958 | type: 'application/vnd.apple.mpegurl' | 3079 | type: 'application/vnd.apple.mpegurl' |
2959 | }); | 3080 | }); |
2960 | openMediaSource(player); | 3081 | openMediaSource(player); |
2961 | player.tech.trigger('play'); | 3082 | player.tech_.trigger('play'); |
2962 | requests[0].respond(200, null, | 3083 | requests[0].respond(200, null, |
2963 | '#EXTM3U\n' + | 3084 | '#EXTM3U\n' + |
2964 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | 3085 | '#EXT-X-MEDIA-SEQUENCE:0\n' + |
... | @@ -2967,7 +3088,7 @@ test('live stream should not call endOfStream', function(){ | ... | @@ -2967,7 +3088,7 @@ test('live stream should not call endOfStream', function(){ |
2967 | ); | 3088 | ); |
2968 | requests[1].response = window.bcSegment; | 3089 | requests[1].response = window.bcSegment; |
2969 | requests[1].respond(200, null, ""); | 3090 | requests[1].respond(200, null, ""); |
2970 | equal("open", player.tech.hls.mediaSource.readyState, | 3091 | equal("open", player.tech_.hls.mediaSource.readyState, |
2971 | "media source should be in open state, not ended state for live stream after the last segment in m3u8 downloaded"); | 3092 | "media source should be in open state, not ended state for live stream after the last segment in m3u8 downloaded"); |
2972 | }); | 3093 | }); |
2973 | 3094 | ||
... | @@ -2981,7 +3102,7 @@ test('does not download segments if preload option set to none', function() { | ... | @@ -2981,7 +3102,7 @@ test('does not download segments if preload option set to none', function() { |
2981 | openMediaSource(player); | 3102 | openMediaSource(player); |
2982 | standardXHRResponse(requests.shift()); // master | 3103 | standardXHRResponse(requests.shift()); // master |
2983 | standardXHRResponse(requests.shift()); // media | 3104 | standardXHRResponse(requests.shift()); // media |
2984 | player.tech.hls.checkBuffer_(); | 3105 | player.tech_.hls.checkBuffer_(); |
2985 | 3106 | ||
2986 | requests = requests.filter(function(request) { | 3107 | requests = requests.filter(function(request) { |
2987 | return !/m3u8$/.test(request.uri); | 3108 | return !/m3u8$/.test(request.uri); | ... | ... |
-
Please register or sign in to post a comment