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
@@ -1,225 +1,226 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import configHandler from "../../../../config";
2
3
  import type { IAdaptation, IPeriod } from "../../../../manifest";
3
- import type { IReadOnlyPlaybackObserver } from "../../../../playback_observer";
4
- import type { SegmentSink } from "../../../segment_sinks";
5
- import { SegmentSinkOperation } from "../../../segment_sinks";
4
+ import {
5
+ DummyPeriod,
6
+ DummyAdaptation,
7
+ DummyRepresentation,
8
+ createSegment,
9
+ } from "../../../../manifest/classes/__tests__/mocks";
10
+ import {
11
+ makeReadyOnlyPlaybackObserver,
12
+ DummyObservationPosition,
13
+ } from "../../../../playback_observer/__tests__/mocks";
14
+ import SharedReference from "../../../../utils/reference";
15
+ import {
16
+ ChunkStatus,
17
+ SegmentSinkOperation,
18
+ type IBufferedChunk,
19
+ type SegmentSink,
20
+ } from "../../../segment_sinks";
21
+ import { DummySegmentSink } from "../../../segment_sinks/__tests__/mocks";
22
+ import type { IRepresentationStreamPlaybackObservation } from "../../representation";
6
23
  import getRepresentationsSwitchingStrategy from "../get_representations_switch_strategy";
7
24
 
8
- /* eslint-disable @typescript-eslint/no-explicit-any */
9
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
10
- /* eslint-disable @typescript-eslint/no-unsafe-argument */
11
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
12
-
13
- // Mock dependencies
14
- vi.mock("../../../config", () => ({
15
- default: {
16
- getCurrent: vi.fn(() => ({
25
+ describe("getRepresentationsSwitchingStrategy", () => {
26
+ let mockPeriod: IPeriod;
27
+ let mockAdaptation: IAdaptation;
28
+ let mockSegmentSink: SegmentSink;
29
+ const mockedPlaybackObserver =
30
+ makeReadyOnlyPlaybackObserver<IRepresentationStreamPlaybackObservation>({
31
+ position: new DummyObservationPosition({
32
+ getPolled: () => 10,
33
+ }),
34
+ paused: {
35
+ last: false,
36
+ pending: undefined,
37
+ },
38
+ speed: 1,
39
+ canStream: true,
40
+ });
41
+ const originalConfig = configHandler.getCurrent();
42
+ vi.spyOn(configHandler, "getCurrent").mockImplementation(() => {
43
+ return {
44
+ ...originalConfig,
17
45
  ADAP_REP_SWITCH_BUFFER_PADDINGS: {
18
46
  video: { before: 0.5, after: 0.5 },
19
47
  audio: { before: 0.5, after: 0.5 },
20
48
  text: { before: 0, after: 0 },
21
49
  },
22
- })),
23
- },
24
- }));
50
+ };
51
+ });
25
52
 
26
- describe("getRepresentationsSwitchingStrategy", () => {
27
- let mockPeriod: IPeriod;
28
- let mockAdaptation: IAdaptation;
29
- let mockSegmentSink: any;
30
- let mockPlaybackObserver: any;
53
+ function makeBufferedChunk({
54
+ bufferedStart,
55
+ bufferedEnd,
56
+ start,
57
+ end,
58
+ periodId = "period-1",
59
+ adaptationId = "adaptation-1",
60
+ representationId = "rep-1",
61
+ }: {
62
+ bufferedStart: number | undefined;
63
+ bufferedEnd: number | undefined;
64
+ start: number;
65
+ end: number;
66
+ periodId?: string;
67
+ adaptationId?: string;
68
+ representationId?: string;
69
+ }): IBufferedChunk {
70
+ return {
71
+ infos: {
72
+ period: new DummyPeriod({ id: periodId }),
73
+ adaptation: new DummyAdaptation({ id: adaptationId }),
74
+ representation: new DummyRepresentation({
75
+ id: representationId,
76
+ }),
77
+ segment: createSegment({ time: start, end }),
78
+ },
79
+ bufferedStart,
80
+ bufferedEnd,
81
+ start,
82
+ end,
83
+ insertionTs: 0,
84
+ chunkSize: 1024,
85
+ precizeStart: true,
86
+ precizeEnd: true,
87
+ status: ChunkStatus.FullyLoaded,
88
+ splitted: false,
89
+ };
90
+ }
31
91
 
32
92
  beforeEach(() => {
33
- mockPeriod = {
93
+ mockPeriod = new DummyPeriod({
34
94
  id: "period-1",
35
95
  start: 0,
36
96
  end: 100,
37
- } as IPeriod;
38
-
39
- mockAdaptation = {
97
+ });
98
+ mockAdaptation = new DummyAdaptation({
40
99
  id: "adaptation-1",
41
100
  type: "video",
42
- } as IAdaptation;
43
-
44
- mockSegmentSink = {
45
- getLastKnownInventory: vi.fn(() => []),
46
- getPendingOperations: vi.fn(() => []),
47
- } as unknown as SegmentSink;
48
-
49
- mockPlaybackObserver = {
50
- getReadyState: vi.fn(() => 4),
51
- getCurrentTime: vi.fn(() => 10),
52
- getReference: vi.fn(() => ({
53
- getValue: () => ({
54
- position: {
55
- getPolled: () => 10,
56
- },
57
- }),
58
- })),
59
- } as unknown as IReadOnlyPlaybackObserver<any>;
101
+ });
102
+ mockSegmentSink = new DummySegmentSink({
103
+ getLastKnownInventory: () => [],
104
+ getPendingOperations: () => [],
105
+ });
106
+ vi.spyOn(mockedPlaybackObserver.observer, "getReadyState").mockImplementation(
107
+ () => 4,
108
+ );
109
+ vi.spyOn(mockedPlaybackObserver.observer, "getCurrentTime").mockImplementation(
110
+ () => 10,
111
+ );
60
112
  });
61
113
  afterEach(() => {
114
+ mockedPlaybackObserver.reset();
62
115
  vi.resetAllMocks();
63
116
  });
64
117
 
65
118
  describe("lazy switching mode", () => {
66
119
  it("should return continue when switching mode is lazy", () => {
67
- const settings = {
68
- switchingMode: "lazy" as const,
69
- representationIds: ["rep-1"],
70
- };
71
-
72
120
  const result = getRepresentationsSwitchingStrategy(
73
121
  mockPeriod,
74
122
  mockAdaptation,
75
- settings,
123
+ { switchingMode: "lazy", representationIds: ["rep-1"] },
76
124
  mockSegmentSink,
77
- mockPlaybackObserver,
125
+ mockedPlaybackObserver.observer,
78
126
  );
79
-
80
127
  expect(result).toEqual({ type: "continue", value: undefined });
81
128
  });
82
129
  });
83
130
 
84
131
  describe("no unwanted segments", () => {
85
132
  it("should return continue when inventory is empty", () => {
86
- const settings = {
87
- switchingMode: "direct" as const,
88
- representationIds: ["rep-1"],
89
- };
90
-
91
133
  const result = getRepresentationsSwitchingStrategy(
92
134
  mockPeriod,
93
135
  mockAdaptation,
94
- settings,
136
+ { switchingMode: "direct", representationIds: ["rep-1"] },
95
137
  mockSegmentSink,
96
- mockPlaybackObserver,
138
+ mockedPlaybackObserver.observer,
97
139
  );
98
-
99
140
  expect(result).toEqual({ type: "continue", value: undefined });
100
141
  });
101
142
 
102
143
  it("should return continue when all segments match current representation", () => {
103
- const settings = {
104
- switchingMode: "direct" as const,
105
- representationIds: ["rep-1"],
106
- };
107
-
108
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
109
- {
110
- infos: {
111
- period: { id: "period-1" },
112
- adaptation: { id: "adaptation-1" },
113
- representation: { id: "rep-1" },
114
- },
115
- bufferedStart: 0,
116
- bufferedEnd: 10,
117
- start: 0,
118
- end: 10,
119
- },
120
- ]);
121
-
144
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
145
+ return [
146
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
147
+ ];
148
+ });
122
149
  const result = getRepresentationsSwitchingStrategy(
123
150
  mockPeriod,
124
151
  mockAdaptation,
125
- settings,
152
+ { switchingMode: "direct", representationIds: ["rep-1"] },
126
153
  mockSegmentSink,
127
- mockPlaybackObserver,
154
+ mockedPlaybackObserver.observer,
128
155
  );
129
-
130
156
  expect(result).toEqual({ type: "continue", value: undefined });
131
157
  });
132
158
  });
133
159
 
134
160
  describe("unwanted segments in inventory", () => {
135
161
  it("should identify unwanted segments from different representation", () => {
136
- const settings = {
137
- switchingMode: "direct" as const,
138
- representationIds: ["rep-2"],
139
- };
140
-
141
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
142
- {
143
- infos: {
144
- period: { id: "period-1" },
145
- adaptation: { id: "adaptation-1" },
146
- representation: { id: "rep-1" }, // Different representation
147
- },
148
- bufferedStart: 0,
149
- bufferedEnd: 10,
150
- start: 0,
151
- end: 10,
152
- },
153
- ]);
154
-
162
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
163
+ return [
164
+ makeBufferedChunk({
165
+ start: 0,
166
+ end: 10,
167
+ bufferedStart: 0,
168
+ bufferedEnd: 10,
169
+ representationId: "rep-1",
170
+ }),
171
+ ];
172
+ });
155
173
  const result = getRepresentationsSwitchingStrategy(
156
174
  mockPeriod,
157
175
  mockAdaptation,
158
- settings,
176
+ { switchingMode: "direct", representationIds: ["rep-2"] },
159
177
  mockSegmentSink,
160
- mockPlaybackObserver,
178
+ mockedPlaybackObserver.observer,
161
179
  );
162
-
163
180
  expect(result.type).toBe("flush-buffer");
164
181
  });
165
182
 
166
183
  it("should identify unwanted segments from different adaptation", () => {
167
- const settings = {
168
- switchingMode: "direct" as const,
169
- representationIds: ["rep-1"],
170
- };
171
-
172
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
173
- {
174
- infos: {
175
- period: { id: "period-1" },
176
- adaptation: { id: "adaptation-2" }, // Different adaptation
177
- representation: { id: "rep-1" },
178
- },
179
- bufferedStart: 0,
180
- bufferedEnd: 10,
181
- start: 0,
182
- end: 10,
183
- },
184
- ]);
185
-
184
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
185
+ return [
186
+ makeBufferedChunk({
187
+ start: 0,
188
+ end: 10,
189
+ bufferedStart: 0,
190
+ bufferedEnd: 10,
191
+ adaptationId: "adaptation-2",
192
+ }),
193
+ ];
194
+ });
186
195
  const result = getRepresentationsSwitchingStrategy(
187
196
  mockPeriod,
188
197
  mockAdaptation,
189
- settings,
198
+ { switchingMode: "direct", representationIds: ["rep-1"] },
190
199
  mockSegmentSink,
191
- mockPlaybackObserver,
200
+ mockedPlaybackObserver.observer,
192
201
  );
193
-
194
202
  expect(result.type).toBe("flush-buffer");
195
203
  });
196
204
 
197
205
  it("should ignore segments from different periods", () => {
198
- const settings = {
199
- switchingMode: "direct" as const,
200
- representationIds: ["rep-2"],
201
- };
202
-
203
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
204
- {
205
- infos: {
206
- period: { id: "period-2" }, // Different period
207
- adaptation: { id: "adaptation-1" },
208
- representation: { id: "rep-1" },
209
- },
210
- bufferedStart: 0,
211
- bufferedEnd: 10,
212
- start: 0,
213
- end: 10,
214
- },
215
- ]);
206
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
207
+ return [
208
+ makeBufferedChunk({
209
+ start: 0,
210
+ end: 10,
211
+ bufferedStart: 0,
212
+ bufferedEnd: 10,
213
+ periodId: "period-2",
214
+ }),
215
+ ];
216
+ });
216
217
 
217
218
  const result = getRepresentationsSwitchingStrategy(
218
219
  mockPeriod,
219
220
  mockAdaptation,
220
- settings,
221
+ { switchingMode: "direct", representationIds: ["rep-2"] },
221
222
  mockSegmentSink,
222
- mockPlaybackObserver,
223
+ mockedPlaybackObserver.observer,
223
224
  );
224
225
 
225
226
  expect(result).toEqual({ type: "continue", value: undefined });
@@ -228,159 +229,127 @@ describe("getRepresentationsSwitchingStrategy", () => {
228
229
 
229
230
  describe("pending operations", () => {
230
231
  it("should identify unwanted segments in pending push operations", () => {
231
- const settings = {
232
- switchingMode: "direct" as const,
233
- representationIds: ["rep-2"],
234
- };
235
-
236
- mockSegmentSink.getPendingOperations = vi.fn(() => [
237
- {
238
- type: SegmentSinkOperation.Push,
239
- value: {
240
- inventoryInfos: {
241
- period: { id: "period-1" },
242
- adaptation: { id: "adaptation-1" },
243
- representation: { id: "rep-1" }, // Different representation
244
- segment: {
245
- time: 5,
246
- duration: 5,
232
+ vi.spyOn(mockSegmentSink, "getPendingOperations").mockImplementation(() => {
233
+ return [
234
+ {
235
+ type: SegmentSinkOperation.Push,
236
+ value: {
237
+ inventoryInfos: {
238
+ period: new DummyPeriod({ id: "period-1" }),
239
+ adaptation: new DummyAdaptation({
240
+ id: "adaptation-1",
241
+ }),
242
+ representation: new DummyRepresentation({
243
+ id: "rep-1",
244
+ }),
245
+ segment: createSegment({ time: 5, duration: 5 }),
246
+ chunkSize: 1024,
247
+ start: 0,
248
+ end: 1000,
249
+ },
250
+ data: {
251
+ initSegmentUniqueId: "4",
252
+ codec: "5",
253
+ timestampOffset: 0,
254
+ appendWindow: [undefined, undefined],
255
+ chunk: new Uint8Array([0, 1, 2, 3]),
247
256
  },
248
257
  },
249
258
  },
250
- },
251
- ]);
252
-
259
+ ];
260
+ });
253
261
  const result = getRepresentationsSwitchingStrategy(
254
262
  mockPeriod,
255
263
  mockAdaptation,
256
- settings,
264
+ { switchingMode: "direct", representationIds: ["rep-2"] },
257
265
  mockSegmentSink,
258
- mockPlaybackObserver,
266
+ mockedPlaybackObserver.observer,
259
267
  );
260
-
261
268
  expect(result.type).toBe("flush-buffer");
262
269
  });
263
270
 
264
271
  it("should ignore non-push pending operations", () => {
265
- const settings = {
266
- switchingMode: "direct" as const,
267
- representationIds: ["rep-2"],
268
- };
269
-
270
- mockSegmentSink.getPendingOperations = vi.fn(() => [
271
- {
272
- type: "remove",
273
- value: {},
274
- },
275
- ]);
276
-
272
+ vi.spyOn(mockSegmentSink, "getPendingOperations").mockImplementation(() => {
273
+ return [
274
+ {
275
+ type: SegmentSinkOperation.Remove,
276
+ value: {
277
+ start: 0,
278
+ end: 100000,
279
+ },
280
+ },
281
+ ];
282
+ });
277
283
  const result = getRepresentationsSwitchingStrategy(
278
284
  mockPeriod,
279
285
  mockAdaptation,
280
- settings,
286
+ { switchingMode: "direct", representationIds: ["rep-2"] },
281
287
  mockSegmentSink,
282
- mockPlaybackObserver,
288
+ mockedPlaybackObserver.observer,
283
289
  );
284
-
285
290
  expect(result).toEqual({ type: "continue", value: undefined });
286
291
  });
287
292
  });
288
293
 
289
294
  describe("reload switching mode", () => {
290
295
  it("should return needs-reload when readyState > 1 and mode is reload", () => {
291
- const settings = {
292
- switchingMode: "reload" as const,
293
- representationIds: ["rep-2"],
294
- };
295
-
296
- mockPlaybackObserver.getReadyState = vi.fn(() => 4);
297
-
298
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
299
- {
300
- infos: {
301
- period: { id: "period-1" },
302
- adaptation: { id: "adaptation-1" },
303
- representation: { id: "rep-1" },
304
- },
305
- bufferedStart: 0,
306
- bufferedEnd: 10,
307
- start: 0,
308
- end: 10,
309
- },
310
- ]);
296
+ vi.spyOn(mockedPlaybackObserver.observer, "getReadyState").mockImplementation(
297
+ () => 4,
298
+ );
299
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
300
+ return [
301
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
302
+ ];
303
+ });
311
304
 
312
305
  const result = getRepresentationsSwitchingStrategy(
313
306
  mockPeriod,
314
307
  mockAdaptation,
315
- settings,
308
+ { switchingMode: "reload", representationIds: ["rep-2"] },
316
309
  mockSegmentSink,
317
- mockPlaybackObserver,
310
+ mockedPlaybackObserver.observer,
318
311
  );
319
312
 
320
313
  expect(result).toEqual({ type: "needs-reload", value: undefined });
321
314
  });
322
315
 
323
316
  it("should reload when readyState is undefined", () => {
324
- const settings = {
325
- switchingMode: "reload" as const,
326
- representationIds: ["rep-2"],
327
- };
328
-
329
- mockPlaybackObserver.getReadyState = vi.fn(() => undefined);
330
-
331
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
332
- {
333
- infos: {
334
- period: { id: "period-1" },
335
- adaptation: { id: "adaptation-1" },
336
- representation: { id: "rep-1" },
337
- },
338
- bufferedStart: 0,
339
- bufferedEnd: 10,
340
- start: 0,
341
- end: 10,
342
- },
343
- ]);
317
+ vi.spyOn(mockedPlaybackObserver.observer, "getReadyState").mockImplementation(
318
+ () => undefined,
319
+ );
320
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
321
+ return [
322
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
323
+ ];
324
+ });
344
325
 
345
326
  const result = getRepresentationsSwitchingStrategy(
346
327
  mockPeriod,
347
328
  mockAdaptation,
348
- settings,
329
+ { switchingMode: "reload", representationIds: ["rep-2"] },
349
330
  mockSegmentSink,
350
- mockPlaybackObserver,
331
+ mockedPlaybackObserver.observer,
351
332
  );
352
333
 
353
334
  expect(result.type).toBe("needs-reload");
354
335
  });
355
336
 
356
337
  it("should not reload when readyState <= 1", () => {
357
- const settings = {
358
- switchingMode: "reload" as const,
359
- representationIds: ["rep-2"],
360
- };
361
-
362
- mockPlaybackObserver.getReadyState = vi.fn(() => 1);
363
-
364
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
365
- {
366
- infos: {
367
- period: { id: "period-1" },
368
- adaptation: { id: "adaptation-1" },
369
- representation: { id: "rep-1" },
370
- },
371
- bufferedStart: 0,
372
- bufferedEnd: 10,
373
- start: 0,
374
- end: 10,
375
- },
376
- ]);
338
+ vi.spyOn(mockedPlaybackObserver.observer, "getReadyState").mockImplementation(
339
+ () => 1,
340
+ );
341
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
342
+ return [
343
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
344
+ ];
345
+ });
377
346
 
378
347
  const result = getRepresentationsSwitchingStrategy(
379
348
  mockPeriod,
380
349
  mockAdaptation,
381
- settings,
350
+ { switchingMode: "reload", representationIds: ["rep-2"] },
382
351
  mockSegmentSink,
383
- mockPlaybackObserver,
352
+ mockedPlaybackObserver.observer,
384
353
  );
385
354
 
386
355
  expect(result.type).not.toBe("needs-reload");
@@ -389,62 +358,36 @@ describe("getRepresentationsSwitchingStrategy", () => {
389
358
 
390
359
  describe("direct vs clean-buffer mode", () => {
391
360
  it("should return flush-buffer when mode is direct", () => {
392
- const settings = {
393
- switchingMode: "direct" as const,
394
- representationIds: ["rep-2"],
395
- };
396
-
397
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
398
- {
399
- infos: {
400
- period: { id: "period-1" },
401
- adaptation: { id: "adaptation-1" },
402
- representation: { id: "rep-1" },
403
- },
404
- bufferedStart: 0,
405
- bufferedEnd: 10,
406
- start: 0,
407
- end: 10,
408
- },
409
- ]);
361
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
362
+ return [
363
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
364
+ ];
365
+ });
410
366
 
411
367
  const result = getRepresentationsSwitchingStrategy(
412
368
  mockPeriod,
413
369
  mockAdaptation,
414
- settings,
370
+ { switchingMode: "direct", representationIds: ["rep-2"] },
415
371
  mockSegmentSink,
416
- mockPlaybackObserver,
372
+ mockedPlaybackObserver.observer,
417
373
  );
418
374
 
419
375
  expect(result.type).toBe("flush-buffer");
420
376
  });
421
377
 
422
378
  it("should return clean-buffer when mode is not direct or reload", () => {
423
- const settings = {
424
- switchingMode: "seamless" as any,
425
- representationIds: ["rep-2"],
426
- };
427
-
428
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
429
- {
430
- infos: {
431
- period: { id: "period-1" },
432
- adaptation: { id: "adaptation-1" },
433
- representation: { id: "rep-1" },
434
- },
435
- bufferedStart: 0,
436
- bufferedEnd: 10,
437
- start: 0,
438
- end: 10,
439
- },
440
- ]);
379
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
380
+ return [
381
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
382
+ ];
383
+ });
441
384
 
442
385
  const result = getRepresentationsSwitchingStrategy(
443
386
  mockPeriod,
444
387
  mockAdaptation,
445
- settings,
388
+ { switchingMode: "seamless", representationIds: ["rep-2"] },
446
389
  mockSegmentSink,
447
- mockPlaybackObserver,
390
+ mockedPlaybackObserver.observer,
448
391
  );
449
392
 
450
393
  expect(result.type).toBe("clean-buffer");
@@ -453,41 +396,35 @@ describe("getRepresentationsSwitchingStrategy", () => {
453
396
 
454
397
  describe("getCurrentTime fallback", () => {
455
398
  it("should use getPolled when getCurrentTime returns undefined", () => {
456
- const settings = {
457
- switchingMode: "seamless" as any,
458
- representationIds: ["rep-2"],
459
- };
460
-
461
399
  const getPolledMock = vi.fn(() => 15);
462
- mockPlaybackObserver.getCurrentTime = vi.fn(() => undefined);
463
- mockPlaybackObserver.getReference = vi.fn(() => ({
464
- getValue: () => ({
465
- position: {
400
+ vi.spyOn(mockedPlaybackObserver.observer, "getCurrentTime").mockImplementation(
401
+ () => undefined,
402
+ );
403
+ vi.spyOn(mockedPlaybackObserver.observer, "getReference").mockImplementation(() => {
404
+ return new SharedReference({
405
+ position: new DummyObservationPosition({
466
406
  getPolled: getPolledMock,
407
+ }),
408
+ paused: {
409
+ last: false,
410
+ pending: undefined,
467
411
  },
468
- }),
469
- }));
470
-
471
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
472
- {
473
- infos: {
474
- period: { id: "period-1" },
475
- adaptation: { id: "adaptation-1" },
476
- representation: { id: "rep-1" },
477
- },
478
- bufferedStart: 0,
479
- bufferedEnd: 10,
480
- start: 0,
481
- end: 10,
482
- },
483
- ]);
412
+ speed: 1,
413
+ canStream: true,
414
+ });
415
+ });
416
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
417
+ return [
418
+ makeBufferedChunk({ start: 0, end: 10, bufferedStart: 0, bufferedEnd: 10 }),
419
+ ];
420
+ });
484
421
 
485
422
  getRepresentationsSwitchingStrategy(
486
423
  mockPeriod,
487
424
  mockAdaptation,
488
- settings,
425
+ { switchingMode: "seamless", representationIds: ["rep-2"] },
489
426
  mockSegmentSink,
490
- mockPlaybackObserver,
427
+ mockedPlaybackObserver.observer,
491
428
  );
492
429
 
493
430
  expect(getPolledMock).toHaveBeenCalled();
@@ -496,62 +433,41 @@ describe("getRepresentationsSwitchingStrategy", () => {
496
433
 
497
434
  describe("segment buffered time handling", () => {
498
435
  it("should use bufferedStart/bufferedEnd when available", () => {
499
- const settings = {
500
- switchingMode: "direct" as const,
501
- representationIds: ["rep-2"],
502
- };
503
-
504
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
505
- {
506
- infos: {
507
- period: { id: "period-1" },
508
- adaptation: { id: "adaptation-1" },
509
- representation: { id: "rep-1" },
510
- },
511
- bufferedStart: 5,
512
- bufferedEnd: 15,
513
- start: 0,
514
- end: 20,
515
- },
516
- ]);
436
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
437
+ return [
438
+ makeBufferedChunk({ start: 0, end: 20, bufferedStart: 5, bufferedEnd: 15 }),
439
+ ];
440
+ });
517
441
 
518
442
  const result = getRepresentationsSwitchingStrategy(
519
443
  mockPeriod,
520
444
  mockAdaptation,
521
- settings,
445
+ { switchingMode: "direct", representationIds: ["rep-2"] },
522
446
  mockSegmentSink,
523
- mockPlaybackObserver,
447
+ mockedPlaybackObserver.observer,
524
448
  );
525
449
 
526
450
  expect(result.type).toBe("flush-buffer");
527
451
  });
528
452
 
529
453
  it("should fallback to start/end when bufferedStart/bufferedEnd is undefined", () => {
530
- const settings = {
531
- switchingMode: "direct" as const,
532
- representationIds: ["rep-2"],
533
- };
534
-
535
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
536
- {
537
- infos: {
538
- period: { id: "period-1" },
539
- adaptation: { id: "adaptation-1" },
540
- representation: { id: "rep-1" },
541
- },
542
- bufferedStart: undefined,
543
- bufferedEnd: undefined,
544
- start: 0,
545
- end: 10,
546
- },
547
- ]);
454
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
455
+ return [
456
+ makeBufferedChunk({
457
+ start: 0,
458
+ end: 10,
459
+ bufferedStart: undefined,
460
+ bufferedEnd: undefined,
461
+ }),
462
+ ];
463
+ });
548
464
 
549
465
  const result = getRepresentationsSwitchingStrategy(
550
466
  mockPeriod,
551
467
  mockAdaptation,
552
- settings,
468
+ { switchingMode: "direct", representationIds: ["rep-2"] },
553
469
  mockSegmentSink,
554
- mockPlaybackObserver,
470
+ mockedPlaybackObserver.observer,
555
471
  );
556
472
 
557
473
  expect(result.type).toBe("flush-buffer");
@@ -560,31 +476,24 @@ describe("getRepresentationsSwitchingStrategy", () => {
560
476
 
561
477
  describe("multiple representation IDs", () => {
562
478
  it("should not mark segments as unwanted if they match any of the representation IDs", () => {
563
- const settings = {
564
- switchingMode: "direct" as const,
565
- representationIds: ["rep-1", "rep-2", "rep-3"],
566
- };
567
-
568
- mockSegmentSink.getLastKnownInventory = vi.fn(() => [
569
- {
570
- infos: {
571
- period: { id: "period-1" },
572
- adaptation: { id: "adaptation-1" },
573
- representation: { id: "rep-2" },
574
- },
575
- bufferedStart: 0,
576
- bufferedEnd: 10,
577
- start: 0,
578
- end: 10,
579
- },
580
- ]);
479
+ vi.spyOn(mockSegmentSink, "getLastKnownInventory").mockImplementation(() => {
480
+ return [
481
+ makeBufferedChunk({
482
+ start: 0,
483
+ end: 10,
484
+ bufferedStart: 0,
485
+ bufferedEnd: 10,
486
+ representationId: "rep-2",
487
+ }),
488
+ ];
489
+ });
581
490
 
582
491
  const result = getRepresentationsSwitchingStrategy(
583
492
  mockPeriod,
584
493
  mockAdaptation,
585
- settings,
494
+ { switchingMode: "direct", representationIds: ["rep-1", "rep-2", "rep-3"] },
586
495
  mockSegmentSink,
587
- mockPlaybackObserver,
496
+ mockedPlaybackObserver.observer,
588
497
  );
589
498
 
590
499
  expect(result).toEqual({ type: "continue", value: undefined });