shaka-player 3.3.5 → 4.0.2
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/config.yml +1 -0
- package/.github/workflows/demo-version-index.yaml +8 -0
- package/.github/workflows/release-please.yaml +18 -2
- 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 +215 -41
- package/CONTRIBUTORS +1 -0
- package/README.md +14 -11
- 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/checkversion.py +1 -1
- package/build/compiler.py +1 -1
- package/build/misspellings.txt +1 -0
- package/build/shaka-lab.yaml +0 -2
- 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.less +0 -1
- 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 +3 -3
- package/dist/controls.css.map +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 +17 -20
- package/dist/locales.js +33 -31
- 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 +311 -314
- package/dist/shaka-player.compiled.debug.d.ts +311 -314
- package/dist/shaka-player.compiled.debug.externs.js +126 -126
- package/dist/shaka-player.compiled.debug.js +430 -484
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +126 -126
- package/dist/shaka-player.compiled.js +829 -845
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +357 -358
- package/dist/shaka-player.ui.debug.d.ts +357 -358
- package/dist/shaka-player.ui.debug.externs.js +134 -126
- package/dist/shaka-player.ui.debug.js +489 -541
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +134 -126
- package/dist/shaka-player.ui.js +988 -1000
- 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 +85 -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 -21
- package/externs/shaka/text.js +12 -12
- package/externs/sourcebuffer.js +15 -0
- package/lib/abr/simple_abr_manager.js +2 -1
- 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 -0
- package/lib/hls/hls_parser.js +390 -747
- package/lib/hls/manifest_text_parser.js +2 -3
- package/lib/media/drm_engine.js +105 -37
- package/lib/media/gap_jumping_controller.js +10 -45
- package/lib/media/media_source_engine.js +150 -30
- 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 +28 -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 +8 -41
- 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 +27 -5
- 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 +16 -5
- package/lib/util/platform.js +45 -0
- package/lib/util/player_configuration.js +17 -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 +5 -2
- package/roadmap.md +19 -19
- package/shaka-player.uncompiled.js +0 -3
- package/test/dash/dash_parser_content_protection_unit.js +44 -0
- 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 +155 -230
- 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 +25 -3
- package/test/media/media_source_engine_unit.js +3 -2
- package/test/media/playhead_unit.js +27 -191
- package/test/media/segment_index_unit.js +15 -25
- package/test/media/streaming_engine_integration.js +2 -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 +116 -59
- 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 +4 -4
- package/ui/less/general.less +1 -1
- package/ui/less/range_elements.less +1 -0
- 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/.github/pull_request_template.md +0 -10
- 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/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: {
|
|
@@ -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
|
};
|
|
@@ -1137,6 +1139,8 @@ describe('Player', () => {
|
|
|
1137
1139
|
pixelAspectRatio: '59:54',
|
|
1138
1140
|
hdr: null,
|
|
1139
1141
|
mimeType: 'video/mp4',
|
|
1142
|
+
audioMimeType: 'audio/mp4',
|
|
1143
|
+
videoMimeType: 'video/mp4',
|
|
1140
1144
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1141
1145
|
audioCodec: 'mp4a.40.2',
|
|
1142
1146
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1171,6 +1175,8 @@ describe('Player', () => {
|
|
|
1171
1175
|
pixelAspectRatio: '59:54',
|
|
1172
1176
|
hdr: null,
|
|
1173
1177
|
mimeType: 'video/mp4',
|
|
1178
|
+
audioMimeType: 'audio/mp4',
|
|
1179
|
+
videoMimeType: 'video/mp4',
|
|
1174
1180
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1175
1181
|
audioCodec: 'mp4a.40.2',
|
|
1176
1182
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1205,6 +1211,8 @@ describe('Player', () => {
|
|
|
1205
1211
|
pixelAspectRatio: '59:54',
|
|
1206
1212
|
hdr: null,
|
|
1207
1213
|
mimeType: 'video/mp4',
|
|
1214
|
+
audioMimeType: 'audio/mp4',
|
|
1215
|
+
videoMimeType: 'video/mp4',
|
|
1208
1216
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1209
1217
|
audioCodec: 'mp4a.40.2',
|
|
1210
1218
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1239,6 +1247,8 @@ describe('Player', () => {
|
|
|
1239
1247
|
pixelAspectRatio: '59:54',
|
|
1240
1248
|
hdr: null,
|
|
1241
1249
|
mimeType: 'video/mp4',
|
|
1250
|
+
audioMimeType: 'audio/mp4',
|
|
1251
|
+
videoMimeType: 'video/mp4',
|
|
1242
1252
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1243
1253
|
audioCodec: 'mp4a.40.2',
|
|
1244
1254
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1273,6 +1283,8 @@ describe('Player', () => {
|
|
|
1273
1283
|
pixelAspectRatio: '59:54',
|
|
1274
1284
|
hdr: null,
|
|
1275
1285
|
mimeType: 'video/mp4',
|
|
1286
|
+
audioMimeType: 'audio/mp4',
|
|
1287
|
+
videoMimeType: 'video/mp4',
|
|
1276
1288
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1277
1289
|
audioCodec: 'mp4a.40.2',
|
|
1278
1290
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1307,6 +1319,8 @@ describe('Player', () => {
|
|
|
1307
1319
|
pixelAspectRatio: '59:54',
|
|
1308
1320
|
hdr: null,
|
|
1309
1321
|
mimeType: 'video/mp4',
|
|
1322
|
+
audioMimeType: 'audio/mp4',
|
|
1323
|
+
videoMimeType: 'video/mp4',
|
|
1310
1324
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1311
1325
|
audioCodec: 'mp4a.40.2',
|
|
1312
1326
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1341,6 +1355,8 @@ describe('Player', () => {
|
|
|
1341
1355
|
pixelAspectRatio: '59:54',
|
|
1342
1356
|
hdr: null,
|
|
1343
1357
|
mimeType: 'video/mp4',
|
|
1358
|
+
audioMimeType: 'audio/mp4',
|
|
1359
|
+
videoMimeType: 'video/mp4',
|
|
1344
1360
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1345
1361
|
audioCodec: 'mp4a.40.2',
|
|
1346
1362
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1375,6 +1391,8 @@ describe('Player', () => {
|
|
|
1375
1391
|
pixelAspectRatio: '59:54',
|
|
1376
1392
|
hdr: null,
|
|
1377
1393
|
mimeType: 'video/mp4',
|
|
1394
|
+
audioMimeType: 'audio/mp4',
|
|
1395
|
+
videoMimeType: 'video/mp4',
|
|
1378
1396
|
codecs: 'avc1.4d401f, mp4a.40.2',
|
|
1379
1397
|
audioCodec: 'mp4a.40.2',
|
|
1380
1398
|
videoCodec: 'avc1.4d401f',
|
|
@@ -1406,6 +1424,8 @@ describe('Player', () => {
|
|
|
1406
1424
|
label: 'Spanish',
|
|
1407
1425
|
kind: 'caption',
|
|
1408
1426
|
mimeType: 'text/vtt',
|
|
1427
|
+
audioMimeType: null,
|
|
1428
|
+
videoMimeType: null,
|
|
1409
1429
|
codecs: null,
|
|
1410
1430
|
audioCodec: null,
|
|
1411
1431
|
videoCodec: null,
|
|
@@ -1440,6 +1460,8 @@ describe('Player', () => {
|
|
|
1440
1460
|
label: 'English',
|
|
1441
1461
|
kind: 'caption',
|
|
1442
1462
|
mimeType: 'application/ttml+xml',
|
|
1463
|
+
audioMimeType: null,
|
|
1464
|
+
videoMimeType: null,
|
|
1443
1465
|
codecs: null,
|
|
1444
1466
|
audioCodec: null,
|
|
1445
1467
|
videoCodec: null,
|
|
@@ -1474,6 +1496,8 @@ describe('Player', () => {
|
|
|
1474
1496
|
label: 'English',
|
|
1475
1497
|
kind: 'caption',
|
|
1476
1498
|
mimeType: 'application/ttml+xml',
|
|
1499
|
+
audioMimeType: null,
|
|
1500
|
+
videoMimeType: null,
|
|
1477
1501
|
codecs: null,
|
|
1478
1502
|
audioCodec: null,
|
|
1479
1503
|
videoCodec: null,
|
|
@@ -1511,6 +1535,8 @@ describe('Player', () => {
|
|
|
1511
1535
|
label: null,
|
|
1512
1536
|
kind: null,
|
|
1513
1537
|
mimeType: 'image/jpeg',
|
|
1538
|
+
audioMimeType: null,
|
|
1539
|
+
videoMimeType: null,
|
|
1514
1540
|
codecs: null,
|
|
1515
1541
|
audioCodec: null,
|
|
1516
1542
|
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
|
};
|