rx-player 4.3.0-dev.2025012900 → 4.3.0-dev.2025030400

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 (372) hide show
  1. package/CHANGELOG.md +10 -2
  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/browser_compatibility_types.d.ts +32 -13
  8. package/dist/commonjs/compat/browser_compatibility_types.d.ts.map +1 -1
  9. package/dist/commonjs/compat/browser_compatibility_types.js +12 -32
  10. package/dist/commonjs/compat/eme/close_session.d.ts +2 -2
  11. package/dist/commonjs/compat/eme/close_session.d.ts.map +1 -1
  12. package/dist/commonjs/compat/eme/custom_key_system_access.d.ts +4 -9
  13. package/dist/commonjs/compat/eme/custom_key_system_access.d.ts.map +1 -1
  14. package/dist/commonjs/compat/eme/custom_media_keys/ie11_media_keys.d.ts +5 -6
  15. package/dist/commonjs/compat/eme/custom_media_keys/ie11_media_keys.d.ts.map +1 -1
  16. package/dist/commonjs/compat/eme/custom_media_keys/ie11_media_keys.js +6 -4
  17. package/dist/commonjs/compat/eme/custom_media_keys/index.d.ts +0 -2
  18. package/dist/commonjs/compat/eme/custom_media_keys/index.d.ts.map +1 -1
  19. package/dist/commonjs/compat/eme/custom_media_keys/moz_media_keys_constructor.d.ts +4 -5
  20. package/dist/commonjs/compat/eme/custom_media_keys/moz_media_keys_constructor.d.ts.map +1 -1
  21. package/dist/commonjs/compat/eme/custom_media_keys/old_webkit_media_keys.d.ts +5 -6
  22. package/dist/commonjs/compat/eme/custom_media_keys/old_webkit_media_keys.d.ts.map +1 -1
  23. package/dist/commonjs/compat/eme/custom_media_keys/old_webkit_media_keys.js +1 -1
  24. package/dist/commonjs/compat/eme/custom_media_keys/webkit_media_keys.d.ts +5 -11
  25. package/dist/commonjs/compat/eme/custom_media_keys/webkit_media_keys.d.ts.map +1 -1
  26. package/dist/commonjs/compat/eme/custom_media_keys/webkit_media_keys.js +2 -2
  27. package/dist/commonjs/compat/eme/eme-api-implementation.d.ts +5 -6
  28. package/dist/commonjs/compat/eme/eme-api-implementation.d.ts.map +1 -1
  29. package/dist/commonjs/compat/eme/eme-api-implementation.js +1 -0
  30. package/dist/commonjs/compat/eme/generate_key_request.d.ts +2 -2
  31. package/dist/commonjs/compat/eme/generate_key_request.d.ts.map +1 -1
  32. package/dist/commonjs/compat/eme/get_init_data.d.ts +2 -2
  33. package/dist/commonjs/compat/eme/get_init_data.d.ts.map +1 -1
  34. package/dist/commonjs/compat/eme/index.d.ts +1 -3
  35. package/dist/commonjs/compat/eme/index.d.ts.map +1 -1
  36. package/dist/commonjs/compat/eme/load_session.d.ts +2 -2
  37. package/dist/commonjs/compat/eme/load_session.d.ts.map +1 -1
  38. package/dist/commonjs/compat/eme/set_media_keys.d.ts +2 -3
  39. package/dist/commonjs/compat/eme/set_media_keys.d.ts.map +1 -1
  40. package/dist/commonjs/compat/event_listeners.d.ts +2 -3
  41. package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
  42. package/dist/commonjs/compat/remove_cue.d.ts +2 -1
  43. package/dist/commonjs/compat/remove_cue.d.ts.map +1 -1
  44. package/dist/commonjs/core/main/common/FreezeResolver.d.ts +176 -0
  45. package/dist/commonjs/core/main/common/FreezeResolver.d.ts.map +1 -0
  46. package/dist/commonjs/core/main/common/FreezeResolver.js +431 -0
  47. package/dist/commonjs/core/main/common/synchronize_sinks_on_observation.d.ts +11 -0
  48. package/dist/commonjs/core/main/common/synchronize_sinks_on_observation.d.ts.map +1 -0
  49. package/dist/commonjs/core/main/common/synchronize_sinks_on_observation.js +20 -0
  50. package/dist/commonjs/core/main/worker/content_preparer.d.ts +82 -5
  51. package/dist/commonjs/core/main/worker/content_preparer.d.ts.map +1 -1
  52. package/dist/commonjs/core/main/worker/content_preparer.js +83 -18
  53. package/dist/commonjs/core/main/worker/worker_main.d.ts.map +1 -1
  54. package/dist/commonjs/core/main/worker/worker_main.js +69 -14
  55. package/dist/commonjs/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  56. package/dist/commonjs/core/stream/adaptation/adaptation_stream.js +26 -4
  57. package/dist/commonjs/core/stream/orchestrator/stream_orchestrator.d.ts.map +1 -1
  58. package/dist/commonjs/default_config.d.ts +26 -0
  59. package/dist/commonjs/default_config.d.ts.map +1 -1
  60. package/dist/commonjs/default_config.js +26 -0
  61. package/dist/commonjs/main_thread/api/option_utils.d.ts +26 -0
  62. package/dist/commonjs/main_thread/api/option_utils.d.ts.map +1 -1
  63. package/dist/commonjs/main_thread/api/option_utils.js +5 -2
  64. package/dist/commonjs/main_thread/api/public_api.d.ts.map +1 -1
  65. package/dist/commonjs/main_thread/api/public_api.js +14 -12
  66. package/dist/commonjs/main_thread/api/utils.d.ts +1 -2
  67. package/dist/commonjs/main_thread/api/utils.d.ts.map +1 -1
  68. package/dist/commonjs/main_thread/api/utils.js +2 -3
  69. package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  70. package/dist/commonjs/main_thread/decrypt/create_or_load_session.d.ts +2 -2
  71. package/dist/commonjs/main_thread/decrypt/create_or_load_session.d.ts.map +1 -1
  72. package/dist/commonjs/main_thread/decrypt/create_session.d.ts +3 -3
  73. package/dist/commonjs/main_thread/decrypt/create_session.d.ts.map +1 -1
  74. package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts +3 -4
  75. package/dist/commonjs/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  76. package/dist/commonjs/main_thread/decrypt/get_media_keys.d.ts +3 -4
  77. package/dist/commonjs/main_thread/decrypt/get_media_keys.d.ts.map +1 -1
  78. package/dist/commonjs/main_thread/decrypt/session_events_listener.d.ts +2 -2
  79. package/dist/commonjs/main_thread/decrypt/session_events_listener.d.ts.map +1 -1
  80. package/dist/commonjs/main_thread/decrypt/set_server_certificate.d.ts +3 -3
  81. package/dist/commonjs/main_thread/decrypt/set_server_certificate.d.ts.map +1 -1
  82. package/dist/commonjs/main_thread/decrypt/utils/check_key_statuses.d.ts +2 -2
  83. package/dist/commonjs/main_thread/decrypt/utils/check_key_statuses.d.ts.map +1 -1
  84. package/dist/commonjs/main_thread/decrypt/utils/is_session_usable.d.ts +2 -2
  85. package/dist/commonjs/main_thread/decrypt/utils/is_session_usable.d.ts.map +1 -1
  86. package/dist/commonjs/main_thread/decrypt/utils/loaded_sessions_store.d.ts +10 -10
  87. package/dist/commonjs/main_thread/decrypt/utils/loaded_sessions_store.d.ts.map +1 -1
  88. package/dist/commonjs/main_thread/decrypt/utils/loaded_sessions_store.js +2 -2
  89. package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts +4 -4
  90. package/dist/commonjs/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -1
  91. package/dist/commonjs/main_thread/decrypt/utils/persistent_sessions_store.d.ts +5 -7
  92. package/dist/commonjs/main_thread/decrypt/utils/persistent_sessions_store.d.ts.map +1 -1
  93. package/dist/commonjs/main_thread/decrypt/utils/persistent_sessions_store.js +3 -5
  94. package/dist/commonjs/main_thread/decrypt/utils/server_certificate_store.d.ts +5 -5
  95. package/dist/commonjs/main_thread/decrypt/utils/server_certificate_store.d.ts.map +1 -1
  96. package/dist/commonjs/main_thread/init/directfile_content_initializer.js +1 -1
  97. package/dist/commonjs/main_thread/init/media_source_content_initializer.d.ts +6 -0
  98. package/dist/commonjs/main_thread/init/media_source_content_initializer.d.ts.map +1 -1
  99. package/dist/commonjs/main_thread/init/media_source_content_initializer.js +77 -25
  100. package/dist/commonjs/main_thread/init/multi_thread_content_initializer.d.ts +6 -0
  101. package/dist/commonjs/main_thread/init/multi_thread_content_initializer.d.ts.map +1 -1
  102. package/dist/commonjs/main_thread/init/multi_thread_content_initializer.js +8 -8
  103. package/dist/commonjs/main_thread/init/types.d.ts +3 -2
  104. package/dist/commonjs/main_thread/init/types.d.ts.map +1 -1
  105. package/dist/commonjs/main_thread/init/utils/create_core_playback_observer.d.ts +2 -0
  106. package/dist/commonjs/main_thread/init/utils/create_core_playback_observer.d.ts.map +1 -1
  107. package/dist/commonjs/main_thread/init/utils/create_core_playback_observer.js +1 -0
  108. package/dist/commonjs/main_thread/init/utils/get_loaded_reference.d.ts +1 -3
  109. package/dist/commonjs/main_thread/init/utils/get_loaded_reference.d.ts.map +1 -1
  110. package/dist/commonjs/main_thread/init/utils/get_loaded_reference.js +4 -5
  111. package/dist/commonjs/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
  112. package/dist/commonjs/main_thread/init/utils/rebuffering_controller.js +1 -13
  113. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts +1 -4
  114. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts.map +1 -1
  115. package/dist/commonjs/main_thread/init/utils/stream_events_emitter/stream_events_emitter.js +3 -5
  116. package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts +2 -2
  117. package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
  118. package/dist/commonjs/main_thread/tracks_store/tracks_store.js +16 -22
  119. package/dist/commonjs/manifest/classes/index.d.ts +2 -2
  120. package/dist/commonjs/manifest/classes/index.d.ts.map +1 -1
  121. package/dist/commonjs/manifest/classes/manifest.d.ts +17 -2
  122. package/dist/commonjs/manifest/classes/manifest.d.ts.map +1 -1
  123. package/dist/commonjs/manifest/classes/manifest.js +55 -12
  124. package/dist/commonjs/manifest/classes/representation.d.ts +9 -0
  125. package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
  126. package/dist/commonjs/manifest/classes/representation.js +1 -0
  127. package/dist/commonjs/manifest/index.d.ts +2 -2
  128. package/dist/commonjs/manifest/index.d.ts.map +1 -1
  129. package/dist/commonjs/manifest/utils.js +1 -1
  130. package/dist/commonjs/multithread_types.d.ts +8 -0
  131. package/dist/commonjs/multithread_types.d.ts.map +1 -1
  132. package/dist/commonjs/parsers/containers/isobmff/extract_complete_chunks.d.ts +1 -1
  133. package/dist/commonjs/parsers/containers/isobmff/extract_complete_chunks.js +1 -1
  134. package/dist/commonjs/parsers/manifest/dash/common/parse_adaptation_sets.js +1 -1
  135. package/dist/commonjs/playback_observer/media_element_playback_observer.d.ts.map +1 -1
  136. package/dist/commonjs/playback_observer/media_element_playback_observer.js +6 -4
  137. package/dist/commonjs/playback_observer/types.d.ts +2 -0
  138. package/dist/commonjs/playback_observer/types.d.ts.map +1 -1
  139. package/dist/commonjs/playback_observer/worker_playback_observer.d.ts +2 -0
  140. package/dist/commonjs/playback_observer/worker_playback_observer.d.ts.map +1 -1
  141. package/dist/commonjs/public_types.d.ts +14 -0
  142. package/dist/commonjs/public_types.d.ts.map +1 -1
  143. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.d.ts.map +1 -1
  144. package/dist/es2017/__GENERATED_CODE/embedded_dash_wasm.js +1 -1
  145. package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
  146. package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
  147. package/dist/es2017/compat/browser_compatibility_types.d.ts +32 -13
  148. package/dist/es2017/compat/browser_compatibility_types.d.ts.map +1 -1
  149. package/dist/es2017/compat/browser_compatibility_types.js +12 -32
  150. package/dist/es2017/compat/eme/close_session.d.ts +2 -2
  151. package/dist/es2017/compat/eme/close_session.d.ts.map +1 -1
  152. package/dist/es2017/compat/eme/custom_key_system_access.d.ts +4 -9
  153. package/dist/es2017/compat/eme/custom_key_system_access.d.ts.map +1 -1
  154. package/dist/es2017/compat/eme/custom_media_keys/ie11_media_keys.d.ts +5 -6
  155. package/dist/es2017/compat/eme/custom_media_keys/ie11_media_keys.d.ts.map +1 -1
  156. package/dist/es2017/compat/eme/custom_media_keys/ie11_media_keys.js +4 -4
  157. package/dist/es2017/compat/eme/custom_media_keys/index.d.ts +0 -2
  158. package/dist/es2017/compat/eme/custom_media_keys/index.d.ts.map +1 -1
  159. package/dist/es2017/compat/eme/custom_media_keys/moz_media_keys_constructor.d.ts +4 -5
  160. package/dist/es2017/compat/eme/custom_media_keys/moz_media_keys_constructor.d.ts.map +1 -1
  161. package/dist/es2017/compat/eme/custom_media_keys/old_webkit_media_keys.d.ts +5 -6
  162. package/dist/es2017/compat/eme/custom_media_keys/old_webkit_media_keys.d.ts.map +1 -1
  163. package/dist/es2017/compat/eme/custom_media_keys/old_webkit_media_keys.js +1 -1
  164. package/dist/es2017/compat/eme/custom_media_keys/webkit_media_keys.d.ts +5 -11
  165. package/dist/es2017/compat/eme/custom_media_keys/webkit_media_keys.d.ts.map +1 -1
  166. package/dist/es2017/compat/eme/custom_media_keys/webkit_media_keys.js +2 -2
  167. package/dist/es2017/compat/eme/eme-api-implementation.d.ts +5 -6
  168. package/dist/es2017/compat/eme/eme-api-implementation.d.ts.map +1 -1
  169. package/dist/es2017/compat/eme/eme-api-implementation.js +1 -0
  170. package/dist/es2017/compat/eme/generate_key_request.d.ts +2 -2
  171. package/dist/es2017/compat/eme/generate_key_request.d.ts.map +1 -1
  172. package/dist/es2017/compat/eme/get_init_data.d.ts +2 -2
  173. package/dist/es2017/compat/eme/get_init_data.d.ts.map +1 -1
  174. package/dist/es2017/compat/eme/index.d.ts +1 -3
  175. package/dist/es2017/compat/eme/index.d.ts.map +1 -1
  176. package/dist/es2017/compat/eme/load_session.d.ts +2 -2
  177. package/dist/es2017/compat/eme/load_session.d.ts.map +1 -1
  178. package/dist/es2017/compat/eme/set_media_keys.d.ts +2 -3
  179. package/dist/es2017/compat/eme/set_media_keys.d.ts.map +1 -1
  180. package/dist/es2017/compat/event_listeners.d.ts +2 -3
  181. package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
  182. package/dist/es2017/compat/remove_cue.d.ts +2 -1
  183. package/dist/es2017/compat/remove_cue.d.ts.map +1 -1
  184. package/dist/es2017/core/main/common/FreezeResolver.d.ts +176 -0
  185. package/dist/es2017/core/main/common/FreezeResolver.d.ts.map +1 -0
  186. package/dist/es2017/core/main/common/FreezeResolver.js +363 -0
  187. package/dist/es2017/core/main/common/synchronize_sinks_on_observation.d.ts +11 -0
  188. package/dist/es2017/core/main/common/synchronize_sinks_on_observation.d.ts.map +1 -0
  189. package/dist/es2017/core/main/common/synchronize_sinks_on_observation.js +17 -0
  190. package/dist/es2017/core/main/worker/content_preparer.d.ts +82 -5
  191. package/dist/es2017/core/main/worker/content_preparer.d.ts.map +1 -1
  192. package/dist/es2017/core/main/worker/content_preparer.js +82 -17
  193. package/dist/es2017/core/main/worker/worker_main.d.ts.map +1 -1
  194. package/dist/es2017/core/main/worker/worker_main.js +68 -14
  195. package/dist/es2017/core/stream/adaptation/adaptation_stream.d.ts.map +1 -1
  196. package/dist/es2017/core/stream/adaptation/adaptation_stream.js +24 -2
  197. package/dist/es2017/core/stream/orchestrator/stream_orchestrator.d.ts.map +1 -1
  198. package/dist/es2017/default_config.d.ts +26 -0
  199. package/dist/es2017/default_config.d.ts.map +1 -1
  200. package/dist/es2017/default_config.js +26 -0
  201. package/dist/es2017/main_thread/api/option_utils.d.ts +26 -0
  202. package/dist/es2017/main_thread/api/option_utils.d.ts.map +1 -1
  203. package/dist/es2017/main_thread/api/option_utils.js +4 -1
  204. package/dist/es2017/main_thread/api/public_api.d.ts.map +1 -1
  205. package/dist/es2017/main_thread/api/public_api.js +14 -12
  206. package/dist/es2017/main_thread/api/utils.d.ts +1 -2
  207. package/dist/es2017/main_thread/api/utils.d.ts.map +1 -1
  208. package/dist/es2017/main_thread/api/utils.js +2 -3
  209. package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
  210. package/dist/es2017/main_thread/decrypt/create_or_load_session.d.ts +2 -2
  211. package/dist/es2017/main_thread/decrypt/create_or_load_session.d.ts.map +1 -1
  212. package/dist/es2017/main_thread/decrypt/create_session.d.ts +3 -3
  213. package/dist/es2017/main_thread/decrypt/create_session.d.ts.map +1 -1
  214. package/dist/es2017/main_thread/decrypt/find_key_system.d.ts +3 -4
  215. package/dist/es2017/main_thread/decrypt/find_key_system.d.ts.map +1 -1
  216. package/dist/es2017/main_thread/decrypt/get_media_keys.d.ts +3 -4
  217. package/dist/es2017/main_thread/decrypt/get_media_keys.d.ts.map +1 -1
  218. package/dist/es2017/main_thread/decrypt/session_events_listener.d.ts +2 -2
  219. package/dist/es2017/main_thread/decrypt/session_events_listener.d.ts.map +1 -1
  220. package/dist/es2017/main_thread/decrypt/set_server_certificate.d.ts +3 -3
  221. package/dist/es2017/main_thread/decrypt/set_server_certificate.d.ts.map +1 -1
  222. package/dist/es2017/main_thread/decrypt/utils/check_key_statuses.d.ts +2 -2
  223. package/dist/es2017/main_thread/decrypt/utils/check_key_statuses.d.ts.map +1 -1
  224. package/dist/es2017/main_thread/decrypt/utils/is_session_usable.d.ts +2 -2
  225. package/dist/es2017/main_thread/decrypt/utils/is_session_usable.d.ts.map +1 -1
  226. package/dist/es2017/main_thread/decrypt/utils/loaded_sessions_store.d.ts +10 -10
  227. package/dist/es2017/main_thread/decrypt/utils/loaded_sessions_store.d.ts.map +1 -1
  228. package/dist/es2017/main_thread/decrypt/utils/loaded_sessions_store.js +2 -2
  229. package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts +4 -4
  230. package/dist/es2017/main_thread/decrypt/utils/media_keys_attacher.d.ts.map +1 -1
  231. package/dist/es2017/main_thread/decrypt/utils/persistent_sessions_store.d.ts +5 -7
  232. package/dist/es2017/main_thread/decrypt/utils/persistent_sessions_store.d.ts.map +1 -1
  233. package/dist/es2017/main_thread/decrypt/utils/persistent_sessions_store.js +3 -5
  234. package/dist/es2017/main_thread/decrypt/utils/server_certificate_store.d.ts +5 -5
  235. package/dist/es2017/main_thread/decrypt/utils/server_certificate_store.d.ts.map +1 -1
  236. package/dist/es2017/main_thread/init/directfile_content_initializer.js +1 -1
  237. package/dist/es2017/main_thread/init/media_source_content_initializer.d.ts +6 -0
  238. package/dist/es2017/main_thread/init/media_source_content_initializer.d.ts.map +1 -1
  239. package/dist/es2017/main_thread/init/media_source_content_initializer.js +77 -26
  240. package/dist/es2017/main_thread/init/multi_thread_content_initializer.d.ts +6 -0
  241. package/dist/es2017/main_thread/init/multi_thread_content_initializer.d.ts.map +1 -1
  242. package/dist/es2017/main_thread/init/multi_thread_content_initializer.js +8 -8
  243. package/dist/es2017/main_thread/init/types.d.ts +3 -2
  244. package/dist/es2017/main_thread/init/types.d.ts.map +1 -1
  245. package/dist/es2017/main_thread/init/utils/create_core_playback_observer.d.ts +2 -0
  246. package/dist/es2017/main_thread/init/utils/create_core_playback_observer.d.ts.map +1 -1
  247. package/dist/es2017/main_thread/init/utils/create_core_playback_observer.js +1 -0
  248. package/dist/es2017/main_thread/init/utils/get_loaded_reference.d.ts +1 -3
  249. package/dist/es2017/main_thread/init/utils/get_loaded_reference.d.ts.map +1 -1
  250. package/dist/es2017/main_thread/init/utils/get_loaded_reference.js +4 -5
  251. package/dist/es2017/main_thread/init/utils/rebuffering_controller.d.ts.map +1 -1
  252. package/dist/es2017/main_thread/init/utils/rebuffering_controller.js +1 -13
  253. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts +1 -4
  254. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.d.ts.map +1 -1
  255. package/dist/es2017/main_thread/init/utils/stream_events_emitter/stream_events_emitter.js +3 -5
  256. package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts +2 -2
  257. package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
  258. package/dist/es2017/main_thread/tracks_store/tracks_store.js +16 -22
  259. package/dist/es2017/manifest/classes/index.d.ts +2 -2
  260. package/dist/es2017/manifest/classes/index.d.ts.map +1 -1
  261. package/dist/es2017/manifest/classes/manifest.d.ts +17 -2
  262. package/dist/es2017/manifest/classes/manifest.d.ts.map +1 -1
  263. package/dist/es2017/manifest/classes/manifest.js +32 -0
  264. package/dist/es2017/manifest/classes/representation.d.ts +9 -0
  265. package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
  266. package/dist/es2017/manifest/classes/representation.js +1 -0
  267. package/dist/es2017/manifest/index.d.ts +2 -2
  268. package/dist/es2017/manifest/index.d.ts.map +1 -1
  269. package/dist/es2017/manifest/utils.js +1 -1
  270. package/dist/es2017/multithread_types.d.ts +8 -0
  271. package/dist/es2017/multithread_types.d.ts.map +1 -1
  272. package/dist/es2017/parsers/containers/isobmff/extract_complete_chunks.d.ts +1 -1
  273. package/dist/es2017/parsers/containers/isobmff/extract_complete_chunks.js +1 -1
  274. package/dist/es2017/parsers/manifest/dash/common/parse_adaptation_sets.js +1 -1
  275. package/dist/es2017/playback_observer/media_element_playback_observer.d.ts.map +1 -1
  276. package/dist/es2017/playback_observer/media_element_playback_observer.js +6 -4
  277. package/dist/es2017/playback_observer/types.d.ts +2 -0
  278. package/dist/es2017/playback_observer/types.d.ts.map +1 -1
  279. package/dist/es2017/playback_observer/worker_playback_observer.d.ts +2 -0
  280. package/dist/es2017/playback_observer/worker_playback_observer.d.ts.map +1 -1
  281. package/dist/es2017/public_types.d.ts +14 -0
  282. package/dist/es2017/public_types.d.ts.map +1 -1
  283. package/dist/mpd-parser.wasm +0 -0
  284. package/dist/rx-player.js +489 -191
  285. package/dist/rx-player.min.js +18 -18
  286. package/dist/worker.js +6 -6
  287. package/package.json +18 -18
  288. package/src/__GENERATED_CODE/embedded_dash_wasm.ts +1 -1
  289. package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
  290. package/src/compat/browser_compatibility_types.ts +45 -42
  291. package/src/compat/eme/close_session.ts +2 -4
  292. package/src/compat/eme/custom_key_system_access.ts +4 -11
  293. package/src/compat/eme/custom_media_keys/ie11_media_keys.ts +29 -23
  294. package/src/compat/eme/custom_media_keys/index.ts +0 -2
  295. package/src/compat/eme/custom_media_keys/moz_media_keys_constructor.ts +5 -9
  296. package/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +15 -20
  297. package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +28 -36
  298. package/src/compat/eme/eme-api-implementation.ts +16 -14
  299. package/src/compat/eme/generate_key_request.ts +2 -2
  300. package/src/compat/eme/get_init_data.ts +2 -2
  301. package/src/compat/eme/index.ts +1 -10
  302. package/src/compat/eme/load_session.ts +4 -10
  303. package/src/compat/eme/set_media_keys.ts +2 -3
  304. package/src/compat/event_listeners.ts +2 -2
  305. package/src/compat/remove_cue.ts +11 -4
  306. package/src/core/main/common/FreezeResolver.ts +584 -0
  307. package/src/core/main/common/synchronize_sinks_on_observation.ts +22 -0
  308. package/src/core/main/worker/content_preparer.ts +112 -24
  309. package/src/core/main/worker/worker_main.ts +90 -13
  310. package/src/core/stream/adaptation/adaptation_stream.ts +38 -4
  311. package/src/core/stream/orchestrator/stream_orchestrator.ts +2 -6
  312. package/src/default_config.ts +27 -0
  313. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/DRMInfos.test.ts +3 -3
  314. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/HDCPPolicy.test.ts +2 -2
  315. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/decodingInfos.test.ts +4 -4
  316. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/mediaContentType.test.ts +2 -2
  317. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/mediaDisplayInfos.test.ts +1 -1
  318. package/src/main_thread/api/__tests__/option_utils.test.ts +3 -0
  319. package/src/main_thread/api/option_utils.ts +30 -0
  320. package/src/main_thread/api/public_api.ts +16 -12
  321. package/src/main_thread/api/utils.ts +1 -3
  322. package/src/main_thread/decrypt/__tests__/__global__/media_key_system_access.test.ts +2 -2
  323. package/src/main_thread/decrypt/content_decryptor.ts +9 -8
  324. package/src/main_thread/decrypt/create_or_load_session.ts +3 -3
  325. package/src/main_thread/decrypt/create_session.ts +3 -3
  326. package/src/main_thread/decrypt/find_key_system.ts +5 -3
  327. package/src/main_thread/decrypt/get_media_keys.ts +9 -6
  328. package/src/main_thread/decrypt/session_events_listener.ts +3 -3
  329. package/src/main_thread/decrypt/set_server_certificate.ts +4 -4
  330. package/src/main_thread/decrypt/utils/check_key_statuses.ts +2 -2
  331. package/src/main_thread/decrypt/utils/is_session_usable.ts +2 -4
  332. package/src/main_thread/decrypt/utils/loaded_sessions_store.ts +15 -16
  333. package/src/main_thread/decrypt/utils/media_keys_attacher.ts +7 -7
  334. package/src/main_thread/decrypt/utils/persistent_sessions_store.ts +5 -7
  335. package/src/main_thread/decrypt/utils/server_certificate_store.ts +6 -12
  336. package/src/main_thread/init/directfile_content_initializer.ts +1 -1
  337. package/src/main_thread/init/media_source_content_initializer.ts +98 -36
  338. package/src/main_thread/init/multi_thread_content_initializer.ts +14 -15
  339. package/src/main_thread/init/types.ts +3 -2
  340. package/src/main_thread/init/utils/create_core_playback_observer.ts +3 -0
  341. package/src/main_thread/init/utils/get_loaded_reference.ts +3 -6
  342. package/src/main_thread/init/utils/rebuffering_controller.ts +2 -24
  343. package/src/main_thread/init/utils/stream_events_emitter/stream_events_emitter.ts +3 -7
  344. package/src/main_thread/tracks_store/tracks_store.ts +16 -26
  345. package/src/manifest/classes/__tests__/representation.test.ts +16 -0
  346. package/src/manifest/classes/index.ts +2 -2
  347. package/src/manifest/classes/manifest.ts +48 -4
  348. package/src/manifest/classes/representation.ts +10 -0
  349. package/src/manifest/index.ts +2 -2
  350. package/src/manifest/utils.ts +1 -1
  351. package/src/multithread_types.ts +8 -0
  352. package/src/parsers/containers/isobmff/extract_complete_chunks.ts +1 -1
  353. package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +1 -1
  354. package/src/playback_observer/media_element_playback_observer.ts +14 -24
  355. package/src/playback_observer/types.ts +2 -0
  356. package/src/playback_observer/worker_playback_observer.ts +2 -0
  357. package/src/public_types.ts +17 -0
  358. package/src/utils/__tests__/logger.test.ts +44 -60
  359. package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts +0 -48
  360. package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts.map +0 -1
  361. package/dist/commonjs/compat/eme/custom_media_keys/types.js +0 -17
  362. package/dist/commonjs/core/main/common/DecipherabilityFreezeDetector.d.ts +0 -80
  363. package/dist/commonjs/core/main/common/DecipherabilityFreezeDetector.d.ts.map +0 -1
  364. package/dist/commonjs/core/main/common/DecipherabilityFreezeDetector.js +0 -127
  365. package/dist/es2017/compat/eme/custom_media_keys/types.d.ts +0 -48
  366. package/dist/es2017/compat/eme/custom_media_keys/types.d.ts.map +0 -1
  367. package/dist/es2017/compat/eme/custom_media_keys/types.js +0 -16
  368. package/dist/es2017/core/main/common/DecipherabilityFreezeDetector.d.ts +0 -80
  369. package/dist/es2017/core/main/common/DecipherabilityFreezeDetector.d.ts.map +0 -1
  370. package/dist/es2017/core/main/common/DecipherabilityFreezeDetector.js +0 -91
  371. package/src/compat/eme/custom_media_keys/types.ts +0 -66
  372. package/src/core/main/common/DecipherabilityFreezeDetector.ts +0 -147
@@ -0,0 +1,584 @@
1
+ import { config } from "../../../experimental";
2
+ import log from "../../../log";
3
+ import type { IAdaptation, IPeriod, IRepresentation } from "../../../manifest";
4
+ import type {
5
+ IFreezingStatus,
6
+ IRebufferingStatus,
7
+ ObservationPosition,
8
+ } from "../../../playback_observer";
9
+ import getMonotonicTimeStamp from "../../../utils/monotonic_timestamp";
10
+ import type SegmentSinksStore from "../../segment_sinks";
11
+ import type { IBufferedChunk } from "../../segment_sinks";
12
+
13
+ /**
14
+ * "Freezing" is a complex situation indicating that playback is not advancing
15
+ * despite no valid reason for it not to.
16
+ *
17
+ * Technically, there's multiple scenarios in which the RxPlayer will consider
18
+ * the stream as "freezing" and try to fix it.
19
+ * One of those scenarios is when there's a
20
+ * `HTMLMediaElement.prototype.readyState` set to `1` (which is how the browser
21
+ * tells us that it doesn't have any data to play), despite the fact that
22
+ * there's actually data in the buffer.
23
+ *
24
+ * The `MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING` is the minimum
25
+ * buffer size in seconds after which we will suspect a "freezing" scenario if
26
+ * the `readyState` is still at `1`.
27
+ */
28
+ const MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING = 6;
29
+
30
+ /**
31
+ * The amount of milliseconds since a freeze was detected from which we consider
32
+ * that the freeze should be worked around: either by flushing buffers,
33
+ * reloading, or any other kind of strategies.
34
+ *
35
+ * Before that delay, will continue to wait to see if the browser succeeds to
36
+ * un-freeze by itself.
37
+ */
38
+ const FREEZING_FOR_TOO_LONG_DELAY = 4000;
39
+
40
+ /**
41
+ * To avoid handling freezes (e.g. "reloading" or "seeking") in a loop when
42
+ * things go wrong, we have a security delay in milliseconds, this
43
+ * `MINIMUM_TIME_BETWEEN_FREEZE_HANDLING` constant, which we'll await between
44
+ * un-freezing attempts.
45
+ */
46
+ const MINIMUM_TIME_BETWEEN_FREEZE_HANDLING = 6000;
47
+
48
+ /**
49
+ * We maintain here a short-term history of what segments have been played
50
+ * recently, to then implement heuristics detecting if a freeze was due to a
51
+ * particular quality or track.
52
+ *
53
+ * To avoid growing that history indefinitely in size, we only save data
54
+ * corresponding to the last `MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME`
55
+ * milliseconds from now.
56
+ */
57
+ const MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME = 60000;
58
+
59
+ /**
60
+ * Set when there is a freeze which seems to be specifically linked to a,
61
+ * or multiple, content's `Representation` despite no attribute of it
62
+ * indicating so (i.e. it is decodable and decipherable).
63
+ * In that case, the recommendation is to avoid playing those
64
+ * `Representation` at all.
65
+ */
66
+ export interface IRepresentationAvoidanceFreezeResolution {
67
+ type: "avoid-representations";
68
+ /** The `Representation` to avoid. */
69
+ value: Array<{
70
+ adaptation: IAdaptation;
71
+ period: IPeriod;
72
+ representation: IRepresentation;
73
+ }>;
74
+ }
75
+
76
+ /**
77
+ * Set when there is a freeze which seem to be fixable by just
78
+ * "flushing" the buffer, e.g. generally by just seeking to another,
79
+ * close, position.
80
+ */
81
+ export interface IFlushFreezeResolution {
82
+ type: "flush";
83
+ value: {
84
+ /**
85
+ * The relative position, when compared to the current playback
86
+ * position, we should be playing at after the flush.
87
+ */
88
+ relativeSeek: number;
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Set when there is a freeze which seem to be fixable by "reloading"
94
+ * the content: meaning re-creating a `MediaSource` and its associated
95
+ * buffers.
96
+ *
97
+ * This can for example be when the RxPlayer is playing undecipherable
98
+ * or undecodable Representation (e.g. because of some race condition),
99
+ * or when an unexplainable freeze might not be fixed by just a flush.
100
+ */
101
+ export interface IReloadFreezeResolution {
102
+ type: "reload";
103
+ value: null;
104
+ }
105
+
106
+ /** Describe a strategy that can be taken to un-freeze playback. */
107
+ export type IFreezeResolution =
108
+ | IRepresentationAvoidanceFreezeResolution
109
+ | IFlushFreezeResolution
110
+ | IReloadFreezeResolution;
111
+
112
+ /**
113
+ * Sometimes playback is stuck for no known reason, despite having data in
114
+ * buffers.
115
+ *
116
+ * This can be due to relatively valid cause: performance being slow on the
117
+ * device making the content slow to start up, decryption keys not being
118
+ * obtained / usable yet etc.
119
+ *
120
+ * Yet in many cases, this is abnormal and may lead to being stuck at the same
121
+ * position and video frame indefinitely.
122
+ *
123
+ * For those situations, we have a series of tricks and heuristic, which are
124
+ * implemented by the `FreezeResolver`.
125
+ *
126
+ * @class FreezeResolver
127
+ */
128
+ export default class FreezeResolver {
129
+ /** Contain information about segments contained in media buffers. */
130
+ private _segmentSinksStore: SegmentSinksStore;
131
+
132
+ /** Contains a short-term history of what content has been played recently. */
133
+ private _lastSegmentInfo: {
134
+ /** Playback history for the video data. */
135
+ video: IPlayedHistoryEntry[];
136
+ /** Playback history for the audio data. */
137
+ audio: IPlayedHistoryEntry[];
138
+ };
139
+
140
+ /**
141
+ * Monotonically-raising timestamp before which we will just ignore freezing
142
+ * situations.
143
+ *
144
+ * To avoid flushing/reloading in a loop, we ignore for some time playback
145
+ * measure before retrying to unstuck playback.
146
+ */
147
+ private _ignoreFreezeUntil: number | null;
148
+
149
+ /**
150
+ * Information on the last attempt to un-freeze playback by "flushing" buffers.
151
+ *
152
+ * `null` if we never attempted to flush buffers.
153
+ */
154
+ private _lastFlushAttempt: {
155
+ /** Monotonically-raising timestamp at the time when we attempted the flush. */
156
+ timestamp: number;
157
+ /** Playback position at which the flush was performed, in seconds. */
158
+ position: number;
159
+ } | null;
160
+
161
+ /**
162
+ * If set to something else than `null`, this is the timestamp at the time the
163
+ * `FreezeResolver` started to consider its decipherability-linked un-freezing
164
+ * logic.
165
+ *
166
+ * This is used as a time of reference: after enough time was spent from that
167
+ * timestamp, the `FreezeResolver` will attempt supplementary unfreezing
168
+ * strategies.
169
+ *
170
+ * When the `FreezeResolver` is not considering those decipherability-related
171
+ * strategies for now, it is set to `null`.
172
+ */
173
+ private _decipherabilityFreezeStartingTimestamp: number | null;
174
+
175
+ constructor(segmentSinksStore: SegmentSinksStore) {
176
+ this._segmentSinksStore = segmentSinksStore;
177
+ this._decipherabilityFreezeStartingTimestamp = null;
178
+ this._ignoreFreezeUntil = null;
179
+ this._lastFlushAttempt = null;
180
+ this._lastSegmentInfo = {
181
+ audio: [],
182
+ video: [],
183
+ };
184
+ }
185
+
186
+ /**
187
+ * Check that playback is not freezing, and if it is, return a solution that
188
+ * should be attempted to unfreeze it.
189
+ *
190
+ * Returns `null` either when there's no freeze happening or if there's one
191
+ * but there's nothing we should do about it yet.
192
+ *
193
+ * Refer to the returned type's definition for more information.
194
+ *
195
+ * @param {Object} observation - The last playback observation produced, it
196
+ * has to be recent (just triggered for example).
197
+ * @returns {Object|null}
198
+ */
199
+ public onNewObservation(
200
+ observation: IFreezeResolverObservation,
201
+ ): IFreezeResolution | null {
202
+ const now = getMonotonicTimeStamp();
203
+ this._addPositionToHistory(observation, now);
204
+
205
+ if (this._ignoreFreezeUntil !== null && now < this._ignoreFreezeUntil) {
206
+ return null;
207
+ }
208
+ this._ignoreFreezeUntil = null;
209
+
210
+ const {
211
+ UNFREEZING_SEEK_DELAY,
212
+ UNFREEZING_DELTA_POSITION,
213
+ FREEZING_FLUSH_FAILURE_DELAY,
214
+ } = config.getCurrent();
215
+ const { readyState, rebuffering, freezing, fullyLoaded } = observation;
216
+
217
+ const freezingPosition = observation.position.getPolled();
218
+ const bufferGap = normalizeBufferGap(observation.bufferGap);
219
+
220
+ /** If set to `true`, we consider playback "frozen" */
221
+ const isFrozen =
222
+ freezing !== null ||
223
+ // When rebuffering, `freezing` might be not set as we're actively pausing
224
+ // playback. Yet, rebuffering occurences can also be abnormal, such as
225
+ // when enough buffer is constructed but with a low readyState (those are
226
+ // generally decryption issues).
227
+ (rebuffering !== null &&
228
+ readyState === 1 &&
229
+ (bufferGap >= MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING ||
230
+ fullyLoaded));
231
+
232
+ if (!isFrozen) {
233
+ this._decipherabilityFreezeStartingTimestamp = null;
234
+ return null;
235
+ }
236
+
237
+ const freezingTs = freezing?.timestamp ?? rebuffering?.timestamp ?? null;
238
+ log.info("FR: Freeze detected", freezingTs, now - (freezingTs ?? now));
239
+
240
+ /**
241
+ * If `true`, we recently tried to "flush" to unstuck playback but playback
242
+ * is still stuck
243
+ */
244
+ const recentFlushAttemptFailed =
245
+ this._lastFlushAttempt !== null &&
246
+ now - this._lastFlushAttempt.timestamp < FREEZING_FLUSH_FAILURE_DELAY.MAXIMUM &&
247
+ now - this._lastFlushAttempt.timestamp >= FREEZING_FLUSH_FAILURE_DELAY.MINIMUM &&
248
+ Math.abs(freezingPosition - this._lastFlushAttempt.position) <
249
+ FREEZING_FLUSH_FAILURE_DELAY.POSITION_DELTA;
250
+
251
+ if (recentFlushAttemptFailed) {
252
+ const secondUnfreezeStrat = this._getStrategyIfFlushingFails(freezingPosition);
253
+ this._decipherabilityFreezeStartingTimestamp = null;
254
+ this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
255
+ return secondUnfreezeStrat;
256
+ }
257
+
258
+ const decipherabilityFreezeStrat = this._checkForDecipherabilityRelatedFreeze(
259
+ observation,
260
+ now,
261
+ );
262
+ if (decipherabilityFreezeStrat !== null) {
263
+ return decipherabilityFreezeStrat;
264
+ }
265
+
266
+ if (freezingTs !== null && now - freezingTs > UNFREEZING_SEEK_DELAY) {
267
+ this._lastFlushAttempt = {
268
+ timestamp: now,
269
+ position: freezingPosition + UNFREEZING_DELTA_POSITION,
270
+ };
271
+ log.debug("FR: trying to flush to un-freeze");
272
+
273
+ this._decipherabilityFreezeStartingTimestamp = null;
274
+ this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
275
+ return {
276
+ type: "flush",
277
+ value: { relativeSeek: UNFREEZING_DELTA_POSITION },
278
+ };
279
+ }
280
+ return null;
281
+ }
282
+
283
+ /**
284
+ * Performs decipherability-related checks if it makes sense.
285
+ *
286
+ * If decipherability-related checks have been performed **AND** an
287
+ * un-freezing strategy has been selected by this method, then return
288
+ * an object describing this wanted unfreezing strategy.
289
+ *
290
+ * If this method decides to take no action for now, it returns `null`.
291
+ * @param {Object} observation - playback observation that has just been
292
+ * performed.
293
+ * @param {number} now - Monotonically-raising timestamp for the current
294
+ * time.
295
+ * @returns {Object|null}
296
+ */
297
+ private _checkForDecipherabilityRelatedFreeze(
298
+ observation: IFreezeResolverObservation,
299
+ now: number,
300
+ ): IFreezeResolution | null {
301
+ const { readyState, rebuffering, freezing, fullyLoaded } = observation;
302
+ const bufferGap = normalizeBufferGap(observation.bufferGap);
303
+ const rebufferingForTooLong =
304
+ rebuffering !== null && now - rebuffering.timestamp > FREEZING_FOR_TOO_LONG_DELAY;
305
+ const frozenForTooLong =
306
+ freezing !== null && now - freezing.timestamp > FREEZING_FOR_TOO_LONG_DELAY;
307
+
308
+ const hasDecipherabilityFreezePotential =
309
+ (rebufferingForTooLong || frozenForTooLong) &&
310
+ (bufferGap >= MINIMUM_BUFFER_GAP_AT_READY_STATE_1_BEFORE_FREEZING || fullyLoaded) &&
311
+ readyState <= 1;
312
+
313
+ if (!hasDecipherabilityFreezePotential) {
314
+ this._decipherabilityFreezeStartingTimestamp = null;
315
+ } else if (this._decipherabilityFreezeStartingTimestamp === null) {
316
+ log.debug("FR: Start of a potential decipherability freeze detected");
317
+ this._decipherabilityFreezeStartingTimestamp = now;
318
+ }
319
+
320
+ const shouldHandleDecipherabilityFreeze =
321
+ this._decipherabilityFreezeStartingTimestamp !== null &&
322
+ getMonotonicTimeStamp() - this._decipherabilityFreezeStartingTimestamp >
323
+ FREEZING_FOR_TOO_LONG_DELAY;
324
+
325
+ let hasOnlyDecipherableSegments = true;
326
+ let isClear = true;
327
+ for (const ttype of ["audio", "video"] as const) {
328
+ const status = this._segmentSinksStore.getStatus(ttype);
329
+ if (status.type === "initialized") {
330
+ for (const segment of status.value.getLastKnownInventory()) {
331
+ const { representation } = segment.infos;
332
+ if (representation.decipherable === false) {
333
+ log.warn("FR: we have undecipherable segments left in the buffer, reloading");
334
+ this._decipherabilityFreezeStartingTimestamp = null;
335
+ this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
336
+ return { type: "reload", value: null };
337
+ } else if (representation.contentProtections !== undefined) {
338
+ isClear = false;
339
+ if (representation.decipherable !== true) {
340
+ hasOnlyDecipherableSegments = false;
341
+ }
342
+ }
343
+ }
344
+ }
345
+ }
346
+
347
+ if (shouldHandleDecipherabilityFreeze && !isClear && hasOnlyDecipherableSegments) {
348
+ log.warn(
349
+ "FR: we are frozen despite only having decipherable " +
350
+ "segments left in the buffer, reloading",
351
+ );
352
+ this._decipherabilityFreezeStartingTimestamp = null;
353
+ this._ignoreFreezeUntil = now + MINIMUM_TIME_BETWEEN_FREEZE_HANDLING;
354
+ return { type: "reload", value: null };
355
+ }
356
+ return null;
357
+ }
358
+
359
+ /**
360
+ * This method should only be called if a "flush" strategy has recently be
361
+ * taken to try to unfreeze playback yet playback is still frozen.
362
+ *
363
+ * It considers the current played content and returns a more-involved
364
+ * unfreezing strategy (most often reload-related) to try to unfree playback.
365
+ * @param {number} freezingPosition - The playback position at which we're
366
+ * currently frozen.
367
+ * @returns {Object}
368
+ */
369
+ private _getStrategyIfFlushingFails(freezingPosition: number): IFreezeResolution {
370
+ log.warn(
371
+ "FR: A recent flush seemed to have no effect on freeze, checking for transitions",
372
+ );
373
+
374
+ /** Contains Representation we might want to avoid after the following algorithm */
375
+ const toAvoid = [];
376
+
377
+ for (const ttype of ["audio", "video"] as const) {
378
+ const segmentList = this._lastSegmentInfo[ttype];
379
+ if (segmentList.length === 0) {
380
+ // There's no buffered segment for that type, go to next type
381
+ continue;
382
+ }
383
+
384
+ /** Played history information on the current segment we're stuck on. */
385
+ let currentSegmentEntry = segmentList[segmentList.length - 1];
386
+ if (currentSegmentEntry.segment === null) {
387
+ // No segment currently played for that given type, go to next type
388
+ continue;
389
+ }
390
+
391
+ /** Metadata on the segment currently being played. */
392
+ const currentSegment = currentSegmentEntry.segment;
393
+
394
+ /**
395
+ * Set to the first previous segment which is linked to a different
396
+ * Representation.
397
+ */
398
+ let previousRepresentationEntry: IPlayedHistoryEntry | undefined;
399
+
400
+ // Now find `previousRepresentationEntry` and `currentSegmentEntry`.
401
+ for (let i = segmentList.length - 2; i >= 0; i--) {
402
+ const segment = segmentList[i];
403
+ if (segment.segment === null) {
404
+ // Before the current segment, there was no segment being played
405
+ previousRepresentationEntry = segment;
406
+ break;
407
+ } else if (
408
+ segment.segment.infos.representation.uniqueId !==
409
+ currentSegment.infos.representation.uniqueId &&
410
+ currentSegmentEntry.timestamp - segment.timestamp < 5000
411
+ ) {
412
+ // Before the current segment, there was a segment of a different
413
+ // Representation being played
414
+ previousRepresentationEntry = segment;
415
+ break;
416
+ } else if (
417
+ segment.segment.start === currentSegment.start &&
418
+ // Ignore history entry concerning the same segment more than 3
419
+ // seconds of playback behind - we don't want to compare things
420
+ // that happended too long ago.
421
+ freezingPosition - segment.position < 3000
422
+ ) {
423
+ // We're still playing the last segment at that point, update it.
424
+ //
425
+ // (We may be playing, or be freezing, on the current segment for some
426
+ // time, this allows to consider a more precize timestamp at which we
427
+ // switched segments).
428
+ currentSegmentEntry = segment;
429
+ }
430
+ }
431
+
432
+ if (
433
+ previousRepresentationEntry === undefined ||
434
+ previousRepresentationEntry.segment === null
435
+ ) {
436
+ log.debug(
437
+ "FR: Freeze when beginning to play a content, try avoiding this quality",
438
+ );
439
+ toAvoid.push({
440
+ adaptation: currentSegment.infos.adaptation,
441
+ period: currentSegment.infos.period,
442
+ representation: currentSegment.infos.representation,
443
+ });
444
+ } else if (
445
+ currentSegment.infos.period.id !==
446
+ previousRepresentationEntry.segment.infos.period.id
447
+ ) {
448
+ log.debug("FR: Freeze when switching Period, reloading");
449
+ return { type: "reload", value: null };
450
+ } else if (
451
+ currentSegment.infos.representation.uniqueId !==
452
+ previousRepresentationEntry.segment.infos.representation.uniqueId
453
+ ) {
454
+ log.warn(
455
+ "FR: Freeze when switching Representation, avoiding",
456
+ currentSegment.infos.representation.bitrate,
457
+ );
458
+ toAvoid.push({
459
+ adaptation: currentSegment.infos.adaptation,
460
+ period: currentSegment.infos.period,
461
+ representation: currentSegment.infos.representation,
462
+ });
463
+ }
464
+ }
465
+
466
+ if (toAvoid.length > 0) {
467
+ return { type: "avoid-representations", value: toAvoid };
468
+ } else {
469
+ log.debug("FR: Reloading because flush doesn't work");
470
+ return { type: "reload", value: null };
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Add entry to `this._lastSegmentInfo` for the position that is currently
476
+ * played according to the given `observation`.
477
+ *
478
+ * @param {Object} observation
479
+ * @param {number} currentTimestamp
480
+ */
481
+ private _addPositionToHistory(
482
+ observation: IFreezeResolverObservation,
483
+ currentTimestamp: number,
484
+ ): void {
485
+ const position = observation.position.getPolled();
486
+ for (const ttype of ["audio", "video"] as const) {
487
+ const status = this._segmentSinksStore.getStatus(ttype);
488
+ if (status.type === "initialized") {
489
+ for (const segment of status.value.getLastKnownInventory()) {
490
+ if (
491
+ (segment.bufferedStart ?? segment.start) <= position &&
492
+ (segment.bufferedEnd ?? segment.end) > position
493
+ ) {
494
+ this._lastSegmentInfo[ttype].push({
495
+ segment,
496
+ position,
497
+ timestamp: currentTimestamp,
498
+ });
499
+ }
500
+ }
501
+ } else {
502
+ this._lastSegmentInfo[ttype].push({
503
+ segment: null,
504
+ position,
505
+ timestamp: currentTimestamp,
506
+ });
507
+ }
508
+ if (this._lastSegmentInfo[ttype].length > 100) {
509
+ const toRemove = this._lastSegmentInfo[ttype].length - 100;
510
+ this._lastSegmentInfo[ttype].splice(0, toRemove);
511
+ }
512
+
513
+ const removalTs = currentTimestamp - MAXIMUM_SEGMENT_HISTORY_RETENTION_TIME;
514
+ let i;
515
+ for (i = 0; i < this._lastSegmentInfo[ttype].length; i++) {
516
+ if (this._lastSegmentInfo[ttype][i].timestamp > removalTs) {
517
+ break;
518
+ }
519
+ }
520
+ if (i > 0) {
521
+ this._lastSegmentInfo[ttype].splice(0, i);
522
+ }
523
+ }
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Constructs a `bufferGap` value that is more usable than what the
529
+ * `PlaybackObserver` returns:
530
+ * - it cannot be `undefined`
531
+ * - its weird `Infinity` value is translated to the more explicit `0`.
532
+ * @param {number|undefined} bufferGap
533
+ * @returns {number}
534
+ */
535
+ function normalizeBufferGap(bufferGap: number | undefined): number {
536
+ return bufferGap !== undefined && isFinite(bufferGap) ? bufferGap : 0;
537
+ }
538
+
539
+ /** Entry for the playback history maintained by the `FreezeResolver`. */
540
+ interface IPlayedHistoryEntry {
541
+ /**
542
+ * Segment and related information that seemed to be played at the
543
+ * associated timestamp and playback position.
544
+ *
545
+ * Note that this is only a guess and not a certainty.
546
+ */
547
+ segment: null | IBufferedChunk;
548
+ /**
549
+ * Playback position, in seconds, as seen on the `HTMLMediaElement`, at which
550
+ * we were playing.
551
+ */
552
+ position: number;
553
+ /** Monotonically-raising timestamp for that entry. */
554
+ timestamp: number;
555
+ }
556
+
557
+ /** Playback observation needed by the `FreezeResolver`. */
558
+ export interface IFreezeResolverObservation {
559
+ /** Current `readyState` value on the media element. */
560
+ readyState: number;
561
+ /**
562
+ * Set if the player is short on audio and/or video media data and is a such,
563
+ * rebuffering.
564
+ * `null` if not.
565
+ */
566
+ rebuffering: IRebufferingStatus | null;
567
+ /**
568
+ * Set if the player is frozen, that is, stuck in place for unknown reason.
569
+ * Note that this reason can be a valid one, such as a necessary license not
570
+ * being obtained yet.
571
+ *
572
+ * `null` if the player is not frozen.
573
+ */
574
+ freezing: IFreezingStatus | null;
575
+ /**
576
+ * Gap between `currentTime` and the next position with un-buffered data.
577
+ * `Infinity` if we don't have buffered data right now.
578
+ * `undefined` if we cannot determine the buffer gap.
579
+ */
580
+ bufferGap: number | undefined;
581
+ position: ObservationPosition;
582
+ /** If `true` the content is loaded until its maximum position. */
583
+ fullyLoaded: boolean;
584
+ }
@@ -0,0 +1,22 @@
1
+ import type { ICorePlaybackObservation } from "../../../main_thread/init/utils/create_core_playback_observer";
2
+ import type SegmentSinksStore from "../../segment_sinks";
3
+
4
+ /**
5
+ * Synchronize SegmentSinks with what has been buffered.
6
+ * @param {Object} observation - The just-received playback observation,
7
+ * including what has been buffered on lower-level buffers
8
+ * @param {Object} segmentSinksStore - Interface allowing to interact
9
+ * with `SegmentSink`s, so their inventory can be updated accordingly.
10
+ */
11
+ export default function synchronizeSegmentSinksOnObservation(
12
+ observation: ICorePlaybackObservation,
13
+ segmentSinksStore: SegmentSinksStore,
14
+ ): void {
15
+ // Synchronize SegmentSinks with what has been buffered.
16
+ ["video" as const, "audio" as const, "text" as const].forEach((tType) => {
17
+ const segmentSinkStatus = segmentSinksStore.getStatus(tType);
18
+ if (segmentSinkStatus.type === "initialized") {
19
+ segmentSinkStatus.value.synchronizeInventory(observation.buffered[tType] ?? []);
20
+ }
21
+ });
22
+ }