@@ -153,7 +153,7 @@ class M4AAudioDemuxer {
153
153
154
154
/* *
155
155
* @brief Writes data to the extractor, extracting frames as sample sizes
156
- * are met.
156
+ * are met. Provides the data via the callback.
157
157
* @param data Pointer to input data.
158
158
* @param len Length of input data.
159
159
* @param is_final True if this is the last chunk of the box.
@@ -228,45 +228,27 @@ class M4AAudioDemuxer {
228
228
channelCfg = chCfg;
229
229
}
230
230
231
- protected:
232
- Vector<stsz_sample_size_t > sampleSizes; // /< Table of sample sizes.
233
- Vector<uint32_t > chunkOffsets; // /< Table of chunk offsets.
234
- Codec codec = Codec::Unknown; // /< Current codec.
235
- FrameCallback callback = nullptr ; // /< Frame callback.
236
- void * ref = nullptr ; // /< Reference pointer for callback.
237
- size_t sampleIndex = 0 ; // /< Current sample index.
238
- SingleBuffer<uint8_t > buffer; // /< Buffer for accumulating sample data.
239
- int aacProfile = 2 , sampleRateIdx = 4 , channelCfg = 2 ; // /< AAC config.
240
- uint32_t fixed_sample_size = 0 ; // /< Fixed sample size (if used).
241
- uint32_t fixed_sample_count = 0 ; // /< Fixed sample count (if used).
242
- size_t current_size = 0 ; // /< Current sample size.
243
- size_t box_size = 0 ; // /< Maximum size of the current sample.
244
- size_t box_pos = 0 ; // /< Current position in the box.
245
-
246
231
/* *
247
- * @brief Executes the callback for a completed frame .
232
+ * @brief Constructs a Frame object for the current codec .
248
233
* @param size Size of the frame.
234
+ * @param buffer SingleBuffer with data.
235
+ * @return Frame object.
249
236
*/
250
- void executeCallback (size_t size) {
251
- size_t frameSize = size;
237
+ Frame getFrame (size_t size, SingleBuffer<uint8_t >& buffer) {
252
238
Frame frame;
253
239
frame.codec = codec;
254
240
frame.data = buffer.data ();
255
- frame.size = frameSize ;
241
+ frame.size = size ;
256
242
switch (codec) {
257
243
case Codec::AAC: {
258
- uint8_t out[frameSize + 7 ];
259
- writeAdtsHeader (out, aacProfile, sampleRateIdx, channelCfg,
260
- frameSize );
261
- memcpy (out + 7 , buffer.data (), frameSize );
262
- frame.data = out ;
263
- frame.size = sizeof (out) ;
244
+ // Prepare ADTS header + AAC frame
245
+ tmp. resize (size + 7 );
246
+ writeAdtsHeader (tmp. data (), aacProfile, sampleRateIdx, channelCfg, size );
247
+ memcpy (tmp. data () + 7 , buffer.data (), size );
248
+ frame.data = tmp. data () ;
249
+ frame.size = size + 7 ;
264
250
frame.mime = " audio/aac" ;
265
- if (callback)
266
- callback (frame, ref);
267
- else
268
- LOGE (" No callback defined for audio frame extraction" );
269
- return ;
251
+ break ;
270
252
}
271
253
case Codec::ALAC:
272
254
frame.mime = " audio/alac" ;
@@ -278,6 +260,31 @@ class M4AAudioDemuxer {
278
260
frame.mime = nullptr ;
279
261
break ;
280
262
}
263
+ return frame;
264
+ }
265
+
266
+ protected:
267
+ Vector<stsz_sample_size_t > sampleSizes; // /< Table of sample sizes.
268
+ Vector<uint32_t > chunkOffsets; // /< Table of chunk offsets.
269
+ 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.
275
+ int aacProfile = 2 , sampleRateIdx = 4 , channelCfg = 2 ; // /< AAC config.
276
+ uint32_t fixed_sample_size = 0 ; // /< Fixed sample size (if used).
277
+ uint32_t fixed_sample_count = 0 ; // /< Fixed sample count (if used).
278
+ size_t current_size = 0 ; // /< Current sample size.
279
+ size_t box_size = 0 ; // /< Maximum size of the current sample.
280
+ size_t box_pos = 0 ; // /< Current position in the box.
281
+
282
+ /* *
283
+ * @brief Executes the callback for a completed frame.
284
+ * @param size Size of the frame.
285
+ */
286
+ void executeCallback (size_t size) {
287
+ Frame frame = getFrame (size, buffer);
281
288
if (callback)
282
289
callback (frame, ref);
283
290
else
@@ -345,6 +352,13 @@ class M4AAudioDemuxer {
345
352
// incremental data callback
346
353
parser.setIncrementalDataCallback (incrementalBoxDataCallback);
347
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
+
348
362
// parsing for content of stsd (Sample Description Box)
349
363
parser.setCallback (" esds" , [](MP4Parser::Box& box, void * ref) {
350
364
static_cast <M4AAudioDemuxer*>(ref)->onEsds (box);
@@ -355,6 +369,12 @@ class M4AAudioDemuxer {
355
369
parser.setCallback (" alac" , [](MP4Parser::Box& box, void * ref) {
356
370
static_cast <M4AAudioDemuxer*>(ref)->onAlac (box);
357
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
358
378
}
359
379
360
380
/* *
@@ -450,20 +470,15 @@ class M4AAudioDemuxer {
450
470
}
451
471
452
472
/* *
453
- * @brief Callback for box data setup.
473
+ * @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
475
+ * receive incremental data.
454
476
* @param box MP4 box.
455
477
* @param ref Reference pointer.
456
478
*/
457
479
static void boxDataSetupCallback (MP4Parser::Box& box, void * ref) {
458
480
M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
459
481
460
- // mdat must not be buffered
461
- if (StrView (box.type ) == " mdat" ) {
462
- LOGI (" Box: %s, size: %u bytes" , box.type , (unsigned )box.size );
463
- self.sampleExtractor .setMaxSize (box.size );
464
- return ;
465
- }
466
-
467
482
bool is_relevant = isRelevantBox (box.type );
468
483
if (is_relevant) {
469
484
LOGI (" Box: %s, size: %u bytes" , box.type , (unsigned )box.size );
@@ -491,13 +506,6 @@ class M4AAudioDemuxer {
491
506
bool is_final, void * ref) {
492
507
M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
493
508
494
- // mdat must not be buffered
495
- if (StrView (box.type ) == " mdat" ) {
496
- LOGI (" *Box: %s, size: %u bytes" , box.type , (unsigned )len);
497
- self.sampleExtractor .write (data, len, is_final);
498
- return ;
499
- }
500
-
501
509
// only process relevant boxes
502
510
if (!isRelevantBox (box.type )) return ;
503
511
0 commit comments