Reload playlists when EXT-X-ENDLIST isn't present
Modify the parser to include an attribute when the endlist tag shows up in a media playlist. Update test playlist parses to add the attribute where appropriate. Trigger a playlist reload and merge if endlist isn't present in the parse. Clean up some formatting.
Showing
40 changed files
with
239 additions
and
60 deletions
... | @@ -345,6 +345,9 @@ | ... | @@ -345,6 +345,9 @@ |
345 | byterange.offset = entry.offset; | 345 | byterange.offset = entry.offset; |
346 | } | 346 | } |
347 | }, | 347 | }, |
348 | 'endlist': function() { | ||
349 | this.manifest.endList = true; | ||
350 | }, | ||
348 | 'inf': function() { | 351 | 'inf': function() { |
349 | if (!('mediaSequence' in this.manifest)) { | 352 | if (!('mediaSequence' in this.manifest)) { |
350 | this.manifest.mediaSequence = 0; | 353 | this.manifest.mediaSequence = 0; |
... | @@ -462,12 +465,14 @@ | ... | @@ -462,12 +465,14 @@ |
462 | */ | 465 | */ |
463 | merge = function(base, update) { | 466 | merge = function(base, update) { |
464 | var | 467 | var |
465 | result = mergeOptions({}, base, update), | 468 | result = mergeOptions({}, base), |
466 | uri = update.segments[0].uri, | 469 | uri = update.segments[0].uri, |
467 | i = base.segments.length, | 470 | i = base.segments ? base.segments.length : 0, |
468 | byterange, | 471 | byterange, |
469 | segment; | 472 | segment; |
470 | 473 | ||
474 | result = mergeOptions(result, update); | ||
475 | |||
471 | // align and apply the updated segments | 476 | // align and apply the updated segments |
472 | while (i--) { | 477 | while (i--) { |
473 | segment = base.segments[i]; | 478 | segment = base.segments[i]; |
... | @@ -488,7 +493,7 @@ | ... | @@ -488,7 +493,7 @@ |
488 | } | 493 | } |
489 | // concatenate the two arrays if there was no overlap | 494 | // concatenate the two arrays if there was no overlap |
490 | if (i < 0) { | 495 | if (i < 0) { |
491 | result.segments = base.segments.concat(update.segments); | 496 | result.segments = (base.segments || []).concat(update.segments); |
492 | } | 497 | } |
493 | return result; | 498 | return result; |
494 | }; | 499 | }; | ... | ... |
... | @@ -341,8 +341,10 @@ var | ... | @@ -341,8 +341,10 @@ var |
341 | variant = bandwidthPlaylists[i]; | 341 | variant = bandwidthPlaylists[i]; |
342 | 342 | ||
343 | // ignore playlists without resolution information | 343 | // ignore playlists without resolution information |
344 | if (!variant.attributes || !variant.attributes.RESOLUTION || | 344 | if (!variant.attributes || |
345 | !variant.attributes.RESOLUTION.width || !variant.attributes.RESOLUTION.height) { | 345 | !variant.attributes.RESOLUTION || |
346 | !variant.attributes.RESOLUTION.width || | ||
347 | !variant.attributes.RESOLUTION.height) { | ||
346 | continue; | 348 | continue; |
347 | } | 349 | } |
348 | 350 | ||
... | @@ -375,9 +377,13 @@ var | ... | @@ -375,9 +377,13 @@ var |
375 | var xhr = new window.XMLHttpRequest(); | 377 | var xhr = new window.XMLHttpRequest(); |
376 | xhr.open('GET', url); | 378 | xhr.open('GET', url); |
377 | xhr.onreadystatechange = function() { | 379 | xhr.onreadystatechange = function() { |
378 | var i, parser, playlist, playlistUri; | 380 | var i, parser, playlist, playlistUri, refreshDelay; |
381 | |||
382 | // wait until the request completes | ||
383 | if (xhr.readyState !== 4) { | ||
384 | return; | ||
385 | } | ||
379 | 386 | ||
380 | if (xhr.readyState === 4) { | ||
381 | if (xhr.status >= 400 || this.status === 0) { | 387 | if (xhr.status >= 400 || this.status === 0) { |
382 | player.hls.error = { | 388 | player.hls.error = { |
383 | status: xhr.status, | 389 | status: xhr.status, |
... | @@ -401,6 +407,7 @@ var | ... | @@ -401,6 +407,7 @@ var |
401 | } | 407 | } |
402 | 408 | ||
403 | // media playlists | 409 | // media playlists |
410 | refreshDelay = (parser.manifest.targetDuration || 10) * 1000; | ||
404 | if (player.hls.master) { | 411 | if (player.hls.master) { |
405 | // merge this playlist into the master | 412 | // merge this playlist into the master |
406 | i = player.hls.master.playlists.length; | 413 | i = player.hls.master.playlists.length; |
... | @@ -409,8 +416,16 @@ var | ... | @@ -409,8 +416,16 @@ var |
409 | playlist = player.hls.master.playlists[i]; | 416 | playlist = player.hls.master.playlists[i]; |
410 | playlistUri = resolveUrl(srcUrl, playlist.uri); | 417 | playlistUri = resolveUrl(srcUrl, playlist.uri); |
411 | if (playlistUri === url) { | 418 | if (playlistUri === url) { |
419 | // if the playlist is unchanged since the last reload, | ||
420 | // try again after half the target duration | ||
421 | // http://tools.ietf.org/html/draft-pantos-http-live-streaming-12#section-6.3.4 | ||
422 | if (playlist.segments && | ||
423 | playlist.segments.length === parser.manifest.segments.length) { | ||
424 | refreshDelay /= 2; | ||
425 | } | ||
426 | |||
412 | player.hls.master.playlists[i] = | 427 | player.hls.master.playlists[i] = |
413 | videojs.util.mergeOptions(playlist, parser.manifest); | 428 | videojs.m3u8.merge(playlist, parser.manifest); |
414 | } | 429 | } |
415 | } | 430 | } |
416 | } else { | 431 | } else { |
... | @@ -420,6 +435,13 @@ var | ... | @@ -420,6 +435,13 @@ var |
420 | }; | 435 | }; |
421 | } | 436 | } |
422 | 437 | ||
438 | // check the playlist for updates if EXT-X-ENDLIST isn't present | ||
439 | if (!parser.manifest.endList) { | ||
440 | window.setTimeout(function() { | ||
441 | downloadPlaylist(url); | ||
442 | }, refreshDelay); | ||
443 | } | ||
444 | |||
423 | // always start playback with the default rendition | 445 | // always start playback with the default rendition |
424 | if (!player.hls.media) { | 446 | if (!player.hls.media) { |
425 | player.hls.media = player.hls.master.playlists[0]; | 447 | player.hls.media = player.hls.master.playlists[0]; |
... | @@ -456,7 +478,6 @@ var | ... | @@ -456,7 +478,6 @@ var |
456 | } | 478 | } |
457 | 479 | ||
458 | player.trigger('loadedmanifest'); | 480 | player.trigger('loadedmanifest'); |
459 | } | ||
460 | }; | 481 | }; |
461 | xhr.send(null); | 482 | xhr.send(null); |
462 | }; | 483 | }; | ... | ... |
... | @@ -514,7 +514,7 @@ | ... | @@ -514,7 +514,7 @@ |
514 | }); | 514 | }); |
515 | 515 | ||
516 | test('merges a manifest that strictly adds to an earlier one', function() { | 516 | test('merges a manifest that strictly adds to an earlier one', function() { |
517 | var key, base, mid, parsed; | 517 | var key, base, manifest, mid; |
518 | for (key in window.manifests) { | 518 | for (key in window.manifests) { |
519 | if (window.expected[key]) { | 519 | if (window.expected[key]) { |
520 | manifest = window.manifests[key]; | 520 | manifest = window.manifests[key]; | ... | ... |
1 | { | 1 | { |
2 | "allowCache": true, | 2 | "allowCache": true, |
3 | "playlists": [{ | 3 | "playlists": [ |
4 | { | ||
4 | "attributes": { | 5 | "attributes": { |
5 | "PROGRAM-ID": 1, | 6 | "PROGRAM-ID": 1, |
6 | "BANDWIDTH": 240000, | 7 | "BANDWIDTH": 240000, |
... | @@ -10,13 +11,15 @@ | ... | @@ -10,13 +11,15 @@ |
10 | } | 11 | } |
11 | }, | 12 | }, |
12 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001" | 13 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001" |
13 | }, { | 14 | }, |
15 | { | ||
14 | "attributes": { | 16 | "attributes": { |
15 | "PROGRAM-ID": 1, | 17 | "PROGRAM-ID": 1, |
16 | "BANDWIDTH": 40000 | 18 | "BANDWIDTH": 40000 |
17 | }, | 19 | }, |
18 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001" | 20 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001" |
19 | }, { | 21 | }, |
22 | { | ||
20 | "attributes": { | 23 | "attributes": { |
21 | "PROGRAM-ID": 1, | 24 | "PROGRAM-ID": 1, |
22 | "BANDWIDTH": 440000, | 25 | "BANDWIDTH": 440000, |
... | @@ -26,7 +29,8 @@ | ... | @@ -26,7 +29,8 @@ |
26 | } | 29 | } |
27 | }, | 30 | }, |
28 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001" | 31 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001" |
29 | }, { | 32 | }, |
33 | { | ||
30 | "attributes": { | 34 | "attributes": { |
31 | "PROGRAM-ID": 1, | 35 | "PROGRAM-ID": 1, |
32 | "BANDWIDTH": 1928000, | 36 | "BANDWIDTH": 1928000, |
... | @@ -36,5 +40,6 @@ | ... | @@ -36,5 +40,6 @@ |
36 | } | 40 | } |
37 | }, | 41 | }, |
38 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001" | 42 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001" |
39 | }] | 43 | } |
44 | ] | ||
40 | } | 45 | } | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -27,5 +27,6 @@ | ... | @@ -27,5 +27,6 @@ |
27 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" | 27 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" |
28 | } | 28 | } |
29 | ], | 29 | ], |
30 | "targetDuration": 10 | 30 | "targetDuration": 10, |
31 | "endList": true | ||
31 | } | 32 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | { | 1 | { |
2 | "allowCache": true, | 2 | "allowCache": true, |
3 | "playlists": [{ | 3 | "playlists": [ |
4 | { | ||
4 | "attributes": { | 5 | "attributes": { |
5 | "PROGRAM-ID": 1, | 6 | "PROGRAM-ID": 1, |
6 | "BANDWIDTH": 240000, | 7 | "BANDWIDTH": 240000, |
... | @@ -10,13 +11,15 @@ | ... | @@ -10,13 +11,15 @@ |
10 | } | 11 | } |
11 | }, | 12 | }, |
12 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001" | 13 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686811001&videoId=1824650741001" |
13 | }, { | 14 | }, |
15 | { | ||
14 | "attributes": { | 16 | "attributes": { |
15 | "PROGRAM-ID": 1, | 17 | "PROGRAM-ID": 1, |
16 | "BANDWIDTH": 40000 | 18 | "BANDWIDTH": 40000 |
17 | }, | 19 | }, |
18 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001" | 20 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824683759001&videoId=1824650741001" |
19 | }, { | 21 | }, |
22 | { | ||
20 | "attributes": { | 23 | "attributes": { |
21 | "PROGRAM-ID": 1, | 24 | "PROGRAM-ID": 1, |
22 | "BANDWIDTH": 440000, | 25 | "BANDWIDTH": 440000, |
... | @@ -26,7 +29,8 @@ | ... | @@ -26,7 +29,8 @@ |
26 | } | 29 | } |
27 | }, | 30 | }, |
28 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001" | 31 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824686593001&videoId=1824650741001" |
29 | }, { | 32 | }, |
33 | { | ||
30 | "attributes": { | 34 | "attributes": { |
31 | "PROGRAM-ID": 1, | 35 | "PROGRAM-ID": 1, |
32 | "BANDWIDTH": 1928000, | 36 | "BANDWIDTH": 1928000, |
... | @@ -36,5 +40,6 @@ | ... | @@ -36,5 +40,6 @@ |
36 | } | 40 | } |
37 | }, | 41 | }, |
38 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001" | 42 | "uri": "http://c.brightcove.com/services/mobile/streaming/index/rendition.m3u8?assetId=1824687660001&videoId=1824650741001" |
39 | }] | 43 | } |
44 | ] | ||
40 | } | 45 | } | ... | ... |
... | @@ -28,5 +28,6 @@ | ... | @@ -28,5 +28,6 @@ |
28 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" | 28 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" |
29 | } | 29 | } |
30 | ], | 30 | ], |
31 | "targetDuration": 10 | 31 | "targetDuration": 10, |
32 | "endList": true | ||
32 | } | 33 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -7,5 +7,6 @@ | ... | @@ -7,5 +7,6 @@ |
7 | "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" | 7 | "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" |
8 | } | 8 | } |
9 | ], | 9 | ], |
10 | "targetDuration": 8 | 10 | "targetDuration": 8, |
11 | "endList": true | ||
11 | } | 12 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -27,5 +27,6 @@ | ... | @@ -27,5 +27,6 @@ |
27 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" | 27 | "uri": "/test/ts-files/zencoder/haze/Haze_Mantel_President_encoded_1200-00006.ts" |
28 | } | 28 | } |
29 | ], | 29 | ], |
30 | "targetDuration": 10 | 30 | "targetDuration": 10, |
31 | "endList": true | ||
31 | } | 32 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -23,5 +23,6 @@ | ... | @@ -23,5 +23,6 @@ |
23 | "uri": "/test/ts-files/zencoder/gogo/00005.ts" | 23 | "uri": "/test/ts-files/zencoder/gogo/00005.ts" |
24 | } | 24 | } |
25 | ], | 25 | ], |
26 | "targetDuration": 10 | 26 | "targetDuration": 10, |
27 | "endList": true | ||
27 | } | 28 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -7,5 +7,6 @@ | ... | @@ -7,5 +7,6 @@ |
7 | "uri": "/test/ts-files/zencoder/gogo/00001.ts" | 7 | "uri": "/test/ts-files/zencoder/gogo/00001.ts" |
8 | } | 8 | } |
9 | ], | 9 | ], |
10 | "targetDuration": 10 | 10 | "targetDuration": 10, |
11 | "endList": true | ||
11 | } | 12 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | { | 1 | { |
2 | "allowCache": true, | 2 | "allowCache": true, |
3 | "playlists": [{ | 3 | "playlists": [ |
4 | { | ||
4 | "attributes": { | 5 | "attributes": { |
5 | "PROGRAM-ID": 1, | 6 | "PROGRAM-ID": 1, |
6 | "BANDWIDTH": 240000, | 7 | "BANDWIDTH": 240000, |
... | @@ -10,13 +11,15 @@ | ... | @@ -10,13 +11,15 @@ |
10 | } | 11 | } |
11 | }, | 12 | }, |
12 | "uri": "media.m3u8" | 13 | "uri": "media.m3u8" |
13 | }, { | 14 | }, |
15 | { | ||
14 | "attributes": { | 16 | "attributes": { |
15 | "PROGRAM-ID": 1, | 17 | "PROGRAM-ID": 1, |
16 | "BANDWIDTH": 40000 | 18 | "BANDWIDTH": 40000 |
17 | }, | 19 | }, |
18 | "uri": "media1.m3u8" | 20 | "uri": "media1.m3u8" |
19 | }, { | 21 | }, |
22 | { | ||
20 | "attributes": { | 23 | "attributes": { |
21 | "PROGRAM-ID": 1, | 24 | "PROGRAM-ID": 1, |
22 | "BANDWIDTH": 440000, | 25 | "BANDWIDTH": 440000, |
... | @@ -26,7 +29,8 @@ | ... | @@ -26,7 +29,8 @@ |
26 | } | 29 | } |
27 | }, | 30 | }, |
28 | "uri": "media2.m3u8" | 31 | "uri": "media2.m3u8" |
29 | }, { | 32 | }, |
33 | { | ||
30 | "attributes": { | 34 | "attributes": { |
31 | "PROGRAM-ID": 1, | 35 | "PROGRAM-ID": 1, |
32 | "BANDWIDTH": 1928000, | 36 | "BANDWIDTH": 1928000, |
... | @@ -36,5 +40,6 @@ | ... | @@ -36,5 +40,6 @@ |
36 | } | 40 | } |
37 | }, | 41 | }, |
38 | "uri": "media3.m3u8" | 42 | "uri": "media3.m3u8" |
39 | }] | 43 | } |
44 | ] | ||
40 | } | 45 | } | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
test/manifest/missingEndlist.json
0 → 100644
test/manifest/missingEndlist.m3u8
0 → 100644
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -2,16 +2,21 @@ | ... | @@ -2,16 +2,21 @@ |
2 | "allowCache": true, | 2 | "allowCache": true, |
3 | "mediaSequence": 0, | 3 | "mediaSequence": 0, |
4 | "targetDuration": 10, | 4 | "targetDuration": 10, |
5 | "segments": [{ | 5 | "segments": [ |
6 | { | ||
6 | "uri": "001.ts" | 7 | "uri": "001.ts" |
7 | }, { | 8 | }, |
9 | { | ||
8 | "uri": "002.ts", | 10 | "uri": "002.ts", |
9 | "duration": 9 | 11 | "duration": 9 |
10 | }, { | 12 | }, |
13 | { | ||
11 | "uri": "003.ts", | 14 | "uri": "003.ts", |
12 | "duration": 7 | 15 | "duration": 7 |
13 | }, { | 16 | }, |
17 | { | ||
14 | "uri": "004.ts", | 18 | "uri": "004.ts", |
15 | "duration": 10 | 19 | "duration": 10 |
16 | }] | 20 | } |
21 | ] | ||
17 | } | 22 | } | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -8,5 +8,6 @@ | ... | @@ -8,5 +8,6 @@ |
8 | "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" | 8 | "uri": "/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts" |
9 | } | 9 | } |
10 | ], | 10 | ], |
11 | "targetDuration": 8 | 11 | "targetDuration": 8, |
12 | "endList": true | ||
12 | } | 13 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -20,5 +20,6 @@ | ... | @@ -20,5 +20,6 @@ |
20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" | 20 | "uri": "/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts" |
21 | } | 21 | } |
22 | ], | 22 | ], |
23 | "targetDuration": 8 | 23 | "targetDuration": 8, |
24 | "endList": true | ||
24 | } | 25 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
... | @@ -181,7 +181,7 @@ test('calculates the duration if needed', function() { | ... | @@ -181,7 +181,7 @@ test('calculates the duration if needed', function() { |
181 | } | 181 | } |
182 | durations.push(duration); | 182 | durations.push(duration); |
183 | }; | 183 | }; |
184 | player.hls('manifest/liveMissingSegmentDuration.m3u8'); | 184 | player.hls('http://example.com/manifest/liveMissingSegmentDuration.m3u8'); |
185 | videojs.mediaSources[player.currentSrc()].trigger({ | 185 | videojs.mediaSources[player.currentSrc()].trigger({ |
186 | type: 'sourceopen' | 186 | type: 'sourceopen' |
187 | }); | 187 | }); |
... | @@ -873,4 +873,87 @@ test('has no effect if native HLS is available', function() { | ... | @@ -873,4 +873,87 @@ test('has no effect if native HLS is available', function() { |
873 | 'no media source was opened'); | 873 | 'no media source was opened'); |
874 | }); | 874 | }); |
875 | 875 | ||
876 | test('reloads live playlists', function() { | ||
877 | var callbacks = []; | ||
878 | // capture timeouts | ||
879 | window.setTimeout = function(callback, timeout) { | ||
880 | callbacks.push({ callback: callback, timeout: timeout }); | ||
881 | }; | ||
882 | player.hls('manifest/missingEndlist.m3u8'); | ||
883 | videojs.mediaSources[player.currentSrc()].trigger({ | ||
884 | type: 'sourceopen' | ||
885 | }); | ||
886 | |||
887 | strictEqual(1, callbacks.length, 'refresh was scheduled'); | ||
888 | strictEqual(player.hls.media.targetDuration * 1000, | ||
889 | callbacks[0].timeout, | ||
890 | 'waited one target duration'); | ||
891 | }); | ||
892 | |||
893 | test('does not reload playlists with an endlist tag', function() { | ||
894 | var callbacks = []; | ||
895 | // capture timeouts | ||
896 | window.setTimeout = function(callback, timeout) { | ||
897 | callbacks.push({ callback: callback, timeout: timeout }); | ||
898 | }; | ||
899 | player.hls('manifest/media.m3u8'); | ||
900 | videojs.mediaSources[player.currentSrc()].trigger({ | ||
901 | type: 'sourceopen' | ||
902 | }); | ||
903 | |||
904 | strictEqual(0, callbacks.length, 'no refresh was scheduled'); | ||
905 | }); | ||
906 | |||
907 | test('reloads a live playlist after half a target duration if it has not ' + | ||
908 | 'changed since the last request', function() { | ||
909 | var callbacks = []; | ||
910 | // capture timeouts | ||
911 | window.setTimeout = function(callback, timeout) { | ||
912 | callbacks.push({ callback: callback, timeout: timeout }); | ||
913 | }; | ||
914 | player.hls('http://example.com/manifest/missingEndlist.m3u8'); | ||
915 | |||
916 | // an identical manifest has already been parsed | ||
917 | player.hls.media = videojs.util.mergeOptions({}, window.expected['missingEndlist']); | ||
918 | player.hls.media.uri = 'http://example.com/manifest/missingEndlist.m3u8'; | ||
919 | player.hls.master = { | ||
920 | playlists: [player.hls.media] | ||
921 | }; | ||
922 | |||
923 | videojs.mediaSources[player.currentSrc()].trigger({ | ||
924 | type: 'sourceopen' | ||
925 | }); | ||
926 | |||
927 | strictEqual(1, callbacks.length, 'refresh was scheduled'); | ||
928 | strictEqual(player.hls.media.targetDuration / 2 * 1000, | ||
929 | callbacks[0].timeout, | ||
930 | 'waited half a target duration'); | ||
931 | }); | ||
932 | |||
933 | test('merges playlist reloads', function() { | ||
934 | var | ||
935 | realMerge = videojs.m3u8.merge, | ||
936 | merges = 0, | ||
937 | callback; | ||
938 | // capture timeouts and playlist merges | ||
939 | window.setTimeout = function(cb) { | ||
940 | callback = cb; | ||
941 | }; | ||
942 | videojs.m3u8.merge = function(base, update) { | ||
943 | merges++; | ||
944 | return update; | ||
945 | }; | ||
946 | |||
947 | player.hls('http://example.com/manifest/missingEndlist.m3u8'); | ||
948 | videojs.mediaSources[player.currentSrc()].trigger({ | ||
949 | type: 'sourceopen' | ||
950 | }); | ||
951 | player.hls.media.uri = 'http://example.com/manifest/missingEndlist.m3u8'; | ||
952 | |||
953 | callback(); | ||
954 | strictEqual(1, merges, 'reloaded playlist was merged'); | ||
955 | |||
956 | videojs.m3u8.merge = realMerge; | ||
957 | }); | ||
958 | |||
876 | })(window, window.videojs); | 959 | })(window, window.videojs); | ... | ... |
-
Please register or sign in to post a comment