@remotion/media-parser 4.0.205 → 4.0.207

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 (127) hide show
  1. package/dist/boxes/iso-base-media/stsd/ctts.js +8 -1
  2. package/dist/boxes/iso-base-media/stsd/samples.d.ts +6 -3
  3. package/dist/boxes/iso-base-media/stsd/samples.js +6 -6
  4. package/dist/boxes/webm/ebml.d.ts +1 -1
  5. package/dist/boxes/webm/make-header.d.ts +6 -2
  6. package/dist/boxes/webm/make-header.js +102 -18
  7. package/dist/boxes/webm/parse-ebml.js +9 -3
  8. package/dist/boxes/webm/segments/all-segments.d.ts +70 -12
  9. package/dist/boxes/webm/segments/all-segments.js +43 -5
  10. package/dist/boxes/webm/segments.js +2 -2
  11. package/dist/create/create-media.d.ts +6 -0
  12. package/dist/create/create-media.js +35 -17
  13. package/dist/create/matroska-info.js +3 -1
  14. package/dist/create/matroska-trackentry.d.ts +13 -3
  15. package/dist/create/matroska-trackentry.js +78 -3
  16. package/dist/index.d.ts +5 -0
  17. package/dist/index.js +5 -1
  18. package/dist/options.d.ts +1 -1
  19. package/dist/parse-media.js +1 -1
  20. package/dist/traversal.d.ts +1 -1
  21. package/package.json +13 -8
  22. package/src/boxes/iso-base-media/stsd/ctts.ts +10 -1
  23. package/src/boxes/iso-base-media/stsd/samples.ts +12 -9
  24. package/src/boxes/webm/make-header.ts +132 -24
  25. package/src/boxes/webm/parse-ebml.ts +11 -3
  26. package/src/boxes/webm/segments/all-segments.ts +67 -7
  27. package/src/boxes/webm/segments.ts +2 -2
  28. package/src/create/cluster-segment.ts +62 -0
  29. package/src/create/create-media.ts +172 -0
  30. package/src/create/matroska-header.ts +63 -0
  31. package/src/create/matroska-info.ts +46 -0
  32. package/src/create/matroska-segment.ts +10 -0
  33. package/src/create/matroska-trackentry.ts +325 -0
  34. package/src/index.ts +9 -0
  35. package/src/options.ts +1 -1
  36. package/src/parse-media.ts +1 -1
  37. package/src/test/av1.test.ts +1 -1
  38. package/src/test/create-matroska.test.ts +31 -6
  39. package/src/test/duration.test.ts +1 -1
  40. package/src/test/matroska.test.ts +35 -5
  41. package/src/test/parse-video.test.ts +1 -1
  42. package/src/test/parse-webm.test.ts +1 -1
  43. package/src/test/stream-local.test.ts +1 -1
  44. package/src/test/stream-samples.test.ts +1 -1
  45. package/src/writers/web-fs.ts +50 -0
  46. package/src/writers/writer.ts +12 -0
  47. package/tsconfig.tsbuildinfo +1 -1
  48. package/dist/av1-codec-string.d.ts +0 -3
  49. package/dist/av1-codec-string.js +0 -91
  50. package/dist/boxes/iso-base-media/ftype.d.ts +0 -9
  51. package/dist/boxes/iso-base-media/ftype.js +0 -31
  52. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.d.ts +0 -20
  53. package/dist/boxes/iso-base-media/stsd/avcc-hvcc.js +0 -73
  54. package/dist/boxes/iso-base-media/stts/stts.d.ts +0 -15
  55. package/dist/boxes/iso-base-media/stts/stts.js +0 -35
  56. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.d.ts +0 -14
  57. package/dist/boxes/webm/bitstream/av1/bitstream-frame-header.js +0 -67
  58. package/dist/boxes/webm/bitstream/av1/bitstream-frame.d.ts +0 -11
  59. package/dist/boxes/webm/bitstream/av1/bitstream-frame.js +0 -14
  60. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.d.ts +0 -6
  61. package/dist/boxes/webm/bitstream/av1/chroma-sample-position.js +0 -9
  62. package/dist/boxes/webm/bitstream/av1/color-config.d.ts +0 -16
  63. package/dist/boxes/webm/bitstream/av1/color-config.js +0 -103
  64. package/dist/boxes/webm/bitstream/av1/color-primaries.d.ts +0 -14
  65. package/dist/boxes/webm/bitstream/av1/color-primaries.js +0 -17
  66. package/dist/boxes/webm/bitstream/av1/decoder-model-info.d.ts +0 -9
  67. package/dist/boxes/webm/bitstream/av1/decoder-model-info.js +0 -17
  68. package/dist/boxes/webm/bitstream/av1/frame.d.ts +0 -0
  69. package/dist/boxes/webm/bitstream/av1/frame.js +0 -1
  70. package/dist/boxes/webm/bitstream/av1/header-segment.d.ts +0 -51
  71. package/dist/boxes/webm/bitstream/av1/header-segment.js +0 -183
  72. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.d.ts +0 -17
  73. package/dist/boxes/webm/bitstream/av1/matrix-coefficients.js +0 -20
  74. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.d.ts +0 -10
  75. package/dist/boxes/webm/bitstream/av1/operating-parameters-info.js +0 -15
  76. package/dist/boxes/webm/bitstream/av1/temporal-point-info.d.ts +0 -5
  77. package/dist/boxes/webm/bitstream/av1/temporal-point-info.js +0 -8
  78. package/dist/boxes/webm/bitstream/av1/timing-info.d.ts +0 -8
  79. package/dist/boxes/webm/bitstream/av1/timing-info.js +0 -20
  80. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.d.ts +0 -21
  81. package/dist/boxes/webm/bitstream/av1/transfer-characteristics.js +0 -24
  82. package/dist/boxes/webm/bitstream/av1/uvlc.d.ts +0 -2
  83. package/dist/boxes/webm/bitstream/av1/uvlc.js +0 -20
  84. package/dist/boxes/webm/bitstream/av1.d.ts +0 -20
  85. package/dist/boxes/webm/bitstream/av1.js +0 -118
  86. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.d.ts +0 -0
  87. package/dist/boxes/webm/bitstream/h264/get-h264-descriptor.js +0 -1
  88. package/dist/boxes/webm/segments/duration.d.ts +0 -6
  89. package/dist/boxes/webm/segments/duration.js +0 -19
  90. package/dist/boxes/webm/segments/info.d.ts +0 -9
  91. package/dist/boxes/webm/segments/info.js +0 -22
  92. package/dist/boxes/webm/segments/main.d.ts +0 -5
  93. package/dist/boxes/webm/segments/main.js +0 -2
  94. package/dist/boxes/webm/segments/muxing.d.ts +0 -6
  95. package/dist/boxes/webm/segments/muxing.js +0 -11
  96. package/dist/boxes/webm/segments/seek-head.d.ts +0 -9
  97. package/dist/boxes/webm/segments/seek-head.js +0 -22
  98. package/dist/boxes/webm/segments/seek-position.d.ts +0 -6
  99. package/dist/boxes/webm/segments/seek-position.js +0 -11
  100. package/dist/boxes/webm/segments/seek.d.ts +0 -13
  101. package/dist/boxes/webm/segments/seek.js +0 -35
  102. package/dist/boxes/webm/segments/timestamp-scale.d.ts +0 -6
  103. package/dist/boxes/webm/segments/timestamp-scale.js +0 -11
  104. package/dist/boxes/webm/segments/tracks.d.ts +0 -8
  105. package/dist/boxes/webm/segments/tracks.js +0 -21
  106. package/dist/boxes/webm/segments/unknown.d.ts +0 -6
  107. package/dist/boxes/webm/segments/unknown.js +0 -11
  108. package/dist/boxes/webm/segments/void.d.ts +0 -6
  109. package/dist/boxes/webm/segments/void.js +0 -11
  110. package/dist/boxes/webm/segments/writing.d.ts +0 -6
  111. package/dist/boxes/webm/segments/writing.js +0 -11
  112. package/dist/boxes/webm/tracks.d.ts +0 -8
  113. package/dist/boxes/webm/tracks.js +0 -21
  114. package/dist/combine-uint8array.d.ts +0 -1
  115. package/dist/combine-uint8array.js +0 -13
  116. package/dist/from-web.d.ts +0 -2
  117. package/dist/from-web.js +0 -45
  118. package/dist/get-video-metadata.d.ts +0 -2
  119. package/dist/get-video-metadata.js +0 -44
  120. package/dist/read-and-increment-offset.d.ts +0 -28
  121. package/dist/read-and-increment-offset.js +0 -177
  122. package/dist/understand-vorbis.d.ts +0 -1
  123. package/dist/understand-vorbis.js +0 -12
  124. /package/src/{from-fetch.ts → readers/from-fetch.ts} +0 -0
  125. /package/src/{from-node.ts → readers/from-node.ts} +0 -0
  126. /package/src/{from-web-file.ts → readers/from-web-file.ts} +0 -0
  127. /package/src/{reader.ts → readers/reader.ts} +0 -0
@@ -11,12 +11,22 @@ export declare const makeMatroskaVideoBytes: ({ color, width, height, }: {
11
11
  width: number;
12
12
  height: number;
13
13
  }) => BytesAndOffset;
14
- export declare const makeMatroskaVideoTrackEntryBytes: ({ color, width, height, defaultDuration, trackNumber, codecId, }: {
14
+ export type MakeTrackAudio = {
15
+ trackNumber: number;
16
+ codecId: string;
17
+ numberOfChannels: number;
18
+ sampleRate: number;
19
+ type: 'audio';
20
+ };
21
+ export type MakeTrackVideo = {
15
22
  color: MatroskaColorParams;
16
23
  width: number;
17
24
  height: number;
18
25
  defaultDuration: number;
19
26
  trackNumber: number;
20
27
  codecId: string;
21
- }) => BytesAndOffset;
22
- export declare const makeMatroskaTracks: (tracks: BytesAndOffset[]) => BytesAndOffset;
28
+ type: 'video';
29
+ };
30
+ export declare const makeMatroskaAudioTrackEntryBytes: ({ trackNumber, codecId, numberOfChannels: audioChannels, sampleRate, }: MakeTrackAudio) => BytesAndOffset;
31
+ export declare const makeMatroskaVideoTrackEntryBytes: ({ color, width, height, defaultDuration, trackNumber, codecId, }: MakeTrackVideo) => BytesAndOffset;
32
+ export declare const makeMatroskaTracks: (tracks: BytesAndOffset[]) => BytesAndOffset[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.makeMatroskaTracks = exports.makeMatroskaVideoTrackEntryBytes = exports.makeMatroskaVideoBytes = exports.makeMatroskaColorBytes = void 0;
3
+ exports.makeMatroskaTracks = exports.makeMatroskaVideoTrackEntryBytes = exports.makeMatroskaAudioTrackEntryBytes = exports.makeMatroskaVideoBytes = exports.makeMatroskaColorBytes = void 0;
4
4
  const make_header_1 = require("../boxes/webm/make-header");
5
5
  const makeMatroskaColorBytes = ({ transferChracteristics, matrixCoefficients, primaries, fullRange, }) => {
6
6
  const rangeValue = transferChracteristics && matrixCoefficients
@@ -112,6 +112,79 @@ const makeMatroskaVideoBytes = ({ color, width, height, }) => {
112
112
  });
113
113
  };
114
114
  exports.makeMatroskaVideoBytes = makeMatroskaVideoBytes;
115
+ const makeMatroskaAudioTrackEntryBytes = ({ trackNumber, codecId, numberOfChannels: audioChannels, sampleRate, }) => {
116
+ return (0, make_header_1.makeMatroskaBytes)({
117
+ type: 'TrackEntry',
118
+ minVintWidth: null,
119
+ value: [
120
+ {
121
+ type: 'TrackNumber',
122
+ value: {
123
+ value: trackNumber,
124
+ byteLength: null,
125
+ },
126
+ minVintWidth: null,
127
+ },
128
+ {
129
+ type: 'TrackUID',
130
+ value: '0x188FEB95C8EFABA',
131
+ minVintWidth: null,
132
+ },
133
+ {
134
+ type: 'TrackType',
135
+ value: {
136
+ value: 2,
137
+ byteLength: null,
138
+ },
139
+ minVintWidth: null,
140
+ },
141
+ {
142
+ type: 'TrackTimestampScale',
143
+ value: {
144
+ value: 1,
145
+ size: '64',
146
+ },
147
+ minVintWidth: null,
148
+ },
149
+ {
150
+ type: 'CodecID',
151
+ value: codecId,
152
+ minVintWidth: null,
153
+ },
154
+ {
155
+ type: 'Audio',
156
+ value: [
157
+ {
158
+ type: 'Channels',
159
+ minVintWidth: null,
160
+ value: {
161
+ value: audioChannels,
162
+ byteLength: null,
163
+ },
164
+ },
165
+ {
166
+ type: 'SamplingFrequency',
167
+ minVintWidth: null,
168
+ value: {
169
+ value: sampleRate,
170
+ size: '64',
171
+ },
172
+ },
173
+ {
174
+ type: 'BitDepth',
175
+ minVintWidth: null,
176
+ value: {
177
+ value: 32,
178
+ byteLength: null,
179
+ },
180
+ },
181
+ ],
182
+ minVintWidth: null,
183
+ },
184
+ ],
185
+ });
186
+ };
187
+ exports.makeMatroskaAudioTrackEntryBytes = makeMatroskaAudioTrackEntryBytes;
115
188
  const makeMatroskaVideoTrackEntryBytes = ({ color, width, height, defaultDuration, trackNumber, codecId, }) => {
116
189
  return (0, make_header_1.makeMatroskaBytes)({
117
190
  type: 'TrackEntry',
@@ -182,10 +255,12 @@ const makeMatroskaVideoTrackEntryBytes = ({ color, width, height, defaultDuratio
182
255
  };
183
256
  exports.makeMatroskaVideoTrackEntryBytes = makeMatroskaVideoTrackEntryBytes;
184
257
  const makeMatroskaTracks = (tracks) => {
185
- return (0, make_header_1.makeMatroskaBytes)({
258
+ return (0, make_header_1.padMatroskaBytes)((0, make_header_1.makeMatroskaBytes)({
186
259
  type: 'Tracks',
187
260
  value: tracks,
188
261
  minVintWidth: null,
189
- });
262
+ }),
263
+ // TODO: That's too much padding
264
+ 1000);
190
265
  };
191
266
  exports.makeMatroskaTracks = makeMatroskaTracks;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,7 @@
1
+ export { AudioTrack, OtherTrack, Track, VideoTrack } from './get-tracks';
1
2
  export { parseMedia } from './parse-media';
2
3
  export { AudioSample, OnAudioSample, OnAudioTrack, OnVideoSample, OnVideoTrack, VideoSample, } from './webcodec-sample-types';
4
+ export type { MediaFn } from './create/create-media';
5
+ export declare const MediaParserInternals: {
6
+ createMedia: (writer: import("./writers/writer").WriterInterface) => Promise<import("./create/create-media").MediaFn>;
7
+ };
package/dist/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseMedia = void 0;
3
+ exports.MediaParserInternals = exports.parseMedia = void 0;
4
+ const create_media_1 = require("./create/create-media");
4
5
  var parse_media_1 = require("./parse-media");
5
6
  Object.defineProperty(exports, "parseMedia", { enumerable: true, get: function () { return parse_media_1.parseMedia; } });
7
+ exports.MediaParserInternals = {
8
+ createMedia: create_media_1.createMedia,
9
+ };
package/dist/options.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Dimensions } from './get-dimensions';
2
2
  import type { AudioTrack, VideoTrack } from './get-tracks';
3
3
  import type { AnySegment } from './parse-result';
4
4
  import type { InternalStats } from './parser-state';
5
- import type { ReaderInterface } from './reader';
5
+ import type { ReaderInterface } from './readers/reader';
6
6
  import type { OnAudioTrack, OnVideoTrack } from './webcodec-sample-types';
7
7
  export type KnownVideoCodecs = 'h264' | 'h265' | 'vp8' | 'vp9' | 'av1' | 'prores';
8
8
  export type KnownAudioCodecs = 'aac' | 'mp3' | 'aiff' | 'opus' | 'pcm' | 'vorbis' | 'unknown';
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseMedia = void 0;
4
4
  const buffer_iterator_1 = require("./buffer-iterator");
5
- const from_fetch_1 = require("./from-fetch");
6
5
  const get_audio_codec_1 = require("./get-audio-codec");
7
6
  const get_dimensions_1 = require("./get-dimensions");
8
7
  const get_duration_1 = require("./get-duration");
@@ -12,6 +11,7 @@ const get_video_codec_1 = require("./get-video-codec");
12
11
  const has_all_info_1 = require("./has-all-info");
13
12
  const parse_video_1 = require("./parse-video");
14
13
  const parser_state_1 = require("./parser-state");
14
+ const from_fetch_1 = require("./readers/from-fetch");
15
15
  const parseMedia = async ({ src, fields, reader: readerInterface = from_fetch_1.fetchReader, onAudioTrack, onVideoTrack, signal, }) => {
16
16
  const state = (0, parser_state_1.makeParserState)({
17
17
  hasAudioCallbacks: onAudioTrack !== null,
@@ -40,7 +40,7 @@ export declare const getClusterSegment: (segment: MainSegment) => ClusterSegment
40
40
  export declare const getTracksSegment: (segment: MainSegment) => {
41
41
  type: "Tracks";
42
42
  value: import("./boxes/webm/segments/all-segments").PossibleEbml[];
43
- minVintWidth: number;
43
+ minVintWidth: number | null;
44
44
  } | null;
45
45
  export declare const getTimescaleSegment: (segment: MainSegment) => TimestampScaleSegment | null;
46
46
  export declare const getVideoSegment: (track: TrackEntry) => VideoSegment | null;
package/package.json CHANGED
@@ -3,11 +3,12 @@
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.205",
6
+ "version": "4.0.207",
7
7
  "main": "dist/index.js",
8
8
  "sideEffects": false,
9
9
  "devDependencies": {
10
- "@remotion/renderer": "4.0.205"
10
+ "@types/wicg-file-system-access": "2023.10.5",
11
+ "@remotion/renderer": "4.0.207"
11
12
  },
12
13
  "publishConfig": {
13
14
  "access": "public"
@@ -17,21 +18,25 @@
17
18
  },
18
19
  "exports": {
19
20
  ".": "./dist/index.js",
20
- "./node": "./dist/from-node.js",
21
- "./fetch": "./dist/from-fetch.js",
22
- "./web-file": "./dist/from-web-file.js",
21
+ "./node": "./dist/readers/from-node.js",
22
+ "./fetch": "./dist/readers/from-fetch.js",
23
+ "./web-file": "./dist/readers/from-web-file.js",
24
+ "./web-fs": "./dist/writers/web-fs.js",
23
25
  "./package.json": "./package.json"
24
26
  },
25
27
  "typesVersions": {
26
28
  ">=1.0": {
27
29
  "node": [
28
- "dist/from-node.d.ts"
30
+ "dist/readers/from-node.d.ts"
29
31
  ],
30
32
  "fetch": [
31
- "dist/from-fetch.d.ts"
33
+ "dist/readers/from-fetch.d.ts"
32
34
  ],
33
35
  "web-file": [
34
- "dist/from-web-file.d.ts"
36
+ "dist/readers/from-web-file.d.ts"
37
+ ],
38
+ "web-fs": [
39
+ "dist/writers/web-fs.d.ts"
35
40
  ]
36
41
  }
37
42
  },
@@ -24,7 +24,7 @@ export const parseCtts = ({
24
24
  size: number;
25
25
  }): CttsBox => {
26
26
  const version = iterator.getUint8();
27
- if (version !== 0) {
27
+ if (version !== 0 && version !== 1) {
28
28
  throw new Error(`Unsupported CTTS version ${version}`);
29
29
  }
30
30
 
@@ -35,7 +35,16 @@ export const parseCtts = ({
35
35
 
36
36
  for (let i = 0; i < entryCount; i++) {
37
37
  const sampleCount = iterator.getUint32();
38
+
39
+ // V1 = signed, V0 = unsigned
40
+ // however some files are buggy
41
+
42
+ // Let's do the same thing as mp4box but uint32, based on our test set of videos
43
+ // https://github.com/gpac/mp4box.js/blob/c6cc468145bc5b031b866446111f29c8b620dbe6/src/parsing/ctts.js#L2
38
44
  const sampleOffset = iterator.getUint32();
45
+ if (sampleOffset < 0) {
46
+ throw new Error('ctts box uses negative values without using version 1');
47
+ }
39
48
 
40
49
  entries.push({
41
50
  sampleCount,
@@ -7,9 +7,6 @@ type SampleBase = {
7
7
  format: string;
8
8
  offset: number;
9
9
  dataReferenceIndex: number;
10
- version: number;
11
- revisionLevel: number;
12
- vendor: number[];
13
10
  size: number;
14
11
  };
15
12
 
@@ -25,6 +22,9 @@ export type AudioSample = SampleBase & {
25
22
  bytesPerFrame: number | null;
26
23
  bitsPerSample: number | null;
27
24
  children: AnySegment[];
25
+ version: number;
26
+ revisionLevel: number;
27
+ vendor: number[];
28
28
  };
29
29
 
30
30
  export type VideoSample = SampleBase & {
@@ -41,6 +41,9 @@ export type VideoSample = SampleBase & {
41
41
  depth: number;
42
42
  colorTableId: number;
43
43
  descriptors: AnySegment[];
44
+ version: number;
45
+ revisionLevel: number;
46
+ vendor: number[];
44
47
  };
45
48
 
46
49
  type UnknownSample = SampleBase & {
@@ -139,9 +142,6 @@ export const processSample = async ({
139
142
  iterator.discard(6);
140
143
 
141
144
  const dataReferenceIndex = iterator.getUint16();
142
- const version = iterator.getUint16();
143
- const revisionLevel = iterator.getUint16();
144
- const vendor = iterator.getSlice(4);
145
145
 
146
146
  if (!isVideo && !isAudio) {
147
147
  const bytesRemainingInBox =
@@ -153,9 +153,6 @@ export const processSample = async ({
153
153
  type: 'unknown',
154
154
  offset: fileOffset,
155
155
  dataReferenceIndex,
156
- version,
157
- revisionLevel,
158
- vendor: [...Array.from(new Uint8Array(vendor))],
159
156
  size: boxSize,
160
157
  format: boxFormat,
161
158
  },
@@ -163,6 +160,9 @@ export const processSample = async ({
163
160
  }
164
161
 
165
162
  if (isAudio) {
163
+ const version = iterator.getUint16();
164
+ const revisionLevel = iterator.getUint16();
165
+ const vendor = iterator.getSlice(4);
166
166
  if (version === 0) {
167
167
  const numberOfChannels = iterator.getUint16();
168
168
  const sampleSize = iterator.getUint16();
@@ -268,6 +268,9 @@ export const processSample = async ({
268
268
  }
269
269
 
270
270
  if (isVideo) {
271
+ const version = iterator.getUint16();
272
+ const revisionLevel = iterator.getUint16();
273
+ const vendor = iterator.getSlice(4);
271
274
  const temporalQuality = iterator.getUint32();
272
275
  const spacialQuality = iterator.getUint32();
273
276
  const width = iterator.getUint16();
@@ -1,16 +1,22 @@
1
1
  import {getVariableInt} from './ebml';
2
2
  import type {
3
+ BytesAndOffset,
3
4
  FloatWithSize,
5
+ OffsetAndChildren,
4
6
  PossibleEbml,
5
7
  PossibleEbmlOrUint8Array,
6
8
  UintWithSize,
9
+ } from './segments/all-segments';
10
+ import {
11
+ ebmlMap,
12
+ getIdForName,
13
+ incrementOffsetAndChildren,
7
14
  matroskaElements,
8
15
  } from './segments/all-segments';
9
- import {ebmlMap, getIdForName} from './segments/all-segments';
10
16
 
11
17
  export const webmPattern = new Uint8Array([0x1a, 0x45, 0xdf, 0xa3]);
12
18
 
13
- const matroskaToHex = (
19
+ export const matroskaToHex = (
14
20
  matrId: (typeof matroskaElements)[keyof typeof matroskaElements],
15
21
  ) => {
16
22
  const numbers: Uint8Array = new Uint8Array((matrId.length - 2) / 2);
@@ -45,10 +51,10 @@ function putUintDynamic(number: number, minimumLength: number | null) {
45
51
  return bytes;
46
52
  }
47
53
 
48
- const makeFromHeaderStructure = (
54
+ const makeFromStructure = (
49
55
  fields: PossibleEbmlOrUint8Array,
50
- ): Uint8Array => {
51
- if (fields instanceof Uint8Array) {
56
+ ): BytesAndOffset => {
57
+ if ('bytes' in fields) {
52
58
  return fields;
53
59
  }
54
60
 
@@ -57,26 +63,51 @@ const makeFromHeaderStructure = (
57
63
  const struct = ebmlMap[getIdForName(fields.type)];
58
64
 
59
65
  if (struct.type === 'uint8array') {
60
- return fields.value as Uint8Array;
66
+ return {
67
+ bytes: fields.value as Uint8Array,
68
+ offsets: {offset: 0, children: [], field: fields.type},
69
+ };
61
70
  }
62
71
 
63
72
  if (struct.type === 'children') {
73
+ const children: OffsetAndChildren[] = [];
74
+ let bytesWritten = 0;
64
75
  for (const item of fields.value as PossibleEbml[]) {
65
- arrays.push(makeMatroskaBytes(item));
76
+ const {bytes, offsets} = makeMatroskaBytes(item);
77
+ arrays.push(bytes);
78
+ children.push(incrementOffsetAndChildren(offsets, bytesWritten));
79
+ bytesWritten += bytes.byteLength;
66
80
  }
67
81
 
68
- return combineUint8Arrays(arrays);
82
+ return {
83
+ bytes: combineUint8Arrays(arrays),
84
+ offsets: {offset: 0, children, field: fields.type},
85
+ };
69
86
  }
70
87
 
71
88
  if (struct.type === 'string') {
72
- return new TextEncoder().encode(fields.value as string);
89
+ return {
90
+ bytes: new TextEncoder().encode(fields.value as string),
91
+ offsets: {
92
+ children: [],
93
+ offset: 0,
94
+ field: fields.type,
95
+ },
96
+ };
73
97
  }
74
98
 
75
99
  if (struct.type === 'uint') {
76
- return putUintDynamic(
77
- (fields.value as UintWithSize).value,
78
- (fields.value as UintWithSize).byteLength,
79
- );
100
+ return {
101
+ bytes: putUintDynamic(
102
+ (fields.value as UintWithSize).value,
103
+ (fields.value as UintWithSize).byteLength,
104
+ ),
105
+ offsets: {
106
+ children: [],
107
+ offset: 0,
108
+ field: fields.type,
109
+ },
110
+ };
80
111
  }
81
112
 
82
113
  if (struct.type === 'hex-string') {
@@ -87,7 +118,14 @@ const makeFromHeaderStructure = (
87
118
  arr[i / 2] = byte;
88
119
  }
89
120
 
90
- return arr;
121
+ return {
122
+ bytes: arr,
123
+ offsets: {
124
+ children: [],
125
+ offset: 0,
126
+ field: fields.type,
127
+ },
128
+ };
91
129
  }
92
130
 
93
131
  if (struct.type === 'float') {
@@ -95,29 +133,89 @@ const makeFromHeaderStructure = (
95
133
  if (value.size === '32') {
96
134
  const dataView = new DataView(new ArrayBuffer(4));
97
135
  dataView.setFloat32(0, value.value);
98
- return new Uint8Array(dataView.buffer);
136
+ return {
137
+ bytes: new Uint8Array(dataView.buffer),
138
+ offsets: {
139
+ children: [],
140
+ offset: 0,
141
+ field: fields.type,
142
+ },
143
+ };
99
144
  }
100
145
 
101
146
  const dataView2 = new DataView(new ArrayBuffer(8));
102
147
  dataView2.setFloat64(0, value.value);
103
- return new Uint8Array(dataView2.buffer);
148
+ return {
149
+ bytes: new Uint8Array(dataView2.buffer),
150
+ offsets: {
151
+ children: [],
152
+ offset: 0,
153
+ field: fields.type,
154
+ },
155
+ };
104
156
  }
105
157
 
106
158
  throw new Error('Unexpected type');
107
159
  };
108
160
 
109
- export const makeMatroskaBytes = (fields: PossibleEbmlOrUint8Array) => {
110
- if (fields instanceof Uint8Array) {
161
+ export const makeMatroskaBytes = (
162
+ fields: PossibleEbmlOrUint8Array,
163
+ ): BytesAndOffset => {
164
+ if ('bytes' in fields) {
111
165
  return fields;
112
166
  }
113
167
 
114
- const value = makeFromHeaderStructure(fields);
168
+ const value = makeFromStructure(fields);
169
+ const header = matroskaToHex(getIdForName(fields.type));
170
+ const size = getVariableInt(value.bytes.length, fields.minVintWidth);
171
+
172
+ const bytes = combineUint8Arrays([header, size, value.bytes]);
173
+
174
+ return {
175
+ bytes,
176
+ offsets: {
177
+ offset: value.offsets.offset,
178
+ field: value.offsets.field,
179
+ children: value.offsets.children.map((c) => {
180
+ return incrementOffsetAndChildren(
181
+ c,
182
+ header.byteLength + size.byteLength,
183
+ );
184
+ }),
185
+ },
186
+ };
187
+ };
188
+
189
+ export const padMatroskaBytes = (
190
+ fields: PossibleEbmlOrUint8Array,
191
+ totalLength: number,
192
+ ): BytesAndOffset[] => {
193
+ const regular = makeMatroskaBytes(fields);
194
+ const paddingLength =
195
+ totalLength -
196
+ regular.bytes.byteLength -
197
+ matroskaToHex(matroskaElements.Void).byteLength;
198
+
199
+ if (paddingLength < 0) {
200
+ throw new Error('ooops');
201
+ }
115
202
 
116
- return combineUint8Arrays([
117
- matroskaToHex(getIdForName(fields.type)),
118
- getVariableInt(value.length, fields.minVintWidth),
119
- value,
120
- ]);
203
+ const padding = makeMatroskaBytes({
204
+ type: 'Void',
205
+ value: new Uint8Array(paddingLength).fill(0),
206
+ minVintWidth: null,
207
+ });
208
+
209
+ return [
210
+ regular,
211
+ {
212
+ bytes: padding.bytes,
213
+ offsets: incrementOffsetAndChildren(
214
+ padding.offsets,
215
+ regular.bytes.length,
216
+ ),
217
+ },
218
+ ];
121
219
  };
122
220
 
123
221
  export const combineUint8Arrays = (arrays: Uint8Array[]) => {
@@ -143,3 +241,13 @@ export const combineUint8Arrays = (arrays: Uint8Array[]) => {
143
241
 
144
242
  return result;
145
243
  };
244
+
245
+ export function serializeUint16(value: number): Uint8Array {
246
+ const buffer = new ArrayBuffer(2);
247
+
248
+ const view = new DataView(buffer);
249
+
250
+ view.setUint16(0, value);
251
+
252
+ return new Uint8Array(buffer);
253
+ }
@@ -41,10 +41,13 @@ export const parseEbml = async (
41
41
 
42
42
  if (hasInMap.type === 'uint') {
43
43
  const beforeUintOffset = iterator.counter.getOffset();
44
- const value = iterator.getUint(size);
44
+ const value = size === 0 ? 0 : iterator.getUint(size);
45
+
46
+ const {name} = hasInMap;
45
47
 
46
48
  return {
47
- type: hasInMap.name,
49
+ // To work around TS limit
50
+ type: name as 'SeekPosition',
48
51
  value: {
49
52
  value,
50
53
  byteLength: iterator.counter.getOffset() - beforeUintOffset,
@@ -64,7 +67,12 @@ export const parseEbml = async (
64
67
  }
65
68
 
66
69
  if (hasInMap.type === 'float') {
67
- const value = size === 4 ? iterator.getFloat32() : iterator.getFloat64();
70
+ const value =
71
+ size === 0
72
+ ? 0.0
73
+ : size === 4
74
+ ? iterator.getFloat32()
75
+ : iterator.getFloat64();
68
76
 
69
77
  return {
70
78
  type: hasInMap.name,