Merge branch 'master' into saucelabs-take2
Conflicts: .travis.yml
Showing
15 changed files
with
125 additions
and
172 deletions
.npmignore
0 → 100644
... | @@ -9,7 +9,10 @@ notifications: | ... | @@ -9,7 +9,10 @@ notifications: |
9 | hipchat: | 9 | hipchat: |
10 | rooms: | 10 | rooms: |
11 | secure: l5TTd5JuPAW883PtcyaIBcJI9Chr9JpsZPQAEUBKAgIEwzuS6y7t5arlkS1PwH6gi1FADzYDf+OXSIou4GkTSrIetnBcT/SAgF0gBKgIhj+eRkuCfZ4VaC7BPhfZ0hgYRE+5Ejf5BM2MJafRm0pj7OlqG4xKrQZwtuV1te5r3JY= | 11 | secure: l5TTd5JuPAW883PtcyaIBcJI9Chr9JpsZPQAEUBKAgIEwzuS6y7t5arlkS1PwH6gi1FADzYDf+OXSIou4GkTSrIetnBcT/SAgF0gBKgIhj+eRkuCfZ4VaC7BPhfZ0hgYRE+5Ejf5BM2MJafRm0pj7OlqG4xKrQZwtuV1te5r3JY= |
12 | irc: chat.freenode.net#videojs | 12 | irc: |
13 | channels: | ||
14 | - "chat.freenode.net#videojs" | ||
15 | use_notice: true | ||
13 | env: | 16 | env: |
14 | global: | 17 | global: |
15 | - secure: dM7svnHPPu5IiUMeFWW5zg+iuWNpwt6SSDi3MmVvhSclNMRLesQoRB+7Qq5J/LiKhmjpv1/GlNVV0CTsHMRhZNwQ3fo38eEuTXv99aAflEITXwSEh/VntKViHbGFubn06EnVkJoH6MX3zJ6kbiwc2QdSQbywKzS6l6quUEpWpd0= | 18 | - secure: dM7svnHPPu5IiUMeFWW5zg+iuWNpwt6SSDi3MmVvhSclNMRLesQoRB+7Qq5J/LiKhmjpv1/GlNVV0CTsHMRhZNwQ3fo38eEuTXv99aAflEITXwSEh/VntKViHbGFubn06EnVkJoH6MX3zJ6kbiwc2QdSQbywKzS6l6quUEpWpd0= | ... | ... |
... | @@ -24,7 +24,6 @@ module.exports = function(grunt) { | ... | @@ -24,7 +24,6 @@ module.exports = function(grunt) { |
24 | dist: { | 24 | dist: { |
25 | nonull: true, | 25 | nonull: true, |
26 | src: ['src/videojs-hls.js', | 26 | src: ['src/videojs-hls.js', |
27 | 'src/async-queue.js', | ||
28 | 'src/flv-tag.js', | 27 | 'src/flv-tag.js', |
29 | 'src/exp-golomb.js', | 28 | 'src/exp-golomb.js', |
30 | 'src/h264-stream.js', | 29 | 'src/h264-stream.js', | ... | ... |
1 | [![Build Status](https://travis-ci.org/videojs/videojs-contrib-hls.png)](https://travis-ci.org/videojs/videojs-contrib-hls) | ||
2 | |||
3 | # video.js HLS Plugin | 1 | # video.js HLS Plugin |
4 | 2 | ||
5 | A video.js plugin that plays HLS video on platforms that don't support it but have Flash. | 3 | A video.js plugin that plays HLS video on platforms that don't support it but have Flash. |
6 | 4 | ||
5 | [![Build Status](https://travis-ci.org/videojs/videojs-contrib-hls.svg?branch=master)](https://travis-ci.org/videojs/videojs-contrib-hls) | ||
6 | |||
7 | ## Getting Started | 7 | ## Getting Started |
8 | Download the [plugin](https://github.com/videojs/videojs-contrib-hls/releases). On your web page: | 8 | Download the [plugin](https://github.com/videojs/videojs-contrib-hls/releases). On your web page: |
9 | 9 | ||
... | @@ -47,9 +47,26 @@ support for: | ... | @@ -47,9 +47,26 @@ support for: |
47 | - Alternate audio and video tracks | 47 | - Alternate audio and video tracks |
48 | - Subtitles | 48 | - Subtitles |
49 | - Segment codecs _other than_ H.264 with AAC audio | 49 | - Segment codecs _other than_ H.264 with AAC audio |
50 | - Live streams | ||
51 | - Internet Explorer < 10 | 50 | - Internet Explorer < 10 |
52 | 51 | ||
52 | ### Plugin Options | ||
53 | |||
54 | You may pass in an options object to the hls plugin upon initialization. This | ||
55 | object may contain one of the following properties: | ||
56 | |||
57 | #### withCredentials | ||
58 | Type: `boolean` | ||
59 | |||
60 | When the `withCredentials` property is set to `true`, all XHR requests for | ||
61 | manifests and segments would have `withCredentials` set to `true` as well. This | ||
62 | enables storing and passing cookies from the server that the manifests and | ||
63 | segments live on. This has some implications on CORS because when set, the | ||
64 | `Access-Control-Allow-Origin` header cannot be set to `*`, also, the response | ||
65 | headers require the addition of `Access-Control-Allow-Credentials` header which | ||
66 | is set to `true`. | ||
67 | See html5rocks's [article](http://www.html5rocks.com/en/tutorials/cors/) | ||
68 | for more info. | ||
69 | |||
53 | ### Runtime Properties | 70 | ### Runtime Properties |
54 | #### player.hls.master | 71 | #### player.hls.master |
55 | Type: `object` | 72 | Type: `object` |
... | @@ -119,6 +136,8 @@ bandwidth and viewport dimensions. | ... | @@ -119,6 +136,8 @@ bandwidth and viewport dimensions. |
119 | - [Best RESOLUTION variant] OR [Best BANDWIDTH variant] OR [inital playlist in manifest] | 136 | - [Best RESOLUTION variant] OR [Best BANDWIDTH variant] OR [inital playlist in manifest] |
120 | 137 | ||
121 | ## Release History | 138 | ## Release History |
139 | - 0.5.0: cookie-based content protection support (see `withCredentials`) | ||
140 | - 0.4.0: Live stream support | ||
122 | - 0.3.0: Performance fixes for high-bitrate streams | 141 | - 0.3.0: Performance fixes for high-bitrate streams |
123 | - 0.2.0: Basic playback and adaptive bitrate selection | 142 | - 0.2.0: Basic playback and adaptive bitrate selection |
124 | - 0.1.0: Initial release | 143 | - 0.1.0: Initial release | ... | ... |
... | @@ -10,11 +10,10 @@ | ... | @@ -10,11 +10,10 @@ |
10 | <script src="node_modules/video.js/dist/video-js/video.js"></script> | 10 | <script src="node_modules/video.js/dist/video-js/video.js"></script> |
11 | 11 | ||
12 | <!-- Media Sources plugin --> | 12 | <!-- Media Sources plugin --> |
13 | <script src="node_modules/videojs-contrib-media-sources/videojs-media-sources.js"></script> | 13 | <script src="node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> |
14 | 14 | ||
15 | <!-- HLS plugin --> | 15 | <!-- HLS plugin --> |
16 | <script src="src/videojs-hls.js"></script> | 16 | <script src="src/videojs-hls.js"></script> |
17 | <script src="src/async-queue.js"></script> | ||
18 | 17 | ||
19 | <!-- segment handling --> | 18 | <!-- segment handling --> |
20 | <script src="src/flv-tag.js"></script> | 19 | <script src="src/flv-tag.js"></script> | ... | ... |
1 | { | 1 | { |
2 | "name": "videojs-contrib-hls", | 2 | "name": "videojs-contrib-hls", |
3 | "version": "0.3.2", | 3 | "version": "0.5.0", |
4 | "engines": { | 4 | "engines": { |
5 | "node": ">= 0.10.12" | 5 | "node": ">= 0.10.12" |
6 | }, | 6 | }, |
... | @@ -13,33 +13,34 @@ | ... | @@ -13,33 +13,34 @@ |
13 | "test": "grunt test" | 13 | "test": "grunt test" |
14 | }, | 14 | }, |
15 | "devDependencies": { | 15 | "devDependencies": { |
16 | "grunt": "~0.4.1", | ||
17 | "grunt-concurrent": "0.4.3", | ||
18 | "grunt-contrib-clean": "~0.4.0", | ||
19 | "grunt-contrib-concat": "~0.3.0", | ||
20 | "grunt-contrib-connect": "~0.6.0", | ||
16 | "grunt-contrib-jshint": "~0.6.0", | 21 | "grunt-contrib-jshint": "~0.6.0", |
17 | "grunt-contrib-qunit": "~0.2.0", | 22 | "grunt-contrib-qunit": "~0.2.0", |
18 | "grunt-contrib-concat": "~0.3.0", | ||
19 | "grunt-contrib-uglify": "~0.2.0", | 23 | "grunt-contrib-uglify": "~0.2.0", |
20 | "grunt-contrib-watch": "~0.4.0", | 24 | "grunt-contrib-watch": "~0.4.0", |
21 | "grunt-contrib-clean": "~0.4.0", | 25 | "grunt-karma": "~0.6.2", |
22 | "grunt-contrib-connect": "~0.6.0", | ||
23 | "grunt-concurrent": "0.4.3", | ||
24 | "grunt-open": "0.2.3", | 26 | "grunt-open": "0.2.3", |
25 | "grunt-shell": "0.6.1", | 27 | "grunt-shell": "0.6.1", |
26 | "grunt": "~0.4.1", | ||
27 | "grunt-karma": "~0.6.2", | ||
28 | "karma": "~0.10.0", | 28 | "karma": "~0.10.0", |
29 | "karma-sauce-launcher": "~0.1.8", | ||
30 | "karma-chrome-launcher": "~0.1.2", | 29 | "karma-chrome-launcher": "~0.1.2", |
31 | "karma-firefox-launcher": "~0.1.3", | 30 | "karma-firefox-launcher": "~0.1.3", |
32 | "karma-ie-launcher": "~0.1.1", | 31 | "karma-ie-launcher": "~0.1.1", |
33 | "karma-opera-launcher": "~0.1.0", | 32 | "karma-opera-launcher": "~0.1.0", |
34 | "karma-phantomjs-launcher": "~0.1.1", | 33 | "karma-phantomjs-launcher": "~0.1.1", |
35 | "karma-safari-launcher": "~0.1.1", | ||
36 | "karma-qunit": "~0.1.1", | 34 | "karma-qunit": "~0.1.1", |
35 | "karma-safari-launcher": "~0.1.1", | ||
36 | "karma-sauce-launcher": "~0.1.8", | ||
37 | "sinon": "^1.9.1", | ||
37 | "video.js": "^4.5" | 38 | "video.js": "^4.5" |
38 | }, | 39 | }, |
39 | "peerDependencies": { | 40 | "peerDependencies": { |
40 | "video.js": "^4.5" | 41 | "video.js": "^4.5" |
41 | }, | 42 | }, |
42 | "dependencies": { | 43 | "dependencies": { |
43 | "videojs-contrib-media-sources": "git+https://github.com/videojs/videojs-contrib-media-sources.git" | 44 | "videojs-contrib-media-sources": "^0.2" |
44 | } | 45 | } |
45 | } | 46 | } | ... | ... |
src/async-queue.js
deleted
100644 → 0
1 | (function(window, videojs, undefined) { | ||
2 | 'use strict'; | ||
3 | /** | ||
4 | * A queue object that manages tasks that should be processed | ||
5 | * serially but asynchronously. Loosely adapted from | ||
6 | * https://github.com/caolan/async#queue. | ||
7 | * @param worker {function} the callback to invoke with each value | ||
8 | * pushed onto the queue | ||
9 | * @return {object} an object with an array of `tasks` that remain to | ||
10 | * be processed and function `push` to add new tasks | ||
11 | */ | ||
12 | videojs.hls.queue = function(worker) { | ||
13 | var | ||
14 | q = { | ||
15 | tasks: [], | ||
16 | running: false, | ||
17 | push: function(task) { | ||
18 | q.tasks.push(task); | ||
19 | if (!q.running) { | ||
20 | window.setTimeout(process, 0); | ||
21 | q.running = true; | ||
22 | } | ||
23 | } | ||
24 | }, | ||
25 | process = function() { | ||
26 | var task; | ||
27 | if (q.tasks.length) { | ||
28 | task = q.tasks.shift(); | ||
29 | worker.call(this, task); | ||
30 | window.setTimeout(process, 0); | ||
31 | } else { | ||
32 | q.running = false; | ||
33 | } | ||
34 | }; | ||
35 | return q; | ||
36 | }; | ||
37 | })(window, window.videojs); |
... | @@ -31,6 +31,9 @@ videojs.hls = { | ... | @@ -31,6 +31,9 @@ videojs.hls = { |
31 | }; | 31 | }; |
32 | 32 | ||
33 | var | 33 | var |
34 | |||
35 | settings, | ||
36 | |||
34 | // the desired length of video to maintain in the buffer, in seconds | 37 | // the desired length of video to maintain in the buffer, in seconds |
35 | goalBufferLength = 5, | 38 | goalBufferLength = 5, |
36 | 39 | ||
... | @@ -109,12 +112,26 @@ var | ... | @@ -109,12 +112,26 @@ var |
109 | method: 'GET' | 112 | method: 'GET' |
110 | }, | 113 | }, |
111 | request; | 114 | request; |
115 | |||
116 | if (typeof callback !== 'function') { | ||
117 | callback = function() {}; | ||
118 | } | ||
119 | |||
112 | if (typeof url === 'object') { | 120 | if (typeof url === 'object') { |
113 | options = videojs.util.mergeOptions(options, url); | 121 | options = videojs.util.mergeOptions(options, url); |
114 | url = options.url; | 122 | url = options.url; |
115 | } | 123 | } |
124 | |||
116 | request = new window.XMLHttpRequest(); | 125 | request = new window.XMLHttpRequest(); |
117 | request.open(options.method, url); | 126 | request.open(options.method, url); |
127 | |||
128 | if (options.responseType) { | ||
129 | request.responseType = options.responseType; | ||
130 | } | ||
131 | if (settings.withCredentials) { | ||
132 | request.withCredentials = true; | ||
133 | } | ||
134 | |||
118 | request.onreadystatechange = function() { | 135 | request.onreadystatechange = function() { |
119 | // wait until the request completes | 136 | // wait until the request completes |
120 | if (this.readyState !== 4) { | 137 | if (this.readyState !== 4) { |
... | @@ -204,13 +221,8 @@ var | ... | @@ -204,13 +221,8 @@ var |
204 | totalDuration = function(playlist) { | 221 | totalDuration = function(playlist) { |
205 | var | 222 | var |
206 | duration = 0, | 223 | duration = 0, |
207 | i, | 224 | segment, |
208 | segment; | 225 | i = (playlist.segments || []).length; |
209 | |||
210 | if (!playlist.segments) { | ||
211 | return 0; | ||
212 | } | ||
213 | i = playlist.segments.length; | ||
214 | 226 | ||
215 | // if present, use the duration specified in the playlist | 227 | // if present, use the duration specified in the playlist |
216 | if (playlist.totalDuration) { | 228 | if (playlist.totalDuration) { |
... | @@ -277,28 +289,22 @@ var | ... | @@ -277,28 +289,22 @@ var |
277 | mediaSource = new videojs.MediaSource(), | 289 | mediaSource = new videojs.MediaSource(), |
278 | segmentParser = new videojs.hls.SegmentParser(), | 290 | segmentParser = new videojs.hls.SegmentParser(), |
279 | player = this, | 291 | player = this, |
280 | |||
281 | // async queue of Uint8Arrays to be appended to the SourceBuffer | ||
282 | tags = videojs.hls.queue(function(tag) { | ||
283 | player.hls.sourceBuffer.appendBuffer(tag, player); | ||
284 | |||
285 | if (player.hls.mediaIndex === player.hls.media.segments.length) { | ||
286 | mediaSource.endOfStream(); | ||
287 | } | ||
288 | }), | ||
289 | srcUrl, | 292 | srcUrl, |
290 | 293 | ||
291 | playlistXhr, | 294 | playlistXhr, |
292 | segmentXhr, | 295 | segmentXhr, |
293 | loadedPlaylist, | 296 | loadedPlaylist, |
294 | fillBuffer, | 297 | fillBuffer, |
295 | updateCurrentPlaylist; | 298 | updateCurrentPlaylist, |
299 | updateDuration; | ||
296 | 300 | ||
297 | // if the video element supports HLS natively, do nothing | 301 | // if the video element supports HLS natively, do nothing |
298 | if (videojs.hls.supportsNativeHls) { | 302 | if (videojs.hls.supportsNativeHls) { |
299 | return; | 303 | return; |
300 | } | 304 | } |
301 | 305 | ||
306 | settings = videojs.util.mergeOptions({}, options); | ||
307 | |||
302 | srcUrl = (function() { | 308 | srcUrl = (function() { |
303 | var | 309 | var |
304 | extname, | 310 | extname, |
... | @@ -312,7 +318,7 @@ var | ... | @@ -312,7 +318,7 @@ var |
312 | // use the URL specified in options if one was provided | 318 | // use the URL specified in options if one was provided |
313 | if (typeof options === 'string') { | 319 | if (typeof options === 'string') { |
314 | return options; | 320 | return options; |
315 | } else if (options) { | 321 | } else if (options && options.url) { |
316 | return options.url; | 322 | return options.url; |
317 | } | 323 | } |
318 | 324 | ||
... | @@ -370,17 +376,35 @@ var | ... | @@ -370,17 +376,35 @@ var |
370 | var currentTime = player.currentTime(); | 376 | var currentTime = player.currentTime(); |
371 | player.hls.mediaIndex = getMediaIndexByTime(player.hls.media, currentTime); | 377 | player.hls.mediaIndex = getMediaIndexByTime(player.hls.media, currentTime); |
372 | 378 | ||
379 | // abort any segments still being decoded | ||
380 | player.hls.sourceBuffer.abort(); | ||
381 | |||
373 | // cancel outstanding requests and buffer appends | 382 | // cancel outstanding requests and buffer appends |
374 | if (segmentXhr) { | 383 | if (segmentXhr) { |
375 | segmentXhr.abort(); | 384 | segmentXhr.abort(); |
376 | } | 385 | } |
377 | tags.tasks = []; | ||
378 | 386 | ||
379 | // begin filling the buffer at the new position | 387 | // begin filling the buffer at the new position |
380 | fillBuffer(currentTime * 1000); | 388 | fillBuffer(currentTime * 1000); |
381 | }); | 389 | }); |
382 | 390 | ||
383 | /** | 391 | /** |
392 | * Update the player duration | ||
393 | */ | ||
394 | updateDuration = function(playlist) { | ||
395 | var tech; | ||
396 | // update the duration | ||
397 | player.duration(totalDuration(playlist)); | ||
398 | // tell the flash tech of the new duration | ||
399 | tech = player.el().querySelector('.vjs-tech'); | ||
400 | if(tech.vjs_setProperty) { | ||
401 | tech.vjs_setProperty('duration', player.duration()); | ||
402 | } | ||
403 | // manually fire the duration change | ||
404 | player.trigger('durationchange'); | ||
405 | }; | ||
406 | |||
407 | /** | ||
384 | * Determine whether the current media playlist should be changed | 408 | * Determine whether the current media playlist should be changed |
385 | * and trigger a switch if necessary. If a sufficiently fresh | 409 | * and trigger a switch if necessary. If a sufficiently fresh |
386 | * version of the target playlist is available, the switch will take | 410 | * version of the target playlist is available, the switch will take |
... | @@ -406,8 +430,7 @@ var | ... | @@ -406,8 +430,7 @@ var |
406 | playlist); | 430 | playlist); |
407 | player.hls.media = playlist; | 431 | player.hls.media = playlist; |
408 | 432 | ||
409 | // update the duration | 433 | updateDuration(player.hls.media); |
410 | player.duration(totalDuration(player.hls.media)); | ||
411 | } | 434 | } |
412 | }; | 435 | }; |
413 | 436 | ||
... | @@ -558,7 +581,7 @@ var | ... | @@ -558,7 +581,7 @@ var |
558 | player.hls.media = player.hls.master.playlists[0]; | 581 | player.hls.media = player.hls.master.playlists[0]; |
559 | 582 | ||
560 | // update the duration | 583 | // update the duration |
561 | player.duration(totalDuration(parser.manifest)); | 584 | updateDuration(parser.manifest); |
562 | 585 | ||
563 | // periodicaly check if the buffer needs to be refilled | 586 | // periodicaly check if the buffer needs to be refilled |
564 | player.on('timeupdate', fillBuffer); | 587 | player.on('timeupdate', fillBuffer); |
... | @@ -585,7 +608,7 @@ var | ... | @@ -585,7 +608,7 @@ var |
585 | var | 608 | var |
586 | buffered = player.buffered(), | 609 | buffered = player.buffered(), |
587 | bufferedTime = 0, | 610 | bufferedTime = 0, |
588 | segment = player.hls.media.segments[player.hls.mediaIndex], | 611 | segment, |
589 | segmentUri, | 612 | segmentUri, |
590 | startTime; | 613 | startTime; |
591 | 614 | ||
... | @@ -594,7 +617,13 @@ var | ... | @@ -594,7 +617,13 @@ var |
594 | return; | 617 | return; |
595 | } | 618 | } |
596 | 619 | ||
620 | // if no segments are available, do nothing | ||
621 | if (!player.hls.media.segments) { | ||
622 | return; | ||
623 | } | ||
624 | |||
597 | // if the video has finished downloading, stop trying to buffer | 625 | // if the video has finished downloading, stop trying to buffer |
626 | segment = player.hls.media.segments[player.hls.mediaIndex]; | ||
598 | if (!segment) { | 627 | if (!segment) { |
599 | return; | 628 | return; |
600 | } | 629 | } |
... | @@ -617,24 +646,20 @@ var | ... | @@ -617,24 +646,20 @@ var |
617 | segment.uri); | 646 | segment.uri); |
618 | } | 647 | } |
619 | 648 | ||
620 | // request the next segment | 649 | startTime = +new Date(); |
621 | segmentXhr = new window.XMLHttpRequest(); | ||
622 | segmentXhr.open('GET', segmentUri); | ||
623 | segmentXhr.responseType = 'arraybuffer'; | ||
624 | segmentXhr.onreadystatechange = function() { | ||
625 | // wait until the request completes | ||
626 | if (this.readyState !== 4) { | ||
627 | return; | ||
628 | } | ||
629 | 650 | ||
651 | // request the next segment | ||
652 | segmentXhr = xhr({ | ||
653 | url: segmentUri, | ||
654 | responseType: 'arraybuffer' | ||
655 | }, function(error, url) { | ||
630 | // the segment request is no longer outstanding | 656 | // the segment request is no longer outstanding |
631 | segmentXhr = null; | 657 | segmentXhr = null; |
632 | 658 | ||
633 | // trigger an error if the request was not successful | 659 | if (error) { |
634 | if (this.status >= 400) { | ||
635 | player.hls.error = { | 660 | player.hls.error = { |
636 | status: this.status, | 661 | status: this.status, |
637 | message: 'HLS segment request error at URL: ' + segmentUri, | 662 | message: 'HLS segment request error at URL: ' + url, |
638 | code: (this.status >= 500) ? 4 : 2 | 663 | code: (this.status >= 500) ? 4 : 2 |
639 | }; | 664 | }; |
640 | 665 | ||
... | @@ -669,17 +694,22 @@ var | ... | @@ -669,17 +694,22 @@ var |
669 | // queue up the bytes to be appended to the SourceBuffer | 694 | // queue up the bytes to be appended to the SourceBuffer |
670 | // the queue gives control back to the browser between tags | 695 | // the queue gives control back to the browser between tags |
671 | // so that large segments don't cause a "hiccup" in playback | 696 | // so that large segments don't cause a "hiccup" in playback |
672 | tags.push(segmentParser.getNextTag().bytes); | 697 | |
698 | player.hls.sourceBuffer.appendBuffer(segmentParser.getNextTag().bytes, | ||
699 | player); | ||
700 | |||
673 | } | 701 | } |
674 | 702 | ||
675 | player.hls.mediaIndex++; | 703 | player.hls.mediaIndex++; |
676 | 704 | ||
705 | if (player.hls.mediaIndex === player.hls.media.segments.length) { | ||
706 | mediaSource.endOfStream(); | ||
707 | } | ||
708 | |||
677 | // figure out what stream the next segment should be downloaded from | 709 | // figure out what stream the next segment should be downloaded from |
678 | // with the updated bandwidth information | 710 | // with the updated bandwidth information |
679 | updateCurrentPlaylist(); | 711 | updateCurrentPlaylist(); |
680 | }; | 712 | }); |
681 | startTime = +new Date(); | ||
682 | segmentXhr.send(null); | ||
683 | }; | 713 | }; |
684 | 714 | ||
685 | // load the MediaSource into the player | 715 | // load the MediaSource into the player | ... | ... |
test/async-queue_test.js
deleted
100644 → 0
1 | (function(window, queue, undefined) { | ||
2 | var | ||
3 | oldSetTimeout, | ||
4 | callbacks; | ||
5 | module('async queue', { | ||
6 | setup: function() { | ||
7 | oldSetTimeout = window.setTimeout; | ||
8 | callbacks = []; | ||
9 | window.setTimeout = function(callback) { | ||
10 | callbacks.push(callback); | ||
11 | }; | ||
12 | }, | ||
13 | teardown: function() { | ||
14 | window.setTimeout = oldSetTimeout; | ||
15 | } | ||
16 | }); | ||
17 | |||
18 | test('runs tasks asynchronously', function() { | ||
19 | var | ||
20 | run = false, | ||
21 | q = queue(function() { | ||
22 | run = true; | ||
23 | }); | ||
24 | q.push(1); | ||
25 | |||
26 | ok(!run, 'tasks are not run immediately'); | ||
27 | |||
28 | callbacks[0](); | ||
29 | ok(run, 'tasks are run asynchronously'); | ||
30 | }); | ||
31 | |||
32 | test('runs one task at a time', function() { | ||
33 | var q = queue(function() {}); | ||
34 | q.push(1); | ||
35 | q.push(2); | ||
36 | q.push(3); | ||
37 | q.push(4); | ||
38 | q.push(5); | ||
39 | |||
40 | strictEqual(q.tasks.length, 5, 'all tasks are queued'); | ||
41 | strictEqual(1, callbacks.length, 'one callback is registered'); | ||
42 | }); | ||
43 | |||
44 | test('tasks are scheduled until the queue is empty', function() { | ||
45 | var q = queue(function() {}); | ||
46 | q.push(1); | ||
47 | q.push(2); | ||
48 | |||
49 | callbacks.shift()(); | ||
50 | strictEqual(1, callbacks.length, 'the next task is scheduled'); | ||
51 | |||
52 | callbacks.shift()(); | ||
53 | strictEqual(1, callbacks.length, 'nothing is scheduled on an empty queue'); | ||
54 | }); | ||
55 | |||
56 | test('can be emptied at any time', function() { | ||
57 | var | ||
58 | runs = 0, | ||
59 | q = queue(function() { | ||
60 | runs++; | ||
61 | }); | ||
62 | q.push(1); | ||
63 | q.push(2); | ||
64 | |||
65 | callbacks.shift()(); | ||
66 | strictEqual(1, runs, 'task one is run'); | ||
67 | |||
68 | q.tasks = []; | ||
69 | callbacks.shift()(); | ||
70 | strictEqual(1, runs, 'the remaining tasks are cancelled'); | ||
71 | }); | ||
72 | })(window, window.videojs.hls.queue); |
... | @@ -40,7 +40,7 @@ module.exports = function(config) { | ... | @@ -40,7 +40,7 @@ module.exports = function(config) { |
40 | 40 | ||
41 | files: [ | 41 | files: [ |
42 | '../node_modules/video.js/dist/video-js/video.js', | 42 | '../node_modules/video.js/dist/video-js/video.js', |
43 | '../node_modules/videojs-contrib-media-sources/videojs-media-sources.js', | 43 | '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js', |
44 | '../test/karma-qunit-shim.js', | 44 | '../test/karma-qunit-shim.js', |
45 | "../src/videojs-hls.js", | 45 | "../src/videojs-hls.js", |
46 | "../src/flv-tag.js", | 46 | "../src/flv-tag.js", | ... | ... |
... | @@ -35,7 +35,7 @@ module.exports = function(config) { | ... | @@ -35,7 +35,7 @@ module.exports = function(config) { |
35 | 35 | ||
36 | files: [ | 36 | files: [ |
37 | '../node_modules/video.js/dist/video-js/video.js', | 37 | '../node_modules/video.js/dist/video-js/video.js', |
38 | '../node_modules/videojs-contrib-media-sources/videojs-media-sources.js', | 38 | '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js', |
39 | '../test/karma-qunit-shim.js', | 39 | '../test/karma-qunit-shim.js', |
40 | "../src/videojs-hls.js", | 40 | "../src/videojs-hls.js", |
41 | "../src/flv-tag.js", | 41 | "../src/flv-tag.js", | ... | ... |
... | @@ -3,13 +3,19 @@ | ... | @@ -3,13 +3,19 @@ |
3 | <head> | 3 | <head> |
4 | <meta charset="utf-8"> | 4 | <meta charset="utf-8"> |
5 | <title>video.js HLS Plugin Test Suite</title> | 5 | <title>video.js HLS Plugin Test Suite</title> |
6 | <!-- Load sinon server for fakeXHR --> | ||
7 | <script src="../node_modules/sinon/lib/sinon.js"></script> | ||
8 | <script src="../node_modules/sinon/lib/sinon/util/event.js"></script> | ||
9 | <script src="../node_modules/sinon/lib/sinon/util/xhr_ie.js"></script> | ||
10 | <script src="../node_modules/sinon/lib/sinon/util/fake_xml_http_request.js"></script> | ||
11 | |||
6 | <!-- Load local QUnit. --> | 12 | <!-- Load local QUnit. --> |
7 | <link rel="stylesheet" href="../libs/qunit/qunit.css" media="screen"> | 13 | <link rel="stylesheet" href="../libs/qunit/qunit.css" media="screen"> |
8 | <script src="../libs/qunit/qunit.js"></script> | 14 | <script src="../libs/qunit/qunit.js"></script> |
9 | 15 | ||
10 | <!-- video.js --> | 16 | <!-- video.js --> |
11 | <script src="../node_modules/video.js/dist/video-js/video.js"></script> | 17 | <script src="../node_modules/video.js/dist/video-js/video.js"></script> |
12 | <script src="../node_modules/videojs-contrib-media-sources/videojs-media-sources.js"></script> | 18 | <script src="../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> |
13 | 19 | ||
14 | <!-- HLS plugin --> | 20 | <!-- HLS plugin --> |
15 | <script src="../src/videojs-hls.js"></script> | 21 | <script src="../src/videojs-hls.js"></script> |
... | @@ -31,9 +37,6 @@ | ... | @@ -31,9 +37,6 @@ |
31 | <script src="tsSegment-bc.js"></script> | 37 | <script src="tsSegment-bc.js"></script> |
32 | <script src="../src/bin-utils.js"></script> | 38 | <script src="../src/bin-utils.js"></script> |
33 | 39 | ||
34 | <!-- async queue --> | ||
35 | <script src="../src/async-queue.js"></script> | ||
36 | |||
37 | <!-- Test cases --> | 40 | <!-- Test cases --> |
38 | <script> | 41 | <script> |
39 | module('environment'); | 42 | module('environment'); |
... | @@ -48,7 +51,6 @@ | ... | @@ -48,7 +51,6 @@ |
48 | <script src="exp-golomb_test.js"></script> | 51 | <script src="exp-golomb_test.js"></script> |
49 | <script src="flv-tag_test.js"></script> | 52 | <script src="flv-tag_test.js"></script> |
50 | <script src="m3u8_test.js"></script> | 53 | <script src="m3u8_test.js"></script> |
51 | <script src="async-queue_test.js"></script> | ||
52 | </head> | 54 | </head> |
53 | <body> | 55 | <body> |
54 | <div id="qunit"></div> | 56 | <div id="qunit"></div> | ... | ... |
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment