Skip to content

Commit 478ffbd

Browse files
committed
Fix regression #44
1 parent 63cae09 commit 478ffbd

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

packages/decode-aac/decode-aac.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,18 @@ function parseBoxes(buf, start, end, cb) {
360360
} else if (size < 8) {
361361
break
362362
}
363-
if (off + size > end) size = end - off
364363

365364
let bodyOff = off + 8
365+
let truncated = off + size > end
366366

367-
if (type === 'stsd') parseSampleDesc(buf, bodyOff, size - 8, cb)
367+
// mdat carries raw frames — partial is fine; callers honour availability
368+
if (type === 'mdat') {
369+
cb(type, buf.subarray(bodyOff, truncated ? end : off + size), bodyOff)
370+
if (truncated) break
371+
}
372+
// any other box must be fully present before parsing — partial tables yield garbage
373+
else if (truncated) break
374+
else if (type === 'stsd') parseSampleDesc(buf, bodyOff, size - 8, cb)
368375
else if (CONTAINERS.has(type)) parseBoxes(buf, bodyOff + (type === 'meta' ? 4 : 0), off + size, cb)
369376
else cb(type, buf.subarray(bodyOff, off + size), bodyOff)
370377

@@ -432,8 +439,10 @@ function extractFrames(buf, stsz, stco, stsc) {
432439
}
433440
let off = stco[ci]
434441
for (let s = 0; s < spc && si < stsz.length; s++) {
435-
let sz = stsz[si++]
436-
if (off + sz <= buf.length) frames.push(buf.subarray(off, off + sz))
442+
let sz = stsz[si]
443+
if (off + sz > buf.length) return frames // sequential: first missing → rest missing
444+
frames.push(buf.subarray(off, off + sz))
445+
si++
437446
off += sz
438447
}
439448
}

packages/decode-aac/test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,34 @@ console.log('lifecycle')
9595
d.free()
9696
}
9797

98+
// ---- M4A streaming (moov split across chunks, non-faststart layout) ----
99+
// Regression: github #44 — init fired on partial moov → garbage stsz/stco → 0 frames.
100+
console.log('M4A streaming')
101+
{
102+
let ref = await decode(m4a)
103+
104+
for (let chunkSize of [16384, 4096, 1024, 256]) {
105+
let dec = await decoder()
106+
let chunks = []
107+
for (let off = 0; off < m4a.length; off += chunkSize) {
108+
let r = dec.decode(m4a.subarray(off, Math.min(off + chunkSize, m4a.length)))
109+
if (r.channelData.length) chunks.push(r.channelData[0])
110+
}
111+
let f = dec.flush()
112+
if (f.channelData.length) chunks.push(f.channelData[0])
113+
dec.free()
114+
115+
let total = chunks.reduce((s, c) => s + c.length, 0)
116+
ok(total === ref.channelData[0].length, 'chunk=' + chunkSize + ' count matches (' + total + ')')
117+
118+
let stream = new Float32Array(total), pos = 0
119+
for (let c of chunks) { stream.set(c, pos); pos += c.length }
120+
let maxDiff = 0
121+
for (let i = 0; i < total; i++) maxDiff = Math.max(maxDiff, Math.abs(stream[i] - ref.channelData[0][i]))
122+
ok(maxDiff === 0, 'chunk=' + chunkSize + ' content identical')
123+
}
124+
}
125+
98126
// ---- ADTS streaming (partial frame buffering) ----
99127
console.log('ADTS streaming')
100128
{

0 commit comments

Comments
 (0)