@remotion/media-parser 4.0.199 → 4.0.201
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.
- package/dist/av1-codec-string.d.ts +5 -0
- package/dist/av1-codec-string.js +18 -1
- package/dist/bitstream/av1.d.ts +2 -0
- package/dist/bitstream/av1.js +12 -0
- package/dist/boxes/iso-base-media/avcc-hvcc.d.ts +20 -0
- package/dist/boxes/iso-base-media/avcc-hvcc.js +73 -0
- package/dist/boxes/iso-base-media/avcc.d.ts +18 -0
- package/dist/boxes/iso-base-media/avcc.js +27 -0
- package/dist/boxes/iso-base-media/esds-descriptors.d.ts +21 -0
- package/dist/boxes/iso-base-media/esds-descriptors.js +62 -0
- package/dist/boxes/iso-base-media/esds.d.ts +15 -0
- package/dist/boxes/iso-base-media/esds.js +27 -0
- package/dist/boxes/iso-base-media/mdat/mdat.js +2 -2
- package/dist/boxes/iso-base-media/moov/moov.js +1 -0
- package/dist/boxes/iso-base-media/process-box.d.ts +4 -2
- package/dist/boxes/iso-base-media/process-box.js +56 -40
- package/dist/boxes/iso-base-media/stsd/mebx.d.ts +2 -1
- package/dist/boxes/iso-base-media/stsd/mebx.js +2 -1
- package/dist/boxes/iso-base-media/stsd/samples.js +3 -0
- package/dist/boxes/iso-base-media/stsd/stco.d.ts +3 -2
- package/dist/boxes/iso-base-media/stsd/stco.js +2 -2
- package/dist/boxes/iso-base-media/trak/trak.js +1 -0
- package/dist/boxes/webm/bitstream/av1.js +10 -1
- package/dist/boxes/webm/ebml.d.ts +2 -0
- package/dist/boxes/webm/ebml.js +72 -0
- package/dist/boxes/webm/make-header.d.ts +9 -0
- package/dist/boxes/webm/make-header.js +79 -0
- package/dist/boxes/webm/parse-ebml.d.ts +7 -0
- package/dist/boxes/webm/parse-ebml.js +66 -0
- package/dist/boxes/webm/parse-webm-header.js +8 -9
- package/dist/boxes/webm/segments/all-segments.d.ts +262 -0
- package/dist/boxes/webm/segments/all-segments.js +130 -1
- package/dist/boxes/webm/segments/block-simple-block-flags.d.ts +9 -0
- package/dist/boxes/webm/segments/block-simple-block-flags.js +38 -0
- package/dist/boxes/webm/segments/seek-position.js +1 -1
- package/dist/boxes/webm/segments/seek.d.ts +1 -1
- package/dist/boxes/webm/segments/seek.js +8 -2
- package/dist/boxes/webm/segments/timestamp-scale.js +1 -1
- package/dist/boxes/webm/segments/track-entry.d.ts +25 -9
- package/dist/boxes/webm/segments/track-entry.js +73 -33
- package/dist/boxes/webm/segments.d.ts +3 -3
- package/dist/boxes/webm/segments.js +64 -30
- package/dist/boxes/webm/traversal.d.ts +1 -0
- package/dist/boxes/webm/traversal.js +12 -1
- package/dist/buffer-iterator.d.ts +10 -6
- package/dist/buffer-iterator.js +92 -9
- package/dist/from-fetch.js +13 -3
- package/dist/from-input-type-file.d.ts +2 -0
- package/dist/from-input-type-file.js +37 -0
- package/dist/from-node.js +9 -2
- package/dist/from-web-file.js +6 -1
- package/dist/from-web.js +15 -6
- package/dist/get-codec.d.ts +4 -0
- package/dist/get-codec.js +22 -0
- package/dist/get-sample-positions.js +1 -1
- package/dist/has-all-info.js +1 -1
- package/dist/options.d.ts +3 -2
- package/dist/parse-media.js +13 -9
- package/dist/parse-video.js +16 -0
- package/dist/parser-state.d.ts +8 -9
- package/dist/parser-state.js +39 -19
- package/dist/reader.d.ts +1 -1
- package/dist/web-file.d.ts +2 -0
- package/dist/web-file.js +37 -0
- package/dist/webcodec-sample-types.d.ts +0 -1
- package/package.json +2 -2
- package/src/boxes/iso-base-media/mdat/mdat.ts +2 -2
- package/src/boxes/iso-base-media/moov/moov.ts +1 -0
- package/src/boxes/iso-base-media/process-box.ts +70 -40
- package/src/boxes/iso-base-media/stsd/mebx.ts +3 -0
- package/src/boxes/iso-base-media/stsd/samples.ts +3 -0
- package/src/boxes/iso-base-media/stsd/stco.ts +5 -3
- package/src/boxes/iso-base-media/trak/trak.ts +1 -0
- package/src/boxes/webm/ebml.ts +78 -0
- package/src/boxes/webm/make-header.ts +138 -0
- package/src/boxes/webm/parse-ebml.ts +93 -0
- package/src/boxes/webm/parse-webm-header.ts +8 -12
- package/src/boxes/webm/segments/all-segments.ts +226 -0
- package/src/boxes/webm/segments/block-simple-block-flags.ts +52 -0
- package/src/boxes/webm/segments/seek-position.ts +1 -1
- package/src/boxes/webm/segments/seek.ts +12 -2
- package/src/boxes/webm/segments/timestamp-scale.ts +1 -1
- package/src/boxes/webm/segments/track-entry.ts +125 -41
- package/src/boxes/webm/segments.ts +107 -40
- package/src/boxes/webm/traversal.ts +13 -0
- package/src/buffer-iterator.ts +110 -10
- package/src/from-fetch.ts +22 -3
- package/src/from-node.ts +18 -4
- package/src/from-web-file.ts +11 -1
- package/src/get-sample-positions.ts +1 -1
- package/src/has-all-info.ts +1 -1
- package/src/options.ts +3 -2
- package/src/parse-media.ts +14 -8
- package/src/parse-video.ts +17 -0
- package/src/parser-state.ts +52 -25
- package/src/reader.ts +1 -0
- package/src/test/create-matroska.test.ts +48 -0
- package/src/test/matroska.test.ts +144 -127
- package/src/test/parse-stco.test.ts +2 -0
- package/src/test/stream-local.test.ts +70 -14
- package/src/test/stream-remote.test.ts +23 -19
- package/src/test/stsd.test.ts +2 -0
- package/src/webcodec-sample-types.ts +0 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/boxes/iso-base-media/ftype.d.ts +0 -9
- package/dist/boxes/iso-base-media/ftype.js +0 -31
- package/dist/get-video-metadata.d.ts +0 -2
- package/dist/get-video-metadata.js +0 -44
- package/dist/read-and-increment-offset.d.ts +0 -28
- package/dist/read-and-increment-offset.js +0 -177
- package/dist/understand-vorbis.d.ts +0 -1
- package/dist/understand-vorbis.js +0 -12
- package/src/boxes/webm/segments/unknown.ts +0 -19
- /package/dist/{boxes/webm/bitstream/av1/frame.d.ts → get-samples.d.ts} +0 -0
- /package/dist/{boxes/webm/bitstream/av1/frame.js → get-samples.js} +0 -0
- /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.d.ts → sample-aspect-ratio.d.ts} +0 -0
- /package/dist/{boxes/webm/bitstream/h264/get-h264-descriptor.js → sample-aspect-ratio.js} +0 -0
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type {BufferIterator} from '../../../buffer-iterator';
|
|
2
2
|
import type {ParserContext} from '../../../parser-context';
|
|
3
|
+
import type {VideoSample} from '../../../webcodec-sample-types';
|
|
3
4
|
import type {MatroskaSegment} from '../segments';
|
|
5
|
+
import type {matroskaElements} from './all-segments';
|
|
6
|
+
import {parseBlockFlags} from './block-simple-block-flags';
|
|
4
7
|
import {expectChildren} from './parse-children';
|
|
5
8
|
|
|
6
9
|
export type TrackEntrySegment = {
|
|
@@ -106,6 +109,11 @@ export type CodecSegment = {
|
|
|
106
109
|
codec: string;
|
|
107
110
|
};
|
|
108
111
|
|
|
112
|
+
export type TrackInfo = {
|
|
113
|
+
codec: string;
|
|
114
|
+
trackTimescale: number | null;
|
|
115
|
+
};
|
|
116
|
+
|
|
109
117
|
export const parseCodecSegment = (
|
|
110
118
|
iterator: BufferIterator,
|
|
111
119
|
length: number,
|
|
@@ -192,7 +200,7 @@ export const parseDefaultDurationSegment = (
|
|
|
192
200
|
iterator: BufferIterator,
|
|
193
201
|
length: number,
|
|
194
202
|
): DefaultDurationSegment => {
|
|
195
|
-
const defaultDuration = iterator.
|
|
203
|
+
const defaultDuration = iterator.getUint(length);
|
|
196
204
|
|
|
197
205
|
return {
|
|
198
206
|
type: 'default-duration-segment',
|
|
@@ -566,80 +574,110 @@ export const parseTimestampSegment = (
|
|
|
566
574
|
iterator: BufferIterator,
|
|
567
575
|
length: number,
|
|
568
576
|
): TimestampSegment => {
|
|
569
|
-
if (length > 2) {
|
|
570
|
-
throw new Error('Expected timestamp segment to be 1 byte or 2 bytes');
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const value = length === 2 ? iterator.getUint16() : iterator.getUint8();
|
|
574
|
-
|
|
575
577
|
return {
|
|
576
578
|
type: 'timestamp-segment',
|
|
577
|
-
timestamp:
|
|
579
|
+
timestamp: iterator.getUint(length),
|
|
578
580
|
};
|
|
579
581
|
};
|
|
580
582
|
|
|
581
|
-
export type
|
|
582
|
-
type: 'simple-block-segment';
|
|
583
|
+
export type SimpleBlockOrBlockSegment = {
|
|
584
|
+
type: 'simple-block-or-block-segment';
|
|
583
585
|
length: number;
|
|
584
586
|
trackNumber: number;
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
lacing: [number, number];
|
|
587
|
+
timecodeInMicroseconds: number;
|
|
588
|
+
keyframe: boolean | null;
|
|
589
|
+
lacing: number;
|
|
589
590
|
invisible: boolean;
|
|
590
|
-
|
|
591
|
+
videoSample: Omit<VideoSample, 'type'> | null;
|
|
591
592
|
};
|
|
592
593
|
|
|
593
594
|
export type GetTracks = () => TrackEntrySegment[];
|
|
594
595
|
|
|
595
|
-
export const
|
|
596
|
+
export const parseSimpleBlockOrBlockSegment = async ({
|
|
596
597
|
iterator,
|
|
597
598
|
length,
|
|
598
599
|
parserContext,
|
|
600
|
+
type,
|
|
599
601
|
}: {
|
|
600
602
|
iterator: BufferIterator;
|
|
601
603
|
length: number;
|
|
602
604
|
parserContext: ParserContext;
|
|
603
|
-
|
|
605
|
+
type:
|
|
606
|
+
| (typeof matroskaElements)['Block']
|
|
607
|
+
| (typeof matroskaElements)['SimpleBlock'];
|
|
608
|
+
}): Promise<SimpleBlockOrBlockSegment> => {
|
|
604
609
|
const start = iterator.counter.getOffset();
|
|
605
610
|
const trackNumber = iterator.getVint();
|
|
606
|
-
|
|
607
|
-
|
|
611
|
+
if (trackNumber === null) {
|
|
612
|
+
throw new Error('Not enough data to get track number, should not happen');
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const timecodeRelativeToCluster = iterator.getUint16();
|
|
616
|
+
|
|
617
|
+
const {invisible, lacing, keyframe} = parseBlockFlags(iterator, type);
|
|
618
|
+
|
|
619
|
+
const {codec, trackTimescale} =
|
|
620
|
+
parserContext.parserState.getTrackInfoByNumber(trackNumber);
|
|
608
621
|
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
622
|
+
const clusterOffset =
|
|
623
|
+
parserContext.parserState.getTimestampOffsetForByteOffset(
|
|
624
|
+
iterator.counter.getOffset(),
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
const timescale = parserContext.parserState.getTimescale();
|
|
628
|
+
|
|
629
|
+
if (clusterOffset === undefined) {
|
|
630
|
+
throw new Error(
|
|
631
|
+
'Could not find offset for byte offset ' + iterator.counter.getOffset(),
|
|
632
|
+
);
|
|
633
|
+
}
|
|
613
634
|
|
|
614
|
-
|
|
635
|
+
// https://github.com/hubblec4/Matroska-Chapters-Specs/blob/master/notes.md/#timestampscale
|
|
636
|
+
// The TimestampScale Element is used to calculate the Raw Timestamp of a Block. The timestamp is obtained by adding the Block's timestamp to the Cluster's Timestamp Element, and then multiplying that result by the TimestampScale. The result will be the Block's Raw Timestamp in nanoseconds.
|
|
637
|
+
const timecodeInNanoSeconds =
|
|
638
|
+
(timecodeRelativeToCluster + clusterOffset) *
|
|
639
|
+
timescale *
|
|
640
|
+
(trackTimescale ?? 1);
|
|
641
|
+
|
|
642
|
+
// Timecode should be in microseconds
|
|
643
|
+
const timecodeInMicroseconds = timecodeInNanoSeconds / 1000;
|
|
615
644
|
|
|
616
645
|
if (!codec) {
|
|
617
646
|
throw new Error('Could not find codec for track ' + trackNumber);
|
|
618
647
|
}
|
|
619
648
|
|
|
620
|
-
const
|
|
649
|
+
const remainingNow = length - (iterator.counter.getOffset() - start);
|
|
621
650
|
|
|
622
|
-
|
|
623
|
-
const remainingNow = length - (iterator.counter.getOffset() - start);
|
|
651
|
+
let videoSample: Omit<VideoSample, 'type'> | null = null;
|
|
624
652
|
|
|
625
|
-
|
|
653
|
+
if (codec.startsWith('V_')) {
|
|
654
|
+
const partialVideoSample: Omit<VideoSample, 'type'> = {
|
|
626
655
|
data: iterator.getSlice(remainingNow),
|
|
627
656
|
cts: null,
|
|
628
657
|
dts: null,
|
|
629
658
|
duration: undefined,
|
|
630
|
-
type: keyframe ? 'key' : 'delta',
|
|
631
659
|
trackId: trackNumber,
|
|
632
|
-
timestamp:
|
|
633
|
-
}
|
|
660
|
+
timestamp: timecodeInMicroseconds,
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
if (keyframe === null) {
|
|
664
|
+
// If we don't know if this is a keyframe, we know after we emit the BlockGroup
|
|
665
|
+
videoSample = partialVideoSample;
|
|
666
|
+
} else {
|
|
667
|
+
const sample: VideoSample = {
|
|
668
|
+
...partialVideoSample,
|
|
669
|
+
type: keyframe ? 'key' : 'delta',
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
await parserContext.parserState.onVideoSample(trackNumber, sample);
|
|
673
|
+
}
|
|
634
674
|
}
|
|
635
675
|
|
|
636
|
-
if (codec.
|
|
637
|
-
const vorbisRemaining = length - (iterator.counter.getOffset() - start);
|
|
676
|
+
if (codec.startsWith('A_')) {
|
|
638
677
|
await parserContext.parserState.onAudioSample(trackNumber, {
|
|
639
|
-
data: iterator.getSlice(
|
|
640
|
-
offset: timecode,
|
|
678
|
+
data: iterator.getSlice(remainingNow),
|
|
641
679
|
trackId: trackNumber,
|
|
642
|
-
timestamp:
|
|
680
|
+
timestamp: timecodeInMicroseconds,
|
|
643
681
|
type: 'key',
|
|
644
682
|
});
|
|
645
683
|
}
|
|
@@ -650,15 +688,14 @@ export const parseSimpleBlockSegment = async ({
|
|
|
650
688
|
}
|
|
651
689
|
|
|
652
690
|
return {
|
|
653
|
-
type: 'simple-block-segment',
|
|
691
|
+
type: 'simple-block-or-block-segment',
|
|
654
692
|
length,
|
|
655
693
|
trackNumber,
|
|
656
|
-
|
|
657
|
-
headerFlags,
|
|
694
|
+
timecodeInMicroseconds,
|
|
658
695
|
keyframe,
|
|
659
|
-
lacing
|
|
696
|
+
lacing,
|
|
660
697
|
invisible,
|
|
661
|
-
|
|
698
|
+
videoSample,
|
|
662
699
|
};
|
|
663
700
|
};
|
|
664
701
|
|
|
@@ -705,6 +742,53 @@ export const parseBlockGroupSegment = async (
|
|
|
705
742
|
};
|
|
706
743
|
};
|
|
707
744
|
|
|
745
|
+
export type ReferenceBlockSegment = {
|
|
746
|
+
type: 'reference-block-segment';
|
|
747
|
+
referenceBlock: number;
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
export const parseReferenceBlockSegment = (
|
|
751
|
+
iterator: BufferIterator,
|
|
752
|
+
length: number,
|
|
753
|
+
): ReferenceBlockSegment => {
|
|
754
|
+
if (length > 4) {
|
|
755
|
+
throw new Error(
|
|
756
|
+
`Expected reference block segment to be 4 bytes, but got ${length}`,
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const referenceBlock =
|
|
761
|
+
length === 4
|
|
762
|
+
? iterator.getUint32()
|
|
763
|
+
: length === 3
|
|
764
|
+
? iterator.getUint24()
|
|
765
|
+
: length === 2
|
|
766
|
+
? iterator.getUint16()
|
|
767
|
+
: iterator.getUint8();
|
|
768
|
+
|
|
769
|
+
return {
|
|
770
|
+
type: 'reference-block-segment',
|
|
771
|
+
referenceBlock,
|
|
772
|
+
};
|
|
773
|
+
};
|
|
774
|
+
|
|
775
|
+
export type BlockAdditionsSegment = {
|
|
776
|
+
type: 'block-additions-segment';
|
|
777
|
+
blockAdditions: Uint8Array;
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
export const parseBlockAdditionsSegment = (
|
|
781
|
+
iterator: BufferIterator,
|
|
782
|
+
length: number,
|
|
783
|
+
): BlockAdditionsSegment => {
|
|
784
|
+
const blockAdditions = iterator.getSlice(length);
|
|
785
|
+
|
|
786
|
+
return {
|
|
787
|
+
type: 'block-additions-segment',
|
|
788
|
+
blockAdditions,
|
|
789
|
+
};
|
|
790
|
+
};
|
|
791
|
+
|
|
708
792
|
export type BlockElement = {
|
|
709
793
|
type: 'block-element-segment';
|
|
710
794
|
length: number;
|
|
@@ -2,7 +2,10 @@ import {registerTrack} from '../../add-new-matroska-tracks';
|
|
|
2
2
|
import type {BufferIterator} from '../../buffer-iterator';
|
|
3
3
|
import type {ParseResult} from '../../parse-result';
|
|
4
4
|
import type {ParserContext} from '../../parser-context';
|
|
5
|
+
import type {VideoSample} from '../../webcodec-sample-types';
|
|
5
6
|
import {getTrack} from './get-track';
|
|
7
|
+
import {parseEbml} from './parse-ebml';
|
|
8
|
+
import type {PossibleEbml} from './segments/all-segments';
|
|
6
9
|
import {matroskaElements} from './segments/all-segments';
|
|
7
10
|
import type {DurationSegment} from './segments/duration';
|
|
8
11
|
import {parseDurationSegment} from './segments/duration';
|
|
@@ -29,6 +32,7 @@ import type {
|
|
|
29
32
|
AlphaModeSegment,
|
|
30
33
|
AudioSegment,
|
|
31
34
|
BitDepthSegment,
|
|
35
|
+
BlockAdditionsSegment,
|
|
32
36
|
BlockElement,
|
|
33
37
|
BlockGroupSegment,
|
|
34
38
|
ChannelsSegment,
|
|
@@ -46,9 +50,10 @@ import type {
|
|
|
46
50
|
InterlacedSegment,
|
|
47
51
|
LanguageSegment,
|
|
48
52
|
MaxBlockAdditionId,
|
|
53
|
+
ReferenceBlockSegment,
|
|
49
54
|
SamplingFrequencySegment,
|
|
50
55
|
SegmentUUIDSegment,
|
|
51
|
-
|
|
56
|
+
SimpleBlockOrBlockSegment,
|
|
52
57
|
TagSegment,
|
|
53
58
|
TagsSegment,
|
|
54
59
|
TimestampSegment,
|
|
@@ -64,6 +69,7 @@ import {
|
|
|
64
69
|
parseAlphaModeSegment,
|
|
65
70
|
parseAudioSegment,
|
|
66
71
|
parseBitDepthSegment,
|
|
72
|
+
parseBlockAdditionsSegment,
|
|
67
73
|
parseBlockElementSegment,
|
|
68
74
|
parseBlockGroupSegment,
|
|
69
75
|
parseChannelsSegment,
|
|
@@ -80,9 +86,10 @@ import {
|
|
|
80
86
|
parseInterlacedSegment,
|
|
81
87
|
parseLanguageSegment,
|
|
82
88
|
parseMaxBlockAdditionId,
|
|
89
|
+
parseReferenceBlockSegment,
|
|
83
90
|
parseSamplingFrequencySegment,
|
|
84
91
|
parseSegmentUUIDSegment,
|
|
85
|
-
|
|
92
|
+
parseSimpleBlockOrBlockSegment,
|
|
86
93
|
parseTagSegment,
|
|
87
94
|
parseTagsSegment,
|
|
88
95
|
parseTimestampSegment,
|
|
@@ -96,8 +103,6 @@ import {
|
|
|
96
103
|
} from './segments/track-entry';
|
|
97
104
|
import type {TracksSegment} from './segments/tracks';
|
|
98
105
|
import {parseTracksSegment} from './segments/tracks';
|
|
99
|
-
import type {UnknownSegment} from './segments/unknown';
|
|
100
|
-
import {parseUnknownSegment} from './segments/unknown';
|
|
101
106
|
import type {VoidSegment} from './segments/void';
|
|
102
107
|
import {parseVoidSegment} from './segments/void';
|
|
103
108
|
import type {WritingAppSegment} from './segments/writing';
|
|
@@ -105,7 +110,6 @@ import {parseWritingSegment} from './segments/writing';
|
|
|
105
110
|
|
|
106
111
|
export type MatroskaSegment =
|
|
107
112
|
| MainSegment
|
|
108
|
-
| UnknownSegment
|
|
109
113
|
| SeekHeadSegment
|
|
110
114
|
| SeekSegment
|
|
111
115
|
| SeekPositionSegment
|
|
@@ -142,14 +146,17 @@ export type MatroskaSegment =
|
|
|
142
146
|
| TagSegment
|
|
143
147
|
| ClusterSegment
|
|
144
148
|
| TimestampSegment
|
|
145
|
-
|
|
|
149
|
+
| SimpleBlockOrBlockSegment
|
|
146
150
|
| BlockGroupSegment
|
|
147
151
|
| BlockElement
|
|
148
152
|
| SeekIdSegment
|
|
149
153
|
| AudioSegment
|
|
150
154
|
| SamplingFrequencySegment
|
|
151
155
|
| ChannelsSegment
|
|
152
|
-
| BitDepthSegment
|
|
156
|
+
| BitDepthSegment
|
|
157
|
+
| ReferenceBlockSegment
|
|
158
|
+
| BlockAdditionsSegment
|
|
159
|
+
| PossibleEbml;
|
|
153
160
|
|
|
154
161
|
export type OnTrackEntrySegment = (trackEntry: TrackEntrySegment) => void;
|
|
155
162
|
|
|
@@ -158,39 +165,24 @@ const parseSegment = async ({
|
|
|
158
165
|
iterator,
|
|
159
166
|
length,
|
|
160
167
|
parserContext,
|
|
168
|
+
headerReadSoFar,
|
|
161
169
|
}: {
|
|
162
170
|
segmentId: string;
|
|
163
171
|
iterator: BufferIterator;
|
|
164
172
|
length: number;
|
|
165
173
|
parserContext: ParserContext;
|
|
174
|
+
headerReadSoFar: number;
|
|
166
175
|
}): Promise<Promise<MatroskaSegment> | MatroskaSegment> => {
|
|
167
176
|
if (length === 0) {
|
|
168
177
|
throw new Error(`Expected length of ${segmentId} to be greater than 0`);
|
|
169
178
|
}
|
|
170
179
|
|
|
171
|
-
if (segmentId === '0x') {
|
|
172
|
-
return {
|
|
173
|
-
type: 'unknown-segment',
|
|
174
|
-
id: segmentId,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Log this to debug
|
|
179
|
-
/*
|
|
180
|
-
console.log(
|
|
181
|
-
'segmentId',
|
|
182
|
-
segmentId,
|
|
183
|
-
getSegmentName(segmentId),
|
|
184
|
-
iterator.counter.getOffset(),
|
|
185
|
-
);
|
|
186
|
-
*/
|
|
187
|
-
|
|
188
180
|
if (segmentId === '0x114d9b74') {
|
|
189
181
|
return parseSeekHeadSegment(iterator, length, parserContext);
|
|
190
182
|
}
|
|
191
183
|
|
|
192
184
|
if (segmentId === '0x53ab') {
|
|
193
|
-
return parseSeekIdSegment(iterator);
|
|
185
|
+
return parseSeekIdSegment(iterator, length);
|
|
194
186
|
}
|
|
195
187
|
|
|
196
188
|
if (segmentId === '0x4dbb') {
|
|
@@ -360,42 +352,92 @@ const parseSegment = async ({
|
|
|
360
352
|
return parseBitDepthSegment(iterator, length);
|
|
361
353
|
}
|
|
362
354
|
|
|
363
|
-
if (segmentId ===
|
|
364
|
-
|
|
355
|
+
if (segmentId === matroskaElements.Timestamp) {
|
|
356
|
+
const offset = iterator.counter.getOffset();
|
|
357
|
+
const timestampSegment = parseTimestampSegment(iterator, length);
|
|
358
|
+
|
|
359
|
+
parserContext.parserState.setTimestampOffset(
|
|
360
|
+
offset,
|
|
361
|
+
timestampSegment.timestamp,
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
return timestampSegment;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
-
if (
|
|
368
|
-
|
|
367
|
+
if (
|
|
368
|
+
segmentId === matroskaElements.SimpleBlock ||
|
|
369
|
+
segmentId === matroskaElements.Block
|
|
370
|
+
) {
|
|
371
|
+
return parseSimpleBlockOrBlockSegment({
|
|
369
372
|
iterator,
|
|
370
373
|
length,
|
|
371
374
|
parserContext,
|
|
375
|
+
type: segmentId,
|
|
372
376
|
});
|
|
373
377
|
}
|
|
374
378
|
|
|
379
|
+
if (segmentId === matroskaElements.ReferenceBlock) {
|
|
380
|
+
return parseReferenceBlockSegment(iterator, length);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (segmentId === matroskaElements.BlockAdditions) {
|
|
384
|
+
return parseBlockAdditionsSegment(iterator, length);
|
|
385
|
+
}
|
|
386
|
+
|
|
375
387
|
if (segmentId === '0xa0') {
|
|
376
|
-
|
|
388
|
+
const blockGroup = await parseBlockGroupSegment(
|
|
389
|
+
iterator,
|
|
390
|
+
length,
|
|
391
|
+
parserContext,
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
// Blocks don't have information about keyframes.
|
|
395
|
+
// https://ffmpeg.org/pipermail/ffmpeg-devel/2015-June/173825.html
|
|
396
|
+
// "For Blocks, keyframes is
|
|
397
|
+
// inferred by the absence of ReferenceBlock element (as done by matroskadec).""
|
|
398
|
+
|
|
399
|
+
const block = blockGroup.children.find(
|
|
400
|
+
(c) => c.type === 'simple-block-or-block-segment',
|
|
401
|
+
);
|
|
402
|
+
if (!block || block.type !== 'simple-block-or-block-segment') {
|
|
403
|
+
throw new Error('Expected block segment');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const hasReferenceBlock = blockGroup.children.find(
|
|
407
|
+
(c) => c.type === 'reference-block-segment',
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
const partialVideoSample = block.videoSample;
|
|
411
|
+
|
|
412
|
+
if (partialVideoSample) {
|
|
413
|
+
const completeFrame: VideoSample = {
|
|
414
|
+
...partialVideoSample,
|
|
415
|
+
type: hasReferenceBlock ? 'delta' : 'key',
|
|
416
|
+
};
|
|
417
|
+
await parserContext.parserState.onVideoSample(
|
|
418
|
+
partialVideoSample.trackId,
|
|
419
|
+
completeFrame,
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return blockGroup;
|
|
377
424
|
}
|
|
378
425
|
|
|
379
426
|
if (segmentId === '0xa1') {
|
|
380
427
|
return parseBlockElementSegment(iterator, length);
|
|
381
428
|
}
|
|
382
429
|
|
|
383
|
-
|
|
384
|
-
const toDiscard = Math.min(
|
|
385
|
-
bytesRemaining,
|
|
386
|
-
length > 0 ? length : bytesRemaining,
|
|
387
|
-
);
|
|
430
|
+
iterator.counter.decrement(headerReadSoFar);
|
|
388
431
|
|
|
389
|
-
|
|
390
|
-
return child;
|
|
432
|
+
return parseEbml(iterator);
|
|
391
433
|
};
|
|
392
434
|
|
|
393
435
|
export const expectSegment = async (
|
|
394
436
|
iterator: BufferIterator,
|
|
395
437
|
parserContext: ParserContext,
|
|
396
438
|
): Promise<ParseResult> => {
|
|
397
|
-
const
|
|
398
|
-
if (
|
|
439
|
+
const offset = iterator.counter.getOffset();
|
|
440
|
+
if (iterator.bytesRemaining() === 0) {
|
|
399
441
|
return {
|
|
400
442
|
status: 'incomplete',
|
|
401
443
|
segments: [],
|
|
@@ -406,9 +448,33 @@ export const expectSegment = async (
|
|
|
406
448
|
};
|
|
407
449
|
}
|
|
408
450
|
|
|
409
|
-
const offset = iterator.counter.getOffset();
|
|
410
451
|
const segmentId = iterator.getMatroskaSegmentId();
|
|
452
|
+
|
|
453
|
+
if (segmentId === null) {
|
|
454
|
+
iterator.counter.decrement(iterator.counter.getOffset() - offset);
|
|
455
|
+
return {
|
|
456
|
+
status: 'incomplete',
|
|
457
|
+
segments: [],
|
|
458
|
+
continueParsing: () => {
|
|
459
|
+
return Promise.resolve(expectSegment(iterator, parserContext));
|
|
460
|
+
},
|
|
461
|
+
skipTo: null,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
|
|
411
465
|
const length = iterator.getVint();
|
|
466
|
+
if (length === null) {
|
|
467
|
+
iterator.counter.decrement(iterator.counter.getOffset() - offset);
|
|
468
|
+
return {
|
|
469
|
+
status: 'incomplete',
|
|
470
|
+
segments: [],
|
|
471
|
+
continueParsing: () => {
|
|
472
|
+
return Promise.resolve(expectSegment(iterator, parserContext));
|
|
473
|
+
},
|
|
474
|
+
skipTo: null,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
412
478
|
const bytesRemainingNow =
|
|
413
479
|
iterator.byteLength() - iterator.counter.getOffset();
|
|
414
480
|
|
|
@@ -463,6 +529,7 @@ export const expectSegment = async (
|
|
|
463
529
|
iterator,
|
|
464
530
|
length,
|
|
465
531
|
parserContext,
|
|
532
|
+
headerReadSoFar: iterator.counter.getOffset() - offset,
|
|
466
533
|
});
|
|
467
534
|
|
|
468
535
|
return {
|
|
@@ -24,6 +24,19 @@ export const getTrackCodec = (track: TrackEntrySegment) => {
|
|
|
24
24
|
return child ?? null;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
export const getTrackTimestampScale = (track: TrackEntrySegment) => {
|
|
28
|
+
const child = track.children.find((b) => b.type === 'TrackTimestampScale');
|
|
29
|
+
if (!child) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (child.type !== 'TrackTimestampScale') {
|
|
34
|
+
throw new Error('Expected TrackTimestampScale');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return child.value;
|
|
38
|
+
};
|
|
39
|
+
|
|
27
40
|
export const getTrackByNumber = (tracks: TrackEntrySegment[], id: number) => {
|
|
28
41
|
return tracks.find((track) => {
|
|
29
42
|
const trackNumber = getTrackNumber(track);
|