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,142 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.Ac3');
8
+
9
+
10
+ /**
11
+ * AC3 utils
12
+ */
13
+ shaka.transmuxer.Ac3 = class {
14
+ /**
15
+ * @param {!Uint8Array} data
16
+ * @param {!number} offset
17
+ * @return {?{sampleRate: number, channelCount: number,
18
+ * audioConfig: !Uint8Array, frameLength: number}}
19
+ */
20
+ static parseFrame(data, offset) {
21
+ if (offset + 8 > data.length) {
22
+ // not enough bytes left
23
+ return null;
24
+ }
25
+
26
+ if (data[offset] !== 0x0b || data[offset + 1] !== 0x77) {
27
+ // invalid magic
28
+ return null;
29
+ }
30
+
31
+ // get sample rate
32
+ const samplingRateCode = data[offset + 4] >> 6;
33
+ if (samplingRateCode >= 3) {
34
+ // invalid sampling rate
35
+ return null;
36
+ }
37
+
38
+ const samplingRateMap = [48000, 44100, 32000];
39
+
40
+ // get frame size
41
+ const frameSizeCode = data[offset + 4] & 0x3f;
42
+ const frameSizeMap = [
43
+ 64, 69, 96, 64, 70, 96, 80, 87, 120, 80, 88, 120, 96, 104, 144, 96, 105,
44
+ 144, 112, 121, 168, 112, 122, 168, 128, 139, 192, 128, 140, 192, 160,
45
+ 174, 240, 160, 175, 240, 192, 208, 288, 192, 209, 288, 224, 243, 336,
46
+ 224, 244, 336, 256, 278, 384, 256, 279, 384, 320, 348, 480, 320, 349,
47
+ 480, 384, 417, 576, 384, 418, 576, 448, 487, 672, 448, 488, 672, 512,
48
+ 557, 768, 512, 558, 768, 640, 696, 960, 640, 697, 960, 768, 835, 1152,
49
+ 768, 836, 1152, 896, 975, 1344, 896, 976, 1344, 1024, 1114, 1536, 1024,
50
+ 1115, 1536, 1152, 1253, 1728, 1152, 1254, 1728, 1280, 1393, 1920, 1280,
51
+ 1394, 1920,
52
+ ];
53
+
54
+ const frameLength = frameSizeMap[frameSizeCode * 3 + samplingRateCode] * 2;
55
+ if (offset + frameLength > data.length) {
56
+ return null;
57
+ }
58
+
59
+ // get channel count
60
+ const channelMode = data[offset + 6] >> 5;
61
+ let skipCount = 0;
62
+ if (channelMode === 2) {
63
+ skipCount += 2;
64
+ } else {
65
+ if ((channelMode & 1) && channelMode !== 1) {
66
+ skipCount += 2;
67
+ }
68
+ if (channelMode & 4) {
69
+ skipCount += 2;
70
+ }
71
+ }
72
+
73
+ const lowFrequencyEffectsChannelOn =
74
+ (((data[offset + 6] << 8) | data[offset + 7]) >> (12 - skipCount)) & 1;
75
+
76
+ const channelsMap = [2, 1, 2, 3, 3, 4, 4, 5];
77
+
78
+ // Audio config for DAC3 box
79
+ const bitStreamIdentification = data[offset + 5] >> 3;
80
+ const bitStreamMode = data[offset + 5] & 7;
81
+
82
+ const config = new Uint8Array([
83
+ (samplingRateCode << 6) |
84
+ (bitStreamIdentification << 1) |
85
+ (bitStreamMode >> 2),
86
+ ((bitStreamMode & 3) << 6) |
87
+ (channelMode << 3) |
88
+ (lowFrequencyEffectsChannelOn << 2) |
89
+ (frameSizeCode >> 4),
90
+ (frameSizeCode << 4) & 0xe0,
91
+ ]);
92
+
93
+ return {
94
+ sampleRate: samplingRateMap[samplingRateCode],
95
+ channelCount: channelsMap[channelMode] + lowFrequencyEffectsChannelOn,
96
+ audioConfig: config,
97
+ frameLength: frameLength,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * @param {!Uint8Array} data
103
+ * @param {!number} offset
104
+ * @return {boolean}
105
+ */
106
+ static probe(data, offset) {
107
+ // look for the ac-3 sync bytes
108
+ if (data[offset] === 0x0b &&
109
+ data[offset + 1] === 0x77) {
110
+ // check the bsid (bitStreamIdentification) to confirm ac-3
111
+ let bsid = 0;
112
+ let numBits = 5;
113
+ offset += numBits;
114
+ /** @type {?number} */
115
+ let temp = null;
116
+ /** @type {?number} */
117
+ let mask = null;
118
+ /** @type {?number} */
119
+ let byte = null;
120
+ while (numBits > 0) {
121
+ byte = data[offset];
122
+ // read remaining bits, upto 8 bits at a time
123
+ const bits = Math.min(numBits, 8);
124
+ const shift = 8 - bits;
125
+ mask = (0xff000000 >>> (24 + shift)) << shift;
126
+ temp = (byte & mask) >> shift;
127
+ bsid = !bsid ? temp : (bsid << bits) | temp;
128
+ offset += 1;
129
+ numBits -= bits;
130
+ }
131
+ if (bsid < 16) {
132
+ return true;
133
+ }
134
+ }
135
+ return false;
136
+ }
137
+ };
138
+
139
+ /**
140
+ * @const {number}
141
+ */
142
+ shaka.transmuxer.Ac3.AC3_SAMPLES_PER_FRAME = 1536;
@@ -0,0 +1,212 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.Ac3Transmuxer');
8
+
9
+ goog.require('shaka.media.Capabilities');
10
+ goog.require('shaka.transmuxer.Ac3');
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.Ac3Transmuxer = 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.isAc3Container_(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/ac3'.
71
+ * @param {string} mimeType
72
+ * @return {boolean}
73
+ * @private
74
+ */
75
+ isAc3Container_(mimeType) {
76
+ return mimeType.toLowerCase().split(';')[0] == 'audio/ac3';
77
+ }
78
+
79
+
80
+ /**
81
+ * @override
82
+ * @export
83
+ */
84
+ convertCodecs(contentType, mimeType) {
85
+ if (this.isAc3Container_(mimeType)) {
86
+ return 'audio/mp4; codecs="ac-3"';
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 Ac3 = shaka.transmuxer.Ac3;
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 (Ac3.probe(uint8ArrayData, offset)) {
115
+ break;
116
+ }
117
+ }
118
+
119
+ let timestamp = reference.endTime * 1000;
120
+
121
+ const frames = shaka.util.Id3Utils.getID3Frames(id3Data);
122
+ if (frames.length && reference) {
123
+ const metadataTimestamp = frames.find((frame) => {
124
+ return frame.description ===
125
+ 'com.apple.streaming.transportStreamTimestamp';
126
+ });
127
+ if (metadataTimestamp) {
128
+ timestamp = /** @type {!number} */(metadataTimestamp.data);
129
+ }
130
+ }
131
+
132
+ /** @type {number} */
133
+ let sampleRate = 0;
134
+
135
+ /** @type {!Uint8Array} */
136
+ let audioConfig = new Uint8Array([]);
137
+
138
+ /** @type {!Array.<shaka.util.Mp4Generator.Mp4Sample>} */
139
+ const samples = [];
140
+
141
+ while (offset < uint8ArrayData.length) {
142
+ const frame = Ac3.parseFrame(uint8ArrayData, offset);
143
+ if (!frame) {
144
+ return Promise.reject(new shaka.util.Error(
145
+ shaka.util.Error.Severity.CRITICAL,
146
+ shaka.util.Error.Category.MEDIA,
147
+ shaka.util.Error.Code.TRANSMUXING_FAILED));
148
+ }
149
+ stream.audioSamplingRate = frame.sampleRate;
150
+ stream.channelsCount = frame.channelCount;
151
+ sampleRate = frame.sampleRate;
152
+ audioConfig = frame.audioConfig;
153
+
154
+ const frameData = uint8ArrayData.subarray(
155
+ offset, offset + frame.frameLength);
156
+
157
+ samples.push({
158
+ data: frameData,
159
+ size: frame.frameLength,
160
+ duration: Ac3.AC3_SAMPLES_PER_FRAME,
161
+ cts: 0,
162
+ flags: {
163
+ isLeading: 0,
164
+ isDependedOn: 0,
165
+ hasRedundancy: 0,
166
+ degradPrio: 0,
167
+ dependsOn: 2,
168
+ isNonSync: 0,
169
+ },
170
+ });
171
+ offset += frame.frameLength;
172
+ }
173
+ /** @type {number} */
174
+ const baseMediaDecodeTime = Math.floor(timestamp * sampleRate / 1000);
175
+
176
+ /** @type {shaka.util.Mp4Generator.StreamInfo} */
177
+ const streamInfo = {
178
+ id: stream.id,
179
+ type: shaka.util.ManifestParserUtils.ContentType.AUDIO,
180
+ encrypted: stream.encrypted && stream.drmInfos.length > 0,
181
+ timescale: sampleRate,
182
+ duration: duration,
183
+ videoNalus: [],
184
+ audioConfig: audioConfig,
185
+ videoConfig: new Uint8Array([]),
186
+ data: {
187
+ sequenceNumber: this.frameIndex_,
188
+ baseMediaDecodeTime: baseMediaDecodeTime,
189
+ samples: samples,
190
+ },
191
+ stream: stream,
192
+ };
193
+ const mp4Generator = new shaka.util.Mp4Generator([streamInfo]);
194
+ let initSegment;
195
+ if (!this.initSegments.has(stream.id)) {
196
+ initSegment = mp4Generator.initSegment();
197
+ this.initSegments.set(stream.id, initSegment);
198
+ } else {
199
+ initSegment = this.initSegments.get(stream.id);
200
+ }
201
+ const segmentData = mp4Generator.segmentData();
202
+
203
+ this.frameIndex_++;
204
+ const transmuxData = Uint8ArrayUtils.concat(initSegment, segmentData);
205
+ return Promise.resolve(transmuxData);
206
+ }
207
+ };
208
+
209
+ shaka.transmuxer.TransmuxerEngine.registerTransmuxer(
210
+ 'audio/ac3',
211
+ () => new shaka.transmuxer.Ac3Transmuxer('audio/ac3'),
212
+ shaka.transmuxer.TransmuxerEngine.PluginPriority.FALLBACK);
@@ -0,0 +1,232 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.ADTS');
8
+
9
+
10
+ /**
11
+ * ADTS utils
12
+ */
13
+ shaka.transmuxer.ADTS = class {
14
+ /**
15
+ * @param {!Uint8Array} data
16
+ * @param {!number} offset
17
+ * @return {?{headerLength: number, frameLength: number}}
18
+ */
19
+ static parseHeader(data, offset) {
20
+ const ADTS = shaka.transmuxer.ADTS;
21
+ // The protection skip bit tells us if we have 2 bytes of CRC data at the
22
+ // end of the ADTS header
23
+ const headerLength = ADTS.getHeaderLength(data, offset);
24
+ if (offset + headerLength <= data.length) {
25
+ // retrieve frame size
26
+ const frameLength = ADTS.getFullFrameLength(data, offset) - headerLength;
27
+ if (frameLength > 0) {
28
+ return {
29
+ headerLength,
30
+ frameLength,
31
+ };
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+
37
+ /**
38
+ * @param {!Uint8Array} data
39
+ * @param {!number} offset
40
+ * @return {?{sampleRate: number, channelCount: number, codec: string}}
41
+ */
42
+ static parseInfo(data, offset) {
43
+ const adtsSamplingRates = [
44
+ 96000,
45
+ 88200,
46
+ 64000,
47
+ 48000,
48
+ 44100,
49
+ 32000,
50
+ 24000,
51
+ 22050,
52
+ 16000,
53
+ 12000,
54
+ 11025,
55
+ 8000,
56
+ 7350,
57
+ ];
58
+ const adtsSamplingIndex = (data[offset + 2] & 0x3c) >>> 2;
59
+ if (adtsSamplingIndex > adtsSamplingRates.length - 1) {
60
+ return null;
61
+ }
62
+ const adtsObjectType = ((data[offset + 2] & 0xc0) >>> 6) + 1;
63
+ let adtsChannelConfig = (data[offset + 2] & 0x01) << 2;
64
+ adtsChannelConfig |= (data[offset + 3] & 0xc0) >>> 6;
65
+ return {
66
+ sampleRate: adtsSamplingRates[adtsSamplingIndex],
67
+ channelCount: adtsChannelConfig,
68
+ codec: 'mp4a.40.' + adtsObjectType,
69
+ };
70
+ }
71
+
72
+ /**
73
+ * @param {!Uint8Array} data
74
+ * @param {!number} offset
75
+ * @return {boolean}
76
+ */
77
+ static isHeaderPattern(data, offset) {
78
+ return data[offset] === 0xff && (data[offset + 1] & 0xf6) === 0xf0;
79
+ }
80
+
81
+ /**
82
+ * @param {!Uint8Array} data
83
+ * @param {!number} offset
84
+ * @return {number}
85
+ */
86
+ static getHeaderLength(data, offset) {
87
+ return data[offset + 1] & 0x01 ? 7 : 9;
88
+ }
89
+
90
+ /**
91
+ * @param {!Uint8Array} data
92
+ * @param {!number} offset
93
+ * @return {number}
94
+ */
95
+ static getFullFrameLength(data, offset) {
96
+ return ((data[offset + 3] & 0x03) << 11) |
97
+ (data[offset + 4] << 3) |
98
+ ((data[offset + 5] & 0xe0) >>> 5);
99
+ }
100
+
101
+ /**
102
+ * @param {!Uint8Array} data
103
+ * @param {!number} offset
104
+ * @return {boolean}
105
+ */
106
+ static isHeader(data, offset) {
107
+ const ADTS = shaka.transmuxer.ADTS;
108
+ // Look for ADTS header | 1111 1111 | 1111 X00X | where X can be
109
+ // either 0 or 1
110
+ // Layer bits (position 14 and 15) in header should be always 0 for ADTS
111
+ // More info https://wiki.multimedia.cx/index.php?title=ADTS
112
+ return offset + 1 < data.length && ADTS.isHeaderPattern(data, offset);
113
+ }
114
+
115
+ /**
116
+ * @param {!Uint8Array} data
117
+ * @param {!number} offset
118
+ * @return {boolean}
119
+ */
120
+ static probe(data, offset) {
121
+ const ADTS = shaka.transmuxer.ADTS;
122
+ // same as isHeader but we also check that ADTS frame follows last ADTS
123
+ // frame or end of data is reached
124
+ if (ADTS.isHeader(data, offset)) {
125
+ // ADTS header Length
126
+ const headerLength = ADTS.getHeaderLength(data, offset);
127
+ if (offset + headerLength >= data.length) {
128
+ return false;
129
+ }
130
+ // ADTS frame Length
131
+ const frameLength = ADTS.getFullFrameLength(data, offset);
132
+ if (frameLength <= headerLength) {
133
+ return false;
134
+ }
135
+
136
+ const newOffset = offset + frameLength;
137
+ return newOffset === data.length || ADTS.isHeader(data, newOffset);
138
+ }
139
+ return false;
140
+ }
141
+
142
+ /**
143
+ * @param {!number} samplerate
144
+ * @return {number}
145
+ */
146
+ static getFrameDuration(samplerate) {
147
+ return (shaka.transmuxer.ADTS.AAC_SAMPLES_PER_FRAME * 90000) / samplerate;
148
+ }
149
+
150
+ /**
151
+ * @param {string} codec
152
+ * @param {number} channelCount
153
+ * @return {?Uint8Array}
154
+ */
155
+ static getSilentFrame(codec, channelCount) {
156
+ switch (codec) {
157
+ case 'mp4a.40.2':
158
+ if (channelCount === 1) {
159
+ return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);
160
+ } else if (channelCount === 2) {
161
+ return new Uint8Array([
162
+ 0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80,
163
+ ]);
164
+ } else if (channelCount === 3) {
165
+ return new Uint8Array([
166
+ 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,
167
+ 0x00, 0x8e,
168
+ ]);
169
+ } else if (channelCount === 4) {
170
+ return new Uint8Array([
171
+ 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,
172
+ 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38,
173
+ ]);
174
+ } else if (channelCount === 5) {
175
+ return new Uint8Array([
176
+ 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,
177
+ 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38,
178
+ ]);
179
+ } else if (channelCount === 6) {
180
+ return new Uint8Array([
181
+ 0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64,
182
+ 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2,
183
+ 0x00, 0x20, 0x08, 0xe0,
184
+ ]);
185
+ }
186
+ break;
187
+ // handle HE-AAC below (mp4a.40.5 / mp4a.40.29)
188
+ default:
189
+ if (channelCount === 1) {
190
+ // eslint-disable-next-line max-len
191
+ // ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
192
+ return new Uint8Array([
193
+ 0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,
194
+ 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
195
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
196
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
197
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
198
+ 0x5a, 0x5e,
199
+ ]);
200
+ } else if (channelCount === 2) {
201
+ // eslint-disable-next-line max-len
202
+ // ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
203
+ return new Uint8Array([
204
+ 0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,
205
+ 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,
206
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
207
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
208
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
209
+ 0x5a, 0x5e,
210
+ ]);
211
+ } else if (channelCount === 3) {
212
+ // eslint-disable-next-line max-len
213
+ // ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
214
+ return new Uint8Array([
215
+ 0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0,
216
+ 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a,
217
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
218
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
219
+ 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
220
+ 0x5a, 0x5e,
221
+ ]);
222
+ }
223
+ break;
224
+ }
225
+ return null;
226
+ }
227
+ };
228
+
229
+ /**
230
+ * @const {number}
231
+ */
232
+ shaka.transmuxer.ADTS.AAC_SAMPLES_PER_FRAME = 1024;
@@ -0,0 +1,103 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.transmuxer.Ec3');
8
+
9
+ goog.require('shaka.util.ExpGolomb');
10
+
11
+
12
+ /**
13
+ * EC3 utils
14
+ */
15
+ shaka.transmuxer.Ec3 = class {
16
+ /**
17
+ * @param {!Uint8Array} data
18
+ * @param {!number} offset
19
+ * @return {?{sampleRate: number, channelCount: number,
20
+ * audioConfig: !Uint8Array, frameLength: number}}
21
+ */
22
+ static parseFrame(data, offset) {
23
+ if (offset + 8 > data.length) {
24
+ // not enough bytes left
25
+ return null;
26
+ }
27
+
28
+ if (!shaka.transmuxer.Ec3.probe(data, offset)) {
29
+ return null;
30
+ }
31
+
32
+ const gb = new shaka.util.ExpGolomb(data.subarray(offset + 2));
33
+ // Skip stream_type
34
+ gb.skipBits(2);
35
+ // Skip sub_stream_id
36
+ gb.skipBits(3);
37
+ const frameLength = (gb.readBits(11) + 1) << 1;
38
+ let samplingRateCode = gb.readBits(2);
39
+ let sampleRate = null;
40
+ let numBlocksCode = null;
41
+ if (samplingRateCode == 0x03) {
42
+ samplingRateCode = gb.readBits(2);
43
+ sampleRate = [24000, 22060, 16000][samplingRateCode];
44
+ numBlocksCode = 3;
45
+ } else {
46
+ sampleRate = [48000, 44100, 32000][samplingRateCode];
47
+ numBlocksCode = gb.readBits(2);
48
+ }
49
+
50
+ const channelMode = gb.readBits(3);
51
+ const lowFrequencyEffectsChannelOn = gb.readBits(1);
52
+ const bitStreamIdentification = gb.readBits(5);
53
+
54
+ if (offset + frameLength > data.byteLength) {
55
+ return null;
56
+ }
57
+
58
+ const channelsMap = [2, 1, 2, 3, 3, 4, 4, 5];
59
+
60
+ const numBlocksMap = [1, 2, 3, 6];
61
+
62
+ const numBlocks = numBlocksMap[numBlocksCode];
63
+
64
+ const dataRateSub =
65
+ Math.floor((frameLength * sampleRate) / (numBlocks * 16));
66
+
67
+ const config = new Uint8Array([
68
+ ((dataRateSub & 0x1FE0) >> 5),
69
+ ((dataRateSub & 0x001F) << 3), // num_ind_sub = zero
70
+ (sampleRate << 6) | (bitStreamIdentification << 1) | (0 << 0),
71
+ (0 << 7) | (0 << 4) |
72
+ (channelMode << 1) | (lowFrequencyEffectsChannelOn << 0),
73
+ (0 << 5) | (0 << 1) | (0 << 0),
74
+ ]);
75
+
76
+ return {
77
+ sampleRate,
78
+ channelCount: channelsMap[channelMode] + lowFrequencyEffectsChannelOn,
79
+ audioConfig: config,
80
+ frameLength,
81
+ };
82
+ }
83
+
84
+ /**
85
+ * @param {!Uint8Array} data
86
+ * @param {!number} offset
87
+ * @return {boolean}
88
+ */
89
+ static probe(data, offset) {
90
+ // search 16-bit 0x0B77 syncword
91
+ const syncword = (data[offset] << 8) | (data[offset + 1] << 0);
92
+ if (syncword === 0x0B77) {
93
+ return true;
94
+ } else {
95
+ return false;
96
+ }
97
+ }
98
+ };
99
+
100
+ /**
101
+ * @const {number}
102
+ */
103
+ shaka.transmuxer.Ec3.EC3_SAMPLES_PER_FRAME = 1536;