shaka-player 4.3.9 → 4.4.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 (321) hide show
  1. package/.github/workflows/build-and-test.yaml +11 -18
  2. package/.github/workflows/compute-incremental-coverage.py +3 -0
  3. package/.github/workflows/release-please.yaml +7 -0
  4. package/.github/workflows/selenium-lab-tests.yaml +45 -10
  5. package/AUTHORS +9 -0
  6. package/CHANGELOG.md +295 -190
  7. package/CONTRIBUTORS +8 -0
  8. package/LICENSE +32 -0
  9. package/README.md +63 -10
  10. package/demo/autoTemplate.txt +40 -5
  11. package/demo/close_button.js +11 -0
  12. package/demo/common/asset.js +13 -1
  13. package/demo/common/assets.js +112 -28
  14. package/demo/common/message_ids.js +25 -1
  15. package/demo/config.js +69 -10
  16. package/demo/customWarning.txt +2 -2
  17. package/demo/index.html +3 -1
  18. package/demo/locales/en.json +26 -2
  19. package/demo/locales/source.json +105 -9
  20. package/demo/main.js +57 -9
  21. package/demo/search.js +3 -1
  22. package/demo/service_worker.js +3 -0
  23. package/dist/controls.css +1 -1
  24. package/dist/controls.css.map +1 -1
  25. package/dist/demo.compiled.debug.js +132 -118
  26. package/dist/demo.compiled.debug.map +3 -3
  27. package/dist/demo.compiled.js +132 -118
  28. package/dist/demo.compiled.map +3 -3
  29. package/dist/deps.js +46 -28
  30. package/dist/locales.js +31 -31
  31. package/dist/receiver.compiled.debug.js +60 -52
  32. package/dist/receiver.compiled.debug.map +3 -3
  33. package/dist/receiver.compiled.js +60 -52
  34. package/dist/receiver.compiled.map +3 -3
  35. package/dist/shaka-player.compiled.d.ts +676 -391
  36. package/dist/shaka-player.compiled.debug.d.ts +676 -391
  37. package/dist/shaka-player.compiled.debug.externs.js +1188 -616
  38. package/dist/shaka-player.compiled.debug.js +1046 -700
  39. package/dist/shaka-player.compiled.debug.map +4 -4
  40. package/dist/shaka-player.compiled.externs.js +1188 -616
  41. package/dist/shaka-player.compiled.js +1094 -933
  42. package/dist/shaka-player.compiled.map +4 -4
  43. package/dist/shaka-player.ui.d.ts +677 -392
  44. package/dist/shaka-player.ui.debug.d.ts +677 -392
  45. package/dist/shaka-player.ui.debug.externs.js +1023 -451
  46. package/dist/shaka-player.ui.debug.js +1101 -738
  47. package/dist/shaka-player.ui.debug.map +4 -4
  48. package/dist/shaka-player.ui.externs.js +1023 -451
  49. package/dist/shaka-player.ui.js +1244 -1071
  50. package/dist/shaka-player.ui.map +4 -4
  51. package/docs/tutorials/ad_monetization.md +15 -1
  52. package/docs/tutorials/application-level-redirects.md +1 -1
  53. package/docs/tutorials/config.md +9 -5
  54. package/docs/tutorials/drm-config.md +61 -0
  55. package/docs/tutorials/fairplay.md +19 -4
  56. package/docs/tutorials/license-server-auth.md +4 -4
  57. package/docs/tutorials/license-wrapping.md +2 -2
  58. package/docs/tutorials/ui-customization.md +7 -3
  59. package/docs/tutorials/ui.md +7 -7
  60. package/docs/tutorials/upgrade.md +3 -0
  61. package/externs/ima.js +123 -2
  62. package/externs/isoboxer.js +217 -0
  63. package/externs/mediakeys.js +18 -0
  64. package/externs/mux.js +1 -105
  65. package/externs/pictureinpicture.js +48 -0
  66. package/externs/shaka/ads.js +61 -1
  67. package/externs/shaka/cea.js +110 -0
  68. package/externs/shaka/codecs.js +32 -0
  69. package/externs/shaka/manifest.js +101 -1
  70. package/externs/shaka/manifest_parser.js +0 -10
  71. package/externs/shaka/net.js +36 -7
  72. package/externs/shaka/offline.js +8 -1
  73. package/externs/shaka/player.js +220 -21
  74. package/externs/shaka/text.js +1 -382
  75. package/externs/shaka/transmuxer.js +59 -0
  76. package/karma.conf.js +15 -0
  77. package/lib/abr/simple_abr_manager.js +6 -3
  78. package/lib/ads/ad_manager.js +60 -2
  79. package/lib/ads/client_side_ad.js +86 -0
  80. package/lib/ads/client_side_ad_manager.js +93 -5
  81. package/lib/ads/server_side_ad.js +86 -0
  82. package/lib/ads/server_side_ad_manager.js +13 -0
  83. package/lib/cast/cast_utils.js +1 -0
  84. package/lib/cea/cea608_data_channel.js +24 -14
  85. package/lib/cea/cea608_memory.js +5 -2
  86. package/lib/cea/cea708_service.js +8 -9
  87. package/lib/cea/cea708_window.js +1 -2
  88. package/lib/cea/cea_decoder.js +23 -6
  89. package/lib/cea/cea_utils.js +25 -2
  90. package/lib/cea/dummy_caption_decoder.js +21 -0
  91. package/lib/cea/dummy_cea_parser.js +1 -3
  92. package/lib/cea/mp4_cea_parser.js +15 -10
  93. package/lib/cea/ts_cea_parser.js +69 -0
  94. package/lib/dash/content_protection.js +32 -2
  95. package/lib/dash/dash_parser.js +93 -31
  96. package/lib/dash/mpd_utils.js +6 -25
  97. package/lib/dash/segment_base.js +12 -14
  98. package/lib/dash/segment_list.js +10 -6
  99. package/lib/dash/segment_template.js +349 -32
  100. package/lib/dependencies/all.js +8 -0
  101. package/lib/hls/hls_classes.js +33 -8
  102. package/lib/hls/hls_parser.js +805 -191
  103. package/lib/hls/manifest_text_parser.js +4 -14
  104. package/lib/media/adaptation_set_criteria.js +43 -3
  105. package/lib/media/closed_caption_parser.js +74 -12
  106. package/lib/media/drm_engine.js +189 -49
  107. package/lib/media/gap_jumping_controller.js +1 -1
  108. package/lib/media/manifest_parser.js +34 -0
  109. package/lib/media/media_source_capabilities.js +10 -0
  110. package/lib/media/media_source_engine.js +475 -231
  111. package/lib/media/playhead.js +1 -1
  112. package/lib/media/presentation_timeline.js +62 -0
  113. package/lib/media/segment_index.js +50 -14
  114. package/lib/media/segment_prefetch.js +277 -0
  115. package/lib/media/segment_reference.js +70 -4
  116. package/lib/media/streaming_engine.js +258 -81
  117. package/lib/media/video_wrapper.js +15 -7
  118. package/lib/mss/content_protection.js +353 -0
  119. package/lib/mss/mss_parser.js +1081 -0
  120. package/lib/net/networking_engine.js +60 -10
  121. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  122. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  123. package/lib/offline/manifest_converter.js +6 -0
  124. package/lib/offline/storage.js +2 -4
  125. package/lib/player.js +309 -105
  126. package/lib/polyfill/media_capabilities.js +43 -3
  127. package/lib/polyfill/patchedmediakeys_apple.js +5 -0
  128. package/lib/polyfill/patchedmediakeys_nop.js +5 -0
  129. package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
  130. package/lib/text/cue.js +208 -130
  131. package/lib/text/lrc_text_parser.js +2 -2
  132. package/lib/text/mp4_vtt_parser.js +2 -2
  133. package/lib/text/sbv_text_parser.js +1 -1
  134. package/lib/text/simple_text_displayer.js +2 -1
  135. package/lib/text/srt_text_parser.js +9 -1
  136. package/lib/text/ssa_text_parser.js +2 -2
  137. package/lib/text/text_engine.js +3 -21
  138. package/lib/text/text_utils.js +71 -20
  139. package/lib/text/ui_text_displayer.js +14 -14
  140. package/lib/text/vtt_text_parser.js +22 -14
  141. package/lib/transmuxer/aac_transmuxer.js +224 -0
  142. package/lib/transmuxer/ac3.js +142 -0
  143. package/lib/transmuxer/ac3_transmuxer.js +212 -0
  144. package/lib/transmuxer/adts.js +232 -0
  145. package/lib/transmuxer/ec3.js +103 -0
  146. package/lib/transmuxer/ec3_transmuxer.js +212 -0
  147. package/lib/transmuxer/h264.js +324 -0
  148. package/lib/transmuxer/mp3_transmuxer.js +204 -0
  149. package/lib/transmuxer/mpeg_audio.js +196 -0
  150. package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
  151. package/lib/transmuxer/mss_transmuxer.js +389 -0
  152. package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
  153. package/lib/transmuxer/transmuxer_engine.js +161 -0
  154. package/lib/transmuxer/ts_transmuxer.js +738 -0
  155. package/lib/util/cmcd_manager.js +131 -71
  156. package/lib/util/error.js +62 -26
  157. package/lib/util/exp_golomb.js +220 -0
  158. package/lib/util/fairplay_utils.js +64 -13
  159. package/lib/util/id3_utils.js +56 -3
  160. package/lib/util/language_utils.js +11 -8
  161. package/lib/util/manifest_parser_utils.js +3 -0
  162. package/lib/util/mime_utils.js +44 -7
  163. package/lib/util/mp4_box_parsers.js +233 -5
  164. package/lib/util/mp4_generator.js +1381 -0
  165. package/lib/util/periods.js +40 -34
  166. package/lib/util/platform.js +25 -3
  167. package/lib/util/player_configuration.js +38 -1
  168. package/lib/util/stream_utils.js +138 -27
  169. package/lib/util/text_parser.js +1 -1
  170. package/lib/util/ts_parser.js +470 -47
  171. package/lib/util/xml_utils.js +16 -3
  172. package/maintained-branches.md +2 -2
  173. package/package.json +4 -2
  174. package/roadmap.md +21 -6
  175. package/shaka-player.uncompiled.js +18 -0
  176. package/test/abr/simple_abr_manager_unit.js +32 -4
  177. package/test/ads/ad_manager_unit.js +18 -2
  178. package/test/cast/cast_utils_unit.js +7 -2
  179. package/test/cea/cea608_memory_unit.js +24 -0
  180. package/test/cea/cea_decoder_unit.js +33 -0
  181. package/test/dash/dash_parser_content_protection_unit.js +93 -3
  182. package/test/dash/dash_parser_live_unit.js +56 -13
  183. package/test/dash/dash_parser_manifest_unit.js +70 -2
  184. package/test/dash/dash_parser_segment_base_unit.js +14 -9
  185. package/test/dash/dash_parser_segment_template_unit.js +286 -6
  186. package/test/demo/demo_unit.js +5 -1
  187. package/test/hls/hls_live_unit.js +188 -28
  188. package/test/hls/hls_parser_unit.js +250 -109
  189. package/test/hls/manifest_text_parser_unit.js +18 -13
  190. package/test/media/adaptation_set_criteria_unit.js +46 -14
  191. package/test/media/adaptation_set_unit.js +2 -0
  192. package/test/media/drm_engine_integration.js +11 -8
  193. package/test/media/drm_engine_unit.js +220 -7
  194. package/test/media/media_source_engine_integration.js +122 -38
  195. package/test/media/media_source_engine_unit.js +133 -153
  196. package/test/media/playhead_unit.js +3 -0
  197. package/test/media/presentation_timeline_unit.js +51 -0
  198. package/test/media/segment_index_unit.js +52 -0
  199. package/test/media/segment_prefetch_unit.js +243 -0
  200. package/test/media/streaming_engine_integration.js +9 -3
  201. package/test/media/streaming_engine_unit.js +440 -59
  202. package/test/mss/mss_parser_content_protection_unit.js +49 -0
  203. package/test/mss/mss_parser_unit.js +472 -0
  204. package/test/mss/mss_player_integration.js +123 -0
  205. package/test/offline/manifest_convert_unit.js +9 -0
  206. package/test/offline/storage_integration.js +6 -1
  207. package/test/player_integration.js +4 -1
  208. package/test/player_unit.js +386 -133
  209. package/test/polyfill/media_capabilities_unit.js +18 -0
  210. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  211. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  212. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  213. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  214. package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
  215. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
  216. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  217. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  218. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  219. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  220. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  221. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  222. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  223. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  224. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
  225. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  226. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  227. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  228. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  229. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  230. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  231. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  232. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  233. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
  234. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
  235. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  236. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  237. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  238. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  239. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
  240. package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
  241. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  242. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  243. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  244. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  245. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  246. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  247. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  248. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  249. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  250. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  251. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  252. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  253. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  254. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  255. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
  256. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  257. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  258. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  259. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  260. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  261. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  262. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
  263. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  264. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  265. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  266. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  267. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  268. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  269. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
  270. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
  271. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  272. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  273. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  274. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  275. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
  276. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  277. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  278. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  279. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  280. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  281. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  282. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
  283. package/test/test/boot.js +7 -2
  284. package/test/test/util/fake_ad.js +99 -0
  285. package/test/test/util/fake_ad_manager.js +7 -1
  286. package/test/test/util/fake_networking_engine.js +41 -14
  287. package/test/test/util/fake_segment_prefetch.js +81 -0
  288. package/test/test/util/manifest_generator.js +19 -5
  289. package/test/test/util/mss_parser_util.js +115 -0
  290. package/test/test/util/offline_utils.js +1 -0
  291. package/test/test/util/simple_fakes.js +12 -3
  292. package/test/test/util/streaming_engine_util.js +14 -4
  293. package/test/test/util/ttml_utils.js +2 -2
  294. package/test/test/util/ui_utils.js +5 -1
  295. package/test/text/cue_integration.js +1 -1
  296. package/test/text/srt_text_parser_unit.js +78 -0
  297. package/test/text/text_engine_unit.js +17 -8
  298. package/test/text/ui_text_displayer_unit.js +4 -4
  299. package/test/text/vtt_text_parser_unit.js +59 -40
  300. package/test/text/web_vtt_generator_unit.js +9 -3
  301. package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
  302. package/test/transmuxer/transmuxer_engine_integration.js +60 -0
  303. package/test/transmuxer/transmuxer_integration.js +296 -0
  304. package/test/util/cmcd_manager_unit.js +162 -13
  305. package/test/util/language_utils_unit.js +9 -2
  306. package/test/util/mp4_box_parsers_unit.js +39 -4
  307. package/test/util/periods_unit.js +34 -26
  308. package/test/util/stream_utils_unit.js +60 -107
  309. package/ui/controls.js +19 -1
  310. package/ui/controls.less +1 -0
  311. package/ui/externs/ui.js +13 -3
  312. package/ui/language_utils.js +15 -0
  313. package/ui/less/thumbnails.less +26 -0
  314. package/ui/locales/oc.json +42 -0
  315. package/ui/pip_button.js +83 -2
  316. package/ui/range_element.js +15 -0
  317. package/ui/resolution_selection.js +9 -2
  318. package/ui/seek_bar.js +230 -1
  319. package/ui/ui.js +5 -0
  320. package/lib/cea/i_caption_decoder.js +0 -51
  321. package/lib/cea/i_cea_parser.js +0 -68
@@ -0,0 +1,389 @@
1
+ /*! @license
2
+ * MSS Transmuxer
3
+ * Copyright 2015 Dash Industry Forum
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+
7
+ /*
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *
11
+ * - Redistributions of source code must retain the above copyright notice,
12
+ * this list of conditions and the following disclaimer.
13
+ * - Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ * - Neither the name of the Dash Industry Forum nor the names of its
17
+ * contributors may be used to endorse or promote products derived from this
18
+ * software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
21
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ * POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ goog.provide('shaka.transmuxer.MssTransmuxer');
34
+
35
+ goog.require('shaka.media.Capabilities');
36
+ goog.require('shaka.transmuxer.TransmuxerEngine');
37
+ goog.require('shaka.util.BufferUtils');
38
+ goog.require('shaka.util.Error');
39
+ goog.require('shaka.util.ManifestParserUtils');
40
+ goog.require('shaka.dependencies');
41
+
42
+ goog.requireType('shaka.media.SegmentReference');
43
+
44
+
45
+ /**
46
+ * @implements {shaka.extern.Transmuxer}
47
+ * @export
48
+ */
49
+ shaka.transmuxer.MssTransmuxer = class {
50
+ /**
51
+ * @param {string} mimeType
52
+ */
53
+ constructor(mimeType) {
54
+ /** @private {string} */
55
+ this.originalMimeType_ = mimeType;
56
+
57
+ /** @private {?ISOBoxer} */
58
+ this.isoBoxer_ = shaka.dependencies.isoBoxer();
59
+
60
+ if (this.isoBoxer_) {
61
+ this.addSpecificBoxProcessor_();
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Add specific box processor for codem-isoboxer
67
+ *
68
+ * @private
69
+ */
70
+ addSpecificBoxProcessor_() {
71
+ // eslint-disable-next-line no-restricted-syntax
72
+ this.isoBoxer_.addBoxProcessor('saio', function() {
73
+ // eslint-disable-next-line no-invalid-this
74
+ const box = /** @type {!ISOBox} */(this);
75
+ box._procFullBox();
76
+ if (box.flags & 1) {
77
+ box._procField('aux_info_type', 'uint', 32);
78
+ box._procField('aux_info_type_parameter', 'uint', 32);
79
+ }
80
+ box._procField('entry_count', 'uint', 32);
81
+ box._procFieldArray('offset', box.entry_count, 'uint',
82
+ (box.version === 1) ? 64 : 32);
83
+ });
84
+ // eslint-disable-next-line no-restricted-syntax
85
+ this.isoBoxer_.addBoxProcessor('saiz', function() {
86
+ // eslint-disable-next-line no-invalid-this
87
+ const box = /** @type {!ISOBox} */(this);
88
+ box._procFullBox();
89
+ if (box.flags & 1) {
90
+ box._procField('aux_info_type', 'uint', 32);
91
+ box._procField('aux_info_type_parameter', 'uint', 32);
92
+ }
93
+ box._procField('default_sample_info_size', 'uint', 8);
94
+ box._procField('sample_count', 'uint', 32);
95
+ if (box.default_sample_info_size === 0) {
96
+ box._procFieldArray('sample_info_size',
97
+ box.sample_count, 'uint', 8);
98
+ }
99
+ });
100
+ // eslint-disable-next-line no-restricted-syntax
101
+ const sencProcessor = function() {
102
+ // eslint-disable-next-line no-invalid-this
103
+ const box = /** @type {!ISOBox} */(this);
104
+ box._procFullBox();
105
+ if (box.flags & 1) {
106
+ box._procField('AlgorithmID', 'uint', 24);
107
+ box._procField('IV_size', 'uint', 8);
108
+ box._procFieldArray('KID', 16, 'uint', 8);
109
+ }
110
+ box._procField('sample_count', 'uint', 32);
111
+ // eslint-disable-next-line no-restricted-syntax
112
+ box._procEntries('entry', box.sample_count, function(entry) {
113
+ // eslint-disable-next-line no-invalid-this
114
+ const boxEntry = /** @type {!ISOBox} */(this);
115
+ boxEntry._procEntryField(entry, 'InitializationVector', 'data', 8);
116
+ if (boxEntry.flags & 2) {
117
+ boxEntry._procEntryField(entry, 'NumberOfEntries', 'uint', 16);
118
+ boxEntry._procSubEntries(entry, 'clearAndCryptedData',
119
+ // eslint-disable-next-line no-restricted-syntax
120
+ entry.NumberOfEntries, function(clearAndCryptedData) {
121
+ // eslint-disable-next-line no-invalid-this
122
+ const subBoxEntry = /** @type {!ISOBox} */(this);
123
+ subBoxEntry._procEntryField(clearAndCryptedData,
124
+ 'BytesOfClearData', 'uint', 16);
125
+ subBoxEntry._procEntryField(clearAndCryptedData,
126
+ 'BytesOfEncryptedData', 'uint', 32);
127
+ });
128
+ }
129
+ });
130
+ };
131
+ this.isoBoxer_.addBoxProcessor('senc', sencProcessor);
132
+ // eslint-disable-next-line no-restricted-syntax
133
+ this.isoBoxer_.addBoxProcessor('uuid', function() {
134
+ const MssTransmuxer = shaka.transmuxer.MssTransmuxer;
135
+ // eslint-disable-next-line no-invalid-this
136
+ const box = /** @type {!ISOBox} */(this);
137
+ let isSENC = true;
138
+ for (let i = 0; i < 16; i++) {
139
+ if (box.usertype[i] !== MssTransmuxer.UUID_SENC_[i]) {
140
+ isSENC = false;
141
+ }
142
+ // Add support for other user types here
143
+ }
144
+
145
+ if (isSENC) {
146
+ if (box._parsing) {
147
+ // Convert this box to sepiff for later processing.
148
+ // See processMediaSegment_ function.
149
+ box.type = 'sepiff';
150
+ }
151
+ // eslint-disable-next-line no-restricted-syntax, no-invalid-this
152
+ sencProcessor.call(/** @type {!ISOBox} */(this));
153
+ }
154
+ });
155
+ }
156
+
157
+
158
+ /**
159
+ * @override
160
+ * @export
161
+ */
162
+ destroy() {
163
+ // Nothing
164
+ }
165
+
166
+
167
+ /**
168
+ * Check if the mime type and the content type is supported.
169
+ * @param {string} mimeType
170
+ * @param {string=} contentType
171
+ * @return {boolean}
172
+ * @override
173
+ * @export
174
+ */
175
+ isSupported(mimeType, contentType) {
176
+ const Capabilities = shaka.media.Capabilities;
177
+
178
+ const isMss = mimeType.startsWith('mss/');
179
+
180
+ if (!this.isoBoxer_ || !isMss) {
181
+ return false;
182
+ }
183
+
184
+ if (contentType) {
185
+ return Capabilities.isTypeSupported(
186
+ this.convertCodecs(contentType, mimeType));
187
+ }
188
+
189
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
190
+
191
+ const audioMime = this.convertCodecs(ContentType.AUDIO, mimeType);
192
+ const videoMime = this.convertCodecs(ContentType.VIDEO, mimeType);
193
+ return Capabilities.isTypeSupported(audioMime) ||
194
+ Capabilities.isTypeSupported(videoMime);
195
+ }
196
+
197
+
198
+ /**
199
+ * @override
200
+ * @export
201
+ */
202
+ convertCodecs(contentType, mimeType) {
203
+ return mimeType.replace('mss/', '');
204
+ }
205
+
206
+
207
+ /**
208
+ * @override
209
+ * @export
210
+ */
211
+ getOrginalMimeType() {
212
+ return this.originalMimeType_;
213
+ }
214
+
215
+
216
+ /**
217
+ * @override
218
+ * @export
219
+ */
220
+ transmux(data, stream, reference) {
221
+ if (!reference) {
222
+ // Init segment doesn't need transmux
223
+ return Promise.resolve(shaka.util.BufferUtils.toUint8(data));
224
+ }
225
+ if (!stream.mssPrivateData) {
226
+ return Promise.reject(new shaka.util.Error(
227
+ shaka.util.Error.Severity.CRITICAL,
228
+ shaka.util.Error.Category.MEDIA,
229
+ shaka.util.Error.Code.MSS_MISSING_DATA_FOR_TRANSMUXING));
230
+ }
231
+ try {
232
+ const transmuxedData = this.processMediaSegment_(
233
+ data, stream, reference);
234
+ return Promise.resolve(transmuxedData);
235
+ } catch (exception) {
236
+ if (exception instanceof shaka.util.Error) {
237
+ return Promise.reject(exception);
238
+ }
239
+ return Promise.reject(new shaka.util.Error(
240
+ shaka.util.Error.Severity.CRITICAL,
241
+ shaka.util.Error.Category.MEDIA,
242
+ shaka.util.Error.Code.MSS_TRANSMUXING_FAILED));
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Process a media segment from a data and stream.
248
+ * @param {BufferSource} data
249
+ * @param {shaka.extern.Stream} stream
250
+ * @param {shaka.media.SegmentReference} reference
251
+ * @return {!Uint8Array}
252
+ * @private
253
+ */
254
+ processMediaSegment_(data, stream, reference) {
255
+ let i;
256
+ const isoFile = this.isoBoxer_.parseBuffer(data);
257
+ // Update track_Id in tfhd box
258
+ const tfhd = isoFile.fetch('tfhd');
259
+ tfhd.track_ID = stream.id + 1;
260
+ // Add tfdt box
261
+ let tfdt = isoFile.fetch('tfdt');
262
+ const traf = isoFile.fetch('traf');
263
+ if (tfdt === null) {
264
+ tfdt = this.isoBoxer_.createFullBox('tfdt', traf, tfhd);
265
+ tfdt.version = 1;
266
+ tfdt.flags = 0;
267
+ const timescale = stream.mssPrivateData.timescale;
268
+ const startTime = reference.startTime;
269
+ tfdt.baseMediaDecodeTime = Math.floor(startTime * timescale);
270
+ }
271
+ const trun = isoFile.fetch('trun');
272
+ // Process tfxd boxes
273
+ // This box provide absolute timestamp but we take the segment start
274
+ // time for tfdt
275
+ let tfxd = isoFile.fetch('tfxd');
276
+ if (tfxd) {
277
+ tfxd._parent.boxes.splice(tfxd._parent.boxes.indexOf(tfxd), 1);
278
+ tfxd = null;
279
+ }
280
+ let tfrf = isoFile.fetch('tfrf');
281
+ if (tfrf) {
282
+ tfrf._parent.boxes.splice(tfrf._parent.boxes.indexOf(tfrf), 1);
283
+ tfrf = null;
284
+ }
285
+
286
+ // If protected content in PIFF1.1 format
287
+ // (sepiff box = Sample Encryption PIFF)
288
+ // => convert sepiff box it into a senc box
289
+ // => create saio and saiz boxes (if not already present)
290
+ const sepiff = isoFile.fetch('sepiff');
291
+ if (sepiff !== null) {
292
+ sepiff.type = 'senc';
293
+ sepiff.usertype = undefined;
294
+
295
+ let saio = isoFile.fetch('saio');
296
+ if (saio === null) {
297
+ // Create Sample Auxiliary Information Offsets Box box (saio)
298
+ saio = this.isoBoxer_.createFullBox('saio', traf);
299
+ saio.version = 0;
300
+ saio.flags = 0;
301
+ saio.entry_count = 1;
302
+ saio.offset = [0];
303
+ const saiz = this.isoBoxer_.createFullBox('saiz', traf);
304
+ saiz.version = 0;
305
+ saiz.flags = 0;
306
+ saiz.sample_count = sepiff.sample_count;
307
+ saiz.default_sample_info_size = 0;
308
+ saiz.sample_info_size = [];
309
+ if (sepiff.flags & 0x02) {
310
+ // Sub-sample encryption => set sample_info_size for each sample
311
+ for (i = 0; i < sepiff.sample_count; i += 1) {
312
+ // 10 = 8 (InitializationVector field size) + 2
313
+ // (subsample_count field size)
314
+ // 6 = 2 (BytesOfClearData field size) + 4
315
+ // (BytesOfEncryptedData field size)
316
+ saiz.sample_info_size[i] =
317
+ 10 + (6 * sepiff.entry[i].NumberOfEntries);
318
+ }
319
+ } else {
320
+ // No sub-sample encryption => set default
321
+ // sample_info_size = InitializationVector field size (8)
322
+ saiz.default_sample_info_size = 8;
323
+ }
324
+ }
325
+ }
326
+
327
+ // set tfhd.base-data-offset-present to false
328
+ tfhd.flags &= 0xFFFFFE;
329
+ // set tfhd.default-base-is-moof to true
330
+ tfhd.flags |= 0x020000;
331
+ // set trun.data-offset-present to true
332
+ trun.flags |= 0x000001;
333
+
334
+ // Update trun.data_offset field that corresponds to first data byte
335
+ // (inside mdat box)
336
+ const moof = isoFile.fetch('moof');
337
+ const length = moof.getLength();
338
+ trun.data_offset = length + 8;
339
+
340
+ // Update saio box offset field according to new senc box offset
341
+ const saio = isoFile.fetch('saio');
342
+ if (saio !== null) {
343
+ const trafPosInMoof = this.getBoxOffset_(moof, 'traf');
344
+ const sencPosInTraf = this.getBoxOffset_(traf, 'senc');
345
+ // Set offset from begin fragment to the first IV field in senc box
346
+ // 16 = box header (12) + sample_count field size (4)
347
+ saio.offset[0] = trafPosInMoof + sencPosInTraf + 16;
348
+ }
349
+
350
+ return shaka.util.BufferUtils.toUint8(isoFile.write());
351
+ }
352
+
353
+ /**
354
+ * This function returns the offset of the 1st byte of a child box within
355
+ * a container box.
356
+ *
357
+ * @param {ISOBox} parent
358
+ * @param {string} type
359
+ * @return {number}
360
+ * @private
361
+ */
362
+ getBoxOffset_(parent, type) {
363
+ let offset = 8;
364
+ for (let i = 0; i < parent.boxes.length; i++) {
365
+ if (parent.boxes[i].type === type) {
366
+ return offset;
367
+ }
368
+ offset += parent.boxes[i].size;
369
+ }
370
+ return offset;
371
+ }
372
+ };
373
+
374
+ /**
375
+ * @private {!Uint8Array}
376
+ */
377
+ shaka.transmuxer.MssTransmuxer.UUID_SENC_ = new Uint8Array([
378
+ 0xA2, 0x39, 0x4F, 0x52, 0x5A, 0x9B, 0x4F, 0x14,
379
+ 0xA2, 0x44, 0x6C, 0x42, 0x7C, 0x64, 0x8D, 0xF4,
380
+ ]);
381
+
382
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
383
+ 'mss/audio/mp4',
384
+ () => new shaka.transmuxer.MssTransmuxer('mss/audio/mp4'),
385
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
386
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
387
+ 'mss/video/mp4',
388
+ () => new shaka.transmuxer.MssTransmuxer('mss/video/mp4'),
389
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
@@ -4,26 +4,24 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
- goog.provide('shaka.media.Transmuxer');
7
+ goog.provide('shaka.transmuxer.MuxjsTransmuxer');
8
8
 
9
9
  goog.require('goog.asserts');
10
+ goog.require('shaka.dependencies');
10
11
  goog.require('shaka.media.Capabilities');
12
+ goog.require('shaka.transmuxer.TransmuxerEngine');
11
13
  goog.require('shaka.util.BufferUtils');
12
14
  goog.require('shaka.util.Error');
13
- goog.require('shaka.util.IDestroyable');
14
15
  goog.require('shaka.util.ManifestParserUtils');
15
16
  goog.require('shaka.util.PublicPromise');
16
17
  goog.require('shaka.util.Uint8ArrayUtils');
17
- goog.require('shaka.dependencies');
18
18
 
19
19
 
20
20
  /**
21
- * Transmuxer provides all operations for transmuxing from Transport
22
- * Stream or AAC to MP4.
23
- *
24
- * @implements {shaka.util.IDestroyable}
21
+ * @implements {shaka.extern.Transmuxer}
22
+ * @export
25
23
  */
26
- shaka.media.Transmuxer = class {
24
+ shaka.transmuxer.MuxjsTransmuxer = class {
27
25
  /**
28
26
  * @param {string} mimeType
29
27
  */
@@ -43,9 +41,6 @@ shaka.media.Transmuxer = class {
43
41
  /** @private {!Array.<!Uint8Array>} */
44
42
  this.transmuxedData_ = [];
45
43
 
46
- /** @private {!Array.<muxjs.mp4.ClosedCaption>} */
47
- this.captions_ = [];
48
-
49
44
  /** @private {boolean} */
50
45
  this.isTransmuxing_ = false;
51
46
 
@@ -58,103 +53,73 @@ shaka.media.Transmuxer = class {
58
53
  }
59
54
  }
60
55
 
56
+
61
57
  /**
62
58
  * @override
59
+ * @export
63
60
  */
64
61
  destroy() {
65
62
  if (this.muxTransmuxer_) {
66
63
  this.muxTransmuxer_.dispose();
67
64
  }
68
65
  this.muxTransmuxer_ = null;
69
- return Promise.resolve();
70
66
  }
71
67
 
72
68
 
73
69
  /**
74
- * Check if the content type is Transport Stream or AAC, and if muxjs is
75
- * loaded.
70
+ * Check if the mime type and the content type is supported.
76
71
  * @param {string} mimeType
77
72
  * @param {string=} contentType
78
73
  * @return {boolean}
74
+ * @override
75
+ * @export
79
76
  */
80
- static isSupported(mimeType, contentType) {
81
- const Transmuxer = shaka.media.Transmuxer;
77
+ isSupported(mimeType, contentType) {
82
78
  const Capabilities = shaka.media.Capabilities;
83
79
 
84
- const isTs = Transmuxer.isTsContainer_(mimeType);
85
- const isAac = Transmuxer.isAacContainer_(mimeType);
80
+ const isTs = this.isTsContainer_(mimeType);
86
81
 
87
- if (!shaka.dependencies.muxjs() || (!isTs && !isAac)) {
82
+ if (!this.muxjs_ || !isTs) {
88
83
  return false;
89
84
  }
90
85
 
91
- if (isAac) {
92
- return Capabilities.isTypeSupported(Transmuxer.convertAacCodecs_());
93
- }
94
-
95
86
  if (contentType) {
96
87
  return Capabilities.isTypeSupported(
97
- Transmuxer.convertTsCodecs_(contentType, mimeType));
88
+ this.convertTsCodecs_(contentType, mimeType));
98
89
  }
99
90
 
100
91
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
101
92
 
102
- const audioMime = Transmuxer.convertTsCodecs_(ContentType.AUDIO, mimeType);
103
- const videoMime = Transmuxer.convertTsCodecs_(ContentType.VIDEO, mimeType);
93
+ const audioMime = this.convertTsCodecs_(ContentType.AUDIO, mimeType);
94
+ const videoMime = this.convertTsCodecs_(ContentType.VIDEO, mimeType);
104
95
  return Capabilities.isTypeSupported(audioMime) ||
105
96
  Capabilities.isTypeSupported(videoMime);
106
97
  }
107
98
 
108
99
 
109
- /**
110
- * Check if the mimetype is 'audio/aac'.
111
- * @param {string} mimeType
112
- * @return {boolean}
113
- * @private
114
- */
115
- static isAacContainer_(mimeType) {
116
- return mimeType.toLowerCase().split(';')[0] == 'audio/aac';
117
- }
118
-
119
-
120
100
  /**
121
101
  * Check if the mimetype contains 'mp2t'.
122
102
  * @param {string} mimeType
123
103
  * @return {boolean}
124
104
  * @private
125
105
  */
126
- static isTsContainer_(mimeType) {
106
+ isTsContainer_(mimeType) {
127
107
  return mimeType.toLowerCase().split(';')[0].split('/')[1] == 'mp2t';
128
108
  }
129
109
 
130
110
 
131
111
  /**
132
- * For any stream, convert its codecs to MP4 codecs.
133
- * @param {string} contentType
134
- * @param {string} mimeType
135
- * @return {string}
112
+ * @override
113
+ * @export
136
114
  */
137
- static convertCodecs(contentType, mimeType) {
138
- const Transmuxer = shaka.media.Transmuxer;
139
- if (Transmuxer.isAacContainer_(mimeType)) {
140
- return Transmuxer.convertAacCodecs_();
141
- } else if (Transmuxer.isTsContainer_(mimeType)) {
142
- return Transmuxer.convertTsCodecs_(contentType, mimeType);
115
+ convertCodecs(contentType, mimeType) {
116
+ if (this.isTsContainer_(mimeType)) {
117
+ return this.convertTsCodecs_(contentType, mimeType);
143
118
  }
144
119
  return mimeType;
145
120
  }
146
121
 
147
122
 
148
- /**
149
- * For aac stream, convert its codecs to MP4 codecs.
150
- * @return {string}
151
- * @private
152
- */
153
- static convertAacCodecs_() {
154
- return 'audio/mp4; codecs="mp4a.40.2"';
155
- }
156
-
157
-
158
123
  /**
159
124
  * For transport stream, convert its codecs to MP4 codecs.
160
125
  * @param {string} contentType
@@ -162,7 +127,7 @@ shaka.media.Transmuxer = class {
162
127
  * @return {string}
163
128
  * @private
164
129
  */
165
- static convertTsCodecs_(contentType, tsMimeType) {
130
+ convertTsCodecs_(contentType, tsMimeType) {
166
131
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
167
132
  let mp4MimeType = tsMimeType.replace(/mp2t/i, 'mp4');
168
133
  if (contentType == ContentType.AUDIO) {
@@ -205,8 +170,8 @@ shaka.media.Transmuxer = class {
205
170
 
206
171
 
207
172
  /**
208
- * Returns the original mimetype of the transmuxer.
209
- * @return {string}
173
+ * @override
174
+ * @export
210
175
  */
211
176
  getOrginalMimeType() {
212
177
  return this.originalMimeType_;
@@ -214,10 +179,8 @@ shaka.media.Transmuxer = class {
214
179
 
215
180
 
216
181
  /**
217
- * Transmux from Transport stream to MP4, using the mux.js library.
218
- * @param {BufferSource} data
219
- * @return {!Promise.<{data: !Uint8Array,
220
- * captions: !Array.<!muxjs.mp4.ClosedCaption>}>}
182
+ * @override
183
+ * @export
221
184
  */
222
185
  transmux(data) {
223
186
  goog.asserts.assert(this.muxTransmuxer_,
@@ -227,7 +190,6 @@ shaka.media.Transmuxer = class {
227
190
  this.isTransmuxing_ = true;
228
191
  this.transmuxPromise_ = new shaka.util.PublicPromise();
229
192
  this.transmuxedData_ = [];
230
- this.captions_ = [];
231
193
 
232
194
  const dataArray = shaka.util.BufferUtils.toUint8(data);
233
195
  this.muxTransmuxer_.push(dataArray);
@@ -247,13 +209,6 @@ shaka.media.Transmuxer = class {
247
209
  return this.transmuxPromise_;
248
210
  }
249
211
 
250
- /**
251
- * Reset captions from Transport stream to MP4, using the mux.js library.
252
- */
253
- resetCaptions() {
254
- this.muxTransmuxer_.resetCaptions();
255
- }
256
-
257
212
  /**
258
213
  * Handles the 'data' event of the transmuxer.
259
214
  * Extracts the cues from the transmuxed segment, and adds them to an array.
@@ -264,7 +219,6 @@ shaka.media.Transmuxer = class {
264
219
  * @private
265
220
  */
266
221
  onTransmuxed_(segment) {
267
- this.captions_ = segment.captions;
268
222
  this.transmuxedData_.push(
269
223
  shaka.util.Uint8ArrayUtils.concat(segment.initSegment, segment.data));
270
224
  }
@@ -276,13 +230,13 @@ shaka.media.Transmuxer = class {
276
230
  * @private
277
231
  */
278
232
  onTransmuxDone_() {
279
- const output = {
280
- data: shaka.util.Uint8ArrayUtils.concat(...this.transmuxedData_),
281
- captions: this.captions_,
282
- };
283
-
284
- this.transmuxPromise_.resolve(output);
233
+ const data = shaka.util.Uint8ArrayUtils.concat(...this.transmuxedData_);
234
+ this.transmuxPromise_.resolve(data);
285
235
  this.isTransmuxing_ = false;
286
236
  }
287
237
  };
288
238
 
239
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
240
+ 'video/mp2t',
241
+ () => new shaka.transmuxer.MuxjsTransmuxer('video/mp2t'),
242
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);