rx-player 4.0.0-dev.2023111400 → 4.0.0-dev.2023121900

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 (336) hide show
  1. package/CHANGELOG.md +20 -60
  2. package/FILES.md +1 -1
  3. package/README.md +2 -33
  4. package/VERSION +1 -1
  5. package/dist/_esm5.processed/core/api/debug/buffer_graph.js +2 -6
  6. package/dist/_esm5.processed/core/api/debug/modules/general_info.js +20 -10
  7. package/dist/_esm5.processed/core/api/option_utils.d.ts +0 -2
  8. package/dist/_esm5.processed/core/api/option_utils.js +0 -6
  9. package/dist/_esm5.processed/core/api/public_api.d.ts +1 -2
  10. package/dist/_esm5.processed/core/api/public_api.js +9 -17
  11. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  12. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +3 -14
  13. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +2 -36
  14. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +2 -82
  15. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +9 -2
  16. package/dist/_esm5.processed/core/segment_buffers/implementations/image/image_segment_buffer.js +1 -1
  17. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +1 -1
  18. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +1 -1
  19. package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
  20. package/dist/_esm5.processed/core/segment_buffers/inventory/index.d.ts +2 -2
  21. package/dist/_esm5.processed/core/segment_buffers/inventory/segment_inventory.d.ts +25 -8
  22. package/dist/_esm5.processed/core/segment_buffers/inventory/segment_inventory.js +19 -10
  23. package/dist/_esm5.processed/core/stream/representation/utils/get_buffer_status.js +1 -1
  24. package/dist/_esm5.processed/core/stream/representation/utils/get_needed_segments.js +1 -1
  25. package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_extent.js +1 -8
  26. package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_line_height.js +2 -1
  27. package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_origin.js +1 -9
  28. package/dist/_esm5.processed/public_types.d.ts +2 -0
  29. package/dist/commonjs/compat/is_codec_supported.js +22 -1
  30. package/dist/commonjs/config.d.ts +2 -1
  31. package/dist/commonjs/core/adaptive/adaptive_representation_selector.d.ts +2 -19
  32. package/dist/commonjs/core/adaptive/adaptive_representation_selector.js +2 -2
  33. package/dist/commonjs/core/adaptive/network_analyzer.js +3 -3
  34. package/dist/commonjs/core/api/debug/buffer_graph.js +2 -6
  35. package/dist/commonjs/core/api/debug/modules/general_info.js +17 -10
  36. package/dist/commonjs/core/api/index.d.ts +1 -1
  37. package/dist/commonjs/core/api/option_utils.d.ts +2 -0
  38. package/dist/commonjs/core/api/option_utils.js +2 -3
  39. package/dist/commonjs/core/api/playback_observer.d.ts +128 -8
  40. package/dist/commonjs/core/api/playback_observer.js +217 -64
  41. package/dist/commonjs/core/api/public_api.d.ts +9 -0
  42. package/dist/commonjs/core/api/public_api.js +41 -16
  43. package/dist/commonjs/core/api/utils.js +1 -1
  44. package/dist/commonjs/core/decrypt/get_media_keys.js +2 -6
  45. package/dist/commonjs/core/fetchers/manifest/manifest_fetcher.d.ts +6 -0
  46. package/dist/commonjs/core/fetchers/manifest/manifest_fetcher.js +11 -3
  47. package/dist/commonjs/core/fetchers/segment/segment_fetcher.d.ts +8 -1
  48. package/dist/commonjs/core/fetchers/segment/segment_fetcher.js +8 -4
  49. package/dist/commonjs/core/fetchers/segment/segment_fetcher_creator.d.ts +1 -0
  50. package/dist/commonjs/core/fetchers/utils/schedule_request.js +1 -1
  51. package/dist/commonjs/core/init/directfile_content_initializer.js +29 -8
  52. package/dist/commonjs/core/init/media_source_content_initializer.d.ts +6 -0
  53. package/dist/commonjs/core/init/media_source_content_initializer.js +32 -20
  54. package/dist/commonjs/core/init/utils/content_time_boundaries_observer.d.ts +13 -12
  55. package/dist/commonjs/core/init/utils/content_time_boundaries_observer.js +17 -19
  56. package/dist/commonjs/core/init/utils/create_stream_playback_observer.d.ts +1 -5
  57. package/dist/commonjs/core/init/utils/create_stream_playback_observer.js +16 -14
  58. package/dist/commonjs/core/init/utils/get_initial_time.d.ts +17 -3
  59. package/dist/commonjs/core/init/utils/get_initial_time.js +9 -7
  60. package/dist/commonjs/core/init/utils/initial_seek_and_play.d.ts +9 -11
  61. package/dist/commonjs/core/init/utils/initial_seek_and_play.js +121 -91
  62. package/dist/commonjs/core/init/utils/rebuffering_controller.js +27 -70
  63. package/dist/commonjs/core/init/utils/stream_events_emitter/stream_events_emitter.js +4 -2
  64. package/dist/commonjs/core/segment_buffers/garbage_collector.js +1 -2
  65. package/dist/commonjs/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +9 -2
  66. package/dist/commonjs/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +1 -1
  67. package/dist/commonjs/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +1 -1
  68. package/dist/commonjs/core/segment_buffers/index.d.ts +2 -2
  69. package/dist/commonjs/core/segment_buffers/inventory/index.d.ts +2 -2
  70. package/dist/commonjs/core/segment_buffers/inventory/segment_inventory.d.ts +25 -8
  71. package/dist/commonjs/core/segment_buffers/inventory/segment_inventory.js +19 -10
  72. package/dist/commonjs/core/stream/adaptation/get_representations_switch_strategy.d.ts +2 -2
  73. package/dist/commonjs/core/stream/adaptation/get_representations_switch_strategy.js +16 -9
  74. package/dist/commonjs/core/stream/orchestrator/stream_orchestrator.js +14 -18
  75. package/dist/commonjs/core/stream/period/period_stream.js +5 -8
  76. package/dist/commonjs/core/stream/period/types.d.ts +2 -3
  77. package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.d.ts +4 -5
  78. package/dist/commonjs/core/stream/period/utils/get_adaptation_switch_strategy.js +17 -13
  79. package/dist/commonjs/core/stream/representation/representation_stream.js +3 -4
  80. package/dist/commonjs/core/stream/representation/types.d.ts +2 -2
  81. package/dist/commonjs/core/stream/representation/utils/append_segment_to_buffer.js +11 -12
  82. package/dist/commonjs/core/stream/representation/utils/get_buffer_status.js +4 -4
  83. package/dist/commonjs/core/stream/representation/utils/get_needed_segments.js +1 -1
  84. package/dist/commonjs/default_config.d.ts +12 -16
  85. package/dist/commonjs/default_config.js +21 -16
  86. package/dist/commonjs/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +3 -1
  87. package/dist/commonjs/experimental/tools/createMetaplaylist/get_duration_from_manifest.js +2 -0
  88. package/dist/commonjs/manifest/adaptation.js +2 -1
  89. package/dist/commonjs/manifest/representation_index/static.d.ts +1 -1
  90. package/dist/commonjs/manifest/representation_index/static.js +2 -2
  91. package/dist/commonjs/manifest/representation_index/types.d.ts +4 -4
  92. package/dist/commonjs/parsers/manifest/dash/common/indexes/base.d.ts +6 -1
  93. package/dist/commonjs/parsers/manifest/dash/common/indexes/base.js +4 -3
  94. package/dist/commonjs/parsers/manifest/dash/common/indexes/get_segments_from_timeline.d.ts +5 -2
  95. package/dist/commonjs/parsers/manifest/dash/common/indexes/get_segments_from_timeline.js +15 -4
  96. package/dist/commonjs/parsers/manifest/dash/common/indexes/index.d.ts +5 -5
  97. package/dist/commonjs/parsers/manifest/dash/common/indexes/list.d.ts +1 -1
  98. package/dist/commonjs/parsers/manifest/dash/common/indexes/list.js +2 -2
  99. package/dist/commonjs/parsers/manifest/dash/common/indexes/template.d.ts +12 -5
  100. package/dist/commonjs/parsers/manifest/dash/common/indexes/template.js +42 -29
  101. package/dist/commonjs/parsers/manifest/dash/common/indexes/timeline/index.d.ts +2 -1
  102. package/dist/commonjs/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +99 -6
  103. package/dist/commonjs/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +250 -51
  104. package/dist/commonjs/parsers/manifest/dash/common/manifest_bounds_calculator.d.ts +40 -17
  105. package/dist/commonjs/parsers/manifest/dash/common/manifest_bounds_calculator.js +38 -18
  106. package/dist/commonjs/parsers/manifest/dash/common/parse_adaptation_sets.js +13 -10
  107. package/dist/commonjs/parsers/manifest/dash/common/parse_mpd.js +27 -14
  108. package/dist/commonjs/parsers/manifest/dash/common/parse_periods.d.ts +1 -1
  109. package/dist/commonjs/parsers/manifest/dash/common/parse_periods.js +17 -18
  110. package/dist/commonjs/parsers/manifest/dash/common/parse_representation_index.d.ts +19 -6
  111. package/dist/commonjs/parsers/manifest/dash/common/parse_representation_index.js +21 -8
  112. package/dist/commonjs/parsers/manifest/dash/common/parse_representations.js +7 -3
  113. package/dist/commonjs/parsers/manifest/local/representation_index.d.ts +1 -1
  114. package/dist/commonjs/parsers/manifest/local/representation_index.js +3 -3
  115. package/dist/commonjs/parsers/manifest/metaplaylist/representation_index.d.ts +1 -1
  116. package/dist/commonjs/parsers/manifest/metaplaylist/representation_index.js +2 -2
  117. package/dist/commonjs/parsers/manifest/smooth/representation_index.d.ts +5 -5
  118. package/dist/commonjs/parsers/manifest/smooth/representation_index.js +25 -9
  119. package/dist/commonjs/parsers/manifest/utils/index_helpers.js +1 -1
  120. package/dist/commonjs/parsers/texttracks/ttml/html/apply_line_height.js +2 -1
  121. package/dist/commonjs/public_types.d.ts +107 -36
  122. package/dist/commonjs/transports/dash/init_segment_loader.js +10 -5
  123. package/dist/commonjs/transports/dash/manifest_parser.js +5 -2
  124. package/dist/commonjs/transports/dash/segment_loader.js +2 -1
  125. package/dist/commonjs/transports/dash/text_loader.js +2 -0
  126. package/dist/commonjs/transports/metaplaylist/manifest_loader.js +2 -1
  127. package/dist/commonjs/transports/metaplaylist/pipelines.js +4 -1
  128. package/dist/commonjs/transports/smooth/pipelines.js +4 -2
  129. package/dist/commonjs/transports/smooth/segment_loader.js +2 -1
  130. package/dist/commonjs/transports/types.d.ts +12 -0
  131. package/dist/commonjs/transports/utils/generate_manifest_loader.js +6 -3
  132. package/dist/commonjs/utils/request/fetch.d.ts +6 -0
  133. package/dist/commonjs/utils/request/fetch.js +29 -8
  134. package/dist/commonjs/utils/request/xhr.d.ts +11 -5
  135. package/dist/commonjs/utils/request/xhr.js +29 -8
  136. package/dist/es2017/compat/is_codec_supported.js +22 -1
  137. package/dist/es2017/config.d.ts +2 -1
  138. package/dist/es2017/core/adaptive/adaptive_representation_selector.d.ts +2 -19
  139. package/dist/es2017/core/adaptive/adaptive_representation_selector.js +2 -2
  140. package/dist/es2017/core/adaptive/network_analyzer.js +3 -3
  141. package/dist/es2017/core/api/debug/buffer_graph.js +2 -6
  142. package/dist/es2017/core/api/debug/modules/general_info.js +17 -10
  143. package/dist/es2017/core/api/index.d.ts +1 -1
  144. package/dist/es2017/core/api/option_utils.d.ts +2 -0
  145. package/dist/es2017/core/api/option_utils.js +2 -3
  146. package/dist/es2017/core/api/playback_observer.d.ts +128 -8
  147. package/dist/es2017/core/api/playback_observer.js +217 -66
  148. package/dist/es2017/core/api/public_api.d.ts +9 -0
  149. package/dist/es2017/core/api/public_api.js +40 -15
  150. package/dist/es2017/core/api/utils.js +1 -1
  151. package/dist/es2017/core/decrypt/get_media_keys.js +2 -6
  152. package/dist/es2017/core/fetchers/manifest/manifest_fetcher.d.ts +6 -0
  153. package/dist/es2017/core/fetchers/manifest/manifest_fetcher.js +11 -3
  154. package/dist/es2017/core/fetchers/segment/segment_fetcher.d.ts +8 -1
  155. package/dist/es2017/core/fetchers/segment/segment_fetcher.js +8 -4
  156. package/dist/es2017/core/fetchers/segment/segment_fetcher_creator.d.ts +1 -0
  157. package/dist/es2017/core/fetchers/utils/schedule_request.js +1 -1
  158. package/dist/es2017/core/init/directfile_content_initializer.js +31 -8
  159. package/dist/es2017/core/init/media_source_content_initializer.d.ts +6 -0
  160. package/dist/es2017/core/init/media_source_content_initializer.js +34 -22
  161. package/dist/es2017/core/init/utils/content_time_boundaries_observer.d.ts +13 -12
  162. package/dist/es2017/core/init/utils/content_time_boundaries_observer.js +17 -17
  163. package/dist/es2017/core/init/utils/create_stream_playback_observer.d.ts +1 -5
  164. package/dist/es2017/core/init/utils/create_stream_playback_observer.js +16 -14
  165. package/dist/es2017/core/init/utils/get_initial_time.d.ts +17 -3
  166. package/dist/es2017/core/init/utils/get_initial_time.js +9 -7
  167. package/dist/es2017/core/init/utils/initial_seek_and_play.d.ts +9 -11
  168. package/dist/es2017/core/init/utils/initial_seek_and_play.js +120 -91
  169. package/dist/es2017/core/init/utils/rebuffering_controller.js +27 -70
  170. package/dist/es2017/core/init/utils/stream_events_emitter/stream_events_emitter.js +4 -2
  171. package/dist/es2017/core/segment_buffers/garbage_collector.js +1 -2
  172. package/dist/es2017/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +9 -2
  173. package/dist/es2017/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +1 -1
  174. package/dist/es2017/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +1 -1
  175. package/dist/es2017/core/segment_buffers/index.d.ts +2 -2
  176. package/dist/es2017/core/segment_buffers/inventory/index.d.ts +2 -2
  177. package/dist/es2017/core/segment_buffers/inventory/segment_inventory.d.ts +25 -8
  178. package/dist/es2017/core/segment_buffers/inventory/segment_inventory.js +19 -10
  179. package/dist/es2017/core/stream/adaptation/get_representations_switch_strategy.d.ts +2 -2
  180. package/dist/es2017/core/stream/adaptation/get_representations_switch_strategy.js +16 -9
  181. package/dist/es2017/core/stream/orchestrator/stream_orchestrator.js +16 -18
  182. package/dist/es2017/core/stream/period/period_stream.js +4 -7
  183. package/dist/es2017/core/stream/period/types.d.ts +2 -3
  184. package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.d.ts +4 -5
  185. package/dist/es2017/core/stream/period/utils/get_adaptation_switch_strategy.js +17 -13
  186. package/dist/es2017/core/stream/representation/representation_stream.js +3 -4
  187. package/dist/es2017/core/stream/representation/types.d.ts +2 -2
  188. package/dist/es2017/core/stream/representation/utils/append_segment_to_buffer.js +1 -2
  189. package/dist/es2017/core/stream/representation/utils/get_buffer_status.js +4 -4
  190. package/dist/es2017/core/stream/representation/utils/get_needed_segments.js +1 -1
  191. package/dist/es2017/default_config.d.ts +12 -16
  192. package/dist/es2017/default_config.js +21 -16
  193. package/dist/es2017/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +3 -1
  194. package/dist/es2017/experimental/tools/createMetaplaylist/get_duration_from_manifest.js +2 -0
  195. package/dist/es2017/manifest/adaptation.js +2 -1
  196. package/dist/es2017/manifest/representation_index/static.d.ts +1 -1
  197. package/dist/es2017/manifest/representation_index/static.js +2 -2
  198. package/dist/es2017/manifest/representation_index/types.d.ts +4 -4
  199. package/dist/es2017/parsers/manifest/dash/common/indexes/base.d.ts +6 -1
  200. package/dist/es2017/parsers/manifest/dash/common/indexes/base.js +4 -3
  201. package/dist/es2017/parsers/manifest/dash/common/indexes/get_segments_from_timeline.d.ts +5 -2
  202. package/dist/es2017/parsers/manifest/dash/common/indexes/get_segments_from_timeline.js +15 -4
  203. package/dist/es2017/parsers/manifest/dash/common/indexes/index.d.ts +5 -5
  204. package/dist/es2017/parsers/manifest/dash/common/indexes/list.d.ts +1 -1
  205. package/dist/es2017/parsers/manifest/dash/common/indexes/list.js +2 -2
  206. package/dist/es2017/parsers/manifest/dash/common/indexes/template.d.ts +12 -5
  207. package/dist/es2017/parsers/manifest/dash/common/indexes/template.js +40 -27
  208. package/dist/es2017/parsers/manifest/dash/common/indexes/timeline/index.d.ts +2 -1
  209. package/dist/es2017/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +99 -6
  210. package/dist/es2017/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +246 -51
  211. package/dist/es2017/parsers/manifest/dash/common/manifest_bounds_calculator.d.ts +40 -17
  212. package/dist/es2017/parsers/manifest/dash/common/manifest_bounds_calculator.js +38 -18
  213. package/dist/es2017/parsers/manifest/dash/common/parse_adaptation_sets.js +11 -8
  214. package/dist/es2017/parsers/manifest/dash/common/parse_mpd.js +27 -13
  215. package/dist/es2017/parsers/manifest/dash/common/parse_periods.d.ts +1 -1
  216. package/dist/es2017/parsers/manifest/dash/common/parse_periods.js +13 -16
  217. package/dist/es2017/parsers/manifest/dash/common/parse_representation_index.d.ts +19 -6
  218. package/dist/es2017/parsers/manifest/dash/common/parse_representation_index.js +10 -8
  219. package/dist/es2017/parsers/manifest/dash/common/parse_representations.js +7 -3
  220. package/dist/es2017/parsers/manifest/local/representation_index.d.ts +1 -1
  221. package/dist/es2017/parsers/manifest/local/representation_index.js +3 -3
  222. package/dist/es2017/parsers/manifest/metaplaylist/representation_index.d.ts +1 -1
  223. package/dist/es2017/parsers/manifest/metaplaylist/representation_index.js +2 -2
  224. package/dist/es2017/parsers/manifest/smooth/representation_index.d.ts +5 -5
  225. package/dist/es2017/parsers/manifest/smooth/representation_index.js +25 -9
  226. package/dist/es2017/parsers/manifest/utils/index_helpers.js +1 -1
  227. package/dist/es2017/parsers/texttracks/ttml/html/apply_line_height.js +2 -1
  228. package/dist/es2017/public_types.d.ts +107 -36
  229. package/dist/es2017/transports/dash/init_segment_loader.js +5 -0
  230. package/dist/es2017/transports/dash/manifest_parser.js +3 -0
  231. package/dist/es2017/transports/dash/segment_loader.js +1 -0
  232. package/dist/es2017/transports/dash/text_loader.js +2 -0
  233. package/dist/es2017/transports/metaplaylist/manifest_loader.js +1 -0
  234. package/dist/es2017/transports/metaplaylist/pipelines.js +4 -1
  235. package/dist/es2017/transports/smooth/pipelines.js +2 -0
  236. package/dist/es2017/transports/smooth/segment_loader.js +1 -0
  237. package/dist/es2017/transports/types.d.ts +12 -0
  238. package/dist/es2017/transports/utils/generate_manifest_loader.js +3 -0
  239. package/dist/es2017/utils/request/fetch.d.ts +6 -0
  240. package/dist/es2017/utils/request/fetch.js +29 -8
  241. package/dist/es2017/utils/request/xhr.d.ts +11 -5
  242. package/dist/es2017/utils/request/xhr.js +30 -9
  243. package/dist/mpd-parser.wasm +0 -0
  244. package/dist/rx-player.js +1335 -812
  245. package/dist/rx-player.min.js +1 -1
  246. package/package.json +7 -4
  247. package/scripts/canal-release.patch +78 -0
  248. package/scripts/make-dev-releases +65 -0
  249. package/scripts/update-version +7 -0
  250. package/sonar-project.properties +1 -1
  251. package/src/compat/is_codec_supported.ts +23 -1
  252. package/src/core/adaptive/adaptive_representation_selector.ts +4 -21
  253. package/src/core/adaptive/network_analyzer.ts +3 -3
  254. package/src/core/api/debug/buffer_graph.ts +2 -5
  255. package/src/core/api/debug/modules/general_info.ts +15 -10
  256. package/src/core/api/index.ts +1 -0
  257. package/src/core/api/option_utils.ts +3 -3
  258. package/src/core/api/playback_observer.ts +327 -107
  259. package/src/core/api/public_api.ts +42 -14
  260. package/src/core/api/utils.ts +3 -1
  261. package/src/core/decrypt/get_media_keys.ts +2 -8
  262. package/src/core/fetchers/manifest/manifest_fetcher.ts +21 -3
  263. package/src/core/fetchers/segment/segment_fetcher.ts +19 -5
  264. package/src/core/fetchers/segment/segment_fetcher_creator.ts +1 -0
  265. package/src/core/fetchers/utils/schedule_request.ts +1 -1
  266. package/src/core/init/directfile_content_initializer.ts +31 -15
  267. package/src/core/init/media_source_content_initializer.ts +40 -27
  268. package/src/core/init/utils/content_time_boundaries_observer.ts +24 -23
  269. package/src/core/init/utils/create_stream_playback_observer.ts +19 -20
  270. package/src/core/init/utils/get_initial_time.ts +25 -12
  271. package/src/core/init/utils/initial_seek_and_play.ts +140 -108
  272. package/src/core/init/utils/rebuffering_controller.ts +32 -77
  273. package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +5 -2
  274. package/src/core/segment_buffers/garbage_collector.ts +1 -1
  275. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +10 -2
  276. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +1 -1
  277. package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +1 -1
  278. package/src/core/segment_buffers/index.ts +2 -0
  279. package/src/core/segment_buffers/inventory/index.ts +2 -0
  280. package/src/core/segment_buffers/inventory/segment_inventory.ts +49 -17
  281. package/src/core/stream/adaptation/get_representations_switch_strategy.ts +21 -12
  282. package/src/core/stream/orchestrator/stream_orchestrator.ts +14 -19
  283. package/src/core/stream/period/period_stream.ts +7 -8
  284. package/src/core/stream/period/types.ts +2 -3
  285. package/src/core/stream/period/utils/get_adaptation_switch_strategy.ts +21 -15
  286. package/src/core/stream/representation/representation_stream.ts +3 -5
  287. package/src/core/stream/representation/types.ts +2 -2
  288. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
  289. package/src/core/stream/representation/utils/get_buffer_status.ts +5 -4
  290. package/src/core/stream/representation/utils/get_needed_segments.ts +2 -2
  291. package/src/default_config.ts +22 -17
  292. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +3 -1
  293. package/src/experimental/tools/createMetaplaylist/get_duration_from_manifest.ts +2 -0
  294. package/src/manifest/adaptation.ts +2 -1
  295. package/src/manifest/representation_index/static.ts +2 -2
  296. package/src/manifest/representation_index/types.ts +4 -4
  297. package/src/parsers/manifest/dash/common/__tests__/manifest_bounds_calculator.test.ts +182 -36
  298. package/src/parsers/manifest/dash/common/indexes/base.ts +12 -4
  299. package/src/parsers/manifest/dash/common/indexes/get_segments_from_timeline.ts +19 -5
  300. package/src/parsers/manifest/dash/common/indexes/index.ts +16 -4
  301. package/src/parsers/manifest/dash/common/indexes/list.ts +2 -2
  302. package/src/parsers/manifest/dash/common/indexes/template.ts +52 -31
  303. package/src/parsers/manifest/dash/common/indexes/timeline/index.ts +4 -1
  304. package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +366 -60
  305. package/src/parsers/manifest/dash/common/manifest_bounds_calculator.ts +63 -25
  306. package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +10 -4
  307. package/src/parsers/manifest/dash/common/parse_mpd.ts +28 -15
  308. package/src/parsers/manifest/dash/common/parse_periods.ts +12 -17
  309. package/src/parsers/manifest/dash/common/parse_representation_index.ts +50 -26
  310. package/src/parsers/manifest/dash/common/parse_representations.ts +9 -3
  311. package/src/parsers/manifest/local/representation_index.ts +3 -3
  312. package/src/parsers/manifest/metaplaylist/representation_index.ts +2 -2
  313. package/src/parsers/manifest/smooth/representation_index.ts +23 -9
  314. package/src/parsers/manifest/utils/__tests__/get_first_time_from_adaptations.test.ts +1 -1
  315. package/src/parsers/manifest/utils/__tests__/get_last_time_from_adaptation.test.ts +1 -1
  316. package/src/parsers/manifest/utils/index_helpers.ts +1 -1
  317. package/src/parsers/texttracks/ttml/html/apply_line_height.ts +3 -1
  318. package/src/public_types.ts +108 -36
  319. package/src/transports/dash/init_segment_loader.ts +5 -0
  320. package/src/transports/dash/manifest_parser.ts +6 -0
  321. package/src/transports/dash/segment_loader.ts +1 -0
  322. package/src/transports/dash/text_loader.ts +2 -0
  323. package/src/transports/metaplaylist/manifest_loader.ts +1 -0
  324. package/src/transports/metaplaylist/pipelines.ts +4 -1
  325. package/src/transports/smooth/pipelines.ts +2 -0
  326. package/src/transports/smooth/segment_loader.ts +1 -0
  327. package/src/transports/types.ts +12 -0
  328. package/src/transports/utils/generate_manifest_loader.ts +3 -0
  329. package/src/utils/request/fetch.ts +35 -8
  330. package/src/utils/request/xhr.ts +45 -14
  331. package/dist/commonjs/parsers/manifest/utils/is_segment_still_available.d.ts +0 -29
  332. package/dist/commonjs/parsers/manifest/utils/is_segment_still_available.js +0 -54
  333. package/dist/es2017/parsers/manifest/utils/is_segment_still_available.d.ts +0 -29
  334. package/dist/es2017/parsers/manifest/utils/is_segment_still_available.js +0 -51
  335. package/src/parsers/manifest/utils/is_segment_still_available.ts +0 -58
  336. package/src/typings/object-assign.d.ts +0 -48
@@ -493,8 +493,8 @@ function doesEndSeemGarbageCollected(
493
493
  currentSeg.end - currentSeg.bufferedEnd > MAX_TIME_MISSING_FROM_COMPLETE_SEGMENT)
494
494
  {
495
495
  log.info("Stream: The end of the wanted segment has been garbage collected",
496
- currentSeg.start,
497
- currentSeg.bufferedStart);
496
+ currentSeg.end,
497
+ currentSeg.bufferedEnd);
498
498
  return true;
499
499
  }
500
500
 
@@ -23,6 +23,11 @@ const DEFAULT_CONFIG = {
23
23
  */
24
24
  DEFAULT_REQUEST_TIMEOUT: 30 * 1000,
25
25
 
26
+ /**
27
+ * Default connection time after which a request will timeout, in ms.
28
+ * @type {Number}
29
+ */
30
+ DEFAULT_CONNECTION_TIMEOUT: 15 * 1000,
26
31
  /**
27
32
  * Can be either:
28
33
  * - "native": Subtitles are all displayed in a <track> element
@@ -158,6 +163,23 @@ const DEFAULT_CONFIG = {
158
163
  } as Partial<Record<"audio"|"video"|"text", number>>,
159
164
  /* eslint-enable @typescript-eslint/consistent-type-assertions */
160
165
 
166
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
167
+ /**
168
+ * Minimum possible buffer ahead for each type of buffer, to avoid Garbage
169
+ * Collecting too much data when it would have adverse effects.
170
+ * Equal to `0` if not defined here.
171
+ * @type {Object}
172
+ */
173
+ MINIMUM_MAX_BUFFER_AHEAD: {
174
+ // Text segments are both much lighter on resources and might
175
+ // actually be much larger than other types of segments in terms
176
+ // of duration. Let's make an exception here by authorizing a
177
+ // larger text buffer ahead, to avoid unnecesarily reloading the
178
+ // same text track.
179
+ text: 2 * 60,
180
+ } as Partial<Record<"audio"|"video"|"image"|"text", number>>,
181
+ /* eslint-enable @typescript-eslint/consistent-type-assertions */
182
+
161
183
  /* eslint-disable @typescript-eslint/consistent-type-assertions */
162
184
  /**
163
185
  * Maximum possible buffer behind for each type of buffer, to avoid too much
@@ -231,23 +253,6 @@ const DEFAULT_CONFIG = {
231
253
  */
232
254
  BUFFER_DISCONTINUITY_THRESHOLD: 0.2,
233
255
 
234
- /**
235
- * When encountering small discontinuities, the RxPlayer may want, in specific
236
- * conditions, ignore those and let the browser seek over them iself (this
237
- * allows for example to avoid conflicts when both the browser and the
238
- * RxPlayer want to seek at a different position, sometimes leading to a
239
- * seeking loop).
240
- * In this case, we however still want to seek it ourselves if the browser
241
- * doesn't take the opportunity soon enough.
242
- *
243
- * This value specifies a delay after which a discontinuity ignored by the
244
- * RxPlayer is finally considered.
245
- * We want to maintain high enough to be sure the browser will not seek yet
246
- * small enough so this (arguably rare) situation won't lead to too much
247
- * waiting time.
248
- */
249
- FORCE_DISCONTINUITY_SEEK_DELAY: 5000,
250
-
251
256
  /**
252
257
  * Ratio used to know if an already loaded segment should be re-buffered.
253
258
  * We re-load the given segment if the current one times that ratio is
@@ -177,7 +177,9 @@ export default class VideoThumbnailLoader {
177
177
  { baseDelay: 0,
178
178
  maxDelay: 0,
179
179
  maxRetry: 0,
180
- requestTimeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT }
180
+ requestTimeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT,
181
+ connectionTimeout: config.getCurrent().DEFAULT_CONNECTION_TIMEOUT,
182
+ }
181
183
  ) as ISegmentFetcher<ArrayBuffer | Uint8Array>;
182
184
  const initSegment = content.representation.index.getInitSegment();
183
185
  const initSegmentUniqueId = initSegment !== null ?
@@ -83,6 +83,7 @@ async function getDurationFromManifest(
83
83
  url,
84
84
  responseType: "document",
85
85
  timeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT,
86
+ connectionTimeout: config.getCurrent().DEFAULT_CONNECTION_TIMEOUT,
86
87
  // We won't cancel
87
88
  cancelSignal: new TaskCanceller().signal,
88
89
  });
@@ -122,6 +123,7 @@ async function getDurationFromManifest(
122
123
  url,
123
124
  responseType: "text",
124
125
  timeout: config.getCurrent().DEFAULT_REQUEST_TIMEOUT,
126
+ connectionTimeout: config.getCurrent().DEFAULT_CONNECTION_TIMEOUT,
125
127
  // We won't cancel
126
128
  cancelSignal: new TaskCanceller().signal,
127
129
  });
@@ -157,7 +157,8 @@ export default class Adaptation {
157
157
  const reprObject : IRepresentationFilterRepresentation = {
158
158
  id: representation.id,
159
159
  bitrate: representation.bitrate,
160
- codec: representation.codec,
160
+ codecs: representation.codec === undefined ? [] :
161
+ [representation.codec],
161
162
  height: representation.height,
162
163
  width: representation.width,
163
164
  frameRate: representation.frameRate,
@@ -137,8 +137,8 @@ export default class StaticRepresentationIndex implements IRepresentationIndex {
137
137
  /**
138
138
  * @returns {Boolean}
139
139
  */
140
- isFinished() : true {
141
- return true;
140
+ isStillAwaitingFutureSegments() : false {
141
+ return false;
142
142
  }
143
143
 
144
144
  /**
@@ -329,7 +329,7 @@ export interface IRepresentationIndex {
329
329
 
330
330
  /**
331
331
  * Returns the ending time, in seconds, of the Representation once it is
332
- * "finished" (@see isFinished).
332
+ * "finished" (@see isStillAwaitingFutureSegments).
333
333
  * Should thus be equivalent to `getLastAvailablePosition` once finished.
334
334
  *
335
335
  * Returns `null` if nothing is in the index
@@ -381,13 +381,13 @@ export interface IRepresentationIndex {
381
381
  checkDiscontinuity(time : number) : number | null;
382
382
 
383
383
  /**
384
- * Returns `true` if the last segments in this index have already been
384
+ * Returns `false` if the last segments in this index have already been
385
385
  * generated so that we can freely go to the next period.
386
- * Returns `false` if the index is still waiting on future segments to be
386
+ * Returns `true` if the index is still waiting on future segments to be
387
387
  * generated.
388
388
  * @returns {boolean}
389
389
  */
390
- isFinished() : boolean;
390
+ isStillAwaitingFutureSegments() : boolean;
391
391
 
392
392
  /**
393
393
  * Returns `true` if this index has all the data it needs to give the list
@@ -18,39 +18,46 @@ import ManifestBoundsCalculator from "../manifest_bounds_calculator";
18
18
 
19
19
  describe("DASH parsers - ManifestBoundsCalculator", () => {
20
20
  /* eslint-disable max-len */
21
- it("should return undefined through `estimateMinimumBound` if the live edge was never set for a dynamic content with a timeShiftBufferDepth", () => {
21
+ it("should return undefined through `getEstimatedMinimumSegmentTime` if the live edge was never set for a dynamic content with a timeShiftBufferDepth", () => {
22
22
  /* eslint-enable max-len */
23
23
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
24
24
  isDynamic: true,
25
25
  timeShiftBufferDepth: 5,
26
+ availabilityStartTime: 0,
27
+ serverTimestampOffset: undefined,
26
28
  });
27
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(undefined);
28
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(undefined);
29
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(undefined);
29
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(undefined);
30
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(undefined);
31
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(undefined);
30
32
  });
31
33
 
32
34
  /* eslint-disable max-len */
33
- it("should return 0 through `estimateMinimumBound` if the live edge was never set for a static content", () => {
35
+ it("should return 0 through `getEstimatedMinimumSegmentTime` for a static content", () => {
34
36
  /* eslint-enable max-len */
35
37
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
36
38
  isDynamic: false,
37
39
  timeShiftBufferDepth: 5,
40
+ availabilityStartTime: 0,
41
+ serverTimestampOffset: 555555,
38
42
  });
39
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
40
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
41
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
43
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
44
+ manifestBoundsCalculator.setLastPosition(5555, 2135);
45
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
46
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
42
47
  });
43
48
 
44
49
  /* eslint-disable max-len */
45
- it("should return 0 through `estimateMinimumBound` if the live edge was never set for a dynamic content with no timeShiftBufferDepth", () => {
50
+ it("should return 0 through `getEstimatedMinimumSegmentTime` if the `serverTimestampOffset` was never set nor the last position for a dynamic content with no timeShiftBufferDepth", () => {
46
51
  /* eslint-enable max-len */
47
52
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
48
53
  isDynamic: false,
49
54
  timeShiftBufferDepth: undefined,
55
+ availabilityStartTime: 0,
56
+ serverTimestampOffset: undefined,
50
57
  });
51
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
52
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
53
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
58
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
59
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
60
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(0);
54
61
  });
55
62
 
56
63
  /* eslint-disable max-len */
@@ -59,9 +66,11 @@ describe("DASH parsers - ManifestBoundsCalculator", () => {
59
66
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
60
67
  isDynamic: true,
61
68
  timeShiftBufferDepth: 5,
69
+ availabilityStartTime: 0,
70
+ serverTimestampOffset: undefined,
62
71
  });
63
72
  expect(manifestBoundsCalculator.lastPositionIsKnown()).toEqual(false);
64
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(undefined);
73
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(undefined);
65
74
  expect(manifestBoundsCalculator.lastPositionIsKnown()).toEqual(false);
66
75
  });
67
76
 
@@ -71,6 +80,8 @@ describe("DASH parsers - ManifestBoundsCalculator", () => {
71
80
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
72
81
  isDynamic: true,
73
82
  timeShiftBufferDepth: 5,
83
+ availabilityStartTime: 0,
84
+ serverTimestampOffset: undefined,
74
85
  });
75
86
  manifestBoundsCalculator.setLastPosition(1000, 0);
76
87
  expect(manifestBoundsCalculator.lastPositionIsKnown()).toEqual(true);
@@ -82,63 +93,198 @@ describe("DASH parsers - ManifestBoundsCalculator", () => {
82
93
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
83
94
  isDynamic: false,
84
95
  timeShiftBufferDepth: 5,
96
+ availabilityStartTime: 0,
97
+ serverTimestampOffset: undefined,
85
98
  });
86
99
  manifestBoundsCalculator.setLastPosition(1000, 0);
87
100
  expect(manifestBoundsCalculator.lastPositionIsKnown()).toEqual(true);
88
101
  });
89
102
 
90
103
  /* eslint-disable max-len */
91
- it("should return how much time has elapsed through `estimateMinimumBound` since the live edge was set for a dynamic content", () => {
104
+ it("should return how much time has elapsed through `getEstimatedMinimumSegmentTime` since the last position was set for a dynamic content", () => {
92
105
  /* eslint-enable max-len */
93
- let date = 5000;
106
+ let performanceNow = 5000;
94
107
  const mockPerformanceNow = jest.spyOn(performance, "now")
95
- .mockImplementation(jest.fn(() => date));
108
+ .mockImplementation(jest.fn(() => performanceNow));
96
109
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
97
110
  isDynamic: true,
98
111
  timeShiftBufferDepth: 5,
112
+ availabilityStartTime: 0,
113
+ serverTimestampOffset: undefined,
99
114
  });
100
115
  manifestBoundsCalculator.setLastPosition(1000, 10);
101
- date = 25000;
102
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(1010);
103
- date = 35000;
104
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(1020);
116
+ performanceNow = 25000;
117
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(1010);
118
+ performanceNow = 35000;
119
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(1020);
105
120
  mockPerformanceNow.mockRestore();
106
121
  });
107
122
 
108
123
  /* eslint-disable max-len */
109
- it("should return 0 even when a last position has been set for a static content", () => {
124
+ it("should prefer relying on the live edge for `getEstimatedMinimumSegmentTime` if it was set", () => {
110
125
  /* eslint-enable max-len */
111
- let date = 5000;
126
+ let performanceNow = 5000;
112
127
  const mockPerformanceNow = jest.spyOn(performance, "now")
113
- .mockImplementation(jest.fn(() => date));
128
+ .mockImplementation(jest.fn(() => performanceNow));
114
129
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
115
- isDynamic: false,
116
- timeShiftBufferDepth: 5,
130
+ isDynamic: true,
131
+ timeShiftBufferDepth: 3,
132
+ availabilityStartTime: 4,
133
+ serverTimestampOffset: 7000,
117
134
  });
118
- manifestBoundsCalculator.setLastPosition(1000, 0);
119
- date = 25000;
120
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
121
- date = 35000;
122
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(0);
135
+ manifestBoundsCalculator.setLastPosition(3000, 10);
136
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime())
137
+ .toEqual(7 + 5 - 4 - 3);
138
+ performanceNow = 25000;
139
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime())
140
+ .toEqual(7 + 25 - 4 - 3);
141
+ performanceNow = 35000;
142
+ manifestBoundsCalculator.setLastPosition(84546464, 5642);
143
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime())
144
+ .toEqual(7 + 35 - 4 - 3);
123
145
  mockPerformanceNow.mockRestore();
124
146
  });
125
147
 
126
148
  /* eslint-disable max-len */
127
149
  it("should authorize and handle multiple `setLastPositionOffset` calls for dynamic contents", () => {
128
150
  /* eslint-enable max-len */
129
- let date = 5000;
151
+ let performanceNow = 5000;
130
152
  const mockPerformanceNow = jest.spyOn(performance, "now")
131
- .mockImplementation(jest.fn(() => date));
153
+ .mockImplementation(jest.fn(() => performanceNow));
132
154
  const manifestBoundsCalculator = new ManifestBoundsCalculator({
133
155
  isDynamic: true,
134
156
  timeShiftBufferDepth: 5,
157
+ availabilityStartTime: 0,
158
+ serverTimestampOffset: undefined,
135
159
  });
136
160
  manifestBoundsCalculator.setLastPosition(1000, 0);
137
- date = 50000;
138
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(1045);
161
+ performanceNow = 50000;
162
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(1045);
139
163
  manifestBoundsCalculator.setLastPosition(0, 0);
140
- date = 55000;
141
- expect(manifestBoundsCalculator.estimateMinimumBound()).toEqual(50);
164
+ performanceNow = 55000;
165
+ expect(manifestBoundsCalculator.getEstimatedMinimumSegmentTime()).toEqual(50);
166
+ mockPerformanceNow.mockRestore();
167
+ });
168
+
169
+ /* eslint-disable max-len */
170
+ it("`getEstimatedMaximumPosition` should be based on the last position on on-dynamic manifest", () => {
171
+ /* eslint-enable max-len */
172
+ let performanceNow = 5000;
173
+ const mockPerformanceNow = jest.spyOn(performance, "now")
174
+ .mockImplementation(jest.fn(() => performanceNow));
175
+ const manifestBoundsCalculator1 = new ManifestBoundsCalculator({
176
+ isDynamic: false,
177
+ timeShiftBufferDepth: 5,
178
+ availabilityStartTime: 0,
179
+ serverTimestampOffset: undefined,
180
+ });
181
+ const manifestBoundsCalculator2 = new ManifestBoundsCalculator({
182
+ isDynamic: false,
183
+ timeShiftBufferDepth: 5,
184
+ availabilityStartTime: 0,
185
+ serverTimestampOffset: 10,
186
+ });
187
+ manifestBoundsCalculator1.setLastPosition(1000, 0);
188
+ manifestBoundsCalculator2.setLastPosition(1000, 0);
189
+ performanceNow = 50000;
190
+ expect(manifestBoundsCalculator1.getEstimatedMaximumPosition(10)).toEqual(1000);
191
+ expect(manifestBoundsCalculator2.getEstimatedMaximumPosition(19)).toEqual(1000);
192
+ performanceNow = 55000;
193
+ expect(manifestBoundsCalculator1.getEstimatedMaximumPosition(98)).toEqual(1000);
194
+ expect(manifestBoundsCalculator2.getEstimatedMaximumPosition(93)).toEqual(1000);
195
+ manifestBoundsCalculator1.setLastPosition(0, 0);
196
+ manifestBoundsCalculator2.setLastPosition(0, 0);
197
+ expect(manifestBoundsCalculator1.getEstimatedMaximumPosition(43)).toEqual(0);
198
+ expect(manifestBoundsCalculator2.getEstimatedMaximumPosition(421)).toEqual(0);
199
+ mockPerformanceNow.mockRestore();
200
+ });
201
+
202
+ /* eslint-disable max-len */
203
+ it("`getEstimatedMaximumPosition` should evolve based on the last position on dynamic manifest without `serverTimestampOffset`", () => {
204
+ /* eslint-enable max-len */
205
+ let performanceNow = 5000;
206
+ const mockPerformanceNow = jest.spyOn(performance, "now")
207
+ .mockImplementation(jest.fn(() => performanceNow));
208
+ const manifestBoundsCalculator = new ManifestBoundsCalculator({
209
+ isDynamic: true,
210
+ timeShiftBufferDepth: 5,
211
+ availabilityStartTime: 7,
212
+ serverTimestampOffset: undefined,
213
+ });
214
+ manifestBoundsCalculator.setLastPosition(1050, 0);
215
+ performanceNow = 50000;
216
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(10)).toEqual(1050 + 50);
217
+ performanceNow = 55000;
218
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(98)).toEqual(1050 + 55);
219
+ manifestBoundsCalculator.setLastPosition(0, 10);
220
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(43)).toEqual(0 + 55 - 10);
221
+ mockPerformanceNow.mockRestore();
222
+ });
223
+
224
+ it("should not return a live edge if `serverTimestampOffset` isn't set", () => {
225
+ const manifestBoundsCalculator = new ManifestBoundsCalculator({
226
+ isDynamic: true,
227
+ timeShiftBufferDepth: 5,
228
+ availabilityStartTime: 0,
229
+ serverTimestampOffset: undefined,
230
+ });
231
+ manifestBoundsCalculator.setLastPosition(1000, 0);
232
+ expect(manifestBoundsCalculator.getEstimatedLiveEdge()).toEqual(undefined);
233
+ });
234
+
235
+ it("should not return a live edge if the manifest is not dynamic", () => {
236
+ const manifestBoundsCalculator = new ManifestBoundsCalculator({
237
+ isDynamic: false,
238
+ timeShiftBufferDepth: 5,
239
+ availabilityStartTime: 0,
240
+ serverTimestampOffset: 100,
241
+ });
242
+ manifestBoundsCalculator.setLastPosition(1000, 0);
243
+ expect(manifestBoundsCalculator.getEstimatedLiveEdge()).toEqual(undefined);
244
+ });
245
+
246
+ it("should rely on `serverTimestampOffset` to produce live edge if set", () => {
247
+ let performanceNow = 3000;
248
+ const mockPerformanceNow = jest.spyOn(performance, "now")
249
+ .mockImplementation(jest.fn(() => performanceNow));
250
+ const manifestBoundsCalculator = new ManifestBoundsCalculator({
251
+ isDynamic: true,
252
+ timeShiftBufferDepth: 5,
253
+ availabilityStartTime: 2,
254
+ serverTimestampOffset: 5000,
255
+ });
256
+ expect(manifestBoundsCalculator.getEstimatedLiveEdge()).toEqual(3 + 5 - 2);
257
+ manifestBoundsCalculator.setLastPosition(1000, 0);
258
+ expect(manifestBoundsCalculator.getEstimatedLiveEdge()).toEqual(3 + 5 - 2);
259
+ performanceNow = 9000;
260
+ expect(manifestBoundsCalculator.getEstimatedLiveEdge()).toEqual(9 + 5 - 2);
261
+ mockPerformanceNow.mockRestore();
262
+ });
263
+
264
+ /* eslint-disable max-len */
265
+ it("`getEstimatedMaximumPosition` should evolve based on the live edge position on dynamic manifest with `serverTimestampOffset`", () => {
266
+ /* eslint-enable max-len */
267
+ let performanceNow = 5000;
268
+ const mockPerformanceNow = jest.spyOn(performance, "now")
269
+ .mockImplementation(jest.fn(() => performanceNow));
270
+ const manifestBoundsCalculator = new ManifestBoundsCalculator({
271
+ isDynamic: true,
272
+ timeShiftBufferDepth: 3,
273
+ availabilityStartTime: 7,
274
+ serverTimestampOffset: 1000,
275
+ });
276
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(4))
277
+ .toEqual(5 + 1 - 7 + 4);
278
+ manifestBoundsCalculator.setLastPosition(1050, 0);
279
+ performanceNow = 70000;
280
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(11))
281
+ .toEqual(5 + 1 - 7 + 11 + 70 - 5);
282
+ performanceNow = 85000;
283
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(98))
284
+ .toEqual(5 + 1 - 7 + 98 + 85 - 5);
285
+ manifestBoundsCalculator.setLastPosition(0, 10);
286
+ expect(manifestBoundsCalculator.getEstimatedMaximumPosition(43))
287
+ .toEqual(5 + 1 - 7 + 43 + 85 - 5);
142
288
  mockPerformanceNow.mockRestore();
143
289
  });
144
290
  });
@@ -27,6 +27,7 @@ import {
27
27
  IIndexSegment,
28
28
  toIndexTime,
29
29
  } from "../../../utils/index_helpers";
30
+ import ManifestBoundsCalculator from "../manifest_bounds_calculator";
30
31
  import getInitSegment from "./get_init_segment";
31
32
  import getSegmentsFromTimeline from "./get_segments_from_timeline";
32
33
  import { constructRepresentationUrl } from "./tokens";
@@ -121,6 +122,8 @@ export interface IBaseIndexContextArgument {
121
122
  representationId? : string | undefined;
122
123
  /** Bitrate of the Representation concerned. */
123
124
  representationBitrate? : number | undefined;
125
+ /** Allows to obtain the minimum and maximum positions of a content. */
126
+ manifestBoundsCalculator : ManifestBoundsCalculator;
124
127
  /* Function that tells if an EMSG is whitelisted by the manifest */
125
128
  isEMSGWhitelisted: (inbandEvent: IEMSG) => boolean;
126
129
  }
@@ -180,6 +183,9 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
180
183
  /** Absolute end of the period, timescaled and converted to index time. */
181
184
  private _scaledPeriodEnd : number | undefined;
182
185
 
186
+ /** Allows to obtain the minimum and maximum positions of a content. */
187
+ private _manifestBoundsCalculator : ManifestBoundsCalculator;
188
+
183
189
  /* Function that tells if an EMSG is whitelisted by the manifest */
184
190
  private _isEMSGWhitelisted: (inbandEvent: IEMSG) => boolean;
185
191
 
@@ -229,6 +235,7 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
229
235
  endNumber: index.endNumber,
230
236
  timeline: index.timeline ?? [],
231
237
  timescale };
238
+ this._manifestBoundsCalculator = context.manifestBoundsCalculator;
232
239
  this._scaledPeriodStart = toIndexTime(periodStart, this._index);
233
240
  this._scaledPeriodEnd = periodEnd == null ? undefined :
234
241
  toIndexTime(periodEnd, this._index);
@@ -262,8 +269,9 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
262
269
  return getSegmentsFromTimeline(this._index,
263
270
  from,
264
271
  dur,
265
- this._isEMSGWhitelisted,
266
- this._scaledPeriodEnd);
272
+ this._manifestBoundsCalculator,
273
+ this._scaledPeriodEnd,
274
+ this._isEMSGWhitelisted);
267
275
  }
268
276
 
269
277
  /**
@@ -360,8 +368,8 @@ export default class BaseRepresentationIndex implements IRepresentationIndex {
360
368
  * should become available in the future.
361
369
  * @returns {Boolean}
362
370
  */
363
- isFinished() : true {
364
- return true;
371
+ isStillAwaitingFutureSegments() : false {
372
+ return false;
365
373
  }
366
374
 
367
375
  /**
@@ -21,6 +21,7 @@ import {
21
21
  IIndexSegment,
22
22
  toIndexTime,
23
23
  } from "../../../utils/index_helpers";
24
+ import ManifestBoundsCalculator from "../manifest_bounds_calculator";
24
25
  import { createDashUrlDetokenizer } from "./tokens";
25
26
 
26
27
  /**
@@ -47,12 +48,14 @@ function getWantedRepeatIndex(
47
48
  * @param {Object} index - index object, constructed by parsing the manifest.
48
49
  * @param {number} from - starting timestamp wanted, in seconds
49
50
  * @param {number} durationWanted - duration wanted, in seconds
51
+ * @param {Object} manifestBoundsCalculator
52
+ * @param {number|undefined} scaledPeriodEnd
50
53
  * @param {function} isEMSGWhitelisted
51
- * @param {number|undefined} maximumTime
52
54
  * @returns {Array.<Object>}
53
55
  */
54
56
  export default function getSegmentsFromTimeline(
55
57
  index : { availabilityTimeComplete? : boolean | undefined;
58
+ availabilityTimeOffset? : number | undefined;
56
59
  segmentUrlTemplate : string | null;
57
60
  startNumber? : number | undefined;
58
61
  endNumber? : number | undefined;
@@ -61,11 +64,16 @@ export default function getSegmentsFromTimeline(
61
64
  indexTimeOffset : number; },
62
65
  from : number,
63
66
  durationWanted : number,
64
- isEMSGWhitelisted: (inbandEvent: IEMSG) => boolean,
65
- maximumTime? : number
67
+ manifestBoundsCalculator : ManifestBoundsCalculator,
68
+ scaledPeriodEnd : number | undefined,
69
+ isEMSGWhitelisted: (inbandEvent: IEMSG) => boolean
66
70
  ) : ISegment[] {
71
+ const maximumTime = manifestBoundsCalculator.getEstimatedMaximumPosition(
72
+ index.availabilityTimeOffset ?? 0
73
+ );
74
+ const wantedMaximum = Math.min(from + durationWanted, maximumTime ?? Infinity);
67
75
  const scaledUp = toIndexTime(from, index);
68
- const scaledTo = toIndexTime(from + durationWanted, index);
76
+ const scaledTo = toIndexTime(wantedMaximum, index);
69
77
  const { timeline, timescale, segmentUrlTemplate, startNumber, endNumber } = index;
70
78
 
71
79
  let currentNumber = startNumber ?? 1;
@@ -77,7 +85,13 @@ export default function getSegmentsFromTimeline(
77
85
  const timelineItem = timeline[i];
78
86
  const { duration, start, range } = timelineItem;
79
87
 
80
- const repeat = calculateRepeat(timelineItem, timeline[i + 1], maximumTime);
88
+ let maxRepeatTime;
89
+ if (maximumTime === undefined) {
90
+ maxRepeatTime = scaledPeriodEnd;
91
+ } else {
92
+ maxRepeatTime = Math.min(maximumTime * timescale, scaledPeriodEnd ?? Infinity);
93
+ }
94
+ const repeat = calculateRepeat(timelineItem, timeline[i + 1], maxRepeatTime);
81
95
  const complete = index.availabilityTimeComplete !== false ||
82
96
  i !== timelineLength - 1 &&
83
97
  repeat !== 0;
@@ -14,14 +14,26 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import BaseRepresentationIndex from "./base";
18
- import ListRepresentationIndex from "./list";
19
- import TemplateRepresentationIndex from "./template";
20
- import TimelineRepresentationIndex from "./timeline";
17
+ import BaseRepresentationIndex, {
18
+ IBaseIndexContextArgument,
19
+ } from "./base";
20
+ import ListRepresentationIndex, {
21
+ IListIndexContextArgument,
22
+ } from "./list";
23
+ import TemplateRepresentationIndex, {
24
+ ITemplateIndexContextArgument,
25
+ } from "./template";
26
+ import TimelineRepresentationIndex, {
27
+ ITimelineIndexContextArgument,
28
+ } from "./timeline";
21
29
 
22
30
  export {
23
31
  BaseRepresentationIndex,
24
32
  ListRepresentationIndex,
25
33
  TemplateRepresentationIndex,
26
34
  TimelineRepresentationIndex,
35
+ IBaseIndexContextArgument,
36
+ IListIndexContextArgument,
37
+ ITemplateIndexContextArgument,
38
+ ITimelineIndexContextArgument,
27
39
  };
@@ -314,8 +314,8 @@ export default class ListRepresentationIndex implements IRepresentationIndex {
314
314
  /**
315
315
  * @returns {Boolean}
316
316
  */
317
- isFinished() : true {
318
- return true;
317
+ isStillAwaitingFutureSegments() : false {
318
+ return false;
319
319
  }
320
320
 
321
321
  /**