Skip to content

Commit 3f27137

Browse files
committed
M4AAudioFileDemuxer Draft
1 parent 8e5de20 commit 3f27137

File tree

4 files changed

+476
-40
lines changed

4 files changed

+476
-40
lines changed

src/AudioTools/AudioCodecs/M4AAudioDemuxer.h

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ class M4AAudioDemuxer {
243243
case Codec::AAC: {
244244
// Prepare ADTS header + AAC frame
245245
tmp.resize(size + 7);
246-
writeAdtsHeader(tmp.data(), aacProfile, sampleRateIdx, channelCfg, size);
246+
writeAdtsHeader(tmp.data(), aacProfile, sampleRateIdx, channelCfg,
247+
size);
247248
memcpy(tmp.data() + 7, buffer.data(), size);
248249
frame.data = tmp.data();
249250
frame.size = size + 7;
@@ -267,11 +268,11 @@ class M4AAudioDemuxer {
267268
Vector<stsz_sample_size_t> sampleSizes; ///< Table of sample sizes.
268269
Vector<uint32_t> chunkOffsets; ///< Table of chunk offsets.
269270
Vector<uint8_t> tmp;
270-
Codec codec = Codec::Unknown; ///< Current codec.
271-
FrameCallback callback = nullptr; ///< Frame callback.
272-
void* ref = nullptr; ///< Reference pointer for callback.
273-
size_t sampleIndex = 0; ///< Current sample index.
274-
SingleBuffer<uint8_t> buffer; ///< Buffer for accumulating sample data.
271+
Codec codec = Codec::Unknown; ///< Current codec.
272+
FrameCallback callback = nullptr; ///< Frame callback.
273+
void* ref = nullptr; ///< Reference pointer for callback.
274+
size_t sampleIndex = 0; ///< Current sample index.
275+
SingleBuffer<uint8_t> buffer; ///< Buffer for accumulating sample data.
275276
int aacProfile = 2, sampleRateIdx = 4, channelCfg = 2; ///< AAC config.
276277
uint32_t fixed_sample_size = 0; ///< Fixed sample size (if used).
277278
uint32_t fixed_sample_count = 0; ///< Fixed sample count (if used).
@@ -344,44 +345,13 @@ class M4AAudioDemuxer {
344345
/**
345346
* @brief Constructor. Sets up parser callbacks.
346347
*/
347-
M4AAudioDemuxer() {
348-
// global box data callback to get sizes
349-
parser.setReference(this);
350-
parser.setCallback(boxDataSetupCallback);
351-
352-
// incremental data callback
353-
parser.setIncrementalDataCallback(incrementalBoxDataCallback);
354-
355-
// Register a specific incremental data callback for mdat
356-
parser.setIncrementalDataCallback("mdat", [](MP4Parser::Box& box, const uint8_t* data, size_t len, bool is_final, void* ref) {
357-
auto* self = static_cast<M4AAudioDemuxer*>(ref);
358-
LOGI("*Box: %s, size: %u bytes", box.type, (unsigned)len);
359-
self->sampleExtractor.write(data, len, is_final);
360-
}, false);
361-
362-
// parsing for content of stsd (Sample Description Box)
363-
parser.setCallback("esds", [](MP4Parser::Box& box, void* ref) {
364-
static_cast<M4AAudioDemuxer*>(ref)->onEsds(box);
365-
});
366-
parser.setCallback("mp4a", [](MP4Parser::Box& box, void* ref) {
367-
static_cast<M4AAudioDemuxer*>(ref)->onMp4a(box);
368-
});
369-
parser.setCallback("alac", [](MP4Parser::Box& box, void* ref) {
370-
static_cast<M4AAudioDemuxer*>(ref)->onAlac(box);
371-
});
372-
parser.setCallback("mdat", [](MP4Parser::Box& box, void* ref) {
373-
M4AAudioDemuxer& self = *static_cast<M4AAudioDemuxer*>(ref);
374-
// mdat must not be buffered
375-
LOGI("Box: %s, size: %u bytes", box.type, (unsigned)box.size);
376-
self.sampleExtractor.setMaxSize(box.size);
377-
}, false); // 'false' prevents the generic callback from being executed
378-
}
348+
M4AAudioDemuxer() { setupParser(); }
379349

380350
/**
381351
* @brief Defines the callback that returns the audio frames.
382352
* @param cb Frame callback function.
383353
*/
384-
void setCallback(FrameCallback cb) {
354+
virtual void setCallback(FrameCallback cb) {
385355
sampleExtractor.setReference(ref);
386356
sampleExtractor.setCallback(cb);
387357
}
@@ -449,6 +419,49 @@ class M4AAudioDemuxer {
449419
bool stsz_processed = false; ///< Marks the stsz table as processed
450420
bool stco_processed = false; ///< Marks the stco table as processed
451421

422+
/**
423+
* @brief Setup all parser callbacks
424+
*/
425+
virtual void setupParser() {
426+
// global box data callback to get sizes
427+
parser.setReference(this);
428+
parser.setCallback(boxDataSetupCallback);
429+
430+
// incremental data callback
431+
parser.setIncrementalDataCallback(incrementalBoxDataCallback);
432+
433+
// Register a specific incremental data callback for mdat
434+
parser.setIncrementalDataCallback(
435+
"mdat",
436+
[](MP4Parser::Box& box, const uint8_t* data, size_t len, bool is_final,
437+
void* ref) {
438+
auto* self = static_cast<M4AAudioDemuxer*>(ref);
439+
LOGI("*Box: %s, size: %u bytes", box.type, (unsigned)len);
440+
self->sampleExtractor.write(data, len, is_final);
441+
},
442+
false);
443+
444+
// parsing for content of stsd (Sample Description Box)
445+
parser.setCallback("esds", [](MP4Parser::Box& box, void* ref) {
446+
static_cast<M4AAudioDemuxer*>(ref)->onEsds(box);
447+
});
448+
parser.setCallback("mp4a", [](MP4Parser::Box& box, void* ref) {
449+
static_cast<M4AAudioDemuxer*>(ref)->onMp4a(box);
450+
});
451+
parser.setCallback("alac", [](MP4Parser::Box& box, void* ref) {
452+
static_cast<M4AAudioDemuxer*>(ref)->onAlac(box);
453+
});
454+
parser.setCallback(
455+
"mdat",
456+
[](MP4Parser::Box& box, void* ref) {
457+
M4AAudioDemuxer& self = *static_cast<M4AAudioDemuxer*>(ref);
458+
// mdat must not be buffered
459+
LOGI("Box: %s, size: %u bytes", box.type, (unsigned)box.size);
460+
self.sampleExtractor.setMaxSize(box.size);
461+
},
462+
false); // 'false' prevents the generic callback from being executed
463+
}
464+
452465
/**
453466
* @brief Reads a 32-bit big-endian unsigned integer from a buffer.
454467
* @param p Pointer to buffer.
@@ -471,7 +484,7 @@ class M4AAudioDemuxer {
471484

472485
/**
473486
* @brief Callback for box data setup. If we contain data we add
474-
* it to the buffer. If there is no data we set up the buffer to
487+
* it to the buffer. If there is no data we set up the buffer to
475488
* receive incremental data.
476489
* @param box MP4 box.
477490
* @param ref Reference pointer.
@@ -506,6 +519,9 @@ class M4AAudioDemuxer {
506519
bool is_final, void* ref) {
507520
M4AAudioDemuxer& self = *static_cast<M4AAudioDemuxer*>(ref);
508521

522+
// mdat is now handled by its specific incremental callback, so remove logic
523+
// here
524+
509525
// only process relevant boxes
510526
if (!isRelevantBox(box.type)) return;
511527

0 commit comments

Comments
 (0)