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
package/dist/rx-player.js CHANGED
@@ -535,6 +535,11 @@ var DEFAULT_CONFIG = {
535
535
  * @type {Number}
536
536
  */
537
537
  DEFAULT_REQUEST_TIMEOUT: 30 * 1000,
538
+ /**
539
+ * Default connection time after which a request will timeout, in ms.
540
+ * @type {Number}
541
+ */
542
+ DEFAULT_CONNECTION_TIMEOUT: 15 * 1000,
538
543
  /**
539
544
  * Can be either:
540
545
  * - "native": Subtitles are all displayed in a <track> element
@@ -660,6 +665,22 @@ var DEFAULT_CONFIG = {
660
665
  },
661
666
  /* eslint-enable @typescript-eslint/consistent-type-assertions */
662
667
  /* eslint-disable @typescript-eslint/consistent-type-assertions */
668
+ /**
669
+ * Minimum possible buffer ahead for each type of buffer, to avoid Garbage
670
+ * Collecting too much data when it would have adverse effects.
671
+ * Equal to `0` if not defined here.
672
+ * @type {Object}
673
+ */
674
+ MINIMUM_MAX_BUFFER_AHEAD: {
675
+ // Text segments are both much lighter on resources and might
676
+ // actually be much larger than other types of segments in terms
677
+ // of duration. Let's make an exception here by authorizing a
678
+ // larger text buffer ahead, to avoid unnecesarily reloading the
679
+ // same text track.
680
+ text: 2 * 60
681
+ },
682
+ /* eslint-enable @typescript-eslint/consistent-type-assertions */
683
+ /* eslint-disable @typescript-eslint/consistent-type-assertions */
663
684
  /**
664
685
  * Maximum possible buffer behind for each type of buffer, to avoid too much
665
686
  * memory usage when playing for a long time.
@@ -725,22 +746,6 @@ var DEFAULT_CONFIG = {
725
746
  * @type {Number}
726
747
  */
727
748
  BUFFER_DISCONTINUITY_THRESHOLD: 0.2,
728
- /**
729
- * When encountering small discontinuities, the RxPlayer may want, in specific
730
- * conditions, ignore those and let the browser seek over them iself (this
731
- * allows for example to avoid conflicts when both the browser and the
732
- * RxPlayer want to seek at a different position, sometimes leading to a
733
- * seeking loop).
734
- * In this case, we however still want to seek it ourselves if the browser
735
- * doesn't take the opportunity soon enough.
736
- *
737
- * This value specifies a delay after which a discontinuity ignored by the
738
- * RxPlayer is finally considered.
739
- * We want to maintain high enough to be sure the browser will not seek yet
740
- * small enough so this (arguably rare) situation won't lead to too much
741
- * waiting time.
742
- */
743
- FORCE_DISCONTINUITY_SEEK_DELAY: 5000,
744
749
  /**
745
750
  * Ratio used to know if an already loaded segment should be re-buffered.
746
751
  * We re-load the given segment if the current one times that ratio is
@@ -5215,8 +5220,7 @@ function parseLoadVideoOptions(options) {
5215
5220
  src_log.warn("API: You have set a textTrackElement without being in " + "an \"html\" textTrackMode. It will be ignored.");
5216
5221
  }
5217
5222
  if (!is_null_or_undefined_isNullOrUndefined(options.startAt)) {
5218
- // TODO Better way to express that in TypeScript?
5219
- if (options.startAt.wallClockTime instanceof Date) {
5223
+ if ("wallClockTime" in options.startAt && options.startAt.wallClockTime instanceof Date) {
5220
5224
  var wallClockTime = options.startAt.wallClockTime.getTime() / 1000;
5221
5225
  startAt = object_assign({}, options.startAt, {
5222
5226
  wallClockTime: wallClockTime
@@ -5260,6 +5264,36 @@ function parseLoadVideoOptions(options) {
5260
5264
  };
5261
5265
  }
5262
5266
 
5267
+ ;// CONCATENATED MODULE: ./src/compat/is_seeking_approximate.ts
5268
+ /**
5269
+ * Copyright 2015 CANAL+ Group
5270
+ *
5271
+ * Licensed under the Apache License, Version 2.0 (the "License");
5272
+ * you may not use this file except in compliance with the License.
5273
+ * You may obtain a copy of the License at
5274
+ *
5275
+ * http://www.apache.org/licenses/LICENSE-2.0
5276
+ *
5277
+ * Unless required by applicable law or agreed to in writing, software
5278
+ * distributed under the License is distributed on an "AS IS" BASIS,
5279
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5280
+ * See the License for the specific language governing permissions and
5281
+ * limitations under the License.
5282
+ */
5283
+
5284
+ /**
5285
+ * On some devices (right now only seen on Tizen), seeking through the
5286
+ * `currentTime` property can lead to the browser re-seeking once the
5287
+ * segments have been loaded to improve seeking performances (for
5288
+ * example, by seeking right to an intra video frame).
5289
+ *
5290
+ * This can lead to conflicts with the RxPlayer code.
5291
+ *
5292
+ * This boolean is only `true` on the devices where this behavior has been
5293
+ * observed.
5294
+ */
5295
+ var isSeekingApproximate = isTizen;
5296
+ /* harmony default export */ var is_seeking_approximate = (isSeekingApproximate);
5263
5297
  ;// CONCATENATED MODULE: ./src/utils/monotonic_timestamp.ts
5264
5298
  /**
5265
5299
  * Returns a monotonically-increasing timestamp in milliseconds that is
@@ -5297,6 +5331,7 @@ function getMonotonicTimeStamp() {
5297
5331
 
5298
5332
 
5299
5333
 
5334
+
5300
5335
  /**
5301
5336
  * HTMLMediaElement Events for which playback observations are calculated and
5302
5337
  * emitted.
@@ -5328,12 +5363,26 @@ var PlaybackObserver = /*#__PURE__*/function () {
5328
5363
  * @param {Object} options
5329
5364
  */
5330
5365
  function PlaybackObserver(mediaElement, options) {
5366
+ var _this = this;
5331
5367
  this._internalSeeksIncoming = [];
5332
5368
  this._mediaElement = mediaElement;
5333
5369
  this._withMediaSource = options.withMediaSource;
5334
5370
  this._lowLatencyMode = options.lowLatencyMode;
5335
5371
  this._canceller = new TaskCanceller();
5336
5372
  this._observationRef = this._createSharedReference();
5373
+ this._expectedSeekingPosition = null;
5374
+ this._pendingSeek = null;
5375
+ var onLoadedMetadata = function onLoadedMetadata() {
5376
+ if (_this._pendingSeek !== null) {
5377
+ var positionToSeekTo = _this._pendingSeek;
5378
+ _this._pendingSeek = null;
5379
+ _this._actuallySetCurrentTime(positionToSeekTo);
5380
+ }
5381
+ };
5382
+ mediaElement.addEventListener("loadedmetadata", onLoadedMetadata);
5383
+ this._canceller.signal.register(function () {
5384
+ mediaElement.removeEventListener("loadedmetadata", onLoadedMetadata);
5385
+ });
5337
5386
  }
5338
5387
  /**
5339
5388
  * Stop the `PlaybackObserver` from emitting playback observations and free all
@@ -5384,9 +5433,13 @@ var PlaybackObserver = /*#__PURE__*/function () {
5384
5433
  * @param {number} time
5385
5434
  */;
5386
5435
  _proto.setCurrentTime = function setCurrentTime(time) {
5387
- this._internalSeeksIncoming.push(time);
5388
- src_log.info("API: Seeking internally", time);
5389
- this._mediaElement.currentTime = time;
5436
+ if (this._mediaElement.readyState >= 1) {
5437
+ this._actuallySetCurrentTime(time);
5438
+ } else {
5439
+ this._internalSeeksIncoming = [];
5440
+ this._pendingSeek = time;
5441
+ this._generateObservationForEvent("manual");
5442
+ }
5390
5443
  }
5391
5444
  /**
5392
5445
  * Update the playback rate of the `HTMLMediaElement`.
@@ -5450,6 +5503,11 @@ var PlaybackObserver = /*#__PURE__*/function () {
5450
5503
  */;
5451
5504
  _proto.deriveReadOnlyObserver = function deriveReadOnlyObserver(transform) {
5452
5505
  return generateReadOnlyObserver(this, transform, this._canceller.signal);
5506
+ };
5507
+ _proto._actuallySetCurrentTime = function _actuallySetCurrentTime(time) {
5508
+ src_log.info("API: Seeking internally", time);
5509
+ this._internalSeeksIncoming.push(time);
5510
+ this._mediaElement.currentTime = time;
5453
5511
  }
5454
5512
  /**
5455
5513
  * Creates the `IReadOnlySharedReference` that will generate playback
@@ -5457,66 +5515,28 @@ var PlaybackObserver = /*#__PURE__*/function () {
5457
5515
  * @returns {Object}
5458
5516
  */;
5459
5517
  _proto._createSharedReference = function _createSharedReference() {
5460
- var _this = this;
5518
+ var _this2 = this;
5461
5519
  if (this._observationRef !== undefined) {
5462
5520
  return this._observationRef;
5463
5521
  }
5464
- var lastObservation;
5465
5522
  var _config$getCurrent = config.getCurrent(),
5466
5523
  SAMPLING_INTERVAL_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_MEDIASOURCE,
5467
5524
  SAMPLING_INTERVAL_LOW_LATENCY = _config$getCurrent.SAMPLING_INTERVAL_LOW_LATENCY,
5468
5525
  SAMPLING_INTERVAL_NO_MEDIASOURCE = _config$getCurrent.SAMPLING_INTERVAL_NO_MEDIASOURCE;
5469
- var getCurrentObservation = function getCurrentObservation(event) {
5470
- var tmpEvt = event;
5471
- var startedInternalSeekTime;
5472
- if (tmpEvt === "seeking" && _this._internalSeeksIncoming.length > 0) {
5473
- tmpEvt = "internal-seeking";
5474
- startedInternalSeekTime = _this._internalSeeksIncoming.shift();
5475
- }
5476
- var _lastObservation = lastObservation !== null && lastObservation !== void 0 ? lastObservation : _this._generateInitialObservation();
5477
- var mediaTimings = getMediaInfos(_this._mediaElement, tmpEvt, _this._withMediaSource);
5478
- var pendingInternalSeek = null;
5479
- if (mediaTimings.seeking) {
5480
- if (typeof startedInternalSeekTime === "number") {
5481
- pendingInternalSeek = startedInternalSeekTime;
5482
- } else if (_lastObservation.pendingInternalSeek !== null && event !== "seeking") {
5483
- pendingInternalSeek = _lastObservation.pendingInternalSeek;
5484
- }
5485
- }
5486
- var rebufferingStatus = getRebufferingStatus(_lastObservation, mediaTimings, {
5487
- lowLatencyMode: _this._lowLatencyMode,
5488
- withMediaSource: _this._withMediaSource
5489
- });
5490
- var freezingStatus = getFreezingStatus(_lastObservation, mediaTimings);
5491
- var timings = object_assign({}, {
5492
- rebuffering: rebufferingStatus,
5493
- freezing: freezingStatus,
5494
- pendingInternalSeek: pendingInternalSeek
5495
- }, mediaTimings);
5496
- if (src_log.hasLevel("DEBUG")) {
5497
- src_log.debug("API: current media element state tick", "event", timings.event, "position", timings.position, "seeking", timings.seeking, "internalSeek", timings.pendingInternalSeek, "rebuffering", timings.rebuffering !== null, "freezing", timings.freezing !== null, "ended", timings.ended, "paused", timings.paused, "playbackRate", timings.playbackRate, "readyState", timings.readyState);
5498
- }
5499
- return timings;
5500
- };
5501
- var returnedSharedReference = new utils_reference(getCurrentObservation("init"), this._canceller.signal);
5502
- var generateObservationForEvent = function generateObservationForEvent(event) {
5503
- var newObservation = getCurrentObservation(event);
5504
- if (src_log.hasLevel("DEBUG")) {
5505
- src_log.debug("API: current playback timeline:\n" + prettyPrintBuffered(newObservation.buffered, newObservation.position), "\n" + event);
5506
- }
5507
- lastObservation = newObservation;
5508
- returnedSharedReference.setValue(newObservation);
5509
- };
5526
+ var returnedSharedReference = new utils_reference(this._getCurrentObservation("init"), this._canceller.signal);
5510
5527
  var interval = this._lowLatencyMode ? SAMPLING_INTERVAL_LOW_LATENCY : this._withMediaSource ? SAMPLING_INTERVAL_MEDIASOURCE : SAMPLING_INTERVAL_NO_MEDIASOURCE;
5528
+ var onInterval = function onInterval() {
5529
+ _this2._generateObservationForEvent("timeupdate");
5530
+ };
5511
5531
  var intervalId = setInterval(onInterval, interval);
5512
5532
  var removeEventListeners = SCANNED_MEDIA_ELEMENTS_EVENTS.map(function (eventName) {
5513
- _this._mediaElement.addEventListener(eventName, onMediaEvent);
5514
- function onMediaEvent() {
5533
+ var onMediaEvent = function onMediaEvent() {
5515
5534
  restartInterval();
5516
- generateObservationForEvent(eventName);
5517
- }
5535
+ _this2._generateObservationForEvent(eventName);
5536
+ };
5537
+ _this2._mediaElement.addEventListener(eventName, onMediaEvent);
5518
5538
  return function () {
5519
- _this._mediaElement.removeEventListener(eventName, onMediaEvent);
5539
+ _this2._mediaElement.removeEventListener(eventName, onMediaEvent);
5520
5540
  };
5521
5541
  });
5522
5542
  this._canceller.signal.register(function () {
@@ -5527,23 +5547,160 @@ var PlaybackObserver = /*#__PURE__*/function () {
5527
5547
  returnedSharedReference.finish();
5528
5548
  });
5529
5549
  return returnedSharedReference;
5530
- function onInterval() {
5531
- generateObservationForEvent("timeupdate");
5532
- }
5533
5550
  function restartInterval() {
5534
5551
  clearInterval(intervalId);
5535
5552
  intervalId = setInterval(onInterval, interval);
5536
5553
  }
5537
5554
  };
5538
- _proto._generateInitialObservation = function _generateInitialObservation() {
5539
- return object_assign(getMediaInfos(this._mediaElement, "init", this._withMediaSource), {
5540
- rebuffering: null,
5541
- freezing: null,
5542
- pendingInternalSeek: null
5555
+ _proto._getCurrentObservation = function _getCurrentObservation(event) {
5556
+ var _a;
5557
+ /** Actual event emitted through an observation. */
5558
+ var tmpEvt = event;
5559
+ // NOTE: `this._observationRef` may be `undefined` because we might here be
5560
+ // called in the constructor when that property is not yet set.
5561
+ var previousObservation = this._observationRef === undefined ? getInitialObservation(this._mediaElement, this._withMediaSource) : this._observationRef.getValue();
5562
+ /**
5563
+ * If `true`, there is a seek operation ongoing but it was done from the
5564
+ * `PlaybackObserver`'s `setCurrentTime` method, not from external code.
5565
+ */
5566
+ var isInternalSeeking = false;
5567
+ /** If set, the position for which we plan to seek to as soon as possible. */
5568
+ var pendingPosition = this._pendingSeek;
5569
+ /** Initially-polled playback observation, before adjustments. */
5570
+ var mediaTimings = getMediaInfos(this._mediaElement, this._withMediaSource);
5571
+ if (tmpEvt === "seeking") {
5572
+ // We just began seeking.
5573
+ // Let's find out if the seek is internal or external and handle approximate
5574
+ // seeking
5575
+ if (this._internalSeeksIncoming.length > 0) {
5576
+ isInternalSeeking = true;
5577
+ tmpEvt = "internal-seeking";
5578
+ var startedInternalSeekTime = this._internalSeeksIncoming.shift();
5579
+ this._expectedSeekingPosition = is_seeking_approximate ? Math.max(mediaTimings.position, startedInternalSeekTime !== null && startedInternalSeekTime !== void 0 ? startedInternalSeekTime : 0) : mediaTimings.position;
5580
+ } else {
5581
+ this._expectedSeekingPosition = mediaTimings.position;
5582
+ }
5583
+ } else if (mediaTimings.seeking) {
5584
+ // we're still seeking, this time without a "seeking" event so it's an
5585
+ // already handled one, keep track of the last wanted position we wanted
5586
+ // to seek to, to work-around devices re-seeking silently.
5587
+ this._expectedSeekingPosition = Math.max(mediaTimings.position, (_a = this._expectedSeekingPosition) !== null && _a !== void 0 ? _a : 0);
5588
+ } else if (is_seeking_approximate && this._expectedSeekingPosition !== null && mediaTimings.position < this._expectedSeekingPosition) {
5589
+ // We're on a target with aproximate seeking, we're not seeking anymore, but
5590
+ // we're not yet at the expected seeking position.
5591
+ // Signal to the rest of the application that the intented position is not
5592
+ // the current position but the one contained in `this._expectedSeekingPosition`
5593
+ pendingPosition = this._expectedSeekingPosition;
5594
+ } else {
5595
+ this._expectedSeekingPosition = null;
5596
+ }
5597
+ if (mediaTimings.seeking && previousObservation.seeking === 1 /* SeekingState.Internal */ && event !== "seeking") {
5598
+ isInternalSeeking = true;
5599
+ }
5600
+ var rebufferingStatus = getRebufferingStatus(previousObservation, mediaTimings, tmpEvt, {
5601
+ lowLatencyMode: this._lowLatencyMode,
5602
+ withMediaSource: this._withMediaSource
5543
5603
  });
5604
+ var freezingStatus = getFreezingStatus(previousObservation, mediaTimings, tmpEvt);
5605
+ var seeking = isInternalSeeking ? 1 /* SeekingState.Internal */ : mediaTimings.seeking ? 2 /* SeekingState.External */ : 0 /* SeekingState.None */;
5606
+ var timings = object_assign({}, mediaTimings, {
5607
+ position: new ObservationPosition(mediaTimings.position, pendingPosition),
5608
+ event: tmpEvt,
5609
+ seeking: seeking,
5610
+ rebuffering: rebufferingStatus,
5611
+ freezing: freezingStatus
5612
+ });
5613
+ if (src_log.hasLevel("DEBUG")) {
5614
+ src_log.debug("API: current media element state tick", "event", timings.event, "position", timings.position.getPolled(), "seeking", timings.seeking, "internalSeek", isInternalSeeking, "rebuffering", timings.rebuffering !== null, "freezing", timings.freezing !== null, "ended", timings.ended, "paused", timings.paused, "playbackRate", timings.playbackRate, "readyState", timings.readyState);
5615
+ }
5616
+ return timings;
5617
+ };
5618
+ _proto._generateObservationForEvent = function _generateObservationForEvent(event) {
5619
+ var newObservation = this._getCurrentObservation(event);
5620
+ if (src_log.hasLevel("DEBUG")) {
5621
+ src_log.debug("API: current playback timeline:\n" + prettyPrintBuffered(newObservation.buffered, newObservation.position.getPolled()), "\n" + event);
5622
+ }
5623
+ this._observationRef.setValue(newObservation);
5544
5624
  };
5545
5625
  return PlaybackObserver;
5546
5626
  }();
5627
+
5628
+ var ObservationPosition = /*#__PURE__*/function () {
5629
+ function ObservationPosition(last, wanted) {
5630
+ this._last = last;
5631
+ this._wanted = wanted;
5632
+ }
5633
+ /**
5634
+ * Returns the playback position actually observed on the media element at
5635
+ * the time the playback observation was made.
5636
+ *
5637
+ * Note that it may be different than the position for which media data is
5638
+ * wanted in rare scenarios where the goal position is not yet set on the
5639
+ * media element.
5640
+ *
5641
+ * You should use this value when you want to obtain the actual position set
5642
+ * on the media element for browser compatibility purposes. Note that this
5643
+ * position was calculated at observation time, it might thus not be
5644
+ * up-to-date if what you want is milliseconds-accuracy.
5645
+ *
5646
+ * If what you want is the actual position which the player is intended to
5647
+ * play, you should rely on `getWanted` instead`.
5648
+ * @returns {number}
5649
+ */
5650
+ var _proto2 = ObservationPosition.prototype;
5651
+ _proto2.getPolled = function getPolled() {
5652
+ return this._last;
5653
+ }
5654
+ /**
5655
+ * Returns the position which the player should consider to load media data
5656
+ * at the time the observation was made.
5657
+ *
5658
+ * It can be different than the value returned by `getPolled` in rare
5659
+ * scenarios:
5660
+ *
5661
+ * - When the initial position has not been set yet.
5662
+ *
5663
+ * - When the current device do not let the RxPlayer peform precize seeks,
5664
+ * usually for perfomance reasons by seeking to a previous IDR frame
5665
+ * instead (for now only Tizen may be like this), in which case we
5666
+ * prefer to generally rely on the position wanted by the player (this
5667
+ * e.g. prevents issues where the RxPlayer logic and the device are
5668
+ * seeking back and forth in a loop).
5669
+ *
5670
+ * - When a wanted position has been "forced" (@see forceWantedPosition).
5671
+ * @returns {number}
5672
+ */;
5673
+ _proto2.getWanted = function getWanted() {
5674
+ var _a;
5675
+ return (_a = this._wanted) !== null && _a !== void 0 ? _a : this._last;
5676
+ }
5677
+ /**
5678
+ * Method to call if you want to overwrite the currently wanted position.
5679
+ * @param {number} pos
5680
+ */;
5681
+ _proto2.forceWantedPosition = function forceWantedPosition(pos) {
5682
+ this._wanted = pos;
5683
+ }
5684
+ /**
5685
+ * Returns `true` when the position wanted returned by `getWanted` and the
5686
+ * actual position returned by `getPolled` may be different, meaning that
5687
+ * we're currently not at the position we want to reach.
5688
+ *
5689
+ * This is a relatively rare situation which only happens when either the
5690
+ * initial seek has not yet been performed. on specific targets where the
5691
+ * seeking behavior is a little broken (@see getWanted) or when the wanted
5692
+ * position has been forced (@see forceWantedPosition).
5693
+ *
5694
+ * In those situations, you might temporarily refrain from acting upon the
5695
+ * actual current media position, as it may change soon.
5696
+ *
5697
+ * @returns {boolean}
5698
+ */;
5699
+ _proto2.isAwaitingFuturePosition = function isAwaitingFuturePosition() {
5700
+ return this._wanted !== null;
5701
+ };
5702
+ return ObservationPosition;
5703
+ }();
5547
5704
  /**
5548
5705
  * Returns the amount of time in seconds the buffer should have ahead of the
5549
5706
  * current position before resuming playback. Based on the infos of the
@@ -5555,7 +5712,6 @@ var PlaybackObserver = /*#__PURE__*/function () {
5555
5712
  * @param {Boolean} lowLatencyMode
5556
5713
  * @returns {Number}
5557
5714
  */
5558
-
5559
5715
  function getRebufferingEndGap(rebufferingStatus, lowLatencyMode) {
5560
5716
  if (rebufferingStatus === null) {
5561
5717
  return 0;
@@ -5592,10 +5748,9 @@ function hasLoadedUntilTheEnd(currentTime, currentRange, ended, duration, lowLat
5592
5748
  /**
5593
5749
  * Get basic playback information.
5594
5750
  * @param {HTMLMediaElement} mediaElement
5595
- * @param {string} event
5596
5751
  * @returns {Object}
5597
5752
  */
5598
- function getMediaInfos(mediaElement, event, withMediaSource) {
5753
+ function getMediaInfos(mediaElement, withMediaSource) {
5599
5754
  var buffered = mediaElement.buffered,
5600
5755
  currentTime = mediaElement.currentTime,
5601
5756
  duration = mediaElement.duration,
@@ -5630,8 +5785,7 @@ function getMediaInfos(mediaElement, event, withMediaSource) {
5630
5785
  paused: paused,
5631
5786
  playbackRate: playbackRate,
5632
5787
  readyState: readyState,
5633
- seeking: seeking,
5634
- event: event
5788
+ seeking: seeking
5635
5789
  };
5636
5790
  }
5637
5791
  /**
@@ -5643,16 +5797,16 @@ function getMediaInfos(mediaElement, event, withMediaSource) {
5643
5797
  * @param {Object} currentInfo - Current set of basic information on the
5644
5798
  * `HTMLMediaElement`. This does not need every single property from a regular
5645
5799
  * playback observation.
5800
+ * @param {string} currentEvt
5646
5801
  * @param {Object} options
5647
5802
  * @returns {Object|null}
5648
5803
  */
5649
- function getRebufferingStatus(prevObservation, currentInfo, _ref) {
5804
+ function getRebufferingStatus(prevObservation, currentInfo, currentEvt, _ref) {
5650
5805
  var withMediaSource = _ref.withMediaSource,
5651
5806
  lowLatencyMode = _ref.lowLatencyMode;
5652
5807
  var _config$getCurrent4 = config.getCurrent(),
5653
5808
  REBUFFERING_GAP = _config$getCurrent4.REBUFFERING_GAP;
5654
- var currentEvt = currentInfo.event,
5655
- currentTime = currentInfo.position,
5809
+ var currentTime = currentInfo.position,
5656
5810
  bufferGap = currentInfo.bufferGap,
5657
5811
  currentRange = currentInfo.currentRange,
5658
5812
  duration = currentInfo.duration,
@@ -5699,9 +5853,9 @@ function getRebufferingStatus(prevObservation, currentInfo, _ref) {
5699
5853
  // own, so we only try to detect when the media timestamp has not changed
5700
5854
  // between two consecutive timeupdates
5701
5855
  else {
5702
- if (canSwitchToRebuffering && (!paused && currentEvt === "timeupdate" && prevEvt === "timeupdate" && currentTime === prevTime || currentEvt === "seeking" && (bufferGap === Infinity || bufferGap === undefined && readyState < 3))) {
5856
+ if (canSwitchToRebuffering && (!paused && currentEvt === "timeupdate" && prevEvt === "timeupdate" && currentTime === prevTime.getPolled() || currentEvt === "seeking" && (bufferGap === Infinity || bufferGap === undefined && readyState < 3))) {
5703
5857
  shouldRebuffer = true;
5704
- } else if (prevRebuffering !== null && (currentEvt !== "seeking" && currentTime !== prevTime || currentEvt === "canplay" || bufferGap === undefined && readyState >= 3 || bufferGap !== undefined && bufferGap < Infinity && (bufferGap > getRebufferingEndGap(prevRebuffering, lowLatencyMode) || fullyLoaded || ended))) {
5858
+ } else if (prevRebuffering !== null && (currentEvt !== "seeking" && currentTime !== prevTime.getPolled() || currentEvt === "canplay" || bufferGap === undefined && readyState >= 3 || bufferGap !== undefined && bufferGap < Infinity && (bufferGap > getRebufferingEndGap(prevRebuffering, lowLatencyMode) || fullyLoaded || ended))) {
5705
5859
  shouldStopRebuffer = true;
5706
5860
  }
5707
5861
  }
@@ -5741,20 +5895,21 @@ function getRebufferingStatus(prevObservation, currentInfo, _ref) {
5741
5895
  * `null` if not.
5742
5896
  * @param {Object} prevObservation
5743
5897
  * @param {Object} currentInfo
5898
+ * @param {string} currentEvt
5744
5899
  * @returns {Object|null}
5745
5900
  */
5746
- function getFreezingStatus(prevObservation, currentInfo) {
5901
+ function getFreezingStatus(prevObservation, currentInfo, currentEvt) {
5747
5902
  var _config$getCurrent5 = config.getCurrent(),
5748
5903
  MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING = _config$getCurrent5.MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING;
5749
5904
  if (prevObservation.freezing) {
5750
- if (currentInfo.ended || currentInfo.paused || currentInfo.readyState === 0 || currentInfo.playbackRate === 0 || prevObservation.position !== currentInfo.position) {
5905
+ if (currentInfo.ended || currentInfo.paused || currentInfo.readyState === 0 || currentInfo.playbackRate === 0 || prevObservation.position.getPolled() !== currentInfo.position) {
5751
5906
  return null; // Quit freezing status
5752
5907
  }
5753
5908
 
5754
5909
  return prevObservation.freezing; // Stay in it
5755
5910
  }
5756
5911
 
5757
- return currentInfo.event === "timeupdate" && currentInfo.bufferGap !== undefined && currentInfo.bufferGap > MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING && !currentInfo.ended && !currentInfo.paused && currentInfo.readyState >= 1 && currentInfo.playbackRate !== 0 && currentInfo.position === prevObservation.position ? {
5912
+ return currentEvt === "timeupdate" && currentInfo.bufferGap !== undefined && currentInfo.bufferGap > MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING && !currentInfo.ended && !currentInfo.paused && currentInfo.readyState >= 1 && currentInfo.playbackRate !== 0 && currentInfo.position === prevObservation.position.getPolled() ? {
5758
5913
  timestamp: getMonotonicTimeStamp()
5759
5914
  } : null;
5760
5915
  }
@@ -5856,6 +6011,26 @@ function generateReadOnlyObserver(src, transform, cancellationSignal) {
5856
6011
  }
5857
6012
  };
5858
6013
  }
6014
+ /**
6015
+ * Generate the initial playback observation for when no event has yet been
6016
+ * emitted to lead to one.
6017
+ * @param {HTMLMediaElement} mediaElement
6018
+ * @param {boolean} withMediaSource
6019
+ * @returns {Object}
6020
+ */
6021
+ function getInitialObservation(mediaElement, withMediaSource) {
6022
+ var mediaTimings = getMediaInfos(mediaElement, withMediaSource);
6023
+ return object_assign(mediaTimings, {
6024
+ rebuffering: null,
6025
+ event: "init",
6026
+ seeking: 0 /* SeekingState.None */,
6027
+ position: {
6028
+ last: mediaTimings.position,
6029
+ pending: undefined
6030
+ },
6031
+ freezing: null
6032
+ });
6033
+ }
5859
6034
  ;// CONCATENATED MODULE: ./src/core/api/track_management/track_dispatcher.ts
5860
6035
 
5861
6036
 
@@ -7074,7 +7249,7 @@ function emitSeekEvents(mediaElement, playbackObserver, onSeeking, onSeeked, can
7074
7249
  if (cancelSignal.isCancelled() || mediaElement === null) {
7075
7250
  return;
7076
7251
  }
7077
- var wasSeeking = playbackObserver.getReference().getValue().seeking;
7252
+ var wasSeeking = playbackObserver.getReference().getValue().seeking === 2 /* SeekingState.External */;
7078
7253
  if (wasSeeking) {
7079
7254
  onSeeking();
7080
7255
  if (cancelSignal.isCancelled()) {
@@ -7299,7 +7474,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
7299
7474
  // Workaround to support Firefox autoplay on FF 42.
7300
7475
  // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
7301
7476
  videoElement.preload = "auto";
7302
- _this.version = /* PLAYER_VERSION */"4.0.0-dev.2023111400";
7477
+ _this.version = /* PLAYER_VERSION */"4.0.0-dev.2023121900";
7303
7478
  _this.log = src_log;
7304
7479
  _this.state = "STOPPED";
7305
7480
  _this.videoElement = videoElement;
@@ -7470,7 +7645,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
7470
7645
  */;
7471
7646
  _proto._priv_initializeContentPlayback = function _priv_initializeContentPlayback(options) {
7472
7647
  var _this2 = this;
7473
- var _a, _b, _c, _d;
7648
+ var _a, _b, _c, _d, _e, _f;
7474
7649
  var autoPlay = options.autoPlay,
7475
7650
  defaultAudioTrackSwitchingMode = options.defaultAudioTrackSwitchingMode,
7476
7651
  enableFastSwitching = options.enableFastSwitching,
@@ -7528,6 +7703,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
7528
7703
  lowLatencyMode: lowLatencyMode,
7529
7704
  maxRetry: (_a = requestConfig.manifest) === null || _a === void 0 ? void 0 : _a.maxRetry,
7530
7705
  requestTimeout: (_b = requestConfig.manifest) === null || _b === void 0 ? void 0 : _b.timeout,
7706
+ connectionTimeout: (_c = requestConfig.manifest) === null || _c === void 0 ? void 0 : _c.connectionTimeout,
7531
7707
  minimumManifestUpdateInterval: minimumManifestUpdateInterval,
7532
7708
  initialManifest: initialManifest
7533
7709
  };
@@ -7579,8 +7755,9 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
7579
7755
  }, this._priv_bufferOptions);
7580
7756
  var segmentRequestOptions = {
7581
7757
  lowLatencyMode: lowLatencyMode,
7582
- maxRetry: (_c = requestConfig.segment) === null || _c === void 0 ? void 0 : _c.maxRetry,
7583
- requestTimeout: (_d = requestConfig.segment) === null || _d === void 0 ? void 0 : _d.timeout
7758
+ maxRetry: (_d = requestConfig.segment) === null || _d === void 0 ? void 0 : _d.maxRetry,
7759
+ requestTimeout: (_e = requestConfig.segment) === null || _e === void 0 ? void 0 : _e.timeout,
7760
+ connectionTimeout: (_f = requestConfig.segment) === null || _f === void 0 ? void 0 : _f.connectionTimeout
7584
7761
  };
7585
7762
  initializer = new src_features.mediaSourceInit({
7586
7763
  adaptiveOptions: adaptiveOptions,
@@ -7724,12 +7901,12 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
7724
7901
  // keep previous metadata
7725
7902
  case "ENDED":
7726
7903
  _this2._priv_reloadingMetadata.reloadInPause = true;
7727
- _this2._priv_reloadingMetadata.reloadPosition = playbackObserver.getReference().getValue().position;
7904
+ _this2._priv_reloadingMetadata.reloadPosition = playbackObserver.getReference().getValue().position.getPolled();
7728
7905
  break;
7729
7906
  default:
7730
7907
  var o = playbackObserver.getReference().getValue();
7731
7908
  _this2._priv_reloadingMetadata.reloadInPause = o.paused;
7732
- _this2._priv_reloadingMetadata.reloadPosition = o.position;
7909
+ _this2._priv_reloadingMetadata.reloadPosition = o.position.getWanted();
7733
7910
  break;
7734
7911
  }
7735
7912
  };
@@ -8807,16 +8984,39 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
8807
8984
  return null;
8808
8985
  }
8809
8986
  /**
8810
- * Get maximum seek-able position.
8987
+ * Returns the current position for live contents.
8988
+ *
8989
+ * Returns `null` if no content is loaded or if the current loaded content is
8990
+ * not considered as a live content.
8991
+ * Returns `undefined` if that live position is currently unknown.
8811
8992
  * @returns {number}
8812
8993
  */;
8813
- _proto.getMaximumPosition = function getMaximumPosition() {
8994
+ _proto.getLivePosition = function getLivePosition() {
8814
8995
  if (this._priv_contentInfos === null) {
8815
8996
  return null;
8816
8997
  }
8817
8998
  var _this$_priv_contentIn17 = this._priv_contentInfos,
8818
8999
  isDirectFile = _this$_priv_contentIn17.isDirectFile,
8819
9000
  manifest = _this$_priv_contentIn17.manifest;
9001
+ if (isDirectFile) {
9002
+ return undefined;
9003
+ }
9004
+ if ((manifest === null || manifest === void 0 ? void 0 : manifest.isLive) !== true) {
9005
+ return null;
9006
+ }
9007
+ return manifest.getLivePosition();
9008
+ }
9009
+ /**
9010
+ * Get maximum seek-able position.
9011
+ * @returns {number}
9012
+ */;
9013
+ _proto.getMaximumPosition = function getMaximumPosition() {
9014
+ if (this._priv_contentInfos === null) {
9015
+ return null;
9016
+ }
9017
+ var _this$_priv_contentIn18 = this._priv_contentInfos,
9018
+ isDirectFile = _this$_priv_contentIn18.isDirectFile,
9019
+ manifest = _this$_priv_contentIn18.manifest;
8820
9020
  if (isDirectFile) {
8821
9021
  if (this.videoElement === null) {
8822
9022
  throw new Error("Disposed player");
@@ -8850,7 +9050,11 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
8850
9050
  return null;
8851
9051
  }
8852
9052
  var segmentBufferStatus = this._priv_contentInfos.segmentBuffersStore.getStatus(bufferType);
8853
- return segmentBufferStatus.type === "initialized" ? segmentBufferStatus.value.getInventory() : null;
9053
+ if (segmentBufferStatus.type === "initialized") {
9054
+ segmentBufferStatus.value.synchronizeInventory();
9055
+ return segmentBufferStatus.value.getInventory();
9056
+ }
9057
+ return null;
8854
9058
  }
8855
9059
  /**
8856
9060
  * /!\ For tools use only! Do not touch!
@@ -8873,9 +9077,9 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
8873
9077
  if (this._priv_contentInfos === null) {
8874
9078
  return null;
8875
9079
  }
8876
- var _this$_priv_contentIn18 = this._priv_contentInfos,
8877
- currentPeriod = _this$_priv_contentIn18.currentPeriod,
8878
- activeAdaptations = _this$_priv_contentIn18.activeAdaptations;
9080
+ var _this$_priv_contentIn19 = this._priv_contentInfos,
9081
+ currentPeriod = _this$_priv_contentIn19.currentPeriod,
9082
+ activeAdaptations = _this$_priv_contentIn19.activeAdaptations;
8879
9083
  if (currentPeriod === null || activeAdaptations === null || is_null_or_undefined_isNullOrUndefined(activeAdaptations[currentPeriod.id])) {
8880
9084
  return null;
8881
9085
  }
@@ -8887,9 +9091,9 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
8887
9091
  if (this._priv_contentInfos === null) {
8888
9092
  return null;
8889
9093
  }
8890
- var _this$_priv_contentIn19 = this._priv_contentInfos,
8891
- currentPeriod = _this$_priv_contentIn19.currentPeriod,
8892
- activeRepresentations = _this$_priv_contentIn19.activeRepresentations;
9094
+ var _this$_priv_contentIn20 = this._priv_contentInfos,
9095
+ currentPeriod = _this$_priv_contentIn20.currentPeriod,
9096
+ activeRepresentations = _this$_priv_contentIn20.activeRepresentations;
8893
9097
  if (currentPeriod === null || activeRepresentations === null || is_null_or_undefined_isNullOrUndefined(activeRepresentations[currentPeriod.id])) {
8894
9098
  return null;
8895
9099
  }
@@ -9316,24 +9520,24 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
9316
9520
  }
9317
9521
  var maximumPosition = manifest !== null ? manifest.getMaximumSafePosition() : undefined;
9318
9522
  var positionData = {
9319
- position: observation.position,
9523
+ position: observation.position.getPolled(),
9320
9524
  duration: observation.duration,
9321
9525
  playbackRate: observation.playbackRate,
9322
9526
  maximumPosition: maximumPosition,
9323
9527
  // TODO bufferGap may be undefined
9324
9528
  bufferGap: observation.bufferGap === undefined || !isFinite(observation.bufferGap) ? 0 : observation.bufferGap
9325
9529
  };
9326
- if (manifest !== null && manifest.isLive && observation.position > 0) {
9530
+ if (manifest !== null && manifest.isLive && observation.position.getPolled() > 0) {
9327
9531
  var ast = (_b = manifest.availabilityStartTime) !== null && _b !== void 0 ? _b : 0;
9328
- positionData.wallClockTime = observation.position + ast;
9532
+ positionData.wallClockTime = observation.position.getPolled() + ast;
9329
9533
  var livePosition = manifest.getLivePosition();
9330
9534
  if (livePosition !== undefined) {
9331
- positionData.liveGap = livePosition - observation.position;
9535
+ positionData.liveGap = livePosition - observation.position.getPolled();
9332
9536
  }
9333
9537
  } else if (isDirectFile && this.videoElement !== null) {
9334
9538
  var startDate = getStartDate(this.videoElement);
9335
9539
  if (startDate !== undefined) {
9336
- positionData.wallClockTime = startDate + observation.position;
9540
+ positionData.wallClockTime = startDate + observation.position.getPolled();
9337
9541
  }
9338
9542
  }
9339
9543
  this.trigger("positionUpdate", positionData);
@@ -9506,7 +9710,7 @@ var Player = /*#__PURE__*/function (_EventEmitter) {
9506
9710
  }]);
9507
9711
  return Player;
9508
9712
  }(EventEmitter);
9509
- Player.version = /* PLAYER_VERSION */"4.0.0-dev.2023111400";
9713
+ Player.version = /* PLAYER_VERSION */"4.0.0-dev.2023121900";
9510
9714
  /* harmony default export */ var public_api = (Player);
9511
9715
  ;// CONCATENATED MODULE: ./src/core/api/index.ts
9512
9716
  /**
@@ -10030,7 +10234,7 @@ function estimateStarvationModeBitrate(pendingRequests, playbackInfo, currentRep
10030
10234
  speed = playbackInfo.speed,
10031
10235
  position = playbackInfo.position;
10032
10236
  var realBufferGap = isFinite(bufferGap) ? bufferGap : 0;
10033
- var nextNeededPosition = position.last + realBufferGap;
10237
+ var nextNeededPosition = position.getWanted() + realBufferGap;
10034
10238
  var concernedRequests = getConcernedRequests(pendingRequests, nextNeededPosition);
10035
10239
  if (concernedRequests.length !== 1) {
10036
10240
  // 0 == no request
@@ -10093,7 +10297,7 @@ function shouldDirectlySwitchToLowBitrate(playbackInfo, requests, lowLatencyMode
10093
10297
  return true;
10094
10298
  }
10095
10299
  var realBufferGap = isFinite(playbackInfo.bufferGap) ? playbackInfo.bufferGap : 0;
10096
- var nextNeededPosition = playbackInfo.position.last + realBufferGap;
10300
+ var nextNeededPosition = playbackInfo.position.getWanted() + realBufferGap;
10097
10301
  var nextRequest = arrayFind(requests, function (_ref) {
10098
10302
  var content = _ref.content;
10099
10303
  return content.segment.duration > 0 && content.segment.time + content.segment.duration > nextNeededPosition;
@@ -10174,7 +10378,7 @@ var NetworkAnalyzer = /*#__PURE__*/function () {
10174
10378
  var _config$getCurrent2 = config.getCurrent(),
10175
10379
  ABR_STARVATION_DURATION_DELTA = _config$getCurrent2.ABR_STARVATION_DURATION_DELTA;
10176
10380
  // check if should get in/out of starvation mode
10177
- if (isNaN(duration) || realBufferGap + position.last < duration - ABR_STARVATION_DURATION_DELTA) {
10381
+ if (isNaN(duration) || realBufferGap + position.getWanted() < duration - ABR_STARVATION_DURATION_DELTA) {
10178
10382
  if (!this._inStarvationMode && realBufferGap <= localConf.starvationGap) {
10179
10383
  src_log.info("ABR: enter starvation mode.");
10180
10384
  this._inStarvationMode = true;
@@ -11180,7 +11384,7 @@ function getEstimateReference(_ref, stopAllEstimates) {
11180
11384
  position = _lastPlaybackObservat.position,
11181
11385
  speed = _lastPlaybackObservat.speed;
11182
11386
  var timeRanges = val.buffered;
11183
- var bufferGap = getLeftSizeOfBufferedTimeRange(timeRanges, position.last);
11387
+ var bufferGap = getLeftSizeOfBufferedTimeRange(timeRanges, position.getWanted());
11184
11388
  var representation = val.content.representation;
11185
11389
  var currentScore = scoreCalculator.getEstimate(representation);
11186
11390
  var currentBitrate = representation.bitrate;
@@ -11274,7 +11478,7 @@ function getEstimateReference(_ref, stopAllEstimates) {
11274
11478
  * `null` if not enabled or if there's currently no guess.
11275
11479
  */
11276
11480
  var chosenRepFromGuessMode = null;
11277
- if (lowLatencyMode && currentRepresentationVal !== null && context.manifest.isDynamic && maximumPosition - position.last < 40) {
11481
+ if (lowLatencyMode && currentRepresentationVal !== null && context.manifest.isDynamic && maximumPosition - position.getWanted() < 40) {
11278
11482
  chosenRepFromGuessMode = guessBasedChooser.getGuess(sortedRepresentations, lastPlaybackObservation, currentRepresentationVal, currentBestBitrate, requests);
11279
11483
  }
11280
11484
  if (chosenRepFromGuessMode !== null && chosenRepFromGuessMode.bitrate > currentBestBitrate) {
@@ -11868,6 +12072,16 @@ var READY_STATES = {
11868
12072
  * limitations under the License.
11869
12073
  */
11870
12074
 
12075
+ /**
12076
+ * Setting this value limit the number of entries in the support map
12077
+ * preventing important memory usage, value is arbitrary
12078
+ */
12079
+ var MAX_SUPPORT_MAP_ENTRIES = 200;
12080
+ /**
12081
+ * caching the codec support reduce the amount of call to `isTypeSupported`
12082
+ * and help for performance especially on low-end devices.
12083
+ */
12084
+ var supportMap = new Map();
11871
12085
  /**
11872
12086
  * Returns true if the given codec is supported by the browser's MediaSource
11873
12087
  * implementation.
@@ -11884,7 +12098,17 @@ function isCodecSupported(mimeType) {
11884
12098
  /* eslint-disable @typescript-eslint/unbound-method */
11885
12099
  if (typeof MediaSource_.isTypeSupported === "function") {
11886
12100
  /* eslint-enable @typescript-eslint/unbound-method */
11887
- return MediaSource_.isTypeSupported(mimeType);
12101
+ var cachedSupport = supportMap.get(mimeType);
12102
+ if (cachedSupport !== undefined) {
12103
+ return cachedSupport;
12104
+ } else {
12105
+ var isSupported = MediaSource_.isTypeSupported(mimeType);
12106
+ if (supportMap.size >= MAX_SUPPORT_MAP_ENTRIES) {
12107
+ supportMap.clear();
12108
+ }
12109
+ supportMap.set(mimeType, isSupported);
12110
+ return isSupported;
12111
+ }
11888
12112
  }
11889
12113
  return true;
11890
12114
  }
@@ -12340,7 +12564,7 @@ var Adaptation = /*#__PURE__*/function () {
12340
12564
  var reprObject = {
12341
12565
  id: representation.id,
12342
12566
  bitrate: representation.bitrate,
12343
- codec: representation.codec,
12567
+ codecs: representation.codec === undefined ? [] : [representation.codec],
12344
12568
  height: representation.height,
12345
12569
  width: representation.width,
12346
12570
  frameRate: representation.frameRate,
@@ -13938,7 +14162,6 @@ function manifest_fetcher_arrayLikeToArray(arr, len) { if (len == null || len >
13938
14162
 
13939
14163
 
13940
14164
 
13941
-
13942
14165
  /**
13943
14166
  * Class allowing to facilitate the task of loading and parsing a Manifest, as
13944
14167
  * well as automatically refreshing it.
@@ -14063,13 +14286,18 @@ var ManifestFetcher = /*#__PURE__*/function (_EventEmitter) {
14063
14286
  case 0:
14064
14287
  callLoaderWithRetries = function _callLoaderWithRetrie(manifestUrl) {
14065
14288
  var loadManifest = pipelines.loadManifest;
14066
- var requestTimeout = is_null_or_undefined_isNullOrUndefined(settings.requestTimeout) ? config.getCurrent().DEFAULT_REQUEST_TIMEOUT : settings.requestTimeout;
14289
+ var requestTimeout = settings.requestTimeout === undefined ? config.getCurrent().DEFAULT_REQUEST_TIMEOUT : settings.requestTimeout;
14290
+ var connectionTimeout = settings.connectionTimeout === undefined ? config.getCurrent().DEFAULT_CONNECTION_TIMEOUT : settings.connectionTimeout;
14067
14291
  if (requestTimeout < 0) {
14068
14292
  requestTimeout = undefined;
14069
14293
  }
14294
+ if (connectionTimeout < 0) {
14295
+ connectionTimeout = undefined;
14296
+ }
14070
14297
  var callLoader = function callLoader() {
14071
14298
  return loadManifest(manifestUrl, {
14072
- timeout: requestTimeout
14299
+ timeout: requestTimeout,
14300
+ connectionTimeout: connectionTimeout
14073
14301
  }, cancelSignal);
14074
14302
  };
14075
14303
  return scheduleRequestPromise(callLoader, backoffSettings, cancelSignal);
@@ -14925,7 +15153,8 @@ var generateRequestID = idGenerator();
14925
15153
  */
14926
15154
  function segment_fetcher_createSegmentFetcher(bufferType, pipeline, cdnPrioritizer, lifecycleCallbacks, options) {
14927
15155
  var requestOptions = {
14928
- timeout: options.requestTimeout < 0 ? undefined : options.requestTimeout
15156
+ timeout: options.requestTimeout < 0 ? undefined : options.requestTimeout,
15157
+ connectionTimeout: options.connectionTimeout === undefined ? undefined : options.connectionTimeout < 0 ? undefined : options.connectionTimeout
14929
15158
  };
14930
15159
  /**
14931
15160
  * Cache audio and video initialization segments.
@@ -15168,17 +15397,20 @@ function segment_fetcher_createSegmentFetcher(bufferType, pipeline, cdnPrioritiz
15168
15397
  function getSegmentFetcherOptions(_ref) {
15169
15398
  var maxRetry = _ref.maxRetry,
15170
15399
  lowLatencyMode = _ref.lowLatencyMode,
15171
- requestTimeout = _ref.requestTimeout;
15400
+ requestTimeout = _ref.requestTimeout,
15401
+ connectionTimeout = _ref.connectionTimeout;
15172
15402
  var _config$getCurrent = config.getCurrent(),
15173
15403
  DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR = _config$getCurrent.DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR,
15174
15404
  DEFAULT_REQUEST_TIMEOUT = _config$getCurrent.DEFAULT_REQUEST_TIMEOUT,
15405
+ DEFAULT_CONNECTION_TIMEOUT = _config$getCurrent.DEFAULT_CONNECTION_TIMEOUT,
15175
15406
  INITIAL_BACKOFF_DELAY_BASE = _config$getCurrent.INITIAL_BACKOFF_DELAY_BASE,
15176
15407
  MAX_BACKOFF_DELAY_BASE = _config$getCurrent.MAX_BACKOFF_DELAY_BASE;
15177
15408
  return {
15178
15409
  maxRetry: maxRetry !== null && maxRetry !== void 0 ? maxRetry : DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR,
15179
15410
  baseDelay: lowLatencyMode ? INITIAL_BACKOFF_DELAY_BASE.LOW_LATENCY : INITIAL_BACKOFF_DELAY_BASE.REGULAR,
15180
15411
  maxDelay: lowLatencyMode ? MAX_BACKOFF_DELAY_BASE.LOW_LATENCY : MAX_BACKOFF_DELAY_BASE.REGULAR,
15181
- requestTimeout: is_null_or_undefined_isNullOrUndefined(requestTimeout) ? DEFAULT_REQUEST_TIMEOUT : requestTimeout
15412
+ requestTimeout: requestTimeout === undefined ? DEFAULT_REQUEST_TIMEOUT : requestTimeout,
15413
+ connectionTimeout: connectionTimeout === undefined ? DEFAULT_CONNECTION_TIMEOUT : connectionTimeout
15182
15414
  };
15183
15415
  }
15184
15416
  ;// CONCATENATED MODULE: ./src/core/fetchers/segment/task_prioritizer.ts
@@ -15825,7 +16057,7 @@ var SegmentInventory = /*#__PURE__*/function () {
15825
16057
  var removed = inventory.splice(indexBefore, numberOfSegmentToDelete);
15826
16058
  for (var _iterator = segment_inventory_createForOfIteratorHelperLoose(removed), _step; !(_step = _iterator()).done;) {
15827
16059
  var seg = _step.value;
15828
- if (seg.bufferedStart === undefined && seg.bufferedEnd === undefined) {
16060
+ if (seg.bufferedStart === undefined && seg.bufferedEnd === undefined && seg.status !== 2 /* ChunkStatus.Failed */) {
15829
16061
  this._bufferedHistory.addBufferedSegment(seg.infos, null);
15830
16062
  }
15831
16063
  }
@@ -15878,7 +16110,7 @@ var SegmentInventory = /*#__PURE__*/function () {
15878
16110
  var _removed = inventory.splice(inventoryIndex, inventory.length - inventoryIndex);
15879
16111
  for (var _iterator2 = segment_inventory_createForOfIteratorHelperLoose(_removed), _step2; !(_step2 = _iterator2()).done;) {
15880
16112
  var _seg = _step2.value;
15881
- if (_seg.bufferedStart === undefined && _seg.bufferedEnd === undefined) {
16113
+ if (_seg.bufferedStart === undefined && _seg.bufferedEnd === undefined && _seg.status !== 2 /* ChunkStatus.Failed */) {
15882
16114
  this._bufferedHistory.addBufferedSegment(_seg.infos, null);
15883
16115
  }
15884
16116
  }
@@ -15894,7 +16126,7 @@ var SegmentInventory = /*#__PURE__*/function () {
15894
16126
  * segment have been inserted, you should call the `completeSegment` method.
15895
16127
  * @param {Object} chunkInformation
15896
16128
  */;
15897
- _proto.insertChunk = function insertChunk(_ref) {
16129
+ _proto.insertChunk = function insertChunk(_ref, succeed) {
15898
16130
  var period = _ref.period,
15899
16131
  adaptation = _ref.adaptation,
15900
16132
  representation = _ref.representation,
@@ -15912,7 +16144,7 @@ var SegmentInventory = /*#__PURE__*/function () {
15912
16144
  }
15913
16145
  var inventory = this._inventory;
15914
16146
  var newSegment = {
15915
- partiallyPushed: true,
16147
+ status: succeed ? 0 /* ChunkStatus.PartiallyPushed */ : 2 /* ChunkStatus.Failed */,
15916
16148
  chunkSize: chunkSize,
15917
16149
  splitted: false,
15918
16150
  start: start,
@@ -16108,7 +16340,7 @@ var SegmentInventory = /*#__PURE__*/function () {
16108
16340
  // ===> : |--|====|-|
16109
16341
  src_log.warn("SI: Segment pushed is contained in a previous one", bufferType, start, end, segmentI.start, segmentI.end);
16110
16342
  var nextSegment = {
16111
- partiallyPushed: segmentI.partiallyPushed,
16343
+ status: segmentI.status,
16112
16344
  /**
16113
16345
  * Note: this sadly means we're doing as if
16114
16346
  * that chunk is present two times.
@@ -16261,7 +16493,10 @@ var SegmentInventory = /*#__PURE__*/function () {
16261
16493
  this._inventory.splice(firstI + 1, length);
16262
16494
  i -= length;
16263
16495
  }
16264
- this._inventory[firstI].partiallyPushed = false;
16496
+ if (this._inventory[firstI].status === 0 /* ChunkStatus.PartiallyPushed */) {
16497
+ this._inventory[firstI].status = 1 /* ChunkStatus.Complete */;
16498
+ }
16499
+
16265
16500
  this._inventory[firstI].chunkSize = segmentSize;
16266
16501
  this._inventory[firstI].end = lastEnd;
16267
16502
  this._inventory[firstI].bufferedEnd = lastBufferedEnd;
@@ -16276,10 +16511,12 @@ var SegmentInventory = /*#__PURE__*/function () {
16276
16511
  for (var _iterator3 = segment_inventory_createForOfIteratorHelperLoose(resSegments), _step3; !(_step3 = _iterator3()).done;) {
16277
16512
  var seg = _step3.value;
16278
16513
  if (seg.bufferedStart !== undefined && seg.bufferedEnd !== undefined) {
16279
- this._bufferedHistory.addBufferedSegment(seg.infos, {
16280
- start: seg.bufferedStart,
16281
- end: seg.bufferedEnd
16282
- });
16514
+ if (seg.status !== 2 /* ChunkStatus.Failed */) {
16515
+ this._bufferedHistory.addBufferedSegment(seg.infos, {
16516
+ start: seg.bufferedStart,
16517
+ end: seg.bufferedEnd
16518
+ });
16519
+ }
16283
16520
  } else {
16284
16521
  src_log.debug("SI: buffered range not known after sync. Skipping history.", seg.start, seg.end);
16285
16522
  }
@@ -16322,7 +16559,7 @@ var SegmentInventory = /*#__PURE__*/function () {
16322
16559
  */
16323
16560
 
16324
16561
  function bufferedStartLooksCoherent(thisSegment) {
16325
- if (thisSegment.bufferedStart === undefined || thisSegment.partiallyPushed) {
16562
+ if (thisSegment.bufferedStart === undefined || thisSegment.status !== 1 /* ChunkStatus.Complete */) {
16326
16563
  return false;
16327
16564
  }
16328
16565
  var start = thisSegment.start,
@@ -16340,7 +16577,7 @@ function bufferedStartLooksCoherent(thisSegment) {
16340
16577
  * @returns {Boolean}
16341
16578
  */
16342
16579
  function bufferedEndLooksCoherent(thisSegment) {
16343
- if (thisSegment.bufferedEnd === undefined || thisSegment.partiallyPushed) {
16580
+ if (thisSegment.bufferedEnd === undefined || thisSegment.status !== 1 /* ChunkStatus.Complete */) {
16344
16581
  return false;
16345
16582
  }
16346
16583
  var start = thisSegment.start,
@@ -16890,7 +17127,12 @@ var AudioVideoSegmentBuffer = /*#__PURE__*/function (_SegmentBuffer) {
16890
17127
  this._lastInitSegmentUniqueId = null; // initialize init segment as a security
16891
17128
  if (this._pendingTask !== null) {
16892
17129
  var error = err instanceof Error ? err : new Error("An unknown error occured when doing operations " + "on the SourceBuffer");
16893
- this._pendingTask.reject(error);
17130
+ var task = this._pendingTask;
17131
+ if (task.type === SegmentBufferOperation.Push && task.data.length === 0 && task.inventoryData !== null) {
17132
+ this._segmentInventory.insertChunk(task.inventoryData, false);
17133
+ }
17134
+ this._pendingTask = null;
17135
+ task.reject(error);
16894
17136
  }
16895
17137
  }
16896
17138
  /**
@@ -16941,7 +17183,7 @@ var AudioVideoSegmentBuffer = /*#__PURE__*/function (_SegmentBuffer) {
16941
17183
  switch (task.type) {
16942
17184
  case SegmentBufferOperation.Push:
16943
17185
  if (task.inventoryData !== null) {
16944
- this._segmentInventory.insertChunk(task.inventoryData);
17186
+ this._segmentInventory.insertChunk(task.inventoryData, true);
16945
17187
  }
16946
17188
  break;
16947
17189
  case SegmentBufferOperation.EndOfSegment:
@@ -17773,8 +18015,7 @@ function BufferGarbageCollector(_ref, cancellationSignal) {
17773
18015
  maxBufferAhead = _ref.maxBufferAhead;
17774
18016
  var lastPosition;
17775
18017
  playbackObserver.listen(function (o) {
17776
- var _a;
17777
- lastPosition = (_a = o.position.pending) !== null && _a !== void 0 ? _a : o.position.last;
18018
+ lastPosition = o.position.getWanted();
17778
18019
  clean();
17779
18020
  }, {
17780
18021
  includeLastObservation: true,
@@ -18883,7 +19124,7 @@ function doesEndSeemGarbageCollected(currentSeg, nextSeg, minimumEndTime) {
18883
19124
  return false;
18884
19125
  }
18885
19126
  if (minimumEndTime > currentSeg.bufferedEnd && currentSeg.end - currentSeg.bufferedEnd > MAX_TIME_MISSING_FROM_COMPLETE_SEGMENT) {
18886
- src_log.info("Stream: The end of the wanted segment has been garbage collected", currentSeg.start, currentSeg.bufferedStart);
19127
+ src_log.info("Stream: The end of the wanted segment has been garbage collected", currentSeg.end, currentSeg.bufferedEnd);
18887
19128
  return true;
18888
19129
  }
18889
19130
  return false;
@@ -19107,7 +19348,7 @@ function getBufferStatus(content, initialWantedTime, playbackObserver, fastSwitc
19107
19348
  * `true` if the current `RepresentationStream` has loaded all the
19108
19349
  * needed segments for this Representation until the end of the Period.
19109
19350
  */
19110
- var hasFinishedLoading = representation.index.isInitialized() && representation.index.isFinished() && neededRange.hasReachedPeriodEnd && prioritizedNeededSegments.length === 0 && segmentsOnHold.length === 0;
19351
+ var hasFinishedLoading = representation.index.isInitialized() && !representation.index.isStillAwaitingFutureSegments() && neededRange.hasReachedPeriodEnd && prioritizedNeededSegments.length === 0 && segmentsOnHold.length === 0;
19111
19352
  /**
19112
19353
  * Start time in seconds of the next available not-yet pushed segment.
19113
19354
  * `null` if no segment is wanted for the current wanted range.
@@ -19156,14 +19397,14 @@ function getRangeOfNeededSegments(content, initialWantedTime, bufferGoal) {
19156
19397
  // In that case, we want to actually request at least the last segment to
19157
19398
  // avoid ending the last Period - and by extension the content - with a
19158
19399
  // segment which isn't the last one.
19159
- if (!is_null_or_undefined_isNullOrUndefined(lastIndexPosition) && segment_buffers.isNative(content.adaptation.type) && initialWantedTime >= lastIndexPosition && representationIndex.isInitialized() && representationIndex.isFinished() && isPeriodTheCurrentAndLastOne(manifest, period, initialWantedTime)) {
19400
+ if (!is_null_or_undefined_isNullOrUndefined(lastIndexPosition) && segment_buffers.isNative(content.adaptation.type) && initialWantedTime >= lastIndexPosition && representationIndex.isInitialized() && !representationIndex.isStillAwaitingFutureSegments() && isPeriodTheCurrentAndLastOne(manifest, period, initialWantedTime)) {
19160
19401
  wantedStartPosition = lastIndexPosition - 1;
19161
19402
  } else {
19162
19403
  wantedStartPosition = initialWantedTime - 0.1;
19163
19404
  }
19164
19405
  var wantedEndPosition = wantedStartPosition + bufferGoal;
19165
19406
  var hasReachedPeriodEnd;
19166
- if (!representation.index.isInitialized() || !representation.index.isFinished() || period.end === undefined) {
19407
+ if (!representation.index.isInitialized() || representation.index.isStillAwaitingFutureSegments() || period.end === undefined) {
19167
19408
  hasReachedPeriodEnd = false;
19168
19409
  } else if (lastIndexPosition === undefined) {
19169
19410
  // We do not know the end of this index.
@@ -19216,7 +19457,7 @@ function getPlayableBufferedSegments(neededRange, segmentInventory) {
19216
19457
  for (var i = segmentInventory.length - 1; i >= 0; i--) {
19217
19458
  var eltInventory = segmentInventory[i];
19218
19459
  var representation = eltInventory.infos.representation;
19219
- if (!eltInventory.partiallyPushed && representation.decipherable !== false && representation.isSupported) {
19460
+ if (eltInventory.status === 1 /* ChunkStatus.Complete */ && representation.decipherable !== false && representation.isSupported) {
19220
19461
  var inventorySegment = eltInventory.infos.segment;
19221
19462
  var eltInventoryStart = inventorySegment.time / inventorySegment.timescale;
19222
19463
  var eltInventoryEnd = !inventorySegment.complete ? eltInventory.end : eltInventoryStart + inventorySegment.duration / inventorySegment.timescale;
@@ -19400,7 +19641,7 @@ function appendSegmentToBuffer(_x, _x2, _x3, _x4) {
19400
19641
  }
19401
19642
  function _appendSegmentToBuffer() {
19402
19643
  _appendSegmentToBuffer = _asyncToGenerator( /*#__PURE__*/regenerator_default().mark(function _callee(playbackObserver, segmentBuffer, dataInfos, cancellationSignal) {
19403
- var _a, reason, _playbackObserver$get, position, currentPos, _reason;
19644
+ var reason, _playbackObserver$get, position, currentPos, _reason;
19404
19645
  return regenerator_default().wrap(function _callee$(_context) {
19405
19646
  while (1) switch (_context.prev = _context.next) {
19406
19647
  case 0:
@@ -19429,7 +19670,7 @@ function _appendSegmentToBuffer() {
19429
19670
  });
19430
19671
  case 14:
19431
19672
  _playbackObserver$get = playbackObserver.getReference().getValue(), position = _playbackObserver$get.position;
19432
- currentPos = (_a = position.pending) !== null && _a !== void 0 ? _a : position.last;
19673
+ currentPos = position.getWanted();
19433
19674
  _context.prev = 16;
19434
19675
  _context.next = 19;
19435
19676
  return forceGarbageCollection(currentPos, segmentBuffer, cancellationSignal);
@@ -19835,13 +20076,12 @@ function RepresentationStream(_ref, callbacks, parentCancelSignal) {
19835
20076
  * issues at the current time, calling the right callbacks if necessary.
19836
20077
  */
19837
20078
  function checkStatus() {
19838
- var _a, _b;
19839
20079
  if (segmentsLoadingCanceller.isUsed()) {
19840
20080
  return; // Stop all buffer status checking if load operations are stopped
19841
20081
  }
19842
20082
 
19843
20083
  var observation = playbackObserver.getReference().getValue();
19844
- var initialWantedTime = (_a = observation.position.pending) !== null && _a !== void 0 ? _a : observation.position.last;
20084
+ var initialWantedTime = observation.position.getWanted();
19845
20085
  var status = getBufferStatus(content, initialWantedTime, playbackObserver, fastSwitchThreshold.getValue(), bufferGoal.getValue(), maxBufferSize.getValue(), segmentBuffer);
19846
20086
  var neededSegments = status.neededSegments;
19847
20087
  var neededInitSegment = null;
@@ -19852,7 +20092,7 @@ function RepresentationStream(_ref, callbacks, parentCancelSignal) {
19852
20092
  } else if (initSegmentState.isLoaded) {
19853
20093
  src_log.warn("Stream: Uninitialized index with an already loaded " + "initialization segment");
19854
20094
  } else {
19855
- var wantedStart = (_b = observation.position.pending) !== null && _b !== void 0 ? _b : observation.position.last;
20095
+ var wantedStart = observation.position.getWanted();
19856
20096
  neededInitSegment = {
19857
20097
  segment: initSegmentState.segment,
19858
20098
  priority: getSegmentPriority(period.start, wantedStart)
@@ -19905,7 +20145,7 @@ function RepresentationStream(_ref, callbacks, parentCancelSignal) {
19905
20145
  }
19906
20146
  callbacks.streamStatusUpdate({
19907
20147
  period: period,
19908
- position: observation.position.last,
20148
+ position: observation.position.getWanted(),
19909
20149
  bufferType: bufferType,
19910
20150
  imminentDiscontinuity: status.imminentDiscontinuity,
19911
20151
  isEmptyStream: false,
@@ -20173,22 +20413,30 @@ function getRepresentationsSwitchingStrategy(period, adaptation, settings, segme
20173
20413
  value: undefined
20174
20414
  };
20175
20415
  }
20176
- var currentTime = playbackObserver.getCurrentTime();
20177
20416
  var readyState = playbackObserver.getReadyState();
20178
- if (settings.switchingMode === "reload" &&
20179
- // We're playing the current Period
20180
- isTimeInRange({
20181
- start: start,
20182
- end: end
20183
- }, currentTime) &&
20184
- // There is data for the current position
20185
- readyState > 1 &&
20186
- // We're not playing the current wanted video Adaptation
20187
- !isTimeInRanges(rangesWithReps, currentTime)) {
20188
- return {
20189
- type: "needs-reload",
20190
- value: undefined
20191
- };
20417
+ if (settings.switchingMode === "reload" && readyState > 1) {
20418
+ var lastObservation = playbackObserver.getReference().getValue();
20419
+ if (lastObservation.position.isAwaitingFuturePosition()) {
20420
+ // We are not at the position we want to reach (e.g. initial seek, tizen
20421
+ // seek-back...), just reload as checks here would be too complex
20422
+ return {
20423
+ type: "needs-reload",
20424
+ value: undefined
20425
+ };
20426
+ } else {
20427
+ var currentTime = playbackObserver.getCurrentTime();
20428
+ if (isTimeInRange({
20429
+ start: start,
20430
+ end: end
20431
+ }, currentTime) &&
20432
+ // We're not playing the current wanted video Adaptation
20433
+ !isTimeInRanges(rangesWithReps, currentTime)) {
20434
+ return {
20435
+ type: "needs-reload",
20436
+ value: undefined
20437
+ };
20438
+ }
20439
+ }
20192
20440
  }
20193
20441
  // From here, clean-up data from the previous Adaptation, if one
20194
20442
  var shouldFlush = settings.switchingMode === "direct";
@@ -20221,9 +20469,10 @@ function getRepresentationsSwitchingStrategy(period, adaptation, settings, segme
20221
20469
  if (paddingAfter == null) {
20222
20470
  paddingAfter = 0;
20223
20471
  }
20472
+ var _currentTime = playbackObserver.getCurrentTime();
20224
20473
  rangesToExclude.push({
20225
- start: currentTime - paddingBefore,
20226
- end: currentTime + paddingAfter
20474
+ start: _currentTime - paddingBefore,
20475
+ end: _currentTime + paddingAfter
20227
20476
  });
20228
20477
  }
20229
20478
  // Now remove possible small range from the end if there is a segment from the
@@ -20851,10 +21100,10 @@ function areCodecsCompatible(a, b) {
20851
21100
  * @param {Object} segmentBuffer
20852
21101
  * @param {Object} period
20853
21102
  * @param {Object} adaptation
20854
- * @param {Object} playbackInfo
21103
+ * @param {Object} playbackObserver
20855
21104
  * @returns {Object}
20856
21105
  */
20857
- function getAdaptationSwitchStrategy(segmentBuffer, period, adaptation, switchingMode, playbackInfo, options) {
21106
+ function getAdaptationSwitchStrategy(segmentBuffer, period, adaptation, switchingMode, playbackObserver, options) {
20858
21107
  if (segmentBuffer.codec !== undefined && options.onCodecSwitch === "reload" && !hasCompatibleCodec(adaptation, segmentBuffer.codec)) {
20859
21108
  return {
20860
21109
  type: "needs-reload",
@@ -20906,24 +21155,28 @@ function getAdaptationSwitchStrategy(segmentBuffer, period, adaptation, switchin
20906
21155
  value: undefined
20907
21156
  };
20908
21157
  }
20909
- var currentTime = playbackInfo.currentTime;
20910
- if (switchingMode === "reload" &&
20911
- // We're playing the current Period
20912
- isTimeInRange({
20913
- start: start,
20914
- end: end
20915
- }, currentTime) && (
20916
- // There is data for the current position or the codecs are differents
20917
- playbackInfo.readyState > 1 || !adaptation.getPlayableRepresentations().some(function (rep) {
20918
- var _a;
20919
- return are_codecs_compatible(rep.getMimeTypeString(), (_a = segmentBuffer.codec) !== null && _a !== void 0 ? _a : "");
20920
- })) &&
20921
- // We're not playing the current wanted video Adaptation
20922
- !isTimeInRanges(adaptationInBuffer, currentTime)) {
20923
- return {
20924
- type: "needs-reload",
20925
- value: undefined
20926
- };
21158
+ var currentTime = playbackObserver.getCurrentTime();
21159
+ var readyState = playbackObserver.getReadyState();
21160
+ if (switchingMode === "reload" && readyState > 1) {
21161
+ var lastObservation = playbackObserver.getReference().getValue();
21162
+ if (lastObservation.position.isAwaitingFuturePosition()) {
21163
+ // We are not at the position we want to reach (e.g. initial seek, tizen
21164
+ // seek-back...), just reload as checks here would be too complex
21165
+ return {
21166
+ type: "needs-reload",
21167
+ value: undefined
21168
+ };
21169
+ } else if (isTimeInRange({
21170
+ start: start,
21171
+ end: end
21172
+ }, currentTime) &&
21173
+ // We're not playing the current wanted video Adaptation
21174
+ !isTimeInRanges(adaptationInBuffer, currentTime)) {
21175
+ return {
21176
+ type: "needs-reload",
21177
+ value: undefined
21178
+ };
21179
+ }
20927
21180
  }
20928
21181
  // From here, clean-up data from the previous Adaptation, if one
20929
21182
  var shouldCleanAll = switchingMode === "direct";
@@ -21005,7 +21258,7 @@ function hasCompatibleCodec(adaptation, segmentBufferCodec) {
21005
21258
  /**
21006
21259
  * Returns buffered ranges of what we know correspond to the given `adaptation`
21007
21260
  * in the SegmentBuffer.
21008
- * @param {Object} segmentBuffer
21261
+ * @param {Array.<Object>} inventory
21009
21262
  * @param {Object} period
21010
21263
  * @param {Object} adaptation
21011
21264
  * @returns {Array.<Object>}
@@ -21123,7 +21376,7 @@ function PeriodStream(_ref, callbacks, parentCancelSignal) {
21123
21376
  adaptationRef.onUpdate(function (choice) {
21124
21377
  // As an IIFE to profit from async/await while respecting onUpdate's signature
21125
21378
  _asyncToGenerator( /*#__PURE__*/regenerator_default().mark(function _callee() {
21126
- var _a, streamCanceller, segmentBufferStatus, periodEnd, _config$getCurrent, DELTA_POSITION_AFTER_RELOAD, relativePosAfterSwitch, adaptation, representations, readyState, segmentBuffer, playbackInfos, strategy, _iterator3, _step3, _step3$value, start, end;
21379
+ var _a, streamCanceller, segmentBufferStatus, periodEnd, _config$getCurrent, DELTA_POSITION_AFTER_RELOAD, relativePosAfterSwitch, adaptation, representations, segmentBuffer, strategy, _iterator3, _step3, _step3$value, start, end;
21127
21380
  return regenerator_default().wrap(function _callee$(_context) {
21128
21381
  while (1) switch (_context.prev = _context.next) {
21129
21382
  case 0:
@@ -21248,65 +21501,60 @@ function PeriodStream(_ref, callbacks, parentCancelSignal) {
21248
21501
  }
21249
21502
  return _context.abrupt("return");
21250
21503
  case 45:
21251
- readyState = playbackObserver.getReadyState();
21252
21504
  segmentBuffer = createOrReuseSegmentBuffer(segmentBuffersStore, bufferType, adaptation, options);
21253
- playbackInfos = {
21254
- currentTime: playbackObserver.getCurrentTime(),
21255
- readyState: readyState
21256
- };
21257
- strategy = getAdaptationSwitchStrategy(segmentBuffer, period, adaptation, choice.switchingMode, playbackInfos, options);
21505
+ strategy = getAdaptationSwitchStrategy(segmentBuffer, period, adaptation, choice.switchingMode, playbackObserver, options);
21258
21506
  if (!(strategy.type === "needs-reload")) {
21259
- _context.next = 51;
21507
+ _context.next = 49;
21260
21508
  break;
21261
21509
  }
21262
21510
  return _context.abrupt("return", askForMediaSourceReload(relativePosAfterSwitch, true, streamCanceller.signal));
21263
- case 51:
21264
- _context.next = 53;
21511
+ case 49:
21512
+ _context.next = 51;
21265
21513
  return segmentBuffersStore.waitForUsableBuffers(streamCanceller.signal);
21266
- case 53:
21514
+ case 51:
21267
21515
  if (!streamCanceller.isUsed()) {
21268
- _context.next = 55;
21516
+ _context.next = 53;
21269
21517
  break;
21270
21518
  }
21271
21519
  return _context.abrupt("return");
21272
- case 55:
21520
+ case 53:
21273
21521
  if (!(strategy.type === "flush-buffer" || strategy.type === "clean-buffer")) {
21274
- _context.next = 69;
21522
+ _context.next = 67;
21275
21523
  break;
21276
21524
  }
21277
21525
  _iterator3 = period_stream_createForOfIteratorHelperLoose(strategy.value);
21278
- case 57:
21526
+ case 55:
21279
21527
  if ((_step3 = _iterator3()).done) {
21280
- _context.next = 65;
21528
+ _context.next = 63;
21281
21529
  break;
21282
21530
  }
21283
21531
  _step3$value = _step3.value, start = _step3$value.start, end = _step3$value.end;
21284
- _context.next = 61;
21532
+ _context.next = 59;
21285
21533
  return segmentBuffer.removeBuffer(start, end, streamCanceller.signal);
21286
- case 61:
21534
+ case 59:
21287
21535
  if (!streamCanceller.isUsed()) {
21288
- _context.next = 63;
21536
+ _context.next = 61;
21289
21537
  break;
21290
21538
  }
21291
21539
  return _context.abrupt("return");
21292
- case 63:
21293
- _context.next = 57;
21540
+ case 61:
21541
+ _context.next = 55;
21294
21542
  break;
21295
- case 65:
21543
+ case 63:
21296
21544
  if (!(strategy.type === "flush-buffer")) {
21297
- _context.next = 69;
21545
+ _context.next = 67;
21298
21546
  break;
21299
21547
  }
21300
21548
  callbacks.needsBufferFlush();
21301
21549
  if (!streamCanceller.isUsed()) {
21302
- _context.next = 69;
21550
+ _context.next = 67;
21303
21551
  break;
21304
21552
  }
21305
21553
  return _context.abrupt("return");
21306
- case 69:
21554
+ case 67:
21307
21555
  garbageCollectors.get(segmentBuffer)(streamCanceller.signal);
21308
21556
  createAdaptationStream(adaptation, representations, segmentBuffer, streamCanceller.signal);
21309
- case 71:
21557
+ case 69:
21310
21558
  case "end":
21311
21559
  return _context.stop();
21312
21560
  }
@@ -21464,7 +21712,7 @@ function createAdaptationStreamPlaybackObserver(initialPlaybackObserver, segment
21464
21712
  function constructAdaptationStreamPlaybackObservation() {
21465
21713
  var baseObservation = observationRef.getValue();
21466
21714
  var buffered = segmentBuffer.getBufferedRanges();
21467
- var bufferGap = getLeftSizeOfBufferedTimeRange(buffered, baseObservation.position.last);
21715
+ var bufferGap = getLeftSizeOfBufferedTimeRange(buffered, baseObservation.position.getWanted());
21468
21716
  return object_assign({}, baseObservation, {
21469
21717
  bufferGap: bufferGap
21470
21718
  });
@@ -21500,7 +21748,7 @@ function createEmptyAdaptationStream(playbackObserver, wantedBufferAhead, buffer
21500
21748
  function sendStatus() {
21501
21749
  var observation = playbackObserver.getReference().getValue();
21502
21750
  var wba = wantedBufferAhead.getValue();
21503
- var position = observation.position.last;
21751
+ var position = observation.position.getWanted();
21504
21752
  if (period.end !== undefined && position + wba >= period.end) {
21505
21753
  src_log.debug("Stream: full \"empty\" AdaptationStream", bufferType);
21506
21754
  hasFinishedLoading = true;
@@ -21508,8 +21756,8 @@ function createEmptyAdaptationStream(playbackObserver, wantedBufferAhead, buffer
21508
21756
  callbacks.streamStatusUpdate({
21509
21757
  period: period,
21510
21758
  bufferType: bufferType,
21511
- position: position,
21512
21759
  imminentDiscontinuity: null,
21760
+ position: position,
21513
21761
  isEmptyStream: true,
21514
21762
  hasFinishedLoading: hasFinishedLoading,
21515
21763
  neededSegments: []
@@ -21683,14 +21931,16 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21683
21931
  wantedBufferAhead = options.wantedBufferAhead,
21684
21932
  maxVideoBufferSize = options.maxVideoBufferSize;
21685
21933
  var _config$getCurrent = config.getCurrent(),
21934
+ MINIMUM_MAX_BUFFER_AHEAD = _config$getCurrent.MINIMUM_MAX_BUFFER_AHEAD,
21686
21935
  MAXIMUM_MAX_BUFFER_AHEAD = _config$getCurrent.MAXIMUM_MAX_BUFFER_AHEAD,
21687
21936
  MAXIMUM_MAX_BUFFER_BEHIND = _config$getCurrent.MAXIMUM_MAX_BUFFER_BEHIND;
21688
21937
  // Keep track of a unique BufferGarbageCollector created per
21689
21938
  // SegmentBuffer.
21690
21939
  var garbageCollectors = new WeakMapMemory(function (segmentBuffer) {
21940
+ var _a, _b;
21691
21941
  var bufferType = segmentBuffer.bufferType;
21692
- var defaultMaxBehind = MAXIMUM_MAX_BUFFER_BEHIND[bufferType] != null ? MAXIMUM_MAX_BUFFER_BEHIND[bufferType] : Infinity;
21693
- var defaultMaxAhead = MAXIMUM_MAX_BUFFER_AHEAD[bufferType] != null ? MAXIMUM_MAX_BUFFER_AHEAD[bufferType] : Infinity;
21942
+ var defaultMaxBehind = (_a = MAXIMUM_MAX_BUFFER_BEHIND[bufferType]) !== null && _a !== void 0 ? _a : Infinity;
21943
+ var maxAheadHigherBound = (_b = MAXIMUM_MAX_BUFFER_AHEAD[bufferType]) !== null && _b !== void 0 ? _b : Infinity;
21694
21944
  return function (gcCancelSignal) {
21695
21945
  BufferGarbageCollector({
21696
21946
  segmentBuffer: segmentBuffer,
@@ -21699,7 +21949,9 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21699
21949
  return Math.min(val, defaultMaxBehind);
21700
21950
  }, gcCancelSignal),
21701
21951
  maxBufferAhead: createMappedReference(maxBufferAhead, function (val) {
21702
- return Math.min(val, defaultMaxAhead);
21952
+ var _a;
21953
+ var lowerBound = Math.max(val, (_a = MINIMUM_MAX_BUFFER_AHEAD[bufferType]) !== null && _a !== void 0 ? _a : 0);
21954
+ return Math.min(lowerBound, maxAheadHigherBound);
21703
21955
  }, gcCancelSignal)
21704
21956
  }, gcCancelSignal);
21705
21957
  };
@@ -21738,8 +21990,8 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21738
21990
  // than the ones already considered
21739
21991
  playbackObserver.listen(function (_ref) {
21740
21992
  var position = _ref.position;
21741
- var _a, _b;
21742
- var time = (_a = position.pending) !== null && _a !== void 0 ? _a : position.last;
21993
+ var _a;
21994
+ var time = position.getWanted();
21743
21995
  if (!enableOutOfBoundsCheck || !isOutOfPeriodList(time)) {
21744
21996
  return;
21745
21997
  }
@@ -21757,7 +22009,7 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21757
22009
  currentCanceller.cancel();
21758
22010
  currentCanceller = new TaskCanceller();
21759
22011
  currentCanceller.linkToSignal(orchestratorCancelSignal);
21760
- var nextPeriod = (_b = manifest.getPeriodForTime(time)) !== null && _b !== void 0 ? _b : manifest.getNextPeriod(time);
22012
+ var nextPeriod = (_a = manifest.getPeriodForTime(time)) !== null && _a !== void 0 ? _a : manifest.getNextPeriod(time);
21761
22013
  if (nextPeriod === undefined) {
21762
22014
  src_log.warn("Stream: The wanted position is not found in the Manifest.");
21763
22015
  return;
@@ -21929,7 +22181,6 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21929
22181
  // to reduce the risk of race conditions where the next observation
21930
22182
  // was going to be emitted synchronously.
21931
22183
  queue_microtask(function () {
21932
- var _a;
21933
22184
  if (orchestratorCancelSignal.isCancelled()) {
21934
22185
  return;
21935
22186
  }
@@ -21946,7 +22197,7 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
21946
22197
  return;
21947
22198
  }
21948
22199
  }
21949
- var lastPosition = (_a = observation.position.pending) !== null && _a !== void 0 ? _a : observation.position.last;
22200
+ var lastPosition = observation.position.getWanted();
21950
22201
  var newInitialPeriod = manifest.getPeriodForTime(lastPosition);
21951
22202
  if (newInitialPeriod == null) {
21952
22203
  callbacks.error(new MediaError("MEDIA_TIME_NOT_FOUND", "The wanted position is not found in the Manifest."));
@@ -22008,9 +22259,8 @@ function StreamOrchestrator(content, playbackObserver, representationEstimator,
22008
22259
  // that Period.
22009
22260
  playbackObserver.listen(function (_ref2, stopListeningObservations) {
22010
22261
  var position = _ref2.position;
22011
- var _a, _b;
22012
- if (basePeriod.end !== undefined && ((_a = position.pending) !== null && _a !== void 0 ? _a : position.last) >= basePeriod.end) {
22013
- src_log.info("Stream: Destroying PeriodStream as the current playhead moved above it", bufferType, basePeriod.start, (_b = position.pending) !== null && _b !== void 0 ? _b : position.last, basePeriod.end);
22262
+ if (basePeriod.end !== undefined && position.getWanted() >= basePeriod.end) {
22263
+ src_log.info("Stream: Destroying PeriodStream as the current playhead moved above it", bufferType, basePeriod.start, position.getWanted(), basePeriod.end);
22014
22264
  stopListeningObservations();
22015
22265
  consecutivePeriodStreamCb.periodStreamCleared({
22016
22266
  type: bufferType,
@@ -22162,7 +22412,7 @@ function needsFlushingAfterClean(observation, cleanedRanges) {
22162
22412
  if (cleanedRanges.length === 0) {
22163
22413
  return false;
22164
22414
  }
22165
- var curPos = observation.position.last;
22415
+ var curPos = observation.position.getPolled();
22166
22416
  // Based on the playback direction, we just check whether we may encounter
22167
22417
  // the corresponding ranges, without seeking or re-switching playback
22168
22418
  // direction which is expected to lead to a low-level flush anyway.
@@ -22270,8 +22520,8 @@ function content_time_boundaries_observer_arrayLikeToArray(arr, len) { if (len =
22270
22520
  /**
22271
22521
  * Observes what's being played and take care of media events relating to time
22272
22522
  * boundaries:
22273
- * - Emits a `durationUpdate` when the duration of the current content is
22274
- * known and every time it changes.
22523
+ * - Emits a `endingPositionChange` when the known maximum playable position
22524
+ * of the current content is known and every time it changes.
22275
22525
  * - Emits `endOfStream` API once segments have been pushed until the end and
22276
22526
  * `resumeStream` if downloads starts back.
22277
22527
  * - Emits a `periodChange` event when the currently-playing Period seemed to
@@ -22303,8 +22553,7 @@ var ContentTimeBoundariesObserver = /*#__PURE__*/function (_EventEmitter) {
22303
22553
  var cancelSignal = _this._canceller.signal;
22304
22554
  playbackObserver.listen(function (_ref) {
22305
22555
  var position = _ref.position;
22306
- var _a;
22307
- var wantedPosition = (_a = position.pending) !== null && _a !== void 0 ? _a : position.last;
22556
+ var wantedPosition = position.getWanted();
22308
22557
  if (wantedPosition < manifest.getMinimumSafePosition()) {
22309
22558
  var warning = new MediaError("MEDIA_TIME_BEFORE_MANIFEST", "The current position is behind the " + "earliest time announced in the Manifest.");
22310
22559
  _this.trigger("warning", warning);
@@ -22317,7 +22566,7 @@ var ContentTimeBoundariesObserver = /*#__PURE__*/function (_EventEmitter) {
22317
22566
  clearSignal: cancelSignal
22318
22567
  });
22319
22568
  manifest.addEventListener("manifestUpdate", function () {
22320
- _this.trigger("durationUpdate", _this._getManifestDuration());
22569
+ _this.trigger("endingPositionChange", _this._getManifestEndTime());
22321
22570
  if (cancelSignal.isCancelled()) {
22322
22571
  return;
22323
22572
  }
@@ -22326,12 +22575,13 @@ var ContentTimeBoundariesObserver = /*#__PURE__*/function (_EventEmitter) {
22326
22575
  return _this;
22327
22576
  }
22328
22577
  /**
22329
- * Returns an estimate of the current duration of the content.
22578
+ * Returns an estimate of the current last position which may be played in
22579
+ * the content at the moment.
22330
22580
  * @returns {Object}
22331
22581
  */
22332
22582
  var _proto = ContentTimeBoundariesObserver.prototype;
22333
- _proto.getCurrentDuration = function getCurrentDuration() {
22334
- return this._getManifestDuration();
22583
+ _proto.getCurrentEndingTime = function getCurrentEndingTime() {
22584
+ return this._getManifestEndTime();
22335
22585
  }
22336
22586
  /**
22337
22587
  * Method to call any time an Adaptation has been selected.
@@ -22357,14 +22607,14 @@ var ContentTimeBoundariesObserver = /*#__PURE__*/function (_EventEmitter) {
22357
22607
  this._maximumPositionCalculator.updateLastVideoAdaptation(adaptation);
22358
22608
  }
22359
22609
  var endingPosition = this._maximumPositionCalculator.getEndingPosition();
22360
- var newDuration = endingPosition !== undefined ? {
22610
+ var newEndingPosition = endingPosition !== undefined ? {
22361
22611
  isEnd: true,
22362
- duration: endingPosition
22612
+ endingPosition: endingPosition
22363
22613
  } : {
22364
22614
  isEnd: false,
22365
- duration: this._maximumPositionCalculator.getMaximumAvailablePosition()
22615
+ endingPosition: this._maximumPositionCalculator.getMaximumAvailablePosition()
22366
22616
  };
22367
- this.trigger("durationUpdate", newDuration);
22617
+ this.trigger("endingPositionChange", newEndingPosition);
22368
22618
  }
22369
22619
  }
22370
22620
  }
@@ -22504,14 +22754,14 @@ var ContentTimeBoundariesObserver = /*#__PURE__*/function (_EventEmitter) {
22504
22754
  if (_ret) return _ret.v;
22505
22755
  }
22506
22756
  };
22507
- _proto._getManifestDuration = function _getManifestDuration() {
22757
+ _proto._getManifestEndTime = function _getManifestEndTime() {
22508
22758
  var endingPosition = this._maximumPositionCalculator.getEndingPosition();
22509
22759
  return endingPosition !== undefined ? {
22510
22760
  isEnd: true,
22511
- duration: endingPosition
22761
+ endingPosition: endingPosition
22512
22762
  } : {
22513
22763
  isEnd: false,
22514
- duration: this._maximumPositionCalculator.getMaximumAvailablePosition()
22764
+ endingPosition: this._maximumPositionCalculator.getMaximumAvailablePosition()
22515
22765
  };
22516
22766
  };
22517
22767
  _proto._lazilyCreateActiveStreamInfo = function _lazilyCreateActiveStreamInfo(bufferType) {
@@ -22588,9 +22838,8 @@ var MaximumPositionCalculator = /*#__PURE__*/function () {
22588
22838
  * @returns {number}
22589
22839
  */;
22590
22840
  _proto2.getMaximumAvailablePosition = function getMaximumAvailablePosition() {
22591
- var _a;
22592
22841
  if (this._manifest.isDynamic) {
22593
- return (_a = this._manifest.getLivePosition()) !== null && _a !== void 0 ? _a : this._manifest.getMaximumSafePosition();
22842
+ return this._manifest.getMaximumSafePosition();
22594
22843
  }
22595
22844
  if (this._lastVideoAdaptation === undefined || this._lastAudioAdaptation === undefined) {
22596
22845
  return this._manifest.getMaximumSafePosition();
@@ -22920,10 +23169,8 @@ function openMediaSource(mediaElement, unlinkSignal) {
22920
23169
  function createStreamPlaybackObserver(srcPlaybackObserver, _ref, fnCancelSignal) {
22921
23170
  var autoPlay = _ref.autoPlay,
22922
23171
  initialPlayPerformed = _ref.initialPlayPerformed,
22923
- initialSeekPerformed = _ref.initialSeekPerformed,
22924
23172
  manifest = _ref.manifest,
22925
- speed = _ref.speed,
22926
- startTime = _ref.startTime;
23173
+ speed = _ref.speed;
22927
23174
  return srcPlaybackObserver.deriveReadOnlyObserver(function transform(observationRef, parentObserverCancelSignal) {
22928
23175
  var canceller = new TaskCanceller();
22929
23176
  canceller.linkToSignal(parentObserverCancelSignal);
@@ -22941,10 +23188,7 @@ function createStreamPlaybackObserver(srcPlaybackObserver, _ref, fnCancelSignal)
22941
23188
  function constructStreamPlaybackObservation() {
22942
23189
  var observation = observationRef.getValue();
22943
23190
  var lastSpeed = speed.getValue();
22944
- var pendingPosition;
22945
- if (!initialSeekPerformed.getValue()) {
22946
- pendingPosition = startTime;
22947
- } else if (!manifest.isDynamic || manifest.isLastPeriodKnown) {
23191
+ if (!manifest.isDynamic || manifest.isLastPeriodKnown) {
22948
23192
  // HACK: When the position is actually further than the maximum
22949
23193
  // position for a finished content, we actually want to be loading
22950
23194
  // the last segment before ending.
@@ -22952,17 +23196,23 @@ function createStreamPlaybackObserver(srcPlaybackObserver, _ref, fnCancelSignal)
22952
23196
  // want to seek one second before the period's end (despite never
22953
23197
  // doing it).
22954
23198
  var lastPeriod = manifest.periods[manifest.periods.length - 1];
22955
- if (lastPeriod !== undefined && lastPeriod.end !== undefined && observation.position > lastPeriod.end) {
22956
- pendingPosition = lastPeriod.end - 1;
23199
+ if (lastPeriod !== undefined && lastPeriod.end !== undefined) {
23200
+ var wantedPosition = observation.position.getWanted();
23201
+ if (wantedPosition >= lastPeriod.start && wantedPosition >= lastPeriod.end - 1) {
23202
+ // We're after the end of the last Period, check if `buffered`
23203
+ // indicates that the last segment is probably not loaded, in which
23204
+ // case act as if we want to load one second before the end.
23205
+ var buffered = observation.buffered;
23206
+ if (buffered.length === 0 || buffered.end(buffered.length - 1) < observation.duration - 1) {
23207
+ observation.position.forceWantedPosition(lastPeriod.end - 1);
23208
+ }
23209
+ }
22957
23210
  }
22958
23211
  }
22959
23212
  return {
22960
23213
  // TODO more exact according to the current Adaptation chosen?
22961
23214
  maximumPosition: manifest.getMaximumSafePosition(),
22962
- position: {
22963
- last: observation.position,
22964
- pending: pendingPosition
22965
- },
23215
+ position: observation.position,
22966
23216
  duration: observation.duration,
22967
23217
  paused: {
22968
23218
  last: observation.paused,
@@ -23106,15 +23356,10 @@ function maintainEndOfStream(mediaSource, cancelSignal) {
23106
23356
  * @returns {Number}
23107
23357
  */
23108
23358
  function getInitialTime(manifest, lowLatencyMode, startAt) {
23359
+ var _a;
23109
23360
  if (!is_null_or_undefined_isNullOrUndefined(startAt)) {
23110
23361
  var min = manifest.getMinimumSafePosition();
23111
- var max;
23112
- if (manifest.isLive) {
23113
- max = manifest.getLivePosition();
23114
- }
23115
- if (max === undefined) {
23116
- max = manifest.getMaximumSafePosition();
23117
- }
23362
+ var max = manifest.getMaximumSafePosition();
23118
23363
  if (!is_null_or_undefined_isNullOrUndefined(startAt.position)) {
23119
23364
  src_log.debug("Init: using startAt.minimumPosition");
23120
23365
  return Math.max(Math.min(startAt.position, max), min);
@@ -23131,6 +23376,11 @@ function getInitialTime(manifest, lowLatencyMode, startAt) {
23131
23376
  src_log.debug("Init: using startAt.fromLastPosition");
23132
23377
  var fromLastPosition = startAt.fromLastPosition;
23133
23378
  return fromLastPosition >= 0 ? max : Math.max(min, max + fromLastPosition);
23379
+ } else if (!is_null_or_undefined_isNullOrUndefined(startAt.fromLivePosition)) {
23380
+ src_log.debug("Init: using startAt.fromLivePosition");
23381
+ var livePosition = (_a = manifest.getLivePosition()) !== null && _a !== void 0 ? _a : max;
23382
+ var fromLivePosition = startAt.fromLivePosition;
23383
+ return fromLivePosition >= 0 ? livePosition : Math.max(min, livePosition + fromLivePosition);
23134
23384
  } else if (!is_null_or_undefined_isNullOrUndefined(startAt.percentage)) {
23135
23385
  src_log.debug("Init: using startAt.percentage");
23136
23386
  var percentage = startAt.percentage;
@@ -23319,116 +23569,156 @@ function getLoadedReference(playbackObserver, mediaElement, isDirectfile, cancel
23319
23569
 
23320
23570
 
23321
23571
 
23322
-
23323
23572
  /**
23324
23573
  * Seek as soon as possible at the initially wanted position and play if
23325
23574
  * autoPlay is wanted.
23326
- * @param {HTMLMediaElement} mediaElement
23327
- * @param {Object} playbackObserver
23328
- * @param {number|Function} startTime
23329
- * @param {boolean} mustAutoPlay
23330
- * @param {Function} onWarning
23575
+ * @param {Object} args
23331
23576
  * @param {Object} cancelSignal
23332
23577
  * @returns {Object}
23333
23578
  */
23334
- function performInitialSeekAndPlay(mediaElement, playbackObserver, startTime, mustAutoPlay, onWarning, cancelSignal) {
23335
- var resolveAutoPlay;
23336
- var rejectAutoPlay;
23337
- var autoPlayResult = new Promise(function (res, rej) {
23338
- resolveAutoPlay = res;
23339
- rejectAutoPlay = rej;
23340
- });
23341
- var initialSeekPerformed = new utils_reference(false, cancelSignal);
23579
+ function performInitialSeekAndPlay(_ref, cancelSignal) {
23580
+ var mediaElement = _ref.mediaElement,
23581
+ playbackObserver = _ref.playbackObserver,
23582
+ startTime = _ref.startTime,
23583
+ mustAutoPlay = _ref.mustAutoPlay,
23584
+ isDirectfile = _ref.isDirectfile,
23585
+ onWarning = _ref.onWarning;
23342
23586
  var initialPlayPerformed = new utils_reference(false, cancelSignal);
23343
- mediaElement.addEventListener("loadedmetadata", onLoadedMetadata);
23344
- var deregisterCancellation = cancelSignal.register(function (err) {
23345
- mediaElement.removeEventListener("loadedmetadata", onLoadedMetadata);
23346
- rejectAutoPlay(err);
23347
- });
23348
- if (mediaElement.readyState >= READY_STATES.HAVE_METADATA) {
23349
- onLoadedMetadata();
23350
- }
23351
- return {
23352
- autoPlayResult: autoPlayResult,
23353
- initialPlayPerformed: initialPlayPerformed,
23354
- initialSeekPerformed: initialSeekPerformed
23355
- };
23356
- function onLoadedMetadata() {
23357
- mediaElement.removeEventListener("loadedmetadata", onLoadedMetadata);
23358
- var initialTime = typeof startTime === "function" ? startTime() : startTime;
23359
- src_log.info("Init: Set initial time", initialTime);
23360
- playbackObserver.setCurrentTime(initialTime);
23361
- initialSeekPerformed.setValue(true);
23362
- initialSeekPerformed.finish();
23363
- if (shouldValidateMetadata() && mediaElement.duration === 0) {
23364
- var error = new MediaError("MEDIA_ERR_NOT_LOADED_METADATA", "Cannot load automatically: your browser " + "falsely announced having loaded the content.");
23365
- onWarning(error);
23366
- }
23367
- if (cancelSignal.isCancelled()) {
23368
- return;
23587
+ var autoPlayResult = new Promise(function (resolveAutoPlay, rejectAutoPlay) {
23588
+ // `startTime` defined as a function might depend on metadata to make its
23589
+ // choice, such as the content duration, minimum and/or maximum position.
23590
+ //
23591
+ // The RxPlayer might already know those through the Manifest file for
23592
+ // non-Directfile contents, yet only through the `HTMLMediaElement` once a
23593
+ // a sufficient `readyState` has been reached for directfile contents.
23594
+ // So let's divide the two possibilities here.
23595
+ if (!isDirectfile || typeof startTime === "number") {
23596
+ playbackObserver.setCurrentTime(typeof startTime === "number" ? startTime : startTime());
23597
+ waitForSeekable();
23598
+ } else {
23599
+ playbackObserver.listen(function (obs, stopListening) {
23600
+ if (obs.readyState >= 1) {
23601
+ stopListening();
23602
+ playbackObserver.setCurrentTime(typeof startTime === "number" ? startTime : startTime());
23603
+ waitForSeekable();
23604
+ }
23605
+ }, {
23606
+ includeLastObservation: true,
23607
+ clearSignal: cancelSignal
23608
+ });
23369
23609
  }
23370
- playbackObserver.listen(function (observation, stopListening) {
23371
- if (!observation.seeking && observation.rebuffering === null && observation.readyState >= 1) {
23372
- stopListening();
23373
- onPlayable();
23374
- }
23375
- }, {
23376
- includeLastObservation: true,
23377
- clearSignal: cancelSignal
23610
+ var deregisterCancellation = cancelSignal.register(function (err) {
23611
+ rejectAutoPlay(err);
23378
23612
  });
23379
- }
23380
- function onPlayable() {
23381
- var _a;
23382
- src_log.info("Init: Can begin to play content");
23383
- if (!mustAutoPlay) {
23384
- if (mediaElement.autoplay) {
23385
- src_log.warn("Init: autoplay is enabled on HTML media element. " + "Media will play as soon as possible.");
23386
- }
23387
- initialPlayPerformed.setValue(true);
23388
- initialPlayPerformed.finish();
23389
- deregisterCancellation();
23390
- return resolveAutoPlay({
23391
- type: "skipped"
23613
+ /**
23614
+ * Logic that should be run once the initial seek has been asked to the
23615
+ * PlaybackObserver.
23616
+ *
23617
+ * Actually wait until the seek has been performed, wait for the right moment
23618
+ * to perform autoplay, resolve the promise once everything has been done and
23619
+ * potentially send warning if a minor issue is detected.
23620
+ */
23621
+ function waitForSeekable() {
23622
+ playbackObserver.listen(function (obs, stopListening) {
23623
+ if (obs.seeking === 0 /* SeekingState.None */ || obs.readyState === 0) {
23624
+ return;
23625
+ }
23626
+ stopListening();
23627
+ if (shouldValidateMetadata() && mediaElement.duration === 0) {
23628
+ var error = new MediaError("MEDIA_ERR_NOT_LOADED_METADATA", "Cannot load automatically: your browser " + "falsely announced having loaded the content.");
23629
+ onWarning(error);
23630
+ }
23631
+ if (cancelSignal.isCancelled()) {
23632
+ return;
23633
+ }
23634
+ waitForPlayable();
23635
+ }, {
23636
+ includeLastObservation: true,
23637
+ clearSignal: cancelSignal
23392
23638
  });
23393
23639
  }
23394
- var playResult;
23395
- try {
23396
- playResult = (_a = mediaElement.play()) !== null && _a !== void 0 ? _a : Promise.resolve();
23397
- } catch (playError) {
23398
- deregisterCancellation();
23399
- return rejectAutoPlay(playError);
23640
+ /**
23641
+ * Logic that should be run once the initial seek has been properly performed.
23642
+ *
23643
+ * Wait for the media being playable before performing the autoplay operation
23644
+ * if asked. Potentially send warning if a minor issue has been detected while
23645
+ * doing so.
23646
+ */
23647
+ function waitForPlayable() {
23648
+ playbackObserver.listen(function (observation, stopListening) {
23649
+ if (observation.seeking === 0 /* SeekingState.None */ && observation.rebuffering === null && observation.readyState >= 1) {
23650
+ stopListening();
23651
+ onPlayable();
23652
+ }
23653
+ }, {
23654
+ includeLastObservation: true,
23655
+ clearSignal: cancelSignal
23656
+ });
23400
23657
  }
23401
- playResult.then(function () {
23402
- if (cancelSignal.isCancelled()) {
23403
- return;
23658
+ /**
23659
+ * Callback called once the content is considered "playable".
23660
+ *
23661
+ * Perform the autoplay if needed, handling potential issues and resolve the
23662
+ * Promise when done.
23663
+ * Might also send warnings if minor issues arise.
23664
+ */
23665
+ function onPlayable() {
23666
+ var _a;
23667
+ src_log.info("Init: Can begin to play content");
23668
+ if (!mustAutoPlay) {
23669
+ if (mediaElement.autoplay) {
23670
+ src_log.warn("Init: autoplay is enabled on HTML media element. " + "Media will play as soon as possible.");
23671
+ }
23672
+ initialPlayPerformed.setValue(true);
23673
+ initialPlayPerformed.finish();
23674
+ deregisterCancellation();
23675
+ return resolveAutoPlay({
23676
+ type: "skipped"
23677
+ });
23404
23678
  }
23405
- initialPlayPerformed.setValue(true);
23406
- initialPlayPerformed.finish();
23407
- deregisterCancellation();
23408
- return resolveAutoPlay({
23409
- type: "autoplay"
23410
- });
23411
- })["catch"](function (playError) {
23412
- deregisterCancellation();
23413
- if (cancelSignal.isCancelled()) {
23414
- return;
23679
+ var playResult;
23680
+ try {
23681
+ playResult = (_a = mediaElement.play()) !== null && _a !== void 0 ? _a : Promise.resolve();
23682
+ } catch (playError) {
23683
+ deregisterCancellation();
23684
+ return rejectAutoPlay(playError);
23415
23685
  }
23416
- if (playError instanceof Error && playError.name === "NotAllowedError") {
23417
- // auto-play was probably prevented.
23418
- src_log.warn("Init: Media element can't play." + " It may be due to browser auto-play policies.");
23419
- var error = new MediaError("MEDIA_ERR_BLOCKED_AUTOPLAY", "Cannot trigger auto-play automatically: " + "your browser does not allow it.");
23420
- onWarning(error);
23686
+ playResult.then(function () {
23421
23687
  if (cancelSignal.isCancelled()) {
23422
23688
  return;
23423
23689
  }
23690
+ initialPlayPerformed.setValue(true);
23691
+ initialPlayPerformed.finish();
23692
+ deregisterCancellation();
23424
23693
  return resolveAutoPlay({
23425
- type: "autoplay-blocked"
23694
+ type: "autoplay"
23426
23695
  });
23427
- } else {
23428
- rejectAutoPlay(playError);
23429
- }
23430
- });
23431
- }
23696
+ })["catch"](function (playError) {
23697
+ deregisterCancellation();
23698
+ if (cancelSignal.isCancelled()) {
23699
+ return;
23700
+ }
23701
+ if (playError instanceof Error && playError.name === "NotAllowedError") {
23702
+ // auto-play was probably prevented.
23703
+ src_log.warn("Init: Media element can't play." + " It may be due to browser auto-play policies.");
23704
+ var error = new MediaError("MEDIA_ERR_BLOCKED_AUTOPLAY", "Cannot trigger auto-play automatically: " + "your browser does not allow it.");
23705
+ onWarning(error);
23706
+ if (cancelSignal.isCancelled()) {
23707
+ return;
23708
+ }
23709
+ return resolveAutoPlay({
23710
+ type: "autoplay-blocked"
23711
+ });
23712
+ } else {
23713
+ rejectAutoPlay(playError);
23714
+ }
23715
+ });
23716
+ }
23717
+ });
23718
+ return {
23719
+ autoPlayResult: autoPlayResult,
23720
+ initialPlayPerformed: initialPlayPerformed
23721
+ };
23432
23722
  }
23433
23723
  ;// CONCATENATED MODULE: ./src/core/decrypt/types.ts
23434
23724
  /**
@@ -23910,36 +24200,6 @@ function getMaximumLiveSeekablePosition(contentLastPosition) {
23910
24200
  // authorize exceptionally going over it.
23911
24201
  return Math.max(Math.pow(2, 32), contentLastPosition + YEAR_IN_SECONDS);
23912
24202
  }
23913
- ;// CONCATENATED MODULE: ./src/compat/is_seeking_approximate.ts
23914
- /**
23915
- * Copyright 2015 CANAL+ Group
23916
- *
23917
- * Licensed under the Apache License, Version 2.0 (the "License");
23918
- * you may not use this file except in compliance with the License.
23919
- * You may obtain a copy of the License at
23920
- *
23921
- * http://www.apache.org/licenses/LICENSE-2.0
23922
- *
23923
- * Unless required by applicable law or agreed to in writing, software
23924
- * distributed under the License is distributed on an "AS IS" BASIS,
23925
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23926
- * See the License for the specific language governing permissions and
23927
- * limitations under the License.
23928
- */
23929
-
23930
- /**
23931
- * On some devices (right now only seen on Tizen), seeking through the
23932
- * `currentTime` property can lead to the browser re-seeking once the
23933
- * segments have been loaded to improve seeking performances (for
23934
- * example, by seeking right to an intra video frame).
23935
- *
23936
- * This can lead to conflicts with the RxPlayer code.
23937
- *
23938
- * This boolean is only `true` on the devices where this behavior has been
23939
- * observed.
23940
- */
23941
- var isSeekingApproximate = isTizen;
23942
- /* harmony default export */ var is_seeking_approximate = (isSeekingApproximate);
23943
24203
  ;// CONCATENATED MODULE: ./src/core/init/utils/rebuffering_controller.ts
23944
24204
 
23945
24205
  function rebuffering_controller_createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = rebuffering_controller_unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -23967,7 +24227,6 @@ function rebuffering_controller_arrayLikeToArray(arr, len) { if (len == null ||
23967
24227
 
23968
24228
 
23969
24229
 
23970
-
23971
24230
  /**
23972
24231
  * Work-around rounding errors with floating points by setting an acceptable,
23973
24232
  * very short, deviation when checking equalities.
@@ -24008,38 +24267,12 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24008
24267
  return;
24009
24268
  }
24010
24269
  this._isStarted = true;
24011
- /**
24012
- * On some devices (right now only seen on Tizen), seeking through the
24013
- * `currentTime` property can lead to the browser re-seeking once the
24014
- * segments have been loaded to improve seeking performances (for
24015
- * example, by seeking right to an intra video frame).
24016
- * In that case, we risk being in a conflict with that behavior: if for
24017
- * example we encounter a small discontinuity at the position the browser
24018
- * seeks to, we will seek over it, the browser would seek back and so on.
24019
- *
24020
- * This variable allows to store the last known position we were seeking to
24021
- * so we can detect when the browser seeked back (to avoid performing another
24022
- * seek after that). When browsers seek back to a position behind a
24023
- * discontinuity, they are usually able to skip them without our help.
24024
- */
24025
- var lastSeekingPosition;
24026
- /**
24027
- * In some conditions (see `lastSeekingPosition`), we might want to not
24028
- * automatically seek over discontinuities because the browser might do it
24029
- * itself instead.
24030
- * In that case, we still want to perform the seek ourselves if the browser
24031
- * doesn't do it after sufficient time.
24032
- * This variable allows to store the timestamp at which a discontinuity began
24033
- * to be ignored.
24034
- */
24035
- var ignoredStallTimeStamp = null;
24036
24270
  var playbackRateUpdater = new PlaybackRateUpdater(this._playbackObserver, this._speed);
24037
24271
  this._canceller.signal.register(function () {
24038
24272
  playbackRateUpdater.dispose();
24039
24273
  });
24040
24274
  var prevFreezingState = null;
24041
24275
  this._playbackObserver.listen(function (observation) {
24042
- var _a;
24043
24276
  var discontinuitiesStore = _this2._discontinuitiesStore;
24044
24277
  var buffered = observation.buffered,
24045
24278
  position = observation.position,
@@ -24048,31 +24281,24 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24048
24281
  freezing = observation.freezing;
24049
24282
  var _config$getCurrent = config.getCurrent(),
24050
24283
  BUFFER_DISCONTINUITY_THRESHOLD = _config$getCurrent.BUFFER_DISCONTINUITY_THRESHOLD,
24051
- FORCE_DISCONTINUITY_SEEK_DELAY = _config$getCurrent.FORCE_DISCONTINUITY_SEEK_DELAY,
24052
24284
  FREEZING_STALLED_DELAY = _config$getCurrent.FREEZING_STALLED_DELAY,
24053
24285
  UNFREEZING_SEEK_DELAY = _config$getCurrent.UNFREEZING_SEEK_DELAY,
24054
24286
  UNFREEZING_DELTA_POSITION = _config$getCurrent.UNFREEZING_DELTA_POSITION;
24055
- if (!observation.seeking && is_seeking_approximate && ignoredStallTimeStamp === null && lastSeekingPosition !== null && observation.position < lastSeekingPosition) {
24056
- src_log.debug("Init: the device appeared to have seeked back by itself.");
24057
- var now = getMonotonicTimeStamp();
24058
- ignoredStallTimeStamp = now;
24059
- }
24060
- lastSeekingPosition = observation.seeking ? Math.max((_a = observation.pendingInternalSeek) !== null && _a !== void 0 ? _a : 0, observation.position) : null;
24061
24287
  if (_this2._checkDecipherabilityFreeze(observation)) {
24062
24288
  return;
24063
24289
  }
24064
24290
  if (freezing !== null) {
24065
- var _now = getMonotonicTimeStamp();
24291
+ var now = getMonotonicTimeStamp();
24066
24292
  var referenceTimestamp = prevFreezingState === null ? freezing.timestamp : prevFreezingState.attemptTimestamp;
24067
- if (_now - referenceTimestamp > UNFREEZING_SEEK_DELAY) {
24293
+ if (!position.isAwaitingFuturePosition() && now - referenceTimestamp > UNFREEZING_SEEK_DELAY) {
24068
24294
  src_log.warn("Init: trying to seek to un-freeze player");
24069
24295
  _this2._playbackObserver.setCurrentTime(_this2._playbackObserver.getCurrentTime() + UNFREEZING_DELTA_POSITION);
24070
24296
  prevFreezingState = {
24071
- attemptTimestamp: _now
24297
+ attemptTimestamp: now
24072
24298
  };
24073
24299
  }
24074
- if (_now - freezing.timestamp > FREEZING_STALLED_DELAY) {
24075
- if (rebuffering === null || ignoredStallTimeStamp !== null) {
24300
+ if (now - freezing.timestamp > FREEZING_STALLED_DELAY) {
24301
+ if (rebuffering === null) {
24076
24302
  playbackRateUpdater.stopRebuffering();
24077
24303
  } else {
24078
24304
  playbackRateUpdater.startRebuffering();
@@ -24089,8 +24315,8 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24089
24315
  // With a readyState set to 1, we should still not be able to play:
24090
24316
  // Return that we're stalled
24091
24317
  var reason;
24092
- if (observation.seeking) {
24093
- reason = observation.pendingInternalSeek !== null ? "internal-seek" : "seeking";
24318
+ if (observation.seeking !== 0 /* SeekingState.None */) {
24319
+ reason = observation.seeking === 1 /* SeekingState.Internal */ ? "internal-seek" : "seeking";
24094
24320
  } else {
24095
24321
  reason = "not-ready";
24096
24322
  }
@@ -24102,19 +24328,13 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24102
24328
  }
24103
24329
  // We want to separate a stall situation when a seek is due to a seek done
24104
24330
  // internally by the player to when its due to a regular user seek.
24105
- var stalledReason = rebuffering.reason === "seeking" && observation.pendingInternalSeek !== null ? "internal-seek" : rebuffering.reason;
24106
- if (ignoredStallTimeStamp !== null) {
24107
- var _now2 = getMonotonicTimeStamp();
24108
- if (_now2 - ignoredStallTimeStamp < FORCE_DISCONTINUITY_SEEK_DELAY) {
24109
- playbackRateUpdater.stopRebuffering();
24110
- src_log.debug("Init: letting the device get out of a stall by itself");
24111
- _this2.trigger("stalled", stalledReason);
24112
- return;
24113
- } else {
24114
- src_log.warn("Init: ignored stall for too long, considering it", _now2 - ignoredStallTimeStamp);
24115
- }
24331
+ var stalledReason = rebuffering.reason === "seeking" && observation.seeking === 1 /* SeekingState.Internal */ ? "internal-seek" : rebuffering.reason;
24332
+ if (position.isAwaitingFuturePosition()) {
24333
+ playbackRateUpdater.stopRebuffering();
24334
+ src_log.debug("Init: let rebuffering happen as we're awaiting a future position");
24335
+ _this2.trigger("stalled", stalledReason);
24336
+ return;
24116
24337
  }
24117
- ignoredStallTimeStamp = null;
24118
24338
  playbackRateUpdater.startRebuffering();
24119
24339
  if (_this2._manifest === null) {
24120
24340
  _this2.trigger("stalled", stalledReason);
@@ -24129,14 +24349,14 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24129
24349
  if (realSeekTime <= _this2._playbackObserver.getCurrentTime()) {
24130
24350
  src_log.info("Init: position to seek already reached, no seeking", _this2._playbackObserver.getCurrentTime(), realSeekTime);
24131
24351
  } else {
24132
- src_log.warn("SA: skippable discontinuity found in the stream", position, realSeekTime);
24352
+ src_log.warn("SA: skippable discontinuity found in the stream", position.getPolled(), realSeekTime);
24133
24353
  _this2._playbackObserver.setCurrentTime(realSeekTime);
24134
24354
  _this2.trigger("warning", generateDiscontinuityError(stalledPosition, realSeekTime));
24135
24355
  return;
24136
24356
  }
24137
24357
  }
24138
24358
  }
24139
- var freezePosition = stalledPosition !== null && stalledPosition !== void 0 ? stalledPosition : position;
24359
+ var positionBlockedAt = stalledPosition !== null && stalledPosition !== void 0 ? stalledPosition : position.getPolled();
24140
24360
  // Is it a very short discontinuity in buffer ? -> Seek at the beginning of the
24141
24361
  // next range
24142
24362
  //
@@ -24144,13 +24364,13 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24144
24364
  // calculate a stalled state. This is useful for some
24145
24365
  // implementation that might drop an injected segment, or in
24146
24366
  // case of small discontinuity in the content.
24147
- var nextBufferRangeGap = getNextBufferedTimeRangeGap(buffered, freezePosition);
24367
+ var nextBufferRangeGap = getNextBufferedTimeRangeGap(buffered, positionBlockedAt);
24148
24368
  if (_this2._speed.getValue() > 0 && nextBufferRangeGap < BUFFER_DISCONTINUITY_THRESHOLD) {
24149
- var seekTo = freezePosition + nextBufferRangeGap + rebuffering_controller_EPSILON;
24369
+ var seekTo = positionBlockedAt + nextBufferRangeGap + rebuffering_controller_EPSILON;
24150
24370
  if (_this2._playbackObserver.getCurrentTime() < seekTo) {
24151
- src_log.warn("Init: discontinuity encountered inferior to the threshold", freezePosition, seekTo, BUFFER_DISCONTINUITY_THRESHOLD);
24371
+ src_log.warn("Init: discontinuity encountered inferior to the threshold", positionBlockedAt, seekTo, BUFFER_DISCONTINUITY_THRESHOLD);
24152
24372
  _this2._playbackObserver.setCurrentTime(seekTo);
24153
- _this2.trigger("warning", generateDiscontinuityError(freezePosition, seekTo));
24373
+ _this2.trigger("warning", generateDiscontinuityError(positionBlockedAt, seekTo));
24154
24374
  return;
24155
24375
  }
24156
24376
  }
@@ -24158,11 +24378,11 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24158
24378
  // next period
24159
24379
  for (var i = _this2._manifest.periods.length - 2; i >= 0; i--) {
24160
24380
  var period = _this2._manifest.periods[i];
24161
- if (period.end !== undefined && period.end <= freezePosition) {
24162
- if (_this2._manifest.periods[i + 1].start > freezePosition && _this2._manifest.periods[i + 1].start > _this2._playbackObserver.getCurrentTime()) {
24381
+ if (period.end !== undefined && period.end <= positionBlockedAt) {
24382
+ if (_this2._manifest.periods[i + 1].start > positionBlockedAt && _this2._manifest.periods[i + 1].start > _this2._playbackObserver.getCurrentTime()) {
24163
24383
  var nextPeriod = _this2._manifest.periods[i + 1];
24164
24384
  _this2._playbackObserver.setCurrentTime(nextPeriod.start);
24165
- _this2.trigger("warning", generateDiscontinuityError(freezePosition, nextPeriod.start));
24385
+ _this2.trigger("warning", generateDiscontinuityError(positionBlockedAt, nextPeriod.start));
24166
24386
  return;
24167
24387
  }
24168
24388
  break;
@@ -24204,10 +24424,10 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24204
24424
  if (!observation.rebuffering || observation.paused || this._speed.getValue() <= 0 || bufferType !== "audio" && bufferType !== "video") {
24205
24425
  return;
24206
24426
  }
24207
- var currPos = observation.position;
24208
- var rebufferingPos = (_a = observation.rebuffering.position) !== null && _a !== void 0 ? _a : currPos;
24427
+ var loadedPos = observation.position.getWanted();
24428
+ var rebufferingPos = (_a = observation.rebuffering.position) !== null && _a !== void 0 ? _a : loadedPos;
24209
24429
  var lockedPeriodStart = period.start;
24210
- if (currPos < lockedPeriodStart && Math.abs(rebufferingPos - lockedPeriodStart) < 1) {
24430
+ if (loadedPos < lockedPeriodStart && Math.abs(rebufferingPos - lockedPeriodStart) < 1) {
24211
24431
  src_log.warn("Init: rebuffering because of a future locked stream.\n" + "Trying to unlock by seeking to the next Period");
24212
24432
  this._playbackObserver.setCurrentTime(lockedPeriodStart + 0.001);
24213
24433
  }
@@ -24240,7 +24460,6 @@ var RebufferingController = /*#__PURE__*/function (_EventEmitter) {
24240
24460
  * right handling steps.
24241
24461
  */;
24242
24462
  _proto._checkDecipherabilityFreeze = function _checkDecipherabilityFreeze(observation) {
24243
- // XXX TODO allow this in in-worker configuration
24244
24463
  var readyState = observation.readyState,
24245
24464
  rebuffering = observation.rebuffering,
24246
24465
  freezing = observation.freezing;
@@ -24360,8 +24579,9 @@ function eventContainsDiscontinuity(evt) {
24360
24579
  * @returns {Array.<Object>}
24361
24580
  */
24362
24581
  function updateDiscontinuitiesStore(discontinuitiesStore, evt, observation) {
24582
+ var gcTime = Math.min(observation.position.getPolled(), observation.position.getWanted());
24363
24583
  // First, perform clean-up of old discontinuities
24364
- while (discontinuitiesStore.length > 0 && discontinuitiesStore[0].period.end !== undefined && discontinuitiesStore[0].period.end + 10 < observation.position) {
24584
+ while (discontinuitiesStore.length > 0 && discontinuitiesStore[0].period.end !== undefined && discontinuitiesStore[0].period.end + 10 < gcTime) {
24365
24585
  discontinuitiesStore.shift();
24366
24586
  }
24367
24587
  var period = evt.period,
@@ -24687,9 +24907,11 @@ var StreamEventsEmitter = /*#__PURE__*/function (_EventEmitter) {
24687
24907
  clearInterval(intervalId);
24688
24908
  });
24689
24909
  function constructObservation() {
24690
- var isSeeking = playbackObserver.getReference().getValue().seeking;
24910
+ var lastObservation = playbackObserver.getReference().getValue();
24911
+ var currentTime = mediaElement.currentTime;
24912
+ var isSeeking = lastObservation.seeking !== 0 /* SeekingState.None */;
24691
24913
  return {
24692
- currentTime: mediaElement.currentTime,
24914
+ currentTime: currentTime,
24693
24915
  isSeeking: isSeeking
24694
24916
  };
24695
24917
  }
@@ -25202,12 +25424,18 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25202
25424
  cancelSignal.register(function () {
25203
25425
  segmentBuffersStore.disposeAll();
25204
25426
  });
25205
- var _performInitialSeekAn = performInitialSeekAndPlay(mediaElement, playbackObserver, initialTime, autoPlay, function (err) {
25206
- return _this6.trigger("warning", err);
25427
+ var _performInitialSeekAn = performInitialSeekAndPlay({
25428
+ mediaElement: mediaElement,
25429
+ playbackObserver: playbackObserver,
25430
+ startTime: initialTime,
25431
+ mustAutoPlay: autoPlay,
25432
+ onWarning: function onWarning(err) {
25433
+ _this6.trigger("warning", err);
25434
+ },
25435
+ isDirectfile: false
25207
25436
  }, cancelSignal),
25208
25437
  autoPlayResult = _performInitialSeekAn.autoPlayResult,
25209
- initialPlayPerformed = _performInitialSeekAn.initialPlayPerformed,
25210
- initialSeekPerformed = _performInitialSeekAn.initialSeekPerformed;
25438
+ initialPlayPerformed = _performInitialSeekAn.initialPlayPerformed;
25211
25439
  if (cancelSignal.isCancelled()) {
25212
25440
  return;
25213
25441
  }
@@ -25234,15 +25462,19 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25234
25462
  autoPlay: autoPlay,
25235
25463
  manifest: manifest,
25236
25464
  initialPlayPerformed: initialPlayPerformed,
25237
- initialSeekPerformed: initialSeekPerformed,
25238
- speed: speed,
25239
- startTime: initialTime
25465
+ speed: speed
25240
25466
  }, cancelSignal);
25241
25467
  var rebufferingController = this._createRebufferingController(playbackObserver, manifest, segmentBuffersStore, speed, cancelSignal);
25242
25468
  rebufferingController.addEventListener("needsReload", function () {
25469
+ var position;
25470
+ var lastObservation = playbackObserver.getReference().getValue();
25471
+ if (lastObservation.position.isAwaitingFuturePosition()) {
25472
+ position = lastObservation.position.getWanted();
25473
+ } else {
25474
+ position = playbackObserver.getCurrentTime();
25475
+ }
25243
25476
  // NOTE couldn't both be always calculated at event destination?
25244
25477
  // Maybe there are exceptions?
25245
- var position = initialSeekPerformed.getValue() ? playbackObserver.getCurrentTime() : initialTime;
25246
25478
  var autoplay = initialPlayPerformed.getValue() ? !playbackObserver.getIsPaused() : autoPlay;
25247
25479
  onReloadOrder({
25248
25480
  position: position,
@@ -25308,10 +25540,10 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25308
25540
  if (
25309
25541
  // Data is buffered around the current position
25310
25542
  obs.currentRange !== null ||
25311
- // Or, for whatever reason, playback is already advancing
25312
- obs.position > seekedTime + 0.1) {
25543
+ // Or, for whatever reason, we have no buffer but we're already advancing
25544
+ obs.position.getPolled() > seekedTime + 0.1) {
25313
25545
  stopListening();
25314
- playbackObserver.setCurrentTime(obs.position + 0.001);
25546
+ playbackObserver.setCurrentTime(obs.position.getWanted() + 0.001);
25315
25547
  }
25316
25548
  }, {
25317
25549
  includeLastObservation: false,
@@ -25400,10 +25632,10 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25400
25632
  return self.trigger("bitrateEstimateChange", value);
25401
25633
  },
25402
25634
  needsMediaSourceReload: function needsMediaSourceReload(payload) {
25403
- var _a, _b;
25635
+ var _a;
25404
25636
  var lastObservation = streamObserver.getReference().getValue();
25405
- var currentPosition = (_a = lastObservation.position.pending) !== null && _a !== void 0 ? _a : streamObserver.getCurrentTime();
25406
- var isPaused = (_b = lastObservation.paused.pending) !== null && _b !== void 0 ? _b : streamObserver.getIsPaused();
25637
+ var currentPosition = lastObservation.position.isAwaitingFuturePosition() ? lastObservation.position.getWanted() : streamObserver.getCurrentTime();
25638
+ var isPaused = (_a = lastObservation.paused.pending) !== null && _a !== void 0 ? _a : streamObserver.getIsPaused();
25407
25639
  var position = currentPosition + payload.timeOffset;
25408
25640
  if (payload.minimumPosition !== undefined) {
25409
25641
  position = Math.max(payload.minimumPosition, position);
@@ -25417,19 +25649,19 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25417
25649
  });
25418
25650
  },
25419
25651
  needsDecipherabilityFlush: function needsDecipherabilityFlush() {
25420
- var _a, _b, _c;
25652
+ var _a;
25421
25653
  var keySystem = get_key_system_configuration_getKeySystemConfiguration(mediaElement);
25422
25654
  if (shouldReloadMediaSourceOnDecipherabilityUpdate(keySystem === null || keySystem === void 0 ? void 0 : keySystem[0])) {
25423
25655
  var lastObservation = streamObserver.getReference().getValue();
25424
- var position = (_a = lastObservation.position.pending) !== null && _a !== void 0 ? _a : streamObserver.getCurrentTime();
25425
- var isPaused = (_b = lastObservation.paused.pending) !== null && _b !== void 0 ? _b : streamObserver.getIsPaused();
25656
+ var position = lastObservation.position.isAwaitingFuturePosition() ? lastObservation.position.getWanted() : streamObserver.getCurrentTime();
25657
+ var isPaused = (_a = lastObservation.paused.pending) !== null && _a !== void 0 ? _a : streamObserver.getIsPaused();
25426
25658
  onReloadOrder({
25427
25659
  position: position,
25428
25660
  autoPlay: !isPaused
25429
25661
  });
25430
25662
  } else {
25431
25663
  var _lastObservation = streamObserver.getReference().getValue();
25432
- var _position = (_c = _lastObservation.position.pending) !== null && _c !== void 0 ? _c : streamObserver.getCurrentTime();
25664
+ var _position = _lastObservation.position.isAwaitingFuturePosition() ? _lastObservation.position.getWanted() : streamObserver.getCurrentTime();
25433
25665
  // simple seek close to the current position
25434
25666
  // to flush the buffers
25435
25667
  if (_position + 0.001 < _lastObservation.duration) {
@@ -25491,8 +25723,8 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25491
25723
  period: period
25492
25724
  });
25493
25725
  });
25494
- contentTimeBoundariesObserver.addEventListener("durationUpdate", function (newDuration) {
25495
- mediaSourceDurationUpdater.updateDuration(newDuration.duration, newDuration.isEnd);
25726
+ contentTimeBoundariesObserver.addEventListener("endingPositionChange", function (x) {
25727
+ return mediaSourceDurationUpdater.updateDuration(x.endingPosition, x.isEnd);
25496
25728
  });
25497
25729
  contentTimeBoundariesObserver.addEventListener("endOfStream", function () {
25498
25730
  if (endOfStreamCanceller === null) {
@@ -25509,8 +25741,8 @@ var MediaSourceContentInitializer = /*#__PURE__*/function (_ContentInitializer)
25509
25741
  endOfStreamCanceller = null;
25510
25742
  }
25511
25743
  });
25512
- var currentDuration = contentTimeBoundariesObserver.getCurrentDuration();
25513
- mediaSourceDurationUpdater.updateDuration(currentDuration.duration, currentDuration.isEnd);
25744
+ var endInfo = contentTimeBoundariesObserver.getCurrentEndingTime();
25745
+ mediaSourceDurationUpdater.updateDuration(endInfo.endingPosition, endInfo.isEnd);
25514
25746
  return contentTimeBoundariesObserver;
25515
25747
  }
25516
25748
  /**
@@ -27117,7 +27349,7 @@ function getTimescaledRange(start, duration, timescale) {
27117
27349
  * timescaled time.
27118
27350
  * Returns -1 if the given time is lower than the start of the first available
27119
27351
  * segment.
27120
- * @param {Object} index
27352
+ * @param {Object} timeline
27121
27353
  * @param {Number} timeTScaled
27122
27354
  * @returns {Number}
27123
27355
  */
@@ -27162,55 +27394,6 @@ function index_helpers_checkDiscontinuity(index, timeSec, maxPosition) {
27162
27394
  var segmentEnd = getIndexSegmentEnd(timelineItem, nextTimelineItem, maxPosition);
27163
27395
  return scaledTime >= segmentEnd && scaledTime < nextStart ? fromIndexTime(nextStart, index) : null;
27164
27396
  }
27165
- ;// CONCATENATED MODULE: ./src/parsers/manifest/utils/is_segment_still_available.ts
27166
- /**
27167
- * Copyright 2015 CANAL+ Group
27168
- *
27169
- * Licensed under the Apache License, Version 2.0 (the "License");
27170
- * you may not use this file except in compliance with the License.
27171
- * You may obtain a copy of the License at
27172
- *
27173
- * http://www.apache.org/licenses/LICENSE-2.0
27174
- *
27175
- * Unless required by applicable law or agreed to in writing, software
27176
- * distributed under the License is distributed on an "AS IS" BASIS,
27177
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27178
- * See the License for the specific language governing permissions and
27179
- * limitations under the License.
27180
- */
27181
- /**
27182
- * Returns true if a Segment returned by the corresponding index is still
27183
- * considered available.
27184
- * Returns false if it is not available anymore.
27185
- * Returns undefined if we cannot know whether it is still available or not.
27186
- * /!\ We do not check the mediaURLs of the segment.
27187
- * @param {Object} segment
27188
- * @param {Array.<Object>} timescale
27189
- * @param {number} timeline
27190
- * @returns {Boolean|undefined}
27191
- */
27192
- function is_segment_still_available_isSegmentStillAvailable(segment, timeline, timescale, indexTimeOffset) {
27193
- for (var i = 0; i < timeline.length; i++) {
27194
- var tSegment = timeline[i];
27195
- var tSegmentTime = (tSegment.start - indexTimeOffset) / timescale;
27196
- if (tSegmentTime > segment.time) {
27197
- return false;
27198
- } else if (tSegmentTime === segment.time) {
27199
- if (tSegment.range === undefined) {
27200
- return segment.range === undefined;
27201
- }
27202
- return segment.range != null && tSegment.range[0] === segment.range[0] && tSegment.range[1] === segment.range[1];
27203
- } else {
27204
- // tSegment.start < segment.time
27205
- if (tSegment.repeatCount >= 0 && tSegment.duration !== undefined) {
27206
- var timeDiff = tSegmentTime - tSegment.start;
27207
- var repeat = timeDiff / tSegment.duration - 1;
27208
- return repeat % 1 === 0 && repeat <= tSegment.repeatCount;
27209
- }
27210
- }
27211
- }
27212
- return false;
27213
- }
27214
27397
  ;// CONCATENATED MODULE: ./src/parsers/manifest/smooth/utils/tokens.ts
27215
27398
  /**
27216
27399
  * Copyright 2015 CANAL+ Group
@@ -27266,7 +27449,6 @@ function replaceSegmentSmoothTokens(url, time) {
27266
27449
 
27267
27450
 
27268
27451
 
27269
-
27270
27452
  /**
27271
27453
  * @param {Number} start
27272
27454
  * @param {Number} up
@@ -27536,7 +27718,7 @@ var SmoothRepresentationIndex = /*#__PURE__*/function () {
27536
27718
  _proto.awaitSegmentBetween = function awaitSegmentBetween(start, end) {
27537
27719
  var _a;
27538
27720
  assert_assert(start <= end);
27539
- if (this.isFinished()) {
27721
+ if (this.isStillAwaitingFutureSegments()) {
27540
27722
  return false;
27541
27723
  }
27542
27724
  var lastAvailablePosition = this.getLastAvailablePosition();
@@ -27574,7 +27756,23 @@ var SmoothRepresentationIndex = /*#__PURE__*/function () {
27574
27756
  var _this$_sharedSmoothTi5 = this._sharedSmoothTimeline,
27575
27757
  timeline = _this$_sharedSmoothTi5.timeline,
27576
27758
  timescale = _this$_sharedSmoothTi5.timescale;
27577
- return is_segment_still_available_isSegmentStillAvailable(segment, timeline, timescale, 0);
27759
+ for (var i = 0; i < timeline.length; i++) {
27760
+ var tSegment = timeline[i];
27761
+ var tSegmentTime = tSegment.start / timescale;
27762
+ if (tSegmentTime > segment.time) {
27763
+ return false; // We went over it without finding it
27764
+ } else if (tSegmentTime === segment.time) {
27765
+ return true;
27766
+ } else {
27767
+ // tSegment.start < segment.time
27768
+ if (tSegment.repeatCount >= 0 && tSegment.duration !== undefined) {
27769
+ var timeDiff = tSegmentTime - tSegment.start;
27770
+ var repeat = timeDiff / tSegment.duration - 1;
27771
+ return repeat % 1 === 0 && repeat <= tSegment.repeatCount;
27772
+ }
27773
+ }
27774
+ }
27775
+ return false;
27578
27776
  }
27579
27777
  /**
27580
27778
  * @param {Error} error
@@ -27607,9 +27805,9 @@ var SmoothRepresentationIndex = /*#__PURE__*/function () {
27607
27805
  this._sharedSmoothTimeline.update(newIndex._sharedSmoothTimeline);
27608
27806
  }
27609
27807
  /**
27610
- * Returns `true` if the last segments in this index have already been
27808
+ * Returns `false` if the last segments in this index have already been
27611
27809
  * generated.
27612
- * Returns `false` if the index is still waiting on future segments to be
27810
+ * Returns `true` if the index is still waiting on future segments to be
27613
27811
  * generated.
27614
27812
  *
27615
27813
  * For Smooth, it should only depend on whether the content is a live content
@@ -27617,8 +27815,8 @@ var SmoothRepresentationIndex = /*#__PURE__*/function () {
27617
27815
  * TODO What about Smooth live content that finishes at some point?
27618
27816
  * @returns {boolean}
27619
27817
  */;
27620
- _proto.isFinished = function isFinished() {
27621
- return !this._isLive;
27818
+ _proto.isStillAwaitingFutureSegments = function isStillAwaitingFutureSegments() {
27819
+ return this._isLive;
27622
27820
  }
27623
27821
  /**
27624
27822
  * @returns {Boolean}
@@ -27633,8 +27831,8 @@ var SmoothRepresentationIndex = /*#__PURE__*/function () {
27633
27831
  * Add segments to a `SharedSmoothSegmentTimeline` that were predicted to come
27634
27832
  * after `currentSegment`.
27635
27833
  * @param {Array.<Object>} nextSegments - The segment information parsed.
27636
- * @param {Object} segment - Information on the segment which contained that
27637
- * new segment information.
27834
+ * @param {Object} currentSegment - Information on the segment which contained
27835
+ * that new segment information.
27638
27836
  */;
27639
27837
  _proto.addPredictedSegments = function addPredictedSegments(nextSegments, currentSegment) {
27640
27838
  this._sharedSmoothTimeline.addPredictedSegments(nextSegments, currentSegment);
@@ -28684,7 +28882,8 @@ function request(options) {
28684
28882
  url: options.url,
28685
28883
  headers: options.headers,
28686
28884
  responseType: is_null_or_undefined_isNullOrUndefined(options.responseType) ? DEFAULT_RESPONSE_TYPE : options.responseType,
28687
- timeout: options.timeout
28885
+ timeout: options.timeout,
28886
+ connectionTimeout: options.connectionTimeout
28688
28887
  };
28689
28888
  return new Promise(function (resolve, reject) {
28690
28889
  var onProgress = options.onProgress,
@@ -28692,7 +28891,8 @@ function request(options) {
28692
28891
  var url = requestOptions.url,
28693
28892
  headers = requestOptions.headers,
28694
28893
  responseType = requestOptions.responseType,
28695
- timeout = requestOptions.timeout;
28894
+ timeout = requestOptions.timeout,
28895
+ connectionTimeout = requestOptions.connectionTimeout;
28696
28896
  var xhr = new XMLHttpRequest();
28697
28897
  xhr.open("GET", url, true);
28698
28898
  var timeoutId;
@@ -28706,9 +28906,19 @@ function request(options) {
28706
28906
  // is more precise, it might also be more efficient.
28707
28907
  timeoutId = setTimeout(function () {
28708
28908
  clearCancellingProcess();
28709
- reject(new RequestError(url, xhr.status, "TIMEOUT"));
28909
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.TIMEOUT));
28710
28910
  }, timeout + 3000);
28711
28911
  }
28912
+ var connectionTimeoutId;
28913
+ if (connectionTimeout !== undefined) {
28914
+ connectionTimeoutId = setTimeout(function () {
28915
+ clearCancellingProcess();
28916
+ if (xhr.readyState !== XMLHttpRequest.DONE) {
28917
+ xhr.abort();
28918
+ }
28919
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.TIMEOUT));
28920
+ }, connectionTimeout);
28921
+ }
28712
28922
  xhr.responseType = responseType;
28713
28923
  if (xhr.responseType === "document") {
28714
28924
  xhr.overrideMimeType("text/xml");
@@ -28727,7 +28937,7 @@ function request(options) {
28727
28937
  if (cancelSignal !== undefined) {
28728
28938
  deregisterCancellationListener = cancelSignal.register(function abortRequest(err) {
28729
28939
  clearCancellingProcess();
28730
- if (!is_null_or_undefined_isNullOrUndefined(xhr) && xhr.readyState !== 4) {
28940
+ if (xhr.readyState !== XMLHttpRequest.DONE) {
28731
28941
  xhr.abort();
28732
28942
  }
28733
28943
  reject(err);
@@ -28738,12 +28948,19 @@ function request(options) {
28738
28948
  }
28739
28949
  xhr.onerror = function onXHRError() {
28740
28950
  clearCancellingProcess();
28741
- reject(new RequestError(url, xhr.status, "ERROR_EVENT"));
28951
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.ERROR_EVENT));
28742
28952
  };
28743
28953
  xhr.ontimeout = function onXHRTimeout() {
28744
28954
  clearCancellingProcess();
28745
- reject(new RequestError(url, xhr.status, "TIMEOUT"));
28955
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.TIMEOUT));
28746
28956
  };
28957
+ if (connectionTimeout !== undefined) {
28958
+ xhr.onreadystatechange = function clearConnectionTimeout() {
28959
+ if (xhr.readyState >= XMLHttpRequest.HEADERS_RECEIVED) {
28960
+ clearTimeout(connectionTimeoutId);
28961
+ }
28962
+ };
28963
+ }
28747
28964
  if (onProgress !== undefined) {
28748
28965
  xhr.onprogress = function onXHRProgress(event) {
28749
28966
  var currentTime = getMonotonicTimeStamp();
@@ -28758,7 +28975,7 @@ function request(options) {
28758
28975
  };
28759
28976
  }
28760
28977
  xhr.onload = function onXHRLoad(event) {
28761
- if (xhr.readyState === 4) {
28978
+ if (xhr.readyState === XMLHttpRequest.DONE) {
28762
28979
  clearCancellingProcess();
28763
28980
  if (xhr.status >= 200 && xhr.status < 300) {
28764
28981
  var receivedTime = getMonotonicTimeStamp();
@@ -28776,7 +28993,7 @@ function request(options) {
28776
28993
  responseData = xhr.response;
28777
28994
  }
28778
28995
  if (is_null_or_undefined_isNullOrUndefined(responseData)) {
28779
- reject(new RequestError(url, xhr.status, "PARSE_ERROR"));
28996
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.PARSE_ERROR));
28780
28997
  return;
28781
28998
  }
28782
28999
  resolve({
@@ -28790,7 +29007,7 @@ function request(options) {
28790
29007
  responseData: responseData
28791
29008
  });
28792
29009
  } else {
28793
- reject(new RequestError(url, xhr.status, "ERROR_HTTP_CODE"));
29010
+ reject(new RequestError(url, xhr.status, NetworkErrorTypes.ERROR_HTTP_CODE));
28794
29011
  }
28795
29012
  }
28796
29013
  };
@@ -28802,6 +29019,9 @@ function request(options) {
28802
29019
  if (timeoutId !== undefined) {
28803
29020
  clearTimeout(timeoutId);
28804
29021
  }
29022
+ if (connectionTimeoutId !== undefined) {
29023
+ clearTimeout(connectionTimeoutId);
29024
+ }
28805
29025
  if (deregisterCancellationListener !== null) {
28806
29026
  deregisterCancellationListener();
28807
29027
  }
@@ -29078,6 +29298,7 @@ function generateRegularManifestLoader(preferredType) {
29078
29298
  url: url,
29079
29299
  responseType: "arraybuffer",
29080
29300
  timeout: loaderOptions.timeout,
29301
+ connectionTimeout: loaderOptions.connectionTimeout,
29081
29302
  cancelSignal: cancelSignal
29082
29303
  });
29083
29304
  case "text":
@@ -29085,6 +29306,7 @@ function generateRegularManifestLoader(preferredType) {
29085
29306
  url: url,
29086
29307
  responseType: "text",
29087
29308
  timeout: loaderOptions.timeout,
29309
+ connectionTimeout: loaderOptions.connectionTimeout,
29088
29310
  cancelSignal: cancelSignal
29089
29311
  });
29090
29312
  case "document":
@@ -29092,6 +29314,7 @@ function generateRegularManifestLoader(preferredType) {
29092
29314
  url: url,
29093
29315
  responseType: "document",
29094
29316
  timeout: loaderOptions.timeout,
29317
+ connectionTimeout: loaderOptions.connectionTimeout,
29095
29318
  cancelSignal: cancelSignal
29096
29319
  });
29097
29320
  default:
@@ -30567,6 +30790,7 @@ function regularSegmentLoader(url, context, callbacks, loaderOptions, cancelSign
30567
30790
  responseType: "arraybuffer",
30568
30791
  headers: headers,
30569
30792
  timeout: loaderOptions.timeout,
30793
+ connectionTimeout: loaderOptions.connectionTimeout,
30570
30794
  cancelSignal: cancelSignal,
30571
30795
  onProgress: callbacks.onProgress
30572
30796
  }).then(function (data) {
@@ -30942,6 +31166,7 @@ function constructSegmentUrl(wantedCdn, segment) {
30942
31166
  url: url,
30943
31167
  responseType: "text",
30944
31168
  timeout: loaderOptions.timeout,
31169
+ connectionTimeout: loaderOptions.connectionTimeout,
30945
31170
  cancelSignal: cancelSignal,
30946
31171
  onProgress: callbacks.onProgress
30947
31172
  }).then(function (data) {
@@ -30955,6 +31180,7 @@ function constructSegmentUrl(wantedCdn, segment) {
30955
31180
  url: url,
30956
31181
  responseType: "arraybuffer",
30957
31182
  timeout: loaderOptions.timeout,
31183
+ connectionTimeout: loaderOptions.connectionTimeout,
30958
31184
  cancelSignal: cancelSignal,
30959
31185
  onProgress: callbacks.onProgress
30960
31186
  }).then(function (data) {
@@ -31494,6 +31720,135 @@ function getMinimumAndMaximumPositions(periods) {
31494
31720
  maximumUnsafePosition: maxPositions.unsafe
31495
31721
  };
31496
31722
  }
31723
+ ;// CONCATENATED MODULE: ./src/parsers/manifest/dash/common/manifest_bounds_calculator.ts
31724
+ /**
31725
+ * Copyright 2015 CANAL+ Group
31726
+ *
31727
+ * Licensed under the Apache License, Version 2.0 (the "License");
31728
+ * you may not use this file except in compliance with the License.
31729
+ * You may obtain a copy of the License at
31730
+ *
31731
+ * http://www.apache.org/licenses/LICENSE-2.0
31732
+ *
31733
+ * Unless required by applicable law or agreed to in writing, software
31734
+ * distributed under the License is distributed on an "AS IS" BASIS,
31735
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31736
+ * See the License for the specific language governing permissions and
31737
+ * limitations under the License.
31738
+ */
31739
+
31740
+ /**
31741
+ * This class allows to easily calculate the first and last available positions
31742
+ * in a content at any time.
31743
+ *
31744
+ * By centralizing the manifest bounds calculation in this class and by giving
31745
+ * an instance of it to each parsed elements which might depend on it, we
31746
+ * ensure that we can provide it once it is known to every one of those
31747
+ * elements without needing to parse a second time the MPD.
31748
+ * @class ManifestBoundsCalculator
31749
+ */
31750
+ var ManifestBoundsCalculator = /*#__PURE__*/function () {
31751
+ /**
31752
+ * @param {Object} args
31753
+ */
31754
+ function ManifestBoundsCalculator(args) {
31755
+ this._isDynamic = args.isDynamic;
31756
+ this._timeShiftBufferDepth = !args.isDynamic || args.timeShiftBufferDepth === undefined ? null : args.timeShiftBufferDepth;
31757
+ this._serverTimestampOffset = args.serverTimestampOffset;
31758
+ this._availabilityStartTime = args.availabilityStartTime;
31759
+ }
31760
+ /**
31761
+ * Set the last position and the position time (the value of the RxPlayer's
31762
+ * monotonically-raising timestamp at the time that position was true
31763
+ * converted into seconds).
31764
+ *
31765
+ * @example
31766
+ * Example if you trust `Date.now()` to give you a reliable offset:
31767
+ * ```js
31768
+ * const lastPosition = Date.now();
31769
+ * const positionTime = getMonotonicTimeStamp() / 1000;
31770
+ * manifestBoundsCalculator.setLastPosition(lastPosition, positionTime);
31771
+ * ```
31772
+ *
31773
+ * @param {number} lastPosition
31774
+ * @param {number|undefined} positionTime
31775
+ */
31776
+ var _proto = ManifestBoundsCalculator.prototype;
31777
+ _proto.setLastPosition = function setLastPosition(lastPosition, positionTime) {
31778
+ this._lastPosition = lastPosition;
31779
+ this._positionTime = positionTime;
31780
+ }
31781
+ /**
31782
+ * Returns `true` if the last position and the position time
31783
+ * (for dynamic content only) have been comunicated.
31784
+ * `false` otherwise.
31785
+ * @returns {boolean}
31786
+ */;
31787
+ _proto.lastPositionIsKnown = function lastPositionIsKnown() {
31788
+ if (this._isDynamic) {
31789
+ return this._positionTime != null && this._lastPosition != null;
31790
+ }
31791
+ return this._lastPosition != null;
31792
+ }
31793
+ /**
31794
+ * Estimate a minimum bound for the content from the last set segment time
31795
+ * and buffer depth.
31796
+ * Consider that it is only an estimation, not the real value.
31797
+ * @return {number|undefined}
31798
+ */;
31799
+ _proto.getEstimatedMinimumSegmentTime = function getEstimatedMinimumSegmentTime() {
31800
+ var _a;
31801
+ if (!this._isDynamic || this._timeShiftBufferDepth === null) {
31802
+ return 0;
31803
+ }
31804
+ var maximumBound = (_a = this.getEstimatedLiveEdge()) !== null && _a !== void 0 ? _a : this.getEstimatedMaximumPosition(0);
31805
+ if (maximumBound === undefined) {
31806
+ return undefined;
31807
+ }
31808
+ var minimumBound = maximumBound - this._timeShiftBufferDepth;
31809
+ return minimumBound;
31810
+ }
31811
+ /**
31812
+ * Estimate the segment time in seconds that corresponds to what could be
31813
+ * considered the live edge (or `undefined` for non-live contents).
31814
+ *
31815
+ * Note that for some contents which just anounce segments in advance, this
31816
+ * value might be very different than the maximum position that is
31817
+ * requestable.
31818
+ * @return {number|undefined}
31819
+ */;
31820
+ _proto.getEstimatedLiveEdge = function getEstimatedLiveEdge() {
31821
+ if (!this._isDynamic || this._serverTimestampOffset === undefined) {
31822
+ return undefined;
31823
+ }
31824
+ return (getMonotonicTimeStamp() + this._serverTimestampOffset) / 1000 - this._availabilityStartTime;
31825
+ }
31826
+ /**
31827
+ * Produce a rough estimate of the ending time of the last requestable segment
31828
+ * in that content.
31829
+ *
31830
+ * This value is only an estimate and may be far from reality.
31831
+ *
31832
+ * The `availabilityTimeOffset` in argument is the corresponding
31833
+ * `availabilityTimeOffset` that applies to the current wanted segment, or `0`
31834
+ * if none exist. It will be applied on live content to deduce the maximum
31835
+ * segment time available.
31836
+ */;
31837
+ _proto.getEstimatedMaximumPosition = function getEstimatedMaximumPosition(availabilityTimeOffset) {
31838
+ if (!this._isDynamic) {
31839
+ return this._lastPosition;
31840
+ }
31841
+ var liveEdge = this.getEstimatedLiveEdge();
31842
+ if (liveEdge !== undefined && availabilityTimeOffset !== Infinity) {
31843
+ return liveEdge + availabilityTimeOffset;
31844
+ } else if (this._positionTime !== undefined && this._lastPosition !== undefined) {
31845
+ return Math.max(this._lastPosition - this._positionTime + getMonotonicTimeStamp() / 1000, 0);
31846
+ }
31847
+ return this._lastPosition;
31848
+ };
31849
+ return ManifestBoundsCalculator;
31850
+ }();
31851
+
31497
31852
  ;// CONCATENATED MODULE: ./src/parsers/manifest/dash/common/parse_availability_start_time.ts
31498
31853
  /**
31499
31854
  * Copyright 2015 CANAL+ Group
@@ -31700,115 +32055,6 @@ function getPeriodsTimeInformation(periodsIR, manifestInfos) {
31700
32055
  });
31701
32056
  return periodsTimeInformation;
31702
32057
  }
31703
- ;// CONCATENATED MODULE: ./src/parsers/manifest/dash/common/manifest_bounds_calculator.ts
31704
- /**
31705
- * Copyright 2015 CANAL+ Group
31706
- *
31707
- * Licensed under the Apache License, Version 2.0 (the "License");
31708
- * you may not use this file except in compliance with the License.
31709
- * You may obtain a copy of the License at
31710
- *
31711
- * http://www.apache.org/licenses/LICENSE-2.0
31712
- *
31713
- * Unless required by applicable law or agreed to in writing, software
31714
- * distributed under the License is distributed on an "AS IS" BASIS,
31715
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31716
- * See the License for the specific language governing permissions and
31717
- * limitations under the License.
31718
- */
31719
-
31720
- /**
31721
- * This class allows to easily calculate the first and last available positions
31722
- * in a content at any time.
31723
- *
31724
- * That task can be an hard for dynamic DASH contents: it depends on a
31725
- * `timeShiftBufferDepth` defined in the MPD and on the maximum possible
31726
- * position.
31727
- *
31728
- * The latter can come from either a clock synchronization mechanism or the
31729
- * indexing schemes (e.g. SegmentTemplate, SegmentTimeline etc.) of the last
31730
- * Periods.
31731
- * As such, it might only be known once a large chunk of the MPD has already
31732
- * been parsed.
31733
- *
31734
- * By centralizing the manifest bounds calculation in this class and by giving
31735
- * an instance of it to each parsed elements which might depend on it, we
31736
- * ensure that we can provide it once it is known to every one of those
31737
- * elements without needing to parse a second time the MPD.
31738
- * @class ManifestBoundsCalculator
31739
- */
31740
- var ManifestBoundsCalculator = /*#__PURE__*/function () {
31741
- /**
31742
- * @param {Object} args
31743
- */
31744
- function ManifestBoundsCalculator(args) {
31745
- this._isDynamic = args.isDynamic;
31746
- this._timeShiftBufferDepth = !args.isDynamic || args.timeShiftBufferDepth === undefined ? null : args.timeShiftBufferDepth;
31747
- }
31748
- /**
31749
- * Set the last position and the position time (the value of the RxPlayer's
31750
- * monotonically-raising timestamp at the time that position was true
31751
- * converted into seconds).
31752
- *
31753
- * @example
31754
- * Example if you trust `Date.now()` to give you a reliable offset:
31755
- * ```js
31756
- * const lastPosition = Date.now();
31757
- * const positionTime = getMonotonicTimeStamp() / 1000;
31758
- * manifestBoundsCalculator.setLastPosition(lastPosition, positionTime);
31759
- * ```
31760
- *
31761
- * @param {number} lastPosition
31762
- * @param {number|undefined} positionTime
31763
- */
31764
- var _proto = ManifestBoundsCalculator.prototype;
31765
- _proto.setLastPosition = function setLastPosition(lastPosition, positionTime) {
31766
- this._lastPosition = lastPosition;
31767
- this._positionTime = positionTime;
31768
- }
31769
- /**
31770
- * Returns `true` if the last position and the position time
31771
- * (for dynamic content only) have been comunicated.
31772
- * `false` otherwise.
31773
- * @returns {boolean}
31774
- */;
31775
- _proto.lastPositionIsKnown = function lastPositionIsKnown() {
31776
- if (this._isDynamic) {
31777
- return this._positionTime != null && this._lastPosition != null;
31778
- }
31779
- return this._lastPosition != null;
31780
- }
31781
- /**
31782
- * Estimate a minimum bound for the content from the last set segment time
31783
- * and buffer depth.
31784
- * Consider that it is only an estimation, not the real value.
31785
- * @return {number|undefined}
31786
- */;
31787
- _proto.estimateMinimumBound = function estimateMinimumBound() {
31788
- if (!this._isDynamic || this._timeShiftBufferDepth === null) {
31789
- return 0;
31790
- }
31791
- var maximumBound = this.estimateMaximumBound();
31792
- if (maximumBound === undefined) {
31793
- return undefined;
31794
- }
31795
- var minimumBound = maximumBound - this._timeShiftBufferDepth;
31796
- return minimumBound;
31797
- }
31798
- /**
31799
- * Estimate a maximum bound for the content from the last set segment time.
31800
- * Consider that it is only an estimation, not the real value.
31801
- * @return {number|undefined}
31802
- */;
31803
- _proto.estimateMaximumBound = function estimateMaximumBound() {
31804
- if (this._isDynamic && this._positionTime != null && this._lastPosition != null) {
31805
- return Math.max(this._lastPosition - this._positionTime + getMonotonicTimeStamp() / 1000, 0);
31806
- }
31807
- return this._lastPosition;
31808
- };
31809
- return ManifestBoundsCalculator;
31810
- }();
31811
-
31812
32058
  ;// CONCATENATED MODULE: ./src/parsers/manifest/dash/common/attach_trickmode_track.ts
31813
32059
  function attach_trickmode_track_createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = attach_trickmode_track_unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
31814
32060
  function attach_trickmode_track_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return attach_trickmode_track_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return attach_trickmode_track_arrayLikeToArray(o, minLen); }
@@ -32240,13 +32486,17 @@ function getWantedRepeatIndex(segmentStartTime, segmentDuration, wantedTime) {
32240
32486
  * @param {Object} index - index object, constructed by parsing the manifest.
32241
32487
  * @param {number} from - starting timestamp wanted, in seconds
32242
32488
  * @param {number} durationWanted - duration wanted, in seconds
32489
+ * @param {Object} manifestBoundsCalculator
32490
+ * @param {number|undefined} scaledPeriodEnd
32243
32491
  * @param {function} isEMSGWhitelisted
32244
- * @param {number|undefined} maximumTime
32245
32492
  * @returns {Array.<Object>}
32246
32493
  */
32247
- function getSegmentsFromTimeline(index, from, durationWanted, isEMSGWhitelisted, maximumTime) {
32494
+ function getSegmentsFromTimeline(index, from, durationWanted, manifestBoundsCalculator, scaledPeriodEnd, isEMSGWhitelisted) {
32495
+ var _a;
32496
+ var maximumTime = manifestBoundsCalculator.getEstimatedMaximumPosition((_a = index.availabilityTimeOffset) !== null && _a !== void 0 ? _a : 0);
32497
+ var wantedMaximum = Math.min(from + durationWanted, maximumTime !== null && maximumTime !== void 0 ? maximumTime : Infinity);
32248
32498
  var scaledUp = toIndexTime(from, index);
32249
- var scaledTo = toIndexTime(from + durationWanted, index);
32499
+ var scaledTo = toIndexTime(wantedMaximum, index);
32250
32500
  var timeline = index.timeline,
32251
32501
  timescale = index.timescale,
32252
32502
  segmentUrlTemplate = index.segmentUrlTemplate,
@@ -32260,7 +32510,13 @@ function getSegmentsFromTimeline(index, from, durationWanted, isEMSGWhitelisted,
32260
32510
  var duration = timelineItem.duration,
32261
32511
  start = timelineItem.start,
32262
32512
  range = timelineItem.range;
32263
- var repeat = calculateRepeat(timelineItem, timeline[i + 1], maximumTime);
32513
+ var maxRepeatTime = void 0;
32514
+ if (maximumTime === undefined) {
32515
+ maxRepeatTime = scaledPeriodEnd;
32516
+ } else {
32517
+ maxRepeatTime = Math.min(maximumTime * timescale, scaledPeriodEnd !== null && scaledPeriodEnd !== void 0 ? scaledPeriodEnd : Infinity);
32518
+ }
32519
+ var repeat = calculateRepeat(timelineItem, timeline[i + 1], maxRepeatTime);
32264
32520
  var complete = index.availabilityTimeComplete !== false || i !== timelineLength - 1 && repeat !== 0;
32265
32521
  var segmentNumberInCurrentRange = getWantedRepeatIndex(start, duration, scaledUp);
32266
32522
  var segmentTime = start + segmentNumberInCurrentRange * duration;
@@ -32393,6 +32649,7 @@ var BaseRepresentationIndex = /*#__PURE__*/function () {
32393
32649
  timeline: (_c = index.timeline) !== null && _c !== void 0 ? _c : [],
32394
32650
  timescale: timescale
32395
32651
  };
32652
+ this._manifestBoundsCalculator = context.manifestBoundsCalculator;
32396
32653
  this._scaledPeriodStart = toIndexTime(periodStart, this._index);
32397
32654
  this._scaledPeriodEnd = periodEnd == null ? undefined : toIndexTime(periodEnd, this._index);
32398
32655
  this._isInitialized = this._index.timeline.length > 0;
@@ -32421,7 +32678,7 @@ var BaseRepresentationIndex = /*#__PURE__*/function () {
32421
32678
  * @returns {Array.<Object>}
32422
32679
  */;
32423
32680
  _proto.getSegments = function getSegments(from, dur) {
32424
- return getSegmentsFromTimeline(this._index, from, dur, this._isEMSGWhitelisted, this._scaledPeriodEnd);
32681
+ return getSegmentsFromTimeline(this._index, from, dur, this._manifestBoundsCalculator, this._scaledPeriodEnd, this._isEMSGWhitelisted);
32425
32682
  }
32426
32683
  /**
32427
32684
  * Returns false as no Segment-Base based index should need to be refreshed.
@@ -32505,8 +32762,8 @@ var BaseRepresentationIndex = /*#__PURE__*/function () {
32505
32762
  * should become available in the future.
32506
32763
  * @returns {Boolean}
32507
32764
  */;
32508
- _proto.isFinished = function isFinished() {
32509
- return true;
32765
+ _proto.isStillAwaitingFutureSegments = function isStillAwaitingFutureSegments() {
32766
+ return false;
32510
32767
  }
32511
32768
  /**
32512
32769
  * No segment in a `BaseRepresentationIndex` are known initially.
@@ -32762,8 +33019,8 @@ var ListRepresentationIndex = /*#__PURE__*/function () {
32762
33019
  /**
32763
33020
  * @returns {Boolean}
32764
33021
  */;
32765
- _proto.isFinished = function isFinished() {
32766
- return true;
33022
+ _proto.isStillAwaitingFutureSegments = function isStillAwaitingFutureSegments() {
33023
+ return false;
32767
33024
  }
32768
33025
  /**
32769
33026
  * @returns {Boolean}
@@ -33209,9 +33466,13 @@ function constructTimelineFromPreviousTimeline(newElements, prevTimeline) {
33209
33466
 
33210
33467
 
33211
33468
 
33212
-
33213
33469
  // eslint-disable-next-line max-len
33214
33470
 
33471
+ /**
33472
+ * `IRepresentationIndex` implementation for a DASH `SegmentTimeline` segment
33473
+ * indexing scheme.
33474
+ * @class TimelineRepresentationIndex
33475
+ */
33215
33476
  var TimelineRepresentationIndex = /*#__PURE__*/function () {
33216
33477
  /**
33217
33478
  * @param {Object} index
@@ -33223,6 +33484,7 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33223
33484
  throw new Error("The given index is not compatible with a " + "TimelineRepresentationIndex.");
33224
33485
  }
33225
33486
  var availabilityTimeComplete = context.availabilityTimeComplete,
33487
+ availabilityTimeOffset = context.availabilityTimeOffset,
33226
33488
  manifestBoundsCalculator = context.manifestBoundsCalculator,
33227
33489
  isDynamic = context.isDynamic,
33228
33490
  isLastPeriod = context.isLastPeriod,
@@ -33249,8 +33511,25 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33249
33511
  this._parseTimeline = (_b = index.timelineParser) !== null && _b !== void 0 ? _b : null;
33250
33512
  var initializationUrl = ((_c = index.initialization) === null || _c === void 0 ? void 0 : _c.media) === undefined ? null : constructRepresentationUrl(index.initialization.media, representationId, representationBitrate);
33251
33513
  var segmentUrlTemplate = index.media === undefined ? null : constructRepresentationUrl(index.media, representationId, representationBitrate);
33514
+ var actualAvailabilityTimeOffset;
33515
+ // Technically, it seems (although it is not clear) that an MPD may contain
33516
+ // future segments and it's the job of a player to not request segments later
33517
+ // than the time at which they should be available.
33518
+ // In practice, we don't do that for various reasons: precision issues,
33519
+ // various DASH spec interpretations by packagers and players...
33520
+ //
33521
+ // So as a compromise, if nothing in the MPD indicates that future segments
33522
+ // may be announced (see code below), we will act as if ALL segments in this
33523
+ // TimelineRepresentationIndex are requestable
33524
+ if (availabilityTimeOffset === undefined && availabilityTimeComplete === undefined) {
33525
+ actualAvailabilityTimeOffset = Infinity; // Meaning: we can request
33526
+ // everything in the index
33527
+ } else {
33528
+ actualAvailabilityTimeOffset = availabilityTimeOffset !== null && availabilityTimeOffset !== void 0 ? availabilityTimeOffset : 0;
33529
+ }
33252
33530
  this._index = {
33253
- availabilityTimeComplete: availabilityTimeComplete,
33531
+ availabilityTimeComplete: availabilityTimeComplete !== null && availabilityTimeComplete !== void 0 ? availabilityTimeComplete : true,
33532
+ availabilityTimeOffset: actualAvailabilityTimeOffset,
33254
33533
  indexRange: index.indexRange,
33255
33534
  indexTimeOffset: indexTimeOffset,
33256
33535
  initialization: index.initialization == null ? undefined : {
@@ -33300,7 +33579,7 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33300
33579
  timeline: timeline,
33301
33580
  timescale: timescale,
33302
33581
  indexTimeOffset: indexTimeOffset
33303
- }, from, duration, this._isEMSGWhitelisted, this._scaledPeriodEnd);
33582
+ }, from, duration, this._manifestBoundsCalculator, this._scaledPeriodEnd, this._isEMSGWhitelisted);
33304
33583
  }
33305
33584
  /**
33306
33585
  * Returns true if the index should be refreshed.
@@ -33332,12 +33611,19 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33332
33611
  * @returns {Number|null}
33333
33612
  */;
33334
33613
  _proto.getLastAvailablePosition = function getLastAvailablePosition() {
33614
+ var _a;
33335
33615
  this._refreshTimeline();
33336
33616
  if (this._index.timeline === null) {
33337
33617
  this._index.timeline = this._getTimeline();
33338
33618
  }
33339
- var lastTime = TimelineRepresentationIndex.getIndexEnd(this._index.timeline, this._scaledPeriodEnd);
33340
- return lastTime === null ? null : fromIndexTime(lastTime, this._index);
33619
+ var lastReqSegInfo = getLastRequestableSegmentInfo(
33620
+ // Needed typecast for TypeScript
33621
+ this._index, this._manifestBoundsCalculator, this._scaledPeriodEnd);
33622
+ if (lastReqSegInfo === null) {
33623
+ return null;
33624
+ }
33625
+ var lastScaledPosition = Math.min(lastReqSegInfo.end, (_a = this._scaledPeriodEnd) !== null && _a !== void 0 ? _a : Infinity);
33626
+ return fromIndexTime(lastScaledPosition, this._index);
33341
33627
  }
33342
33628
  /**
33343
33629
  * Returns the absolute end in seconds this RepresentationIndex can reach once
@@ -33345,11 +33631,20 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33345
33631
  * @returns {number|null|undefined}
33346
33632
  */;
33347
33633
  _proto.getEnd = function getEnd() {
33348
- if (!this._isDynamic || !this._isLastPeriod) {
33349
- // @see isFinished
33350
- return this.getLastAvailablePosition();
33634
+ var _a;
33635
+ if (this._isDynamic && !this._isLastPeriod) {
33636
+ return undefined;
33351
33637
  }
33352
- return undefined;
33638
+ this._refreshTimeline();
33639
+ if (this._index.timeline === null) {
33640
+ this._index.timeline = this._getTimeline();
33641
+ }
33642
+ if (this._index.timeline.length <= 0) {
33643
+ return null;
33644
+ }
33645
+ var lastSegment = this._index.timeline[this._index.timeline.length - 1];
33646
+ var lastTime = Math.min(getIndexSegmentEnd(lastSegment, null, this._scaledPeriodEnd), (_a = this._scaledPeriodEnd) !== null && _a !== void 0 ? _a : Infinity);
33647
+ return fromIndexTime(lastTime, this._index);
33353
33648
  }
33354
33649
  /**
33355
33650
  * Returns:
@@ -33363,34 +33658,56 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33363
33658
  * @returns {boolean|undefined}
33364
33659
  */;
33365
33660
  _proto.awaitSegmentBetween = function awaitSegmentBetween(start, end) {
33366
- var _a;
33661
+ var _a, _b;
33367
33662
  assert_assert(start <= end);
33368
- if (!this._isDynamic || !this._isLastPeriod) {
33369
- return false;
33663
+ if (!this._isDynamic) {
33664
+ return false; // No segment will be newly available in the future
33370
33665
  }
33666
+
33371
33667
  this._refreshTimeline();
33372
33668
  if (this._index.timeline === null) {
33373
33669
  this._index.timeline = this._getTimeline();
33374
33670
  }
33375
33671
  var _this$_index2 = this._index,
33376
- timeline = _this$_index2.timeline,
33377
- timescale = _this$_index2.timescale;
33672
+ timescale = _this$_index2.timescale,
33673
+ timeline = _this$_index2.timeline;
33378
33674
  var segmentTimeRounding = getSegmentTimeRoundingError(timescale);
33379
- var scaledEnd = toIndexTime(end, this._index);
33380
- if (timeline.length > 0) {
33381
- var lastTimelineElement = timeline[timeline.length - 1];
33382
- var lastSegmentEnd = getIndexSegmentEnd(lastTimelineElement, null, this._scaledPeriodEnd);
33383
- var roundedEnd = lastSegmentEnd + segmentTimeRounding;
33384
- if (roundedEnd >= Math.min(scaledEnd, (_a = this._scaledPeriodEnd) !== null && _a !== void 0 ? _a : Infinity)) {
33385
- return false; // already loaded
33675
+ var scaledWantedEnd = toIndexTime(end, this._index);
33676
+ var lastReqSegInfo = getLastRequestableSegmentInfo(
33677
+ // Needed typecast for TypeScript
33678
+ this._index, this._manifestBoundsCalculator, this._scaledPeriodEnd);
33679
+ if (lastReqSegInfo !== null) {
33680
+ var lastReqSegmentEnd = Math.min(lastReqSegInfo.end, (_a = this._scaledPeriodEnd) !== null && _a !== void 0 ? _a : Infinity);
33681
+ var roundedReqSegmentEnd = lastReqSegmentEnd + segmentTimeRounding;
33682
+ if (roundedReqSegmentEnd >= Math.min(scaledWantedEnd, (_b = this._scaledPeriodEnd) !== null && _b !== void 0 ? _b : Infinity)) {
33683
+ return false; // everything up to that point is already requestable
33386
33684
  }
33387
33685
  }
33388
33686
 
33687
+ var scaledWantedStart = toIndexTime(start, this._index);
33688
+ if (timeline.length > 0 && lastReqSegInfo !== null && !lastReqSegInfo.isLastOfTimeline) {
33689
+ // There are some future segments already anounced in the MPD
33690
+ var lastSegment = timeline[timeline.length - 1];
33691
+ var lastSegmentEnd = getIndexSegmentEnd(lastSegment, null, this._scaledPeriodEnd);
33692
+ var roundedLastSegEnd = lastSegmentEnd + segmentTimeRounding;
33693
+ if (scaledWantedStart < roundedLastSegEnd + segmentTimeRounding) {
33694
+ return true; // The MPD's timeline already contains one such element,
33695
+ // It is just not requestable yet
33696
+ }
33697
+ }
33698
+
33699
+ if (!this._isLastPeriod) {
33700
+ // Let's consider - perhaps wrongly, that Periods which aren't the last
33701
+ // one have all of their segments announced.
33702
+ return false;
33703
+ }
33389
33704
  if (this._scaledPeriodEnd === undefined) {
33390
- return scaledEnd + segmentTimeRounding > this._scaledPeriodStart ? undefined : false;
33705
+ return scaledWantedEnd + segmentTimeRounding > this._scaledPeriodStart ? undefined :
33706
+ // There may be future segments at this point
33707
+ false; // Before the current Period
33391
33708
  }
33392
- var scaledStart = toIndexTime(start, this._index);
33393
- return scaledStart - segmentTimeRounding < this._scaledPeriodEnd && scaledEnd + segmentTimeRounding > this._scaledPeriodStart;
33709
+ // `true` if within the boundaries of this Period. `false` otherwise.
33710
+ return scaledWantedStart - segmentTimeRounding < this._scaledPeriodEnd && scaledWantedEnd + segmentTimeRounding > this._scaledPeriodStart;
33394
33711
  }
33395
33712
  /**
33396
33713
  * Returns true if a Segment returned by this index is still considered
@@ -33408,11 +33725,9 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33408
33725
  if (this._index.timeline === null) {
33409
33726
  this._index.timeline = this._getTimeline();
33410
33727
  }
33411
- var _this$_index3 = this._index,
33412
- timeline = _this$_index3.timeline,
33413
- timescale = _this$_index3.timescale,
33414
- indexTimeOffset = _this$_index3.indexTimeOffset;
33415
- return is_segment_still_available_isSegmentStillAvailable(segment, timeline, timescale, indexTimeOffset);
33728
+ return _isSegmentStillAvailable(segment,
33729
+ // Needed typecast for TypeScript
33730
+ this._index, this._manifestBoundsCalculator, this._scaledPeriodEnd);
33416
33731
  }
33417
33732
  /**
33418
33733
  * Checks if the time given is in a discontinuity. That is:
@@ -33476,6 +33791,8 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33476
33791
  if (hasReplaced) {
33477
33792
  this._index.startNumber = newIndex._index.startNumber;
33478
33793
  }
33794
+ this._index.availabilityTimeOffset = newIndex._index.availabilityTimeOffset;
33795
+ this._index.availabilityTimeComplete = newIndex._index.availabilityTimeComplete;
33479
33796
  this._index.endNumber = newIndex._index.endNumber;
33480
33797
  this._isDynamic = newIndex._isDynamic;
33481
33798
  this._scaledPeriodStart = newIndex._scaledPeriodStart;
@@ -33484,32 +33801,66 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33484
33801
  this._isLastPeriod = newIndex._isLastPeriod;
33485
33802
  }
33486
33803
  /**
33487
- * Returns `true` if this RepresentationIndex currently contains its last
33804
+ * Returns `false` if this RepresentationIndex currently contains its last
33488
33805
  * segment.
33489
- * Returns `false` if it's still pending.
33806
+ * Returns `true` if it's still pending.
33490
33807
  * @returns {Boolean}
33491
33808
  */;
33492
- _proto.isFinished = function isFinished() {
33493
- if (!this._isDynamic || !this._isLastPeriod) {
33494
- // Either the content is not dynamic, in which case no new segment will
33495
- // be generated, either it is but this index is not linked to the current
33496
- // last Period in the MPD, in which case it is inferred that it has been
33497
- // completely generated. Note that this second condition might break very
33498
- // very rare use cases where old Periods are still being generated, yet it
33499
- // should fix more cases than it breaks.
33500
- return true;
33809
+ _proto.isStillAwaitingFutureSegments = function isStillAwaitingFutureSegments() {
33810
+ var _a;
33811
+ if (!this._isDynamic) {
33812
+ return false;
33501
33813
  }
33814
+ this._refreshTimeline();
33502
33815
  if (this._index.timeline === null) {
33503
33816
  this._index.timeline = this._getTimeline();
33504
33817
  }
33505
33818
  var timeline = this._index.timeline;
33506
- if (this._scaledPeriodEnd === undefined || timeline.length === 0) {
33507
- return false;
33819
+ if (timeline.length === 0) {
33820
+ // No segment announced in this Period
33821
+ if (this._scaledPeriodEnd !== undefined) {
33822
+ var liveEdge = this._manifestBoundsCalculator.getEstimatedLiveEdge();
33823
+ if (liveEdge !== undefined && toIndexTime(liveEdge, this._index) > this._scaledPeriodEnd) {
33824
+ // This Period is over, we're not awaiting anything
33825
+ return false;
33826
+ }
33827
+ }
33828
+ // Let's just consider that we're awaiting only for when this is the last Period.
33829
+ return this._isLastPeriod;
33508
33830
  }
33509
- var lastTimelineElement = timeline[timeline.length - 1];
33510
- var lastTime = getIndexSegmentEnd(lastTimelineElement, null, this._scaledPeriodEnd);
33511
33831
  var segmentTimeRounding = getSegmentTimeRoundingError(this._index.timescale);
33512
- return lastTime + segmentTimeRounding >= this._scaledPeriodEnd;
33832
+ var lastReqSegInfo = getLastRequestableSegmentInfo(
33833
+ // Needed typecast for TypeScript
33834
+ this._index, this._manifestBoundsCalculator, this._scaledPeriodEnd);
33835
+ if (lastReqSegInfo !== null && !lastReqSegInfo.isLastOfTimeline) {
33836
+ // There might be non-yet requestable segments in the manifest
33837
+ var lastReqSegmentEnd = Math.min(lastReqSegInfo.end, (_a = this._scaledPeriodEnd) !== null && _a !== void 0 ? _a : Infinity);
33838
+ if (this._scaledPeriodEnd !== undefined && lastReqSegmentEnd + segmentTimeRounding >= this._scaledPeriodEnd) {
33839
+ // The last requestable segment ends after the end of the Period anyway
33840
+ return false;
33841
+ }
33842
+ return true; // There are not-yet requestable segments
33843
+ }
33844
+
33845
+ if (!this._isLastPeriod) {
33846
+ // This index is not linked to the current last Period in the MPD, in
33847
+ // which case it is inferred that all segments have been announced.
33848
+ //
33849
+ // Note that this condition might break very very rare use cases where old
33850
+ // Periods are still being generated, yet it should fix more cases than it
33851
+ // breaks.
33852
+ return false;
33853
+ }
33854
+ if (this._scaledPeriodEnd === undefined) {
33855
+ // This is the last Period of a dynamic content whose end is unknown.
33856
+ // Just return true.
33857
+ return true;
33858
+ }
33859
+ var lastSegment = timeline[timeline.length - 1];
33860
+ var lastSegmentEnd = getIndexSegmentEnd(lastSegment, null, this._scaledPeriodEnd);
33861
+ // We're awaiting future segments only if the current end is before the end
33862
+ // of the Period
33863
+ return lastSegmentEnd + segmentTimeRounding < this._scaledPeriodEnd;
33513
33864
  }
33514
33865
  /**
33515
33866
  * @returns {Boolean}
@@ -33543,7 +33894,7 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33543
33894
  if (!this._isDynamic) {
33544
33895
  return;
33545
33896
  }
33546
- var firstPosition = this._manifestBoundsCalculator.estimateMinimumBound();
33897
+ var firstPosition = this._manifestBoundsCalculator.getEstimatedMinimumSegmentTime();
33547
33898
  if (firstPosition == null) {
33548
33899
  return; // we don't know yet
33549
33900
  }
@@ -33555,12 +33906,6 @@ var TimelineRepresentationIndex = /*#__PURE__*/function () {
33555
33906
  } else if (this._index.endNumber !== undefined) {
33556
33907
  this._index.startNumber = nbEltsRemoved + 1;
33557
33908
  }
33558
- };
33559
- TimelineRepresentationIndex.getIndexEnd = function getIndexEnd(timeline, scaledPeriodEnd) {
33560
- if (timeline.length <= 0) {
33561
- return null;
33562
- }
33563
- return Math.min(getIndexSegmentEnd(timeline[timeline.length - 1], null, scaledPeriodEnd), scaledPeriodEnd !== null && scaledPeriodEnd !== void 0 ? scaledPeriodEnd : Infinity);
33564
33909
  }
33565
33910
  /**
33566
33911
  * Allows to generate the "timeline" for this RepresentationIndex.
@@ -33649,6 +33994,113 @@ function updateTimelineFromEndNumber(timeline, startNumber, endNumber) {
33649
33994
  }
33650
33995
  return timeline;
33651
33996
  }
33997
+ /**
33998
+ * Returns true if a Segment returned by the corresponding index is still
33999
+ * considered available.
34000
+ * Returns false if it is not available anymore.
34001
+ * Returns undefined if we cannot know whether it is still available or not.
34002
+ * /!\ We do not check the mediaURLs of the segment.
34003
+ * @param {Object} segment
34004
+ * @param {Object} index
34005
+ * @param {Object} manifestBoundsCalculator
34006
+ * @param {number|undefined} scaledPeriodEnd
34007
+ * @returns {Boolean|undefined}
34008
+ */
34009
+ function _isSegmentStillAvailable(segment, index, manifestBoundsCalculator, scaledPeriodEnd) {
34010
+ var lastReqSegInfo = getLastRequestableSegmentInfo(index, manifestBoundsCalculator, scaledPeriodEnd);
34011
+ if (lastReqSegInfo === null) {
34012
+ return false;
34013
+ }
34014
+ for (var i = 0; i < index.timeline.length; i++) {
34015
+ if (lastReqSegInfo.timelineIdx < i) {
34016
+ return false;
34017
+ }
34018
+ var tSegment = index.timeline[i];
34019
+ var tSegmentTime = (tSegment.start - index.indexTimeOffset) / index.timescale;
34020
+ if (tSegmentTime > segment.time) {
34021
+ return false; // We went over it without finding it
34022
+ } else if (tSegmentTime === segment.time) {
34023
+ if (tSegment.range === undefined) {
34024
+ return segment.range === undefined;
34025
+ }
34026
+ return segment.range != null && tSegment.range[0] === segment.range[0] && tSegment.range[1] === segment.range[1];
34027
+ } else {
34028
+ // tSegment.start < segment.time
34029
+ if (tSegment.repeatCount >= 0 && tSegment.duration !== undefined) {
34030
+ var timeDiff = tSegmentTime - tSegment.start;
34031
+ var repeat = timeDiff / tSegment.duration - 1;
34032
+ return repeat % 1 === 0 && repeat <= lastReqSegInfo.newRepeatCount;
34033
+ }
34034
+ }
34035
+ }
34036
+ return false;
34037
+ }
34038
+ /**
34039
+ * Returns from the given RepresentationIndex information on the last segment
34040
+ * that may be requested currently.
34041
+ *
34042
+ * Returns `null` if there's no such segment.
34043
+ * @param {Object} index
34044
+ * @param {Object} manifestBoundsCalculator
34045
+ * @param {number|undefined} scaledPeriodEnd
34046
+ * @returns {number|null}
34047
+ */
34048
+
34049
+ function getLastRequestableSegmentInfo(index, manifestBoundsCalculator, scaledPeriodEnd) {
34050
+ if (index.timeline.length <= 0) {
34051
+ return null;
34052
+ }
34053
+ if (index.availabilityTimeOffset === Infinity) {
34054
+ // availabilityTimeOffset to Infinity == Everything is requestable in the timeline.
34055
+ var lastIndex = index.timeline.length - 1;
34056
+ var lastElem = index.timeline[lastIndex];
34057
+ return {
34058
+ isLastOfTimeline: true,
34059
+ timelineIdx: lastIndex,
34060
+ newRepeatCount: lastElem.repeatCount,
34061
+ end: getIndexSegmentEnd(lastElem, null, scaledPeriodEnd)
34062
+ };
34063
+ }
34064
+ var adjustedMaxSeconds = manifestBoundsCalculator.getEstimatedMaximumPosition(index.availabilityTimeOffset);
34065
+ if (adjustedMaxSeconds === undefined) {
34066
+ var _lastIndex = index.timeline.length - 1;
34067
+ var _lastElem = index.timeline[_lastIndex];
34068
+ return {
34069
+ isLastOfTimeline: true,
34070
+ timelineIdx: _lastIndex,
34071
+ newRepeatCount: _lastElem.repeatCount,
34072
+ end: getIndexSegmentEnd(_lastElem, null, scaledPeriodEnd)
34073
+ };
34074
+ }
34075
+ for (var i = index.timeline.length - 1; i >= index.timeline.length; i--) {
34076
+ var element = index.timeline[i];
34077
+ var endOfFirstOccurence = element.start + element.duration;
34078
+ if (fromIndexTime(endOfFirstOccurence, index) <= adjustedMaxSeconds) {
34079
+ var endTime = getIndexSegmentEnd(element, index.timeline[i + 1], scaledPeriodEnd);
34080
+ if (fromIndexTime(endTime, index) <= adjustedMaxSeconds) {
34081
+ return {
34082
+ isLastOfTimeline: i === index.timeline.length - 1,
34083
+ timelineIdx: i,
34084
+ newRepeatCount: element.repeatCount,
34085
+ end: endOfFirstOccurence
34086
+ };
34087
+ } else {
34088
+ // We have to find the right repeatCount
34089
+ var maxIndexTime = toIndexTime(adjustedMaxSeconds, index);
34090
+ var diffToSegStart = maxIndexTime - element.start;
34091
+ var nbOfSegs = Math.floor(diffToSegStart / element.duration);
34092
+ assert_assert(nbOfSegs >= 1);
34093
+ return {
34094
+ isLastOfTimeline: false,
34095
+ timelineIdx: i,
34096
+ newRepeatCount: nbOfSegs - 1,
34097
+ end: element.start + nbOfSegs * element.duration
34098
+ };
34099
+ }
34100
+ }
34101
+ }
34102
+ return null;
34103
+ }
33652
34104
  ;// CONCATENATED MODULE: ./src/parsers/manifest/dash/common/indexes/timeline/index.ts
33653
34105
  /**
33654
34106
  * Copyright 2015 CANAL+ Group
@@ -33878,13 +34330,22 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
33878
34330
  var timescale = this._index.timescale;
33879
34331
  var segmentTimeRounding = getSegmentTimeRoundingError(timescale);
33880
34332
  var scaledPeriodStart = this._periodStart * timescale;
34333
+ var scaledRelativeStart = start * timescale - scaledPeriodStart;
33881
34334
  var scaledRelativeEnd = end * timescale - scaledPeriodStart;
34335
+ var lastSegmentStart = this._getLastSegmentStart();
34336
+ if (is_null_or_undefined_isNullOrUndefined(lastSegmentStart)) {
34337
+ var _relativeScaledIndexEnd = this._estimateRelativeScaledEnd();
34338
+ if (_relativeScaledIndexEnd === undefined) {
34339
+ return scaledRelativeEnd + segmentTimeRounding >= 0;
34340
+ }
34341
+ return scaledRelativeEnd + segmentTimeRounding >= 0 && scaledRelativeStart < _relativeScaledIndexEnd - segmentTimeRounding;
34342
+ }
34343
+ var lastSegmentEnd = lastSegmentStart + this._index.duration;
33882
34344
  var relativeScaledIndexEnd = this._estimateRelativeScaledEnd();
33883
34345
  if (relativeScaledIndexEnd === undefined) {
33884
- return scaledRelativeEnd + segmentTimeRounding >= 0;
34346
+ return scaledRelativeEnd > lastSegmentEnd - segmentTimeRounding;
33885
34347
  }
33886
- var scaledRelativeStart = start * timescale - scaledPeriodStart;
33887
- return scaledRelativeStart - segmentTimeRounding < relativeScaledIndexEnd;
34348
+ return scaledRelativeEnd > lastSegmentEnd - segmentTimeRounding && scaledRelativeStart < relativeScaledIndexEnd - segmentTimeRounding;
33888
34349
  }
33889
34350
  /**
33890
34351
  * Returns true if, based on the arguments, the index should be refreshed.
@@ -33927,30 +34388,30 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
33927
34388
  return false;
33928
34389
  }
33929
34390
  /**
33930
- * Returns `true` if the last segments in this index have already been
34391
+ * Returns `false` if the last segments in this index have already been
33931
34392
  * generated so that we can freely go to the next period.
33932
- * Returns `false` if the index is still waiting on future segments to be
34393
+ * Returns `true` if the index is still waiting on future segments to be
33933
34394
  * generated.
33934
34395
  * @returns {Boolean}
33935
34396
  */;
33936
- _proto.isFinished = function isFinished() {
34397
+ _proto.isStillAwaitingFutureSegments = function isStillAwaitingFutureSegments() {
33937
34398
  if (!this._isDynamic) {
33938
- return true;
34399
+ return false;
33939
34400
  }
33940
34401
  var scaledRelativeIndexEnd = this._estimateRelativeScaledEnd();
33941
34402
  if (scaledRelativeIndexEnd === undefined) {
33942
- return false;
34403
+ return true;
33943
34404
  }
33944
34405
  var timescale = this._index.timescale;
33945
34406
  var lastSegmentStart = this._getLastSegmentStart();
33946
34407
  // As last segment start is null if live time is before
33947
34408
  // current period, consider the index not to be finished.
33948
34409
  if (is_null_or_undefined_isNullOrUndefined(lastSegmentStart)) {
33949
- return false;
34410
+ return true;
33950
34411
  }
33951
34412
  var lastSegmentEnd = lastSegmentStart + this._index.duration;
33952
34413
  var segmentTimeRounding = getSegmentTimeRoundingError(timescale);
33953
- return lastSegmentEnd + segmentTimeRounding >= scaledRelativeIndexEnd;
34414
+ return lastSegmentEnd + segmentTimeRounding < scaledRelativeIndexEnd;
33954
34415
  }
33955
34416
  /**
33956
34417
  * @returns {Boolean}
@@ -33988,6 +34449,7 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
33988
34449
  * @returns {number | null | undefined}
33989
34450
  */;
33990
34451
  _proto._getFirstSegmentStart = function _getFirstSegmentStart() {
34452
+ var _a;
33991
34453
  if (!this._isDynamic) {
33992
34454
  return 0; // it is the start of the Period
33993
34455
  }
@@ -33996,8 +34458,8 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
33996
34458
  // /!\ The scaled max position augments continuously and might not
33997
34459
  // reflect exactly the real server-side value. As segments are
33998
34460
  // generated discretely.
33999
- var maximumBound = this._manifestBoundsCalculator.estimateMaximumBound();
34000
- if (maximumBound !== undefined && maximumBound < this._periodStart) {
34461
+ var maximumSegmentTime = this._manifestBoundsCalculator.getEstimatedMaximumPosition((_a = this._availabilityTimeOffset) !== null && _a !== void 0 ? _a : 0);
34462
+ if (maximumSegmentTime !== undefined && maximumSegmentTime < this._periodStart) {
34001
34463
  // Maximum position is before this period.
34002
34464
  // No segment is yet available here
34003
34465
  return null;
@@ -34006,7 +34468,7 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
34006
34468
  var _this$_index = this._index,
34007
34469
  duration = _this$_index.duration,
34008
34470
  timescale = _this$_index.timescale;
34009
- var firstPosition = this._manifestBoundsCalculator.estimateMinimumBound();
34471
+ var firstPosition = this._manifestBoundsCalculator.getEstimatedMinimumSegmentTime();
34010
34472
  if (firstPosition === undefined) {
34011
34473
  return undefined;
34012
34474
  }
@@ -34021,7 +34483,7 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
34021
34483
  * @returns {number|null|undefined}
34022
34484
  */;
34023
34485
  _proto._getLastSegmentStart = function _getLastSegmentStart() {
34024
- var _a;
34486
+ var _a, _b;
34025
34487
  var _this$_index2 = this._index,
34026
34488
  duration = _this$_index2.duration,
34027
34489
  timescale = _this$_index2.timescale,
@@ -34029,34 +34491,34 @@ var TemplateRepresentationIndex = /*#__PURE__*/function () {
34029
34491
  _this$_index2$startNu = _this$_index2.startNumber,
34030
34492
  startNumber = _this$_index2$startNu === void 0 ? 1 : _this$_index2$startNu;
34031
34493
  if (this._isDynamic) {
34032
- var lastPos = this._manifestBoundsCalculator.estimateMaximumBound();
34033
- if (lastPos === undefined) {
34034
- return undefined;
34035
- }
34036
- if (this._scaledRelativePeriodEnd !== undefined && this._scaledRelativePeriodEnd < (lastPos - this._periodStart) * this._index.timescale) {
34494
+ var liveEdge = this._manifestBoundsCalculator.getEstimatedLiveEdge();
34495
+ if (liveEdge !== undefined && this._scaledRelativePeriodEnd !== undefined && this._scaledRelativePeriodEnd < liveEdge - this._periodStart * this._index.timescale) {
34037
34496
  var numberOfSegments = Math.ceil(this._scaledRelativePeriodEnd / duration);
34038
34497
  if (endNumber !== undefined && endNumber - startNumber + 1 < numberOfSegments) {
34039
34498
  numberOfSegments = endNumber - startNumber + 1;
34040
34499
  }
34041
34500
  return (numberOfSegments - 1) * duration;
34042
34501
  }
34502
+ var lastPosition = this._manifestBoundsCalculator.getEstimatedMaximumPosition((_a = this._availabilityTimeOffset) !== null && _a !== void 0 ? _a : 0);
34503
+ if (lastPosition === undefined) {
34504
+ return undefined;
34505
+ }
34043
34506
  // /!\ The scaled last position augments continuously and might not
34044
34507
  // reflect exactly the real server-side value. As segments are
34045
34508
  // generated discretely.
34046
- var scaledLastPosition = (lastPos - this._periodStart) * timescale;
34509
+ var scaledLastPosition = (lastPosition - this._periodStart) * timescale;
34047
34510
  // Maximum position is before this period.
34048
34511
  // No segment is yet available here
34049
34512
  if (scaledLastPosition < 0) {
34050
34513
  return null;
34051
34514
  }
34052
- var availabilityTimeOffset = (this._availabilityTimeOffset !== undefined ? this._availabilityTimeOffset : 0) * timescale;
34053
- var numberOfSegmentsAvailable = Math.floor((scaledLastPosition + availabilityTimeOffset) / duration);
34515
+ var numberOfSegmentsAvailable = Math.floor(scaledLastPosition / duration);
34054
34516
  if (endNumber !== undefined && endNumber - startNumber + 1 < numberOfSegmentsAvailable) {
34055
34517
  numberOfSegmentsAvailable = endNumber - startNumber + 1;
34056
34518
  }
34057
34519
  return numberOfSegmentsAvailable <= 0 ? null : (numberOfSegmentsAvailable - 1) * duration;
34058
34520
  } else {
34059
- var maximumTime = (_a = this._scaledRelativePeriodEnd) !== null && _a !== void 0 ? _a : 0;
34521
+ var maximumTime = (_b = this._scaledRelativePeriodEnd) !== null && _b !== void 0 ? _b : 0;
34060
34522
  var _numberOfSegments = Math.ceil(maximumTime / duration);
34061
34523
  if (endNumber !== undefined && endNumber - startNumber + 1 < _numberOfSegments) {
34062
34524
  _numberOfSegments = endNumber - startNumber + 1;
@@ -34128,7 +34590,6 @@ function parseRepresentationIndex(representation, context) {
34128
34590
  periodEnd = context.end,
34129
34591
  periodStart = context.start,
34130
34592
  receivedTime = context.receivedTime,
34131
- timeShiftBufferDepth = context.timeShiftBufferDepth,
34132
34593
  unsafelyBaseOnPreviousRepresentation = context.unsafelyBaseOnPreviousRepresentation,
34133
34594
  inbandEventStreams = context.inbandEventStreams,
34134
34595
  isLastPeriod = context.isLastPeriod;
@@ -34142,7 +34603,7 @@ function parseRepresentationIndex(representation, context) {
34142
34603
  });
34143
34604
  };
34144
34605
  var reprIndexCtxt = {
34145
- availabilityTimeComplete: true,
34606
+ availabilityTimeComplete: undefined,
34146
34607
  availabilityTimeOffset: availabilityTimeOffset,
34147
34608
  unsafelyBaseOnPreviousRepresentation: unsafelyBaseOnPreviousRepresentation,
34148
34609
  isEMSGWhitelisted: isEMSGWhitelisted,
@@ -34153,8 +34614,7 @@ function parseRepresentationIndex(representation, context) {
34153
34614
  periodStart: periodStart,
34154
34615
  receivedTime: receivedTime,
34155
34616
  representationBitrate: representation.attributes.bitrate,
34156
- representationId: representation.attributes.id,
34157
- timeShiftBufferDepth: timeShiftBufferDepth
34617
+ representationId: representation.attributes.id
34158
34618
  };
34159
34619
  var representationIndex;
34160
34620
  if (representation.children.segmentBase !== undefined) {
@@ -34170,8 +34630,9 @@ function parseRepresentationIndex(representation, context) {
34170
34630
  segmentTemplates.push(childSegmentTemplate);
34171
34631
  }
34172
34632
  var segmentTemplate = object_assign.apply(void 0, [{}].concat(segmentTemplates));
34173
- reprIndexCtxt.availabilityTimeComplete = (_a = segmentTemplate.availabilityTimeComplete) !== null && _a !== void 0 ? _a : context.availabilityTimeComplete;
34174
- reprIndexCtxt.availabilityTimeOffset = ((_b = segmentTemplate.availabilityTimeOffset) !== null && _b !== void 0 ? _b : 0) + context.availabilityTimeOffset;
34633
+ if (segmentTemplate.availabilityTimeOffset !== undefined || context.availabilityTimeOffset !== undefined) {
34634
+ reprIndexCtxt.availabilityTimeOffset = ((_a = segmentTemplate.availabilityTimeOffset) !== null && _a !== void 0 ? _a : 0) + ((_b = context.availabilityTimeOffset) !== null && _b !== void 0 ? _b : 0);
34635
+ }
34175
34636
  representationIndex = timeline.isTimelineIndexArgument(segmentTemplate) ? new timeline(segmentTemplate, reprIndexCtxt) : new TemplateRepresentationIndex(segmentTemplate, reprIndexCtxt);
34176
34637
  } else {
34177
34638
  var adaptationChildren = context.adaptation.children;
@@ -34337,7 +34798,7 @@ function getHDRInformation(_ref) {
34337
34798
  * @returns {Array.<Object>}
34338
34799
  */
34339
34800
  function parseRepresentations(representationsIR, adaptation, context) {
34340
- var _a, _b, _c, _d;
34801
+ var _a, _b, _c, _d, _e;
34341
34802
  var parsedRepresentations = [];
34342
34803
  var _loop = function _loop() {
34343
34804
  var representation = _step.value;
@@ -34353,7 +34814,10 @@ function parseRepresentations(representationsIR, adaptation, context) {
34353
34814
  var unsafelyBaseOnPreviousRepresentation = (_b = (_a = context.unsafelyBaseOnPreviousAdaptation) === null || _a === void 0 ? void 0 : _a.getRepresentation(representationID)) !== null && _b !== void 0 ? _b : null;
34354
34815
  var inbandEventStreams = combineInbandEventStreams(representation, adaptation);
34355
34816
  var availabilityTimeComplete = (_c = representation.attributes.availabilityTimeComplete) !== null && _c !== void 0 ? _c : context.availabilityTimeComplete;
34356
- var availabilityTimeOffset = ((_d = representation.attributes.availabilityTimeOffset) !== null && _d !== void 0 ? _d : 0) + context.availabilityTimeOffset;
34817
+ var availabilityTimeOffset;
34818
+ if (representation.attributes.availabilityTimeOffset !== undefined || context.availabilityTimeOffset !== undefined) {
34819
+ availabilityTimeOffset = ((_d = representation.attributes.availabilityTimeOffset) !== null && _d !== void 0 ? _d : 0) + ((_e = context.availabilityTimeOffset) !== null && _e !== void 0 ? _e : 0);
34820
+ }
34357
34821
  var reprIndexCtxt = object_assign({}, context, {
34358
34822
  availabilityTimeOffset: availabilityTimeOffset,
34359
34823
  availabilityTimeComplete: availabilityTimeComplete,
@@ -34671,7 +35135,7 @@ function getAdaptationSetSwitchingIDs(adaptation) {
34671
35135
  * @returns {Array.<Object>}
34672
35136
  */
34673
35137
  function parseAdaptationSets(adaptationsIR, context) {
34674
- var _a, _b, _c, _d, _e, _f;
35138
+ var _a, _b, _c, _d, _e, _f, _g;
34675
35139
  var parsedAdaptations = {
34676
35140
  video: [],
34677
35141
  audio: [],
@@ -34693,14 +35157,17 @@ function parseAdaptationSets(adaptationsIR, context) {
34693
35157
  });
34694
35158
  var representationsIR = adaptation.children.representations;
34695
35159
  var availabilityTimeComplete = (_a = adaptation.attributes.availabilityTimeComplete) !== null && _a !== void 0 ? _a : context.availabilityTimeComplete;
34696
- var availabilityTimeOffset = ((_b = adaptation.attributes.availabilityTimeOffset) !== null && _b !== void 0 ? _b : 0) + context.availabilityTimeOffset;
35160
+ var availabilityTimeOffset = void 0;
35161
+ if (adaptation.attributes.availabilityTimeOffset !== undefined || context.availabilityTimeOffset !== undefined) {
35162
+ availabilityTimeOffset = ((_b = adaptation.attributes.availabilityTimeOffset) !== null && _b !== void 0 ? _b : 0) + ((_c = context.availabilityTimeOffset) !== null && _c !== void 0 ? _c : 0);
35163
+ }
34697
35164
  var adaptationMimeType = adaptation.attributes.mimeType;
34698
35165
  var adaptationCodecs = adaptation.attributes.codecs;
34699
35166
  var type = inferAdaptationType(representationsIR, isNonEmptyString(adaptationMimeType) ? adaptationMimeType : null, isNonEmptyString(adaptationCodecs) ? adaptationCodecs : null, adaptationChildren.roles != null ? adaptationChildren.roles : null);
34700
35167
  if (type === undefined) {
34701
35168
  continue;
34702
35169
  }
34703
- var priority = (_c = adaptation.attributes.selectionPriority) !== null && _c !== void 0 ? _c : 1;
35170
+ var priority = (_d = adaptation.attributes.selectionPriority) !== null && _d !== void 0 ? _d : 1;
34704
35171
  var originalID = adaptation.attributes.id;
34705
35172
  var adaptationSetSwitchingIDs = getAdaptationSetSwitchingIDs(adaptation);
34706
35173
  var parentSegmentTemplates = [];
@@ -34722,13 +35189,12 @@ function parseAdaptationSets(adaptationsIR, context) {
34722
35189
  parentSegmentTemplates: parentSegmentTemplates,
34723
35190
  receivedTime: context.receivedTime,
34724
35191
  start: context.start,
34725
- timeShiftBufferDepth: context.timeShiftBufferDepth,
34726
35192
  unsafelyBaseOnPreviousAdaptation: null
34727
35193
  };
34728
35194
  var trickModeProperty = Array.isArray(essentialProperties) ? arrayFind(essentialProperties, function (scheme) {
34729
35195
  return scheme.schemeIdUri === "http://dashif.org/guidelines/trickmode";
34730
35196
  }) : undefined;
34731
- var trickModeAttachedAdaptationIds = (_d = trickModeProperty === null || trickModeProperty === void 0 ? void 0 : trickModeProperty.value) === null || _d === void 0 ? void 0 : _d.split(" ");
35197
+ var trickModeAttachedAdaptationIds = (_e = trickModeProperty === null || trickModeProperty === void 0 ? void 0 : trickModeProperty.value) === null || _e === void 0 ? void 0 : _e.split(" ");
34732
35198
  var isTrickModeTrack = trickModeAttachedAdaptationIds !== undefined;
34733
35199
  var accessibilities = adaptationChildren.accessibilities;
34734
35200
  var isDub = void 0;
@@ -34775,7 +35241,7 @@ function parseAdaptationSets(adaptationsIR, context) {
34775
35241
  }
34776
35242
  var newID = adaptationID;
34777
35243
  parsedAdaptationsIDs.push(adaptationID);
34778
- reprCtxt.unsafelyBaseOnPreviousAdaptation = (_f = (_e = context.unsafelyBaseOnPreviousPeriod) === null || _e === void 0 ? void 0 : _e.getAdaptation(adaptationID)) !== null && _f !== void 0 ? _f : null;
35244
+ reprCtxt.unsafelyBaseOnPreviousAdaptation = (_g = (_f = context.unsafelyBaseOnPreviousPeriod) === null || _f === void 0 ? void 0 : _f.getAdaptation(adaptationID)) !== null && _g !== void 0 ? _g : null;
34779
35245
  var representations = parseRepresentations(representationsIR, adaptation, reprCtxt);
34780
35246
  var parsedAdaptationSet = {
34781
35247
  id: adaptationID,
@@ -34909,8 +35375,8 @@ function parse_periods_arrayLikeToArray(arr, len) { if (len == null || len > arr
34909
35375
 
34910
35376
 
34911
35377
 
34912
- // eslint-disable-next-line max-len
34913
35378
 
35379
+ // eslint-disable-next-line max-len
34914
35380
 
34915
35381
 
34916
35382
 
@@ -34923,19 +35389,15 @@ var generatePeriodID = idGenerator();
34923
35389
  * @returns {Array.<Object>}
34924
35390
  */
34925
35391
  function parsePeriods(periodsIR, context) {
34926
- var _a, _b, _c, _d, _e, _f;
35392
+ var _a, _b, _c, _d;
34927
35393
  var parsedPeriods = [];
34928
35394
  var periodsTimeInformation = getPeriodsTimeInformation(periodsIR, context);
34929
35395
  if (periodsTimeInformation.length !== periodsIR.length) {
34930
35396
  throw new Error("MPD parsing error: the time information are incoherent.");
34931
35397
  }
34932
35398
  var isDynamic = context.isDynamic,
34933
- timeShiftBufferDepth = context.timeShiftBufferDepth;
34934
- var manifestBoundsCalculator = new ManifestBoundsCalculator({
34935
- isDynamic: isDynamic,
34936
- timeShiftBufferDepth: timeShiftBufferDepth
34937
- });
34938
- if (!isDynamic && context.duration != null) {
35399
+ manifestBoundsCalculator = context.manifestBoundsCalculator;
35400
+ if (!isDynamic && !is_null_or_undefined_isNullOrUndefined(context.duration)) {
34939
35401
  manifestBoundsCalculator.setLastPosition(context.duration);
34940
35402
  }
34941
35403
  // We parse it in reverse because we might need to deduce the buffer depth from
@@ -34950,7 +35412,7 @@ function parsePeriods(periodsIR, context) {
34950
35412
  periodDuration = _periodsTimeInformati.periodDuration,
34951
35413
  periodEnd = _periodsTimeInformati.periodEnd;
34952
35414
  var periodID;
34953
- if (periodIR.attributes.id == null) {
35415
+ if (is_null_or_undefined_isNullOrUndefined(periodIR.attributes.id)) {
34954
35416
  src_log.warn("DASH: No usable id found in the Period. Generating one.");
34955
35417
  periodID = "gen-dash-period-" + generatePeriodID();
34956
35418
  } else {
@@ -34964,8 +35426,8 @@ function parsePeriods(periodsIR, context) {
34964
35426
  }
34965
35427
  var receivedTime = xlinkInfos !== undefined ? xlinkInfos.receivedTime : context.receivedTime;
34966
35428
  var unsafelyBaseOnPreviousPeriod = (_b = (_a = context.unsafelyBaseOnPreviousManifest) === null || _a === void 0 ? void 0 : _a.getPeriod(periodID)) !== null && _b !== void 0 ? _b : null;
34967
- var availabilityTimeComplete = (_c = periodIR.attributes.availabilityTimeComplete) !== null && _c !== void 0 ? _c : true;
34968
- var availabilityTimeOffset = (_d = periodIR.attributes.availabilityTimeOffset) !== null && _d !== void 0 ? _d : 0;
35429
+ var availabilityTimeComplete = periodIR.attributes.availabilityTimeComplete;
35430
+ var availabilityTimeOffset = periodIR.attributes.availabilityTimeOffset;
34969
35431
  var manifestProfiles = context.manifestProfiles;
34970
35432
  var segmentTemplate = periodIR.children.segmentTemplate;
34971
35433
  var adapCtxt = {
@@ -34980,11 +35442,10 @@ function parsePeriods(periodsIR, context) {
34980
35442
  receivedTime: receivedTime,
34981
35443
  segmentTemplate: segmentTemplate,
34982
35444
  start: periodStart,
34983
- timeShiftBufferDepth: timeShiftBufferDepth,
34984
35445
  unsafelyBaseOnPreviousPeriod: unsafelyBaseOnPreviousPeriod
34985
35446
  };
34986
35447
  var adaptations = parseAdaptationSets(periodIR.children.adaptations, adapCtxt);
34987
- var namespaces = ((_e = context.xmlNamespaces) !== null && _e !== void 0 ? _e : []).concat((_f = periodIR.attributes.namespaces) !== null && _f !== void 0 ? _f : []);
35448
+ var namespaces = ((_c = context.xmlNamespaces) !== null && _c !== void 0 ? _c : []).concat((_d = periodIR.attributes.namespaces) !== null && _d !== void 0 ? _d : []);
34988
35449
  var streamEvents = generateStreamEvents(periodIR.children.eventStreams, periodStart, namespaces);
34989
35450
  var parsedPeriod = {
34990
35451
  id: periodID,
@@ -35059,7 +35520,7 @@ function parsePeriods(periodsIR, context) {
35059
35520
  * @returns {Array.<number|undefined>}
35060
35521
  */
35061
35522
  function guessLastPositionFromClock(context, minimumTime) {
35062
- if (context.clockOffset != null) {
35523
+ if (!is_null_or_undefined_isNullOrUndefined(context.clockOffset)) {
35063
35524
  var lastPosition = context.clockOffset / 1000 - context.availabilityStartTime;
35064
35525
  var positionTime = getMonotonicTimeStamp() / 1000;
35065
35526
  var timeInSec = positionTime + lastPosition;
@@ -35091,7 +35552,7 @@ function getMaximumLastPosition(adaptationsPerType) {
35091
35552
  var maxEncounteredPosition = null;
35092
35553
  var allIndexAreEmpty = true;
35093
35554
  var adaptationsVal = object_values(adaptationsPerType).filter(function (ada) {
35094
- return ada != null;
35555
+ return !is_null_or_undefined_isNullOrUndefined(ada);
35095
35556
  });
35096
35557
  var allAdaptations = flatMap(adaptationsVal, function (adaptationsForType) {
35097
35558
  return adaptationsForType;
@@ -35105,12 +35566,12 @@ function getMaximumLastPosition(adaptationsPerType) {
35105
35566
  if (position !== null) {
35106
35567
  allIndexAreEmpty = false;
35107
35568
  if (typeof position === "number") {
35108
- maxEncounteredPosition = maxEncounteredPosition == null ? position : Math.max(maxEncounteredPosition, position);
35569
+ maxEncounteredPosition = is_null_or_undefined_isNullOrUndefined(maxEncounteredPosition) ? position : Math.max(maxEncounteredPosition, position);
35109
35570
  }
35110
35571
  }
35111
35572
  }
35112
35573
  }
35113
- if (maxEncounteredPosition != null) {
35574
+ if (!is_null_or_undefined_isNullOrUndefined(maxEncounteredPosition)) {
35114
35575
  return maxEncounteredPosition;
35115
35576
  } else if (allIndexAreEmpty) {
35116
35577
  return null;
@@ -35208,6 +35669,7 @@ function parse_mpd_arrayLikeToArray(arr, len) { if (len == null || len > arr.len
35208
35669
 
35209
35670
 
35210
35671
 
35672
+
35211
35673
  /**
35212
35674
  * Checks if xlinks needs to be loaded before actually parsing the manifest.
35213
35675
  * @param {Object} mpdIR
@@ -35330,12 +35792,20 @@ function parseCompleteIntermediateRepresentation(mpdIR, args, warnings, xlinkInf
35330
35792
  var timeShiftBufferDepth = rootAttributes.timeShiftBufferDepth;
35331
35793
  var clockOffset = args.externalClockOffset,
35332
35794
  unsafelyBaseOnPreviousManifest = args.unsafelyBaseOnPreviousManifest;
35795
+ var externalClockOffset = args.externalClockOffset;
35796
+ var manifestBoundsCalculator = new ManifestBoundsCalculator({
35797
+ availabilityStartTime: availabilityStartTime,
35798
+ isDynamic: isDynamic,
35799
+ timeShiftBufferDepth: timeShiftBufferDepth,
35800
+ serverTimestampOffset: externalClockOffset
35801
+ });
35333
35802
  var manifestInfos = {
35334
35803
  availabilityStartTime: availabilityStartTime,
35335
35804
  baseURLs: mpdBaseUrls,
35336
35805
  clockOffset: clockOffset,
35337
35806
  duration: rootAttributes.duration,
35338
35807
  isDynamic: isDynamic,
35808
+ manifestBoundsCalculator: manifestBoundsCalculator,
35339
35809
  manifestProfiles: mpdIR.attributes.profiles,
35340
35810
  receivedTime: args.manifestReceivedTime,
35341
35811
  timeShiftBufferDepth: timeShiftBufferDepth,
@@ -35377,29 +35847,32 @@ function parseCompleteIntermediateRepresentation(mpdIR, args, warnings, xlinkInf
35377
35847
  time: now
35378
35848
  };
35379
35849
  } else {
35380
- minimumTime = minimumSafePosition;
35381
- timeshiftDepth = timeShiftBufferDepth !== null && timeShiftBufferDepth !== void 0 ? timeShiftBufferDepth : null;
35850
+ // Determine the maximum seekable position
35382
35851
  var _finalMaximumSafePosition;
35383
- var livePosition;
35384
- if (maximumUnsafePosition !== undefined) {
35385
- livePosition = maximumUnsafePosition;
35386
- }
35387
35852
  if (maximumSafePosition !== undefined) {
35388
35853
  _finalMaximumSafePosition = maximumSafePosition;
35389
35854
  } else {
35390
- var ast = availabilityStartTime !== null && availabilityStartTime !== void 0 ? availabilityStartTime : 0;
35391
- var externalClockOffset = args.externalClockOffset;
35392
35855
  if (externalClockOffset === undefined) {
35393
35856
  src_log.warn("DASH Parser: use system clock to define maximum position");
35394
- _finalMaximumSafePosition = Date.now() / 1000 - ast;
35857
+ _finalMaximumSafePosition = Date.now() / 1000 - availabilityStartTime;
35395
35858
  } else {
35396
35859
  var serverTime = getMonotonicTimeStamp() + externalClockOffset;
35397
- _finalMaximumSafePosition = serverTime / 1000 - ast;
35860
+ _finalMaximumSafePosition = serverTime / 1000 - availabilityStartTime;
35398
35861
  }
35399
35862
  }
35863
+ // Determine live edge (what position corresponds to live content, can be
35864
+ // inferior or superior to the maximum anounced position in some specific
35865
+ // scenarios). However, the `timeShiftBufferDepth` should be based on it.
35866
+ var livePosition = manifestBoundsCalculator.getEstimatedLiveEdge();
35400
35867
  if (livePosition === undefined) {
35401
- livePosition = _finalMaximumSafePosition;
35868
+ if (maximumUnsafePosition !== undefined) {
35869
+ livePosition = maximumUnsafePosition;
35870
+ } else {
35871
+ livePosition = _finalMaximumSafePosition;
35872
+ }
35873
+ // manifestBoundsCalculator.forceLiveEdge(livePosition);
35402
35874
  }
35875
+
35403
35876
  maximumTimeData = {
35404
35877
  isLinear: true,
35405
35878
  maximumSafePosition: _finalMaximumSafePosition,
@@ -35408,8 +35881,10 @@ function parseCompleteIntermediateRepresentation(mpdIR, args, warnings, xlinkInf
35408
35881
  };
35409
35882
  // if the minimum calculated time is even below the buffer depth, perhaps we
35410
35883
  // can go even lower in terms of depth
35411
- if (timeshiftDepth !== null && minimumTime !== undefined && _finalMaximumSafePosition - minimumTime > timeshiftDepth) {
35412
- timeshiftDepth = _finalMaximumSafePosition - minimumTime;
35884
+ minimumTime = minimumSafePosition;
35885
+ timeshiftDepth = timeShiftBufferDepth !== null && timeShiftBufferDepth !== void 0 ? timeShiftBufferDepth : null;
35886
+ if (timeshiftDepth !== null && minimumTime !== undefined && livePosition - minimumTime > timeshiftDepth) {
35887
+ timeshiftDepth = livePosition - minimumTime;
35413
35888
  }
35414
35889
  }
35415
35890
  // `isLastPeriodKnown` should be `true` in two cases for DASH contents:
@@ -37562,15 +38037,18 @@ function generateManifestParser(options) {
37562
38037
  var externalResources = value.urls.map(function (resourceUrl) {
37563
38038
  return scheduleRequest(function () {
37564
38039
  var defaultTimeout = config.getCurrent().DEFAULT_REQUEST_TIMEOUT;
38040
+ var defaultConnectionTimeout = config.getCurrent().DEFAULT_CONNECTION_TIMEOUT;
37565
38041
  return value.format === "string" ? utils_request({
37566
38042
  url: resourceUrl,
37567
38043
  responseType: "text",
37568
38044
  timeout: defaultTimeout,
38045
+ connectionTimeout: defaultConnectionTimeout,
37569
38046
  cancelSignal: cancelSignal
37570
38047
  }) : utils_request({
37571
38048
  url: resourceUrl,
37572
38049
  responseType: "arraybuffer",
37573
38050
  timeout: defaultTimeout,
38051
+ connectionTimeout: defaultConnectionTimeout,
37574
38052
  cancelSignal: cancelSignal
37575
38053
  });
37576
38054
  }).then(function (res) {
@@ -37764,7 +38242,8 @@ function fetchRequest(options) {
37764
38242
  }
37765
38243
  src_log.debug("Fetch: Called with URL", options.url);
37766
38244
  var cancellation = null;
37767
- var timeouted = false;
38245
+ var isTimedOut = false;
38246
+ var isConnectionTimedOut = false;
37768
38247
  var sendingTime = getMonotonicTimeStamp();
37769
38248
  var abortController = !is_null_or_undefined_isNullOrUndefined(_AbortController) ? new _AbortController() : null;
37770
38249
  /**
@@ -37778,13 +38257,26 @@ function fetchRequest(options) {
37778
38257
  }
37779
38258
  abortController.abort();
37780
38259
  }
37781
- var timeout;
38260
+ var timeoutId;
37782
38261
  if (options.timeout !== undefined) {
37783
- timeout = setTimeout(function () {
37784
- timeouted = true;
38262
+ timeoutId = setTimeout(function () {
38263
+ isTimedOut = true;
38264
+ if (connectionTimeoutId !== undefined) {
38265
+ clearTimeout(connectionTimeoutId);
38266
+ }
37785
38267
  abortFetch();
37786
38268
  }, options.timeout);
37787
38269
  }
38270
+ var connectionTimeoutId;
38271
+ if (options.connectionTimeout !== undefined) {
38272
+ connectionTimeoutId = setTimeout(function () {
38273
+ isConnectionTimedOut = true;
38274
+ if (timeoutId !== undefined) {
38275
+ clearTimeout(timeoutId);
38276
+ }
38277
+ abortFetch();
38278
+ }, options.connectionTimeout);
38279
+ }
37788
38280
  var deregisterCancelLstnr = options.cancelSignal.register(function abortRequest(err) {
37789
38281
  cancellation = err;
37790
38282
  abortFetch();
@@ -37797,8 +38289,8 @@ function fetchRequest(options) {
37797
38289
  }
37798
38290
  fetchOpts.signal = !is_null_or_undefined_isNullOrUndefined(abortController) ? abortController.signal : null;
37799
38291
  return fetch(options.url, fetchOpts).then(function (response) {
37800
- if (!is_null_or_undefined_isNullOrUndefined(timeout)) {
37801
- clearTimeout(timeout);
38292
+ if (connectionTimeoutId !== undefined) {
38293
+ clearTimeout(connectionTimeoutId);
37802
38294
  }
37803
38295
  if (response.status >= 300) {
37804
38296
  src_log.warn("Fetch: Request HTTP Error", response.status, response.url);
@@ -37845,9 +38337,12 @@ function fetchRequest(options) {
37845
38337
  return _context.abrupt("return", readBufferAndSendEvents());
37846
38338
  case 11:
37847
38339
  if (!data.done) {
37848
- _context.next = 16;
38340
+ _context.next = 17;
37849
38341
  break;
37850
38342
  }
38343
+ if (timeoutId !== undefined) {
38344
+ clearTimeout(timeoutId);
38345
+ }
37851
38346
  deregisterCancelLstnr();
37852
38347
  receivedTime = getMonotonicTimeStamp();
37853
38348
  requestDuration = receivedTime - sendingTime;
@@ -37859,9 +38354,9 @@ function fetchRequest(options) {
37859
38354
  status: response.status,
37860
38355
  url: response.url
37861
38356
  });
37862
- case 16:
37863
- return _context.abrupt("return", readBufferAndSendEvents());
37864
38357
  case 17:
38358
+ return _context.abrupt("return", readBufferAndSendEvents());
38359
+ case 18:
37865
38360
  case "end":
37866
38361
  return _context.stop();
37867
38362
  }
@@ -37874,8 +38369,11 @@ function fetchRequest(options) {
37874
38369
  throw cancellation;
37875
38370
  }
37876
38371
  deregisterCancelLstnr();
37877
- if (timeouted) {
37878
- src_log.warn("Fetch: Request timeouted.");
38372
+ if (isTimedOut) {
38373
+ src_log.warn("Fetch: Request timed out.");
38374
+ throw new RequestError(options.url, 0, NetworkErrorTypes.TIMEOUT);
38375
+ } else if (isConnectionTimedOut) {
38376
+ src_log.warn("Fetch: Request connection timed out.");
37879
38377
  throw new RequestError(options.url, 0, NetworkErrorTypes.TIMEOUT);
37880
38378
  } else if (err instanceof RequestError) {
37881
38379
  throw err;
@@ -38068,6 +38566,7 @@ function initSegmentLoader(url, segment, options, cancelSignal, callbacks) {
38068
38566
  url: url,
38069
38567
  responseType: "arraybuffer",
38070
38568
  timeout: options.timeout,
38569
+ connectionTimeout: options.connectionTimeout,
38071
38570
  cancelSignal: cancelSignal,
38072
38571
  onProgress: callbacks.onProgress
38073
38572
  }).then(function (data) {
@@ -38085,6 +38584,7 @@ function initSegmentLoader(url, segment, options, cancelSignal, callbacks) {
38085
38584
  },
38086
38585
  responseType: "arraybuffer",
38087
38586
  timeout: options.timeout,
38587
+ connectionTimeout: options.connectionTimeout,
38088
38588
  cancelSignal: cancelSignal,
38089
38589
  onProgress: callbacks.onProgress
38090
38590
  }).then(function (data) {
@@ -38103,6 +38603,7 @@ function initSegmentLoader(url, segment, options, cancelSignal, callbacks) {
38103
38603
  },
38104
38604
  responseType: "arraybuffer",
38105
38605
  timeout: options.timeout,
38606
+ connectionTimeout: options.connectionTimeout,
38106
38607
  cancelSignal: cancelSignal,
38107
38608
  onProgress: callbacks.onProgress
38108
38609
  }).then(function (data) {
@@ -38119,6 +38620,7 @@ function initSegmentLoader(url, segment, options, cancelSignal, callbacks) {
38119
38620
  },
38120
38621
  responseType: "arraybuffer",
38121
38622
  timeout: options.timeout,
38623
+ connectionTimeout: options.connectionTimeout,
38122
38624
  cancelSignal: cancelSignal,
38123
38625
  onProgress: callbacks.onProgress
38124
38626
  });
@@ -38129,6 +38631,7 @@ function initSegmentLoader(url, segment, options, cancelSignal, callbacks) {
38129
38631
  },
38130
38632
  responseType: "arraybuffer",
38131
38633
  timeout: options.timeout,
38634
+ connectionTimeout: options.connectionTimeout,
38132
38635
  cancelSignal: cancelSignal,
38133
38636
  onProgress: callbacks.onProgress
38134
38637
  });
@@ -38342,6 +38845,7 @@ function segment_loader_regularSegmentLoader(url, context, lowLatencyMode, optio
38342
38845
  Range: byteRange(segment.range)
38343
38846
  } : undefined,
38344
38847
  timeout: options.timeout,
38848
+ connectionTimeout: options.connectionTimeout,
38345
38849
  cancelSignal: cancelSignal,
38346
38850
  onProgress: callbacks.onProgress
38347
38851
  }).then(function (data) {
@@ -39232,6 +39736,7 @@ function generateTextTrackLoader(_ref) {
39232
39736
  Range: byteRange(range)
39233
39737
  } : null,
39234
39738
  timeout: options.timeout,
39739
+ connectionTimeout: options.connectionTimeout,
39235
39740
  onProgress: callbacks.onProgress,
39236
39741
  cancelSignal: cancelSignal
39237
39742
  }).then(function (data) {
@@ -39248,6 +39753,7 @@ function generateTextTrackLoader(_ref) {
39248
39753
  Range: byteRange(range)
39249
39754
  } : null,
39250
39755
  timeout: options.timeout,
39756
+ connectionTimeout: options.connectionTimeout,
39251
39757
  onProgress: callbacks.onProgress,
39252
39758
  cancelSignal: cancelSignal
39253
39759
  }).then(function (data) {
@@ -40445,6 +40951,7 @@ function disableVideoTracks(videoTracks) {
40445
40951
 
40446
40952
 
40447
40953
 
40954
+
40448
40955
  /**
40449
40956
  * `ContentIntializer` which will load contents by putting their URL in the
40450
40957
  * `src` attribute of the given HTMLMediaElement.
@@ -40600,8 +41107,15 @@ var DirectFileContentInitializer = /*#__PURE__*/function (_ContentInitializer) {
40600
41107
  src_log.debug("Init: Initial time calculated:", initTime);
40601
41108
  return initTime;
40602
41109
  };
40603
- performInitialSeekAndPlay(mediaElement, playbackObserver, initialTime, autoPlay, function (err) {
40604
- return _this3.trigger("warning", err);
41110
+ performInitialSeekAndPlay({
41111
+ mediaElement: mediaElement,
41112
+ playbackObserver: playbackObserver,
41113
+ startTime: initialTime,
41114
+ mustAutoPlay: autoPlay,
41115
+ onWarning: function onWarning(err) {
41116
+ return _this3.trigger("warning", err);
41117
+ },
41118
+ isDirectfile: true
40605
41119
  }, cancelSignal).autoPlayResult.then(function () {
40606
41120
  return getLoadedReference(playbackObserver, mediaElement, true, cancelSignal).onUpdate(function (isLoaded, stopListening) {
40607
41121
  if (isLoaded) {
@@ -40630,10 +41144,10 @@ var DirectFileContentInitializer = /*#__PURE__*/function (_ContentInitializer) {
40630
41144
  */
40631
41145
 
40632
41146
  function getDirectFileInitialTime(mediaElement, startAt) {
40633
- if (startAt == null) {
41147
+ if (is_null_or_undefined_isNullOrUndefined(startAt)) {
40634
41148
  return 0;
40635
41149
  }
40636
- if (startAt.position != null) {
41150
+ if (!is_null_or_undefined_isNullOrUndefined(startAt.position)) {
40637
41151
  return startAt.position;
40638
41152
  } else if (startAt.wallClockTime != null) {
40639
41153
  return startAt.wallClockTime;
@@ -40641,13 +41155,24 @@ function getDirectFileInitialTime(mediaElement, startAt) {
40641
41155
  return startAt.fromFirstPosition;
40642
41156
  }
40643
41157
  var duration = mediaElement.duration;
40644
- if (duration == null || !isFinite(duration)) {
40645
- src_log.warn("startAt.fromLastPosition set but no known duration, " + "beginning at 0.");
40646
- return 0;
40647
- }
40648
41158
  if (typeof startAt.fromLastPosition === "number") {
41159
+ if (is_null_or_undefined_isNullOrUndefined(duration) || !isFinite(duration)) {
41160
+ src_log.warn("startAt.fromLastPosition set but no known duration, " + "beginning at 0.");
41161
+ return 0;
41162
+ }
40649
41163
  return Math.max(0, duration + startAt.fromLastPosition);
41164
+ } else if (typeof startAt.fromLivePosition === "number") {
41165
+ var livePosition = mediaElement.seekable.length > 0 ? mediaElement.seekable.end(0) : duration;
41166
+ if (is_null_or_undefined_isNullOrUndefined(livePosition)) {
41167
+ src_log.warn("startAt.fromLivePosition set but no known live position, " + "beginning at 0.");
41168
+ return 0;
41169
+ }
41170
+ return Math.max(0, livePosition + startAt.fromLivePosition);
40650
41171
  } else if (startAt.percentage != null) {
41172
+ if (is_null_or_undefined_isNullOrUndefined(duration) || !isFinite(duration)) {
41173
+ src_log.warn("startAt.percentage set but no known duration, " + "beginning at 0.");
41174
+ return 0;
41175
+ }
40651
41176
  var percentage = startAt.percentage;
40652
41177
  if (percentage >= 100) {
40653
41178
  return duration;
@@ -44604,12 +45129,9 @@ var serverCertificateHashesMap = new WeakMap();
44604
45129
  * @returns {Object|null}
44605
45130
  */
44606
45131
  function createPersistentSessionsStorage(keySystemOptions) {
44607
- if (is_null_or_undefined_isNullOrUndefined(keySystemOptions.persistentLicenseConfig)) {
44608
- return null;
44609
- }
44610
45132
  var persistentLicenseConfig = keySystemOptions.persistentLicenseConfig;
44611
- if (persistentLicenseConfig == null) {
44612
- throw new EncryptedMediaError("INVALID_KEY_SYSTEM", "No `persistentLicenseConfig` found for " + "persistent license.");
45133
+ if (is_null_or_undefined_isNullOrUndefined(persistentLicenseConfig)) {
45134
+ return null;
44613
45135
  }
44614
45136
  src_log.debug("DRM: Set the given license storage");
44615
45137
  return new PersistentSessionsStore(persistentLicenseConfig);
@@ -47138,7 +47660,7 @@ var NativeTextSegmentBuffer = /*#__PURE__*/function (_SegmentBuffer) {
47138
47660
  }
47139
47661
  this._buffered.insert(start, end);
47140
47662
  if (infos.inventoryInfos !== null) {
47141
- this._segmentInventory.insertChunk(infos.inventoryInfos);
47663
+ this._segmentInventory.insertChunk(infos.inventoryInfos, true);
47142
47664
  }
47143
47665
  } catch (err) {
47144
47666
  return Promise.reject(err);
@@ -50301,7 +50823,7 @@ var HTMLTextSegmentBuffer = /*#__PURE__*/function (_SegmentBuffer) {
50301
50823
  return;
50302
50824
  }
50303
50825
  if (infos.inventoryInfos !== null) {
50304
- this._segmentInventory.insertChunk(infos.inventoryInfos);
50826
+ this._segmentInventory.insertChunk(infos.inventoryInfos, true);
50305
50827
  }
50306
50828
  this._buffer.insert(cues, start, end);
50307
50829
  this._buffered.insert(start, end);
@@ -50714,10 +51236,11 @@ function applyFontSize(element, fontSize) {
50714
51236
  */
50715
51237
  function applyLineHeight(element, lineHeight) {
50716
51238
  var trimmedLineHeight = lineHeight.trim();
51239
+ var splittedLineHeight = trimmedLineHeight.split(" ");
50717
51240
  if (trimmedLineHeight === "auto") {
50718
51241
  return;
50719
51242
  }
50720
- var firstLineHeight = REGXP_LENGTH.exec(trimmedLineHeight[0]);
51243
+ var firstLineHeight = REGXP_LENGTH.exec(splittedLineHeight[0]);
50721
51244
  if (firstLineHeight === null) {
50722
51245
  return;
50723
51246
  }