arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
M4ACommonDemuxer.h
1#pragma once
2
3#include <cstdint>
4#include <functional>
5#include <string>
6
7#include "AudioTools/AudioCodecs/MP4Parser.h"
8#include "AudioTools/CoreAudio/Buffers.h"
9#include "MP4Parser.h"
10
11namespace audio_tools {
12
17using stsz_sample_size_t = uint16_t;
18
24 public:
25 enum class Codec { Unknown, AAC, ALAC, MP3 };
26
27 struct Frame {
28 Codec codec;
29 const char* mime = nullptr;
30 const uint8_t* data;
31 size_t size;
32 };
33
35 Codec codec = Codec::Unknown;
36 // aac
37 int aacProfile = 2, sampleRateIdx = 4, channelCfg = 2;
38 // cookie
40 };
41
47 struct ESDSParser {
48 uint8_t audioObjectType;
49 uint8_t samplingRateIndex;
50 uint8_t channelConfiguration;
51
52 // Parses esds content to extract audioObjectType, frequencyIndex, and
53 // channelConfiguration
54 bool parse(const uint8_t* data, size_t size) {
55 const uint8_t* ptr = data;
56 const uint8_t* end = data + size;
57
58 if (ptr + 4 > end) return false;
59 ptr += 4; // skip version + flags
60
61 if (ptr >= end || *ptr++ != 0x03) return false;
62 size_t es_len = parse_descriptor_length(ptr, end);
63 if (ptr + es_len > end) return false;
64
65 ptr += 2; // skip ES_ID
66 ptr += 1; // skip flags
67
68 if (ptr >= end || *ptr++ != 0x04) return false;
69 size_t dec_len = parse_descriptor_length(ptr, end);
70 if (ptr + dec_len > end) return false;
71
72 ptr += 13; // skip objectTypeIndication, streamType, bufferSizeDB,
73 // maxBitrate, avgBitrate
74
75 if (ptr >= end || *ptr++ != 0x05) return false;
76 size_t dsi_len = parse_descriptor_length(ptr, end);
77 if (ptr + dsi_len > end || dsi_len < 2) return false;
78
79 uint8_t byte1 = ptr[0];
80 uint8_t byte2 = ptr[1];
81
82 audioObjectType = (byte1 >> 3) & 0x1F;
83 samplingRateIndex = ((byte1 & 0x07) << 1) | ((byte2 >> 7) & 0x01);
84 channelConfiguration = (byte2 >> 3) & 0x0F;
85 return true;
86 }
87
88 protected:
89 // Helper to decode variable-length descriptor lengths (e.g. 0x80 80 80 05)
90 inline size_t parse_descriptor_length(const uint8_t*& ptr,
91 const uint8_t* end) {
92 size_t len = 0;
93 for (int i = 0; i < 4 && ptr < end; ++i) {
94 uint8_t b = *ptr++;
95 len = (len << 7) | (b & 0x7F);
96 if ((b & 0x80) == 0) break;
97 }
98 return len;
99 }
100 };
101
108 public:
110 using Codec = M4ACommonDemuxer::Codec;
112 using FrameCallback = std::function<void(const Frame&, void*)>;
113
117 SampleExtractor(M4AAudioConfig& cfg) : audio_config{cfg} { begin(); }
118
122 void begin() {
123 sampleIndex = 0;
124 buffer.clear();
125 p_chunk_offsets->clear();
126 p_sample_sizes->clear();
127 buffer.resize(1024);
128 current_size = 0;
129 box_pos = 0;
130 box_size = 0;
131 }
132
137 void setCallback(FrameCallback cb) { callback = cb; }
138
143 void setReference(void* r) { ref = r; }
144
151 void setMaxSize(size_t size) {
152 box_size = size;
153 }
154
163 size_t write(const uint8_t* data, size_t len, bool is_final) {
164 // Resize buffer to the current sample size
165 size_t currentSize = currentSampleSize();
166 if (currentSize == 0) {
167 LOGE("No sample size defined: e.g. mdat before stsz!");
168 return 0;
169 }
170 resize(currentSize);
171
173 for (int j = 0; j < len; j++) {
174 assert(buffer.write(data[j]));
175 if (buffer.available() >= currentSize) {
176 LOGI("Sample# %zu: size %zu bytes", sampleIndex, currentSize);
177 executeCallback(currentSize);
178 buffer.clear();
179 box_pos += currentSize;
180 ++sampleIndex;
181 currentSize = currentSampleSize();
182 if (box_pos >= box_size) {
183 LOGI("Reached end of box: %s write",
184 is_final ? "final" : "not final");
185 return j;
186 }
187 if (currentSize == 0) {
188 LOGE("No sample size defined, cannot write data");
189 return j;
190 }
191 }
192 }
193 return len;
194 }
195
201 return *p_sample_sizes;
202 }
203
211
216 BaseBuffer<uint32_t>& getChunkOffsetsBuffer() { return *p_chunk_offsets; }
217
223 p_chunk_offsets = &buffer;
224 }
225
232 void setFixedSampleCount(uint32_t sampleSize, uint32_t sampleCount) {
233 fixed_sample_size = sampleSize;
234 fixed_sample_count = sampleCount;
235 }
236
244 Frame frame;
245 frame.codec = audio_config.codec;
246 frame.data = buffer.data();
247 frame.size = size;
248 switch (audio_config.codec) {
249 case Codec::AAC: {
250 // Prepare ADTS header + AAC frame
251 tmp.resize(size + 7);
252 writeAdtsHeader(tmp.data(), audio_config.aacProfile,
253 audio_config.sampleRateIdx, audio_config.channelCfg,
254 size);
255 memcpy(tmp.data() + 7, buffer.data(), size);
256 frame.data = tmp.data();
257 frame.size = size + 7;
258 frame.mime = "audio/aac";
259 break;
260 }
261 case Codec::ALAC:
262 frame.mime = "audio/alac";
263 break;
264 case Codec::MP3:
265 frame.mime = "audio/mpeg";
266 break;
267 default:
268 frame.mime = nullptr;
269 break;
270 }
271 return frame;
272 }
273
274 protected:
275 M4AAudioConfig& audio_config;
280 BaseBuffer<uint32_t>* p_chunk_offsets = &defaultChunkOffsets;
281 Vector<uint8_t> tmp;
282 FrameCallback callback = nullptr;
283 void* ref = nullptr;
284 size_t sampleIndex = 0;
286 uint32_t fixed_sample_size = 0;
287 uint32_t fixed_sample_count = 0;
288 size_t current_size = 0;
289 size_t box_size = 0;
290 size_t box_pos = 0;
291
296 void executeCallback(size_t size) {
297 Frame frame = getFrame(size, buffer);
298 if (callback)
299 callback(frame, ref);
300 else
301 LOGE("No callback defined for audio frame extraction");
302 }
303
308 void resize(size_t newSize) {
309 if (buffer.size() < newSize) {
310 buffer.resize(newSize);
311 }
312 }
313
319 static size_t last_index = -1;
320 static size_t last_size = -1;
321
322 // Return cached size
323 if (sampleIndex == last_index) {
324 return last_size;
325 }
326
327 // using fixed sizes w/o table
328 if (fixed_sample_size > 0 && fixed_sample_count > 0 &&
330 return fixed_sample_size;
331 }
332 stsz_sample_size_t nextSize = 0;
333 if (p_sample_sizes->read(nextSize)) {
334 last_index = sampleIndex;
335 last_size = nextSize;
336 return nextSize;
337 }
338 return 0;
339 }
340
349 static void writeAdtsHeader(uint8_t* adts, int aacProfile,
350 int sampleRateIdx, int channelCfg,
351 int frameLen) {
352 adts[0] = 0xFF;
353 adts[1] = 0xF1;
354 adts[2] = ((aacProfile - 1) << 6) | (sampleRateIdx << 2) |
355 ((channelCfg >> 2) & 0x1);
356 adts[3] = ((channelCfg & 0x3) << 6) | ((frameLen + 7) >> 11);
357 adts[4] = ((frameLen + 7) >> 3) & 0xFF;
358 adts[5] = (((frameLen + 7) & 0x7) << 5) | 0x1F;
359 adts[6] = 0xFC;
360 }
361 };
362
363 using FrameCallback = std::function<void(const Frame&, void* ref)>;
364
365 M4ACommonDemuxer() = default;
366 virtual ~M4ACommonDemuxer() = default;
367
372 virtual void setCallback(FrameCallback cb) { frame_callback = cb; }
387
388 void begin() {
389 stsz_processed = false;
390 stco_processed = false;
391 audio_config.alacMagicCookie.clear();
392 audio_config.codec = Codec::Unknown;
393 parser.begin();
395 chunk_offsets_count = 0;
396 sample_count = 0;
397 }
404 void setAACConfig(int profile, int srIdx, int chCfg) {
405 audio_config.aacProfile = profile;
406 audio_config.sampleRateIdx = srIdx;
407 audio_config.channelCfg = chCfg;
408 }
409
410 void setM4AAudioConfig(M4AAudioConfig cfg) { audio_config = cfg; }
411
412 M4AAudioConfig getM4AAudioConfig() { return audio_config; }
413
414 void resize(int size) {
415 default_size = size;
416 if (buffer.size() < size) {
417 buffer.resize(size);
418 }
419 }
420
422 uint32_t getStszFileOffset() const {
423 return stsz_offset;
424 }
425
427 uint32_t getSampleCount() const {
428 return sample_count;
429 }
430
431 virtual void setupParser() = 0;
432
433 protected:
434 FrameCallback frame_callback = nullptr;
436 audio_config};
438 bool stsz_processed = false;
439 bool stco_processed = false;
440 bool stsd_processed = false;
441 M4AAudioConfig audio_config;
443 uint32_t sample_count = 0;
444 uint32_t stsz_offset = 0;
445 uint32_t chunk_offsets_count = 0;
446 size_t default_size = 2 * 1024;
447
453 static uint32_t readU32(const uint8_t* p) {
454 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
455 }
456
457 static uint32_t readU32(const uint32_t num) {
458 uint8_t* p = (uint8_t*)&num;
459 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
460 }
461
462 uint32_t readU32Buffer() {
463 uint32_t nextSize = 0;
464 buffer.readArray((uint8_t*)&nextSize, 4);
465 return readU32(nextSize);
466 }
467
468
476 bool checkType(uint8_t* buffer, const char* type, int offset) {
477 if (buffer == nullptr || type == nullptr) return false;
478 bool result = buffer[offset] == type[0] && buffer[offset + 1] == type[1] &&
479 buffer[offset + 2] == type[2] &&
480 buffer[offset + 3] == type[3];
481 return result;
482 }
483
484 void onStsd(const MP4Parser::Box& box) {
485 LOGI("Box: %s, size: %u bytes", box.type, (unsigned)box.available);
486 if (box.seq == 0) {
487 resize(box.size);
488 buffer.clear();
489 }
490
492
493 if (box.is_complete && buffer.available() >= 8) {
494 // printHexDump(box);
495 uint32_t entryCount = readU32(buffer.data() + 4);
496 // One or more sample entry boxes (e.g. mp4a, .mp3, alac)
497 parser.parseString(buffer.data() + 8, box.data_size - 8,
498 box.file_offset + 8 + 8, box.level + 1);
499 buffer.clear();
500 }
501 }
502
507 void onMp4a(const MP4Parser::Box& box) {
508 LOGI("onMp4a: %s, size: %zu bytes", box.type, box.data_size);
509
510 if (box.is_complete) {
511 // printHexDump(box);
512
513 // use default configuration
514 int aacProfile = 2; // Default: AAC LC
515 int sampleRateIdx = 4; // Default: 44100 Hz
516 int channelCfg = 2; // Default: Stereo
517 setAACConfig(aacProfile, sampleRateIdx, channelCfg);
518 audio_config.codec = Codec::AAC;
519
521 int pos = 36 - 8;
522 parser.parseString(box.data + pos, box.data_size - pos, box.level + 1);
523 }
524 }
525
530 void onEsds(const MP4Parser::Box& box) {
531 LOGI("onEsds: %s, size: %zu bytes", box.type, box.data_size);
532 // printHexDump(box);
533 ESDSParser esdsParser;
534 if (!esdsParser.parse(box.data, box.data_size)) {
535 LOGE("Failed to parse esds box");
536 return;
537 }
538 LOGI(
539 "-> esds: AAC objectType: %u, samplingRateIdx: %u, "
540 "channelCfg: %u",
541 esdsParser.audioObjectType, esdsParser.samplingRateIndex,
542 esdsParser.channelConfiguration);
543 setAACConfig(esdsParser.audioObjectType, esdsParser.samplingRateIndex,
544 esdsParser.channelConfiguration);
545 }
546
547 // void fixALACMagicCookie(uint8_t* cookie, size_t len) {
548 // if (len < 28) {
549 // return;
550 // }
551
552 // // Helper to read/write big-endian
553 // auto read32 = [](uint8_t* p) -> uint32_t {
554 // return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
555 // };
556 // auto write32 = [](uint8_t* p, uint32_t val) {
557 // p[0] = (val >> 24) & 0xFF;
558 // p[1] = (val >> 16) & 0xFF;
559 // p[2] = (val >> 8) & 0xFF;
560 // p[3] = val & 0xFF;
561 // };
562 // auto read16 = [](uint8_t* p) -> uint16_t { return (p[0] << 8) | p[1]; };
563 // auto write16 = [](uint8_t* p, uint16_t val) {
564 // p[0] = (val >> 8) & 0xFF;
565 // p[1] = val & 0xFF;
566 // };
567
568 // // Fix values if zero or invalid
569 // if (read32(cookie + 0) == 0) write32(cookie + 0, 4096); // frameLength
570 // if (cookie[6] == 0) cookie[6] = 16; // bitDepth
571 // if (cookie[7] == 0 || cookie[7] > 32) cookie[7] = 10; // pb
572 // if (cookie[8] == 0 || cookie[8] > 32) cookie[8] = 14; // mb
573 // if (cookie[9] == 0 || cookie[9] > 32) cookie[9] = 10; // kb
574 // if (cookie[10] == 0 || cookie[10] > 8) cookie[10] = 2; // numChannels
575 // if (read16(cookie + 11) == 0) write16(cookie + 11, 255); // maxRun
576 // if (read32(cookie + 13) == 0) write32(cookie + 13, 8192); // maxFrameBytes
577 // if (read32(cookie + 17) == 0) write32(cookie + 17, 512000); // avgBitRate
578 // if (read32(cookie + 21) == 0) write32(cookie + 21, 44100); // sampleRate
579 // }
580
585 void onAlac(const MP4Parser::Box& box) {
586 LOGI("onAlac: %s, size: %zu bytes", box.type, box.data_size);
587 audio_config.codec = Codec::ALAC;
588
589 // only alac box in alac contains magic cookie
590 MP4Parser::Box alac;
591 if (parser.findBox("alac", box.data, box.data_size, alac)) {
592 // fixALACMagicCookie((uint8_t*)alac.data, alac.data_size);
593 audio_config.alacMagicCookie.resize(alac.data_size - 4);
594 std::memcpy(audio_config.alacMagicCookie.data(), alac.data + 4,
595 alac.data_size - 4);
596 }
597 }
598
605 LOGI("onStsz #%u: %s, size: %u of %u bytes", (unsigned) box.seq, box.type, (unsigned) box.available, (unsigned) box.data_size);
606 if (stsz_processed) return;
607 BaseBuffer<stsz_sample_size_t>& sampleSizes =
609
611 size_t written = buffer.writeArray(box.data, box.available);
612 assert(written = box.available);
613
614 // get sample count and size from the box
615 if (sample_count == 0 && buffer.available() > 12) {
616 readU32Buffer(); // skip version + flags
617 uint32_t sampleSize = readU32Buffer();
618 uint32_t sampleCount = readU32Buffer();
619 sample_count = sampleCount;
620 stsz_offset = box.file_offset;
621
622 sampleSizes.resize(sample_count);
623 if (sampleSize != 0) {
624 sampleExtractor.setFixedSampleCount(sampleSize, sampleCount);
625 }
626 }
627
628 // incrementally process sampleSize
629 int count = 0;
630 while (buffer.available() >= 4) {
631 stsz_sample_size_t sampleSize = readU32Buffer();
632 assert(sampleSizes.write(sampleSize));
633 count += 4;
634 }
635 // Remove processed data
636 buffer.trim();
637
638 if (box.is_complete) {
639 stsz_processed = true;
640 }
641 }
642
643 // /**
644 // * @brief Handles the stco (Chunk Offset) box.
645 // * @param box MP4 box.
646 // */
647 // void onStco(MP4Parser::Box& box) {
648 // LOGI("onStco: %s, size: %zu bytes", box.type, box.data_size);
649 // if (stco_processed) return;
650 // BaseBuffer<uint32_t>& chunkOffsets =
651 // sampleExtractor.getChunkOffsetsBuffer();
652
653 // buffer.resize(box.available);
654 // buffer.writeArray(box.data, box.available);
655
656 // // get chunk_offsets_count from the box
657 // if (chunk_offsets_count == 0 && buffer.available() > 12) {
658 // chunk_offsets_count = readU32(buffer.data());
659 // buffer.clearArray(4); // clear version + flags
660 // }
661
662 // // incrementally process sampleSize
663 // int j = 0;
664 // for (j = 0; j < buffer.available(); j += 4) {
665 // uint32_t sampleSize = readU32(buffer.data() + j);
666 // chunkOffsets.write(sampleSize);
667 // }
668 // buffer.clearArray(j);
669
670 // if (box.is_complete) {
671 // stco_processed = true;
672 // }
673 // }
674
675 void printHexDump(const MP4Parser::Box& box) {
676 const uint8_t* data = box.data;
677 size_t len = box.data_size;
678 LOGI("===========================");
679 for (size_t i = 0; i < len; i += 16) {
680 char hex[49] = {0};
681 char ascii[17] = {0};
682 for (size_t j = 0; j < 16 && i + j < len; ++j) {
683 sprintf(hex + j * 3, "%02X ", data[i + j]);
684 ascii[j] = (data[i + j] >= 32 && data[i + j] < 127) ? data[i + j] : '.';
685 }
686 ascii[16] = 0;
687 LOGI("%04zx: %-48s |%s|", i, hex, ascii);
688 }
689 LOGI("===========================");
690 }
691};
692
693} // namespace audio_tools
Shared functionality of all buffers.
Definition Buffers.h:22
virtual bool read(T &result)=0
reads a single value
virtual int readArray(T data[], int len)
reads multiple values
Definition Buffers.h:33
void clear()
same as reset
Definition Buffers.h:95
virtual bool write(T data)=0
write add an entry to the buffer
virtual bool resize(int bytes)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:117
Extracts audio data based on the sample sizes defined in the stsz box. It collects the data from the ...
Definition M4ACommonDemuxer.h:107
size_t write(const uint8_t *data, size_t len, bool is_final)
Writes data to the extractor, extracting frames as sample sizes are met. Provides the data via the ca...
Definition M4ACommonDemuxer.h:163
void setFixedSampleCount(uint32_t sampleSize, uint32_t sampleCount)
Sets a fixed sample size/count instead of using the sampleSizes table.
Definition M4ACommonDemuxer.h:232
void * ref
Reference pointer for callback.
Definition M4ACommonDemuxer.h:283
FrameCallback callback
Frame callback.
Definition M4ACommonDemuxer.h:282
void executeCallback(size_t size)
Executes the callback for a completed frame.
Definition M4ACommonDemuxer.h:296
void setSampleSizesBuffer(BaseBuffer< stsz_sample_size_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:208
static void writeAdtsHeader(uint8_t *adts, int aacProfile, int sampleRateIdx, int channelCfg, int frameLen)
Writes an ADTS header for an AAC frame.
Definition M4ACommonDemuxer.h:349
size_t currentSampleSize()
Returns the current sample size.
Definition M4ACommonDemuxer.h:318
SampleExtractor(M4AAudioConfig &cfg)
Constructor. Initializes the extractor.
Definition M4ACommonDemuxer.h:117
size_t sampleIndex
Current sample index.
Definition M4ACommonDemuxer.h:284
size_t box_pos
Current position in the box.
Definition M4ACommonDemuxer.h:290
void resize(size_t newSize)
Resizes the internal buffer if needed.
Definition M4ACommonDemuxer.h:308
SingleBuffer< uint32_t > defaultChunkOffsets
Table of chunk offsets.
Definition M4ACommonDemuxer.h:278
SingleBuffer< stsz_sample_size_t > defaultSampleSizes
Table of sample sizes.
Definition M4ACommonDemuxer.h:277
BaseBuffer< uint32_t > & getChunkOffsetsBuffer()
Returns the buffer of chunk offsets.
Definition M4ACommonDemuxer.h:216
size_t current_size
Current sample size.
Definition M4ACommonDemuxer.h:288
SingleBuffer< uint8_t > buffer
Buffer for accumulating sample data.
Definition M4ACommonDemuxer.h:285
void begin()
Resets the extractor state.
Definition M4ACommonDemuxer.h:122
size_t box_size
Maximum size of the current sample.
Definition M4ACommonDemuxer.h:289
BaseBuffer< stsz_sample_size_t > & getSampleSizesBuffer()
Returns the buffer of sample sizes.
Definition M4ACommonDemuxer.h:200
void setCallback(FrameCallback cb)
Sets the callback to be called for each extracted frame.
Definition M4ACommonDemuxer.h:137
Frame getFrame(size_t size, SingleBuffer< uint8_t > &buffer)
Constructs a Frame object for the current codec.
Definition M4ACommonDemuxer.h:243
void setReference(void *r)
Sets a reference pointer passed to the callback.
Definition M4ACommonDemuxer.h:143
uint32_t fixed_sample_size
Fixed sample size (if used).
Definition M4ACommonDemuxer.h:286
void setChunkOffsetsBuffer(BaseBuffer< uint32_t > &buffer)
Sets the buffer to use for chunk offsets.
Definition M4ACommonDemuxer.h:222
uint32_t fixed_sample_count
Fixed sample count (if used).
Definition M4ACommonDemuxer.h:287
void setMaxSize(size_t size)
Sets the maximum box size (e.g., for mdat). This is called before the mdat data is posted....
Definition M4ACommonDemuxer.h:151
Abstract base class for M4A/MP4 demuxers. Provides shared functionality for both file-based and strea...
Definition M4ACommonDemuxer.h:23
MP4Parser parser
Underlying MP4 parser.
Definition M4ACommonDemuxer.h:437
void setAACConfig(int profile, int srIdx, int chCfg)
Sets the AAC configuration for ADTS header generation.
Definition M4ACommonDemuxer.h:404
uint32_t sample_count
Number of samples in stsz.
Definition M4ACommonDemuxer.h:443
void onEsds(const MP4Parser::Box &box)
Handles the esds (Elementary Stream Descriptor) box.
Definition M4ACommonDemuxer.h:530
virtual void setCallback(FrameCallback cb)
Sets the callback for extracted audio frames.
Definition M4ACommonDemuxer.h:372
SampleExtractor sampleExtractor
Extractor for audio samples.
Definition M4ACommonDemuxer.h:435
void setSampleSizesBuffer(BaseBuffer< stsz_sample_size_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:377
uint32_t getSampleCount() const
samples in stsz
Definition M4ACommonDemuxer.h:427
void onAlac(const MP4Parser::Box &box)
Handles the alac box.
Definition M4ACommonDemuxer.h:585
void onStsz(MP4Parser::Box &box)
Handles the stsz (Sample Size) box.
Definition M4ACommonDemuxer.h:603
void onMp4a(const MP4Parser::Box &box)
Handles the mp4a box.
Definition M4ACommonDemuxer.h:507
static uint32_t readU32(const uint8_t *p)
Reads a 32-bit big-endian unsigned integer from a buffer.
Definition M4ACommonDemuxer.h:453
SingleBuffer< uint8_t > buffer
Buffer for incremental data.
Definition M4ACommonDemuxer.h:442
size_t default_size
Default buffer size.
Definition M4ACommonDemuxer.h:446
bool stsz_processed
Marks the stsz table as processed.
Definition M4ACommonDemuxer.h:438
bool checkType(uint8_t *buffer, const char *type, int offset)
Checks if the buffer at the given offset matches the specified type.
Definition M4ACommonDemuxer.h:476
uint32_t getStszFileOffset() const
File offset of stsz box.
Definition M4ACommonDemuxer.h:422
void setChunkOffsetsBuffer(BaseBuffer< uint32_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:384
bool stco_processed
Marks the stco table as processed.
Definition M4ACommonDemuxer.h:439
MP4Parser is a class that parses MP4 container files and extracts boxes (atoms). It provides a callba...
Definition MP4Parser.h:28
static void defaultCallback(const Box &box, void *ref)
Default callback that prints box information to Serial.
Definition MP4Parser.h:223
bool begin()
Initializes the parser.
Definition MP4Parser.h:107
int parseString(const uint8_t *str, int len, int fileOffset=0, int level=0)
Trigger separate parsing (and callbacks) on the indicated string.
Definition MP4Parser.h:170
bool findBox(const char *name, const uint8_t *data, size_t len, Box &result)
find box in box
Definition MP4Parser.h:197
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:172
void trim()
Moves the unprocessed data to the beginning of the buffer.
Definition Buffers.h:260
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:202
int available() override
provides the number of entries that are available to read
Definition Buffers.h:229
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:292
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:197
T * data()
Provides address of actual data.
Definition Buffers.h:271
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint16_t stsz_sample_size_t
Definition M4ACommonDemuxer.h:17
A parser for the ESDS segment to extract the relevant aac information.
Definition M4ACommonDemuxer.h:47
Definition M4ACommonDemuxer.h:27
Definition M4ACommonDemuxer.h:34
Vector< uint8_t > alacMagicCookie
ALAC codec config.
Definition M4ACommonDemuxer.h:39
int channelCfg
AAC config.
Definition M4ACommonDemuxer.h:37
Codec codec
Current codec.
Definition M4ACommonDemuxer.h:35
Represents an individual box in the MP4 file.
Definition MP4Parser.h:33
const uint8_t * data
Pointer to box payload (not including header)
Definition MP4Parser.h:40
int available
Number of bytes available as data.
Definition MP4Parser.h:47
uint64_t file_offset
File offset where box starts.
Definition MP4Parser.h:46
size_t size
Size of payload including subboxes (not including header)
Definition MP4Parser.h:43
bool is_complete
True if the box data is complete.
Definition MP4Parser.h:48
size_t seq
Sequence number for the box per id.
Definition MP4Parser.h:38
char type[5]
4-character box type (null-terminated)
Definition MP4Parser.h:39
int level
Nesting depth.
Definition MP4Parser.h:45
size_t data_size
Size of payload (not including header)
Definition MP4Parser.h:42