rx-player 4.2.0-dev.2024080600 → 4.2.0-dev.2024081300

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.
Files changed (39) hide show
  1. package/VERSION +1 -1
  2. package/dist/commonjs/main_thread/api/public_api.js +2 -2
  3. package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts +6 -1
  4. package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts.map +1 -1
  5. package/dist/commonjs/main_thread/decrypt/attach_media_keys.js +2 -1
  6. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  7. package/dist/commonjs/main_thread/decrypt/content_decryptor.js +2 -1
  8. package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts +17 -5
  9. package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  10. package/dist/commonjs/main_thread/decrypt/find_key_system.js +56 -26
  11. package/dist/commonjs/main_thread/decrypt/get_media_keys.d.ts +5 -0
  12. package/dist/commonjs/main_thread/decrypt/get_media_keys.d.ts.map +1 -1
  13. package/dist/commonjs/main_thread/decrypt/get_media_keys.js +4 -2
  14. package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts +5 -0
  15. package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +1 -1
  16. package/dist/es2017/main_thread/api/public_api.js +2 -2
  17. package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts +6 -1
  18. package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts.map +1 -1
  19. package/dist/es2017/main_thread/decrypt/attach_media_keys.js +2 -1
  20. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  21. package/dist/es2017/main_thread/decrypt/content_decryptor.js +2 -1
  22. package/dist/es2017/main_thread/decrypt/find_key_system.d.ts +17 -5
  23. package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  24. package/dist/es2017/main_thread/decrypt/find_key_system.js +61 -35
  25. package/dist/es2017/main_thread/decrypt/get_media_keys.d.ts +5 -0
  26. package/dist/es2017/main_thread/decrypt/get_media_keys.d.ts.map +1 -1
  27. package/dist/es2017/main_thread/decrypt/get_media_keys.js +3 -1
  28. package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts +5 -0
  29. package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +1 -1
  30. package/dist/rx-player.js +15 -15
  31. package/package.json +1 -1
  32. package/src/main_thread/api/public_api.ts +2 -2
  33. package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +376 -102
  34. package/src/main_thread/decrypt/__tests__/__global__/utils.ts +4 -23
  35. package/src/main_thread/decrypt/attach_media_keys.ts +7 -0
  36. package/src/main_thread/decrypt/content_decryptor.ts +3 -1
  37. package/src/main_thread/decrypt/find_key_system.ts +78 -43
  38. package/src/main_thread/decrypt/get_media_keys.ts +8 -1
  39. package/src/main_thread/decrypt/utils/media_keys_infos_store.ts +6 -0
@@ -21,7 +21,7 @@ import { strToUtf8, utf8ToStr } from "../../../../utils/string_parsing";
21
21
  import type { CancellationSignal } from "../../../../utils/task_canceller";
22
22
 
23
23
  /** Default MediaKeySystemAccess configuration used by the RxPlayer. */
24
- export const defaultKSConfig = [
24
+ export const defaultKSConfig: MediaKeySystemConfiguration[] = [
25
25
  {
26
26
  audioCapabilities: [
27
27
  { contentType: 'audio/mp4;codecs="mp4a.40.2"' },
@@ -38,21 +38,13 @@ export const defaultKSConfig = [
38
38
  { contentType: 'video/webm;codecs="vp8"' },
39
39
  ],
40
40
  },
41
- {
42
- audioCapabilities: undefined,
43
- distinctiveIdentifier: "optional" as const,
44
- initDataTypes: ["cenc"] as const,
45
- persistentState: "optional" as const,
46
- sessionTypes: ["temporary"] as const,
47
- videoCapabilities: undefined,
48
- },
49
41
  ];
50
42
 
51
43
  /**
52
44
  * Default "com.microsoft.playready.recommendation" MediaKeySystemAccess
53
45
  * configuration used by the RxPlayer.
54
46
  */
55
- export const defaultPRRecommendationKSConfig = [
47
+ export const defaultPRRecommendationKSConfig: MediaKeySystemConfiguration[] = [
56
48
  {
57
49
  audioCapabilities: [
58
50
  { robustness: "3000", contentType: 'audio/mp4;codecs="mp4a.40.2"' },
@@ -75,18 +67,10 @@ export const defaultPRRecommendationKSConfig = [
75
67
  { robustness: "2000", contentType: 'video/webm;codecs="vp8"' },
76
68
  ],
77
69
  },
78
- {
79
- audioCapabilities: undefined,
80
- distinctiveIdentifier: "optional" as const,
81
- initDataTypes: ["cenc"] as const,
82
- persistentState: "optional" as const,
83
- sessionTypes: ["temporary"] as const,
84
- videoCapabilities: undefined,
85
- },
86
70
  ];
87
71
 
88
72
  /** Default Widevine MediaKeySystemAccess configuration used by the RxPlayer. */
89
- export const defaultWidevineConfig = (() => {
73
+ export const defaultWidevineConfig: MediaKeySystemConfiguration[] = (() => {
90
74
  const ROBUSTNESSES = [
91
75
  "HW_SECURE_ALL",
92
76
  "HW_SECURE_DECODE",
@@ -108,10 +92,7 @@ export const defaultWidevineConfig = (() => {
108
92
  { contentType: "audio/webm;codecs=opus", robustness },
109
93
  ];
110
94
  });
111
- return [
112
- { ...defaultKSConfig[0], audioCapabilities, videoCapabilities },
113
- defaultKSConfig[1],
114
- ];
95
+ return [{ ...defaultKSConfig[0], audioCapabilities, videoCapabilities }];
115
96
  })();
116
97
 
117
98
  /**
@@ -55,6 +55,7 @@ export default async function attachMediaKeys(
55
55
  {
56
56
  emeImplementation,
57
57
  keySystemOptions,
58
+ askedConfiguration,
58
59
  loadedSessionsStore,
59
60
  mediaKeySystemAccess,
60
61
  mediaKeys,
@@ -81,6 +82,7 @@ export default async function attachMediaKeys(
81
82
  mediaKeySystemAccess,
82
83
  mediaKeys,
83
84
  loadedSessionsStore,
85
+ askedConfiguration,
84
86
  });
85
87
  if (mediaElement.mediaKeys === mediaKeys) {
86
88
  return;
@@ -109,6 +111,11 @@ export interface IMediaKeysState {
109
111
  mediaKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess;
110
112
  /** The MediaKeys instance to attach to the media element. */
111
113
  mediaKeys: MediaKeys | ICustomMediaKeys;
114
+ /**
115
+ * The MediaKeySystemConfiguration that has been provided to the
116
+ * `requestMediaKeySystemAccess` API.
117
+ */
118
+ askedConfiguration: MediaKeySystemConfiguration;
112
119
  /**
113
120
  * The chosen EME implementation abstraction linked to `mediaKeys`.
114
121
  * Different EME implementation might for example be used while debugging or
@@ -255,7 +255,8 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
255
255
  }
256
256
 
257
257
  const { mediaElement, mediaKeysInfo } = this._stateData.data;
258
- const { options, mediaKeys, mediaKeySystemAccess, stores } = mediaKeysInfo;
258
+ const { options, mediaKeys, mediaKeySystemAccess, stores, askedConfiguration } =
259
+ mediaKeysInfo;
259
260
  const shouldDisableLock = options.disableMediaKeysAttachmentLock === true;
260
261
 
261
262
  if (shouldDisableLock) {
@@ -279,6 +280,7 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
279
280
  loadedSessionsStore: stores.loadedSessionsStore,
280
281
  mediaKeySystemAccess,
281
282
  mediaKeys,
283
+ askedConfiguration,
282
284
  keySystemOptions: options,
283
285
  };
284
286
 
@@ -26,11 +26,7 @@ import shouldRenewMediaKeySystemAccess from "../../compat/should_renew_media_key
26
26
  import config from "../../config";
27
27
  import { EncryptedMediaError } from "../../errors";
28
28
  import log from "../../log";
29
- import type {
30
- IAudioCapabilitiesConfiguration,
31
- IKeySystemOption,
32
- IVideoCapabilitiesConfiguration,
33
- } from "../../public_types";
29
+ import type { IKeySystemOption } from "../../public_types";
34
30
  import { parseCodec } from "../../utils/are_codecs_compatible";
35
31
  import arrayIncludes from "../../utils/array_includes";
36
32
  import flatMap from "../../utils/flat_map";
@@ -47,8 +43,19 @@ export type ICodecSupportList = Array<{
47
43
  }>;
48
44
 
49
45
  export interface IMediaKeySystemAccessInfos {
46
+ /** `MediaKeySystemAccess` to use to create `MediaKeys` instances. */
50
47
  mediaKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess;
48
+ /**
49
+ * The MediaKeySystemConfiguration that has been provided to the
50
+ * `requestMediaKeySystemAccess` API.
51
+ */
52
+ askedConfiguration: MediaKeySystemConfiguration;
53
+ /**
54
+ * Corresponding `keySystems` element that has led to the creation of the
55
+ * `MediaKeySystemAccess`.
56
+ */
51
57
  options: IKeySystemOption;
58
+ /** Information on supported or unsupported codec on that `MediaKeySystemAccess`. */
52
59
  codecSupport: ICodecSupportList;
53
60
  }
54
61
 
@@ -88,10 +95,12 @@ interface IKeySystemType {
88
95
  */
89
96
  function checkCachedMediaKeySystemAccess(
90
97
  keySystems: IKeySystemOption[],
98
+ askedConfiguration: MediaKeySystemConfiguration,
91
99
  currentKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess,
92
100
  currentKeySystemOptions: IKeySystemOption,
93
101
  ): null | {
94
102
  keySystemOptions: IKeySystemOption;
103
+ askedConfiguration: MediaKeySystemConfiguration;
95
104
  keySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess;
96
105
  } {
97
106
  const mksConfiguration = currentKeySystemAccess.getConfiguration();
@@ -127,6 +136,7 @@ function checkCachedMediaKeySystemAccess(
127
136
  return {
128
137
  keySystemOptions: firstCompatibleOption,
129
138
  keySystemAccess: currentKeySystemAccess,
139
+ askedConfiguration,
130
140
  };
131
141
  }
132
142
  return null;
@@ -265,6 +275,31 @@ function buildKeySystemConfigurations(
265
275
  sessionTypes,
266
276
  };
267
277
 
278
+ if (audioCapabilitiesConfig !== undefined) {
279
+ if (videoCapabilitiesConfig !== undefined) {
280
+ return [wantedMediaKeySystemConfiguration];
281
+ }
282
+ return [
283
+ wantedMediaKeySystemConfiguration,
284
+ {
285
+ ...wantedMediaKeySystemConfiguration,
286
+ // Re-try without `videoCapabilities` in case the EME implementation is
287
+ // buggy
288
+ videoCapabilities: undefined,
289
+ } as unknown as MediaKeySystemConfiguration,
290
+ ];
291
+ } else if (videoCapabilitiesConfig !== undefined) {
292
+ return [
293
+ wantedMediaKeySystemConfiguration,
294
+ {
295
+ ...wantedMediaKeySystemConfiguration,
296
+ // Re-try without `audioCapabilities` in case the EME implementation is
297
+ // buggy
298
+ audioCapabilities: undefined,
299
+ } as unknown as MediaKeySystemConfiguration,
300
+ ];
301
+ }
302
+
268
303
  return [
269
304
  wantedMediaKeySystemConfiguration,
270
305
 
@@ -280,29 +315,23 @@ function buildKeySystemConfigurations(
280
315
  }
281
316
  /**
282
317
  * Extract from the current mediaKeys the supported Codecs.
283
- * @param {Object | undefined} audioCapabilitiesConfig - The audio capabilities provided to the KeySystem.
284
- * @param {Object | undefined} videoCapabilitiesConfig - The video capabilities provided to the KeySystem.
285
- * @param {Object | undefined} mksConfiguration - The result of getConfiguration() of the media keys.
318
+ * @param {Object} initialConfiguration - The MediaKeySystemConfiguration given
319
+ * to the `navigator.requestMediaKeySystemAccess` API.
320
+ * @param {Object | undefined} mksConfiguration - The result of
321
+ * getConfiguration() of the media keys.
286
322
  * @return {Array} The list of supported codec by the CDM.
287
323
  */
288
324
  export function extractCodecSupportListFromConfiguration(
289
- audioCapabilitiesConfig: IAudioCapabilitiesConfiguration | undefined,
290
- videoCapabilitiesConfig: IVideoCapabilitiesConfiguration | undefined,
325
+ initialConfiguration: MediaKeySystemConfiguration,
291
326
  mksConfiguration: MediaKeySystemConfiguration,
292
327
  ): ICodecSupportList {
293
- const { EME_DEFAULT_AUDIO_CODECS, EME_DEFAULT_VIDEO_CODECS } = config.getCurrent();
294
-
295
328
  const testedAudioCodecs =
296
- audioCapabilitiesConfig?.type === "contentType"
297
- ? audioCapabilitiesConfig?.value
298
- : EME_DEFAULT_AUDIO_CODECS;
299
-
329
+ initialConfiguration.audioCapabilities?.map((v) => v.contentType) ?? [];
300
330
  const testedVideoCodecs =
301
- videoCapabilitiesConfig?.type === "contentType"
302
- ? videoCapabilitiesConfig.value
303
- : EME_DEFAULT_VIDEO_CODECS;
304
-
305
- const testedCodecs = testedAudioCodecs.concat(testedVideoCodecs);
331
+ initialConfiguration.videoCapabilities?.map((v) => v.contentType) ?? [];
332
+ const testedCodecs: string[] = testedAudioCodecs
333
+ .concat(testedVideoCodecs)
334
+ .filter((c): c is string => c !== undefined);
306
335
  const supportedVideoCodecs = mksConfiguration.videoCapabilities?.map(
307
336
  (entry) => entry.contentType,
308
337
  );
@@ -368,6 +397,7 @@ export default function getMediaKeySystemAccess(
368
397
  // one as exactly the same compatibility options.
369
398
  const cachedKeySystemAccess = checkCachedMediaKeySystemAccess(
370
399
  keySystemsConfigs,
400
+ currentState.askedConfiguration,
371
401
  currentState.mediaKeySystemAccess,
372
402
  currentState.keySystemOptions,
373
403
  );
@@ -377,10 +407,10 @@ export default function getMediaKeySystemAccess(
377
407
  type: "reuse-media-key-system-access" as const,
378
408
  value: {
379
409
  mediaKeySystemAccess: cachedKeySystemAccess.keySystemAccess,
410
+ askedConfiguration: cachedKeySystemAccess.askedConfiguration,
380
411
  options: cachedKeySystemAccess.keySystemOptions,
381
412
  codecSupport: extractCodecSupportListFromConfiguration(
382
- cachedKeySystemAccess.keySystemOptions.audioCapabilitiesConfig,
383
- cachedKeySystemAccess.keySystemOptions.videoCapabilitiesConfig,
413
+ cachedKeySystemAccess.askedConfiguration,
384
414
  cachedKeySystemAccess.keySystemAccess.getConfiguration(),
385
415
  ),
386
416
  },
@@ -458,30 +488,35 @@ export default function getMediaKeySystemAccess(
458
488
  `${index + 1} of ${keySystemsType.length}`,
459
489
  );
460
490
 
461
- try {
462
- const keySystemAccess = await testKeySystem(keyType, keySystemConfigurations);
463
- log.info("DRM: Found compatible keysystem", keyType, index + 1);
464
- return {
465
- type: "create-media-key-system-access" as const,
466
- value: {
467
- options: keySystemOptions,
468
- mediaKeySystemAccess: keySystemAccess,
469
- codecSupport: extractCodecSupportListFromConfiguration(
470
- keySystemOptions.audioCapabilitiesConfig,
471
- keySystemOptions.videoCapabilitiesConfig,
472
- keySystemAccess.getConfiguration(),
473
- ),
474
- },
475
- };
476
- } catch (_) {
477
- log.debug("DRM: Rejected access to keysystem", keyType, index + 1);
478
- if (cancelSignal.cancellationError !== null) {
479
- throw cancelSignal.cancellationError;
491
+ let keySystemAccess;
492
+ for (let configIdx = 0; configIdx < keySystemConfigurations.length; configIdx++) {
493
+ const keySystemConfiguration = keySystemConfigurations[configIdx];
494
+ try {
495
+ keySystemAccess = await testKeySystem(keyType, [keySystemConfiguration]);
496
+ log.info("DRM: Found compatible keysystem", keyType, index + 1);
497
+ return {
498
+ type: "create-media-key-system-access" as const,
499
+ value: {
500
+ options: keySystemOptions,
501
+ mediaKeySystemAccess: keySystemAccess,
502
+ askedConfiguration: keySystemConfiguration,
503
+ codecSupport: extractCodecSupportListFromConfiguration(
504
+ keySystemConfiguration,
505
+ keySystemAccess.getConfiguration(),
506
+ ),
507
+ },
508
+ };
509
+ } catch (_) {
510
+ log.debug("DRM: Rejected access to keysystem", keyType, index + 1, configIdx);
511
+ if (cancelSignal.cancellationError !== null) {
512
+ throw cancelSignal.cancellationError;
513
+ }
480
514
  }
481
- return recursivelyTestKeySystems(index + 1);
482
515
  }
516
+ return recursivelyTestKeySystems(index + 1);
483
517
  }
484
518
  }
519
+
485
520
  /**
486
521
  * Test a key system configuration, resolves with the MediaKeySystemAccess
487
522
  * or reject if the key system is unsupported.
@@ -51,6 +51,11 @@ function createPersistentSessionsStorage(
51
51
  export interface IMediaKeysInfos {
52
52
  /** The MediaKeySystemAccess which allowed to create the MediaKeys instance. */
53
53
  mediaKeySystemAccess: MediaKeySystemAccess | ICustomMediaKeySystemAccess;
54
+ /**
55
+ * The MediaKeySystemConfiguration that has been provided to the
56
+ * `requestMediaKeySystemAccess` API.
57
+ */
58
+ askedConfiguration: MediaKeySystemConfiguration;
54
59
  /** The MediaKeys instance. */
55
60
  mediaKeys: MediaKeys | ICustomMediaKeys;
56
61
  /** Stores allowing to create and retrieve MediaKeySessions. */
@@ -88,7 +93,7 @@ export default async function getMediaKeysInfos(
88
93
  throw cancelSignal.cancellationError;
89
94
  }
90
95
 
91
- const { options, mediaKeySystemAccess, codecSupport } = evt.value;
96
+ const { options, mediaKeySystemAccess, askedConfiguration, codecSupport } = evt.value;
92
97
  const currentState = MediaKeysInfosStore.getState(mediaElement);
93
98
  const persistentSessionsStore = createPersistentSessionsStorage(options);
94
99
 
@@ -110,6 +115,7 @@ export default async function getMediaKeysInfos(
110
115
  return {
111
116
  mediaKeys,
112
117
  mediaKeySystemAccess,
118
+ askedConfiguration,
113
119
  stores: { loadedSessionsStore, persistentSessionsStore },
114
120
  options,
115
121
  codecSupport,
@@ -123,6 +129,7 @@ export default async function getMediaKeysInfos(
123
129
  return {
124
130
  mediaKeys,
125
131
  mediaKeySystemAccess,
132
+ askedConfiguration,
126
133
  stores: { loadedSessionsStore, persistentSessionsStore },
127
134
  options,
128
135
  codecSupport,
@@ -30,6 +30,12 @@ export interface IMediaElementMediaKeysInfos {
30
30
  /** Last keySystemOptions used with that HTMLMediaElement. */
31
31
  keySystemOptions: IKeySystemOption;
32
32
 
33
+ /**
34
+ * The actual MediaKeySystemConfiguration asked to the
35
+ * `requestMediaKeySystemAccess` API.
36
+ */
37
+ askedConfiguration: MediaKeySystemConfiguration;
38
+
33
39
  /**
34
40
  * Last MediaKeySystemAccess used to create a MediaKeys bound to that
35
41
  * HTMLMediaElement.