shaka-player 4.7.13 → 4.8.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/AUTHORS +2 -0
- package/CONTRIBUTORS +2 -0
- package/LICENSE +54 -0
- package/README.md +22 -1
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +34 -23
- package/dist/locales.js +41 -31
- package/dist/shaka-player.compiled.d.ts +196 -45
- package/dist/shaka-player.compiled.debug.d.ts +196 -45
- package/dist/shaka-player.compiled.debug.externs.js +491 -348
- package/dist/shaka-player.compiled.debug.js +969 -847
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +491 -348
- package/dist/shaka-player.compiled.js +1238 -1171
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +259 -48
- package/dist/shaka-player.ui.debug.d.ts +259 -48
- package/dist/shaka-player.ui.debug.externs.js +598 -377
- package/dist/shaka-player.ui.debug.js +1185 -980
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +598 -377
- package/dist/shaka-player.ui.js +1526 -1408
- package/dist/shaka-player.ui.map +4 -4
- package/externs/device_sensor_event.js +18 -0
- package/externs/hisense.js +16 -0
- package/externs/playstation.js +31 -0
- package/externs/shaka/abr_manager.js +3 -1
- package/externs/shaka/ads.js +5 -0
- package/externs/shaka/codecs.js +13 -0
- package/externs/shaka/manifest.js +58 -6
- package/externs/shaka/net.js +13 -1
- package/externs/shaka/player.js +184 -13
- package/externs/shaka/text.js +19 -0
- package/externs/tizen.js +41 -0
- package/externs/webos.js +19 -0
- package/externs/xbox.js +43 -0
- package/lib/abr/simple_abr_manager.js +9 -1
- package/lib/ads/ad_manager.js +19 -2
- package/lib/ads/client_side_ad_manager.js +5 -3
- package/lib/ads/media_tailor_ad_manager.js +9 -0
- package/lib/cast/cast_receiver.js +0 -14
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/mp4_cea_parser.js +6 -1
- package/lib/dash/content_protection.js +97 -53
- package/lib/dash/dash_parser.js +237 -177
- package/lib/dash/mpd_utils.js +72 -65
- package/lib/dash/segment_base.js +27 -21
- package/lib/dash/segment_list.js +18 -16
- package/lib/dash/segment_template.js +45 -22
- package/lib/hls/hls_parser.js +358 -164
- package/lib/media/buffering_observer.js +25 -1
- package/lib/media/drm_engine.js +91 -71
- package/lib/media/manifest_filterer.js +220 -0
- package/lib/media/media_source_engine.js +34 -5
- package/lib/media/preload_manager.js +827 -0
- package/lib/media/presentation_timeline.js +11 -0
- package/lib/media/segment_index.js +93 -47
- package/lib/media/segment_prefetch.js +140 -43
- package/lib/media/segment_reference.js +43 -8
- package/lib/media/segment_utils.js +208 -25
- package/lib/media/streaming_engine.js +355 -66
- package/lib/mss/content_protection.js +31 -25
- package/lib/mss/mss_parser.js +79 -55
- package/lib/net/networking_engine.js +49 -4
- package/lib/offline/storage.js +3 -3
- package/lib/player.js +882 -672
- package/lib/polyfill/media_capabilities.js +16 -1
- package/lib/text/simple_text_displayer.js +9 -0
- package/lib/text/stub_text_displayer.js +7 -0
- package/lib/text/text_engine.js +16 -3
- package/lib/text/ttml_text_parser.js +116 -114
- package/lib/text/ui_text_displayer.js +28 -11
- package/lib/text/vtt_text_parser.js +54 -115
- package/lib/transmuxer/opus.js +91 -0
- package/lib/transmuxer/ts_transmuxer.js +115 -0
- package/lib/util/cmcd_manager.js +153 -3
- package/lib/util/dom_utils.js +11 -0
- package/lib/util/error.js +5 -0
- package/lib/util/fake_event.js +2 -0
- package/lib/util/manifest_parser_utils.js +97 -3
- package/lib/util/mp4_box_parsers.js +346 -17
- package/lib/util/mp4_generator.js +23 -0
- package/lib/util/periods.js +19 -0
- package/lib/util/platform.js +161 -9
- package/lib/util/player_configuration.js +79 -13
- package/lib/util/stats.js +16 -0
- package/lib/util/stream_utils.js +22 -8
- package/lib/util/string_utils.js +36 -0
- package/lib/util/tXml.js +814 -0
- package/lib/util/ts_parser.js +50 -0
- package/lib/util/xml_utils.js +10 -338
- package/package.json +2 -2
- package/shaka-player.uncompiled.js +8 -0
- package/ui/controls.js +187 -5
- package/ui/enums.js +2 -0
- package/ui/externs/ui.js +30 -3
- package/ui/gl_matrix/matrix_4x4.js +568 -0
- package/ui/gl_matrix/matrix_quaternion.js +45 -0
- package/ui/less/containers.less +11 -0
- package/ui/locales/en-GB.json +2 -0
- package/ui/locales/en.json +2 -0
- package/ui/locales/es-419.json +2 -0
- package/ui/locales/es.json +2 -0
- package/ui/locales/source.json +8 -0
- package/ui/recenter_vr.js +126 -0
- package/ui/resolution_selection.js +25 -5
- package/ui/statistics_button.js +12 -0
- package/ui/text_selection.js +1 -1
- package/ui/toggle_stereoscopic.js +127 -0
- package/ui/ui.js +74 -38
- package/ui/vr_manager.js +557 -0
- package/ui/vr_utils.js +232 -0
- package/ui/vr_webgl.js +697 -0
package/lib/util/platform.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.util.Platform');
|
|
8
8
|
|
|
9
|
+
goog.require('shaka.log');
|
|
9
10
|
goog.require('shaka.util.Timer');
|
|
10
11
|
|
|
11
12
|
|
|
@@ -149,10 +150,9 @@ shaka.util.Platform = class {
|
|
|
149
150
|
* @return {boolean}
|
|
150
151
|
*/
|
|
151
152
|
static isWebOS3() {
|
|
152
|
-
// See:
|
|
153
|
-
return shaka.util.Platform.
|
|
154
|
-
shaka.util.Platform.
|
|
155
|
-
'Chrome/38.0.2125.122 Safari/537.36');
|
|
153
|
+
// See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
|
|
154
|
+
return shaka.util.Platform.isWebOS() &&
|
|
155
|
+
shaka.util.Platform.chromeVersion() === 38;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
/**
|
|
@@ -161,18 +161,20 @@ shaka.util.Platform = class {
|
|
|
161
161
|
* @return {boolean}
|
|
162
162
|
*/
|
|
163
163
|
static isWebOS4() {
|
|
164
|
-
// See:
|
|
165
|
-
return
|
|
164
|
+
// See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
|
|
165
|
+
return shaka.util.Platform.isWebOS() &&
|
|
166
|
+
shaka.util.Platform.chromeVersion() === 53;
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
/**
|
|
169
|
-
* Check if the current platform is a WebOS
|
|
170
|
+
* Check if the current platform is a WebOS 5.
|
|
170
171
|
*
|
|
171
172
|
* @return {boolean}
|
|
172
173
|
*/
|
|
173
174
|
static isWebOS5() {
|
|
174
|
-
// See:
|
|
175
|
-
return
|
|
175
|
+
// See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
|
|
176
|
+
return shaka.util.Platform.isWebOS() &&
|
|
177
|
+
shaka.util.Platform.chromeVersion() === 68;
|
|
176
178
|
}
|
|
177
179
|
|
|
178
180
|
/**
|
|
@@ -440,6 +442,25 @@ shaka.util.Platform = class {
|
|
|
440
442
|
return shaka.util.Platform.userAgentContains_('Android');
|
|
441
443
|
}
|
|
442
444
|
|
|
445
|
+
/**
|
|
446
|
+
* Return true if the platform is controlled by a remote control.
|
|
447
|
+
*
|
|
448
|
+
* @return {boolean}
|
|
449
|
+
*/
|
|
450
|
+
static isSmartTV() {
|
|
451
|
+
const Platform = shaka.util.Platform;
|
|
452
|
+
if (Platform.isTizen() || Platform.isWebOS() ||
|
|
453
|
+
Platform.isXboxOne() || Platform.isPS4() ||
|
|
454
|
+
Platform.isPS5() || Platform.isAmazonFireTV() ||
|
|
455
|
+
Platform.isEOS() || Platform.isAPL() ||
|
|
456
|
+
Platform.isVirginMedia() || Platform.isOrange() ||
|
|
457
|
+
Platform.isWPE() || Platform.isChromecast() ||
|
|
458
|
+
Platform.isHisense()) {
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
|
|
443
464
|
/**
|
|
444
465
|
* Check if the user agent contains a key. This is the best way we know of
|
|
445
466
|
* right now to detect platforms. If there is a better way, please send a
|
|
@@ -554,6 +575,137 @@ shaka.util.Platform = class {
|
|
|
554
575
|
|
|
555
576
|
return false;
|
|
556
577
|
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Detect the maximum resolution that the platform's hardware can handle.
|
|
581
|
+
*
|
|
582
|
+
* @return {!Promise.<{width: number, height: number}>}
|
|
583
|
+
*/
|
|
584
|
+
static async detectMaxHardwareResolution() {
|
|
585
|
+
const Platform = shaka.util.Platform;
|
|
586
|
+
const maxResolution = {
|
|
587
|
+
width: Infinity,
|
|
588
|
+
height: Infinity,
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
if (Platform.isChromecast()) {
|
|
592
|
+
// In our tests, the original Chromecast seems to have trouble decoding
|
|
593
|
+
// above 1080p. It would be a waste to select a higher res anyway, given
|
|
594
|
+
// that the device only outputs 1080p to begin with.
|
|
595
|
+
// Chromecast has an extension to query the device/display's resolution.
|
|
596
|
+
if (window.cast && cast.__platform__ &&
|
|
597
|
+
cast.__platform__.canDisplayType && cast.__platform__.canDisplayType(
|
|
598
|
+
'video/mp4; codecs="avc1.640028"; width=3840; height=2160')) {
|
|
599
|
+
// The device and display can both do 4k. Assume a 4k limit.
|
|
600
|
+
maxResolution.width = 3840;
|
|
601
|
+
maxResolution.height = 2160;
|
|
602
|
+
} else {
|
|
603
|
+
// Chromecast has always been able to do 1080p. Assume a 1080p limit.
|
|
604
|
+
maxResolution.width = 1920;
|
|
605
|
+
maxResolution.height = 1080;
|
|
606
|
+
}
|
|
607
|
+
} else if (Platform.isTizen()) {
|
|
608
|
+
maxResolution.width = 1920;
|
|
609
|
+
maxResolution.height = 1080;
|
|
610
|
+
try {
|
|
611
|
+
if (webapis.systeminfo && webapis.systeminfo.getMaxVideoResolution) {
|
|
612
|
+
const maxVideoResolution =
|
|
613
|
+
webapis.systeminfo.getMaxVideoResolution();
|
|
614
|
+
maxResolution.width = maxVideoResolution.width;
|
|
615
|
+
maxResolution.height = maxVideoResolution.height;
|
|
616
|
+
} else {
|
|
617
|
+
if (webapis.productinfo.is8KPanelSupported &&
|
|
618
|
+
webapis.productinfo.is8KPanelSupported()) {
|
|
619
|
+
maxResolution.width = 7680;
|
|
620
|
+
maxResolution.height = 4320;
|
|
621
|
+
} else if (webapis.productinfo.isUdPanelSupported &&
|
|
622
|
+
webapis.productinfo.isUdPanelSupported()) {
|
|
623
|
+
maxResolution.width = 3840;
|
|
624
|
+
maxResolution.height = 2160;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
} catch (e) {
|
|
628
|
+
shaka.log.alwaysWarn('Tizen: Error detecting screen size, default ' +
|
|
629
|
+
'screen size 1920x1080.');
|
|
630
|
+
}
|
|
631
|
+
} else if (Platform.isXboxOne()) {
|
|
632
|
+
const protectionCapabilities =
|
|
633
|
+
new Windows.Media.Protection.ProtectionCapabilities();
|
|
634
|
+
const protectionResult =
|
|
635
|
+
Windows.Media.Protection.ProtectionCapabilityResult;
|
|
636
|
+
// isTypeSupported may return "maybe", which means the operation is not
|
|
637
|
+
// completed. This means we need to retry
|
|
638
|
+
// https://learn.microsoft.com/en-us/uwp/api/windows.media.protection.protectioncapabilityresult?view=winrt-22621
|
|
639
|
+
let result = null;
|
|
640
|
+
try {
|
|
641
|
+
const type =
|
|
642
|
+
'video/mp4;codecs="hvc1,mp4a";features="decode-res-x=3840,' +
|
|
643
|
+
'decode-res-y=2160,decode-bitrate=20000,decode-fps=30,' +
|
|
644
|
+
'decode-bpc=10,display-res-x=3840,display-res-y=2160,' +
|
|
645
|
+
'display-bpc=8"';
|
|
646
|
+
const keySystem = 'com.microsoft.playready.recommendation';
|
|
647
|
+
do {
|
|
648
|
+
result = protectionCapabilities.isTypeSupported(type, keySystem);
|
|
649
|
+
} while (result === protectionResult.maybe);
|
|
650
|
+
} catch (e) {
|
|
651
|
+
result = protectionResult.notSupported;
|
|
652
|
+
}
|
|
653
|
+
if (result === protectionResult.probably) {
|
|
654
|
+
maxResolution.width = 3840;
|
|
655
|
+
maxResolution.height = 2160;
|
|
656
|
+
} else {
|
|
657
|
+
maxResolution.width = 1920;
|
|
658
|
+
maxResolution.height = 1080;
|
|
659
|
+
}
|
|
660
|
+
} else if (Platform.isWebOS()) {
|
|
661
|
+
try {
|
|
662
|
+
const deviceInfo =
|
|
663
|
+
/** @type {{screenWidth: number, screenHeight: number}} */(
|
|
664
|
+
JSON.parse(window.PalmSystem.deviceInfo));
|
|
665
|
+
// WebOS has always been able to do 1080p. Assume a 1080p limit.
|
|
666
|
+
maxResolution.width = Math.max(1920, deviceInfo.screenWidth);
|
|
667
|
+
maxResolution.height = Math.max(1080, deviceInfo.screenHeight);
|
|
668
|
+
} catch (e) {
|
|
669
|
+
shaka.log.alwaysWarn('WebOS: Error detecting screen size, default ' +
|
|
670
|
+
'screen size 1920x1080.');
|
|
671
|
+
maxResolution.width = 1920;
|
|
672
|
+
maxResolution.height = 1080;
|
|
673
|
+
}
|
|
674
|
+
} else if (Platform.isHisense()) {
|
|
675
|
+
// eslint-disable-next-line new-cap
|
|
676
|
+
if (window.Hisense_Get4KSupportState &&
|
|
677
|
+
// eslint-disable-next-line new-cap
|
|
678
|
+
window.Hisense_Get4KSupportState()) {
|
|
679
|
+
maxResolution.width = 3840;
|
|
680
|
+
maxResolution.height = 2160;
|
|
681
|
+
} else {
|
|
682
|
+
maxResolution.width = 1920;
|
|
683
|
+
maxResolution.height = 1080;
|
|
684
|
+
}
|
|
685
|
+
} else if (Platform.isPS4() || Platform.isPS5()) {
|
|
686
|
+
let supports4K = false;
|
|
687
|
+
try {
|
|
688
|
+
const result = await window.msdk.device.getDisplayInfo();
|
|
689
|
+
supports4K = result.resolution === '4K';
|
|
690
|
+
} catch (e) {
|
|
691
|
+
try {
|
|
692
|
+
const result = await window.msdk.device.getDisplayInfoImmediate();
|
|
693
|
+
supports4K = result.resolution === '4K';
|
|
694
|
+
} catch (e) {
|
|
695
|
+
shaka.log.alwaysWarn(
|
|
696
|
+
'PlayStation: Failed to get the display info:', e);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (supports4K) {
|
|
700
|
+
maxResolution.width = 3840;
|
|
701
|
+
maxResolution.height = 2160;
|
|
702
|
+
} else {
|
|
703
|
+
maxResolution.width = 1920;
|
|
704
|
+
maxResolution.height = 1080;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return maxResolution;
|
|
708
|
+
}
|
|
557
709
|
};
|
|
558
710
|
|
|
559
711
|
/** @private {shaka.util.Timer} */
|
|
@@ -94,6 +94,13 @@ shaka.util.PlayerConfiguration = class {
|
|
|
94
94
|
ignoreDuplicateInitData: !shaka.util.Platform.isTizen2(),
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
+
// The Xbox One and PS4 only support the Playready DRM, so they should
|
|
98
|
+
// prefer that key system by default to improve startup performance.
|
|
99
|
+
if (shaka.util.Platform.isXboxOne() ||
|
|
100
|
+
shaka.util.Platform.isPS4()) {
|
|
101
|
+
drm.preferredKeySystems.push('com.microsoft.playready');
|
|
102
|
+
}
|
|
103
|
+
|
|
97
104
|
let codecSwitchingStrategy = shaka.config.CodecSwitchingStrategy.RELOAD;
|
|
98
105
|
let multiTypeVariantsAllowed = false;
|
|
99
106
|
if (shaka.util.Platform.supportsSmoothCodecSwitching()) {
|
|
@@ -133,17 +140,16 @@ shaka.util.PlayerConfiguration = class {
|
|
|
133
140
|
'com.microsoft.playready',
|
|
134
141
|
'urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95':
|
|
135
142
|
'com.microsoft.playready',
|
|
136
|
-
'urn:uuid:f239e769-efa3-4850-9c16-a903c6932efb':
|
|
137
|
-
'com.adobe.primetime',
|
|
138
|
-
},
|
|
139
|
-
manifestPreprocessor: (element) => {
|
|
140
|
-
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
141
|
-
[element],
|
|
142
|
-
element);
|
|
143
143
|
},
|
|
144
|
+
manifestPreprocessor:
|
|
145
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
146
|
+
manifestPreprocessorTXml:
|
|
147
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
|
144
148
|
sequenceMode: false,
|
|
145
149
|
enableAudioGroups: false,
|
|
146
150
|
multiTypeVariantsAllowed,
|
|
151
|
+
useStreamOnceInPeriodFlattening: false,
|
|
152
|
+
updatePeriod: -1,
|
|
147
153
|
},
|
|
148
154
|
hls: {
|
|
149
155
|
ignoreTextStreamFailures: false,
|
|
@@ -151,6 +157,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
151
157
|
defaultAudioCodec: 'mp4a.40.2',
|
|
152
158
|
defaultVideoCodec: 'avc1.42E01E',
|
|
153
159
|
ignoreManifestProgramDateTime: false,
|
|
160
|
+
ignoreManifestProgramDateTimeForTypes: [],
|
|
154
161
|
mediaPlaylistFullMimeType:
|
|
155
162
|
'video/mp2t; codecs="avc1.42E01E, mp4a.40.2"',
|
|
156
163
|
useSafariBehaviorForLive: true,
|
|
@@ -161,11 +168,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
161
168
|
allowLowLatencyByteRangeOptimization: true,
|
|
162
169
|
},
|
|
163
170
|
mss: {
|
|
164
|
-
manifestPreprocessor:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
},
|
|
171
|
+
manifestPreprocessor:
|
|
172
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
173
|
+
manifestPreprocessorTXml:
|
|
174
|
+
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
|
169
175
|
sequenceMode: false,
|
|
170
176
|
keySystemsBySystemId: {
|
|
171
177
|
'9a04f079-9840-4286-ab92-e65be0885f95':
|
|
@@ -192,6 +198,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
192
198
|
rebufferingGoal: 2,
|
|
193
199
|
bufferingGoal: 10,
|
|
194
200
|
bufferBehind: 30,
|
|
201
|
+
evictionGoal: 1,
|
|
195
202
|
ignoreTextStreamFailures: false,
|
|
196
203
|
alwaysStreamText: false,
|
|
197
204
|
startAtSegmentBoundary: false,
|
|
@@ -205,6 +212,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
205
212
|
stallThreshold: 1 /* seconds */,
|
|
206
213
|
stallSkip: 0.1 /* seconds */,
|
|
207
214
|
useNativeHlsOnSafari: true,
|
|
215
|
+
useNativeHlsForFairPlay: true,
|
|
208
216
|
// If we are within 2 seconds of the start of a live segment, fetch the
|
|
209
217
|
// previous one. This allows for segment drift, but won't download an
|
|
210
218
|
// extra segment if we aren't close to the start.
|
|
@@ -223,13 +231,23 @@ shaka.util.PlayerConfiguration = class {
|
|
|
223
231
|
// When low latency streaming is enabled, segmentPrefetchLimit will
|
|
224
232
|
// default to 2 if not specified.
|
|
225
233
|
segmentPrefetchLimit: 0,
|
|
234
|
+
prefetchAudioLanguages: [],
|
|
235
|
+
disableAudioPrefetch: false,
|
|
236
|
+
disableTextPrefetch: false,
|
|
237
|
+
disableVideoPrefetch: false,
|
|
226
238
|
liveSync: false,
|
|
227
239
|
liveSyncMaxLatency: 1,
|
|
228
240
|
liveSyncPlaybackRate: 1.1,
|
|
229
241
|
liveSyncMinLatency: 0,
|
|
230
242
|
liveSyncMinPlaybackRate: 1,
|
|
243
|
+
liveSyncPanicMode: false,
|
|
244
|
+
liveSyncPanicThreshold: 60,
|
|
231
245
|
allowMediaSourceRecoveries: true,
|
|
232
246
|
minTimeBetweenRecoveries: 5,
|
|
247
|
+
vodDynamicPlaybackRate: false,
|
|
248
|
+
vodDynamicPlaybackRateLowBufferRate: 0.95,
|
|
249
|
+
vodDynamicPlaybackRateBufferRatio: 0.5,
|
|
250
|
+
infiniteLiveStreamDuration: false,
|
|
233
251
|
};
|
|
234
252
|
|
|
235
253
|
// WebOS, Tizen, Chromecast and Hisense have long hardware pipelines
|
|
@@ -316,7 +334,9 @@ shaka.util.PlayerConfiguration = class {
|
|
|
316
334
|
enabled: false,
|
|
317
335
|
sessionId: '',
|
|
318
336
|
contentId: '',
|
|
337
|
+
rtpSafetyFactor: 5,
|
|
319
338
|
useHeaders: false,
|
|
339
|
+
includeKeys: [],
|
|
320
340
|
};
|
|
321
341
|
|
|
322
342
|
const cmsd = {
|
|
@@ -334,13 +354,38 @@ shaka.util.PlayerConfiguration = class {
|
|
|
334
354
|
|
|
335
355
|
const mediaSource = {
|
|
336
356
|
codecSwitchingStrategy: codecSwitchingStrategy,
|
|
337
|
-
|
|
357
|
+
addExtraFeaturesToSourceBuffer: (mimeType) => {
|
|
358
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
359
|
+
[mimeType],
|
|
360
|
+
'');
|
|
361
|
+
},
|
|
338
362
|
forceTransmux: false,
|
|
339
363
|
insertFakeEncryptionInInit: true,
|
|
364
|
+
modifyCueCallback: (cue, uri) => {
|
|
365
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
366
|
+
[cue, uri],
|
|
367
|
+
undefined);
|
|
368
|
+
},
|
|
340
369
|
};
|
|
341
370
|
|
|
371
|
+
let skipPlayDetection = false;
|
|
372
|
+
if (shaka.util.Platform.isWebOS() ||
|
|
373
|
+
shaka.util.Platform.isTizen() ||
|
|
374
|
+
shaka.util.Platform.isChromecast() ||
|
|
375
|
+
shaka.util.Platform.isHisense() ||
|
|
376
|
+
shaka.util.Platform.isPS5() ||
|
|
377
|
+
shaka.util.Platform.isPS4() ||
|
|
378
|
+
shaka.util.Platform.isXboxOne()) {
|
|
379
|
+
skipPlayDetection = true;
|
|
380
|
+
}
|
|
381
|
+
|
|
342
382
|
const ads = {
|
|
343
383
|
customPlayheadTracker: false,
|
|
384
|
+
skipPlayDetection,
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const textDisplayer = {
|
|
388
|
+
captionsUpdatePeriod: 0.25,
|
|
344
389
|
};
|
|
345
390
|
|
|
346
391
|
const AutoShowText = shaka.config.AutoShowText;
|
|
@@ -383,6 +428,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
383
428
|
},
|
|
384
429
|
playRangeStart: 0,
|
|
385
430
|
playRangeEnd: Infinity,
|
|
431
|
+
textDisplayer: textDisplayer,
|
|
386
432
|
textDisplayFactory: () => null,
|
|
387
433
|
cmcd: cmcd,
|
|
388
434
|
cmsd: cmsd,
|
|
@@ -557,4 +603,24 @@ shaka.util.PlayerConfiguration = class {
|
|
|
557
603
|
|
|
558
604
|
return selectedTracks;
|
|
559
605
|
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* @param {!Element} element
|
|
609
|
+
* @return {!Element}
|
|
610
|
+
*/
|
|
611
|
+
static defaultManifestPreprocessor(element) {
|
|
612
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
613
|
+
[element],
|
|
614
|
+
element);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* @param {!shaka.extern.xml.Node} element
|
|
619
|
+
* @return {!shaka.extern.xml.Node}
|
|
620
|
+
*/
|
|
621
|
+
static defaultManifestPreprocessorTXml(element) {
|
|
622
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
623
|
+
[element],
|
|
624
|
+
element);
|
|
625
|
+
}
|
|
560
626
|
};
|
package/lib/util/stats.js
CHANGED
|
@@ -62,6 +62,9 @@ shaka.util.Stats = class {
|
|
|
62
62
|
/** @private {number} */
|
|
63
63
|
this.bandwidthEstimate_ = NaN;
|
|
64
64
|
|
|
65
|
+
/** @private {number} */
|
|
66
|
+
this.bytesDownloaded_ = NaN;
|
|
67
|
+
|
|
65
68
|
/** @private {!shaka.util.StateHistory} */
|
|
66
69
|
this.stateHistory_ = new shaka.util.StateHistory();
|
|
67
70
|
|
|
@@ -203,6 +206,17 @@ shaka.util.Stats = class {
|
|
|
203
206
|
this.bandwidthEstimate_ = bandwidth;
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
/**
|
|
210
|
+
* @param {number} bytesDownloaded
|
|
211
|
+
*/
|
|
212
|
+
addBytesDownloaded(bytesDownloaded) {
|
|
213
|
+
if (isNaN(this.bytesDownloaded_)) {
|
|
214
|
+
this.bytesDownloaded_ = bytesDownloaded;
|
|
215
|
+
} else {
|
|
216
|
+
this.bytesDownloaded_ += bytesDownloaded;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
206
220
|
/**
|
|
207
221
|
* @return {!shaka.util.StateHistory}
|
|
208
222
|
*/
|
|
@@ -244,6 +258,7 @@ shaka.util.Stats = class {
|
|
|
244
258
|
licenseTime: this.licenseTimeSeconds_,
|
|
245
259
|
liveLatency: this.liveLatencySeconds_,
|
|
246
260
|
maxSegmentDuration: this.maxSegmentDurationSeconds_,
|
|
261
|
+
bytesDownloaded: this.bytesDownloaded_,
|
|
247
262
|
stateHistory: this.stateHistory_.getCopy(),
|
|
248
263
|
switchHistory: this.switchHistory_.getCopy(),
|
|
249
264
|
};
|
|
@@ -276,6 +291,7 @@ shaka.util.Stats = class {
|
|
|
276
291
|
licenseTime: NaN,
|
|
277
292
|
liveLatency: NaN,
|
|
278
293
|
maxSegmentDuration: NaN,
|
|
294
|
+
bytesDownloaded: NaN,
|
|
279
295
|
switchHistory: [],
|
|
280
296
|
stateHistory: [],
|
|
281
297
|
};
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -263,13 +263,20 @@ shaka.util.StreamUtils = class {
|
|
|
263
263
|
// |video.width| and |video.height| can be undefined, which breaks
|
|
264
264
|
// the math, so make sure they are there first.
|
|
265
265
|
if (video && video.width && video.height) {
|
|
266
|
-
|
|
266
|
+
let videoWidth = video.width;
|
|
267
|
+
let videoHeight = video.height;
|
|
268
|
+
if (videoHeight > videoWidth) {
|
|
269
|
+
// Vertical video.
|
|
270
|
+
[videoWidth, videoHeight] = [videoHeight, videoWidth];
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (!inRange(videoWidth,
|
|
267
274
|
restrictions.minWidth,
|
|
268
275
|
Math.min(restrictions.maxWidth, maxHwRes.width))) {
|
|
269
276
|
return false;
|
|
270
277
|
}
|
|
271
278
|
|
|
272
|
-
if (!inRange(
|
|
279
|
+
if (!inRange(videoHeight,
|
|
273
280
|
restrictions.minHeight,
|
|
274
281
|
Math.min(restrictions.maxHeight, maxHwRes.height))) {
|
|
275
282
|
return false;
|
|
@@ -330,10 +337,12 @@ shaka.util.StreamUtils = class {
|
|
|
330
337
|
*
|
|
331
338
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
332
339
|
* @param {shaka.extern.Manifest} manifest
|
|
340
|
+
* @param {!Array<string>=} preferredKeySystems
|
|
333
341
|
*/
|
|
334
|
-
static async filterManifest(drmEngine, manifest) {
|
|
342
|
+
static async filterManifest(drmEngine, manifest, preferredKeySystems = []) {
|
|
335
343
|
await shaka.util.StreamUtils.filterManifestByMediaCapabilities(
|
|
336
|
-
drmEngine, manifest, manifest.offlineSessionIds.length > 0
|
|
344
|
+
drmEngine, manifest, manifest.offlineSessionIds.length > 0,
|
|
345
|
+
preferredKeySystems);
|
|
337
346
|
shaka.util.StreamUtils.filterTextStreams_(manifest);
|
|
338
347
|
await shaka.util.StreamUtils.filterImageStreams_(manifest);
|
|
339
348
|
}
|
|
@@ -346,15 +355,16 @@ shaka.util.StreamUtils = class {
|
|
|
346
355
|
* @param {shaka.media.DrmEngine} drmEngine
|
|
347
356
|
* @param {shaka.extern.Manifest} manifest
|
|
348
357
|
* @param {boolean} usePersistentLicenses
|
|
358
|
+
* @param {!Array<string>} preferredKeySystems
|
|
349
359
|
*/
|
|
350
360
|
static async filterManifestByMediaCapabilities(
|
|
351
|
-
drmEngine, manifest, usePersistentLicenses) {
|
|
361
|
+
drmEngine, manifest, usePersistentLicenses, preferredKeySystems) {
|
|
352
362
|
goog.asserts.assert(navigator.mediaCapabilities,
|
|
353
363
|
'MediaCapabilities should be valid.');
|
|
354
364
|
|
|
355
365
|
await shaka.util.StreamUtils.getDecodingInfosForVariants(
|
|
356
366
|
manifest.variants, usePersistentLicenses, /* srcEquals= */ false,
|
|
357
|
-
|
|
367
|
+
preferredKeySystems);
|
|
358
368
|
|
|
359
369
|
let keySystem = null;
|
|
360
370
|
if (drmEngine) {
|
|
@@ -973,8 +983,12 @@ shaka.util.StreamUtils = class {
|
|
|
973
983
|
// currently don't support 'fLaC', while 'flac' is supported by most
|
|
974
984
|
// major browsers.
|
|
975
985
|
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
|
|
976
|
-
if (codecs
|
|
977
|
-
|
|
986
|
+
if (codecs.toLowerCase() == 'flac') {
|
|
987
|
+
if (!shaka.util.Platform.isSafari()) {
|
|
988
|
+
return 'flac';
|
|
989
|
+
} else {
|
|
990
|
+
return 'fLaC';
|
|
991
|
+
}
|
|
978
992
|
}
|
|
979
993
|
|
|
980
994
|
// The same is true for 'Opus'.
|
package/lib/util/string_utils.js
CHANGED
|
@@ -276,6 +276,42 @@ shaka.util.StringUtils = class {
|
|
|
276
276
|
static resetFromCharCode() {
|
|
277
277
|
shaka.util.StringUtils.fromCharCodeImpl_.reset();
|
|
278
278
|
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* This method converts the HTML entities &, <, >, ", ',
|
|
282
|
+
* , ‎ and ‏ in string to their corresponding characters.
|
|
283
|
+
*
|
|
284
|
+
* @param {!string} input
|
|
285
|
+
* @return {string}
|
|
286
|
+
*/
|
|
287
|
+
static htmlUnescape(input) {
|
|
288
|
+
// Used to map HTML entities to characters.
|
|
289
|
+
const htmlUnescapes = {
|
|
290
|
+
'&': '&',
|
|
291
|
+
'<': '<',
|
|
292
|
+
'>': '>',
|
|
293
|
+
'"': '"',
|
|
294
|
+
''': '\'',
|
|
295
|
+
''': '\'',
|
|
296
|
+
' ': '\u{a0}',
|
|
297
|
+
'‎': '\u{200e}',
|
|
298
|
+
'‏': '\u{200f}',
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// Used to match HTML entities and HTML characters.
|
|
302
|
+
const reEscapedHtml = /&(?:amp|lt|gt|quot|apos|#(0+)?39|nbsp|lrm|rlm);/g;
|
|
303
|
+
const reHasEscapedHtml = RegExp(reEscapedHtml.source);
|
|
304
|
+
// This check is an optimization, since replace always makes a copy
|
|
305
|
+
if (input && reHasEscapedHtml.test(input)) {
|
|
306
|
+
return input.replace(reEscapedHtml, (entity) => {
|
|
307
|
+
// The only thing that might not match the dictionary above is the
|
|
308
|
+
// single quote, which can be matched by many strings in the regex, but
|
|
309
|
+
// only has a single entry in the dictionary.
|
|
310
|
+
return htmlUnescapes[entity] || '\'';
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return input || '';
|
|
314
|
+
}
|
|
279
315
|
};
|
|
280
316
|
|
|
281
317
|
|