shaka-player 4.3.10 → 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 (316) hide show
  1. package/.github/workflows/release-please.yaml +7 -0
  2. package/AUTHORS +9 -0
  3. package/CHANGELOG.md +295 -200
  4. package/CONTRIBUTORS +8 -0
  5. package/LICENSE +32 -0
  6. package/README.md +63 -10
  7. package/demo/autoTemplate.txt +40 -5
  8. package/demo/close_button.js +11 -0
  9. package/demo/common/asset.js +13 -1
  10. package/demo/common/assets.js +53 -3
  11. package/demo/common/message_ids.js +25 -1
  12. package/demo/config.js +69 -10
  13. package/demo/customWarning.txt +2 -2
  14. package/demo/index.html +3 -1
  15. package/demo/locales/en.json +26 -2
  16. package/demo/locales/source.json +105 -9
  17. package/demo/main.js +52 -9
  18. package/demo/search.js +3 -1
  19. package/demo/service_worker.js +3 -0
  20. package/dist/controls.css +1 -1
  21. package/dist/controls.css.map +1 -1
  22. package/dist/demo.compiled.debug.js +124 -112
  23. package/dist/demo.compiled.debug.map +3 -3
  24. package/dist/demo.compiled.js +124 -112
  25. package/dist/demo.compiled.map +3 -3
  26. package/dist/deps.js +46 -28
  27. package/dist/locales.js +28 -28
  28. package/dist/receiver.compiled.debug.js +52 -46
  29. package/dist/receiver.compiled.debug.map +3 -3
  30. package/dist/receiver.compiled.js +52 -46
  31. package/dist/receiver.compiled.map +3 -3
  32. package/dist/shaka-player.compiled.d.ts +676 -391
  33. package/dist/shaka-player.compiled.debug.d.ts +676 -391
  34. package/dist/shaka-player.compiled.debug.externs.js +1188 -616
  35. package/dist/shaka-player.compiled.debug.js +1045 -700
  36. package/dist/shaka-player.compiled.debug.map +4 -4
  37. package/dist/shaka-player.compiled.externs.js +1188 -616
  38. package/dist/shaka-player.compiled.js +1094 -933
  39. package/dist/shaka-player.compiled.map +4 -4
  40. package/dist/shaka-player.ui.d.ts +677 -392
  41. package/dist/shaka-player.ui.debug.d.ts +677 -392
  42. package/dist/shaka-player.ui.debug.externs.js +1023 -451
  43. package/dist/shaka-player.ui.debug.js +1100 -739
  44. package/dist/shaka-player.ui.debug.map +4 -4
  45. package/dist/shaka-player.ui.externs.js +1023 -451
  46. package/dist/shaka-player.ui.js +1244 -1071
  47. package/dist/shaka-player.ui.map +4 -4
  48. package/docs/tutorials/ad_monetization.md +15 -1
  49. package/docs/tutorials/application-level-redirects.md +1 -1
  50. package/docs/tutorials/config.md +9 -5
  51. package/docs/tutorials/drm-config.md +61 -0
  52. package/docs/tutorials/fairplay.md +19 -4
  53. package/docs/tutorials/license-server-auth.md +4 -4
  54. package/docs/tutorials/license-wrapping.md +2 -2
  55. package/docs/tutorials/ui-customization.md +7 -3
  56. package/docs/tutorials/ui.md +7 -7
  57. package/docs/tutorials/upgrade.md +3 -0
  58. package/externs/ima.js +123 -2
  59. package/externs/isoboxer.js +217 -0
  60. package/externs/mediakeys.js +18 -0
  61. package/externs/mux.js +1 -105
  62. package/externs/pictureinpicture.js +48 -0
  63. package/externs/shaka/ads.js +61 -1
  64. package/externs/shaka/cea.js +110 -0
  65. package/externs/shaka/codecs.js +32 -0
  66. package/externs/shaka/manifest.js +101 -1
  67. package/externs/shaka/manifest_parser.js +0 -10
  68. package/externs/shaka/net.js +36 -7
  69. package/externs/shaka/offline.js +8 -1
  70. package/externs/shaka/player.js +220 -21
  71. package/externs/shaka/text.js +1 -382
  72. package/externs/shaka/transmuxer.js +59 -0
  73. package/karma.conf.js +13 -0
  74. package/lib/abr/simple_abr_manager.js +6 -3
  75. package/lib/ads/ad_manager.js +60 -2
  76. package/lib/ads/client_side_ad.js +86 -0
  77. package/lib/ads/client_side_ad_manager.js +79 -3
  78. package/lib/ads/server_side_ad.js +86 -0
  79. package/lib/ads/server_side_ad_manager.js +13 -0
  80. package/lib/cast/cast_utils.js +1 -0
  81. package/lib/cea/cea608_data_channel.js +24 -14
  82. package/lib/cea/cea608_memory.js +5 -2
  83. package/lib/cea/cea708_service.js +8 -9
  84. package/lib/cea/cea708_window.js +1 -2
  85. package/lib/cea/cea_decoder.js +23 -6
  86. package/lib/cea/cea_utils.js +25 -2
  87. package/lib/cea/dummy_caption_decoder.js +21 -0
  88. package/lib/cea/dummy_cea_parser.js +1 -3
  89. package/lib/cea/mp4_cea_parser.js +15 -10
  90. package/lib/cea/ts_cea_parser.js +69 -0
  91. package/lib/dash/content_protection.js +32 -2
  92. package/lib/dash/dash_parser.js +93 -31
  93. package/lib/dash/mpd_utils.js +6 -25
  94. package/lib/dash/segment_base.js +12 -14
  95. package/lib/dash/segment_list.js +10 -6
  96. package/lib/dash/segment_template.js +349 -32
  97. package/lib/dependencies/all.js +8 -0
  98. package/lib/hls/hls_classes.js +33 -8
  99. package/lib/hls/hls_parser.js +805 -191
  100. package/lib/hls/manifest_text_parser.js +4 -14
  101. package/lib/media/adaptation_set_criteria.js +43 -3
  102. package/lib/media/closed_caption_parser.js +74 -12
  103. package/lib/media/drm_engine.js +189 -49
  104. package/lib/media/gap_jumping_controller.js +1 -1
  105. package/lib/media/manifest_parser.js +34 -0
  106. package/lib/media/media_source_capabilities.js +10 -0
  107. package/lib/media/media_source_engine.js +475 -231
  108. package/lib/media/playhead.js +1 -1
  109. package/lib/media/presentation_timeline.js +62 -0
  110. package/lib/media/segment_index.js +50 -14
  111. package/lib/media/segment_prefetch.js +277 -0
  112. package/lib/media/segment_reference.js +70 -4
  113. package/lib/media/streaming_engine.js +258 -81
  114. package/lib/media/video_wrapper.js +15 -7
  115. package/lib/mss/content_protection.js +353 -0
  116. package/lib/mss/mss_parser.js +1081 -0
  117. package/lib/net/networking_engine.js +60 -10
  118. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  119. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  120. package/lib/offline/manifest_converter.js +6 -0
  121. package/lib/offline/storage.js +2 -4
  122. package/lib/player.js +309 -105
  123. package/lib/polyfill/media_capabilities.js +43 -3
  124. package/lib/polyfill/patchedmediakeys_apple.js +5 -0
  125. package/lib/polyfill/patchedmediakeys_nop.js +5 -0
  126. package/lib/polyfill/patchedmediakeys_webkit.js +5 -0
  127. package/lib/text/cue.js +208 -130
  128. package/lib/text/lrc_text_parser.js +2 -2
  129. package/lib/text/mp4_vtt_parser.js +2 -2
  130. package/lib/text/sbv_text_parser.js +1 -1
  131. package/lib/text/simple_text_displayer.js +2 -1
  132. package/lib/text/srt_text_parser.js +9 -1
  133. package/lib/text/ssa_text_parser.js +2 -2
  134. package/lib/text/text_engine.js +3 -21
  135. package/lib/text/text_utils.js +71 -20
  136. package/lib/text/ui_text_displayer.js +14 -14
  137. package/lib/text/vtt_text_parser.js +22 -14
  138. package/lib/transmuxer/aac_transmuxer.js +224 -0
  139. package/lib/transmuxer/ac3.js +142 -0
  140. package/lib/transmuxer/ac3_transmuxer.js +212 -0
  141. package/lib/transmuxer/adts.js +232 -0
  142. package/lib/transmuxer/ec3.js +103 -0
  143. package/lib/transmuxer/ec3_transmuxer.js +212 -0
  144. package/lib/transmuxer/h264.js +324 -0
  145. package/lib/transmuxer/mp3_transmuxer.js +204 -0
  146. package/lib/transmuxer/mpeg_audio.js +196 -0
  147. package/lib/transmuxer/mpeg_ts_transmuxer.js +182 -0
  148. package/lib/transmuxer/mss_transmuxer.js +389 -0
  149. package/lib/{media/transmuxer.js → transmuxer/muxjs_transmuxer.js} +34 -80
  150. package/lib/transmuxer/transmuxer_engine.js +161 -0
  151. package/lib/transmuxer/ts_transmuxer.js +738 -0
  152. package/lib/util/cmcd_manager.js +131 -71
  153. package/lib/util/error.js +62 -26
  154. package/lib/util/exp_golomb.js +220 -0
  155. package/lib/util/fairplay_utils.js +64 -13
  156. package/lib/util/id3_utils.js +56 -3
  157. package/lib/util/language_utils.js +11 -8
  158. package/lib/util/manifest_parser_utils.js +3 -0
  159. package/lib/util/mime_utils.js +44 -7
  160. package/lib/util/mp4_box_parsers.js +233 -5
  161. package/lib/util/mp4_generator.js +1381 -0
  162. package/lib/util/periods.js +40 -34
  163. package/lib/util/platform.js +17 -3
  164. package/lib/util/player_configuration.js +38 -1
  165. package/lib/util/stream_utils.js +138 -27
  166. package/lib/util/text_parser.js +1 -1
  167. package/lib/util/ts_parser.js +470 -47
  168. package/lib/util/xml_utils.js +16 -3
  169. package/maintained-branches.md +2 -2
  170. package/package.json +3 -1
  171. package/roadmap.md +21 -6
  172. package/shaka-player.uncompiled.js +18 -0
  173. package/test/abr/simple_abr_manager_unit.js +32 -4
  174. package/test/ads/ad_manager_unit.js +18 -2
  175. package/test/cast/cast_utils_unit.js +7 -2
  176. package/test/cea/cea608_memory_unit.js +24 -0
  177. package/test/cea/cea_decoder_unit.js +33 -0
  178. package/test/dash/dash_parser_content_protection_unit.js +93 -3
  179. package/test/dash/dash_parser_live_unit.js +56 -13
  180. package/test/dash/dash_parser_manifest_unit.js +70 -2
  181. package/test/dash/dash_parser_segment_base_unit.js +14 -9
  182. package/test/dash/dash_parser_segment_template_unit.js +286 -6
  183. package/test/demo/demo_unit.js +5 -1
  184. package/test/hls/hls_live_unit.js +188 -28
  185. package/test/hls/hls_parser_unit.js +250 -109
  186. package/test/hls/manifest_text_parser_unit.js +18 -13
  187. package/test/media/adaptation_set_criteria_unit.js +46 -14
  188. package/test/media/adaptation_set_unit.js +2 -0
  189. package/test/media/drm_engine_integration.js +11 -8
  190. package/test/media/drm_engine_unit.js +220 -7
  191. package/test/media/media_source_engine_integration.js +122 -38
  192. package/test/media/media_source_engine_unit.js +133 -153
  193. package/test/media/playhead_unit.js +3 -0
  194. package/test/media/presentation_timeline_unit.js +51 -0
  195. package/test/media/segment_index_unit.js +52 -0
  196. package/test/media/segment_prefetch_unit.js +243 -0
  197. package/test/media/streaming_engine_integration.js +9 -3
  198. package/test/media/streaming_engine_unit.js +440 -59
  199. package/test/mss/mss_parser_content_protection_unit.js +49 -0
  200. package/test/mss/mss_parser_unit.js +472 -0
  201. package/test/mss/mss_player_integration.js +123 -0
  202. package/test/offline/manifest_convert_unit.js +9 -0
  203. package/test/offline/storage_integration.js +6 -1
  204. package/test/player_unit.js +386 -133
  205. package/test/polyfill/media_capabilities_unit.js +18 -0
  206. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  207. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  208. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  209. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  210. package/test/test/assets/hls-raw-aac/manifest.m3u8 +4 -0
  211. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +14 -0
  212. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  213. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  214. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  215. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  216. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  217. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  218. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  219. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  220. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +31 -0
  221. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  222. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  223. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  224. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  225. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  226. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  227. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  228. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  229. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +31 -0
  230. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +13 -0
  231. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  232. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  233. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  234. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  235. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +4 -0
  236. package/test/test/assets/hls-ts-aac/playlist.m3u8 +23 -0
  237. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  238. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  239. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  240. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  241. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  242. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  243. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  244. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  245. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  246. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  247. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  248. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  249. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  250. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  251. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +19 -0
  252. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  253. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  254. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  255. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  256. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  257. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  258. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +19 -0
  259. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  260. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  261. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  262. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  263. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  264. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  265. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +25 -0
  266. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +13 -0
  267. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  268. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  269. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  270. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  271. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +17 -0
  272. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  273. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  274. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  275. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  276. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  277. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  278. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +4 -0
  279. package/test/test/boot.js +7 -2
  280. package/test/test/util/fake_ad.js +99 -0
  281. package/test/test/util/fake_ad_manager.js +7 -1
  282. package/test/test/util/fake_networking_engine.js +41 -14
  283. package/test/test/util/fake_segment_prefetch.js +81 -0
  284. package/test/test/util/manifest_generator.js +19 -5
  285. package/test/test/util/mss_parser_util.js +115 -0
  286. package/test/test/util/offline_utils.js +1 -0
  287. package/test/test/util/simple_fakes.js +12 -3
  288. package/test/test/util/streaming_engine_util.js +14 -4
  289. package/test/test/util/ttml_utils.js +2 -2
  290. package/test/text/cue_integration.js +1 -1
  291. package/test/text/srt_text_parser_unit.js +78 -0
  292. package/test/text/text_engine_unit.js +17 -8
  293. package/test/text/ui_text_displayer_unit.js +4 -4
  294. package/test/text/vtt_text_parser_unit.js +59 -40
  295. package/test/text/web_vtt_generator_unit.js +9 -3
  296. package/test/{media/transmuxer_integration.js → transmuxer/muxjs_transmuxer_integration.js} +30 -33
  297. package/test/transmuxer/transmuxer_engine_integration.js +60 -0
  298. package/test/transmuxer/transmuxer_integration.js +296 -0
  299. package/test/util/cmcd_manager_unit.js +162 -13
  300. package/test/util/language_utils_unit.js +9 -2
  301. package/test/util/mp4_box_parsers_unit.js +39 -4
  302. package/test/util/periods_unit.js +34 -26
  303. package/test/util/stream_utils_unit.js +60 -107
  304. package/ui/controls.js +19 -1
  305. package/ui/controls.less +1 -0
  306. package/ui/externs/ui.js +11 -1
  307. package/ui/language_utils.js +15 -0
  308. package/ui/less/thumbnails.less +26 -0
  309. package/ui/locales/oc.json +42 -0
  310. package/ui/pip_button.js +83 -2
  311. package/ui/range_element.js +15 -0
  312. package/ui/resolution_selection.js +9 -2
  313. package/ui/seek_bar.js +223 -0
  314. package/ui/ui.js +5 -0
  315. package/lib/cea/i_caption_decoder.js +0 -51
  316. package/lib/cea/i_cea_parser.js +0 -68
@@ -8,6 +8,7 @@ goog.provide('shaka.util.TsParser');
8
8
 
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.log');
11
+ goog.require('shaka.util.ExpGolomb');
11
12
  goog.require('shaka.util.Id3Utils');
12
13
  goog.require('shaka.util.Uint8ArrayUtils');
13
14
 
@@ -56,14 +57,28 @@ shaka.util.TsParser = class {
56
57
  this.id3Data_ = [];
57
58
  }
58
59
 
60
+ /**
61
+ * Clear previous data
62
+ *
63
+ * @export
64
+ */
65
+ clearData() {
66
+ this.videoStartTime_ = null;
67
+ this.videoData_ = [];
68
+ this.audioStartTime_ = null;
69
+ this.audioData_ = [];
70
+ this.id3Data_ = [];
71
+ }
72
+
59
73
  /**
60
74
  * Parse the given data
61
75
  *
62
76
  * @param {Uint8Array} data
63
77
  * @return {!shaka.util.TsParser}
78
+ * @export
64
79
  */
65
80
  parse(data) {
66
- const timescale = shaka.util.TsParser.Timescale_;
81
+ const timescale = shaka.util.TsParser.Timescale;
67
82
  const packetLength = shaka.util.TsParser.PacketLength_;
68
83
 
69
84
  // A TS fragment should contain at least 3 TS packets, a PAT, a PMT, and
@@ -79,7 +94,7 @@ shaka.util.TsParser = class {
79
94
 
80
95
  // loop through TS packets
81
96
  for (let start = syncOffset; start < length; start += packetLength) {
82
- if (data[start] === 0x47) {
97
+ if (data[start] == 0x47) {
83
98
  const payloadUnitStartIndicator = !!(data[start + 1] & 0x40);
84
99
  // pid is a 13-bit field starting at the last 5 bits of TS[1]
85
100
  const pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2];
@@ -91,7 +106,7 @@ shaka.util.TsParser = class {
91
106
  if (adaptationFieldControl > 1) {
92
107
  offset = start + 5 + data[start + 4];
93
108
  // continue if there is only adaptation field
94
- if (offset === start + packetLength) {
109
+ if (offset == start + packetLength) {
95
110
  continue;
96
111
  }
97
112
  } else {
@@ -113,7 +128,7 @@ shaka.util.TsParser = class {
113
128
  offset += data[offset] + 1;
114
129
  }
115
130
 
116
- const parsedPIDs = this.parsePMT(data, offset);
131
+ const parsedPIDs = this.parsePMT_(data, offset);
117
132
 
118
133
  // only update track id if track PID found while parsing PMT
119
134
  // this is to avoid resetting the PID to -1 in case
@@ -146,10 +161,12 @@ shaka.util.TsParser = class {
146
161
  }
147
162
  case this.videoPid_: {
148
163
  const videoData = data.subarray(offset, start + packetLength);
149
- if (this.videoStartTime_ == null) {
150
- const pes = this.parsePES(videoData);
151
- if (pes && pes.pts != null) {
152
- this.videoStartTime_ = pes.pts / timescale;
164
+ const pes = this.parsePES_(videoData, /* isVideo= */ true);
165
+ if (pes && pes.pts != null) {
166
+ const startTime = Math.min(pes.dts, pes.pts) / timescale;
167
+ if (this.videoStartTime_ == null ||
168
+ this.videoStartTime_ > startTime) {
169
+ this.videoStartTime_ = startTime;
153
170
  }
154
171
  }
155
172
  this.videoData_.push(videoData);
@@ -157,10 +174,12 @@ shaka.util.TsParser = class {
157
174
  }
158
175
  case this.audioPid_: {
159
176
  const audioData = data.subarray(offset, start + packetLength);
160
- if (this.audioStartTime_ == null) {
161
- const pes = this.parsePES(audioData);
162
- if (pes && pes.pts != null) {
163
- this.audioStartTime_ = pes.pts / timescale;
177
+ const pes = this.parsePES_(audioData);
178
+ if (pes && pes.pts != null) {
179
+ const startTime = Math.min(pes.dts, pes.pts) / timescale;
180
+ if (this.audioStartTime_ == null ||
181
+ this.audioStartTime_ > startTime) {
182
+ this.audioStartTime_ = startTime;
164
183
  }
165
184
  }
166
185
  this.audioData_.push(audioData);
@@ -199,8 +218,9 @@ shaka.util.TsParser = class {
199
218
  * @param {Uint8Array} data
200
219
  * @param {number} offset
201
220
  * @return {!shaka.util.TsParser.PMT}
221
+ * @private
202
222
  */
203
- parsePMT(data, offset) {
223
+ parsePMT_(data, offset) {
204
224
  const result = {
205
225
  audio: -1,
206
226
  video: -1,
@@ -218,20 +238,49 @@ shaka.util.TsParser = class {
218
238
  offset += 12 + programInfoLength;
219
239
  while (offset < tableEnd) {
220
240
  const pid = ((data[offset + 1] & 0x1f) << 8) | data[offset + 2];
241
+ const esInfoLength = ((data[offset + 3] & 0x0f) << 8) | data[offset + 4];
221
242
  switch (data[offset]) {
243
+ case 0x06:
244
+ // stream_type 6 can mean a lot of different things in case of DVB.
245
+ // We need to look at the descriptors. Right now, we're only
246
+ // interested in AC-3 and EC-3 audio, so we do the descriptor parsing
247
+ // only when we don't have an audio PID yet.
248
+ if (result.audio == -1 && esInfoLength > 0) {
249
+ let parsePos = offset + 5;
250
+ let remaining = esInfoLength;
251
+ while (remaining > 2) {
252
+ const descriptorId = data[parsePos];
253
+ switch (descriptorId) {
254
+ // DVB Descriptor for AC-3
255
+ case 0x6a:
256
+ result.audio = pid;
257
+ result.audioCodec = 'ac3';
258
+ break;
259
+ // DVB Descriptor for EC-3
260
+ case 0x7a:
261
+ result.audio = pid;
262
+ result.audioCodec = 'ec3';
263
+ break;
264
+ }
265
+ const descriptorLen = data[parsePos + 1] + 2;
266
+ parsePos += descriptorLen;
267
+ remaining -= descriptorLen;
268
+ }
269
+ }
270
+ break;
222
271
  // SAMPLE-AES AAC
223
272
  case 0xcf:
224
273
  break;
225
274
  // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)
226
275
  case 0x0f:
227
- if (result.audio === -1) {
276
+ if (result.audio == -1) {
228
277
  result.audio = pid;
229
278
  result.audioCodec = 'aac';
230
279
  }
231
280
  break;
232
281
  // Packetized metadata (ID3)
233
282
  case 0x15:
234
- if (result.id3 === -1) {
283
+ if (result.id3 == -1) {
235
284
  result.id3 = pid;
236
285
  }
237
286
  break;
@@ -240,7 +289,7 @@ shaka.util.TsParser = class {
240
289
  break;
241
290
  // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)
242
291
  case 0x1b:
243
- if (result.video === -1) {
292
+ if (result.video == -1) {
244
293
  result.video = pid;
245
294
  result.videoCodec = 'avc';
246
295
  }
@@ -249,25 +298,40 @@ shaka.util.TsParser = class {
249
298
  // or ISO/IEC 13818-3 (MPEG-2 halved sample rate audio)
250
299
  case 0x03:
251
300
  case 0x04:
252
- if (result.audio === -1) {
301
+ if (result.audio == -1) {
253
302
  result.audio = pid;
254
303
  result.audioCodec = 'mp3';
255
304
  }
256
305
  break;
257
306
  // HEVC
258
307
  case 0x24:
259
- if (result.video === -1) {
308
+ if (result.video == -1) {
260
309
  result.video = pid;
261
310
  result.videoCodec = 'hvc';
262
311
  }
263
312
  break;
313
+ // AC-3
314
+ case 0x81:
315
+ if (result.audio == -1) {
316
+ result.audio = pid;
317
+ result.audioCodec = 'ac3';
318
+ }
319
+ break;
320
+ // EC-3
321
+ case 0x84:
322
+ case 0x87:
323
+ if (result.audio == -1) {
324
+ result.audio = pid;
325
+ result.audioCodec = 'ec3';
326
+ }
327
+ break;
264
328
  default:
265
329
  // shaka.log.warning('Unknown stream type:', data[offset]);
266
330
  break;
267
331
  }
268
332
  // move to the next table entry
269
333
  // skip past the elementary stream descriptors, if present
270
- offset += (((data[offset + 3] & 0x0f) << 8) | data[offset + 4]) + 5;
334
+ offset += esInfoLength + 5;
271
335
  }
272
336
  return result;
273
337
  }
@@ -276,9 +340,11 @@ shaka.util.TsParser = class {
276
340
  * Parse PES
277
341
  *
278
342
  * @param {Uint8Array} data
279
- * @return {?shaka.util.TsParser.PES}
343
+ * @param {boolean=} isVideo
344
+ * @return {?shaka.extern.MPEG_PES}
345
+ * @private
280
346
  */
281
- parsePES(data) {
347
+ parsePES_(data, isVideo = false) {
282
348
  const startPrefix = (data[0] << 16) | (data[1] << 8) | data[2];
283
349
  // In certain live streams, the start of a TS fragment has ts packets
284
350
  // that are frame data that is continuing from the previous fragment. This
@@ -286,15 +352,21 @@ shaka.util.TsParser = class {
286
352
  if (startPrefix !== 1) {
287
353
  return null;
288
354
  }
289
- /** @type {shaka.util.TsParser.PES} */
355
+ /** @type {shaka.extern.MPEG_PES} */
290
356
  const pes = {
291
357
  data: new Uint8Array(0),
292
358
  // get the packet length, this will be 0 for video
293
- packetLength: 6 + ((data[4] << 8) | data[5]),
359
+ packetLength: ((data[4] << 8) | data[5]),
294
360
  pts: null,
295
361
  dts: null,
296
362
  };
297
363
 
364
+ // If it is video, we expect the packet length to be 0. When the PES packet
365
+ // length is set to zero, the PES packet can be any length.
366
+ if (isVideo && pes.packetLength != 0) {
367
+ return null;
368
+ }
369
+
298
370
  // PES packets may be annotated with a PTS value, or a PTS value
299
371
  // and a DTS value. Determine what combination of values is
300
372
  // available to work with.
@@ -337,17 +409,143 @@ shaka.util.TsParser = class {
337
409
  return pes;
338
410
  }
339
411
 
412
+ /**
413
+ * Parse AVC Nalus
414
+ *
415
+ * The code is based on hls.js
416
+ * Credit to https://github.com/video-dev/hls.js/blob/master/src/demux/tsdemuxer.ts
417
+ *
418
+ * @param {shaka.extern.MPEG_PES} pes
419
+ * @param {?shaka.extern.MPEG_PES=} nextPes
420
+ * @return {!Array.<shaka.extern.VideoNalu>}
421
+ * @export
422
+ */
423
+ parseAvcNalus(pes, nextPes) {
424
+ const timescale = shaka.util.TsParser.Timescale;
425
+ const time = pes.pts ? pes.pts / timescale : null;
426
+ let data = pes.data;
427
+ let len = data.byteLength;
428
+
429
+ // A NALU does not contain is its size.
430
+ // The Annex B specification solves this by requiring ‘Start Codes’ to
431
+ // precede each NALU. A start code is 2 or 3 0x00 bytes followed with a
432
+ // 0x01 byte. e.g. 0x000001 or 0x00000001.
433
+ // More info in: https://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream/24890903#24890903
434
+ let numZeros = 0;
435
+
436
+ /** @type {!Array.<shaka.extern.VideoNalu>} */
437
+ const nalus = [];
438
+
439
+ // Start position includes the first byte where we read the type.
440
+ // The data we extract begins at the next byte.
441
+ let lastNaluStart = -1;
442
+ // Extracted from the first byte.
443
+ let lastNaluType = 0;
444
+
445
+ let tryToFinishLastNalu = false;
446
+
447
+ /** @type {?shaka.extern.VideoNalu} */
448
+ let infoOfLastNalu;
449
+
450
+ for (let i = 0; i < len; ++i) {
451
+ const value = data[i];
452
+ if (!value) {
453
+ numZeros++;
454
+ } else if (numZeros >= 2 && value == 1 && tryToFinishLastNalu) {
455
+ // If we are scanning the next PES, we need append the data to the
456
+ // previous Nalu and don't scan for more nalus.
457
+ if (i <= 2) {
458
+ break;
459
+ }
460
+ infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
461
+ infoOfLastNalu.data, data.subarray(0, i - 2));
462
+ infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
463
+ infoOfLastNalu.fullData, data.subarray(0, i - 2));
464
+ break;
465
+ } else if (numZeros >= 2 && value == 1) {
466
+ // We just read a start code. Consume the NALU we passed, if any.
467
+ if (lastNaluStart >= 0) {
468
+ // Because the start position includes the type, skip the first byte.
469
+ const firstByteToKeep = lastNaluStart + 1;
470
+
471
+ // Compute the last byte to keep. The start code is at most 3 zeros.
472
+ // Any earlier zeros are not part of the start code.
473
+ const startCodeSize = (numZeros > 3 ? 3 : numZeros) + 1;
474
+ const lastByteToKeep = i - startCodeSize;
475
+
476
+ /** @type {shaka.extern.VideoNalu} */
477
+ const nalu = {
478
+ // subarray's end position is exclusive, so add one.
479
+ data: data.subarray(firstByteToKeep, lastByteToKeep + 1),
480
+ fullData: data.subarray(lastNaluStart, lastByteToKeep + 1),
481
+ type: lastNaluType,
482
+ time: time,
483
+ };
484
+ nalus.push(nalu);
485
+ }
486
+
487
+ // We just read a start code, so there should be another byte here, at
488
+ // least, for the NALU type. Check just in case.
489
+ if (i >= len - 1) {
490
+ shaka.log.warning('Malformed TS, incomplete NALU, ignoring.');
491
+ return nalus;
492
+ }
493
+
494
+ // Advance and read the type of the next NALU.
495
+ i++;
496
+ lastNaluStart = i;
497
+ lastNaluType = data[i] & 0x1f;
498
+ numZeros = 0;
499
+ } else {
500
+ numZeros = 0;
501
+ }
502
+ // If we have gone through all the data from the PES and we have an
503
+ // unfinished Nalu, we will try to use the next PES to complete the
504
+ // unfinished Nalu.
505
+ if (i >= (len - 1) && lastNaluStart >= 0 && numZeros >= 0) {
506
+ if (tryToFinishLastNalu) {
507
+ infoOfLastNalu.data = shaka.util.Uint8ArrayUtils.concat(
508
+ infoOfLastNalu.data, data);
509
+ infoOfLastNalu.fullData = shaka.util.Uint8ArrayUtils.concat(
510
+ infoOfLastNalu.fullData, data);
511
+ } else {
512
+ tryToFinishLastNalu = true;
513
+ // The rest of the buffer was a NALU.
514
+ // Because the start position includes the type, skip the first byte.
515
+ const firstByteToKeep = lastNaluStart + 1;
516
+ infoOfLastNalu = {
517
+ data: data.subarray(firstByteToKeep, len),
518
+ fullData: data.subarray(lastNaluStart, len),
519
+ type: lastNaluType,
520
+ time: time,
521
+ };
522
+ if (nextPes) {
523
+ data = nextPes.data;
524
+ len = data.byteLength;
525
+ i = -1;
526
+ }
527
+ }
528
+ }
529
+ }
530
+
531
+ if (infoOfLastNalu) {
532
+ nalus.push(infoOfLastNalu);
533
+ }
534
+ return nalus;
535
+ }
536
+
340
537
  /**
341
538
  * Return the ID3 metadata
342
539
  *
343
540
  * @return {!Array.<shaka.extern.ID3Metadata>}
541
+ * @export
344
542
  */
345
543
  getMetadata() {
346
- const timescale = shaka.util.TsParser.Timescale_;
544
+ const timescale = shaka.util.TsParser.Timescale;
347
545
  const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
348
546
  const metadata = [];
349
547
  let prevId3Data = new Uint8Array(0);
350
- // parsePES() only works if the data begins on a PES boundary.
548
+ // parsePES_() only works if the data begins on a PES boundary.
351
549
  // Try the last data blob first, and if it doesn't begin on a
352
550
  // PES boundary, prepend the previous blob and try again.
353
551
  // This way, a successful parse will always begin and end on
@@ -356,7 +554,7 @@ shaka.util.TsParser = class {
356
554
  const data = this.id3Data_[i];
357
555
  goog.asserts.assert(data, 'We should have a data');
358
556
  const id3Data = Uint8ArrayUtils.concat(data, prevId3Data);
359
- const pes = this.parsePES(id3Data);
557
+ const pes = this.parsePES_(id3Data);
360
558
  if (pes) {
361
559
  metadata.unshift({
362
560
  cueTime: pes.pts ? pes.pts / timescale : null,
@@ -373,10 +571,71 @@ shaka.util.TsParser = class {
373
571
  return metadata;
374
572
  }
375
573
 
574
+ /**
575
+ * Return the audio data
576
+ *
577
+ * @return {!Array.<shaka.extern.MPEG_PES>}
578
+ * @export
579
+ */
580
+ getAudioData() {
581
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
582
+ const audio = [];
583
+ let prevAudioData = new Uint8Array(0);
584
+ // parsePES_() only works if the data begins on a PES boundary.
585
+ // Try the last data blob first, and if it doesn't begin on a
586
+ // PES boundary, prepend the previous blob and try again.
587
+ // This way, a successful parse will always begin and end on
588
+ // the correct boundary, and no data will be skipped.
589
+ for (let i = this.audioData_.length - 1; i >= 0; i--) {
590
+ const data = this.audioData_[i];
591
+ goog.asserts.assert(data, 'We should have a data');
592
+ const audioData = Uint8ArrayUtils.concat(data, prevAudioData);
593
+ const pes = this.parsePES_(audioData);
594
+ if (pes) {
595
+ audio.unshift(pes);
596
+ prevAudioData = new Uint8Array(0);
597
+ } else {
598
+ prevAudioData = audioData;
599
+ }
600
+ }
601
+ return audio;
602
+ }
603
+
604
+ /**
605
+ * Return the audio data
606
+ *
607
+ * @return {!Array.<shaka.extern.MPEG_PES>}
608
+ * @export
609
+ */
610
+ getVideoData() {
611
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
612
+ const video = [];
613
+ let prevVideoData = new Uint8Array(0);
614
+ // parsePES_() only works if the data begins on a PES boundary.
615
+ // Try the last data blob first, and if it doesn't begin on a
616
+ // PES boundary, prepend the previous blob and try again.
617
+ // This way, a successful parse will always begin and end on
618
+ // the correct boundary, and no data will be skipped.
619
+ for (let i = this.videoData_.length - 1; i >= 0; i--) {
620
+ const data = this.videoData_[i];
621
+ goog.asserts.assert(data, 'We should have a data');
622
+ const videoData = Uint8ArrayUtils.concat(data, prevVideoData);
623
+ const pes = this.parsePES_(videoData, /* isVideo= */ true);
624
+ if (pes) {
625
+ video.unshift(pes);
626
+ prevVideoData = new Uint8Array(0);
627
+ } else {
628
+ prevVideoData = videoData;
629
+ }
630
+ }
631
+ return video;
632
+ }
633
+
376
634
  /**
377
635
  * Return the start time for the audio and video
378
636
  *
379
637
  * @return {{audio: ?number, video: ?number}}
638
+ * @export
380
639
  */
381
640
  getStartTime() {
382
641
  return {
@@ -389,6 +648,7 @@ shaka.util.TsParser = class {
389
648
  * Return the audio and video codecs
390
649
  *
391
650
  * @return {{audio: ?string, video: ?string}}
651
+ * @export
392
652
  */
393
653
  getCodecs() {
394
654
  return {
@@ -397,11 +657,169 @@ shaka.util.TsParser = class {
397
657
  };
398
658
  }
399
659
 
660
+ /**
661
+ * Return the video data
662
+ *
663
+ * @return {!Array.<shaka.extern.VideoNalu>}
664
+ * @export
665
+ */
666
+ getVideoNalus() {
667
+ const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
668
+ let nalus = [];
669
+ let prevVideoData = new Uint8Array(0);
670
+ // parsePES_() only works if the data begins on a PES boundary.
671
+ // Try the last data blob first, and if it doesn't begin on a
672
+ // PES boundary, prepend the previous blob and try again.
673
+ // This way, a successful parse will always begin and end on
674
+ // the correct boundary, and no data will be skipped.
675
+ for (let i = this.videoData_.length - 1; i >= 0; i--) {
676
+ const data = this.videoData_[i];
677
+ goog.asserts.assert(data, 'We should have a data');
678
+ const videoData = Uint8ArrayUtils.concat(data, prevVideoData);
679
+ const pes = this.parsePES_(videoData);
680
+ if (pes) {
681
+ if (this.videoCodec_ == 'avc') {
682
+ nalus = nalus.concat(this.parseAvcNalus(pes));
683
+ }
684
+ prevVideoData = new Uint8Array(0);
685
+ } else {
686
+ prevVideoData = videoData;
687
+ }
688
+ }
689
+ // We need to invert the array to return it in the correct order.
690
+ return nalus.reverse();
691
+ }
692
+
693
+ /**
694
+ * Return the video resolution
695
+ *
696
+ * @return {{height: ?string, width: ?string}}
697
+ * @export
698
+ */
699
+ getVideoResolution() {
700
+ const TsParser = shaka.util.TsParser;
701
+ const resolution = {
702
+ height: null,
703
+ width: null,
704
+ };
705
+ const videoNalus = this.getVideoNalus();
706
+ if (!videoNalus.length) {
707
+ return resolution;
708
+ }
709
+ const spsNalu = videoNalus.find((nalu) => {
710
+ return nalu.type == TsParser.H264_NALU_TYPE_SPS_;
711
+ });
712
+ if (!spsNalu) {
713
+ return resolution;
714
+ }
715
+
716
+ const expGolombDecoder = new shaka.util.ExpGolomb(spsNalu.data);
717
+ // profile_idc
718
+ const profileIdc = expGolombDecoder.readUnsignedByte();
719
+ // constraint_set[0-5]_flag
720
+ expGolombDecoder.readUnsignedByte();
721
+ // level_idc u(8)
722
+ expGolombDecoder.readUnsignedByte();
723
+ // seq_parameter_set_id
724
+ expGolombDecoder.skipExpGolomb();
725
+
726
+ // some profiles have more optional data we don't need
727
+ if (TsParser.PROFILES_WITH_OPTIONAL_SPS_DATA_.includes(profileIdc)) {
728
+ const chromaFormatIdc = expGolombDecoder.readUnsignedExpGolomb();
729
+ if (chromaFormatIdc === 3) {
730
+ // separate_colour_plane_flag
731
+ expGolombDecoder.skipBits(1);
732
+ }
733
+ // bit_depth_luma_minus8
734
+ expGolombDecoder.skipExpGolomb();
735
+ // bit_depth_chroma_minus8
736
+ expGolombDecoder.skipExpGolomb();
737
+ // qpprime_y_zero_transform_bypass_flag
738
+ expGolombDecoder.skipBits(1);
739
+ // seq_scaling_matrix_present_flag
740
+ if (expGolombDecoder.readBoolean()) {
741
+ const scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;
742
+ for (let i = 0; i < scalingListCount; i++) {
743
+ // seq_scaling_list_present_flag[ i ]
744
+ if (expGolombDecoder.readBoolean()) {
745
+ if (i < 6) {
746
+ expGolombDecoder.skipScalingList(16);
747
+ } else {
748
+ expGolombDecoder.skipScalingList(64);
749
+ }
750
+ }
751
+ }
752
+ }
753
+ }
754
+
755
+ // log2_max_frame_num_minus4
756
+ expGolombDecoder.skipExpGolomb();
757
+ const picOrderCntType = expGolombDecoder.readUnsignedExpGolomb();
758
+
759
+ if (picOrderCntType === 0) {
760
+ // log2_max_pic_order_cnt_lsb_minus4
761
+ expGolombDecoder.readUnsignedExpGolomb();
762
+ } else if (picOrderCntType === 1) {
763
+ // delta_pic_order_always_zero_flag
764
+ expGolombDecoder.skipBits(1);
765
+ // offset_for_non_ref_pic
766
+ expGolombDecoder.skipExpGolomb();
767
+ // offset_for_top_to_bottom_field
768
+ expGolombDecoder.skipExpGolomb();
769
+ const numRefFramesInPicOrderCntCycle =
770
+ expGolombDecoder.readUnsignedExpGolomb();
771
+ for (let i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
772
+ // offset_for_ref_frame[ i ]
773
+ expGolombDecoder.skipExpGolomb();
774
+ }
775
+ }
776
+
777
+ // max_num_ref_frames
778
+ expGolombDecoder.skipExpGolomb();
779
+ // gaps_in_frame_num_value_allowed_flag
780
+ expGolombDecoder.skipBits(1);
781
+
782
+ const picWidthInMbsMinus1 =
783
+ expGolombDecoder.readUnsignedExpGolomb();
784
+ const picHeightInMapUnitsMinus1 =
785
+ expGolombDecoder.readUnsignedExpGolomb();
786
+
787
+ const frameMbsOnlyFlag = expGolombDecoder.readBits(1);
788
+ if (frameMbsOnlyFlag === 0) {
789
+ // mb_adaptive_frame_field_flag
790
+ expGolombDecoder.skipBits(1);
791
+ }
792
+ // direct_8x8_inference_flag
793
+ expGolombDecoder.skipBits(1);
794
+
795
+ let frameCropLeftOffset = 0;
796
+ let frameCropRightOffset = 0;
797
+ let frameCropTopOffset = 0;
798
+ let frameCropBottomOffset = 0;
799
+
800
+ // frame_cropping_flag
801
+ if (expGolombDecoder.readBoolean()) {
802
+ frameCropLeftOffset = expGolombDecoder.readUnsignedExpGolomb();
803
+ frameCropRightOffset = expGolombDecoder.readUnsignedExpGolomb();
804
+ frameCropTopOffset = expGolombDecoder.readUnsignedExpGolomb();
805
+ frameCropBottomOffset = expGolombDecoder.readUnsignedExpGolomb();
806
+ }
807
+
808
+ resolution.height = String(((2 - frameMbsOnlyFlag) *
809
+ (picHeightInMapUnitsMinus1 + 1) * 16) - (frameCropTopOffset * 2) -
810
+ (frameCropBottomOffset * 2));
811
+ resolution.width = String(((picWidthInMbsMinus1 + 1) * 16) -
812
+ frameCropLeftOffset * 2 - frameCropRightOffset * 2);
813
+
814
+ return resolution;
815
+ }
816
+
400
817
  /**
401
818
  * Check if the passed data corresponds to an MPEG2-TS
402
819
  *
403
820
  * @param {Uint8Array} data
404
821
  * @return {boolean}
822
+ * @export
405
823
  */
406
824
  static probe(data) {
407
825
  const syncOffset = shaka.util.TsParser.syncOffset(data);
@@ -421,6 +839,7 @@ shaka.util.TsParser = class {
421
839
  *
422
840
  * @param {Uint8Array} data
423
841
  * @return {number}
842
+ * @export
424
843
  */
425
844
  static syncOffset(data) {
426
845
  const packetLength = shaka.util.TsParser.PacketLength_;
@@ -430,9 +849,9 @@ shaka.util.TsParser = class {
430
849
  while (i < scanwindow) {
431
850
  // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and
432
851
  // one PID, each starting with 0x47
433
- if (data[i] === 0x47 &&
434
- data[i + packetLength] === 0x47 &&
435
- data[i + 2 * packetLength] === 0x47) {
852
+ if (data[i] == 0x47 &&
853
+ data[i + packetLength] == 0x47 &&
854
+ data[i + 2 * packetLength] == 0x47) {
436
855
  return i;
437
856
  } else {
438
857
  i++;
@@ -443,6 +862,13 @@ shaka.util.TsParser = class {
443
862
  };
444
863
 
445
864
 
865
+ /**
866
+ * @const {number}
867
+ * @export
868
+ */
869
+ shaka.util.TsParser.Timescale = 90000;
870
+
871
+
446
872
  /**
447
873
  * @const {number}
448
874
  * @private
@@ -451,10 +877,24 @@ shaka.util.TsParser.PacketLength_ = 188;
451
877
 
452
878
 
453
879
  /**
880
+ * NALU type for Sequence Parameter Set (SPS) for H.264.
454
881
  * @const {number}
455
882
  * @private
456
883
  */
457
- shaka.util.TsParser.Timescale_ = 90000;
884
+ shaka.util.TsParser.H264_NALU_TYPE_SPS_ = 0x07;
885
+
886
+
887
+ /**
888
+ * Values of profile_idc that indicate additional fields are included in the
889
+ * SPS.
890
+ * see Recommendation ITU-T H.264 (4/2013)
891
+ * 7.3.2.1.1 Sequence parameter set data syntax
892
+ *
893
+ * @const {!Array.<number>}
894
+ * @private
895
+ */
896
+ shaka.util.TsParser.PROFILES_WITH_OPTIONAL_SPS_DATA_ =
897
+ [100, 110, 122, 244, 44, 83, 86, 118, 128, 138, 139, 134];
458
898
 
459
899
 
460
900
  /**
@@ -480,20 +920,3 @@ shaka.util.TsParser.Timescale_ = 90000;
480
920
  */
481
921
  shaka.util.TsParser.PMT;
482
922
 
483
-
484
- /**
485
- * @typedef {{
486
- * data: Uint8Array,
487
- * packetLength: number,
488
- * pts: ?number,
489
- * dts: ?number
490
- * }}
491
- *
492
- * @summary PES.
493
- * @property {Uint8Array} data
494
- * @property {number} packetLength
495
- * @property {?number} pts
496
- * @property {?number} dts
497
- */
498
- shaka.util.TsParser.PES;
499
-