Files
appRobotWebcam/test/fmp4Parser.test.js
2026-06-07 17:00:43 +02:00

74 lines
3.1 KiB
JavaScript

'use strict';
const { Fmp4Parser } = require('../src/fmp4Parser');
// Baut eine ISO-BMFF-Box: [4B size][4B type][payload]. size deckt size+type ab.
function box(type, payload = Buffer.alloc(0)) {
const head = Buffer.alloc(8);
head.writeUInt32BE(8 + payload.length, 0);
head.write(type, 4, 'latin1');
return Buffer.concat([head, payload]);
}
// Typischer FFmpeg-fMP4-Stream: ftyp moov | (moof mdat)…
function ftyp() { return box('ftyp', Buffer.from('isom')); }
function moov() { return box('moov', Buffer.from([1, 2, 3, 4])); }
function frag(n) { return Buffer.concat([box('moof', Buffer.from([n])), box('mdat', Buffer.from([n, n, n]))]); }
describe('Fmp4Parser', () => {
test('Init-Segment = ftyp + moov, einmalig', () => {
const inits = []; const segs = [];
const p = new Fmp4Parser({ onInit: (b) => inits.push(b), onSegment: (b) => segs.push(b) });
p.push(Buffer.concat([ftyp(), moov()]));
expect(inits).toHaveLength(1);
expect(inits[0].equals(Buffer.concat([ftyp(), moov()]))).toBe(true);
expect(segs).toHaveLength(0);
});
test('Fragmente = moof + mdat', () => {
const inits = []; const segs = [];
const p = new Fmp4Parser({ onInit: (b) => inits.push(b), onSegment: (b) => segs.push(b) });
p.push(Buffer.concat([ftyp(), moov(), frag(1), frag(2)]));
expect(inits).toHaveLength(1);
expect(segs).toHaveLength(2);
expect(segs[0].equals(frag(1))).toBe(true);
expect(segs[1].equals(frag(2))).toBe(true);
});
test('über beliebige Chunk-Grenzen gesplittet', () => {
const inits = []; const segs = [];
const p = new Fmp4Parser({ onInit: (b) => inits.push(b), onSegment: (b) => segs.push(b) });
const stream = Buffer.concat([ftyp(), moov(), frag(1), frag(2), frag(3)]);
for (let i = 0; i < stream.length; i += 3) p.push(stream.subarray(i, i + 3)); // 3-Byte-Häppchen
expect(inits).toHaveLength(1);
expect(segs).toHaveLength(3);
expect(segs[2].equals(frag(3))).toBe(true);
});
test('Byte-für-Byte (Extremfall)', () => {
const inits = []; const segs = [];
const p = new Fmp4Parser({ onInit: (b) => inits.push(b), onSegment: (b) => segs.push(b) });
const stream = Buffer.concat([ftyp(), moov(), frag(7)]);
for (const byte of stream) p.push(Buffer.from([byte]));
expect(inits).toHaveLength(1);
expect(segs).toHaveLength(1);
expect(segs[0].equals(frag(7))).toBe(true);
});
test('64-Bit largesize (size==1) wird verstanden', () => {
const inits = [];
const p = new Fmp4Parser({ onInit: (b) => inits.push(b) });
// ftyp normal, moov als 64-Bit-Box
const payload = Buffer.from([9, 9]);
const head = Buffer.alloc(16);
head.writeUInt32BE(1, 0); // size == 1 → largesize folgt
head.write('moov', 4, 'latin1');
head.writeUInt32BE(0, 8); // largesize high
head.writeUInt32BE(16 + payload.length, 12); // largesize low
const moov64 = Buffer.concat([head, payload]);
p.push(Buffer.concat([ftyp(), moov64]));
expect(inits).toHaveLength(1);
expect(inits[0].equals(Buffer.concat([ftyp(), moov64]))).toBe(true);
});
});