@amazon/vinyl 3.0.1 → 3.2.0

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 (268) hide show
  1. package/dist/index.cjs +1103 -1042
  2. package/dist/index.cjs.map +4 -4
  3. package/dist/index.js +810 -739
  4. package/dist/index.js.map +4 -4
  5. package/dist/test/benchmark.js.map +2 -2
  6. package/dist/test/integ.es5.js +394 -388
  7. package/dist/test/integ.js +2626 -2032
  8. package/dist/test/integ.js.map +4 -4
  9. package/dist/test/jasmine.css +50 -3
  10. package/dist/test/jasmineHtml.es5.js +195 -155
  11. package/dist/test/jasmineHtml.js +2938 -1833
  12. package/dist/test/jasmineHtml.js.map +3 -3
  13. package/dist/types/current/ad/AdControllerImpl.d.ts.map +1 -1
  14. package/dist/types/current/ad/AdControllerImpl.js +4 -1
  15. package/dist/types/current/ad/discoverHlsInterstitials.d.ts.map +1 -1
  16. package/dist/types/current/ad/discoverHlsInterstitials.js +2 -2
  17. package/dist/types/current/drm/DrmControllerImpl.d.ts +19 -1
  18. package/dist/types/current/drm/DrmControllerImpl.d.ts.map +1 -1
  19. package/dist/types/current/drm/DrmControllerImpl.js +101 -58
  20. package/dist/types/current/drm/licenseProvider/defaultLicenseProvider.d.ts.map +1 -1
  21. package/dist/types/current/drm/licenseProvider/defaultLicenseProvider.js +2 -2
  22. package/dist/types/current/index.d.ts +3 -6
  23. package/dist/types/current/index.d.ts.map +1 -1
  24. package/dist/types/current/index.js +3 -6
  25. package/dist/types/current/playback/PlaybackControllerImpl.d.ts +15 -0
  26. package/dist/types/current/playback/PlaybackControllerImpl.d.ts.map +1 -1
  27. package/dist/types/current/playback/PlaybackControllerImpl.js +100 -9
  28. package/dist/types/current/playback/ReadonlyPlaybackController.d.ts +27 -1
  29. package/dist/types/current/playback/ReadonlyPlaybackController.d.ts.map +1 -1
  30. package/dist/types/current/playback/ReadonlyPlaybackController.js +16 -0
  31. package/dist/types/current/playback/createStallDetector.d.ts +43 -0
  32. package/dist/types/current/playback/createStallDetector.d.ts.map +1 -0
  33. package/dist/types/current/playback/createStallDetector.js +101 -0
  34. package/dist/types/current/playback/createStallMonitor.d.ts +45 -0
  35. package/dist/types/current/playback/createStallMonitor.d.ts.map +1 -0
  36. package/dist/types/current/playback/createStallMonitor.js +94 -0
  37. package/dist/types/current/streaming/AudioOptions.d.ts +27 -0
  38. package/dist/types/current/streaming/AudioOptions.d.ts.map +1 -1
  39. package/dist/types/current/streaming/AudioOptions.js +5 -1
  40. package/dist/types/current/streaming/ContentStream.d.ts +0 -5
  41. package/dist/types/current/streaming/ContentStream.d.ts.map +1 -1
  42. package/dist/types/current/streaming/ContentStream.js +0 -4
  43. package/dist/types/current/streaming/LoadMetric.d.ts +15 -1
  44. package/dist/types/current/streaming/LoadMetric.d.ts.map +1 -1
  45. package/dist/types/current/streaming/StreamingEventMap.d.ts +1 -5
  46. package/dist/types/current/streaming/StreamingEventMap.d.ts.map +1 -1
  47. package/dist/types/current/streaming/StreamingEventMap.js +0 -1
  48. package/dist/types/current/streaming/buffering/BufferingController.d.ts +0 -11
  49. package/dist/types/current/streaming/buffering/BufferingController.d.ts.map +1 -1
  50. package/dist/types/current/streaming/buffering/BufferingController.js +0 -13
  51. package/dist/types/current/streaming/createDefaultMediaTimelineTransformer.d.ts.map +1 -1
  52. package/dist/types/current/streaming/createDefaultMediaTimelineTransformer.js +13 -4
  53. package/dist/types/current/streaming/mediaTimelineFilter.d.ts +4 -2
  54. package/dist/types/current/streaming/mediaTimelineFilter.d.ts.map +1 -1
  55. package/dist/types/current/streaming/mediaTimelineFilter.js +23 -8
  56. package/dist/types/current/text/SidecarTextTrackLoader.d.ts.map +1 -1
  57. package/dist/types/current/text/SidecarTextTrackLoader.js +4 -4
  58. package/dist/types/current/text/TextTrack.d.ts.map +1 -1
  59. package/dist/types/current/track/TrackController.d.ts.map +1 -1
  60. package/dist/types/current/track/TrackController.js +8 -2
  61. package/dist/types/current/track/createSegmentDataProvider.d.ts.map +1 -1
  62. package/dist/types/current/track/createSegmentDataProvider.js +6 -3
  63. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  64. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.d.ts.map +1 -1
  65. package/dist/types/current/track/dash/DashMediaQualityMetadataResolver.js +13 -8
  66. package/dist/types/current/track/dash/createDashFactories.d.ts +1 -1
  67. package/dist/types/current/track/dash/timeline/DashRepresentationSegmentProvider.d.ts.map +1 -1
  68. package/dist/types/current/track/dash/timeline/DashRepresentationSegmentProvider.js +71 -3
  69. package/dist/types/current/track/dash/urlDashManifestProvider.js +2 -2
  70. package/dist/types/current/track/dash/util/mpd.d.ts +6 -0
  71. package/dist/types/current/track/dash/util/mpd.d.ts.map +1 -1
  72. package/dist/types/current/track/dash/util/mpd.js +24 -3
  73. package/dist/types/current/track/filters/resourceTypeFilter.d.ts +4 -0
  74. package/dist/types/current/track/filters/resourceTypeFilter.d.ts.map +1 -1
  75. package/dist/types/current/track/filters/resourceTypeFilter.js +4 -0
  76. package/dist/types/current/track/filters/sampleRateFilter.d.ts +25 -7
  77. package/dist/types/current/track/filters/sampleRateFilter.d.ts.map +1 -1
  78. package/dist/types/current/track/filters/sampleRateFilter.js +52 -24
  79. package/dist/types/current/track/hls/createHlsFactories.d.ts +1 -1
  80. package/dist/types/current/track/hls/createUrlHlsManifestProvider.d.ts.map +1 -1
  81. package/dist/types/current/track/hls/createUrlHlsManifestProvider.js +3 -3
  82. package/dist/types/current/track/mse/MseTrack.d.ts +0 -17
  83. package/dist/types/current/track/mse/MseTrack.d.ts.map +1 -1
  84. package/dist/types/current/track/mse/MseTrack.js +1 -45
  85. package/dist/types/current/tsconfig.tsbuildinfo +1 -1
  86. package/dist/types/current/util/media/mimeType.d.ts +8 -0
  87. package/dist/types/current/util/media/mimeType.d.ts.map +1 -0
  88. package/dist/types/current/util/media/mimeType.js +13 -0
  89. package/dist/types/current/vinyl/VinylPlayer.d.ts +5 -0
  90. package/dist/types/current/vinyl/VinylPlayer.d.ts.map +1 -1
  91. package/dist/types/current/vinyl/VinylPlayer.js +23 -1
  92. package/dist/types/current/vinyl/createVinylFactories.d.ts +7 -16
  93. package/dist/types/current/vinyl/createVinylFactories.d.ts.map +1 -1
  94. package/dist/types/current/vinyl/createVinylFactories.js +2 -12
  95. package/dist/types/ts3.7/drm/DrmControllerImpl.d.ts +19 -1
  96. package/dist/types/ts3.7/index.d.ts +3 -6
  97. package/dist/types/ts3.7/playback/PlaybackControllerImpl.d.ts +15 -0
  98. package/dist/types/ts3.7/playback/ReadonlyPlaybackController.d.ts +28 -0
  99. package/dist/types/ts3.7/playback/createStallDetector.d.ts +43 -0
  100. package/dist/types/ts3.7/playback/createStallMonitor.d.ts +45 -0
  101. package/dist/types/ts3.7/streaming/AudioOptions.d.ts +27 -0
  102. package/dist/types/ts3.7/streaming/ContentStream.d.ts +0 -5
  103. package/dist/types/ts3.7/streaming/LoadMetric.d.ts +15 -1
  104. package/dist/types/ts3.7/streaming/StreamingEventMap.d.ts +0 -5
  105. package/dist/types/ts3.7/streaming/buffering/BufferingController.d.ts +0 -11
  106. package/dist/types/ts3.7/streaming/mediaTimelineFilter.d.ts +4 -2
  107. package/dist/types/ts3.7/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  108. package/dist/types/ts3.7/track/dash/createDashFactories.d.ts +1 -1
  109. package/dist/types/ts3.7/track/dash/util/mpd.d.ts +6 -0
  110. package/dist/types/ts3.7/track/filters/resourceTypeFilter.d.ts +4 -0
  111. package/dist/types/ts3.7/track/filters/sampleRateFilter.d.ts +25 -7
  112. package/dist/types/ts3.7/track/hls/createHlsFactories.d.ts +1 -1
  113. package/dist/types/ts3.7/track/mse/MseTrack.d.ts +0 -17
  114. package/dist/types/ts3.7/util/media/mimeType.d.ts +8 -0
  115. package/dist/types/ts3.7/vinyl/VinylPlayer.d.ts +5 -0
  116. package/dist/types/ts3.7/vinyl/createVinylFactories.d.ts +7 -16
  117. package/dist/types/ts4.1/drm/DrmControllerImpl.d.ts +19 -1
  118. package/dist/types/ts4.1/index.d.ts +3 -6
  119. package/dist/types/ts4.1/playback/PlaybackControllerImpl.d.ts +15 -0
  120. package/dist/types/ts4.1/playback/ReadonlyPlaybackController.d.ts +28 -0
  121. package/dist/types/ts4.1/playback/createStallDetector.d.ts +43 -0
  122. package/dist/types/ts4.1/playback/createStallMonitor.d.ts +45 -0
  123. package/dist/types/ts4.1/streaming/AudioOptions.d.ts +27 -0
  124. package/dist/types/ts4.1/streaming/ContentStream.d.ts +0 -5
  125. package/dist/types/ts4.1/streaming/LoadMetric.d.ts +15 -1
  126. package/dist/types/ts4.1/streaming/StreamingEventMap.d.ts +0 -5
  127. package/dist/types/ts4.1/streaming/buffering/BufferingController.d.ts +0 -11
  128. package/dist/types/ts4.1/streaming/mediaTimelineFilter.d.ts +4 -2
  129. package/dist/types/ts4.1/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  130. package/dist/types/ts4.1/track/dash/createDashFactories.d.ts +1 -1
  131. package/dist/types/ts4.1/track/dash/util/mpd.d.ts +6 -0
  132. package/dist/types/ts4.1/track/filters/resourceTypeFilter.d.ts +4 -0
  133. package/dist/types/ts4.1/track/filters/sampleRateFilter.d.ts +25 -7
  134. package/dist/types/ts4.1/track/hls/createHlsFactories.d.ts +1 -1
  135. package/dist/types/ts4.1/track/mse/MseTrack.d.ts +0 -17
  136. package/dist/types/ts4.1/util/media/mimeType.d.ts +8 -0
  137. package/dist/types/ts4.1/vinyl/VinylPlayer.d.ts +5 -0
  138. package/dist/types/ts4.1/vinyl/createVinylFactories.d.ts +7 -16
  139. package/dist/types/ts4.7/drm/DrmControllerImpl.d.ts +19 -1
  140. package/dist/types/ts4.7/index.d.ts +3 -6
  141. package/dist/types/ts4.7/playback/PlaybackControllerImpl.d.ts +15 -0
  142. package/dist/types/ts4.7/playback/ReadonlyPlaybackController.d.ts +28 -0
  143. package/dist/types/ts4.7/playback/createStallDetector.d.ts +43 -0
  144. package/dist/types/ts4.7/playback/createStallMonitor.d.ts +45 -0
  145. package/dist/types/ts4.7/streaming/AudioOptions.d.ts +27 -0
  146. package/dist/types/ts4.7/streaming/ContentStream.d.ts +0 -5
  147. package/dist/types/ts4.7/streaming/LoadMetric.d.ts +15 -1
  148. package/dist/types/ts4.7/streaming/StreamingEventMap.d.ts +0 -5
  149. package/dist/types/ts4.7/streaming/buffering/BufferingController.d.ts +0 -11
  150. package/dist/types/ts4.7/streaming/mediaTimelineFilter.d.ts +4 -2
  151. package/dist/types/ts4.7/track/dash/DashMediaQualityMetadataResolver.d.ts +10 -6
  152. package/dist/types/ts4.7/track/dash/createDashFactories.d.ts +1 -1
  153. package/dist/types/ts4.7/track/dash/util/mpd.d.ts +6 -0
  154. package/dist/types/ts4.7/track/filters/resourceTypeFilter.d.ts +4 -0
  155. package/dist/types/ts4.7/track/filters/sampleRateFilter.d.ts +25 -7
  156. package/dist/types/ts4.7/track/hls/createHlsFactories.d.ts +1 -1
  157. package/dist/types/ts4.7/track/mse/MseTrack.d.ts +0 -17
  158. package/dist/types/ts4.7/util/media/mimeType.d.ts +8 -0
  159. package/dist/types/ts4.7/vinyl/VinylPlayer.d.ts +5 -0
  160. package/dist/types/ts4.7/vinyl/createVinylFactories.d.ts +7 -16
  161. package/dist/unit/types/current/ad/AdControllerImpl.test.js +27 -1
  162. package/dist/unit/types/current/drm/DrmControllerImpl.test.js +146 -9
  163. package/dist/unit/types/current/index.d.ts +3 -4
  164. package/dist/unit/types/current/index.d.ts.map +1 -1
  165. package/dist/unit/types/current/index.js +3 -4
  166. package/dist/unit/types/current/playback/PlaybackControllerImpl.test.js +165 -0
  167. package/dist/unit/types/current/playback/createStallDetector.test.d.ts +2 -0
  168. package/dist/unit/types/current/playback/createStallDetector.test.d.ts.map +1 -0
  169. package/dist/unit/types/current/playback/createStallDetector.test.js +163 -0
  170. package/dist/unit/types/current/playback/createStallMonitor.test.d.ts +2 -0
  171. package/dist/unit/types/current/playback/createStallMonitor.test.d.ts.map +1 -0
  172. package/dist/unit/types/current/playback/createStallMonitor.test.js +125 -0
  173. package/dist/unit/types/current/streaming/ContentStream.test.js +0 -11
  174. package/dist/unit/types/current/streaming/MseTrack.test.js +49 -73
  175. package/dist/unit/types/current/streaming/abr/QualitySelectorImpl.test.js +1 -1
  176. package/dist/unit/types/current/streaming/buffering/BufferingController.test.js +0 -21
  177. package/dist/unit/types/current/streaming/createDefaultMediaTimelineTransformer.test.js +133 -0
  178. package/dist/unit/types/current/streaming/mediaTimelineFilter.test.js +60 -54
  179. package/dist/unit/types/current/track/TrackController.test.js +61 -1
  180. package/dist/unit/types/current/track/createSegmentDataProvider.test.js +18 -0
  181. package/dist/unit/types/current/track/dash/DashMediaQualityMetadataResolver.test.js +46 -14
  182. package/dist/unit/types/current/track/dash/createSegmentControllerFactory.test.js +1 -0
  183. package/dist/unit/types/current/track/dash/timeline/DashRepresentationSegmentProvider.test.js +114 -0
  184. package/dist/unit/types/current/track/dash/util/mpd.test.js +37 -0
  185. package/dist/unit/types/current/track/filters/resourceTypeFilter.test.js +7 -0
  186. package/dist/unit/types/current/track/filters/sampleRateFilter.test.js +211 -34
  187. package/dist/unit/types/current/track/source/SourceObjectTrack.test.js +1 -1
  188. package/dist/unit/types/current/tsconfig.tsbuildinfo +1 -1
  189. package/dist/unit/types/current/util/media/mimeType.test.d.ts +2 -0
  190. package/dist/unit/types/current/util/media/mimeType.test.d.ts.map +1 -0
  191. package/dist/unit/types/current/util/media/mimeType.test.js +22 -0
  192. package/dist/unit/types/current/vinyl/VinylPlayer.test.js +33 -2
  193. package/dist/unit/types/current/vinyl/createVinylFactories.test.js +2 -36
  194. package/dist/vinylTestUtil/index.js +6 -4
  195. package/dist/vinylTestUtil/index.js.map +2 -2
  196. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts +1 -0
  197. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.d.ts.map +1 -1
  198. package/dist/vinylTestUtil/types/current/assets/vinylTestAssets.js +1 -0
  199. package/dist/vinylTestUtil/types/current/media/FrequencyAnalyzer.d.ts.map +1 -1
  200. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.d.ts +0 -1
  201. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.d.ts.map +1 -1
  202. package/dist/vinylTestUtil/types/current/mock/streaming/MockContentStream.js +0 -1
  203. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  204. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.d.ts.map +1 -1
  205. package/dist/vinylTestUtil/types/current/mock/streaming/buffering/MockBufferingController.js +0 -1
  206. package/dist/vinylTestUtil/types/current/tsconfig.tsbuildinfo +1 -1
  207. package/dist/vinylTestUtil/types/current/util/playback/eventPromises.js +1 -1
  208. package/dist/vinylTestUtil/types/current/util/playback/expectTrackCanSeek.d.ts.map +1 -1
  209. package/dist/vinylTestUtil/types/current/util/playback/expectTrackCanSeek.js +9 -1
  210. package/dist/vinylTestUtil/types/ts3.7/assets/vinylTestAssets.d.ts +1 -0
  211. package/dist/vinylTestUtil/types/ts3.7/mock/streaming/MockContentStream.d.ts +0 -1
  212. package/dist/vinylTestUtil/types/ts3.7/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  213. package/dist/vinylTestUtil/types/ts4.1/assets/vinylTestAssets.d.ts +1 -0
  214. package/dist/vinylTestUtil/types/ts4.1/mock/streaming/MockContentStream.d.ts +0 -1
  215. package/dist/vinylTestUtil/types/ts4.1/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  216. package/dist/vinylTestUtil/types/ts4.7/assets/vinylTestAssets.d.ts +1 -0
  217. package/dist/vinylTestUtil/types/ts4.7/mock/streaming/MockContentStream.d.ts +0 -1
  218. package/dist/vinylTestUtil/types/ts4.7/mock/streaming/buffering/MockBufferingController.d.ts +0 -1
  219. package/docs/USAGE.md +29 -0
  220. package/package.json +11 -10
  221. package/dist/types/current/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  222. package/dist/types/current/patch/media/HtmlMediaElementPatch.d.ts.map +0 -1
  223. package/dist/types/current/patch/media/HtmlMediaElementPatch.js +0 -5
  224. package/dist/types/current/patch/media/MediaElementPatchOptions.d.ts +0 -19
  225. package/dist/types/current/patch/media/MediaElementPatchOptions.d.ts.map +0 -1
  226. package/dist/types/current/patch/media/MediaElementPatchOptions.js +0 -16
  227. package/dist/types/current/patch/media/patchMediaElement.d.ts +0 -9
  228. package/dist/types/current/patch/media/patchMediaElement.d.ts.map +0 -1
  229. package/dist/types/current/patch/media/patchMediaElement.js +0 -15
  230. package/dist/types/current/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  231. package/dist/types/current/patch/media/patches/createPreventStallsPatch.d.ts.map +0 -1
  232. package/dist/types/current/patch/media/patches/createPreventStallsPatch.js +0 -55
  233. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  234. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts.map +0 -1
  235. package/dist/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.js +0 -218
  236. package/dist/types/current/vinyl/VinylPatchOptions.d.ts +0 -10
  237. package/dist/types/current/vinyl/VinylPatchOptions.d.ts.map +0 -1
  238. package/dist/types/current/vinyl/VinylPatchOptions.js +0 -11
  239. package/dist/types/ts3.7/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  240. package/dist/types/ts3.7/patch/media/MediaElementPatchOptions.d.ts +0 -19
  241. package/dist/types/ts3.7/patch/media/patchMediaElement.d.ts +0 -9
  242. package/dist/types/ts3.7/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  243. package/dist/types/ts3.7/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  244. package/dist/types/ts3.7/vinyl/VinylPatchOptions.d.ts +0 -10
  245. package/dist/types/ts4.1/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  246. package/dist/types/ts4.1/patch/media/MediaElementPatchOptions.d.ts +0 -19
  247. package/dist/types/ts4.1/patch/media/patchMediaElement.d.ts +0 -9
  248. package/dist/types/ts4.1/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  249. package/dist/types/ts4.1/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  250. package/dist/types/ts4.1/vinyl/VinylPatchOptions.d.ts +0 -10
  251. package/dist/types/ts4.7/patch/media/HtmlMediaElementPatch.d.ts +0 -3
  252. package/dist/types/ts4.7/patch/media/MediaElementPatchOptions.d.ts +0 -19
  253. package/dist/types/ts4.7/patch/media/patchMediaElement.d.ts +0 -9
  254. package/dist/types/ts4.7/patch/media/patches/createPreventStallsPatch.d.ts +0 -17
  255. package/dist/types/ts4.7/patch/media/patches/createUnreliablePlaybackEventsPatch.d.ts +0 -26
  256. package/dist/types/ts4.7/vinyl/VinylPatchOptions.d.ts +0 -10
  257. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.d.ts +0 -2
  258. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.d.ts.map +0 -1
  259. package/dist/unit/types/current/patch/media/MediaElementPatchOptions.test.js +0 -17
  260. package/dist/unit/types/current/patch/media/patchMediaElement.test.d.ts +0 -2
  261. package/dist/unit/types/current/patch/media/patchMediaElement.test.d.ts.map +0 -1
  262. package/dist/unit/types/current/patch/media/patchMediaElement.test.js +0 -36
  263. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.d.ts +0 -2
  264. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.d.ts.map +0 -1
  265. package/dist/unit/types/current/patch/media/patches/createPreventStallsPatch.test.js +0 -93
  266. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.d.ts +0 -2
  267. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.d.ts.map +0 -1
  268. package/dist/unit/types/current/patch/media/patches/createUnreliablePlaybackEventsPatch.test.js +0 -423
@@ -480,6 +480,66 @@ describe('TrackControllerImpl', () => {
480
480
  });
481
481
  });
482
482
  });
483
+ describe('guards async ad continuations after dispose', () => {
484
+ it('does not dispatch trackEnded when disposed before the postroll resolves', async () => {
485
+ let resolvePostroll = () => { };
486
+ deps.adController.enterPostroll.and.returnValue(new Promise((res) => {
487
+ resolvePostroll = res;
488
+ }));
489
+ trackController.load(...createLoadOptionsList(2));
490
+ await clock.tick(); // activate the first track
491
+ const endedSpy = jasmine.createSpy('trackEnded');
492
+ trackController.on('trackEnded', endedSpy);
493
+ deps.playbackController.dispatch('ended', {}); // onEnded → enterPostroll pending
494
+ trackController.dispose();
495
+ disposed = true;
496
+ resolvePostroll(null); // .then guarded by interrupted()
497
+ await clock.tick();
498
+ expect(endedSpy).not.toHaveBeenCalled();
499
+ });
500
+ it('does not advance the queue when disposed within the trackEnded handler', async () => {
501
+ trackController.load(...createLoadOptionsList(2));
502
+ await clock.tick(); // activate the first track
503
+ trackController.on('trackEnded', () => {
504
+ trackController.dispose(); // interrupt before the queued next()
505
+ disposed = true;
506
+ });
507
+ const activatedSpy = jasmine.createSpy('trackActivated');
508
+ trackController.on('trackActivated', activatedSpy);
509
+ deps.playbackController.dispatch('ended', {});
510
+ await clock.tick();
511
+ // The queued next() is skipped: interrupted() is true in the microtask.
512
+ expect(activatedSpy).not.toHaveBeenCalled();
513
+ });
514
+ it('swallows a postroll rejection after dispose', async () => {
515
+ let rejectPostroll = () => { };
516
+ deps.adController.enterPostroll.and.returnValue(new Promise((_res, rej) => {
517
+ rejectPostroll = rej;
518
+ }));
519
+ trackController.load(...createLoadOptionsList(1));
520
+ await clock.tick();
521
+ deps.playbackController.dispatch('ended', {});
522
+ trackController.dispose();
523
+ disposed = true;
524
+ rejectPostroll(new Error('late')); // .catch guarded by interrupted()
525
+ await clock.tick();
526
+ expect(trackController.disposed).toBeTrue();
527
+ });
528
+ it('does not activate when disposed before the preroll rejects', async () => {
529
+ let rejectPreroll = () => { };
530
+ deps.adController.enterPreroll.and.returnValue(new Promise((_res, rej) => {
531
+ rejectPreroll = rej;
532
+ }));
533
+ const activatedSpy = jasmine.createSpy('trackActivated');
534
+ trackController.on('trackActivated', activatedSpy);
535
+ trackController.load(...createLoadOptionsList(1)); // activation deferred behind enterPreroll
536
+ trackController.dispose();
537
+ disposed = true;
538
+ rejectPreroll(new Error('late')); // .catch guarded by interrupted()
539
+ await clock.tick();
540
+ expect(activatedSpy).not.toHaveBeenCalled();
541
+ });
542
+ });
483
543
  describe('unload', () => {
484
544
  it('unloads the active track and clears the queue', () => {
485
545
  trackController.load(...createLoadOptionsList(3));
@@ -813,7 +873,7 @@ describe('TrackControllerImpl', () => {
813
873
  expect(() => trackController.reset()).not.toThrow();
814
874
  });
815
875
  });
816
- describe('reset', () => {
876
+ describe('reset (hard)', () => {
817
877
  it('delegates a hard reset to the current track', async () => {
818
878
  trackController.load(...createLoadOptionsList(1));
819
879
  await clock.tick();
@@ -208,6 +208,24 @@ describe('createSegmentDataProvider', () => {
208
208
  serviceId: 'example.com',
209
209
  }));
210
210
  });
211
+ it('does not report transfer entry when aborted before the metrics read', async () => {
212
+ const abort = new Abort();
213
+ const response = new Response(new ArrayBuffer(10));
214
+ spyOn(response, 'arrayBuffer').and.callFake(() => {
215
+ // Abort after the fetch resolves, before the metrics read.
216
+ abort.abort();
217
+ return Promise.resolve(new ArrayBuffer(10));
218
+ });
219
+ mockRequester.request.and.resolveTo(response);
220
+ const provider = createSegmentDataProvider(deps, {
221
+ url: 'https://example.com/seg0.mp4',
222
+ reportDownlinkMetrics: true,
223
+ });
224
+ const promise = provider(abort);
225
+ await clock.tick(2);
226
+ await promise;
227
+ expect(networkMetricsControllerRef.value.addDownlinkTransferEntry).not.toHaveBeenCalled();
228
+ });
211
229
  });
212
230
  describe('when reportDownlinkMetrics is false', () => {
213
231
  it('does not report transfer entry', async () => {
@@ -422,7 +422,7 @@ describe('getPeriodSortedBandwidths', () => {
422
422
  });
423
423
  });
424
424
  describe('estimatePeakBandwidth', () => {
425
- it('pairs proportionally when video has more qualities than audio', () => {
425
+ it('pairs each tier with the cheapest peer in its bucket', () => {
426
426
  // language=XML
427
427
  const m = parseDashManifest(`<?xml version="1.0" ?>
428
428
  <MPD minBufferTime="PT0S" profiles="" xmlns="urn:mpeg:dash:schema:mpd:2011">
@@ -441,20 +441,51 @@ describe('estimatePeakBandwidth', () => {
441
441
  </MPD>`);
442
442
  const as0 = m.MPD.Period[0].AdaptationSet[0];
443
443
  const as1 = m.MPD.Period[0].AdaptationSet[1];
444
- // video sorted: [4000, 3000, 2000, 1000], audio sorted: [200, 100]
445
- // v1 pos=0/3=0.00 → audio index round(0.00*1)=0 → 200. total=4200
444
+ // video sorted: [4000, 3000, 2000, 1000], audio sorted: [200, 100].
445
+ // Video's two audio buckets: v1,v2 → a1(200); v3,v4 → a2(100).
446
446
  expect(estimatePeakBandwidth(as0.Representation[0], 'video')).toBe(4200);
447
- // v2 pos=1/3=0.33 → audio index round(0.33*1)=0 → 200. total=3200
448
447
  expect(estimatePeakBandwidth(as0.Representation[1], 'video')).toBe(3200);
449
- // v3 pos=2/3=0.67 → audio index round(0.67*1)=1 → 100. total=2100
450
448
  expect(estimatePeakBandwidth(as0.Representation[2], 'video')).toBe(2100);
451
- // v4 pos=3/3=1.00 → audio index round(1.00*1)=1 → 100. total=1100
452
449
  expect(estimatePeakBandwidth(as0.Representation[3], 'video')).toBe(1100);
453
- // a1 pos=0/1=0 → video index round(0*3)=0 → 4000. total=4200
454
- expect(estimatePeakBandwidth(as1.Representation[0], 'audio')).toBe(4200);
455
- // a2 pos=1/1=1 → video index round(1*3)=3 → 1000. total=1100
450
+ // Audio's two video buckets: a1's bucket is v1,v2 so it pairs with the
451
+ // cheapest of those (v2=3000); a2's bucket is v3,v4 (cheapest v4=1000).
452
+ expect(estimatePeakBandwidth(as1.Representation[0], 'audio')).toBe(3200);
456
453
  expect(estimatePeakBandwidth(as1.Representation[1], 'audio')).toBe(1100);
457
454
  });
455
+ it('does not pin a small stream to its lowest tier across a finer peer', () => {
456
+ // 2 audio tiers alongside 10 video tiers: the top audio must stay
457
+ // affordable across the whole top half of video, not only at the very
458
+ // top. (Regression: it was priced with the single top video.)
459
+ // language=XML
460
+ const m = parseDashManifest(`<?xml version="1.0" ?>
461
+ <MPD minBufferTime="PT0S" profiles="" xmlns="urn:mpeg:dash:schema:mpd:2011">
462
+ <Period>
463
+ <AdaptationSet mimeType="video/mp4" codecs="avc1.640015">
464
+ <Representation bandwidth="10000" id="v1"/>
465
+ <Representation bandwidth="9000" id="v2"/>
466
+ <Representation bandwidth="8000" id="v3"/>
467
+ <Representation bandwidth="7000" id="v4"/>
468
+ <Representation bandwidth="6000" id="v5"/>
469
+ <Representation bandwidth="5000" id="v6"/>
470
+ <Representation bandwidth="4000" id="v7"/>
471
+ <Representation bandwidth="3000" id="v8"/>
472
+ <Representation bandwidth="2000" id="v9"/>
473
+ <Representation bandwidth="1000" id="v10"/>
474
+ </AdaptationSet>
475
+ <AdaptationSet mimeType="audio/mp4" codecs="mp4a.40.2">
476
+ <Representation bandwidth="200" id="a1"/>
477
+ <Representation bandwidth="100" id="a2"/>
478
+ </AdaptationSet>
479
+ </Period>
480
+ </MPD>`);
481
+ const audio = m.MPD.Period[0].AdaptationSet[1];
482
+ // Top audio's bucket is video[0..4]; it pairs with the cheapest of those
483
+ // (video[4]=6000), NOT video[0]=10000. So its total is 6200, keeping it
484
+ // affordable for the top half of video tiers.
485
+ expect(estimatePeakBandwidth(audio.Representation[0], 'audio')).toBe(6200);
486
+ // Bottom audio's bucket is video[5..9]; cheapest video[9]=1000 → 1100.
487
+ expect(estimatePeakBandwidth(audio.Representation[1], 'audio')).toBe(1100);
488
+ });
458
489
  it('returns bandwidth as-is for single content type periods', () => {
459
490
  // language=XML
460
491
  const m = parseDashManifest(`<?xml version="1.0" ?>
@@ -482,7 +513,7 @@ describe('estimatePeakBandwidth', () => {
482
513
  </MPD>`);
483
514
  expect(estimatePeakBandwidth(m.MPD.Period[0].AdaptationSet[0].Representation[0], 'text')).toBe(50000);
484
515
  });
485
- it('pairs proportionally with three content types', () => {
516
+ it('pairs with the cheapest peer bucket across three content types', () => {
486
517
  // language=XML
487
518
  const m = parseDashManifest(`<?xml version="1.0" ?>
488
519
  <MPD minBufferTime="PT0S" profiles="" xmlns="urn:mpeg:dash:schema:mpd:2011">
@@ -500,12 +531,13 @@ describe('estimatePeakBandwidth', () => {
500
531
  </AdaptationSet>
501
532
  </Period>
502
533
  </MPD>`);
503
- // v1 pos=0 → audio[0]=200, text[0]=10. total=2210
534
+ // v1 → cheapest audio in its bucket (200) + cheapest text (10). total=2210
504
535
  expect(estimatePeakBandwidth(m.MPD.Period[0].AdaptationSet[0].Representation[0], 'video')).toBe(2210);
505
- // v2 pos=1 → audio[1]=100, text[0]=10. total=1110
536
+ // v2 → audio bucket cheapest (100) + text (10). total=1110
506
537
  expect(estimatePeakBandwidth(m.MPD.Period[0].AdaptationSet[0].Representation[1], 'video')).toBe(1110);
507
- // t1 pos=0 (only 1 text) → video[0]=2000, audio[0]=200. total=2210
508
- expect(estimatePeakBandwidth(m.MPD.Period[0].AdaptationSet[2].Representation[0], 'text')).toBe(2210);
538
+ // t1 is the only text tier, so its bucket spans every peer — it pairs
539
+ // with the cheapest video (1000) and cheapest audio (100). total=1110
540
+ expect(estimatePeakBandwidth(m.MPD.Period[0].AdaptationSet[2].Representation[0], 'text')).toBe(1110);
509
541
  });
510
542
  it('handles single quality per content type', () => {
511
543
  // language=XML
@@ -22,5 +22,6 @@ describe('createSegmentControllerFactory', () => {
22
22
  });
23
23
  expect(controller).toEqual(jasmine.any(Object));
24
24
  expect(controller.options).toEqual(objectContaining({ prefetchActive: 100 }));
25
+ controller.dispose();
25
26
  });
26
27
  });
@@ -277,6 +277,120 @@ describe('createDashRepresentationSegmentProvider', () => {
277
277
  });
278
278
  });
279
279
  });
280
+ describe('when SegmentBase is a WebM stream', () => {
281
+ // Minimal EBML builders for a synthetic WebM init + Cues.
282
+ const vintSize = (n) => n < 0x80 ? [0x80 | n] : [0x40 | (n >> 8), n & 0xff];
283
+ const el = (id, content) => [
284
+ ...id,
285
+ ...vintSize(content.length),
286
+ ...content,
287
+ ];
288
+ const bytesToArrayBuffer = (bytes) => new Uint8Array(bytes).buffer;
289
+ // EBML header (5 bytes) then Segment(Info > TimecodeScale=1_000_000);
290
+ // the Segment data starts at offset 10, so cue positions are + 10.
291
+ const initBuffer = bytesToArrayBuffer([
292
+ ...el([0x1a, 0x45, 0xdf, 0xa3], []),
293
+ ...el([0x18, 0x53, 0x80, 0x67], el([0x15, 0x49, 0xa9, 0x66], el([0x2a, 0xd7, 0xb1], [0x0f, 0x42, 0x40]))),
294
+ ]);
295
+ const cuePoint = (time, pos) => el([0xbb], [
296
+ ...el([0xb3], time),
297
+ ...el([0xb7], [...el([0xf7], [0x01]), ...el([0xf1], pos)]),
298
+ ]);
299
+ // Cue 0 @ t=0 → cluster pos 100; cue 1 @ t=2000ms → cluster pos 200.
300
+ const cuesBuffer = bytesToArrayBuffer(el([0x1c, 0x53, 0xbb, 0x6b], [
301
+ ...cuePoint([0x00], [0x00, 0x64]),
302
+ ...cuePoint([0x07, 0xd0], [0x00, 0xc8]),
303
+ ]));
304
+ beforeEach(() => {
305
+ // WebM Cues don't carry the last segment's end, so a period end is
306
+ // required (VOD defines one).
307
+ manifest.MPD.mediaPresentationDuration = 60;
308
+ representation.BaseURL = [
309
+ { _content: 'https://example.com/v.webm' },
310
+ ];
311
+ representation.mimeType = 'video/webm';
312
+ representation.codecs = 'vp9';
313
+ representation.SegmentBase = {
314
+ indexRangeExact: false,
315
+ indexRange: [100, 199],
316
+ timescale: 1000000,
317
+ Initialization: { range: [0, 99] },
318
+ };
319
+ // The provider fetches the init and Cues ranges in parallel; return
320
+ // the matching buffer per Range header.
321
+ mockRequesterRef.value.request.and.callFake(((_input, init) => {
322
+ const range = init?.headers?.['Range'];
323
+ const body = range === 'bytes=0-99'
324
+ ? initBuffer
325
+ : range === 'bytes=100-199'
326
+ ? cuesBuffer
327
+ : new ArrayBuffer(0);
328
+ return Promise.resolve(new Response(body));
329
+ }));
330
+ });
331
+ it('creates a timeline from the WebM Cues', async () => {
332
+ const timeline = createTimeline();
333
+ // Prime the timeline (fetch init + Cues), then assert the segments.
334
+ await timeline.getSegment(0);
335
+ clearRequestCalls();
336
+ const info = await getSegmentRequestData(timeline);
337
+ expect(info).toEqual({
338
+ init: {
339
+ qualityId: any(String),
340
+ decoderId: any(String),
341
+ mimeType: 'video/webm; codecs="vp9"',
342
+ href: 'https://example.com/v.webm',
343
+ serviceId: 'example.com',
344
+ range: 'bytes=0-99',
345
+ },
346
+ segments: [
347
+ {
348
+ startTime: 0,
349
+ endTime: 2,
350
+ timestampOffset: 0,
351
+ href: 'https://example.com/v.webm',
352
+ serviceId: 'example.com',
353
+ // segmentDataStart(10) + cue positions 100..200.
354
+ range: 'bytes=110-209',
355
+ },
356
+ {
357
+ startTime: 2,
358
+ endTime: 60,
359
+ timestampOffset: 2,
360
+ href: 'https://example.com/v.webm',
361
+ serviceId: 'example.com',
362
+ // Last cluster runs open-ended to end of file.
363
+ range: 'bytes=210-',
364
+ },
365
+ ],
366
+ });
367
+ });
368
+ it('indexes WebM without an explicit SegmentBase timescale', async () => {
369
+ delete representation.SegmentBase
370
+ .timescale;
371
+ const timeline = createTimeline();
372
+ const segment = await timeline.getSegment(0);
373
+ expect(segment).not.toBeNull();
374
+ // Cue 0 at ticks 0 → 0s (TimecodeScale-derived ticks-per-second).
375
+ expect(segment.startTime).toBe(0);
376
+ });
377
+ it('throws when the period has no determinable end', () => {
378
+ delete manifest.MPD
379
+ .mediaPresentationDuration;
380
+ const timeline = createTimeline();
381
+ return expectAsync(timeline.getSegment(0)).toBeRejectedWithError(/mediaPresentationDuration or Period\.duration required/);
382
+ });
383
+ it('throws when the Cues contain no cue points', () => {
384
+ // A Cues element whose only CuePoint lacks a cluster position.
385
+ const emptyCues = bytesToArrayBuffer(el([0x1c, 0x53, 0xbb, 0x6b], el([0xbb], el([0xb3], [0x00]))));
386
+ mockRequesterRef.value.request.and.callFake(((_input, init) => {
387
+ const range = init?.headers?.['Range'];
388
+ return Promise.resolve(new Response(range === 'bytes=0-99' ? initBuffer : emptyCues));
389
+ }));
390
+ const timeline = createTimeline();
391
+ return expectAsync(timeline.getSegment(0)).toBeRejectedWithError(/Cues contained no cue points/);
392
+ });
393
+ });
280
394
  describe('when SegmentList is defined', () => {
281
395
  let segmentList;
282
396
  beforeEach(() => {
@@ -146,6 +146,31 @@ describe('mpd utils', () => {
146
146
  expect(calculatePeriodStart(manifest.MPD.Period[0])).toEqual(0);
147
147
  });
148
148
  });
149
+ describe('when period.start is absent but periods have durations', () => {
150
+ it('derives the start from the preceding period durations', () => {
151
+ // language=XML
152
+ const manifest = parseDashManifest(`<?xml version="1.0" ?>
153
+ <MPD minBufferTime="PT0.0S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011">
154
+ <Period duration="888.053"/>
155
+ <Period duration="888.053"/>
156
+ <Period duration="888.053"/>
157
+ </MPD>`);
158
+ expect(manifest.MPD.Period.map(calculatePeriodStart)).toEqual([
159
+ 0, 888.053, 1776.106,
160
+ ]);
161
+ });
162
+ it('inherits the previous start when the previous period has no duration', () => {
163
+ // language=XML
164
+ const manifest = parseDashManifest(`<?xml version="1.0" ?>
165
+ <MPD minBufferTime="PT0.0S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011">
166
+ <Period/>
167
+ <Period/>
168
+ </MPD>`);
169
+ // The first period has neither start nor duration, so the
170
+ // second period cannot advance and inherits start 0.
171
+ expect(calculatePeriodStart(manifest.MPD.Period[1])).toEqual(0);
172
+ });
173
+ });
149
174
  });
150
175
  describe('getPeriodAtTime', () => {
151
176
  it('returns the period spanning the given presentation time', () => {
@@ -331,6 +356,18 @@ describe('mpd utils', () => {
331
356
  expect(calculateDuration(manifest)).toBe(50);
332
357
  });
333
358
  });
359
+ describe('when only per-period durations are present', () => {
360
+ it('sums the period durations across the presentation', () => {
361
+ // language=XML
362
+ const manifest = parseDashManifest(`<?xml version="1.0" ?>
363
+ <MPD minBufferTime="PT0.0S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" type="static" xmlns="urn:mpeg:dash:schema:mpd:2011">
364
+ <Period duration="888.053"/>
365
+ <Period duration="888.053"/>
366
+ <Period duration="888.053"/>
367
+ </MPD>`);
368
+ expect(calculateDuration(manifest)).toBeCloseTo(2664.159, 3);
369
+ });
370
+ });
334
371
  describe('when MPD type is dynamic', () => {
335
372
  it('returns Infinity for live presentations', () => {
336
373
  // language=XML
@@ -22,6 +22,13 @@ describe('canPlayMimeType', () => {
22
22
  expect(canPlayMimeType({ capabilities }, metadata)).toBe(true);
23
23
  expect(capabilities.canPlayTypeMse).toHaveBeenCalledWith('audio/mp4; codecs="opus"');
24
24
  });
25
+ it('supports WebM when the browser reports support', () => {
26
+ capabilities.canPlayTypeMse.and.returnValue(true);
27
+ const metadata = createEmptyMediaQualityMetadata();
28
+ metadata.mimeType = 'video/webm; codecs="vp9"';
29
+ expect(canPlayMimeType({ capabilities }, metadata)).toBe(true);
30
+ expect(capabilities.canPlayTypeMse).toHaveBeenCalledWith('video/webm; codecs="vp9"');
31
+ });
25
32
  it('returns false for null mime type', () => {
26
33
  capabilities.canPlayTypeMse.and.returnValue(true);
27
34
  const metadata = createEmptyMediaQualityMetadata();