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
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import isSeekingApproximate from "../../compat/is_seeking_approximate";
17
18
  import config from "../../config";
18
19
  import log from "../../log";
19
20
  import getMonotonicTimeStamp from "../../utils/monotonic_timestamp";
@@ -68,6 +69,14 @@ export default class PlaybackObserver {
68
69
  */
69
70
  private _lowLatencyMode : boolean;
70
71
 
72
+ /**
73
+ * If set, position which could not yet be seeked to as the HTMLMediaElement
74
+ * had a readyState of `0`.
75
+ * This position should be seeked to as soon as the HTMLMediaElement is able
76
+ * to handle it.
77
+ */
78
+ private _pendingSeek : number | null;
79
+
71
80
  /**
72
81
  * The RxPlayer usually wants to differientate when a seek was sourced from
73
82
  * the RxPlayer's internal logic vs when it was sourced from an outside
@@ -88,7 +97,7 @@ export default class PlaybackObserver {
88
97
  /**
89
98
  * Stores the last playback observation produced by the `PlaybackObserver`.:
90
99
  */
91
- private _observationRef : IReadOnlySharedReference<IPlaybackObservation>;
100
+ private _observationRef : SharedReference<IPlaybackObservation>;
92
101
 
93
102
  /**
94
103
  * `TaskCanceller` allowing to free all resources and stop producing playback
@@ -96,6 +105,22 @@ export default class PlaybackObserver {
96
105
  */
97
106
  private _canceller : TaskCanceller;
98
107
 
108
+ /**
109
+ * On some devices (right now only seen on Tizen), seeking through the
110
+ * `currentTime` property can lead to the browser re-seeking once the
111
+ * segments have been loaded to improve seeking performances (for
112
+ * example, by seeking right to an intra video frame).
113
+ * In that case, we risk being in a conflict with that behavior: if for
114
+ * example we encounter a small discontinuity at the position the browser
115
+ * seeks to, we will seek over it, the browser would seek back and so on.
116
+ *
117
+ * This variable allows to store the maximum known position we were seeking to
118
+ * so we can detect when the browser seeked back (to avoid performing another
119
+ * seek after that). When browsers seek back to a position behind a
120
+ * discontinuity, they are usually able to skip them without our help.
121
+ */
122
+ private _expectedSeekingPosition : number | null;
123
+
99
124
  /**
100
125
  * Create a new `PlaybackObserver`, which allows to produce new "playback
101
126
  * observations" on various media events and intervals.
@@ -113,6 +138,20 @@ export default class PlaybackObserver {
113
138
  this._lowLatencyMode = options.lowLatencyMode;
114
139
  this._canceller = new TaskCanceller();
115
140
  this._observationRef = this._createSharedReference();
141
+ this._expectedSeekingPosition = null;
142
+ this._pendingSeek = null;
143
+
144
+ const onLoadedMetadata = () => {
145
+ if (this._pendingSeek !== null) {
146
+ const positionToSeekTo = this._pendingSeek;
147
+ this._pendingSeek = null;
148
+ this._actuallySetCurrentTime(positionToSeekTo);
149
+ }
150
+ };
151
+ mediaElement.addEventListener("loadedmetadata", onLoadedMetadata);
152
+ this._canceller.signal.register(() => {
153
+ mediaElement.removeEventListener("loadedmetadata", onLoadedMetadata);
154
+ });
116
155
  }
117
156
 
118
157
  /**
@@ -167,9 +206,13 @@ export default class PlaybackObserver {
167
206
  * @param {number} time
168
207
  */
169
208
  public setCurrentTime(time: number) : void {
170
- this._internalSeeksIncoming.push(time);
171
- log.info("API: Seeking internally", time);
172
- this._mediaElement.currentTime = time;
209
+ if (this._mediaElement.readyState >= 1) {
210
+ this._actuallySetCurrentTime(time);
211
+ } else {
212
+ this._internalSeeksIncoming = [];
213
+ this._pendingSeek = time;
214
+ this._generateObservationForEvent("manual");
215
+ }
173
216
  }
174
217
 
175
218
  /**
@@ -251,112 +294,53 @@ export default class PlaybackObserver {
251
294
  return generateReadOnlyObserver(this, transform, this._canceller.signal);
252
295
  }
253
296
 
297
+ private _actuallySetCurrentTime(time: number) : void {
298
+ log.info("API: Seeking internally", time);
299
+ this._internalSeeksIncoming.push(time);
300
+ this._mediaElement.currentTime = time;
301
+ }
302
+
254
303
  /**
255
304
  * Creates the `IReadOnlySharedReference` that will generate playback
256
305
  * observations.
257
306
  * @returns {Object}
258
307
  */
259
- private _createSharedReference() : IReadOnlySharedReference<IPlaybackObservation> {
308
+ private _createSharedReference() : SharedReference<IPlaybackObservation> {
260
309
  if (this._observationRef !== undefined) {
261
310
  return this._observationRef;
262
311
  }
263
312
 
264
- let lastObservation : IPlaybackObservation | null;
265
313
  const { SAMPLING_INTERVAL_MEDIASOURCE,
266
314
  SAMPLING_INTERVAL_LOW_LATENCY,
267
315
  SAMPLING_INTERVAL_NO_MEDIASOURCE } = config.getCurrent();
268
-
269
- const getCurrentObservation = (
270
- event : IPlaybackObserverEventType
271
- ) : IPlaybackObservation => {
272
- let tmpEvt: IPlaybackObserverEventType = event;
273
- let startedInternalSeekTime : number | undefined;
274
- if (tmpEvt === "seeking" && this._internalSeeksIncoming.length > 0) {
275
- tmpEvt = "internal-seeking";
276
- startedInternalSeekTime = this._internalSeeksIncoming.shift();
277
- }
278
- const _lastObservation = lastObservation ?? this._generateInitialObservation();
279
- const mediaTimings = getMediaInfos(this._mediaElement,
280
- tmpEvt,
281
- this._withMediaSource);
282
- let pendingInternalSeek : number | null = null;
283
- if (mediaTimings.seeking) {
284
- if (typeof startedInternalSeekTime === "number") {
285
- pendingInternalSeek = startedInternalSeekTime;
286
- } else if (_lastObservation.pendingInternalSeek !== null && event !== "seeking") {
287
- pendingInternalSeek = _lastObservation.pendingInternalSeek;
288
- }
289
- }
290
- const rebufferingStatus = getRebufferingStatus(
291
- _lastObservation,
292
- mediaTimings,
293
- { lowLatencyMode: this._lowLatencyMode,
294
- withMediaSource: this._withMediaSource });
295
-
296
- const freezingStatus = getFreezingStatus(_lastObservation, mediaTimings);
297
- const timings = objectAssign(
298
- {},
299
- { rebuffering: rebufferingStatus,
300
- freezing: freezingStatus,
301
- pendingInternalSeek },
302
- mediaTimings);
303
- if (log.hasLevel("DEBUG")) {
304
- log.debug("API: current media element state tick",
305
- "event", timings.event,
306
- "position", timings.position,
307
- "seeking", timings.seeking,
308
- "internalSeek", timings.pendingInternalSeek,
309
- "rebuffering", timings.rebuffering !== null,
310
- "freezing", timings.freezing !== null,
311
- "ended", timings.ended,
312
- "paused", timings.paused,
313
- "playbackRate", timings.playbackRate,
314
- "readyState", timings.readyState);
315
- }
316
- return timings;
317
- };
318
-
319
- const returnedSharedReference = new SharedReference(getCurrentObservation("init"),
320
- this._canceller.signal);
321
-
322
- const generateObservationForEvent = (event : IPlaybackObserverEventType) => {
323
- const newObservation = getCurrentObservation(event);
324
- if (log.hasLevel("DEBUG")) {
325
- log.debug("API: current playback timeline:\n" +
326
- prettyPrintBuffered(newObservation.buffered,
327
- newObservation.position),
328
- `\n${event}`);
329
- }
330
- lastObservation = newObservation;
331
- returnedSharedReference.setValue(newObservation);
332
- };
333
-
316
+ const returnedSharedReference = new SharedReference(
317
+ this._getCurrentObservation("init"),
318
+ this._canceller.signal
319
+ );
334
320
  const interval = this._lowLatencyMode ? SAMPLING_INTERVAL_LOW_LATENCY :
335
321
  this._withMediaSource ? SAMPLING_INTERVAL_MEDIASOURCE :
336
322
  SAMPLING_INTERVAL_NO_MEDIASOURCE;
323
+ const onInterval = () => {
324
+ this._generateObservationForEvent("timeupdate");
325
+ };
337
326
  let intervalId = setInterval(onInterval, interval);
338
327
  const removeEventListeners = SCANNED_MEDIA_ELEMENTS_EVENTS.map((eventName) => {
339
- this._mediaElement.addEventListener(eventName, onMediaEvent);
340
- function onMediaEvent() {
328
+ const onMediaEvent = () => {
341
329
  restartInterval();
342
- generateObservationForEvent(eventName);
343
- }
330
+ this._generateObservationForEvent(eventName);
331
+ };
332
+ this._mediaElement.addEventListener(eventName, onMediaEvent);
344
333
  return () => {
345
334
  this._mediaElement.removeEventListener(eventName, onMediaEvent);
346
335
  };
347
336
  });
348
-
349
337
  this._canceller.signal.register(() => {
350
338
  clearInterval(intervalId);
351
339
  removeEventListeners.forEach(cb => cb());
352
340
  returnedSharedReference.finish();
353
341
  });
354
-
355
342
  return returnedSharedReference;
356
343
 
357
- function onInterval() {
358
- generateObservationForEvent("timeupdate");
359
- }
360
344
 
361
345
  function restartInterval() {
362
346
  clearInterval(intervalId);
@@ -364,20 +348,123 @@ export default class PlaybackObserver {
364
348
  }
365
349
  }
366
350
 
367
- private _generateInitialObservation() : IPlaybackObservation {
368
- return objectAssign(getMediaInfos(this._mediaElement,
369
- "init",
370
- this._withMediaSource),
371
- { rebuffering: null,
372
- freezing: null,
373
- pendingInternalSeek: null });
351
+ private _getCurrentObservation(
352
+ event : IPlaybackObserverEventType
353
+ ) : IPlaybackObservation {
354
+ /** Actual event emitted through an observation. */
355
+ let tmpEvt: IPlaybackObserverEventType = event;
356
+
357
+ // NOTE: `this._observationRef` may be `undefined` because we might here be
358
+ // called in the constructor when that property is not yet set.
359
+ const previousObservation = this._observationRef === undefined ?
360
+ getInitialObservation(this._mediaElement, this._withMediaSource) :
361
+ this._observationRef.getValue();
362
+
363
+ /**
364
+ * If `true`, there is a seek operation ongoing but it was done from the
365
+ * `PlaybackObserver`'s `setCurrentTime` method, not from external code.
366
+ */
367
+ let isInternalSeeking = false;
368
+
369
+ /** If set, the position for which we plan to seek to as soon as possible. */
370
+ let pendingPosition: number | null = this._pendingSeek;
371
+
372
+ /** Initially-polled playback observation, before adjustments. */
373
+ const mediaTimings = getMediaInfos(this._mediaElement, this._withMediaSource);
374
+
375
+ if (tmpEvt === "seeking") {
376
+ // We just began seeking.
377
+ // Let's find out if the seek is internal or external and handle approximate
378
+ // seeking
379
+ if (this._internalSeeksIncoming.length > 0) {
380
+ isInternalSeeking = true;
381
+ tmpEvt = "internal-seeking";
382
+ const startedInternalSeekTime = this._internalSeeksIncoming.shift();
383
+ this._expectedSeekingPosition = isSeekingApproximate ?
384
+ Math.max(mediaTimings.position, startedInternalSeekTime ?? 0) :
385
+ mediaTimings.position;
386
+ } else {
387
+ this._expectedSeekingPosition = mediaTimings.position;
388
+ }
389
+ } else if (mediaTimings.seeking) {
390
+ // we're still seeking, this time without a "seeking" event so it's an
391
+ // already handled one, keep track of the last wanted position we wanted
392
+ // to seek to, to work-around devices re-seeking silently.
393
+ this._expectedSeekingPosition = Math.max(mediaTimings.position,
394
+ this._expectedSeekingPosition ?? 0);
395
+ } else if (isSeekingApproximate &&
396
+ this._expectedSeekingPosition !== null &&
397
+ mediaTimings.position < this._expectedSeekingPosition)
398
+ {
399
+ // We're on a target with aproximate seeking, we're not seeking anymore, but
400
+ // we're not yet at the expected seeking position.
401
+ // Signal to the rest of the application that the intented position is not
402
+ // the current position but the one contained in `this._expectedSeekingPosition`
403
+ pendingPosition = this._expectedSeekingPosition;
404
+ } else {
405
+ this._expectedSeekingPosition = null;
406
+ }
407
+
408
+ if (mediaTimings.seeking &&
409
+ previousObservation.seeking === SeekingState.Internal &&
410
+ event !== "seeking")
411
+ {
412
+ isInternalSeeking = true;
413
+ }
414
+ const rebufferingStatus = getRebufferingStatus(
415
+ previousObservation,
416
+ mediaTimings,
417
+ tmpEvt,
418
+ { lowLatencyMode: this._lowLatencyMode,
419
+ withMediaSource: this._withMediaSource });
420
+
421
+ const freezingStatus = getFreezingStatus(previousObservation, mediaTimings, tmpEvt);
422
+
423
+ const seeking = isInternalSeeking ? SeekingState.Internal :
424
+ mediaTimings.seeking ? SeekingState.External :
425
+ SeekingState.None;
426
+ const timings: IPlaybackObservation = objectAssign(
427
+ {},
428
+ mediaTimings,
429
+ { position: new ObservationPosition(mediaTimings.position, pendingPosition),
430
+ event: tmpEvt,
431
+ seeking,
432
+ rebuffering: rebufferingStatus,
433
+ freezing: freezingStatus });
434
+ if (log.hasLevel("DEBUG")) {
435
+ log.debug("API: current media element state tick",
436
+ "event", timings.event,
437
+ "position", timings.position.getPolled(),
438
+ "seeking", timings.seeking,
439
+ "internalSeek", isInternalSeeking,
440
+ "rebuffering", timings.rebuffering !== null,
441
+ "freezing", timings.freezing !== null,
442
+ "ended", timings.ended,
443
+ "paused", timings.paused,
444
+ "playbackRate", timings.playbackRate,
445
+ "readyState", timings.readyState);
446
+ }
447
+ return timings;
448
+ }
449
+
450
+ private _generateObservationForEvent(event : IPlaybackObserverEventType): void {
451
+ const newObservation = this._getCurrentObservation(event);
452
+ if (log.hasLevel("DEBUG")) {
453
+ log.debug("API: current playback timeline:\n" +
454
+ prettyPrintBuffered(newObservation.buffered,
455
+ newObservation.position.getPolled()),
456
+ `\n${event}`);
457
+ }
458
+ this._observationRef.setValue(newObservation);
374
459
  }
375
460
  }
376
461
 
377
462
  /** "Event" that triggered the playback observation. */
378
463
  export type IPlaybackObserverEventType =
379
464
  /** First playback observation automatically emitted. */
380
- "init" | // set once on first emit
465
+ "init" |
466
+ /** Observation manually forced by the PlaybackObserver. */
467
+ "manual" |
381
468
  /** Regularly emitted playback observation when no event happened in a long time. */
382
469
  "timeupdate" |
383
470
  /** On the HTML5 event with the same name */
@@ -439,8 +526,19 @@ interface IMediaInfos {
439
526
  readyState : number;
440
527
  /** Current `seeking` value on the mediaElement. */
441
528
  seeking : boolean;
442
- /** Event that triggered this playback observation. */
443
- event : IPlaybackObserverEventType;
529
+ }
530
+
531
+ /** Categorize a pending seek operation. */
532
+ export const enum SeekingState {
533
+ /** We're not currently seeking. */
534
+ None,
535
+ /**
536
+ * We're currently seeking due to an internal logic of the RxPlayer (e.g.
537
+ * discontinuity skipping).
538
+ */
539
+ Internal,
540
+ /** We're currently seeking due to a regular seek wanted by the application. */
541
+ External,
444
542
  }
445
543
 
446
544
  /**
@@ -483,7 +581,16 @@ export interface IFreezingStatus {
483
581
  }
484
582
 
485
583
  /** Information emitted on each playback observation. */
486
- export interface IPlaybackObservation extends IMediaInfos {
584
+ export interface IPlaybackObservation extends Omit<IMediaInfos, "position" | "seeking"> {
585
+ /** Event that triggered this playback observation. */
586
+ event : IPlaybackObserverEventType;
587
+ /** Current seeking state. */
588
+ seeking : SeekingState;
589
+ /**
590
+ * Information on the current position being played, the position for which
591
+ * media is wanted etc.
592
+ */
593
+ position : IObservationPosition;
487
594
  /**
488
595
  * Set if the player is short on audio and/or video media data and is a such,
489
596
  * rebuffering.
@@ -498,11 +605,103 @@ export interface IPlaybackObservation extends IMediaInfos {
498
605
  * `null` if the player is not frozen.
499
606
  */
500
607
  freezing : IFreezingStatus | null;
608
+ }
609
+
610
+ export type IObservationPosition = ObservationPosition;
611
+
612
+ class ObservationPosition {
613
+ /**
614
+ * Known position at the time the Observation was emitted, in seconds.
615
+ *
616
+ * Note that it might have changed since. If you want truly precize
617
+ * information, you should recuperate it from the HTMLMediaElement directly
618
+ * through another mean.
619
+ */
620
+ private _last: number;
621
+ /**
622
+ * Actually wanted position in seconds that is not yet reached.
623
+ *
624
+ * This might for example be set to the initial position when the content is
625
+ * loading (and thus potentially at a `0` position) but which will be seeked
626
+ * to a given position once possible. It may also be the position of a seek
627
+ * that has not been properly accounted for by the current device.
628
+ */
629
+ private _wanted: number | null;
630
+ constructor(last: number, wanted: number | null) {
631
+ this._last = last;
632
+ this._wanted = wanted;
633
+ }
634
+
501
635
  /**
502
- * If `true`, an "internal seek" (a seeking operation triggered by the
503
- * RxPlayer code) is currently pending.
636
+ * Returns the playback position actually observed on the media element at
637
+ * the time the playback observation was made.
638
+ *
639
+ * Note that it may be different than the position for which media data is
640
+ * wanted in rare scenarios where the goal position is not yet set on the
641
+ * media element.
642
+ *
643
+ * You should use this value when you want to obtain the actual position set
644
+ * on the media element for browser compatibility purposes. Note that this
645
+ * position was calculated at observation time, it might thus not be
646
+ * up-to-date if what you want is milliseconds-accuracy.
647
+ *
648
+ * If what you want is the actual position which the player is intended to
649
+ * play, you should rely on `getWanted` instead`.
650
+ * @returns {number}
504
651
  */
505
- pendingInternalSeek : number | null;
652
+ public getPolled(): number {
653
+ return this._last;
654
+ }
655
+
656
+ /**
657
+ * Returns the position which the player should consider to load media data
658
+ * at the time the observation was made.
659
+ *
660
+ * It can be different than the value returned by `getPolled` in rare
661
+ * scenarios:
662
+ *
663
+ * - When the initial position has not been set yet.
664
+ *
665
+ * - When the current device do not let the RxPlayer peform precize seeks,
666
+ * usually for perfomance reasons by seeking to a previous IDR frame
667
+ * instead (for now only Tizen may be like this), in which case we
668
+ * prefer to generally rely on the position wanted by the player (this
669
+ * e.g. prevents issues where the RxPlayer logic and the device are
670
+ * seeking back and forth in a loop).
671
+ *
672
+ * - When a wanted position has been "forced" (@see forceWantedPosition).
673
+ * @returns {number}
674
+ */
675
+ public getWanted(): number {
676
+ return this._wanted ?? this._last;
677
+ }
678
+
679
+ /**
680
+ * Method to call if you want to overwrite the currently wanted position.
681
+ * @param {number} pos
682
+ */
683
+ public forceWantedPosition(pos: number): void {
684
+ this._wanted = pos;
685
+ }
686
+
687
+ /**
688
+ * Returns `true` when the position wanted returned by `getWanted` and the
689
+ * actual position returned by `getPolled` may be different, meaning that
690
+ * we're currently not at the position we want to reach.
691
+ *
692
+ * This is a relatively rare situation which only happens when either the
693
+ * initial seek has not yet been performed. on specific targets where the
694
+ * seeking behavior is a little broken (@see getWanted) or when the wanted
695
+ * position has been forced (@see forceWantedPosition).
696
+ *
697
+ * In those situations, you might temporarily refrain from acting upon the
698
+ * actual current media position, as it may change soon.
699
+ *
700
+ * @returns {boolean}
701
+ */
702
+ public isAwaitingFuturePosition(): boolean {
703
+ return this._wanted !== null;
704
+ }
506
705
  }
507
706
 
508
707
  /**
@@ -640,12 +839,10 @@ function hasLoadedUntilTheEnd(
640
839
  /**
641
840
  * Get basic playback information.
642
841
  * @param {HTMLMediaElement} mediaElement
643
- * @param {string} event
644
842
  * @returns {Object}
645
843
  */
646
844
  function getMediaInfos(
647
845
  mediaElement : HTMLMediaElement,
648
- event : IPlaybackObserverEventType,
649
846
  withMediaSource : boolean
650
847
  ) : IMediaInfos {
651
848
  const { buffered,
@@ -682,8 +879,7 @@ function getMediaInfos(
682
879
  paused,
683
880
  playbackRate,
684
881
  readyState,
685
- seeking,
686
- event };
882
+ seeking };
687
883
  }
688
884
 
689
885
  /**
@@ -695,18 +891,19 @@ function getMediaInfos(
695
891
  * @param {Object} currentInfo - Current set of basic information on the
696
892
  * `HTMLMediaElement`. This does not need every single property from a regular
697
893
  * playback observation.
894
+ * @param {string} currentEvt
698
895
  * @param {Object} options
699
896
  * @returns {Object|null}
700
897
  */
701
898
  function getRebufferingStatus(
702
899
  prevObservation : IPlaybackObservation,
703
900
  currentInfo : IMediaInfos,
901
+ currentEvt : IPlaybackObserverEventType,
704
902
  { withMediaSource, lowLatencyMode } : IPlaybackObserverOptions
705
903
  ) : IRebufferingStatus | null {
706
904
 
707
905
  const { REBUFFERING_GAP } = config.getCurrent();
708
- const { event: currentEvt,
709
- position: currentTime,
906
+ const { position: currentTime,
710
907
  bufferGap,
711
908
  currentRange,
712
909
  duration,
@@ -777,7 +974,7 @@ function getRebufferingStatus(
777
974
  (
778
975
  !paused &&
779
976
  currentEvt === "timeupdate" && prevEvt === "timeupdate" &&
780
- currentTime === prevTime
977
+ currentTime === prevTime.getPolled()
781
978
  ) ||
782
979
  (
783
980
  currentEvt === "seeking" && (
@@ -790,7 +987,7 @@ function getRebufferingStatus(
790
987
  } else if (
791
988
  prevRebuffering !== null &&
792
989
  (
793
- (currentEvt !== "seeking" && currentTime !== prevTime) ||
990
+ (currentEvt !== "seeking" && currentTime !== prevTime.getPolled()) ||
794
991
  currentEvt === "canplay" ||
795
992
  (bufferGap === undefined && readyState >= 3) ||
796
993
  (
@@ -840,11 +1037,13 @@ function getRebufferingStatus(
840
1037
  * `null` if not.
841
1038
  * @param {Object} prevObservation
842
1039
  * @param {Object} currentInfo
1040
+ * @param {string} currentEvt
843
1041
  * @returns {Object|null}
844
1042
  */
845
1043
  function getFreezingStatus(
846
1044
  prevObservation : IPlaybackObservation,
847
- currentInfo : IMediaInfos
1045
+ currentInfo : IMediaInfos,
1046
+ currentEvt : IPlaybackObserverEventType
848
1047
  ) : IFreezingStatus | null {
849
1048
  const { MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING } = config.getCurrent();
850
1049
  if (prevObservation.freezing) {
@@ -852,21 +1051,21 @@ function getFreezingStatus(
852
1051
  currentInfo.paused ||
853
1052
  currentInfo.readyState === 0 ||
854
1053
  currentInfo.playbackRate === 0 ||
855
- prevObservation.position !== currentInfo.position)
1054
+ prevObservation.position.getPolled() !== currentInfo.position)
856
1055
  {
857
1056
  return null; // Quit freezing status
858
1057
  }
859
1058
  return prevObservation.freezing; // Stay in it
860
1059
  }
861
1060
 
862
- return currentInfo.event === "timeupdate" &&
1061
+ return currentEvt === "timeupdate" &&
863
1062
  currentInfo.bufferGap !== undefined &&
864
1063
  currentInfo.bufferGap > MINIMUM_BUFFER_AMOUNT_BEFORE_FREEZING &&
865
1064
  !currentInfo.ended &&
866
1065
  !currentInfo.paused &&
867
1066
  currentInfo.readyState >= 1 &&
868
1067
  currentInfo.playbackRate !== 0 &&
869
- currentInfo.position === prevObservation.position ?
1068
+ currentInfo.position === prevObservation.position.getPolled() ?
870
1069
  { timestamp: getMonotonicTimeStamp() } :
871
1070
  null;
872
1071
  }
@@ -999,3 +1198,24 @@ function generateReadOnlyObserver<TSource, TDest>(
999
1198
  },
1000
1199
  };
1001
1200
  }
1201
+
1202
+ /**
1203
+ * Generate the initial playback observation for when no event has yet been
1204
+ * emitted to lead to one.
1205
+ * @param {HTMLMediaElement} mediaElement
1206
+ * @param {boolean} withMediaSource
1207
+ * @returns {Object}
1208
+ */
1209
+ function getInitialObservation(
1210
+ mediaElement: HTMLMediaElement,
1211
+ withMediaSource: boolean
1212
+ ) : IPlaybackObservation {
1213
+ const mediaTimings = getMediaInfos(mediaElement, withMediaSource);
1214
+ return objectAssign(mediaTimings,
1215
+ { rebuffering: null,
1216
+ event: "init",
1217
+ seeking: SeekingState.None,
1218
+ position: { last: mediaTimings.position,
1219
+ pending: undefined },
1220
+ freezing: null });
1221
+ }