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.
Files changed (169) hide show
  1. package/CHANGELOG.md +24 -8
  2. package/VERSION +1 -1
  3. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
  4. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  5. package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  6. package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
  7. package/dist/commonjs/compat/browser_compatibility_types.d.ts +7 -2
  8. package/dist/commonjs/compat/browser_compatibility_types.d.ts.map +1 -1
  9. package/dist/commonjs/compat/browser_compatibility_types.js +0 -1
  10. package/dist/commonjs/compat/browser_detection.js +1 -1
  11. package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
  12. package/dist/commonjs/compat/event_listeners.js +2 -4
  13. package/dist/commonjs/compat/has_mse_in_worker.d.ts.map +1 -1
  14. package/dist/commonjs/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
  15. package/dist/commonjs/core/cmcd/cmcd_data_builder.js +1 -2
  16. package/dist/commonjs/core/main/worker/send_message.d.ts.map +1 -1
  17. package/dist/commonjs/core/main/worker/send_message.js +0 -1
  18. package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  19. package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +4 -8
  20. package/dist/commonjs/core/stream/period/period_stream.js +1 -3
  21. package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
  22. package/dist/commonjs/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
  23. package/dist/commonjs/main_thread/api/public_api.js +4 -4
  24. package/dist/commonjs/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
  25. package/dist/commonjs/main_thread/decrypt/clear_on_stop.js +60 -14
  26. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  27. package/dist/commonjs/main_thread/decrypt/content_decryptor.js +21 -9
  28. package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
  29. package/dist/commonjs/main_thread/decrypt/dispose_decryption_resources.js +2 -18
  30. package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  31. package/dist/commonjs/main_thread/decrypt/find_key_system.js +134 -68
  32. package/dist/commonjs/main_thread/decrypt/get_key_system_configuration.js +2 -2
  33. package/dist/commonjs/main_thread/decrypt/get_media_keys.js +5 -3
  34. package/dist/commonjs/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
  35. package/dist/commonjs/main_thread/decrypt/init_media_keys.js +2 -2
  36. 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
  37. package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
  38. package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.js +282 -0
  39. package/dist/commonjs/main_thread/init/utils/rebuffering_controller.js +1 -1
  40. package/dist/commonjs/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
  41. package/dist/commonjs/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
  42. package/dist/commonjs/main_thread/tracks_store/track_dispatcher.js +3 -4
  43. package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
  44. package/dist/commonjs/main_thread/tracks_store/tracks_store.js +1 -1
  45. package/dist/commonjs/manifest/classes/representation.d.ts +15 -1
  46. package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
  47. package/dist/commonjs/manifest/classes/representation.js +17 -0
  48. package/dist/commonjs/manifest/utils.d.ts +15 -0
  49. package/dist/commonjs/manifest/utils.d.ts.map +1 -1
  50. package/dist/commonjs/manifest/utils.js +28 -5
  51. package/dist/commonjs/parsers/manifest/dash/common/parse_representations.js +2 -2
  52. package/dist/commonjs/playback_observer/media_element_playback_observer.js +1 -1
  53. package/dist/commonjs/public_types.d.ts +44 -0
  54. package/dist/commonjs/public_types.d.ts.map +1 -1
  55. package/dist/commonjs/utils/flat_map.d.ts +2 -2
  56. package/dist/commonjs/utils/flat_map.js +2 -2
  57. package/dist/commonjs/utils/url-utils.d.ts.map +1 -1
  58. package/dist/commonjs/utils/url-utils.js +11 -10
  59. package/dist/commonjs/utils/xml-parser.d.ts.map +1 -1
  60. package/dist/commonjs/utils/xml-parser.js +10 -8
  61. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts +1 -1
  62. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  63. package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  64. package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
  65. package/dist/es2017/compat/browser_compatibility_types.d.ts +7 -2
  66. package/dist/es2017/compat/browser_compatibility_types.d.ts.map +1 -1
  67. package/dist/es2017/compat/browser_compatibility_types.js +0 -1
  68. package/dist/es2017/compat/browser_detection.js +1 -1
  69. package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
  70. package/dist/es2017/compat/event_listeners.js +2 -4
  71. package/dist/es2017/compat/has_mse_in_worker.d.ts.map +1 -1
  72. package/dist/es2017/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
  73. package/dist/es2017/core/cmcd/cmcd_data_builder.js +1 -2
  74. package/dist/es2017/core/main/worker/send_message.d.ts.map +1 -1
  75. package/dist/es2017/core/main/worker/send_message.js +0 -1
  76. package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  77. package/dist/es2017/core/stream/adaptation/adaptation_stream.js +4 -6
  78. package/dist/es2017/core/stream/period/period_stream.js +1 -3
  79. package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.js +1 -2
  80. package/dist/es2017/experimental/tools/mediaCapabilitiesProber/api/index.d.ts.map +1 -1
  81. package/dist/es2017/main_thread/api/public_api.js +4 -4
  82. package/dist/es2017/main_thread/decrypt/clear_on_stop.d.ts.map +1 -1
  83. package/dist/es2017/main_thread/decrypt/clear_on_stop.js +3 -3
  84. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  85. package/dist/es2017/main_thread/decrypt/content_decryptor.js +21 -9
  86. package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.d.ts.map +1 -1
  87. package/dist/es2017/main_thread/decrypt/dispose_decryption_resources.js +2 -12
  88. package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  89. package/dist/es2017/main_thread/decrypt/find_key_system.js +102 -56
  90. package/dist/es2017/main_thread/decrypt/get_key_system_configuration.js +2 -2
  91. package/dist/es2017/main_thread/decrypt/get_media_keys.js +2 -2
  92. package/dist/es2017/main_thread/decrypt/init_media_keys.d.ts.map +1 -1
  93. package/dist/es2017/main_thread/decrypt/init_media_keys.js +2 -2
  94. 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
  95. package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -0
  96. package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.js +180 -0
  97. package/dist/es2017/main_thread/init/utils/rebuffering_controller.js +1 -1
  98. package/dist/es2017/main_thread/text_displayer/html/text_track_cues_store.js +1 -1
  99. package/dist/es2017/main_thread/tracks_store/track_dispatcher.d.ts.map +1 -1
  100. package/dist/es2017/main_thread/tracks_store/track_dispatcher.js +3 -4
  101. package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
  102. package/dist/es2017/main_thread/tracks_store/tracks_store.js +2 -2
  103. package/dist/es2017/manifest/classes/representation.d.ts +15 -1
  104. package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
  105. package/dist/es2017/manifest/classes/representation.js +17 -0
  106. package/dist/es2017/manifest/utils.d.ts +15 -0
  107. package/dist/es2017/manifest/utils.d.ts.map +1 -1
  108. package/dist/es2017/manifest/utils.js +27 -5
  109. package/dist/es2017/parsers/manifest/dash/common/parse_representations.js +2 -2
  110. package/dist/es2017/playback_observer/media_element_playback_observer.js +1 -1
  111. package/dist/es2017/public_types.d.ts +44 -0
  112. package/dist/es2017/public_types.d.ts.map +1 -1
  113. package/dist/es2017/utils/flat_map.d.ts +2 -2
  114. package/dist/es2017/utils/flat_map.js +2 -2
  115. package/dist/es2017/utils/url-utils.d.ts.map +1 -1
  116. package/dist/es2017/utils/url-utils.js +11 -10
  117. package/dist/es2017/utils/xml-parser.d.ts.map +1 -1
  118. package/dist/es2017/utils/xml-parser.js +10 -8
  119. package/dist/rx-player.js +494 -364
  120. package/dist/rx-player.min.js +18 -18
  121. package/dist/worker.js +6 -6
  122. package/package.json +21 -19
  123. package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
  124. package/src/compat/browser_compatibility_types.ts +22 -4
  125. package/src/compat/browser_detection.ts +1 -1
  126. package/src/compat/event_listeners.ts +2 -4
  127. package/src/compat/has_mse_in_worker.ts +1 -1
  128. package/src/core/cmcd/cmcd_data_builder.ts +1 -4
  129. package/src/core/main/worker/send_message.ts +4 -2
  130. package/src/core/stream/adaptation/adaptation_stream.ts +4 -7
  131. package/src/core/stream/period/period_stream.ts +3 -3
  132. package/src/core/stream/period/utils/get_adaptation_switch_strategy.ts +1 -2
  133. package/src/main_thread/api/public_api.ts +4 -4
  134. package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +239 -6
  135. package/src/main_thread/decrypt/__tests__/find_key_system.test.ts +325 -0
  136. package/src/main_thread/decrypt/clear_on_stop.ts +3 -3
  137. package/src/main_thread/decrypt/content_decryptor.ts +26 -8
  138. package/src/main_thread/decrypt/dispose_decryption_resources.ts +2 -13
  139. package/src/main_thread/decrypt/find_key_system.ts +120 -81
  140. package/src/main_thread/decrypt/get_key_system_configuration.ts +2 -2
  141. package/src/main_thread/decrypt/get_media_keys.ts +2 -2
  142. package/src/main_thread/decrypt/init_media_keys.ts +2 -2
  143. package/src/main_thread/decrypt/utils/media_keys_attacher.ts +284 -0
  144. package/src/main_thread/init/utils/rebuffering_controller.ts +1 -1
  145. package/src/main_thread/text_displayer/html/text_track_cues_store.ts +1 -1
  146. package/src/main_thread/tracks_store/track_dispatcher.ts +3 -6
  147. package/src/main_thread/tracks_store/tracks_store.ts +2 -1
  148. package/src/manifest/classes/representation.ts +18 -1
  149. package/src/manifest/utils.ts +30 -9
  150. package/src/parsers/manifest/dash/common/parse_representations.ts +2 -2
  151. package/src/playback_observer/media_element_playback_observer.ts +1 -1
  152. package/src/public_types.ts +45 -0
  153. package/src/utils/__tests__/flat_map.test.ts +7 -20
  154. package/src/utils/flat_map.ts +2 -2
  155. package/src/utils/url-utils.ts +11 -10
  156. package/src/utils/xml-parser.ts +13 -8
  157. package/vitest.config.mjs +9 -4
  158. package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts +0 -60
  159. package/dist/commonjs/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
  160. package/dist/commonjs/main_thread/decrypt/attach_media_keys.js +0 -124
  161. package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
  162. package/dist/commonjs/main_thread/decrypt/utils/media_keys_infos_store.js +0 -45
  163. package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts +0 -60
  164. package/dist/es2017/main_thread/decrypt/attach_media_keys.d.ts.map +0 -1
  165. package/dist/es2017/main_thread/decrypt/attach_media_keys.js +0 -73
  166. package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.d.ts.map +0 -1
  167. package/dist/es2017/main_thread/decrypt/utils/media_keys_infos_store.js +0 -43
  168. package/src/main_thread/decrypt/attach_media_keys.ts +0 -125
  169. package/src/main_thread/decrypt/utils/media_keys_infos_store.ts +0 -88
package/dist/rx-player.js CHANGED
@@ -628,7 +628,7 @@
628
628
  isPanasonic = true;
629
629
  } else if (navigator.userAgent.indexOf("Xbox") !== -1) {
630
630
  isXbox = true;
631
- } else if (navigator.userAgent.indexOf("Model/a1-kstb40xx")) {
631
+ } else if (navigator.userAgent.indexOf("Model/a1-kstb40xx") !== -1) {
632
632
  isA1KStb40xx = true;
633
633
  }
634
634
  })();
@@ -3380,6 +3380,11 @@
3380
3380
  });
3381
3381
  }
3382
3382
 
3383
+ // src/utils/is_non_empty_string.ts
3384
+ function isNonEmptyString(x) {
3385
+ return typeof x === "string" && x.length > 0;
3386
+ }
3387
+
3383
3388
  // src/utils/starts_with.ts
3384
3389
  function startsWith(completeString, searchString, position) {
3385
3390
  if (typeof String.prototype.startsWith === "function") {
@@ -3446,11 +3451,11 @@
3446
3451
  }
3447
3452
  let result = relativePath;
3448
3453
  if (relativePath === "" && newParts.query === baseParts.query) {
3449
- } else if (newParts.query) {
3454
+ } else if (isNonEmptyString(newParts.query)) {
3450
3455
  result += "?";
3451
3456
  result += newParts.query;
3452
3457
  }
3453
- if (newParts.fragment) {
3458
+ if (isNonEmptyString(newParts.fragment)) {
3454
3459
  result += "#";
3455
3460
  result += newParts.fragment;
3456
3461
  }
@@ -3459,7 +3464,7 @@
3459
3464
  function _resolveURL(base, relative) {
3460
3465
  const baseParts = parseURL(base);
3461
3466
  const relativeParts = parseURL(relative);
3462
- if (relativeParts.scheme) {
3467
+ if (isNonEmptyString(relativeParts.scheme)) {
3463
3468
  return formatURL(relativeParts);
3464
3469
  }
3465
3470
  const target = {
@@ -3469,14 +3474,14 @@
3469
3474
  query: relativeParts.query,
3470
3475
  fragment: relativeParts.fragment
3471
3476
  };
3472
- if (relativeParts.authority) {
3477
+ if (isNonEmptyString(relativeParts.authority)) {
3473
3478
  target.authority = relativeParts.authority;
3474
3479
  target.path = removeDotSegment(relativeParts.path);
3475
3480
  return formatURL(target);
3476
3481
  }
3477
3482
  if (relativeParts.path === "") {
3478
3483
  target.path = baseParts.path;
3479
- if (!relativeParts.query) {
3484
+ if (!isNonEmptyString(relativeParts.query)) {
3480
3485
  target.query = baseParts.query;
3481
3486
  }
3482
3487
  } else {
@@ -3522,17 +3527,17 @@
3522
3527
  }
3523
3528
  function formatURL(parts) {
3524
3529
  let url = "";
3525
- if (parts.scheme) {
3530
+ if (isNonEmptyString(parts.scheme)) {
3526
3531
  url += parts.scheme + ":";
3527
3532
  }
3528
- if (parts.authority) {
3533
+ if (isNonEmptyString(parts.authority)) {
3529
3534
  url += "//" + parts.authority;
3530
3535
  }
3531
3536
  url += parts.path;
3532
- if (parts.query) {
3537
+ if (isNonEmptyString(parts.query)) {
3533
3538
  url += "?" + parts.query;
3534
3539
  }
3535
- if (parts.fragment) {
3540
+ if (isNonEmptyString(parts.fragment)) {
3536
3541
  url += "#" + parts.fragment;
3537
3542
  }
3538
3543
  return url;
@@ -3563,7 +3568,7 @@
3563
3568
  return output.join("");
3564
3569
  }
3565
3570
  function mergePaths(baseParts, relativePath) {
3566
- if (baseParts.authority && baseParts.path === "") {
3571
+ if (isNonEmptyString(baseParts.authority) && baseParts.path === "") {
3567
3572
  return "/" + relativePath;
3568
3573
  }
3569
3574
  const basePath = baseParts.path;
@@ -3776,7 +3781,7 @@
3776
3781
  props.st = content.manifest.isDynamic ? "l" : "v";
3777
3782
  props.tb = content.adaptation.representations.reduce(
3778
3783
  (acc, representation) => {
3779
- if (representation.isSupported !== true || representation.decipherable === false) {
3784
+ if (representation.isPlayable() !== true) {
3780
3785
  return acc;
3781
3786
  }
3782
3787
  if (acc === void 0) {
@@ -4106,11 +4111,6 @@
4106
4111
  return typeof global_scope_default.fetch === "function" && !isNullOrUndefined(_AbortController) && !isNullOrUndefined(_Headers);
4107
4112
  }
4108
4113
 
4109
- // src/utils/is_non_empty_string.ts
4110
- function isNonEmptyString(x) {
4111
- return typeof x === "string" && x.length > 0;
4112
- }
4113
-
4114
4114
  // src/utils/request/xhr.ts
4115
4115
  var DEFAULT_RESPONSE_TYPE = "json";
4116
4116
  function request(options) {
@@ -4975,6 +4975,211 @@
4975
4975
  return true;
4976
4976
  }
4977
4977
 
4978
+ // src/manifest/utils.ts
4979
+ var SUPPORTED_ADAPTATIONS_TYPE = ["audio", "video", "text"];
4980
+ function getMinimumSafePosition(manifest) {
4981
+ var _a2, _b2;
4982
+ const windowData = manifest.timeBounds;
4983
+ if (windowData.timeshiftDepth === null) {
4984
+ return (_a2 = windowData.minimumSafePosition) != null ? _a2 : 0;
4985
+ }
4986
+ const { maximumTimeData } = windowData;
4987
+ let maximumTime;
4988
+ if (!windowData.maximumTimeData.isLinear) {
4989
+ maximumTime = maximumTimeData.maximumSafePosition;
4990
+ } else {
4991
+ const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
4992
+ maximumTime = maximumTimeData.maximumSafePosition + timeDiff / 1e3;
4993
+ }
4994
+ const theoricalMinimum = maximumTime - windowData.timeshiftDepth;
4995
+ return Math.max((_b2 = windowData.minimumSafePosition) != null ? _b2 : 0, theoricalMinimum);
4996
+ }
4997
+ function getLivePosition(manifest) {
4998
+ const { maximumTimeData } = manifest.timeBounds;
4999
+ if (!manifest.isLive || maximumTimeData.livePosition === void 0) {
5000
+ return void 0;
5001
+ }
5002
+ if (!maximumTimeData.isLinear) {
5003
+ return maximumTimeData.livePosition;
5004
+ }
5005
+ const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
5006
+ return maximumTimeData.livePosition + timeDiff / 1e3;
5007
+ }
5008
+ function getMaximumSafePosition(manifest) {
5009
+ const { maximumTimeData } = manifest.timeBounds;
5010
+ if (!maximumTimeData.isLinear) {
5011
+ return maximumTimeData.maximumSafePosition;
5012
+ }
5013
+ const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
5014
+ return maximumTimeData.maximumSafePosition + timeDiff / 1e3;
5015
+ }
5016
+ function getSupportedAdaptations(period, type) {
5017
+ if (type === void 0) {
5018
+ return getAdaptations(period).filter((ada) => {
5019
+ return ada.supportStatus.hasSupportedCodec !== false && ada.supportStatus.isDecipherable !== false;
5020
+ });
5021
+ }
5022
+ const adaptationsForType = period.adaptations[type];
5023
+ if (adaptationsForType === void 0) {
5024
+ return [];
5025
+ }
5026
+ return adaptationsForType.filter((ada) => {
5027
+ return ada.supportStatus.hasSupportedCodec !== false && ada.supportStatus.isDecipherable !== false;
5028
+ });
5029
+ }
5030
+ function getPeriodForTime(manifest, time) {
5031
+ let nextPeriod = null;
5032
+ for (const period of manifest.periods) {
5033
+ if (periodContainsTime(period, time, nextPeriod)) {
5034
+ return period;
5035
+ }
5036
+ nextPeriod = period;
5037
+ }
5038
+ }
5039
+ function getPeriodAfter(manifest, period) {
5040
+ const endOfPeriod = period.end;
5041
+ if (endOfPeriod === void 0) {
5042
+ return null;
5043
+ }
5044
+ const nextPeriod = arrayFind(manifest.periods, (_period) => {
5045
+ return _period.end === void 0 || endOfPeriod < _period.end;
5046
+ });
5047
+ return nextPeriod === void 0 ? null : nextPeriod;
5048
+ }
5049
+ function periodContainsTime(period, time, nextPeriod) {
5050
+ if (time >= period.start && (period.end === void 0 || time < period.end)) {
5051
+ return true;
5052
+ } else if (time === period.end && (nextPeriod === null || nextPeriod.start > period.end)) {
5053
+ return true;
5054
+ }
5055
+ return false;
5056
+ }
5057
+ function getAdaptations(period) {
5058
+ const adaptationsByType = period.adaptations;
5059
+ return objectValues(adaptationsByType).reduce(
5060
+ // Note: the second case cannot happen. TS is just being dumb here
5061
+ (acc, adaptations) => !isNullOrUndefined(adaptations) ? acc.concat(adaptations) : acc,
5062
+ []
5063
+ );
5064
+ }
5065
+ function toAudioTrack(adaptation, filterPlayable) {
5066
+ var _a2, _b2;
5067
+ const formatted = {
5068
+ language: (_a2 = adaptation.language) != null ? _a2 : "",
5069
+ normalized: (_b2 = adaptation.normalizedLanguage) != null ? _b2 : "",
5070
+ audioDescription: adaptation.isAudioDescription === true,
5071
+ id: adaptation.id,
5072
+ representations: (filterPlayable ? adaptation.representations.filter((r) => isRepresentationPlayable(r)) : adaptation.representations).map(toAudioRepresentation),
5073
+ label: adaptation.label
5074
+ };
5075
+ if (adaptation.isDub === true) {
5076
+ formatted.dub = true;
5077
+ }
5078
+ return formatted;
5079
+ }
5080
+ function toTextTrack(adaptation) {
5081
+ var _a2, _b2;
5082
+ return {
5083
+ language: (_a2 = adaptation.language) != null ? _a2 : "",
5084
+ normalized: (_b2 = adaptation.normalizedLanguage) != null ? _b2 : "",
5085
+ closedCaption: adaptation.isClosedCaption === true,
5086
+ id: adaptation.id,
5087
+ label: adaptation.label,
5088
+ forced: adaptation.isForcedSubtitles
5089
+ };
5090
+ }
5091
+ function toVideoTrack(adaptation, filterPlayable) {
5092
+ const trickModeTracks = adaptation.trickModeTracks !== void 0 ? adaptation.trickModeTracks.map((trickModeAdaptation) => {
5093
+ const representations = (filterPlayable ? trickModeAdaptation.representations.filter(
5094
+ (r) => isRepresentationPlayable(r) === true
5095
+ ) : trickModeAdaptation.representations).map(toVideoRepresentation);
5096
+ const trickMode = {
5097
+ id: trickModeAdaptation.id,
5098
+ representations,
5099
+ isTrickModeTrack: true
5100
+ };
5101
+ if (trickModeAdaptation.isSignInterpreted === true) {
5102
+ trickMode.signInterpreted = true;
5103
+ }
5104
+ return trickMode;
5105
+ }) : void 0;
5106
+ const videoTrack = {
5107
+ id: adaptation.id,
5108
+ representations: (filterPlayable ? adaptation.representations.filter((r) => isRepresentationPlayable(r) === true) : adaptation.representations).map(toVideoRepresentation),
5109
+ label: adaptation.label
5110
+ };
5111
+ if (adaptation.isSignInterpreted === true) {
5112
+ videoTrack.signInterpreted = true;
5113
+ }
5114
+ if (adaptation.isTrickModeTrack === true) {
5115
+ videoTrack.isTrickModeTrack = true;
5116
+ }
5117
+ if (trickModeTracks !== void 0) {
5118
+ videoTrack.trickModeTracks = trickModeTracks;
5119
+ }
5120
+ return videoTrack;
5121
+ }
5122
+ function toAudioRepresentation(representation) {
5123
+ const { id, bitrate, codecs, isSpatialAudio, isSupported, decipherable } = representation;
5124
+ return {
5125
+ id,
5126
+ bitrate,
5127
+ codec: codecs == null ? void 0 : codecs[0],
5128
+ isSpatialAudio,
5129
+ isCodecSupported: isSupported,
5130
+ decipherable
5131
+ };
5132
+ }
5133
+ function toVideoRepresentation(representation) {
5134
+ const {
5135
+ id,
5136
+ bitrate,
5137
+ frameRate,
5138
+ width,
5139
+ height,
5140
+ codecs,
5141
+ hdrInfo,
5142
+ isSupported,
5143
+ decipherable,
5144
+ contentProtections
5145
+ } = representation;
5146
+ return {
5147
+ id,
5148
+ bitrate,
5149
+ frameRate,
5150
+ width,
5151
+ height,
5152
+ codec: codecs == null ? void 0 : codecs[0],
5153
+ hdrInfo,
5154
+ isCodecSupported: isSupported,
5155
+ decipherable,
5156
+ contentProtections: contentProtections !== void 0 ? {
5157
+ keyIds: contentProtections.keyIds
5158
+ } : void 0
5159
+ };
5160
+ }
5161
+ function toTaggedTrack(adaptation) {
5162
+ switch (adaptation.type) {
5163
+ case "audio":
5164
+ return { type: "audio", track: toAudioTrack(adaptation, false) };
5165
+ case "video":
5166
+ return { type: "video", track: toVideoTrack(adaptation, false) };
5167
+ case "text":
5168
+ return { type: "text", track: toTextTrack(adaptation) };
5169
+ }
5170
+ }
5171
+ function isRepresentationPlayable(representation) {
5172
+ if (representation.decipherable === false) {
5173
+ return false;
5174
+ }
5175
+ return representation.isSupported;
5176
+ }
5177
+ function createRepresentationFilterFromFnString(fnString) {
5178
+ return new Function(
5179
+ `return (${fnString}(arguments[0], arguments[1]))`
5180
+ );
5181
+ }
5182
+
4978
5183
  // src/utils/id_generator.ts
4979
5184
  function idGenerator() {
4980
5185
  let prefix = "";
@@ -5262,6 +5467,22 @@
5262
5467
  this.contentProtections.initData.push({ type: initDataType, values: data });
5263
5468
  return true;
5264
5469
  }
5470
+ /**
5471
+ * Returns `true` if the `Representation` has a high chance of being playable on
5472
+ * the current device (its codec seems supported and we don't consider it to be
5473
+ * un-decipherable).
5474
+ *
5475
+ * Returns `false` if the `Representation` has a high chance of being unplayable
5476
+ * on the current device (its codec seems unsupported and/or we consider it to
5477
+ * be un-decipherable).
5478
+ *
5479
+ * Returns `undefined` if we don't know as the codec has not been checked yet.
5480
+ *
5481
+ * @returns {boolean|undefined}
5482
+ */
5483
+ isPlayable() {
5484
+ return isRepresentationPlayable(this);
5485
+ }
5265
5486
  /**
5266
5487
  * Format the current `Representation`'s properties into a
5267
5488
  * `IRepresentationMetadata` format which can better be communicated through
@@ -5534,56 +5755,177 @@
5534
5755
  ]);
5535
5756
  }
5536
5757
 
5537
- // src/main_thread/decrypt/utils/media_keys_infos_store.ts
5758
+ // src/main_thread/decrypt/utils/media_keys_attacher.ts
5538
5759
  var currentMediaState = /* @__PURE__ */ new WeakMap();
5539
- var media_keys_infos_store_default = {
5760
+ var media_keys_attacher_default = {
5540
5761
  /**
5541
- * Update MediaKeys infos set on a HMTLMediaElement
5762
+ * Attach new MediaKeys infos set on a HMTLMediaElement.
5542
5763
  * @param {HTMLMediaElement} mediaElement
5543
- * @param {Object} state
5764
+ * @param {Object} mediaKeysInfo
5765
+ * @returns {Promise}
5544
5766
  */
5545
- setState(mediaElement, state) {
5546
- currentMediaState.set(mediaElement, state);
5767
+ async attach(mediaElement, mediaKeysInfo) {
5768
+ const previousState = currentMediaState.get(mediaElement);
5769
+ const pendingTask = attachMediaKeys(mediaElement, previousState, mediaKeysInfo).then(
5770
+ () => {
5771
+ currentMediaState.set(mediaElement, {
5772
+ pendingTask: null,
5773
+ mediaKeysState: mediaKeysInfo
5774
+ });
5775
+ },
5776
+ () => {
5777
+ currentMediaState.set(mediaElement, {
5778
+ pendingTask: null,
5779
+ mediaKeysState: null
5780
+ });
5781
+ }
5782
+ );
5783
+ currentMediaState.set(mediaElement, {
5784
+ pendingTask,
5785
+ mediaKeysState: mediaKeysInfo
5786
+ });
5787
+ return pendingTask;
5547
5788
  },
5548
5789
  /**
5549
- * Get MediaKeys infos currently set on a HMTLMediaElement
5790
+ * Get MediaKeys information expected to be linked to the given
5791
+ * `HTMLMediaElement`.
5792
+ *
5793
+ * Unlike `getAttachedMediaKeysState`, this method is synchronous and will
5794
+ * also return the expected state when `MediaKeys` attachment is still
5795
+ * pending and thus when that state is not truly applied (and where it
5796
+ * might fail before being applied).
5797
+ *
5798
+ * As such, only call this method if you want the currently expected state,
5799
+ * not the actual one.
5550
5800
  * @param {HTMLMediaElement} mediaElement
5551
- * @returns {Object}
5801
+ * @returns {Array}
5802
+ */
5803
+ getAwaitedState(mediaElement) {
5804
+ var _a2;
5805
+ const currentState = currentMediaState.get(mediaElement);
5806
+ return (_a2 = currentState == null ? void 0 : currentState.mediaKeysState) != null ? _a2 : null;
5807
+ },
5808
+ /**
5809
+ * Get MediaKeys information set on a HMTLMediaElement.
5810
+ *
5811
+ * This method is asynchronous because that state may still be in a process
5812
+ * of being attached to the `HTMLMediaElement` (and the state we're
5813
+ * currently setting may not work out).
5814
+ * @param {HTMLMediaElement} mediaElement
5815
+ * @returns {Object|null}
5552
5816
  */
5553
- getState(mediaElement) {
5817
+ async getAttachedMediaKeysState(mediaElement) {
5554
5818
  const currentState = currentMediaState.get(mediaElement);
5555
- return currentState === void 0 ? null : currentState;
5819
+ if (currentState === void 0) {
5820
+ return null;
5821
+ }
5822
+ if (currentState.pendingTask !== null) {
5823
+ await currentState.pendingTask;
5824
+ return this.getAttachedMediaKeysState(mediaElement);
5825
+ }
5826
+ return currentState.mediaKeysState;
5556
5827
  },
5557
5828
  /**
5558
- * Remove MediaKeys infos currently set on a HMTLMediaElement
5829
+ * Remove MediaKeys currently set on a HMTLMediaElement and update state
5830
+ * accordingly.
5559
5831
  * @param {HTMLMediaElement} mediaElement
5832
+ * @returns {Promise}
5560
5833
  */
5561
- clearState(mediaElement) {
5562
- currentMediaState.set(mediaElement, null);
5834
+ clearMediaKeys(mediaElement) {
5835
+ const previousState = currentMediaState.get(mediaElement);
5836
+ const pendingTask = clearMediaKeys(mediaElement, previousState).then(
5837
+ () => {
5838
+ currentMediaState.set(mediaElement, {
5839
+ pendingTask: null,
5840
+ mediaKeysState: null
5841
+ });
5842
+ },
5843
+ () => {
5844
+ currentMediaState.set(mediaElement, {
5845
+ pendingTask: null,
5846
+ mediaKeysState: null
5847
+ });
5848
+ }
5849
+ );
5850
+ currentMediaState.set(mediaElement, {
5851
+ pendingTask,
5852
+ mediaKeysState: null
5853
+ });
5854
+ return pendingTask;
5563
5855
  }
5564
5856
  };
5565
-
5566
- // src/main_thread/decrypt/dispose_decryption_resources.ts
5567
- async function disposeDecryptionResources(mediaElement) {
5568
- const currentState = media_keys_infos_store_default.getState(mediaElement);
5569
- if (currentState === null) {
5570
- return void 0;
5857
+ async function awaitMediaKeysAttachment(previousState) {
5858
+ const promise = previousState.pendingTask;
5859
+ if (isNullOrUndefined(promise)) {
5860
+ return;
5861
+ }
5862
+ log_default.info("DRM: Awaiting previous MediaKeys attachment operation");
5863
+ try {
5864
+ await previousState.pendingTask;
5865
+ } catch (err) {
5866
+ log_default.info(
5867
+ "DRM: previous MediaKeys attachment operation failed",
5868
+ err instanceof Error ? err : "Unknown error"
5869
+ );
5870
+ }
5871
+ }
5872
+ async function attachMediaKeys(mediaElement, previousState, mediaKeysInfo) {
5873
+ if (previousState !== void 0) {
5874
+ if (previousState.pendingTask !== null) {
5875
+ await awaitMediaKeysAttachment(previousState);
5876
+ }
5877
+ const closeAllSessions = !isNullOrUndefined(previousState.mediaKeysState) && previousState.mediaKeysState.loadedSessionsStore !== mediaKeysInfo.loadedSessionsStore ? previousState.mediaKeysState.loadedSessionsStore.closeAllSessions() : Promise.resolve();
5878
+ await closeAllSessions;
5879
+ if (mediaElement.mediaKeys === mediaKeysInfo.mediaKeys) {
5880
+ log_default.debug("DRM: Right MediaKeys already set");
5881
+ return;
5882
+ }
5883
+ }
5884
+ log_default.info("DRM: Attaching MediaKeys to the media element");
5885
+ try {
5886
+ await setMediaKeys(
5887
+ mediaKeysInfo.emeImplementation,
5888
+ mediaElement,
5889
+ mediaKeysInfo.mediaKeys
5890
+ );
5891
+ log_default.info("DRM: MediaKeys attached with success");
5892
+ } catch (err) {
5893
+ const errMessage = err instanceof Error ? err.toString() : "Unknown Error";
5894
+ throw new EncryptedMediaError(
5895
+ "MEDIA_KEYS_ATTACHMENT_ERROR",
5896
+ "Could not attach the MediaKeys to the media element: " + errMessage
5897
+ );
5898
+ }
5899
+ }
5900
+ async function clearMediaKeys(mediaElement, previousState) {
5901
+ if (previousState === void 0) {
5902
+ return;
5903
+ }
5904
+ if (previousState.pendingTask !== null) {
5905
+ await awaitMediaKeysAttachment(previousState);
5906
+ }
5907
+ if (previousState.mediaKeysState === null) {
5908
+ return;
5571
5909
  }
5572
5910
  log_default.info("DRM: Disposing of the current MediaKeys");
5573
- const { loadedSessionsStore } = currentState;
5574
- media_keys_infos_store_default.clearState(mediaElement);
5911
+ const { loadedSessionsStore } = previousState.mediaKeysState;
5575
5912
  await loadedSessionsStore.closeAllSessions();
5576
- return setMediaKeys(currentState.emeImplementation, mediaElement, null);
5913
+ return setMediaKeys(previousState.mediaKeysState.emeImplementation, mediaElement, null);
5914
+ }
5915
+
5916
+ // src/main_thread/decrypt/dispose_decryption_resources.ts
5917
+ async function disposeDecryptionResources(mediaElement) {
5918
+ return media_keys_attacher_default.clearMediaKeys(mediaElement);
5577
5919
  }
5578
5920
 
5579
5921
  // src/main_thread/decrypt/clear_on_stop.ts
5580
- function clearOnStop(mediaElement) {
5922
+ async function clearOnStop(mediaElement) {
5581
5923
  log_default.info("DRM: Clearing-up DRM session.");
5582
5924
  if (shouldUnsetMediaKeys()) {
5583
5925
  log_default.info("DRM: disposing current MediaKeys.");
5584
5926
  return disposeDecryptionResources(mediaElement);
5585
5927
  }
5586
- const currentState = media_keys_infos_store_default.getState(mediaElement);
5928
+ const currentState = await media_keys_attacher_default.getAttachedMediaKeysState(mediaElement);
5587
5929
  if (currentState !== null && currentState.keySystemOptions.closeSessionsOnStop === true) {
5588
5930
  log_default.info("DRM: closing all current sessions.");
5589
5931
  return currentState.loadedSessionsStore.closeAllSessions();
@@ -8135,50 +8477,6 @@
8135
8477
  return false;
8136
8478
  }
8137
8479
 
8138
- // src/main_thread/decrypt/attach_media_keys.ts
8139
- function disableMediaKeys(mediaElement) {
8140
- var _a2;
8141
- const previousState = media_keys_infos_store_default.getState(mediaElement);
8142
- media_keys_infos_store_default.setState(mediaElement, null);
8143
- return setMediaKeys((_a2 = previousState == null ? void 0 : previousState.emeImplementation) != null ? _a2 : eme_default, mediaElement, null);
8144
- }
8145
- async function attachMediaKeys(mediaElement, {
8146
- emeImplementation,
8147
- keySystemOptions,
8148
- askedConfiguration,
8149
- loadedSessionsStore,
8150
- mediaKeySystemAccess,
8151
- mediaKeys
8152
- }, cancelSignal) {
8153
- const previousState = media_keys_infos_store_default.getState(mediaElement);
8154
- const closeAllSessions = previousState !== null && previousState.loadedSessionsStore !== loadedSessionsStore ? previousState.loadedSessionsStore.closeAllSessions() : Promise.resolve();
8155
- await closeAllSessions;
8156
- if (cancelSignal.isCancelled()) {
8157
- throw cancelSignal.cancellationError;
8158
- }
8159
- media_keys_infos_store_default.setState(mediaElement, {
8160
- emeImplementation,
8161
- keySystemOptions,
8162
- mediaKeySystemAccess,
8163
- mediaKeys,
8164
- loadedSessionsStore,
8165
- askedConfiguration
8166
- });
8167
- if (mediaElement.mediaKeys === mediaKeys) {
8168
- return;
8169
- }
8170
- log_default.info("DRM: Attaching MediaKeys to the media element");
8171
- return setMediaKeys(emeImplementation, mediaElement, mediaKeys).then(() => {
8172
- log_default.info("DRM: MediaKeys attached with success");
8173
- }).catch((err) => {
8174
- const errMessage = err instanceof Error ? err.toString() : "Unknown Error";
8175
- throw new EncryptedMediaError(
8176
- "MEDIA_KEYS_ATTACHMENT_ERROR",
8177
- "Could not attach the MediaKeys to the media element: " + errMessage
8178
- );
8179
- });
8180
- }
8181
-
8182
8480
  // src/main_thread/decrypt/utils/is_session_usable.ts
8183
8481
  function isSessionUsable(loadedSession) {
8184
8482
  if (loadedSession.sessionId === "") {
@@ -8486,25 +8784,49 @@
8486
8784
  }
8487
8785
 
8488
8786
  // src/main_thread/decrypt/find_key_system.ts
8489
- function checkCachedMediaKeySystemAccess(keySystem, askedConfiguration, currentKeySystemAccess, currentKeySystemOptions) {
8490
- const mksConfiguration = currentKeySystemAccess.getConfiguration();
8491
- if (shouldRenewMediaKeySystemAccess() || isNullOrUndefined(mksConfiguration)) {
8492
- return null;
8787
+ function isNewMediaKeySystemConfigurationCompatibleWithPreviousOne(newConfiguration, prevConfiguration) {
8788
+ var _a2, _b2, _c2, _d2, _e2, _f, _g, _h, _i, _j;
8789
+ if (newConfiguration.label !== prevConfiguration.label) {
8790
+ return false;
8493
8791
  }
8494
- if (keySystem.type !== currentKeySystemOptions.type) {
8495
- return null;
8792
+ const prevDistinctiveIdentifier = (_a2 = prevConfiguration.distinctiveIdentifier) != null ? _a2 : "optional";
8793
+ const newDistinctiveIdentifier = (_b2 = newConfiguration.distinctiveIdentifier) != null ? _b2 : "optional";
8794
+ if (prevDistinctiveIdentifier !== newDistinctiveIdentifier) {
8795
+ return false;
8496
8796
  }
8497
- if ((!isNullOrUndefined(keySystem.persistentLicenseConfig) || keySystem.persistentState === "required") && mksConfiguration.persistentState !== "required") {
8498
- return null;
8797
+ const prevPersistentState = (_c2 = prevConfiguration.persistentState) != null ? _c2 : "optional";
8798
+ const newPersistentState = (_d2 = newConfiguration.persistentState) != null ? _d2 : "optional";
8799
+ if (prevPersistentState !== newPersistentState) {
8800
+ return false;
8499
8801
  }
8500
- if (keySystem.distinctiveIdentifier === "required" && mksConfiguration.distinctiveIdentifier !== "required") {
8501
- return null;
8802
+ const prevInitDataTypes = (_e2 = prevConfiguration.initDataTypes) != null ? _e2 : [];
8803
+ const newInitDataTypes = (_f = newConfiguration.initDataTypes) != null ? _f : [];
8804
+ if (!isArraySubsetOf(newInitDataTypes, prevInitDataTypes)) {
8805
+ return false;
8502
8806
  }
8503
- return {
8504
- keySystemOptions: keySystem,
8505
- keySystemAccess: currentKeySystemAccess,
8506
- askedConfiguration
8507
- };
8807
+ const prevSessionTypes = (_g = prevConfiguration.sessionTypes) != null ? _g : [];
8808
+ const newSessionTypes = (_h = newConfiguration.sessionTypes) != null ? _h : [];
8809
+ if (!isArraySubsetOf(newSessionTypes, prevSessionTypes)) {
8810
+ return false;
8811
+ }
8812
+ for (const prop of ["audioCapabilities", "videoCapabilities"]) {
8813
+ const newCapabilities = (_i = newConfiguration[prop]) != null ? _i : [];
8814
+ const prevCapabilities = (_j = prevConfiguration[prop]) != null ? _j : [];
8815
+ const wasFound = newCapabilities.every((n) => {
8816
+ var _a3, _b3, _c3, _d3, _e3, _f2;
8817
+ for (let i = 0; i < prevCapabilities.length; i++) {
8818
+ const prevCap = prevCapabilities[i];
8819
+ if (((_a3 = prevCap.robustness) != null ? _a3 : "") === ((_b3 = n.robustness) != null ? _b3 : "") || ((_c3 = prevCap.encryptionScheme) != null ? _c3 : null) === ((_d3 = n.encryptionScheme) != null ? _d3 : null) || ((_e3 = prevCap.robustness) != null ? _e3 : "") === ((_f2 = n.robustness) != null ? _f2 : "")) {
8820
+ return true;
8821
+ }
8822
+ }
8823
+ return false;
8824
+ });
8825
+ if (!wasFound) {
8826
+ return false;
8827
+ }
8828
+ }
8829
+ return true;
8508
8830
  }
8509
8831
  function findKeySystemCanonicalName(ksType) {
8510
8832
  const { EME_KEY_SYSTEMS } = config_default.getCurrent();
@@ -8517,12 +8839,19 @@
8517
8839
  }
8518
8840
  function buildKeySystemConfigurations(keySystemTypeInfo) {
8519
8841
  const { keyName, keyType, keySystemOptions: keySystem } = keySystemTypeInfo;
8520
- const sessionTypes = ["temporary"];
8842
+ let sessionTypes;
8521
8843
  let persistentState = "optional";
8522
8844
  let distinctiveIdentifier = "optional";
8523
- if (!isNullOrUndefined(keySystem.persistentLicenseConfig)) {
8845
+ if (Array.isArray(keySystem.wantedSessionTypes)) {
8846
+ sessionTypes = keySystem.wantedSessionTypes;
8847
+ if (arrayIncludes(keySystem.wantedSessionTypes, "persistent-license") && !isNullOrUndefined(keySystem.persistentLicenseConfig)) {
8848
+ persistentState = "required";
8849
+ }
8850
+ } else if (!isNullOrUndefined(keySystem.persistentLicenseConfig)) {
8524
8851
  persistentState = "required";
8525
- sessionTypes.push("persistent-license");
8852
+ sessionTypes = ["persistent-license"];
8853
+ } else {
8854
+ sessionTypes = ["temporary"];
8526
8855
  }
8527
8856
  if (!isNullOrUndefined(keySystem.persistentState)) {
8528
8857
  persistentState = keySystem.persistentState;
@@ -8690,40 +9019,34 @@
8690
9019
  throw new Error("requestMediaKeySystemAccess is not implemented in your browser.");
8691
9020
  }
8692
9021
  const chosenType = keySystemsType[index];
8693
- const currentState = media_keys_infos_store_default.getState(mediaElement);
8694
- if (currentState !== null) {
8695
- if (eme_default.implementation === currentState.emeImplementation.implementation) {
8696
- const cachedKeySystemAccess = checkCachedMediaKeySystemAccess(
8697
- chosenType.keySystemOptions,
8698
- currentState.askedConfiguration,
8699
- currentState.mediaKeySystemAccess,
8700
- currentState.keySystemOptions
8701
- );
8702
- if (cachedKeySystemAccess !== null) {
8703
- log_default.info("DRM: Found cached compatible keySystem");
8704
- return Promise.resolve({
8705
- type: "reuse-media-key-system-access",
8706
- value: {
8707
- mediaKeySystemAccess: cachedKeySystemAccess.keySystemAccess,
8708
- askedConfiguration: cachedKeySystemAccess.askedConfiguration,
8709
- options: cachedKeySystemAccess.keySystemOptions,
8710
- codecSupport: extractCodecSupportListFromConfiguration(
8711
- cachedKeySystemAccess.askedConfiguration,
8712
- cachedKeySystemAccess.keySystemAccess.getConfiguration()
8713
- )
8714
- }
8715
- });
8716
- }
8717
- }
8718
- }
8719
9022
  const { keyType, keySystemOptions } = chosenType;
8720
9023
  const keySystemConfigurations = buildKeySystemConfigurations(chosenType);
8721
9024
  log_default.debug(
8722
9025
  `DRM: Request keysystem access ${keyType},${index + 1} of ${keySystemsType.length}`
8723
9026
  );
8724
9027
  let keySystemAccess;
9028
+ const currentState = await media_keys_attacher_default.getAttachedMediaKeysState(mediaElement);
8725
9029
  for (let configIdx = 0; configIdx < keySystemConfigurations.length; configIdx++) {
8726
9030
  const keySystemConfiguration = keySystemConfigurations[configIdx];
9031
+ if (currentState !== null && !shouldRenewMediaKeySystemAccess() && // TODO: Do it with MediaKeySystemAccess.prototype.keySystem instead?
9032
+ keyType === currentState.mediaKeySystemAccess.keySystem && eme_default.implementation === currentState.emeImplementation.implementation && isNewMediaKeySystemConfigurationCompatibleWithPreviousOne(
9033
+ keySystemConfiguration,
9034
+ currentState.askedConfiguration
9035
+ )) {
9036
+ log_default.info("DRM: Found cached compatible keySystem");
9037
+ return Promise.resolve({
9038
+ type: "reuse-media-key-system-access",
9039
+ value: {
9040
+ mediaKeySystemAccess: currentState.mediaKeySystemAccess,
9041
+ askedConfiguration: currentState.askedConfiguration,
9042
+ options: keySystemOptions,
9043
+ codecSupport: extractCodecSupportListFromConfiguration(
9044
+ currentState.askedConfiguration,
9045
+ currentState.mediaKeySystemAccess.getConfiguration()
9046
+ )
9047
+ }
9048
+ });
9049
+ }
8727
9050
  try {
8728
9051
  keySystemAccess = await testKeySystem(keyType, [keySystemConfiguration]);
8729
9052
  log_default.info("DRM: Found compatible keysystem", keyType, index + 1);
@@ -8770,6 +9093,14 @@
8770
9093
  }
8771
9094
  return keySystemAccess;
8772
9095
  }
9096
+ function isArraySubsetOf(arr1, arr2) {
9097
+ for (let i = 0; i < arr1.length; i++) {
9098
+ if (!arrayIncludes(arr2, arr1[i])) {
9099
+ return false;
9100
+ }
9101
+ }
9102
+ return true;
9103
+ }
8773
9104
 
8774
9105
  // src/main_thread/decrypt/utils/key_id_comparison.ts
8775
9106
  function areAllKeyIdsContainedIn(wantedKeyIds, keyIdsArr) {
@@ -9746,7 +10077,7 @@
9746
10077
  throw cancelSignal.cancellationError;
9747
10078
  }
9748
10079
  const { options, mediaKeySystemAccess, askedConfiguration, codecSupport } = evt.value;
9749
- const currentState = media_keys_infos_store_default.getState(mediaElement);
10080
+ const currentState = await media_keys_attacher_default.getAttachedMediaKeysState(mediaElement);
9750
10081
  const persistentSessionsStore = createPersistentSessionsStorage(options);
9751
10082
  if (evt.value.options.reuseMediaKeys !== false && canReuseMediaKeys() && currentState !== null && evt.type === "reuse-media-key-system-access") {
9752
10083
  log_default.debug("DRM: Reusing already created MediaKeys");
@@ -9796,7 +10127,7 @@
9796
10127
  const shouldDisableOldMediaKeys = mediaElement.mediaKeys !== null && mediaElement.mediaKeys !== void 0 && mediaKeys !== mediaElement.mediaKeys;
9797
10128
  if (shouldDisableOldMediaKeys) {
9798
10129
  log_default.debug("DRM: Disabling old MediaKeys");
9799
- await disableMediaKeys(mediaElement);
10130
+ await media_keys_attacher_default.clearMediaKeys(mediaElement);
9800
10131
  }
9801
10132
  return mediaKeysInfo;
9802
10133
  }
@@ -10460,7 +10791,10 @@
10460
10791
  keySystemOptions: options
10461
10792
  };
10462
10793
  log_default.debug("DRM: Attaching current MediaKeys");
10463
- attachMediaKeys(mediaElement, stateToAttach, this._canceller.signal).then(async () => {
10794
+ media_keys_attacher_default.attach(mediaElement, stateToAttach).then(async () => {
10795
+ if (this._isStopped()) {
10796
+ return;
10797
+ }
10464
10798
  this._stateData.isMediaKeysAttached = 2 /* Attached */;
10465
10799
  const { serverCertificate } = options;
10466
10800
  if (!isNullOrUndefined(serverCertificate)) {
@@ -10654,13 +10988,10 @@
10654
10988
  }
10655
10989
  this._lockInitDataQueue();
10656
10990
  let wantedSessionType;
10657
- if (isNullOrUndefined(options.persistentLicenseConfig)) {
10658
- wantedSessionType = "temporary";
10659
- } else if (!canCreatePersistentSession(mediaKeySystemAccess)) {
10660
- log_default.warn('DRM: Cannot create "persistent-license" session: not supported');
10661
- wantedSessionType = "temporary";
10662
- } else {
10991
+ if (canCreatePersistentSession(mediaKeySystemAccess) && (!isNullOrUndefined(options.persistentLicenseConfig) || !canCreateTemporarySession(mediaKeySystemAccess))) {
10663
10992
  wantedSessionType = "persistent-license";
10993
+ } else {
10994
+ wantedSessionType = "temporary";
10664
10995
  }
10665
10996
  const {
10666
10997
  EME_DEFAULT_MAX_SIMULTANEOUS_MEDIA_KEY_SESSIONS,
@@ -10985,6 +11316,10 @@
10985
11316
  const { sessionTypes } = mediaKeySystemAccess.getConfiguration();
10986
11317
  return sessionTypes !== void 0 && arrayIncludes(sessionTypes, "persistent-license");
10987
11318
  }
11319
+ function canCreateTemporarySession(mediaKeySystemAccess) {
11320
+ const { sessionTypes } = mediaKeySystemAccess.getConfiguration();
11321
+ return sessionTypes !== void 0 && arrayIncludes(sessionTypes, "temporary");
11322
+ }
10988
11323
  function getMissingKeyIds(expectedKeyIds, actualKeyIds) {
10989
11324
  return expectedKeyIds.filter((expected) => {
10990
11325
  return !actualKeyIds.some((actual) => areArraysOfNumbersEqual(actual, expected));
@@ -11093,7 +11428,7 @@
11093
11428
 
11094
11429
  // src/main_thread/decrypt/get_key_system_configuration.ts
11095
11430
  function getKeySystemConfiguration(mediaElement) {
11096
- const currentState = media_keys_infos_store_default.getState(mediaElement);
11431
+ const currentState = media_keys_attacher_default.getAwaitedState(mediaElement);
11097
11432
  if (currentState === null) {
11098
11433
  return null;
11099
11434
  }
@@ -11141,209 +11476,6 @@
11141
11476
  }
11142
11477
  }
11143
11478
 
11144
- // src/manifest/utils.ts
11145
- var SUPPORTED_ADAPTATIONS_TYPE = ["audio", "video", "text"];
11146
- function getMinimumSafePosition(manifest) {
11147
- var _a2, _b2;
11148
- const windowData = manifest.timeBounds;
11149
- if (windowData.timeshiftDepth === null) {
11150
- return (_a2 = windowData.minimumSafePosition) != null ? _a2 : 0;
11151
- }
11152
- const { maximumTimeData } = windowData;
11153
- let maximumTime;
11154
- if (!windowData.maximumTimeData.isLinear) {
11155
- maximumTime = maximumTimeData.maximumSafePosition;
11156
- } else {
11157
- const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
11158
- maximumTime = maximumTimeData.maximumSafePosition + timeDiff / 1e3;
11159
- }
11160
- const theoricalMinimum = maximumTime - windowData.timeshiftDepth;
11161
- return Math.max((_b2 = windowData.minimumSafePosition) != null ? _b2 : 0, theoricalMinimum);
11162
- }
11163
- function getLivePosition(manifest) {
11164
- const { maximumTimeData } = manifest.timeBounds;
11165
- if (!manifest.isLive || maximumTimeData.livePosition === void 0) {
11166
- return void 0;
11167
- }
11168
- if (!maximumTimeData.isLinear) {
11169
- return maximumTimeData.livePosition;
11170
- }
11171
- const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
11172
- return maximumTimeData.livePosition + timeDiff / 1e3;
11173
- }
11174
- function getMaximumSafePosition(manifest) {
11175
- const { maximumTimeData } = manifest.timeBounds;
11176
- if (!maximumTimeData.isLinear) {
11177
- return maximumTimeData.maximumSafePosition;
11178
- }
11179
- const timeDiff = monotonic_timestamp_default() - maximumTimeData.time;
11180
- return maximumTimeData.maximumSafePosition + timeDiff / 1e3;
11181
- }
11182
- function getSupportedAdaptations(period, type) {
11183
- if (type === void 0) {
11184
- return getAdaptations(period).filter((ada) => {
11185
- return ada.supportStatus.hasSupportedCodec !== false && ada.supportStatus.isDecipherable !== false;
11186
- });
11187
- }
11188
- const adaptationsForType = period.adaptations[type];
11189
- if (adaptationsForType === void 0) {
11190
- return [];
11191
- }
11192
- return adaptationsForType.filter((ada) => {
11193
- return ada.supportStatus.hasSupportedCodec !== false && ada.supportStatus.isDecipherable !== false;
11194
- });
11195
- }
11196
- function getPeriodForTime(manifest, time) {
11197
- let nextPeriod = null;
11198
- for (const period of manifest.periods) {
11199
- if (periodContainsTime(period, time, nextPeriod)) {
11200
- return period;
11201
- }
11202
- nextPeriod = period;
11203
- }
11204
- }
11205
- function getPeriodAfter(manifest, period) {
11206
- const endOfPeriod = period.end;
11207
- if (endOfPeriod === void 0) {
11208
- return null;
11209
- }
11210
- const nextPeriod = arrayFind(manifest.periods, (_period) => {
11211
- return _period.end === void 0 || endOfPeriod < _period.end;
11212
- });
11213
- return nextPeriod === void 0 ? null : nextPeriod;
11214
- }
11215
- function periodContainsTime(period, time, nextPeriod) {
11216
- if (time >= period.start && (period.end === void 0 || time < period.end)) {
11217
- return true;
11218
- } else if (time === period.end && (nextPeriod === null || nextPeriod.start > period.end)) {
11219
- return true;
11220
- }
11221
- return false;
11222
- }
11223
- function getAdaptations(period) {
11224
- const adaptationsByType = period.adaptations;
11225
- return objectValues(adaptationsByType).reduce(
11226
- // Note: the second case cannot happen. TS is just being dumb here
11227
- (acc, adaptations) => !isNullOrUndefined(adaptations) ? acc.concat(adaptations) : acc,
11228
- []
11229
- );
11230
- }
11231
- function toAudioTrack(adaptation, filterPlayable) {
11232
- var _a2, _b2;
11233
- const formatted = {
11234
- language: (_a2 = adaptation.language) != null ? _a2 : "",
11235
- normalized: (_b2 = adaptation.normalizedLanguage) != null ? _b2 : "",
11236
- audioDescription: adaptation.isAudioDescription === true,
11237
- id: adaptation.id,
11238
- representations: (filterPlayable ? adaptation.representations.filter(
11239
- (r) => r.isSupported === true && r.decipherable !== false
11240
- ) : adaptation.representations).map(toAudioRepresentation),
11241
- label: adaptation.label
11242
- };
11243
- if (adaptation.isDub === true) {
11244
- formatted.dub = true;
11245
- }
11246
- return formatted;
11247
- }
11248
- function toTextTrack(adaptation) {
11249
- var _a2, _b2;
11250
- return {
11251
- language: (_a2 = adaptation.language) != null ? _a2 : "",
11252
- normalized: (_b2 = adaptation.normalizedLanguage) != null ? _b2 : "",
11253
- closedCaption: adaptation.isClosedCaption === true,
11254
- id: adaptation.id,
11255
- label: adaptation.label,
11256
- forced: adaptation.isForcedSubtitles
11257
- };
11258
- }
11259
- function toVideoTrack(adaptation, filterPlayable) {
11260
- const trickModeTracks = adaptation.trickModeTracks !== void 0 ? adaptation.trickModeTracks.map((trickModeAdaptation) => {
11261
- const representations = (filterPlayable ? trickModeAdaptation.representations.filter(
11262
- (r) => r.isSupported === true && r.decipherable !== false
11263
- ) : trickModeAdaptation.representations).map(toVideoRepresentation);
11264
- const trickMode = {
11265
- id: trickModeAdaptation.id,
11266
- representations,
11267
- isTrickModeTrack: true
11268
- };
11269
- if (trickModeAdaptation.isSignInterpreted === true) {
11270
- trickMode.signInterpreted = true;
11271
- }
11272
- return trickMode;
11273
- }) : void 0;
11274
- const videoTrack = {
11275
- id: adaptation.id,
11276
- representations: (filterPlayable ? adaptation.representations.filter(
11277
- (r) => r.isSupported === true && r.decipherable !== false
11278
- ) : adaptation.representations).map(toVideoRepresentation),
11279
- label: adaptation.label
11280
- };
11281
- if (adaptation.isSignInterpreted === true) {
11282
- videoTrack.signInterpreted = true;
11283
- }
11284
- if (adaptation.isTrickModeTrack === true) {
11285
- videoTrack.isTrickModeTrack = true;
11286
- }
11287
- if (trickModeTracks !== void 0) {
11288
- videoTrack.trickModeTracks = trickModeTracks;
11289
- }
11290
- return videoTrack;
11291
- }
11292
- function toAudioRepresentation(representation) {
11293
- const { id, bitrate, codecs, isSpatialAudio, isSupported, decipherable } = representation;
11294
- return {
11295
- id,
11296
- bitrate,
11297
- codec: codecs == null ? void 0 : codecs[0],
11298
- isSpatialAudio,
11299
- isCodecSupported: isSupported,
11300
- decipherable
11301
- };
11302
- }
11303
- function toVideoRepresentation(representation) {
11304
- const {
11305
- id,
11306
- bitrate,
11307
- frameRate,
11308
- width,
11309
- height,
11310
- codecs,
11311
- hdrInfo,
11312
- isSupported,
11313
- decipherable,
11314
- contentProtections
11315
- } = representation;
11316
- return {
11317
- id,
11318
- bitrate,
11319
- frameRate,
11320
- width,
11321
- height,
11322
- codec: codecs == null ? void 0 : codecs[0],
11323
- hdrInfo,
11324
- isCodecSupported: isSupported,
11325
- decipherable,
11326
- contentProtections: contentProtections !== void 0 ? {
11327
- keyIds: contentProtections.keyIds
11328
- } : void 0
11329
- };
11330
- }
11331
- function toTaggedTrack(adaptation) {
11332
- switch (adaptation.type) {
11333
- case "audio":
11334
- return { type: "audio", track: toAudioTrack(adaptation, false) };
11335
- case "video":
11336
- return { type: "video", track: toVideoTrack(adaptation, false) };
11337
- case "text":
11338
- return { type: "text", track: toTextTrack(adaptation) };
11339
- }
11340
- }
11341
- function createRepresentationFilterFromFnString(fnString) {
11342
- return new Function(
11343
- `return (${fnString}(arguments[0], arguments[1]))`
11344
- );
11345
- }
11346
-
11347
11479
  // src/manifest/classes/codec_support_cache.ts
11348
11480
  var CodecSupportCache = class {
11349
11481
  /**
@@ -17536,7 +17668,7 @@
17536
17668
  let previouslyEmittedBitrate;
17537
17669
  const initialRepIds = content.representations.getValue().representationIds;
17538
17670
  const initialRepresentations = content.adaptation.representations.filter(
17539
- (r) => arrayIncludes(initialRepIds, r.id) && r.decipherable !== false && r.isSupported !== false
17671
+ (r) => arrayIncludes(initialRepIds, r.id) && r.isPlayable() !== false
17540
17672
  );
17541
17673
  const representationsList = new reference_default(
17542
17674
  initialRepresentations,
@@ -17702,11 +17834,11 @@
17702
17834
  representation
17703
17835
  };
17704
17836
  currentRepresentation.setValue(representation);
17705
- if (adapStreamCanceller.isUsed()) {
17837
+ if (fnCancelSignal.isCancelled()) {
17706
17838
  return;
17707
17839
  }
17708
17840
  callbacks.representationChange(repInfo);
17709
- if (adapStreamCanceller.isUsed()) {
17841
+ if (fnCancelSignal.isCancelled()) {
17710
17842
  return;
17711
17843
  }
17712
17844
  const representationStreamCallbacks = {
@@ -17784,7 +17916,7 @@
17784
17916
  representationStreamCallbacks.error(formattedError);
17785
17917
  return;
17786
17918
  }
17787
- cancellableSleep(4e3, adapStreamCanceller.signal).then(() => {
17919
+ cancellableSleep(4e3, fnCancelSignal).then(() => {
17788
17920
  return createRepresentationStream(
17789
17921
  representation,
17790
17922
  terminateCurrentStream,
@@ -17933,7 +18065,7 @@
17933
18065
  }
17934
18066
  function hasCompatibleCodec(adaptation, segmentSinkCodec) {
17935
18067
  return adaptation.representations.some(
17936
- (rep) => rep.isSupported === true && rep.decipherable !== false && are_codecs_compatible_default(rep.getMimeTypeString(), segmentSinkCodec)
18068
+ (rep) => rep.isPlayable() === true && are_codecs_compatible_default(rep.getMimeTypeString(), segmentSinkCodec)
17937
18069
  );
17938
18070
  }
17939
18071
 
@@ -18225,9 +18357,9 @@
18225
18357
  return segmentSinksStore.createSegmentSink(bufferType, codec);
18226
18358
  }
18227
18359
  function getFirstDeclaredMimeType(adaptation) {
18228
- const representations = adaptation.representations.filter((r) => {
18229
- return r.isSupported === true && r.decipherable !== false;
18230
- });
18360
+ const representations = adaptation.representations.filter(
18361
+ (r) => r.isPlayable() !== false
18362
+ );
18231
18363
  if (representations.length === 0) {
18232
18364
  const noRepErr = new MediaError(
18233
18365
  "NO_PLAYABLE_REPRESENTATION",
@@ -20410,7 +20542,7 @@
20410
20542
  this.start();
20411
20543
  }
20412
20544
  const observation = this._playbackObserver.getReference().getValue();
20413
- if (!observation.rebuffering || observation.paused || this._speed.getValue() <= 0 || bufferType !== "audio" && bufferType !== "video") {
20545
+ if (observation.rebuffering === null || observation.paused || this._speed.getValue() <= 0 || bufferType !== "audio" && bufferType !== "video") {
20414
20546
  return;
20415
20547
  }
20416
20548
  const loadedPos = observation.position.getWanted();
@@ -24614,7 +24746,7 @@
24614
24746
  return { eotf: "hlg" };
24615
24747
  }
24616
24748
  }
24617
- if (codecs !== void 0 && /^vp(08|09|10)/.exec(codecs)) {
24749
+ if (codecs !== void 0 && /^vp(08|09|10)/.test(codecs)) {
24618
24750
  return getWEBMHDRInformation(codecs);
24619
24751
  }
24620
24752
  }
@@ -24671,7 +24803,7 @@
24671
24803
  if (representation.children.supplementalProperties !== void 0 && arrayFind(
24672
24804
  representation.children.supplementalProperties,
24673
24805
  (r) => r.schemeIdUri === "tag:dolby.com,2018:dash:EC3_ExtensionType:2018" && r.value === "JOC"
24674
- )) {
24806
+ ) !== void 0) {
24675
24807
  parsedRepresentation.isSpatialAudio = true;
24676
24808
  }
24677
24809
  let codecs;
@@ -29591,7 +29723,7 @@
29591
29723
  }
29592
29724
  }
29593
29725
  }
29594
- if (cuesBuffer.length) {
29726
+ if (cuesBuffer.length > 0) {
29595
29727
  const lastCue = cuesBuffer[cuesBuffer.length - 1];
29596
29728
  if (areNearlyEqual(lastCue.end, start, relativeDelta)) {
29597
29729
  lastCue.end = start;
@@ -35319,7 +35451,7 @@ ${event}`
35319
35451
  }
35320
35452
  function getFreezingStatus(prevObservation, currentInfo, currentEvt, bufferGap) {
35321
35453
  const { MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING } = config_default.getCurrent();
35322
- if (prevObservation.freezing) {
35454
+ if (prevObservation.freezing !== null) {
35323
35455
  if (currentInfo.ended || currentInfo.paused || currentInfo.readyState === 0 || currentInfo.playbackRate === 0 || prevObservation.position.getPolled() !== currentInfo.position) {
35324
35456
  return null;
35325
35457
  }
@@ -35461,9 +35593,7 @@ ${event}`
35461
35593
  let playableRepresentations;
35462
35594
  if (repSettings === null) {
35463
35595
  playableRepresentations = trackInfo.adaptation.representations.filter(
35464
- (representation) => {
35465
- return representation.isSupported === true && representation.decipherable !== false;
35466
- }
35596
+ (representation) => isRepresentationPlayable(representation) === true
35467
35597
  );
35468
35598
  switchingMode = "lazy";
35469
35599
  } else {
@@ -35473,7 +35603,7 @@ ${event}`
35473
35603
  (r) => arrayIncludes(representationIds, r.id)
35474
35604
  );
35475
35605
  playableRepresentations = representations.filter(
35476
- (r) => r.isSupported === true && r.decipherable !== false
35606
+ (representation) => isRepresentationPlayable(representation) === true
35477
35607
  );
35478
35608
  if (playableRepresentations.length === 0) {
35479
35609
  self2.trigger("noPlayableLockedRepresentation", null);
@@ -35749,7 +35879,7 @@ ${event}`
35749
35879
  return false;
35750
35880
  }
35751
35881
  const playableRepresentations = adaptation.representations.filter(
35752
- (r) => r.isSupported === true && r.decipherable !== false
35882
+ (r) => isRepresentationPlayable(r) === true
35753
35883
  );
35754
35884
  return playableRepresentations.length > 0;
35755
35885
  }
@@ -37033,7 +37163,7 @@ ${event}`
37033
37163
  } = parseConstructorOptions(options);
37034
37164
  videoElement.preload = "auto";
37035
37165
  this.version = /* PLAYER_VERSION */
37036
- "4.3.0-dev.2024112900";
37166
+ "4.3.0-dev.2025011000";
37037
37167
  this.log = log_default;
37038
37168
  this.state = "STOPPED";
37039
37169
  this.videoElement = videoElement;
@@ -37815,7 +37945,7 @@ ${event}`
37815
37945
  * `false` otherwise.
37816
37946
  */
37817
37947
  isPaused() {
37818
- if (this.videoElement) {
37948
+ if (this.videoElement !== null) {
37819
37949
  if (arrayIncludes(["LOADING", "RELOADING"], this.state)) {
37820
37950
  return !this._priv_lastAutoPlay;
37821
37951
  } else {
@@ -39113,7 +39243,7 @@ ${event}`
39113
39243
  const tracksStore = (_b2 = this._priv_contentInfos) == null ? void 0 : _b2.tracksStore;
39114
39244
  if (!isNullOrUndefined(tracksStore)) {
39115
39245
  const periodRef = tracksStore.getPeriodObjectFromPeriod(period);
39116
- if (periodRef) {
39246
+ if (periodRef !== void 0) {
39117
39247
  const audioTrack = tracksStore.getChosenAudioTrack(periodRef, true);
39118
39248
  this._priv_triggerEventIfNotStopped("audioTrackChange", audioTrack, cancelSignal);
39119
39249
  const textTrack = tracksStore.getChosenTextTrack(periodRef);
@@ -39574,7 +39704,7 @@ ${event}`
39574
39704
  _Player._priv_currentlyUsedVideoElements = /* @__PURE__ */ new WeakSet();
39575
39705
  var Player = _Player;
39576
39706
  Player.version = /* PLAYER_VERSION */
39577
- "4.3.0-dev.2024112900";
39707
+ "4.3.0-dev.2025011000";
39578
39708
  var public_api_default = Player;
39579
39709
 
39580
39710
  // src/main_thread/api/index.ts