shaka-player 3.1.4 → 3.3.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/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
- package/.github/ISSUE_TEMPLATE/question.md +1 -1
- package/AUTHORS +6 -5
- package/CHANGELOG.md +363 -0
- package/CONTRIBUTORS +4 -2
- package/README.md +4 -4
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +2 -0
- package/build/types/ui +2 -0
- package/demo/common/asset.js +9 -7
- package/demo/common/assets.js +28 -1
- package/demo/common/message_ids.js +15 -2
- package/demo/config.js +35 -2
- package/demo/index.html +1 -1
- package/demo/locales/en.json +14 -1
- package/demo/locales/source.json +56 -4
- package/demo/main.js +2 -1
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +24 -21
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +24 -21
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +33 -25
- package/dist/locales.js +31 -29
- package/dist/receiver.compiled.debug.js +14 -12
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +14 -12
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.d.ts +258 -20
- package/dist/shaka-player.compiled.debug.externs.js +1005 -695
- package/dist/shaka-player.compiled.debug.js +720 -640
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +1005 -695
- package/dist/shaka-player.compiled.js +850 -817
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +274 -21
- package/dist/shaka-player.ui.debug.d.ts +274 -21
- package/dist/shaka-player.ui.debug.externs.js +766 -429
- package/dist/shaka-player.ui.debug.js +863 -765
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +766 -429
- package/dist/shaka-player.ui.js +1042 -996
- package/dist/shaka-player.ui.map +4 -4
- package/docs/design/bg-fetch-after.gv +29 -0
- package/docs/design/bg-fetch-after.gv.png +0 -0
- package/docs/design/bg-fetch-before.gv +18 -0
- package/docs/design/bg-fetch-before.gv.png +0 -0
- package/docs/design/bg-fetch.md +134 -0
- package/docs/tutorials/blob-url.md +15 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/aria.js +6 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +29 -1
- package/externs/shaka/manifest.js +18 -2
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +36 -2
- package/externs/shaka/player.js +182 -13
- package/externs/shaka/text.js +24 -10
- package/externs/texttrack.js +3 -0
- package/externs/webcrypto.js +18 -0
- package/lib/abr/ewma.js +14 -0
- package/lib/abr/ewma_bandwidth_estimator.js +16 -2
- package/lib/abr/simple_abr_manager.js +6 -0
- package/lib/ads/ad_manager.js +16 -15
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +14 -6
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +19 -2
- package/lib/cast/cast_proxy.js +8 -0
- package/lib/cast/cast_utils.js +7 -1
- package/lib/cea/cea608_data_channel.js +56 -56
- package/lib/cea/cea608_memory.js +33 -33
- package/lib/cea/cea708_service.js +43 -43
- package/lib/cea/cea708_window.js +38 -38
- package/lib/cea/cea_decoder.js +13 -14
- package/lib/cea/cea_utils.js +23 -23
- package/lib/cea/dtvcc_packet_builder.js +7 -7
- package/lib/cea/i_caption_decoder.js +2 -3
- package/lib/cea/i_cea_parser.js +2 -2
- package/lib/cea/mp4_cea_parser.js +6 -6
- package/lib/dash/dash_parser.js +53 -14
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +18 -9
- package/lib/dash/segment_template.js +23 -10
- package/lib/hls/hls_parser.js +210 -30
- package/lib/media/closed_caption_parser.js +1 -2
- package/lib/media/drm_engine.js +162 -192
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +9 -1
- package/lib/media/segment_reference.js +37 -5
- package/lib/media/streaming_engine.js +48 -10
- package/lib/net/http_fetch_plugin.js +31 -11
- package/lib/net/http_plugin_utils.js +1 -0
- package/lib/net/http_xhr_plugin.js +40 -14
- package/lib/net/networking_engine.js +82 -18
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +14 -7
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/manifest_converter.js +3 -1
- package/lib/offline/storage.js +404 -297
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +622 -153
- package/lib/polyfill/aria.js +82 -0
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/routing/walker.js +2 -3
- package/lib/text/cue.js +12 -0
- package/lib/text/srt_text_parser.js +4 -4
- package/lib/text/text_engine.js +2 -2
- package/lib/text/ttml_text_parser.js +25 -2
- package/lib/text/ui_text_displayer.js +2 -2
- package/lib/text/vtt_text_parser.js +2 -2
- package/lib/text/web_vtt_generator.js +55 -12
- package/lib/util/cmcd_manager.js +826 -0
- package/lib/util/error.js +12 -0
- package/lib/util/language_utils.js +12 -0
- package/lib/util/manifest_parser_utils.js +1 -0
- package/lib/util/mp4_box_parsers.js +20 -20
- package/lib/util/multi_map.js +8 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +98 -64
- package/lib/util/player_configuration.js +31 -1
- package/lib/util/stream_utils.js +140 -85
- package/lib/util/xml_utils.js +31 -12
- package/package.json +1 -1
- package/roadmap.md +24 -22
- package/shaka-player.uncompiled.js +4 -0
- package/test/cast/cast_utils_unit.js +1 -0
- package/test/cea/cea608_memory_unit.js +1 -1
- package/test/cea/cea708_service_unit.js +8 -8
- package/test/cea/cea708_window_unit.js +6 -6
- package/test/cea/cea_decoder_unit.js +1 -1
- package/test/cea/dtvcc_packet_builder_unit.js +2 -2
- package/test/dash/dash_parser_content_protection_unit.js +2 -0
- package/test/dash/dash_parser_live_unit.js +101 -1
- package/test/dash/dash_parser_manifest_unit.js +78 -2
- package/test/dash/dash_parser_segment_base_unit.js +2 -0
- package/test/dash/dash_parser_segment_list_unit.js +2 -1
- package/test/dash/dash_parser_segment_template_unit.js +2 -1
- package/test/hls/hls_live_unit.js +2 -0
- package/test/hls/hls_parser_unit.js +252 -0
- package/test/media/drm_engine_integration.js +86 -12
- package/test/media/drm_engine_unit.js +310 -450
- package/test/media/quality_observer_unit.js +139 -0
- package/test/media/segment_reference_unit.js +16 -1
- package/test/media/streaming_engine_integration.js +2 -1
- package/test/media/streaming_engine_unit.js +2 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/manifest_convert_unit.js +2 -0
- package/test/offline/storage_integration.js +117 -23
- package/test/player_integration.js +151 -0
- package/test/player_src_equals_integration.js +52 -0
- package/test/player_unit.js +11 -33
- package/test/test/assets/chapters.srt +11 -0
- package/test/test/assets/chapters.vtt +10 -0
- package/test/test/util/cea_utils.js +12 -12
- package/test/test/util/dash_parser_util.js +4 -0
- package/test/test/util/fake_ad.js +7 -0
- package/test/test/util/fake_ad_manager.js +7 -0
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +5 -2
- package/test/test/util/manifest_parser_util.js +3 -1
- package/test/test/util/test_scheme.js +14 -1
- package/test/text/ttml_text_parser_unit.js +47 -0
- package/test/text/web_vtt_generator_unit.js +81 -7
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +277 -0
- package/test/util/stream_utils_unit.js +118 -10
- package/ui/airplay_button.js +2 -1
- package/ui/audio_language_selection.js +9 -5
- package/ui/cast_button.js +5 -6
- package/ui/constants.js +0 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +41 -7
- package/ui/controls.less +1 -0
- package/ui/enums.js +4 -0
- package/ui/externs/ui.js +28 -1
- package/ui/fast_forward_button.js +16 -8
- package/ui/fullscreen_button.js +2 -3
- package/ui/language_utils.js +1 -1
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +74 -0
- package/ui/less/overflow_menu.less +0 -10
- package/ui/less/tooltip.less +97 -0
- package/ui/locales/en.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/loop_button.js +6 -3
- package/ui/mute_button.js +3 -4
- package/ui/overflow_menu.js +7 -28
- package/ui/pip_button.js +10 -7
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +11 -15
- package/ui/presentation_time.js +1 -3
- package/ui/resolution_selection.js +11 -7
- package/ui/rewind_button.js +17 -9
- package/ui/seek_bar.js +6 -6
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/spacer.js +1 -1
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +19 -15
- package/ui/ui.js +30 -0
- package/ui/ui_utils.js +1 -1
- package/ui/volume_bar.js +2 -4
|
@@ -39,6 +39,8 @@ describe('DashParser Live', () => {
|
|
|
39
39
|
parser.configure(shaka.util.PlayerConfiguration.createDefault().manifest);
|
|
40
40
|
playerInterface = {
|
|
41
41
|
networkingEngine: fakeNetEngine,
|
|
42
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
43
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
42
44
|
filter: (manifest) => Promise.resolve(),
|
|
43
45
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
44
46
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -364,7 +366,7 @@ describe('DashParser Live', () => {
|
|
|
364
366
|
});
|
|
365
367
|
}
|
|
366
368
|
|
|
367
|
-
it('can add Periods', async () => {
|
|
369
|
+
it('can add Periods with SegmentTemplate', async () => {
|
|
368
370
|
const template1 = [
|
|
369
371
|
'<MPD type="dynamic" availabilityStartTime="1970-01-01T00:00:00Z"',
|
|
370
372
|
' suggestedPresentationDelay="PT5S"',
|
|
@@ -440,6 +442,104 @@ describe('DashParser Live', () => {
|
|
|
440
442
|
// two segments (10-14s).
|
|
441
443
|
expect(stream.segmentIndex.find(9)).not.toBe(null);
|
|
442
444
|
expect(stream.segmentIndex.find(13)).not.toBe(null);
|
|
445
|
+
|
|
446
|
+
stream.closeSegmentIndex();
|
|
447
|
+
await stream.createSegmentIndex();
|
|
448
|
+
|
|
449
|
+
expect(stream.segmentIndex.find(9)).not.toBe(null);
|
|
450
|
+
expect(stream.segmentIndex.find(13)).not.toBe(null);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it('can add Periods with SegmentList', async () => {
|
|
454
|
+
const list1 = [
|
|
455
|
+
'<MPD type="dynamic" availabilityStartTime="1970-01-01T00:00:00Z"',
|
|
456
|
+
' suggestedPresentationDelay="PT5S"',
|
|
457
|
+
' minimumUpdatePeriod="PT%(updateTime)dS">',
|
|
458
|
+
' <Period id="1">',
|
|
459
|
+
' <AdaptationSet mimeType="video/mp4">',
|
|
460
|
+
' <Representation id="1" bandwidth="500">',
|
|
461
|
+
' <BaseURL>http://example.com</BaseURL>',
|
|
462
|
+
' <SegmentList>',
|
|
463
|
+
' <SegmentURL media="s1.mp4" />',
|
|
464
|
+
' <SegmentURL media="s2.mp4" />',
|
|
465
|
+
' <SegmentURL media="s3.mp4" />',
|
|
466
|
+
' <SegmentTimeline>',
|
|
467
|
+
' <S d="10" t="0" r="2"/>',
|
|
468
|
+
' </SegmentTimeline>',
|
|
469
|
+
' </SegmentList>',
|
|
470
|
+
' </Representation>',
|
|
471
|
+
' </AdaptationSet>',
|
|
472
|
+
' </Period>',
|
|
473
|
+
'</MPD>',
|
|
474
|
+
].join('\n');
|
|
475
|
+
const list2 = [
|
|
476
|
+
'<MPD type="dynamic" availabilityStartTime="1970-01-01T00:00:00Z"',
|
|
477
|
+
' suggestedPresentationDelay="PT5S"',
|
|
478
|
+
' minimumUpdatePeriod="PT%(updateTime)dS">',
|
|
479
|
+
' <Period id="1" duration="PT40S">',
|
|
480
|
+
' <AdaptationSet mimeType="video/mp4">',
|
|
481
|
+
' <Representation id="1" bandwidth="500">',
|
|
482
|
+
' <BaseURL>http://example.com</BaseURL>',
|
|
483
|
+
' <SegmentList>',
|
|
484
|
+
' <SegmentURL media="s1.mp4" />',
|
|
485
|
+
' <SegmentURL media="s2.mp4" />',
|
|
486
|
+
' <SegmentURL media="s3.mp4" />',
|
|
487
|
+
' <SegmentURL media="s4.mp4" />',
|
|
488
|
+
' <SegmentTimeline>',
|
|
489
|
+
' <S d="10" t="0" r="3"/>',
|
|
490
|
+
' </SegmentTimeline>',
|
|
491
|
+
' </SegmentList>',
|
|
492
|
+
' </Representation>',
|
|
493
|
+
' </AdaptationSet>',
|
|
494
|
+
' </Period>',
|
|
495
|
+
' <Period id="2">',
|
|
496
|
+
' <AdaptationSet mimeType="video/mp4">',
|
|
497
|
+
' <Representation id="2" bandwidth="500">',
|
|
498
|
+
' <BaseURL>http://example.com</BaseURL>',
|
|
499
|
+
' <SegmentList>',
|
|
500
|
+
' <SegmentURL media="s1.mp4" />',
|
|
501
|
+
' <SegmentURL media="s2.mp4" />',
|
|
502
|
+
' <SegmentTimeline>',
|
|
503
|
+
' <S d="10" t="0" r="1"/>',
|
|
504
|
+
' </SegmentTimeline>',
|
|
505
|
+
' </SegmentList>',
|
|
506
|
+
' </Representation>',
|
|
507
|
+
' </AdaptationSet>',
|
|
508
|
+
' </Period>',
|
|
509
|
+
'</MPD>',
|
|
510
|
+
].join('\n');
|
|
511
|
+
const firstManifest = sprintf(list1, {updateTime: updateTime});
|
|
512
|
+
const secondManifest = sprintf(list2, {updateTime: updateTime});
|
|
513
|
+
|
|
514
|
+
fakeNetEngine.setResponseText('dummy://foo', firstManifest);
|
|
515
|
+
// First three segments should exist.
|
|
516
|
+
Date.now = () => 5;
|
|
517
|
+
|
|
518
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
519
|
+
const variant = manifest.variants[0];
|
|
520
|
+
const stream = variant.video;
|
|
521
|
+
await stream.createSegmentIndex();
|
|
522
|
+
|
|
523
|
+
// First three segments exist, but not the fourth.
|
|
524
|
+
expect(stream.segmentIndex.find(25)).not.toBe(null);
|
|
525
|
+
expect(stream.segmentIndex.find(45)).toBe(null);
|
|
526
|
+
|
|
527
|
+
fakeNetEngine.setResponseText('dummy://foo', secondManifest);
|
|
528
|
+
Date.now = () => 25;
|
|
529
|
+
|
|
530
|
+
await updateManifest();
|
|
531
|
+
|
|
532
|
+
// The update should have affected the same variant object we captured
|
|
533
|
+
// before. Now the entire first period should exist (0-40s), plus the next
|
|
534
|
+
// two segments of the second period(40-60s).
|
|
535
|
+
expect(stream.segmentIndex.find(25)).not.toBe(null);
|
|
536
|
+
expect(stream.segmentIndex.find(45)).not.toBe(null);
|
|
537
|
+
|
|
538
|
+
stream.closeSegmentIndex();
|
|
539
|
+
await stream.createSegmentIndex();
|
|
540
|
+
|
|
541
|
+
expect(stream.segmentIndex.find(25)).not.toBe(null);
|
|
542
|
+
expect(stream.segmentIndex.find(45)).not.toBe(null);
|
|
443
543
|
});
|
|
444
544
|
|
|
445
545
|
it('uses redirect URL for manifest BaseURL and updates', async () => {
|
|
@@ -36,7 +36,7 @@ describe('DashParser Manifest', () => {
|
|
|
36
36
|
/** @type {!ArrayBuffer} */
|
|
37
37
|
let mp4Index;
|
|
38
38
|
|
|
39
|
-
/** @type {
|
|
39
|
+
/** @type {string} */
|
|
40
40
|
const thumbnailScheme = 'http://dashif.org/guidelines/thumbnail_tile';
|
|
41
41
|
/**
|
|
42
42
|
* CICP scheme. parameter must be one of the following: "ColourPrimaries",
|
|
@@ -57,6 +57,8 @@ describe('DashParser Manifest', () => {
|
|
|
57
57
|
onEventSpy = jasmine.createSpy('onEvent');
|
|
58
58
|
playerInterface = {
|
|
59
59
|
networkingEngine: fakeNetEngine,
|
|
60
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
61
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
60
62
|
filter: (manifest) => Promise.resolve(),
|
|
61
63
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
62
64
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -1798,6 +1800,48 @@ describe('DashParser Manifest', () => {
|
|
|
1798
1800
|
expect(manifest.presentationTimeline).toBeTruthy();
|
|
1799
1801
|
});
|
|
1800
1802
|
|
|
1803
|
+
it('Invokes manifestPreprocessor in config', async () => {
|
|
1804
|
+
const manifestText = [
|
|
1805
|
+
'<MPD minBufferTime="PT75S">',
|
|
1806
|
+
' <Period id="1" duration="PT30S">',
|
|
1807
|
+
' <AdaptationSet id="2" mimeType="video/mp4">',
|
|
1808
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1809
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1810
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1811
|
+
' </Representation>',
|
|
1812
|
+
' </AdaptationSet>',
|
|
1813
|
+
' <AdaptationSet id="3" mimeType="audio/mp4">',
|
|
1814
|
+
' <Representation id="audio-en">',
|
|
1815
|
+
' <BaseURL>a-en.mp4</BaseURL>',
|
|
1816
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1817
|
+
' </Representation>',
|
|
1818
|
+
' </AdaptationSet>',
|
|
1819
|
+
' <AdaptationSet mimeType="text/vtt" lang="de">',
|
|
1820
|
+
' <Representation>',
|
|
1821
|
+
' <BaseURL>http://example.com/de.vtt</BaseURL>',
|
|
1822
|
+
' </Representation>',
|
|
1823
|
+
' </AdaptationSet>',
|
|
1824
|
+
' </Period>',
|
|
1825
|
+
'</MPD>',
|
|
1826
|
+
].join('\n');
|
|
1827
|
+
|
|
1828
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1829
|
+
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
1830
|
+
config.dash.manifestPreprocessor = (mpd) => {
|
|
1831
|
+
const selector = 'AdaptationSet[mimeType="text/vtt"';
|
|
1832
|
+
const vttElements = mpd.querySelectorAll(selector);
|
|
1833
|
+
for (const element of vttElements) {
|
|
1834
|
+
element.parentNode.removeChild(element);
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
parser.configure(config);
|
|
1838
|
+
|
|
1839
|
+
/** @type {shaka.extern.Manifest} */
|
|
1840
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1841
|
+
const stream = manifest.textStreams[0];
|
|
1842
|
+
expect(stream).toBeUndefined();
|
|
1843
|
+
});
|
|
1844
|
+
|
|
1801
1845
|
it('converts Accessibility element to "kind"', async () => {
|
|
1802
1846
|
const manifestText = [
|
|
1803
1847
|
'<MPD minBufferTime="PT75S">',
|
|
@@ -1830,7 +1874,7 @@ describe('DashParser Manifest', () => {
|
|
|
1830
1874
|
expect(textStream.kind).toBe('caption');
|
|
1831
1875
|
});
|
|
1832
1876
|
|
|
1833
|
-
it('converts Roles element to "forced"', async () => {
|
|
1877
|
+
it('converts Roles element to "forced" (old role)', async () => {
|
|
1834
1878
|
const manifestText = [
|
|
1835
1879
|
'<MPD minBufferTime="PT75S">',
|
|
1836
1880
|
' <Period id="1" duration="PT30S">',
|
|
@@ -1862,6 +1906,38 @@ describe('DashParser Manifest', () => {
|
|
|
1862
1906
|
expect(textStream.forced).toBe(true);
|
|
1863
1907
|
});
|
|
1864
1908
|
|
|
1909
|
+
it('converts Roles element to "forced"', async () => {
|
|
1910
|
+
const manifestText = [
|
|
1911
|
+
'<MPD minBufferTime="PT75S">',
|
|
1912
|
+
' <Period id="1" duration="PT30S">',
|
|
1913
|
+
' <AdaptationSet id="1" contentType="text">',
|
|
1914
|
+
' <Accessibility schemeIdUri="urn:mpeg:dash:role:2011" ',
|
|
1915
|
+
' value="captions" />',
|
|
1916
|
+
' <Accessibility schemeIdUri="urn:mpeg:dash:role:2011" ',
|
|
1917
|
+
' value="forced-subtitle" />',
|
|
1918
|
+
' <Accessibility schemeIdUri="foobar" value="bar" />',
|
|
1919
|
+
' <Representation id="text-en" mimeType="text/webvtt">',
|
|
1920
|
+
' <BaseURL>t-en.vtt</BaseURL>',
|
|
1921
|
+
' </Representation>',
|
|
1922
|
+
' </AdaptationSet>',
|
|
1923
|
+
' <AdaptationSet id="1" mimeType="video/mp4">',
|
|
1924
|
+
' <Representation id="video-sd" width="640" height="480">',
|
|
1925
|
+
' <BaseURL>v-sd.mp4</BaseURL>',
|
|
1926
|
+
' <SegmentBase indexRange="100-200" />',
|
|
1927
|
+
' </Representation>',
|
|
1928
|
+
' </AdaptationSet>',
|
|
1929
|
+
' </Period>',
|
|
1930
|
+
'</MPD>',
|
|
1931
|
+
].join('\n');
|
|
1932
|
+
|
|
1933
|
+
fakeNetEngine.setResponseText('dummy://foo', manifestText);
|
|
1934
|
+
/** @type {shaka.extern.Manifest} */
|
|
1935
|
+
const manifest = await parser.start('dummy://foo', playerInterface);
|
|
1936
|
+
const textStream = manifest.textStreams[0];
|
|
1937
|
+
expect(textStream.roles).toEqual(['captions', 'forced-subtitle']);
|
|
1938
|
+
expect(textStream.forced).toBe(true);
|
|
1939
|
+
});
|
|
1940
|
+
|
|
1865
1941
|
it('supports HDR signaling via profiles', async () => {
|
|
1866
1942
|
// (DASH-IF IOP v4.3 10.3.3.)
|
|
1867
1943
|
const hdrProfile =
|
|
@@ -35,6 +35,8 @@ describe('DashParser SegmentBase', () => {
|
|
|
35
35
|
|
|
36
36
|
playerInterface = {
|
|
37
37
|
networkingEngine: fakeNetEngine,
|
|
38
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
39
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
38
40
|
filter: (manifest) => Promise.resolve(),
|
|
39
41
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
40
42
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -344,6 +344,8 @@ describe('DashParser SegmentList', () => {
|
|
|
344
344
|
|
|
345
345
|
const playerInterface = {
|
|
346
346
|
networkingEngine: networkingEngine,
|
|
347
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
348
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
347
349
|
filter: () => {},
|
|
348
350
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
349
351
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -374,4 +376,3 @@ describe('DashParser SegmentList', () => {
|
|
|
374
376
|
expect(actual).toEqual(expected);
|
|
375
377
|
});
|
|
376
378
|
});
|
|
377
|
-
|
|
@@ -46,6 +46,8 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
46
46
|
|
|
47
47
|
playerInterface = {
|
|
48
48
|
networkingEngine: fakeNetEngine,
|
|
49
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
50
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
49
51
|
filter: (manifest) => Promise.resolve(),
|
|
50
52
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
51
53
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -585,4 +587,3 @@ describe('DashParser SegmentTemplate', () => {
|
|
|
585
587
|
});
|
|
586
588
|
});
|
|
587
589
|
});
|
|
588
|
-
|
|
@@ -116,6 +116,8 @@ describe('HlsParser live', () => {
|
|
|
116
116
|
|
|
117
117
|
config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
118
118
|
playerInterface = {
|
|
119
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
120
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
119
121
|
filter: () => Promise.resolve(),
|
|
120
122
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
121
123
|
networkingEngine: fakeNetEngine,
|
|
@@ -94,6 +94,8 @@ describe('HlsParser', () => {
|
|
|
94
94
|
config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
95
95
|
onEventSpy = jasmine.createSpy('onEvent');
|
|
96
96
|
playerInterface = {
|
|
97
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
98
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
97
99
|
filter: () => Promise.resolve(),
|
|
98
100
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
99
101
|
networkingEngine: fakeNetEngine,
|
|
@@ -1318,6 +1320,103 @@ describe('HlsParser', () => {
|
|
|
1318
1320
|
expect(actual.variants[0].video).toBeTruthy();
|
|
1319
1321
|
});
|
|
1320
1322
|
|
|
1323
|
+
it('parse image streams', async () => {
|
|
1324
|
+
const master = [
|
|
1325
|
+
'#EXTM3U\n',
|
|
1326
|
+
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
|
|
1327
|
+
'URI="text"\n',
|
|
1328
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
|
|
1329
|
+
'CHANNELS="2",URI="audio"\n',
|
|
1330
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1331
|
+
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1332
|
+
'video\n',
|
|
1333
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg",',
|
|
1334
|
+
'URI="image"\n',
|
|
1335
|
+
].join('');
|
|
1336
|
+
|
|
1337
|
+
const video = [
|
|
1338
|
+
'#EXTM3U\n',
|
|
1339
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1340
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1341
|
+
'#EXTINF:5,\n',
|
|
1342
|
+
'main.mp4\n',
|
|
1343
|
+
'#EXTINF:5,\n',
|
|
1344
|
+
'main.mp4\n',
|
|
1345
|
+
'#EXTINF:5,\n',
|
|
1346
|
+
'main.mp4\n',
|
|
1347
|
+
].join('');
|
|
1348
|
+
|
|
1349
|
+
const audio = [
|
|
1350
|
+
'#EXTM3U\n',
|
|
1351
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1352
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1353
|
+
'#EXTINF:5,\n',
|
|
1354
|
+
'main.mp4\n',
|
|
1355
|
+
'#EXTINF:5,\n',
|
|
1356
|
+
'main.mp4\n',
|
|
1357
|
+
'#EXTINF:5,\n',
|
|
1358
|
+
'main.mp4\n',
|
|
1359
|
+
].join('');
|
|
1360
|
+
|
|
1361
|
+
const text = [
|
|
1362
|
+
'#EXTM3U\n',
|
|
1363
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1364
|
+
'#EXTINF:5,\n',
|
|
1365
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1366
|
+
'main.vtt',
|
|
1367
|
+
].join('');
|
|
1368
|
+
|
|
1369
|
+
const image = [
|
|
1370
|
+
'#EXTM3U\n',
|
|
1371
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1372
|
+
'#EXTINF:5,\n',
|
|
1373
|
+
'image.jpg\n',
|
|
1374
|
+
'#EXTINF:5,\n',
|
|
1375
|
+
'#EXT-X-TILES:RESOLUTION=640x360,LAYOUT=5x2,DURATION=6.006\n',
|
|
1376
|
+
'image.jpg\n',
|
|
1377
|
+
'#EXTINF:5,\n',
|
|
1378
|
+
'image.jpg\n',
|
|
1379
|
+
].join('');
|
|
1380
|
+
|
|
1381
|
+
fakeNetEngine
|
|
1382
|
+
.setResponseText('test:/master', master)
|
|
1383
|
+
.setResponseText('test:/audio', audio)
|
|
1384
|
+
.setResponseText('test:/video', video)
|
|
1385
|
+
.setResponseText('test:/text', text)
|
|
1386
|
+
.setResponseText('test:/image', image)
|
|
1387
|
+
.setResponseText('test:/main.vtt', vttText)
|
|
1388
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1389
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
1390
|
+
|
|
1391
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
1392
|
+
|
|
1393
|
+
expect(actual.imageStreams.length).toBe(1);
|
|
1394
|
+
expect(actual.textStreams.length).toBe(1);
|
|
1395
|
+
expect(actual.variants.length).toBe(1);
|
|
1396
|
+
|
|
1397
|
+
const thumbnails = actual.imageStreams[0];
|
|
1398
|
+
|
|
1399
|
+
await thumbnails.createSegmentIndex();
|
|
1400
|
+
goog.asserts.assert(thumbnails.segmentIndex != null, 'Null segmentIndex!');
|
|
1401
|
+
|
|
1402
|
+
const firstThumbnailReference = thumbnails.segmentIndex.get(0);
|
|
1403
|
+
const secondThumbnailReference = thumbnails.segmentIndex.get(1);
|
|
1404
|
+
const thirdThumbnailReference = thumbnails.segmentIndex.get(2);
|
|
1405
|
+
|
|
1406
|
+
expect(firstThumbnailReference).not.toBe(null);
|
|
1407
|
+
expect(secondThumbnailReference).not.toBe(null);
|
|
1408
|
+
expect(thirdThumbnailReference).not.toBe(null);
|
|
1409
|
+
if (firstThumbnailReference) {
|
|
1410
|
+
expect(firstThumbnailReference.getTilesLayout()).toBe('1x1');
|
|
1411
|
+
}
|
|
1412
|
+
if (secondThumbnailReference) {
|
|
1413
|
+
expect(secondThumbnailReference.getTilesLayout()).toBe('5x2');
|
|
1414
|
+
}
|
|
1415
|
+
if (thirdThumbnailReference) {
|
|
1416
|
+
expect(thirdThumbnailReference.getTilesLayout()).toBe('1x1');
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
|
|
1321
1420
|
it('Disable audio does not create audio streams', async () => {
|
|
1322
1421
|
const master = [
|
|
1323
1422
|
'#EXTM3U\n',
|
|
@@ -1328,6 +1427,8 @@ describe('HlsParser', () => {
|
|
|
1328
1427
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1329
1428
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1330
1429
|
'video\n',
|
|
1430
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg",',
|
|
1431
|
+
'URI="image"\n',
|
|
1331
1432
|
].join('');
|
|
1332
1433
|
|
|
1333
1434
|
const video = [
|
|
@@ -1360,11 +1461,23 @@ describe('HlsParser', () => {
|
|
|
1360
1461
|
'main.vtt',
|
|
1361
1462
|
].join('');
|
|
1362
1463
|
|
|
1464
|
+
const image = [
|
|
1465
|
+
'#EXTM3U\n',
|
|
1466
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1467
|
+
'#EXTINF:5,\n',
|
|
1468
|
+
'image.jpg\n',
|
|
1469
|
+
'#EXTINF:5,\n',
|
|
1470
|
+
'image.jpg\n',
|
|
1471
|
+
'#EXTINF:5,\n',
|
|
1472
|
+
'image.jpg\n',
|
|
1473
|
+
].join('');
|
|
1474
|
+
|
|
1363
1475
|
fakeNetEngine
|
|
1364
1476
|
.setResponseText('test:/master', master)
|
|
1365
1477
|
.setResponseText('test:/audio', audio)
|
|
1366
1478
|
.setResponseText('test:/video', video)
|
|
1367
1479
|
.setResponseText('test:/text', text)
|
|
1480
|
+
.setResponseText('test:/image', image)
|
|
1368
1481
|
.setResponseText('test:/main.vtt', vttText)
|
|
1369
1482
|
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1370
1483
|
.setResponseValue('test:/main.mp4', segmentData);
|
|
@@ -1389,6 +1502,8 @@ describe('HlsParser', () => {
|
|
|
1389
1502
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1390
1503
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1391
1504
|
'video\n',
|
|
1505
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg",',
|
|
1506
|
+
'URI="image"\n',
|
|
1392
1507
|
].join('');
|
|
1393
1508
|
|
|
1394
1509
|
const video = [
|
|
@@ -1421,11 +1536,23 @@ describe('HlsParser', () => {
|
|
|
1421
1536
|
'main.vtt',
|
|
1422
1537
|
].join('');
|
|
1423
1538
|
|
|
1539
|
+
const image = [
|
|
1540
|
+
'#EXTM3U\n',
|
|
1541
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1542
|
+
'#EXTINF:5,\n',
|
|
1543
|
+
'image.jpg\n',
|
|
1544
|
+
'#EXTINF:5,\n',
|
|
1545
|
+
'image.jpg\n',
|
|
1546
|
+
'#EXTINF:5,\n',
|
|
1547
|
+
'image.jpg\n',
|
|
1548
|
+
].join('');
|
|
1549
|
+
|
|
1424
1550
|
fakeNetEngine
|
|
1425
1551
|
.setResponseText('test:/master', master)
|
|
1426
1552
|
.setResponseText('test:/audio', audio)
|
|
1427
1553
|
.setResponseText('test:/video', video)
|
|
1428
1554
|
.setResponseText('test:/text', text)
|
|
1555
|
+
.setResponseText('test:/image', image)
|
|
1429
1556
|
.setResponseText('test:/main.vtt', vttText)
|
|
1430
1557
|
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1431
1558
|
.setResponseValue('test:/main.mp4', segmentData);
|
|
@@ -1450,6 +1577,8 @@ describe('HlsParser', () => {
|
|
|
1450
1577
|
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1451
1578
|
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1452
1579
|
'video\n',
|
|
1580
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg",',
|
|
1581
|
+
'URI="image"\n',
|
|
1453
1582
|
].join('');
|
|
1454
1583
|
|
|
1455
1584
|
const video = [
|
|
@@ -1482,11 +1611,23 @@ describe('HlsParser', () => {
|
|
|
1482
1611
|
'main.vtt',
|
|
1483
1612
|
].join('');
|
|
1484
1613
|
|
|
1614
|
+
const image = [
|
|
1615
|
+
'#EXTM3U\n',
|
|
1616
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1617
|
+
'#EXTINF:5,\n',
|
|
1618
|
+
'image.jpg\n',
|
|
1619
|
+
'#EXTINF:5,\n',
|
|
1620
|
+
'image.jpg\n',
|
|
1621
|
+
'#EXTINF:5,\n',
|
|
1622
|
+
'image.jpg\n',
|
|
1623
|
+
].join('');
|
|
1624
|
+
|
|
1485
1625
|
fakeNetEngine
|
|
1486
1626
|
.setResponseText('test:/master', master)
|
|
1487
1627
|
.setResponseText('test:/audio', audio)
|
|
1488
1628
|
.setResponseText('test:/video', video)
|
|
1489
1629
|
.setResponseText('test:/text', text)
|
|
1630
|
+
.setResponseText('test:/image', image)
|
|
1490
1631
|
.setResponseText('test:/main.vtt', vttText)
|
|
1491
1632
|
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1492
1633
|
.setResponseValue('test:/main.mp4', segmentData);
|
|
@@ -1500,6 +1641,80 @@ describe('HlsParser', () => {
|
|
|
1500
1641
|
expect(stream).toBeUndefined();
|
|
1501
1642
|
});
|
|
1502
1643
|
|
|
1644
|
+
it('Disable thumbnails does not create image streams', async () => {
|
|
1645
|
+
const master = [
|
|
1646
|
+
'#EXTM3U\n',
|
|
1647
|
+
'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="sub1",LANGUAGE="eng",',
|
|
1648
|
+
'URI="text"\n',
|
|
1649
|
+
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
|
|
1650
|
+
'CHANNELS="2",URI="audio"\n',
|
|
1651
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",',
|
|
1652
|
+
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1",SUBTITLES="sub1"\n',
|
|
1653
|
+
'video\n',
|
|
1654
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg",',
|
|
1655
|
+
'URI="image"\n',
|
|
1656
|
+
].join('');
|
|
1657
|
+
|
|
1658
|
+
const video = [
|
|
1659
|
+
'#EXTM3U\n',
|
|
1660
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1661
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1662
|
+
'#EXTINF:5,\n',
|
|
1663
|
+
'main.mp4\n',
|
|
1664
|
+
'#EXTINF:5,\n',
|
|
1665
|
+
'main.mp4\n',
|
|
1666
|
+
'#EXTINF:5,\n',
|
|
1667
|
+
'main.mp4\n',
|
|
1668
|
+
].join('');
|
|
1669
|
+
|
|
1670
|
+
const audio = [
|
|
1671
|
+
'#EXTM3U\n',
|
|
1672
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1673
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1674
|
+
'#EXTINF:5,\n',
|
|
1675
|
+
'main.mp4\n',
|
|
1676
|
+
'#EXTINF:5,\n',
|
|
1677
|
+
'main.mp4\n',
|
|
1678
|
+
].join('');
|
|
1679
|
+
|
|
1680
|
+
const text = [
|
|
1681
|
+
'#EXTM3U\n',
|
|
1682
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1683
|
+
'#EXTINF:5,\n',
|
|
1684
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1685
|
+
'main.vtt',
|
|
1686
|
+
].join('');
|
|
1687
|
+
|
|
1688
|
+
const image = [
|
|
1689
|
+
'#EXTM3U\n',
|
|
1690
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1691
|
+
'#EXTINF:5,\n',
|
|
1692
|
+
'image.jpg\n',
|
|
1693
|
+
'#EXTINF:5,\n',
|
|
1694
|
+
'image.jpg\n',
|
|
1695
|
+
'#EXTINF:5,\n',
|
|
1696
|
+
'image.jpg\n',
|
|
1697
|
+
].join('');
|
|
1698
|
+
|
|
1699
|
+
fakeNetEngine
|
|
1700
|
+
.setResponseText('test:/master', master)
|
|
1701
|
+
.setResponseText('test:/audio', audio)
|
|
1702
|
+
.setResponseText('test:/video', video)
|
|
1703
|
+
.setResponseText('test:/text', text)
|
|
1704
|
+
.setResponseText('test:/image', image)
|
|
1705
|
+
.setResponseText('test:/main.vtt', vttText)
|
|
1706
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1707
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
1708
|
+
|
|
1709
|
+
const config = shaka.util.PlayerConfiguration.createDefault().manifest;
|
|
1710
|
+
config.disableThumbnails = true;
|
|
1711
|
+
parser.configure(config);
|
|
1712
|
+
|
|
1713
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
1714
|
+
const stream = actual.imageStreams[0];
|
|
1715
|
+
expect(stream).toBeUndefined();
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1503
1718
|
it('parses manifest with MP4+TTML streams', async () => {
|
|
1504
1719
|
const master = [
|
|
1505
1720
|
'#EXTM3U\n',
|
|
@@ -1670,6 +1885,43 @@ describe('HlsParser', () => {
|
|
|
1670
1885
|
expect(actual).toEqual(manifest);
|
|
1671
1886
|
});
|
|
1672
1887
|
|
|
1888
|
+
it('drops failed image streams when configured to', async () => {
|
|
1889
|
+
const master = [
|
|
1890
|
+
'#EXTM3U\n',
|
|
1891
|
+
'#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1",',
|
|
1892
|
+
'RESOLUTION=960x540,FRAME-RATE=60\n',
|
|
1893
|
+
'video\n',
|
|
1894
|
+
'#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240×135,CODECS="jpeg"\n',
|
|
1895
|
+
].join('');
|
|
1896
|
+
|
|
1897
|
+
const media = [
|
|
1898
|
+
'#EXTM3U\n',
|
|
1899
|
+
'#EXT-X-PLAYLIST-TYPE:VOD\n',
|
|
1900
|
+
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="616@0"\n',
|
|
1901
|
+
'#EXTINF:5,\n',
|
|
1902
|
+
'#EXT-X-BYTERANGE:121090@616\n',
|
|
1903
|
+
'main.mp4',
|
|
1904
|
+
].join('');
|
|
1905
|
+
|
|
1906
|
+
const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
1907
|
+
manifest.anyTimeline();
|
|
1908
|
+
manifest.addPartialVariant((variant) => {
|
|
1909
|
+
variant.addPartialStream(ContentType.VIDEO);
|
|
1910
|
+
});
|
|
1911
|
+
});
|
|
1912
|
+
|
|
1913
|
+
fakeNetEngine
|
|
1914
|
+
.setResponseText('test:/master', master)
|
|
1915
|
+
.setResponseText('test:/audio', media)
|
|
1916
|
+
.setResponseText('test:/video', media)
|
|
1917
|
+
.setResponseValue('test:/init.mp4', initSegmentData)
|
|
1918
|
+
.setResponseValue('test:/main.mp4', segmentData);
|
|
1919
|
+
|
|
1920
|
+
config.hls.ignoreImageStreamFailures = true;
|
|
1921
|
+
const actual = await parser.start('test:/master', playerInterface);
|
|
1922
|
+
expect(actual).toEqual(manifest);
|
|
1923
|
+
});
|
|
1924
|
+
|
|
1673
1925
|
it('parses video described by a media tag', async () => {
|
|
1674
1926
|
const master = [
|
|
1675
1927
|
'#EXTM3U\n',
|