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,1388 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.Mp4Generator');
8
+
9
+ goog.require('goog.asserts');
10
+ goog.require('shaka.util.ManifestParserUtils');
11
+ goog.require('shaka.util.Uint8ArrayUtils');
12
+
13
+
14
+ shaka.util.Mp4Generator = class {
15
+ /**
16
+ * @param {!Array.<shaka.util.Mp4Generator.StreamInfo>} streamInfos
17
+ */
18
+ constructor(streamInfos) {
19
+ shaka.util.Mp4Generator.initStaticProperties_();
20
+
21
+ /** @private {!Array.<shaka.util.Mp4Generator.StreamInfo>} */
22
+ this.streamInfos_ = streamInfos;
23
+ }
24
+
25
+ /**
26
+ * Generate a Init Segment (MP4).
27
+ *
28
+ * @return {!Uint8Array}
29
+ */
30
+ initSegment() {
31
+ const Mp4Generator = shaka.util.Mp4Generator;
32
+ const movie = this.moov_();
33
+ const length = Mp4Generator.FTYP_.byteLength + movie.byteLength;
34
+ const result = new Uint8Array(length);
35
+ result.set(Mp4Generator.FTYP_);
36
+ result.set(movie, Mp4Generator.FTYP_.byteLength);
37
+ return result;
38
+ }
39
+
40
+ /**
41
+ * Generate a MOOV box
42
+ *
43
+ * @return {!Uint8Array}
44
+ * @private
45
+ */
46
+ moov_() {
47
+ goog.asserts.assert(this.streamInfos_.length > 0,
48
+ 'StreamInfos must have elements');
49
+ const Mp4Generator = shaka.util.Mp4Generator;
50
+ let traks = new Uint8Array([]);
51
+ for (const streamInfo of this.streamInfos_) {
52
+ traks = shaka.util.Uint8ArrayUtils.concat(traks, this.trak_(streamInfo));
53
+ }
54
+ const firstStreamInfo = this.streamInfos_[0];
55
+ return Mp4Generator.box('moov',
56
+ this.mvhd_(firstStreamInfo),
57
+ traks,
58
+ this.mvex_(),
59
+ this.pssh_(firstStreamInfo));
60
+ }
61
+
62
+ /**
63
+ * Generate a MVHD box
64
+ *
65
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
66
+ * @return {!Uint8Array}
67
+ * @private
68
+ */
69
+ mvhd_(streamInfo) {
70
+ const Mp4Generator = shaka.util.Mp4Generator;
71
+ const duration = streamInfo.duration * streamInfo.timescale;
72
+ const upperWordDuration =
73
+ Math.floor(duration / (Mp4Generator.UINT32_MAX_ + 1));
74
+ const lowerWordDuration =
75
+ Math.floor(duration % (Mp4Generator.UINT32_MAX_ + 1));
76
+ const bytes = new Uint8Array([
77
+ 0x01, // version 1
78
+ 0x00, 0x00, 0x00, // flags
79
+ 0x00, 0x00, 0x00, 0x00,
80
+ 0x00, 0x00, 0x00, 0x02, // creation_time
81
+ 0x00, 0x00, 0x00, 0x00,
82
+ 0x00, 0x00, 0x00, 0x03, // modification_time
83
+ ...this.breakNumberIntoBytes_(streamInfo.timescale, 4), // timescale
84
+ ...this.breakNumberIntoBytes_(upperWordDuration, 4),
85
+ ...this.breakNumberIntoBytes_(lowerWordDuration, 4), // duration
86
+ 0x00, 0x01, 0x00, 0x00, // 1.0 rate
87
+ 0x01, 0x00, // 1.0 volume
88
+ 0x00, 0x00, // reserved
89
+ 0x00, 0x00, 0x00, 0x00, // reserved
90
+ 0x00, 0x00, 0x00, 0x00, // reserved
91
+ 0x00, 0x01, 0x00, 0x00,
92
+ 0x00, 0x00, 0x00, 0x00,
93
+ 0x00, 0x00, 0x00, 0x00,
94
+ 0x00, 0x00, 0x00, 0x00,
95
+ 0x00, 0x01, 0x00, 0x00,
96
+ 0x00, 0x00, 0x00, 0x00,
97
+ 0x00, 0x00, 0x00, 0x00,
98
+ 0x00, 0x00, 0x00, 0x00,
99
+ 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
100
+ 0x00, 0x00, 0x00, 0x00,
101
+ 0x00, 0x00, 0x00, 0x00,
102
+ 0x00, 0x00, 0x00, 0x00,
103
+ 0x00, 0x00, 0x00, 0x00,
104
+ 0x00, 0x00, 0x00, 0x00,
105
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
106
+ 0xff, 0xff, 0xff, 0xff, // next_track_ID
107
+ ]);
108
+ return Mp4Generator.box('mvhd', bytes);
109
+ }
110
+
111
+ /**
112
+ * Generate a TRAK box
113
+ *
114
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
115
+ * @return {!Uint8Array}
116
+ * @private
117
+ */
118
+ trak_(streamInfo) {
119
+ const Mp4Generator = shaka.util.Mp4Generator;
120
+ return Mp4Generator.box('trak',
121
+ this.tkhd_(streamInfo), this.mdia_(streamInfo));
122
+ }
123
+
124
+ /**
125
+ * Generate a TKHD box
126
+ *
127
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
128
+ * @return {!Uint8Array}
129
+ * @private
130
+ */
131
+ tkhd_(streamInfo) {
132
+ const Mp4Generator = shaka.util.Mp4Generator;
133
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
134
+ const id = streamInfo.id + 1;
135
+ let width = streamInfo.stream.width || 0;
136
+ let height = streamInfo.stream.height || 0;
137
+ if (streamInfo.type == ContentType.AUDIO) {
138
+ width = 0;
139
+ height = 0;
140
+ }
141
+ const duration = streamInfo.duration * streamInfo.timescale;
142
+ const upperWordDuration =
143
+ Math.floor(duration / (Mp4Generator.UINT32_MAX_ + 1));
144
+ const lowerWordDuration =
145
+ Math.floor(duration % (Mp4Generator.UINT32_MAX_ + 1));
146
+ const bytes = new Uint8Array([
147
+ 0x01, // version 1
148
+ 0x00, 0x00, 0x07, // flags
149
+ 0x00, 0x00, 0x00, 0x00,
150
+ 0x00, 0x00, 0x00, 0x02, // creation_time
151
+ 0x00, 0x00, 0x00, 0x00,
152
+ 0x00, 0x00, 0x00, 0x03, // modification_time
153
+ ...this.breakNumberIntoBytes_(id, 4), // track_ID
154
+ 0x00, 0x00, 0x00, 0x00, // reserved
155
+ ...this.breakNumberIntoBytes_(upperWordDuration, 4),
156
+ ...this.breakNumberIntoBytes_(lowerWordDuration, 4), // duration
157
+ 0x00, 0x00, 0x00, 0x00,
158
+ 0x00, 0x00, 0x00, 0x00, // reserved
159
+ 0x00, 0x00, // layer
160
+ 0x00, 0x00, // alternate_group
161
+ 0x00, 0x00, // non-audio track volume
162
+ 0x00, 0x00, // reserved
163
+ 0x00, 0x01, 0x00, 0x00,
164
+ 0x00, 0x00, 0x00, 0x00,
165
+ 0x00, 0x00, 0x00, 0x00,
166
+ 0x00, 0x00, 0x00, 0x00,
167
+ 0x00, 0x01, 0x00, 0x00,
168
+ 0x00, 0x00, 0x00, 0x00,
169
+ 0x00, 0x00, 0x00, 0x00,
170
+ 0x00, 0x00, 0x00, 0x00,
171
+ 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix
172
+ ...this.breakNumberIntoBytes_(width, 2),
173
+ 0x00, 0x00, // width
174
+ ...this.breakNumberIntoBytes_(height, 2),
175
+ 0x00, 0x00, // height
176
+ ]);
177
+ return Mp4Generator.box('tkhd', bytes);
178
+ }
179
+
180
+ /**
181
+ * Generate a MDIA box
182
+ *
183
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
184
+ * @return {!Uint8Array}
185
+ * @private
186
+ */
187
+ mdia_(streamInfo) {
188
+ const Mp4Generator = shaka.util.Mp4Generator;
189
+ return Mp4Generator.box('mdia', this.mdhd_(streamInfo),
190
+ this.hdlr_(streamInfo), this.minf_(streamInfo));
191
+ }
192
+
193
+ /**
194
+ * Generate a MDHD box
195
+ *
196
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
197
+ * @return {!Uint8Array}
198
+ * @private
199
+ */
200
+ mdhd_(streamInfo) {
201
+ const Mp4Generator = shaka.util.Mp4Generator;
202
+ const duration = streamInfo.duration * streamInfo.timescale;
203
+ const upperWordDuration =
204
+ Math.floor(duration / (Mp4Generator.UINT32_MAX_ + 1));
205
+ const lowerWordDuration =
206
+ Math.floor(duration % (Mp4Generator.UINT32_MAX_ + 1));
207
+ const language = streamInfo.stream.language;
208
+ const languageNumber = ((language.charCodeAt(0) - 0x60) << 10) |
209
+ ((language.charCodeAt(1) - 0x60) << 5) |
210
+ ((language.charCodeAt(2) - 0x60));
211
+ const bytes = new Uint8Array([
212
+ 0x01, // version 1
213
+ 0x00, 0x00, 0x00, // flags
214
+ 0x00, 0x00, 0x00, 0x00,
215
+ 0x00, 0x00, 0x00, 0x02, // creation_time
216
+ 0x00, 0x00, 0x00, 0x00,
217
+ 0x00, 0x00, 0x00, 0x03, // modification_time
218
+ ...this.breakNumberIntoBytes_(streamInfo.timescale, 4), // timescale
219
+ ...this.breakNumberIntoBytes_(upperWordDuration, 4),
220
+ ...this.breakNumberIntoBytes_(lowerWordDuration, 4), // duration
221
+ ...this.breakNumberIntoBytes_(languageNumber, 2), // language
222
+ 0x00, 0x00,
223
+ ]);
224
+ return Mp4Generator.box('mdhd', bytes);
225
+ }
226
+
227
+ /**
228
+ * Generate a HDLR box
229
+ *
230
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
231
+ * @return {!Uint8Array}
232
+ * @private
233
+ */
234
+ hdlr_(streamInfo) {
235
+ const Mp4Generator = shaka.util.Mp4Generator;
236
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
237
+ let bytes = new Uint8Array([]);
238
+ switch (streamInfo.type) {
239
+ case ContentType.VIDEO:
240
+ bytes = Mp4Generator.HDLR_TYPES_.video;
241
+ break;
242
+ case ContentType.AUDIO:
243
+ bytes = Mp4Generator.HDLR_TYPES_.audio;
244
+ break;
245
+ }
246
+ return Mp4Generator.box('hdlr', bytes);
247
+ }
248
+
249
+ /**
250
+ * Generate a MINF box
251
+ *
252
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
253
+ * @return {!Uint8Array}
254
+ * @private
255
+ */
256
+ minf_(streamInfo) {
257
+ const Mp4Generator = shaka.util.Mp4Generator;
258
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
259
+ switch (streamInfo.type) {
260
+ case ContentType.VIDEO:
261
+ return Mp4Generator.box(
262
+ 'minf', Mp4Generator.box('vmhd', Mp4Generator.VMHD_),
263
+ Mp4Generator.DINF_, this.stbl_(streamInfo));
264
+ case ContentType.AUDIO:
265
+ return Mp4Generator.box(
266
+ 'minf', Mp4Generator.box('smhd', Mp4Generator.SMHD_),
267
+ Mp4Generator.DINF_, this.stbl_(streamInfo));
268
+ }
269
+ return new Uint8Array([]);
270
+ }
271
+
272
+ /**
273
+ * Generate a STBL box
274
+ *
275
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
276
+ * @return {!Uint8Array}
277
+ * @private
278
+ */
279
+ stbl_(streamInfo) {
280
+ const Mp4Generator = shaka.util.Mp4Generator;
281
+ return Mp4Generator.box(
282
+ 'stbl',
283
+ this.stsd_(streamInfo),
284
+ Mp4Generator.box('stts', Mp4Generator.STTS_),
285
+ Mp4Generator.box('stsc', Mp4Generator.STSC_),
286
+ Mp4Generator.box('stsz', Mp4Generator.STSZ_),
287
+ Mp4Generator.box('stco', Mp4Generator.STCO_));
288
+ }
289
+
290
+ /**
291
+ * Generate a STSD box
292
+ *
293
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
294
+ * @return {!Uint8Array}
295
+ * @private
296
+ */
297
+ stsd_(streamInfo) {
298
+ const Mp4Generator = shaka.util.Mp4Generator;
299
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
300
+ let bytes = new Uint8Array([]);
301
+ switch (streamInfo.type) {
302
+ case ContentType.VIDEO:
303
+ if (streamInfo.codecs.includes('avc1')) {
304
+ bytes = this.avc1_(streamInfo);
305
+ } else if (streamInfo.codecs.includes('hvc1')) {
306
+ bytes = this.hvc1_(streamInfo);
307
+ }
308
+ break;
309
+ case ContentType.AUDIO:
310
+ if (streamInfo.codecs.includes('mp3')) {
311
+ bytes = this.mp3_(streamInfo);
312
+ } else if (streamInfo.codecs.includes('ac-3')) {
313
+ bytes = this.ac3_(streamInfo);
314
+ } else if (streamInfo.codecs.includes('ec-3')) {
315
+ bytes = this.ec3_(streamInfo);
316
+ } else {
317
+ bytes = this.mp4a_(streamInfo);
318
+ }
319
+ break;
320
+ }
321
+ return Mp4Generator.box('stsd', Mp4Generator.STSD_, bytes);
322
+ }
323
+
324
+ /**
325
+ * Generate a AVC1 box
326
+ *
327
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
328
+ * @return {!Uint8Array}
329
+ * @private
330
+ */
331
+ avc1_(streamInfo) {
332
+ const Mp4Generator = shaka.util.Mp4Generator;
333
+
334
+ const width = streamInfo.stream.width || 0;
335
+ const height = streamInfo.stream.height || 0;
336
+
337
+ let avcCBox;
338
+ if (streamInfo.videoConfig.byteLength > 0) {
339
+ avcCBox = Mp4Generator.box('avcC', streamInfo.videoConfig);
340
+ } else {
341
+ avcCBox = Mp4Generator.box('avcC', this.avcC_(streamInfo));
342
+ }
343
+
344
+ const avc1Bytes = new Uint8Array([
345
+ 0x00, 0x00, 0x00,
346
+ 0x00, 0x00, 0x00, // reserved
347
+ 0x00, 0x01, // data_reference_index
348
+ 0x00, 0x00, // pre_defined
349
+ 0x00, 0x00, // reserved
350
+ 0x00, 0x00, 0x00, 0x00,
351
+ 0x00, 0x00, 0x00, 0x00,
352
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
353
+ ...this.breakNumberIntoBytes_(width, 2), // width
354
+ ...this.breakNumberIntoBytes_(height, 2), // height
355
+ 0x00, 0x48, 0x00, 0x00, // horizresolution
356
+ 0x00, 0x48, 0x00, 0x00, // vertresolution
357
+ 0x00, 0x00, 0x00, 0x00, // reserved
358
+ 0x00, 0x01, // frame_count
359
+ 0x13,
360
+ 0x76, 0x69, 0x64, 0x65,
361
+ 0x6f, 0x6a, 0x73, 0x2d,
362
+ 0x63, 0x6f, 0x6e, 0x74,
363
+ 0x72, 0x69, 0x62, 0x2d,
364
+ 0x68, 0x6c, 0x73, 0x00,
365
+ 0x00, 0x00, 0x00, 0x00,
366
+ 0x00, 0x00, 0x00, 0x00,
367
+ 0x00, 0x00, 0x00, // compressorname
368
+ 0x00, 0x18, // depth = 24
369
+ 0x11, 0x11, // pre_defined = -1
370
+ ]);
371
+
372
+ let boxName = 'avc1';
373
+ let sinfBox = new Uint8Array([]);
374
+ if (streamInfo.encrypted) {
375
+ sinfBox = this.sinf_(streamInfo);
376
+ boxName = 'encv';
377
+ }
378
+ return Mp4Generator.box(boxName, avc1Bytes, avcCBox, sinfBox);
379
+ }
380
+
381
+ /**
382
+ * Generate a AVCC box
383
+ *
384
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
385
+ * @return {!Uint8Array}
386
+ * @private
387
+ */
388
+ avcC_(streamInfo) {
389
+ const NALUTYPE_SPS = 7;
390
+ const NALUTYPE_PPS = 8;
391
+
392
+ // length = 7 by default (0 SPS and 0 PPS)
393
+ let avcCLength = 7;
394
+
395
+ // First get all SPS and PPS from nalus
396
+ const sps = [];
397
+ const pps = [];
398
+ let AVCProfileIndication = 0;
399
+ let AVCLevelIndication = 0;
400
+ let profileCompatibility = 0;
401
+ for (let i = 0; i < streamInfo.videoNalus.length; i++) {
402
+ const naluBytes = this.hexStringToBuffer_(streamInfo.videoNalus[i]);
403
+ const naluType = naluBytes[0] & 0x1F;
404
+ switch (naluType) {
405
+ case NALUTYPE_SPS:
406
+ sps.push(naluBytes);
407
+ // 2 = sequenceParameterSetLength field length
408
+ avcCLength += naluBytes.length + 2;
409
+ break;
410
+ case NALUTYPE_PPS:
411
+ pps.push(naluBytes);
412
+ // 2 = pictureParameterSetLength field length
413
+ avcCLength += naluBytes.length + 2;
414
+ break;
415
+ default:
416
+ break;
417
+ }
418
+ }
419
+ // Get profile and level from SPS
420
+ if (sps.length > 0) {
421
+ AVCProfileIndication = sps[0][1];
422
+ profileCompatibility = sps[0][2];
423
+ AVCLevelIndication = sps[0][3];
424
+ }
425
+
426
+ // Generate avcC buffer
427
+ const avcCBytes = new Uint8Array(avcCLength);
428
+ let i = 0;
429
+ // configurationVersion = 1
430
+ avcCBytes[i++] = 1;
431
+ avcCBytes[i++] = AVCProfileIndication;
432
+ avcCBytes[i++] = profileCompatibility;
433
+ avcCBytes[i++] = AVCLevelIndication;
434
+ // '11111' + lengthSizeMinusOne = 3
435
+ avcCBytes[i++] = 0xFF;
436
+ // '111' + numOfSequenceParameterSets
437
+ avcCBytes[i++] = 0xE0 | sps.length;
438
+ for (let n = 0; n < sps.length; n++) {
439
+ avcCBytes[i++] = (sps[n].length & 0xFF00) >> 8;
440
+ avcCBytes[i++] = (sps[n].length & 0x00FF);
441
+ avcCBytes.set(sps[n], i);
442
+ i += sps[n].length;
443
+ }
444
+ // numOfPictureParameterSets
445
+ avcCBytes[i++] = pps.length;
446
+ for (let n = 0; n < pps.length; n++) {
447
+ avcCBytes[i++] = (pps[n].length & 0xFF00) >> 8;
448
+ avcCBytes[i++] = (pps[n].length & 0x00FF);
449
+ avcCBytes.set(pps[n], i);
450
+ i += pps[n].length;
451
+ }
452
+ return avcCBytes;
453
+ }
454
+
455
+ /**
456
+ * Generate a HVC1 box
457
+ *
458
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
459
+ * @return {!Uint8Array}
460
+ * @private
461
+ */
462
+ hvc1_(streamInfo) {
463
+ const Mp4Generator = shaka.util.Mp4Generator;
464
+
465
+ const width = streamInfo.stream.width || 0;
466
+ const height = streamInfo.stream.height || 0;
467
+
468
+ let hvcCBox = new Uint8Array([]);
469
+ if (streamInfo.videoConfig.byteLength > 0) {
470
+ hvcCBox = Mp4Generator.box('hvcC', streamInfo.videoConfig);
471
+ }
472
+
473
+ const hvc1Bytes = new Uint8Array([
474
+ 0x00, 0x00, 0x00,
475
+ 0x00, 0x00, 0x00, // reserved
476
+ 0x00, 0x01, // data_reference_index
477
+ 0x00, 0x00, // pre_defined
478
+ 0x00, 0x00, // reserved
479
+ 0x00, 0x00, 0x00, 0x00,
480
+ 0x00, 0x00, 0x00, 0x00,
481
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
482
+ ...this.breakNumberIntoBytes_(width, 2), // width
483
+ ...this.breakNumberIntoBytes_(height, 2), // height
484
+ 0x00, 0x48, 0x00, 0x00, // horizresolution
485
+ 0x00, 0x48, 0x00, 0x00, // vertresolution
486
+ 0x00, 0x00, 0x00, 0x00, // reserved
487
+ 0x00, 0x01, // frame_count
488
+ 0x13,
489
+ 0x76, 0x69, 0x64, 0x65,
490
+ 0x6f, 0x6a, 0x73, 0x2d,
491
+ 0x63, 0x6f, 0x6e, 0x74,
492
+ 0x72, 0x69, 0x62, 0x2d,
493
+ 0x68, 0x6c, 0x73, 0x00,
494
+ 0x00, 0x00, 0x00, 0x00,
495
+ 0x00, 0x00, 0x00, 0x00,
496
+ 0x00, 0x00, 0x00, // compressorname
497
+ 0x00, 0x18, // depth = 24
498
+ 0x11, 0x11, // pre_defined = -1
499
+ ]);
500
+
501
+ let boxName = 'hvc1';
502
+ let sinfBox = new Uint8Array([]);
503
+ if (streamInfo.encrypted) {
504
+ sinfBox = this.sinf_(streamInfo);
505
+ boxName = 'encv';
506
+ }
507
+ return Mp4Generator.box(boxName, hvc1Bytes, hvcCBox, sinfBox);
508
+ }
509
+
510
+ /**
511
+ * Generate STSD bytes
512
+ *
513
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
514
+ * @return {!Uint8Array}
515
+ * @private
516
+ */
517
+ audioStsd_(streamInfo) {
518
+ const channelsCount = streamInfo.stream.channelsCount || 2;
519
+ const audioSamplingRate = streamInfo.stream.audioSamplingRate || 44100;
520
+ const bytes = new Uint8Array([
521
+ 0x00, 0x00, 0x00, // reserved
522
+ 0x00, 0x00, 0x00, // reserved
523
+ 0x00, 0x01, // data_reference_index
524
+ 0x00, 0x00, 0x00, 0x00,
525
+ 0x00, 0x00, 0x00, 0x00, // reserved
526
+ 0x00,
527
+ channelsCount, // channelcount
528
+ 0x00, 0x10, // sampleSize:16bits
529
+ 0x00, 0x00, 0x00, 0x00, // reserved2
530
+ ...this.breakNumberIntoBytes_(audioSamplingRate, 2), // Sample Rate
531
+ 0x00, 0x00,
532
+ ]);
533
+ return bytes;
534
+ }
535
+
536
+ /**
537
+ * Generate a .MP3 box
538
+ *
539
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
540
+ * @return {!Uint8Array}
541
+ * @private
542
+ */
543
+ mp3_(streamInfo) {
544
+ const Mp4Generator = shaka.util.Mp4Generator;
545
+ return Mp4Generator.box('.mp3', this.audioStsd_(streamInfo));
546
+ }
547
+
548
+ /**
549
+ * Generate a AC-3 box
550
+ *
551
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
552
+ * @return {!Uint8Array}
553
+ * @private
554
+ */
555
+ ac3_(streamInfo) {
556
+ const Mp4Generator = shaka.util.Mp4Generator;
557
+ const dac3Box = Mp4Generator.box('dac3', streamInfo.audioConfig);
558
+
559
+ let boxName = 'ac-3';
560
+ let sinfBox = new Uint8Array([]);
561
+ if (streamInfo.encrypted) {
562
+ sinfBox = this.sinf_(streamInfo);
563
+ boxName = 'enca';
564
+ }
565
+ return Mp4Generator.box(boxName,
566
+ this.audioStsd_(streamInfo), dac3Box, sinfBox);
567
+ }
568
+
569
+ /**
570
+ * Generate a EC-3 box
571
+ *
572
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
573
+ * @return {!Uint8Array}
574
+ * @private
575
+ */
576
+ ec3_(streamInfo) {
577
+ const Mp4Generator = shaka.util.Mp4Generator;
578
+ const dec3Box = Mp4Generator.box('dec3', streamInfo.audioConfig);
579
+
580
+ let boxName = 'ec-3';
581
+ let sinfBox = new Uint8Array([]);
582
+ if (streamInfo.encrypted) {
583
+ sinfBox = this.sinf_(streamInfo);
584
+ boxName = 'enca';
585
+ }
586
+ return Mp4Generator.box(boxName,
587
+ this.audioStsd_(streamInfo), dec3Box, sinfBox);
588
+ }
589
+
590
+ /**
591
+ * Generate a MP4A box
592
+ *
593
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
594
+ * @return {!Uint8Array}
595
+ * @private
596
+ */
597
+ mp4a_(streamInfo) {
598
+ const Mp4Generator = shaka.util.Mp4Generator;
599
+ let esdsBox;
600
+ if (streamInfo.audioConfig.byteLength > 0) {
601
+ esdsBox = Mp4Generator.box('esds', streamInfo.audioConfig);
602
+ } else {
603
+ esdsBox = Mp4Generator.box('esds', this.esds_(streamInfo));
604
+ }
605
+
606
+ let boxName = 'mp4a';
607
+ let sinfBox = new Uint8Array([]);
608
+ if (streamInfo.encrypted) {
609
+ sinfBox = this.sinf_(streamInfo);
610
+ boxName = 'enca';
611
+ }
612
+ return Mp4Generator.box(boxName,
613
+ this.audioStsd_(streamInfo), esdsBox, sinfBox);
614
+ }
615
+
616
+ /**
617
+ * Generate a ESDS box
618
+ *
619
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
620
+ * @return {!Uint8Array}
621
+ * @private
622
+ */
623
+ esds_(streamInfo) {
624
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
625
+
626
+ const id = streamInfo.id + 1;
627
+ const bandwidth = streamInfo.stream.bandwidth || 0;
628
+ const channelsCount = streamInfo.stream.channelsCount || 2;
629
+ const audioSamplingRate = streamInfo.stream.audioSamplingRate || 44100;
630
+
631
+ const audioCodec = shaka.util.ManifestParserUtils.guessCodecs(
632
+ ContentType.AUDIO, streamInfo.codecs.split(','));
633
+
634
+ const samplingFrequencyIndex = {
635
+ 96000: 0x0,
636
+ 88200: 0x1,
637
+ 64000: 0x2,
638
+ 48000: 0x3,
639
+ 44100: 0x4,
640
+ 32000: 0x5,
641
+ 24000: 0x6,
642
+ 22050: 0x7,
643
+ 16000: 0x8,
644
+ 12000: 0x9,
645
+ 11025: 0xA,
646
+ 8000: 0xB,
647
+ 7350: 0xC,
648
+ };
649
+
650
+ let indexFreq = samplingFrequencyIndex[audioSamplingRate];
651
+ // In HE AAC Sampling frequence equals to SamplingRate * 2
652
+ if (audioCodec === 'mp4a.40.5' || audioCodec === 'mp4a.40.29') {
653
+ indexFreq = samplingFrequencyIndex[audioSamplingRate * 2];
654
+ }
655
+
656
+ const audioObjectType = parseInt(audioCodec.split('.').pop(), 10);
657
+
658
+ return new Uint8Array([
659
+ 0x00, // version
660
+ 0x00, 0x00, 0x00, // flags
661
+
662
+ // ES_Descriptor
663
+ 0x03, // tag, ES_DescrTag
664
+ 0x19, // length
665
+ ...this.breakNumberIntoBytes_(id, 2), // ES_ID
666
+ 0x00, // streamDependenceFlag, URL_flag, reserved, streamPriority
667
+
668
+ // DecoderConfigDescriptor
669
+ 0x04, // tag, DecoderConfigDescrTag
670
+ 0x11, // length
671
+ 0x40, // object type
672
+ 0x15, // streamType
673
+ 0x00, 0x06, 0x00, // bufferSizeDB
674
+ ...this.breakNumberIntoBytes_(bandwidth, 4), // maxBitrate
675
+ ...this.breakNumberIntoBytes_(bandwidth, 4), // avgBitrate
676
+ // DecoderSpecificInfo
677
+ 0x05, // tag, DecoderSpecificInfoTag
678
+ 0x02, // length
679
+ // ISO/IEC 14496-3, AudioSpecificConfig
680
+ // for samplingFrequencyIndex see
681
+ // ISO/IEC 13818-7:2006, 8.1.3.2.2, Table 35
682
+ (audioObjectType << 3) | (indexFreq >>> 1),
683
+ (indexFreq << 7) | (channelsCount << 3),
684
+ 0x06, 0x01, 0x02, // GASpecificConfig
685
+ ]);
686
+ }
687
+
688
+ /**
689
+ * Generate a MVEX box
690
+ *
691
+ * @return {!Uint8Array}
692
+ * @private
693
+ */
694
+ mvex_() {
695
+ const Mp4Generator = shaka.util.Mp4Generator;
696
+ let trexs = new Uint8Array([]);
697
+ for (const streamInfo of this.streamInfos_) {
698
+ trexs = shaka.util.Uint8ArrayUtils.concat(trexs, this.trex_(streamInfo));
699
+ }
700
+ return Mp4Generator.box('mvex', trexs);
701
+ }
702
+
703
+ /**
704
+ * Generate a TREX box
705
+ *
706
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
707
+ * @return {!Uint8Array}
708
+ * @private
709
+ */
710
+ trex_(streamInfo) {
711
+ const Mp4Generator = shaka.util.Mp4Generator;
712
+ const id = streamInfo.id + 1;
713
+ const bytes = new Uint8Array([
714
+ 0x00, // version 0
715
+ 0x00, 0x00, 0x00, // flags
716
+ ...this.breakNumberIntoBytes_(id, 4), // track_ID
717
+ 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
718
+ 0x00, 0x00, 0x00, 0x00, // default_sample_duration
719
+ 0x00, 0x00, 0x00, 0x00, // default_sample_size
720
+ 0x00, 0x01, 0x00, 0x01, // default_sample_flags
721
+ ]);
722
+ return Mp4Generator.box('trex', bytes);
723
+ }
724
+
725
+ /**
726
+ * Generate a PSSH box
727
+ *
728
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
729
+ * @return {!Uint8Array}
730
+ * @private
731
+ */
732
+ pssh_(streamInfo) {
733
+ let boxes = new Uint8Array([]);
734
+ if (!streamInfo.encrypted) {
735
+ return boxes;
736
+ }
737
+
738
+ for (const drmInfo of streamInfo.stream.drmInfos) {
739
+ if (!drmInfo.initData) {
740
+ continue;
741
+ }
742
+ for (const initData of drmInfo.initData) {
743
+ boxes = shaka.util.Uint8ArrayUtils.concat(boxes, initData.initData);
744
+ }
745
+ }
746
+ return boxes;
747
+ }
748
+
749
+ /**
750
+ * Generate a SINF box
751
+ *
752
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
753
+ * @return {!Uint8Array}
754
+ * @private
755
+ */
756
+ sinf_(streamInfo) {
757
+ const Mp4Generator = shaka.util.Mp4Generator;
758
+ return Mp4Generator.box('sinf',
759
+ this.frma_(streamInfo), this.schm_(), this.schi_(streamInfo));
760
+ }
761
+
762
+ /**
763
+ * Generate a FRMA box
764
+ *
765
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
766
+ * @return {!Uint8Array}
767
+ * @private
768
+ */
769
+ frma_(streamInfo) {
770
+ const codec = streamInfo.codecs.substring(
771
+ 0, streamInfo.codecs.indexOf('.'));
772
+ const Mp4Generator = shaka.util.Mp4Generator;
773
+ const codecNumber = this.stringToCharCode_(codec);
774
+ const bytes = new Uint8Array([
775
+ ...this.breakNumberIntoBytes_(codecNumber, 4),
776
+ ]);
777
+ return Mp4Generator.box('frma', bytes);
778
+ }
779
+
780
+ /**
781
+ * Generate a SCHM box
782
+ *
783
+ * @return {!Uint8Array}
784
+ * @private
785
+ */
786
+ schm_() {
787
+ const Mp4Generator = shaka.util.Mp4Generator;
788
+ const bytes = new Uint8Array([
789
+ 0x00, // version 0
790
+ 0x00, 0x00, 0x00, // flags
791
+ 0x63, 0x65, 0x6e, 0x63, // Scheme: cenc
792
+ 0x00, 0x01, 0x00, 0x00, // Scheme version: 1.0
793
+ ]);
794
+ return Mp4Generator.box('schm', bytes);
795
+ }
796
+
797
+ /**
798
+ * Generate a SCHI box
799
+ *
800
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
801
+ * @return {!Uint8Array}
802
+ * @private
803
+ */
804
+ schi_(streamInfo) {
805
+ const Mp4Generator = shaka.util.Mp4Generator;
806
+ return Mp4Generator.box('schi', this.tenc_(streamInfo));
807
+ }
808
+
809
+ /**
810
+ * Generate a TENC box
811
+ *
812
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
813
+ * @return {!Uint8Array}
814
+ * @private
815
+ */
816
+ tenc_(streamInfo) {
817
+ // Default key ID: all zeros (dummy)
818
+ let defaultKeyId = new Uint8Array([
819
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821
+ ]);
822
+ for (const drmInfo of streamInfo.stream.drmInfos) {
823
+ if (drmInfo && drmInfo.keyIds && drmInfo.keyIds.size) {
824
+ for (const keyId of drmInfo.keyIds) {
825
+ defaultKeyId = this.hexStringToBuffer_(keyId);
826
+ }
827
+ }
828
+ }
829
+
830
+ const Mp4Generator = shaka.util.Mp4Generator;
831
+ const bytes = new Uint8Array([
832
+ 0x00, // version 0
833
+ 0x00, 0x00, 0x00, // flags
834
+ 0x00, 0x00, // Reserved fields
835
+ 0x01, // Default protected: true
836
+ 0x08, // Default per-sample IV size: 8
837
+ ]);
838
+ goog.asserts.assert(defaultKeyId, 'Default KID should be non-null');
839
+ return Mp4Generator.box('tenc', bytes, defaultKeyId);
840
+ }
841
+
842
+ /**
843
+ * Generate a Segment Data (MP4).
844
+ *
845
+ * @return {!Uint8Array}
846
+ */
847
+ segmentData() {
848
+ let result = new Uint8Array([]);
849
+ for (const streamInfo of this.streamInfos_) {
850
+ result = shaka.util.Uint8ArrayUtils.concat(result,
851
+ this.moof_(streamInfo), this.mdat_(streamInfo));
852
+ }
853
+ return result;
854
+ }
855
+
856
+ /**
857
+ * Generate a MOOF box
858
+ *
859
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
860
+ * @return {!Uint8Array}
861
+ * @private
862
+ */
863
+ moof_(streamInfo) {
864
+ const Mp4Generator = shaka.util.Mp4Generator;
865
+ return Mp4Generator.box('moof',
866
+ this.mfhd_(streamInfo), this.traf_(streamInfo));
867
+ }
868
+
869
+ /**
870
+ * Generate a MOOF box
871
+ *
872
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
873
+ * @return {!Uint8Array}
874
+ * @private
875
+ */
876
+ mfhd_(streamInfo) {
877
+ const Mp4Generator = shaka.util.Mp4Generator;
878
+ const sequenceNumber =
879
+ streamInfo.data ? streamInfo.data.sequenceNumber : 0;
880
+ const bytes = new Uint8Array([
881
+ 0x00, // version 0
882
+ 0x00, 0x00, 0x00, // flags
883
+ ...this.breakNumberIntoBytes_(sequenceNumber, 4),
884
+ ]);
885
+ return Mp4Generator.box('mfhd', bytes);
886
+ }
887
+
888
+ /**
889
+ * Generate a TRAF box
890
+ *
891
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
892
+ * @return {!Uint8Array}
893
+ * @private
894
+ */
895
+ traf_(streamInfo) {
896
+ const Mp4Generator = shaka.util.Mp4Generator;
897
+ const sampleDependencyTable = this.sdtp_(streamInfo);
898
+ const offset = sampleDependencyTable.length +
899
+ 32 + // tfhd
900
+ 20 + // tfdt
901
+ 8 + // traf header
902
+ 16 + // mfhd
903
+ 8 + // moof header
904
+ 8; // mdat header;
905
+ return Mp4Generator.box('traf',
906
+ this.tfhd_(streamInfo),
907
+ this.tfdt_(streamInfo),
908
+ this.trun_(streamInfo, offset),
909
+ sampleDependencyTable);
910
+ }
911
+
912
+ /**
913
+ * Generate a SDTP box
914
+ *
915
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
916
+ * @return {!Uint8Array}
917
+ * @private
918
+ */
919
+ sdtp_(streamInfo) {
920
+ const Mp4Generator = shaka.util.Mp4Generator;
921
+ const samples = streamInfo.data ? streamInfo.data.samples : [];
922
+ const bytes = new Uint8Array(4 + samples.length);
923
+ // leave the full box header (4 bytes) all zero
924
+ // write the sample table
925
+ for (let i = 0; i < samples.length; i++) {
926
+ const flags = samples[i].flags;
927
+ bytes[i + 4] = (flags.dependsOn << 4) |
928
+ (flags.isDependedOn << 2) |
929
+ flags.hasRedundancy;
930
+ }
931
+ return Mp4Generator.box('sdtp', bytes);
932
+ }
933
+
934
+ /**
935
+ * Generate a TFHD box
936
+ *
937
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
938
+ * @return {!Uint8Array}
939
+ * @private
940
+ */
941
+ tfhd_(streamInfo) {
942
+ const Mp4Generator = shaka.util.Mp4Generator;
943
+ const id = streamInfo.id + 1;
944
+ const bytes = new Uint8Array([
945
+ 0x00, // version 0
946
+ 0x00, 0x00, 0x3a, // flags
947
+ ...this.breakNumberIntoBytes_(id, 4), // track_ID
948
+ 0x00, 0x00, 0x00, 0x01, // sample_description_index
949
+ 0x00, 0x00, 0x00, 0x00, // default_sample_duration
950
+ 0x00, 0x00, 0x00, 0x00, // default_sample_size
951
+ 0x00, 0x00, 0x00, 0x00, // default_sample_flags
952
+ ]);
953
+ return Mp4Generator.box('tfhd', bytes);
954
+ }
955
+
956
+ /**
957
+ * Generate a TFDT box
958
+ *
959
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
960
+ * @return {!Uint8Array}
961
+ * @private
962
+ */
963
+ tfdt_(streamInfo) {
964
+ const Mp4Generator = shaka.util.Mp4Generator;
965
+ const baseMediaDecodeTime =
966
+ streamInfo.data ? streamInfo.data.baseMediaDecodeTime : 0;
967
+ const upperWordBaseMediaDecodeTime =
968
+ Math.floor(baseMediaDecodeTime / (Mp4Generator.UINT32_MAX_ + 1));
969
+ const lowerWordBaseMediaDecodeTime =
970
+ Math.floor(baseMediaDecodeTime % (Mp4Generator.UINT32_MAX_ + 1));
971
+ const bytes = new Uint8Array([
972
+ 0x01, // version 1
973
+ 0x00, 0x00, 0x00, // flags
974
+ ...this.breakNumberIntoBytes_(upperWordBaseMediaDecodeTime, 4),
975
+ ...this.breakNumberIntoBytes_(lowerWordBaseMediaDecodeTime, 4),
976
+ ]);
977
+ return Mp4Generator.box('tfdt', bytes);
978
+ }
979
+
980
+ /**
981
+ * Generate a TRUN box
982
+ *
983
+ * @param {shaka.util.Mp4Generator.StreamInfo} streamInfo
984
+ * @param {number} offset
985
+ * @return {!Uint8Array}
986
+ * @private
987
+ */
988
+ trun_(streamInfo, offset) {
989
+ const ContentType = shaka.util.ManifestParserUtils.ContentType;
990
+ const Mp4Generator = shaka.util.Mp4Generator;
991
+
992
+ const samples = streamInfo.data ? streamInfo.data.samples : [];
993
+ const samplesLength = samples.length;
994
+ const byteslen = 12 + 16 * samplesLength;
995
+ const bytes = new Uint8Array(byteslen);
996
+ offset += 8 + byteslen;
997
+ const isVideo = streamInfo.type === ContentType.VIDEO;
998
+ bytes.set(
999
+ [
1000
+ // version 1 for video with signed-int sample_composition_time_offset
1001
+ isVideo ? 0x01 : 0x00,
1002
+ 0x00, 0x0f, 0x01, // flags
1003
+ ...this.breakNumberIntoBytes_(samplesLength, 4), // sample_count
1004
+ ...this.breakNumberIntoBytes_(offset, 4), // data_offset
1005
+ ],
1006
+ 0,
1007
+ );
1008
+ for (let i = 0; i < samplesLength; i++) {
1009
+ const sample = samples[i];
1010
+ const duration = this.breakNumberIntoBytes_(sample.duration, 4);
1011
+ const size = this.breakNumberIntoBytes_(sample.size, 4);
1012
+ const flags = sample.flags;
1013
+ const cts = this.breakNumberIntoBytes_(sample.cts, 4);
1014
+ bytes.set(
1015
+ [
1016
+ ...duration, // sample_duration
1017
+ ...size, // sample_size
1018
+ (flags.isLeading << 2) | flags.dependsOn,
1019
+ (flags.isDependedOn << 6) | (flags.hasRedundancy << 4) |
1020
+ flags.isNonSync,
1021
+ flags.degradPrio & (0xf0 << 8),
1022
+ flags.degradPrio & 0x0f, // sample_flags
1023
+ ...cts, // sample_composition_time_offset
1024
+ ],
1025
+ 12 + 16 * i,
1026
+ );
1027
+ }
1028
+ return Mp4Generator.box('trun', bytes);
1029
+ }
1030
+
1031
+ /**
1032
+ * Generate a MDAT box
1033
+ *
1034
+ * @return {!Uint8Array}
1035
+ * @private
1036
+ */
1037
+ mdat_(streamInfo) {
1038
+ const Mp4Generator = shaka.util.Mp4Generator;
1039
+ const samples = streamInfo.data ? streamInfo.data.samples : [];
1040
+ let bytes = new Uint8Array([]);
1041
+ for (const sample of samples) {
1042
+ bytes = shaka.util.Uint8ArrayUtils.concat(bytes, sample.data);
1043
+ }
1044
+ return Mp4Generator.box('mdat', bytes);
1045
+ }
1046
+
1047
+
1048
+ /**
1049
+ * @param {number} number
1050
+ * @param {number} numBytes
1051
+ * @return {!Array.<number>}
1052
+ * @private
1053
+ */
1054
+ breakNumberIntoBytes_(number, numBytes) {
1055
+ const bytes = [];
1056
+ for (let byte = numBytes - 1; byte >= 0; byte--) {
1057
+ bytes.push((number >> (8 * byte)) & 0xff);
1058
+ }
1059
+ return bytes;
1060
+ }
1061
+
1062
+ /**
1063
+ * Convert a hex string to buffer.
1064
+ *
1065
+ * @param {string} str
1066
+ * @return {Uint8Array}
1067
+ * @private
1068
+ */
1069
+ hexStringToBuffer_(str) {
1070
+ const buf = new Uint8Array(str.length / 2);
1071
+ for (let i = 0; i < str.length / 2; i += 1) {
1072
+ buf[i] = parseInt(String(str[i * 2] + str[i * 2 + 1]), 16);
1073
+ }
1074
+ return buf;
1075
+ }
1076
+
1077
+ /**
1078
+ * Convert a string to char code.
1079
+ *
1080
+ * @param {string} str
1081
+ * @return {number}
1082
+ * @private
1083
+ */
1084
+ stringToCharCode_(str) {
1085
+ let code = 0;
1086
+ for (let i = 0; i < str.length; i += 1) {
1087
+ code |= str.charCodeAt(i) << ((str.length - i - 1) * 8);
1088
+ }
1089
+ return code;
1090
+ }
1091
+
1092
+ /**
1093
+ * @private
1094
+ */
1095
+ static initStaticProperties_() {
1096
+ const Mp4Generator = shaka.util.Mp4Generator;
1097
+ if (Mp4Generator.initializated_) {
1098
+ return;
1099
+ }
1100
+
1101
+ Mp4Generator.initializated_ = true;
1102
+
1103
+ const majorBrand = new Uint8Array([105, 115, 111, 109]); // isom
1104
+ const avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1
1105
+ const minorVersion = new Uint8Array([0, 0, 0, 1]);
1106
+
1107
+ Mp4Generator.FTYP_ = Mp4Generator.box(
1108
+ 'ftyp', majorBrand, minorVersion, majorBrand, avc1Brand);
1109
+ const drefBox = Mp4Generator.box('dref', Mp4Generator.DREF_);
1110
+ Mp4Generator.DINF_ = Mp4Generator.box('dinf', drefBox);
1111
+ }
1112
+
1113
+ /**
1114
+ * Generate a box
1115
+ *
1116
+ * @param {string} boxName
1117
+ * @param {...!Uint8Array} payload
1118
+ * @return {!Uint8Array}
1119
+ */
1120
+ static box(boxName, ...payload) {
1121
+ let type = shaka.util.Mp4Generator.BOX_TYPES_[boxName];
1122
+ if (!type) {
1123
+ type = [
1124
+ boxName.charCodeAt(0),
1125
+ boxName.charCodeAt(1),
1126
+ boxName.charCodeAt(2),
1127
+ boxName.charCodeAt(3),
1128
+ ];
1129
+ shaka.util.Mp4Generator.BOX_TYPES_[boxName] = type;
1130
+ }
1131
+ // make the header for the box
1132
+ let size = 8;
1133
+ // calculate the total size we need to allocate
1134
+ for (let i = payload.length - 1; i >= 0; i--) {
1135
+ size += payload[i].byteLength;
1136
+ }
1137
+ const result = new Uint8Array(size);
1138
+ result[0] = (size >> 24) & 0xff;
1139
+ result[1] = (size >> 16) & 0xff;
1140
+ result[2] = (size >> 8) & 0xff;
1141
+ result[3] = size & 0xff;
1142
+ result.set(type, 4);
1143
+
1144
+ // copy the payload into the result
1145
+ for (let i = 0, pointer = 8; i < payload.length; i++) {
1146
+ // copy payload[i] array @ offset pointer
1147
+ result.set(payload[i], pointer);
1148
+ pointer += payload[i].byteLength;
1149
+ }
1150
+ return result;
1151
+ }
1152
+ };
1153
+
1154
+ /**
1155
+ * @private {boolean}
1156
+ */
1157
+ shaka.util.Mp4Generator.initializated_ = false;
1158
+
1159
+
1160
+ /**
1161
+ * @private {number}
1162
+ */
1163
+ shaka.util.Mp4Generator.UINT32_MAX_ = Math.pow(2, 32) - 1;
1164
+
1165
+ /**
1166
+ * @private {!Object.<string, !Array.<number>>}
1167
+ */
1168
+ shaka.util.Mp4Generator.BOX_TYPES_ = {};
1169
+
1170
+ /**
1171
+ * @private {{video: !Uint8Array, audio: !Uint8Array}}
1172
+ */
1173
+ shaka.util.Mp4Generator.HDLR_TYPES_ = {
1174
+ video: new Uint8Array([
1175
+ 0x00, // version 0
1176
+ 0x00, 0x00, 0x00, // flags
1177
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
1178
+ 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'
1179
+ 0x00, 0x00, 0x00, 0x00, // reserved
1180
+ 0x00, 0x00, 0x00, 0x00, // reserved
1181
+ 0x00, 0x00, 0x00, 0x00, // reserved
1182
+ 0x56, 0x69, 0x64, 0x65,
1183
+ 0x6f, 0x48, 0x61, 0x6e,
1184
+ 0x64, 0x6c, 0x65, 0x72, 0x00, // name: 'VideoHandler'
1185
+ ]),
1186
+ audio: new Uint8Array([
1187
+ 0x00, // version 0
1188
+ 0x00, 0x00, 0x00, // flags
1189
+ 0x00, 0x00, 0x00, 0x00, // pre_defined
1190
+ 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun'
1191
+ 0x00, 0x00, 0x00, 0x00, // reserved
1192
+ 0x00, 0x00, 0x00, 0x00, // reserved
1193
+ 0x00, 0x00, 0x00, 0x00, // reserved
1194
+ 0x53, 0x6f, 0x75, 0x6e,
1195
+ 0x64, 0x48, 0x61, 0x6e,
1196
+ 0x64, 0x6c, 0x65, 0x72, 0x00, // name: 'SoundHandler'
1197
+ ]),
1198
+ };
1199
+
1200
+ /**
1201
+ * @private {!Uint8Array}
1202
+ */
1203
+ shaka.util.Mp4Generator.STTS_ = new Uint8Array([
1204
+ 0x00, // version
1205
+ 0x00, 0x00, 0x00, // flags
1206
+ 0x00, 0x00, 0x00, 0x00, // entry_count
1207
+ ]);
1208
+
1209
+ /**
1210
+ * @private {!Uint8Array}
1211
+ */
1212
+ shaka.util.Mp4Generator.STSC_ = new Uint8Array([
1213
+ 0x00, // version
1214
+ 0x00, 0x00, 0x00, // flags
1215
+ 0x00, 0x00, 0x00, 0x00, // entry_count
1216
+ ]);
1217
+
1218
+ /**
1219
+ * @private {!Uint8Array}
1220
+ */
1221
+ shaka.util.Mp4Generator.STCO_ = new Uint8Array([
1222
+ 0x00, // version
1223
+ 0x00, 0x00, 0x00, // flags
1224
+ 0x00, 0x00, 0x00, 0x00, // entry_count
1225
+ ]);
1226
+
1227
+ /**
1228
+ * @private {!Uint8Array}
1229
+ */
1230
+ shaka.util.Mp4Generator.STSZ_ = new Uint8Array([
1231
+ 0x00, // version
1232
+ 0x00, 0x00, 0x00, // flags
1233
+ 0x00, 0x00, 0x00, 0x00, // sample_size
1234
+ 0x00, 0x00, 0x00, 0x00, // sample_count
1235
+ ]);
1236
+
1237
+ /**
1238
+ * @private {!Uint8Array}
1239
+ */
1240
+ shaka.util.Mp4Generator.VMHD_ = new Uint8Array([
1241
+ 0x00, // version
1242
+ 0x00, 0x00, 0x01, // flags
1243
+ 0x00, 0x00, // graphicsmode
1244
+ 0x00, 0x00,
1245
+ 0x00, 0x00,
1246
+ 0x00, 0x00, // opcolor
1247
+ ]);
1248
+
1249
+ /**
1250
+ * @private {!Uint8Array}
1251
+ */
1252
+ shaka.util.Mp4Generator.SMHD_ = new Uint8Array([
1253
+ 0x00, // version
1254
+ 0x00, 0x00, 0x00, // flags
1255
+ 0x00, 0x00, // balance, 0 means centered
1256
+ 0x00, 0x00, // reserved
1257
+ ]);
1258
+
1259
+ /**
1260
+ * @private {!Uint8Array}
1261
+ */
1262
+ shaka.util.Mp4Generator.STSD_ = new Uint8Array([
1263
+ 0x00, // version 0
1264
+ 0x00, 0x00, 0x00, // flags
1265
+ 0x00, 0x00, 0x00, 0x01, // entry_count
1266
+ ]);
1267
+
1268
+ /**
1269
+ * @private {!Uint8Array}
1270
+ */
1271
+ shaka.util.Mp4Generator.FTYP_ = new Uint8Array([]);
1272
+
1273
+ /**
1274
+ * @private {!Uint8Array}
1275
+ */
1276
+ shaka.util.Mp4Generator.DREF_ = new Uint8Array([
1277
+ 0x00, // version 0
1278
+ 0x00, 0x00, 0x00, // flags
1279
+ 0x00, 0x00, 0x00, 0x01, // entry_count
1280
+ 0x00, 0x00, 0x00, 0x0c, // entry_size
1281
+ 0x75, 0x72, 0x6c, 0x20, // 'url' type
1282
+ 0x00, // version 0
1283
+ 0x00, 0x00, 0x01, // entry_flags
1284
+ ]);
1285
+
1286
+ /**
1287
+ * @private {!Uint8Array}
1288
+ */
1289
+ shaka.util.Mp4Generator.DINF_ = new Uint8Array([]);
1290
+
1291
+ /**
1292
+ * @typedef {{
1293
+ * id: number,
1294
+ * type: string,
1295
+ * codecs: string,
1296
+ * encrypted: boolean,
1297
+ * timescale: number,
1298
+ * duration: number,
1299
+ * videoNalus: !Array.<string>,
1300
+ * audioConfig: !Uint8Array,
1301
+ * videoConfig: !Uint8Array,
1302
+ * data: ?shaka.util.Mp4Generator.Data,
1303
+ * stream: !shaka.extern.Stream
1304
+ * }}
1305
+ *
1306
+ * @property {number} id
1307
+ * A unique ID
1308
+ * @property {string} type
1309
+ * Indicate the content type: 'video' or 'audio'.
1310
+ * @property {string} codecs
1311
+ * <i>Defaults to '' (i.e., unknown / not needed).</i> <br>
1312
+ * The Stream's codecs, e.g., 'avc1.4d4015' or 'vp9'<br>
1313
+ * See {@link https://tools.ietf.org/html/rfc6381}
1314
+ * @property {boolean} encrypted
1315
+ * Indicate if the stream is encrypted.
1316
+ * @property {number} timescale
1317
+ * The Stream's timescale.
1318
+ * @property {number} duration
1319
+ * The Stream's duration.
1320
+ * @property {!Array.<string>} videoNalus
1321
+ * The stream's video nalus.
1322
+ * @property {!Uint8Array} audioConfig
1323
+ * The stream's audio config.
1324
+ * @property {!Uint8Array} videoConfig
1325
+ * The stream's video config.
1326
+ * @property {?shaka.util.Mp4Generator.Data} data
1327
+ * The stream's data.
1328
+ * @property {!shaka.extern.Stream} stream
1329
+ * The Stream.
1330
+ */
1331
+ shaka.util.Mp4Generator.StreamInfo;
1332
+
1333
+ /**
1334
+ * @typedef {{
1335
+ * sequenceNumber: number,
1336
+ * baseMediaDecodeTime: number,
1337
+ * samples: !Array.<shaka.util.Mp4Generator.Mp4Sample>
1338
+ * }}
1339
+ *
1340
+ * @property {number} sequenceNumber
1341
+ * The sequence number.
1342
+ * @property {number} baseMediaDecodeTime
1343
+ * The base media decode time.
1344
+ * @property {!Array.<shaka.util.Mp4Generator.Mp4Sample>} samples
1345
+ * The data samples.
1346
+ */
1347
+ shaka.util.Mp4Generator.Data;
1348
+
1349
+ /**
1350
+ * @typedef {{
1351
+ * data: !Uint8Array,
1352
+ * size: number,
1353
+ * duration: number,
1354
+ * cts: number,
1355
+ * flags: !shaka.util.Mp4Generator.Mp4SampleFlags
1356
+ * }}
1357
+ *
1358
+ * @property {!Uint8Array} data
1359
+ * The sample data.
1360
+ * @property {number} size
1361
+ * The sample size.
1362
+ * @property {number} duration
1363
+ * The sample duration.
1364
+ * @property {number} cts
1365
+ * The sample composition time.
1366
+ * @property {!shaka.util.Mp4Generator.Mp4SampleFlags} flags
1367
+ * The sample flags.
1368
+ */
1369
+ shaka.util.Mp4Generator.Mp4Sample;
1370
+
1371
+ /**
1372
+ * @typedef {{
1373
+ * isLeading: number,
1374
+ * isDependedOn: number,
1375
+ * hasRedundancy: number,
1376
+ * degradPrio: number,
1377
+ * dependsOn: number,
1378
+ * isNonSync: number
1379
+ * }}
1380
+ *
1381
+ * @property {number} isLeading
1382
+ * @property {number} isDependedOn
1383
+ * @property {number} hasRedundancy
1384
+ * @property {number} degradPrio
1385
+ * @property {number} dependsOn
1386
+ * @property {number} isNonSync
1387
+ */
1388
+ shaka.util.Mp4Generator.Mp4SampleFlags;