shaka-player 4.2.9 → 4.2.11
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/workflows/demo-version-index.yaml +3 -3
- package/.github/workflows/selenium-lab-tests.yaml +23 -1
- package/AUTHORS +2 -1
- package/CHANGELOG.md +44 -0
- package/CONTRIBUTORS +4 -1
- package/README.md +3 -0
- package/demo/demo.less +1 -0
- package/dist/controls.css +1 -1
- package/dist/demo.compiled.debug.js +154 -276
- package/dist/demo.compiled.debug.map +4 -4
- package/dist/demo.compiled.js +154 -276
- package/dist/demo.compiled.map +4 -4
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +1 -1
- package/dist/locales.js +33 -33
- package/dist/receiver.compiled.debug.js +36 -65
- package/dist/receiver.compiled.debug.map +4 -4
- package/dist/receiver.compiled.js +36 -65
- package/dist/receiver.compiled.map +4 -4
- package/dist/shaka-player.compiled.d.ts +20 -3
- package/dist/shaka-player.compiled.debug.d.ts +20 -3
- package/dist/shaka-player.compiled.debug.externs.js +26 -12
- package/dist/shaka-player.compiled.debug.js +185 -180
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +26 -12
- package/dist/shaka-player.compiled.js +821 -818
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +20 -3
- package/dist/shaka-player.ui.debug.d.ts +20 -3
- package/dist/shaka-player.ui.debug.externs.js +14 -0
- package/dist/shaka-player.ui.debug.js +266 -261
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +14 -0
- package/dist/shaka-player.ui.js +964 -960
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/a11y.md +0 -4
- package/docs/tutorials/ad_monetization.md +0 -4
- package/docs/tutorials/basic-usage.md +0 -5
- package/docs/tutorials/config.md +0 -5
- package/docs/tutorials/debugging.md +0 -5
- package/docs/tutorials/drm-config.md +0 -5
- package/docs/tutorials/fairplay.md +2 -2
- package/docs/tutorials/license-server-auth.md +0 -5
- package/docs/tutorials/license-wrapping.md +0 -5
- package/docs/tutorials/network-and-buffering-config.md +0 -5
- package/docs/tutorials/ui-customization.md +0 -5
- package/docs/tutorials/ui.md +0 -7
- package/docs/tutorials/welcome.md +1 -6
- package/externs/network_information.js +7 -2
- package/externs/shaka/abr_manager.js +6 -0
- package/externs/shaka/net.js +1 -0
- package/externs/shaka/player.js +13 -7
- package/lib/abr/simple_abr_manager.js +27 -3
- package/lib/ads/client_side_ad_manager.js +6 -3
- package/lib/dash/dash_parser.js +49 -48
- package/lib/debug/log.js +9 -13
- package/lib/hls/hls_parser.js +6 -0
- package/lib/hls/manifest_text_parser.js +10 -1
- package/lib/media/drm_engine.js +9 -6
- package/lib/media/media_source_engine.js +17 -8
- package/lib/media/segment_index.js +2 -0
- package/lib/media/segment_reference.js +22 -0
- package/lib/media/streaming_engine.js +17 -7
- package/lib/net/http_fetch_plugin.js +79 -57
- package/lib/net/networking_engine.js +1 -0
- package/lib/player.js +26 -3
- package/lib/polyfill/media_capabilities.js +13 -0
- package/lib/text/mp4_vtt_parser.js +4 -0
- package/lib/text/text_engine.js +1 -0
- package/lib/util/manifest_parser_utils.js +1 -2
- package/lib/util/mime_utils.js +11 -0
- package/lib/util/periods.js +5 -5
- package/lib/util/stream_utils.js +2 -2
- package/maintained-branches.md +3 -4
- package/package.json +9 -3
- package/test/hls/hls_live_unit.js +3 -1
- package/test/media/content_workarounds_unit.js +43 -0
- package/test/media/drm_engine_integration.js +4 -17
- package/test/media/media_source_engine_unit.js +31 -0
- package/test/media/streaming_engine_unit.js +6 -1
- package/test/net/networking_engine_unit.js +6 -1
- package/test/player_integration.js +39 -0
- package/test/player_unit.js +57 -0
- package/test/polyfill/media_capabilities_unit.js +0 -1
- package/test/test/assets/text-clip-alt.vtt +63 -0
- package/test/test/util/fake_drm_engine.js +3 -0
- package/test/test/util/layout_tests.js +4 -3
- package/test/test/util/simple_fakes.js +6 -0
- package/test/test/util/test_scheme.js +9 -14
- package/test/text/mp4_vtt_parser_unit.js +8 -0
- package/test/util/mime_utils_unit.js +10 -0
package/docs/tutorials/a11y.md
CHANGED
|
@@ -222,7 +222,3 @@ before instantiating the player.
|
|
|
222
222
|
// myapp.CustomAdManager is a placeholder name for your ad manager implementation.
|
|
223
223
|
shaka.Player.setAdManagerFactory(() => new myapp.CustomAdManager());
|
|
224
224
|
```
|
|
225
|
-
|
|
226
|
-
#### Continue the Tutorials
|
|
227
|
-
|
|
228
|
-
Next, check out {@tutorial plugins}.
|
package/docs/tutorials/config.md
CHANGED
|
@@ -142,8 +142,3 @@ player.configure({
|
|
|
142
142
|
|
|
143
143
|
For more detail on individual configuration options, please see the API docs for
|
|
144
144
|
{@link shaka.extern.PlayerConfiguration} and {@link shaka.Player#configure}.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
#### Continue the Tutorials
|
|
148
|
-
|
|
149
|
-
Next, check out {@tutorial network-and-buffering-config}.
|
|
@@ -187,8 +187,3 @@ To sum up, remember these points when debugging your application:
|
|
|
187
187
|
- Use the debug version of Shaka Player for debugging and integration work
|
|
188
188
|
- Refer to the docs for error codes
|
|
189
189
|
- Increase the log level when you need more detail
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
#### Continue the Tutorials
|
|
193
|
-
|
|
194
|
-
Next, check out {@tutorial config}.
|
|
@@ -208,8 +208,3 @@ you should provide an empty string as robustness
|
|
|
208
208
|
##### Other key-systems
|
|
209
209
|
|
|
210
210
|
Values for other key systems are not known to us at this time.
|
|
211
|
-
|
|
212
|
-
#### Continue the Tutorials
|
|
213
|
-
|
|
214
|
-
Next, check out {@tutorial license-server-auth}.
|
|
215
|
-
Or check out {@tutorial fairplay}.
|
|
@@ -65,13 +65,13 @@ is used by the browser to generate the license request. If you don't use the
|
|
|
65
65
|
default content ID derivation, you need to specify a custom init data transform:
|
|
66
66
|
|
|
67
67
|
```js
|
|
68
|
-
player.configure('drm.initDataTransform', (initData, initDataType) => {
|
|
68
|
+
player.configure('drm.initDataTransform', (initData, initDataType, drmInfo) => {
|
|
69
69
|
if (initDataType != 'skd')
|
|
70
70
|
return initData;
|
|
71
71
|
// 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
|
|
72
72
|
const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
|
|
73
73
|
const contentId = getMyContentId(skdUri);
|
|
74
|
-
const cert =
|
|
74
|
+
const cert = drmInfo.serverCertificate;
|
|
75
75
|
return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
|
|
76
76
|
});
|
|
77
77
|
```
|
|
@@ -166,8 +166,3 @@ using a request filter:
|
|
|
166
166
|
|
|
167
167
|
Load the page again, and the license response will be accepted by the Widevine
|
|
168
168
|
CDM. Open the JavaScript console to see what the server sent back.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
#### Continue the Tutorials
|
|
172
|
-
|
|
173
|
-
Next, check out {@tutorial ui}.
|
|
@@ -117,8 +117,3 @@ URLs in your manifests always use `https:`, or by having it not include the
|
|
|
117
117
|
scheme (e.g., `//example.com/file.mp4`).
|
|
118
118
|
|
|
119
119
|
[CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
#### Continue the Tutorials
|
|
123
|
-
|
|
124
|
-
Next, check out {@tutorial drm-config}.
|
|
@@ -265,8 +265,3 @@ PR contributions to [the gallery repo][] are welcome.
|
|
|
265
265
|
[@lucksy]: https://github.com/lucksy
|
|
266
266
|
[pre-packaged Shaka UI themes]: https://lucksy.github.io/shaka-player-themes/
|
|
267
267
|
[the gallery repo]: https://github.com/lucksy/shaka-player-themes
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
#### Continue the Tutorials
|
|
271
|
-
|
|
272
|
-
Next, check out {@tutorial a11y} to make your custom buttons accessible to screen readers.
|
package/docs/tutorials/ui.md
CHANGED
|
@@ -29,7 +29,7 @@ You can build Shaka on Linux, Windows, or Mac.
|
|
|
29
29
|
To get the sources and compile the library, you will need:
|
|
30
30
|
* {@link https://git-scm.com/downloads Git v1.9+}
|
|
31
31
|
* {@link https://www.python.org/downloads/ Python v2.7 or v3.5+}
|
|
32
|
-
* {@link https://
|
|
32
|
+
* {@link https://learn.microsoft.com/en-us/java/openjdk/download Java Runtime Environment v14+}
|
|
33
33
|
* {@link https://nodejs.org/en/download/ NodeJS v14+}
|
|
34
34
|
* A local web server, such as {@link https://httpd.apache.org/ Apache}
|
|
35
35
|
* _NOTE: A local web server is required because browsers place restrictions
|
|
@@ -106,8 +106,3 @@ To subscribe to new releases on GitHub, you can follow
|
|
|
106
106
|
To receive infrequent announcements and surveys from us, you can join our
|
|
107
107
|
[mailing list](https://groups.google.com/forum/#!forum/shaka-player-users).
|
|
108
108
|
The list is very low volume, and can only be written to by us.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
#### Continue the Tutorials
|
|
112
|
-
|
|
113
|
-
Next, check out {@tutorial basic-usage}.
|
|
@@ -19,5 +19,10 @@ NetworkInformation.prototype.saveData;
|
|
|
19
19
|
* @param {string} type
|
|
20
20
|
* @param {Function} listener
|
|
21
21
|
*/
|
|
22
|
-
NetworkInformation.prototype.addEventListener =
|
|
23
|
-
|
|
22
|
+
NetworkInformation.prototype.addEventListener = function(type, listener) {};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {string} type
|
|
26
|
+
* @param {Function} listener
|
|
27
|
+
*/
|
|
28
|
+
NetworkInformation.prototype.removeEventListener = function(type, listener) {};
|
package/externs/shaka/net.js
CHANGED
package/externs/shaka/player.js
CHANGED
|
@@ -627,9 +627,7 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
627
627
|
* clearKeys: !Object.<string, string>,
|
|
628
628
|
* delayLicenseRequestUntilPlayed: boolean,
|
|
629
629
|
* advanced: Object.<string, shaka.extern.AdvancedDrmConfiguration>,
|
|
630
|
-
* initDataTransform:
|
|
631
|
-
* ((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
|
|
632
|
-
* undefined),
|
|
630
|
+
* initDataTransform:(shaka.extern.InitDataTransform|undefined),
|
|
633
631
|
* logLicenseExchange: boolean,
|
|
634
632
|
* updateExpirationTime: number,
|
|
635
633
|
* preferredKeySystems: !Array.<string>,
|
|
@@ -655,10 +653,7 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
655
653
|
* <i>Optional.</i> <br>
|
|
656
654
|
* A dictionary which maps key system IDs to advanced DRM configuration for
|
|
657
655
|
* those key systems.
|
|
658
|
-
* @property
|
|
659
|
-
* {((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
|
|
660
|
-
* undefined)}
|
|
661
|
-
* initDataTransform
|
|
656
|
+
* @property {shaka.extern.InitDataTransform|undefined} initDataTransform
|
|
662
657
|
* <i>Optional.</i><br>
|
|
663
658
|
* If given, this function is called with the init data from the
|
|
664
659
|
* manifest/media and should return the (possibly transformed) init data to
|
|
@@ -687,6 +682,17 @@ shaka.extern.AdvancedDrmConfiguration;
|
|
|
687
682
|
*/
|
|
688
683
|
shaka.extern.DrmConfiguration;
|
|
689
684
|
|
|
685
|
+
/**
|
|
686
|
+
* @typedef {function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array}
|
|
687
|
+
*
|
|
688
|
+
* @description
|
|
689
|
+
* A callback function to handle custom content ID signaling for FairPlay
|
|
690
|
+
* content.
|
|
691
|
+
*
|
|
692
|
+
* @exportDoc
|
|
693
|
+
*/
|
|
694
|
+
shaka.extern.InitDataTransform;
|
|
695
|
+
|
|
690
696
|
|
|
691
697
|
/**
|
|
692
698
|
* @typedef {{
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
goog.provide('shaka.abr.SimpleAbrManager');
|
|
8
8
|
|
|
9
|
+
goog.require('shaka.util.IReleasable');
|
|
9
10
|
goog.require('goog.asserts');
|
|
10
11
|
goog.require('shaka.abr.EwmaBandwidthEstimator');
|
|
11
12
|
goog.require('shaka.log');
|
|
@@ -32,6 +33,7 @@ goog.require('shaka.util.Timer');
|
|
|
32
33
|
* </p>
|
|
33
34
|
*
|
|
34
35
|
* @implements {shaka.extern.AbrManager}
|
|
36
|
+
* @implements {shaka.util.IReleasable}
|
|
35
37
|
* @export
|
|
36
38
|
*/
|
|
37
39
|
shaka.abr.SimpleAbrManager = class {
|
|
@@ -50,8 +52,8 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
50
52
|
// retrieving information about a user's network connection. We listen
|
|
51
53
|
// to the change event to be able to make quick changes in case the type
|
|
52
54
|
// of connectivity changes.
|
|
53
|
-
if (navigator.connection) {
|
|
54
|
-
|
|
55
|
+
if (navigator.connection && navigator.connection.addEventListener) {
|
|
56
|
+
this.onNetworkInformationChange_ = () => {
|
|
55
57
|
if (this.config_.useNetworkInformation && this.enabled_) {
|
|
56
58
|
this.bandwidthEstimator_ = new shaka.abr.EwmaBandwidthEstimator();
|
|
57
59
|
if (this.config_) {
|
|
@@ -62,7 +64,10 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
62
64
|
this.switch_(chosenVariant);
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
|
-
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
navigator.connection.addEventListener(
|
|
70
|
+
'change', this.onNetworkInformationChange_);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/**
|
|
@@ -93,6 +98,9 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
93
98
|
/** @private {ResizeObserver} */
|
|
94
99
|
this.resizeObserver_ = null;
|
|
95
100
|
|
|
101
|
+
/** @private {?function():void} */
|
|
102
|
+
this.onNetworkInformationChange_ = null;
|
|
103
|
+
|
|
96
104
|
/** @private {shaka.util.Timer} */
|
|
97
105
|
this.resizeObserverTimer_ = new shaka.util.Timer(() => {
|
|
98
106
|
if (this.config_.restrictToElementSize) {
|
|
@@ -128,6 +136,22 @@ shaka.abr.SimpleAbrManager = class {
|
|
|
128
136
|
// can start using bandwidth estimates right away after init() is called.
|
|
129
137
|
}
|
|
130
138
|
|
|
139
|
+
/**
|
|
140
|
+
* @override
|
|
141
|
+
* @export
|
|
142
|
+
*/
|
|
143
|
+
release() {
|
|
144
|
+
// stop() should already have been called for unload
|
|
145
|
+
|
|
146
|
+
if (navigator.connection && navigator.connection.removeEventListener) {
|
|
147
|
+
navigator.connection.removeEventListener(
|
|
148
|
+
'change', this.onNetworkInformationChange_);
|
|
149
|
+
this.onNetworkInformationChange_ = null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.resizeObserverTimer_ = null;
|
|
153
|
+
}
|
|
154
|
+
|
|
131
155
|
|
|
132
156
|
/**
|
|
133
157
|
* @override
|
|
@@ -219,9 +219,9 @@ shaka.ads.ClientSideAdManager = class {
|
|
|
219
219
|
// seen the ads actually play until requestAds() is called.
|
|
220
220
|
// Note: We listen for a play event to avoid autoplay issues that might
|
|
221
221
|
// crash IMA.
|
|
222
|
-
this.
|
|
222
|
+
this.eventManager_.listenOnce(this.video_, 'play', () => {
|
|
223
223
|
this.imaAdsManager_.start();
|
|
224
|
-
}
|
|
224
|
+
});
|
|
225
225
|
} catch (adError) {
|
|
226
226
|
// If there was a problem with the VAST response,
|
|
227
227
|
// we we won't be getting an ad. Hide ad UI if we showed it already
|
|
@@ -427,7 +427,10 @@ shaka.ads.ClientSideAdManager = class {
|
|
|
427
427
|
if (this.ad_.isLinear()) {
|
|
428
428
|
this.adContainer_.setAttribute('ad-active', 'true');
|
|
429
429
|
this.video_.pause();
|
|
430
|
-
this.ad_.setVolume(this.video_.
|
|
430
|
+
this.ad_.setVolume(this.video_.volume);
|
|
431
|
+
if (this.video_.muted) {
|
|
432
|
+
this.ad_.setMuted(true);
|
|
433
|
+
}
|
|
431
434
|
}
|
|
432
435
|
}
|
|
433
436
|
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -1279,55 +1279,56 @@ shaka.dash.DashParser = class {
|
|
|
1279
1279
|
context.period.id + ',' + context.representation.id : '';
|
|
1280
1280
|
|
|
1281
1281
|
/** @type {shaka.extern.Stream} */
|
|
1282
|
-
|
|
1283
|
-
id: this.globalId_++,
|
|
1284
|
-
originalId: context.representation.id,
|
|
1285
|
-
createSegmentIndex: async () => {
|
|
1286
|
-
// If we have a stream with the same context id stored in the map
|
|
1287
|
-
// that has no segmentIndex, we should set the segmentIndex for it.
|
|
1288
|
-
const storedInMap = contextId && context.dynamic &&
|
|
1289
|
-
this.streamMap_[contextId];
|
|
1290
|
-
|
|
1291
|
-
const currentStream = storedInMap ? this.streamMap_[contextId] : stream;
|
|
1292
|
-
if (!currentStream.segmentIndex) {
|
|
1293
|
-
currentStream.segmentIndex = await streamInfo.generateSegmentIndex();
|
|
1294
|
-
}
|
|
1295
|
-
},
|
|
1282
|
+
let stream;
|
|
1296
1283
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1284
|
+
if (contextId && this.streamMap_[contextId]) {
|
|
1285
|
+
stream = this.streamMap_[contextId];
|
|
1286
|
+
} else {
|
|
1287
|
+
stream = {
|
|
1288
|
+
id: this.globalId_++,
|
|
1289
|
+
originalId: context.representation.id,
|
|
1290
|
+
createSegmentIndex: () => Promise.resolve(),
|
|
1291
|
+
closeSegmentIndex: () => {
|
|
1292
|
+
if (stream.segmentIndex) {
|
|
1293
|
+
stream.segmentIndex.release();
|
|
1294
|
+
stream.segmentIndex = null;
|
|
1295
|
+
}
|
|
1296
|
+
},
|
|
1297
|
+
segmentIndex: null,
|
|
1298
|
+
mimeType: context.representation.mimeType,
|
|
1299
|
+
codecs: context.representation.codecs,
|
|
1300
|
+
frameRate: context.representation.frameRate,
|
|
1301
|
+
pixelAspectRatio: context.representation.pixelAspectRatio,
|
|
1302
|
+
bandwidth: context.bandwidth,
|
|
1303
|
+
width: context.representation.width,
|
|
1304
|
+
height: context.representation.height,
|
|
1305
|
+
kind,
|
|
1306
|
+
encrypted: contentProtection.drmInfos.length > 0,
|
|
1307
|
+
drmInfos: contentProtection.drmInfos,
|
|
1308
|
+
keyIds,
|
|
1309
|
+
language,
|
|
1310
|
+
label,
|
|
1311
|
+
type: context.adaptationSet.contentType,
|
|
1312
|
+
primary: isPrimary,
|
|
1313
|
+
trickModeVideo: null,
|
|
1314
|
+
emsgSchemeIdUris:
|
|
1315
|
+
context.representation.emsgSchemeIdUris,
|
|
1316
|
+
roles,
|
|
1317
|
+
forced,
|
|
1318
|
+
channelsCount: context.representation.numChannels,
|
|
1319
|
+
audioSamplingRate: context.representation.audioSamplingRate,
|
|
1320
|
+
spatialAudio,
|
|
1321
|
+
closedCaptions,
|
|
1322
|
+
hdr,
|
|
1323
|
+
tilesLayout,
|
|
1324
|
+
matchedStreams: [],
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
stream.createSegmentIndex = async () => {
|
|
1329
|
+
if (!stream.segmentIndex) {
|
|
1330
|
+
stream.segmentIndex = await streamInfo.generateSegmentIndex();
|
|
1331
|
+
}
|
|
1331
1332
|
};
|
|
1332
1333
|
|
|
1333
1334
|
if (contextId && context.dynamic && !this.streamMap_[contextId]) {
|
package/lib/debug/log.js
CHANGED
|
@@ -134,23 +134,19 @@ shaka.log.MAX_LOG_LEVEL = 3;
|
|
|
134
134
|
shaka.log.oneTimeWarningIssued_ = new Set();
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
// IE9 console methods are not Functions and have no bind.
|
|
139
|
-
if (window.console && window.console.log.bind) {
|
|
137
|
+
if (window.console) {
|
|
140
138
|
/** @private {!Object.<shaka.log.Level, function(...*)>} */
|
|
141
139
|
shaka.log.logMap_ = {
|
|
142
|
-
|
|
143
|
-
[shaka.log.Level.
|
|
144
|
-
[shaka.log.Level.
|
|
145
|
-
[shaka.log.Level.
|
|
146
|
-
[shaka.log.Level.
|
|
147
|
-
[shaka.log.Level.
|
|
148
|
-
[shaka.log.Level.V2]: console.debug.bind(console),
|
|
149
|
-
/* eslint-enable no-restricted-syntax */
|
|
140
|
+
[shaka.log.Level.ERROR]: (...args) => console.error(...args),
|
|
141
|
+
[shaka.log.Level.WARNING]: (...args) => console.warn(...args),
|
|
142
|
+
[shaka.log.Level.INFO]: (...args) => console.info(...args),
|
|
143
|
+
[shaka.log.Level.DEBUG]: (...args) => console.log(...args),
|
|
144
|
+
[shaka.log.Level.V1]: (...args) => console.debug(...args),
|
|
145
|
+
[shaka.log.Level.V2]: (...args) => console.debug(...args),
|
|
150
146
|
};
|
|
151
147
|
|
|
152
|
-
shaka.log.alwaysWarn =
|
|
153
|
-
shaka.log.alwaysError =
|
|
148
|
+
shaka.log.alwaysWarn = (...args) => console.warn(...args);
|
|
149
|
+
shaka.log.alwaysError = (...args) => console.error(...args);
|
|
154
150
|
|
|
155
151
|
if (goog.DEBUG) {
|
|
156
152
|
// Since we don't want to export shaka.log in production builds, we don't
|
package/lib/hls/hls_parser.js
CHANGED
|
@@ -2131,6 +2131,9 @@ shaka.hls.HlsParser = class {
|
|
|
2131
2131
|
/* tileDuration= */ null,
|
|
2132
2132
|
/* syncTime= */ null,
|
|
2133
2133
|
partialStatus);
|
|
2134
|
+
if (item.name == 'EXT-X-PRELOAD-HINT') {
|
|
2135
|
+
partial.markAsPreload();
|
|
2136
|
+
}
|
|
2134
2137
|
partialSegmentRefs.push(partial);
|
|
2135
2138
|
} // for-loop of hlsSegment.partialSegments
|
|
2136
2139
|
}
|
|
@@ -2451,6 +2454,9 @@ shaka.hls.HlsParser = class {
|
|
|
2451
2454
|
* @private
|
|
2452
2455
|
*/
|
|
2453
2456
|
variableSubstitution_(uri, variables) {
|
|
2457
|
+
if (!variables.size) {
|
|
2458
|
+
return uri;
|
|
2459
|
+
}
|
|
2454
2460
|
let newUri = String(uri).replace(/%7B/g, '{').replace(/%7D/g, '}');
|
|
2455
2461
|
|
|
2456
2462
|
const uriVariables = newUri.match(/{\$\w*}/g);
|
|
@@ -158,7 +158,15 @@ shaka.hls.ManifestTextParser = class {
|
|
|
158
158
|
partialSegmentTags.push(tag);
|
|
159
159
|
} else if (tag.name == 'EXT-X-PRELOAD-HINT') {
|
|
160
160
|
if (tag.getAttributeValue('TYPE') == 'PART') {
|
|
161
|
-
|
|
161
|
+
// Note: BYTERANGE-START without BYTERANGE-LENGTH is being
|
|
162
|
+
// ignored.
|
|
163
|
+
if (tag.getAttributeValue('BYTERANGE-START') != null) {
|
|
164
|
+
if (tag.getAttributeValue('BYTERANGE-LENGTH') != null) {
|
|
165
|
+
partialSegmentTags.push(tag);
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
partialSegmentTags.push(tag);
|
|
169
|
+
}
|
|
162
170
|
} else if (tag.getAttributeValue('TYPE') == 'MAP') {
|
|
163
171
|
// Rename the Preload Hint tag to be a Map tag.
|
|
164
172
|
tag.setName('EXT-X-MAP');
|
|
@@ -300,6 +308,7 @@ shaka.hls.ManifestTextParser.MEDIA_PLAYLIST_TAGS = [
|
|
|
300
308
|
'EXT-X-ENDLIST',
|
|
301
309
|
'EXT-X-SERVER-CONTROL',
|
|
302
310
|
'EXT-X-SKIP',
|
|
311
|
+
'EXT-X-PART-INF',
|
|
303
312
|
];
|
|
304
313
|
|
|
305
314
|
|
package/lib/media/drm_engine.js
CHANGED
|
@@ -133,6 +133,9 @@ shaka.media.DrmEngine = class {
|
|
|
133
133
|
|
|
134
134
|
/** @private {Promise} */
|
|
135
135
|
this.mediaKeysAttached_ = null;
|
|
136
|
+
|
|
137
|
+
/** @private {?shaka.extern.InitDataOverride} */
|
|
138
|
+
this.manifestInitData_ = null;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
/** @override */
|
|
@@ -480,10 +483,10 @@ shaka.media.DrmEngine = class {
|
|
|
480
483
|
() => this.closeOpenSessions_());
|
|
481
484
|
}
|
|
482
485
|
|
|
483
|
-
|
|
484
|
-
this.currentDrmInfo_.initData.find(
|
|
486
|
+
this.manifestInitData_ = this.currentDrmInfo_ ?
|
|
487
|
+
(this.currentDrmInfo_.initData.find(
|
|
485
488
|
(initDataOverride) => initDataOverride.initData.length > 0,
|
|
486
|
-
) : null;
|
|
489
|
+
) || null) : null;
|
|
487
490
|
|
|
488
491
|
/**
|
|
489
492
|
* We can attach media keys before the playback actually begins when:
|
|
@@ -491,7 +494,7 @@ shaka.media.DrmEngine = class {
|
|
|
491
494
|
* - Some initData already has been generated (through the manifest)
|
|
492
495
|
* - In case of an offline session
|
|
493
496
|
*/
|
|
494
|
-
if (
|
|
497
|
+
if (this.manifestInitData_ ||
|
|
495
498
|
this.currentDrmInfo_.keySystem !== 'com.apple.fps' ||
|
|
496
499
|
this.offlineSessionIds_.length) {
|
|
497
500
|
await this.attachMediaKeys_();
|
|
@@ -504,7 +507,7 @@ shaka.media.DrmEngine = class {
|
|
|
504
507
|
// Also suppress 'encrypted' events when parsing in-band ppsh
|
|
505
508
|
// from media segments because that serves the same purpose as the
|
|
506
509
|
// 'encrypted' events.
|
|
507
|
-
if (!
|
|
510
|
+
if (!this.manifestInitData_ && !this.offlineSessionIds_.length &&
|
|
508
511
|
!this.config_.parseInbandPsshEnabled) {
|
|
509
512
|
this.eventManager_.listen(
|
|
510
513
|
this.video_, 'encrypted', (e) => this.onEncryptedEvent_(e));
|
|
@@ -2353,7 +2356,7 @@ shaka.media.DrmEngine = class {
|
|
|
2353
2356
|
* @return {!Promise<void>}
|
|
2354
2357
|
*/
|
|
2355
2358
|
parseInbandPssh(contentType, mediaSegment) {
|
|
2356
|
-
if (!this.config_.parseInbandPsshEnabled) {
|
|
2359
|
+
if (!this.config_.parseInbandPsshEnabled || this.manifestInitData_) {
|
|
2357
2360
|
return Promise.resolve();
|
|
2358
2361
|
}
|
|
2359
2362
|
|
|
@@ -99,15 +99,15 @@ shaka.media.MediaSourceEngine = class {
|
|
|
99
99
|
/** @private {!shaka.util.PublicPromise} */
|
|
100
100
|
this.mediaSourceOpen_ = new shaka.util.PublicPromise();
|
|
101
101
|
|
|
102
|
+
/** @private {string} */
|
|
103
|
+
this.url_ = '';
|
|
104
|
+
|
|
102
105
|
/** @private {MediaSource} */
|
|
103
106
|
this.mediaSource_ = this.createMediaSource(this.mediaSourceOpen_);
|
|
104
107
|
|
|
105
108
|
/** @type {!shaka.util.Destroyer} */
|
|
106
109
|
this.destroyer_ = new shaka.util.Destroyer(() => this.doDestroy_());
|
|
107
110
|
|
|
108
|
-
/** @private {string} */
|
|
109
|
-
this.url_ = '';
|
|
110
|
-
|
|
111
111
|
/** @private {boolean} */
|
|
112
112
|
this.sequenceMode_ = false;
|
|
113
113
|
|
|
@@ -144,6 +144,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
144
144
|
* @private
|
|
145
145
|
*/
|
|
146
146
|
onSourceOpen_(p) {
|
|
147
|
+
goog.asserts.assert(this.url_, 'Must have object URL');
|
|
148
|
+
|
|
147
149
|
// Release the object URL that was previously created, to prevent memory
|
|
148
150
|
// leak.
|
|
149
151
|
// createObjectURL creates a strong reference to the MediaSource object
|
|
@@ -192,6 +194,9 @@ shaka.media.MediaSourceEngine = class {
|
|
|
192
194
|
'audio/mp4; codecs="ec-3"',
|
|
193
195
|
'audio/mp4; codecs="opus"',
|
|
194
196
|
'audio/mp4; codecs="flac"',
|
|
197
|
+
'audio/mp4; codecs="dtsc"', // DTS Digital Surround
|
|
198
|
+
'audio/mp4; codecs="dtse"', // DTS Express
|
|
199
|
+
'audio/mp4; codecs="dtsx"', // DTS:X
|
|
195
200
|
// WebM types
|
|
196
201
|
'video/webm; codecs="vp8"',
|
|
197
202
|
'video/webm; codecs="vp9"',
|
|
@@ -556,7 +561,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
556
561
|
// For HLS CEA-608/708 CLOSED-CAPTIONS, text data is embedded in
|
|
557
562
|
// the video stream, so textEngine may not have been initialized.
|
|
558
563
|
if (!this.textEngine_) {
|
|
559
|
-
this.reinitText(
|
|
564
|
+
this.reinitText(shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE,
|
|
565
|
+
this.sequenceMode_);
|
|
560
566
|
}
|
|
561
567
|
|
|
562
568
|
if (transmuxedData.metadata) {
|
|
@@ -584,7 +590,8 @@ shaka.media.MediaSourceEngine = class {
|
|
|
584
590
|
data = transmuxedData.data;
|
|
585
591
|
} else if (hasClosedCaptions) {
|
|
586
592
|
if (!this.textEngine_) {
|
|
587
|
-
this.reinitText(
|
|
593
|
+
this.reinitText(shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE,
|
|
594
|
+
this.sequenceMode_);
|
|
588
595
|
}
|
|
589
596
|
// If it is the init segment for closed captions, initialize the closed
|
|
590
597
|
// caption parser.
|
|
@@ -705,7 +712,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
705
712
|
this.append_(contentType, data);
|
|
706
713
|
});
|
|
707
714
|
|
|
708
|
-
if (goog.DEBUG && reference) {
|
|
715
|
+
if (goog.DEBUG && reference && !reference.isPreload()) {
|
|
709
716
|
const bufferedAfter = this.getBuffered_(contentType);
|
|
710
717
|
const newBuffered = shaka.media.TimeRangesUtils.computeAddedRange(
|
|
711
718
|
bufferedBefore, bufferedAfter);
|
|
@@ -910,8 +917,10 @@ shaka.media.MediaSourceEngine = class {
|
|
|
910
917
|
async endOfStream(reason) {
|
|
911
918
|
await this.enqueueBlockingOperation_(() => {
|
|
912
919
|
// If endOfStream() has already been called on the media source,
|
|
913
|
-
// don't call it again.
|
|
914
|
-
|
|
920
|
+
// don't call it again. Also do not call if readyState is
|
|
921
|
+
// 'closed' (not attached to video element) since it is not a
|
|
922
|
+
// valid operation.
|
|
923
|
+
if (this.ended() || this.mediaSource_.readyState === 'closed') {
|
|
915
924
|
return;
|
|
916
925
|
}
|
|
917
926
|
// Tizen won't let us pass undefined, but it will let us omit the
|