shaka-player 4.7.13 → 4.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/CONTRIBUTORS +1 -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 +44 -34
- package/dist/shaka-player.compiled.d.ts +194 -44
- package/dist/shaka-player.compiled.debug.d.ts +194 -44
- package/dist/shaka-player.compiled.debug.externs.js +474 -337
- package/dist/shaka-player.compiled.debug.js +949 -832
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +474 -337
- package/dist/shaka-player.compiled.js +1237 -1171
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +257 -47
- package/dist/shaka-player.ui.debug.d.ts +257 -47
- package/dist/shaka-player.ui.debug.externs.js +591 -376
- package/dist/shaka-player.ui.debug.js +1165 -965
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +591 -376
- package/dist/shaka-player.ui.js +1521 -1404
- 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 +230 -176
- 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 +26 -21
- 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 +40 -30
- package/lib/media/segment_prefetch.js +140 -43
- package/lib/media/segment_reference.js +31 -8
- package/lib/media/segment_utils.js +208 -25
- package/lib/media/streaming_engine.js +319 -63
- package/lib/mss/content_protection.js +31 -25
- package/lib/mss/mss_parser.js +74 -55
- package/lib/net/networking_engine.js +49 -4
- package/lib/offline/storage.js +3 -3
- package/lib/player.js +882 -673
- 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 +152 -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 +61 -3
- package/lib/util/stats.js +16 -0
- package/lib/util/stream_utils.js +16 -6
- 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,22 @@ 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
143
|
},
|
|
139
144
|
manifestPreprocessor: (element) => {
|
|
140
145
|
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
141
146
|
[element],
|
|
142
147
|
element);
|
|
143
148
|
},
|
|
149
|
+
manifestPreprocessorTXml: (element) => {
|
|
150
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
151
|
+
[element],
|
|
152
|
+
element);
|
|
153
|
+
},
|
|
144
154
|
sequenceMode: false,
|
|
145
155
|
enableAudioGroups: false,
|
|
146
156
|
multiTypeVariantsAllowed,
|
|
157
|
+
useStreamOnceInPeriodFlattening: false,
|
|
158
|
+
updatePeriod: -1,
|
|
147
159
|
},
|
|
148
160
|
hls: {
|
|
149
161
|
ignoreTextStreamFailures: false,
|
|
@@ -151,6 +163,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
151
163
|
defaultAudioCodec: 'mp4a.40.2',
|
|
152
164
|
defaultVideoCodec: 'avc1.42E01E',
|
|
153
165
|
ignoreManifestProgramDateTime: false,
|
|
166
|
+
ignoreManifestProgramDateTimeForTypes: [],
|
|
154
167
|
mediaPlaylistFullMimeType:
|
|
155
168
|
'video/mp2t; codecs="avc1.42E01E, mp4a.40.2"',
|
|
156
169
|
useSafariBehaviorForLive: true,
|
|
@@ -166,6 +179,11 @@ shaka.util.PlayerConfiguration = class {
|
|
|
166
179
|
[element],
|
|
167
180
|
element);
|
|
168
181
|
},
|
|
182
|
+
manifestPreprocessorTXml: (element) => {
|
|
183
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
184
|
+
[element],
|
|
185
|
+
element);
|
|
186
|
+
},
|
|
169
187
|
sequenceMode: false,
|
|
170
188
|
keySystemsBySystemId: {
|
|
171
189
|
'9a04f079-9840-4286-ab92-e65be0885f95':
|
|
@@ -192,6 +210,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
192
210
|
rebufferingGoal: 2,
|
|
193
211
|
bufferingGoal: 10,
|
|
194
212
|
bufferBehind: 30,
|
|
213
|
+
evictionGoal: 1,
|
|
195
214
|
ignoreTextStreamFailures: false,
|
|
196
215
|
alwaysStreamText: false,
|
|
197
216
|
startAtSegmentBoundary: false,
|
|
@@ -205,6 +224,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
205
224
|
stallThreshold: 1 /* seconds */,
|
|
206
225
|
stallSkip: 0.1 /* seconds */,
|
|
207
226
|
useNativeHlsOnSafari: true,
|
|
227
|
+
useNativeHlsForFairPlay: true,
|
|
208
228
|
// If we are within 2 seconds of the start of a live segment, fetch the
|
|
209
229
|
// previous one. This allows for segment drift, but won't download an
|
|
210
230
|
// extra segment if we aren't close to the start.
|
|
@@ -223,13 +243,23 @@ shaka.util.PlayerConfiguration = class {
|
|
|
223
243
|
// When low latency streaming is enabled, segmentPrefetchLimit will
|
|
224
244
|
// default to 2 if not specified.
|
|
225
245
|
segmentPrefetchLimit: 0,
|
|
246
|
+
prefetchAudioLanguages: [],
|
|
247
|
+
disableAudioPrefetch: false,
|
|
248
|
+
disableTextPrefetch: false,
|
|
249
|
+
disableVideoPrefetch: false,
|
|
226
250
|
liveSync: false,
|
|
227
251
|
liveSyncMaxLatency: 1,
|
|
228
252
|
liveSyncPlaybackRate: 1.1,
|
|
229
253
|
liveSyncMinLatency: 0,
|
|
230
254
|
liveSyncMinPlaybackRate: 1,
|
|
255
|
+
liveSyncPanicMode: false,
|
|
256
|
+
liveSyncPanicThreshold: 60,
|
|
231
257
|
allowMediaSourceRecoveries: true,
|
|
232
258
|
minTimeBetweenRecoveries: 5,
|
|
259
|
+
vodDynamicPlaybackRate: false,
|
|
260
|
+
vodDynamicPlaybackRateLowBufferRate: 0.95,
|
|
261
|
+
vodDynamicPlaybackRateBufferRatio: 0.5,
|
|
262
|
+
infiniteLiveStreamDuration: false,
|
|
233
263
|
};
|
|
234
264
|
|
|
235
265
|
// WebOS, Tizen, Chromecast and Hisense have long hardware pipelines
|
|
@@ -316,7 +346,9 @@ shaka.util.PlayerConfiguration = class {
|
|
|
316
346
|
enabled: false,
|
|
317
347
|
sessionId: '',
|
|
318
348
|
contentId: '',
|
|
349
|
+
rtpSafetyFactor: 5,
|
|
319
350
|
useHeaders: false,
|
|
351
|
+
includeKeys: [],
|
|
320
352
|
};
|
|
321
353
|
|
|
322
354
|
const cmsd = {
|
|
@@ -334,13 +366,38 @@ shaka.util.PlayerConfiguration = class {
|
|
|
334
366
|
|
|
335
367
|
const mediaSource = {
|
|
336
368
|
codecSwitchingStrategy: codecSwitchingStrategy,
|
|
337
|
-
|
|
369
|
+
addExtraFeaturesToSourceBuffer: (mimeType) => {
|
|
370
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
371
|
+
[mimeType],
|
|
372
|
+
'');
|
|
373
|
+
},
|
|
338
374
|
forceTransmux: false,
|
|
339
375
|
insertFakeEncryptionInInit: true,
|
|
376
|
+
modifyCueCallback: (cue, uri) => {
|
|
377
|
+
return shaka.util.ConfigUtils.referenceParametersAndReturn(
|
|
378
|
+
[cue, uri],
|
|
379
|
+
undefined);
|
|
380
|
+
},
|
|
340
381
|
};
|
|
341
382
|
|
|
383
|
+
let skipPlayDetection = false;
|
|
384
|
+
if (shaka.util.Platform.isWebOS() ||
|
|
385
|
+
shaka.util.Platform.isTizen() ||
|
|
386
|
+
shaka.util.Platform.isChromecast() ||
|
|
387
|
+
shaka.util.Platform.isHisense() ||
|
|
388
|
+
shaka.util.Platform.isPS5() ||
|
|
389
|
+
shaka.util.Platform.isPS4() ||
|
|
390
|
+
shaka.util.Platform.isXboxOne()) {
|
|
391
|
+
skipPlayDetection = true;
|
|
392
|
+
}
|
|
393
|
+
|
|
342
394
|
const ads = {
|
|
343
395
|
customPlayheadTracker: false,
|
|
396
|
+
skipPlayDetection,
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const textDisplayer = {
|
|
400
|
+
captionsUpdatePeriod: 0.25,
|
|
344
401
|
};
|
|
345
402
|
|
|
346
403
|
const AutoShowText = shaka.config.AutoShowText;
|
|
@@ -383,6 +440,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
383
440
|
},
|
|
384
441
|
playRangeStart: 0,
|
|
385
442
|
playRangeEnd: Infinity,
|
|
443
|
+
textDisplayer: textDisplayer,
|
|
386
444
|
textDisplayFactory: () => null,
|
|
387
445
|
cmcd: cmcd,
|
|
388
446
|
cmsd: cmsd,
|
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) {
|
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
|
|