shaka-player 3.0.11 → 3.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +5 -0
- package/CHANGELOG.md +132 -0
- package/CONTRIBUTORS +5 -0
- package/README.md +3 -0
- package/build/apps.py +2 -2
- package/build/check.py +2 -2
- package/build/conformance.textproto +0 -9
- package/build/generateExterns.js +1 -1
- package/build/shakaBuildHelpers.py +6 -5
- package/build/subprocessWindowsPatch.py +103 -0
- package/demo/common/assets.js +1 -1
- package/demo/common/message_ids.js +1 -0
- package/demo/config.js +2 -1
- package/demo/demo.less +4 -0
- package/demo/demo_utils.js +1 -0
- package/demo/input_container.js +2 -1
- package/demo/locales/en.json +1 -0
- package/demo/locales/source.json +4 -0
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +63 -60
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +63 -60
- package/dist/demo.compiled.map +3 -3
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +9 -9
- package/dist/locales.js +35 -33
- package/dist/receiver.compiled.debug.js +59 -56
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +59 -56
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +131 -5
- package/dist/shaka-player.compiled.debug.d.ts +131 -5
- package/dist/shaka-player.compiled.debug.externs.js +142 -8
- package/dist/shaka-player.compiled.debug.js +330 -312
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +142 -8
- package/dist/shaka-player.compiled.js +707 -702
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +131 -5
- package/dist/shaka-player.ui.debug.d.ts +131 -5
- package/dist/shaka-player.ui.debug.externs.js +144 -10
- package/dist/shaka-player.ui.debug.js +354 -333
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +144 -10
- package/dist/shaka-player.ui.js +860 -855
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/fairplay.md +1 -1
- package/docs/tutorials/faq.md +25 -0
- package/externs/aria.js +18 -0
- package/externs/ima.js +4 -0
- package/externs/shaka/ads.js +2 -0
- package/karma.conf.js +1 -0
- package/lib/ads/ad_manager.js +29 -11
- package/lib/ads/client_side_ad_manager.js +76 -86
- package/lib/ads/server_side_ad_manager.js +26 -11
- package/lib/cast/cast_proxy.js +3 -2
- package/lib/cast/cast_receiver.js +6 -2
- package/lib/cast/cast_sender.js +2 -2
- package/lib/dash/dash_parser.js +63 -1
- package/lib/dash/segment_list.js +1 -1
- package/lib/dash/segment_template.js +41 -14
- package/lib/hls/hls_parser.js +41 -11
- package/lib/media/content_workarounds.js +18 -0
- package/lib/media/drm_engine.js +8 -0
- package/lib/media/gap_jumping_controller.js +8 -4
- package/lib/media/media_source_engine.js +7 -0
- package/lib/media/playhead.js +1 -1
- package/lib/media/presentation_timeline.js +3 -2
- package/lib/media/segment_index.js +41 -11
- package/lib/media/streaming_engine.js +34 -21
- package/lib/net/networking_engine.js +2 -1
- package/lib/offline/download_manager.js +1 -2
- package/lib/player.js +99 -44
- package/lib/polyfill/encryption_scheme.js +2 -0
- package/lib/polyfill/fullscreen.js +2 -0
- package/lib/polyfill/mathround.js +2 -0
- package/lib/polyfill/mediasource.js +2 -0
- package/lib/polyfill/patchedmediakeys_apple.js +6 -4
- package/lib/polyfill/patchedmediakeys_ms.js +6 -4
- package/lib/polyfill/patchedmediakeys_nop.js +2 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
- package/lib/polyfill/pip_webkit.js +2 -0
- package/lib/polyfill/video_play_promise.js +2 -0
- package/lib/polyfill/videoplaybackquality.js +2 -0
- package/lib/polyfill/vttcue.js +2 -0
- package/lib/text/mp4_ttml_parser.js +3 -0
- package/lib/text/ttml_text_parser.js +5 -0
- package/lib/text/ui_text_displayer.js +37 -3
- package/lib/util/error.js +1 -4
- package/lib/util/fake_event.js +53 -7
- package/lib/util/mime_utils.js +33 -0
- package/lib/util/periods.js +25 -3
- package/lib/util/stream_utils.js +11 -0
- package/package.json +3 -3
- package/test/cast/cast_proxy_unit.js +12 -6
- package/test/cast/cast_receiver_integration.js +1 -1
- package/test/cast/cast_utils_unit.js +1 -1
- package/test/dash/dash_parser_manifest_unit.js +73 -0
- package/test/demo/demo_unit.js +0 -1
- package/test/hls/hls_parser_unit.js +45 -1
- package/test/media/drm_engine_unit.js +56 -0
- package/test/media/playhead_unit.js +27 -1
- package/test/media/presentation_timeline_unit.js +19 -0
- package/test/media/segment_index_unit.js +79 -6
- package/test/media/streaming_engine_unit.js +3 -3
- package/test/player_integration.js +38 -0
- package/test/player_unit.js +19 -1
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +30 -0
- package/test/test/assets/3675/dash_1.mpd +30 -0
- package/test/test/assets/3675/dash_2.mpd +30 -0
- package/test/test/assets/3675/dash_3.mpd +30 -0
- package/test/test/assets/3675/dash_4.mpd +30 -0
- package/test/test/assets/3675/dash_5.mpd +26 -0
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/util/fake_ad_manager.js +4 -1
- package/test/test/util/fake_media_source_engine.js +4 -0
- package/test/test/util/simple_fakes.js +5 -3
- package/test/test/util/waiter.js +36 -2
- package/test/text/ttml_text_parser_unit.js +9 -0
- package/test/text/ui_text_displayer_unit.js +19 -3
- package/test/ui/localization_unit.js +15 -14
- package/test/ui/ui_unit.js +4 -0
- package/ui/big_play_button.js +10 -0
- package/ui/cast_button.js +2 -3
- package/ui/controls.js +9 -7
- package/ui/less/containers.less +3 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/ru.json +6 -6
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +28 -51
- package/ui/pip_button.js +2 -3
- package/ui/play_button.js +10 -10
- package/ui/small_play_button.js +12 -0
|
@@ -1295,12 +1295,13 @@ describe('Playhead', () => {
|
|
|
1295
1295
|
});
|
|
1296
1296
|
|
|
1297
1297
|
// Regression test for https://github.com/google/shaka-player/issues/2987
|
|
1298
|
-
it('does gap jump if paused at 0', () => {
|
|
1298
|
+
it('does gap jump if paused at 0 and has autoplay', () => {
|
|
1299
1299
|
const buffered = [{start: 10, end: 20}];
|
|
1300
1300
|
video.buffered = createFakeBuffered(buffered);
|
|
1301
1301
|
video.currentTime = 0;
|
|
1302
1302
|
video.readyState = HTMLMediaElement.HAVE_ENOUGH_DATA;
|
|
1303
1303
|
video.paused = true;
|
|
1304
|
+
video.autoplay = true;
|
|
1304
1305
|
|
|
1305
1306
|
config.jumpLargeGaps = true;
|
|
1306
1307
|
playhead = new shaka.media.MediaSourcePlayhead(
|
|
@@ -1318,6 +1319,31 @@ describe('Playhead', () => {
|
|
|
1318
1319
|
expect(video.currentTime).toBe(10);
|
|
1319
1320
|
});
|
|
1320
1321
|
|
|
1322
|
+
// Regression test for https://github.com/google/shaka-player/issues/3451
|
|
1323
|
+
it('doesn\'t gap jump if paused at 0 and hasn\'t autoplay', () => {
|
|
1324
|
+
const buffered = [{start: 10, end: 20}];
|
|
1325
|
+
video.buffered = createFakeBuffered(buffered);
|
|
1326
|
+
video.currentTime = 0;
|
|
1327
|
+
video.readyState = HTMLMediaElement.HAVE_ENOUGH_DATA;
|
|
1328
|
+
video.paused = true;
|
|
1329
|
+
video.autoplay = false;
|
|
1330
|
+
|
|
1331
|
+
config.jumpLargeGaps = true;
|
|
1332
|
+
playhead = new shaka.media.MediaSourcePlayhead(
|
|
1333
|
+
video,
|
|
1334
|
+
manifest,
|
|
1335
|
+
config,
|
|
1336
|
+
/* startTime= */ 0,
|
|
1337
|
+
Util.spyFunc(onSeek),
|
|
1338
|
+
Util.spyFunc(onEvent));
|
|
1339
|
+
|
|
1340
|
+
playhead.notifyOfBufferingChange();
|
|
1341
|
+
jasmine.clock().tick(500);
|
|
1342
|
+
|
|
1343
|
+
// There should NOT have been a gap jump.
|
|
1344
|
+
expect(video.currentTime).toBe(0);
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1321
1347
|
/**
|
|
1322
1348
|
* @param {string} name
|
|
1323
1349
|
* @param {SeekTestInfo} data
|
|
@@ -290,6 +290,25 @@ describe('PresentationTimeline', () => {
|
|
|
290
290
|
// last segment time (50)
|
|
291
291
|
expect(timeline.getSegmentAvailabilityEnd()).toBe(50);
|
|
292
292
|
});
|
|
293
|
+
|
|
294
|
+
it('calculates time when there a transition of live to static', () => {
|
|
295
|
+
const timeline = makeLiveTimeline(/* availability= */ 20);
|
|
296
|
+
|
|
297
|
+
const ref1 = makeSegmentReference(0, 10);
|
|
298
|
+
const ref2 = makeSegmentReference(10, 20);
|
|
299
|
+
const ref3 = makeSegmentReference(20, 30);
|
|
300
|
+
const ref4 = makeSegmentReference(30, 40);
|
|
301
|
+
const ref5 = makeSegmentReference(40, 50);
|
|
302
|
+
|
|
303
|
+
setElapsed(50);
|
|
304
|
+
timeline.notifySegments([ref1, ref2, ref3, ref4, ref5]);
|
|
305
|
+
|
|
306
|
+
expect(timeline.getSegmentAvailabilityEnd()).toBe(50);
|
|
307
|
+
|
|
308
|
+
timeline.setStatic(true);
|
|
309
|
+
|
|
310
|
+
expect(timeline.getSegmentAvailabilityEnd()).toBe(50);
|
|
311
|
+
});
|
|
293
312
|
});
|
|
294
313
|
|
|
295
314
|
describe('getDuration', () => {
|
|
@@ -329,12 +329,40 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
329
329
|
makeReference(uri(20), 20, 30),
|
|
330
330
|
];
|
|
331
331
|
|
|
332
|
-
// The first
|
|
333
|
-
// should be discarded.
|
|
334
|
-
index1.mergeAndEvict(references2,
|
|
332
|
+
// The first two references end before the availabilityWindowStart, so
|
|
333
|
+
// they should be discarded.
|
|
334
|
+
index1.mergeAndEvict(references2, 21);
|
|
335
|
+
expect(index1.references.length).toBe(1);
|
|
336
|
+
expect(index1.references[0]).toEqual(references2[2]);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('discards segments that end before the first old segment', () => {
|
|
340
|
+
/** @type {!Array.<!shaka.media.SegmentReference>} */
|
|
341
|
+
const references1 = [
|
|
342
|
+
// Assuming ref(0, 10) has been already evicted
|
|
343
|
+
makeReference(uri(10), 10, 20),
|
|
344
|
+
];
|
|
345
|
+
const index1 = new shaka.media.SegmentIndex(references1);
|
|
346
|
+
const position1 = index1.find(10);
|
|
347
|
+
|
|
348
|
+
/** @type {!Array.<!shaka.media.SegmentReference>} */
|
|
349
|
+
const references2 = [
|
|
350
|
+
makeReference(uri(0), 0, 10),
|
|
351
|
+
makeReference(uri(10), 10, 20),
|
|
352
|
+
makeReference(uri(20), 20, 30),
|
|
353
|
+
];
|
|
354
|
+
|
|
355
|
+
// The new first reference ends before the first old reference starts, so
|
|
356
|
+
// it should be discarded. We will never grow the list at the beginning.
|
|
357
|
+
index1.mergeAndEvict(references2, 0);
|
|
335
358
|
expect(index1.references.length).toBe(2);
|
|
336
359
|
expect(index1.references[0]).toEqual(references2[1]);
|
|
337
360
|
expect(index1.references[1]).toEqual(references2[2]);
|
|
361
|
+
|
|
362
|
+
// The positions should be the same, as well.
|
|
363
|
+
expect(index1.find(10)).toBe(position1);
|
|
364
|
+
goog.asserts.assert(position1 != null, 'Position should not be null!');
|
|
365
|
+
expect(index1.get(position1)).toBe(references2[1]);
|
|
338
366
|
});
|
|
339
367
|
});
|
|
340
368
|
|
|
@@ -407,9 +435,15 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
407
435
|
|
|
408
436
|
describe('SegmentIterator', () => {
|
|
409
437
|
const inputRefs = [
|
|
410
|
-
makeReference(uri(0), 0, 10),
|
|
411
|
-
makeReference(uri(
|
|
412
|
-
makeReference(uri(
|
|
438
|
+
makeReference(uri(0.10), 0, 10),
|
|
439
|
+
makeReference(uri(10.20), 10, 20),
|
|
440
|
+
makeReference(uri(20.30), 20, 30),
|
|
441
|
+
];
|
|
442
|
+
|
|
443
|
+
const additionalRefs = [
|
|
444
|
+
makeReference(uri(30.40), 30, 40),
|
|
445
|
+
makeReference(uri(40.50), 40, 50),
|
|
446
|
+
makeReference(uri(50.60), 50, 60),
|
|
413
447
|
];
|
|
414
448
|
|
|
415
449
|
it('works with Array.from', () => {
|
|
@@ -433,6 +467,45 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
433
467
|
expect(Array.from(index)).toEqual(inputRefs.slice(1));
|
|
434
468
|
});
|
|
435
469
|
|
|
470
|
+
it('resumes iteration after new references are added', () => {
|
|
471
|
+
const refs = inputRefs.slice();
|
|
472
|
+
const index = new shaka.media.SegmentIndex(refs);
|
|
473
|
+
|
|
474
|
+
// This simulates the pattern of calls in StreamingEngine when we buffer
|
|
475
|
+
// to the edge of a live stream.
|
|
476
|
+
const iterator = index[Symbol.iterator]();
|
|
477
|
+
iterator.next();
|
|
478
|
+
expect(iterator.current()).toBe(inputRefs[0]);
|
|
479
|
+
|
|
480
|
+
iterator.next();
|
|
481
|
+
expect(iterator.current()).toBe(inputRefs[1]);
|
|
482
|
+
|
|
483
|
+
iterator.next();
|
|
484
|
+
expect(iterator.current()).toBe(inputRefs[2]);
|
|
485
|
+
|
|
486
|
+
iterator.next();
|
|
487
|
+
expect(iterator.current()).toBe(null);
|
|
488
|
+
// After we reach the end of the iteration, we should still get null back
|
|
489
|
+
// on subsequent requests.
|
|
490
|
+
expect(iterator.current()).toBe(null);
|
|
491
|
+
expect(iterator.current()).toBe(null);
|
|
492
|
+
|
|
493
|
+
// Although we have reached the end, we should still be able to add new
|
|
494
|
+
// references and iterate to them without starting over the iteration.
|
|
495
|
+
refs.push(...additionalRefs);
|
|
496
|
+
|
|
497
|
+
expect(iterator.current()).toBe(additionalRefs[0]);
|
|
498
|
+
|
|
499
|
+
iterator.next();
|
|
500
|
+
expect(iterator.current()).toBe(additionalRefs[1]);
|
|
501
|
+
|
|
502
|
+
iterator.next();
|
|
503
|
+
expect(iterator.current()).toBe(additionalRefs[2]);
|
|
504
|
+
|
|
505
|
+
iterator.next();
|
|
506
|
+
expect(iterator.current()).toBe(null);
|
|
507
|
+
});
|
|
508
|
+
|
|
436
509
|
describe('seek', () => {
|
|
437
510
|
it('returns the matching segment', () => {
|
|
438
511
|
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
@@ -788,7 +788,7 @@ describe('StreamingEngine', () => {
|
|
|
788
788
|
// This would let some media types buffer faster than others if unchecked.
|
|
789
789
|
netEngineDelays.text = 0.1;
|
|
790
790
|
netEngineDelays.audio = 1.0;
|
|
791
|
-
netEngineDelays.video =
|
|
791
|
+
netEngineDelays.video = 5.0; // Need init segment and media segment
|
|
792
792
|
|
|
793
793
|
mediaSourceEngine.appendBuffer.and.callFake((type, data, start, end) => {
|
|
794
794
|
// Call to the underlying implementation.
|
|
@@ -2123,13 +2123,13 @@ describe('StreamingEngine', () => {
|
|
|
2123
2123
|
.bind(mediaSourceEngine);
|
|
2124
2124
|
|
|
2125
2125
|
mediaSourceEngine.remove.and.callFake((type, start, end) => {
|
|
2126
|
-
expect(presentationTimeInSeconds).
|
|
2126
|
+
expect(presentationTimeInSeconds).toBeGreaterThanOrEqual(20);
|
|
2127
2127
|
expect(start).toBe(0);
|
|
2128
2128
|
expect(end).toBe(10);
|
|
2129
2129
|
|
|
2130
2130
|
if (mediaSourceEngine.remove.calls.count() == 3) {
|
|
2131
2131
|
mediaSourceEngine.remove.and.callFake((type, start, end) => {
|
|
2132
|
-
expect(presentationTimeInSeconds).
|
|
2132
|
+
expect(presentationTimeInSeconds).toBeGreaterThanOrEqual(30);
|
|
2133
2133
|
expect(start).toBe(10);
|
|
2134
2134
|
expect(end).toBe(20);
|
|
2135
2135
|
return originalRemove(type, start, end);
|
|
@@ -649,6 +649,44 @@ describe('Player', () => {
|
|
|
649
649
|
});
|
|
650
650
|
});
|
|
651
651
|
|
|
652
|
+
describe('seek range', () => {
|
|
653
|
+
// Regression test for Issue #3675.
|
|
654
|
+
it('has a reasonable seek range after going from live to VOD', async () => {
|
|
655
|
+
const netEngine = player.getNetworkingEngine();
|
|
656
|
+
const startTime = Date.now();
|
|
657
|
+
netEngine.registerRequestFilter((type, request) => {
|
|
658
|
+
if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
// Simulate a live stream by providing different manifests over time.
|
|
662
|
+
const time = (Date.now() - startTime) / 1000;
|
|
663
|
+
const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
|
|
664
|
+
request.uris = [
|
|
665
|
+
'/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
|
|
666
|
+
];
|
|
667
|
+
console.log('getting manifest', request.uris);
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
// Play the stream.
|
|
671
|
+
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
672
|
+
video.play();
|
|
673
|
+
|
|
674
|
+
// Wait for the stream to be over.
|
|
675
|
+
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
676
|
+
/** @type {shaka.test.Waiter} */
|
|
677
|
+
const waiter = new shaka.test.Waiter(eventManager)
|
|
678
|
+
.timeoutAfter(20).failOnTimeout(true);
|
|
679
|
+
await waiter.waitForEnd(video);
|
|
680
|
+
|
|
681
|
+
// The stream should have transitioned to VOD by now.
|
|
682
|
+
expect(player.isLive()).toBe(false);
|
|
683
|
+
|
|
684
|
+
// Check that the final seek range is as expected.
|
|
685
|
+
const seekRange = player.seekRange();
|
|
686
|
+
expect(seekRange.end).toBe(14);
|
|
687
|
+
});
|
|
688
|
+
});
|
|
689
|
+
|
|
652
690
|
describe('buffering', () => {
|
|
653
691
|
const startBuffering = jasmine.objectContaining({buffering: true});
|
|
654
692
|
const endBuffering = jasmine.objectContaining({buffering: false});
|
package/test/player_unit.js
CHANGED
|
@@ -1818,6 +1818,24 @@ describe('Player', () => {
|
|
|
1818
1818
|
expect(variantChanged).not.toHaveBeenCalled();
|
|
1819
1819
|
});
|
|
1820
1820
|
});
|
|
1821
|
+
|
|
1822
|
+
it('chooses the configured text language and role at start', async () => {
|
|
1823
|
+
player.configure({
|
|
1824
|
+
preferredTextLanguage: 'en',
|
|
1825
|
+
preferredTextRole: 'commentary',
|
|
1826
|
+
});
|
|
1827
|
+
|
|
1828
|
+
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
1829
|
+
|
|
1830
|
+
// Text was turned on during startup.
|
|
1831
|
+
expect(player.isTextTrackVisible()).toBe(true);
|
|
1832
|
+
|
|
1833
|
+
expect(getActiveTextTrack()).toEqual(jasmine.objectContaining({
|
|
1834
|
+
id: 52,
|
|
1835
|
+
language: 'en',
|
|
1836
|
+
roles: ['commentary'],
|
|
1837
|
+
}));
|
|
1838
|
+
});
|
|
1821
1839
|
}); // describe('tracks')
|
|
1822
1840
|
|
|
1823
1841
|
describe('languages', () => {
|
|
@@ -2744,7 +2762,7 @@ describe('Player', () => {
|
|
|
2744
2762
|
|
|
2745
2763
|
manifest.addVariant(1, (variant) => {
|
|
2746
2764
|
variant.addVideo(2, (stream) => {
|
|
2747
|
-
stream.size(200,
|
|
2765
|
+
stream.size(200, 1024);
|
|
2748
2766
|
});
|
|
2749
2767
|
});
|
|
2750
2768
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="dynamic"
|
|
8
|
+
minimumUpdatePeriod="PT2S"
|
|
9
|
+
suggestedPresentationDelay="PT2S"
|
|
10
|
+
availabilityStartTime="2021-10-28T07:36:27.755Z"
|
|
11
|
+
publishTime="2021-10-28T07:36:29.744Z"
|
|
12
|
+
timeShiftBufferDepth="PT10.0S"
|
|
13
|
+
maxSegmentDuration="PT2.0S"
|
|
14
|
+
minBufferTime="PT4.0S">
|
|
15
|
+
<ProgramInformation>
|
|
16
|
+
</ProgramInformation>
|
|
17
|
+
<ServiceDescription id="0">
|
|
18
|
+
</ServiceDescription>
|
|
19
|
+
<Period id="0" start="PT0.0S">
|
|
20
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
21
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
22
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
|
|
23
|
+
<SegmentTimeline>
|
|
24
|
+
<S t="0" d="30720" />
|
|
25
|
+
</SegmentTimeline>
|
|
26
|
+
</SegmentTemplate>
|
|
27
|
+
</Representation>
|
|
28
|
+
</AdaptationSet>
|
|
29
|
+
</Period>
|
|
30
|
+
</MPD>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="dynamic"
|
|
8
|
+
minimumUpdatePeriod="PT2S"
|
|
9
|
+
suggestedPresentationDelay="PT2S"
|
|
10
|
+
availabilityStartTime="2021-10-28T07:36:27.755Z"
|
|
11
|
+
publishTime="2021-10-28T07:36:31.750Z"
|
|
12
|
+
timeShiftBufferDepth="PT10.0S"
|
|
13
|
+
maxSegmentDuration="PT2.0S"
|
|
14
|
+
minBufferTime="PT4.0S">
|
|
15
|
+
<ProgramInformation>
|
|
16
|
+
</ProgramInformation>
|
|
17
|
+
<ServiceDescription id="0">
|
|
18
|
+
</ServiceDescription>
|
|
19
|
+
<Period id="0" start="PT0.0S">
|
|
20
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
21
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
22
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
|
|
23
|
+
<SegmentTimeline>
|
|
24
|
+
<S t="0" d="30720" r="1" />
|
|
25
|
+
</SegmentTimeline>
|
|
26
|
+
</SegmentTemplate>
|
|
27
|
+
</Representation>
|
|
28
|
+
</AdaptationSet>
|
|
29
|
+
</Period>
|
|
30
|
+
</MPD>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="dynamic"
|
|
8
|
+
minimumUpdatePeriod="PT2S"
|
|
9
|
+
suggestedPresentationDelay="PT2S"
|
|
10
|
+
availabilityStartTime="2021-10-28T07:36:27.755Z"
|
|
11
|
+
publishTime="2021-10-28T07:36:35.752Z"
|
|
12
|
+
timeShiftBufferDepth="PT10.0S"
|
|
13
|
+
maxSegmentDuration="PT2.0S"
|
|
14
|
+
minBufferTime="PT4.0S">
|
|
15
|
+
<ProgramInformation>
|
|
16
|
+
</ProgramInformation>
|
|
17
|
+
<ServiceDescription id="0">
|
|
18
|
+
</ServiceDescription>
|
|
19
|
+
<Period id="0" start="PT0.0S">
|
|
20
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
21
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
22
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
|
|
23
|
+
<SegmentTimeline>
|
|
24
|
+
<S t="0" d="30720" r="3" />
|
|
25
|
+
</SegmentTimeline>
|
|
26
|
+
</SegmentTemplate>
|
|
27
|
+
</Representation>
|
|
28
|
+
</AdaptationSet>
|
|
29
|
+
</Period>
|
|
30
|
+
</MPD>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="dynamic"
|
|
8
|
+
minimumUpdatePeriod="PT2S"
|
|
9
|
+
suggestedPresentationDelay="PT2S"
|
|
10
|
+
availabilityStartTime="2021-10-28T07:36:27.755Z"
|
|
11
|
+
publishTime="2021-10-28T07:36:37.752Z"
|
|
12
|
+
timeShiftBufferDepth="PT10.0S"
|
|
13
|
+
maxSegmentDuration="PT2.0S"
|
|
14
|
+
minBufferTime="PT4.0S">
|
|
15
|
+
<ProgramInformation>
|
|
16
|
+
</ProgramInformation>
|
|
17
|
+
<ServiceDescription id="0">
|
|
18
|
+
</ServiceDescription>
|
|
19
|
+
<Period id="0" start="PT0.0S">
|
|
20
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
21
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
22
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
|
|
23
|
+
<SegmentTimeline>
|
|
24
|
+
<S t="0" d="30720" r="4" />
|
|
25
|
+
</SegmentTimeline>
|
|
26
|
+
</SegmentTemplate>
|
|
27
|
+
</Representation>
|
|
28
|
+
</AdaptationSet>
|
|
29
|
+
</Period>
|
|
30
|
+
</MPD>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="dynamic"
|
|
8
|
+
minimumUpdatePeriod="PT2S"
|
|
9
|
+
suggestedPresentationDelay="PT2S"
|
|
10
|
+
availabilityStartTime="2021-10-28T07:36:27.755Z"
|
|
11
|
+
publishTime="2021-10-28T07:36:41.751Z"
|
|
12
|
+
timeShiftBufferDepth="PT10.0S"
|
|
13
|
+
maxSegmentDuration="PT2.0S"
|
|
14
|
+
minBufferTime="PT4.0S">
|
|
15
|
+
<ProgramInformation>
|
|
16
|
+
</ProgramInformation>
|
|
17
|
+
<ServiceDescription id="0">
|
|
18
|
+
</ServiceDescription>
|
|
19
|
+
<Period id="0" start="PT0.0S">
|
|
20
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
21
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
22
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="3">
|
|
23
|
+
<SegmentTimeline>
|
|
24
|
+
<S t="61440" d="30720" r="4" />
|
|
25
|
+
</SegmentTimeline>
|
|
26
|
+
</SegmentTemplate>
|
|
27
|
+
</Representation>
|
|
28
|
+
</AdaptationSet>
|
|
29
|
+
</Period>
|
|
30
|
+
</MPD>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
3
|
+
xmlns="urn:mpeg:dash:schema:mpd:2011"
|
|
4
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
5
|
+
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
|
|
6
|
+
profiles="urn:mpeg:dash:profile:isoff-live:2011"
|
|
7
|
+
type="static"
|
|
8
|
+
mediaPresentationDuration="PT14.0S"
|
|
9
|
+
maxSegmentDuration="PT2.0S"
|
|
10
|
+
minBufferTime="PT4.0S">
|
|
11
|
+
<ProgramInformation>
|
|
12
|
+
</ProgramInformation>
|
|
13
|
+
<ServiceDescription id="0">
|
|
14
|
+
</ServiceDescription>
|
|
15
|
+
<Period id="0" start="PT0.0S">
|
|
16
|
+
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="30/1" maxWidth="1280" maxHeight="720" par="16:9">
|
|
17
|
+
<Representation id="0" mimeType="video/mp4" codecs="avc1.64001f" bandwidth="122012" width="1280" height="720" sar="1:1">
|
|
18
|
+
<SegmentTemplate timescale="15360" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="3">
|
|
19
|
+
<SegmentTimeline>
|
|
20
|
+
<S t="61440" d="30720" r="4" />
|
|
21
|
+
</SegmentTimeline>
|
|
22
|
+
</SegmentTemplate>
|
|
23
|
+
</Representation>
|
|
24
|
+
</AdaptationSet>
|
|
25
|
+
</Period>
|
|
26
|
+
</MPD>
|
|
Binary file
|
|
@@ -25,6 +25,9 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
|
|
|
25
25
|
this.stats_ = new shaka.ads.AdsStats();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/** @override */
|
|
29
|
+
release() {}
|
|
30
|
+
|
|
28
31
|
/** @override */
|
|
29
32
|
setLocale(locale) {}
|
|
30
33
|
|
|
@@ -75,7 +78,7 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
|
|
|
75
78
|
*/
|
|
76
79
|
startAd(ad) {
|
|
77
80
|
const event = new shaka.util.FakeEvent(shaka.ads.AdManager.AD_STARTED,
|
|
78
|
-
|
|
81
|
+
(new Map()).set('ad', ad));
|
|
79
82
|
|
|
80
83
|
this.dispatchEvent(event);
|
|
81
84
|
}
|
|
@@ -124,6 +124,10 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
124
124
|
/** @type {!jasmine.Spy} */
|
|
125
125
|
this.flush = jasmine.createSpy('flush').and.returnValue(Promise.resolve());
|
|
126
126
|
|
|
127
|
+
/** @type {!jasmine.Spy} */
|
|
128
|
+
this.clearSelectedClosedCaptionId =
|
|
129
|
+
jasmine.createSpy('clearSelectedClosedCaptionId');
|
|
130
|
+
|
|
127
131
|
/** @type {!jasmine.Spy} */
|
|
128
132
|
this.getTextDisplayer =
|
|
129
133
|
jasmine.createSpy('getTextDisplayer')
|
|
@@ -90,13 +90,15 @@ shaka.test.FakeAbrManager = class {
|
|
|
90
90
|
/** @extends {shaka.media.StreamingEngine} */
|
|
91
91
|
shaka.test.FakeStreamingEngine = class {
|
|
92
92
|
constructor() {
|
|
93
|
-
const resolve = () => Promise.resolve();
|
|
94
|
-
|
|
95
93
|
let activeVariant = null;
|
|
96
94
|
let activeText = null;
|
|
97
95
|
|
|
98
96
|
/** @type {!jasmine.Spy} */
|
|
99
|
-
this.destroy = jasmine.createSpy('destroy').and.callFake(
|
|
97
|
+
this.destroy = jasmine.createSpy('destroy').and.callFake(() => {
|
|
98
|
+
activeVariant = null;
|
|
99
|
+
activeText = null;
|
|
100
|
+
return Promise.resolve();
|
|
101
|
+
});
|
|
100
102
|
|
|
101
103
|
/** @type {!jasmine.Spy} */
|
|
102
104
|
this.configure = jasmine.createSpy('configure');
|
package/test/test/util/waiter.js
CHANGED
|
@@ -132,10 +132,43 @@ shaka.test.Waiter = class {
|
|
|
132
132
|
* @return {!Promise}
|
|
133
133
|
*/
|
|
134
134
|
waitForEnd(mediaElement) {
|
|
135
|
-
|
|
135
|
+
// Sometimes, the ended flag is not set, or the event does not fire,
|
|
136
|
+
// (I'm looking at **you**, Safari), so also check if we've reached the
|
|
137
|
+
// duration.
|
|
138
|
+
if (mediaElement.ended ||
|
|
139
|
+
mediaElement.currentTime >= mediaElement.duration) {
|
|
136
140
|
return Promise.resolve();
|
|
137
141
|
}
|
|
138
|
-
|
|
142
|
+
|
|
143
|
+
// The name of what we're waiting for.
|
|
144
|
+
const goalName = 'end of media';
|
|
145
|
+
|
|
146
|
+
// Cleanup on timeout.
|
|
147
|
+
const cleanup = () => {
|
|
148
|
+
this.eventManager_.unlisten(mediaElement, 'timeupdate');
|
|
149
|
+
this.eventManager_.unlisten(mediaElement, 'ended');
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// The conditions for success. Don't rely on either time, or the ended
|
|
153
|
+
// flag, or the ended event, specifically. Any of these is sufficient.
|
|
154
|
+
// This flexibility cuts down on test flake on Safari (currently 14) in
|
|
155
|
+
// particular, where the flag might be set, but the ended event did not
|
|
156
|
+
// fire.
|
|
157
|
+
const p = new Promise((resolve) => {
|
|
158
|
+
this.eventManager_.listen(mediaElement, 'timeupdate', () => {
|
|
159
|
+
if (mediaElement.currentTime >= mediaElement.duration ||
|
|
160
|
+
mediaElement.ended) {
|
|
161
|
+
cleanup();
|
|
162
|
+
resolve();
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
this.eventManager_.listen(mediaElement, 'ended', () => {
|
|
166
|
+
cleanup();
|
|
167
|
+
resolve();
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
return this.waitUntilGeneric_(goalName, p, cleanup, mediaElement);
|
|
139
172
|
}
|
|
140
173
|
|
|
141
174
|
/**
|
|
@@ -256,6 +289,7 @@ shaka.test.Waiter = class {
|
|
|
256
289
|
'ready state', mediaElement.readyState,
|
|
257
290
|
'playback rate', mediaElement.playbackRate,
|
|
258
291
|
'paused', mediaElement.paused,
|
|
292
|
+
'ended', mediaElement.ended,
|
|
259
293
|
'buffered', buffered);
|
|
260
294
|
}
|
|
261
295
|
};
|
|
@@ -305,6 +305,15 @@ describe('TtmlTextParser', () => {
|
|
|
305
305
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0});
|
|
306
306
|
});
|
|
307
307
|
|
|
308
|
+
it('supports comments in the body', () => {
|
|
309
|
+
verifyHelper(
|
|
310
|
+
[],
|
|
311
|
+
'<tt><body><div>' +
|
|
312
|
+
'<!-- text-based TTML -->' +
|
|
313
|
+
'</div></body></tt>',
|
|
314
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0});
|
|
315
|
+
});
|
|
316
|
+
|
|
308
317
|
it('parses alignment from textAlign attribute of a region', () => {
|
|
309
318
|
verifyHelper(
|
|
310
319
|
[
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
goog.require('shaka.test.UiUtils');
|
|
8
7
|
goog.require('shaka.test.Util');
|
|
9
8
|
goog.require('shaka.text.Cue');
|
|
10
9
|
goog.require('shaka.text.UITextDisplayer');
|
|
@@ -51,8 +50,7 @@ describe('UITextDisplayer', () => {
|
|
|
51
50
|
/** @type {!HTMLElement} */ (document.createElement('div'));
|
|
52
51
|
videoContainer.style.height = `${videoContainerHeight}px`;
|
|
53
52
|
document.body.appendChild(videoContainer);
|
|
54
|
-
video = shaka.test.
|
|
55
|
-
videoContainer.appendChild(video);
|
|
53
|
+
video = new shaka.test.FakeVideo();
|
|
56
54
|
});
|
|
57
55
|
|
|
58
56
|
beforeEach(() => {
|
|
@@ -316,4 +314,22 @@ describe('UITextDisplayer', () => {
|
|
|
316
314
|
// duplicates.
|
|
317
315
|
expect(captions.length).toBe(3);
|
|
318
316
|
});
|
|
317
|
+
|
|
318
|
+
it('hides currently displayed cue when removed', async () => {
|
|
319
|
+
const cue = new shaka.text.Cue(0, 50, 'One');
|
|
320
|
+
textDisplayer.setTextVisibility(true);
|
|
321
|
+
textDisplayer.append([cue]);
|
|
322
|
+
video.currentTime = 10;
|
|
323
|
+
await shaka.test.Util.delay(0.5);
|
|
324
|
+
const textContainer = videoContainer.querySelector('.shaka-text-container');
|
|
325
|
+
|
|
326
|
+
let cueElements = textContainer.querySelectorAll('span');
|
|
327
|
+
expect(cueElements.length).toBe(1);
|
|
328
|
+
expect(cueElements[0].textContent).toBe('One');
|
|
329
|
+
|
|
330
|
+
textDisplayer.remove(0, 100);
|
|
331
|
+
|
|
332
|
+
cueElements = textContainer.querySelectorAll('span');
|
|
333
|
+
expect(cueElements.length).toBe(0);
|
|
334
|
+
});
|
|
319
335
|
});
|