shaka-player 3.3.4 → 4.0.0
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/.github/workflows/build-and-test.yaml +0 -1
- package/.github/workflows/demo-version-index.yaml +8 -0
- package/.github/workflows/release-please.yaml +23 -2
- package/.github/workflows/selenium-lab-tests.yaml +0 -1
- package/.github/workflows/sync-labels.yaml +33 -0
- package/.github/workflows/update-issues.yaml +29 -0
- package/.github/workflows/validate-pr-title.yaml +35 -0
- package/AUTHORS +1 -0
- package/CHANGELOG.md +198 -32
- package/CONTRIBUTORS +1 -0
- package/README.md +10 -7
- package/app-engine/demo-version-index/README.md +3 -3
- package/app-engine/demo-version-index/app.yaml +27 -1
- package/app-engine/demo-version-index/generate.py +164 -0
- package/app-engine/demo-version-index/main.py +4 -155
- package/app-engine/demo-version-index/requirements.txt +0 -1
- package/build/README.md +2 -2
- package/build/compiler.py +1 -1
- package/build/generateTsDefs.py +0 -2
- package/build/shaka-lab.yaml +0 -2
- package/build/test.py +7 -1
- package/build/types/core +0 -1
- package/build/types/polyfill +0 -3
- package/demo/common/asset.js +17 -1
- package/demo/common/assets.js +29 -0
- package/demo/common/message_ids.js +6 -3
- package/demo/config.js +10 -11
- package/demo/custom.js +39 -0
- package/demo/demo_utils.js +0 -1
- package/demo/locales/en.json +6 -3
- package/demo/locales/source.json +22 -10
- package/demo/main.js +9 -6
- package/demo/search.js +2 -1
- package/dist/controls.css +1 -1
- package/dist/demo.compiled.debug.js +71 -64
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +71 -64
- package/dist/demo.compiled.map +3 -3
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +16 -20
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +32 -28
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +32 -28
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +78 -83
- package/dist/shaka-player.compiled.debug.d.ts +78 -83
- package/dist/shaka-player.compiled.debug.externs.js +126 -126
- package/dist/shaka-player.compiled.debug.js +426 -483
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +126 -126
- package/dist/shaka-player.compiled.js +838 -856
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +80 -83
- package/dist/shaka-player.ui.debug.d.ts +80 -83
- package/dist/shaka-player.ui.debug.externs.js +134 -126
- package/dist/shaka-player.ui.debug.js +488 -543
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +134 -126
- package/dist/shaka-player.ui.js +980 -994
- package/dist/shaka-player.ui.map +4 -4
- package/docs/tutorials/config.md +0 -2
- package/docs/tutorials/drm-config.md +5 -0
- package/docs/tutorials/fairplay.md +7 -22
- package/docs/tutorials/faq.md +0 -11
- package/docs/tutorials/index.json +2 -8
- package/docs/tutorials/plugins.md +1 -3
- package/docs/tutorials/upgrade.md +83 -11
- package/externs/polyfill.js +15 -0
- package/externs/shaka/manifest.js +5 -1
- package/externs/shaka/net.js +12 -0
- package/externs/shaka/offline.js +5 -1
- package/externs/shaka/player.js +39 -32
- package/externs/shaka/text.js +12 -12
- package/externs/sourcebuffer.js +15 -0
- package/lib/ads/client_side_ad.js +13 -2
- package/lib/ads/client_side_ad_manager.js +22 -4
- package/lib/cast/cast_utils.js +0 -1
- package/lib/dash/content_protection.js +85 -5
- package/lib/dash/dash_parser.js +1 -1
- package/lib/hls/hls_parser.js +378 -743
- package/lib/hls/manifest_text_parser.js +2 -3
- package/lib/media/drm_engine.js +102 -53
- package/lib/media/gap_jumping_controller.js +10 -45
- package/lib/media/media_source_engine.js +87 -15
- package/lib/media/playhead.js +2 -5
- package/lib/media/presentation_timeline.js +1 -2
- package/lib/media/segment_index.js +13 -46
- package/lib/media/segment_reference.js +47 -1
- package/lib/media/streaming_engine.js +29 -11
- package/lib/media/time_ranges_utils.js +4 -9
- package/lib/net/networking_engine.js +3 -0
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +100 -132
- package/lib/player.js +17 -201
- package/lib/polyfill/media_capabilities.js +12 -6
- package/lib/polyfill/mediasource.js +0 -28
- package/lib/polyfill/patchedmediakeys_nop.js +2 -0
- package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
- package/lib/text/cue.js +0 -6
- package/lib/text/lrc_text_parser.js +8 -0
- package/lib/text/mp4_ttml_parser.js +8 -0
- package/lib/text/mp4_vtt_parser.js +8 -0
- package/lib/text/sbv_text_parser.js +8 -0
- package/lib/text/simple_text_displayer.js +1 -7
- package/lib/text/srt_text_parser.js +8 -0
- package/lib/text/ssa_text_parser.js +8 -0
- package/lib/text/text_engine.js +19 -3
- package/lib/text/ttml_text_parser.js +8 -0
- package/lib/text/ui_text_displayer.js +1 -7
- package/lib/text/vtt_text_parser.js +24 -2
- package/lib/text/web_vtt_generator.js +1 -7
- package/lib/util/error.js +9 -13
- package/lib/util/fairplay_utils.js +109 -0
- package/lib/util/functional.js +0 -42
- package/lib/util/mime_utils.js +2 -0
- package/lib/util/platform.js +45 -0
- package/lib/util/player_configuration.js +12 -6
- package/lib/util/pssh.js +23 -4
- package/lib/util/stream_utils.js +92 -22
- package/lib/util/uint8array_utils.js +0 -16
- package/lib/util/xml_utils.js +1 -1
- package/package.json +1 -1
- package/roadmap.md +19 -19
- package/shaka-player.uncompiled.js +0 -3
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/dash/dash_parser_content_protection_unit.js +44 -0
- package/test/dash/dash_parser_manifest_unit.js +0 -24
- package/test/dash/dash_parser_segment_template_unit.js +3 -4
- package/test/demo/demo_unit.js +2 -1
- package/test/hls/hls_live_unit.js +99 -220
- package/test/hls/hls_parser_unit.js +515 -432
- package/test/media/drm_engine_unit.js +86 -120
- package/test/media/media_source_engine_integration.js +26 -3
- package/test/media/media_source_engine_unit.js +7 -6
- package/test/media/playhead_unit.js +27 -191
- package/test/media/segment_index_unit.js +15 -25
- package/test/media/streaming_engine_integration.js +4 -39
- package/test/media/streaming_engine_unit.js +3 -2
- package/test/media/time_ranges_utils_unit.js +0 -5
- package/test/offline/manifest_convert_unit.js +34 -4
- package/test/offline/offline_manifest_parser_unit.js +1 -0
- package/test/offline/storage_integration.js +5 -4
- package/test/player_external.js +0 -6
- package/test/player_integration.js +16 -0
- package/test/player_unit.js +26 -0
- package/test/test/util/fake_media_source_engine.js +11 -4
- package/test/test/util/manifest_generator.js +3 -1
- package/test/test/util/manifest_parser_util.js +4 -1
- package/test/test/util/offline_utils.js +1 -0
- package/test/test/util/streaming_engine_util.js +1 -0
- package/test/test/util/test_scheme.js +24 -1
- package/test/test/util/util.js +4 -4
- package/test/text/cue_integration.js +2 -2
- package/test/text/lrc_text_parser_unit.js +6 -7
- package/test/text/mp4_ttml_parser_unit.js +6 -4
- package/test/text/mp4_vtt_parser_unit.js +6 -5
- package/test/text/sbv_text_parser_unit.js +5 -6
- package/test/text/srt_text_parser_unit.js +5 -6
- package/test/text/ssa_text_parser_unit.js +17 -29
- package/test/text/text_engine_unit.js +45 -5
- package/test/text/ttml_text_parser_unit.js +77 -77
- package/test/text/vtt_text_parser_unit.js +55 -57
- package/test/ui/ui_integration.js +0 -16
- package/test/ui/ui_unit.js +27 -0
- package/test/util/cmcd_manager_unit.js +3 -0
- package/test/util/stream_utils_unit.js +23 -7
- package/ui/controls.js +65 -40
- package/ui/fullscreen_button.js +26 -6
- package/ui/less/containers.less +3 -3
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +5 -0
- package/ui/resolution_selection.js +31 -33
- package/ui/ui.js +0 -17
- package/docs/tutorials/upgrade-v2-5.md +0 -441
- package/docs/tutorials/upgrade-v3.md +0 -38
- package/lib/polyfill/mathround.js +0 -49
- package/lib/polyfill/patchedmediakeys_apple.js +0 -744
- package/lib/polyfill/patchedmediakeys_ms.js +0 -698
- package/lib/util/mutex.js +0 -52
- package/test/util/functional_unit.js +0 -82
|
@@ -693,22 +693,6 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
693
693
|
expect(iterator.current()).toBe(null);
|
|
694
694
|
});
|
|
695
695
|
|
|
696
|
-
describe('seek', () => {
|
|
697
|
-
it('returns the matching segment', () => {
|
|
698
|
-
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
699
|
-
const iterator = index[Symbol.iterator]();
|
|
700
|
-
expect(iterator.seek(10)).toBe(inputRefs[1]);
|
|
701
|
-
expect(iterator.current()).toBe(inputRefs[1]);
|
|
702
|
-
});
|
|
703
|
-
|
|
704
|
-
it('returns the matching segment with partial segments', () => {
|
|
705
|
-
const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
|
|
706
|
-
const iterator = index[Symbol.iterator]();
|
|
707
|
-
expect(iterator.seek(8)).toBe(inputRefsWithPartial[0]);
|
|
708
|
-
expect(iterator.seek(10)).toBe(partialRefs1[0]);
|
|
709
|
-
});
|
|
710
|
-
});
|
|
711
|
-
|
|
712
696
|
describe('next', () => {
|
|
713
697
|
it('starts with the first segment', () => {
|
|
714
698
|
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
@@ -725,20 +709,20 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
725
709
|
expect(iterator.next().value).toBe(null);
|
|
726
710
|
});
|
|
727
711
|
|
|
728
|
-
it('iterates
|
|
712
|
+
it('iterates from getIteratorForTime', () => {
|
|
729
713
|
const index = new shaka.media.SegmentIndex(inputRefs);
|
|
730
|
-
const iterator = index
|
|
731
|
-
expect(iterator.
|
|
714
|
+
const iterator = index.getIteratorForTime(10);
|
|
715
|
+
expect(iterator.next().value).toBe(inputRefs[1]);
|
|
732
716
|
expect(iterator.current()).toBe(inputRefs[1]);
|
|
733
717
|
expect(iterator.next().value).toBe(inputRefs[2]);
|
|
734
718
|
expect(iterator.current()).toBe(inputRefs[2]);
|
|
735
719
|
expect(iterator.next().value).toBe(null);
|
|
736
720
|
});
|
|
737
721
|
|
|
738
|
-
it('iterates
|
|
722
|
+
it('iterates from getIteratorForTime with partial segments', () => {
|
|
739
723
|
const index = new shaka.media.SegmentIndex(inputRefsWithPartial);
|
|
740
|
-
const iterator = index
|
|
741
|
-
expect(iterator.
|
|
724
|
+
const iterator = index.getIteratorForTime(10);
|
|
725
|
+
expect(iterator.next().value).toBe(partialRefs1[0]);
|
|
742
726
|
expect(iterator.current()).toBe(partialRefs1[0]);
|
|
743
727
|
expect(iterator.next().value).toBe(partialRefs1[1]);
|
|
744
728
|
expect(iterator.current()).toBe(partialRefs1[1]);
|
|
@@ -935,11 +919,17 @@ describe('SegmentIndex', /** @suppress {accessControls} */ () => {
|
|
|
935
919
|
expect(Array.from(metaIndex)).toEqual(oldRefs);
|
|
936
920
|
|
|
937
921
|
// Every 0.1 seconds, return the next new ref.
|
|
938
|
-
|
|
939
|
-
|
|
922
|
+
const done = new Promise((resolve, reject) => {
|
|
923
|
+
index1.updateEvery(0.1, () => {
|
|
924
|
+
if (newRefs.length == 0) {
|
|
925
|
+
resolve();
|
|
926
|
+
}
|
|
927
|
+
return [newRefs.shift()];
|
|
928
|
+
});
|
|
940
929
|
});
|
|
941
930
|
// Wait long enough for all three new refs to be appended.
|
|
942
|
-
|
|
931
|
+
// Or for all of the new refs to be passed out.
|
|
932
|
+
await Promise.race([shaka.test.Util.delay(1), done]);
|
|
943
933
|
|
|
944
934
|
expect(Array.from(metaIndex)).toEqual(oldRefs.concat(inputRefs2));
|
|
945
935
|
});
|
|
@@ -214,8 +214,7 @@ describe('StreamingEngine', () => {
|
|
|
214
214
|
manifest,
|
|
215
215
|
config,
|
|
216
216
|
/* startTime= */ null,
|
|
217
|
-
onSeek
|
|
218
|
-
shaka.test.Util.spyFunc(onEvent));
|
|
217
|
+
onSeek);
|
|
219
218
|
}
|
|
220
219
|
|
|
221
220
|
function setupManifest(
|
|
@@ -403,7 +402,6 @@ describe('StreamingEngine', () => {
|
|
|
403
402
|
// TODO: Consider also adding tests for missing frames.
|
|
404
403
|
describe('gap jumping', () => {
|
|
405
404
|
it('jumps small gaps at the beginning', async () => {
|
|
406
|
-
config.smallGapLimit = 5;
|
|
407
405
|
await setupGappyContent(/* gapAtStart= */ 1, /* dropSegment= */ false);
|
|
408
406
|
|
|
409
407
|
// Let's go!
|
|
@@ -419,8 +417,6 @@ describe('StreamingEngine', () => {
|
|
|
419
417
|
});
|
|
420
418
|
|
|
421
419
|
it('jumps large gaps at the beginning', async () => {
|
|
422
|
-
config.smallGapLimit = 1;
|
|
423
|
-
config.jumpLargeGaps = true;
|
|
424
420
|
await setupGappyContent(/* gapAtStart= */ 5, /* dropSegment= */ false);
|
|
425
421
|
|
|
426
422
|
// Let's go!
|
|
@@ -436,7 +432,6 @@ describe('StreamingEngine', () => {
|
|
|
436
432
|
});
|
|
437
433
|
|
|
438
434
|
it('jumps small gaps in the middle', async () => {
|
|
439
|
-
config.smallGapLimit = 20;
|
|
440
435
|
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
441
436
|
|
|
442
437
|
// Let's go!
|
|
@@ -451,11 +446,9 @@ describe('StreamingEngine', () => {
|
|
|
451
446
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
452
447
|
// Should be close enough to still have the gap buffered.
|
|
453
448
|
expect(video.buffered.length).toBe(2);
|
|
454
|
-
expect(onEvent).not.toHaveBeenCalled();
|
|
455
449
|
});
|
|
456
450
|
|
|
457
451
|
it('jumps large gaps in the middle', async () => {
|
|
458
|
-
config.jumpLargeGaps = true;
|
|
459
452
|
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
460
453
|
|
|
461
454
|
// Let's go!
|
|
@@ -470,37 +463,6 @@ describe('StreamingEngine', () => {
|
|
|
470
463
|
await waiter.timeoutAfter(60).waitUntilPlayheadReaches(video, 23);
|
|
471
464
|
// Should be close enough to still have the gap buffered.
|
|
472
465
|
expect(video.buffered.length).toBe(2);
|
|
473
|
-
expect(onEvent).toHaveBeenCalled();
|
|
474
|
-
});
|
|
475
|
-
|
|
476
|
-
it('won\'t jump large gaps with preventDefault()', async () => {
|
|
477
|
-
config.jumpLargeGaps = true;
|
|
478
|
-
await setupGappyContent(/* gapAtStart= */ 0, /* dropSegment= */ true);
|
|
479
|
-
|
|
480
|
-
onEvent.and.callFake((event) => {
|
|
481
|
-
event.preventDefault();
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
// Let's go!
|
|
485
|
-
streamingEngine.switchVariant(variant);
|
|
486
|
-
await streamingEngine.start();
|
|
487
|
-
|
|
488
|
-
await waiter.timeoutAfter(5).waitForEvent(video, 'loadeddata');
|
|
489
|
-
|
|
490
|
-
let seekCount = 0;
|
|
491
|
-
eventManager.listen(video, 'seeking', () => {
|
|
492
|
-
seekCount++;
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
video.currentTime = 8;
|
|
496
|
-
video.play();
|
|
497
|
-
|
|
498
|
-
await shaka.test.Util.delay(5);
|
|
499
|
-
|
|
500
|
-
// Edge somehow plays _into_ the gap, and Xbox One plays _through_ the
|
|
501
|
-
// gap. Just make sure _we_ don't jump the gap by seeking. One seek is
|
|
502
|
-
// required to start playback at time 8.
|
|
503
|
-
expect(seekCount).toBe(1);
|
|
504
466
|
});
|
|
505
467
|
|
|
506
468
|
/**
|
|
@@ -610,6 +572,7 @@ describe('StreamingEngine', () => {
|
|
|
610
572
|
minBufferTime: 2,
|
|
611
573
|
textStreams: [],
|
|
612
574
|
imageStreams: [],
|
|
575
|
+
sequenceMode: false,
|
|
613
576
|
variants: [{
|
|
614
577
|
id: 1,
|
|
615
578
|
video: {
|
|
@@ -622,6 +585,7 @@ describe('StreamingEngine', () => {
|
|
|
622
585
|
width: 600,
|
|
623
586
|
height: 400,
|
|
624
587
|
type: shaka.util.ManifestParserUtils.ContentType.VIDEO,
|
|
588
|
+
drmInfos: [],
|
|
625
589
|
},
|
|
626
590
|
audio: {
|
|
627
591
|
id: 3,
|
|
@@ -631,6 +595,7 @@ describe('StreamingEngine', () => {
|
|
|
631
595
|
codecs: 'mp4a.40.2',
|
|
632
596
|
bandwidth: 192000,
|
|
633
597
|
type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
|
|
598
|
+
drmInfos: [],
|
|
634
599
|
},
|
|
635
600
|
}],
|
|
636
601
|
};
|
|
@@ -496,7 +496,8 @@ describe('StreamingEngine', () => {
|
|
|
496
496
|
expectedMseInit.set(ContentType.VIDEO, videoStream);
|
|
497
497
|
expectedMseInit.set(ContentType.TEXT, textStream);
|
|
498
498
|
|
|
499
|
-
expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit,
|
|
499
|
+
expect(mediaSourceEngine.init).toHaveBeenCalledWith(expectedMseInit,
|
|
500
|
+
/** forceTransmuxTS= */ false, /** sequenceMode= */ false);
|
|
500
501
|
expect(mediaSourceEngine.init).toHaveBeenCalledTimes(1);
|
|
501
502
|
|
|
502
503
|
expect(mediaSourceEngine.setDuration).toHaveBeenCalledTimes(1);
|
|
@@ -801,7 +802,7 @@ describe('StreamingEngine', () => {
|
|
|
801
802
|
asymmetricMatch: (val) => val > 40 && val <= 40.1,
|
|
802
803
|
};
|
|
803
804
|
expect(mediaSourceEngine.setStreamProperties)
|
|
804
|
-
.toHaveBeenCalledWith('video', 0, lt20, gt40);
|
|
805
|
+
.toHaveBeenCalledWith('video', 0, lt20, gt40, false);
|
|
805
806
|
});
|
|
806
807
|
|
|
807
808
|
// Regression test for https://github.com/shaka-project/shaka-player/issues/3717
|
|
@@ -22,11 +22,6 @@ describe('TimeRangesUtils', () => {
|
|
|
22
22
|
expect(TimeRangesUtils.isBuffered(b, 13)).toBe(true);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
it('returns buffered when having a small gap', () => {
|
|
26
|
-
const b = createFakeBuffered([{start: 10, end: 20}]);
|
|
27
|
-
expect(TimeRangesUtils.isBuffered(b, 9, 1)).toBe(true);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
25
|
// Ranges: [10-20], [30-40], [50-60]
|
|
31
26
|
defineTest('returns false when before range', {time: 3, expected: false});
|
|
32
27
|
defineTest('returns true inside first range', {time: 12, expected: true});
|
|
@@ -107,6 +107,7 @@ describe('ManifestConverter', () => {
|
|
|
107
107
|
},
|
|
108
108
|
appMetadata: null,
|
|
109
109
|
creationTime: 0,
|
|
110
|
+
sequenceMode: false,
|
|
110
111
|
};
|
|
111
112
|
|
|
112
113
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -143,6 +144,7 @@ describe('ManifestConverter', () => {
|
|
|
143
144
|
createVideoStreamDB(1, [0]),
|
|
144
145
|
createVideoStreamDB(2, [1]),
|
|
145
146
|
],
|
|
147
|
+
sequenceMode: false,
|
|
146
148
|
};
|
|
147
149
|
|
|
148
150
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -170,6 +172,7 @@ describe('ManifestConverter', () => {
|
|
|
170
172
|
createAudioStreamDB(1, [0]),
|
|
171
173
|
createAudioStreamDB(2, [1]),
|
|
172
174
|
],
|
|
175
|
+
sequenceMode: false,
|
|
173
176
|
};
|
|
174
177
|
|
|
175
178
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -182,6 +185,29 @@ describe('ManifestConverter', () => {
|
|
|
182
185
|
expect(manifest.variants[1].video).toBe(null);
|
|
183
186
|
});
|
|
184
187
|
|
|
188
|
+
it('supports containerless content', () => {
|
|
189
|
+
/** @type {shaka.extern.ManifestDB} */
|
|
190
|
+
const manifestDb = {
|
|
191
|
+
originalManifestUri: 'http://example.com/foo',
|
|
192
|
+
duration: 60,
|
|
193
|
+
size: 1234,
|
|
194
|
+
expiration: Infinity,
|
|
195
|
+
sessionIds: [],
|
|
196
|
+
drmInfo: null,
|
|
197
|
+
appMetadata: null,
|
|
198
|
+
creationTime: 0,
|
|
199
|
+
streams: [
|
|
200
|
+
createVideoStreamDB(1, [0]),
|
|
201
|
+
createAudioStreamDB(2, [0]),
|
|
202
|
+
],
|
|
203
|
+
sequenceMode: true,
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
207
|
+
expect(manifest.sequenceMode).toBe(true);
|
|
208
|
+
expect(manifest.variants.length).toBe(1);
|
|
209
|
+
});
|
|
210
|
+
|
|
185
211
|
it('supports text streams', () => {
|
|
186
212
|
/** @type {shaka.extern.ManifestDB} */
|
|
187
213
|
const manifestDb = {
|
|
@@ -197,6 +223,7 @@ describe('ManifestConverter', () => {
|
|
|
197
223
|
createVideoStreamDB(1, [0]),
|
|
198
224
|
createTextStreamDB(2),
|
|
199
225
|
],
|
|
226
|
+
sequenceMode: false,
|
|
200
227
|
};
|
|
201
228
|
|
|
202
229
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -235,6 +262,7 @@ describe('ManifestConverter', () => {
|
|
|
235
262
|
createVideoStreamDB(video1, [variant1]),
|
|
236
263
|
createVideoStreamDB(video2, [variant2, variant3]),
|
|
237
264
|
],
|
|
265
|
+
sequenceMode: false,
|
|
238
266
|
};
|
|
239
267
|
|
|
240
268
|
const manifest = createConverter().fromManifestDB(manifestDb);
|
|
@@ -509,8 +537,6 @@ describe('ManifestConverter', () => {
|
|
|
509
537
|
|
|
510
538
|
// Assume that we don't have to call createSegmentIndex.
|
|
511
539
|
|
|
512
|
-
const iterator = stream.segmentIndex[Symbol.iterator]();
|
|
513
|
-
|
|
514
540
|
streamDb.segments.forEach((segmentDb, i) => {
|
|
515
541
|
const uri = shaka.offline.OfflineUri.segment(
|
|
516
542
|
'mechanism', 'cell', segmentDb.dataKey);
|
|
@@ -520,10 +546,14 @@ describe('ManifestConverter', () => {
|
|
|
520
546
|
null;
|
|
521
547
|
|
|
522
548
|
/** @type {shaka.media.SegmentReference} */
|
|
523
|
-
const segment =
|
|
549
|
+
const segment =
|
|
550
|
+
stream.segmentIndex
|
|
551
|
+
.getIteratorForTime(segmentDb.startTime).next().value;
|
|
524
552
|
|
|
525
553
|
/** @type {shaka.media.SegmentReference} */
|
|
526
|
-
const sameSegment =
|
|
554
|
+
const sameSegment =
|
|
555
|
+
stream.segmentIndex
|
|
556
|
+
.getIteratorForTime(segmentDb.endTime - 0.1).next().value;
|
|
527
557
|
|
|
528
558
|
expect(segment).toBe(sameSegment);
|
|
529
559
|
expect(segment.startTime).toBe(segmentDb.startTime);
|
|
@@ -1110,10 +1110,7 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1110
1110
|
aRequestIsStarted.resolve();
|
|
1111
1111
|
await promise;
|
|
1112
1112
|
|
|
1113
|
-
|
|
1114
|
-
// and will be downloaded sequentially. Thus, we expect only the first
|
|
1115
|
-
// download to be aborted.
|
|
1116
|
-
expect(abortCheck()).toBe(i == 0 ? true : false);
|
|
1113
|
+
expect(abortCheck()).toBe(true);
|
|
1117
1114
|
|
|
1118
1115
|
return new ArrayBuffer(16);
|
|
1119
1116
|
});
|
|
@@ -1355,6 +1352,8 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1355
1352
|
pixelAspectRatio: '59:54',
|
|
1356
1353
|
hdr: null,
|
|
1357
1354
|
mimeType: 'video/mp4,audio/mp4',
|
|
1355
|
+
audioMimeType: 'audio/mp4',
|
|
1356
|
+
videoMimeType: 'video/mp4',
|
|
1358
1357
|
codecs: 'mp4,mp4',
|
|
1359
1358
|
audioCodec: 'mp4',
|
|
1360
1359
|
videoCodec: 'mp4',
|
|
@@ -1397,6 +1396,8 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1397
1396
|
pixelAspectRatio: null,
|
|
1398
1397
|
hdr: null,
|
|
1399
1398
|
mimeType: 'text/vtt',
|
|
1399
|
+
audioMimeType: null,
|
|
1400
|
+
videoMimeType: null,
|
|
1400
1401
|
codecs: 'vtt',
|
|
1401
1402
|
audioCodec: null,
|
|
1402
1403
|
videoCodec: null,
|
package/test/player_external.js
CHANGED
|
@@ -107,12 +107,6 @@ describe('Player', () => {
|
|
|
107
107
|
player.configure('manifest.dash.clockSyncUri',
|
|
108
108
|
'https://shaka-player-demo.appspot.com/time.txt');
|
|
109
109
|
|
|
110
|
-
// Make sure we don't get stuck on gaps that only appear in some
|
|
111
|
-
// browsers (Safari, Firefox).
|
|
112
|
-
// TODO(https://github.com/shaka-project/shaka-player/issues/1702):
|
|
113
|
-
// Is this necessary because of a bug in Shaka Player?
|
|
114
|
-
player.configure('streaming.jumpLargeGaps', true);
|
|
115
|
-
|
|
116
110
|
// Add asset-specific configuration.
|
|
117
111
|
player.configure(asset.getConfiguration());
|
|
118
112
|
|
|
@@ -418,6 +418,22 @@ describe('Player', () => {
|
|
|
418
418
|
expect(video.playbackRate).toBe(1);
|
|
419
419
|
});
|
|
420
420
|
|
|
421
|
+
it('in sequence mode', async () => {
|
|
422
|
+
const testSchemeMimeType = 'application/x-test-manifest';
|
|
423
|
+
player = new compiledShaka.Player(video);
|
|
424
|
+
await player.load('test:sintel_sequence_compiled', 0, testSchemeMimeType);
|
|
425
|
+
expect(player.getManifest().sequenceMode).toBe(true);
|
|
426
|
+
|
|
427
|
+
// Ensure the video plays.
|
|
428
|
+
video.play();
|
|
429
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 5, 10);
|
|
430
|
+
|
|
431
|
+
// Seek the video, and see if it can continue playing from that point.
|
|
432
|
+
video.currentTime = 20;
|
|
433
|
+
// Expect that we can then reach the end of the video.
|
|
434
|
+
await waiter.timeoutAfter(20).waitForEnd(video);
|
|
435
|
+
});
|
|
436
|
+
|
|
421
437
|
// Regression test for #2326.
|
|
422
438
|
//
|
|
423
439
|
// 1. Construct an instance with a video element.
|
package/test/player_unit.js
CHANGED
|
@@ -116,6 +116,8 @@ describe('Player', () => {
|
|
|
116
116
|
jasmine.createSpy('destroy').and.returnValue(Promise.resolve()),
|
|
117
117
|
setUseEmbeddedText: jasmine.createSpy('setUseEmbeddedText'),
|
|
118
118
|
getUseEmbeddedText: jasmine.createSpy('getUseEmbeddedText'),
|
|
119
|
+
setSegmentRelativeVttTiming:
|
|
120
|
+
jasmine.createSpy('setSegmentRelativeVttTiming'),
|
|
119
121
|
getTextDisplayer: () => textDisplayer,
|
|
120
122
|
ended: jasmine.createSpy('ended').and.returnValue(false),
|
|
121
123
|
};
|
|
@@ -1130,6 +1132,8 @@ describe('Player', () => {
|
|
|
1130
1132
|
pixelAspectRatio: '59:54',
|
|
1131
1133
|
hdr: null,
|
|
1132
1134
|
mimeType: 'video/mp4',
|
|
1135
|
+
audioMimeType: 'audio/mp4',
|
|
1136
|
+
videoMimeType: 'video/mp4',
|
|
1133
1137
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1134
1138
|
audioCodec: 'mp4a.40.2',
|
|
1135
1139
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1164,6 +1168,8 @@ describe('Player', () => {
|
|
|
1164
1168
|
pixelAspectRatio: '59:54',
|
|
1165
1169
|
hdr: null,
|
|
1166
1170
|
mimeType: 'video/mp4',
|
|
1171
|
+
audioMimeType: 'audio/mp4',
|
|
1172
|
+
videoMimeType: 'video/mp4',
|
|
1167
1173
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1168
1174
|
audioCodec: 'mp4a.40.2',
|
|
1169
1175
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1198,6 +1204,8 @@ describe('Player', () => {
|
|
|
1198
1204
|
pixelAspectRatio: '59:54',
|
|
1199
1205
|
hdr: null,
|
|
1200
1206
|
mimeType: 'video/mp4',
|
|
1207
|
+
audioMimeType: 'audio/mp4',
|
|
1208
|
+
videoMimeType: 'video/mp4',
|
|
1201
1209
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1202
1210
|
audioCodec: 'mp4a.40.2',
|
|
1203
1211
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1232,6 +1240,8 @@ describe('Player', () => {
|
|
|
1232
1240
|
pixelAspectRatio: '59:54',
|
|
1233
1241
|
hdr: null,
|
|
1234
1242
|
mimeType: 'video/mp4',
|
|
1243
|
+
audioMimeType: 'audio/mp4',
|
|
1244
|
+
videoMimeType: 'video/mp4',
|
|
1235
1245
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1236
1246
|
audioCodec: 'mp4a.40.2',
|
|
1237
1247
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1266,6 +1276,8 @@ describe('Player', () => {
|
|
|
1266
1276
|
pixelAspectRatio: '59:54',
|
|
1267
1277
|
hdr: null,
|
|
1268
1278
|
mimeType: 'video/mp4',
|
|
1279
|
+
audioMimeType: 'audio/mp4',
|
|
1280
|
+
videoMimeType: 'video/mp4',
|
|
1269
1281
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1270
1282
|
audioCodec: 'mp4a.40.2',
|
|
1271
1283
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1300,6 +1312,8 @@ describe('Player', () => {
|
|
|
1300
1312
|
pixelAspectRatio: '59:54',
|
|
1301
1313
|
hdr: null,
|
|
1302
1314
|
mimeType: 'video/mp4',
|
|
1315
|
+
audioMimeType: 'audio/mp4',
|
|
1316
|
+
videoMimeType: 'video/mp4',
|
|
1303
1317
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1304
1318
|
audioCodec: 'mp4a.40.2',
|
|
1305
1319
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1334,6 +1348,8 @@ describe('Player', () => {
|
|
|
1334
1348
|
pixelAspectRatio: '59:54',
|
|
1335
1349
|
hdr: null,
|
|
1336
1350
|
mimeType: 'video/mp4',
|
|
1351
|
+
audioMimeType: 'audio/mp4',
|
|
1352
|
+
videoMimeType: 'video/mp4',
|
|
1337
1353
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1338
1354
|
audioCodec: 'mp4a.40.2',
|
|
1339
1355
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1368,6 +1384,8 @@ describe('Player', () => {
|
|
|
1368
1384
|
pixelAspectRatio: '59:54',
|
|
1369
1385
|
hdr: null,
|
|
1370
1386
|
mimeType: 'video/mp4',
|
|
1387
|
+
audioMimeType: 'audio/mp4',
|
|
1388
|
+
videoMimeType: 'video/mp4',
|
|
1371
1389
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1372
1390
|
audioCodec: 'mp4a.40.2',
|
|
1373
1391
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1399,6 +1417,8 @@ describe('Player', () => {
|
|
|
1399
1417
|
label: 'Spanish',
|
|
1400
1418
|
kind: 'caption',
|
|
1401
1419
|
mimeType: 'text/vtt',
|
|
1420
|
+
audioMimeType: null,
|
|
1421
|
+
videoMimeType: null,
|
|
1402
1422
|
codecs: null,
|
|
1403
1423
|
audioCodec: null,
|
|
1404
1424
|
videoCodec: null,
|
|
@@ -1433,6 +1453,8 @@ describe('Player', () => {
|
|
|
1433
1453
|
label: 'English',
|
|
1434
1454
|
kind: 'caption',
|
|
1435
1455
|
mimeType: 'application/ttml+xml',
|
|
1456
|
+
audioMimeType: null,
|
|
1457
|
+
videoMimeType: null,
|
|
1436
1458
|
codecs: null,
|
|
1437
1459
|
audioCodec: null,
|
|
1438
1460
|
videoCodec: null,
|
|
@@ -1467,6 +1489,8 @@ describe('Player', () => {
|
|
|
1467
1489
|
label: 'English',
|
|
1468
1490
|
kind: 'caption',
|
|
1469
1491
|
mimeType: 'application/ttml+xml',
|
|
1492
|
+
audioMimeType: null,
|
|
1493
|
+
videoMimeType: null,
|
|
1470
1494
|
codecs: null,
|
|
1471
1495
|
audioCodec: null,
|
|
1472
1496
|
videoCodec: null,
|
|
@@ -1504,6 +1528,8 @@ describe('Player', () => {
|
|
|
1504
1528
|
label: null,
|
|
1505
1529
|
kind: null,
|
|
1506
1530
|
mimeType: 'image/jpeg',
|
|
1531
|
+
audioMimeType: null,
|
|
1532
|
+
videoMimeType: null,
|
|
1507
1533
|
codecs: null,
|
|
1508
1534
|
audioCodec: null,
|
|
1509
1535
|
videoCodec: null,
|
|
@@ -107,8 +107,8 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
107
107
|
|
|
108
108
|
/** @type {!jasmine.Spy} */
|
|
109
109
|
this.setStreamProperties = jasmine.createSpy('setStreamProperties')
|
|
110
|
-
.and.callFake((type, offset, end) =>
|
|
111
|
-
this.setStreamPropertiesImpl_(type, offset, end));
|
|
110
|
+
.and.callFake((type, offset, end, sequenceMode) =>
|
|
111
|
+
this.setStreamPropertiesImpl_(type, offset, end, sequenceMode));
|
|
112
112
|
|
|
113
113
|
/** @type {!jasmine.Spy} */
|
|
114
114
|
this.remove = jasmine.createSpy('remove')
|
|
@@ -125,6 +125,10 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
125
125
|
this.getTextDisplayer =
|
|
126
126
|
jasmine.createSpy('getTextDisplayer')
|
|
127
127
|
.and.returnValue(new shaka.test.FakeTextDisplayer());
|
|
128
|
+
|
|
129
|
+
/** @type {!jasmine.Spy} */
|
|
130
|
+
this.setSegmentRelativeVttTiming =
|
|
131
|
+
jasmine.createSpy('setSegmentRelativeVttTiming').and.stub();
|
|
128
132
|
}
|
|
129
133
|
|
|
130
134
|
/** @override */
|
|
@@ -355,14 +359,17 @@ shaka.test.FakeMediaSourceEngine = class {
|
|
|
355
359
|
* @param {string} type
|
|
356
360
|
* @param {number} offset
|
|
357
361
|
* @param {number} appendWindowEnd
|
|
362
|
+
* @param {boolean} sequenceMode
|
|
358
363
|
* @return {!Promise}
|
|
359
364
|
* @private
|
|
360
365
|
*/
|
|
361
|
-
setStreamPropertiesImpl_(type, offset, appendWindowEnd) {
|
|
366
|
+
setStreamPropertiesImpl_(type, offset, appendWindowEnd, sequenceMode) {
|
|
362
367
|
if (!this.segments[type]) {
|
|
363
368
|
throw new Error('unexpected type');
|
|
364
369
|
}
|
|
365
|
-
|
|
370
|
+
if (!sequenceMode) {
|
|
371
|
+
this.timestampOffsets_[type] = offset;
|
|
372
|
+
}
|
|
366
373
|
// Don't use |appendWindowEnd|.
|
|
367
374
|
return Promise.resolve();
|
|
368
375
|
}
|
|
@@ -95,6 +95,8 @@ shaka.test.ManifestGenerator.Manifest = class {
|
|
|
95
95
|
this.offlineSessionIds = [];
|
|
96
96
|
/** @type {number} */
|
|
97
97
|
this.minBufferTime = 0;
|
|
98
|
+
/** @type {boolean} */
|
|
99
|
+
this.sequenceMode = false;
|
|
98
100
|
|
|
99
101
|
/** @type {shaka.extern.Manifest} */
|
|
100
102
|
const foo = this;
|
|
@@ -421,7 +423,7 @@ shaka.test.ManifestGenerator.DrmInfo = class {
|
|
|
421
423
|
if (!this.initData) {
|
|
422
424
|
this.initData = [];
|
|
423
425
|
}
|
|
424
|
-
this.initData.push({initData: buffer, initDataType: type
|
|
426
|
+
this.initData.push({initData: buffer, initDataType: type});
|
|
425
427
|
}
|
|
426
428
|
|
|
427
429
|
/**
|
|
@@ -51,11 +51,12 @@ shaka.test.ManifestParser = class {
|
|
|
51
51
|
* @param {number=} timestampOffset
|
|
52
52
|
* @param {!Array.<!shaka.media.SegmentReference>=} partialReferences
|
|
53
53
|
* @param {?string=} tilesLayout
|
|
54
|
+
* @param {?number=} syncTime
|
|
54
55
|
* @return {!shaka.media.SegmentReference}
|
|
55
56
|
*/
|
|
56
57
|
static makeReference(uri, start, end, baseUri = '',
|
|
57
58
|
startByte = 0, endByte = null, timestampOffset = 0,
|
|
58
|
-
partialReferences = [], tilesLayout = '') {
|
|
59
|
+
partialReferences = [], tilesLayout = '', syncTime = null) {
|
|
59
60
|
const getUris = () => uri.length ? [baseUri + uri] : [];
|
|
60
61
|
|
|
61
62
|
// If a test wants to verify these, they can be set explicitly after
|
|
@@ -80,6 +81,8 @@ shaka.test.ManifestParser = class {
|
|
|
80
81
|
appendWindowEnd,
|
|
81
82
|
partialReferences,
|
|
82
83
|
tilesLayout,
|
|
84
|
+
/* tileDuration= */ undefined,
|
|
85
|
+
syncTime,
|
|
83
86
|
);
|
|
84
87
|
}
|
|
85
88
|
};
|