Merge branch 'hotfix/stream-ended' of https://github.com/videojs/videojs-contrib…
…-hls into reorg-w-114 close #114 closes #115 Conflicts: src/videojs-hls.js
Showing
2 changed files
with
112 additions
and
133 deletions
... | @@ -158,6 +158,19 @@ videojs.Hls.prototype.handleSourceOpen = function() { | ... | @@ -158,6 +158,19 @@ videojs.Hls.prototype.handleSourceOpen = function() { |
158 | }); | 158 | }); |
159 | }; | 159 | }; |
160 | 160 | ||
161 | /** | ||
162 | * Reset the mediaIndex if play() is called after the video has | ||
163 | * ended. | ||
164 | */ | ||
165 | videojs.Hls.prototype.play = function() { | ||
166 | if (this.ended()) { | ||
167 | this.mediaIndex = 0; | ||
168 | } | ||
169 | |||
170 | // delegate back to the Flash implementation | ||
171 | return videojs.Flash.prototype.play.apply(this, arguments); | ||
172 | }; | ||
173 | |||
161 | videojs.Hls.prototype.duration = function() { | 174 | videojs.Hls.prototype.duration = function() { |
162 | var playlists = this.playlists; | 175 | var playlists = this.playlists; |
163 | if (playlists) { | 176 | if (playlists) { |
... | @@ -458,7 +471,9 @@ videojs.Hls.prototype.drainBuffer = function(event) { | ... | @@ -458,7 +471,9 @@ videojs.Hls.prototype.drainBuffer = function(event) { |
458 | // we're done processing this segment | 471 | // we're done processing this segment |
459 | segmentBuffer.shift(); | 472 | segmentBuffer.shift(); |
460 | 473 | ||
461 | if (mediaIndex === playlist.segments.length) { | 474 | // transition the sourcebuffer to the ended state if we've hit the end of |
475 | // the playlist | ||
476 | if (mediaIndex + 1 === playlist.segments.length) { | ||
462 | this.mediaSource.endOfStream(); | 477 | this.mediaSource.endOfStream(); |
463 | } | 478 | } |
464 | }; | 479 | }; | ... | ... |
... | @@ -51,10 +51,18 @@ var | ... | @@ -51,10 +51,18 @@ var |
51 | tech.vjs_getProperty = function() {}; | 51 | tech.vjs_getProperty = function() {}; |
52 | tech.vjs_setProperty = function() {}; | 52 | tech.vjs_setProperty = function() {}; |
53 | tech.vjs_src = function() {}; | 53 | tech.vjs_src = function() {}; |
54 | tech.vjs_play = function() {}; | ||
54 | videojs.Flash.onReady(tech.id); | 55 | videojs.Flash.onReady(tech.id); |
55 | 56 | ||
56 | return player; | 57 | return player; |
57 | }, | 58 | }, |
59 | openMediaSource = function(player) { | ||
60 | player.hls.mediaSource.trigger({ | ||
61 | type: 'sourceopen' | ||
62 | }); | ||
63 | // endOfStream triggers an exception if flash isn't available | ||
64 | player.hls.mediaSource.endOfStream = function() {}; | ||
65 | }, | ||
58 | standardXHRResponse = function(request) { | 66 | standardXHRResponse = function(request) { |
59 | if (!request.url) { | 67 | if (!request.url) { |
60 | return; | 68 | return; |
... | @@ -160,9 +168,7 @@ test('starts playing if autoplay is specified', function() { | ... | @@ -160,9 +168,7 @@ test('starts playing if autoplay is specified', function() { |
160 | src: 'manifest/playlist.m3u8', | 168 | src: 'manifest/playlist.m3u8', |
161 | type: 'application/vnd.apple.mpegurl' | 169 | type: 'application/vnd.apple.mpegurl' |
162 | }); | 170 | }); |
163 | player.hls.mediaSource.trigger({ | 171 | openMediaSource(player); |
164 | type: 'sourceopen' | ||
165 | }); | ||
166 | 172 | ||
167 | standardXHRResponse(requests[0]); | 173 | standardXHRResponse(requests[0]); |
168 | strictEqual(1, plays, 'play was called'); | 174 | strictEqual(1, plays, 'play was called'); |
... | @@ -179,9 +185,7 @@ test('creates a PlaylistLoader on init', function() { | ... | @@ -179,9 +185,7 @@ test('creates a PlaylistLoader on init', function() { |
179 | src:'manifest/playlist.m3u8', | 185 | src:'manifest/playlist.m3u8', |
180 | type: 'application/vnd.apple.mpegurl' | 186 | type: 'application/vnd.apple.mpegurl' |
181 | }); | 187 | }); |
182 | player.hls.mediaSource.trigger({ | 188 | openMediaSource(player); |
183 | type: 'sourceopen' | ||
184 | }); | ||
185 | standardXHRResponse(requests[0]); | 189 | standardXHRResponse(requests[0]); |
186 | ok(loadedmetadata, 'loadedmetadata fires'); | 190 | ok(loadedmetadata, 'loadedmetadata fires'); |
187 | ok(player.hls.playlists.master, 'set the master playlist'); | 191 | ok(player.hls.playlists.master, 'set the master playlist'); |
... | @@ -204,9 +208,7 @@ test('sets the duration if one is available on the playlist', function() { | ... | @@ -204,9 +208,7 @@ test('sets the duration if one is available on the playlist', function() { |
204 | src: 'manifest/media.m3u8', | 208 | src: 'manifest/media.m3u8', |
205 | type: 'application/vnd.apple.mpegurl' | 209 | type: 'application/vnd.apple.mpegurl' |
206 | }); | 210 | }); |
207 | player.hls.mediaSource.trigger({ | 211 | openMediaSource(player); |
208 | type: 'sourceopen' | ||
209 | }); | ||
210 | 212 | ||
211 | standardXHRResponse(requests[0]); | 213 | standardXHRResponse(requests[0]); |
212 | strictEqual(calls, 1, 'duration is set'); | 214 | strictEqual(calls, 1, 'duration is set'); |
... | @@ -226,9 +228,7 @@ test('calculates the duration if needed', function() { | ... | @@ -226,9 +228,7 @@ test('calculates the duration if needed', function() { |
226 | src: 'http://example.com/manifest/missingExtinf.m3u8', | 228 | src: 'http://example.com/manifest/missingExtinf.m3u8', |
227 | type: 'application/vnd.apple.mpegurl' | 229 | type: 'application/vnd.apple.mpegurl' |
228 | }); | 230 | }); |
229 | player.hls.mediaSource.trigger({ | 231 | openMediaSource(player); |
230 | type: 'sourceopen' | ||
231 | }); | ||
232 | 232 | ||
233 | standardXHRResponse(requests[0]); | 233 | standardXHRResponse(requests[0]); |
234 | strictEqual(durations.length, 1, 'duration is set'); | 234 | strictEqual(durations.length, 1, 'duration is set'); |
... | @@ -245,9 +245,7 @@ test('starts downloading a segment on loadedmetadata', function() { | ... | @@ -245,9 +245,7 @@ test('starts downloading a segment on loadedmetadata', function() { |
245 | player.buffered = function() { | 245 | player.buffered = function() { |
246 | return videojs.createTimeRange(0, 0); | 246 | return videojs.createTimeRange(0, 0); |
247 | }; | 247 | }; |
248 | player.hls.mediaSource.trigger({ | 248 | openMediaSource(player); |
249 | type: 'sourceopen' | ||
250 | }); | ||
251 | 249 | ||
252 | standardXHRResponse(requests[0]); | 250 | standardXHRResponse(requests[0]); |
253 | standardXHRResponse(requests[1]); | 251 | standardXHRResponse(requests[1]); |
... | @@ -263,9 +261,7 @@ test('recognizes absolute URIs and requests them unmodified', function() { | ... | @@ -263,9 +261,7 @@ test('recognizes absolute URIs and requests them unmodified', function() { |
263 | src: 'manifest/absoluteUris.m3u8', | 261 | src: 'manifest/absoluteUris.m3u8', |
264 | type: 'application/vnd.apple.mpegurl' | 262 | type: 'application/vnd.apple.mpegurl' |
265 | }); | 263 | }); |
266 | player.hls.mediaSource.trigger({ | 264 | openMediaSource(player); |
267 | type: 'sourceopen' | ||
268 | }); | ||
269 | 265 | ||
270 | standardXHRResponse(requests[0]); | 266 | standardXHRResponse(requests[0]); |
271 | standardXHRResponse(requests[1]); | 267 | standardXHRResponse(requests[1]); |
... | @@ -279,9 +275,7 @@ test('recognizes domain-relative URLs', function() { | ... | @@ -279,9 +275,7 @@ test('recognizes domain-relative URLs', function() { |
279 | src: 'manifest/domainUris.m3u8', | 275 | src: 'manifest/domainUris.m3u8', |
280 | type: 'application/vnd.apple.mpegurl' | 276 | type: 'application/vnd.apple.mpegurl' |
281 | }); | 277 | }); |
282 | player.hls.mediaSource.trigger({ | 278 | openMediaSource(player); |
283 | type: 'sourceopen' | ||
284 | }); | ||
285 | 279 | ||
286 | standardXHRResponse(requests[0]); | 280 | standardXHRResponse(requests[0]); |
287 | standardXHRResponse(requests[1]); | 281 | standardXHRResponse(requests[1]); |
... | @@ -297,9 +291,7 @@ test('re-initializes the tech for each source', function() { | ... | @@ -297,9 +291,7 @@ test('re-initializes the tech for each source', function() { |
297 | src: 'manifest/master.m3u8', | 291 | src: 'manifest/master.m3u8', |
298 | type: 'application/vnd.apple.mpegurl' | 292 | type: 'application/vnd.apple.mpegurl' |
299 | }); | 293 | }); |
300 | player.hls.mediaSource.trigger({ | 294 | openMediaSource(player); |
301 | type: 'sourceopen' | ||
302 | }); | ||
303 | firstPlaylists = player.hls.playlists; | 295 | firstPlaylists = player.hls.playlists; |
304 | firstMSE = player.hls.mediaSource; | 296 | firstMSE = player.hls.mediaSource; |
305 | 297 | ||
... | @@ -307,9 +299,7 @@ test('re-initializes the tech for each source', function() { | ... | @@ -307,9 +299,7 @@ test('re-initializes the tech for each source', function() { |
307 | src: 'manifest/master.m3u8', | 299 | src: 'manifest/master.m3u8', |
308 | type: 'application/vnd.apple.mpegurl' | 300 | type: 'application/vnd.apple.mpegurl' |
309 | }); | 301 | }); |
310 | player.hls.mediaSource.trigger({ | 302 | openMediaSource(player); |
311 | type: 'sourceopen' | ||
312 | }); | ||
313 | secondPlaylists = player.hls.playlists; | 303 | secondPlaylists = player.hls.playlists; |
314 | secondMSE = player.hls.mediaSource; | 304 | secondMSE = player.hls.mediaSource; |
315 | 305 | ||
... | @@ -326,9 +316,7 @@ test('triggers an error when a master playlist request errors', function() { | ... | @@ -326,9 +316,7 @@ test('triggers an error when a master playlist request errors', function() { |
326 | src: 'manifest/master.m3u8', | 316 | src: 'manifest/master.m3u8', |
327 | type: 'application/vnd.apple.mpegurl' | 317 | type: 'application/vnd.apple.mpegurl' |
328 | }); | 318 | }); |
329 | player.hls.mediaSource.trigger({ | 319 | openMediaSource(player); |
330 | type: 'sourceopen' | ||
331 | }); | ||
332 | requests.pop().respond(500); | 320 | requests.pop().respond(500); |
333 | 321 | ||
334 | ok(player.error(), 'an error is triggered'); | 322 | ok(player.error(), 'an error is triggered'); |
... | @@ -341,9 +329,7 @@ test('downloads media playlists after loading the master', function() { | ... | @@ -341,9 +329,7 @@ test('downloads media playlists after loading the master', function() { |
341 | src: 'manifest/master.m3u8', | 329 | src: 'manifest/master.m3u8', |
342 | type: 'application/vnd.apple.mpegurl' | 330 | type: 'application/vnd.apple.mpegurl' |
343 | }); | 331 | }); |
344 | player.hls.mediaSource.trigger({ | 332 | openMediaSource(player); |
345 | type: 'sourceopen' | ||
346 | }); | ||
347 | 333 | ||
348 | standardXHRResponse(requests[0]); | 334 | standardXHRResponse(requests[0]); |
349 | standardXHRResponse(requests[1]); | 335 | standardXHRResponse(requests[1]); |
... | @@ -367,9 +353,7 @@ test('timeupdates do not check to fill the buffer until a media playlist is read | ... | @@ -367,9 +353,7 @@ test('timeupdates do not check to fill the buffer until a media playlist is read |
367 | src: 'manifest/media.m3u8', | 353 | src: 'manifest/media.m3u8', |
368 | type: 'application/vnd.apple.mpegurl' | 354 | type: 'application/vnd.apple.mpegurl' |
369 | }); | 355 | }); |
370 | player.hls.mediaSource.trigger({ | 356 | openMediaSource(player); |
371 | type: 'sourceopen' | ||
372 | }); | ||
373 | player.trigger('timeupdate'); | 357 | player.trigger('timeupdate'); |
374 | 358 | ||
375 | strictEqual(1, requests.length, 'one request was made'); | 359 | strictEqual(1, requests.length, 'one request was made'); |
... | @@ -381,9 +365,7 @@ test('calculates the bandwidth after downloading a segment', function() { | ... | @@ -381,9 +365,7 @@ test('calculates the bandwidth after downloading a segment', function() { |
381 | src: 'manifest/media.m3u8', | 365 | src: 'manifest/media.m3u8', |
382 | type: 'application/vnd.apple.mpegurl' | 366 | type: 'application/vnd.apple.mpegurl' |
383 | }); | 367 | }); |
384 | player.hls.mediaSource.trigger({ | 368 | openMediaSource(player); |
385 | type: 'sourceopen' | ||
386 | }); | ||
387 | 369 | ||
388 | standardXHRResponse(requests[0]); | 370 | standardXHRResponse(requests[0]); |
389 | standardXHRResponse(requests[1]); | 371 | standardXHRResponse(requests[1]); |
... | @@ -405,9 +387,7 @@ test('selects a playlist after segment downloads', function() { | ... | @@ -405,9 +387,7 @@ test('selects a playlist after segment downloads', function() { |
405 | calls++; | 387 | calls++; |
406 | return player.hls.playlists.master.playlists[0]; | 388 | return player.hls.playlists.master.playlists[0]; |
407 | }; | 389 | }; |
408 | player.hls.mediaSource.trigger({ | 390 | openMediaSource(player); |
409 | type: 'sourceopen' | ||
410 | }); | ||
411 | 391 | ||
412 | standardXHRResponse(requests[0]); | 392 | standardXHRResponse(requests[0]); |
413 | standardXHRResponse(requests[1]); | 393 | standardXHRResponse(requests[1]); |
... | @@ -433,9 +413,7 @@ test('moves to the next segment if there is a network error', function() { | ... | @@ -433,9 +413,7 @@ test('moves to the next segment if there is a network error', function() { |
433 | src: 'manifest/master.m3u8', | 413 | src: 'manifest/master.m3u8', |
434 | type: 'application/vnd.apple.mpegurl' | 414 | type: 'application/vnd.apple.mpegurl' |
435 | }); | 415 | }); |
436 | player.hls.mediaSource.trigger({ | 416 | openMediaSource(player); |
437 | type: 'sourceopen' | ||
438 | }); | ||
439 | 417 | ||
440 | standardXHRResponse(requests[0]); | 418 | standardXHRResponse(requests[0]); |
441 | standardXHRResponse(requests[1]); | 419 | standardXHRResponse(requests[1]); |
... | @@ -468,9 +446,7 @@ test('updates the duration after switching playlists', function() { | ... | @@ -468,9 +446,7 @@ test('updates the duration after switching playlists', function() { |
468 | calls++; | 446 | calls++; |
469 | } | 447 | } |
470 | }; | 448 | }; |
471 | player.hls.mediaSource.trigger({ | 449 | openMediaSource(player); |
472 | type: 'sourceopen' | ||
473 | }); | ||
474 | 450 | ||
475 | standardXHRResponse(requests[0]); | 451 | standardXHRResponse(requests[0]); |
476 | standardXHRResponse(requests[1]); | 452 | standardXHRResponse(requests[1]); |
... | @@ -490,9 +466,7 @@ test('downloads additional playlists if required', function() { | ... | @@ -490,9 +466,7 @@ test('downloads additional playlists if required', function() { |
490 | src: 'manifest/master.m3u8', | 466 | src: 'manifest/master.m3u8', |
491 | type: 'application/vnd.apple.mpegurl' | 467 | type: 'application/vnd.apple.mpegurl' |
492 | }); | 468 | }); |
493 | player.hls.mediaSource.trigger({ | 469 | openMediaSource(player); |
494 | type: 'sourceopen' | ||
495 | }); | ||
496 | 470 | ||
497 | standardXHRResponse(requests[0]); | 471 | standardXHRResponse(requests[0]); |
498 | standardXHRResponse(requests[1]); | 472 | standardXHRResponse(requests[1]); |
... | @@ -531,9 +505,7 @@ test('selects a playlist below the current bandwidth', function() { | ... | @@ -531,9 +505,7 @@ test('selects a playlist below the current bandwidth', function() { |
531 | src: 'manifest/master.m3u8', | 505 | src: 'manifest/master.m3u8', |
532 | type: 'application/vnd.apple.mpegurl' | 506 | type: 'application/vnd.apple.mpegurl' |
533 | }); | 507 | }); |
534 | player.hls.mediaSource.trigger({ | 508 | openMediaSource(player); |
535 | type: 'sourceopen' | ||
536 | }); | ||
537 | 509 | ||
538 | standardXHRResponse(requests[0]); | 510 | standardXHRResponse(requests[0]); |
539 | 511 | ||
... | @@ -556,9 +528,7 @@ test('raises the minimum bitrate for a stream proportionially', function() { | ... | @@ -556,9 +528,7 @@ test('raises the minimum bitrate for a stream proportionially', function() { |
556 | src: 'manifest/master.m3u8', | 528 | src: 'manifest/master.m3u8', |
557 | type: 'application/vnd.apple.mpegurl' | 529 | type: 'application/vnd.apple.mpegurl' |
558 | }); | 530 | }); |
559 | player.hls.mediaSource.trigger({ | 531 | openMediaSource(player); |
560 | type: 'sourceopen' | ||
561 | }); | ||
562 | 532 | ||
563 | standardXHRResponse(requests[0]); | 533 | standardXHRResponse(requests[0]); |
564 | 534 | ||
... | @@ -581,9 +551,7 @@ test('uses the lowest bitrate if no other is suitable', function() { | ... | @@ -581,9 +551,7 @@ test('uses the lowest bitrate if no other is suitable', function() { |
581 | src: 'manifest/master.m3u8', | 551 | src: 'manifest/master.m3u8', |
582 | type: 'application/vnd.apple.mpegurl' | 552 | type: 'application/vnd.apple.mpegurl' |
583 | }); | 553 | }); |
584 | player.hls.mediaSource.trigger({ | 554 | openMediaSource(player); |
585 | type: 'sourceopen' | ||
586 | }); | ||
587 | 555 | ||
588 | standardXHRResponse(requests[0]); | 556 | standardXHRResponse(requests[0]); |
589 | 557 | ||
... | @@ -605,9 +573,7 @@ test('selects the correct rendition by player dimensions', function() { | ... | @@ -605,9 +573,7 @@ test('selects the correct rendition by player dimensions', function() { |
605 | type: 'application/vnd.apple.mpegurl' | 573 | type: 'application/vnd.apple.mpegurl' |
606 | }); | 574 | }); |
607 | 575 | ||
608 | player.hls.mediaSource.trigger({ | 576 | openMediaSource(player); |
609 | type: 'sourceopen' | ||
610 | }); | ||
611 | 577 | ||
612 | standardXHRResponse(requests[0]); | 578 | standardXHRResponse(requests[0]); |
613 | 579 | ||
... | @@ -644,9 +610,7 @@ test('does not download the next segment if the buffer is full', function() { | ... | @@ -644,9 +610,7 @@ test('does not download the next segment if the buffer is full', function() { |
644 | player.buffered = function() { | 610 | player.buffered = function() { |
645 | return videojs.createTimeRange(0, currentTime + videojs.Hls.GOAL_BUFFER_LENGTH); | 611 | return videojs.createTimeRange(0, currentTime + videojs.Hls.GOAL_BUFFER_LENGTH); |
646 | }; | 612 | }; |
647 | player.hls.mediaSource.trigger({ | 613 | openMediaSource(player); |
648 | type: 'sourceopen' | ||
649 | }); | ||
650 | 614 | ||
651 | standardXHRResponse(requests[0]); | 615 | standardXHRResponse(requests[0]); |
652 | 616 | ||
... | @@ -660,9 +624,7 @@ test('downloads the next segment if the buffer is getting low', function() { | ... | @@ -660,9 +624,7 @@ test('downloads the next segment if the buffer is getting low', function() { |
660 | src: 'manifest/media.m3u8', | 624 | src: 'manifest/media.m3u8', |
661 | type: 'application/vnd.apple.mpegurl' | 625 | type: 'application/vnd.apple.mpegurl' |
662 | }); | 626 | }); |
663 | player.hls.mediaSource.trigger({ | 627 | openMediaSource(player); |
664 | type: 'sourceopen' | ||
665 | }); | ||
666 | 628 | ||
667 | standardXHRResponse(requests[0]); | 629 | standardXHRResponse(requests[0]); |
668 | standardXHRResponse(requests[1]); | 630 | standardXHRResponse(requests[1]); |
... | @@ -691,9 +653,7 @@ test('stops downloading segments at the end of the playlist', function() { | ... | @@ -691,9 +653,7 @@ test('stops downloading segments at the end of the playlist', function() { |
691 | src: 'manifest/media.m3u8', | 653 | src: 'manifest/media.m3u8', |
692 | type: 'application/vnd.apple.mpegurl' | 654 | type: 'application/vnd.apple.mpegurl' |
693 | }); | 655 | }); |
694 | player.hls.mediaSource.trigger({ | 656 | openMediaSource(player); |
695 | type: 'sourceopen' | ||
696 | }); | ||
697 | standardXHRResponse(requests[0]); | 657 | standardXHRResponse(requests[0]); |
698 | requests = []; | 658 | requests = []; |
699 | player.hls.mediaIndex = 4; | 659 | player.hls.mediaIndex = 4; |
... | @@ -707,9 +667,7 @@ test('only makes one segment request at a time', function() { | ... | @@ -707,9 +667,7 @@ test('only makes one segment request at a time', function() { |
707 | src: 'manifest/media.m3u8', | 667 | src: 'manifest/media.m3u8', |
708 | type: 'application/vnd.apple.mpegurl' | 668 | type: 'application/vnd.apple.mpegurl' |
709 | }); | 669 | }); |
710 | player.hls.mediaSource.trigger({ | 670 | openMediaSource(player); |
711 | type: 'sourceopen' | ||
712 | }); | ||
713 | standardXHRResponse(requests.pop()); | 671 | standardXHRResponse(requests.pop()); |
714 | player.trigger('timeupdate'); | 672 | player.trigger('timeupdate'); |
715 | 673 | ||
... | @@ -723,9 +681,7 @@ test('cancels outstanding XHRs when seeking', function() { | ... | @@ -723,9 +681,7 @@ test('cancels outstanding XHRs when seeking', function() { |
723 | src: 'manifest/media.m3u8', | 681 | src: 'manifest/media.m3u8', |
724 | type: 'application/vnd.apple.mpegurl' | 682 | type: 'application/vnd.apple.mpegurl' |
725 | }); | 683 | }); |
726 | player.hls.mediaSource.trigger({ | 684 | openMediaSource(player); |
727 | type: 'sourceopen' | ||
728 | }); | ||
729 | standardXHRResponse(requests[0]); | 685 | standardXHRResponse(requests[0]); |
730 | player.hls.media = { | 686 | player.hls.media = { |
731 | segments: [{ | 687 | segments: [{ |
... | @@ -764,9 +720,7 @@ test('flushes the parser after each segment', function() { | ... | @@ -764,9 +720,7 @@ test('flushes the parser after each segment', function() { |
764 | src: 'manifest/media.m3u8', | 720 | src: 'manifest/media.m3u8', |
765 | type: 'application/vnd.apple.mpegurl' | 721 | type: 'application/vnd.apple.mpegurl' |
766 | }); | 722 | }); |
767 | player.hls.mediaSource.trigger({ | 723 | openMediaSource(player); |
768 | type: 'sourceopen' | ||
769 | }); | ||
770 | 724 | ||
771 | standardXHRResponse(requests[0]); | 725 | standardXHRResponse(requests[0]); |
772 | standardXHRResponse(requests[1]); | 726 | standardXHRResponse(requests[1]); |
... | @@ -794,9 +748,7 @@ test('drops tags before the target timestamp when seeking', function() { | ... | @@ -794,9 +748,7 @@ test('drops tags before the target timestamp when seeking', function() { |
794 | src: 'manifest/media.m3u8', | 748 | src: 'manifest/media.m3u8', |
795 | type: 'application/vnd.apple.mpegurl' | 749 | type: 'application/vnd.apple.mpegurl' |
796 | }); | 750 | }); |
797 | player.hls.mediaSource.trigger({ | 751 | openMediaSource(player); |
798 | type: 'sourceopen' | ||
799 | }); | ||
800 | standardXHRResponse(requests[0]); | 752 | standardXHRResponse(requests[0]); |
801 | standardXHRResponse(requests[1]); | 753 | standardXHRResponse(requests[1]); |
802 | 754 | ||
... | @@ -836,9 +788,7 @@ test('calls abort() on the SourceBuffer before seeking', function() { | ... | @@ -836,9 +788,7 @@ test('calls abort() on the SourceBuffer before seeking', function() { |
836 | src: 'manifest/media.m3u8', | 788 | src: 'manifest/media.m3u8', |
837 | type: 'application/vnd.apple.mpegurl' | 789 | type: 'application/vnd.apple.mpegurl' |
838 | }); | 790 | }); |
839 | player.hls.mediaSource.trigger({ | 791 | openMediaSource(player); |
840 | type: 'sourceopen' | ||
841 | }); | ||
842 | 792 | ||
843 | standardXHRResponse(requests[0]); | 793 | standardXHRResponse(requests[0]); |
844 | standardXHRResponse(requests[1]); | 794 | standardXHRResponse(requests[1]); |
... | @@ -863,9 +813,7 @@ test('playlist 404 should trigger MEDIA_ERR_NETWORK', function() { | ... | @@ -863,9 +813,7 @@ test('playlist 404 should trigger MEDIA_ERR_NETWORK', function() { |
863 | src: 'manifest/media.m3u8', | 813 | src: 'manifest/media.m3u8', |
864 | type: 'application/vnd.apple.mpegurl' | 814 | type: 'application/vnd.apple.mpegurl' |
865 | }); | 815 | }); |
866 | player.hls.mediaSource.trigger({ | 816 | openMediaSource(player); |
867 | type: 'sourceopen' | ||
868 | }); | ||
869 | requests.pop().respond(404); | 817 | requests.pop().respond(404); |
870 | 818 | ||
871 | equal(errorTriggered, | 819 | equal(errorTriggered, |
... | @@ -883,9 +831,7 @@ test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { | ... | @@ -883,9 +831,7 @@ test('segment 404 should trigger MEDIA_ERR_NETWORK', function () { |
883 | type: 'application/vnd.apple.mpegurl' | 831 | type: 'application/vnd.apple.mpegurl' |
884 | }); | 832 | }); |
885 | 833 | ||
886 | player.hls.mediaSource.trigger({ | 834 | openMediaSource(player); |
887 | type: 'sourceopen' | ||
888 | }); | ||
889 | 835 | ||
890 | standardXHRResponse(requests[0]); | 836 | standardXHRResponse(requests[0]); |
891 | requests[1].respond(404); | 837 | requests[1].respond(404); |
... | @@ -899,9 +845,7 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { | ... | @@ -899,9 +845,7 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { |
899 | type: 'application/vnd.apple.mpegurl' | 845 | type: 'application/vnd.apple.mpegurl' |
900 | }); | 846 | }); |
901 | 847 | ||
902 | player.hls.mediaSource.trigger({ | 848 | openMediaSource(player); |
903 | type: 'sourceopen' | ||
904 | }); | ||
905 | 849 | ||
906 | standardXHRResponse(requests[0]); | 850 | standardXHRResponse(requests[0]); |
907 | requests[1].respond(500); | 851 | requests[1].respond(500); |
... | @@ -914,9 +858,7 @@ test('duration is Infinity for live playlists', function() { | ... | @@ -914,9 +858,7 @@ test('duration is Infinity for live playlists', function() { |
914 | src: 'http://example.com/manifest/missingEndlist.m3u8', | 858 | src: 'http://example.com/manifest/missingEndlist.m3u8', |
915 | type: 'application/vnd.apple.mpegurl' | 859 | type: 'application/vnd.apple.mpegurl' |
916 | }); | 860 | }); |
917 | player.hls.mediaSource.trigger({ | 861 | openMediaSource(player); |
918 | type: 'sourceopen' | ||
919 | }); | ||
920 | 862 | ||
921 | standardXHRResponse(requests[0]); | 863 | standardXHRResponse(requests[0]); |
922 | 864 | ||
... | @@ -929,9 +871,7 @@ test('updates the media index when a playlist reloads', function() { | ... | @@ -929,9 +871,7 @@ test('updates the media index when a playlist reloads', function() { |
929 | src: 'http://example.com/live-updating.m3u8', | 871 | src: 'http://example.com/live-updating.m3u8', |
930 | type: 'application/vnd.apple.mpegurl' | 872 | type: 'application/vnd.apple.mpegurl' |
931 | }); | 873 | }); |
932 | player.hls.mediaSource.trigger({ | 874 | openMediaSource(player); |
933 | type: 'sourceopen' | ||
934 | }); | ||
935 | 875 | ||
936 | requests[0].respond(200, null, | 876 | requests[0].respond(200, null, |
937 | '#EXTM3U\n' + | 877 | '#EXTM3U\n' + |
... | @@ -971,9 +911,7 @@ test('mediaIndex is zero before the first segment loads', function() { | ... | @@ -971,9 +911,7 @@ test('mediaIndex is zero before the first segment loads', function() { |
971 | src: 'http://example.com/first-seg-load.m3u8', | 911 | src: 'http://example.com/first-seg-load.m3u8', |
972 | type: 'application/vnd.apple.mpegurl' | 912 | type: 'application/vnd.apple.mpegurl' |
973 | }); | 913 | }); |
974 | player.hls.mediaSource.trigger({ | 914 | openMediaSource(player); |
975 | type: 'sourceopen' | ||
976 | }); | ||
977 | 915 | ||
978 | strictEqual(player.hls.mediaIndex, 0, 'mediaIndex is zero'); | 916 | strictEqual(player.hls.mediaIndex, 0, 'mediaIndex is zero'); |
979 | }); | 917 | }); |
... | @@ -983,9 +921,7 @@ test('reloads out-of-date live playlists when switching variants', function() { | ... | @@ -983,9 +921,7 @@ test('reloads out-of-date live playlists when switching variants', function() { |
983 | src: 'http://example.com/master.m3u8', | 921 | src: 'http://example.com/master.m3u8', |
984 | type: 'application/vnd.apple.mpegurl' | 922 | type: 'application/vnd.apple.mpegurl' |
985 | }); | 923 | }); |
986 | player.hls.mediaSource.trigger({ | 924 | openMediaSource(player); |
987 | type: 'sourceopen' | ||
988 | }); | ||
989 | 925 | ||
990 | player.hls.master = { | 926 | player.hls.master = { |
991 | playlists: [{ | 927 | playlists: [{ |
... | @@ -1026,9 +962,7 @@ test('if withCredentials option is used, withCredentials is set on the XHR objec | ... | @@ -1026,9 +962,7 @@ test('if withCredentials option is used, withCredentials is set on the XHR objec |
1026 | src: 'http://example.com/media.m3u8', | 962 | src: 'http://example.com/media.m3u8', |
1027 | type: 'application/vnd.apple.mpegurl' | 963 | type: 'application/vnd.apple.mpegurl' |
1028 | }); | 964 | }); |
1029 | player.hls.mediaSource.trigger({ | 965 | openMediaSource(player); |
1030 | type: 'sourceopen' | ||
1031 | }); | ||
1032 | ok(requests[0].withCredentials, "with credentials should be set to true if that option is passed in"); | 966 | ok(requests[0].withCredentials, "with credentials should be set to true if that option is passed in"); |
1033 | }); | 967 | }); |
1034 | 968 | ||
... | @@ -1038,9 +972,7 @@ test('does not break if the playlist has no segments', function() { | ... | @@ -1038,9 +972,7 @@ test('does not break if the playlist has no segments', function() { |
1038 | type: 'application/vnd.apple.mpegurl' | 972 | type: 'application/vnd.apple.mpegurl' |
1039 | }); | 973 | }); |
1040 | try { | 974 | try { |
1041 | player.hls.mediaSource.trigger({ | 975 | openMediaSource(player); |
1042 | type: 'sourceopen' | ||
1043 | }); | ||
1044 | requests[0].respond(200, null, | 976 | requests[0].respond(200, null, |
1045 | '#EXTM3U\n' + | 977 | '#EXTM3U\n' + |
1046 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + | 978 | '#EXT-X-PLAYLIST-TYPE:VOD\n' + |
... | @@ -1060,9 +992,7 @@ test('waits until the buffer is empty before appending bytes at a discontinuity' | ... | @@ -1060,9 +992,7 @@ test('waits until the buffer is empty before appending bytes at a discontinuity' |
1060 | src: 'disc.m3u8', | 992 | src: 'disc.m3u8', |
1061 | type: 'application/vnd.apple.mpegurl' | 993 | type: 'application/vnd.apple.mpegurl' |
1062 | }); | 994 | }); |
1063 | player.hls.mediaSource.trigger({ | 995 | openMediaSource(player); |
1064 | type: 'sourceopen' | ||
1065 | }); | ||
1066 | player.currentTime = function() { return currentTime; }; | 996 | player.currentTime = function() { return currentTime; }; |
1067 | player.buffered = function() { | 997 | player.buffered = function() { |
1068 | return videojs.createTimeRange(0, bufferEnd); | 998 | return videojs.createTimeRange(0, bufferEnd); |
... | @@ -1109,9 +1039,7 @@ test('clears the segment buffer on seek', function() { | ... | @@ -1109,9 +1039,7 @@ test('clears the segment buffer on seek', function() { |
1109 | src: 'disc.m3u8', | 1039 | src: 'disc.m3u8', |
1110 | type: 'application/vnd.apple.mpegurl' | 1040 | type: 'application/vnd.apple.mpegurl' |
1111 | }); | 1041 | }); |
1112 | player.hls.mediaSource.trigger({ | 1042 | openMediaSource(player); |
1113 | type: 'sourceopen' | ||
1114 | }); | ||
1115 | oldCurrentTime = player.currentTime; | 1043 | oldCurrentTime = player.currentTime; |
1116 | player.currentTime = function(time) { | 1044 | player.currentTime = function(time) { |
1117 | if (time !== undefined) { | 1045 | if (time !== undefined) { |
... | @@ -1158,9 +1086,7 @@ test('resets the switching algorithm if a request times out', function() { | ... | @@ -1158,9 +1086,7 @@ test('resets the switching algorithm if a request times out', function() { |
1158 | src: 'master.m3u8', | 1086 | src: 'master.m3u8', |
1159 | type: 'application/vnd.apple.mpegurl' | 1087 | type: 'application/vnd.apple.mpegurl' |
1160 | }); | 1088 | }); |
1161 | player.hls.mediaSource.trigger({ | 1089 | openMediaSource(player); |
1162 | type: 'sourceopen' | ||
1163 | }); | ||
1164 | standardXHRResponse(requests.shift()); // master | 1090 | standardXHRResponse(requests.shift()); // master |
1165 | standardXHRResponse(requests.shift()); // media.m3u8 | 1091 | standardXHRResponse(requests.shift()); // media.m3u8 |
1166 | // simulate a segment timeout | 1092 | // simulate a segment timeout |
... | @@ -1181,9 +1107,7 @@ test('disposes the playlist loader', function() { | ... | @@ -1181,9 +1107,7 @@ test('disposes the playlist loader', function() { |
1181 | src: 'manifest/master.m3u8', | 1107 | src: 'manifest/master.m3u8', |
1182 | type: 'application/vnd.apple.mpegurl' | 1108 | type: 'application/vnd.apple.mpegurl' |
1183 | }); | 1109 | }); |
1184 | player.hls.mediaSource.trigger({ | 1110 | openMediaSource(player); |
1185 | type: 'sourceopen' | ||
1186 | }); | ||
1187 | loaderDispose = player.hls.playlists.dispose; | 1111 | loaderDispose = player.hls.playlists.dispose; |
1188 | player.hls.playlists.dispose = function() { | 1112 | player.hls.playlists.dispose = function() { |
1189 | disposes++; | 1113 | disposes++; |
... | @@ -1232,9 +1156,7 @@ test('tracks the bytes downloaded', function() { | ... | @@ -1232,9 +1156,7 @@ test('tracks the bytes downloaded', function() { |
1232 | src: 'http://example.com/media.m3u8', | 1156 | src: 'http://example.com/media.m3u8', |
1233 | type: 'application/vnd.apple.mpegurl' | 1157 | type: 'application/vnd.apple.mpegurl' |
1234 | }); | 1158 | }); |
1235 | player.hls.mediaSource.trigger({ | 1159 | openMediaSource(player); |
1236 | type: 'sourceopen' | ||
1237 | }); | ||
1238 | 1160 | ||
1239 | strictEqual(player.hls.bytesReceived, 0, 'no bytes received'); | 1161 | strictEqual(player.hls.bytesReceived, 0, 'no bytes received'); |
1240 | 1162 | ||
... | @@ -1270,9 +1192,7 @@ test('re-emits mediachange events', function() { | ... | @@ -1270,9 +1192,7 @@ test('re-emits mediachange events', function() { |
1270 | src: 'http://example.com/media.m3u8', | 1192 | src: 'http://example.com/media.m3u8', |
1271 | type: 'application/vnd.apple.mpegurl' | 1193 | type: 'application/vnd.apple.mpegurl' |
1272 | }); | 1194 | }); |
1273 | player.hls.mediaSource.trigger({ | 1195 | openMediaSource(player); |
1274 | type: 'sourceopen' | ||
1275 | }); | ||
1276 | 1196 | ||
1277 | player.hls.playlists.trigger('mediachange'); | 1197 | player.hls.playlists.trigger('mediachange'); |
1278 | strictEqual(mediaChanges, 1, 'fired mediachange'); | 1198 | strictEqual(mediaChanges, 1, 'fired mediachange'); |
... | @@ -1302,4 +1222,48 @@ test('can be disposed before finishing initialization', function() { | ... | @@ -1302,4 +1222,48 @@ test('can be disposed before finishing initialization', function() { |
1302 | } | 1222 | } |
1303 | }); | 1223 | }); |
1304 | 1224 | ||
1225 | test('calls ended() on the media source at the end of a playlist', function() { | ||
1226 | var endOfStreams = 0; | ||
1227 | player.src({ | ||
1228 | src: 'http://example.com/media.m3u8', | ||
1229 | type: 'application/vnd.apple.mpegurl' | ||
1230 | }); | ||
1231 | openMediaSource(player); | ||
1232 | player.hls.mediaSource.endOfStream = function() { | ||
1233 | endOfStreams++; | ||
1234 | }; | ||
1235 | // playlist response | ||
1236 | requests.shift().respond(200, null, | ||
1237 | '#EXTM3U\n' + | ||
1238 | '#EXTINF:10,\n' + | ||
1239 | '0.ts\n' + | ||
1240 | '#EXT-X-ENDLIST\n'); | ||
1241 | // segment response | ||
1242 | requests[0].response = new ArrayBuffer(17); | ||
1243 | requests.shift().respond(200, null, ''); | ||
1244 | |||
1245 | strictEqual(endOfStreams, 1, 'ended media source'); | ||
1246 | }); | ||
1247 | |||
1248 | test('calling play() at the end of a video resets the media index', function() { | ||
1249 | player.src({ | ||
1250 | src: 'http://example.com/media.m3u8', | ||
1251 | type: 'application/vnd.apple.mpegurl' | ||
1252 | }); | ||
1253 | openMediaSource(player); | ||
1254 | requests.shift().respond(200, null, | ||
1255 | '#EXTM3U\n' + | ||
1256 | '#EXTINF:10,\n' + | ||
1257 | '0.ts\n' + | ||
1258 | '#EXT-X-ENDLIST\n'); | ||
1259 | standardXHRResponse(requests.shift()); | ||
1260 | |||
1261 | strictEqual(player.hls.mediaIndex, 1, 'index is 1 after the first segment'); | ||
1262 | player.hls.ended = function() { | ||
1263 | return true; | ||
1264 | }; | ||
1265 | player.play(); | ||
1266 | strictEqual(player.hls.mediaIndex, 0, 'index is 1 after the first segment'); | ||
1267 | }); | ||
1268 | |||
1305 | })(window, window.videojs); | 1269 | })(window, window.videojs); | ... | ... |
-
Please register or sign in to post a comment