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
@@ -0,0 +1,707 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import type {
3
+ IManifest,
4
+ IPeriod,
5
+ IUpdatedRepresentationInfo,
6
+ } from "../../../../manifest";
7
+ import {
8
+ DummyAdaptation,
9
+ DummyManifest,
10
+ DummyPeriod,
11
+ DummyRepresentation,
12
+ createSegment,
13
+ } from "../../../../manifest/classes/__tests__/mocks";
14
+ import type { IManifestEvents } from "../../../../manifest/classes/manifest";
15
+ import type { IPeriodsUpdateResult } from "../../../../manifest/classes/update_periods";
16
+ import {
17
+ DummyObservationPosition,
18
+ makeReadyOnlyPlaybackObserver,
19
+ } from "../../../../playback_observer/__tests__/mocks";
20
+ import EventEmitter from "../../../../utils/event_emitter";
21
+ import SharedReference from "../../../../utils/reference";
22
+ import type { CancellationSignal } from "../../../../utils/task_canceller";
23
+ import TaskCanceller from "../../../../utils/task_canceller";
24
+ import { makeMockedClass } from "../../../../utils/test-utils";
25
+ import type { IRepresentationEstimator } from "../../../adaptive";
26
+ import type { SegmentQueueCreator } from "../../../fetchers";
27
+ import { ChunkStatus } from "../../../segment_sinks";
28
+ import type { IBufferedChunk, SegmentSink } from "../../../segment_sinks";
29
+ import type SegmentSinksStore from "../../../segment_sinks";
30
+ import { DummySegmentSink } from "../../../segment_sinks/__tests__/mocks";
31
+ import type {
32
+ IAdaptationChoice,
33
+ IWaitingMediaSourceReloadPayload,
34
+ } from "../../adaptation";
35
+ import type {
36
+ IPeriodStreamArguments,
37
+ IPeriodStreamCallbacks,
38
+ IPeriodStreamReadyPayload,
39
+ } from "../../period";
40
+ import type { IStreamStatusPayload } from "../../representation";
41
+ import StreamOrchestrator from "../stream_orchestrator";
42
+ import type {
43
+ IPeriodStreamClearedPayload,
44
+ IStreamOrchestratorCallbacks,
45
+ IStreamOrchestratorPlaybackObservation,
46
+ } from "../stream_orchestrator";
47
+
48
+ type IPeriodStreamFunction = (
49
+ args: IPeriodStreamArguments,
50
+ callbacks: IPeriodStreamCallbacks,
51
+ cancelSignal: CancellationSignal,
52
+ ) => void;
53
+
54
+ const { mockPeriodStream, queuedMicrotasks } = vi.hoisted(() => {
55
+ const microtasks: Array<() => void> = [];
56
+ return {
57
+ mockPeriodStream: vi.fn<IPeriodStreamFunction>(),
58
+ queuedMicrotasks: microtasks,
59
+ };
60
+ });
61
+
62
+ vi.mock("../../period", () => ({
63
+ default: mockPeriodStream,
64
+ }));
65
+
66
+ vi.mock("../../../../utils/queue_microtask", () => ({
67
+ default: (fn: () => void) => {
68
+ queuedMicrotasks.push(fn);
69
+ },
70
+ }));
71
+
72
+ const DummySegmentSinksStore = makeMockedClass<SegmentSinksStore>(
73
+ {
74
+ getBufferTypes: notImplemented("getBufferTypes"),
75
+ getNativeBufferTypes: notImplemented("getNativeBufferTypes"),
76
+ getStatus: notImplemented("getStatus"),
77
+ waitForUsableBuffers: notImplemented("waitForUsableBuffers"),
78
+ disableSegmentSink: notImplemented("disableSegmentSink"),
79
+ createSegmentSink: notImplemented("createSegmentSink"),
80
+ disposeSegmentSink: notImplemented("disposeSegmentSink"),
81
+ disposeAll: notImplemented("disposeAll"),
82
+ getSegmentSinksMetrics: notImplemented("getSegmentSinksMetrics"),
83
+ },
84
+ {},
85
+ );
86
+
87
+ const DummySegmentQueueCreator = makeMockedClass<SegmentQueueCreator>(
88
+ {
89
+ createSegmentQueue: notImplemented("createSegmentQueue"),
90
+ },
91
+ {},
92
+ );
93
+
94
+ describe("StreamOrchestrator", () => {
95
+ let manifest: IManifest;
96
+ let period: IPeriod;
97
+ let nextPeriod: IPeriod;
98
+ let manifestEventEmitter: TestManifestEventEmitter;
99
+ let playbackObserver: ReturnType<
100
+ typeof makeReadyOnlyPlaybackObserver<IStreamOrchestratorPlaybackObservation>
101
+ >;
102
+ let segmentSink: SegmentSink;
103
+ let removeBufferSpy: ReturnType<typeof vi.fn<SegmentSink["removeBuffer"]>>;
104
+ let segmentSinksStore: SegmentSinksStore;
105
+ let callbacks: IStreamOrchestratorCallbacks;
106
+ let periodStreamClearedSpy: ReturnType<
107
+ typeof vi.fn<(payload: IPeriodStreamClearedPayload) => void>
108
+ >;
109
+ let lockedStreamSpy: ReturnType<
110
+ typeof vi.fn<IStreamOrchestratorCallbacks["lockedStream"]>
111
+ >;
112
+ let needsMediaSourceReloadSpy: ReturnType<
113
+ typeof vi.fn<IStreamOrchestratorCallbacks["needsMediaSourceReload"]>
114
+ >;
115
+ let streamStatusUpdateSpy: ReturnType<
116
+ typeof vi.fn<IStreamOrchestratorCallbacks["streamStatusUpdate"]>
117
+ >;
118
+ let needsDecipherabilityFlushSpy: ReturnType<
119
+ typeof vi.fn<IStreamOrchestratorCallbacks["needsDecipherabilityFlush"]>
120
+ >;
121
+ let periodStreamCalls: IPeriodStreamCall[];
122
+ let orchestratorCanceller: TaskCanceller;
123
+ let representationEstimator: IRepresentationEstimator;
124
+ let segmentQueueCreator: SegmentQueueCreator;
125
+
126
+ beforeEach(() => {
127
+ queuedMicrotasks.length = 0;
128
+ mockPeriodStream.mockReset();
129
+ periodStreamCalls = [];
130
+
131
+ period = new DummyPeriod({ id: "period-1", start: 0, end: 10 });
132
+ nextPeriod = new DummyPeriod({ id: "period-2", start: 10, end: 20 });
133
+ manifestEventEmitter = new TestManifestEventEmitter();
134
+ manifest = new DummyManifest({
135
+ periods: [period, nextPeriod],
136
+ addEventListener: manifestEventEmitter.addEventListener.bind(manifestEventEmitter),
137
+ removeEventListener:
138
+ manifestEventEmitter.removeEventListener.bind(manifestEventEmitter),
139
+ });
140
+
141
+ vi.spyOn(manifest, "getPeriodForTime").mockImplementation((time) => {
142
+ if (time < 10) {
143
+ return period;
144
+ }
145
+ if (time < 20) {
146
+ return nextPeriod;
147
+ }
148
+ return undefined;
149
+ });
150
+ vi.spyOn(manifest, "getNextPeriod").mockReturnValue(undefined);
151
+
152
+ playbackObserver =
153
+ makeReadyOnlyPlaybackObserver<IStreamOrchestratorPlaybackObservation>({
154
+ position: new DummyObservationPosition({
155
+ getWanted: () => 5,
156
+ getPolled: () => 5,
157
+ }),
158
+ paused: { last: false, pending: undefined },
159
+ duration: 20,
160
+ readyState: 4,
161
+ speed: 1,
162
+ maximumPosition: 20,
163
+ buffered: { audio: null, video: null, text: null },
164
+ canStream: true,
165
+ });
166
+
167
+ removeBufferSpy = vi.fn<SegmentSink["removeBuffer"]>().mockResolvedValue([]);
168
+ segmentSink = new DummySegmentSink({
169
+ bufferType: "video",
170
+ getPendingOperations: () => [],
171
+ getLastKnownInventory: () => [makeBufferedChunk()],
172
+ removeBuffer: removeBufferSpy,
173
+ });
174
+
175
+ segmentSinksStore = new DummySegmentSinksStore({
176
+ getBufferTypes: () => ["video"],
177
+ getStatus: () => ({ type: "initialized", value: segmentSink }),
178
+ });
179
+
180
+ ({
181
+ callbacks,
182
+ periodStreamClearedSpy,
183
+ lockedStreamSpy,
184
+ needsMediaSourceReloadSpy,
185
+ streamStatusUpdateSpy,
186
+ needsDecipherabilityFlushSpy,
187
+ } = createCallbacks());
188
+ orchestratorCanceller = new TaskCanceller("test");
189
+ representationEstimator = () => {
190
+ throw new Error("representationEstimator not implemented");
191
+ };
192
+ segmentQueueCreator = new DummySegmentQueueCreator();
193
+ mockPeriodStream.mockImplementation((args, orchestratorCallbacks, signal) => {
194
+ periodStreamCalls.push({
195
+ args,
196
+ callbacks: orchestratorCallbacks,
197
+ streamCancellerSignal: signal,
198
+ });
199
+ });
200
+ });
201
+
202
+ afterEach(() => {
203
+ orchestratorCanceller.cancel("cleanup");
204
+ playbackObserver.reset();
205
+ vi.resetAllMocks();
206
+ });
207
+
208
+ it("should ignore stale decipherability restarts once a newer restart supersedes them", async () => {
209
+ startOrchestrator(
210
+ manifest,
211
+ period,
212
+ playbackObserver,
213
+ representationEstimator,
214
+ segmentSinksStore,
215
+ segmentQueueCreator,
216
+ callbacks,
217
+ orchestratorCanceller,
218
+ );
219
+ expect(mockPeriodStream).toHaveBeenCalledTimes(1);
220
+
221
+ const updates = [makeDecipherabilityUpdate()];
222
+ manifestEventEmitter.emit("decipherabilityUpdate", updates);
223
+ manifestEventEmitter.emit("decipherabilityUpdate", updates);
224
+ await Promise.resolve();
225
+ await Promise.resolve();
226
+
227
+ expect(queuedMicrotasks).toHaveLength(2);
228
+
229
+ while (queuedMicrotasks.length > 0) {
230
+ const task = queuedMicrotasks.shift();
231
+ task?.();
232
+ }
233
+ await Promise.resolve();
234
+
235
+ expect(mockPeriodStream).toHaveBeenCalledTimes(2);
236
+ });
237
+
238
+ it("should clear an already-created next PeriodStream when a manifest update removes it", () => {
239
+ let currentNextPeriod: IPeriod | null = nextPeriod;
240
+ vi.spyOn(manifest, "getPeriodAfter").mockImplementation((askedPeriod) => {
241
+ return askedPeriod.id === period.id ? currentNextPeriod : null;
242
+ });
243
+
244
+ startOrchestrator(
245
+ manifest,
246
+ period,
247
+ playbackObserver,
248
+ representationEstimator,
249
+ segmentSinksStore,
250
+ segmentQueueCreator,
251
+ callbacks,
252
+ orchestratorCanceller,
253
+ );
254
+ expect(periodStreamCalls).toHaveLength(1);
255
+
256
+ periodStreamCalls[0].callbacks.streamStatusUpdate(makeFinishedLoadingStatus(period));
257
+ expect(periodStreamCalls).toHaveLength(2);
258
+
259
+ currentNextPeriod = null;
260
+ manifestEventEmitter.emit(
261
+ "manifestUpdate",
262
+ makeManifestUpdateRemovingNextPeriod(nextPeriod),
263
+ );
264
+
265
+ expect(periodStreamCalls[1].streamCancellerSignal.isCancelled()).toBe(true);
266
+ expect(periodStreamClearedSpy).toHaveBeenCalledWith({
267
+ type: "video",
268
+ manifest,
269
+ period: nextPeriod,
270
+ });
271
+ });
272
+
273
+ it("should create one PeriodStream per available buffer type", () => {
274
+ segmentSinksStore = new DummySegmentSinksStore({
275
+ getBufferTypes: () => ["audio", "video"],
276
+ getStatus: () => ({ type: "initialized", value: segmentSink }),
277
+ });
278
+
279
+ startOrchestrator(
280
+ manifest,
281
+ period,
282
+ playbackObserver,
283
+ representationEstimator,
284
+ segmentSinksStore,
285
+ segmentQueueCreator,
286
+ callbacks,
287
+ orchestratorCanceller,
288
+ );
289
+
290
+ expect(periodStreamCalls).toHaveLength(2);
291
+ expect(periodStreamCalls.map((call) => call.args.bufferType)).toEqual([
292
+ "audio",
293
+ "video",
294
+ ]);
295
+ });
296
+
297
+ it("should lock waiting media source reloads for non-current periods", () => {
298
+ startOrchestrator(
299
+ manifest,
300
+ period,
301
+ playbackObserver,
302
+ representationEstimator,
303
+ segmentSinksStore,
304
+ segmentQueueCreator,
305
+ callbacks,
306
+ orchestratorCanceller,
307
+ );
308
+
309
+ periodStreamCalls[0].callbacks.waitingMediaSourceReload(
310
+ makeWaitingMediaSourceReloadPayload(nextPeriod, false),
311
+ );
312
+
313
+ expect(lockedStreamSpy).toHaveBeenCalledWith({
314
+ bufferType: "video",
315
+ period: nextPeriod,
316
+ });
317
+ expect(needsMediaSourceReloadSpy).not.toHaveBeenCalled();
318
+ });
319
+
320
+ it("should request a media source reload for the current period with bounded positions", () => {
321
+ startOrchestrator(
322
+ manifest,
323
+ period,
324
+ playbackObserver,
325
+ representationEstimator,
326
+ segmentSinksStore,
327
+ segmentQueueCreator,
328
+ callbacks,
329
+ orchestratorCanceller,
330
+ );
331
+ periodStreamCalls[0].callbacks.periodStreamReady(
332
+ makePeriodStreamReadyPayload(period),
333
+ );
334
+
335
+ periodStreamCalls[0].callbacks.waitingMediaSourceReload(
336
+ makeWaitingMediaSourceReloadPayload(period, true),
337
+ );
338
+
339
+ expect(needsMediaSourceReloadSpy).toHaveBeenCalledWith({
340
+ timeOffset: 12,
341
+ minimumPosition: period.start,
342
+ maximumPosition: period.end,
343
+ });
344
+ expect(lockedStreamSpy).not.toHaveBeenCalled();
345
+ });
346
+
347
+ it("should restart from the wanted period when playback goes out of the current period list", () => {
348
+ vi.spyOn(manifest, "getPeriodAfter").mockReturnValue(nextPeriod);
349
+
350
+ startOrchestrator(
351
+ manifest,
352
+ period,
353
+ playbackObserver,
354
+ representationEstimator,
355
+ segmentSinksStore,
356
+ segmentQueueCreator,
357
+ callbacks,
358
+ orchestratorCanceller,
359
+ );
360
+ periodStreamCalls[0].callbacks.periodStreamReady(
361
+ makePeriodStreamReadyPayload(period),
362
+ );
363
+
364
+ playbackObserver.emit(makeObservationAt(15));
365
+
366
+ expect(periodStreamClearedSpy).toHaveBeenCalledWith({
367
+ type: "video",
368
+ manifest,
369
+ period,
370
+ });
371
+ expect(periodStreamCalls[0].streamCancellerSignal.isCancelled()).toBe(true);
372
+ expect(periodStreamCalls).toHaveLength(2);
373
+ expect(periodStreamCalls[1].args.content.period).toBe(nextPeriod);
374
+ });
375
+
376
+ it("should destroy the prefetched next PeriodStream when the current one becomes active again", () => {
377
+ vi.spyOn(manifest, "getPeriodAfter").mockReturnValue(nextPeriod);
378
+
379
+ startOrchestrator(
380
+ manifest,
381
+ period,
382
+ playbackObserver,
383
+ representationEstimator,
384
+ segmentSinksStore,
385
+ segmentQueueCreator,
386
+ callbacks,
387
+ orchestratorCanceller,
388
+ );
389
+
390
+ periodStreamCalls[0].callbacks.streamStatusUpdate(makeFinishedLoadingStatus(period));
391
+ expect(periodStreamCalls).toHaveLength(2);
392
+
393
+ periodStreamCalls[0].callbacks.streamStatusUpdate(makeActiveStatus(period));
394
+
395
+ expect(periodStreamClearedSpy).toHaveBeenCalledWith({
396
+ type: "video",
397
+ manifest,
398
+ period: nextPeriod,
399
+ });
400
+ expect(periodStreamCalls[1].streamCancellerSignal.isCancelled()).toBe(true);
401
+ expect(streamStatusUpdateSpy).toHaveBeenLastCalledWith(makeActiveStatus(period));
402
+ });
403
+
404
+ it("should ask for media source reload when the current period is removed from the manifest", () => {
405
+ startOrchestrator(
406
+ manifest,
407
+ period,
408
+ playbackObserver,
409
+ representationEstimator,
410
+ segmentSinksStore,
411
+ segmentQueueCreator,
412
+ callbacks,
413
+ orchestratorCanceller,
414
+ );
415
+
416
+ manifestEventEmitter.emit("manifestUpdate", {
417
+ addedPeriods: [],
418
+ removedPeriods: [{ id: period.id, start: period.start, end: period.end }],
419
+ updatedPeriods: [],
420
+ });
421
+ expect(queuedMicrotasks).toHaveLength(1);
422
+
423
+ queuedMicrotasks.shift()?.();
424
+
425
+ expect(needsMediaSourceReloadSpy).toHaveBeenCalledWith({
426
+ timeOffset: 0,
427
+ minimumPosition: undefined,
428
+ maximumPosition: undefined,
429
+ });
430
+ });
431
+
432
+ it("should clear a PeriodStream once playback moves beyond its period end", () => {
433
+ const boundedPeriod = new DummyPeriod({
434
+ id: "period-bounded",
435
+ start: 0,
436
+ end: 10,
437
+ containsTime: () => false,
438
+ });
439
+ manifest = new DummyManifest({
440
+ periods: [boundedPeriod, nextPeriod],
441
+ addEventListener: manifestEventEmitter.addEventListener.bind(manifestEventEmitter),
442
+ removeEventListener:
443
+ manifestEventEmitter.removeEventListener.bind(manifestEventEmitter),
444
+ });
445
+ vi.spyOn(manifest, "getPeriodForTime").mockReturnValue(boundedPeriod);
446
+ vi.spyOn(manifest, "getNextPeriod").mockReturnValue(undefined);
447
+ vi.spyOn(manifest, "getPeriodAfter").mockReturnValue(nextPeriod);
448
+
449
+ startOrchestrator(
450
+ manifest,
451
+ boundedPeriod,
452
+ playbackObserver,
453
+ representationEstimator,
454
+ segmentSinksStore,
455
+ segmentQueueCreator,
456
+ callbacks,
457
+ orchestratorCanceller,
458
+ );
459
+
460
+ playbackObserver.emit(makeObservationAt(12));
461
+
462
+ expect(periodStreamClearedSpy).toHaveBeenCalledWith({
463
+ type: "video",
464
+ manifest,
465
+ period: boundedPeriod,
466
+ });
467
+ expect(periodStreamCalls[0].streamCancellerSignal.isCancelled()).toBe(true);
468
+ });
469
+
470
+ it("should remove undecipherable ranges, request a flush, and restart the stream", async () => {
471
+ startOrchestrator(
472
+ manifest,
473
+ period,
474
+ playbackObserver,
475
+ representationEstimator,
476
+ segmentSinksStore,
477
+ segmentQueueCreator,
478
+ callbacks,
479
+ orchestratorCanceller,
480
+ );
481
+ periodStreamCalls[0].callbacks.periodStreamReady(
482
+ makePeriodStreamReadyPayload(period),
483
+ );
484
+
485
+ manifestEventEmitter.emit("decipherabilityUpdate", [makeDecipherabilityUpdate()]);
486
+ await Promise.resolve();
487
+ expect(periodStreamClearedSpy).toHaveBeenCalledWith({
488
+ type: "video",
489
+ manifest,
490
+ period,
491
+ });
492
+ expect(removeBufferSpy).toHaveBeenCalledWith(0, 1);
493
+ expect(queuedMicrotasks).toHaveLength(1);
494
+
495
+ queuedMicrotasks.shift()?.();
496
+
497
+ expect(needsDecipherabilityFlushSpy).toHaveBeenCalledTimes(1);
498
+ expect(periodStreamCalls).toHaveLength(2);
499
+ expect(periodStreamCalls[1].args.content.period).toBe(period);
500
+ });
501
+ });
502
+
503
+ interface IPeriodStreamCall {
504
+ args: IPeriodStreamArguments;
505
+ callbacks: IPeriodStreamCallbacks;
506
+ streamCancellerSignal: TaskCanceller["signal"];
507
+ }
508
+
509
+ class TestManifestEventEmitter extends EventEmitter<IManifestEvents> {
510
+ public emit<TEventName extends keyof IManifestEvents>(
511
+ eventName: TEventName,
512
+ payload: IManifestEvents[TEventName],
513
+ ): void {
514
+ this.trigger(eventName, payload);
515
+ }
516
+ }
517
+
518
+ function startOrchestrator(
519
+ manifest: IManifest,
520
+ initialPeriod: IPeriod,
521
+ playbackObserver: ReturnType<
522
+ typeof makeReadyOnlyPlaybackObserver<IStreamOrchestratorPlaybackObservation>
523
+ >,
524
+ representationEstimator: IRepresentationEstimator,
525
+ segmentSinksStore: SegmentSinksStore,
526
+ segmentQueueCreator: SegmentQueueCreator,
527
+ callbacks: IStreamOrchestratorCallbacks,
528
+ orchestratorCanceller: TaskCanceller,
529
+ ): void {
530
+ StreamOrchestrator(
531
+ { manifest, initialPeriod },
532
+ playbackObserver.observer,
533
+ representationEstimator,
534
+ segmentSinksStore,
535
+ segmentQueueCreator,
536
+ {
537
+ drmSystemId: undefined,
538
+ enableFastSwitching: true,
539
+ onCodecSwitch: "continue",
540
+ wantedBufferAhead: new SharedReference(20),
541
+ maxVideoBufferSize: new SharedReference(20),
542
+ maxBufferAhead: new SharedReference(20),
543
+ maxBufferBehind: new SharedReference(20),
544
+ },
545
+ callbacks,
546
+ orchestratorCanceller.signal,
547
+ );
548
+ }
549
+
550
+ function createCallbacks(): {
551
+ callbacks: IStreamOrchestratorCallbacks;
552
+ periodStreamClearedSpy: ReturnType<
553
+ typeof vi.fn<(payload: IPeriodStreamClearedPayload) => void>
554
+ >;
555
+ lockedStreamSpy: ReturnType<typeof vi.fn<IStreamOrchestratorCallbacks["lockedStream"]>>;
556
+ needsMediaSourceReloadSpy: ReturnType<
557
+ typeof vi.fn<IStreamOrchestratorCallbacks["needsMediaSourceReload"]>
558
+ >;
559
+ streamStatusUpdateSpy: ReturnType<
560
+ typeof vi.fn<IStreamOrchestratorCallbacks["streamStatusUpdate"]>
561
+ >;
562
+ needsDecipherabilityFlushSpy: ReturnType<
563
+ typeof vi.fn<IStreamOrchestratorCallbacks["needsDecipherabilityFlush"]>
564
+ >;
565
+ } {
566
+ const periodStreamClearedSpy = vi.fn<(payload: IPeriodStreamClearedPayload) => void>();
567
+ const lockedStreamSpy = vi.fn<IStreamOrchestratorCallbacks["lockedStream"]>();
568
+ const needsMediaSourceReloadSpy =
569
+ vi.fn<IStreamOrchestratorCallbacks["needsMediaSourceReload"]>();
570
+ const streamStatusUpdateSpy =
571
+ vi.fn<IStreamOrchestratorCallbacks["streamStatusUpdate"]>();
572
+ const needsDecipherabilityFlushSpy =
573
+ vi.fn<IStreamOrchestratorCallbacks["needsDecipherabilityFlush"]>();
574
+ return {
575
+ callbacks: {
576
+ adaptationChange: vi.fn(),
577
+ bitrateEstimateChange: vi.fn(),
578
+ encryptionDataEncountered: vi.fn(),
579
+ error: vi.fn(),
580
+ inbandEvent: vi.fn(),
581
+ lockedStream: lockedStreamSpy,
582
+ manifestMightBeOufOfSync: vi.fn(),
583
+ needsBufferFlush: vi.fn(),
584
+ needsDecipherabilityFlush: needsDecipherabilityFlushSpy,
585
+ needsManifestRefresh: vi.fn(),
586
+ needsMediaSourceReload: needsMediaSourceReloadSpy,
587
+ periodStreamCleared: periodStreamClearedSpy,
588
+ periodStreamReady: vi.fn(),
589
+ representationChange: vi.fn(),
590
+ streamStatusUpdate: streamStatusUpdateSpy,
591
+ warning: vi.fn(),
592
+ },
593
+ periodStreamClearedSpy,
594
+ lockedStreamSpy,
595
+ needsMediaSourceReloadSpy,
596
+ streamStatusUpdateSpy,
597
+ needsDecipherabilityFlushSpy,
598
+ };
599
+ }
600
+
601
+ function makeFinishedLoadingStatus(period: IPeriod): IStreamStatusPayload {
602
+ return {
603
+ period,
604
+ bufferType: "video",
605
+ imminentDiscontinuity: null,
606
+ hasFinishedLoading: true,
607
+ isEmptyStream: false,
608
+ neededSegments: [],
609
+ position: period.start,
610
+ };
611
+ }
612
+
613
+ function makeActiveStatus(period: IPeriod): IStreamStatusPayload {
614
+ return {
615
+ period,
616
+ bufferType: "video",
617
+ imminentDiscontinuity: null,
618
+ hasFinishedLoading: false,
619
+ isEmptyStream: false,
620
+ neededSegments: [],
621
+ position: period.start,
622
+ };
623
+ }
624
+
625
+ function makePeriodStreamReadyPayload(period: IPeriod): IPeriodStreamReadyPayload {
626
+ return {
627
+ type: "video",
628
+ manifest: new DummyManifest(),
629
+ period,
630
+ adaptationRef: new SharedReference<IAdaptationChoice | null | undefined>(undefined),
631
+ };
632
+ }
633
+
634
+ function makeManifestUpdateRemovingNextPeriod(nextPeriod: IPeriod): IPeriodsUpdateResult {
635
+ return {
636
+ addedPeriods: [],
637
+ removedPeriods: [{ id: nextPeriod.id, start: nextPeriod.start, end: nextPeriod.end }],
638
+ updatedPeriods: [],
639
+ };
640
+ }
641
+
642
+ function makeObservationAt(position: number): IStreamOrchestratorPlaybackObservation {
643
+ return {
644
+ position: new DummyObservationPosition({
645
+ getWanted: () => position,
646
+ getPolled: () => position,
647
+ }),
648
+ paused: { last: false, pending: undefined },
649
+ duration: 20,
650
+ readyState: 4,
651
+ speed: 1,
652
+ maximumPosition: 20,
653
+ buffered: { audio: null, video: null, text: null },
654
+ canStream: true,
655
+ };
656
+ }
657
+
658
+ function makeDecipherabilityUpdate(): IUpdatedRepresentationInfo {
659
+ return {
660
+ manifest: new DummyManifest(),
661
+ adaptation: new DummyAdaptation({ id: "adaptation-1", type: "video" }),
662
+ period: new DummyPeriod({ id: "period-1", start: 0, end: 10 }),
663
+ representation: new DummyRepresentation({
664
+ id: "representation-1",
665
+ decipherable: false,
666
+ }),
667
+ };
668
+ }
669
+
670
+ function makeWaitingMediaSourceReloadPayload(
671
+ period: IPeriod,
672
+ stayInPeriod: boolean,
673
+ ): IWaitingMediaSourceReloadPayload {
674
+ return {
675
+ period,
676
+ bufferType: "video",
677
+ timeOffset: 12,
678
+ stayInPeriod,
679
+ };
680
+ }
681
+
682
+ function makeBufferedChunk(): IBufferedChunk {
683
+ return {
684
+ infos: {
685
+ period: new DummyPeriod({ id: "period-1", start: 0, end: 10 }),
686
+ adaptation: new DummyAdaptation({ id: "adaptation-1", type: "video" }),
687
+ representation: new DummyRepresentation({ id: "representation-1" }),
688
+ segment: createSegment({ time: 0, duration: 1, end: 1 }),
689
+ },
690
+ bufferedStart: 0,
691
+ bufferedEnd: 1,
692
+ start: 0,
693
+ end: 1,
694
+ insertionTs: 0,
695
+ chunkSize: 1,
696
+ precizeStart: true,
697
+ precizeEnd: true,
698
+ status: ChunkStatus.FullyLoaded,
699
+ splitted: false,
700
+ };
701
+ }
702
+
703
+ function notImplemented(name: string): () => never {
704
+ return () => {
705
+ throw new Error(`${name} not implemented`);
706
+ };
707
+ }