shaka-player 3.2.1 → 3.3.1
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 +9 -5
- package/CHANGELOG.md +358 -0
- package/CONTRIBUTORS +7 -2
- package/build/conformance.textproto +183 -169
- package/build/generateExterns.js +1 -1
- package/build/types/core +3 -0
- package/build/types/offline +1 -0
- package/build/types/polyfill +1 -0
- package/build/types/ui +2 -0
- package/demo/common/assets.js +19 -1
- package/demo/common/message_ids.js +13 -1
- package/demo/config.js +31 -1
- package/demo/index.html +1 -1
- package/demo/locales/en.json +12 -0
- package/demo/locales/source.json +48 -0
- package/dist/controls.css +26 -2
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +20 -17
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +20 -17
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +19 -12
- package/dist/locales.js +39 -37
- package/dist/receiver.compiled.debug.js +12 -10
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +12 -10
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.d.ts +231 -18
- package/dist/shaka-player.compiled.debug.externs.js +279 -8
- package/dist/shaka-player.compiled.debug.js +512 -449
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +279 -8
- package/dist/shaka-player.compiled.js +854 -821
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +247 -19
- package/dist/shaka-player.ui.debug.d.ts +247 -19
- package/dist/shaka-player.ui.debug.externs.js +307 -9
- package/dist/shaka-player.ui.debug.js +662 -580
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +307 -9
- package/dist/shaka-player.ui.js +1047 -1000
- 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/fairplay.md +1 -1
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +66 -0
- package/docs/tutorials/ui.md +5 -5
- package/externs/cmcd.js +186 -0
- package/externs/ima.js +3 -0
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/manifest.js +12 -1
- package/externs/shaka/manifest_parser.js +10 -1
- package/externs/shaka/net.js +20 -4
- package/externs/shaka/offline.js +31 -2
- package/externs/shaka/player.js +138 -5
- package/externs/shaka/text.js +24 -0
- package/externs/webcrypto.js +18 -0
- package/karma.conf.js +1 -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/client_side_ad.js +8 -0
- package/lib/ads/client_side_ad_manager.js +54 -90
- package/lib/ads/server_side_ad.js +7 -0
- package/lib/ads/server_side_ad_manager.js +7 -10
- package/lib/cast/cast_proxy.js +3 -2
- package/lib/cast/cast_receiver.js +2 -1
- package/lib/cast/cast_sender.js +2 -2
- package/lib/cast/cast_utils.js +1 -0
- package/lib/dash/dash_parser.js +141 -16
- package/lib/dash/segment_base.js +25 -1
- package/lib/dash/segment_list.js +19 -10
- package/lib/dash/segment_template.js +24 -11
- package/lib/hls/hls_parser.js +146 -40
- package/lib/media/drm_engine.js +7 -0
- package/lib/media/gap_jumping_controller.js +4 -2
- package/lib/media/media_source_engine.js +1 -2
- package/lib/media/quality_observer.js +291 -0
- package/lib/media/segment_index.js +8 -1
- package/lib/media/segment_reference.js +37 -4
- package/lib/media/streaming_engine.js +49 -7
- 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 +83 -19
- package/lib/offline/download_info.js +68 -0
- package/lib/offline/download_manager.js +13 -5
- package/lib/offline/indexeddb/base_storage_cell.js +35 -0
- package/lib/offline/indexeddb/storage_mechanism.js +1 -1
- package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
- package/lib/offline/storage.js +393 -284
- package/lib/offline/stored_content_utils.js +2 -0
- package/lib/player.js +249 -43
- package/lib/polyfill/media_capabilities.js +36 -15
- package/lib/polyfill/mediasource.js +6 -0
- package/lib/polyfill/orientation.js +1 -1
- package/lib/polyfill/patchedmediakeys_apple.js +4 -4
- package/lib/polyfill/patchedmediakeys_ms.js +4 -4
- package/lib/polyfill/patchedmediakeys_webkit.js +4 -4
- package/lib/polyfill/random_uuid.js +52 -0
- package/lib/text/cue.js +18 -0
- package/lib/text/mp4_ttml_parser.js +3 -0
- package/lib/text/text_engine.js +14 -2
- package/lib/text/ttml_text_parser.js +114 -60
- package/lib/text/ui_text_displayer.js +95 -41
- package/lib/util/cmcd_manager.js +672 -0
- package/lib/util/error.js +6 -0
- package/lib/util/fake_event.js +53 -7
- package/lib/util/language_utils.js +12 -0
- package/lib/util/mutex.js +52 -0
- package/lib/util/periods.js +102 -65
- package/lib/util/platform.js +13 -1
- package/lib/util/player_configuration.js +18 -0
- package/lib/util/stream_utils.js +99 -10
- package/lib/util/xml_utils.js +19 -0
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +3 -0
- package/test/cast/cast_proxy_unit.js +12 -6
- package/test/cast/cast_utils_unit.js +1 -1
- 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 +222 -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 +7 -1
- package/test/media/closed_caption_parser_unit.js +6 -1
- package/test/media/drm_engine_unit.js +47 -3
- 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 +4 -2
- package/test/media/streaming_engine_unit.js +147 -0
- package/test/net/http_plugin_unit.js +20 -15
- package/test/offline/storage_integration.js +108 -4
- package/test/player_integration.js +178 -8
- package/test/player_src_equals_integration.js +41 -8
- package/test/player_unit.js +19 -9
- package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
- package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
- package/test/test/assets/3675/dash_0.mpd +30 -0
- package/test/test/assets/3675/dash_1.mpd +30 -0
- package/test/test/assets/3675/dash_2.mpd +30 -0
- package/test/test/assets/3675/dash_3.mpd +30 -0
- package/test/test/assets/3675/dash_4.mpd +30 -0
- package/test/test/assets/3675/dash_5.mpd +26 -0
- package/test/test/assets/3675/init-stream0.m4s +0 -0
- package/test/test/assets/chapters.vtt +2 -2
- package/test/test/assets/chapters2.vtt +10 -0
- 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 +1 -1
- package/test/test/util/fake_drm_engine.js +9 -2
- package/test/test/util/manifest_generator.js +3 -2
- package/test/test/util/test_scheme.js +14 -1
- package/test/test/util/ttml_utils.js +81 -0
- package/test/text/mp4_ttml_parser_unit.js +11 -18
- package/test/text/ttml_text_parser_unit.js +552 -227
- package/test/text/ui_text_displayer_unit.js +29 -17
- package/test/ui/localization_unit.js +15 -14
- package/test/ui/text_displayer_layout_unit.js +13 -1
- package/test/ui/ui_unit.js +250 -0
- package/test/util/cmcd_manager_unit.js +291 -0
- package/test/util/stream_utils_unit.js +45 -4
- package/third_party/closure-uri/uri.js +21 -0
- package/ui/airplay_button.js +1 -0
- package/ui/audio_language_selection.js +7 -0
- package/ui/cast_button.js +3 -3
- package/ui/context_menu.js +109 -0
- package/ui/controls.js +45 -13
- 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 +14 -5
- package/ui/fullscreen_button.js +1 -0
- package/ui/less/buttons.less +0 -4
- package/ui/less/containers.less +77 -7
- 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/ru.json +6 -6
- package/ui/locales/source.json +4 -0
- package/ui/localization.js +28 -51
- package/ui/loop_button.js +5 -0
- package/ui/mute_button.js +2 -1
- package/ui/overflow_menu.js +5 -25
- package/ui/pip_button.js +7 -3
- package/ui/play_button.js +2 -2
- package/ui/playback_rate_selection.js +8 -9
- package/ui/resolution_selection.js +7 -0
- package/ui/rewind_button.js +15 -6
- package/ui/seek_bar.js +4 -2
- package/ui/settings_menu.js +36 -4
- package/ui/small_play_button.js +1 -0
- package/ui/statistics_button.js +253 -0
- package/ui/text_selection.js +12 -4
- package/ui/ui.js +30 -0
- package/ui/volume_bar.js +1 -1
- package/externs/media_capabilities.js +0 -16
|
@@ -97,6 +97,9 @@ describe('StreamingEngine', () => {
|
|
|
97
97
|
/** @type {!shaka.media.StreamingEngine} */
|
|
98
98
|
let streamingEngine;
|
|
99
99
|
|
|
100
|
+
/** @type {function(function(), number)} */
|
|
101
|
+
let realSetTimeout;
|
|
102
|
+
|
|
100
103
|
/**
|
|
101
104
|
* Runs the fake event loop.
|
|
102
105
|
* @param {function()=} callback An optional callback that is executed
|
|
@@ -116,6 +119,7 @@ describe('StreamingEngine', () => {
|
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
beforeAll(() => {
|
|
122
|
+
realSetTimeout = window.setTimeout;
|
|
119
123
|
jasmine.clock().install();
|
|
120
124
|
jasmine.clock().mockDate();
|
|
121
125
|
});
|
|
@@ -451,6 +455,7 @@ describe('StreamingEngine', () => {
|
|
|
451
455
|
presentationTimeInSeconds != undefined,
|
|
452
456
|
'All tests should have defined an initial presentation time by now!');
|
|
453
457
|
const playerInterface = {
|
|
458
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
454
459
|
getPresentationTime: () => presentationTimeInSeconds,
|
|
455
460
|
getBandwidthEstimate: Util.spyFunc(getBandwidthEstimate),
|
|
456
461
|
mediaSourceEngine: mediaSourceEngine,
|
|
@@ -459,6 +464,7 @@ describe('StreamingEngine', () => {
|
|
|
459
464
|
onEvent: Util.spyFunc(onEvent),
|
|
460
465
|
onManifestUpdate: Util.spyFunc(onManifestUpdate),
|
|
461
466
|
onSegmentAppended: Util.spyFunc(onSegmentAppended),
|
|
467
|
+
onInitSegmentAppended: () => {},
|
|
462
468
|
};
|
|
463
469
|
streamingEngine = new shaka.media.StreamingEngine(
|
|
464
470
|
/** @type {shaka.extern.Manifest} */(manifest), playerInterface);
|
|
@@ -822,6 +828,53 @@ describe('StreamingEngine', () => {
|
|
|
822
828
|
.toHaveBeenCalledWith('video', 0, lt20, gt40);
|
|
823
829
|
});
|
|
824
830
|
|
|
831
|
+
// Regression test for https://github.com/google/shaka-player/issues/3717
|
|
832
|
+
it('applies fudge factors for the duration', async () => {
|
|
833
|
+
setupVod();
|
|
834
|
+
|
|
835
|
+
// In #3717, the duration was just barely large enough to encompass an
|
|
836
|
+
// additional segment, but that segment didn't exist, so playback never
|
|
837
|
+
// completed. Here, we set the duration to just beyond the 3rd segment, and
|
|
838
|
+
// we make the 4th segment fail when requested.
|
|
839
|
+
const duration = 30.000000005;
|
|
840
|
+
timeline.getDuration.and.returnValue(duration);
|
|
841
|
+
|
|
842
|
+
const targetUri = '1_video_3'; // The URI of the 4th video segment.
|
|
843
|
+
failRequestsForTarget(netEngine, targetUri);
|
|
844
|
+
|
|
845
|
+
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
846
|
+
createStreamingEngine();
|
|
847
|
+
|
|
848
|
+
// Here we go!
|
|
849
|
+
streamingEngine.switchVariant(variant);
|
|
850
|
+
streamingEngine.switchTextStream(textStream);
|
|
851
|
+
await streamingEngine.start();
|
|
852
|
+
playing = true;
|
|
853
|
+
await runTest();
|
|
854
|
+
|
|
855
|
+
// The end of the stream should have been reached, and the 4th segment from
|
|
856
|
+
// each type should never have been requested.
|
|
857
|
+
expect(mediaSourceEngine.endOfStream).toHaveBeenCalled();
|
|
858
|
+
|
|
859
|
+
const segmentType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
|
|
860
|
+
|
|
861
|
+
netEngine.expectRequest('0_audio_0', segmentType);
|
|
862
|
+
netEngine.expectRequest('0_video_0', segmentType);
|
|
863
|
+
netEngine.expectRequest('0_text_0', segmentType);
|
|
864
|
+
|
|
865
|
+
netEngine.expectRequest('0_audio_1', segmentType);
|
|
866
|
+
netEngine.expectRequest('0_video_1', segmentType);
|
|
867
|
+
netEngine.expectRequest('0_text_1', segmentType);
|
|
868
|
+
|
|
869
|
+
netEngine.expectRequest('1_audio_2', segmentType);
|
|
870
|
+
netEngine.expectRequest('1_video_2', segmentType);
|
|
871
|
+
netEngine.expectRequest('1_text_2', segmentType);
|
|
872
|
+
|
|
873
|
+
netEngine.expectNoRequest('1_audio_3', segmentType);
|
|
874
|
+
netEngine.expectNoRequest('1_video_3', segmentType);
|
|
875
|
+
netEngine.expectNoRequest('1_text_3', segmentType);
|
|
876
|
+
});
|
|
877
|
+
|
|
825
878
|
it('does not buffer one media type ahead of another', async () => {
|
|
826
879
|
setupVod();
|
|
827
880
|
mediaSourceEngine = new shaka.test.FakeMediaSourceEngine(segmentData);
|
|
@@ -1389,6 +1442,66 @@ describe('StreamingEngine', () => {
|
|
|
1389
1442
|
});
|
|
1390
1443
|
});
|
|
1391
1444
|
|
|
1445
|
+
it('into unbuffered regions when nothing is buffered ' +
|
|
1446
|
+
'and mediaState is performing an update', async () => {
|
|
1447
|
+
// Here we go!
|
|
1448
|
+
streamingEngine.switchVariant(variant);
|
|
1449
|
+
streamingEngine.switchTextStream(textStream);
|
|
1450
|
+
// ensure init source buffer promise does not resolve before seeked()
|
|
1451
|
+
// so mediaState remains in "performingUpdate" state
|
|
1452
|
+
const initSourceBufferPromise = new shaka.util.PublicPromise();
|
|
1453
|
+
mediaSourceEngine.setStreamProperties.and
|
|
1454
|
+
.returnValue(initSourceBufferPromise);
|
|
1455
|
+
await streamingEngine.start();
|
|
1456
|
+
playing = true;
|
|
1457
|
+
|
|
1458
|
+
// tick to trigger mediaState updates
|
|
1459
|
+
jasmine.clock().tick(1);
|
|
1460
|
+
// give a chance for fetchAndAppend_ to be invoked
|
|
1461
|
+
// by async onUpdate_ callback
|
|
1462
|
+
await Util.shortDelay(realSetTimeout);
|
|
1463
|
+
|
|
1464
|
+
// Nothing is buffered yet.
|
|
1465
|
+
expect(mediaSourceEngine.segments).toEqual({
|
|
1466
|
+
audio: [false, false, false, false],
|
|
1467
|
+
video: [false, false, false, false],
|
|
1468
|
+
text: [false, false, false, false],
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
// Seek forward to an unbuffered region in the first Period.
|
|
1472
|
+
presentationTimeInSeconds = 15;
|
|
1473
|
+
streamingEngine.seeked();
|
|
1474
|
+
|
|
1475
|
+
// resolve initSourceBufferPromise after seeked(), waitingToClearBuffer
|
|
1476
|
+
// should have been set, so this will now trigger the actual flush of
|
|
1477
|
+
// the buffer
|
|
1478
|
+
initSourceBufferPromise.resolve();
|
|
1479
|
+
mediaSourceEngine.setStreamProperties.and
|
|
1480
|
+
.returnValue(Promise.resolve());
|
|
1481
|
+
|
|
1482
|
+
// allow mediaState update to resolve
|
|
1483
|
+
await Util.shortDelay(realSetTimeout);
|
|
1484
|
+
|
|
1485
|
+
onTick.and.callFake(() => {
|
|
1486
|
+
expect(mediaSourceEngine.clear).toHaveBeenCalled();
|
|
1487
|
+
onTick.and.stub();
|
|
1488
|
+
});
|
|
1489
|
+
|
|
1490
|
+
await runTest(Util.spyFunc(onTick));
|
|
1491
|
+
|
|
1492
|
+
// Verify buffers.
|
|
1493
|
+
expect(mediaSourceEngine.initSegments).toEqual({
|
|
1494
|
+
audio: [false, true],
|
|
1495
|
+
video: [false, true],
|
|
1496
|
+
text: [],
|
|
1497
|
+
});
|
|
1498
|
+
expect(mediaSourceEngine.segments).toEqual({
|
|
1499
|
+
audio: [false, true, true, true],
|
|
1500
|
+
video: [false, true, true, true],
|
|
1501
|
+
text: [false, true, true, true],
|
|
1502
|
+
});
|
|
1503
|
+
});
|
|
1504
|
+
|
|
1392
1505
|
it('into unbuffered regions near segment start', async () => {
|
|
1393
1506
|
// Here we go!
|
|
1394
1507
|
streamingEngine.switchVariant(variant);
|
|
@@ -3388,6 +3501,40 @@ describe('StreamingEngine', () => {
|
|
|
3388
3501
|
segmentAvailability.end++;
|
|
3389
3502
|
}
|
|
3390
3503
|
|
|
3504
|
+
/**
|
|
3505
|
+
* @param {!shaka.test.FakeNetworkingEngine} netEngine A NetworkingEngine
|
|
3506
|
+
* look-alike.
|
|
3507
|
+
* @param {string} targetUri
|
|
3508
|
+
* @param {shaka.util.Error.Code=} errorCode
|
|
3509
|
+
*/
|
|
3510
|
+
function failRequestsForTarget(
|
|
3511
|
+
netEngine, targetUri, errorCode=shaka.util.Error.Code.BAD_HTTP_STATUS) {
|
|
3512
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
3513
|
+
const originalNetEngineRequest = netEngine.request.bind(netEngine);
|
|
3514
|
+
|
|
3515
|
+
netEngine.request = jasmine.createSpy('request').and.callFake(
|
|
3516
|
+
(requestType, request) => {
|
|
3517
|
+
if (request.uris[0] == targetUri) {
|
|
3518
|
+
const data = [targetUri];
|
|
3519
|
+
|
|
3520
|
+
if (errorCode == shaka.util.Error.Code.BAD_HTTP_STATUS) {
|
|
3521
|
+
data.push(404);
|
|
3522
|
+
data.push('');
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
// The compiler still sees the error code parameter as potentially
|
|
3526
|
+
// undefined, even though we gave it a default value.
|
|
3527
|
+
goog.asserts.assert(errorCode != undefined, 'Undefined error code');
|
|
3528
|
+
|
|
3529
|
+
return shaka.util.AbortableOperation.failed(new shaka.util.Error(
|
|
3530
|
+
shaka.util.Error.Severity.CRITICAL,
|
|
3531
|
+
shaka.util.Error.Category.NETWORK,
|
|
3532
|
+
errorCode, data));
|
|
3533
|
+
}
|
|
3534
|
+
return originalNetEngineRequest(requestType, request);
|
|
3535
|
+
});
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3391
3538
|
/**
|
|
3392
3539
|
* @param {!shaka.test.FakeNetworkingEngine} netEngine A NetworkingEngine
|
|
3393
3540
|
* look-alike.
|
|
@@ -26,6 +26,9 @@ function httpPluginTests(usingFetch) {
|
|
|
26
26
|
// A dummy progress callback.
|
|
27
27
|
const progressUpdated = (elapsedMs, bytes, bytesRemaining) => {};
|
|
28
28
|
|
|
29
|
+
// A dummy headers callback.
|
|
30
|
+
const headersReceived = (headers) => {};
|
|
31
|
+
|
|
29
32
|
/** @type {shaka.extern.RetryParameters} */
|
|
30
33
|
let retryParameters;
|
|
31
34
|
|
|
@@ -168,7 +171,8 @@ function httpPluginTests(usingFetch) {
|
|
|
168
171
|
request.method = 'POST';
|
|
169
172
|
request.headers['BAZ'] = '123';
|
|
170
173
|
|
|
171
|
-
await plugin(
|
|
174
|
+
await plugin(
|
|
175
|
+
request.uris[0], request, requestType, progressUpdated, headersReceived)
|
|
172
176
|
.promise;
|
|
173
177
|
|
|
174
178
|
const actual = mostRecentRequest();
|
|
@@ -189,8 +193,8 @@ function httpPluginTests(usingFetch) {
|
|
|
189
193
|
request.body = null;
|
|
190
194
|
request.method = 'GET';
|
|
191
195
|
|
|
192
|
-
await plugin(request.uris[0], request, requestType, progressUpdated
|
|
193
|
-
.promise;
|
|
196
|
+
await plugin(request.uris[0], request, requestType, progressUpdated,
|
|
197
|
+
headersReceived).promise;
|
|
194
198
|
|
|
195
199
|
const actual = jasmine.Fetch.requests.mostRecent();
|
|
196
200
|
expect(actual).toBeTruthy();
|
|
@@ -205,8 +209,8 @@ function httpPluginTests(usingFetch) {
|
|
|
205
209
|
|
|
206
210
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
207
211
|
[uri], retryParameters, Util.spyFunc(streamDataCallback));
|
|
208
|
-
const response =
|
|
209
|
-
|
|
212
|
+
const response = await plugin(
|
|
213
|
+
uri, request, requestType, progressUpdated, headersReceived).promise;
|
|
210
214
|
|
|
211
215
|
expect(mostRecentRequest().url).toBe(uri);
|
|
212
216
|
expect(response).toBeTruthy();
|
|
@@ -297,9 +301,9 @@ function httpPluginTests(usingFetch) {
|
|
|
297
301
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
298
302
|
['https://foo.bar/cache'], retryParameters);
|
|
299
303
|
|
|
300
|
-
const response =
|
|
301
|
-
|
|
302
|
-
|
|
304
|
+
const response = await plugin(
|
|
305
|
+
request.uris[0], request, requestType, progressUpdated, headersReceived)
|
|
306
|
+
.promise;
|
|
303
307
|
expect(response).toBeTruthy();
|
|
304
308
|
expect(response.fromCache).toBe(true);
|
|
305
309
|
});
|
|
@@ -312,8 +316,8 @@ function httpPluginTests(usingFetch) {
|
|
|
312
316
|
uri = 'https://foo.bar/timeout';
|
|
313
317
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
314
318
|
[uri], retryParameters);
|
|
315
|
-
const operation = plugin(
|
|
316
|
-
|
|
319
|
+
const operation = plugin(request.uris[0], request, requestType,
|
|
320
|
+
progressUpdated, headersReceived);
|
|
317
321
|
|
|
318
322
|
/** @type {jasmine.Fetch.RequestStub} */
|
|
319
323
|
const actual = jasmine.Fetch.requests.mostRecent();
|
|
@@ -354,8 +358,8 @@ function httpPluginTests(usingFetch) {
|
|
|
354
358
|
uri = 'https://foo.bar/';
|
|
355
359
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
356
360
|
[uri], retryParameters);
|
|
357
|
-
operation = plugin(
|
|
358
|
-
|
|
361
|
+
operation = plugin(request.uris[0], request, requestType, progressUpdated,
|
|
362
|
+
headersReceived);
|
|
359
363
|
requestPromise = operation.promise;
|
|
360
364
|
}
|
|
361
365
|
|
|
@@ -388,8 +392,8 @@ function httpPluginTests(usingFetch) {
|
|
|
388
392
|
async function testSucceeds(uri, overrideUri) {
|
|
389
393
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
390
394
|
[uri], retryParameters);
|
|
391
|
-
const response =
|
|
392
|
-
|
|
395
|
+
const response = await plugin(
|
|
396
|
+
uri, request, requestType, progressUpdated, headersReceived).promise;
|
|
393
397
|
|
|
394
398
|
expect(mostRecentRequest().url).toBe(uri);
|
|
395
399
|
expect(response).toBeTruthy();
|
|
@@ -410,7 +414,8 @@ function httpPluginTests(usingFetch) {
|
|
|
410
414
|
const request = shaka.net.NetworkingEngine.makeRequest(
|
|
411
415
|
[uri], retryParameters);
|
|
412
416
|
|
|
413
|
-
const p = plugin(
|
|
417
|
+
const p = plugin(
|
|
418
|
+
uri, request, requestType, progressUpdated, headersReceived).promise;
|
|
414
419
|
if (expected.code == shaka.util.Error.Code.TIMEOUT) {
|
|
415
420
|
jasmine.clock().tick(5000);
|
|
416
421
|
}
|
|
@@ -22,10 +22,12 @@ goog.require('shaka.test.ManifestGenerator');
|
|
|
22
22
|
goog.require('shaka.test.TestScheme');
|
|
23
23
|
goog.require('shaka.test.Util');
|
|
24
24
|
goog.require('shaka.util.AbortableOperation');
|
|
25
|
+
goog.require('shaka.util.BufferUtils');
|
|
25
26
|
goog.require('shaka.util.Error');
|
|
26
27
|
goog.require('shaka.util.EventManager');
|
|
27
28
|
goog.require('shaka.util.PlayerConfiguration');
|
|
28
29
|
goog.require('shaka.util.PublicPromise');
|
|
30
|
+
goog.require('shaka.util.Uint8ArrayUtils');
|
|
29
31
|
goog.requireType('shaka.media.SegmentReference');
|
|
30
32
|
|
|
31
33
|
/** @return {boolean} */
|
|
@@ -58,12 +60,16 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
58
60
|
const manifestWithNonZeroStartUri = 'fake:manifest-with-non-zero-start';
|
|
59
61
|
const manifestWithLiveTimelineUri = 'fake:manifest-with-live-timeline';
|
|
60
62
|
const manifestWithAlternateSegmentsUri = 'fake:manifest-with-alt-segments';
|
|
63
|
+
const manifestWithVideoInitSegmentsUri =
|
|
64
|
+
'fake:manifest-with-video-init-segments';
|
|
61
65
|
|
|
66
|
+
const initSegmentUri = 'fake:init-segment';
|
|
62
67
|
const segment1Uri = 'fake:segment-1';
|
|
63
68
|
const segment2Uri = 'fake:segment-2';
|
|
64
69
|
const segment3Uri = 'fake:segment-3';
|
|
65
70
|
const segment4Uri = 'fake:segment-4';
|
|
66
71
|
|
|
72
|
+
const alternateInitSegmentUri = 'fake:alt-init-segment';
|
|
67
73
|
const alternateSegment1Uri = 'fake:alt-segment-1';
|
|
68
74
|
const alternateSegment2Uri = 'fake:alt-segment-2';
|
|
69
75
|
const alternateSegment3Uri = 'fake:alt-segment-3';
|
|
@@ -945,6 +951,46 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
945
951
|
}
|
|
946
952
|
});
|
|
947
953
|
|
|
954
|
+
it('can extract DRM info from segments', async () => {
|
|
955
|
+
const pssh1 =
|
|
956
|
+
'00000028' + // atom size
|
|
957
|
+
'70737368' + // atom type='pssh'
|
|
958
|
+
'00000000' + // v0, flags=0
|
|
959
|
+
'edef8ba979d64acea3c827dcd51d21ed' + // system id (Widevine)
|
|
960
|
+
'00000008' + // data size
|
|
961
|
+
'0102030405060708'; // data
|
|
962
|
+
const psshData1 = shaka.util.Uint8ArrayUtils.fromHex(pssh1);
|
|
963
|
+
const pssh2 =
|
|
964
|
+
'00000028' + // atom size
|
|
965
|
+
'70737368' + // atom type='pssh'
|
|
966
|
+
'00000000' + // v0, flags=0
|
|
967
|
+
'edef8ba979d64acea3c827dcd51d21ed' + // system id (Widevine)
|
|
968
|
+
'00000008' + // data size
|
|
969
|
+
'1337420123456789'; // data
|
|
970
|
+
const psshData2 = shaka.util.Uint8ArrayUtils.fromHex(pssh2);
|
|
971
|
+
netEngine.setResponseValue(initSegmentUri,
|
|
972
|
+
shaka.util.BufferUtils.toArrayBuffer(psshData1));
|
|
973
|
+
netEngine.setResponseValue(alternateInitSegmentUri,
|
|
974
|
+
shaka.util.BufferUtils.toArrayBuffer(psshData2));
|
|
975
|
+
|
|
976
|
+
const drm = new shaka.test.FakeDrmEngine();
|
|
977
|
+
const drmInfo = makeDrmInfo();
|
|
978
|
+
drmInfo.keySystem = 'com.widevine.alpha';
|
|
979
|
+
drm.setDrmInfo(drmInfo);
|
|
980
|
+
overrideDrmAndManifest(
|
|
981
|
+
storage,
|
|
982
|
+
drm,
|
|
983
|
+
makeManifestWithVideoInitSegments());
|
|
984
|
+
|
|
985
|
+
const stored = await storage.store(
|
|
986
|
+
manifestWithVideoInitSegmentsUri, noMetadata, fakeMimeType).promise;
|
|
987
|
+
goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
|
|
988
|
+
|
|
989
|
+
// The manifest chooses the alternate stream, so expect only the alt init
|
|
990
|
+
// segment.
|
|
991
|
+
expect(drm.newInitData).toHaveBeenCalledWith('cenc', psshData2);
|
|
992
|
+
});
|
|
993
|
+
|
|
948
994
|
it('can store multiple assets at once', async () => {
|
|
949
995
|
// Block the network so that we won't finish the first store command.
|
|
950
996
|
/** @type {!shaka.util.PublicPromise} */
|
|
@@ -1234,11 +1280,11 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1234
1280
|
goog.asserts.assert(
|
|
1235
1281
|
content.offlineUri != null, 'URI should not be null!');
|
|
1236
1282
|
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1283
|
+
// We expect 5 progress events because there are 4 unique segments, plus
|
|
1284
|
+
// the manifest.
|
|
1285
|
+
/** @type {!Array.<number>}*/
|
|
1240
1286
|
const progressSteps = [
|
|
1241
|
-
0.
|
|
1287
|
+
0.2, 0.4, 0.6, 0.8, 1,
|
|
1242
1288
|
];
|
|
1243
1289
|
|
|
1244
1290
|
const progressCallback = (content, progress) => {
|
|
@@ -1399,6 +1445,62 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1399
1445
|
};
|
|
1400
1446
|
}
|
|
1401
1447
|
|
|
1448
|
+
/** @return {shaka.extern.Manifest} */
|
|
1449
|
+
function makeManifestWithVideoInitSegments() {
|
|
1450
|
+
const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
1451
|
+
manifest.presentationTimeline.setDuration(20);
|
|
1452
|
+
|
|
1453
|
+
manifest.addVariant(0, (variant) => {
|
|
1454
|
+
variant.bandwidth = kbps(13);
|
|
1455
|
+
variant.addVideo(1, (stream) => {
|
|
1456
|
+
stream.bandwidth = kbps(13);
|
|
1457
|
+
stream.size(100, 200);
|
|
1458
|
+
});
|
|
1459
|
+
});
|
|
1460
|
+
manifest.addVariant(2, (variant) => {
|
|
1461
|
+
variant.bandwidth = kbps(20);
|
|
1462
|
+
variant.addVideo(3, (stream) => {
|
|
1463
|
+
stream.bandwidth = kbps(20);
|
|
1464
|
+
stream.size(200, 400);
|
|
1465
|
+
});
|
|
1466
|
+
});
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1469
|
+
const stream = manifest.variants[0].video;
|
|
1470
|
+
goog.asserts.assert(stream, 'The first stream should exist');
|
|
1471
|
+
stream.encrypted = true;
|
|
1472
|
+
const init = new shaka.media.InitSegmentReference(
|
|
1473
|
+
() => [initSegmentUri], 0, null);
|
|
1474
|
+
const refs = [
|
|
1475
|
+
makeReference(segment1Uri, 0, 1),
|
|
1476
|
+
makeReference(segment2Uri, 1, 2),
|
|
1477
|
+
makeReference(segment3Uri, 2, 3),
|
|
1478
|
+
makeReference(segment4Uri, 3, 4),
|
|
1479
|
+
];
|
|
1480
|
+
for (const ref of refs) {
|
|
1481
|
+
ref.initSegmentReference = init;
|
|
1482
|
+
}
|
|
1483
|
+
overrideSegmentIndex(stream, refs);
|
|
1484
|
+
|
|
1485
|
+
const streamAlt = manifest.variants[1].video;
|
|
1486
|
+
goog.asserts.assert(streamAlt, 'The second stream should exist');
|
|
1487
|
+
streamAlt.encrypted = true;
|
|
1488
|
+
const initAlt = new shaka.media.InitSegmentReference(
|
|
1489
|
+
() => [alternateInitSegmentUri], 0, null);
|
|
1490
|
+
const refsAlt = [
|
|
1491
|
+
makeReference(alternateSegment1Uri, 0, 1),
|
|
1492
|
+
makeReference(alternateSegment2Uri, 1, 2),
|
|
1493
|
+
makeReference(alternateSegment3Uri, 2, 3),
|
|
1494
|
+
makeReference(alternateSegment4Uri, 3, 4),
|
|
1495
|
+
];
|
|
1496
|
+
for (const ref of refsAlt) {
|
|
1497
|
+
ref.initSegmentReference = initAlt;
|
|
1498
|
+
}
|
|
1499
|
+
overrideSegmentIndex(streamAlt, refsAlt);
|
|
1500
|
+
|
|
1501
|
+
return manifest;
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1402
1504
|
/** @return {shaka.extern.Manifest} */
|
|
1403
1505
|
function makeManifestWithPerStreamBandwidth() {
|
|
1404
1506
|
const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
|
|
@@ -1612,6 +1714,8 @@ filterDescribe('Storage', storageSupport, () => {
|
|
|
1612
1714
|
makeManifestWithLiveTimeline();
|
|
1613
1715
|
this.map_[manifestWithAlternateSegmentsUri] =
|
|
1614
1716
|
makeManifestWithAlternateSegments();
|
|
1717
|
+
this.map_[manifestWithVideoInitSegmentsUri] =
|
|
1718
|
+
makeManifestWithVideoInitSegments();
|
|
1615
1719
|
}
|
|
1616
1720
|
|
|
1617
1721
|
/** @override */
|
|
@@ -87,6 +87,41 @@ describe('Player', () => {
|
|
|
87
87
|
});
|
|
88
88
|
}); // describe('attach')
|
|
89
89
|
|
|
90
|
+
describe('updateStartTime() in manifestparsed event handler', () => {
|
|
91
|
+
it('does not get segments prior to startTime', async () => {
|
|
92
|
+
player.addEventListener('manifestparsed', () => {
|
|
93
|
+
player.updateStartTime(24);
|
|
94
|
+
});
|
|
95
|
+
const results = {
|
|
96
|
+
requestedVideoSegment0: false,
|
|
97
|
+
requestedVideoSegment1: false,
|
|
98
|
+
requestedVideoSegment2: false,
|
|
99
|
+
};
|
|
100
|
+
const expected = {
|
|
101
|
+
requestedVideoSegment0: false,
|
|
102
|
+
requestedVideoSegment1: false,
|
|
103
|
+
requestedVideoSegment2: true,
|
|
104
|
+
};
|
|
105
|
+
player.getNetworkingEngine().registerRequestFilter(
|
|
106
|
+
(type, request) => {
|
|
107
|
+
if (request.uris[0] == 'test:sintel/video/0') {
|
|
108
|
+
results.requestedVideoSegment0 = true;
|
|
109
|
+
}
|
|
110
|
+
if (request.uris[0] == 'test:sintel/video/1') {
|
|
111
|
+
results.requestedVideoSegment1 = true;
|
|
112
|
+
}
|
|
113
|
+
if (request.uris[0] == 'test:sintel/video/2') {
|
|
114
|
+
results.requestedVideoSegment2 = true;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
await player.load('test:sintel_compiled');
|
|
118
|
+
video.play();
|
|
119
|
+
await waiter.waitUntilPlayheadReachesOrFailOnTimeout(video, 25, 30);
|
|
120
|
+
expect(results).toEqual(expected);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
|
|
90
125
|
describe('getStats', () => {
|
|
91
126
|
it('gives stats about current stream', async () => {
|
|
92
127
|
// This is tested more in player_unit.js. This is here to test the public
|
|
@@ -652,6 +687,108 @@ describe('Player', () => {
|
|
|
652
687
|
});
|
|
653
688
|
});
|
|
654
689
|
|
|
690
|
+
describe('mediaQualityChanges', () => {
|
|
691
|
+
/** @type {!jasmine.Spy} */
|
|
692
|
+
let onQualityChange;
|
|
693
|
+
/** @type {!shaka.test.Waiter} */
|
|
694
|
+
let waiter;
|
|
695
|
+
|
|
696
|
+
const qualityChange1 = jasmine.objectContaining({
|
|
697
|
+
mediaQuality: jasmine.objectContaining({
|
|
698
|
+
bandwidth: 1,
|
|
699
|
+
codecs: 'mp4a.40.2',
|
|
700
|
+
contentType: 'audio',
|
|
701
|
+
mimeType: 'audio/mp4',
|
|
702
|
+
}),
|
|
703
|
+
type: 'mediaqualitychanged',
|
|
704
|
+
position: jasmine.any(Number),
|
|
705
|
+
});
|
|
706
|
+
const qualityChange2 = jasmine.objectContaining({
|
|
707
|
+
mediaQuality: jasmine.objectContaining({
|
|
708
|
+
bandwidth: 1,
|
|
709
|
+
codecs: 'avc1.42c01e',
|
|
710
|
+
contentType: 'video',
|
|
711
|
+
mimeType: 'video/mp4',
|
|
712
|
+
}),
|
|
713
|
+
type: 'mediaqualitychanged',
|
|
714
|
+
position: jasmine.any(Number),
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
beforeEach(() => {
|
|
718
|
+
onQualityChange = jasmine.createSpy('onQualityChange');
|
|
719
|
+
// const spyFunc = Util.spyFunc(onQualityChange);
|
|
720
|
+
player.addEventListener('mediaqualitychanged',
|
|
721
|
+
Util.spyFunc(onQualityChange));
|
|
722
|
+
waiter = new shaka.test.Waiter(eventManager)
|
|
723
|
+
.timeoutAfter(10)
|
|
724
|
+
.failOnTimeout(true);
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
it('emits audio/video quality changes at start when enabled', async () => {
|
|
728
|
+
player.configure('streaming.observeQualityChanges', true);
|
|
729
|
+
|
|
730
|
+
await player.load('test:sintel_compiled');
|
|
731
|
+
video.play();
|
|
732
|
+
|
|
733
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
734
|
+
// seconds, fail the test.
|
|
735
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
736
|
+
expect(onQualityChange).toHaveBeenCalledTimes(2);
|
|
737
|
+
expect(onQualityChange).toHaveBeenCalledWith(qualityChange1);
|
|
738
|
+
expect(onQualityChange).toHaveBeenCalledWith(qualityChange2);
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
it('does not emit quality changes at start when disabled', async () => {
|
|
742
|
+
player.configure('streaming.observeQualityChanges', false);
|
|
743
|
+
|
|
744
|
+
await player.load('test:sintel_compiled');
|
|
745
|
+
video.play();
|
|
746
|
+
|
|
747
|
+
// Wait for the video to start playback. If it takes longer than 10
|
|
748
|
+
// seconds, fail the test.
|
|
749
|
+
await waiter.waitForMovementOrFailOnTimeout(video, 10);
|
|
750
|
+
expect(onQualityChange).not.toHaveBeenCalled();
|
|
751
|
+
});
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
describe('seek range', () => {
|
|
755
|
+
// Regression test for Issue #3675.
|
|
756
|
+
it('has a reasonable seek range after going from live to VOD', async () => {
|
|
757
|
+
const netEngine = player.getNetworkingEngine();
|
|
758
|
+
const startTime = Date.now();
|
|
759
|
+
netEngine.registerRequestFilter((type, request) => {
|
|
760
|
+
if (type != shaka.net.NetworkingEngine.RequestType.MANIFEST) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
// Simulate a live stream by providing different manifests over time.
|
|
764
|
+
const time = (Date.now() - startTime) / 1000;
|
|
765
|
+
const manifestNumber = Math.min(5, Math.floor(0.5 + time / 2));
|
|
766
|
+
request.uris = [
|
|
767
|
+
'/base/test/test/assets/3675/dash_' + manifestNumber + '.mpd',
|
|
768
|
+
];
|
|
769
|
+
console.log('getting manifest', request.uris);
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
// Play the stream.
|
|
773
|
+
await player.load('/base/test/test/assets/3675/dash_0.mpd');
|
|
774
|
+
video.play();
|
|
775
|
+
|
|
776
|
+
// Wait for the stream to be over.
|
|
777
|
+
eventManager.listen(player, 'error', Util.spyFunc(onErrorSpy));
|
|
778
|
+
/** @type {shaka.test.Waiter} */
|
|
779
|
+
const waiter = new shaka.test.Waiter(eventManager)
|
|
780
|
+
.timeoutAfter(20).failOnTimeout(true);
|
|
781
|
+
await waiter.waitForEnd(video);
|
|
782
|
+
|
|
783
|
+
// The stream should have transitioned to VOD by now.
|
|
784
|
+
expect(player.isLive()).toBe(false);
|
|
785
|
+
|
|
786
|
+
// Check that the final seek range is as expected.
|
|
787
|
+
const seekRange = player.seekRange();
|
|
788
|
+
expect(seekRange.end).toBe(14);
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
|
|
655
792
|
describe('buffering', () => {
|
|
656
793
|
const startBuffering = jasmine.objectContaining({buffering: true});
|
|
657
794
|
const endBuffering = jasmine.objectContaining({buffering: false});
|
|
@@ -926,9 +1063,9 @@ describe('Player', () => {
|
|
|
926
1063
|
it('add external chapters in vtt format', async () => {
|
|
927
1064
|
await player.load('test:sintel_no_text_compiled');
|
|
928
1065
|
const locationUri = new goog.Uri(location.href);
|
|
929
|
-
const
|
|
930
|
-
const
|
|
931
|
-
await player.addChaptersTrack(
|
|
1066
|
+
const partialUri1 = new goog.Uri('/base/test/test/assets/chapters.vtt');
|
|
1067
|
+
const absoluteUri1 = locationUri.resolve(partialUri1);
|
|
1068
|
+
await player.addChaptersTrack(absoluteUri1.toString(), 'en');
|
|
932
1069
|
|
|
933
1070
|
await shaka.test.Util.delay(1.5);
|
|
934
1071
|
|
|
@@ -941,11 +1078,44 @@ describe('Player', () => {
|
|
|
941
1078
|
const chapter2 = chapters[1];
|
|
942
1079
|
expect(chapter2.title).toBe('Chapter 2');
|
|
943
1080
|
expect(chapter2.startTime).toBe(5);
|
|
944
|
-
expect(chapter2.endTime).toBe(
|
|
1081
|
+
expect(chapter2.endTime).toBe(10);
|
|
945
1082
|
const chapter3 = chapters[2];
|
|
946
1083
|
expect(chapter3.title).toBe('Chapter 3');
|
|
947
|
-
expect(chapter3.startTime).toBe(
|
|
948
|
-
expect(chapter3.endTime).toBe(
|
|
1084
|
+
expect(chapter3.startTime).toBe(10);
|
|
1085
|
+
expect(chapter3.endTime).toBe(20);
|
|
1086
|
+
|
|
1087
|
+
const partialUri2 = new goog.Uri('/base/test/test/assets/chapters2.vtt');
|
|
1088
|
+
const absoluteUri2 = locationUri.resolve(partialUri2);
|
|
1089
|
+
await player.addChaptersTrack(absoluteUri2.toString(), 'en');
|
|
1090
|
+
|
|
1091
|
+
await shaka.test.Util.delay(1.5);
|
|
1092
|
+
|
|
1093
|
+
const chaptersUpdated = player.getChapters('en');
|
|
1094
|
+
expect(chaptersUpdated.length).toBe(6);
|
|
1095
|
+
const chapterUpdated1 = chaptersUpdated[0];
|
|
1096
|
+
expect(chapterUpdated1.title).toBe('Chapter 1');
|
|
1097
|
+
expect(chapterUpdated1.startTime).toBe(0);
|
|
1098
|
+
expect(chapterUpdated1.endTime).toBe(5);
|
|
1099
|
+
const chapterUpdated2 = chaptersUpdated[1];
|
|
1100
|
+
expect(chapterUpdated2.title).toBe('Chapter 2');
|
|
1101
|
+
expect(chapterUpdated2.startTime).toBe(5);
|
|
1102
|
+
expect(chapterUpdated2.endTime).toBe(10);
|
|
1103
|
+
const chapterUpdated3 = chaptersUpdated[2];
|
|
1104
|
+
expect(chapterUpdated3.title).toBe('Chapter 3');
|
|
1105
|
+
expect(chapterUpdated3.startTime).toBe(10);
|
|
1106
|
+
expect(chapterUpdated3.endTime).toBe(20);
|
|
1107
|
+
const chapterUpdated4 = chaptersUpdated[3];
|
|
1108
|
+
expect(chapterUpdated4.title).toBe('Chapter 4');
|
|
1109
|
+
expect(chapterUpdated4.startTime).toBe(20);
|
|
1110
|
+
expect(chapterUpdated4.endTime).toBe(30);
|
|
1111
|
+
const chapterUpdated5 = chaptersUpdated[4];
|
|
1112
|
+
expect(chapterUpdated5.title).toBe('Chapter 5');
|
|
1113
|
+
expect(chapterUpdated5.startTime).toBe(30);
|
|
1114
|
+
expect(chapterUpdated5.endTime).toBe(40);
|
|
1115
|
+
const chapterUpdated6 = chaptersUpdated[5];
|
|
1116
|
+
expect(chapterUpdated6.title).toBe('Chapter 6');
|
|
1117
|
+
expect(chapterUpdated6.startTime).toBe(40);
|
|
1118
|
+
expect(chapterUpdated6.endTime).toBe(61.349);
|
|
949
1119
|
});
|
|
950
1120
|
|
|
951
1121
|
it('add external chapters in srt format', async () => {
|
|
@@ -953,11 +1123,11 @@ describe('Player', () => {
|
|
|
953
1123
|
const locationUri = new goog.Uri(location.href);
|
|
954
1124
|
const partialUri = new goog.Uri('/base/test/test/assets/chapters.srt');
|
|
955
1125
|
const absoluteUri = locationUri.resolve(partialUri);
|
|
956
|
-
await player.addChaptersTrack(absoluteUri.toString(), '
|
|
1126
|
+
await player.addChaptersTrack(absoluteUri.toString(), 'es');
|
|
957
1127
|
|
|
958
1128
|
await shaka.test.Util.delay(1.5);
|
|
959
1129
|
|
|
960
|
-
const chapters = player.getChapters('
|
|
1130
|
+
const chapters = player.getChapters('es');
|
|
961
1131
|
expect(chapters.length).toBe(3);
|
|
962
1132
|
const chapter1 = chapters[0];
|
|
963
1133
|
expect(chapter1.title).toBe('Chapter 1');
|