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
@@ -34,7 +34,6 @@ import {
34
34
  IIndexSegment,
35
35
  toIndexTime,
36
36
  } from "../../../../utils/index_helpers";
37
- import isSegmentStillAvailable from "../../../../utils/is_segment_still_available";
38
37
  import updateSegmentTimeline from "../../../../utils/update_segment_timeline";
39
38
  import { ISegmentTimelineElement } from "../../../node_parser_types";
40
39
  import ManifestBoundsCalculator from "../../manifest_bounds_calculator";
@@ -54,6 +53,8 @@ import constructTimelineFromPreviousTimeline from "./construct_timeline_from_pre
54
53
  export interface ITimelineIndex {
55
54
  /** If `false`, the last segment anounced might be still incomplete. */
56
55
  availabilityTimeComplete : boolean;
56
+ /** Minimum availabilityTimeOffset concerning the segments of this Representation. */
57
+ availabilityTimeOffset : number;
57
58
  /** Byte range for a possible index of segments in the server. */
58
59
  indexRange?: [number, number] | undefined;
59
60
  /**
@@ -152,8 +153,25 @@ export interface ITimelineIndexIndexArgument {
152
153
 
153
154
  /** Aditional context needed by a SegmentTimeline RepresentationIndex. */
154
155
  export interface ITimelineIndexContextArgument {
155
- /** If `false`, the last segment anounced might be still incomplete. */
156
- availabilityTimeComplete : boolean;
156
+ /**
157
+ * If `false`, declared segments in the MPD might still be not completely generated.
158
+ * If `true`, they are completely generated.
159
+ *
160
+ * If `undefined`, the corresponding property was not set in the MPD and it is
161
+ * thus assumed that they are all generated.
162
+ * It might however be semantically different than `true` in the RxPlayer as it
163
+ * means that the packager didn't include that information in the MPD.
164
+ */
165
+ availabilityTimeComplete : boolean | undefined;
166
+ /**
167
+ * availability time offset of the concerned Adaptation.
168
+ *
169
+ * If `undefined`, the corresponding property was not set in the MPD and it is
170
+ * thus assumed to be equal to `0`.
171
+ * It might however be semantically different than `0` in the RxPlayer as it
172
+ * means that the packager didn't include that information in the MPD.
173
+ */
174
+ availabilityTimeOffset : number | undefined;
157
175
  /** Allows to obtain the minimum and maximum positions of a content. */
158
176
  manifestBoundsCalculator : ManifestBoundsCalculator;
159
177
  /** Start of the period linked to this RepresentationIndex, in seconds. */
@@ -196,6 +214,11 @@ export interface ILastSegmentInformation {
196
214
  time : number;
197
215
  }
198
216
 
217
+ /**
218
+ * `IRepresentationIndex` implementation for a DASH `SegmentTimeline` segment
219
+ * indexing scheme.
220
+ * @class TimelineRepresentationIndex
221
+ */
199
222
  export default class TimelineRepresentationIndex implements IRepresentationIndex {
200
223
  /** Underlying structure to retrieve segment information. */
201
224
  protected _index : ITimelineIndex;
@@ -253,6 +276,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
253
276
  "TimelineRepresentationIndex.");
254
277
  }
255
278
  const { availabilityTimeComplete,
279
+ availabilityTimeOffset,
256
280
  manifestBoundsCalculator,
257
281
  isDynamic,
258
282
  isLastPeriod,
@@ -301,7 +325,29 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
301
325
  const segmentUrlTemplate = index.media === undefined ?
302
326
  null :
303
327
  constructRepresentationUrl(index.media, representationId, representationBitrate);
304
- this._index = { availabilityTimeComplete,
328
+
329
+ let actualAvailabilityTimeOffset;
330
+ // Technically, it seems (although it is not clear) that an MPD may contain
331
+ // future segments and it's the job of a player to not request segments later
332
+ // than the time at which they should be available.
333
+ // In practice, we don't do that for various reasons: precision issues,
334
+ // various DASH spec interpretations by packagers and players...
335
+ //
336
+ // So as a compromise, if nothing in the MPD indicates that future segments
337
+ // may be announced (see code below), we will act as if ALL segments in this
338
+ // TimelineRepresentationIndex are requestable
339
+ if (
340
+ availabilityTimeOffset === undefined &&
341
+ availabilityTimeComplete === undefined
342
+ ) {
343
+ actualAvailabilityTimeOffset = Infinity; // Meaning: we can request
344
+ // everything in the index
345
+ } else {
346
+ actualAvailabilityTimeOffset = availabilityTimeOffset ?? 0;
347
+ }
348
+
349
+ this._index = { availabilityTimeComplete: availabilityTimeComplete ?? true,
350
+ availabilityTimeOffset: actualAvailabilityTimeOffset,
305
351
  indexRange: index.indexRange,
306
352
  indexTimeOffset,
307
353
  initialization: index.initialization == null ?
@@ -319,6 +365,7 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
319
365
  index.startNumber,
320
366
  index.endNumber),
321
367
  timescale };
368
+
322
369
  this._scaledPeriodStart = toIndexTime(periodStart, this._index);
323
370
  this._scaledPeriodEnd = periodEnd === undefined ? undefined :
324
371
  toIndexTime(periodEnd, this._index);
@@ -359,8 +406,9 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
359
406
  indexTimeOffset },
360
407
  from,
361
408
  duration,
362
- this._isEMSGWhitelisted,
363
- this._scaledPeriodEnd);
409
+ this._manifestBoundsCalculator,
410
+ this._scaledPeriodEnd,
411
+ this._isEMSGWhitelisted);
364
412
  }
365
413
 
366
414
  /**
@@ -402,10 +450,19 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
402
450
  if (this._index.timeline === null) {
403
451
  this._index.timeline = this._getTimeline();
404
452
  }
405
- const lastTime = TimelineRepresentationIndex.getIndexEnd(this._index.timeline,
406
- this._scaledPeriodEnd);
407
- return lastTime === null ? null :
408
- fromIndexTime(lastTime, this._index);
453
+
454
+ const lastReqSegInfo = getLastRequestableSegmentInfo(
455
+ // Needed typecast for TypeScript
456
+ this._index as typeof this._index & { timeline: IIndexSegment[] },
457
+ this._manifestBoundsCalculator,
458
+ this._scaledPeriodEnd
459
+ );
460
+ if (lastReqSegInfo === null) {
461
+ return null;
462
+ }
463
+ const lastScaledPosition = Math.min(lastReqSegInfo.end,
464
+ this._scaledPeriodEnd ?? Infinity);
465
+ return fromIndexTime(lastScaledPosition, this._index);
409
466
  }
410
467
 
411
468
  /**
@@ -414,10 +471,23 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
414
471
  * @returns {number|null|undefined}
415
472
  */
416
473
  getEnd(): number | undefined | null {
417
- if (!this._isDynamic || !this._isLastPeriod) { // @see isFinished
418
- return this.getLastAvailablePosition();
474
+ if (this._isDynamic && !this._isLastPeriod) {
475
+ return undefined;
476
+ }
477
+
478
+ this._refreshTimeline();
479
+ if (this._index.timeline === null) {
480
+ this._index.timeline = this._getTimeline();
481
+ }
482
+ if (this._index.timeline.length <= 0) {
483
+ return null;
419
484
  }
420
- return undefined;
485
+ const lastSegment = this._index.timeline[this._index.timeline.length - 1];
486
+ const lastTime = Math.min(getIndexSegmentEnd(lastSegment,
487
+ null,
488
+ this._scaledPeriodEnd),
489
+ this._scaledPeriodEnd ?? Infinity);
490
+ return fromIndexTime(lastTime, this._index);
421
491
  }
422
492
 
423
493
  /**
@@ -433,33 +503,67 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
433
503
  */
434
504
  awaitSegmentBetween(start: number, end: number): boolean | undefined {
435
505
  assert(start <= end);
436
- if (!this._isDynamic || !this._isLastPeriod) {
437
- return false;
506
+ if (!this._isDynamic) {
507
+ return false; // No segment will be newly available in the future
438
508
  }
509
+
439
510
  this._refreshTimeline();
440
511
  if (this._index.timeline === null) {
441
512
  this._index.timeline = this._getTimeline();
442
513
  }
443
- const { timeline, timescale } = this._index;
514
+ const { timescale, timeline } = this._index;
444
515
  const segmentTimeRounding = getSegmentTimeRoundingError(timescale);
445
- const scaledEnd = toIndexTime(end, this._index);
446
- if (timeline.length > 0) {
447
- const lastTimelineElement = timeline[timeline.length - 1];
448
- const lastSegmentEnd = getIndexSegmentEnd(lastTimelineElement,
516
+ const scaledWantedEnd = toIndexTime(end, this._index);
517
+ const lastReqSegInfo = getLastRequestableSegmentInfo(
518
+ // Needed typecast for TypeScript
519
+ this._index as typeof this._index & { timeline: IIndexSegment[] },
520
+ this._manifestBoundsCalculator,
521
+ this._scaledPeriodEnd
522
+ );
523
+ if (lastReqSegInfo !== null) {
524
+ const lastReqSegmentEnd = Math.min(lastReqSegInfo.end,
525
+ this._scaledPeriodEnd ?? Infinity);
526
+ const roundedReqSegmentEnd = lastReqSegmentEnd + segmentTimeRounding;
527
+ if (roundedReqSegmentEnd >= Math.min(scaledWantedEnd,
528
+ this._scaledPeriodEnd ?? Infinity))
529
+ {
530
+ return false; // everything up to that point is already requestable
531
+ }
532
+ }
533
+
534
+ const scaledWantedStart = toIndexTime(start, this._index);
535
+ if (timeline.length > 0 &&
536
+ lastReqSegInfo !== null &&
537
+ !lastReqSegInfo.isLastOfTimeline)
538
+ {
539
+ // There are some future segments already anounced in the MPD
540
+
541
+ const lastSegment = timeline[timeline.length - 1];
542
+ const lastSegmentEnd = getIndexSegmentEnd(lastSegment,
449
543
  null,
450
544
  this._scaledPeriodEnd);
451
- const roundedEnd = lastSegmentEnd + segmentTimeRounding;
452
- if (roundedEnd >= Math.min(scaledEnd, this._scaledPeriodEnd ?? Infinity)) {
453
- return false; // already loaded
545
+ const roundedLastSegEnd = lastSegmentEnd + segmentTimeRounding;
546
+ if (scaledWantedStart < roundedLastSegEnd + segmentTimeRounding) {
547
+ return true; // The MPD's timeline already contains one such element,
548
+ // It is just not requestable yet
454
549
  }
455
550
  }
551
+
552
+ if (!this._isLastPeriod) {
553
+ // Let's consider - perhaps wrongly, that Periods which aren't the last
554
+ // one have all of their segments announced.
555
+ return false;
556
+ }
557
+
456
558
  if (this._scaledPeriodEnd === undefined) {
457
- return (scaledEnd + segmentTimeRounding) > this._scaledPeriodStart ? undefined :
458
- false;
559
+ return (scaledWantedEnd + segmentTimeRounding) > this._scaledPeriodStart ?
560
+ undefined : // There may be future segments at this point
561
+ false; // Before the current Period
459
562
  }
460
- const scaledStart = toIndexTime(start, this._index);
461
- return (scaledStart - segmentTimeRounding) < this._scaledPeriodEnd &&
462
- (scaledEnd + segmentTimeRounding) > this._scaledPeriodStart;
563
+
564
+ // `true` if within the boundaries of this Period. `false` otherwise.
565
+ return (scaledWantedStart - segmentTimeRounding) < this._scaledPeriodEnd &&
566
+ (scaledWantedEnd + segmentTimeRounding) > this._scaledPeriodStart;
463
567
  }
464
568
 
465
569
  /**
@@ -478,8 +582,13 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
478
582
  if (this._index.timeline === null) {
479
583
  this._index.timeline = this._getTimeline();
480
584
  }
481
- const { timeline, timescale, indexTimeOffset } = this._index;
482
- return isSegmentStillAvailable(segment, timeline, timescale, indexTimeOffset);
585
+ return isSegmentStillAvailable(segment,
586
+ // Needed typecast for TypeScript
587
+ this._index as typeof this._index & {
588
+ timeline: IIndexSegment[];
589
+ },
590
+ this._manifestBoundsCalculator,
591
+ this._scaledPeriodEnd);
483
592
  }
484
593
 
485
594
  /**
@@ -549,6 +658,8 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
549
658
  if (hasReplaced) {
550
659
  this._index.startNumber = newIndex._index.startNumber;
551
660
  }
661
+ this._index.availabilityTimeOffset = newIndex._index.availabilityTimeOffset;
662
+ this._index.availabilityTimeComplete = newIndex._index.availabilityTimeComplete;
552
663
  this._index.endNumber = newIndex._index.endNumber;
553
664
  this._isDynamic = newIndex._isDynamic;
554
665
  this._scaledPeriodStart = newIndex._scaledPeriodStart;
@@ -558,35 +669,80 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
558
669
  }
559
670
 
560
671
  /**
561
- * Returns `true` if this RepresentationIndex currently contains its last
672
+ * Returns `false` if this RepresentationIndex currently contains its last
562
673
  * segment.
563
- * Returns `false` if it's still pending.
674
+ * Returns `true` if it's still pending.
564
675
  * @returns {Boolean}
565
676
  */
566
- isFinished() : boolean {
567
- if (!this._isDynamic || !this._isLastPeriod) {
568
- // Either the content is not dynamic, in which case no new segment will
569
- // be generated, either it is but this index is not linked to the current
570
- // last Period in the MPD, in which case it is inferred that it has been
571
- // completely generated. Note that this second condition might break very
572
- // very rare use cases where old Periods are still being generated, yet it
573
- // should fix more cases than it breaks.
574
- return true;
677
+ isStillAwaitingFutureSegments() : boolean {
678
+ if (!this._isDynamic) {
679
+ return false;
575
680
  }
576
681
 
682
+ this._refreshTimeline();
577
683
  if (this._index.timeline === null) {
578
684
  this._index.timeline = this._getTimeline();
579
685
  }
686
+
580
687
  const { timeline } = this._index;
581
- if (this._scaledPeriodEnd === undefined || timeline.length === 0) {
582
- return false;
688
+ if (timeline.length === 0) {
689
+ // No segment announced in this Period
690
+ if (this._scaledPeriodEnd !== undefined) {
691
+ const liveEdge = this._manifestBoundsCalculator.getEstimatedLiveEdge();
692
+ if (liveEdge !== undefined &&
693
+ toIndexTime(liveEdge, this._index) > this._scaledPeriodEnd)
694
+ {
695
+ // This Period is over, we're not awaiting anything
696
+ return false;
697
+ }
698
+ }
699
+ // Let's just consider that we're awaiting only for when this is the last Period.
700
+ return this._isLastPeriod;
583
701
  }
584
- const lastTimelineElement = timeline[timeline.length - 1];
585
- const lastTime = getIndexSegmentEnd(lastTimelineElement,
586
- null,
587
- this._scaledPeriodEnd);
702
+
588
703
  const segmentTimeRounding = getSegmentTimeRoundingError(this._index.timescale);
589
- return (lastTime + segmentTimeRounding) >= this._scaledPeriodEnd;
704
+ const lastReqSegInfo = getLastRequestableSegmentInfo(
705
+ // Needed typecast for TypeScript
706
+ this._index as typeof this._index & { timeline: IIndexSegment[] },
707
+ this._manifestBoundsCalculator,
708
+ this._scaledPeriodEnd
709
+ );
710
+
711
+ if (lastReqSegInfo !== null && !lastReqSegInfo.isLastOfTimeline) {
712
+ // There might be non-yet requestable segments in the manifest
713
+ const lastReqSegmentEnd = Math.min(lastReqSegInfo.end,
714
+ this._scaledPeriodEnd ?? Infinity);
715
+ if (this._scaledPeriodEnd !== undefined &&
716
+ lastReqSegmentEnd + segmentTimeRounding >= this._scaledPeriodEnd)
717
+ {
718
+ // The last requestable segment ends after the end of the Period anyway
719
+ return false;
720
+ }
721
+ return true; // There are not-yet requestable segments
722
+ }
723
+
724
+ if (!this._isLastPeriod) {
725
+ // This index is not linked to the current last Period in the MPD, in
726
+ // which case it is inferred that all segments have been announced.
727
+ //
728
+ // Note that this condition might break very very rare use cases where old
729
+ // Periods are still being generated, yet it should fix more cases than it
730
+ // breaks.
731
+ return false;
732
+ }
733
+
734
+ if (this._scaledPeriodEnd === undefined) {
735
+ // This is the last Period of a dynamic content whose end is unknown.
736
+ // Just return true.
737
+ return true;
738
+ }
739
+ const lastSegment = timeline[timeline.length - 1];
740
+ const lastSegmentEnd = getIndexSegmentEnd(lastSegment,
741
+ null,
742
+ this._scaledPeriodEnd);
743
+ // We're awaiting future segments only if the current end is before the end
744
+ // of the Period
745
+ return (lastSegmentEnd + segmentTimeRounding) < this._scaledPeriodEnd;
590
746
  }
591
747
 
592
748
  /**
@@ -626,7 +782,8 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
626
782
  if (!this._isDynamic) {
627
783
  return;
628
784
  }
629
- const firstPosition = this._manifestBoundsCalculator.estimateMinimumBound();
785
+ const firstPosition = this._manifestBoundsCalculator
786
+ .getEstimatedMinimumSegmentTime();
630
787
  if (firstPosition == null) {
631
788
  return; // we don't know yet
632
789
  }
@@ -640,17 +797,6 @@ export default class TimelineRepresentationIndex implements IRepresentationIndex
640
797
  }
641
798
  }
642
799
 
643
- static getIndexEnd(timeline : IIndexSegment[],
644
- scaledPeriodEnd : number | undefined) : number | null {
645
- if (timeline.length <= 0) {
646
- return null;
647
- }
648
- return Math.min(getIndexSegmentEnd(timeline[timeline.length - 1],
649
- null,
650
- scaledPeriodEnd),
651
- scaledPeriodEnd ?? Infinity);
652
- }
653
-
654
800
  /**
655
801
  * Allows to generate the "timeline" for this RepresentationIndex.
656
802
  * Call this function when the timeline is unknown.
@@ -752,3 +898,163 @@ function updateTimelineFromEndNumber(
752
898
  }
753
899
  return timeline;
754
900
  }
901
+
902
+ /**
903
+ * Returns true if a Segment returned by the corresponding index is still
904
+ * considered available.
905
+ * Returns false if it is not available anymore.
906
+ * Returns undefined if we cannot know whether it is still available or not.
907
+ * /!\ We do not check the mediaURLs of the segment.
908
+ * @param {Object} segment
909
+ * @param {Object} index
910
+ * @param {Object} manifestBoundsCalculator
911
+ * @param {number|undefined} scaledPeriodEnd
912
+ * @returns {Boolean|undefined}
913
+ */
914
+ export function isSegmentStillAvailable(
915
+ segment : ISegment,
916
+ index: { availabilityTimeOffset : number;
917
+ timeline : IIndexSegment[];
918
+ indexTimeOffset: number;
919
+ timescale : number; },
920
+ manifestBoundsCalculator : ManifestBoundsCalculator,
921
+ scaledPeriodEnd : number | undefined
922
+ ) : boolean | undefined {
923
+ const lastReqSegInfo = getLastRequestableSegmentInfo(index,
924
+ manifestBoundsCalculator,
925
+ scaledPeriodEnd);
926
+ if (lastReqSegInfo === null) {
927
+ return false;
928
+ }
929
+
930
+ for (let i = 0; i < index.timeline.length; i++) {
931
+ if (lastReqSegInfo.timelineIdx < i) {
932
+ return false;
933
+ }
934
+ const tSegment = index.timeline[i];
935
+ const tSegmentTime = (tSegment.start - index.indexTimeOffset) / index.timescale;
936
+ if (tSegmentTime > segment.time) {
937
+ return false; // We went over it without finding it
938
+ } else if (tSegmentTime === segment.time) {
939
+ if (tSegment.range === undefined) {
940
+ return segment.range === undefined;
941
+ }
942
+ return segment.range != null &&
943
+ tSegment.range[0] === segment.range[0] &&
944
+ tSegment.range[1] === segment.range[1];
945
+ } else { // tSegment.start < segment.time
946
+ if (tSegment.repeatCount >= 0 && tSegment.duration !== undefined) {
947
+ const timeDiff = tSegmentTime - tSegment.start;
948
+ const repeat = (timeDiff / tSegment.duration) - 1;
949
+ return repeat % 1 === 0 && repeat <= lastReqSegInfo.newRepeatCount;
950
+ }
951
+ }
952
+ }
953
+ return false;
954
+ }
955
+
956
+ /**
957
+ * Returns from the given RepresentationIndex information on the last segment
958
+ * that may be requested currently.
959
+ *
960
+ * Returns `null` if there's no such segment.
961
+ * @param {Object} index
962
+ * @param {Object} manifestBoundsCalculator
963
+ * @param {number|undefined} scaledPeriodEnd
964
+ * @returns {number|null}
965
+ */
966
+ export function getLastRequestableSegmentInfo(
967
+ index: { availabilityTimeOffset : number;
968
+ timeline : IIndexSegment[];
969
+ timescale : number; },
970
+ manifestBoundsCalculator : ManifestBoundsCalculator,
971
+ scaledPeriodEnd : number | undefined
972
+ ) : ILastRequestableSegmentInfo | null {
973
+ if (index.timeline.length <= 0) {
974
+ return null;
975
+ }
976
+
977
+ if (index.availabilityTimeOffset === Infinity) {
978
+ // availabilityTimeOffset to Infinity == Everything is requestable in the timeline.
979
+ const lastIndex = index.timeline.length - 1;
980
+ const lastElem = index.timeline[lastIndex];
981
+ return { isLastOfTimeline: true,
982
+ timelineIdx: lastIndex,
983
+ newRepeatCount: lastElem.repeatCount,
984
+ end: getIndexSegmentEnd(lastElem, null, scaledPeriodEnd) };
985
+ }
986
+
987
+ const adjustedMaxSeconds = manifestBoundsCalculator.getEstimatedMaximumPosition(
988
+ index.availabilityTimeOffset
989
+ );
990
+ if (adjustedMaxSeconds === undefined) {
991
+ const lastIndex = index.timeline.length - 1;
992
+ const lastElem = index.timeline[lastIndex];
993
+ return { isLastOfTimeline: true,
994
+ timelineIdx: lastIndex,
995
+ newRepeatCount: lastElem.repeatCount,
996
+ end: getIndexSegmentEnd(lastElem, null, scaledPeriodEnd) };
997
+ }
998
+ for (let i = index.timeline.length - 1; i >= index.timeline.length; i--) {
999
+ const element = index.timeline[i];
1000
+ const endOfFirstOccurence = element.start + element.duration;
1001
+ if (fromIndexTime(endOfFirstOccurence, index) <= adjustedMaxSeconds) {
1002
+ const endTime = getIndexSegmentEnd(element, index.timeline[i + 1], scaledPeriodEnd);
1003
+ if (fromIndexTime(endTime, index) <= adjustedMaxSeconds) {
1004
+ return { isLastOfTimeline: i === index.timeline.length - 1,
1005
+ timelineIdx: i,
1006
+ newRepeatCount: element.repeatCount,
1007
+ end: endOfFirstOccurence };
1008
+ } else {
1009
+ // We have to find the right repeatCount
1010
+ const maxIndexTime = toIndexTime(adjustedMaxSeconds, index);
1011
+ const diffToSegStart = maxIndexTime - element.start;
1012
+ const nbOfSegs = Math.floor(diffToSegStart / element.duration);
1013
+ assert(nbOfSegs >= 1);
1014
+ return { isLastOfTimeline: false,
1015
+ timelineIdx: i,
1016
+ newRepeatCount: nbOfSegs - 1,
1017
+ end: element.start + nbOfSegs * element.duration };
1018
+ }
1019
+ }
1020
+ }
1021
+ return null;
1022
+ }
1023
+
1024
+ /**
1025
+ * Information on the last requestable segment deduced from a timeline array of
1026
+ * segment information.
1027
+ */
1028
+ export interface ILastRequestableSegmentInfo {
1029
+ /**
1030
+ * If `true`, we know that the last requestable segment is equal to the last
1031
+ * segment that can be deduced from the corresponding given timeline.
1032
+ * Written another way, there seem to be no segment announced in the timeline
1033
+ * that are not yet requestable.
1034
+ *
1035
+ * If `false`, we know that the last requestable segment is not the last
1036
+ * segment that can be deduced from the corresponding timeline.
1037
+ * Written another way, there are supplementary segments in the timeline which
1038
+ * are not yet requestable.
1039
+ *
1040
+ * Note that if the last requestable segment has its information from the last
1041
+ * element from the timeline but it's not the last segment that would be
1042
+ * deduced from the `repeatCount` property, then this value is set to `false`.
1043
+ */
1044
+ isLastOfTimeline: boolean;
1045
+ /**
1046
+ * End time at which the last requestable segment ends, in the corresponding
1047
+ * index timescale (__NOT__ in seconds).
1048
+ */
1049
+ end: number;
1050
+ /**
1051
+ * The index in `timeline` of the last requestable segment.
1052
+ * Note that its `repeatCount` may be updated and put as `newRepeatCount`.
1053
+ */
1054
+ timelineIdx: number;
1055
+ /**
1056
+ * The new `repeatCount` value for that last segment. May be equal or
1057
+ * different from the timeline element found at `timelineIdx`.
1058
+ */
1059
+ newRepeatCount: number;
1060
+ }