shaka-player 4.3.11 → 4.4.1

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 (315) hide show
  1. package/AUTHORS +9 -0
  2. package/CHANGELOG.md +303 -202
  3. package/CONTRIBUTORS +8 -0
  4. package/LICENSE +32 -0
  5. package/README.md +63 -10
  6. package/demo/autoTemplate.txt +40 -5
  7. package/demo/close_button.js +11 -0
  8. package/demo/common/asset.js +13 -1
  9. package/demo/common/assets.js +53 -3
  10. package/demo/common/message_ids.js +25 -1
  11. package/demo/config.js +69 -10
  12. package/demo/customWarning.txt +2 -2
  13. package/demo/index.html +3 -1
  14. package/demo/locales/en.json +26 -2
  15. package/demo/locales/source.json +105 -9
  16. package/demo/main.js +52 -9
  17. package/demo/search.js +3 -1
  18. package/demo/service_worker.js +3 -0
  19. package/dist/controls.css +1 -1
  20. package/dist/controls.css.map +1 -1
  21. package/dist/demo.compiled.debug.js +124 -112
  22. package/dist/demo.compiled.debug.map +3 -3
  23. package/dist/demo.compiled.js +124 -112
  24. package/dist/demo.compiled.map +3 -3
  25. package/dist/deps.js +46 -28
  26. package/dist/locales.js +33 -33
  27. package/dist/receiver.compiled.debug.js +52 -46
  28. package/dist/receiver.compiled.debug.map +3 -3
  29. package/dist/receiver.compiled.js +52 -46
  30. package/dist/receiver.compiled.map +3 -3
  31. package/dist/shaka-player.compiled.d.ts +676 -391
  32. package/dist/shaka-player.compiled.debug.d.ts +676 -391
  33. package/dist/shaka-player.compiled.debug.externs.js +1188 -616
  34. package/dist/shaka-player.compiled.debug.js +1043 -699
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +1188 -616
  37. package/dist/shaka-player.compiled.js +1091 -929
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +677 -392
  40. package/dist/shaka-player.ui.debug.d.ts +677 -392
  41. package/dist/shaka-player.ui.debug.externs.js +1023 -451
  42. package/dist/shaka-player.ui.debug.js +1098 -737
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +1023 -451
  45. package/dist/shaka-player.ui.js +1246 -1071
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/tutorials/ad_monetization.md +15 -1
  48. package/docs/tutorials/application-level-redirects.md +1 -1
  49. package/docs/tutorials/config.md +9 -5
  50. package/docs/tutorials/drm-config.md +61 -0
  51. package/docs/tutorials/fairplay.md +19 -4
  52. package/docs/tutorials/license-server-auth.md +4 -4
  53. package/docs/tutorials/license-wrapping.md +2 -2
  54. package/docs/tutorials/ui-customization.md +7 -3
  55. package/docs/tutorials/ui.md +7 -7
  56. package/docs/tutorials/upgrade.md +3 -0
  57. package/externs/ima.js +123 -2
  58. package/externs/isoboxer.js +217 -0
  59. package/externs/mediakeys.js +18 -0
  60. package/externs/mux.js +1 -105
  61. package/externs/pictureinpicture.js +48 -0
  62. package/externs/shaka/ads.js +61 -1
  63. package/externs/shaka/cea.js +110 -0
  64. package/externs/shaka/codecs.js +32 -0
  65. package/externs/shaka/manifest.js +101 -1
  66. package/externs/shaka/manifest_parser.js +0 -10
  67. package/externs/shaka/net.js +36 -7
  68. package/externs/shaka/offline.js +8 -1
  69. package/externs/shaka/player.js +220 -21
  70. package/externs/shaka/text.js +1 -382
  71. package/externs/shaka/transmuxer.js +60 -0
  72. package/karma.conf.js +13 -0
  73. package/lib/abr/simple_abr_manager.js +6 -3
  74. package/lib/ads/ad_manager.js +60 -2
  75. package/lib/ads/client_side_ad.js +86 -0
  76. package/lib/ads/client_side_ad_manager.js +79 -3
  77. package/lib/ads/server_side_ad.js +86 -0
  78. package/lib/ads/server_side_ad_manager.js +13 -0
  79. package/lib/cast/cast_utils.js +1 -0
  80. package/lib/cea/cea608_data_channel.js +24 -14
  81. package/lib/cea/cea608_memory.js +5 -2
  82. package/lib/cea/cea708_service.js +8 -9
  83. package/lib/cea/cea708_window.js +1 -2
  84. package/lib/cea/cea_decoder.js +23 -6
  85. package/lib/cea/cea_utils.js +25 -2
  86. package/lib/cea/dummy_caption_decoder.js +21 -0
  87. package/lib/cea/dummy_cea_parser.js +1 -3
  88. package/lib/cea/mp4_cea_parser.js +15 -10
  89. package/lib/cea/ts_cea_parser.js +69 -0
  90. package/lib/dash/content_protection.js +32 -2
  91. package/lib/dash/dash_parser.js +93 -31
  92. package/lib/dash/mpd_utils.js +6 -25
  93. package/lib/dash/segment_base.js +12 -14
  94. package/lib/dash/segment_list.js +10 -6
  95. package/lib/dash/segment_template.js +349 -32
  96. package/lib/dependencies/all.js +8 -0
  97. package/lib/hls/hls_classes.js +33 -8
  98. package/lib/hls/hls_parser.js +805 -191
  99. package/lib/hls/manifest_text_parser.js +4 -14
  100. package/lib/media/adaptation_set_criteria.js +43 -3
  101. package/lib/media/closed_caption_parser.js +74 -12
  102. package/lib/media/drm_engine.js +189 -49
  103. package/lib/media/gap_jumping_controller.js +1 -1
  104. package/lib/media/manifest_parser.js +34 -0
  105. package/lib/media/media_source_capabilities.js +10 -0
  106. package/lib/media/media_source_engine.js +495 -231
  107. package/lib/media/playhead.js +1 -1
  108. package/lib/media/presentation_timeline.js +62 -0
  109. package/lib/media/segment_index.js +50 -14
  110. package/lib/media/segment_prefetch.js +277 -0
  111. package/lib/media/segment_reference.js +70 -4
  112. package/lib/media/streaming_engine.js +258 -81
  113. package/lib/media/video_wrapper.js +15 -7
  114. package/lib/mss/content_protection.js +353 -0
  115. package/lib/mss/mss_parser.js +1082 -0
  116. package/lib/net/networking_engine.js +60 -10
  117. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  118. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  119. package/lib/offline/manifest_converter.js +6 -0
  120. package/lib/offline/storage.js +2 -4
  121. package/lib/player.js +309 -105
  122. package/lib/polyfill/media_capabilities.js +43 -3
  123. package/lib/polyfill/patchedmediakeys_apple.js +5 -0
  124. package/lib/polyfill/patchedmediakeys_nop.js +5 -0
  125. package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
  126. package/lib/text/cue.js +208 -130
  127. package/lib/text/lrc_text_parser.js +2 -2
  128. package/lib/text/mp4_vtt_parser.js +2 -2
  129. package/lib/text/sbv_text_parser.js +1 -1
  130. package/lib/text/simple_text_displayer.js +1 -1
  131. package/lib/text/srt_text_parser.js +9 -1
  132. package/lib/text/ssa_text_parser.js +2 -2
  133. package/lib/text/text_engine.js +3 -21
  134. package/lib/text/text_utils.js +71 -20
  135. package/lib/text/ui_text_displayer.js +14 -14
  136. package/lib/text/vtt_text_parser.js +22 -14
  137. package/lib/transmuxer/aac_transmuxer.js +224 -0
  138. package/lib/transmuxer/ac3.js +142 -0
  139. package/lib/transmuxer/ac3_transmuxer.js +213 -0
  140. package/lib/transmuxer/adts.js +232 -0
  141. package/lib/transmuxer/ec3.js +103 -0
  142. package/lib/transmuxer/ec3_transmuxer.js +213 -0
  143. package/lib/transmuxer/h264.js +324 -0
  144. package/lib/transmuxer/mp3_transmuxer.js +205 -0
  145. package/lib/transmuxer/mpeg_audio.js +196 -0
  146. package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
  147. package/lib/transmuxer/mss_transmuxer.js +389 -0
  148. package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
  149. package/lib/transmuxer/transmuxer_engine.js +161 -0
  150. package/lib/transmuxer/ts_transmuxer.js +721 -0
  151. package/lib/util/cmcd_manager.js +131 -71
  152. package/lib/util/error.js +62 -26
  153. package/lib/util/exp_golomb.js +220 -0
  154. package/lib/util/fairplay_utils.js +64 -13
  155. package/lib/util/id3_utils.js +56 -3
  156. package/lib/util/language_utils.js +11 -8
  157. package/lib/util/manifest_parser_utils.js +3 -0
  158. package/lib/util/mime_utils.js +44 -7
  159. package/lib/util/mp4_box_parsers.js +233 -5
  160. package/lib/util/mp4_generator.js +1388 -0
  161. package/lib/util/periods.js +40 -34
  162. package/lib/util/platform.js +17 -3
  163. package/lib/util/player_configuration.js +38 -1
  164. package/lib/util/stream_utils.js +138 -27
  165. package/lib/util/text_parser.js +1 -1
  166. package/lib/util/ts_parser.js +460 -74
  167. package/lib/util/xml_utils.js +16 -3
  168. package/maintained-branches.md +2 -2
  169. package/package.json +3 -1
  170. package/roadmap.md +21 -6
  171. package/shaka-player.uncompiled.js +18 -0
  172. package/test/abr/simple_abr_manager_unit.js +32 -4
  173. package/test/ads/ad_manager_unit.js +18 -2
  174. package/test/cast/cast_utils_unit.js +7 -2
  175. package/test/cea/cea608_memory_unit.js +24 -0
  176. package/test/cea/cea_decoder_unit.js +33 -0
  177. package/test/dash/dash_parser_content_protection_unit.js +93 -3
  178. package/test/dash/dash_parser_live_unit.js +56 -13
  179. package/test/dash/dash_parser_manifest_unit.js +70 -2
  180. package/test/dash/dash_parser_segment_base_unit.js +14 -9
  181. package/test/dash/dash_parser_segment_template_unit.js +286 -6
  182. package/test/demo/demo_unit.js +5 -1
  183. package/test/hls/hls_live_unit.js +188 -28
  184. package/test/hls/hls_parser_unit.js +250 -109
  185. package/test/hls/manifest_text_parser_unit.js +18 -13
  186. package/test/media/adaptation_set_criteria_unit.js +46 -14
  187. package/test/media/adaptation_set_unit.js +2 -0
  188. package/test/media/drm_engine_integration.js +11 -8
  189. package/test/media/drm_engine_unit.js +220 -7
  190. package/test/media/media_source_engine_integration.js +124 -40
  191. package/test/media/media_source_engine_unit.js +133 -153
  192. package/test/media/playhead_unit.js +3 -0
  193. package/test/media/presentation_timeline_unit.js +51 -0
  194. package/test/media/segment_index_unit.js +52 -0
  195. package/test/media/segment_prefetch_unit.js +243 -0
  196. package/test/media/streaming_engine_integration.js +9 -3
  197. package/test/media/streaming_engine_unit.js +440 -59
  198. package/test/mss/mss_parser_content_protection_unit.js +49 -0
  199. package/test/mss/mss_parser_unit.js +472 -0
  200. package/test/mss/mss_player_integration.js +123 -0
  201. package/test/offline/manifest_convert_unit.js +9 -0
  202. package/test/offline/storage_integration.js +6 -1
  203. package/test/player_unit.js +386 -133
  204. package/test/polyfill/media_capabilities_unit.js +18 -0
  205. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  206. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  207. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  208. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  209. package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
  210. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
  211. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  212. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  213. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  214. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  215. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  216. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  217. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  218. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  219. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
  220. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  221. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  222. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  223. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  224. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  225. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  226. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  227. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  228. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
  229. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
  230. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  231. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  232. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  233. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  234. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
  235. package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
  236. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  237. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  238. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  239. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  240. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  241. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  242. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  243. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  244. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  245. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  246. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  247. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  248. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  249. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  250. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
  251. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  252. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  253. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  254. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  255. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  256. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  257. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
  258. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  259. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  260. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  261. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  262. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  263. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  264. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
  265. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
  266. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  267. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  268. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  269. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  270. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
  271. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  272. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  273. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  274. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  275. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  276. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  277. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
  278. package/test/test/boot.js +7 -2
  279. package/test/test/util/fake_ad.js +99 -0
  280. package/test/test/util/fake_ad_manager.js +7 -1
  281. package/test/test/util/fake_networking_engine.js +41 -14
  282. package/test/test/util/fake_segment_prefetch.js +81 -0
  283. package/test/test/util/manifest_generator.js +19 -5
  284. package/test/test/util/mss_parser_util.js +115 -0
  285. package/test/test/util/offline_utils.js +1 -0
  286. package/test/test/util/simple_fakes.js +12 -3
  287. package/test/test/util/streaming_engine_util.js +14 -4
  288. package/test/test/util/ttml_utils.js +2 -2
  289. package/test/text/cue_integration.js +1 -1
  290. package/test/text/srt_text_parser_unit.js +78 -0
  291. package/test/text/text_engine_unit.js +17 -8
  292. package/test/text/ui_text_displayer_unit.js +4 -4
  293. package/test/text/vtt_text_parser_unit.js +59 -40
  294. package/test/text/web_vtt_generator_unit.js +9 -3
  295. package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
  296. package/test/transmuxer/transmuxer_engine_integration.js +60 -0
  297. package/test/transmuxer/transmuxer_integration.js +296 -0
  298. package/test/util/cmcd_manager_unit.js +162 -13
  299. package/test/util/language_utils_unit.js +9 -2
  300. package/test/util/mp4_box_parsers_unit.js +39 -4
  301. package/test/util/periods_unit.js +34 -26
  302. package/test/util/stream_utils_unit.js +60 -107
  303. package/ui/controls.js +19 -1
  304. package/ui/controls.less +1 -0
  305. package/ui/externs/ui.js +11 -1
  306. package/ui/language_utils.js +15 -0
  307. package/ui/less/thumbnails.less +26 -0
  308. package/ui/locales/oc.json +42 -0
  309. package/ui/pip_button.js +83 -2
  310. package/ui/range_element.js +15 -0
  311. package/ui/resolution_selection.js +9 -2
  312. package/ui/seek_bar.js +223 -0
  313. package/ui/ui.js +5 -0
  314. package/lib/cea/i_caption_decoder.js +0 -51
  315. package/lib/cea/i_cea_parser.js +0 -68
@@ -0,0 +1,205 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.Mp3Transmuxer');
8
+
9
+ goog.require('shaka.media.Capabilities');
10
+ goog.require('shaka.transmuxer.MpegAudio');
11
+ goog.require('shaka.transmuxer.TransmuxerEngine');
12
+ goog.require('shaka.util.BufferUtils');
13
+ goog.require('shaka.util.Error');
14
+ goog.require('shaka.util.Id3Utils');
15
+ goog.require('shaka.util.ManifestParserUtils');
16
+ goog.require('shaka.util.Mp4Generator');
17
+ goog.require('shaka.util.Uint8ArrayUtils');
18
+
19
+
20
+ /**
21
+ * @implements {shaka.extern.Transmuxer}
22
+ * @export
23
+ */
24
+ shaka.transmuxer.Mp3Transmuxer = class {
25
+ /**
26
+ * @param {string} mimeType
27
+ */
28
+ constructor(mimeType) {
29
+ /** @private {string} */
30
+ this.originalMimeType_ = mimeType;
31
+
32
+ /** @private {number} */
33
+ this.frameIndex_ = 0;
34
+
35
+ /** @private {!Map.<number, !Uint8Array>} */
36
+ this.initSegments = new Map();
37
+ }
38
+
39
+
40
+ /**
41
+ * @override
42
+ * @export
43
+ */
44
+ destroy() {
45
+ this.initSegments.clear();
46
+ }
47
+
48
+
49
+ /**
50
+ * Check if the mime type and the content type is supported.
51
+ * @param {string} mimeType
52
+ * @param {string=} contentType
53
+ * @return {boolean}
54
+ * @override
55
+ * @export
56
+ */
57
+ isSupported(mimeType, contentType) {
58
+ const Capabilities = shaka.media.Capabilities;
59
+
60
+ if (!this.isMpegContainer_(mimeType)) {
61
+ return false;
62
+ }
63
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
64
+ return Capabilities.isTypeSupported(
65
+ this.convertCodecs(ContentType.AUDIO, mimeType));
66
+ }
67
+
68
+
69
+ /**
70
+ * Check if the mimetype is 'audio/mpeg'.
71
+ * @param {string} mimeType
72
+ * @return {boolean}
73
+ * @private
74
+ */
75
+ isMpegContainer_(mimeType) {
76
+ return mimeType.toLowerCase().split(';')[0] == 'audio/mpeg';
77
+ }
78
+
79
+
80
+ /**
81
+ * @override
82
+ * @export
83
+ */
84
+ convertCodecs(contentType, mimeType) {
85
+ if (this.isMpegContainer_(mimeType)) {
86
+ return 'audio/mp4; codecs="mp3"';
87
+ }
88
+ return mimeType;
89
+ }
90
+
91
+
92
+ /**
93
+ * @override
94
+ * @export
95
+ */
96
+ getOrginalMimeType() {
97
+ return this.originalMimeType_;
98
+ }
99
+
100
+
101
+ /**
102
+ * @override
103
+ * @export
104
+ */
105
+ transmux(data, stream, reference, duration) {
106
+ const MpegAudio = shaka.transmuxer.MpegAudio;
107
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
108
+
109
+ const uint8ArrayData = shaka.util.BufferUtils.toUint8(data);
110
+
111
+ const id3Data = shaka.util.Id3Utils.getID3Data(uint8ArrayData);
112
+ let offset = id3Data.length;
113
+ for (; offset < uint8ArrayData.length; offset++) {
114
+ if (MpegAudio.probe(uint8ArrayData, offset)) {
115
+ break;
116
+ }
117
+ }
118
+
119
+ const timescale = 90000;
120
+ let firstHeader;
121
+
122
+ /** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
123
+ const samples = [];
124
+
125
+ while (offset < uint8ArrayData.length) {
126
+ const header = MpegAudio.parseHeader(uint8ArrayData, offset);
127
+ if (!header) {
128
+ return Promise.reject(new shaka.util.Error(
129
+ shaka.util.Error.Severity.CRITICAL,
130
+ shaka.util.Error.Category.MEDIA,
131
+ shaka.util.Error.Code.TRANSMUXING_FAILED));
132
+ }
133
+ if (!firstHeader) {
134
+ firstHeader = header;
135
+ }
136
+ if (offset + header.frameLength <= uint8ArrayData.length) {
137
+ samples.push({
138
+ data: uint8ArrayData.subarray(offset, offset + header.frameLength),
139
+ size: header.frameLength,
140
+ duration: MpegAudio.MPEG_AUDIO_SAMPLE_PER_FRAME,
141
+ cts: 0,
142
+ flags: {
143
+ isLeading: 0,
144
+ isDependedOn: 0,
145
+ hasRedundancy: 0,
146
+ degradPrio: 0,
147
+ dependsOn: 2,
148
+ isNonSync: 0,
149
+ },
150
+ });
151
+ }
152
+ offset += header.frameLength;
153
+ }
154
+ if (!firstHeader) {
155
+ return Promise.reject(new shaka.util.Error(
156
+ shaka.util.Error.Severity.CRITICAL,
157
+ shaka.util.Error.Category.MEDIA,
158
+ shaka.util.Error.Code.TRANSMUXING_FAILED));
159
+ }
160
+ /** @type {number} */
161
+ const sampleRate = firstHeader.sampleRate;
162
+ /** @type {number} */
163
+ const frameDuration =
164
+ firstHeader.samplesPerFrame * timescale / firstHeader.sampleRate;
165
+ /** @type {number} */
166
+ const baseMediaDecodeTime = this.frameIndex_ * frameDuration;
167
+
168
+ /** @type {shaka.util.Mp4Generator.StreamInfo} */
169
+ const streamInfo = {
170
+ id: stream.id,
171
+ type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
172
+ codecs: 'mp3',
173
+ encrypted: stream.encrypted && stream.drmInfos.length > 0,
174
+ timescale: sampleRate,
175
+ duration: duration,
176
+ videoNalus: [],
177
+ audioConfig: new Uint8Array([]),
178
+ videoConfig: new Uint8Array([]),
179
+ data: {
180
+ sequenceNumber: this.frameIndex_,
181
+ baseMediaDecodeTime: baseMediaDecodeTime,
182
+ samples: samples,
183
+ },
184
+ stream: stream,
185
+ };
186
+ const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
187
+ let initSegment;
188
+ if (!this.initSegments.has(stream.id)) {
189
+ initSegment = mp4Generator.initSegment();
190
+ this.initSegments.set(stream.id, initSegment);
191
+ } else {
192
+ initSegment = this.initSegments.get(stream.id);
193
+ }
194
+ const segmentData = mp4Generator.segmentData();
195
+
196
+ this.frameIndex_++;
197
+ const transmuxData = Uint8ArrayUtils.concat(initSegment, segmentData);
198
+ return Promise.resolve(transmuxData);
199
+ }
200
+ };
201
+
202
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
203
+ 'audio/mpeg',
204
+ () => new shaka.transmuxer.Mp3Transmuxer('audio/mpeg'),
205
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
@@ -0,0 +1,196 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.MpegAudio');
8
+
9
+
10
+ /**
11
+ * MPEG parser utils
12
+ *
13
+ * @see https://en.wikipedia.org/wiki/MP3
14
+ */
15
+ shaka.transmuxer.MpegAudio = class {
16
+ /**
17
+ * @param {!Uint8Array} data
18
+ * @param {!number} offset
19
+ * @return {?{sampleRate: number, channelCount: number,
20
+ * frameLength: number, samplesPerFrame: number}}
21
+ */
22
+ static parseHeader(data, offset) {
23
+ const MpegAudio = shaka.transmuxer.MpegAudio;
24
+
25
+ const mpegVersion = (data[offset + 1] >> 3) & 3;
26
+ const mpegLayer = (data[offset + 1] >> 1) & 3;
27
+ const bitRateIndex = (data[offset + 2] >> 4) & 15;
28
+ const sampleRateIndex = (data[offset + 2] >> 2) & 3;
29
+ if (mpegVersion !== 1 && bitRateIndex !== 0 &&
30
+ bitRateIndex !== 15 && sampleRateIndex !== 3) {
31
+ const paddingBit = (data[offset + 2] >> 1) & 1;
32
+ const channelMode = data[offset + 3] >> 6;
33
+ let columnInBitrates = 0;
34
+ if (mpegVersion === 3) {
35
+ columnInBitrates = 3 - mpegLayer;
36
+ } else {
37
+ columnInBitrates = mpegLayer === 3 ? 3 : 4;
38
+ }
39
+ const bitRate = MpegAudio.BITRATES_MAP_[
40
+ columnInBitrates * 14 + bitRateIndex - 1] * 1000;
41
+ const columnInSampleRates =
42
+ mpegVersion === 3 ? 0 : mpegVersion === 2 ? 1 : 2;
43
+ const sampleRate = MpegAudio.SAMPLINGRATE_MAP_[
44
+ columnInSampleRates * 3 + sampleRateIndex];
45
+ // If bits of channel mode are `11` then it is a single channel (Mono)
46
+ const channelCount = channelMode === 3 ? 1 : 2;
47
+ const sampleCoefficient =
48
+ MpegAudio.SAMPLES_COEFFICIENTS_[mpegVersion][mpegLayer];
49
+ const bytesInSlot = MpegAudio.BYTES_IN_SLOT_[mpegLayer];
50
+ const samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;
51
+ const frameLength =
52
+ Math.floor((sampleCoefficient * bitRate) / sampleRate + paddingBit) *
53
+ bytesInSlot;
54
+
55
+ const userAgent = navigator.userAgent || '';
56
+ // This affect to Tizen also for example.
57
+ const result = userAgent.match(/Chrome\/(\d+)/i);
58
+ const chromeVersion = result ? parseInt(result[1], 10) : 0;
59
+ const needChromeFix = !!chromeVersion && chromeVersion <= 87;
60
+
61
+ if (needChromeFix && mpegLayer === 2 &&
62
+ bitRate >= 224000 && channelMode === 0) {
63
+ // Work around bug in Chromium by setting channelMode
64
+ // to dual-channel (01) instead of stereo (00)
65
+ data[offset + 3] = data[offset + 3] | 0x80;
66
+ }
67
+
68
+ return {sampleRate, channelCount, frameLength, samplesPerFrame};
69
+ }
70
+ return null;
71
+ }
72
+
73
+ /**
74
+ * @param {!Uint8Array} data
75
+ * @param {!number} offset
76
+ * @return {boolean}
77
+ */
78
+ static isHeaderPattern(data, offset) {
79
+ return (
80
+ data[offset] === 0xff &&
81
+ (data[offset + 1] & 0xe0) === 0xe0 &&
82
+ (data[offset + 1] & 0x06) !== 0x00
83
+ );
84
+ }
85
+
86
+ /**
87
+ * @param {!Uint8Array} data
88
+ * @param {!number} offset
89
+ * @return {boolean}
90
+ */
91
+ static isHeader(data, offset) {
92
+ // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either
93
+ // 0 or 1 and Y or Z should be 1
94
+ // Layer bits (position 14 and 15) in header should be always different
95
+ // from 0 (Layer I or Layer II or Layer III)
96
+ // More info http://www.mp3-tech.org/programmer/frame_header.html
97
+ return offset + 1 < data.length &&
98
+ shaka.transmuxer.MpegAudio.isHeaderPattern(data, offset);
99
+ }
100
+
101
+ /**
102
+ * @param {!Uint8Array} data
103
+ * @param {!number} offset
104
+ * @return {boolean}
105
+ */
106
+ static probe(data, offset) {
107
+ const MpegAudio = shaka.transmuxer.MpegAudio;
108
+ // same as isHeader but we also check that MPEG frame follows last
109
+ // MPEG frame or end of data is reached
110
+ if (offset + 1 < data.length &&
111
+ MpegAudio.isHeaderPattern(data, offset)) {
112
+ // MPEG header Length
113
+ const headerLength = 4;
114
+ // MPEG frame Length
115
+ const header = MpegAudio.parseHeader(data, offset);
116
+ let frameLength = headerLength;
117
+ if (header && header.frameLength) {
118
+ frameLength = header.frameLength;
119
+ }
120
+
121
+ const newOffset = offset + frameLength;
122
+ return newOffset === data.length ||
123
+ MpegAudio.isHeader(data, newOffset);
124
+ }
125
+ return false;
126
+ }
127
+ };
128
+
129
+
130
+ /**
131
+ * @private {!Array.<number>}
132
+ */
133
+ shaka.transmuxer.MpegAudio.BITRATES_MAP_ = [
134
+ 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56,
135
+ 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80,
136
+ 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144,
137
+ 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144,
138
+ 160,
139
+ ];
140
+
141
+ /**
142
+ * @private {!Array.<number>}
143
+ */
144
+ shaka.transmuxer.MpegAudio.SAMPLINGRATE_MAP_ = [
145
+ 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000,
146
+ ];
147
+
148
+ /**
149
+ * @private {!Array.<!Array.<number>>}
150
+ */
151
+ shaka.transmuxer.MpegAudio.SAMPLES_COEFFICIENTS_ = [
152
+ // MPEG 2.5
153
+ [
154
+ 0, // Reserved
155
+ 72, // Layer3
156
+ 144, // Layer2
157
+ 12, // Layer1
158
+ ],
159
+ // Reserved
160
+ [
161
+ 0, // Reserved
162
+ 0, // Layer3
163
+ 0, // Layer2
164
+ 0, // Layer1
165
+ ],
166
+ // MPEG 2
167
+ [
168
+ 0, // Reserved
169
+ 72, // Layer3
170
+ 144, // Layer2
171
+ 12, // Layer1
172
+ ],
173
+ // MPEG 1
174
+ [
175
+ 0, // Reserved
176
+ 144, // Layer3
177
+ 144, // Layer2
178
+ 12, // Layer1
179
+ ],
180
+ ];
181
+
182
+
183
+ /**
184
+ * @private {!Array.<number>}
185
+ */
186
+ shaka.transmuxer.MpegAudio.BYTES_IN_SLOT_ = [
187
+ 0, // Reserved
188
+ 1, // Layer3
189
+ 1, // Layer2
190
+ 4, // Layer1
191
+ ];
192
+
193
+ /**
194
+ * @const {number}
195
+ */
196
+ shaka.transmuxer.MpegAudio.MPEG_AUDIO_SAMPLE_PER_FRAME = 1152;
@@ -0,0 +1,182 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.MpegTsTransmuxer');
8
+
9
+ goog.require('shaka.media.Capabilities');
10
+ goog.require('shaka.transmuxer.MpegAudio');
11
+ goog.require('shaka.transmuxer.TransmuxerEngine');
12
+ goog.require('shaka.util.BufferUtils');
13
+ goog.require('shaka.util.Error');
14
+ goog.require('shaka.util.ManifestParserUtils');
15
+ goog.require('shaka.util.MimeUtils');
16
+ goog.require('shaka.util.TsParser');
17
+ goog.require('shaka.util.Uint8ArrayUtils');
18
+
19
+ /**
20
+ * @fileoverview
21
+ *
22
+ * This transmuxer takes an audio-only TS with MP3, and converts it to
23
+ * raw MP3(audio/mpeg). We don't do it in ts_transmuxer.js because the
24
+ * output of it is always MP4. This transmuxer is necessary because the only
25
+ * browser that supports MP3 in MP4 is Firefox(audio/mp4; codecs="mp3"),
26
+ * other browsers don't support it.
27
+ */
28
+
29
+ /**
30
+ * @implements {shaka.extern.Transmuxer}
31
+ * @export
32
+ */
33
+ shaka.transmuxer.MpegTsTransmuxer = class {
34
+ /**
35
+ * @param {string} mimeType
36
+ */
37
+ constructor(mimeType) {
38
+ /** @private {string} */
39
+ this.originalMimeType_ = mimeType;
40
+
41
+ /** @private {?shaka.util.TsParser} */
42
+ this.tsParser_ = null;
43
+ }
44
+
45
+
46
+ /**
47
+ * @override
48
+ * @export
49
+ */
50
+ destroy() {
51
+ // Nothing
52
+ }
53
+
54
+
55
+ /**
56
+ * Check if the mime type and the content type is supported.
57
+ * @param {string} mimeType
58
+ * @param {string=} contentType
59
+ * @return {boolean}
60
+ * @override
61
+ * @export
62
+ */
63
+ isSupported(mimeType, contentType) {
64
+ const Capabilities = shaka.media.Capabilities;
65
+
66
+ if (!this.isTsContainer_(mimeType)) {
67
+ return false;
68
+ }
69
+
70
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
71
+ const MimeUtils = shaka.util.MimeUtils;
72
+
73
+ const codecs = MimeUtils.getCodecs(mimeType);
74
+ const allCodecs = MimeUtils.splitCodecs(codecs);
75
+
76
+ const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
77
+ ContentType.AUDIO, allCodecs);
78
+ const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
79
+ ContentType.VIDEO, allCodecs);
80
+
81
+ if (!audioCodec || videoCodec) {
82
+ return false;
83
+ }
84
+ const normalizedCodec = MimeUtils.getNormalizedCodec(audioCodec);
85
+
86
+ if (normalizedCodec != 'mp3') {
87
+ return false;
88
+ }
89
+
90
+ return Capabilities.isTypeSupported(
91
+ this.convertCodecs(ContentType.AUDIO, mimeType));
92
+ }
93
+
94
+
95
+ /**
96
+ * Check if the mimetype is 'video/mp2t'.
97
+ * @param {string} mimeType
98
+ * @return {boolean}
99
+ * @private
100
+ */
101
+ isTsContainer_(mimeType) {
102
+ return mimeType.toLowerCase().split(';')[0] == 'video/mp2t';
103
+ }
104
+
105
+
106
+ /**
107
+ * @override
108
+ * @export
109
+ */
110
+ convertCodecs(contentType, mimeType) {
111
+ if (this.isTsContainer_(mimeType)) {
112
+ return 'audio/mpeg';
113
+ }
114
+ return mimeType;
115
+ }
116
+
117
+
118
+ /**
119
+ * @override
120
+ * @export
121
+ */
122
+ getOrginalMimeType() {
123
+ return this.originalMimeType_;
124
+ }
125
+
126
+
127
+ /**
128
+ * @override
129
+ * @export
130
+ */
131
+ transmux(data) {
132
+ const MpegAudio = shaka.transmuxer.MpegAudio;
133
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
134
+
135
+ if (!this.tsParser_) {
136
+ this.tsParser_ = new shaka.util.TsParser();
137
+ } else {
138
+ this.tsParser_.clearData();
139
+ }
140
+
141
+ const uint8ArrayData = shaka.util.BufferUtils.toUint8(data);
142
+
143
+ const tsParser = this.tsParser_.parse(uint8ArrayData);
144
+ const codecs = tsParser.getCodecs();
145
+ if (codecs.audio != 'mp3' || codecs.video) {
146
+ return Promise.reject(new shaka.util.Error(
147
+ shaka.util.Error.Severity.CRITICAL,
148
+ shaka.util.Error.Category.MEDIA,
149
+ shaka.util.Error.Code.TRANSMUXING_FAILED));
150
+ }
151
+
152
+ let transmuxData = new Uint8Array([]);
153
+
154
+ for (const audioData of tsParser.getAudioData()) {
155
+ const data = audioData.data;
156
+ if (!data) {
157
+ continue;
158
+ }
159
+ let offset = 0;
160
+ while (offset < data.length) {
161
+ const header = MpegAudio.parseHeader(data, offset);
162
+ if (!header) {
163
+ offset++;
164
+ continue;
165
+ }
166
+ if (offset + header.frameLength <= data.length) {
167
+ transmuxData = Uint8ArrayUtils.concat(transmuxData,
168
+ data.subarray(offset, offset + header.frameLength));
169
+ }
170
+ offset += header.frameLength;
171
+ }
172
+ }
173
+
174
+ return Promise.resolve(transmuxData);
175
+ }
176
+ };
177
+
178
+
179
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
180
+ 'video/mp2t',
181
+ () => new shaka.transmuxer.MpegTsTransmuxer('video/mp2t'),
182
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.PREFERRED_SECONDARY);