@remotion/media-parser 4.0.233 → 4.0.235

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 (95) hide show
  1. package/dist/aac-codecprivate.d.ts +19 -0
  2. package/dist/aac-codecprivate.js +122 -0
  3. package/dist/add-avc-profile-to-track.d.ts +1 -1
  4. package/dist/boxes/iso-base-media/get-actual-number-of-channels.d.ts +13 -0
  5. package/dist/boxes/iso-base-media/get-actual-number-of-channels.js +22 -0
  6. package/dist/boxes/iso-base-media/make-track.js +16 -7
  7. package/dist/boxes/iso-base-media/meta/hdlr.d.ts +12 -0
  8. package/dist/boxes/iso-base-media/meta/hdlr.js +33 -0
  9. package/dist/boxes/iso-base-media/meta/ilst.d.ts +28 -0
  10. package/dist/boxes/iso-base-media/meta/ilst.js +86 -0
  11. package/dist/boxes/iso-base-media/meta/keys.d.ts +10 -0
  12. package/dist/boxes/iso-base-media/meta/keys.js +17 -0
  13. package/dist/boxes/iso-base-media/meta/list.d.ts +12 -0
  14. package/dist/boxes/iso-base-media/meta/list.js +33 -0
  15. package/dist/boxes/iso-base-media/moov/moov.d.ts +3 -1
  16. package/dist/boxes/iso-base-media/moov/moov.js +2 -1
  17. package/dist/boxes/iso-base-media/process-box.d.ts +5 -2
  18. package/dist/boxes/iso-base-media/process-box.js +66 -8
  19. package/dist/boxes/iso-base-media/stsd/keys.d.ts +15 -1
  20. package/dist/boxes/iso-base-media/stsd/keys.js +25 -12
  21. package/dist/boxes/iso-base-media/stsd/mebx.d.ts +3 -1
  22. package/dist/boxes/iso-base-media/stsd/mebx.js +2 -1
  23. package/dist/boxes/iso-base-media/stsd/samples.d.ts +5 -2
  24. package/dist/boxes/iso-base-media/stsd/samples.js +7 -2
  25. package/dist/boxes/iso-base-media/stsd/stsd.d.ts +3 -1
  26. package/dist/boxes/iso-base-media/stsd/stsd.js +2 -1
  27. package/dist/boxes/iso-base-media/trak/trak.d.ts +3 -1
  28. package/dist/boxes/iso-base-media/trak/trak.js +2 -1
  29. package/dist/boxes/riff/expect-riff-box.d.ts +1 -0
  30. package/dist/boxes/riff/expect-riff-box.js +1 -1
  31. package/dist/boxes/riff/get-tracks-from-avi.d.ts +2 -1
  32. package/dist/boxes/riff/get-tracks-from-avi.js +14 -8
  33. package/dist/boxes/riff/parse-box.d.ts +3 -1
  34. package/dist/boxes/riff/parse-box.js +38 -5
  35. package/dist/boxes/riff/parse-isft.d.ts +6 -0
  36. package/dist/boxes/riff/parse-isft.js +17 -0
  37. package/dist/boxes/riff/parse-movi.js +31 -20
  38. package/dist/boxes/riff/parse-riff-box.js +4 -0
  39. package/dist/boxes/riff/riff-box.d.ts +5 -1
  40. package/dist/boxes/webm/ebml.d.ts +1 -1
  41. package/dist/boxes/webm/parse-ebml.js +2 -1
  42. package/dist/boxes/webm/parse-webm-header.d.ts +6 -1
  43. package/dist/boxes/webm/parse-webm-header.js +3 -1
  44. package/dist/boxes/webm/segments/all-segments.d.ts +42 -2
  45. package/dist/boxes/webm/segments/all-segments.js +28 -3
  46. package/dist/boxes/webm/segments/parse-children.d.ts +8 -3
  47. package/dist/boxes/webm/segments/parse-children.js +39 -4
  48. package/dist/boxes/webm/segments.d.ts +5 -2
  49. package/dist/boxes/webm/segments.js +23 -3
  50. package/dist/boxes/webm/traversal.d.ts +1 -0
  51. package/dist/boxes/webm/traversal.js +18 -2
  52. package/dist/buffer-iterator.d.ts +3 -0
  53. package/dist/buffer-iterator.js +23 -0
  54. package/dist/create/iso-base-media/codec-specific/mp4a.js +1 -17
  55. package/dist/create/iso-base-media/mp4-header.js +2 -1
  56. package/dist/emit-available-info.d.ts +1 -1
  57. package/dist/emit-available-info.js +17 -6
  58. package/dist/esm/index.mjs +992 -162
  59. package/dist/get-audio-codec.d.ts +1 -1
  60. package/dist/get-dimensions.d.ts +1 -1
  61. package/dist/get-duration.d.ts +1 -1
  62. package/dist/get-is-hdr.d.ts +1 -1
  63. package/dist/get-metadata.d.ts +7 -0
  64. package/dist/get-metadata.js +63 -0
  65. package/dist/get-tracks.d.ts +1 -1
  66. package/dist/get-tracks.js +1 -1
  67. package/dist/get-video-codec.d.ts +1 -1
  68. package/dist/has-all-info.d.ts +8 -3
  69. package/dist/has-all-info.js +21 -12
  70. package/dist/index.d.ts +6 -0
  71. package/dist/index.js +2 -0
  72. package/dist/metadata/get-metadata.d.ts +7 -0
  73. package/dist/metadata/get-metadata.js +16 -0
  74. package/dist/metadata/metadata-from-iso.d.ts +4 -0
  75. package/dist/metadata/metadata-from-iso.js +148 -0
  76. package/dist/metadata/metadata-from-matroska.d.ts +3 -0
  77. package/dist/metadata/metadata-from-matroska.js +53 -0
  78. package/dist/metadata/metadata-from-riff.d.ts +3 -0
  79. package/dist/metadata/metadata-from-riff.js +24 -0
  80. package/dist/options.d.ts +9 -3
  81. package/dist/parse-media.js +32 -29
  82. package/dist/parse-result.d.ts +3 -1
  83. package/dist/parse-video.d.ts +3 -1
  84. package/dist/parse-video.js +5 -3
  85. package/dist/parser-context.d.ts +1 -2
  86. package/dist/register-track.d.ts +1 -1
  87. package/dist/state/can-skip-tracks.d.ts +9 -0
  88. package/dist/state/can-skip-tracks.js +33 -0
  89. package/dist/state/has-tracks-section.d.ts +6 -0
  90. package/dist/state/has-tracks-section.js +21 -0
  91. package/dist/state/parser-state.d.ts +51 -0
  92. package/dist/state/parser-state.js +170 -0
  93. package/dist/version.d.ts +1 -1
  94. package/dist/version.js +1 -1
  95. package/package.json +3 -3
@@ -105,6 +105,115 @@ var fetchReader = {
105
105
  }
106
106
  };
107
107
 
108
+ // src/aac-codecprivate.ts
109
+ var getConfigForSampleRate = (sampleRate) => {
110
+ if (sampleRate === 96000) {
111
+ return 0;
112
+ }
113
+ if (sampleRate === 88200) {
114
+ return 1;
115
+ }
116
+ if (sampleRate === 64000) {
117
+ return 2;
118
+ }
119
+ if (sampleRate === 48000) {
120
+ return 3;
121
+ }
122
+ if (sampleRate === 44100) {
123
+ return 4;
124
+ }
125
+ if (sampleRate === 32000) {
126
+ return 5;
127
+ }
128
+ if (sampleRate === 24000) {
129
+ return 6;
130
+ }
131
+ if (sampleRate === 22050) {
132
+ return 7;
133
+ }
134
+ if (sampleRate === 16000) {
135
+ return 8;
136
+ }
137
+ if (sampleRate === 12000) {
138
+ return 9;
139
+ }
140
+ if (sampleRate === 11025) {
141
+ return 10;
142
+ }
143
+ if (sampleRate === 8000) {
144
+ return 11;
145
+ }
146
+ if (sampleRate === 7350) {
147
+ return 12;
148
+ }
149
+ throw new Error(`Unexpected sample rate ${sampleRate}`);
150
+ };
151
+ var createAacCodecPrivate = ({
152
+ audioObjectType,
153
+ sampleRate,
154
+ channelConfiguration
155
+ }) => {
156
+ const bits = `${audioObjectType.toString(2).padStart(5, "0")}${getConfigForSampleRate(sampleRate).toString(2).padStart(4, "0")}${channelConfiguration.toString(2).padStart(4, "0")}000`;
157
+ if (bits.length !== 16) {
158
+ throw new Error("Invalid AAC codec private " + bits.length);
159
+ }
160
+ if (channelConfiguration === 0 || channelConfiguration > 7) {
161
+ throw new Error("Invalid channel configuration " + channelConfiguration);
162
+ }
163
+ const firstByte = parseInt(bits.slice(0, 8), 2);
164
+ const secondByte = parseInt(bits.slice(8, 16), 2);
165
+ return new Uint8Array([firstByte, secondByte]);
166
+ };
167
+ var parseAacCodecPrivate = (bytes) => {
168
+ if (bytes.length < 2) {
169
+ throw new Error("Invalid AAC codec private length");
170
+ }
171
+ const bits = `${bytes[0].toString(2).padStart(8, "0")}${bytes[1].toString(2).padStart(8, "0")}`;
172
+ if (bits.length !== 16) {
173
+ throw new Error("Invalid AAC codec private bits length");
174
+ }
175
+ const audioObjectType = parseInt(bits.slice(0, 5), 2);
176
+ const samplingFrequencyIndex = parseInt(bits.slice(5, 9), 2);
177
+ const channelConfiguration = parseInt(bits.slice(9, 13), 2);
178
+ const sampleRate = (() => {
179
+ switch (samplingFrequencyIndex) {
180
+ case 0:
181
+ return 96000;
182
+ case 1:
183
+ return 88200;
184
+ case 2:
185
+ return 64000;
186
+ case 3:
187
+ return 48000;
188
+ case 4:
189
+ return 44100;
190
+ case 5:
191
+ return 32000;
192
+ case 6:
193
+ return 24000;
194
+ case 7:
195
+ return 22050;
196
+ case 8:
197
+ return 16000;
198
+ case 9:
199
+ return 12000;
200
+ case 10:
201
+ return 11025;
202
+ case 11:
203
+ return 8000;
204
+ case 12:
205
+ return 7350;
206
+ default:
207
+ throw new Error(`Unexpected sampling frequency index ${samplingFrequencyIndex}`);
208
+ }
209
+ })();
210
+ return {
211
+ audioObjectType,
212
+ sampleRate,
213
+ channelConfiguration
214
+ };
215
+ };
216
+
108
217
  // src/create/event-emitter.ts
109
218
  class IoEventEmitter {
110
219
  listeners = {
@@ -574,6 +683,10 @@ var titleType = {
574
683
  name: "Title",
575
684
  type: "string"
576
685
  };
686
+ var tagTrackUidType = {
687
+ name: "TagTrackUID",
688
+ type: "hex-string"
689
+ };
577
690
  var samplingFrequency = {
578
691
  name: "SamplingFrequency",
579
692
  type: "float"
@@ -608,7 +721,7 @@ var flagLacing = {
608
721
  };
609
722
  var tagSegment = {
610
723
  name: "Tag",
611
- type: "uint8array"
724
+ type: "children"
612
725
  };
613
726
  var tags = {
614
727
  name: "Tags",
@@ -714,9 +827,29 @@ var blockGroup = {
714
827
  name: "BlockGroup",
715
828
  type: "children"
716
829
  };
830
+ var targetsType = {
831
+ name: "Targets",
832
+ type: "children"
833
+ };
834
+ var simpleTagType = {
835
+ name: "SimpleTag",
836
+ type: "children"
837
+ };
838
+ var tagNameType = {
839
+ name: "TagName",
840
+ type: "string"
841
+ };
842
+ var tagStringType = {
843
+ name: "TagString",
844
+ type: "string"
845
+ };
717
846
  var ebmlMap = {
718
847
  [matroskaElements.Header]: matroskaHeader,
719
848
  [matroskaElements.DocType]: docType,
849
+ [matroskaElements.Targets]: targetsType,
850
+ [matroskaElements.SimpleTag]: simpleTagType,
851
+ [matroskaElements.TagName]: tagNameType,
852
+ [matroskaElements.TagString]: tagStringType,
720
853
  [matroskaElements.DocTypeVersion]: docTypeVersion,
721
854
  [matroskaElements.DocTypeReadVersion]: docTypeReadVersion,
722
855
  [matroskaElements.EBMLVersion]: ebmlVersion,
@@ -786,6 +919,7 @@ var ebmlMap = {
786
919
  name: "SliceDuration",
787
920
  type: "uint8array"
788
921
  },
922
+ [matroskaElements.TagTrackUID]: tagTrackUidType,
789
923
  [matroskaElements.SeekHead]: seekHead,
790
924
  [matroskaElements.Seek]: seek,
791
925
  [matroskaElements.SeekID]: seekId,
@@ -1208,6 +1342,9 @@ var createIsoBaseMediaFtyp = ({
1208
1342
  return createFtyp({ compatibleBrands, majorBrand, minorBrand });
1209
1343
  };
1210
1344
 
1345
+ // src/version.ts
1346
+ var VERSION = "4.0.235";
1347
+
1211
1348
  // src/create/iso-base-media/create-ilst.ts
1212
1349
  var createIlst = (items) => {
1213
1350
  return addSize(combineUint8Arrays([
@@ -1975,7 +2112,7 @@ var createPaddedMoovAtom = ({
1975
2112
  hdlr: createHdlr("mdir"),
1976
2113
  ilst: createIlst([
1977
2114
  createToo("WebCodecs"),
1978
- createCmt("Made with @remotion/webcodecs")
2115
+ createCmt(`Made with @remotion/webcodecs ${VERSION}`)
1979
2116
  ])
1980
2117
  }))
1981
2118
  }), HEADER_LENGTH);
@@ -2583,11 +2720,25 @@ var getDisplayWidthSegment = (track) => {
2583
2720
  };
2584
2721
  var getTracksSegment = (segment) => {
2585
2722
  const tracksSegment = segment.value.find((b) => b.type === "Tracks");
2586
- if (!tracksSegment || tracksSegment.type !== "Tracks") {
2723
+ if (!tracksSegment) {
2587
2724
  return null;
2588
2725
  }
2589
2726
  return tracksSegment;
2590
2727
  };
2728
+ var getTrackWithUid = (segment, trackUid) => {
2729
+ const tracksSegment = getTracksSegment(segment);
2730
+ if (!tracksSegment) {
2731
+ return null;
2732
+ }
2733
+ const trackEntries = tracksSegment.value.filter((t) => t.type === "TrackEntry");
2734
+ const trackEntry2 = trackEntries.find((entry) => {
2735
+ return entry?.value.find((t) => t.type === "TrackUID" && t.value === trackUid);
2736
+ });
2737
+ if (!trackEntry2) {
2738
+ return null;
2739
+ }
2740
+ return trackEntry2.value.find((t) => t.type === "TrackNumber")?.value.value ?? null;
2741
+ };
2591
2742
  var getVideoSegment = (track) => {
2592
2743
  const videoSegment2 = track.value.find((b) => b.type === "Video");
2593
2744
  if (!videoSegment2 || videoSegment2.type !== "Video") {
@@ -3483,6 +3634,194 @@ var getMdatBox = (anySegment) => {
3483
3634
  return mdat;
3484
3635
  };
3485
3636
 
3637
+ // src/metadata/metadata-from-iso.ts
3638
+ var mapToKey = (index) => {
3639
+ if (index === 2839630420) {
3640
+ return "artist";
3641
+ }
3642
+ if (index === 2841734242) {
3643
+ return "album";
3644
+ }
3645
+ if (index === 2841865588) {
3646
+ return "comment";
3647
+ }
3648
+ if (index === 2841928057) {
3649
+ return "releaseDate";
3650
+ }
3651
+ if (index === 2842125678) {
3652
+ return "genre";
3653
+ }
3654
+ if (index === 2842583405) {
3655
+ return "title";
3656
+ }
3657
+ if (index === 2842980207) {
3658
+ return "encoder";
3659
+ }
3660
+ if (index === 2843177588) {
3661
+ return "writer";
3662
+ }
3663
+ if (index === 2841866361) {
3664
+ return "copyright";
3665
+ }
3666
+ if (index === 2841930098) {
3667
+ return "director";
3668
+ }
3669
+ if (index === 2842718820) {
3670
+ return "producer";
3671
+ }
3672
+ if (index === 2841929075) {
3673
+ return "description";
3674
+ }
3675
+ return null;
3676
+ };
3677
+ var parseIlstBoxWithoutKeys = (ilstBox) => {
3678
+ return ilstBox.entries.map((entry) => {
3679
+ const key = mapToKey(entry.index);
3680
+ if (!key) {
3681
+ return null;
3682
+ }
3683
+ if (entry.value.type === "unknown") {
3684
+ return null;
3685
+ }
3686
+ return {
3687
+ trackId: null,
3688
+ key,
3689
+ value: entry.value.value
3690
+ };
3691
+ }).filter(truthy);
3692
+ };
3693
+ var parseIsoMetaBox = (meta, trackId) => {
3694
+ const ilstBox = meta.children.find((b) => b.type === "ilst-box");
3695
+ const keysBox = meta.children.find((b) => b.type === "keys-box");
3696
+ if (!ilstBox || !keysBox) {
3697
+ if (ilstBox) {
3698
+ return parseIlstBoxWithoutKeys(ilstBox);
3699
+ }
3700
+ return [];
3701
+ }
3702
+ const entries = [];
3703
+ for (let i = 0;i < ilstBox.entries.length; i++) {
3704
+ const ilstEntry = ilstBox.entries[i];
3705
+ const keysEntry = keysBox.entries[i];
3706
+ if (ilstEntry.value.type !== "unknown") {
3707
+ const value = typeof ilstEntry.value.value === "string" && ilstEntry.value.value.endsWith("\x00") ? ilstEntry.value.value.slice(0, -1) : ilstEntry.value.value;
3708
+ entries.push({
3709
+ key: keysEntry.value,
3710
+ value,
3711
+ trackId
3712
+ });
3713
+ }
3714
+ }
3715
+ return entries;
3716
+ };
3717
+ var getMetadataFromIsoBase = (isoBase) => {
3718
+ const moov = getMoovBox(isoBase.boxes);
3719
+ if (!moov) {
3720
+ return [];
3721
+ }
3722
+ const traks = getTraks(moov);
3723
+ const meta = moov.children.find((b) => b.type === "regular-box" && b.boxType === "meta");
3724
+ const udta = moov.children.find((b) => b.type === "regular-box" && b.boxType === "udta");
3725
+ const metaInUdta = udta?.children.find((b) => {
3726
+ return b.type === "regular-box" && b.boxType === "meta";
3727
+ });
3728
+ const metaInTracks = traks.map((t) => {
3729
+ const metaBox = t.children.find((child) => child.type === "regular-box" && child.boxType === "meta");
3730
+ if (metaBox) {
3731
+ const tkhd = getTkhdBox(t);
3732
+ if (!tkhd) {
3733
+ throw new Error("No tkhd box found");
3734
+ }
3735
+ return parseIsoMetaBox(metaBox, tkhd.trackId);
3736
+ }
3737
+ return null;
3738
+ }).filter(truthy);
3739
+ return [
3740
+ ...meta ? parseIsoMetaBox(meta, null) : [],
3741
+ ...metaInUdta ? parseIsoMetaBox(metaInUdta, null) : [],
3742
+ ...metaInTracks.flat(1)
3743
+ ];
3744
+ };
3745
+
3746
+ // src/metadata/metadata-from-matroska.ts
3747
+ var removeEndZeroes = (value) => {
3748
+ return value.endsWith("\x00") ? removeEndZeroes(value.slice(0, -1)) : value;
3749
+ };
3750
+ var parseSimpleTagIntoEbml = (children, trackId) => {
3751
+ const tagName = children.find((c) => c.type === "TagName");
3752
+ const tagString = children.find((c) => c.type === "TagString");
3753
+ if (!tagName || !tagString) {
3754
+ return null;
3755
+ }
3756
+ return {
3757
+ trackId,
3758
+ key: tagName.value.toLowerCase(),
3759
+ value: removeEndZeroes(tagString.value)
3760
+ };
3761
+ };
3762
+ var getMetadataFromMatroska = (structure) => {
3763
+ const entries = [];
3764
+ for (const segment of structure.boxes) {
3765
+ if (segment.type !== "Segment") {
3766
+ continue;
3767
+ }
3768
+ const tags2 = segment.value.filter((s) => s.type === "Tags");
3769
+ for (const tag of tags2) {
3770
+ for (const child of tag.value) {
3771
+ if (child.type !== "Tag") {
3772
+ continue;
3773
+ }
3774
+ let trackId = null;
3775
+ const target = child.value.find((c) => c.type === "Targets");
3776
+ if (target) {
3777
+ const tagTrackId = target.value.find((c) => c.type === "TagTrackUID")?.value;
3778
+ if (tagTrackId) {
3779
+ trackId = getTrackWithUid(segment, tagTrackId);
3780
+ }
3781
+ }
3782
+ const simpleTags = child.value.filter((s) => s.type === "SimpleTag");
3783
+ for (const simpleTag of simpleTags) {
3784
+ const parsed = parseSimpleTagIntoEbml(simpleTag.value, trackId);
3785
+ if (parsed) {
3786
+ entries.push(parsed);
3787
+ }
3788
+ }
3789
+ }
3790
+ }
3791
+ }
3792
+ return entries;
3793
+ };
3794
+
3795
+ // src/metadata/metadata-from-riff.ts
3796
+ var getMetadataFromRiff = (structure) => {
3797
+ const boxes = structure.boxes.find((b) => b.type === "list-box" && b.listType === "INFO");
3798
+ if (!boxes) {
3799
+ return [];
3800
+ }
3801
+ const { children } = boxes;
3802
+ return children.map((child) => {
3803
+ if (child.type !== "isft-box") {
3804
+ return null;
3805
+ }
3806
+ return {
3807
+ trackId: null,
3808
+ key: "encoder",
3809
+ value: child.software
3810
+ };
3811
+ }).filter(truthy);
3812
+ };
3813
+
3814
+ // src/metadata/get-metadata.ts
3815
+ var getMetadata = (structure) => {
3816
+ if (structure.type === "matroska") {
3817
+ return getMetadataFromMatroska(structure);
3818
+ }
3819
+ if (structure.type === "riff") {
3820
+ return getMetadataFromRiff(structure);
3821
+ }
3822
+ return getMetadataFromIsoBase(structure);
3823
+ };
3824
+
3486
3825
  // src/boxes/riff/traversal.ts
3487
3826
  var isRiffAvi = (structure) => {
3488
3827
  return structure.boxes.some((box) => box.type === "riff-header" && box.fileType === "AVI");
@@ -4012,6 +4351,15 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4012
4351
  const discard = (length) => {
4013
4352
  counter.increment(length);
4014
4353
  };
4354
+ const readUntilNullTerminator = () => {
4355
+ const bytes = [];
4356
+ let byte;
4357
+ while ((byte = getUint8()) !== 0) {
4358
+ bytes.push(byte);
4359
+ }
4360
+ counter.decrement(1);
4361
+ return new TextDecoder().decode(new Uint8Array(bytes));
4362
+ };
4015
4363
  const getUint8 = () => {
4016
4364
  const val = view.getUint8(counter.getDiscardedOffset());
4017
4365
  counter.increment(1);
@@ -4067,6 +4415,11 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4067
4415
  counter.increment(8);
4068
4416
  return val;
4069
4417
  };
4418
+ const getInt64 = (littleEndian = false) => {
4419
+ const val = view.getBigInt64(counter.getDiscardedOffset(), littleEndian);
4420
+ counter.increment(8);
4421
+ return val;
4422
+ };
4070
4423
  const startBox = (size) => {
4071
4424
  const startOffset = counter.getOffset();
4072
4425
  return {
@@ -4328,6 +4681,13 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4328
4681
  counter.increment(3);
4329
4682
  return val1 << 16 | val2 << 8 | val3;
4330
4683
  },
4684
+ getInt24: () => {
4685
+ const val1 = view.getInt8(counter.getDiscardedOffset());
4686
+ const val2 = view.getUint8(counter.getDiscardedOffset() + 1);
4687
+ const val3 = view.getUint8(counter.getDiscardedOffset() + 2);
4688
+ counter.increment(3);
4689
+ return val1 << 16 | val2 << 8 | val3;
4690
+ },
4331
4691
  getInt16: () => {
4332
4692
  const val = view.getInt16(counter.getDiscardedOffset());
4333
4693
  counter.increment(2);
@@ -4335,6 +4695,7 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4335
4695
  },
4336
4696
  getUint32,
4337
4697
  getUint64,
4698
+ getInt64,
4338
4699
  getFixedPointUnsigned1616Number: () => {
4339
4700
  const val = getUint32();
4340
4701
  return val / 2 ** 16;
@@ -4365,6 +4726,7 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4365
4726
  counter.increment(8);
4366
4727
  return val;
4367
4728
  },
4729
+ readUntilNullTerminator,
4368
4730
  getFloat32: () => {
4369
4731
  const val = view.getFloat32(counter.getDiscardedOffset());
4370
4732
  counter.increment(4);
@@ -4615,6 +4977,27 @@ var getVideoCodecString = (trakBox) => {
4615
4977
  return videoSample.format;
4616
4978
  };
4617
4979
 
4980
+ // src/boxes/iso-base-media/get-actual-number-of-channels.ts
4981
+ var getActualDecoderParameters = ({
4982
+ audioCodec,
4983
+ codecPrivate: codecPrivate2,
4984
+ numberOfChannels,
4985
+ sampleRate
4986
+ }) => {
4987
+ if (audioCodec !== "aac") {
4988
+ return { numberOfChannels, sampleRate, codecPrivate: codecPrivate2 };
4989
+ }
4990
+ if (codecPrivate2 === null) {
4991
+ return { numberOfChannels, sampleRate, codecPrivate: codecPrivate2 };
4992
+ }
4993
+ const parsed = parseAacCodecPrivate(codecPrivate2);
4994
+ return {
4995
+ numberOfChannels: parsed.channelConfiguration,
4996
+ sampleRate: parsed.sampleRate,
4997
+ codecPrivate: createAacCodecPrivate(parsed)
4998
+ };
4999
+ };
5000
+
4618
5001
  // src/boxes/iso-base-media/make-track.ts
4619
5002
  var makeBaseMediaTrack = (trakBox) => {
4620
5003
  const tkhdBox = getTkhdBox(trakBox);
@@ -4636,17 +5019,25 @@ var makeBaseMediaTrack = (trakBox) => {
4636
5019
  throw new Error("Could not find sample rate");
4637
5020
  }
4638
5021
  const { codecString, description } = getAudioCodecStringFromTrak(trakBox);
5022
+ const codecPrivate2 = getCodecPrivateFromTrak(trakBox) ?? description ?? null;
5023
+ const codecWithoutConfig = getAudioCodecFromTrack(trakBox);
5024
+ const actual = getActualDecoderParameters({
5025
+ audioCodec: codecWithoutConfig,
5026
+ codecPrivate: codecPrivate2,
5027
+ numberOfChannels,
5028
+ sampleRate
5029
+ });
4639
5030
  return {
4640
5031
  type: "audio",
4641
5032
  trackId: tkhdBox.trackId,
4642
5033
  timescale: timescaleAndDuration.timescale,
4643
5034
  codec: codecString,
4644
- numberOfChannels,
4645
- sampleRate,
4646
- description,
5035
+ numberOfChannels: actual.numberOfChannels,
5036
+ sampleRate: actual.sampleRate,
5037
+ description: actual.codecPrivate ?? undefined,
4647
5038
  trakBox,
4648
- codecPrivate: getCodecPrivateFromTrak(trakBox) ?? description ?? null,
4649
- codecWithoutConfig: getAudioCodecFromTrack(trakBox)
5039
+ codecPrivate: actual.codecPrivate,
5040
+ codecWithoutConfig
4650
5041
  };
4651
5042
  }
4652
5043
  if (!trakBoxContainsVideo(trakBox)) {
@@ -4734,6 +5125,7 @@ var addAvcProfileToTrack = (track, avc1Profile) => {
4734
5125
  var MEDIA_PARSER_RIFF_TIMESCALE = 1e6;
4735
5126
 
4736
5127
  // src/boxes/riff/get-tracks-from-avi.ts
5128
+ var TO_BE_OVERRIDDEN_LATER = "to-be-overriden-later";
4737
5129
  var getNumberOfTracks = (structure) => {
4738
5130
  const avihBox = getAvihBox(structure);
4739
5131
  if (avihBox) {
@@ -4771,7 +5163,7 @@ var makeAviVideoTrack = ({
4771
5163
  }
4772
5164
  return {
4773
5165
  codecPrivate: null,
4774
- codec: "to-be-overriden-later",
5166
+ codec: TO_BE_OVERRIDDEN_LATER,
4775
5167
  codecWithoutConfig: "h264",
4776
5168
  codedHeight: strf.height,
4777
5169
  codedWidth: strf.width,
@@ -4828,9 +5220,13 @@ var hasAllTracksFromAvi = (structure, state) => {
4828
5220
  if (!isRiffAvi(structure)) {
4829
5221
  throw new Error("Not an AVI file");
4830
5222
  }
4831
- const numberOfTracks = getNumberOfTracks(structure);
4832
- const tracks2 = getTracksFromAvi(structure, state);
4833
- return tracks2.videoTracks.length + tracks2.audioTracks.length + tracks2.otherTracks.length === numberOfTracks;
5223
+ try {
5224
+ const numberOfTracks = getNumberOfTracks(structure);
5225
+ const tracks2 = getTracksFromAvi(structure, state);
5226
+ return tracks2.videoTracks.length + tracks2.audioTracks.length + tracks2.otherTracks.length === numberOfTracks;
5227
+ } catch {
5228
+ return false;
5229
+ }
4834
5230
  };
4835
5231
 
4836
5232
  // src/make-hvc1-codec-strings.ts
@@ -5217,7 +5613,7 @@ var hasTracks = (structure, state) => {
5217
5613
  if (structure.type === "matroska") {
5218
5614
  const mainSegment = getMainSegment(structure.boxes);
5219
5615
  if (!mainSegment) {
5220
- throw new Error("No main segment found");
5616
+ return false;
5221
5617
  }
5222
5618
  return getTracksSegment(mainSegment) !== null;
5223
5619
  }
@@ -5752,9 +6148,8 @@ var emitAvailableInfo = ({
5752
6148
  continue;
5753
6149
  }
5754
6150
  if (key === "internalStats") {
5755
- if (hasInfo.internalStats && returnValue.internalStats === undefined) {
6151
+ if (hasInfo.internalStats) {
5756
6152
  const internalStats = state.getInternalStats();
5757
- moreFields.onInternalStats?.(internalStats);
5758
6153
  returnValue.internalStats = internalStats;
5759
6154
  }
5760
6155
  continue;
@@ -5789,41 +6184,49 @@ var emitAvailableInfo = ({
5789
6184
  }
5790
6185
  continue;
5791
6186
  }
6187
+ if (key === "metadata") {
6188
+ if (returnValue.metadata === undefined && hasInfo.metadata && parseResult) {
6189
+ const metadata = getMetadata(parseResult.segments);
6190
+ moreFields.onMetadata?.(metadata);
6191
+ returnValue.metadata = metadata;
6192
+ }
6193
+ continue;
6194
+ }
5792
6195
  throw new Error(`Unhandled key: ${key}`);
5793
6196
  }
5794
6197
  };
5795
6198
 
5796
6199
  // src/has-all-info.ts
5797
- var getAvailableInfo = (options, parseResult, state) => {
6200
+ var getAvailableInfo = (options, structure, state) => {
5798
6201
  const keys = Object.entries(options).filter(([, value]) => value);
5799
6202
  const infos = keys.map(([_key]) => {
5800
6203
  const key = _key;
5801
6204
  if (key === "structure") {
5802
- return Boolean(parseResult && parseResult.status === "done");
6205
+ return false;
5803
6206
  }
5804
6207
  if (key === "durationInSeconds") {
5805
- return Boolean(parseResult && hasDuration(parseResult.segments, state));
6208
+ return Boolean(structure && hasDuration(structure, state));
5806
6209
  }
5807
6210
  if (key === "dimensions" || key === "rotation" || key === "unrotatedDimensions") {
5808
- return Boolean(parseResult && hasDimensions(parseResult.segments, state));
6211
+ return Boolean(structure && hasDimensions(structure, state));
5809
6212
  }
5810
6213
  if (key === "fps") {
5811
- return Boolean(parseResult && hasFps(parseResult.segments));
6214
+ return Boolean(structure && hasFps(structure));
5812
6215
  }
5813
6216
  if (key === "isHdr") {
5814
- return Boolean(parseResult && hasHdr(parseResult.segments, state));
6217
+ return Boolean(structure && hasHdr(structure, state));
5815
6218
  }
5816
6219
  if (key === "videoCodec") {
5817
- return Boolean(parseResult && hasVideoCodec(parseResult.segments, state));
6220
+ return Boolean(structure && hasVideoCodec(structure, state));
5818
6221
  }
5819
6222
  if (key === "audioCodec") {
5820
- return Boolean(parseResult && hasAudioCodec(parseResult.segments, state));
6223
+ return Boolean(structure && hasAudioCodec(structure, state));
5821
6224
  }
5822
6225
  if (key === "tracks") {
5823
- return Boolean(parseResult && hasTracks(parseResult.segments, state));
6226
+ return Boolean(structure && hasTracks(structure, state));
5824
6227
  }
5825
6228
  if (key === "internalStats") {
5826
- return false;
6229
+ return true;
5827
6230
  }
5828
6231
  if (key === "size") {
5829
6232
  return true;
@@ -5832,7 +6235,10 @@ var getAvailableInfo = (options, parseResult, state) => {
5832
6235
  return true;
5833
6236
  }
5834
6237
  if (key === "container") {
5835
- return Boolean(parseResult && hasContainer(parseResult.segments));
6238
+ return Boolean(structure && hasContainer(structure));
6239
+ }
6240
+ if (key === "metadata") {
6241
+ return false;
5836
6242
  }
5837
6243
  throw new Error(`Unknown key: ${key}`);
5838
6244
  });
@@ -5843,6 +6249,14 @@ var getAvailableInfo = (options, parseResult, state) => {
5843
6249
  }
5844
6250
  return Object.fromEntries(entries);
5845
6251
  };
6252
+ var hasAllInfo = ({
6253
+ fields,
6254
+ state,
6255
+ structure
6256
+ }) => {
6257
+ const availableInfo = getAvailableInfo(fields ?? {}, structure, state);
6258
+ return Object.values(availableInfo).every(Boolean) && (state.maySkipVideoData() || state.canSkipTracksState.canSkipTracks());
6259
+ };
5846
6260
 
5847
6261
  // src/register-track.ts
5848
6262
  var registerTrack = async ({
@@ -6174,6 +6588,119 @@ var parseMdhd = ({
6174
6588
  };
6175
6589
  };
6176
6590
 
6591
+ // src/boxes/iso-base-media/meta/hdlr.ts
6592
+ var parseHdlr = ({
6593
+ iterator,
6594
+ size,
6595
+ offset
6596
+ }) => {
6597
+ const box = iterator.startBox(size - 8);
6598
+ const version = iterator.getUint8();
6599
+ if (version !== 0) {
6600
+ throw new Error(`Unsupported hdlr version: ${version}`);
6601
+ }
6602
+ iterator.discard(3);
6603
+ iterator.discard(4);
6604
+ const hdlrType = iterator.getByteString(4);
6605
+ iterator.discard(4);
6606
+ iterator.discard(4);
6607
+ iterator.discard(4);
6608
+ const componentName = iterator.readUntilNullTerminator();
6609
+ box.discardRest();
6610
+ return Promise.resolve({
6611
+ type: "hdlr-box",
6612
+ boxSize: size,
6613
+ offset,
6614
+ hdlrType,
6615
+ componentName
6616
+ });
6617
+ };
6618
+
6619
+ // src/boxes/iso-base-media/meta/ilst.ts
6620
+ var parseFromWellKnownType = (wellKnownType, iterator, size) => {
6621
+ if (wellKnownType === 1) {
6622
+ const value = iterator.getByteString(size);
6623
+ return { type: "text", value };
6624
+ }
6625
+ if (wellKnownType === 21) {
6626
+ if (size === 1) {
6627
+ return { type: "number", value: iterator.getInt8() };
6628
+ }
6629
+ if (size === 2) {
6630
+ return { type: "number", value: iterator.getInt16() };
6631
+ }
6632
+ if (size === 3) {
6633
+ return { type: "number", value: iterator.getInt24() };
6634
+ }
6635
+ if (size === 4) {
6636
+ return { type: "number", value: iterator.getInt32() };
6637
+ }
6638
+ if (size === 8) {
6639
+ return { type: "number", value: Number(iterator.getInt64()) };
6640
+ }
6641
+ throw new Error(`Weird size for number ${size}`);
6642
+ }
6643
+ if (wellKnownType === 22) {
6644
+ if (size === 1) {
6645
+ return { type: "number", value: iterator.getUint8() };
6646
+ }
6647
+ if (size === 2) {
6648
+ return { type: "number", value: iterator.getUint16() };
6649
+ }
6650
+ if (size === 3) {
6651
+ return { type: "number", value: iterator.getUint24() };
6652
+ }
6653
+ if (size === 4) {
6654
+ return { type: "number", value: iterator.getUint32() };
6655
+ }
6656
+ throw new Error(`Weird size for number ${size}`);
6657
+ }
6658
+ if (wellKnownType === 23) {
6659
+ if (size === 4) {
6660
+ return { type: "number", value: iterator.getFloat32() };
6661
+ }
6662
+ if (size === 8) {
6663
+ return { type: "number", value: iterator.getFloat64() };
6664
+ }
6665
+ throw new Error(`Weird size for number ${size}`);
6666
+ }
6667
+ iterator.discard(size);
6668
+ return { type: "unknown", value: null };
6669
+ };
6670
+ var parseIlstBox = ({
6671
+ iterator,
6672
+ size,
6673
+ offset
6674
+ }) => {
6675
+ const box = iterator.startBox(size - 8);
6676
+ const entries = [];
6677
+ while (iterator.counter.getOffset() < size + offset) {
6678
+ const metadataSize = iterator.getUint32();
6679
+ const index = iterator.getUint32();
6680
+ if (index === 1936419184) {
6681
+ iterator.discard(metadataSize - 8);
6682
+ continue;
6683
+ }
6684
+ const innerSize = iterator.getUint32();
6685
+ const type = iterator.getAtom();
6686
+ const typeIndicator = iterator.getUint8();
6687
+ if (typeIndicator !== 0) {
6688
+ throw new Error("Expected type indicator to be 0");
6689
+ }
6690
+ const wellKnownType = iterator.getUint24();
6691
+ iterator.discard(4);
6692
+ const value = parseFromWellKnownType(wellKnownType, iterator, innerSize - 16);
6693
+ entries.push({ index, type, wellKnownType, value });
6694
+ }
6695
+ box.discardRest();
6696
+ return {
6697
+ type: "ilst-box",
6698
+ boxSize: size,
6699
+ offset,
6700
+ entries
6701
+ };
6702
+ };
6703
+
6177
6704
  // src/boxes/iso-base-media/moov/moov.ts
6178
6705
  var parseMoov = async ({
6179
6706
  iterator,
@@ -6181,7 +6708,8 @@ var parseMoov = async ({
6181
6708
  size,
6182
6709
  options,
6183
6710
  signal,
6184
- logLevel
6711
+ logLevel,
6712
+ fields
6185
6713
  }) => {
6186
6714
  const children = await parseIsoBaseMediaBoxes({
6187
6715
  iterator,
@@ -6191,7 +6719,8 @@ var parseMoov = async ({
6191
6719
  options,
6192
6720
  continueMdat: false,
6193
6721
  signal,
6194
- logLevel
6722
+ logLevel,
6723
+ fields
6195
6724
  });
6196
6725
  if (children.status === "incomplete") {
6197
6726
  throw new Error("Incomplete boxes are not allowed");
@@ -6495,13 +7024,47 @@ var parseHvcc = ({
6495
7024
  };
6496
7025
  };
6497
7026
 
7027
+ // src/boxes/iso-base-media/stsd/keys.ts
7028
+ var parseKeys = ({
7029
+ iterator,
7030
+ offset,
7031
+ size
7032
+ }) => {
7033
+ const box = iterator.startBox(size - 8);
7034
+ const version = iterator.getUint8();
7035
+ iterator.discard(3);
7036
+ const entryCount = iterator.getUint32();
7037
+ const entries = [];
7038
+ for (let i = 0;i < entryCount; i++) {
7039
+ const keySize = iterator.getUint32();
7040
+ const namespace = iterator.getAtom();
7041
+ const value = iterator.getByteString(keySize - 8);
7042
+ const entry = {
7043
+ keySize,
7044
+ namespace,
7045
+ value
7046
+ };
7047
+ entries.push(entry);
7048
+ }
7049
+ box.discardRest();
7050
+ return {
7051
+ type: "keys-box",
7052
+ boxSize: size,
7053
+ offset,
7054
+ version,
7055
+ entryCount,
7056
+ entries
7057
+ };
7058
+ };
7059
+
6498
7060
  // src/boxes/iso-base-media/stsd/mebx.ts
6499
7061
  var parseMebx = async ({
6500
7062
  iterator,
6501
7063
  offset,
6502
7064
  size,
6503
7065
  options,
6504
- signal
7066
+ signal,
7067
+ fields
6505
7068
  }) => {
6506
7069
  iterator.discard(6);
6507
7070
  const dataReferenceIndex = iterator.getUint16();
@@ -6513,7 +7076,8 @@ var parseMebx = async ({
6513
7076
  options,
6514
7077
  continueMdat: false,
6515
7078
  signal,
6516
- logLevel: "info"
7079
+ logLevel: "info",
7080
+ fields
6517
7081
  });
6518
7082
  if (children.status === "incomplete") {
6519
7083
  throw new Error("Incomplete boxes are not allowed");
@@ -6679,7 +7243,8 @@ var processSample = async ({
6679
7243
  iterator,
6680
7244
  options,
6681
7245
  signal,
6682
- logLevel
7246
+ logLevel,
7247
+ fields
6683
7248
  }) => {
6684
7249
  const fileOffset = iterator.counter.getOffset();
6685
7250
  const bytesRemaining = iterator.bytesRemaining();
@@ -6724,7 +7289,8 @@ var processSample = async ({
6724
7289
  options,
6725
7290
  continueMdat: false,
6726
7291
  signal,
6727
- logLevel
7292
+ logLevel,
7293
+ fields
6728
7294
  });
6729
7295
  if (children.status === "incomplete") {
6730
7296
  throw new Error("Incomplete boxes are not allowed");
@@ -6771,7 +7337,8 @@ var processSample = async ({
6771
7337
  options,
6772
7338
  continueMdat: false,
6773
7339
  signal,
6774
- logLevel
7340
+ logLevel,
7341
+ fields
6775
7342
  });
6776
7343
  if (children.status === "incomplete") {
6777
7344
  throw new Error("Incomplete boxes are not allowed");
@@ -6822,7 +7389,8 @@ var processSample = async ({
6822
7389
  options,
6823
7390
  continueMdat: false,
6824
7391
  signal,
6825
- logLevel
7392
+ logLevel,
7393
+ fields
6826
7394
  });
6827
7395
  if (children.status === "incomplete") {
6828
7396
  throw new Error("Incomplete boxes are not allowed");
@@ -6876,7 +7444,8 @@ var processSample = async ({
6876
7444
  options,
6877
7445
  continueMdat: false,
6878
7446
  signal,
6879
- logLevel
7447
+ logLevel,
7448
+ fields
6880
7449
  }) : (iterator.discard(bytesRemainingInBox), { status: "done", segments: { boxes: [], type: "iso-base-media" } });
6881
7450
  if (children.status === "incomplete") {
6882
7451
  throw new Error("Incomplete boxes are not allowed");
@@ -6913,7 +7482,8 @@ var parseSamples = async ({
6913
7482
  maxBytes,
6914
7483
  options,
6915
7484
  signal,
6916
- logLevel
7485
+ logLevel,
7486
+ fields
6917
7487
  }) => {
6918
7488
  const samples = [];
6919
7489
  const initialOffset = iterator.counter.getOffset();
@@ -6922,7 +7492,8 @@ var parseSamples = async ({
6922
7492
  iterator,
6923
7493
  options,
6924
7494
  signal,
6925
- logLevel
7495
+ logLevel,
7496
+ fields
6926
7497
  });
6927
7498
  if (sample) {
6928
7499
  samples.push(sample);
@@ -6937,7 +7508,8 @@ var parseStsd = async ({
6937
7508
  offset,
6938
7509
  size,
6939
7510
  options,
6940
- signal
7511
+ signal,
7512
+ fields
6941
7513
  }) => {
6942
7514
  const version = iterator.getUint8();
6943
7515
  if (version !== 0) {
@@ -6951,7 +7523,8 @@ var parseStsd = async ({
6951
7523
  maxBytes: bytesRemainingInBox,
6952
7524
  options,
6953
7525
  signal,
6954
- logLevel: "info"
7526
+ logLevel: "info",
7527
+ fields
6955
7528
  });
6956
7529
  if (boxes.length !== numberOfEntries) {
6957
7530
  throw new Error(`Expected ${numberOfEntries} sample descriptions, got ${boxes.length}`);
@@ -7222,7 +7795,8 @@ var parseTrak = async ({
7222
7795
  offsetAtStart,
7223
7796
  options,
7224
7797
  signal,
7225
- logLevel
7798
+ logLevel,
7799
+ fields
7226
7800
  }) => {
7227
7801
  const children = await parseIsoBaseMediaBoxes({
7228
7802
  iterator: data,
@@ -7232,7 +7806,8 @@ var parseTrak = async ({
7232
7806
  options,
7233
7807
  continueMdat: false,
7234
7808
  signal,
7235
- logLevel
7809
+ logLevel,
7810
+ fields
7236
7811
  });
7237
7812
  if (children.status === "incomplete") {
7238
7813
  throw new Error("Incomplete boxes are not allowed");
@@ -7294,9 +7869,10 @@ var getChildren = async ({
7294
7869
  bytesRemainingInBox,
7295
7870
  options,
7296
7871
  signal,
7297
- logLevel
7872
+ logLevel,
7873
+ fields
7298
7874
  }) => {
7299
- const parseChildren = boxType === "mdia" || boxType === "minf" || boxType === "stbl" || boxType === "moof" || boxType === "dims" || boxType === "wave" || boxType === "traf" || boxType === "stsb";
7875
+ const parseChildren = boxType === "mdia" || boxType === "minf" || boxType === "stbl" || boxType === "udta" || boxType === "moof" || boxType === "dims" || boxType === "meta" || boxType === "wave" || boxType === "traf" || boxType === "stsb";
7300
7876
  if (parseChildren) {
7301
7877
  const parsed = await parseIsoBaseMediaBoxes({
7302
7878
  iterator,
@@ -7306,7 +7882,8 @@ var getChildren = async ({
7306
7882
  options,
7307
7883
  continueMdat: false,
7308
7884
  signal,
7309
- logLevel
7885
+ logLevel,
7886
+ fields
7310
7887
  });
7311
7888
  if (parsed.status === "incomplete") {
7312
7889
  throw new Error("Incomplete boxes are not allowed");
@@ -7356,7 +7933,8 @@ var processBox = async ({
7356
7933
  parsedBoxes,
7357
7934
  options,
7358
7935
  signal,
7359
- logLevel
7936
+ logLevel,
7937
+ fields
7360
7938
  }) => {
7361
7939
  const fileOffset = iterator.counter.getOffset();
7362
7940
  const bytesRemaining = iterator.bytesRemaining();
@@ -7385,7 +7963,7 @@ var processBox = async ({
7385
7963
  const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber() : boxSizeRaw;
7386
7964
  if (bytesRemaining < boxSize) {
7387
7965
  if (boxType === "mdat") {
7388
- const shouldSkip = (options.canSkipVideoData || !hasTracks({ type: "iso-base-media", boxes: parsedBoxes }, options.parserState)) && options.supportsContentRange;
7966
+ const shouldSkip = options.parserState.maySkipVideoData() || !hasTracks({ type: "iso-base-media", boxes: parsedBoxes }, options.parserState) && options.supportsContentRange;
7389
7967
  if (shouldSkip) {
7390
7968
  const skipTo = fileOffset + boxSize;
7391
7969
  const bytesToSkip = skipTo - iterator.counter.getOffset();
@@ -7484,7 +8062,8 @@ var processBox = async ({
7484
8062
  offset: fileOffset,
7485
8063
  size: boxSize,
7486
8064
  options,
7487
- signal
8065
+ signal,
8066
+ fields
7488
8067
  });
7489
8068
  return {
7490
8069
  type: "complete",
@@ -7578,7 +8157,39 @@ var processBox = async ({
7578
8157
  offset: fileOffset,
7579
8158
  size: boxSize,
7580
8159
  options,
7581
- signal
8160
+ signal,
8161
+ fields
8162
+ });
8163
+ return {
8164
+ type: "complete",
8165
+ box,
8166
+ size: boxSize,
8167
+ skipTo: null
8168
+ };
8169
+ }
8170
+ if (boxType === "hdlr") {
8171
+ const box = await parseHdlr({ iterator, size: boxSize, offset: fileOffset });
8172
+ return {
8173
+ type: "complete",
8174
+ box,
8175
+ size: boxSize,
8176
+ skipTo: null
8177
+ };
8178
+ }
8179
+ if (boxType === "keys") {
8180
+ const box = parseKeys({ iterator, size: boxSize, offset: fileOffset });
8181
+ return {
8182
+ type: "complete",
8183
+ box,
8184
+ size: boxSize,
8185
+ skipTo: null
8186
+ };
8187
+ }
8188
+ if (boxType === "ilst") {
8189
+ const box = parseIlstBox({
8190
+ iterator,
8191
+ offset: fileOffset,
8192
+ size: boxSize
7582
8193
  });
7583
8194
  return {
7584
8195
  type: "complete",
@@ -7594,8 +8205,10 @@ var processBox = async ({
7594
8205
  size: boxSize,
7595
8206
  options,
7596
8207
  signal,
7597
- logLevel
8208
+ logLevel,
8209
+ fields
7598
8210
  });
8211
+ options.parserState.tracks.setIsDone();
7599
8212
  return {
7600
8213
  type: "complete",
7601
8214
  box,
@@ -7610,7 +8223,8 @@ var processBox = async ({
7610
8223
  offsetAtStart: fileOffset,
7611
8224
  options,
7612
8225
  signal,
7613
- logLevel
8226
+ logLevel,
8227
+ fields
7614
8228
  });
7615
8229
  const transformedTrack = makeBaseMediaTrack(box);
7616
8230
  if (transformedTrack) {
@@ -7743,7 +8357,8 @@ var processBox = async ({
7743
8357
  bytesRemainingInBox,
7744
8358
  options,
7745
8359
  signal,
7746
- logLevel
8360
+ logLevel,
8361
+ fields
7747
8362
  });
7748
8363
  return {
7749
8364
  type: "complete",
@@ -7766,7 +8381,8 @@ var parseIsoBaseMediaBoxes = async ({
7766
8381
  options,
7767
8382
  continueMdat,
7768
8383
  signal,
7769
- logLevel
8384
+ logLevel,
8385
+ fields
7770
8386
  }) => {
7771
8387
  const structure = {
7772
8388
  type: "iso-base-media",
@@ -7788,7 +8404,8 @@ var parseIsoBaseMediaBoxes = async ({
7788
8404
  parsedBoxes: initialBoxes,
7789
8405
  options,
7790
8406
  signal,
7791
- logLevel
8407
+ logLevel,
8408
+ fields
7792
8409
  });
7793
8410
  if (result.type === "incomplete") {
7794
8411
  if (Number.isFinite(maxBytes)) {
@@ -7806,7 +8423,8 @@ var parseIsoBaseMediaBoxes = async ({
7806
8423
  options,
7807
8424
  continueMdat: false,
7808
8425
  signal,
7809
- logLevel
8426
+ logLevel,
8427
+ fields
7810
8428
  });
7811
8429
  },
7812
8430
  skipTo: null
@@ -7825,7 +8443,8 @@ var parseIsoBaseMediaBoxes = async ({
7825
8443
  options,
7826
8444
  continueMdat: result,
7827
8445
  signal,
7828
- logLevel
8446
+ logLevel,
8447
+ fields
7829
8448
  }));
7830
8449
  },
7831
8450
  skipTo: null
@@ -7841,6 +8460,12 @@ var parseIsoBaseMediaBoxes = async ({
7841
8460
  break;
7842
8461
  } else {
7843
8462
  structure.boxes.push(result.box);
8463
+ if (hasAllInfo({ fields, state: options.parserState, structure })) {
8464
+ return {
8465
+ status: "done",
8466
+ segments: structure
8467
+ };
8468
+ }
7844
8469
  }
7845
8470
  if (result.skipTo !== null) {
7846
8471
  if (!options.supportsContentRange) {
@@ -7858,7 +8483,8 @@ var parseIsoBaseMediaBoxes = async ({
7858
8483
  options,
7859
8484
  continueMdat: false,
7860
8485
  signal,
7861
- logLevel
8486
+ logLevel,
8487
+ fields
7862
8488
  });
7863
8489
  },
7864
8490
  skipTo: result.skipTo
@@ -7877,7 +8503,8 @@ var parseIsoBaseMediaBoxes = async ({
7877
8503
  options,
7878
8504
  continueMdat: false,
7879
8505
  signal,
7880
- logLevel
8506
+ logLevel,
8507
+ fields
7881
8508
  });
7882
8509
  },
7883
8510
  skipTo: null
@@ -7886,8 +8513,8 @@ var parseIsoBaseMediaBoxes = async ({
7886
8513
  iterator.removeBytesRead();
7887
8514
  }
7888
8515
  const mdatState = getMdatBox(structure.boxes);
7889
- const skipped = mdatState?.status === "samples-skipped" && !options.canSkipVideoData && options.supportsContentRange;
7890
- const buffered = mdatState?.status === "samples-buffered" && !options.canSkipVideoData;
8516
+ const skipped = mdatState?.status === "samples-skipped" && !options.parserState.maySkipVideoData() && options.supportsContentRange;
8517
+ const buffered = mdatState?.status === "samples-buffered" && !options.parserState.maySkipVideoData();
7891
8518
  if (skipped || buffered) {
7892
8519
  return {
7893
8520
  status: "incomplete",
@@ -7904,7 +8531,8 @@ var parseIsoBaseMediaBoxes = async ({
7904
8531
  options,
7905
8532
  continueMdat: false,
7906
8533
  signal,
7907
- logLevel
8534
+ logLevel,
8535
+ fields
7908
8536
  });
7909
8537
  },
7910
8538
  skipTo: skipped ? mdatState.fileOffset : null
@@ -8057,6 +8685,7 @@ var handleChunk = async ({
8057
8685
  const ppsProfile = infos.find((i) => i.type === "avc-pps");
8058
8686
  if (avcProfile && ppsProfile) {
8059
8687
  await options.parserState.onProfile({ pps: ppsProfile, sps: avcProfile });
8688
+ options.parserState.tracks.setIsDone();
8060
8689
  }
8061
8690
  await options.parserState.onVideoSample(trackId, {
8062
8691
  cts: timestamp,
@@ -8067,26 +8696,26 @@ var handleChunk = async ({
8067
8696
  trackId,
8068
8697
  type: keyOrDelta.type === "keyframe" ? "key" : "delta"
8069
8698
  });
8070
- } else {
8071
- const audioChunk = ckId.match(/^([0-9]{2})wb$/);
8072
- if (audioChunk) {
8073
- const trackId = parseInt(audioChunk[1], 10);
8074
- const strh = getStrhForIndex(structure, trackId);
8075
- const samplesPerSecond = strh.rate / strh.scale;
8076
- const nthSample = options.parserState.getSamplesForTrack(trackId);
8077
- const timeInSec = nthSample / samplesPerSecond;
8078
- const timestamp = timeInSec * MEDIA_PARSER_RIFF_TIMESCALE;
8079
- const duration2 = 1 / samplesPerSecond * MEDIA_PARSER_RIFF_TIMESCALE;
8080
- await options.parserState.onAudioSample(trackId, {
8081
- cts: timestamp,
8082
- dts: timestamp,
8083
- data: iterator.getSlice(ckSize),
8084
- duration: duration2,
8085
- timestamp,
8086
- trackId,
8087
- type: "key"
8088
- });
8089
- }
8699
+ return;
8700
+ }
8701
+ const audioChunk = ckId.match(/^([0-9]{2})wb$/);
8702
+ if (audioChunk) {
8703
+ const trackId = parseInt(audioChunk[1], 10);
8704
+ const strh = getStrhForIndex(structure, trackId);
8705
+ const samplesPerSecond = strh.rate / strh.scale;
8706
+ const nthSample = options.parserState.getSamplesForTrack(trackId);
8707
+ const timeInSec = nthSample / samplesPerSecond;
8708
+ const timestamp = timeInSec * MEDIA_PARSER_RIFF_TIMESCALE;
8709
+ const duration2 = 1 / samplesPerSecond * MEDIA_PARSER_RIFF_TIMESCALE;
8710
+ await options.parserState.onAudioSample(trackId, {
8711
+ cts: timestamp,
8712
+ dts: timestamp,
8713
+ data: iterator.getSlice(ckSize),
8714
+ duration: duration2,
8715
+ timestamp,
8716
+ trackId,
8717
+ type: "key"
8718
+ });
8090
8719
  }
8091
8720
  };
8092
8721
  var parseMovi = async ({
@@ -8106,6 +8735,15 @@ var parseMovi = async ({
8106
8735
  }
8107
8736
  const ckId = iterator.getByteString(4);
8108
8737
  const ckSize = iterator.getUint32Le();
8738
+ if (options.parserState.maySkipVideoData() && options.parserState.getAvcProfile()) {
8739
+ return {
8740
+ type: "complete",
8741
+ box: {
8742
+ type: "movi-box"
8743
+ },
8744
+ skipTo: maxOffset
8745
+ };
8746
+ }
8109
8747
  if (iterator.bytesRemaining() < ckSize) {
8110
8748
  iterator.counter.decrement(8);
8111
8749
  return {
@@ -8128,7 +8766,8 @@ var parseMovi = async ({
8128
8766
  type: "complete",
8129
8767
  box: {
8130
8768
  type: "movi-box"
8131
- }
8769
+ },
8770
+ skipTo: null
8132
8771
  };
8133
8772
  }
8134
8773
  if (iterator.counter.getOffset() > maxOffset) {
@@ -8210,6 +8849,24 @@ var parseFmtBox = ({
8210
8849
  };
8211
8850
  };
8212
8851
 
8852
+ // src/boxes/riff/parse-isft.ts
8853
+ var parseIsft = ({
8854
+ iterator,
8855
+ size
8856
+ }) => {
8857
+ const { expectNoMoreBytes } = iterator.startBox(size);
8858
+ const software = iterator.getByteString(size - 1);
8859
+ const last = iterator.getUint8();
8860
+ if (last !== 0) {
8861
+ throw new Error(`Expected 0 byte, got ${last}`);
8862
+ }
8863
+ expectNoMoreBytes();
8864
+ return {
8865
+ type: "isft-box",
8866
+ software
8867
+ };
8868
+ };
8869
+
8213
8870
  // src/boxes/riff/parse-list-box.ts
8214
8871
  var parseListBox = async ({
8215
8872
  iterator,
@@ -8377,6 +9034,9 @@ var parseRiffBox = ({
8377
9034
  if (id === "LIST") {
8378
9035
  return parseListBox({ iterator, size, options });
8379
9036
  }
9037
+ if (id === "ISFT") {
9038
+ return Promise.resolve(parseIsft({ iterator, size }));
9039
+ }
8380
9040
  if (id === "avih") {
8381
9041
  return Promise.resolve(parseAvih({ iterator, size }));
8382
9042
  }
@@ -8437,7 +9097,8 @@ var expectRiffBox = async ({
8437
9097
  size: ckSize,
8438
9098
  boxes: structure.boxes,
8439
9099
  options
8440
- })
9100
+ }),
9101
+ skipTo: null
8441
9102
  };
8442
9103
  };
8443
9104
 
@@ -8465,10 +9126,8 @@ var continueAfterRiffBoxResult = ({
8465
9126
  skipTo: null
8466
9127
  });
8467
9128
  }
8468
- if (result.type === "complete") {
8469
- if (result.box) {
8470
- structure.boxes.push(result.box);
8471
- }
9129
+ if (result.type === "complete" && result.box) {
9130
+ structure.boxes.push(result.box);
8472
9131
  }
8473
9132
  return parseRiffBody({ iterator, maxOffset, options, structure });
8474
9133
  };
@@ -8484,6 +9143,22 @@ var parseRiffBody = async ({
8484
9143
  options,
8485
9144
  structure
8486
9145
  });
9146
+ if (result.type === "complete" && result.skipTo !== null) {
9147
+ return {
9148
+ status: "incomplete",
9149
+ skipTo: result.skipTo,
9150
+ segments: structure,
9151
+ continueParsing() {
9152
+ return Promise.resolve(continueAfterRiffBoxResult({
9153
+ iterator,
9154
+ maxOffset,
9155
+ options,
9156
+ result,
9157
+ structure
9158
+ }));
9159
+ }
9160
+ };
9161
+ }
8487
9162
  if (result.type === "incomplete") {
8488
9163
  return {
8489
9164
  status: "incomplete",
@@ -8504,6 +9179,15 @@ var parseRiffBody = async ({
8504
9179
  continue;
8505
9180
  }
8506
9181
  structure.boxes.push(result.box);
9182
+ if (result.box.type === "list-box" && result.box.listType === "hdrl") {
9183
+ const tracks2 = getTracks(structure, options.parserState);
9184
+ if (!tracks2.videoTracks.some((t) => t.codec === TO_BE_OVERRIDDEN_LATER)) {
9185
+ options.parserState.tracks.setIsDone();
9186
+ }
9187
+ }
9188
+ if (result.box.type === "wave-format-box") {
9189
+ options.parserState.tracks.setIsDone();
9190
+ }
8507
9191
  if (result.box.type === "strf-box-video" || result.box.type === "strf-box-audio") {
8508
9192
  const strh = getStrhBox(structure.boxes);
8509
9193
  const strf = getStrfBox(structure.boxes);
@@ -8543,7 +9227,8 @@ var parseRiffBody = async ({
8543
9227
  };
8544
9228
  var parseRiff = ({
8545
9229
  iterator,
8546
- options
9230
+ options,
9231
+ fields
8547
9232
  }) => {
8548
9233
  const structure = { type: "riff", boxes: [] };
8549
9234
  const riff = iterator.getByteString(4);
@@ -8556,6 +9241,12 @@ var parseRiff = ({
8556
9241
  throw new Error(`File type ${fileType} not supported`);
8557
9242
  }
8558
9243
  structure.boxes.push({ type: "riff-header", fileSize: size, fileType });
9244
+ if (hasAllInfo({ fields, structure, state: options.parserState })) {
9245
+ return Promise.resolve({
9246
+ status: "done",
9247
+ segments: structure
9248
+ });
9249
+ }
8559
9250
  return parseRiffBody({ iterator, structure, maxOffset: Infinity, options });
8560
9251
  };
8561
9252
 
@@ -8711,7 +9402,7 @@ var parseEbml = async (iterator, parserContext) => {
8711
9402
  if (hasInMap.type === "hex-string") {
8712
9403
  return {
8713
9404
  type: hasInMap.name,
8714
- value: "0x" + [...iterator.getSlice(size)].map((b) => b.toString(16).padStart(2, "0")).join(""),
9405
+ value: "0x" + [...iterator.getSlice(size)].map((b) => b.toString(16).padStart(2, "0")).join("").replace(new RegExp("^" + hex), ""),
8715
9406
  minVintWidth
8716
9407
  };
8717
9408
  }
@@ -8859,7 +9550,9 @@ var expectSegment = async ({
8859
9550
  iterator,
8860
9551
  parserContext,
8861
9552
  offset,
8862
- children
9553
+ children,
9554
+ fields,
9555
+ topLevelStructure
8863
9556
  }) => {
8864
9557
  iterator.counter.decrement(iterator.counter.getOffset() - offset);
8865
9558
  if (iterator.bytesRemaining() === 0) {
@@ -8870,7 +9563,9 @@ var expectSegment = async ({
8870
9563
  iterator,
8871
9564
  parserContext,
8872
9565
  offset,
8873
- children
9566
+ children,
9567
+ fields,
9568
+ topLevelStructure
8874
9569
  });
8875
9570
  },
8876
9571
  segment: null
@@ -8886,7 +9581,9 @@ var expectSegment = async ({
8886
9581
  iterator,
8887
9582
  parserContext,
8888
9583
  offset,
8889
- children
9584
+ children,
9585
+ fields,
9586
+ topLevelStructure
8890
9587
  });
8891
9588
  },
8892
9589
  segment: null
@@ -8900,7 +9597,14 @@ var expectSegment = async ({
8900
9597
  return {
8901
9598
  status: "incomplete",
8902
9599
  continueParsing: () => {
8903
- return expectSegment({ iterator, parserContext, offset, children });
9600
+ return expectSegment({
9601
+ iterator,
9602
+ parserContext,
9603
+ offset,
9604
+ children,
9605
+ fields,
9606
+ topLevelStructure
9607
+ });
8904
9608
  },
8905
9609
  segment: null
8906
9610
  };
@@ -8917,7 +9621,9 @@ var expectSegment = async ({
8917
9621
  length,
8918
9622
  children: newSegment.value,
8919
9623
  parserContext,
8920
- startOffset: iterator.counter.getOffset()
9624
+ startOffset: iterator.counter.getOffset(),
9625
+ fields,
9626
+ topLevelStructure
8921
9627
  });
8922
9628
  if (main.status === "incomplete") {
8923
9629
  return {
@@ -8945,7 +9651,14 @@ var expectSegment = async ({
8945
9651
  status: "incomplete",
8946
9652
  segment: null,
8947
9653
  continueParsing: () => {
8948
- return expectSegment({ iterator, parserContext, offset, children });
9654
+ return expectSegment({
9655
+ iterator,
9656
+ parserContext,
9657
+ offset,
9658
+ children,
9659
+ fields,
9660
+ topLevelStructure
9661
+ });
8949
9662
  }
8950
9663
  };
8951
9664
  }
@@ -8981,10 +9694,22 @@ var parseSegment = async ({
8981
9694
  // src/boxes/webm/segments/parse-children.ts
8982
9695
  var processParseResult = ({
8983
9696
  parseResult,
8984
- children
9697
+ children,
9698
+ state,
9699
+ fields,
9700
+ topLevelStructure
8985
9701
  }) => {
8986
9702
  if (parseResult.segment && !children.includes(parseResult.segment)) {
8987
9703
  children.push(parseResult.segment);
9704
+ if (hasAllInfo({ fields, state, structure: topLevelStructure })) {
9705
+ return {
9706
+ status: "done",
9707
+ segment: parseResult.segment
9708
+ };
9709
+ }
9710
+ if (parseResult.segment.type === "Tracks") {
9711
+ state.tracks.setIsDone();
9712
+ }
8988
9713
  }
8989
9714
  if (parseResult.status === "incomplete") {
8990
9715
  return {
@@ -8994,7 +9719,10 @@ var processParseResult = ({
8994
9719
  const newParseResult = await parseResult.continueParsing();
8995
9720
  return processParseResult({
8996
9721
  children,
8997
- parseResult: newParseResult
9722
+ parseResult: newParseResult,
9723
+ state,
9724
+ fields,
9725
+ topLevelStructure
8998
9726
  });
8999
9727
  }
9000
9728
  };
@@ -9008,17 +9736,24 @@ var expectAndProcessSegment = async ({
9008
9736
  iterator,
9009
9737
  parserContext,
9010
9738
  offset,
9011
- children
9739
+ children,
9740
+ fields,
9741
+ topLevelStructure
9012
9742
  }) => {
9013
9743
  const segment = await expectSegment({
9014
9744
  iterator,
9015
9745
  parserContext,
9016
9746
  offset,
9017
- children
9747
+ children,
9748
+ fields,
9749
+ topLevelStructure
9018
9750
  });
9019
9751
  return processParseResult({
9020
9752
  children,
9021
- parseResult: segment
9753
+ parseResult: segment,
9754
+ state: parserContext.parserState,
9755
+ fields,
9756
+ topLevelStructure
9022
9757
  });
9023
9758
  };
9024
9759
  var continueAfterSegmentResult = async ({
@@ -9027,7 +9762,9 @@ var continueAfterSegmentResult = async ({
9027
9762
  children,
9028
9763
  parserContext,
9029
9764
  iterator,
9030
- startOffset
9765
+ startOffset,
9766
+ fields,
9767
+ topLevelStructure
9031
9768
  }) => {
9032
9769
  if (result.status === "done") {
9033
9770
  throw new Error("Should not continue after done");
@@ -9042,7 +9779,9 @@ var continueAfterSegmentResult = async ({
9042
9779
  iterator,
9043
9780
  length,
9044
9781
  parserContext,
9045
- startOffset
9782
+ startOffset,
9783
+ fields,
9784
+ topLevelStructure
9046
9785
  });
9047
9786
  },
9048
9787
  skipTo: null
@@ -9057,7 +9796,9 @@ var continueAfterSegmentResult = async ({
9057
9796
  iterator,
9058
9797
  length,
9059
9798
  parserContext,
9060
- startOffset
9799
+ startOffset,
9800
+ fields,
9801
+ topLevelStructure
9061
9802
  });
9062
9803
  },
9063
9804
  skipTo: null
@@ -9068,7 +9809,9 @@ var expectChildren = async ({
9068
9809
  length,
9069
9810
  children,
9070
9811
  parserContext,
9071
- startOffset
9812
+ startOffset,
9813
+ fields,
9814
+ topLevelStructure
9072
9815
  }) => {
9073
9816
  while (iterator.counter.getOffset() < startOffset + length) {
9074
9817
  if (iterator.bytesRemaining() === 0) {
@@ -9079,8 +9822,19 @@ var expectChildren = async ({
9079
9822
  iterator,
9080
9823
  parserContext,
9081
9824
  offset: currentOffset,
9082
- children
9825
+ children,
9826
+ fields,
9827
+ topLevelStructure
9083
9828
  });
9829
+ if (hasAllInfo({
9830
+ fields,
9831
+ state: parserContext.parserState,
9832
+ structure: topLevelStructure
9833
+ })) {
9834
+ return {
9835
+ status: "done"
9836
+ };
9837
+ }
9084
9838
  if (child.status === "incomplete") {
9085
9839
  return {
9086
9840
  status: "incomplete",
@@ -9091,7 +9845,9 @@ var expectChildren = async ({
9091
9845
  iterator,
9092
9846
  length: length - (currentOffset - startOffset),
9093
9847
  parserContext,
9094
- startOffset: currentOffset
9848
+ startOffset: currentOffset,
9849
+ fields,
9850
+ topLevelStructure
9095
9851
  });
9096
9852
  },
9097
9853
  skipTo: null
@@ -9121,14 +9877,20 @@ var continueAfterMatroskaResult = (result, structure) => {
9121
9877
  skipTo: null
9122
9878
  };
9123
9879
  };
9124
- var parseWebm = async (counter, parserContext) => {
9880
+ var parseWebm = async ({
9881
+ counter,
9882
+ parserContext,
9883
+ fields
9884
+ }) => {
9125
9885
  const structure = { type: "matroska", boxes: [] };
9126
9886
  const results = await expectChildren({
9127
9887
  iterator: counter,
9128
9888
  length: Infinity,
9129
9889
  children: structure.boxes,
9130
9890
  parserContext,
9131
- startOffset: counter.counter.getOffset()
9891
+ startOffset: counter.counter.getOffset(),
9892
+ fields,
9893
+ topLevelStructure: structure
9132
9894
  });
9133
9895
  return continueAfterMatroskaResult(results, structure);
9134
9896
  };
@@ -9138,13 +9900,15 @@ var parseVideo = ({
9138
9900
  iterator,
9139
9901
  options,
9140
9902
  signal,
9141
- logLevel
9903
+ logLevel,
9904
+ fields
9142
9905
  }) => {
9143
9906
  if (iterator.bytesRemaining() === 0) {
9144
9907
  return Promise.reject(new Error("no bytes"));
9145
9908
  }
9146
9909
  if (iterator.isRiff()) {
9147
- return Promise.resolve(parseRiff({ iterator, options }));
9910
+ Log.verbose(logLevel, "Detected RIFF container");
9911
+ return Promise.resolve(parseRiff({ iterator, options, fields }));
9148
9912
  }
9149
9913
  if (iterator.isIsoBaseMedia()) {
9150
9914
  Log.verbose(logLevel, "Detected ISO Base Media container");
@@ -9156,12 +9920,13 @@ var parseVideo = ({
9156
9920
  options,
9157
9921
  continueMdat: false,
9158
9922
  signal,
9159
- logLevel
9923
+ logLevel,
9924
+ fields
9160
9925
  });
9161
9926
  }
9162
9927
  if (iterator.isWebm()) {
9163
9928
  Log.verbose(logLevel, "Detected Matroska container");
9164
- return parseWebm(iterator, options);
9929
+ return parseWebm({ counter: iterator, parserContext: options, fields });
9165
9930
  }
9166
9931
  if (iterator.isMp3()) {
9167
9932
  return Promise.reject(new Error("MP3 files are not yet supported"));
@@ -9169,11 +9934,67 @@ var parseVideo = ({
9169
9934
  return Promise.reject(new Error("Unknown video format"));
9170
9935
  };
9171
9936
 
9172
- // src/parser-state.ts
9937
+ // src/state/can-skip-tracks.ts
9938
+ var needsTracksField = {
9939
+ audioCodec: true,
9940
+ container: false,
9941
+ dimensions: true,
9942
+ durationInSeconds: true,
9943
+ fps: true,
9944
+ internalStats: false,
9945
+ isHdr: true,
9946
+ name: false,
9947
+ rotation: true,
9948
+ size: false,
9949
+ structure: true,
9950
+ tracks: true,
9951
+ unrotatedDimensions: true,
9952
+ videoCodec: true,
9953
+ metadata: true
9954
+ };
9955
+ var makeCanSkipTracksState = ({
9956
+ hasAudioTrackHandlers,
9957
+ fields,
9958
+ hasVideoTrackHandlers
9959
+ }) => {
9960
+ return {
9961
+ canSkipTracks: () => {
9962
+ if (hasAudioTrackHandlers || hasVideoTrackHandlers) {
9963
+ return false;
9964
+ }
9965
+ const keys = Object.keys(fields ?? {});
9966
+ const selectedKeys = keys.filter((k) => fields[k]);
9967
+ return !selectedKeys.some((k) => needsTracksField[k]);
9968
+ }
9969
+ };
9970
+ };
9971
+
9972
+ // src/state/has-tracks-section.ts
9973
+ var makeTracksSectionState = (canSkipTracksState) => {
9974
+ let doneWithTracks = false;
9975
+ return {
9976
+ hasAllTracks: () => doneWithTracks,
9977
+ setIsDone: () => {
9978
+ doneWithTracks = true;
9979
+ },
9980
+ ensureHasTracksAtEnd: () => {
9981
+ if (canSkipTracksState.canSkipTracks()) {
9982
+ return;
9983
+ }
9984
+ if (!doneWithTracks) {
9985
+ throw new Error("Error in Media Parser: End of parsing has been reached, but no tracks have been found");
9986
+ }
9987
+ }
9988
+ };
9989
+ };
9990
+
9991
+ // src/state/parser-state.ts
9173
9992
  var makeParserState = ({
9174
- hasAudioCallbacks,
9175
- hasVideoCallbacks,
9176
- signal
9993
+ hasAudioTrackHandlers,
9994
+ hasVideoTrackHandlers,
9995
+ signal,
9996
+ getIterator,
9997
+ fields
9177
9998
  }) => {
9178
9999
  const trackEntries = {};
9179
10000
  const onTrackEntrySegment = (trackEntry2) => {
@@ -9198,14 +10019,17 @@ var makeParserState = ({
9198
10019
  const audioSampleCallbacks = {};
9199
10020
  const queuedAudioSamples = {};
9200
10021
  const queuedVideoSamples = {};
9201
- const declinedTrackNumbers = [];
9202
10022
  let timescale2 = null;
10023
+ let skippedBytes = 0;
9203
10024
  const getTimescale = () => {
9204
10025
  if (timescale2 === null) {
9205
10026
  return 1e6;
9206
10027
  }
9207
10028
  return timescale2;
9208
10029
  };
10030
+ const increaseSkippedBytes = (bytes) => {
10031
+ skippedBytes += bytes;
10032
+ };
9209
10033
  const setTimescale = (newTimescale) => {
9210
10034
  timescale2 = newTimescale;
9211
10035
  };
@@ -9239,6 +10063,12 @@ var makeParserState = ({
9239
10063
  }
9240
10064
  profileCallbacks.length = 0;
9241
10065
  };
10066
+ const canSkipTracksState = makeCanSkipTracksState({
10067
+ hasAudioTrackHandlers,
10068
+ fields,
10069
+ hasVideoTrackHandlers
10070
+ });
10071
+ const tracksState = makeTracksSectionState(canSkipTracksState);
9242
10072
  return {
9243
10073
  onTrackEntrySegment,
9244
10074
  onProfile,
@@ -9247,7 +10077,6 @@ var makeParserState = ({
9247
10077
  registerVideoSampleCallback: async (id, callback) => {
9248
10078
  if (callback === null) {
9249
10079
  delete videoSampleCallbacks[id];
9250
- declinedTrackNumbers.push(id);
9251
10080
  return;
9252
10081
  }
9253
10082
  videoSampleCallbacks[id] = callback;
@@ -9261,7 +10090,6 @@ var makeParserState = ({
9261
10090
  registerAudioSampleCallback: async (id, callback) => {
9262
10091
  if (callback === null) {
9263
10092
  delete audioSampleCallbacks[id];
9264
- declinedTrackNumbers.push(id);
9265
10093
  return;
9266
10094
  }
9267
10095
  audioSampleCallbacks[id] = callback;
@@ -9281,13 +10109,6 @@ var makeParserState = ({
9281
10109
  const callback = audioSampleCallbacks[trackId];
9282
10110
  if (callback) {
9283
10111
  await callback(audioSample);
9284
- } else {
9285
- if (declinedTrackNumbers.includes(trackId)) {
9286
- return;
9287
- }
9288
- if (!hasAudioCallbacks) {
9289
- throw new Error("No audio callbacks registered");
9290
- }
9291
10112
  }
9292
10113
  },
9293
10114
  onVideoSample: async (trackId, videoSample) => {
@@ -9301,16 +10122,8 @@ var makeParserState = ({
9301
10122
  const callback = videoSampleCallbacks[trackId];
9302
10123
  if (callback) {
9303
10124
  await callback(videoSample);
9304
- } else {
9305
- if (declinedTrackNumbers.includes(trackId)) {
9306
- return;
9307
- }
9308
- if (!hasVideoCallbacks) {
9309
- throw new Error("No video callbacks registered");
9310
- }
9311
10125
  }
9312
10126
  },
9313
- getInternalStats: () => ({}),
9314
10127
  getTimescale,
9315
10128
  setTimescale,
9316
10129
  getSamplesForTrack: (trackId) => {
@@ -9318,7 +10131,18 @@ var makeParserState = ({
9318
10131
  },
9319
10132
  getAvcProfile: () => {
9320
10133
  return avcProfile;
9321
- }
10134
+ },
10135
+ getInternalStats: () => ({
10136
+ skippedBytes,
10137
+ finalCursorOffset: getIterator()?.counter.getOffset() ?? 0
10138
+ }),
10139
+ getSkipBytes: () => skippedBytes,
10140
+ increaseSkippedBytes,
10141
+ maySkipVideoData: () => {
10142
+ return tracksState.hasAllTracks() && Object.values(videoSampleCallbacks).length === 0 && Object.values(audioSampleCallbacks).length === 0;
10143
+ },
10144
+ tracks: tracksState,
10145
+ canSkipTracksState
9322
10146
  };
9323
10147
  };
9324
10148
 
@@ -9334,10 +10158,14 @@ var parseMedia = async ({
9334
10158
  onParseProgress,
9335
10159
  ...more
9336
10160
  }) => {
10161
+ let iterator = null;
10162
+ let parseResult = null;
9337
10163
  const state = makeParserState({
9338
- hasAudioCallbacks: onAudioTrack !== null,
9339
- hasVideoCallbacks: onVideoTrack !== null,
9340
- signal
10164
+ hasAudioTrackHandlers: Boolean(onAudioTrack),
10165
+ hasVideoTrackHandlers: Boolean(onVideoTrack),
10166
+ signal,
10167
+ getIterator: () => iterator,
10168
+ fields: fields ?? {}
9341
10169
  });
9342
10170
  const {
9343
10171
  reader,
@@ -9349,16 +10177,7 @@ var parseMedia = async ({
9349
10177
  const supportsContentRange = readerSupportsContentRange && !(typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.DISABLE_CONTENT_RANGE === "true");
9350
10178
  const returnValue = {};
9351
10179
  const moreFields = more;
9352
- let iterator = null;
9353
- let parseResult = null;
9354
- const canSkipVideoData = !onVideoTrack && !onAudioTrack;
9355
- if (canSkipVideoData) {
9356
- Log.verbose(logLevel, "Only parsing metadata, because no onVideoTrack and onAudioTrack callbacks were passed.");
9357
- } else {
9358
- Log.verbose(logLevel, "Parsing video data, because onVideoTrack/onAudioTrack callbacks were passed.");
9359
- }
9360
10180
  const options = {
9361
- canSkipVideoData,
9362
10181
  onAudioTrack: onAudioTrack ?? null,
9363
10182
  onVideoTrack: onVideoTrack ?? null,
9364
10183
  parserState: state,
@@ -9366,15 +10185,8 @@ var parseMedia = async ({
9366
10185
  supportsContentRange,
9367
10186
  nextTrackIndex: 0
9368
10187
  };
9369
- const hasAllInfo = () => {
9370
- if (parseResult === null) {
9371
- return false;
9372
- }
9373
- const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
9374
- return Object.values(availableInfo).every(Boolean);
9375
- };
9376
10188
  const triggerInfoEmit = () => {
9377
- const availableInfo = getAvailableInfo(fields ?? {}, parseResult, state);
10189
+ const availableInfo = getAvailableInfo(fields ?? {}, parseResult?.segments ?? null, state);
9378
10190
  emitAvailableInfo({
9379
10191
  hasInfo: availableInfo,
9380
10192
  moreFields,
@@ -9426,16 +10238,33 @@ var parseMedia = async ({
9426
10238
  iterator,
9427
10239
  options,
9428
10240
  signal: signal ?? null,
9429
- logLevel
10241
+ logLevel,
10242
+ fields: fields ?? {}
9430
10243
  });
9431
10244
  }
9432
- if (hasAllInfo() && !onVideoTrack && !onAudioTrack) {
10245
+ if (parseResult.status === "incomplete" && parseResult.skipTo !== null) {
10246
+ state.increaseSkippedBytes(parseResult.skipTo - iterator.counter.getOffset());
10247
+ }
10248
+ if (hasAllInfo({
10249
+ fields: fields ?? {},
10250
+ structure: parseResult.segments,
10251
+ state
10252
+ })) {
10253
+ Log.verbose(logLevel, "Got all info, skipping to the end.");
10254
+ if (contentLength !== null) {
10255
+ state.increaseSkippedBytes(contentLength - iterator.counter.getOffset());
10256
+ }
9433
10257
  break;
9434
10258
  }
9435
- if (parseResult && parseResult.status === "incomplete" && parseResult.skipTo !== null) {
10259
+ if (parseResult.status === "incomplete" && parseResult.skipTo !== null) {
9436
10260
  if (!supportsContentRange) {
9437
10261
  throw new Error("Content-Range header is not supported by the reader, but was asked to seek");
9438
10262
  }
10263
+ if (parseResult.skipTo === contentLength) {
10264
+ Log.verbose(logLevel, "Skipped to end of file, not fetching.");
10265
+ break;
10266
+ }
10267
+ Log.verbose(logLevel, `Skipping over video data from position ${iterator.counter.getOffset()} -> ${parseResult.skipTo}`);
9439
10268
  currentReader.abort();
9440
10269
  const { reader: newReader } = await readerInterface.read(src, parseResult.skipTo, signal);
9441
10270
  currentReader = newReader;
@@ -9445,7 +10274,9 @@ var parseMedia = async ({
9445
10274
  Log.verbose(logLevel, "Finished parsing file");
9446
10275
  emitAvailableInfo({
9447
10276
  hasInfo: Object.keys(fields ?? {}).reduce((acc, key) => {
9448
- acc[key] = true;
10277
+ if (fields?.[key]) {
10278
+ acc[key] = true;
10279
+ }
9449
10280
  return acc;
9450
10281
  }, {}),
9451
10282
  moreFields,
@@ -9457,11 +10288,9 @@ var parseMedia = async ({
9457
10288
  });
9458
10289
  currentReader.abort();
9459
10290
  iterator?.destroy();
10291
+ state.tracks.ensureHasTracksAtEnd();
9460
10292
  return returnValue;
9461
10293
  };
9462
- // src/version.ts
9463
- var VERSION = "4.0.233";
9464
-
9465
10294
  // src/index.ts
9466
10295
  var MediaParserInternals = {
9467
10296
  createMatroskaMedia,
@@ -9471,7 +10300,8 @@ var MediaParserInternals = {
9471
10300
  IoEventEmitter,
9472
10301
  makeProgressTracker,
9473
10302
  withResolvers,
9474
- withResolversAndWaitForReturn
10303
+ withResolversAndWaitForReturn,
10304
+ createAacCodecPrivate
9475
10305
  };
9476
10306
  export {
9477
10307
  parseMedia,