Skip to content

Commit

Permalink
Merge pull request #4679 from remotion-dev/4668-media-parser-ebml-id-…
Browse files Browse the repository at this point in the history
…0x536e-is-not-supported
  • Loading branch information
JonnyBurger authored Dec 29, 2024
2 parents e3983b7 + 1e780af commit bf75987
Show file tree
Hide file tree
Showing 22 changed files with 61 additions and 41 deletions.
10 changes: 4 additions & 6 deletions packages/convert/app/components/Probe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,10 @@ export const Probe: React.FC<{
)}
</CardTitle>
{error ? (
<CardDescription className="!mt-0">
<p className="text-red-500">
Failed to parse media:
<br />
{error.message}
</p>
<CardDescription className="!mt-0 text-red-500">
Failed to parse media:
<br />
{error.message}
</CardDescription>
) : null}
<CardDescription
Expand Down
4 changes: 2 additions & 2 deletions packages/media-parser/src/boxes/iso-base-media/ftyp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ export const parseFtyp = ({
size: number;
offset: number;
}): FtypBox => {
const majorBrand = iterator.getByteString(4);
const majorBrand = iterator.getByteString(4, false);
const minorVersion = iterator.getFourByteNumber();

const types = (size - iterator.counter.getOffset()) / 4;
const compatibleBrands: string[] = [];
for (let i = 0; i < types; i++) {
compatibleBrands.push(iterator.getByteString(4).trim());
compatibleBrands.push(iterator.getByteString(4, false).trim());
}

const offsetAtEnd = iterator.counter.getOffset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const parseHdlr = ({
// predefined
iterator.discard(4);
// type
const hdlrType = iterator.getByteString(4);
const hdlrType = iterator.getByteString(4, false);
// component manufactor
iterator.discard(4);
// component flags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const parseFromWellKnownType = (
size: number,
): Value => {
if (wellKnownType === 1) {
const value = iterator.getByteString(size);
const value = iterator.getByteString(size, false);
return {type: 'text', value};
}

Expand Down
24 changes: 12 additions & 12 deletions packages/media-parser/src/boxes/iso-base-media/parse-icc-profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,28 @@ export const parseIccProfile = (data: Uint8Array): IccProfile => {
throw new Error('Invalid ICC profile size');
}

const preferredCMMType = iterator.getByteString(4);
const profileVersion = iterator.getByteString(4);
const profileDeviceClass = iterator.getByteString(4);
const colorSpace = iterator.getByteString(4);
const pcs = iterator.getByteString(4);
const preferredCMMType = iterator.getByteString(4, false);
const profileVersion = iterator.getByteString(4, false);
const profileDeviceClass = iterator.getByteString(4, false);
const colorSpace = iterator.getByteString(4, false);
const pcs = iterator.getByteString(4, false);
const dateTime = iterator.getSlice(12);
const signature = iterator.getByteString(4);
const signature = iterator.getByteString(4, false);
if (signature !== 'acsp') {
throw new Error('Invalid ICC profile signature');
}

const primaryPlatform = iterator.getByteString(4);
const primaryPlatform = iterator.getByteString(4, false);
const profileFlags = iterator.getUint32();
const deviceManufacturer = iterator.getByteString(4);
const deviceModel = iterator.getByteString(4);
const deviceManufacturer = iterator.getByteString(4, false);
const deviceModel = iterator.getByteString(4, false);
const deviceAttributes = iterator.getUint64();
const renderingIntent = iterator.getUint32();
const pcsIlluminant1 = iterator.getUint32();
const pcsIlluminant2 = iterator.getUint32();
const pcsIlluminant3 = iterator.getUint32();
const profileCreator = iterator.getByteString(4);
const profileId = iterator.getByteString(16);
const profileCreator = iterator.getByteString(4, false);
const profileId = iterator.getByteString(16, false);

// reserved
iterator.discard(28);
Expand All @@ -74,7 +74,7 @@ export const parseIccProfile = (data: Uint8Array): IccProfile => {
const entries: Entry[] = [];
for (let i = 0; i < tagCount; i++) {
const entry: Entry = {
tag: iterator.getByteString(4),
tag: iterator.getByteString(4, false),
offset: iterator.getUint32(),
size: iterator.getUint32(),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export const processBox = async ({
};
}

const boxType = iterator.getByteString(4);
const boxType = iterator.getByteString(4, false);

const boxSize = boxSizeRaw === 1 ? iterator.getEightByteNumber() : boxSizeRaw;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const parseColorParameterBox = ({
iterator: BufferIterator;
size: number;
}): ColorParameterBox => {
const byteString = iterator.getByteString(4);
const byteString = iterator.getByteString(4, false);

if (byteString === 'nclx') {
const primaries = iterator.getUint16();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const parseKeys = ({
// key_size
const keySize = iterator.getUint32();
const namespace = iterator.getAtom();
const value = iterator.getByteString(keySize - 8);
const value = iterator.getByteString(keySize - 8, false);
// data
const entry: KeysEntry = {
keySize,
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/expect-riff-box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const expectRiffBox = async ({
};
}

const ckId = iterator.getByteString(4);
const ckId = iterator.getByteString(4, false);
const ckSize = iterator.getUint32Le();

if (isMoviAtom(iterator, ckId)) {
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/is-movi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const isMoviAtom = (iterator: BufferIterator, ckId: string): boolean => {
return false;
}

const listType = iterator.getByteString(4);
const listType = iterator.getByteString(4, false);
iterator.counter.decrement(4);
return listType === 'movi';
};
4 changes: 2 additions & 2 deletions packages/media-parser/src/boxes/riff/parse-box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export const parseRiff = ({
state: ParserState;
fields: Options<ParseMediaFields>;
}): Promise<ParseResult> => {
const riff = iterator.getByteString(4);
const riff = iterator.getByteString(4, false);
if (riff !== 'RIFF') {
throw new Error('Not a RIFF file');
}
Expand All @@ -195,7 +195,7 @@ export const parseRiff = ({
}

const size = iterator.getUint32Le();
const fileType = iterator.getByteString(4);
const fileType = iterator.getByteString(4, false);
if (fileType !== 'WAVE' && fileType !== 'AVI') {
throw new Error(`File type ${fileType} not supported`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/parse-isft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const parseIsft = ({
size: number;
}): IsftBox => {
const {expectNoMoreBytes} = iterator.startBox(size);
const software = iterator.getByteString(size - 1);
const software = iterator.getByteString(size - 1, false);
const last = iterator.getUint8();
if (last !== 0) {
throw new Error(`Expected 0 byte, got ${last}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/parse-list-box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const parseListBox = async ({
state: ParserState;
}): Promise<RiffBox> => {
const counter = iterator.counter.getOffset();
const listType = iterator.getByteString(4);
const listType = iterator.getByteString(4, false);

if (listType === 'movi') {
throw new Error('should not be handled here');
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/parse-movi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export const parseMovi = async ({
};
}

const ckId = iterator.getByteString(4);
const ckId = iterator.getByteString(4, false);
const ckSize = iterator.getUint32Le();

if (
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/riff/parse-strf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const parseStrfVideo = ({
const height = iterator.getInt32Le();
const planes = iterator.getUint16Le();
const bitCount = iterator.getUint16Le();
const compression = iterator.getByteString(4);
const compression = iterator.getByteString(4, false);
const sizeImage = iterator.getUint32Le();
const xPelsPerMeter = iterator.getInt32Le();
const yPelsPerMeter = iterator.getInt32Le();
Expand Down
6 changes: 4 additions & 2 deletions packages/media-parser/src/boxes/riff/parse-strh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ export const parseStrh = ({
size: number;
}): RiffBox => {
const box = iterator.startBox(size);
const fccType = iterator.getByteString(4);
const fccType = iterator.getByteString(4, false);
if (fccType !== 'vids' && fccType !== 'auds') {
throw new Error('Expected AVI handler to be vids / auds');
}

const handler =
fccType === 'vids' ? iterator.getByteString(4) : iterator.getUint32Le();
fccType === 'vids'
? iterator.getByteString(4, false)
: iterator.getUint32Le();
if (typeof handler === 'string' && handler !== 'H264') {
throw new Error(
`Only H264 is supported as a stream type in .avi, got ${handler}`,
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/webm/description.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const getAudioDescription = (
// type
bufferIterator.getUint8();
// vorbis
const vorbis = bufferIterator.getByteString(6);
const vorbis = bufferIterator.getByteString(6, false);
if (vorbis !== 'vorbis') {
throw new Error('Error parsing vorbis codec private');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/boxes/webm/parse-ebml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const parseEbml = async (
}

if (hasInMap.type === 'string') {
const value = iterator.getByteString(size);
const value = iterator.getByteString(size, true);

return {
type: hasInMap.name,
Expand Down
12 changes: 12 additions & 0 deletions packages/media-parser/src/boxes/webm/segments/all-segments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ export const seekId = {
type: 'hex-string',
} as const satisfies Ebml;

export const _name = {
name: 'Name',
type: 'string',
} as const satisfies Ebml;

export const seekPosition = {
name: 'SeekPosition',
type: 'uint',
Expand Down Expand Up @@ -622,6 +627,11 @@ export const referenceBlock = {
type: 'uint',
} as const satisfies Ebml;

export const blockDurationSegment = {
name: 'BlockDuration',
type: 'uint',
} as const satisfies Ebml;

export const blockElement = {
name: 'Block',
type: 'uint8array',
Expand Down Expand Up @@ -838,6 +848,7 @@ export const ebmlMap = {
[matroskaElements.SeekHead]: seekHead,
[matroskaElements.Seek]: seek,
[matroskaElements.SeekID]: seekId,
[matroskaElements.Name]: _name,
[matroskaElements.SeekPosition]: seekPosition,
[matroskaElements.Crc32]: {
name: 'Crc32',
Expand Down Expand Up @@ -879,6 +890,7 @@ export const ebmlMap = {
[matroskaElements.Language]: language,
[matroskaElements.DefaultDuration]: defaultDuration,
[matroskaElements.CodecPrivate]: codecPrivate,
[matroskaElements.BlockDuration]: blockDurationSegment,
[matroskaElements.BlockAdditions]: blockAdditionsSegment,
[matroskaElements.MaxBlockAdditionID]: maxBlockAdditionIdSegment,
[matroskaElements.Audio]: audioSegment,
Expand Down
11 changes: 9 additions & 2 deletions packages/media-parser/src/buffer-iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,15 @@ export const getArrayBufferIterator = (
0,
);
},
getByteString(length: number): string {
const bytes = getSlice(length);
getByteString(length: number, trimTrailingZeroes: boolean): string {
let bytes = getSlice(length);
// This file has trailing zeroes throughout
// https://github.com/remotion-dev/remotion/issues/4668#issuecomment-2561904068
// eslint-disable-next-line no-unmodified-loop-condition
while (trimTrailingZeroes && bytes[bytes.length - 1] === 0) {
bytes = bytes.slice(0, -1);
}

return new TextDecoder().decode(bytes).trim();
},
getFloat64: () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/media-parser/src/test/create-matroska.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ test('Can we disassemble a Matroska file and assembled it again', async () => {
throw new Error('Not a webm file');
}

expect(stringifyWebm(parsed.boxes).byteLength).toEqual(
// +1 because two files has leading 0x0 boxes which we strip during parsing
expect(stringifyWebm(parsed.boxes).byteLength + 2).toEqual(
new Uint8Array(bytes).byteLength,
);
process.env.KEEP_SAMPLES = 'false';
Expand Down
2 changes: 1 addition & 1 deletion packages/media-parser/src/test/matroska.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ test('Should get duration of AV1 video', async () => {
{
minVintWidth: 1,
type: 'TagString',
value: '00:00:01.000000000\u0000\u0000',
value: '00:00:01.000000000',
},
],
},
Expand Down

0 comments on commit bf75987

Please sign in to comment.