@remotion/media-parser 4.0.201 → 4.0.202

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 (113) hide show
  1. package/dist/boxes/iso-base-media/mvhd.js +2 -2
  2. package/dist/boxes/iso-base-media/stsd/keys.js +1 -1
  3. package/dist/boxes/webm/av1-codec-private.js +1 -1
  4. package/dist/boxes/webm/description.d.ts +2 -2
  5. package/dist/boxes/webm/description.js +2 -2
  6. package/dist/boxes/webm/ebml.d.ts +2 -2
  7. package/dist/boxes/webm/ebml.js +23 -1
  8. package/dist/boxes/webm/get-ready-tracks.d.ts +1 -1
  9. package/dist/boxes/webm/get-ready-tracks.js +3 -3
  10. package/dist/boxes/webm/get-sample-from-block.d.ts +17 -0
  11. package/dist/boxes/webm/get-sample-from-block.js +78 -0
  12. package/dist/boxes/webm/get-track.d.ts +2 -2
  13. package/dist/boxes/webm/get-track.js +26 -25
  14. package/dist/boxes/webm/make-header.d.ts +3 -8
  15. package/dist/boxes/webm/make-header.js +43 -20
  16. package/dist/boxes/webm/parse-ebml.d.ts +9 -4
  17. package/dist/boxes/webm/parse-ebml.js +122 -13
  18. package/dist/boxes/webm/segments/all-segments.d.ts +421 -107
  19. package/dist/boxes/webm/segments/all-segments.js +260 -33
  20. package/dist/boxes/webm/segments/seek-position.js +1 -1
  21. package/dist/boxes/webm/segments/seek.d.ts +1 -1
  22. package/dist/boxes/webm/segments/seek.js +2 -8
  23. package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
  24. package/dist/boxes/webm/segments/track-entry.d.ts +3 -191
  25. package/dist/boxes/webm/segments/track-entry.js +2 -456
  26. package/dist/boxes/webm/segments.d.ts +3 -16
  27. package/dist/boxes/webm/segments.js +12 -196
  28. package/dist/boxes/webm/traversal.d.ts +5 -6
  29. package/dist/boxes/webm/traversal.js +6 -6
  30. package/dist/buffer-iterator.d.ts +1 -1
  31. package/dist/buffer-iterator.js +3 -3
  32. package/dist/create/create-media.d.ts +2 -0
  33. package/dist/create/create-media.js +36 -0
  34. package/dist/create/matroska-header.d.ts +1 -0
  35. package/dist/create/matroska-header.js +66 -0
  36. package/dist/create/matroska-info.d.ts +4 -0
  37. package/dist/create/matroska-info.js +39 -0
  38. package/dist/create/matroska-segment.d.ts +1 -0
  39. package/dist/create/matroska-segment.js +12 -0
  40. package/dist/create/matroska-trackentry.d.ts +21 -0
  41. package/dist/create/matroska-trackentry.js +191 -0
  42. package/dist/create-media.d.ts +1 -0
  43. package/dist/create-media.js +78 -0
  44. package/dist/get-audio-codec.d.ts +1 -1
  45. package/dist/get-audio-codec.js +13 -13
  46. package/dist/get-duration.js +12 -14
  47. package/dist/get-tracks.js +2 -2
  48. package/dist/get-video-codec.js +13 -13
  49. package/dist/parse-media.js +4 -1
  50. package/dist/parser-context.d.ts +1 -0
  51. package/dist/parser-state.js +3 -2
  52. package/dist/readers/from-fetch.d.ts +2 -0
  53. package/dist/readers/from-fetch.js +64 -0
  54. package/dist/readers/from-node.d.ts +2 -0
  55. package/dist/readers/from-node.js +40 -0
  56. package/dist/readers/from-web-file.d.ts +2 -0
  57. package/dist/readers/from-web-file.js +39 -0
  58. package/dist/readers/reader.d.ts +11 -0
  59. package/dist/readers/reader.js +2 -0
  60. package/dist/traversal.d.ts +19 -17
  61. package/dist/traversal.js +38 -39
  62. package/dist/writers/web-fs.d.ts +2 -0
  63. package/dist/writers/web-fs.js +28 -0
  64. package/dist/writers/writer.d.ts +9 -0
  65. package/dist/writers/writer.js +2 -0
  66. package/input.webm +0 -0
  67. package/package.json +2 -2
  68. package/src/boxes/iso-base-media/mvhd.ts +2 -2
  69. package/src/boxes/iso-base-media/stsd/keys.ts +1 -1
  70. package/src/boxes/webm/av1-codec-private.ts +1 -1
  71. package/src/boxes/webm/description.ts +7 -4
  72. package/src/boxes/webm/ebml.ts +24 -4
  73. package/src/boxes/webm/get-ready-tracks.ts +4 -4
  74. package/src/boxes/webm/get-sample-from-block.ts +125 -0
  75. package/src/boxes/webm/get-track.ts +38 -31
  76. package/src/boxes/webm/make-header.ts +58 -51
  77. package/src/boxes/webm/parse-ebml.ts +170 -16
  78. package/src/boxes/webm/segments/all-segments.ts +379 -62
  79. package/src/boxes/webm/segments/track-entry.ts +3 -846
  80. package/src/boxes/webm/segments.ts +18 -410
  81. package/src/boxes/webm/traversal.ts +17 -17
  82. package/src/buffer-iterator.ts +5 -4
  83. package/src/get-audio-codec.ts +14 -16
  84. package/src/get-duration.ts +15 -16
  85. package/src/get-tracks.ts +2 -2
  86. package/src/get-video-codec.ts +13 -15
  87. package/src/parse-media.ts +6 -1
  88. package/src/parser-context.ts +1 -0
  89. package/src/parser-state.ts +2 -2
  90. package/src/test/create-matroska.test.ts +237 -23
  91. package/src/test/matroska.test.ts +283 -348
  92. package/src/test/mvhd.test.ts +1 -1
  93. package/src/test/parse-esds.test.ts +2 -2
  94. package/src/test/parse-stco.test.ts +2 -2
  95. package/src/test/parse-stsc.test.ts +2 -2
  96. package/src/test/parse-stsz.test.ts +2 -2
  97. package/src/test/parse-stts.test.ts +1 -1
  98. package/src/test/stsd.test.ts +4 -2
  99. package/src/test/tkhd.test.ts +1 -1
  100. package/src/traversal.ts +62 -85
  101. package/tsconfig.tsbuildinfo +1 -1
  102. package/src/boxes/webm/segments/duration.ts +0 -29
  103. package/src/boxes/webm/segments/info.ts +0 -34
  104. package/src/boxes/webm/segments/main.ts +0 -6
  105. package/src/boxes/webm/segments/muxing.ts +0 -18
  106. package/src/boxes/webm/segments/seek-head.ts +0 -34
  107. package/src/boxes/webm/segments/seek-position.ts +0 -18
  108. package/src/boxes/webm/segments/seek.ts +0 -55
  109. package/src/boxes/webm/segments/timestamp-scale.ts +0 -17
  110. package/src/boxes/webm/segments/tracks.ts +0 -32
  111. package/src/boxes/webm/segments/void.ts +0 -18
  112. package/src/boxes/webm/segments/writing.ts +0 -18
  113. package/src/combine-uint8array.ts +0 -13
@@ -11,9 +11,7 @@ import type { StszBox } from './boxes/iso-base-media/stsd/stsz';
11
11
  import type { SttsBox } from './boxes/iso-base-media/stsd/stts';
12
12
  import type { TkhdBox } from './boxes/iso-base-media/tkhd';
13
13
  import type { TrakBox } from './boxes/iso-base-media/trak/trak';
14
- import type { MainSegment } from './boxes/webm/segments/main';
15
- import type { TimestampScaleSegment } from './boxes/webm/segments/timestamp-scale';
16
- import type { AudioSegment, ClusterSegment, CodecSegment, DisplayHeightSegment, DisplayWidthSegment, HeightSegment, TrackEntrySegment, TrackTypeSegment, VideoSegment, WidthSegment } from './boxes/webm/segments/track-entry';
14
+ import type { AudioSegment, ClusterSegment, CodecIdSegment, DisplayHeightSegment, DisplayWidthSegment, HeightSegment, MainSegment, TimestampScaleSegment, TrackEntry, TrackTypeSegment, VideoSegment, WidthSegment } from './boxes/webm/segments/all-segments';
17
15
  import type { AnySegment, RegularBox } from './parse-result';
18
16
  export declare const getFtypBox: (segments: AnySegment[]) => FtypBox | null;
19
17
  export declare const getMoovBox: (segments: AnySegment[]) => MoovBox | null;
@@ -32,21 +30,25 @@ export declare const getStszBox: (trakBox: TrakBox) => StszBox | null;
32
30
  export declare const getStscBox: (trakBox: TrakBox) => StscBox | null;
33
31
  export declare const getStssBox: (trakBox: TrakBox) => StssBox | null;
34
32
  export declare const getClusterSegment: (segment: MainSegment) => ClusterSegment | null;
35
- export declare const getTracksSegment: (segment: MainSegment) => import("./boxes/webm/segments/tracks").TracksSegment | null;
33
+ export declare const getTracksSegment: (segment: MainSegment) => {
34
+ type: "Tracks";
35
+ value: import("./boxes/webm/segments/all-segments").PossibleEbml[];
36
+ minVintWidth: number;
37
+ } | null;
36
38
  export declare const getTimescaleSegment: (segment: MainSegment) => TimestampScaleSegment | null;
37
- export declare const getVideoSegment: (track: TrackEntrySegment) => VideoSegment | null;
38
- export declare const getAudioSegment: (track: TrackEntrySegment) => AudioSegment | null;
39
- export declare const getSampleRate: (track: TrackEntrySegment) => number | null;
40
- export declare const getNumberOfChannels: (track: TrackEntrySegment) => number;
41
- export declare const getBitDepth: (track: TrackEntrySegment) => number | null;
42
- export declare const getPrivateData: (track: TrackEntrySegment) => Uint8Array | null;
43
- export declare const getWidthSegment: (track: TrackEntrySegment) => WidthSegment | null;
44
- export declare const getHeightSegment: (track: TrackEntrySegment) => HeightSegment | null;
45
- export declare const getDisplayWidthSegment: (track: TrackEntrySegment) => DisplayWidthSegment | null;
46
- export declare const getDisplayHeightSegment: (track: TrackEntrySegment) => DisplayHeightSegment | null;
47
- export declare const getTrackTypeSegment: (track: TrackEntrySegment) => TrackTypeSegment | null;
48
- export declare const getTrackId: (track: TrackEntrySegment) => number;
49
- export declare const getCodecSegment: (track: TrackEntrySegment) => CodecSegment | null;
39
+ export declare const getVideoSegment: (track: TrackEntry) => VideoSegment | null;
40
+ export declare const getAudioSegment: (track: TrackEntry) => AudioSegment | null;
41
+ export declare const getSampleRate: (track: TrackEntry) => number | null;
42
+ export declare const getNumberOfChannels: (track: TrackEntry) => number;
43
+ export declare const getBitDepth: (track: TrackEntry) => number | null;
44
+ export declare const getPrivateData: (track: TrackEntry) => Uint8Array | null;
45
+ export declare const getWidthSegment: (track: TrackEntry) => WidthSegment | null;
46
+ export declare const getHeightSegment: (track: TrackEntry) => HeightSegment | null;
47
+ export declare const getDisplayWidthSegment: (track: TrackEntry) => DisplayWidthSegment | null;
48
+ export declare const getDisplayHeightSegment: (track: TrackEntry) => DisplayHeightSegment | null;
49
+ export declare const getTrackTypeSegment: (track: TrackEntry) => TrackTypeSegment | null;
50
+ export declare const getTrackId: (track: TrackEntry) => number;
51
+ export declare const getCodecSegment: (track: TrackEntry) => CodecIdSegment | null;
50
52
  export declare const hasSkippedMdatProcessing: (anySegment: AnySegment[]) => {
51
53
  skipped: false;
52
54
  fileOffset?: undefined;
package/dist/traversal.js CHANGED
@@ -151,41 +151,41 @@ const getStssBox = (trakBox) => {
151
151
  };
152
152
  exports.getStssBox = getStssBox;
153
153
  const getClusterSegment = (segment) => {
154
- const clusterSegment = segment.children.find((b) => b.type === 'cluster-segment');
154
+ const clusterSegment = segment.value.find((b) => b.type === 'Cluster');
155
155
  return clusterSegment !== null && clusterSegment !== void 0 ? clusterSegment : null;
156
156
  };
157
157
  exports.getClusterSegment = getClusterSegment;
158
158
  const getTracksSegment = (segment) => {
159
- const tracksSegment = segment.children.find((b) => b.type === 'tracks-segment');
160
- if (!tracksSegment || tracksSegment.type !== 'tracks-segment') {
159
+ const tracksSegment = segment.value.find((b) => b.type === 'Tracks');
160
+ if (!tracksSegment || tracksSegment.type !== 'Tracks') {
161
161
  return null;
162
162
  }
163
163
  return tracksSegment;
164
164
  };
165
165
  exports.getTracksSegment = getTracksSegment;
166
166
  const getTimescaleSegment = (segment) => {
167
- const infoSegment = segment.children.find((b) => b.type === 'info-segment');
168
- if (!infoSegment || infoSegment.type !== 'info-segment') {
167
+ const infoSegment = segment.value.find((b) => b.type === 'Info');
168
+ if (!infoSegment || infoSegment.type !== 'Info') {
169
169
  return null;
170
170
  }
171
- const timescale = infoSegment.children.find((b) => b.type === 'timestamp-scale-segment');
172
- if (!timescale || timescale.type !== 'timestamp-scale-segment') {
171
+ const timescale = infoSegment.value.find((b) => b.type === 'TimestampScale');
172
+ if (!timescale || timescale.type !== 'TimestampScale') {
173
173
  return null;
174
174
  }
175
175
  return timescale;
176
176
  };
177
177
  exports.getTimescaleSegment = getTimescaleSegment;
178
178
  const getVideoSegment = (track) => {
179
- const videoSegment = track.children.find((b) => b.type === 'video-segment');
180
- if (!videoSegment || videoSegment.type !== 'video-segment') {
179
+ const videoSegment = track.value.find((b) => b.type === 'Video');
180
+ if (!videoSegment || videoSegment.type !== 'Video') {
181
181
  return null;
182
182
  }
183
183
  return videoSegment !== null && videoSegment !== void 0 ? videoSegment : null;
184
184
  };
185
185
  exports.getVideoSegment = getVideoSegment;
186
186
  const getAudioSegment = (track) => {
187
- const audioSegment = track.children.find((b) => b.type === 'audio-segment');
188
- if (!audioSegment || audioSegment.type !== 'audio-segment') {
187
+ const audioSegment = track.value.find((b) => b.type === 'Audio');
188
+ if (!audioSegment || audioSegment.type !== 'Audio') {
189
189
  return null;
190
190
  }
191
191
  return audioSegment !== null && audioSegment !== void 0 ? audioSegment : null;
@@ -196,12 +196,11 @@ const getSampleRate = (track) => {
196
196
  if (!audioSegment) {
197
197
  return null;
198
198
  }
199
- const samplingFrequency = audioSegment.children.find((b) => b.type === 'sampling-frequency-segment');
200
- if (!samplingFrequency ||
201
- samplingFrequency.type !== 'sampling-frequency-segment') {
199
+ const samplingFrequency = audioSegment.value.find((b) => b.type === 'SamplingFrequency');
200
+ if (!samplingFrequency || samplingFrequency.type !== 'SamplingFrequency') {
202
201
  return null;
203
202
  }
204
- return samplingFrequency.samplingFrequency;
203
+ return samplingFrequency.value.value;
205
204
  };
206
205
  exports.getSampleRate = getSampleRate;
207
206
  const getNumberOfChannels = (track) => {
@@ -209,11 +208,11 @@ const getNumberOfChannels = (track) => {
209
208
  if (!audioSegment) {
210
209
  throw new Error('Could not find audio segment');
211
210
  }
212
- const channels = audioSegment.children.find((b) => b.type === 'channels-segment');
213
- if (!channels || channels.type !== 'channels-segment') {
211
+ const channels = audioSegment.value.find((b) => b.type === 'Channels');
212
+ if (!channels || channels.type !== 'Channels') {
214
213
  return 1;
215
214
  }
216
- return channels.channels;
215
+ return channels.value.value;
217
216
  };
218
217
  exports.getNumberOfChannels = getNumberOfChannels;
219
218
  const getBitDepth = (track) => {
@@ -221,19 +220,19 @@ const getBitDepth = (track) => {
221
220
  if (!audioSegment) {
222
221
  return null;
223
222
  }
224
- const bitDepth = audioSegment.children.find((b) => b.type === 'bit-depth-segment');
225
- if (!bitDepth || bitDepth.type !== 'bit-depth-segment') {
223
+ const bitDepth = audioSegment.value.find((b) => b.type === 'BitDepth');
224
+ if (!bitDepth || bitDepth.type !== 'BitDepth') {
226
225
  return null;
227
226
  }
228
- return bitDepth.bitDepth;
227
+ return bitDepth.value.value;
229
228
  };
230
229
  exports.getBitDepth = getBitDepth;
231
230
  const getPrivateData = (track) => {
232
- const privateData = track.children.find((b) => b.type === 'codec-private-segment');
233
- if (!privateData || privateData.type !== 'codec-private-segment') {
231
+ const privateData = track.value.find((b) => b.type === 'CodecPrivate');
232
+ if (!privateData || privateData.type !== 'CodecPrivate') {
234
233
  return null;
235
234
  }
236
- return privateData.codecPrivateData;
235
+ return privateData.value;
237
236
  };
238
237
  exports.getPrivateData = getPrivateData;
239
238
  const getWidthSegment = (track) => {
@@ -241,8 +240,8 @@ const getWidthSegment = (track) => {
241
240
  if (!videoSegment) {
242
241
  return null;
243
242
  }
244
- const width = videoSegment.children.find((b) => b.type === 'width-segment');
245
- if (!width || width.type !== 'width-segment') {
243
+ const width = videoSegment.value.find((b) => b.type === 'PixelWidth');
244
+ if (!width || width.type !== 'PixelWidth') {
246
245
  return null;
247
246
  }
248
247
  return width;
@@ -253,8 +252,8 @@ const getHeightSegment = (track) => {
253
252
  if (!videoSegment) {
254
253
  return null;
255
254
  }
256
- const height = videoSegment.children.find((b) => b.type === 'height-segment');
257
- if (!height || height.type !== 'height-segment') {
255
+ const height = videoSegment.value.find((b) => b.type === 'PixelHeight');
256
+ if (!height || height.type !== 'PixelHeight') {
258
257
  return null;
259
258
  }
260
259
  return height;
@@ -265,8 +264,8 @@ const getDisplayWidthSegment = (track) => {
265
264
  if (!videoSegment) {
266
265
  return null;
267
266
  }
268
- const displayWidth = videoSegment.children.find((b) => b.type === 'display-width-segment');
269
- if (!displayWidth || displayWidth.type !== 'display-width-segment') {
267
+ const displayWidth = videoSegment.value.find((b) => b.type === 'DisplayWidth');
268
+ if (!displayWidth || displayWidth.type !== 'DisplayWidth') {
270
269
  return null;
271
270
  }
272
271
  return displayWidth;
@@ -277,32 +276,32 @@ const getDisplayHeightSegment = (track) => {
277
276
  if (!videoSegment) {
278
277
  return null;
279
278
  }
280
- const displayHeight = videoSegment.children.find((b) => b.type === 'display-height-segment');
281
- if (!displayHeight || displayHeight.type !== 'display-height-segment') {
279
+ const displayHeight = videoSegment.value.find((b) => b.type === 'DisplayHeight');
280
+ if (!displayHeight || displayHeight.type !== 'DisplayHeight') {
282
281
  return null;
283
282
  }
284
283
  return displayHeight;
285
284
  };
286
285
  exports.getDisplayHeightSegment = getDisplayHeightSegment;
287
286
  const getTrackTypeSegment = (track) => {
288
- const trackType = track.children.find((b) => b.type === 'track-type-segment');
289
- if (!trackType || trackType.type !== 'track-type-segment') {
287
+ const trackType = track.value.find((b) => b.type === 'TrackType');
288
+ if (!trackType || trackType.type !== 'TrackType') {
290
289
  return null;
291
290
  }
292
291
  return trackType;
293
292
  };
294
293
  exports.getTrackTypeSegment = getTrackTypeSegment;
295
294
  const getTrackId = (track) => {
296
- const trackId = track.children.find((b) => b.type === 'track-number-segment');
297
- if (!trackId || trackId.type !== 'track-number-segment') {
295
+ const trackId = track.value.find((b) => b.type === 'TrackNumber');
296
+ if (!trackId || trackId.type !== 'TrackNumber') {
298
297
  throw new Error('Expected track number segment');
299
298
  }
300
- return trackId.trackNumber;
299
+ return trackId.value.value;
301
300
  };
302
301
  exports.getTrackId = getTrackId;
303
302
  const getCodecSegment = (track) => {
304
- const codec = track.children.find((b) => b.type === 'codec-segment');
305
- if (!codec || codec.type !== 'codec-segment') {
303
+ const codec = track.value.find((b) => b.type === 'CodecID');
304
+ if (!codec || codec.type !== 'CodecID') {
306
305
  return null;
307
306
  }
308
307
  return codec;
@@ -0,0 +1,2 @@
1
+ import type { WriterInterface } from './writer';
2
+ export declare const webFsWriter: WriterInterface;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.webFsWriter = void 0;
4
+ const createContent = async () => {
5
+ const directoryHandle = await navigator.storage.getDirectory();
6
+ const fileHandle = await directoryHandle.getFileHandle('out.web', {
7
+ create: true,
8
+ });
9
+ const f = await fileHandle.getFile();
10
+ const writable = await fileHandle.createWritable();
11
+ return {
12
+ write: async (arr) => {
13
+ await writable.write(arr);
14
+ },
15
+ save: async () => {
16
+ const picker = await window.showSaveFilePicker({
17
+ suggestedName: `${Math.random().toString().replace('.', '')}.webm`,
18
+ });
19
+ const pickerWriteable = await picker.createWritable();
20
+ const stream = f.stream();
21
+ await stream.pipeTo(pickerWriteable);
22
+ await writable.close();
23
+ },
24
+ };
25
+ };
26
+ exports.webFsWriter = {
27
+ createContent,
28
+ };
@@ -0,0 +1,9 @@
1
+ type Writer = {
2
+ write: (arr: Uint8Array) => Promise<void>;
3
+ save: () => Promise<void>;
4
+ };
5
+ type CreateContent = () => Promise<Writer>;
6
+ export type WriterInterface = {
7
+ createContent: CreateContent;
8
+ };
9
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/input.webm ADDED
Binary file
package/package.json CHANGED
@@ -3,11 +3,11 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/media-parser"
4
4
  },
5
5
  "name": "@remotion/media-parser",
6
- "version": "4.0.201",
6
+ "version": "4.0.202",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "devDependencies": {
10
- "@remotion/renderer": "4.0.201"
10
+ "@remotion/renderer": "4.0.202"
11
11
  },
12
12
  "publishConfig": {
13
13
  "access": "public"
@@ -59,7 +59,7 @@ export const parseMvhd = ({
59
59
  const durationInSeconds = durationInUnits / timeScale;
60
60
 
61
61
  const rateArray = iterator.getSlice(4);
62
- const rateView = getArrayBufferIterator(rateArray);
62
+ const rateView = getArrayBufferIterator(rateArray, rateArray.length);
63
63
  const rate =
64
64
  rateView.getInt8() * 10 +
65
65
  rateView.getInt8() +
@@ -67,7 +67,7 @@ export const parseMvhd = ({
67
67
  rateView.getInt8() * 0.01;
68
68
 
69
69
  const volumeArray = iterator.getSlice(2);
70
- const volumeView = getArrayBufferIterator(volumeArray);
70
+ const volumeView = getArrayBufferIterator(volumeArray, volumeArray.length);
71
71
 
72
72
  const volume = volumeView.getInt8() + volumeView.getInt8() * 0.1;
73
73
 
@@ -6,7 +6,7 @@ export interface KeysBox extends BaseBox {
6
6
  }
7
7
 
8
8
  export const parseKeys = (data: Uint8Array, offset: number): KeysBox => {
9
- const iterator = getArrayBufferIterator(data);
9
+ const iterator = getArrayBufferIterator(data, data.byteLength);
10
10
  const size = iterator.getUint32();
11
11
  if (size !== data.byteLength) {
12
12
  throw new Error(`Expected keys size of ${data.byteLength}, got ${size}`);
@@ -5,7 +5,7 @@ export const parseAv1PrivateData = (
5
5
  data: Uint8Array,
6
6
  colrAtom: ColorParameterBox | null,
7
7
  ) => {
8
- const iterator = getArrayBufferIterator(data);
8
+ const iterator = getArrayBufferIterator(data, data.byteLength);
9
9
  iterator.startReadingBits();
10
10
  if (iterator.getBits(1) !== 1) {
11
11
  iterator.destroy();
@@ -1,12 +1,12 @@
1
1
  import {getArrayBufferIterator} from '../../buffer-iterator';
2
2
  import {getCodecSegment, getPrivateData} from '../../traversal';
3
- import type {TrackEntrySegment} from './segments/track-entry';
3
+ import type {TrackEntry} from './segments/all-segments';
4
4
 
5
5
  export const getAudioDescription = (
6
- track: TrackEntrySegment,
6
+ track: TrackEntry,
7
7
  ): undefined | Uint8Array => {
8
8
  const codec = getCodecSegment(track);
9
- if (!codec || codec.codec !== 'A_VORBIS') {
9
+ if (!codec || codec.value !== 'A_VORBIS') {
10
10
  return undefined;
11
11
  }
12
12
 
@@ -59,7 +59,10 @@ export const getAudioDescription = (
59
59
 
60
60
  const vorbisBooks = privateData.slice(offset);
61
61
 
62
- const bufferIterator = getArrayBufferIterator(vorbisInfo.slice(0));
62
+ const bufferIterator = getArrayBufferIterator(
63
+ vorbisInfo.slice(0),
64
+ vorbisInfo.length,
65
+ );
63
66
 
64
67
  // type
65
68
  bufferIterator.getUint8();
@@ -32,10 +32,9 @@ export const measureEBMLVarInt = (value: number) => {
32
32
  throw new Error('EBML VINT size not supported ' + value);
33
33
  };
34
34
 
35
- export const getVariableInt = (
36
- value: number,
37
- width: number = measureEBMLVarInt(value),
38
- ) => {
35
+ export const getVariableInt = (value: number, minWidth: number | null) => {
36
+ const width = Math.max(measureEBMLVarInt(value), minWidth ?? 0);
37
+
39
38
  switch (width) {
40
39
  case 1:
41
40
  return new Uint8Array([(1 << 7) | value]);
@@ -72,6 +71,27 @@ export const getVariableInt = (
72
71
  value >> 8,
73
72
  value,
74
73
  ]);
74
+ case 7:
75
+ return new Uint8Array([
76
+ (1 << 1) | ((value / 2 ** 48) & 0x1),
77
+ (value / 2 ** 40) | 0,
78
+ (value / 2 ** 32) | 0,
79
+ value >> 24,
80
+ value >> 16,
81
+ value >> 8,
82
+ value,
83
+ ]);
84
+ case 8:
85
+ return new Uint8Array([
86
+ (1 << 0) | ((value / 2 ** 56) & 0x1),
87
+ (value / 2 ** 48) | 0,
88
+ (value / 2 ** 40) | 0,
89
+ (value / 2 ** 32) | 0,
90
+ value >> 24,
91
+ value >> 16,
92
+ value >> 8,
93
+ value,
94
+ ]);
75
95
  default:
76
96
  throw new Error('Bad EBML VINT size ' + width);
77
97
  }
@@ -1,7 +1,7 @@
1
1
  import type {Track} from '../../get-tracks';
2
2
  import {getTracksSegment} from '../../traversal';
3
3
  import {getTrack} from './get-track';
4
- import type {MainSegment} from './segments/main';
4
+ import type {MainSegment} from './segments/all-segments';
5
5
 
6
6
  export const getTracksFromMatroska = (
7
7
  segment: MainSegment,
@@ -14,12 +14,12 @@ export const getTracksFromMatroska = (
14
14
 
15
15
  const tracks: Track[] = [];
16
16
 
17
- for (const trackEntrySegment of tracksSegment.children) {
18
- if (trackEntrySegment.type === 'crc32-segment') {
17
+ for (const trackEntrySegment of tracksSegment.value) {
18
+ if (trackEntrySegment.type === 'Crc32') {
19
19
  continue;
20
20
  }
21
21
 
22
- if (trackEntrySegment.type !== 'track-entry-segment') {
22
+ if (trackEntrySegment.type !== 'TrackEntry') {
23
23
  throw new Error('Expected track entry segment');
24
24
  }
25
25
 
@@ -0,0 +1,125 @@
1
+ import {getArrayBufferIterator} from '../../buffer-iterator';
2
+ import type {ParserContext} from '../../parser-context';
3
+ import type {AudioSample, VideoSample} from '../../webcodec-sample-types';
4
+ import type {BlockSegment, SimpleBlockSegment} from './segments/all-segments';
5
+ import {matroskaElements} from './segments/all-segments';
6
+ import {parseBlockFlags} from './segments/block-simple-block-flags';
7
+
8
+ type SampleResult =
9
+ | {
10
+ type: 'video-sample';
11
+ videoSample: VideoSample;
12
+ }
13
+ | {
14
+ type: 'audio-sample';
15
+ audioSample: AudioSample;
16
+ }
17
+ | {
18
+ type: 'partial-video-sample';
19
+ partialVideoSample: Omit<VideoSample, 'type'>;
20
+ }
21
+ | {
22
+ type: 'no-sample';
23
+ };
24
+
25
+ export const getSampleFromBlock = (
26
+ ebml: BlockSegment | SimpleBlockSegment,
27
+ parserContext: ParserContext,
28
+ offset: number,
29
+ ): SampleResult => {
30
+ const iterator = getArrayBufferIterator(ebml.value, ebml.value.length);
31
+ const trackNumber = iterator.getVint();
32
+ if (trackNumber === null) {
33
+ throw new Error('Not enough data to get track number, should not happen');
34
+ }
35
+
36
+ const timecodeRelativeToCluster = iterator.getUint16();
37
+
38
+ const {keyframe} = parseBlockFlags(
39
+ iterator,
40
+ ebml.type === 'SimpleBlock'
41
+ ? matroskaElements.SimpleBlock
42
+ : matroskaElements.Block,
43
+ );
44
+
45
+ const {codec, trackTimescale} =
46
+ parserContext.parserState.getTrackInfoByNumber(trackNumber);
47
+
48
+ const clusterOffset =
49
+ parserContext.parserState.getTimestampOffsetForByteOffset(offset);
50
+
51
+ const timescale = parserContext.parserState.getTimescale();
52
+
53
+ if (clusterOffset === undefined) {
54
+ throw new Error('Could not find offset for byte offset ' + offset);
55
+ }
56
+
57
+ // https://github.com/hubblec4/Matroska-Chapters-Specs/blob/master/notes.md/#timestampscale
58
+ // The TimestampScale Element is used to calculate the Raw Timestamp of a Block. The timestamp is obtained by adding the Block's timestamp to the Cluster's Timestamp Element, and then multiplying that result by the TimestampScale. The result will be the Block's Raw Timestamp in nanoseconds.
59
+ const timecodeInNanoSeconds =
60
+ (timecodeRelativeToCluster + clusterOffset) *
61
+ timescale *
62
+ (trackTimescale ?? 1);
63
+
64
+ // Timecode should be in microseconds
65
+ const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;
66
+
67
+ if (!codec) {
68
+ throw new Error(`Could not find codec for track ${trackNumber}`);
69
+ }
70
+
71
+ const remainingNow = ebml.value.length - (iterator.counter.getOffset() - 0);
72
+
73
+ if (codec.startsWith('V_')) {
74
+ const partialVideoSample: Omit<VideoSample, 'type'> = {
75
+ data: iterator.getSlice(remainingNow),
76
+ cts: null,
77
+ dts: null,
78
+ duration: undefined,
79
+ trackId: trackNumber,
80
+ timestamp: timecodeInMicroseconds,
81
+ };
82
+
83
+ if (keyframe === null) {
84
+ iterator.destroy();
85
+
86
+ return {
87
+ type: 'partial-video-sample',
88
+ partialVideoSample,
89
+ };
90
+ }
91
+
92
+ const sample: VideoSample = {
93
+ ...partialVideoSample,
94
+ type: keyframe ? 'key' : 'delta',
95
+ };
96
+
97
+ iterator.destroy();
98
+
99
+ return {
100
+ type: 'video-sample',
101
+ videoSample: sample,
102
+ };
103
+ }
104
+
105
+ if (codec.startsWith('A_')) {
106
+ const audioSample: AudioSample = {
107
+ data: iterator.getSlice(remainingNow),
108
+ trackId: trackNumber,
109
+ timestamp: timecodeInMicroseconds,
110
+ type: 'key',
111
+ };
112
+
113
+ iterator.destroy();
114
+
115
+ return {
116
+ type: 'audio-sample',
117
+ audioSample,
118
+ };
119
+ }
120
+
121
+ iterator.destroy();
122
+ return {
123
+ type: 'no-sample',
124
+ };
125
+ };