@@ -75,8 +75,9 @@ class M4AAudioDemuxer {
75
75
box_pos += currentSize;
76
76
++sampleIndex;
77
77
currentSize = currentSampleSize ();
78
- if (box_pos >= box_size){
79
- LOGI (" Reached end of box: %s write" , is_final ? " final" : " not final" );
78
+ if (box_pos >= box_size) {
79
+ LOGI (" Reached end of box: %s write" ,
80
+ is_final ? " final" : " not final" );
80
81
return j;
81
82
}
82
83
if (currentSize == 0 ) {
@@ -92,7 +93,7 @@ class M4AAudioDemuxer {
92
93
Vector<size_t >& getSampleSizes () { return sampleSizes; }
93
94
Vector<size_t >& getChunkOffsets () { return chunkOffsets; }
94
95
95
- void setAacConfig (int profile, int srIdx, int chCfg) {
96
+ void setAACConfig (int profile, int srIdx, int chCfg) {
96
97
aacProfile = profile;
97
98
sampleRateIdx = srIdx;
98
99
channelCfg = chCfg;
@@ -181,6 +182,10 @@ class M4AAudioDemuxer {
181
182
M4AAudioDemuxer () {
182
183
parser.setReference (this );
183
184
parser.setCallback (boxCallback);
185
+ // parsing for content of stsd (Sample Description Box)
186
+ parser.setCallback (" esds" , esdsCallback);
187
+ parser.setCallback (" mp4a" , mp4aCallback);
188
+ parser.setCallback (" alac" , alacCallback);
184
189
185
190
// incremental data callback
186
191
parser.setDataCallback (boxDataCallback);
@@ -205,7 +210,7 @@ class M4AAudioDemuxer {
205
210
206
211
int availableForWrite () { return parser.availableForWrite (); }
207
212
208
- Vector<uint8_t >& getAlacMagicCookie () { return alacMagicCookie; }
213
+ Vector<uint8_t >& getALACMagicCookie () { return alacMagicCookie; }
209
214
210
215
void setReference (void * ref) { this ->ref = ref; }
211
216
@@ -231,6 +236,21 @@ class M4AAudioDemuxer {
231
236
StrView (type) == " stco" );
232
237
}
233
238
239
+ static void mp4aCallback (MP4Parser::Box& box, void * ref) {
240
+ M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
241
+ self.onMp4a (box);
242
+ }
243
+
244
+ static void esdsCallback (MP4Parser::Box& box, void * ref) {
245
+ M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
246
+ self.onEsds (box);
247
+ }
248
+
249
+ static void alacCallback (MP4Parser::Box& box, void * ref) {
250
+ M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
251
+ self.OnAlac (box);
252
+ }
253
+
234
254
// / Just prints the box name and the number of bytes received
235
255
static void boxCallback (MP4Parser::Box& box, void * ref) {
236
256
M4AAudioDemuxer& self = *static_cast <M4AAudioDemuxer*>(ref);
@@ -314,90 +334,60 @@ class M4AAudioDemuxer {
314
334
size_t size = box.data_size ;
315
335
if (size < 8 ) return ;
316
336
uint32_t entryCount = readU32 (data + 4 );
317
- size_t cursor = 8 ;
318
- for (uint32_t i = 0 ; i < entryCount; ++i) {
319
- if (cursor + 8 > size) break ;
320
- uint32_t entrySize = readU32 (data + cursor);
321
- const char * entryType = (const char *)(data + cursor + 4 );
322
- if (entrySize < 36 || cursor + entrySize > size) break ;
323
- size_t childrenStart = cursor + 8 + 28 ;
324
- size_t childrenEnd = cursor + entrySize;
325
- codec = Codec::Unknown;
326
- if (StrView (entryType) == " mp4a" ) {
327
- LOGI (" -> AAC" )
328
- codec = Codec::AAC;
329
- sampleExtractor.setCodec (codec);
330
- onStsdHandleMp4a (data, size, childrenStart, childrenEnd);
331
- break ;
332
- } else if (StrView (entryType) == " .mp3" ) {
333
- LOGI (" -> MP3" )
334
- codec = Codec::MP3;
335
- sampleExtractor.setCodec (codec);
336
- break ;
337
- } else if (StrView (entryType) == " alac" ) {
338
- LOGI (" -> ALAC" )
339
- codec = Codec::ALAC;
340
- sampleExtractor.setCodec (codec);
341
- onStsdHandleAlac (data, size, childrenStart, childrenEnd);
342
- break ;
343
- }
344
- cursor += entrySize;
345
- }
337
+ // One or more sample entry boxes (e.g. mp4a, .mp3, alac)
338
+ parser.parseString (data + 8 , size - 8 );
346
339
}
347
340
348
- void onStsdHandleMp4a (const uint8_t * data, size_t size, size_t childrenStart,
349
- size_t childrenEnd) {
341
+ void onMp4a (const MP4Parser::Box& box) {
342
+ LOGI (" onMp4a: %s, size: %zu bytes" , box.type , box.data_size );
343
+ if (box.data_size < 36 ) return ; // Minimum size for mp4a box
344
+
345
+ // use default configuration
350
346
int aacProfile = 2 ; // Default: AAC LC
351
347
int sampleRateIdx = 4 ; // Default: 44100 Hz
352
348
int channelCfg = 2 ; // Default: Stereo
349
+ sampleExtractor.setAACConfig (aacProfile, sampleRateIdx, channelCfg);
350
+ codec = Codec::AAC;
351
+ sampleExtractor.setCodec (codec);
353
352
354
- // Look for 'esds' box inside children
355
- size_t childOffset = childrenStart;
356
- while (childOffset + 8 <= childrenEnd && childOffset + 8 <= size) {
357
- uint32_t childSize = readU32 (data + childOffset);
358
- const char * childType = (const char *)(data + childOffset + 4 );
359
- if (childSize < 8 || childOffset + childSize > size) break ;
360
- if (StrView (childType) == " esds" ) {
361
- onStsdParseEsdsForAacConfig (data + childOffset + 8 , childSize - 8 ,
362
- aacProfile, sampleRateIdx, channelCfg);
363
- break ;
364
- }
365
- childOffset += childSize;
366
- }
367
- sampleExtractor.setAacConfig (aacProfile, sampleRateIdx, channelCfg);
353
+ // / for mp4a we expect to contain a esds: child boxes start at 36
354
+ int pos = 36 - 8 ;
355
+ parser.parseString (box.data + pos, box.data_size - pos);
368
356
}
369
357
370
- void onStsdParseEsdsForAacConfig (const uint8_t * esds, size_t esdsLen,
371
- int & aacProfile, int & sampleRateIdx,
372
- int & channelCfg) {
373
- for (size_t j = 0 ; j + 2 < esdsLen; ++j) {
374
- if (esds[j] == 0x05 ) { // 0x05 = AudioSpecificConfig tag
375
- // Next byte is length, then AudioSpecificConfig
376
- const uint8_t * asc = esds + j + 2 ;
377
- aacProfile = ((asc[0 ] >> 3 ) & 0x1F ); // 5 bits
358
+ void onEsds (const MP4Parser::Box& box) {
359
+ LOGI (" onEsds: %s, size: %zu bytes" , box.type , box.data_size );
360
+ int aacProfile = 2 ; // Default: AAC LC
361
+ int sampleRateIdx = 4 ; // Default: 44100 Hz
362
+ int channelCfg = 2 ; // Default: Stereo
363
+
364
+ for (size_t i = 2 ; i + 4 < box.data_size ; ++i) {
365
+ if (box.data [i] == 0x05 ) { // 0x05 = AudioSpecificConfig tag
366
+ uint8_t asc_len = box.data [i + 1 ];
367
+ if (i + 2 + asc_len > box.data_size ) {
368
+ LOGW (" esds box not long enough for AudioSpecificConfig" );
369
+ // break;
370
+ };
371
+ const uint8_t * asc = box.data + i + 2 ;
372
+ // AudioSpecificConfig is at least 2 bytes
373
+ aacProfile = (asc[0 ] >> 3 ) & 0x1F ; // 5 bits
378
374
sampleRateIdx =
379
375
((asc[0 ] & 0x07 ) << 1 ) | ((asc[1 ] >> 7 ) & 0x01 ); // 4 bits
380
376
channelCfg = (asc[1 ] >> 3 ) & 0x0F ; // 4 bits
381
- break ;
377
+ LOGI (" AudioSpecificConfig: profile=%d, sampleRateIdx=%d, channelCfg=%d" ,
378
+ aacProfile, sampleRateIdx, channelCfg);
379
+ sampleExtractor.setAACConfig (aacProfile, sampleRateIdx, channelCfg);
382
380
}
383
381
}
384
382
}
385
383
386
- void onStsdHandleAlac (const uint8_t * data, size_t size, size_t childrenStart,
387
- size_t childrenEnd) {
388
- size_t childOffset = childrenStart;
389
- while (childOffset + 8 <= childrenEnd && childOffset + 8 <= size) {
390
- uint32_t childSize = readU32 (data + childOffset);
391
- const char * childType = (const char *)(data + childOffset + 4 );
392
- if (childSize < 8 || childOffset + childSize > size) break ;
393
- if (StrView (childType) == " alac" ) {
394
- alacMagicCookie.resize (childSize - 8 );
395
- std::memcpy (alacMagicCookie.data (), data + childOffset + 8 ,
396
- childSize - 8 );
397
- break ;
398
- }
399
- childOffset += childSize;
400
- }
384
+ void OnAlac (const MP4Parser::Box& box) {
385
+ LOGI (" onAlac: %s, size: %zu bytes" , box.type , box.data_size );
386
+ codec = Codec::ALAC;
387
+ sampleExtractor.setCodec (codec);
388
+
389
+ alacMagicCookie.resize (box.data_size );
390
+ std::memcpy (alacMagicCookie.data (), box.data , box.data_size );
401
391
}
402
392
403
393
void onStsz (MP4Parser::Box& box) {
0 commit comments