@remotion/media-parser 4.0.194 → 4.0.196

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 (275) hide show
  1. package/dist/add-new-matroska-tracks.d.ts +8 -0
  2. package/dist/add-new-matroska-tracks.js +14 -0
  3. package/dist/av1-codec-string.d.ts +3 -0
  4. package/dist/av1-codec-string.js +91 -0
  5. package/dist/boxes/iso-base-media/esds/decoder-specific-config.d.ts +14 -0
  6. package/dist/boxes/iso-base-media/esds/decoder-specific-config.js +38 -0
  7. package/dist/boxes/iso-base-media/esds/esds-descriptors.d.ts +8 -0
  8. package/dist/boxes/iso-base-media/esds/esds-descriptors.js +22 -2
  9. package/dist/boxes/iso-base-media/ftype.d.ts +9 -0
  10. package/dist/boxes/iso-base-media/ftype.js +31 -0
  11. package/dist/boxes/iso-base-media/make-track.d.ts +3 -0
  12. package/dist/boxes/iso-base-media/make-track.js +112 -0
  13. package/dist/boxes/iso-base-media/mdat/mdat.d.ts +6 -2
  14. package/dist/boxes/iso-base-media/mdat/mdat.js +90 -6
  15. package/dist/boxes/iso-base-media/moov/moov.d.ts +4 -2
  16. package/dist/boxes/iso-base-media/moov/moov.js +4 -2
  17. package/dist/boxes/iso-base-media/mvhd.js +7 -1
  18. package/dist/boxes/iso-base-media/process-box.d.ts +20 -3
  19. package/dist/boxes/iso-base-media/process-box.js +322 -34
  20. package/dist/boxes/iso-base-media/stsd/av1c.d.ts +9 -0
  21. package/dist/boxes/iso-base-media/stsd/av1c.js +10 -0
  22. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.d.ts +20 -0
  23. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.js +73 -0
  24. package/dist/boxes/iso-base-media/stsd/avcc.d.ts +10 -0
  25. package/dist/boxes/iso-base-media/stsd/avcc.js +21 -0
  26. package/dist/boxes/iso-base-media/stsd/colr.d.ts +11 -0
  27. package/dist/boxes/iso-base-media/stsd/colr.js +35 -0
  28. package/dist/boxes/iso-base-media/stsd/ctts.d.ts +19 -0
  29. package/dist/boxes/iso-base-media/stsd/ctts.js +30 -0
  30. package/dist/boxes/iso-base-media/stsd/hvcc.d.ts +11 -0
  31. package/dist/boxes/iso-base-media/stsd/hvcc.js +17 -0
  32. package/dist/boxes/iso-base-media/stsd/keys.js +1 -0
  33. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +4 -2
  34. package/dist/boxes/iso-base-media/stsd/mebx.js +4 -2
  35. package/dist/boxes/iso-base-media/stsd/pasp.d.ts +12 -0
  36. package/dist/boxes/iso-base-media/stsd/pasp.js +17 -0
  37. package/dist/boxes/iso-base-media/stsd/samples.d.ts +12 -5
  38. package/dist/boxes/iso-base-media/stsd/samples.js +27 -10
  39. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +4 -2
  40. package/dist/boxes/iso-base-media/stsd/stsd.js +6 -2
  41. package/dist/boxes/iso-base-media/stsd/stss.d.ts +13 -0
  42. package/dist/boxes/iso-base-media/stsd/stss.js +28 -0
  43. package/dist/boxes/iso-base-media/stsd/stsz.d.ts +9 -3
  44. package/dist/boxes/iso-base-media/stsd/stsz.js +14 -2
  45. package/dist/boxes/iso-base-media/stsd/stts.d.ts +15 -0
  46. package/dist/boxes/iso-base-media/stsd/stts.js +35 -0
  47. package/dist/boxes/iso-base-media/tkhd.d.ts +3 -0
  48. package/dist/boxes/iso-base-media/tkhd.js +41 -14
  49. package/dist/boxes/iso-base-media/trak/trak.d.ts +4 -2
  50. package/dist/boxes/iso-base-media/trak/trak.js +4 -2
  51. package/dist/boxes/iso-base-media/void-box.d.ts +4 -0
  52. package/dist/boxes/iso-base-media/void-box.js +2 -0
  53. package/dist/boxes/webm/allowed-partial-segments.d.ts +1 -0
  54. package/dist/boxes/webm/allowed-partial-segments.js +4 -0
  55. package/dist/boxes/webm/av1-codec-private.d.ts +2 -0
  56. package/dist/boxes/webm/av1-codec-private.js +95 -0
  57. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.d.ts +14 -0
  58. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.js +67 -0
  59. package/dist/boxes/webm/bitstream/av1/bitstream-frame.d.ts +11 -0
  60. package/dist/boxes/webm/bitstream/av1/bitstream-frame.js +14 -0
  61. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.d.ts +6 -0
  62. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.js +9 -0
  63. package/dist/boxes/webm/bitstream/av1/color-config.d.ts +16 -0
  64. package/dist/boxes/webm/bitstream/av1/color-config.js +103 -0
  65. package/dist/boxes/webm/bitstream/av1/color-primaries.d.ts +14 -0
  66. package/dist/boxes/webm/bitstream/av1/color-primaries.js +17 -0
  67. package/dist/boxes/webm/bitstream/av1/decoder-model-info.d.ts +9 -0
  68. package/dist/boxes/webm/bitstream/av1/decoder-model-info.js +17 -0
  69. package/dist/boxes/webm/bitstream/av1/header-segment.d.ts +51 -0
  70. package/dist/boxes/webm/bitstream/av1/header-segment.js +183 -0
  71. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.d.ts +17 -0
  72. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.js +20 -0
  73. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.d.ts +10 -0
  74. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.js +15 -0
  75. package/dist/boxes/webm/bitstream/av1/temporal-point-info.d.ts +5 -0
  76. package/dist/boxes/webm/bitstream/av1/temporal-point-info.js +8 -0
  77. package/dist/boxes/webm/bitstream/av1/timing-info.d.ts +8 -0
  78. package/dist/boxes/webm/bitstream/av1/timing-info.js +20 -0
  79. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.d.ts +21 -0
  80. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.js +24 -0
  81. package/dist/boxes/webm/bitstream/av1/uvlc.d.ts +2 -0
  82. package/dist/boxes/webm/bitstream/av1/uvlc.js +20 -0
  83. package/dist/boxes/webm/bitstream/av1.d.ts +20 -0
  84. package/dist/boxes/webm/bitstream/av1.js +118 -0
  85. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.d.ts +0 -0
  86. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.js +1 -0
  87. package/dist/boxes/webm/description.d.ts +2 -0
  88. package/dist/boxes/webm/description.js +83 -0
  89. package/dist/boxes/webm/get-ready-tracks.d.ts +3 -0
  90. package/dist/boxes/webm/get-ready-tracks.js +29 -0
  91. package/dist/boxes/webm/get-track.d.ts +6 -0
  92. package/dist/boxes/webm/get-track.js +183 -0
  93. package/dist/boxes/webm/parse-webm-header.d.ts +2 -1
  94. package/dist/boxes/webm/parse-webm-header.js +2 -2
  95. package/dist/boxes/webm/segments/all-segments.d.ts +269 -0
  96. package/dist/boxes/webm/segments/all-segments.js +277 -0
  97. package/dist/boxes/webm/segments/duration.d.ts +1 -1
  98. package/dist/boxes/webm/segments/duration.js +13 -9
  99. package/dist/boxes/webm/segments/info.d.ts +2 -1
  100. package/dist/boxes/webm/segments/info.js +12 -4
  101. package/dist/boxes/webm/segments/main.d.ts +0 -2
  102. package/dist/boxes/webm/segments/main.js +0 -11
  103. package/dist/boxes/webm/segments/muxing.d.ts +1 -1
  104. package/dist/boxes/webm/segments/muxing.js +1 -2
  105. package/dist/boxes/webm/segments/parse-children.d.ts +11 -1
  106. package/dist/boxes/webm/segments/parse-children.js +82 -6
  107. package/dist/boxes/webm/segments/seek-head.d.ts +2 -1
  108. package/dist/boxes/webm/segments/seek-head.js +12 -3
  109. package/dist/boxes/webm/segments/seek-position.d.ts +1 -1
  110. package/dist/boxes/webm/segments/seek-position.js +1 -2
  111. package/dist/boxes/webm/segments/seek.d.ts +7 -2
  112. package/dist/boxes/webm/segments/seek.js +22 -9
  113. package/dist/boxes/webm/segments/track-entry.d.ts +102 -22
  114. package/dist/boxes/webm/segments/track-entry.js +269 -57
  115. package/dist/boxes/webm/segments/tracks.d.ts +2 -1
  116. package/dist/boxes/webm/segments/tracks.js +12 -4
  117. package/dist/boxes/webm/segments/void.d.ts +1 -1
  118. package/dist/boxes/webm/segments/void.js +1 -2
  119. package/dist/boxes/webm/segments/writing.d.ts +1 -1
  120. package/dist/boxes/webm/segments/writing.js +1 -2
  121. package/dist/boxes/webm/segments.d.ts +8 -4
  122. package/dist/boxes/webm/segments.js +176 -40
  123. package/dist/boxes/webm/traversal.d.ts +7 -0
  124. package/dist/boxes/webm/traversal.js +25 -0
  125. package/dist/buffer-iterator.d.ts +15 -1
  126. package/dist/buffer-iterator.js +115 -46
  127. package/dist/combine-uint8array.d.ts +1 -0
  128. package/dist/combine-uint8array.js +13 -0
  129. package/dist/from-fetch.d.ts +2 -0
  130. package/dist/from-fetch.js +54 -0
  131. package/dist/from-node.js +6 -0
  132. package/dist/from-web-file.d.ts +2 -0
  133. package/dist/from-web-file.js +34 -0
  134. package/dist/from-web.js +6 -9
  135. package/dist/get-audio-codec.d.ts +19 -0
  136. package/dist/get-audio-codec.js +153 -60
  137. package/dist/get-dimensions.d.ts +8 -2
  138. package/dist/get-dimensions.js +13 -91
  139. package/dist/get-duration.js +4 -7
  140. package/dist/get-fps.d.ts +4 -3
  141. package/dist/get-fps.js +17 -116
  142. package/dist/get-sample-aspect-ratio.d.ts +37 -0
  143. package/dist/get-sample-aspect-ratio.js +137 -0
  144. package/dist/get-sample-positions.d.ts +11 -1
  145. package/dist/get-sample-positions.js +31 -2
  146. package/dist/get-tracks.d.ts +44 -5
  147. package/dist/get-tracks.js +66 -48
  148. package/dist/get-video-codec.d.ts +2 -0
  149. package/dist/get-video-codec.js +47 -31
  150. package/dist/get-video-metadata.d.ts +2 -0
  151. package/dist/get-video-metadata.js +44 -0
  152. package/dist/has-all-info.d.ts +2 -1
  153. package/dist/has-all-info.js +14 -5
  154. package/dist/index.d.ts +1 -0
  155. package/dist/make-hvc1-codec-strings.d.ts +2 -0
  156. package/dist/make-hvc1-codec-strings.js +47 -0
  157. package/dist/options.d.ts +26 -4
  158. package/dist/parse-media.js +62 -17
  159. package/dist/parse-result.d.ts +16 -5
  160. package/dist/parse-video.d.ts +11 -2
  161. package/dist/parse-video.js +14 -6
  162. package/dist/parser-context.d.ts +8 -0
  163. package/dist/parser-context.js +2 -0
  164. package/dist/parser-state.d.ts +23 -0
  165. package/dist/parser-state.js +112 -0
  166. package/dist/read-and-increment-offset.d.ts +28 -0
  167. package/dist/read-and-increment-offset.js +177 -0
  168. package/dist/reader.d.ts +2 -2
  169. package/dist/traversal.d.ts +37 -0
  170. package/dist/traversal.js +244 -1
  171. package/dist/understand-vorbis.d.ts +1 -0
  172. package/dist/understand-vorbis.js +12 -0
  173. package/dist/webcodec-sample-types.d.ts +21 -0
  174. package/dist/webcodec-sample-types.js +2 -0
  175. package/package.json +10 -2
  176. package/src/add-new-matroska-tracks.ts +23 -0
  177. package/src/boxes/iso-base-media/esds/decoder-specific-config.ts +61 -0
  178. package/src/boxes/iso-base-media/esds/esds-descriptors.ts +33 -2
  179. package/src/boxes/iso-base-media/make-track.ts +157 -0
  180. package/src/boxes/iso-base-media/mdat/mdat.ts +131 -0
  181. package/src/boxes/iso-base-media/moov/moov.ts +8 -3
  182. package/src/boxes/iso-base-media/mvhd.ts +7 -1
  183. package/src/boxes/iso-base-media/process-box.ts +388 -38
  184. package/src/boxes/iso-base-media/stsd/av1c.ts +19 -0
  185. package/src/boxes/iso-base-media/stsd/avcc.ts +36 -0
  186. package/src/boxes/iso-base-media/stsd/colr.ts +49 -0
  187. package/src/boxes/iso-base-media/stsd/ctts.ts +55 -0
  188. package/src/boxes/iso-base-media/stsd/hvcc.ts +32 -0
  189. package/src/boxes/iso-base-media/stsd/keys.ts +2 -0
  190. package/src/boxes/iso-base-media/stsd/mebx.ts +8 -3
  191. package/src/boxes/iso-base-media/stsd/pasp.ts +32 -0
  192. package/src/boxes/iso-base-media/stsd/samples.ts +43 -16
  193. package/src/boxes/iso-base-media/stsd/stco.ts +50 -0
  194. package/src/boxes/iso-base-media/stsd/stsc.ts +61 -0
  195. package/src/boxes/iso-base-media/stsd/stsd.ts +10 -3
  196. package/src/boxes/iso-base-media/stsd/stss.ts +47 -0
  197. package/src/boxes/iso-base-media/stsd/stsz.ts +75 -0
  198. package/src/boxes/iso-base-media/tkhd.ts +63 -16
  199. package/src/boxes/iso-base-media/trak/trak.ts +8 -3
  200. package/src/boxes/iso-base-media/void-box.ts +4 -0
  201. package/src/boxes/webm/allowed-partial-segments.ts +1 -0
  202. package/src/boxes/webm/av1-codec-private.ts +113 -0
  203. package/src/boxes/webm/description.ts +101 -0
  204. package/src/boxes/webm/get-ready-tracks.ts +36 -0
  205. package/src/boxes/webm/get-track.ts +250 -0
  206. package/src/boxes/webm/parse-webm-header.ts +6 -2
  207. package/src/boxes/webm/segments/all-segments.ts +285 -0
  208. package/src/boxes/webm/segments/duration.ts +15 -8
  209. package/src/boxes/webm/segments/info.ts +18 -4
  210. package/src/boxes/webm/segments/main.ts +0 -13
  211. package/src/boxes/webm/segments/muxing.ts +1 -1
  212. package/src/boxes/webm/segments/parse-children.ts +132 -9
  213. package/src/boxes/webm/segments/seek-head.ts +17 -4
  214. package/src/boxes/webm/segments/seek-position.ts +1 -2
  215. package/src/boxes/webm/segments/seek.ts +31 -9
  216. package/src/boxes/webm/segments/track-entry.ts +475 -65
  217. package/src/boxes/webm/segments/tracks.ts +17 -7
  218. package/src/boxes/webm/segments/void.ts +4 -2
  219. package/src/boxes/webm/segments/writing.ts +1 -1
  220. package/src/boxes/webm/segments.ts +266 -42
  221. package/src/boxes/webm/traversal.ts +32 -0
  222. package/src/buffer-iterator.ts +140 -45
  223. package/src/combine-uint8array.ts +13 -0
  224. package/src/{from-web.ts → from-fetch.ts} +9 -1
  225. package/src/from-node.ts +8 -0
  226. package/src/from-web-file.ts +39 -0
  227. package/src/get-audio-codec.ts +213 -84
  228. package/src/get-dimensions.ts +25 -132
  229. package/src/get-duration.ts +4 -8
  230. package/src/get-fps.ts +27 -172
  231. package/src/get-sample-aspect-ratio.ts +204 -0
  232. package/src/get-sample-positions.ts +93 -0
  233. package/src/get-tracks.ts +147 -0
  234. package/src/get-video-codec.ts +62 -47
  235. package/src/has-all-info.ts +35 -5
  236. package/src/index.ts +8 -0
  237. package/src/make-hvc1-codec-strings.ts +55 -0
  238. package/src/options.ts +48 -9
  239. package/src/parse-media.ts +90 -21
  240. package/src/parse-result.ts +28 -4
  241. package/src/parse-video.ts +30 -7
  242. package/src/parser-context.ts +9 -0
  243. package/src/parser-state.ts +151 -0
  244. package/src/reader.ts +2 -2
  245. package/src/test/aspect-ratio.test.ts +42 -0
  246. package/src/test/av1.test.ts +108 -0
  247. package/src/test/duration.test.ts +5 -21
  248. package/src/test/matroska.test.ts +350 -31
  249. package/src/test/mvhd.test.ts +6 -1
  250. package/src/test/parse-esds.test.ts +29 -6
  251. package/src/test/parse-stco.test.ts +59 -0
  252. package/src/test/parse-stsc.test.ts +104 -0
  253. package/src/test/parse-stsz.test.ts +57 -0
  254. package/src/test/parse-stts.test.ts +1 -1
  255. package/src/test/parse-video.test.ts +23 -35
  256. package/src/test/parse-webm.test.ts +5 -5
  257. package/src/test/stream-local.test.ts +542 -46
  258. package/src/test/stream-remote.test.ts +15 -13
  259. package/src/test/stream-samples.test.ts +259 -0
  260. package/src/test/stsd.test.ts +60 -8
  261. package/src/test/tkhd.test.ts +4 -1
  262. package/src/traversal.ts +496 -0
  263. package/src/webcodec-sample-types.ts +30 -0
  264. package/tsconfig.json +5 -1
  265. package/tsconfig.tsbuildinfo +1 -1
  266. package/boxes.json +0 -1
  267. package/dist/boxes/iso-base-media/esds-descriptors.d.ts +0 -21
  268. package/dist/boxes/iso-base-media/esds-descriptors.js +0 -62
  269. package/dist/boxes/iso-base-media/esds.d.ts +0 -15
  270. package/dist/boxes/iso-base-media/esds.js +0 -27
  271. package/dist/get-codec.d.ts +0 -4
  272. package/dist/get-codec.js +0 -22
  273. /package/dist/{get-samples.d.ts → boxes/webm/bitstream/av1/frame.d.ts} +0 -0
  274. /package/dist/{get-samples.js → boxes/webm/bitstream/av1/frame.js} +0 -0
  275. /package/src/boxes/iso-base-media/{stts → stsd}/stts.ts +0 -0
@@ -1,4 +1,5 @@
1
1
  import type {BufferIterator} from '../../../buffer-iterator';
2
+ import type {ParserContext} from '../../../parser-context';
2
3
  import type {MatroskaSegment} from '../segments';
3
4
  import {expectChildren} from './parse-children';
4
5
 
@@ -7,19 +8,25 @@ export type TrackEntrySegment = {
7
8
  children: MatroskaSegment[];
8
9
  };
9
10
 
10
- export const parseTrackEntry = (
11
+ export const parseTrackEntry = async (
11
12
  iterator: BufferIterator,
12
- ): TrackEntrySegment => {
13
- const offset = iterator.counter.getOffset();
14
-
15
- const length = iterator.getVint();
13
+ length: number,
14
+ parserContext: ParserContext,
15
+ ): Promise<TrackEntrySegment> => {
16
+ const children = await expectChildren({
17
+ iterator,
18
+ length,
19
+ initialChildren: [],
20
+ wrap: null,
21
+ parserContext,
22
+ });
23
+ if (children.status === 'incomplete') {
24
+ throw new Error('Incomplete children ' + length);
25
+ }
16
26
 
17
27
  return {
18
28
  type: 'track-entry-segment',
19
- children: expectChildren(
20
- iterator,
21
- length - (iterator.counter.getOffset() - offset),
22
- ),
29
+ children: children.segments as MatroskaSegment[],
23
30
  };
24
31
  };
25
32
 
@@ -28,30 +35,15 @@ export type TrackNumberSegment = {
28
35
  trackNumber: number;
29
36
  };
30
37
 
31
- export const parseTrackNumber = (
32
- iterator: BufferIterator,
33
- ): TrackNumberSegment => {
34
- const length = iterator.getVint();
35
- if (length !== 1) {
36
- throw new Error('Expected track number to be 1 byte');
37
- }
38
-
39
- const trackNumber = iterator.getUint8();
40
-
41
- return {
42
- type: 'track-number-segment',
43
- trackNumber,
44
- };
45
- };
46
-
47
38
  export type TrackUIDSegment = {
48
39
  type: 'track-uid-segment';
49
40
  trackUid: string;
50
41
  };
51
42
 
52
- export const parseTrackUID = (iterator: BufferIterator): TrackUIDSegment => {
53
- const length = iterator.getVint();
54
-
43
+ export const parseTrackUID = (
44
+ iterator: BufferIterator,
45
+ length: number,
46
+ ): TrackUIDSegment => {
55
47
  const bytes = iterator.getSlice(length);
56
48
 
57
49
  const asString = [...bytes]
@@ -70,8 +62,8 @@ export type FlagLacingSegment = {
70
62
 
71
63
  export const parseFlagLacing = (
72
64
  iterator: BufferIterator,
65
+ length: number,
73
66
  ): FlagLacingSegment => {
74
- const length = iterator.getVint();
75
67
  if (length !== 1) {
76
68
  throw new Error('Expected flag lacing to be 1 byte');
77
69
  }
@@ -95,8 +87,8 @@ export type LanguageSegment = {
95
87
 
96
88
  export const parseLanguageSegment = (
97
89
  iterator: BufferIterator,
90
+ length: number,
98
91
  ): LanguageSegment => {
99
- const length = iterator.getVint();
100
92
  if (length !== 3) {
101
93
  throw new Error('Expected language segment to be 3 bytes');
102
94
  }
@@ -114,9 +106,10 @@ export type CodecSegment = {
114
106
  codec: string;
115
107
  };
116
108
 
117
- export const parseCodecSegment = (iterator: BufferIterator): CodecSegment => {
118
- const length = iterator.getVint();
119
-
109
+ export const parseCodecSegment = (
110
+ iterator: BufferIterator,
111
+ length: number,
112
+ ): CodecSegment => {
120
113
  // Could make a TypeScript enum with it
121
114
  // https://www.matroska.org/technical/codec_specs.html
122
115
  const codec = iterator.getByteString(length);
@@ -127,21 +120,53 @@ export const parseCodecSegment = (iterator: BufferIterator): CodecSegment => {
127
120
  };
128
121
  };
129
122
 
123
+ type TrackType =
124
+ | 'video'
125
+ | 'audio'
126
+ | 'complex'
127
+ | 'subtitle'
128
+ | 'button'
129
+ | 'control'
130
+ | 'metadata';
131
+
130
132
  export type TrackTypeSegment = {
131
133
  type: 'track-type-segment';
132
- trackType: number;
134
+ trackType: TrackType;
135
+ };
136
+
137
+ const trackTypeToString = (trackType: number): TrackType => {
138
+ switch (trackType) {
139
+ case 1:
140
+ return 'video';
141
+ case 2:
142
+ return 'audio';
143
+ case 3:
144
+ return 'complex';
145
+ case 4:
146
+ return 'subtitle';
147
+ case 5:
148
+ return 'button';
149
+ case 6:
150
+ return 'control';
151
+ case 7:
152
+ return 'metadata';
153
+ default:
154
+ throw new Error(`Unknown track type: ${trackType}`);
155
+ }
133
156
  };
134
157
 
135
158
  export const parseTrackTypeSegment = (
136
159
  iterator: BufferIterator,
160
+ length: number,
137
161
  ): TrackTypeSegment => {
138
- const length = iterator.getVint();
139
162
  if (length !== 1) {
140
163
  throw new Error('Expected track type segment to be 1 byte');
141
164
  }
142
165
 
143
166
  const trackType = iterator.getUint8();
144
167
 
168
+ const trackTypeString = trackTypeToString(trackType);
169
+
145
170
  // Could make the return type nicer
146
171
  /* 1 - video,
147
172
  2 - audio,
@@ -154,7 +179,7 @@ export const parseTrackTypeSegment = (
154
179
  */
155
180
  return {
156
181
  type: 'track-type-segment',
157
- trackType,
182
+ trackType: trackTypeString,
158
183
  };
159
184
  };
160
185
 
@@ -165,9 +190,8 @@ export type DefaultDurationSegment = {
165
190
 
166
191
  export const parseDefaultDurationSegment = (
167
192
  iterator: BufferIterator,
193
+ length: number,
168
194
  ): DefaultDurationSegment => {
169
- const length = iterator.getVint();
170
-
171
195
  const defaultDuration = iterator.getDecimalBytes(length);
172
196
 
173
197
  return {
@@ -178,16 +202,57 @@ export const parseDefaultDurationSegment = (
178
202
 
179
203
  export type VideoSegment = {
180
204
  type: 'video-segment';
181
-
182
205
  children: MatroskaSegment[];
183
206
  };
184
207
 
185
- export const parseVideoSegment = (iterator: BufferIterator): VideoSegment => {
186
- const length = iterator.getVint();
208
+ export const parseVideoSegment = async (
209
+ iterator: BufferIterator,
210
+ length: number,
211
+ parserContext: ParserContext,
212
+ ): Promise<VideoSegment> => {
213
+ const children = await expectChildren({
214
+ iterator,
215
+ length,
216
+ initialChildren: [],
217
+ wrap: null,
218
+ parserContext,
219
+ });
220
+
221
+ if (children.status === 'incomplete') {
222
+ throw new Error('Incomplete children');
223
+ }
187
224
 
188
225
  return {
189
226
  type: 'video-segment',
190
- children: expectChildren(iterator, length),
227
+ children: children.segments as MatroskaSegment[],
228
+ };
229
+ };
230
+
231
+ export type AudioSegment = {
232
+ type: 'audio-segment';
233
+ children: MatroskaSegment[];
234
+ };
235
+
236
+ export const parseAudioSegment = async (
237
+ iterator: BufferIterator,
238
+ length: number,
239
+ parserContext: ParserContext,
240
+ ): Promise<AudioSegment> => {
241
+ const children = await expectChildren({
242
+ iterator,
243
+ length,
244
+ initialChildren: [],
245
+ wrap: null,
246
+ parserContext,
247
+ });
248
+
249
+ if (children.status === 'incomplete') {
250
+ throw new Error('Incomplete children');
251
+ }
252
+
253
+ return {
254
+ type: 'audio-segment',
255
+ children: children.segments as MatroskaSegment[],
191
256
  };
192
257
  };
193
258
 
@@ -196,8 +261,10 @@ export type WidthSegment = {
196
261
  width: number;
197
262
  };
198
263
 
199
- export const parseWidthSegment = (iterator: BufferIterator): WidthSegment => {
200
- const length = iterator.getVint();
264
+ export const parseWidthSegment = (
265
+ iterator: BufferIterator,
266
+ length: number,
267
+ ): WidthSegment => {
201
268
  if (length !== 2) {
202
269
  throw new Error('Expected width segment to be 2 bytes');
203
270
  }
@@ -215,8 +282,10 @@ export type HeightSegment = {
215
282
  height: number;
216
283
  };
217
284
 
218
- export const parseHeightSegment = (iterator: BufferIterator): HeightSegment => {
219
- const length = iterator.getVint();
285
+ export const parseHeightSegment = (
286
+ iterator: BufferIterator,
287
+ length: number,
288
+ ): HeightSegment => {
220
289
  if (length !== 2) {
221
290
  throw new Error('Expected height segment to be 2 bytes');
222
291
  }
@@ -229,6 +298,52 @@ export const parseHeightSegment = (iterator: BufferIterator): HeightSegment => {
229
298
  };
230
299
  };
231
300
 
301
+ export type DisplayWidthSegment = {
302
+ type: 'display-width-segment';
303
+ displayWidth: number;
304
+ };
305
+
306
+ export const parseDisplayWidthSegment = (
307
+ iterator: BufferIterator,
308
+ length: number,
309
+ ): DisplayWidthSegment => {
310
+ if (length !== 2) {
311
+ throw new Error(
312
+ `Expected display width segment to be 2 bytes, got ${length}`,
313
+ );
314
+ }
315
+
316
+ const displayWidth = iterator.getUint16();
317
+
318
+ return {
319
+ type: 'display-width-segment',
320
+ displayWidth,
321
+ };
322
+ };
323
+
324
+ export type DisplayHeightSegment = {
325
+ type: 'display-height-segment';
326
+ displayHeight: number;
327
+ };
328
+
329
+ export const parseDisplayHeightSegment = (
330
+ iterator: BufferIterator,
331
+ length: number,
332
+ ): DisplayHeightSegment => {
333
+ if (length !== 2) {
334
+ throw new Error(
335
+ `Expected display height segment to be 2 bytes, got ${length}`,
336
+ );
337
+ }
338
+
339
+ const displayHeight = iterator.getUint16();
340
+
341
+ return {
342
+ type: 'display-height-segment',
343
+ displayHeight,
344
+ };
345
+ };
346
+
232
347
  export type AlphaModeSegment = {
233
348
  type: 'alpha-mode-segment';
234
349
  alphaMode: number;
@@ -236,8 +351,8 @@ export type AlphaModeSegment = {
236
351
 
237
352
  export const parseAlphaModeSegment = (
238
353
  iterator: BufferIterator,
354
+ length: number,
239
355
  ): AlphaModeSegment => {
240
- const length = iterator.getVint();
241
356
  if (length !== 1) {
242
357
  throw new Error('Expected alpha mode segment to be 1 byte');
243
358
  }
@@ -257,8 +372,8 @@ export type MaxBlockAdditionId = {
257
372
 
258
373
  export const parseMaxBlockAdditionId = (
259
374
  iterator: BufferIterator,
375
+ length: number,
260
376
  ): MaxBlockAdditionId => {
261
- const length = iterator.getVint();
262
377
  if (length !== 1) {
263
378
  throw new Error('Expected alpha mode segment to be 1 byte');
264
379
  }
@@ -273,15 +388,18 @@ export const parseMaxBlockAdditionId = (
273
388
 
274
389
  export type ColorSegment = {
275
390
  type: 'color-segment';
391
+ length: number;
276
392
  };
277
393
 
278
- export const parseColorSegment = (iterator: BufferIterator): ColorSegment => {
279
- const length = iterator.getVint();
280
-
394
+ export const parseColorSegment = (
395
+ iterator: BufferIterator,
396
+ length: number,
397
+ ): ColorSegment => {
281
398
  iterator.discard(length);
282
399
 
283
400
  return {
284
401
  type: 'color-segment',
402
+ length,
285
403
  };
286
404
  };
287
405
 
@@ -290,8 +408,10 @@ export type TitleSegment = {
290
408
  title: string;
291
409
  };
292
410
 
293
- export const parseTitleSegment = (iterator: BufferIterator): TitleSegment => {
294
- const length = iterator.getVint();
411
+ export const parseTitleSegment = (
412
+ iterator: BufferIterator,
413
+ length: number,
414
+ ): TitleSegment => {
295
415
  const title = iterator.getByteString(length);
296
416
 
297
417
  return {
@@ -307,10 +427,12 @@ export type InterlacedSegment = {
307
427
 
308
428
  export const parseInterlacedSegment = (
309
429
  iterator: BufferIterator,
430
+ length: number,
310
431
  ): InterlacedSegment => {
311
- const length = iterator.getVint();
312
432
  if (length !== 1) {
313
- throw new Error('Expected interlaced segment to be 1 byte');
433
+ throw new Error(
434
+ 'Expected interlaced segment to be 1 byte, but is ' + length,
435
+ );
314
436
  }
315
437
 
316
438
  const interlaced = iterator.getUint8();
@@ -323,17 +445,16 @@ export const parseInterlacedSegment = (
323
445
 
324
446
  export type CodecPrivateSegment = {
325
447
  type: 'codec-private-segment';
326
- codecPrivateData: number[];
448
+ codecPrivateData: Uint8Array;
327
449
  };
328
450
 
329
451
  export const parseCodecPrivateSegment = (
330
452
  iterator: BufferIterator,
453
+ length: number,
331
454
  ): CodecPrivateSegment => {
332
- const length = iterator.getVint();
333
-
334
455
  return {
335
456
  type: 'codec-private-segment',
336
- codecPrivateData: [...iterator.getSlice(length)],
457
+ codecPrivateData: iterator.getSlice(length),
337
458
  };
338
459
  };
339
460
 
@@ -342,9 +463,10 @@ export type Crc32Segment = {
342
463
  crc32: number[];
343
464
  };
344
465
 
345
- export const parseCrc32Segment = (iterator: BufferIterator): Crc32Segment => {
346
- const length = iterator.getVint();
347
-
466
+ export const parseCrc32Segment = (
467
+ iterator: BufferIterator,
468
+ length: number,
469
+ ): Crc32Segment => {
348
470
  return {
349
471
  type: 'crc32-segment',
350
472
  crc32: [...iterator.getSlice(length)],
@@ -358,9 +480,8 @@ export type SegmentUUIDSegment = {
358
480
 
359
481
  export const parseSegmentUUIDSegment = (
360
482
  iterator: BufferIterator,
483
+ length: number,
361
484
  ): SegmentUUIDSegment => {
362
- const length = iterator.getVint();
363
-
364
485
  return {
365
486
  type: 'segment-uuid-segment',
366
487
  segmentUUID: iterator.getSlice(length).toString(),
@@ -374,8 +495,8 @@ export type DefaultFlagSegment = {
374
495
 
375
496
  export const parseDefaultFlagSegment = (
376
497
  iterator: BufferIterator,
498
+ length: number,
377
499
  ): DefaultFlagSegment => {
378
- const length = iterator.getVint();
379
500
  if (length !== 1) {
380
501
  throw new Error('Expected default flag segment to be 1 byte');
381
502
  }
@@ -385,3 +506,292 @@ export const parseDefaultFlagSegment = (
385
506
  defaultFlag: Boolean(iterator.getUint8()),
386
507
  };
387
508
  };
509
+
510
+ export type TagsSegment = {
511
+ type: 'tags-segment';
512
+ children: MatroskaSegment[];
513
+ };
514
+
515
+ export const parseTagsSegment = async (
516
+ iterator: BufferIterator,
517
+ length: number,
518
+ parserContext: ParserContext,
519
+ ): Promise<TagsSegment> => {
520
+ const children = await expectChildren({
521
+ iterator,
522
+ length,
523
+ initialChildren: [],
524
+ wrap: null,
525
+ parserContext,
526
+ });
527
+
528
+ if (children.status === 'incomplete') {
529
+ throw new Error('Incomplete children');
530
+ }
531
+
532
+ return {
533
+ type: 'tags-segment',
534
+ children: children.segments as MatroskaSegment[],
535
+ };
536
+ };
537
+
538
+ export type TagSegment = {
539
+ type: 'tag-segment';
540
+ length: number;
541
+ };
542
+
543
+ export const parseTagSegment = (
544
+ iterator: BufferIterator,
545
+ length: number,
546
+ ): TagSegment => {
547
+ iterator.discard(length);
548
+
549
+ return {
550
+ type: 'tag-segment',
551
+ length,
552
+ };
553
+ };
554
+
555
+ export type ClusterSegment = {
556
+ type: 'cluster-segment';
557
+ children: MatroskaSegment[];
558
+ };
559
+
560
+ export type TimestampSegment = {
561
+ type: 'timestamp-segment';
562
+ timestamp: number;
563
+ };
564
+
565
+ export const parseTimestampSegment = (
566
+ iterator: BufferIterator,
567
+ length: number,
568
+ ): TimestampSegment => {
569
+ if (length > 2) {
570
+ throw new Error('Expected timestamp segment to be 1 byte or 2 bytes');
571
+ }
572
+
573
+ const value = length === 2 ? iterator.getUint16() : iterator.getUint8();
574
+
575
+ return {
576
+ type: 'timestamp-segment',
577
+ timestamp: value,
578
+ };
579
+ };
580
+
581
+ export type SimpleBlockSegment = {
582
+ type: 'simple-block-segment';
583
+ length: number;
584
+ trackNumber: number;
585
+ timecode: number;
586
+ headerFlags: number;
587
+ keyframe: boolean;
588
+ lacing: [number, number];
589
+ invisible: boolean;
590
+ children: MatroskaSegment[];
591
+ };
592
+
593
+ export type GetTracks = () => TrackEntrySegment[];
594
+
595
+ export const parseSimpleBlockSegment = async ({
596
+ iterator,
597
+ length,
598
+ parserContext,
599
+ }: {
600
+ iterator: BufferIterator;
601
+ length: number;
602
+ parserContext: ParserContext;
603
+ }): Promise<SimpleBlockSegment> => {
604
+ const start = iterator.counter.getOffset();
605
+ const trackNumber = iterator.getVint();
606
+ const timecode = iterator.getUint16();
607
+ const headerFlags = iterator.getUint8();
608
+
609
+ const invisible = Boolean((headerFlags >> 5) & 1);
610
+ const pos6 = (headerFlags >> 6) & 1;
611
+ const pos7 = (headerFlags >> 6) & 1;
612
+ const keyframe = Boolean((headerFlags >> 7) & 1);
613
+
614
+ const codec = parserContext.parserState.getTrackInfoByNumber(trackNumber);
615
+
616
+ if (!codec) {
617
+ throw new Error('Could not find codec for track ' + trackNumber);
618
+ }
619
+
620
+ const children: MatroskaSegment[] = [];
621
+
622
+ if (codec.codec.startsWith('V_')) {
623
+ const remainingNow = length - (iterator.counter.getOffset() - start);
624
+
625
+ await parserContext.parserState.onVideoSample(trackNumber, {
626
+ data: iterator.getSlice(remainingNow),
627
+ cts: null,
628
+ dts: null,
629
+ duration: undefined,
630
+ type: keyframe ? 'key' : 'delta',
631
+ trackId: trackNumber,
632
+ timestamp: timecode,
633
+ });
634
+ }
635
+
636
+ if (codec.codec.startsWith('A_')) {
637
+ const vorbisRemaining = length - (iterator.counter.getOffset() - start);
638
+ await parserContext.parserState.onAudioSample(trackNumber, {
639
+ data: iterator.getSlice(vorbisRemaining),
640
+ offset: timecode,
641
+ trackId: trackNumber,
642
+ timestamp: timecode,
643
+ type: 'key',
644
+ });
645
+ }
646
+
647
+ const remainingNowAfter = length - (iterator.counter.getOffset() - start);
648
+ if (remainingNowAfter > 0) {
649
+ iterator.discard(remainingNowAfter);
650
+ }
651
+
652
+ return {
653
+ type: 'simple-block-segment',
654
+ length,
655
+ trackNumber,
656
+ timecode,
657
+ headerFlags,
658
+ keyframe,
659
+ lacing: [pos6, pos7],
660
+ invisible,
661
+ children,
662
+ };
663
+ };
664
+
665
+ export const parseTrackNumber = (
666
+ iterator: BufferIterator,
667
+ length: number,
668
+ ): TrackNumberSegment => {
669
+ if (length !== 1) {
670
+ throw new Error('Expected track number to be 1 byte');
671
+ }
672
+
673
+ const trackNumber = iterator.getUint8();
674
+
675
+ return {
676
+ type: 'track-number-segment',
677
+ trackNumber,
678
+ };
679
+ };
680
+
681
+ export type BlockGroupSegment = {
682
+ type: 'block-group-segment';
683
+ children: MatroskaSegment[];
684
+ };
685
+
686
+ export const parseBlockGroupSegment = async (
687
+ iterator: BufferIterator,
688
+ length: number,
689
+ parserContext: ParserContext,
690
+ ): Promise<BlockGroupSegment> => {
691
+ const children = await expectChildren({
692
+ iterator,
693
+ length,
694
+ initialChildren: [],
695
+ wrap: null,
696
+ parserContext,
697
+ });
698
+ if (children.status === 'incomplete') {
699
+ throw new Error('Incomplete boxes are not allowed');
700
+ }
701
+
702
+ return {
703
+ type: 'block-group-segment',
704
+ children: children.segments as MatroskaSegment[],
705
+ };
706
+ };
707
+
708
+ export type BlockElement = {
709
+ type: 'block-element-segment';
710
+ length: number;
711
+ };
712
+
713
+ export const parseBlockElementSegment = (
714
+ iterator: BufferIterator,
715
+ length: number,
716
+ ): BlockElement => {
717
+ iterator.discard(length);
718
+
719
+ return {
720
+ type: 'block-element-segment',
721
+ length,
722
+ };
723
+ };
724
+
725
+ export type SamplingFrequencySegment = {
726
+ type: 'sampling-frequency-segment';
727
+ samplingFrequency: number;
728
+ };
729
+
730
+ export const parseSamplingFrequencySegment = (
731
+ iterator: BufferIterator,
732
+ length: number,
733
+ ): SamplingFrequencySegment => {
734
+ if (length === 4) {
735
+ return {
736
+ type: 'sampling-frequency-segment',
737
+ samplingFrequency: iterator.getFloat32(),
738
+ };
739
+ }
740
+
741
+ if (length === 8) {
742
+ return {
743
+ type: 'sampling-frequency-segment',
744
+ samplingFrequency: iterator.getFloat64(),
745
+ };
746
+ }
747
+
748
+ throw new Error(
749
+ `Expected length of sampling frequency segment to be 4 or 8, got ${length}`,
750
+ );
751
+ };
752
+
753
+ export type ChannelsSegment = {
754
+ type: 'channels-segment';
755
+ channels: number;
756
+ };
757
+
758
+ export const parseChannelsSegment = (
759
+ iterator: BufferIterator,
760
+ length: number,
761
+ ): ChannelsSegment => {
762
+ if (length !== 1) {
763
+ throw new Error(
764
+ `Expected length of channels segment to be 1, got ${length}`,
765
+ );
766
+ }
767
+
768
+ const channels = iterator.getUint8();
769
+
770
+ return {
771
+ type: 'channels-segment',
772
+ channels,
773
+ };
774
+ };
775
+
776
+ export type BitDepthSegment = {
777
+ type: 'bit-depth-segment';
778
+ bitDepth: number;
779
+ };
780
+
781
+ export const parseBitDepthSegment = (
782
+ iterator: BufferIterator,
783
+ length: number,
784
+ ): BitDepthSegment => {
785
+ if (length !== 1) {
786
+ throw new Error(
787
+ `Expected length of bit depth segment to be 1, got ${length}`,
788
+ );
789
+ }
790
+
791
+ const bitDepth = iterator.getUint8();
792
+
793
+ return {
794
+ type: 'bit-depth-segment',
795
+ bitDepth,
796
+ };
797
+ };