50a78066 by David LaPalomento

Merge pull request #62 from videojs/tech2

HLS Tech
2 parents fafd0563 d30df95f
...@@ -45,9 +45,6 @@ module.exports = function(grunt) { ...@@ -45,9 +45,6 @@ module.exports = function(grunt) {
45 dest: 'dist/videojs.hls.min.js' 45 dest: 'dist/videojs.hls.min.js'
46 } 46 }
47 }, 47 },
48 qunit: {
49 files: ['test/**/*.html', '!test/perf.html', '!test/muxer/**']
50 },
51 jshint: { 48 jshint: {
52 gruntfile: { 49 gruntfile: {
53 options: { 50 options: {
...@@ -93,11 +90,11 @@ module.exports = function(grunt) { ...@@ -93,11 +90,11 @@ module.exports = function(grunt) {
93 }, 90 },
94 src: { 91 src: {
95 files: '<%= jshint.src.src %>', 92 files: '<%= jshint.src.src %>',
96 tasks: ['jshint:src', 'qunit'] 93 tasks: ['jshint:src', 'test']
97 }, 94 },
98 test: { 95 test: {
99 files: '<%= jshint.test.src %>', 96 files: '<%= jshint.test.src %>',
100 tasks: ['jshint:test', 'qunit'] 97 tasks: ['jshint:test', 'test']
101 } 98 }
102 }, 99 },
103 concurrent: { 100 concurrent: {
...@@ -194,7 +191,6 @@ module.exports = function(grunt) { ...@@ -194,7 +191,6 @@ module.exports = function(grunt) {
194 grunt.loadNpmTasks('grunt-contrib-clean'); 191 grunt.loadNpmTasks('grunt-contrib-clean');
195 grunt.loadNpmTasks('grunt-contrib-concat'); 192 grunt.loadNpmTasks('grunt-contrib-concat');
196 grunt.loadNpmTasks('grunt-contrib-uglify'); 193 grunt.loadNpmTasks('grunt-contrib-uglify');
197 grunt.loadNpmTasks('grunt-contrib-qunit');
198 grunt.loadNpmTasks('grunt-contrib-jshint'); 194 grunt.loadNpmTasks('grunt-contrib-jshint');
199 grunt.loadNpmTasks('grunt-contrib-watch'); 195 grunt.loadNpmTasks('grunt-contrib-watch');
200 grunt.loadNpmTasks('grunt-contrib-connect'); 196 grunt.loadNpmTasks('grunt-contrib-connect');
...@@ -255,7 +251,7 @@ module.exports = function(grunt) { ...@@ -255,7 +251,7 @@ module.exports = function(grunt) {
255 ['clean', 251 ['clean',
256 'jshint', 252 'jshint',
257 'manifests-to-js', 253 'manifests-to-js',
258 'qunit', 254 'test',
259 'concat', 255 'concat',
260 'uglify']); 256 'uglify']);
261 257
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
31 <!-- bipbop --> 31 <!-- bipbop -->
32 <!-- <script src="test/tsSegment.js"></script> --> 32 <!-- <script src="test/tsSegment.js"></script> -->
33 <!-- bunnies --> 33 <!-- bunnies -->
34 <script src="test/tsSegment-bc.js"></script> 34 <!--<script src="test/tsSegment-bc.js"></script>-->
35 35
36 <style> 36 <style>
37 body { 37 body {
...@@ -63,10 +63,12 @@ ...@@ -63,10 +63,12 @@
63 <script> 63 <script>
64 videojs.options.flash.swf = 'node_modules/video.js/dist/video-js/video-js.swf'; 64 videojs.options.flash.swf = 'node_modules/video.js/dist/video-js/video-js.swf';
65 // initialize the player 65 // initialize the player
66 var player = videojs('video'); 66 var player = videojs('video', {
67 techOrder: ['hls']
68 });
67 69
68 // initialize the plugin 70 // initialize the plugin
69 player.hls(); 71 //player.hls()
70 </script> 72 </script>
71 </body> 73 </body>
72 </html> 74 </html>
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
19 "grunt-contrib-concat": "~0.3.0", 19 "grunt-contrib-concat": "~0.3.0",
20 "grunt-contrib-connect": "~0.6.0", 20 "grunt-contrib-connect": "~0.6.0",
21 "grunt-contrib-jshint": "~0.6.0", 21 "grunt-contrib-jshint": "~0.6.0",
22 "grunt-contrib-qunit": "~0.2.0",
23 "grunt-contrib-uglify": "~0.2.0", 22 "grunt-contrib-uglify": "~0.2.0",
24 "grunt-contrib-watch": "~0.4.0", 23 "grunt-contrib-watch": "~0.4.0",
25 "grunt-karma": "~0.6.2", 24 "grunt-karma": "~0.6.2",
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
8 8
9 (function(window) { 9 (function(window) {
10 var 10 var
11 FlvTag = window.videojs.hls.FlvTag, 11 FlvTag = window.videojs.Hls.FlvTag,
12 adtsSampleingRates = [ 12 adtsSampleingRates = [
13 96000, 88200, 13 96000, 88200,
14 64000, 48000, 14 64000, 48000,
...@@ -17,7 +17,7 @@ var ...@@ -17,7 +17,7 @@ var
17 16000, 12000 17 16000, 12000
18 ]; 18 ];
19 19
20 window.videojs.hls.AacStream = function() { 20 window.videojs.Hls.AacStream = function() {
21 var 21 var
22 next_pts, // :uint 22 next_pts, // :uint
23 pts_offset, // :int 23 pts_offset, // :int
......
...@@ -29,5 +29,5 @@ ...@@ -29,5 +29,5 @@
29 } 29 }
30 }; 30 };
31 31
32 window.videojs.hls.utils = module; 32 window.videojs.Hls.utils = module;
33 })(this); 33 })(this);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 * Parser for exponential Golomb codes, a variable-bitwidth number encoding 4 * Parser for exponential Golomb codes, a variable-bitwidth number encoding
5 * scheme used by h264. 5 * scheme used by h264.
6 */ 6 */
7 window.videojs.hls.ExpGolomb = function(workingData) { 7 window.videojs.Hls.ExpGolomb = function(workingData) {
8 var 8 var
9 // the number of bytes left to examine in workingData 9 // the number of bytes left to examine in workingData
10 workingBytesAvailable = workingData.byteLength, 10 workingBytesAvailable = workingData.byteLength,
......
1 (function(window) { 1 (function(window) {
2 2
3 window.videojs = window.videojs || {}; 3 window.videojs = window.videojs || {};
4 window.videojs.hls = window.videojs.hls || {}; 4 window.videojs.Hls = window.videojs.Hls || {};
5 5
6 var hls = window.videojs.hls; 6 var hls = window.videojs.Hls;
7 7
8 // (type:uint, extraData:Boolean = false) extends ByteArray 8 // (type:uint, extraData:Boolean = false) extends ByteArray
9 hls.FlvTag = function(type, extraData) { 9 hls.FlvTag = function(type, extraData) {
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
8 8
9 (function(window) { 9 (function(window) {
10 var 10 var
11 ExpGolomb = window.videojs.hls.ExpGolomb, 11 ExpGolomb = window.videojs.Hls.ExpGolomb,
12 FlvTag = window.videojs.hls.FlvTag, 12 FlvTag = window.videojs.Hls.FlvTag,
13 13
14 H264ExtraData = function() { 14 H264ExtraData = function() {
15 this.sps = []; // :Array 15 this.sps = []; // :Array
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
234 * an h264 stream. Exactly one byte. 234 * an h264 stream. Exactly one byte.
235 */ 235 */
236 // incomplete, see Table 7.1 of ITU-T H.264 for 12-32 236 // incomplete, see Table 7.1 of ITU-T H.264 for 12-32
237 window.videojs.hls.NALUnitType = NALUnitType = { 237 window.videojs.Hls.NALUnitType = NALUnitType = {
238 unspecified: 0, 238 unspecified: 0,
239 slice_layer_without_partitioning_rbsp_non_idr: 1, 239 slice_layer_without_partitioning_rbsp_non_idr: 1,
240 slice_data_partition_a_layer_rbsp: 2, 240 slice_data_partition_a_layer_rbsp: 2,
...@@ -249,7 +249,7 @@ ...@@ -249,7 +249,7 @@
249 end_of_stream_rbsp: 11 249 end_of_stream_rbsp: 11
250 }; 250 };
251 251
252 window.videojs.hls.H264Stream = function() { 252 window.videojs.Hls.H264Stream = function() {
253 var 253 var
254 next_pts, // :uint; 254 next_pts, // :uint;
255 next_dts, // :uint; 255 next_dts, // :uint;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
32 } 32 }
33 return result; 33 return result;
34 }, 34 },
35 Stream = videojs.hls.Stream, 35 Stream = videojs.Hls.Stream,
36 LineStream, 36 LineStream,
37 ParseStream, 37 ParseStream,
38 Parser; 38 Parser;
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
5 (function(window, videojs) { 5 (function(window, videojs) {
6 'use strict'; 6 'use strict';
7 var 7 var
8 resolveUrl = videojs.hls.resolveUrl, 8 resolveUrl = videojs.Hls.resolveUrl,
9 xhr = videojs.hls.xhr, 9 xhr = videojs.Hls.xhr,
10 10
11 /** 11 /**
12 * Returns a new master playlist that is the result of merging an 12 * Returns a new master playlist that is the result of merging an
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
51 var 51 var
52 loader = this, 52 loader = this,
53 media, 53 media,
54 mediaUpdateTimeout,
54 request, 55 request,
55 56
56 haveMetadata = function(error, xhr, url) { 57 haveMetadata = function(error, xhr, url) {
...@@ -88,7 +89,7 @@ ...@@ -88,7 +89,7 @@
88 89
89 // refresh live playlists after a target duration passes 90 // refresh live playlists after a target duration passes
90 if (!loader.media().endList) { 91 if (!loader.media().endList) {
91 window.setTimeout(function() { 92 mediaUpdateTimeout = window.setTimeout(function() {
92 loader.trigger('mediaupdatetimeout'); 93 loader.trigger('mediaupdatetimeout');
93 }, refreshDelay); 94 }, refreshDelay);
94 } 95 }
...@@ -104,6 +105,13 @@ ...@@ -104,6 +105,13 @@
104 105
105 loader.state = 'HAVE_NOTHING'; 106 loader.state = 'HAVE_NOTHING';
106 107
108 loader.dispose = function() {
109 if (request) {
110 request.abort();
111 }
112 window.clearTimeout(mediaUpdateTimeout);
113 };
114
107 /** 115 /**
108 * When called without any arguments, returns the currently 116 * When called without any arguments, returns the currently
109 * active media playlist. When called with a single argument, 117 * active media playlist. When called with a single argument,
...@@ -213,7 +221,9 @@ ...@@ -213,7 +221,9 @@
213 haveMetadata(error, 221 haveMetadata(error,
214 this, 222 this,
215 parser.manifest.playlists[0].uri); 223 parser.manifest.playlists[0].uri);
224 if (!error) {
216 loader.trigger('loadedmetadata'); 225 loader.trigger('loadedmetadata');
226 }
217 }); 227 });
218 return loader.trigger('loadedplaylist'); 228 return loader.trigger('loadedplaylist');
219 } 229 }
...@@ -231,7 +241,7 @@ ...@@ -231,7 +241,7 @@
231 return loader.trigger('loadedmetadata'); 241 return loader.trigger('loadedmetadata');
232 }); 242 });
233 }; 243 };
234 PlaylistLoader.prototype = new videojs.hls.Stream(); 244 PlaylistLoader.prototype = new videojs.Hls.Stream();
235 245
236 videojs.hls.PlaylistLoader = PlaylistLoader; 246 videojs.Hls.PlaylistLoader = PlaylistLoader;
237 })(window, window.videojs); 247 })(window, window.videojs);
......
1 (function(window) { 1 (function(window) {
2 var 2 var
3 videojs = window.videojs, 3 videojs = window.videojs,
4 FlvTag = videojs.hls.FlvTag, 4 FlvTag = videojs.Hls.FlvTag,
5 H264Stream = videojs.hls.H264Stream, 5 H264Stream = videojs.Hls.H264Stream,
6 AacStream = videojs.hls.AacStream, 6 AacStream = videojs.Hls.AacStream,
7 MP2T_PACKET_LENGTH, 7 MP2T_PACKET_LENGTH,
8 STREAM_TYPES; 8 STREAM_TYPES;
9 9
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 * An object that incrementally transmuxes MPEG2 Trasport Stream 11 * An object that incrementally transmuxes MPEG2 Trasport Stream
12 * chunks into an FLV. 12 * chunks into an FLV.
13 */ 13 */
14 videojs.hls.SegmentParser = function() { 14 videojs.Hls.SegmentParser = function() {
15 var 15 var
16 self = this, 16 self = this,
17 parseTSPacket, 17 parseTSPacket,
...@@ -432,8 +432,8 @@ ...@@ -432,8 +432,8 @@
432 }; 432 };
433 433
434 // MPEG2-TS constants 434 // MPEG2-TS constants
435 videojs.hls.SegmentParser.MP2T_PACKET_LENGTH = MP2T_PACKET_LENGTH = 188; 435 videojs.Hls.SegmentParser.MP2T_PACKET_LENGTH = MP2T_PACKET_LENGTH = 188;
436 videojs.hls.SegmentParser.STREAM_TYPES = STREAM_TYPES = { 436 videojs.Hls.SegmentParser.STREAM_TYPES = STREAM_TYPES = {
437 h264: 0x1b, 437 h264: 0x1b,
438 adts: 0x0f 438 adts: 0x0f
439 }; 439 };
......
...@@ -65,5 +65,5 @@ ...@@ -65,5 +65,5 @@
65 }); 65 });
66 }; 66 };
67 67
68 videojs.hls.Stream = Stream; 68 videojs.Hls.Stream = Stream;
69 })(window.videojs); 69 })(window.videojs);
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
21 */ 21 */
22 var 22 var
23 buffer, 23 buffer,
24 ExpGolomb = window.videojs.hls.ExpGolomb, 24 ExpGolomb = window.videojs.Hls.ExpGolomb,
25 expGolomb; 25 expGolomb;
26 26
27 module('Exponential Golomb coding'); 27 module('Exponential Golomb coding');
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
19 notStrictEqual(actual, expected, [message]) 19 notStrictEqual(actual, expected, [message])
20 throws(block, [expected], [message]) 20 throws(block, [expected], [message])
21 */ 21 */
22 var FlvTag = window.videojs.hls.FlvTag; 22 var FlvTag = window.videojs.Hls.FlvTag;
23 23
24 module('FLV tag'); 24 module('FLV tag');
25 25
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
2 module('H264 Stream'); 2 module('H264 Stream');
3 3
4 var 4 var
5 nalUnitTypes = window.videojs.hls.NALUnitType, 5 nalUnitTypes = window.videojs.Hls.NALUnitType,
6 FlvTag = window.videojs.hls.FlvTag; 6 FlvTag = window.videojs.Hls.FlvTag;
7 7
8 test('metadata is generated for IDRs after a full NAL unit is written', function() { 8 test('metadata is generated for IDRs after a full NAL unit is written', function() {
9 var 9 var
10 h264Stream = new videojs.hls.H264Stream(), 10 h264Stream = new videojs.Hls.H264Stream(),
11 accessUnitDelimiter = new Uint8Array([ 11 accessUnitDelimiter = new Uint8Array([
12 0x00, 12 0x00,
13 0x00, 13 0x00,
...@@ -62,7 +62,7 @@ test('metadata is generated for IDRs after a full NAL unit is written', function ...@@ -62,7 +62,7 @@ test('metadata is generated for IDRs after a full NAL unit is written', function
62 62
63 test('starting PTS values can be negative', function() { 63 test('starting PTS values can be negative', function() {
64 var 64 var
65 h264Stream = new videojs.hls.H264Stream(), 65 h264Stream = new videojs.Hls.H264Stream(),
66 accessUnitDelimiter = new Uint8Array([ 66 accessUnitDelimiter = new Uint8Array([
67 0x00, 67 0x00,
68 0x00, 68 0x00,
......
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
127 original.addEventListener('change', function() { 127 original.addEventListener('change', function() {
128 var reader = new FileReader(); 128 var reader = new FileReader();
129 reader.addEventListener('loadend', function() { 129 reader.addEventListener('loadend', function() {
130 var parser = new videojs.hls.SegmentParser(), 130 var parser = new videojs.Hls.SegmentParser(),
131 tags = [parser.getFlvHeader()], 131 tags = [parser.getFlvHeader()],
132 tag, 132 tag,
133 hex, 133 hex,
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
164 } 164 }
165 165
166 hex = '<pre>' 166 hex = '<pre>'
167 hex += videojs.hls.utils.hexDump(data); 167 hex += videojs.Hls.utils.hexDump(data);
168 hex += '</pre>' 168 hex += '</pre>'
169 169
170 vjsOutput.innerHTML = hex; 170 vjsOutput.innerHTML = hex;
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
201 } 201 }
202 202
203 // output the hex dump 203 // output the hex dump
204 hex += videojs.hls.utils.hexDump(bytes); 204 hex += videojs.Hls.utils.hexDump(bytes);
205 hex += '</pre>'; 205 hex += '</pre>';
206 workingOutput.innerHTML = hex; 206 workingOutput.innerHTML = hex;
207 }); 207 });
......
...@@ -36,26 +36,26 @@ ...@@ -36,26 +36,26 @@
36 36
37 test('throws if the playlist url is empty or undefined', function() { 37 test('throws if the playlist url is empty or undefined', function() {
38 throws(function() { 38 throws(function() {
39 videojs.hls.PlaylistLoader(); 39 videojs.Hls.PlaylistLoader();
40 }, 'requires an argument'); 40 }, 'requires an argument');
41 throws(function() { 41 throws(function() {
42 videojs.hls.PlaylistLoader(''); 42 videojs.Hls.PlaylistLoader('');
43 }, 'does not accept the empty string'); 43 }, 'does not accept the empty string');
44 }); 44 });
45 45
46 test('starts without any metadata', function() { 46 test('starts without any metadata', function() {
47 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 47 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
48 strictEqual(loader.state, 'HAVE_NOTHING', 'no metadata has loaded yet'); 48 strictEqual(loader.state, 'HAVE_NOTHING', 'no metadata has loaded yet');
49 }); 49 });
50 50
51 test('requests the initial playlist immediately', function() { 51 test('requests the initial playlist immediately', function() {
52 new videojs.hls.PlaylistLoader('master.m3u8'); 52 new videojs.Hls.PlaylistLoader('master.m3u8');
53 strictEqual(requests.length, 1, 'made a request'); 53 strictEqual(requests.length, 1, 'made a request');
54 strictEqual(requests[0].url, 'master.m3u8', 'requested the initial playlist'); 54 strictEqual(requests[0].url, 'master.m3u8', 'requested the initial playlist');
55 }); 55 });
56 56
57 test('moves to HAVE_MASTER after loading a master playlist', function() { 57 test('moves to HAVE_MASTER after loading a master playlist', function() {
58 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 58 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
59 requests.pop().respond(200, null, 59 requests.pop().respond(200, null,
60 '#EXTM3U\n' + 60 '#EXTM3U\n' +
61 '#EXT-X-STREAM-INF:\n' + 61 '#EXT-X-STREAM-INF:\n' +
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
67 test('jumps to HAVE_METADATA when initialized with a media playlist', function() { 67 test('jumps to HAVE_METADATA when initialized with a media playlist', function() {
68 var 68 var
69 loadedmetadatas = 0, 69 loadedmetadatas = 0,
70 loader = new videojs.hls.PlaylistLoader('media.m3u8'); 70 loader = new videojs.Hls.PlaylistLoader('media.m3u8');
71 loader.on('loadedmetadata', function() { 71 loader.on('loadedmetadata', function() {
72 loadedmetadatas++; 72 loadedmetadatas++;
73 }); 73 });
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
85 }); 85 });
86 86
87 test('jumps to HAVE_METADATA when initialized with a live media playlist', function() { 87 test('jumps to HAVE_METADATA when initialized with a live media playlist', function() {
88 var loader = new videojs.hls.PlaylistLoader('media.m3u8'); 88 var loader = new videojs.Hls.PlaylistLoader('media.m3u8');
89 requests.pop().respond(200, null, 89 requests.pop().respond(200, null,
90 '#EXTM3U\n' + 90 '#EXTM3U\n' +
91 '#EXTINF:10,\n' + 91 '#EXTINF:10,\n' +
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
99 var 99 var
100 loadedPlaylist = 0, 100 loadedPlaylist = 0,
101 loadedMetadata = 0, 101 loadedMetadata = 0,
102 loader = new videojs.hls.PlaylistLoader('master.m3u8'); 102 loader = new videojs.Hls.PlaylistLoader('master.m3u8');
103 loader.on('loadedplaylist', function() { 103 loader.on('loadedplaylist', function() {
104 loadedPlaylist++; 104 loadedPlaylist++;
105 }); 105 });
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
131 }); 131 });
132 132
133 test('moves to HAVE_CURRENT_METADATA when refreshing the playlist', function() { 133 test('moves to HAVE_CURRENT_METADATA when refreshing the playlist', function() {
134 var loader = new videojs.hls.PlaylistLoader('live.m3u8'); 134 var loader = new videojs.Hls.PlaylistLoader('live.m3u8');
135 requests.pop().respond(200, null, 135 requests.pop().respond(200, null,
136 '#EXTM3U\n' + 136 '#EXTM3U\n' +
137 '#EXTINF:10,\n' + 137 '#EXTINF:10,\n' +
...@@ -145,7 +145,7 @@ ...@@ -145,7 +145,7 @@
145 }); 145 });
146 146
147 test('returns to HAVE_METADATA after refreshing the playlist', function() { 147 test('returns to HAVE_METADATA after refreshing the playlist', function() {
148 var loader = new videojs.hls.PlaylistLoader('live.m3u8'); 148 var loader = new videojs.Hls.PlaylistLoader('live.m3u8');
149 requests.pop().respond(200, null, 149 requests.pop().respond(200, null,
150 '#EXTM3U\n' + 150 '#EXTM3U\n' +
151 '#EXTINF:10,\n' + 151 '#EXTINF:10,\n' +
...@@ -161,7 +161,7 @@ ...@@ -161,7 +161,7 @@
161 test('emits an error when an initial playlist request fails', function() { 161 test('emits an error when an initial playlist request fails', function() {
162 var 162 var
163 errors = [], 163 errors = [],
164 loader = new videojs.hls.PlaylistLoader('master.m3u8'); 164 loader = new videojs.Hls.PlaylistLoader('master.m3u8');
165 165
166 loader.on('error', function() { 166 loader.on('error', function() {
167 errors.push(loader.error); 167 errors.push(loader.error);
...@@ -175,7 +175,7 @@ ...@@ -175,7 +175,7 @@
175 test('errors when an initial media playlist request fails', function() { 175 test('errors when an initial media playlist request fails', function() {
176 var 176 var
177 errors = [], 177 errors = [],
178 loader = new videojs.hls.PlaylistLoader('master.m3u8'); 178 loader = new videojs.Hls.PlaylistLoader('master.m3u8');
179 179
180 loader.on('error', function() { 180 loader.on('error', function() {
181 errors.push(loader.error); 181 errors.push(loader.error);
...@@ -197,7 +197,7 @@ ...@@ -197,7 +197,7 @@
197 // http://tools.ietf.org/html/draft-pantos-http-live-streaming-12#section-6.3.4 197 // http://tools.ietf.org/html/draft-pantos-http-live-streaming-12#section-6.3.4
198 test('halves the refresh timeout if a playlist is unchanged' + 198 test('halves the refresh timeout if a playlist is unchanged' +
199 'since the last reload', function() { 199 'since the last reload', function() {
200 new videojs.hls.PlaylistLoader('live.m3u8'); 200 new videojs.Hls.PlaylistLoader('live.m3u8');
201 requests.pop().respond(200, null, 201 requests.pop().respond(200, null,
202 '#EXTM3U\n' + 202 '#EXTM3U\n' +
203 '#EXT-X-MEDIA-SEQUENCE:0\n' + 203 '#EXT-X-MEDIA-SEQUENCE:0\n' +
...@@ -218,7 +218,7 @@ ...@@ -218,7 +218,7 @@
218 }); 218 });
219 219
220 test('media-sequence updates are considered a playlist change', function() { 220 test('media-sequence updates are considered a playlist change', function() {
221 new videojs.hls.PlaylistLoader('live.m3u8'); 221 new videojs.Hls.PlaylistLoader('live.m3u8');
222 requests.pop().respond(200, null, 222 requests.pop().respond(200, null,
223 '#EXTM3U\n' + 223 '#EXTM3U\n' +
224 '#EXT-X-MEDIA-SEQUENCE:0\n' + 224 '#EXT-X-MEDIA-SEQUENCE:0\n' +
...@@ -238,7 +238,7 @@ ...@@ -238,7 +238,7 @@
238 test('emits an error if a media refresh fails', function() { 238 test('emits an error if a media refresh fails', function() {
239 var 239 var
240 errors = 0, 240 errors = 0,
241 loader = new videojs.hls.PlaylistLoader('live.m3u8'); 241 loader = new videojs.Hls.PlaylistLoader('live.m3u8');
242 242
243 loader.on('error', function() { 243 loader.on('error', function() {
244 errors++; 244 errors++;
...@@ -256,7 +256,7 @@ ...@@ -256,7 +256,7 @@
256 }); 256 });
257 257
258 test('switches media playlists when requested', function() { 258 test('switches media playlists when requested', function() {
259 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 259 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
260 requests.pop().respond(200, null, 260 requests.pop().respond(200, null,
261 '#EXTM3U\n' + 261 '#EXTM3U\n' +
262 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + 262 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
...@@ -284,7 +284,7 @@ ...@@ -284,7 +284,7 @@
284 }); 284 });
285 285
286 test('can switch media playlists based on URI', function() { 286 test('can switch media playlists based on URI', function() {
287 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 287 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
288 requests.pop().respond(200, null, 288 requests.pop().respond(200, null,
289 '#EXTM3U\n' + 289 '#EXTM3U\n' +
290 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + 290 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
...@@ -312,7 +312,7 @@ ...@@ -312,7 +312,7 @@
312 }); 312 });
313 313
314 test('aborts in-flight playlist refreshes when switching', function() { 314 test('aborts in-flight playlist refreshes when switching', function() {
315 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 315 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
316 requests.pop().respond(200, null, 316 requests.pop().respond(200, null,
317 '#EXTM3U\n' + 317 '#EXTM3U\n' +
318 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + 318 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
...@@ -331,7 +331,7 @@ ...@@ -331,7 +331,7 @@
331 }); 331 });
332 332
333 test('switching to the active playlist is a no-op', function() { 333 test('switching to the active playlist is a no-op', function() {
334 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 334 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
335 requests.pop().respond(200, null, 335 requests.pop().respond(200, null,
336 '#EXTM3U\n' + 336 '#EXTM3U\n' +
337 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + 337 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
...@@ -350,7 +350,7 @@ ...@@ -350,7 +350,7 @@
350 }); 350 });
351 351
352 test('throws an error if a media switch is initiated too early', function() { 352 test('throws an error if a media switch is initiated too early', function() {
353 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 353 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
354 354
355 throws(function() { 355 throws(function() {
356 loader.media('high.m3u8'); 356 loader.media('high.m3u8');
...@@ -368,7 +368,7 @@ ...@@ -368,7 +368,7 @@
368 }); 368 });
369 369
370 test('throws an error if a switch to an unrecognized playlist is requested', function() { 370 test('throws an error if a switch to an unrecognized playlist is requested', function() {
371 var loader = new videojs.hls.PlaylistLoader('master.m3u8'); 371 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
372 requests.pop().respond(200, null, 372 requests.pop().respond(200, null,
373 '#EXTM3U\n' + 373 '#EXTM3U\n' +
374 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' + 374 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
...@@ -378,4 +378,31 @@ ...@@ -378,4 +378,31 @@
378 loader.media('unrecognized.m3u8'); 378 loader.media('unrecognized.m3u8');
379 }, 'throws an error'); 379 }, 'throws an error');
380 }); 380 });
381
382 test('dispose cancels the refresh timeout', function() {
383 var loader = new videojs.Hls.PlaylistLoader('live.m3u8');
384 requests.pop().respond(200, null,
385 '#EXTM3U\n' +
386 '#EXT-X-MEDIA-SEQUENCE:0\n' +
387 '#EXTINF:10,\n' +
388 '0.ts\n');
389 loader.dispose();
390 // a lot of time passes...
391 clock.tick(15 * 1000);
392
393 strictEqual(requests.length, 0, 'no refresh request was made');
394 });
395
396 test('dispose aborts pending refresh requests', function() {
397 var loader = new videojs.Hls.PlaylistLoader('live.m3u8');
398 requests.pop().respond(200, null,
399 '#EXTM3U\n' +
400 '#EXT-X-MEDIA-SEQUENCE:0\n' +
401 '#EXTINF:10,\n' +
402 '0.ts\n');
403 clock.tick(10 * 1000);
404
405 loader.dispose();
406 ok(requests[0].aborted, 'refresh request aborted');
407 });
381 })(window); 408 })(window);
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
39 39
40 module('segment parser', { 40 module('segment parser', {
41 setup: function() { 41 setup: function() {
42 parser = new window.videojs.hls.SegmentParser(); 42 parser = new window.videojs.Hls.SegmentParser();
43 } 43 }
44 }); 44 });
45 45
...@@ -168,11 +168,11 @@ ...@@ -168,11 +168,11 @@
168 result = result.concat(makePsi(settings)); 168 result = result.concat(makePsi(settings));
169 169
170 // ensure the resulting packet is the correct size 170 // ensure the resulting packet is the correct size
171 result.length = window.videojs.hls.SegmentParser.MP2T_PACKET_LENGTH; 171 result.length = window.videojs.Hls.SegmentParser.MP2T_PACKET_LENGTH;
172 return result; 172 return result;
173 }, 173 },
174 h264Type = window.videojs.hls.SegmentParser.STREAM_TYPES.h264, 174 h264Type = window.videojs.Hls.SegmentParser.STREAM_TYPES.h264,
175 adtsType = window.videojs.hls.SegmentParser.STREAM_TYPES.adts; 175 adtsType = window.videojs.Hls.SegmentParser.STREAM_TYPES.adts;
176 176
177 parser.parseSegmentBinaryData(new Uint8Array(makePacket({ 177 parser.parseSegmentBinaryData(new Uint8Array(makePacket({
178 programs: { 178 programs: {
......