rx-player 4.5.0-dev.2026033100 → 4.5.0-dev.2026041501

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 (251) hide show
  1. package/CHANGELOG.md +22 -5
  2. package/VERSION +1 -1
  3. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  4. package/dist/commonjs/__GENERATED_CODE/embedded_dash_wasm.js +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/can_patch_out_pssh.d.ts +42 -0
  8. package/dist/commonjs/compat/can_patch_out_pssh.d.ts.map +1 -0
  9. package/dist/commonjs/compat/can_patch_out_pssh.js +53 -0
  10. package/dist/commonjs/compat/env_detector.d.ts +2 -0
  11. package/dist/commonjs/compat/env_detector.d.ts.map +1 -1
  12. package/dist/commonjs/compat/env_detector.js +5 -0
  13. package/dist/commonjs/core/adaptive/network_analyzer.d.ts +1 -2
  14. package/dist/commonjs/core/adaptive/network_analyzer.d.ts.map +1 -1
  15. package/dist/commonjs/core/adaptive/network_analyzer.js +3 -3
  16. package/dist/commonjs/core/adaptive/utils/representation_score_calculator.js +2 -2
  17. package/dist/commonjs/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
  18. package/dist/commonjs/core/cmcd/cmcd_data_builder.js +9 -3
  19. package/dist/commonjs/core/entry/content_preparer.d.ts.map +1 -1
  20. package/dist/commonjs/core/entry/content_preparer.js +5 -7
  21. package/dist/commonjs/core/entry/core_entry.d.ts.map +1 -1
  22. package/dist/commonjs/core/entry/core_entry.js +6 -2
  23. package/dist/commonjs/core/entry/core_text_displayer_interface.js +3 -3
  24. package/dist/commonjs/core/fetchers/manifest/manifest_fetcher.d.ts.map +1 -1
  25. package/dist/commonjs/core/fetchers/manifest/manifest_fetcher.js +12 -0
  26. package/dist/commonjs/core/fetchers/thumbnails/thumbnail_fetcher.js +1 -1
  27. package/dist/commonjs/core/fetchers/utils/schedule_request.d.ts.map +1 -1
  28. package/dist/commonjs/core/fetchers/utils/schedule_request.js +4 -3
  29. package/dist/commonjs/core/segment_sinks/garbage_collector.d.ts +0 -2
  30. package/dist/commonjs/core/segment_sinks/garbage_collector.d.ts.map +1 -1
  31. package/dist/commonjs/core/segment_sinks/garbage_collector.js +0 -3
  32. package/dist/commonjs/core/segment_sinks/implementations/text/text_segment_sink.d.ts +1 -1
  33. package/dist/commonjs/core/segment_sinks/implementations/text/text_segment_sink.d.ts.map +1 -1
  34. package/dist/commonjs/core/segment_sinks/implementations/text/text_segment_sink.js +2 -2
  35. package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  36. package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +6 -6
  37. package/dist/commonjs/core/stream/orchestrator/stream_orchestrator.d.ts.map +1 -1
  38. package/dist/commonjs/core/stream/orchestrator/stream_orchestrator.js +37 -40
  39. package/dist/commonjs/default_config.d.ts +5 -0
  40. package/dist/commonjs/default_config.d.ts.map +1 -1
  41. package/dist/commonjs/default_config.js +5 -0
  42. package/dist/commonjs/main_thread/api/public_api.d.ts.map +1 -1
  43. package/dist/commonjs/main_thread/api/public_api.js +23 -16
  44. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  45. package/dist/commonjs/main_thread/decrypt/content_decryptor.js +4 -1
  46. package/dist/commonjs/main_thread/decrypt/session_events_listener.js +1 -1
  47. package/dist/commonjs/main_thread/decrypt/set_server_certificate.d.ts +2 -0
  48. package/dist/commonjs/main_thread/decrypt/set_server_certificate.d.ts.map +1 -1
  49. package/dist/commonjs/main_thread/decrypt/set_server_certificate.js +4 -0
  50. package/dist/commonjs/main_thread/init/media_source_content_initializer.d.ts +0 -8
  51. package/dist/commonjs/main_thread/init/media_source_content_initializer.d.ts.map +1 -1
  52. package/dist/commonjs/main_thread/init/media_source_content_initializer.js +58 -50
  53. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts +35 -5
  54. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts.map +1 -1
  55. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.js +60 -19
  56. package/dist/commonjs/main_thread/render_thumbnail.d.ts.map +1 -1
  57. package/dist/commonjs/main_thread/render_thumbnail.js +4 -0
  58. package/dist/commonjs/main_thread/tracks_store/media_element_tracks_store.d.ts.map +1 -1
  59. package/dist/commonjs/main_thread/tracks_store/media_element_tracks_store.js +1 -0
  60. package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts +1 -1
  61. package/dist/commonjs/main_thread/tracks_store/tracks_store.js +1 -1
  62. package/dist/{es2017/parsers/containers/isobmff/take_pssh_out.d.ts → commonjs/parsers/containers/isobmff/extract_pssh.d.ts} +6 -4
  63. package/dist/commonjs/parsers/containers/isobmff/extract_pssh.d.ts.map +1 -0
  64. package/dist/commonjs/parsers/containers/isobmff/{take_pssh_out.js → extract_pssh.js} +22 -17
  65. package/dist/commonjs/parsers/containers/isobmff/index.d.ts +2 -2
  66. package/dist/commonjs/parsers/containers/isobmff/index.d.ts.map +1 -1
  67. package/dist/commonjs/parsers/containers/isobmff/index.js +4 -4
  68. package/dist/commonjs/playback_observer/core_playback_observer.d.ts +4 -4
  69. package/dist/commonjs/playback_observer/core_playback_observer.d.ts.map +1 -1
  70. package/dist/commonjs/playback_observer/media_element_playback_observer.d.ts +1 -2
  71. package/dist/commonjs/playback_observer/media_element_playback_observer.d.ts.map +1 -1
  72. package/dist/commonjs/transports/dash/segment_parser.js +1 -1
  73. package/dist/commonjs/transports/local/segment_parser.js +1 -1
  74. package/dist/commonjs/utils/test-utils.d.ts +30 -0
  75. package/dist/commonjs/utils/test-utils.d.ts.map +1 -0
  76. package/dist/commonjs/utils/test-utils.js +79 -0
  77. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  78. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.js +1 -1
  79. package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  80. package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
  81. package/dist/es2017/compat/can_patch_out_pssh.d.ts +42 -0
  82. package/dist/es2017/compat/can_patch_out_pssh.d.ts.map +1 -0
  83. package/dist/es2017/compat/can_patch_out_pssh.js +50 -0
  84. package/dist/es2017/compat/env_detector.d.ts +2 -0
  85. package/dist/es2017/compat/env_detector.d.ts.map +1 -1
  86. package/dist/es2017/compat/env_detector.js +5 -0
  87. package/dist/es2017/core/adaptive/network_analyzer.d.ts +1 -2
  88. package/dist/es2017/core/adaptive/network_analyzer.d.ts.map +1 -1
  89. package/dist/es2017/core/adaptive/network_analyzer.js +3 -3
  90. package/dist/es2017/core/adaptive/utils/representation_score_calculator.js +2 -2
  91. package/dist/es2017/core/cmcd/cmcd_data_builder.d.ts.map +1 -1
  92. package/dist/es2017/core/cmcd/cmcd_data_builder.js +9 -3
  93. package/dist/es2017/core/entry/content_preparer.d.ts.map +1 -1
  94. package/dist/es2017/core/entry/content_preparer.js +3 -5
  95. package/dist/es2017/core/entry/core_entry.d.ts.map +1 -1
  96. package/dist/es2017/core/entry/core_entry.js +6 -2
  97. package/dist/es2017/core/entry/core_text_displayer_interface.js +3 -3
  98. package/dist/es2017/core/fetchers/manifest/manifest_fetcher.d.ts.map +1 -1
  99. package/dist/es2017/core/fetchers/manifest/manifest_fetcher.js +12 -0
  100. package/dist/es2017/core/fetchers/thumbnails/thumbnail_fetcher.js +1 -1
  101. package/dist/es2017/core/fetchers/utils/schedule_request.d.ts.map +1 -1
  102. package/dist/es2017/core/fetchers/utils/schedule_request.js +2 -3
  103. package/dist/es2017/core/segment_sinks/garbage_collector.d.ts +0 -2
  104. package/dist/es2017/core/segment_sinks/garbage_collector.d.ts.map +1 -1
  105. package/dist/es2017/core/segment_sinks/garbage_collector.js +0 -3
  106. package/dist/es2017/core/segment_sinks/implementations/text/text_segment_sink.d.ts +1 -1
  107. package/dist/es2017/core/segment_sinks/implementations/text/text_segment_sink.d.ts.map +1 -1
  108. package/dist/es2017/core/segment_sinks/implementations/text/text_segment_sink.js +2 -2
  109. package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  110. package/dist/es2017/core/stream/adaptation/adaptation_stream.js +6 -6
  111. package/dist/es2017/core/stream/orchestrator/stream_orchestrator.d.ts.map +1 -1
  112. package/dist/es2017/core/stream/orchestrator/stream_orchestrator.js +40 -39
  113. package/dist/es2017/default_config.d.ts +5 -0
  114. package/dist/es2017/default_config.d.ts.map +1 -1
  115. package/dist/es2017/default_config.js +5 -0
  116. package/dist/es2017/main_thread/api/public_api.d.ts.map +1 -1
  117. package/dist/es2017/main_thread/api/public_api.js +20 -13
  118. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  119. package/dist/es2017/main_thread/decrypt/content_decryptor.js +4 -1
  120. package/dist/es2017/main_thread/decrypt/session_events_listener.js +1 -1
  121. package/dist/es2017/main_thread/decrypt/set_server_certificate.d.ts +2 -0
  122. package/dist/es2017/main_thread/decrypt/set_server_certificate.d.ts.map +1 -1
  123. package/dist/es2017/main_thread/decrypt/set_server_certificate.js +4 -0
  124. package/dist/es2017/main_thread/init/media_source_content_initializer.d.ts +0 -8
  125. package/dist/es2017/main_thread/init/media_source_content_initializer.d.ts.map +1 -1
  126. package/dist/es2017/main_thread/init/media_source_content_initializer.js +58 -50
  127. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts +35 -5
  128. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts.map +1 -1
  129. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.js +60 -19
  130. package/dist/es2017/main_thread/render_thumbnail.d.ts.map +1 -1
  131. package/dist/es2017/main_thread/render_thumbnail.js +4 -0
  132. package/dist/es2017/main_thread/tracks_store/media_element_tracks_store.d.ts.map +1 -1
  133. package/dist/es2017/main_thread/tracks_store/media_element_tracks_store.js +1 -0
  134. package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts +1 -1
  135. package/dist/es2017/main_thread/tracks_store/tracks_store.js +1 -1
  136. package/dist/{commonjs/parsers/containers/isobmff/take_pssh_out.d.ts → es2017/parsers/containers/isobmff/extract_pssh.d.ts} +6 -4
  137. package/dist/es2017/parsers/containers/isobmff/extract_pssh.d.ts.map +1 -0
  138. package/dist/es2017/parsers/containers/isobmff/{take_pssh_out.js → extract_pssh.js} +21 -16
  139. package/dist/es2017/parsers/containers/isobmff/index.d.ts +2 -2
  140. package/dist/es2017/parsers/containers/isobmff/index.d.ts.map +1 -1
  141. package/dist/es2017/parsers/containers/isobmff/index.js +2 -2
  142. package/dist/es2017/playback_observer/core_playback_observer.d.ts +4 -4
  143. package/dist/es2017/playback_observer/core_playback_observer.d.ts.map +1 -1
  144. package/dist/es2017/playback_observer/media_element_playback_observer.d.ts +1 -2
  145. package/dist/es2017/playback_observer/media_element_playback_observer.d.ts.map +1 -1
  146. package/dist/es2017/transports/dash/segment_parser.js +2 -2
  147. package/dist/es2017/transports/local/segment_parser.js +2 -2
  148. package/dist/es2017/utils/test-utils.d.ts +30 -0
  149. package/dist/es2017/utils/test-utils.d.ts.map +1 -0
  150. package/dist/es2017/utils/test-utils.js +36 -0
  151. package/dist/mpd-parser.wasm +0 -0
  152. package/dist/worker.js +6 -6
  153. package/package.json +4 -2
  154. package/src/README.md +7 -7
  155. package/src/__GENERATED_CODE/embedded_dash_wasm.ts +1 -1
  156. package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
  157. package/src/compat/__tests__/can_patch_out_pssh.test.ts +40 -0
  158. package/src/compat/can_patch_out_pssh.ts +53 -0
  159. package/src/compat/env_detector.ts +4 -0
  160. package/src/core/README.md +1 -1
  161. package/src/core/adaptive/README.md +3 -3
  162. package/src/core/adaptive/__tests__/adaptive_representation_selector.test.ts +181 -110
  163. package/src/core/adaptive/__tests__/guess_based_chooser.test.ts +229 -123
  164. package/src/core/adaptive/__tests__/mocks.ts +100 -0
  165. package/src/core/adaptive/__tests__/network_analyzer.test.ts +152 -59
  166. package/src/core/adaptive/network_analyzer.ts +4 -4
  167. package/src/core/adaptive/utils/__tests__/filter_by_bitrate.test.ts +11 -19
  168. package/src/core/adaptive/utils/__tests__/filter_by_resolution.test.ts +12 -12
  169. package/src/core/adaptive/utils/__tests__/last_estimate_storage.test.ts +25 -12
  170. package/src/core/adaptive/utils/__tests__/pending_requests_store.test.ts +13 -9
  171. package/src/core/adaptive/utils/__tests__/representation_score_calculator.test.ts +11 -11
  172. package/src/core/adaptive/utils/__tests__/select_optimal_representation.test.ts +13 -23
  173. package/src/core/adaptive/utils/representation_score_calculator.ts +2 -2
  174. package/src/core/cmcd/__tests__/cmcd_data_builder.test.ts +60 -15
  175. package/src/core/cmcd/cmcd_data_builder.ts +9 -3
  176. package/src/core/entry/README.md +2 -2
  177. package/src/core/entry/__tests__/core_text_displayer_interface.test.ts +20 -0
  178. package/src/core/entry/content_preparer.ts +2 -5
  179. package/src/core/entry/core_entry.ts +6 -2
  180. package/src/core/entry/core_text_displayer_interface.ts +3 -3
  181. package/src/core/fetchers/manifest/__tests__/manifest_fetcher.test.ts +52 -3
  182. package/src/core/fetchers/manifest/manifest_fetcher.ts +12 -0
  183. package/src/core/fetchers/thumbnails/__tests__/thumbnail_fetcher.test.ts +70 -0
  184. package/src/core/fetchers/thumbnails/thumbnail_fetcher.ts +1 -1
  185. package/src/core/fetchers/utils/schedule_request.ts +5 -3
  186. package/src/core/segment_sinks/__tests__/garbage_collector.test.ts +434 -0
  187. package/src/core/segment_sinks/__tests__/mocks.ts +49 -0
  188. package/src/core/segment_sinks/garbage_collector.ts +0 -3
  189. package/src/core/segment_sinks/implementations/text/__tests__/text_segment_sink.test.ts +177 -0
  190. package/src/core/segment_sinks/implementations/text/text_segment_sink.ts +2 -2
  191. package/src/core/segment_sinks/inventory/__tests__/buffered_history.test.ts +215 -0
  192. package/src/core/segment_sinks/inventory/__tests__/segment_inventory.test.ts +448 -0
  193. package/src/core/stream/adaptation/__tests__/adaptation_stream.test.ts +973 -0
  194. package/src/core/stream/adaptation/__tests__/get_representations_switch_strategy.test.ts +283 -374
  195. package/src/core/stream/adaptation/adaptation_stream.ts +6 -8
  196. package/src/core/stream/orchestrator/README.md +4 -4
  197. package/src/core/stream/orchestrator/__tests__/stream_orchestrator.test.ts +707 -0
  198. package/src/core/stream/orchestrator/stream_orchestrator.ts +41 -46
  199. package/src/core/stream/period/utils/__tests__/get_adaptation_switch_strategy.test.ts +290 -220
  200. package/src/core/stream/representation/__tests__/encryption_data_notifier.test.ts +93 -63
  201. package/src/core/stream/representation/utils/__tests__/append_segment_to_buffer.test.ts +106 -63
  202. package/src/core/stream/representation/utils/__tests__/check_for_discontinuity.test.ts +179 -204
  203. package/src/core/stream/representation/utils/__tests__/get_segment_priority.test.ts +7 -7
  204. package/src/core/stream/representation/utils/__tests__/push_init_segment.test.ts +103 -60
  205. package/src/core/stream/representation/utils/__tests__/push_media_segment.test.ts +231 -165
  206. package/src/default_config.ts +6 -0
  207. package/src/experimental/README.md +1 -1
  208. package/src/features/README.md +3 -3
  209. package/src/main_thread/api/README.md +6 -7
  210. package/src/main_thread/api/public_api.ts +16 -10
  211. package/src/main_thread/decrypt/README.md +4 -4
  212. package/src/main_thread/decrypt/__tests__/__global__/content_decryptor.test.ts +135 -0
  213. package/src/main_thread/decrypt/__tests__/__global__/get_license.test.ts +70 -0
  214. package/src/main_thread/decrypt/__tests__/__global__/server_certificate.test.ts +44 -0
  215. package/src/main_thread/decrypt/__tests__/__global__/utils.ts +2 -2
  216. package/src/main_thread/decrypt/content_decryptor.ts +6 -1
  217. package/src/main_thread/decrypt/session_events_listener.ts +1 -1
  218. package/src/main_thread/decrypt/set_server_certificate.ts +5 -0
  219. package/src/main_thread/init/media_source_content_initializer.ts +69 -55
  220. package/src/main_thread/init/utils/__tests__/stream_events_emitter.test.ts +175 -0
  221. package/src/main_thread/init/utils/stream_events_emitter/stream_events_emitter.ts +90 -26
  222. package/src/main_thread/render_thumbnail.ts +4 -0
  223. package/src/main_thread/tracks_store/README.md +12 -0
  224. package/src/main_thread/tracks_store/__tests__/media_element_tracks_store.test.ts +25 -18
  225. package/src/main_thread/tracks_store/media_element_tracks_store.ts +1 -0
  226. package/src/main_thread/tracks_store/tracks_store.ts +1 -1
  227. package/src/manifest/classes/__tests__/mocks.ts +202 -0
  228. package/src/parsers/containers/isobmff/__tests__/extract_pssh.test.ts +199 -0
  229. package/src/parsers/containers/isobmff/{take_pssh_out.ts → extract_pssh.ts} +21 -17
  230. package/src/parsers/containers/isobmff/index.ts +2 -2
  231. package/src/parsers/manifest/dash/wasm-parser/README.md +9 -9
  232. package/src/playback_observer/__tests__/mocks.ts +152 -0
  233. package/src/playback_observer/core_playback_observer.ts +4 -4
  234. package/src/playback_observer/media_element_playback_observer.ts +1 -1
  235. package/src/tools/README.md +2 -2
  236. package/src/transports/README.md +5 -5
  237. package/src/transports/dash/segment_parser.ts +2 -2
  238. package/src/transports/local/segment_parser.ts +2 -2
  239. package/src/transports/metaplaylist/README.md +4 -4
  240. package/src/utils/README.md +3 -3
  241. package/src/utils/test-utils.ts +50 -0
  242. package/dist/commonjs/core/entry/synchronize_sinks_on_observation.d.ts +0 -11
  243. package/dist/commonjs/core/entry/synchronize_sinks_on_observation.d.ts.map +0 -1
  244. package/dist/commonjs/core/entry/synchronize_sinks_on_observation.js +0 -20
  245. package/dist/commonjs/parsers/containers/isobmff/take_pssh_out.d.ts.map +0 -1
  246. package/dist/es2017/core/entry/synchronize_sinks_on_observation.d.ts +0 -11
  247. package/dist/es2017/core/entry/synchronize_sinks_on_observation.d.ts.map +0 -1
  248. package/dist/es2017/core/entry/synchronize_sinks_on_observation.js +0 -17
  249. package/dist/es2017/parsers/containers/isobmff/take_pssh_out.d.ts.map +0 -1
  250. package/src/core/adaptive/utils/__tests__/bandwith_estimator.test.ts +0 -117
  251. package/src/core/entry/synchronize_sinks_on_observation.ts +0 -22
@@ -3,24 +3,27 @@ import type { IMediaElement } from "../../../compat/browser_compatibility_types"
3
3
  import assert from "../../../utils/assert";
4
4
  import MediaElementTracksStore from "../media_element_tracks_store";
5
5
 
6
- const fakeMediaElement = {
7
- audioTracks: [
8
- { language: "en", enabled: false },
9
- { language: "fr", enabled: true },
10
- { language: "el", enabled: false },
11
- { language: "pt-BR", enabled: false },
12
- ],
13
- textTracks: [
14
- { language: "en", mode: "hidden" },
15
- { language: "fr", mode: "showing" },
16
- { language: "el", mode: "hidden" },
17
- { language: "pt-BR", mode: "hidden" },
18
- ],
19
- videoTracks: [{ language: "", selected: true }],
20
- } as unknown as IMediaElement;
6
+ function createFakeMediaElement(): IMediaElement {
7
+ return {
8
+ audioTracks: [
9
+ { language: "en", enabled: false },
10
+ { language: "fr", enabled: true },
11
+ { language: "el", enabled: false },
12
+ { language: "pt-BR", enabled: false },
13
+ ],
14
+ textTracks: [
15
+ { language: "en", mode: "hidden" },
16
+ { language: "fr", mode: "showing" },
17
+ { language: "el", mode: "hidden" },
18
+ { language: "pt-BR", mode: "hidden" },
19
+ ],
20
+ videoTracks: [{ language: "", selected: true }],
21
+ } as unknown as IMediaElement;
22
+ }
21
23
 
22
24
  describe("API - MediaElementTracksStore", () => {
23
25
  it("should returns correct results for getter", () => {
26
+ const fakeMediaElement = createFakeMediaElement();
24
27
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
25
28
  const audioTracks = trackManager.getAvailableAudioTracks();
26
29
  const textTracks = trackManager.getAvailableTextTracks();
@@ -54,6 +57,7 @@ describe("API - MediaElementTracksStore", () => {
54
57
  });
55
58
  });
56
59
  it("should returns correct results for setters", () => {
60
+ const fakeMediaElement = createFakeMediaElement();
57
61
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
58
62
 
59
63
  trackManager.setAudioTrackById("gen_audio_en_1");
@@ -80,6 +84,7 @@ describe("API - MediaElementTracksStore", () => {
80
84
  });
81
85
  });
82
86
  it("should emit available tracks change when changing text contents", () => {
87
+ const fakeMediaElement = createFakeMediaElement();
83
88
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
84
89
 
85
90
  return new Promise<void>((res) => {
@@ -107,6 +112,7 @@ describe("API - MediaElementTracksStore", () => {
107
112
  });
108
113
 
109
114
  it("should emit available tracks change when changing video contents", () => {
115
+ const fakeMediaElement = createFakeMediaElement();
110
116
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
111
117
  return new Promise<void>((res) => {
112
118
  trackManager.addEventListener("availableVideoTracksChange", (tracks) => {
@@ -129,6 +135,7 @@ describe("API - MediaElementTracksStore", () => {
129
135
  });
130
136
 
131
137
  it("should emit available tracks change when changing audio contents", () => {
138
+ const fakeMediaElement = createFakeMediaElement();
132
139
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
133
140
  return new Promise<void>((res) => {
134
141
  trackManager.addEventListener("availableAudioTracksChange", (tracks) => {
@@ -154,18 +161,18 @@ describe("API - MediaElementTracksStore", () => {
154
161
  });
155
162
 
156
163
  it("should emit chosen track when changing text content", () => {
164
+ const fakeMediaElement = createFakeMediaElement();
157
165
  const trackManager = new MediaElementTracksStore(fakeMediaElement);
158
166
 
159
167
  return new Promise<void>((res) => {
160
168
  trackManager.addEventListener("textTrackChange", (chosenTrack) => {
161
- expect(chosenTrack?.id).toBe("gen_text_fr_1");
169
+ expect(chosenTrack?.id).toBe("gen_text_en_1");
162
170
  res();
163
171
  });
164
172
 
165
- trackManager.setTextTrackById("gen_text_fr_1");
173
+ trackManager.setTextTrackById("gen_text_en_1");
166
174
 
167
175
  // Fake browser behavior
168
- fakeMediaElement.textTracks[0].mode = "hidden";
169
176
  (
170
177
  fakeMediaElement.textTracks as {
171
178
  onchange: ((arg: Event) => void) | undefined;
@@ -627,6 +627,7 @@ export default class MediaElementTracksStore extends EventEmitter<IMediaElementT
627
627
  const newAudioTracks = createAudioTracks(this._nativeAudioTracks);
628
628
  if (areTrackArraysDifferent(this._audioTracks, newAudioTracks)) {
629
629
  this._audioTracks = newAudioTracks;
630
+ this._setPreviouslyLockedAudioTrack();
630
631
  this.trigger("availableAudioTracksChange", this.getAvailableAudioTracks());
631
632
  const chosenAudioTrack = this._getCurrentAudioTrack();
632
633
  if (chosenAudioTrack?.nativeTrack !== this._lastEmittedNativeAudioTrack) {
@@ -1153,7 +1153,7 @@ export default class TracksStore extends EventEmitter<ITracksStoreEvents> {
1153
1153
  * Period.
1154
1154
  *
1155
1155
  * Returns `null` is the the current audio track is disabled or not
1156
- * set yet.a pas bcp de marge de manoeuvre j'ai l'impression
1156
+ * set yet.
1157
1157
  *
1158
1158
  * Returns `undefined` if the given Period's id is not currently found in the
1159
1159
  * `TracksStore`. The cause being most probably that the corresponding
@@ -0,0 +1,202 @@
1
+ /**
2
+ * This file contains "dummy" versions of the exported classes imported from
3
+ * this location:
4
+ *
5
+ * - They respect the same API (e.g. a `DummyRepresentation` is a
6
+ * `Representation`-compliant type).
7
+ *
8
+ * - They're doing no side-effect.
9
+ *
10
+ * - All of their methods throw an error immediately on call (you have to
11
+ * implement the ones you want, generally through testing tools).
12
+ */
13
+ import type { IRepresentationIndex, ISegment } from "../..";
14
+ import { makeMockedClass } from "../../../utils/test-utils";
15
+ import { ManifestMetadataFormat } from "../../types";
16
+ import type Adaptation from "../adaptation";
17
+ import type Manifest from "../manifest";
18
+ import type Period from "../period";
19
+ import type Representation from "../representation";
20
+
21
+ export const DummyManifest = makeMockedClass<Manifest>(
22
+ {
23
+ addEventListener: notImplemented("addEventListener"),
24
+ removeEventListener: notImplemented("removeEventListener"),
25
+ updateCodecSupport: notImplemented("updateCodecSupport"),
26
+ getPeriod: notImplemented("getPeriod"),
27
+ getPeriodForTime: notImplemented("getPeriodForTime"),
28
+ getNextPeriod: notImplemented("getNextPeriod"),
29
+ getPeriodAfter: notImplemented("getPeriodAfter"),
30
+ getUrls: notImplemented("getUrls"),
31
+ replace: notImplemented("replace"),
32
+ update: notImplemented("update"),
33
+ getMinimumSafePosition: notImplemented("getMinimumSafePosition"),
34
+ getLivePosition: notImplemented("getLivePosition"),
35
+ getMaximumSafePosition: notImplemented("getMaximumSafePosition"),
36
+ updateCodecSupportList: notImplemented("updateCodecSupportList"),
37
+ updateRepresentationsDeciperability: notImplemented(
38
+ "updateRepresentationsDecipherability",
39
+ ),
40
+ addRepresentationsToAvoid: notImplemented("addRepresentationsToAvoid"),
41
+ getAdaptations: notImplemented("getAdaptations"),
42
+ getAdaptation: notImplemented("getAdaptation"),
43
+ getAdaptationsForType: notImplemented("getAdaptationsForType"),
44
+ getMetadataSnapshot: notImplemented("getMetadataSnapshot"),
45
+ getCodecsWithUnknownSupport: notImplemented("getCodecsWithUnknownSupport"),
46
+ },
47
+ {
48
+ id: "n/a",
49
+ manifestFormat: ManifestMetadataFormat.Class,
50
+ transport: "test",
51
+ periods: [],
52
+ expired: null,
53
+ adaptations: {},
54
+ isDynamic: false,
55
+ isLive: false,
56
+ isLastPeriodKnown: true,
57
+ uris: [],
58
+ updateUrl: undefined,
59
+ suggestedPresentationDelay: undefined,
60
+ lifetime: undefined,
61
+ availabilityStartTime: undefined,
62
+ publishTime: undefined,
63
+ clockOffset: undefined,
64
+ timeBounds: {
65
+ minimumSafePosition: undefined,
66
+ timeshiftDepth: null,
67
+ maximumTimeData: {
68
+ livePosition: undefined,
69
+ isLinear: false,
70
+ maximumSafePosition: Number.MAX_SAFE_INTEGER,
71
+ time: 0,
72
+ },
73
+ },
74
+ },
75
+ );
76
+
77
+ export const DummyPeriod = makeMockedClass<Period>(
78
+ {
79
+ getAdaptations: notImplemented("getAdaptations"),
80
+ getAdaptation: notImplemented("getAdaptation"),
81
+ getAdaptationsForType: notImplemented("getAdaptationsForType"),
82
+ getSupportedAdaptations: notImplemented("getSupportedAdaptations"),
83
+ getMetadataSnapshot: notImplemented("getMetadataSnapshot"),
84
+ containsTime: notImplemented("containsTime"),
85
+ refreshCodecSupport: notImplemented("refreshCodecSupport"),
86
+ },
87
+ {
88
+ id: "n/a",
89
+ start: 0,
90
+ adaptations: {},
91
+ streamEvents: [],
92
+ thumbnailTracks: [],
93
+ duration: undefined,
94
+ end: undefined,
95
+ },
96
+ );
97
+
98
+ export const DummyAdaptation = makeMockedClass<Adaptation>(
99
+ {
100
+ getRepresentation: notImplemented("getRepresentation"),
101
+ getMetadataSnapshot: notImplemented("getMetadataSnapshot"),
102
+ refreshCodecSupport: notImplemented("refreshCodecSupport"),
103
+ },
104
+ {
105
+ id: "n/a",
106
+ type: "video",
107
+ representations: [],
108
+ supportStatus: {
109
+ hasCodecWithUndefinedSupport: false,
110
+ hasSupportedCodec: true,
111
+ isDecipherable: undefined,
112
+ },
113
+ isDub: undefined,
114
+ label: undefined,
115
+ language: undefined,
116
+ manuallyAdded: undefined,
117
+ isClosedCaption: undefined,
118
+ trickModeTracks: undefined,
119
+ isTrickModeTrack: undefined,
120
+ isForcedSubtitles: undefined,
121
+ isSignInterpreted: undefined,
122
+ isAudioDescription: undefined,
123
+ normalizedLanguage: undefined,
124
+ },
125
+ );
126
+
127
+ export const DummyRepresentationIndex = makeMockedClass<IRepresentationIndex>(
128
+ {
129
+ getLastAvailablePosition: notImplemented("getLastAvailablePosition"),
130
+ addPredictedSegments: notImplemented("addPredictedSegments"),
131
+ getFirstAvailablePosition: notImplemented("getFirstAvailablePosition"),
132
+ getTargetSegmentDuration: notImplemented("getTargetSegmentDuration"),
133
+ getSegments: notImplemented("getSegments"),
134
+ getEnd: notImplemented("getEnd"),
135
+ getInitSegment: notImplemented("getInitSegment"),
136
+ shouldRefresh: notImplemented("shouldRefresh"),
137
+ isInitialized: notImplemented("isInitialized"),
138
+ isSegmentStillAvailable: notImplemented("isSegmentStillAvailable"),
139
+ initialize: notImplemented("initialize"),
140
+ isStillAwaitingFutureSegments: notImplemented("isStillAwaitingFutureSegments"),
141
+ canBeOutOfSyncError: notImplemented("canBeOutOfSyncError"),
142
+ checkDiscontinuity: notImplemented("checkDiscontinuity"),
143
+ awaitSegmentBetween: notImplemented("awaitSegmentBetween"),
144
+ _replace: notImplemented("_replace"),
145
+ _update: notImplemented("_update"),
146
+ },
147
+ {},
148
+ );
149
+
150
+ export const DummyRepresentation = makeMockedClass<Representation>(
151
+ {
152
+ isPlayable: notImplemented("isPlayable"),
153
+ addProtectionData: notImplemented("addProtectionData"),
154
+ getMimeTypeString: notImplemented("getMimeTypeString"),
155
+ getEncryptionData: notImplemented("getEncryptionData"),
156
+ getAllEncryptionData: notImplemented("getAllEncryptionData"),
157
+ getMetadataSnapshot: notImplemented("getMetadataSnapshot"),
158
+ refreshCodecSupport: notImplemented("refreshCodecSupport"),
159
+ },
160
+ {
161
+ id: "n/a",
162
+ isSupported: undefined,
163
+ index: new DummyRepresentationIndex(),
164
+ chosenCodec: undefined,
165
+ baseCodecs: [],
166
+ bitrate: 1000,
167
+ uniqueId: "n/a",
168
+ decipherable: undefined,
169
+ isSpatialAudio: undefined,
170
+ shouldBeAvoided: false,
171
+ isCodecSupportedInWebWorker: undefined,
172
+ trackType: "video",
173
+ cdnMetadata: null,
174
+ width: undefined,
175
+ height: undefined,
176
+ mimeType: undefined,
177
+ frameRate: undefined,
178
+ hdrInfo: undefined,
179
+ contentProtections: undefined,
180
+ },
181
+ );
182
+
183
+ export function createSegment(props: Partial<ISegment> = {}): ISegment {
184
+ return {
185
+ id: "n/a",
186
+ isInit: false,
187
+ time: 0,
188
+ end: 2,
189
+ duration: 2,
190
+ timescale: 1,
191
+ complete: true,
192
+ url: null,
193
+ privateInfos: {},
194
+ ...props,
195
+ };
196
+ }
197
+
198
+ function notImplemented(name: string): () => never {
199
+ return () => {
200
+ throw new Error(`${name} not implemented`);
201
+ };
202
+ }
@@ -0,0 +1,199 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { concat } from "../../../../utils/byte_parsing";
3
+ import extractPssh, { getPsshSystemID } from "../extract_pssh";
4
+
5
+ const { mockCanPatchOutPsshBox, mockLog } = vi.hoisted(() => {
6
+ return {
7
+ mockCanPatchOutPsshBox: vi.fn(() => false),
8
+ mockLog: {
9
+ warn: vi.fn(),
10
+ info: vi.fn(),
11
+ debug: vi.fn(),
12
+ log: vi.fn(),
13
+ error: vi.fn(),
14
+ },
15
+ };
16
+ });
17
+
18
+ vi.mock("../../../../compat/can_patch_out_pssh", () => ({
19
+ default: mockCanPatchOutPsshBox,
20
+ }));
21
+
22
+ vi.mock("../../../../log", () => ({
23
+ default: mockLog,
24
+ }));
25
+
26
+ /** Build a minimal moov box wrapping `innerBytes`. */
27
+ function buildMoovBox(innerBytes: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer> {
28
+ const size = 8 + innerBytes.length;
29
+ const buf = new Uint8Array(size);
30
+ const view = new DataView(buf.buffer);
31
+ view.setUint32(0, size, false);
32
+ buf[4] = 0x6d;
33
+ buf[5] = 0x6f;
34
+ buf[6] = 0x6f;
35
+ buf[7] = 0x76; // "moov"
36
+ buf.set(innerBytes, 8);
37
+ return buf;
38
+ }
39
+
40
+ /**
41
+ * Build a pssh box.
42
+ *
43
+ * Layout (after size + name):
44
+ * 1 byte version
45
+ * 3 bytes flags
46
+ * 16 bytes systemId
47
+ * N bytes extra data
48
+ */
49
+ function buildPsshBox(
50
+ systemId: Uint8Array<ArrayBuffer>,
51
+ version = 0,
52
+ extraData: Uint8Array<ArrayBuffer> = new Uint8Array(0),
53
+ ): Uint8Array<ArrayBuffer> {
54
+ // 8 (size+name) + 1 (version) + 3 (flags) + 16 (systemId) + extraData
55
+ const size = 8 + 1 + 3 + 16 + extraData.length;
56
+ const buf = new Uint8Array(size);
57
+ const view = new DataView(buf.buffer);
58
+ view.setUint32(0, size, false);
59
+ buf[4] = 0x70;
60
+ buf[5] = 0x73;
61
+ buf[6] = 0x73;
62
+ buf[7] = 0x68; // "pssh"
63
+ buf[8] = version; // version (bytes 0 of version+flags)
64
+ // flags stay 0x000000
65
+ buf.set(systemId, 12); // offset 8+4 = 12
66
+ buf.set(extraData, 28);
67
+ return buf;
68
+ }
69
+
70
+ const SYSTEM_ID_A = new Uint8Array([
71
+ 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2,
72
+ 0xfb, 0x4b,
73
+ ]);
74
+ const SYSTEM_ID_B = new Uint8Array([
75
+ 0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6, 0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc, 0xd5, 0x1d,
76
+ 0x21, 0xed,
77
+ ]);
78
+
79
+ const systemIdAHex = Array.from(SYSTEM_ID_A)
80
+ .map((b) => b.toString(16).padStart(2, "0"))
81
+ .join("");
82
+ const systemIdBHex = Array.from(SYSTEM_ID_B)
83
+ .map((b) => b.toString(16).padStart(2, "0"))
84
+ .join("");
85
+
86
+ describe("extractPssh", () => {
87
+ beforeEach(() => {
88
+ mockCanPatchOutPsshBox.mockReturnValue(true);
89
+ });
90
+ afterEach(() => {
91
+ vi.resetAllMocks();
92
+ });
93
+
94
+ it("returns [] when there is no moov box", () => {
95
+ const data = new Uint8Array(32); // no moov, only `0`
96
+ expect(extractPssh(data)).toEqual([]);
97
+ });
98
+
99
+ it("returns [] when moov contains no pssh box", () => {
100
+ // An empty moov (just the 8-byte header, no inner boxes)
101
+ const data = buildMoovBox(new Uint8Array(0));
102
+ expect(extractPssh(data)).toEqual([]);
103
+ });
104
+
105
+ it("extracts a single pssh box", () => {
106
+ const pssh = buildPsshBox(SYSTEM_ID_A);
107
+ const data = buildMoovBox(pssh);
108
+ const result = extractPssh(data);
109
+ expect(result).toHaveLength(1);
110
+ expect(result[0].systemId).toBe(systemIdAHex);
111
+ });
112
+
113
+ it("extracts multiple pssh boxes in order", () => {
114
+ const psshA = buildPsshBox(SYSTEM_ID_A);
115
+ const psshB = buildPsshBox(SYSTEM_ID_B);
116
+ const data = buildMoovBox(concat(psshA, psshB));
117
+ const result = extractPssh(data);
118
+ expect(result).toHaveLength(2);
119
+ expect(result[0].systemId).toBe(systemIdAHex);
120
+ expect(result[1].systemId).toBe(systemIdBHex);
121
+ });
122
+
123
+ it("skips a pssh whose systemId cannot be parsed and keeps going", () => {
124
+ // A pssh with version > 1 triggers the 'un-handled PSSH version' warn path,
125
+ // so getPsshSystemID returns undefined and the box is omitted.
126
+ const psshBad = buildPsshBox(SYSTEM_ID_A, 2 /* unsupported version */);
127
+ const psshGood = buildPsshBox(SYSTEM_ID_B);
128
+ const data = buildMoovBox(concat(psshBad, psshGood));
129
+ const result = extractPssh(data);
130
+ expect(result).toHaveLength(1);
131
+ expect(result[0].systemId).toBe(systemIdBHex);
132
+ expect(mockLog.warn).toHaveBeenCalledWith("isobmff", "un-handled PSSH version");
133
+ });
134
+
135
+ it("patches out pssh bytes when canPatchOutPsshBox returns true", () => {
136
+ mockCanPatchOutPsshBox.mockReturnValue(true);
137
+ const pssh = buildPsshBox(SYSTEM_ID_A);
138
+ const moov = buildMoovBox(pssh);
139
+ // The pssh box starts at offset 8 inside moov content (right after moov header).
140
+ // After patching, bytes 4–7 of the pssh box should be "free" (0x66 0x72 0x65 0x65).
141
+ extractPssh(moov);
142
+ // moov content starts at offset 8 of the full segment.
143
+ // pssh name is at moov_content[4..7] = segment[12..15]
144
+ expect(moov[12]).toBe(0x66); // 'f'
145
+ expect(moov[13]).toBe(0x72); // 'r'
146
+ expect(moov[14]).toBe(0x65); // 'e'
147
+ expect(moov[15]).toBe(0x65); // 'e'
148
+ });
149
+
150
+ it("does not patch bytes when canPatchOutPsshBox returns false", () => {
151
+ mockCanPatchOutPsshBox.mockReturnValue(false);
152
+ const pssh = buildPsshBox(SYSTEM_ID_A);
153
+ const originalNameByte1 = pssh[4]; // should be 0x70 ('p')
154
+ const originalNameByte2 = pssh[5]; // 's'
155
+ const originalNameByte3 = pssh[6]; // 's'
156
+ const originalNameByte4 = pssh[7]; // 'h'
157
+ const moov = buildMoovBox(pssh);
158
+ extractPssh(moov);
159
+ expect(moov[12]).toBe(originalNameByte1);
160
+ expect(moov[13]).toBe(originalNameByte2);
161
+ expect(moov[14]).toBe(originalNameByte3);
162
+ expect(moov[15]).toBe(originalNameByte4);
163
+ });
164
+ });
165
+
166
+ describe("getPsshSystemID", () => {
167
+ afterEach(() => {
168
+ vi.resetAllMocks();
169
+ });
170
+
171
+ it("parses a valid version-0 pssh and returns hex systemId", () => {
172
+ const pssh = buildPsshBox(SYSTEM_ID_A);
173
+ // initialDataOffset is the offset right after size (4) + name (4) = 8
174
+ const result = getPsshSystemID(pssh, 8);
175
+ expect(result).toBe(systemIdAHex);
176
+ });
177
+
178
+ it("parses a valid version-1 pssh", () => {
179
+ const pssh = buildPsshBox(SYSTEM_ID_B, 1);
180
+ const result = getPsshSystemID(pssh, 8);
181
+ expect(result).toBe(systemIdBHex);
182
+ });
183
+
184
+ it("returns undefined and warns for version > 1", () => {
185
+ const pssh = buildPsshBox(SYSTEM_ID_A, 2);
186
+ const result = getPsshSystemID(pssh, 8);
187
+ expect(result).toBeUndefined();
188
+ expect(mockLog.warn).toHaveBeenCalledWith("isobmff", "un-handled PSSH version");
189
+ });
190
+
191
+ it("returns undefined when buffer is too short to contain a full systemId", () => {
192
+ // Build a buffer that's big enough for the header (version + flags = 4 bytes)
193
+ // but lacks the 16-byte systemId.
194
+ const buf = new Uint8Array(8 + 4 + 10); // only 10 bytes where 16 are needed
195
+ const result = getPsshSystemID(buf, 8);
196
+ expect(result).toBeUndefined();
197
+ expect(mockLog.warn).not.toHaveBeenCalled();
198
+ });
199
+ });
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import canPatchOutPsshBox from "../../../compat/can_patch_out_pssh";
17
18
  import log from "../../../log";
18
19
  import sliceUint8Array from "../../../utils/slice_uint8array";
19
20
  import { bytesToHex } from "../../../utils/string_parsing";
@@ -28,46 +29,49 @@ export interface IISOBMFFPSSHInfo {
28
29
  }
29
30
 
30
31
  /**
31
- * Replace every PSSH box from an ISOBMFF segment by FREE boxes and returns the
32
- * removed PSSH in an array.
32
+ * Return every `pssh` box from an ISOBMFF segment.
33
+ *
34
+ * If the current device has no issue with it, also replace them by `free` boxes.
33
35
  * Useful to manually manage encryption while avoiding the round-trip with the
34
36
  * browser's encrypted event.
37
+ *
35
38
  * @param {Uint8Array} data - the ISOBMFF segment
36
39
  * @returns {Array.<Uint8Array>} - The extracted PSSH boxes. In the order they
37
40
  * are encountered.
38
41
  */
39
- export default function takePSSHOut(data: Uint8Array<ArrayBuffer>): IISOBMFFPSSHInfo[] {
40
- let i = 0;
41
- const moov = getBoxContent(data, 0x6d6f6f76 /* moov */);
42
- if (moov === null) {
42
+ export default function extractPssh(data: Uint8Array<ArrayBuffer>): IISOBMFFPSSHInfo[] {
43
+ const moovContent = getBoxContent(data, 0x6d6f6f76 /* moov */);
44
+ if (moovContent === null) {
43
45
  return [];
44
46
  }
45
47
 
46
48
  const psshBoxes: IISOBMFFPSSHInfo[] = [];
47
- while (i < moov.length) {
49
+ let remainingMoovContent = moovContent;
50
+ while (remainingMoovContent.length > 0) {
48
51
  let psshOffsets;
49
52
  try {
50
- psshOffsets = getBoxOffsets(moov, 0x70737368 /* pssh */);
53
+ psshOffsets = getBoxOffsets(remainingMoovContent, 0x70737368 /* pssh */);
51
54
  } catch (e) {
52
- const err = e instanceof Error ? e : "";
55
+ const err = e instanceof Error ? e : new Error("Unknown ISOBMFF box reading error");
53
56
  log.warn("isobmff", "Error while removing PSSH from ISOBMFF", err);
54
57
  return psshBoxes;
55
58
  }
56
59
  if (psshOffsets === null) {
57
60
  return psshBoxes;
58
61
  }
59
- const pssh = sliceUint8Array(moov, psshOffsets[0], psshOffsets[2]);
62
+ const pssh = sliceUint8Array(remainingMoovContent, psshOffsets[0], psshOffsets[2]);
60
63
  const systemId = getPsshSystemID(pssh, psshOffsets[1] - psshOffsets[0]);
61
64
  if (systemId !== undefined) {
62
65
  psshBoxes.push({ systemId, data: pssh });
63
66
  }
64
-
65
- // replace by `free` box.
66
- moov[psshOffsets[0] + 4] = 0x66;
67
- moov[psshOffsets[0] + 5] = 0x72;
68
- moov[psshOffsets[0] + 6] = 0x65;
69
- moov[psshOffsets[0] + 7] = 0x65;
70
- i = psshOffsets[2];
67
+ if (canPatchOutPsshBox()) {
68
+ // replace by `free` box.
69
+ remainingMoovContent[psshOffsets[0] + 4] = 0x66;
70
+ remainingMoovContent[psshOffsets[0] + 5] = 0x72;
71
+ remainingMoovContent[psshOffsets[0] + 6] = 0x65;
72
+ remainingMoovContent[psshOffsets[0] + 7] = 0x65;
73
+ }
74
+ remainingMoovContent = remainingMoovContent.subarray(psshOffsets[2]);
71
75
  }
72
76
  return psshBoxes;
73
77
  }
@@ -15,9 +15,9 @@
15
15
  */
16
16
 
17
17
  import extractCompleteChunks, { extractInitSegment } from "./extract_complete_chunks";
18
+ import extractPssh, { getPsshSystemID } from "./extract_pssh";
18
19
  import findCompleteBox from "./find_complete_box";
19
20
  import removeDolbyVisionConfigData from "./remove_dolby_vision_config_data";
20
- import takePSSHOut, { getPsshSystemID } from "./take_pssh_out";
21
21
 
22
22
  export { extractInitSegment };
23
23
  export { createBox, createBoxWithChildren } from "./create_box";
@@ -44,5 +44,5 @@ export {
44
44
  findCompleteBox,
45
45
  getPsshSystemID,
46
46
  removeDolbyVisionConfigData,
47
- takePSSHOut,
47
+ extractPssh,
48
48
  };
@@ -7,7 +7,7 @@ the default JS-based one, especially on very large (multiple megabytes) MPDs.
7
7
 
8
8
  ### How Manifest parsing works in the RxPlayer
9
9
 
10
- In the RxPlayer every Manifest parser output the same final Manifest format which follow
10
+ In the RxPlayer every Manifest parser outputs the same final Manifest format which follows
11
11
  the same structure regardless of the transport protocol used (e.g. DASH, Smooth etc.).
12
12
 
13
13
  For the MPD (DASH's Manifest format), this transformation (from an XML to that final
@@ -30,7 +30,7 @@ XML format in JavaScript.
30
30
  Before the DASH-WASM parser, we only had the JavaScript parser, which relied on the
31
31
  browser's DOM APIs (e.g. `DOMParser`).
32
32
 
33
- This parser works fine but we found that its performance was really poor when encoutering
33
+ This parser works fine but we found that its performance was really poor when encountering
34
34
  huge MPDs (several MBs), that we're dealing with at Canal+ on a regular basis. Usually
35
35
  those problematic MPDs have several gigantic `<SegmentTimeline>` elements that takes a lot
36
36
  of time to parse.
@@ -39,11 +39,11 @@ After multiple tests, profiling and improvements, it appeared that the issue had
39
39
  with XML parsing and the DOM APIs (regarding the speed of the parsing operation, but also
40
40
  some stability issues most likely related to garbage collection pressure).
41
41
 
42
- Moreover, on some embedded devices, this operation could take several seconds. This leaded
43
- us to try to implement a parser running in a WebWorker (to avoid blocking the main thread,
42
+ Moreover, on some embedded devices, this operation could take several seconds. This led us
43
+ to try to implement a parser running in a WebWorker (to avoid blocking the main thread,
44
44
  which is also handling the user interface).
45
45
 
46
- As no DOM API are available in a WebWorker, we had to re-define the XML parsing APIs. We
46
+ As no DOM APIs are available in a WebWorker, we had to re-define the XML parsing APIs. We
47
47
  first opted for a JavaScript library, yet found performance in our initial tests to be
48
48
  subpar. We ended up trying with WebAssembly instead.
49
49
 
@@ -82,7 +82,7 @@ In the context of the RxPlayer, we only use it for optimization reasons, when we
82
82
  that switching the DASH MPD parser to WebAssembly has a high impact in terms of
83
83
  performance when compared to the equivalent JavaScript code.
84
84
 
85
- ### Where does the DASH-WASM parser fits into this
85
+ ### Where does the DASH-WASM parser fit into this
86
86
 
87
87
  The DASH-WASM MPD parser only does the first step of transforming the initial XML format
88
88
  into the "intermediate representation", by using WebAssembly.
@@ -111,7 +111,7 @@ This logic was written as such because:
111
111
 
112
112
  ### Directories
113
113
 
114
- The DASH-WASM parser comes into part:
114
+ The DASH-WASM parser comes in two parts:
115
115
 
116
116
  - the Rust part, written in the `rs` directory, that browses the XML and convert values to
117
117
  the right format.
@@ -142,7 +142,7 @@ Currently, the DASH-WASM parser parses in one go the XML.
142
142
  If the XML element encountered is recognized, it will call a JavaScript callback with
143
143
  the right number, to signal that this element has been encountered.
144
144
 
145
- 4. This callback, registered by the TypeScript code, begin to create the object
145
+ 4. This callback, registered by the TypeScript code, begins to create the object
146
146
  corresponding to that element and update some callbacks called by Rust so that new
147
147
  elements and attributes are considered as part of this element.
148
148
 
@@ -181,7 +181,7 @@ preferable for any reason, don't hesitate to propose a change (through an issue
181
181
 
182
182
  ### Details on FFI
183
183
 
184
- Technically, some data and function calls needs to cross the language boundaries between
184
+ Technically, some data and function calls need to cross the language boundaries between
185
185
  the compiled JavaScript and WebAssembly code.
186
186
 
187
187
  On the JavaScript/TypeScript-side, everything stays relatively simple, with few