Initial tests for allow_cache, extinf, mediasequence, and byterange.
Showing
6 changed files
with
469 additions
and
36 deletions
... | @@ -73,11 +73,11 @@ | ... | @@ -73,11 +73,11 @@ |
73 | ok(parsedData); | 73 | ok(parsedData); |
74 | }); | 74 | }); |
75 | 75 | ||
76 | test('should populate the manifest data object', function() { | 76 | test('valid manifest should populate the manifest data object', function() { |
77 | var data = m3u8parser.parse(window.playlistData); | 77 | var data = m3u8parser.parse(window.playlistData); |
78 | 78 | ||
79 | notEqual(data, null, 'data is not NULL'); | 79 | notEqual(data, null, 'data is not NULL'); |
80 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 80 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
81 | equal(data.hasValidM3UTag, true, 'data has valid EXTM3U'); | 81 | equal(data.hasValidM3UTag, true, 'data has valid EXTM3U'); |
82 | equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); | 82 | equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); |
83 | equal(data.allowCache, "NO", 'acceptable ALLOW CACHE'); | 83 | equal(data.allowCache, "NO", 'acceptable ALLOW CACHE'); |
... | @@ -101,7 +101,8 @@ | ... | @@ -101,7 +101,8 @@ |
101 | tag. | 101 | tag. |
102 | 102 | ||
103 | The EXT-X-PLAYLIST-TYPE tag MUST NOT appear in a Master Playlist. | 103 | The EXT-X-PLAYLIST-TYPE tag MUST NOT appear in a Master Playlist. |
104 | */ | 104 | */ |
105 | |||
105 | test('should have parsed VOD playlist type', function() { | 106 | test('should have parsed VOD playlist type', function() { |
106 | var | 107 | var |
107 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 108 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
... | @@ -110,7 +111,7 @@ | ... | @@ -110,7 +111,7 @@ |
110 | data = m3u8parser.parse(playlistData); | 111 | data = m3u8parser.parse(playlistData); |
111 | 112 | ||
112 | notEqual(data, null, 'data is not NULL'); | 113 | notEqual(data, null, 'data is not NULL'); |
113 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 114 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
114 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); | 115 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); |
115 | }); | 116 | }); |
116 | 117 | ||
... | @@ -121,7 +122,7 @@ | ... | @@ -121,7 +122,7 @@ |
121 | playlistData = playlistTemplate(testData), | 122 | playlistData = playlistTemplate(testData), |
122 | data = m3u8parser.parse(playlistData); | 123 | data = m3u8parser.parse(playlistData); |
123 | notEqual(data, null, 'data is not NULL'); | 124 | notEqual(data, null, 'data is not NULL'); |
124 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 125 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
125 | equal(data.playlistType, "EVENT", 'acceptable PLAYLIST TYPE'); | 126 | equal(data.playlistType, "EVENT", 'acceptable PLAYLIST TYPE'); |
126 | }); | 127 | }); |
127 | 128 | ||
... | @@ -133,7 +134,8 @@ | ... | @@ -133,7 +134,8 @@ |
133 | data = m3u8parser.parse(playlistData); | 134 | data = m3u8parser.parse(playlistData); |
134 | 135 | ||
135 | notEqual(data, null, 'data is not NULL'); | 136 | notEqual(data, null, 'data is not NULL'); |
136 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 137 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
138 | equal(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD'); | ||
137 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); | 139 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); |
138 | }); | 140 | }); |
139 | 141 | ||
... | @@ -145,18 +147,19 @@ | ... | @@ -145,18 +147,19 @@ |
145 | data = m3u8parser.parse(playlistData); | 147 | data = m3u8parser.parse(playlistData); |
146 | notEqual(data, null, 'data is not NULL'); | 148 | notEqual(data, null, 'data is not NULL'); |
147 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 149 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
148 | equal(data.invalidReasons[0], 'Invalid Playlist Type Value: baklsdhfajsdf'); | 150 | equal(data.invalidReasons[0], 'Invalid Playlist Type Value: \'baklsdhfajsdf\''); |
149 | }); | 151 | }); |
150 | 152 | ||
151 | test('should have an invalid reason due to invalid playlist type', function() { | 153 | test('should have assumed VOD playlist type is empty', function() { |
152 | var | 154 | var |
153 | playlistTemplate = Handlebars.compile(window.playlist_type_template), | 155 | playlistTemplate = Handlebars.compile(window.playlist_type_template), |
154 | testData = {playlistType: ''}, | 156 | testData = {playlistType: ''}, |
155 | playlistData = playlistTemplate(testData), | 157 | playlistData = playlistTemplate(testData), |
156 | data = m3u8parser.parse(playlistData); | 158 | data = m3u8parser.parse(playlistData); |
157 | notEqual(data, null, 'data is not NULL'); | 159 | notEqual(data, null, 'data is not NULL'); |
158 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 160 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
159 | equal(data.invalidReasons[0], 'Invalid Playlist Type Value: \'\''); | 161 | equal(data.warnings, 'EXT-X-PLAYLIST-TYPE was empty or missing. Assuming VOD'); |
162 | equal(data.playlistType, "VOD", 'acceptable PLAYLIST TYPE'); | ||
160 | }); | 163 | }); |
161 | 164 | ||
162 | /*3.4.2. EXT-X-TARGETDURATION | 165 | /*3.4.2. EXT-X-TARGETDURATION |
... | @@ -190,33 +193,43 @@ | ... | @@ -190,33 +193,43 @@ |
190 | test('NaN target duration', function() { | 193 | test('NaN target duration', function() { |
191 | var | 194 | var |
192 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | 195 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
193 | testData = {targetDuration: '10'}, | 196 | testData = {targetDuration: 'string'}, |
194 | playlistData = playlistTemplate(testData), | 197 | playlistData = playlistTemplate(testData), |
195 | data = m3u8parser.parse(playlistData); | 198 | data = m3u8parser.parse(playlistData); |
196 | notEqual(data, null, 'data is not NULL'); | 199 | console.log(playlistData); |
197 | equal(data.targetDuration, 10, 'data has correct TARGET DURATION'); | 200 | console.log(data.targetDuration); |
198 | equal(data.invalidReasons.length, 0, 'data has 1 invalid reasons'); | 201 | notEqual(data, null, 'data is not NULL'); |
199 | |||
200 | testData = {targetDuration: 'string'}; | ||
201 | playlistData = playlistTemplate(testData); | ||
202 | data = m3u8parser.parse(playlistData); | ||
203 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 202 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
204 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 203 | equal(data.invalidReasons.length, 1, 'data has 0 invalid reasons'); |
205 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: string'); | 204 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\''); |
205 | }); | ||
206 | 206 | ||
207 | testData = {targetDuration: ''}; | 207 | test('empty target duration', function() { |
208 | playlistData = playlistTemplate(testData); | 208 | var |
209 | data = m3u8parser.parse(playlistData); | 209 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), |
210 | testData = {targetDuration: '\'\''}, | ||
211 | playlistData = playlistTemplate(testData), | ||
212 | data = m3u8parser.parse(playlistData); | ||
213 | console.log(playlistData); | ||
214 | console.log(data.targetDuration); | ||
215 | notEqual(data, null, 'data is not NULL'); | ||
210 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 216 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
211 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 217 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
212 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'\''); | 218 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'NaN\''); |
219 | }); | ||
213 | 220 | ||
214 | testData = {}; | 221 | test('undefined target duration', function() { |
215 | playlistData = playlistTemplate(testData); | 222 | var |
223 | playlistTemplate = Handlebars.compile(window.playlist_target_duration_template), | ||
224 | testData = {}, | ||
225 | playlistData = playlistTemplate(testData), | ||
226 | data = m3u8parser.parse(playlistData); | ||
227 | console.log(playlistData); | ||
228 | console.log(data.targetDuration); | ||
216 | notEqual(data, null, 'data is not NULL'); | 229 | notEqual(data, null, 'data is not NULL'); |
217 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 230 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
218 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 231 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
219 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: '+ undefined); | 232 | equal(data.invalidReasons[0], 'Invalid Target Duration Value: \'undefined\''); |
220 | 233 | ||
221 | }); | 234 | }); |
222 | 235 | ||
... | @@ -251,11 +264,11 @@ | ... | @@ -251,11 +264,11 @@ |
251 | MEDIA-SEQUENCE tag then the sequence number of the first segment in | 264 | MEDIA-SEQUENCE tag then the sequence number of the first segment in |
252 | the playlist SHALL be considered to be 0. A client MUST NOT assume | 265 | the playlist SHALL be considered to be 0. A client MUST NOT assume |
253 | that segments with the same sequence number in different Media | 266 | that segments with the same sequence number in different Media |
254 | Playlists contain matching content. | 267 | Playlists contain matching content. |
255 | 268 | ||
256 | A media URI is not required to contain its sequence number. | 269 | A media URI is not required to contain its sequence number. |
257 | */ | 270 | */ |
258 | 271 | ||
259 | test('media sequence is valid in the playlist', function() { | 272 | test('media sequence is valid in the playlist', function() { |
260 | var | 273 | var |
261 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), | 274 | playlistTemplate = Handlebars.compile(window.playlist_media_sequence_template), |
... | @@ -265,7 +278,7 @@ | ... | @@ -265,7 +278,7 @@ |
265 | 278 | ||
266 | notEqual(data, null, 'data is not NULL'); | 279 | notEqual(data, null, 'data is not NULL'); |
267 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 280 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
268 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 281 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
269 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); | 282 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE is correct'); |
270 | }); | 283 | }); |
271 | 284 | ||
... | @@ -278,7 +291,7 @@ | ... | @@ -278,7 +291,7 @@ |
278 | 291 | ||
279 | notEqual(data, null, 'data is not NULL'); | 292 | notEqual(data, null, 'data is not NULL'); |
280 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 293 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
281 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 294 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
282 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE tags after the first should be ignored'); | 295 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE tags after the first should be ignored'); |
283 | }); | 296 | }); |
284 | 297 | ||
... | @@ -291,7 +304,7 @@ | ... | @@ -291,7 +304,7 @@ |
291 | 304 | ||
292 | notEqual(data, null, 'data is not NULL'); | 305 | notEqual(data, null, 'data is not NULL'); |
293 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 306 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
294 | equal(data.invalidReasons.length, 0, 'data has 0 invalid reasons'); | 307 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); |
295 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE should default to 0 when not present.'); | 308 | equal(data.mediaSequence, 0, 'MEDIA SEQUENCE should default to 0 when not present.'); |
296 | }); | 309 | }); |
297 | 310 | ||
... | @@ -318,7 +331,7 @@ | ... | @@ -318,7 +331,7 @@ |
318 | notEqual(data, null, 'data is not NULL'); | 331 | notEqual(data, null, 'data is not NULL'); |
319 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 332 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
320 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 333 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
321 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: 1'); | 334 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'1\''); |
322 | }); | 335 | }); |
323 | 336 | ||
324 | test('media sequence (-1) in the playlist', function() { | 337 | test('media sequence (-1) in the playlist', function() { |
... | @@ -331,7 +344,7 @@ | ... | @@ -331,7 +344,7 @@ |
331 | notEqual(data, null, 'data is not NULL'); | 344 | notEqual(data, null, 'data is not NULL'); |
332 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 345 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
333 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 346 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
334 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: -1'); | 347 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'-1\''); |
335 | }); | 348 | }); |
336 | 349 | ||
337 | test('media sequence invalid (string) in the playlist', function() { | 350 | test('media sequence invalid (string) in the playlist', function() { |
... | @@ -344,7 +357,7 @@ | ... | @@ -344,7 +357,7 @@ |
344 | notEqual(data, null, 'data is not NULL'); | 357 | notEqual(data, null, 'data is not NULL'); |
345 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | 358 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); |
346 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | 359 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); |
347 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: asdfkasdkfl'); | 360 | equal(data.invalidReasons[0], 'Invalid Media Sequence Value: \'asdfkasdkfl\''); |
348 | }); | 361 | }); |
349 | 362 | ||
350 | module('brightcove playlist', { | 363 | module('brightcove playlist', { |
... | @@ -365,4 +378,245 @@ | ... | @@ -365,4 +378,245 @@ |
365 | equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct'); | 378 | equal(data.playlistItems[0].resolution.height, 224, 'First rendition index resolution height is correct'); |
366 | 379 | ||
367 | }); | 380 | }); |
381 | |||
382 | /*3.3.2. EXTINF | ||
383 | |||
384 | The EXTINF tag specifies the duration of a media segment. It applies | ||
385 | only to the media segment that follows it, and MUST be followed by a | ||
386 | media segment URI. Each media segment MUST be preceded by an EXTINF | ||
387 | tag. Its format is: | ||
388 | |||
389 | #EXTINF:<duration>,<title> | ||
390 | |||
391 | where duration is an decimal-integer or decimal-floating-point number | ||
392 | that specifies the duration of the media segment in seconds. | ||
393 | Durations that are reported as integers SHOULD be rounded to the | ||
394 | nearest integer. Durations MUST be integers if the protocol version | ||
395 | of the Playlist file is less than 3. Durations SHOULD be floating- | ||
396 | point if the version is equal to or greater than 3. The remainder of | ||
397 | the line following the comma is an optional human-readable | ||
398 | informative title of the media segment. | ||
399 | |||
400 | The EXTINF duration of each media segment in the Playlist | ||
401 | file, when rounded to the nearest integer, MUST be less than or equal | ||
402 | to the target duration. | ||
403 | */ | ||
404 | |||
405 | test('test valid extinf values in playlist', function() { | ||
406 | var | ||
407 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
408 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, | ||
409 | playlistData = playlistTemplate(testData), | ||
410 | data = m3u8parser.parse(playlistData); | ||
411 | |||
412 | notEqual(data, null, 'data is not NULL'); | ||
413 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
414 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); | ||
415 | }); | ||
416 | |||
417 | test('test valid extinf without associated segment in playlist', function() { | ||
418 | var | ||
419 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
420 | testData = {version: 4, extInf: '10', extInf1: '10', extInf2: '10'}, | ||
421 | playlistData = playlistTemplate(testData), | ||
422 | data = m3u8parser.parse(playlistData); | ||
423 | |||
424 | notEqual(data, null, 'data is not NULL'); | ||
425 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
426 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
427 | //equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF missing segment\''); | ||
428 | }); | ||
429 | |||
430 | // | ||
431 | test('test invalid extinf values in playlist', function() { | ||
432 | var | ||
433 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
434 | testData = {version: 4, extInf: 'asdf', extInf1: '10', extInf2: '10', segment: 'hls_450k_video.ts'}, | ||
435 | playlistData = playlistTemplate(testData), | ||
436 | data = m3u8parser.parse(playlistData); | ||
437 | |||
438 | notEqual(data, null, 'data is not NULL'); | ||
439 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
440 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
441 | }); | ||
442 | |||
443 | //its best practice that every extinf have the same value, but its not required | ||
444 | test('test inconsistent extinf values in playlist below target duration', function() { | ||
445 | var | ||
446 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
447 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, | ||
448 | playlistData = playlistTemplate(testData), | ||
449 | data = m3u8parser.parse(playlistData); | ||
450 | |||
451 | notEqual(data, null, 'data is not NULL'); | ||
452 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
453 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); | ||
454 | }); | ||
455 | |||
456 | //extinf values must be below the target duration | ||
457 | test('test inconsistent extinf values in playlist above target duration', function() { | ||
458 | var | ||
459 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
460 | testData = {version: 4, extInf: '10', extInf1: '7', extInf2: '10', segment: 'hls_450k_video.ts'}, | ||
461 | playlistData = playlistTemplate(testData), | ||
462 | data = m3u8parser.parse(playlistData); | ||
463 | |||
464 | notEqual(data, null, 'data is not NULL'); | ||
465 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
466 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
467 | equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value higher than #TARGETDURATION\''); | ||
468 | }); | ||
469 | |||
470 | //extinf values must be below the target duration | ||
471 | test('test floating-point values not accepted with version 3', function() { | ||
472 | var | ||
473 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
474 | testData = {version: 3, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | ||
475 | playlistData = playlistTemplate(testData), | ||
476 | data = m3u8parser.parse(playlistData); | ||
477 | |||
478 | notEqual(data, null, 'data is not NULL'); | ||
479 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
480 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
481 | equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value not an integer\''); | ||
482 | }); | ||
483 | |||
484 | //extinf values must be below the target duration | ||
485 | test('test floating-point values accepted with version 4', function() { | ||
486 | var | ||
487 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
488 | testData = {version: 4, extInf: '10.5', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | ||
489 | playlistData = playlistTemplate(testData), | ||
490 | data = m3u8parser.parse(playlistData); | ||
491 | |||
492 | notEqual(data, null, 'data is not NULL'); | ||
493 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
494 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); | ||
495 | }); | ||
496 | |||
497 | //extinf values must be below the target duration | ||
498 | test('test empty EXTINF values', function() { | ||
499 | var | ||
500 | playlistTemplate = Handlebars.compile(window.playlist_extinf_template), | ||
501 | testData = {version: 4, extInf: '', extInf1: '10.5', extInf2: '10.5', segment: 'hls_450k_video.ts'}, | ||
502 | playlistData = playlistTemplate(testData), | ||
503 | data = m3u8parser.parse(playlistData); | ||
504 | |||
505 | notEqual(data, null, 'data is not NULL'); | ||
506 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
507 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
508 | equal(data.invalidReasons[0], 'Invalid Segment Data: \'#EXTINF value empty\''); | ||
509 | }); | ||
510 | |||
511 | /* | ||
512 | 3.3.6. EXT-X-ALLOW-CACHE | ||
513 | |||
514 | The EXT-X-ALLOW-CACHE tag indicates whether the client MAY or MUST | ||
515 | NOT cache downloaded media segments for later replay. It MAY occur | ||
516 | anywhere in the Playlist file; it MUST NOT occur more than once. The | ||
517 | EXT-X-ALLOW-CACHE tag applies to all segments in the playlist. Its | ||
518 | format is: | ||
519 | |||
520 | #EXT-X-ALLOW-CACHE:<YES|NO> | ||
521 | */ | ||
522 | |||
523 | test('test EXT-X-ALLOW-CACHE YES', function() { | ||
524 | var | ||
525 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | ||
526 | testData = {version: 4, allowCache: 'YES'}, | ||
527 | playlistData = playlistTemplate(testData), | ||
528 | data = m3u8parser.parse(playlistData); | ||
529 | |||
530 | notEqual(data, null, 'data is not NULL'); | ||
531 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
532 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); | ||
533 | equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should be YES'); | ||
534 | }); | ||
535 | |||
536 | test('test EXT-X-ALLOW-CACHE NO', function() { | ||
537 | var | ||
538 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | ||
539 | testData = {version: 4, allowCache: 'NO'}, | ||
540 | playlistData = playlistTemplate(testData), | ||
541 | data = m3u8parser.parse(playlistData); | ||
542 | |||
543 | notEqual(data, null, 'data is not NULL'); | ||
544 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
545 | equal(data.invalidReasons.length, 0, 'Errors object should not be empty.'); | ||
546 | equal(data.allowCache, 'NO', 'EXT-X-ALLOW-CACHE should be NO'); | ||
547 | }); | ||
548 | |||
549 | test('test EXT-X-ALLOW-CACHE invalid, default to YES', function() { | ||
550 | var | ||
551 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | ||
552 | testData = {version: 4, allowCache: 'YESTERDAYNO'}, | ||
553 | playlistData = playlistTemplate(testData), | ||
554 | data = m3u8parser.parse(playlistData); | ||
555 | |||
556 | notEqual(data, null, 'data is not NULL'); | ||
557 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
558 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
559 | equal(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'YESTERDAYNO\''); | ||
560 | equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.'); | ||
561 | }); | ||
562 | |||
563 | test('test EXT-X-ALLOW-CACHE empty, default to YES', function() { | ||
564 | var | ||
565 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | ||
566 | testData = {version: 4, allowCache: ''}, | ||
567 | playlistData = playlistTemplate(testData), | ||
568 | data = m3u8parser.parse(playlistData); | ||
569 | |||
570 | notEqual(data, null, 'data is not NULL'); | ||
571 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
572 | equal(data.invalidReasons.length, 1, 'data has 1 invalid reasons'); | ||
573 | equal(data.invalidReasons[0], 'Invalid EXT-X-ALLOW-CACHE value: \'\''); | ||
574 | equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES.'); | ||
575 | }); | ||
576 | |||
577 | test('test EXT-X-ALLOW-CACHE missing, default to YES', function() { | ||
578 | var | ||
579 | playlistTemplate = Handlebars.compile(window.playlist_allow_cache), | ||
580 | testData = {version: 4}, | ||
581 | playlistData = playlistTemplate(testData), | ||
582 | data = m3u8parser.parse(playlistData); | ||
583 | |||
584 | notEqual(data, null, 'data is not NULL'); | ||
585 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
586 | equal(data.invalidReasons.length, 1, 'No EXT-X-ALLOW-CACHE specified. Default: YES.'); | ||
587 | equal(data.allowCache, 'YES', 'EXT-X-ALLOW-CACHE should default to YES'); | ||
588 | }); | ||
589 | |||
590 | test('test EXT-X-BYTERANGE valid', function() { | ||
591 | var | ||
592 | playlistTemplate = Handlebars.compile(window.playlist_byte_range), | ||
593 | testData = {version: 4, byteRange: '522828,0', byteRange1: '587500,522828', byteRange2: '44556,8353216'}, | ||
594 | playlistData = playlistTemplate(testData), | ||
595 | data = m3u8parser.parse(playlistData); | ||
596 | |||
597 | notEqual(data, null, 'data is not NULL'); | ||
598 | notEqual(data.invalidReasons, null, 'invalidReasons is not NULL'); | ||
599 | equal(data.invalidReasons.length, 0, 'Errors object should be empty.'); | ||
600 | //TODO: Validate the byteRange info | ||
601 | equal(data.mediaItems.length, 16, '16 segments should have been parsed.'); | ||
602 | equal(data.mediaItems[0].byterange, testData.byteRange, 'byteRange incorrect.'); | ||
603 | equal(data.mediaItems[1].byterange, testData.byteRange1, 'byteRange1 incorrect.'); | ||
604 | equal(data.mediaItems[15].byterange, testData.byteRange2, 'byteRange2 incorrect.'); | ||
605 | }); | ||
606 | |||
607 | test('test EXT-X-BYTERANGE used but version is < 4', function() { | ||
608 | var | ||
609 | playlistTemplate = Handlebars.compile(window.playlist_byte_range), | ||
610 | testData = {version: 3, byteRange: ['522828,0'], byteRange1: ['587500,522828'], byteRange2: ['44556,8353216']}, | ||
611 | playlistData = playlistTemplate(testData), | ||
612 | data = m3u8parser.parse(playlistData); | ||
613 | |||
614 | notEqual(data, null, 'data is not NULL'); | ||
615 | equal(data.mediaItems.length, 16, '16 segments should have been parsed.'); | ||
616 | notEqual(data.invalidReasons, null, 'there should be an error'); | ||
617 | equal(data.invalidReasons.length, 1, 'there should be 1 error'); | ||
618 | //TODO: Validate the byteRange info | ||
619 | equal(data.invalidReasons[0], 'EXT-X-BYTERANGE used but version is < 4.') | ||
620 | }); | ||
621 | |||
368 | })(this); | 622 | })(this); |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | window.playlist_allow_cache = '#EXTM3U\n'+ | ||
2 | '#EXT-X-TARGETDURATION:10\n' + | ||
3 | '#EXT-X-VERSION:{{{version}}}\n' + | ||
4 | '{{#if allowCache}}#EXT-X-ALLOW-CACHE:{{{allowCache}}}{{/if}}\n' + | ||
5 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | ||
6 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | ||
7 | '#EXTINF:10,\n' + | ||
8 | '#EXT-X-BYTERANGE:522828@0\n' + | ||
9 | 'hls_450k_video.ts\n' + | ||
10 | '#EXTINF:10,\n' + | ||
11 | '#EXT-X-BYTERANGE:587500@522828\n' + | ||
12 | 'hls_450k_video.ts\n' + | ||
13 | '#EXTINF:10,\n' + | ||
14 | '#EXT-X-BYTERANGE:713084@1110328\n' + | ||
15 | 'hls_450k_video.ts\n' + | ||
16 | '#EXTINF:10,\n' + | ||
17 | '#EXT-X-BYTERANGE:476580@1823412\n' + | ||
18 | 'hls_450k_video.ts\n' + | ||
19 | '#EXTINF:10,\n' + | ||
20 | '#EXT-X-BYTERANGE:535612@2299992\n' + | ||
21 | 'hls_450k_video.ts\n' + | ||
22 | '#EXTINF:10,\n' + | ||
23 | '#EXT-X-BYTERANGE:207176@2835604\n' + | ||
24 | 'hls_450k_video.ts\n' + | ||
25 | '#EXTINF:10,\n' + | ||
26 | '#EXT-X-BYTERANGE:455900@3042780\n' + | ||
27 | 'hls_450k_video.ts\n' + | ||
28 | '#EXTINF:10,\n' + | ||
29 | '#EXT-X-BYTERANGE:657248@3498680\n' + | ||
30 | 'hls_450k_video.ts\n' + | ||
31 | '#EXTINF:10,\n' + | ||
32 | '#EXT-X-BYTERANGE:571708@4155928\n' + | ||
33 | 'hls_450k_video.ts\n' + | ||
34 | '#EXTINF:10,\n' + | ||
35 | '#EXT-X-BYTERANGE:485040@4727636\n' + | ||
36 | 'hls_450k_video.ts\n' + | ||
37 | '#EXTINF:10,\n' + | ||
38 | '#EXT-X-BYTERANGE:709136@5212676\n' + | ||
39 | 'hls_450k_video.ts\n' + | ||
40 | '#EXTINF:10,\n' + | ||
41 | '#EXT-X-BYTERANGE:730004@5921812\n' + | ||
42 | 'hls_450k_video.ts\n' + | ||
43 | '#EXTINF:10,\n' + | ||
44 | '#EXT-X-BYTERANGE:456276@6651816\n' + | ||
45 | 'hls_450k_video.ts\n' + | ||
46 | '#EXTINF:10,\n' + | ||
47 | '#EXT-X-BYTERANGE:468684@7108092\n' + | ||
48 | 'hls_450k_video.ts' + | ||
49 | '#EXTINF:10,\n' + | ||
50 | '#EXT-X-BYTERANGE:444996@7576776\n' + | ||
51 | 'hls_450k_video.ts\n' + | ||
52 | '#EXTINF:10,\n' + | ||
53 | '#EXT-X-BYTERANGE:331444@8021772\n' + | ||
54 | 'hls_450k_video.ts\n' + | ||
55 | '#EXTINF:1.4167,\n' + | ||
56 | '#EXT-X-BYTERANGE:44556@8353216\n' + | ||
57 | 'hls_450k_video.ts\n' + | ||
58 | '#EXT-X-ENDLIST'; |
1 | window.playlist_byte_range = '#EXTM3U\n'+ | ||
2 | '#EXT-X-TARGETDURATION:10\n' + | ||
3 | '#EXT-X-VERSION:{{{version}}}\n' + | ||
4 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | ||
5 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | ||
6 | '#EXTINF:10,\n' + | ||
7 | '{{#if byteRange}}#EXT-X-BYTERANGE:{{{byteRange}}}{{/if}}\n' + | ||
8 | //'#EXT-X-BYTERANGE:522828@0\n' + | ||
9 | 'hls_450k_video.ts\n' + | ||
10 | '#EXTINF:10,\n' + | ||
11 | '{{#if byteRange1}}#EXT-X-BYTERANGE:{{{byteRange1}}}{{/if}}\n' + | ||
12 | //'#EXT-X-BYTERANGE:587500@522828\n' + | ||
13 | 'hls_450k_video.ts\n' + | ||
14 | '#EXTINF:10,\n' + | ||
15 | '#EXT-X-BYTERANGE:713084@1110328\n' + | ||
16 | 'hls_450k_video.ts\n' + | ||
17 | '#EXTINF:10,\n' + | ||
18 | '#EXT-X-BYTERANGE:476580@1823412\n' + | ||
19 | 'hls_450k_video.ts\n' + | ||
20 | '#EXTINF:10,\n' + | ||
21 | '#EXT-X-BYTERANGE:535612@2299992\n' + | ||
22 | 'hls_450k_video.ts\n' + | ||
23 | '#EXTINF:10,\n' + | ||
24 | '#EXT-X-BYTERANGE:207176@2835604\n' + | ||
25 | 'hls_450k_video.ts\n' + | ||
26 | '#EXTINF:10,\n' + | ||
27 | '#EXT-X-BYTERANGE:455900@3042780\n' + | ||
28 | 'hls_450k_video.ts\n' + | ||
29 | '#EXTINF:10,\n' + | ||
30 | '#EXT-X-BYTERANGE:657248@3498680\n' + | ||
31 | 'hls_450k_video.ts\n' + | ||
32 | '#EXTINF:10,\n' + | ||
33 | '#EXT-X-BYTERANGE:571708@4155928\n' + | ||
34 | 'hls_450k_video.ts\n' + | ||
35 | '#EXTINF:10,\n' + | ||
36 | '#EXT-X-BYTERANGE:485040@4727636\n' + | ||
37 | 'hls_450k_video.ts\n' + | ||
38 | '#EXTINF:10,\n' + | ||
39 | '#EXT-X-BYTERANGE:709136@5212676\n' + | ||
40 | 'hls_450k_video.ts\n' + | ||
41 | '#EXTINF:10,\n' + | ||
42 | '#EXT-X-BYTERANGE:730004@5921812\n' + | ||
43 | 'hls_450k_video.ts\n' + | ||
44 | '#EXTINF:10,\n' + | ||
45 | '#EXT-X-BYTERANGE:456276@6651816\n' + | ||
46 | 'hls_450k_video.ts\n' + | ||
47 | '#EXTINF:10,\n' + | ||
48 | '#EXT-X-BYTERANGE:468684@7108092\n' + | ||
49 | 'hls_450k_video.ts' + | ||
50 | '#EXTINF:10,\n' + | ||
51 | '#EXT-X-BYTERANGE:444996@7576776\n' + | ||
52 | 'hls_450k_video.ts\n' + | ||
53 | '#EXTINF:10,\n' + | ||
54 | '#EXT-X-BYTERANGE:331444@8021772\n' + | ||
55 | 'hls_450k_video.ts\n' + | ||
56 | '#EXTINF:1.4167,\n' + | ||
57 | '{{#if byteRange2}}#EXT-X-BYTERANGE:{{{byteRange2}}}{{/if}}\n' + | ||
58 | //'#EXT-X-BYTERANGE:44556@8353216\n' + | ||
59 | 'hls_450k_video.ts\n' + | ||
60 | '#EXT-X-ENDLIST'; |
test/manifest/playlist_extinf_template.js
0 → 100644
1 | window.playlist_extinf_template = '#EXTM3U\n'+ | ||
2 | '#EXT-X-TARGETDURATION:10\n' + | ||
3 | '#EXT-X-VERSION:{{{version}}}\n' + | ||
4 | '#EXT-X-MEDIA-SEQUENCE:0\n' + | ||
5 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | ||
6 | '{{#if extInf}}#EXTINF:{{{extInf}}}{{/if}}\n' + | ||
7 | '#EXT-X-BYTERANGE:522828@0\n' + | ||
8 | '{{#if segment}}{{{segment}}}\n{{/if}}' + | ||
9 | '{{#if extInf1}}#EXTINF:{{{extInf1}}}{{/if}}\n' + | ||
10 | '#EXT-X-BYTERANGE:587500@522828\n' + | ||
11 | 'hls_450k_video.ts\n' + | ||
12 | '#EXTINF:10,\n' + | ||
13 | '#EXT-X-BYTERANGE:713084@1110328\n' + | ||
14 | 'hls_450k_video.ts\n' + | ||
15 | '#EXTINF:10,\n' + | ||
16 | '#EXT-X-BYTERANGE:476580@1823412\n' + | ||
17 | 'hls_450k_video.ts\n' + | ||
18 | '#EXTINF:10,\n' + | ||
19 | '#EXT-X-BYTERANGE:535612@2299992\n' + | ||
20 | 'hls_450k_video.ts\n' + | ||
21 | '#EXTINF:10,\n' + | ||
22 | '#EXT-X-BYTERANGE:207176@2835604\n' + | ||
23 | 'hls_450k_video.ts\n' + | ||
24 | '#EXTINF:10,\n' + | ||
25 | '#EXT-X-BYTERANGE:455900@3042780\n' + | ||
26 | 'hls_450k_video.ts\n' + | ||
27 | '#EXTINF:10,\n' + | ||
28 | '#EXT-X-BYTERANGE:657248@3498680\n' + | ||
29 | 'hls_450k_video.ts\n' + | ||
30 | '#EXTINF:10,\n' + | ||
31 | '#EXT-X-BYTERANGE:571708@4155928\n' + | ||
32 | 'hls_450k_video.ts\n' + | ||
33 | '#EXTINF:10,\n' + | ||
34 | '#EXT-X-BYTERANGE:485040@4727636\n' + | ||
35 | 'hls_450k_video.ts\n' + | ||
36 | '#EXTINF:10,\n' + | ||
37 | '#EXT-X-BYTERANGE:709136@5212676\n' + | ||
38 | 'hls_450k_video.ts\n' + | ||
39 | '#EXTINF:10,\n' + | ||
40 | '#EXT-X-BYTERANGE:730004@5921812\n' + | ||
41 | 'hls_450k_video.ts\n' + | ||
42 | '#EXTINF:10,\n' + | ||
43 | '#EXT-X-BYTERANGE:456276@6651816\n' + | ||
44 | 'hls_450k_video.ts\n' + | ||
45 | '#EXTINF:10,\n' + | ||
46 | '#EXT-X-BYTERANGE:468684@7108092\n' + | ||
47 | 'hls_450k_video.ts' + | ||
48 | '#EXTINF:10,\n' + | ||
49 | '#EXT-X-BYTERANGE:444996@7576776\n' + | ||
50 | 'hls_450k_video.ts\n' + | ||
51 | '#EXTINF:10,\n' + | ||
52 | '#EXT-X-BYTERANGE:331444@8021772\n' + | ||
53 | 'hls_450k_video.ts\n' + | ||
54 | '{{#if extInf2}}#EXTINF:{{{extInf2}}}{{/if}}\n' + | ||
55 | '#EXT-X-BYTERANGE:44556@8353216\n' + | ||
56 | 'hls_450k_video.ts\n' + | ||
57 | '#EXT-X-ENDLIST'; |
1 | window.playlist_media_sequence_template = '#EXTM3U\n'+ | 1 | window.playlist_media_sequence_template = '#EXTM3U\n'+ |
2 | '#EXT-X-PLAYLIST-TYPE:VOD\n'+ | 2 | '#EXT-X-PLAYLIST-TYPE:VOD\n'+ |
3 | '{{#if mediaSequence}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence}}}{{/if}}\n'+ | 3 | '{{#if mediaSequence}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence}}}{{/if}}\n'+ |
4 | '{{#if mediaSequence2}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence2}}}{{/if}}\n'+ | 4 | '{{#if mediaSequence1}}#EXT-X-MEDIA-SEQUENCE:{{{mediaSequence2}}}{{/if}}\n'+ |
5 | '#EXT-X-ALLOW-CACHE:YES\n'+ | 5 | '#EXT-X-ALLOW-CACHE:YES\n'+ |
6 | '#EXT-X-TARGETDURATION:8\n'+ | 6 | '#EXT-X-TARGETDURATION:8\n'+ |
7 | '#EXTINF:6.640,{}\n'+ | 7 | '#EXTINF:6.640,{}\n'+ | ... | ... |
... | @@ -32,6 +32,10 @@ | ... | @@ -32,6 +32,10 @@ |
32 | <script src="manifest/playlist_type_template.js"></script> | 32 | <script src="manifest/playlist_type_template.js"></script> |
33 | <script src="manifest/playlist_media_sequence_template.js"></script> | 33 | <script src="manifest/playlist_media_sequence_template.js"></script> |
34 | <script src="manifest/playlist_target_duration_template.js"></script> | 34 | <script src="manifest/playlist_target_duration_template.js"></script> |
35 | <script src="manifest/playlist_extinf_template.js"></script> | ||
36 | <script src="manifest/playlist_allow_cache_template.js"></script> | ||
37 | <script src="manifest/playlist_byte_range_template.js"></script> | ||
38 | |||
35 | <!-- M3U8 --> | 39 | <!-- M3U8 --> |
36 | <!-- SEGMENT --> | 40 | <!-- SEGMENT --> |
37 | <script src="tsSegment-bc.js"></script> | 41 | <script src="tsSegment-bc.js"></script> | ... | ... |
-
Please register or sign in to post a comment