'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); }); });