rx-player 4.3.0-dev.2024112900 → 4.3.0-dev.2025011000
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/CHANGELOG.md +24 -8
- package/VERSION +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/commonjs/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/commonjs/compat/browser_compatibility_types.js +0 -1
- package/dist/commonjs/compat/browser_detection.js +1 -1
- package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
- package/dist/commonjs/compat/event_listeners.js +2 -4
- package/dist/commonjs/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/commonjs/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/commonjs/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/commonjs/core/main/worker/send_message.js +0 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +4 -8
- package/dist/commonjs/core/stream/period/period_stream.js +1 -3
- package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/commonjs/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/commonjs/main_thread/api/public_api.js +4 -4
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/clear_on_stop.js +60 -14
- package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.js +2 -18
- package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/find_key_system.js +134 -68
- package/dist/commonjs/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/commonjs/main_thread/decrypt/get_media_keys.js +5 -3
- package/dist/commonjs/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts → commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.js +282 -0
- package/dist/commonjs/main_thread/init/utils/rebuffering_controller.js +1 -1
- package/dist/commonjs/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/tracks_store.js +1 -1
- package/dist/commonjs/manifest/classes/representation.d.ts +15 -1
- package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
- package/dist/commonjs/manifest/classes/representation.js +17 -0
- package/dist/commonjs/manifest/utils.d.ts +15 -0
- package/dist/commonjs/manifest/utils.d.ts.map +1 -1
- package/dist/commonjs/manifest/utils.js +28 -5
- package/dist/commonjs/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/commonjs/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/commonjs/public_types.d.ts +44 -0
- package/dist/commonjs/public_types.d.ts.map +1 -1
- package/dist/commonjs/utils/flat_map.d.ts +2 -2
- package/dist/commonjs/utils/flat_map.js +2 -2
- package/dist/commonjs/utils/url-utils.d.ts.map +1 -1
- package/dist/commonjs/utils/url-utils.js +11 -10
- package/dist/commonjs/utils/xml-parser.d.ts.map +1 -1
- package/dist/commonjs/utils/xml-parser.js +10 -8
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/es2017/compat/browser_compatibility_types.d.ts +7 -2
- package/dist/es2017/compat/browser_compatibility_types.d.ts.map +1 -1
- package/dist/es2017/compat/browser_compatibility_types.js +0 -1
- package/dist/es2017/compat/browser_detection.js +1 -1
- package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
- package/dist/es2017/compat/event_listeners.js +2 -4
- package/dist/es2017/compat/has_mse_in_worker.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
- package/dist/es2017/core/cmcd/cmcd_data_builder.js +1 -2
- package/dist/es2017/core/main/worker/send_message.d.ts.map +1 -1
- package/dist/es2017/core/main/worker/send_message.js +0 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
- package/dist/es2017/core/stream/adaptation/adaptation_stream.js +4 -6
- package/dist/es2017/core/stream/period/period_stream.js +1 -3
- package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
- package/dist/es2017/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
- package/dist/es2017/main_thread/api/public_api.js +4 -4
- package/dist/es2017/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/clear_on_stop.js +3 -3
- package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/content_decryptor.js +21 -9
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.js +2 -12
- package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/find_key_system.js +102 -56
- package/dist/es2017/main_thread/decrypt/get_key_system_configuration.js +2 -2
- package/dist/es2017/main_thread/decrypt/get_media_keys.js +2 -2
- package/dist/es2017/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/init_media_keys.js +2 -2
- package/dist/{commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts → es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts} +31 -9
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
- package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.js +180 -0
- package/dist/es2017/main_thread/init/utils/rebuffering_controller.js +1 -1
- package/dist/es2017/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/track_dispatcher.js +3 -4
- package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/tracks_store.js +2 -2
- package/dist/es2017/manifest/classes/representation.d.ts +15 -1
- package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
- package/dist/es2017/manifest/classes/representation.js +17 -0
- package/dist/es2017/manifest/utils.d.ts +15 -0
- package/dist/es2017/manifest/utils.d.ts.map +1 -1
- package/dist/es2017/manifest/utils.js +27 -5
- package/dist/es2017/parsers/manifest/dash/common/parse_representations.js +2 -2
- package/dist/es2017/playback_observer/media_element_playback_observer.js +1 -1
- package/dist/es2017/public_types.d.ts +44 -0
- package/dist/es2017/public_types.d.ts.map +1 -1
- package/dist/es2017/utils/flat_map.d.ts +2 -2
- package/dist/es2017/utils/flat_map.js +2 -2
- package/dist/es2017/utils/url-utils.d.ts.map +1 -1
- package/dist/es2017/utils/url-utils.js +11 -10
- package/dist/es2017/utils/xml-parser.d.ts.map +1 -1
- package/dist/es2017/utils/xml-parser.js +10 -8
- package/dist/rx-player.js +494 -364
- package/dist/rx-player.min.js +18 -18
- package/dist/worker.js +6 -6
- package/package.json +21 -19
- package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
- package/src/compat/browser_compatibility_types.ts +22 -4
- package/src/compat/browser_detection.ts +1 -1
- package/src/compat/event_listeners.ts +2 -4
- package/src/compat/has_mse_in_worker.ts +1 -1
- package/src/core/cmcd/cmcd_data_builder.ts +1 -4
- package/src/core/main/worker/send_message.ts +4 -2
- package/src/core/stream/adaptation/adaptation_stream.ts +4 -7
- package/src/core/stream/period/period_stream.ts +3 -3
- package/src/core/stream/period/utils/get_adaptation_switch_strategy.ts +1 -2
- package/src/main_thread/api/public_api.ts +4 -4
- package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +239 -6
- package/src/main_thread/decrypt/__tests__/find_key_system.test.ts +325 -0
- package/src/main_thread/decrypt/clear_on_stop.ts +3 -3
- package/src/main_thread/decrypt/content_decryptor.ts +26 -8
- package/src/main_thread/decrypt/dispose_decryption_resources.ts +2 -13
- package/src/main_thread/decrypt/find_key_system.ts +120 -81
- package/src/main_thread/decrypt/get_key_system_configuration.ts +2 -2
- package/src/main_thread/decrypt/get_media_keys.ts +2 -2
- package/src/main_thread/decrypt/init_media_keys.ts +2 -2
- package/src/main_thread/decrypt/utils/media_keys_attacher.ts +284 -0
- package/src/main_thread/init/utils/rebuffering_controller.ts +1 -1
- package/src/main_thread/text_displayer/html/text_track_cues_store.ts +1 -1
- package/src/main_thread/tracks_store/track_dispatcher.ts +3 -6
- package/src/main_thread/tracks_store/tracks_store.ts +2 -1
- package/src/manifest/classes/representation.ts +18 -1
- package/src/manifest/utils.ts +30 -9
- package/src/parsers/manifest/dash/common/parse_representations.ts +2 -2
- package/src/playback_observer/media_element_playback_observer.ts +1 -1
- package/src/public_types.ts +45 -0
- package/src/utils/__tests__/flat_map.test.ts +7 -20
- package/src/utils/flat_map.ts +2 -2
- package/src/utils/url-utils.ts +11 -10
- package/src/utils/xml-parser.ts +13 -8
- package/vitest.config.mjs +9 -4
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/attach_media_keys.js +0 -124
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.js +0 -45
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts +0 -60
- package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/attach_media_keys.js +0 -73
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
- package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.js +0 -43
- package/src/main_thread/decrypt/attach_media_keys.ts +0 -125
- package/src/main_thread/decrypt/utils/media_keys_infos_store.ts +0 -88
|
@@ -24,37 +24,67 @@ import { parseCodec } from "../../utils/are_codecs_compatible";
|
|
|
24
24
|
import arrayIncludes from "../../utils/array_includes";
|
|
25
25
|
import flatMap from "../../utils/flat_map";
|
|
26
26
|
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
27
|
-
import
|
|
27
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
29
|
+
* Takes a `newConfiguration` `MediaKeySystemConfiguration`, that is intended
|
|
30
|
+
* for the creation of a `MediaKeySystemAccess`, and a `prevConfiguration`
|
|
31
|
+
* `MediaKeySystemConfiguration`, that was the one used at creation of the
|
|
32
|
+
* current `MediaKeySystemAccess`.
|
|
33
|
+
*
|
|
34
|
+
* This function will then return `true` if it determined that the new
|
|
35
|
+
* configuration is conceptually compatible with the one used before, and
|
|
36
|
+
* `false` otherwise.
|
|
37
|
+
* @param {Object} newConfiguration - New wanted `MediaKeySystemConfiguration`
|
|
38
|
+
* @param {Object} prevConfiguration - The `MediaKeySystemConfiguration` that is
|
|
39
|
+
* relied on util now.
|
|
40
|
+
* @returns {boolean} - `true` if `newConfiguration` is compatible with
|
|
41
|
+
* `prevConfiguration`.
|
|
34
42
|
*/
|
|
35
|
-
function
|
|
36
|
-
|
|
37
|
-
if (
|
|
38
|
-
return
|
|
43
|
+
function isNewMediaKeySystemConfigurationCompatibleWithPreviousOne(newConfiguration, prevConfiguration) {
|
|
44
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
45
|
+
if (newConfiguration.label !== prevConfiguration.label) {
|
|
46
|
+
return false;
|
|
39
47
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
const prevDistinctiveIdentifier = (_a = prevConfiguration.distinctiveIdentifier) !== null && _a !== void 0 ? _a : "optional";
|
|
49
|
+
const newDistinctiveIdentifier = (_b = newConfiguration.distinctiveIdentifier) !== null && _b !== void 0 ? _b : "optional";
|
|
50
|
+
if (prevDistinctiveIdentifier !== newDistinctiveIdentifier) {
|
|
51
|
+
return false;
|
|
43
52
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return
|
|
53
|
+
const prevPersistentState = (_c = prevConfiguration.persistentState) !== null && _c !== void 0 ? _c : "optional";
|
|
54
|
+
const newPersistentState = (_d = newConfiguration.persistentState) !== null && _d !== void 0 ? _d : "optional";
|
|
55
|
+
if (prevPersistentState !== newPersistentState) {
|
|
56
|
+
return false;
|
|
48
57
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
const prevInitDataTypes = (_e = prevConfiguration.initDataTypes) !== null && _e !== void 0 ? _e : [];
|
|
59
|
+
const newInitDataTypes = (_f = newConfiguration.initDataTypes) !== null && _f !== void 0 ? _f : [];
|
|
60
|
+
if (!isArraySubsetOf(newInitDataTypes, prevInitDataTypes)) {
|
|
61
|
+
return false;
|
|
52
62
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
63
|
+
const prevSessionTypes = (_g = prevConfiguration.sessionTypes) !== null && _g !== void 0 ? _g : [];
|
|
64
|
+
const newSessionTypes = (_h = newConfiguration.sessionTypes) !== null && _h !== void 0 ? _h : [];
|
|
65
|
+
if (!isArraySubsetOf(newSessionTypes, prevSessionTypes)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
for (const prop of ["audioCapabilities", "videoCapabilities"]) {
|
|
69
|
+
const newCapabilities = (_j = newConfiguration[prop]) !== null && _j !== void 0 ? _j : [];
|
|
70
|
+
const prevCapabilities = (_k = prevConfiguration[prop]) !== null && _k !== void 0 ? _k : [];
|
|
71
|
+
const wasFound = newCapabilities.every((n) => {
|
|
72
|
+
var _a, _b, _c, _d, _e, _f;
|
|
73
|
+
for (let i = 0; i < prevCapabilities.length; i++) {
|
|
74
|
+
const prevCap = prevCapabilities[i];
|
|
75
|
+
if (((_a = prevCap.robustness) !== null && _a !== void 0 ? _a : "") === ((_b = n.robustness) !== null && _b !== void 0 ? _b : "") ||
|
|
76
|
+
((_c = prevCap.encryptionScheme) !== null && _c !== void 0 ? _c : null) === ((_d = n.encryptionScheme) !== null && _d !== void 0 ? _d : null) ||
|
|
77
|
+
((_e = prevCap.robustness) !== null && _e !== void 0 ? _e : "") === ((_f = n.robustness) !== null && _f !== void 0 ? _f : "")) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
});
|
|
83
|
+
if (!wasFound) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
58
88
|
}
|
|
59
89
|
/**
|
|
60
90
|
* Find key system canonical name from key system type.
|
|
@@ -79,12 +109,22 @@ function findKeySystemCanonicalName(ksType) {
|
|
|
79
109
|
*/
|
|
80
110
|
function buildKeySystemConfigurations(keySystemTypeInfo) {
|
|
81
111
|
const { keyName, keyType, keySystemOptions: keySystem } = keySystemTypeInfo;
|
|
82
|
-
|
|
112
|
+
let sessionTypes;
|
|
83
113
|
let persistentState = "optional";
|
|
84
114
|
let distinctiveIdentifier = "optional";
|
|
85
|
-
if (
|
|
115
|
+
if (Array.isArray(keySystem.wantedSessionTypes)) {
|
|
116
|
+
sessionTypes = keySystem.wantedSessionTypes;
|
|
117
|
+
if (arrayIncludes(keySystem.wantedSessionTypes, "persistent-license") &&
|
|
118
|
+
!isNullOrUndefined(keySystem.persistentLicenseConfig)) {
|
|
119
|
+
persistentState = "required";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (!isNullOrUndefined(keySystem.persistentLicenseConfig)) {
|
|
86
123
|
persistentState = "required";
|
|
87
|
-
sessionTypes
|
|
124
|
+
sessionTypes = ["persistent-license"];
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
sessionTypes = ["temporary"];
|
|
88
128
|
}
|
|
89
129
|
if (!isNullOrUndefined(keySystem.persistentState)) {
|
|
90
130
|
persistentState = keySystem.persistentState;
|
|
@@ -259,14 +299,7 @@ export function extractCodecSupportListFromConfiguration(initialConfiguration, m
|
|
|
259
299
|
*/
|
|
260
300
|
export default function getMediaKeySystemAccess(mediaElement, keySystemsConfigs, cancelSignal) {
|
|
261
301
|
log.info("DRM: Searching for compatible MediaKeySystemAccess");
|
|
262
|
-
/**
|
|
263
|
-
* Array of set keySystems for this content.
|
|
264
|
-
* Each item of this array is an object containing the following keys:
|
|
265
|
-
* - keyName {string}: keySystem canonical name (e.g. "widevine")
|
|
266
|
-
* - keyType {string}: keySystem type (e.g. "com.widevine.alpha")
|
|
267
|
-
* - keySystem {Object}: the original keySystem object
|
|
268
|
-
* @type {Array.<Object>}
|
|
269
|
-
*/
|
|
302
|
+
/** Array of set keySystems for this content. */
|
|
270
303
|
const keySystemsType = keySystemsConfigs.reduce((arr, keySystemOptions) => {
|
|
271
304
|
const { EME_KEY_SYSTEMS } = config.getCurrent();
|
|
272
305
|
const managedRDNs = EME_KEY_SYSTEMS[keySystemOptions.type];
|
|
@@ -306,33 +339,32 @@ export default function getMediaKeySystemAccess(mediaElement, keySystemsConfigs,
|
|
|
306
339
|
throw new Error("requestMediaKeySystemAccess is not implemented in your browser.");
|
|
307
340
|
}
|
|
308
341
|
const chosenType = keySystemsType[index];
|
|
309
|
-
const currentState = MediaKeysInfosStore.getState(mediaElement);
|
|
310
|
-
if (currentState !== null) {
|
|
311
|
-
if (eme.implementation === currentState.emeImplementation.implementation) {
|
|
312
|
-
// Fast way to find a compatible keySystem if the currently loaded
|
|
313
|
-
// one as exactly the same compatibility options.
|
|
314
|
-
const cachedKeySystemAccess = checkCachedMediaKeySystemAccess(chosenType.keySystemOptions, currentState.askedConfiguration, currentState.mediaKeySystemAccess, currentState.keySystemOptions);
|
|
315
|
-
if (cachedKeySystemAccess !== null) {
|
|
316
|
-
log.info("DRM: Found cached compatible keySystem");
|
|
317
|
-
return Promise.resolve({
|
|
318
|
-
type: "reuse-media-key-system-access",
|
|
319
|
-
value: {
|
|
320
|
-
mediaKeySystemAccess: cachedKeySystemAccess.keySystemAccess,
|
|
321
|
-
askedConfiguration: cachedKeySystemAccess.askedConfiguration,
|
|
322
|
-
options: cachedKeySystemAccess.keySystemOptions,
|
|
323
|
-
codecSupport: extractCodecSupportListFromConfiguration(cachedKeySystemAccess.askedConfiguration, cachedKeySystemAccess.keySystemAccess.getConfiguration()),
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
342
|
const { keyType, keySystemOptions } = chosenType;
|
|
330
343
|
const keySystemConfigurations = buildKeySystemConfigurations(chosenType);
|
|
331
344
|
log.debug(`DRM: Request keysystem access ${keyType},` +
|
|
332
345
|
`${index + 1} of ${keySystemsType.length}`);
|
|
333
346
|
let keySystemAccess;
|
|
347
|
+
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
|
|
334
348
|
for (let configIdx = 0; configIdx < keySystemConfigurations.length; configIdx++) {
|
|
335
349
|
const keySystemConfiguration = keySystemConfigurations[configIdx];
|
|
350
|
+
// Check if the current `MediaKeySystemAccess` created cannot be reused here
|
|
351
|
+
if (currentState !== null &&
|
|
352
|
+
!shouldRenewMediaKeySystemAccess() &&
|
|
353
|
+
// TODO: Do it with MediaKeySystemAccess.prototype.keySystem instead?
|
|
354
|
+
keyType === currentState.mediaKeySystemAccess.keySystem &&
|
|
355
|
+
eme.implementation === currentState.emeImplementation.implementation &&
|
|
356
|
+
isNewMediaKeySystemConfigurationCompatibleWithPreviousOne(keySystemConfiguration, currentState.askedConfiguration)) {
|
|
357
|
+
log.info("DRM: Found cached compatible keySystem");
|
|
358
|
+
return Promise.resolve({
|
|
359
|
+
type: "reuse-media-key-system-access",
|
|
360
|
+
value: {
|
|
361
|
+
mediaKeySystemAccess: currentState.mediaKeySystemAccess,
|
|
362
|
+
askedConfiguration: currentState.askedConfiguration,
|
|
363
|
+
options: keySystemOptions,
|
|
364
|
+
codecSupport: extractCodecSupportListFromConfiguration(currentState.askedConfiguration, currentState.mediaKeySystemAccess.getConfiguration()),
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
}
|
|
336
368
|
try {
|
|
337
369
|
keySystemAccess = await testKeySystem(keyType, [keySystemConfiguration]);
|
|
338
370
|
log.info("DRM: Found compatible keysystem", keyType, index + 1);
|
|
@@ -382,3 +414,17 @@ export async function testKeySystem(keyType, keySystemConfigurations) {
|
|
|
382
414
|
}
|
|
383
415
|
return keySystemAccess;
|
|
384
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Returns `true` if `arr1`'s values are entirely contained in `arr2`.
|
|
419
|
+
* @param {string} arr1
|
|
420
|
+
* @param {string} arr2
|
|
421
|
+
* @return {boolean}
|
|
422
|
+
*/
|
|
423
|
+
function isArraySubsetOf(arr1, arr2) {
|
|
424
|
+
for (let i = 0; i < arr1.length; i++) {
|
|
425
|
+
if (!arrayIncludes(arr2, arr1[i])) {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import
|
|
16
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
17
17
|
/**
|
|
18
18
|
* Returns the name of the current key system used as well as its configuration,
|
|
19
19
|
* as reported by the `MediaKeySystemAccess` itself.
|
|
@@ -21,7 +21,7 @@ import MediaKeysInfosStore from "./utils/media_keys_infos_store";
|
|
|
21
21
|
* @returns {Array|null}
|
|
22
22
|
*/
|
|
23
23
|
export default function getKeySystemConfiguration(mediaElement) {
|
|
24
|
-
const currentState =
|
|
24
|
+
const currentState = MediaKeysAttacher.getAwaitedState(mediaElement);
|
|
25
25
|
if (currentState === null) {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
@@ -19,7 +19,7 @@ import log from "../../log";
|
|
|
19
19
|
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
20
20
|
import getMediaKeySystemAccess from "./find_key_system";
|
|
21
21
|
import LoadedSessionsStore from "./utils/loaded_sessions_store";
|
|
22
|
-
import
|
|
22
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
23
23
|
import PersistentSessionsStore from "./utils/persistent_sessions_store";
|
|
24
24
|
import ServerCertificateStore from "./utils/server_certificate_store";
|
|
25
25
|
/**
|
|
@@ -54,7 +54,7 @@ export default async function getMediaKeysInfos(mediaElement, keySystemsConfigs,
|
|
|
54
54
|
throw cancelSignal.cancellationError;
|
|
55
55
|
}
|
|
56
56
|
const { options, mediaKeySystemAccess, askedConfiguration, codecSupport } = evt.value;
|
|
57
|
-
const currentState =
|
|
57
|
+
const currentState = await MediaKeysAttacher.getAttachedMediaKeysState(mediaElement);
|
|
58
58
|
const persistentSessionsStore = createPersistentSessionsStorage(options);
|
|
59
59
|
if (evt.value.options.reuseMediaKeys !== false &&
|
|
60
60
|
canReuseMediaKeys() &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init_media_keys.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/decrypt/init_media_keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"init_media_keys.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/decrypt/init_media_keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD;;;;;;GAMG;AACH,wBAA8B,aAAa,CACzC,YAAY,EAAE,aAAa,EAC3B,iBAAiB,EAAE,gBAAgB,EAAE,EACrC,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,eAAe,CAAC,CAkB1B"}
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import log from "../../log";
|
|
17
|
-
import { disableMediaKeys } from "./attach_media_keys";
|
|
18
17
|
import getMediaKeysInfos from "./get_media_keys";
|
|
18
|
+
import MediaKeysAttacher from "./utils/media_keys_attacher";
|
|
19
19
|
/**
|
|
20
20
|
* Get media keys infos from key system configs then attach media keys to media element.
|
|
21
21
|
* @param {HTMLMediaElement} mediaElement
|
|
@@ -31,7 +31,7 @@ export default async function initMediaKeys(mediaElement, keySystemsConfigs, can
|
|
|
31
31
|
mediaKeys !== mediaElement.mediaKeys;
|
|
32
32
|
if (shouldDisableOldMediaKeys) {
|
|
33
33
|
log.debug("DRM: Disabling old MediaKeys");
|
|
34
|
-
await
|
|
34
|
+
await MediaKeysAttacher.clearMediaKeys(mediaElement);
|
|
35
35
|
}
|
|
36
36
|
return mediaKeysInfo;
|
|
37
37
|
}
|
|
@@ -42,22 +42,44 @@ export interface IMediaElementMediaKeysInfos {
|
|
|
42
42
|
}
|
|
43
43
|
declare const _default: {
|
|
44
44
|
/**
|
|
45
|
-
*
|
|
45
|
+
* Attach new MediaKeys infos set on a HMTLMediaElement.
|
|
46
46
|
* @param {HTMLMediaElement} mediaElement
|
|
47
|
-
* @param {Object}
|
|
47
|
+
* @param {Object} mediaKeysInfo
|
|
48
|
+
* @returns {Promise}
|
|
48
49
|
*/
|
|
49
|
-
|
|
50
|
+
attach(mediaElement: IMediaElement, mediaKeysInfo: IMediaElementMediaKeysInfos): Promise<void>;
|
|
50
51
|
/**
|
|
51
|
-
* Get MediaKeys
|
|
52
|
+
* Get MediaKeys information expected to be linked to the given
|
|
53
|
+
* `HTMLMediaElement`.
|
|
54
|
+
*
|
|
55
|
+
* Unlike `getAttachedMediaKeysState`, this method is synchronous and will
|
|
56
|
+
* also return the expected state when `MediaKeys` attachment is still
|
|
57
|
+
* pending and thus when that state is not truly applied (and where it
|
|
58
|
+
* might fail before being applied).
|
|
59
|
+
*
|
|
60
|
+
* As such, only call this method if you want the currently expected state,
|
|
61
|
+
* not the actual one.
|
|
52
62
|
* @param {HTMLMediaElement} mediaElement
|
|
53
|
-
* @returns {
|
|
63
|
+
* @returns {Array}
|
|
54
64
|
*/
|
|
55
|
-
|
|
65
|
+
getAwaitedState(mediaElement: IMediaElement): IMediaElementMediaKeysInfos | null;
|
|
56
66
|
/**
|
|
57
|
-
*
|
|
67
|
+
* Get MediaKeys information set on a HMTLMediaElement.
|
|
68
|
+
*
|
|
69
|
+
* This method is asynchronous because that state may still be in a process
|
|
70
|
+
* of being attached to the `HTMLMediaElement` (and the state we're
|
|
71
|
+
* currently setting may not work out).
|
|
58
72
|
* @param {HTMLMediaElement} mediaElement
|
|
73
|
+
* @returns {Object|null}
|
|
59
74
|
*/
|
|
60
|
-
|
|
75
|
+
getAttachedMediaKeysState(mediaElement: IMediaElement): Promise<IMediaElementMediaKeysInfos | null>;
|
|
76
|
+
/**
|
|
77
|
+
* Remove MediaKeys currently set on a HMTLMediaElement and update state
|
|
78
|
+
* accordingly.
|
|
79
|
+
* @param {HTMLMediaElement} mediaElement
|
|
80
|
+
* @returns {Promise}
|
|
81
|
+
*/
|
|
82
|
+
clearMediaKeys(mediaElement: IMediaElement): Promise<void>;
|
|
61
83
|
};
|
|
62
84
|
export default _default;
|
|
63
|
-
//# sourceMappingURL=
|
|
85
|
+
//# sourceMappingURL=media_keys_attacher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media_keys_attacher.d.ts","sourceRoot":"","sources":["../../../../../src/main_thread/decrypt/utils/media_keys_attacher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EACV,gBAAgB,EAChB,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,mBAAmB,MAAM,yBAAyB,CAAC;AAE/D,6EAA6E;AAC7E,MAAM,WAAW,2BAA2B;IAC1C,iBAAiB,EAAE,qBAAqB,CAAC;IAEzC,6DAA6D;IAC7D,gBAAgB,EAAE,gBAAgB,CAAC;IAEnC;;;OAGG;IACH,kBAAkB,EAAE,2BAA2B,CAAC;IAEhD;;;OAGG;IACH,oBAAoB,EAAE,2BAA2B,GAAG,oBAAoB,CAAC;IAEzE,8DAA8D;IAC9D,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAAC;IAExC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C;;IA6BC;;;;;OAKG;yBAEa,aAAa,iBACZ,2BAA2B,GACzC,OAAO,CAAC,IAAI,CAAC;IAuBhB;;;;;;;;;;;;;OAaG;kCAC2B,aAAa,GAAG,2BAA2B,GAAG,IAAI;IAKhF;;;;;;;;OAQG;4CAEa,aAAa,GAC1B,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;IAY9C;;;;;OAKG;iCAC0B,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;;AAjF5D,wBAuGE"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2015 CANAL+ Group
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { setMediaKeys } from "../../../compat/eme/set_media_keys";
|
|
17
|
+
import { EncryptedMediaError } from "../../../errors";
|
|
18
|
+
import log from "../../../log";
|
|
19
|
+
import isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
20
|
+
// Store the MediaKeys infos attached to a media element.
|
|
21
|
+
const currentMediaState = new WeakMap();
|
|
22
|
+
export default {
|
|
23
|
+
/**
|
|
24
|
+
* Attach new MediaKeys infos set on a HMTLMediaElement.
|
|
25
|
+
* @param {HTMLMediaElement} mediaElement
|
|
26
|
+
* @param {Object} mediaKeysInfo
|
|
27
|
+
* @returns {Promise}
|
|
28
|
+
*/
|
|
29
|
+
async attach(mediaElement, mediaKeysInfo) {
|
|
30
|
+
const previousState = currentMediaState.get(mediaElement);
|
|
31
|
+
const pendingTask = attachMediaKeys(mediaElement, previousState, mediaKeysInfo).then(() => {
|
|
32
|
+
currentMediaState.set(mediaElement, {
|
|
33
|
+
pendingTask: null,
|
|
34
|
+
mediaKeysState: mediaKeysInfo,
|
|
35
|
+
});
|
|
36
|
+
}, () => {
|
|
37
|
+
currentMediaState.set(mediaElement, {
|
|
38
|
+
pendingTask: null,
|
|
39
|
+
mediaKeysState: null,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
currentMediaState.set(mediaElement, {
|
|
43
|
+
pendingTask,
|
|
44
|
+
mediaKeysState: mediaKeysInfo,
|
|
45
|
+
});
|
|
46
|
+
return pendingTask;
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Get MediaKeys information expected to be linked to the given
|
|
50
|
+
* `HTMLMediaElement`.
|
|
51
|
+
*
|
|
52
|
+
* Unlike `getAttachedMediaKeysState`, this method is synchronous and will
|
|
53
|
+
* also return the expected state when `MediaKeys` attachment is still
|
|
54
|
+
* pending and thus when that state is not truly applied (and where it
|
|
55
|
+
* might fail before being applied).
|
|
56
|
+
*
|
|
57
|
+
* As such, only call this method if you want the currently expected state,
|
|
58
|
+
* not the actual one.
|
|
59
|
+
* @param {HTMLMediaElement} mediaElement
|
|
60
|
+
* @returns {Array}
|
|
61
|
+
*/
|
|
62
|
+
getAwaitedState(mediaElement) {
|
|
63
|
+
var _a;
|
|
64
|
+
const currentState = currentMediaState.get(mediaElement);
|
|
65
|
+
return (_a = currentState === null || currentState === void 0 ? void 0 : currentState.mediaKeysState) !== null && _a !== void 0 ? _a : null;
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Get MediaKeys information set on a HMTLMediaElement.
|
|
69
|
+
*
|
|
70
|
+
* This method is asynchronous because that state may still be in a process
|
|
71
|
+
* of being attached to the `HTMLMediaElement` (and the state we're
|
|
72
|
+
* currently setting may not work out).
|
|
73
|
+
* @param {HTMLMediaElement} mediaElement
|
|
74
|
+
* @returns {Object|null}
|
|
75
|
+
*/
|
|
76
|
+
async getAttachedMediaKeysState(mediaElement) {
|
|
77
|
+
const currentState = currentMediaState.get(mediaElement);
|
|
78
|
+
if (currentState === undefined) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
if (currentState.pendingTask !== null) {
|
|
82
|
+
await currentState.pendingTask;
|
|
83
|
+
return this.getAttachedMediaKeysState(mediaElement);
|
|
84
|
+
}
|
|
85
|
+
return currentState.mediaKeysState;
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Remove MediaKeys currently set on a HMTLMediaElement and update state
|
|
89
|
+
* accordingly.
|
|
90
|
+
* @param {HTMLMediaElement} mediaElement
|
|
91
|
+
* @returns {Promise}
|
|
92
|
+
*/
|
|
93
|
+
clearMediaKeys(mediaElement) {
|
|
94
|
+
const previousState = currentMediaState.get(mediaElement);
|
|
95
|
+
const pendingTask = clearMediaKeys(mediaElement, previousState).then(() => {
|
|
96
|
+
currentMediaState.set(mediaElement, {
|
|
97
|
+
pendingTask: null,
|
|
98
|
+
mediaKeysState: null,
|
|
99
|
+
});
|
|
100
|
+
}, () => {
|
|
101
|
+
currentMediaState.set(mediaElement, {
|
|
102
|
+
pendingTask: null,
|
|
103
|
+
mediaKeysState: null,
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
currentMediaState.set(mediaElement, {
|
|
107
|
+
pendingTask,
|
|
108
|
+
mediaKeysState: null,
|
|
109
|
+
});
|
|
110
|
+
return pendingTask;
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Ensure that the last `MediaKeys` set on the given HTMLMediaElement is
|
|
115
|
+
* attached.
|
|
116
|
+
*
|
|
117
|
+
* The returned Promise never rejects, it will just log an error if the
|
|
118
|
+
* previous attachment failed.
|
|
119
|
+
*
|
|
120
|
+
* @param {Object} previousState
|
|
121
|
+
* @returns {Promise.<undefined>}
|
|
122
|
+
*/
|
|
123
|
+
async function awaitMediaKeysAttachment(previousState) {
|
|
124
|
+
const promise = previousState.pendingTask;
|
|
125
|
+
if (isNullOrUndefined(promise)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
log.info("DRM: Awaiting previous MediaKeys attachment operation");
|
|
129
|
+
try {
|
|
130
|
+
await previousState.pendingTask;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
log.info("DRM: previous MediaKeys attachment operation failed", err instanceof Error ? err : "Unknown error");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function attachMediaKeys(mediaElement, previousState, mediaKeysInfo) {
|
|
137
|
+
if (previousState !== undefined) {
|
|
138
|
+
if (previousState.pendingTask !== null) {
|
|
139
|
+
// Ensure the `MediaKeys` has been fully attached to the HTMLMediaElement before
|
|
140
|
+
// resetting things, to avoid browser errors due to an invalid state.
|
|
141
|
+
await awaitMediaKeysAttachment(previousState);
|
|
142
|
+
}
|
|
143
|
+
const closeAllSessions = !isNullOrUndefined(previousState.mediaKeysState) &&
|
|
144
|
+
previousState.mediaKeysState.loadedSessionsStore !==
|
|
145
|
+
mediaKeysInfo.loadedSessionsStore
|
|
146
|
+
? previousState.mediaKeysState.loadedSessionsStore.closeAllSessions()
|
|
147
|
+
: Promise.resolve();
|
|
148
|
+
await closeAllSessions;
|
|
149
|
+
if (mediaElement.mediaKeys === mediaKeysInfo.mediaKeys) {
|
|
150
|
+
log.debug("DRM: Right MediaKeys already set");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
log.info("DRM: Attaching MediaKeys to the media element");
|
|
155
|
+
try {
|
|
156
|
+
await setMediaKeys(mediaKeysInfo.emeImplementation, mediaElement, mediaKeysInfo.mediaKeys);
|
|
157
|
+
log.info("DRM: MediaKeys attached with success");
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
const errMessage = err instanceof Error ? err.toString() : "Unknown Error";
|
|
161
|
+
throw new EncryptedMediaError("MEDIA_KEYS_ATTACHMENT_ERROR", "Could not attach the MediaKeys to the media element: " + errMessage);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
async function clearMediaKeys(mediaElement, previousState) {
|
|
165
|
+
if (previousState === undefined) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (previousState.pendingTask !== null) {
|
|
169
|
+
// Ensure the `MediaKeys` has been fully attached to the HTMLMediaElement before
|
|
170
|
+
// resetting things, to avoid browser errors due to an invalid state.
|
|
171
|
+
await awaitMediaKeysAttachment(previousState);
|
|
172
|
+
}
|
|
173
|
+
if (previousState.mediaKeysState === null) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
log.info("DRM: Disposing of the current MediaKeys");
|
|
177
|
+
const { loadedSessionsStore } = previousState.mediaKeysState;
|
|
178
|
+
await loadedSessionsStore.closeAllSessions();
|
|
179
|
+
return setMediaKeys(previousState.mediaKeysState.emeImplementation, mediaElement, null);
|
|
180
|
+
}
|
|
@@ -214,7 +214,7 @@ export default class RebufferingController extends EventEmitter {
|
|
|
214
214
|
this.start();
|
|
215
215
|
}
|
|
216
216
|
const observation = this._playbackObserver.getReference().getValue();
|
|
217
|
-
if (
|
|
217
|
+
if (observation.rebuffering === null ||
|
|
218
218
|
observation.paused ||
|
|
219
219
|
this._speed.getValue() <= 0 ||
|
|
220
220
|
(bufferType !== "audio" && bufferType !== "video")) {
|
|
@@ -336,7 +336,7 @@ export default class TextTrackCuesStore {
|
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
|
-
if (cuesBuffer.length) {
|
|
339
|
+
if (cuesBuffer.length > 0) {
|
|
340
340
|
const lastCue = cuesBuffer[cuesBuffer.length - 1];
|
|
341
341
|
if (areNearlyEqual(lastCue.end, start, relativeDelta)) {
|
|
342
342
|
// Match the end of the previous cue to the start of the following one
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track_dispatcher.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/tracks_store/track_dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"track_dispatcher.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/tracks_store/track_dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,gBAAgB,CAAC;AAOnF,OAAO,YAAY,MAAM,2BAA2B,CAAC;AAErD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,eAAe,MAAM,uBAAuB,CAAC;AAGpD;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,YAAY,CAAC,qBAAqB,CAAC;IAC9E;;;;;;;OAOG;IACI,OAAO,EAAE,MAAM,IAAI,CAAC;IAE3B;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAa7B;IAEF;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY,CAON;IAEd,iFAAiF;IACjF,OAAO,CAAC,UAAU,CAAgB;IAElC;;;;;;OAMG;IACH,OAAO,CAAC,YAAY,CAAU;IAE9B;;;;;;OAMG;gBACS,aAAa,EAAE,eAAe,CAAC,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAShF;;;;;OAKG;IACI,WAAW,IAAI,OAAO;IAI7B;;;OAGG;IACI,WAAW,CAAC,YAAY,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI;IAoC5D;;;;;;OAMG;IACH,OAAO,CAAC,wCAAwC;IA+EhD;;;OAGG;IACI,OAAO,IAAI,IAAI;CAKvB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,8BAA8B,EAAE,IAAI,CAAC;IACrC,wBAAwB,EAAE,IAAI,CAAC;CAChC;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,UAAU,EAAE,mBAAmB,CAAC;IAChC,gEAAgE;IAChE,aAAa,EAAE,mBAAmB,CAAC;IACnC,sDAAsD;IACtD,wBAAwB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9C;;;;;;;OAOG;IACH,qBAAqB,EAAE,wBAAwB,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;CAChF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRepresentationPlayable } from "../../manifest";
|
|
1
2
|
import arrayIncludes from "../../utils/array_includes";
|
|
2
3
|
import EventEmitter from "../../utils/event_emitter";
|
|
3
4
|
import noop from "../../utils/noop";
|
|
@@ -101,9 +102,7 @@ export default class TrackDispatcher extends EventEmitter {
|
|
|
101
102
|
let playableRepresentations;
|
|
102
103
|
if (repSettings === null) {
|
|
103
104
|
// unlocking
|
|
104
|
-
playableRepresentations = trackInfo.adaptation.representations.filter((representation) =>
|
|
105
|
-
return (representation.isSupported === true && representation.decipherable !== false);
|
|
106
|
-
});
|
|
105
|
+
playableRepresentations = trackInfo.adaptation.representations.filter((representation) => isRepresentationPlayable(representation) === true);
|
|
107
106
|
// No need to remove the previous content when unlocking
|
|
108
107
|
switchingMode = "lazy";
|
|
109
108
|
}
|
|
@@ -111,7 +110,7 @@ export default class TrackDispatcher extends EventEmitter {
|
|
|
111
110
|
const { representationIds } = repSettings;
|
|
112
111
|
switchingMode = repSettings.switchingMode;
|
|
113
112
|
const representations = trackInfo.adaptation.representations.filter((r) => arrayIncludes(representationIds, r.id));
|
|
114
|
-
playableRepresentations = representations.filter((
|
|
113
|
+
playableRepresentations = representations.filter((representation) => isRepresentationPlayable(representation) === true);
|
|
115
114
|
if (playableRepresentations.length === 0) {
|
|
116
115
|
self.trigger("noPlayableLockedRepresentation", null);
|
|
117
116
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracks_store.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/tracks_store/tracks_store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAGlF,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EAChB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tracks_store.d.ts","sourceRoot":"","sources":["../../../../src/main_thread/tracks_store/tracks_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import config from "../../config";
|
|
21
21
|
import { MediaError } from "../../errors";
|
|
22
22
|
import log from "../../log";
|
|
23
|
-
import { getSupportedAdaptations, toAudioTrack, toTextTrack, toVideoTrack, } from "../../manifest";
|
|
23
|
+
import { getSupportedAdaptations, isRepresentationPlayable, toAudioTrack, toTextTrack, toVideoTrack, } from "../../manifest";
|
|
24
24
|
import arrayFind from "../../utils/array_find";
|
|
25
25
|
import assert from "../../utils/assert";
|
|
26
26
|
import EventEmitter from "../../utils/event_emitter";
|
|
@@ -283,7 +283,7 @@ export default class TracksStore extends EventEmitter {
|
|
|
283
283
|
adaptation.supportStatus.isDecipherable === false) {
|
|
284
284
|
return false;
|
|
285
285
|
}
|
|
286
|
-
const playableRepresentations = adaptation.representations.filter((r) => r
|
|
286
|
+
const playableRepresentations = adaptation.representations.filter((r) => isRepresentationPlayable(r) === true);
|
|
287
287
|
return playableRepresentations.length > 0;
|
|
288
288
|
});
|
|
289
289
|
if (nextAdaptation === undefined) {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
-
import type
|
|
16
|
+
import { type IRepresentationMetadata } from "../../manifest";
|
|
17
17
|
import type { ICdnMetadata, IContentProtections, IParsedRepresentation } from "../../parsers/manifest";
|
|
18
18
|
import type { ITrackType, IHDRInformation } from "../../public_types";
|
|
19
19
|
import type codecSupportCache from "./codec_support_cache";
|
|
@@ -193,6 +193,20 @@ declare class Representation implements IRepresentationMetadata {
|
|
|
193
193
|
systemId: string;
|
|
194
194
|
data: Uint8Array;
|
|
195
195
|
}>): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Returns `true` if the `Representation` has a high chance of being playable on
|
|
198
|
+
* the current device (its codec seems supported and we don't consider it to be
|
|
199
|
+
* un-decipherable).
|
|
200
|
+
*
|
|
201
|
+
* Returns `false` if the `Representation` has a high chance of being unplayable
|
|
202
|
+
* on the current device (its codec seems unsupported and/or we consider it to
|
|
203
|
+
* be un-decipherable).
|
|
204
|
+
*
|
|
205
|
+
* Returns `undefined` if we don't know as the codec has not been checked yet.
|
|
206
|
+
*
|
|
207
|
+
* @returns {boolean|undefined}
|
|
208
|
+
*/
|
|
209
|
+
isPlayable(): boolean | undefined;
|
|
196
210
|
/**
|
|
197
211
|
* Format the current `Representation`'s properties into a
|
|
198
212
|
* `IRepresentationMetadata` format which can better be communicated through
|