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
package/lib/util/stream_utils.js
CHANGED
|
@@ -419,13 +419,48 @@ shaka.util.StreamUtils = class {
|
|
|
419
419
|
*/
|
|
420
420
|
static async filterManifestByMediaCapabilities(
|
|
421
421
|
manifest, usePersistentLicenses) {
|
|
422
|
-
goog.asserts.assert(
|
|
422
|
+
goog.asserts.assert(navigator.mediaCapabilities,
|
|
423
423
|
'MediaCapabilities should be valid.');
|
|
424
424
|
|
|
425
425
|
await shaka.util.StreamUtils.getDecodingInfosForVariants(
|
|
426
426
|
manifest.variants, usePersistentLicenses, /* srcEquals= */ false);
|
|
427
427
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
428
|
+
// See: https://github.com/google/shaka-player/issues/3860
|
|
428
429
|
const video = variant.video;
|
|
430
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
431
|
+
if (video) {
|
|
432
|
+
let videoCodecs = shaka.util.StreamUtils.patchVp9(video.codecs);
|
|
433
|
+
// For multiplexed streams. Here we must check the audio of the
|
|
434
|
+
// stream to see if it is compatible.
|
|
435
|
+
if (video.codecs.includes(',')) {
|
|
436
|
+
const allCodecs = video.codecs.split(',');
|
|
437
|
+
videoCodecs = shaka.util.ManifestParserUtils.guessCodecs(
|
|
438
|
+
ContentType.VIDEO, allCodecs);
|
|
439
|
+
const audioCodecs = shaka.util.ManifestParserUtils.guessCodecs(
|
|
440
|
+
ContentType.AUDIO, allCodecs);
|
|
441
|
+
const audioFullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
442
|
+
video.mimeType, audioCodecs, ContentType.AUDIO);
|
|
443
|
+
if (!MediaSource.isTypeSupported(audioFullType)) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
448
|
+
video.mimeType, videoCodecs, ContentType.VIDEO);
|
|
449
|
+
if (!MediaSource.isTypeSupported(fullType)) {
|
|
450
|
+
return false;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
const audio = variant.audio;
|
|
454
|
+
if (audio) {
|
|
455
|
+
const codecs =
|
|
456
|
+
shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
457
|
+
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
458
|
+
audio.mimeType, codecs, ContentType.AUDIO);
|
|
459
|
+
if (!MediaSource.isTypeSupported(fullType)) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
429
464
|
// See: https://github.com/google/shaka-player/issues/3380
|
|
430
465
|
if (shaka.util.Platform.isXboxOne() && video &&
|
|
431
466
|
((video.width && video.width > 1920) ||
|
|
@@ -468,7 +503,7 @@ shaka.util.StreamUtils = class {
|
|
|
468
503
|
return;
|
|
469
504
|
}
|
|
470
505
|
|
|
471
|
-
const mediaCapabilities =
|
|
506
|
+
const mediaCapabilities = navigator.mediaCapabilities;
|
|
472
507
|
|
|
473
508
|
const operations = [];
|
|
474
509
|
const getVariantDecodingInfos = (async (variant, decodingConfig) => {
|
|
@@ -547,14 +582,23 @@ shaka.util.StreamUtils = class {
|
|
|
547
582
|
// framerate must be greater than 0, otherwise the config is invalid.
|
|
548
583
|
framerate: video.frameRate || 1,
|
|
549
584
|
};
|
|
585
|
+
if (video.hdr) {
|
|
586
|
+
switch (video.hdr) {
|
|
587
|
+
case 'SDR':
|
|
588
|
+
mediaDecodingConfig.video.transferFunction = 'srgb';
|
|
589
|
+
break;
|
|
590
|
+
case 'PQ':
|
|
591
|
+
mediaDecodingConfig.video.transferFunction = 'pq';
|
|
592
|
+
break;
|
|
593
|
+
case 'HLG':
|
|
594
|
+
mediaDecodingConfig.video.transferFunction = 'hlg';
|
|
595
|
+
break;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
550
598
|
}
|
|
551
599
|
if (audio) {
|
|
552
|
-
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
553
|
-
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
554
|
-
// See https://github.com/google/shaka-player/issues/2989 for details.
|
|
555
600
|
const codecs =
|
|
556
|
-
(audio.codecs
|
|
557
|
-
shaka.util.Platform.isTizen()) ? 'ec-3' : audio.codecs;
|
|
601
|
+
shaka.util.StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
558
602
|
const fullType = shaka.util.MimeUtils.getFullOrConvertedType(
|
|
559
603
|
audio.mimeType, codecs, ContentType.AUDIO);
|
|
560
604
|
|
|
@@ -665,6 +709,26 @@ shaka.util.StreamUtils = class {
|
|
|
665
709
|
return configs;
|
|
666
710
|
}
|
|
667
711
|
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Generates the correct audio codec for MediaDecodingConfiguration and
|
|
715
|
+
* for MediaSource.isTypeSupported.
|
|
716
|
+
* @param {string} codecs
|
|
717
|
+
* @return {string}
|
|
718
|
+
* @private
|
|
719
|
+
*/
|
|
720
|
+
static getCorrectAudioCodecs_(codecs) {
|
|
721
|
+
// Some Tizen devices seem to misreport AC-3 support, but correctly
|
|
722
|
+
// report EC-3 support. So query EC-3 as a fallback for AC-3.
|
|
723
|
+
// See https://github.com/google/shaka-player/issues/2989 for details.
|
|
724
|
+
if (shaka.util.Platform.isTizen()) {
|
|
725
|
+
return codecs.toLowerCase() == 'ac-3' ? 'ec-3' : codecs;
|
|
726
|
+
} else {
|
|
727
|
+
return codecs;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
|
|
668
732
|
/**
|
|
669
733
|
* MediaCapabilities supports 'vp09...' codecs, but not 'vp9'. Translate vp9
|
|
670
734
|
* codec strings into 'vp09...', to allow such content to play with
|
|
@@ -976,6 +1040,31 @@ shaka.util.StreamUtils = class {
|
|
|
976
1040
|
static imageStreamToTrack(stream) {
|
|
977
1041
|
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
978
1042
|
|
|
1043
|
+
let width = stream.width || null;
|
|
1044
|
+
let height = stream.height || null;
|
|
1045
|
+
|
|
1046
|
+
// The stream width and height represent the size of the entire thumbnail
|
|
1047
|
+
// sheet, so divide by the layout.
|
|
1048
|
+
let reference = null;
|
|
1049
|
+
// Note: segmentIndex is built by default for HLS, but not for DASH, but
|
|
1050
|
+
// in DASH this information comes at the stream level and not at the
|
|
1051
|
+
// segment level.
|
|
1052
|
+
if (stream.segmentIndex) {
|
|
1053
|
+
reference = stream.segmentIndex.get(0);
|
|
1054
|
+
}
|
|
1055
|
+
let layout = stream.tilesLayout;
|
|
1056
|
+
if (reference) {
|
|
1057
|
+
layout = reference.getTilesLayout() || layout;
|
|
1058
|
+
}
|
|
1059
|
+
if (layout && width != null) {
|
|
1060
|
+
width /= Number(layout.split('x')[0]);
|
|
1061
|
+
}
|
|
1062
|
+
if (layout && height != null) {
|
|
1063
|
+
height /= Number(layout.split('x')[1]);
|
|
1064
|
+
}
|
|
1065
|
+
// TODO: What happens if there are multiple grids, with different
|
|
1066
|
+
// layout sizes, inside this image stream?
|
|
1067
|
+
|
|
979
1068
|
/** @type {shaka.extern.Track} */
|
|
980
1069
|
const track = {
|
|
981
1070
|
id: stream.id,
|
|
@@ -985,8 +1074,8 @@ shaka.util.StreamUtils = class {
|
|
|
985
1074
|
language: '',
|
|
986
1075
|
label: null,
|
|
987
1076
|
kind: null,
|
|
988
|
-
width
|
|
989
|
-
height
|
|
1077
|
+
width,
|
|
1078
|
+
height,
|
|
990
1079
|
frameRate: null,
|
|
991
1080
|
pixelAspectRatio: null,
|
|
992
1081
|
hdr: null,
|
|
@@ -1003,7 +1092,7 @@ shaka.util.StreamUtils = class {
|
|
|
1003
1092
|
channelsCount: null,
|
|
1004
1093
|
audioSamplingRate: null,
|
|
1005
1094
|
spatialAudio: false,
|
|
1006
|
-
tilesLayout:
|
|
1095
|
+
tilesLayout: layout || null,
|
|
1007
1096
|
audioBandwidth: null,
|
|
1008
1097
|
videoBandwidth: null,
|
|
1009
1098
|
originalVideoId: null,
|
package/lib/util/xml_utils.js
CHANGED
|
@@ -103,6 +103,25 @@ shaka.util.XmlUtils = class {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Gets a namespace-qualified attribute.
|
|
108
|
+
* @param {!Element} elem The element to get from.
|
|
109
|
+
* @param {!Array.<string>} nsList The lis of namespace URIs.
|
|
110
|
+
* @param {string} name The local name of the attribute.
|
|
111
|
+
* @return {?string} The attribute's value, or null if not present.
|
|
112
|
+
*/
|
|
113
|
+
static getAttributeNSList(elem, nsList, name) {
|
|
114
|
+
// Some browsers return the empty string when the attribute is missing,
|
|
115
|
+
// so check if it exists first. See: https://mzl.la/2L7F0UK
|
|
116
|
+
for (const ns of nsList) {
|
|
117
|
+
if (elem.hasAttributeNS(ns, name)) {
|
|
118
|
+
return elem.getAttributeNS(ns, name);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
106
125
|
/**
|
|
107
126
|
* Gets the text contents of a node.
|
|
108
127
|
* @param {!Node} elem The XML element.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shaka-player",
|
|
3
3
|
"description": "DASH/EME video player library",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.3.1",
|
|
5
5
|
"homepage": "https://github.com/google/shaka-player",
|
|
6
6
|
"author": "Google",
|
|
7
7
|
"maintainers": [
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@chiragrupani/karma-chromium-edge-launcher": "^2.1.0",
|
|
15
|
+
"@onslip/karma-safari-launcher": "^1.0.1",
|
|
15
16
|
"@teppeis/clutz": "^1.0.29-4c95e12.v20190929",
|
|
16
17
|
"awesomplete": "^1.1.4",
|
|
17
18
|
"babel-core": "^6.26.3",
|
|
@@ -44,7 +45,6 @@
|
|
|
44
45
|
"karma-jasmine": "^3.3.1",
|
|
45
46
|
"karma-jasmine-ajax": "^0.1.13",
|
|
46
47
|
"karma-opera-launcher": "^1.0.0",
|
|
47
|
-
"karma-safari-launcher": "^1.0.0",
|
|
48
48
|
"karma-sourcemap-loader": "^0.3.7",
|
|
49
49
|
"karma-spec-reporter": "0.0.32",
|
|
50
50
|
"karma-webdriver-launcher": "^1.0.8",
|
|
@@ -44,6 +44,7 @@ goog.require('shaka.polyfill.PatchedMediaKeysMs');
|
|
|
44
44
|
goog.require('shaka.polyfill.PatchedMediaKeysNop');
|
|
45
45
|
goog.require('shaka.polyfill.PatchedMediaKeysWebkit');
|
|
46
46
|
goog.require('shaka.polyfill.PiPWebkit');
|
|
47
|
+
goog.require('shaka.polyfill.RandomUUID');
|
|
47
48
|
goog.require('shaka.polyfill.VTTCue');
|
|
48
49
|
goog.require('shaka.polyfill.VideoPlayPromise');
|
|
49
50
|
goog.require('shaka.polyfill.VideoPlaybackQuality');
|
|
@@ -70,6 +71,7 @@ goog.require('shaka.ui.AdPosition');
|
|
|
70
71
|
goog.require('shaka.ui.AirPlayButton');
|
|
71
72
|
goog.require('shaka.ui.BigPlayButton');
|
|
72
73
|
goog.require('shaka.ui.CastButton');
|
|
74
|
+
goog.require('shaka.ui.ContextMenu');
|
|
73
75
|
goog.require('shaka.ui.Element');
|
|
74
76
|
goog.require('shaka.ui.FastForwardButton');
|
|
75
77
|
goog.require('shaka.ui.FullscreenButton');
|
|
@@ -85,6 +87,7 @@ goog.require('shaka.ui.RewindButton');
|
|
|
85
87
|
goog.require('shaka.ui.SkipAdButton');
|
|
86
88
|
goog.require('shaka.ui.SmallPlayButton');
|
|
87
89
|
goog.require('shaka.ui.Spacer');
|
|
90
|
+
goog.require('shaka.ui.StatisticsButton');
|
|
88
91
|
goog.require('shaka.ui.TextSelection');
|
|
89
92
|
goog.require('shaka.ui.VolumeBar');
|
|
90
93
|
goog.require('shaka.util.Dom');
|
|
@@ -297,7 +297,8 @@ describe('CastProxy', () => {
|
|
|
297
297
|
'timeupdate', Util.spyFunc(proxyListener));
|
|
298
298
|
|
|
299
299
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
300
|
-
const fakeEvent = new FakeEvent(
|
|
300
|
+
const fakeEvent = new FakeEvent(
|
|
301
|
+
'timeupdate', (new Map()).set('detail', 8675309));
|
|
301
302
|
mockVideo.on['timeupdate'](fakeEvent);
|
|
302
303
|
expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
303
304
|
type: 'timeupdate',
|
|
@@ -315,7 +316,8 @@ describe('CastProxy', () => {
|
|
|
315
316
|
mockSender.hasRemoteProperties.and.returnValue(true);
|
|
316
317
|
|
|
317
318
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
318
|
-
const fakeEvent = new FakeEvent(
|
|
319
|
+
const fakeEvent = new FakeEvent(
|
|
320
|
+
'timeupdate', (new Map()).set('detail', 8675309));
|
|
319
321
|
mockVideo.on['timeupdate'](fakeEvent);
|
|
320
322
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
321
323
|
});
|
|
@@ -332,7 +334,8 @@ describe('CastProxy', () => {
|
|
|
332
334
|
mockSender.hasRemoteProperties.and.returnValue(true);
|
|
333
335
|
|
|
334
336
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
335
|
-
const fakeEvent = new FakeEvent(
|
|
337
|
+
const fakeEvent = new FakeEvent(
|
|
338
|
+
'timeupdate', (new Map()).set('detail', 8675309));
|
|
336
339
|
mockSender.onRemoteEvent('video', fakeEvent);
|
|
337
340
|
expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
338
341
|
type: 'timeupdate',
|
|
@@ -446,7 +449,8 @@ describe('CastProxy', () => {
|
|
|
446
449
|
'buffering', Util.spyFunc(proxyListener));
|
|
447
450
|
|
|
448
451
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
449
|
-
const fakeEvent = new FakeEvent(
|
|
452
|
+
const fakeEvent = new FakeEvent(
|
|
453
|
+
'buffering', (new Map()).set('detail', 8675309));
|
|
450
454
|
mockPlayer.listeners['buffering'](fakeEvent);
|
|
451
455
|
expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
452
456
|
type: 'buffering',
|
|
@@ -464,7 +468,8 @@ describe('CastProxy', () => {
|
|
|
464
468
|
mockSender.hasRemoteProperties.and.returnValue(true);
|
|
465
469
|
|
|
466
470
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
467
|
-
const fakeEvent = new FakeEvent(
|
|
471
|
+
const fakeEvent = new FakeEvent(
|
|
472
|
+
'buffering', (new Map()).set('detail', 8675309));
|
|
468
473
|
mockPlayer.listeners['buffering'](fakeEvent);
|
|
469
474
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
470
475
|
});
|
|
@@ -481,7 +486,8 @@ describe('CastProxy', () => {
|
|
|
481
486
|
mockSender.hasRemoteProperties.and.returnValue(true);
|
|
482
487
|
|
|
483
488
|
expect(proxyListener).not.toHaveBeenCalled();
|
|
484
|
-
const fakeEvent = new FakeEvent(
|
|
489
|
+
const fakeEvent = new FakeEvent(
|
|
490
|
+
'buffering', (new Map()).set('detail', 8675309));
|
|
485
491
|
mockSender.onRemoteEvent('player', fakeEvent);
|
|
486
492
|
expect(proxyListener).toHaveBeenCalledWith(jasmine.objectContaining({
|
|
487
493
|
type: 'buffering',
|
|
@@ -123,7 +123,7 @@ describe('CastUtils', () => {
|
|
|
123
123
|
expect(typeof deserialized).toBe('object');
|
|
124
124
|
|
|
125
125
|
// The object can be used to construct a FakeEvent.
|
|
126
|
-
const fakeEvent =
|
|
126
|
+
const fakeEvent = FakeEvent.fromRealEvent(deserialized);
|
|
127
127
|
|
|
128
128
|
// The fake event has the same type and properties as the original.
|
|
129
129
|
const asObj = /** @type {!Object} */ (fakeEvent);
|
|
@@ -42,6 +42,8 @@ describe('DashParser ContentProtection', () => {
|
|
|
42
42
|
|
|
43
43
|
const playerInterface = {
|
|
44
44
|
networkingEngine: netEngine,
|
|
45
|
+
modifyManifestRequest: (request, manifestInfo) => {},
|
|
46
|
+
modifySegmentRequest: (request, segmentInfo) => {},
|
|
45
47
|
filter: (manifest) => Promise.resolve(),
|
|
46
48
|
makeTextStreamsForClosedCaptions: (manifest) => {},
|
|
47
49
|
onTimelineRegionAdded: fail, // Should not have any EventStream elements.
|
|
@@ -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 () => {
|