arduino-audio-tools
Loading...
Searching...
No Matches
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
19using stsz_sample_size_t = uint16_t;
20
26 public:
27 enum class Codec { Unknown, AAC, ALAC, MP3 };
28
29 struct Frame {
30 Codec codec;
31 const char* mime = nullptr;
32 const uint8_t* data;
33 size_t size;
34 };
35
37 Codec codec = Codec::Unknown;
38 // aac
39 int aacProfile = 2, sampleRateIdx = 4, channelCfg = 2;
40 // cookie
42 };
43
49 struct ESDSParser {
50 uint8_t audioObjectType;
51 uint8_t samplingRateIndex;
52 uint8_t channelConfiguration;
53
54 // Parses esds content to extract audioObjectType, frequencyIndex, and
55 // channelConfiguration
56 bool parse(const uint8_t* data, size_t size) {
57 const uint8_t* ptr = data;
58 const uint8_t* end = data + size;
59
60 if (ptr + 4 > end) return false;
61 ptr += 4; // skip version + flags
62
63 if (ptr >= end || *ptr++ != 0x03) return false;
64 size_t es_len = parse_descriptor_length(ptr, end);
65 if (ptr + es_len > end) return false;
66
67 ptr += 2; // skip ES_ID
68 ptr += 1; // skip flags
69
70 if (ptr >= end || *ptr++ != 0x04) return false;
71 size_t dec_len = parse_descriptor_length(ptr, end);
72 if (ptr + dec_len > end) return false;
73
74 ptr += 13; // skip objectTypeIndication, streamType, bufferSizeDB,
75 // maxBitrate, avgBitrate
76
77 if (ptr >= end || *ptr++ != 0x05) return false;
78 size_t dsi_len = parse_descriptor_length(ptr, end);
79 if (ptr + dsi_len > end || dsi_len < 2) return false;
80
81 uint8_t byte1 = ptr[0];
82 uint8_t byte2 = ptr[1];
83
84 audioObjectType = (byte1 >> 3) & 0x1F;
85 samplingRateIndex = ((byte1 & 0x07) << 1) | ((byte2 >> 7) & 0x01);
86 channelConfiguration = (byte2 >> 3) & 0x0F;
87 return true;
88 }
89
90 protected:
91 // Helper to decode variable-length descriptor lengths (e.g. 0x80 80 80 05)
92 inline size_t parse_descriptor_length(const uint8_t*& ptr,
93 const uint8_t* end) {
94 size_t len = 0;
95 for (int i = 0; i < 4 && ptr < end; ++i) {
96 uint8_t b = *ptr++;
97 len = (len << 7) | (b & 0x7F);
98 if ((b & 0x80) == 0) break;
99 }
100 return len;
101 }
102 };
103
110 public:
112 using Codec = M4ACommonDemuxer::Codec;
114 using FrameCallback = std::function<void(const Frame&, void*)>;
115
119 SampleExtractor(M4AAudioConfig& cfg) : audio_config{cfg} { begin(); }
120
124 void begin() {
125 sampleIndex = 0;
126 buffer.clear();
127 p_chunk_offsets->clear();
128 p_sample_sizes->clear();
129 buffer.resize(1024);
130 current_size = 0;
131 box_pos = 0;
132 box_size = 0;
133 }
134
139 void setCallback(FrameCallback cb) { callback = cb; }
140
145 void setReference(void* r) { ref = r; }
146
153 void setMaxSize(size_t size) {
154 box_size = size;
155 }
156
165 size_t write(const uint8_t* data, size_t len, bool is_final) {
166 // Resize buffer to the current sample size
167 size_t currentSize = currentSampleSize();
168 if (currentSize == 0) {
169 LOGE("No sample size defined: e.g. mdat before stsz!");
170 return 0;
171 }
172 resize(currentSize);
173
175 for (int j = 0; j < len; j++) {
176 assert(buffer.write(data[j]));
177 if (buffer.available() >= currentSize) {
178 LOGI("Sample# %zu: size %zu bytes", sampleIndex, currentSize);
179 executeCallback(currentSize);
180 buffer.clear();
181 box_pos += currentSize;
182 ++sampleIndex;
183 currentSize = currentSampleSize();
184 if (box_pos >= box_size) {
185 LOGI("Reached end of box: %s write",
186 is_final ? "final" : "not final");
187 return j;
188 }
189 if (currentSize == 0) {
190 LOGE("No sample size defined, cannot write data");
191 return j;
192 }
193 }
194 }
195 return len;
196 }
197
203 return *p_sample_sizes;
204 }
205
213
218 BaseBuffer<uint32_t>& getChunkOffsetsBuffer() { return *p_chunk_offsets; }
219
225 p_chunk_offsets = &buffer;
226 }
227
234 void setFixedSampleCount(uint32_t sampleSize, uint32_t sampleCount) {
235 fixed_sample_size = sampleSize;
236 fixed_sample_count = sampleCount;
237 }
238
246 Frame frame;
247 frame.codec = audio_config.codec;
248 frame.data = buffer.data();
249 frame.size = size;
250 switch (audio_config.codec) {
251 case Codec::AAC: {
252 // Prepare ADTS header + AAC frame
253 tmp.resize(size + 7);
254 writeAdtsHeader(tmp.data(), audio_config.aacProfile,
255 audio_config.sampleRateIdx, audio_config.channelCfg,
256 size);
257 memcpy(tmp.data() + 7, buffer.data(), size);
258 frame.data = tmp.data();
259 frame.size = size + 7;
260 frame.mime = "audio/aac";
261 break;
262 }
263 case Codec::ALAC:
264 frame.mime = "audio/alac";
265 break;
266 case Codec::MP3:
267 frame.mime = "audio/mpeg";
268 break;
269 default:
270 frame.mime = nullptr;
271 break;
272 }
273 return frame;
274 }
275
276 protected:
277 M4AAudioConfig& audio_config;
282 BaseBuffer<uint32_t>* p_chunk_offsets = &defaultChunkOffsets;
283 Vector<uint8_t> tmp;
284 FrameCallback callback = nullptr;
285 void* ref = nullptr;
286 size_t sampleIndex = 0;
288 uint32_t fixed_sample_size = 0;
289 uint32_t fixed_sample_count = 0;
290 size_t current_size = 0;
291 size_t box_size = 0;
292 size_t box_pos = 0;
293
298 void executeCallback(size_t size) {
299 Frame frame = getFrame(size, buffer);
300 if (callback)
301 callback(frame, ref);
302 else
303 LOGE("No callback defined for audio frame extraction");
304 }
305
310 void resize(size_t newSize) {
311 if (buffer.size() < newSize) {
312 buffer.resize(newSize);
313 }
314 }
315
321 static size_t last_index = -1;
322 static size_t last_size = -1;
323
324 // Return cached size
325 if (sampleIndex == last_index) {
326 return last_size;
327 }
328
329 // using fixed sizes w/o table
330 if (fixed_sample_size > 0 && fixed_sample_count > 0 &&
332 return fixed_sample_size;
333 }
334 stsz_sample_size_t nextSize = 0;
335 if (p_sample_sizes->read(nextSize)) {
336 last_index = sampleIndex;
337 last_size = nextSize;
338 return nextSize;
339 }
340 return 0;
341 }
342
351 static void writeAdtsHeader(uint8_t* adts, int aacProfile,
352 int sampleRateIdx, int channelCfg,
353 int frameLen) {
354 adts[0] = 0xFF;
355 adts[1] = 0xF1;
356 adts[2] = ((aacProfile - 1) << 6) | (sampleRateIdx << 2) |
357 ((channelCfg >> 2) & 0x1);
358 adts[3] = ((channelCfg & 0x3) << 6) | ((frameLen + 7) >> 11);
359 adts[4] = ((frameLen + 7) >> 3) & 0xFF;
360 adts[5] = (((frameLen + 7) & 0x7) << 5) | 0x1F;
361 adts[6] = 0xFC;
362 }
363 };
364
365 using FrameCallback = std::function<void(const Frame&, void* ref)>;
366
367 M4ACommonDemuxer() = default;
368 virtual ~M4ACommonDemuxer() = default;
369
374 virtual void setCallback(FrameCallback cb) { frame_callback = cb; }
389
390 void begin() {
391 stsz_processed = false;
392 stco_processed = false;
393 audio_config.alacMagicCookie.clear();
394 audio_config.codec = Codec::Unknown;
395 parser.begin();
397 chunk_offsets_count = 0;
398 sample_count = 0;
399 }
406 void setAACConfig(int profile, int srIdx, int chCfg) {
407 audio_config.aacProfile = profile;
408 audio_config.sampleRateIdx = srIdx;
409 audio_config.channelCfg = chCfg;
410 }
411
412 void setM4AAudioConfig(M4AAudioConfig cfg) { audio_config = cfg; }
413
414 M4AAudioConfig getM4AAudioConfig() { return audio_config; }
415
416 void resize(int size) {
417 default_size = size;
418 if (buffer.size() < size) {
419 buffer.resize(size);
420 }
421 }
422
424 uint32_t getStszFileOffset() const {
425 return stsz_offset;
426 }
427
429 uint32_t getSampleCount() const {
430 return sample_count;
431 }
432
433 virtual void setupParser() = 0;
434
435 protected:
436 FrameCallback frame_callback = nullptr;
438 audio_config};
440 bool stsz_processed = false;
441 bool stco_processed = false;
442 bool stsd_processed = false;
443 M4AAudioConfig audio_config;
445 uint32_t sample_count = 0;
446 uint32_t stsz_offset = 0;
447 uint32_t chunk_offsets_count = 0;
448 size_t default_size = 2 * 1024;
449
455 static uint32_t readU32(const uint8_t* p) {
456 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
457 }
458
459 static uint32_t readU32(const uint32_t num) {
460 uint8_t* p = (uint8_t*)&num;
461 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
462 }
463
464 uint32_t readU32Buffer() {
465 uint32_t nextSize = 0;
466 buffer.readArray((uint8_t*)&nextSize, 4);
467 return readU32(nextSize);
468 }
469
470
478 bool checkType(uint8_t* buffer, const char* type, int offset) {
479 if (buffer == nullptr || type == nullptr) return false;
480 bool result = buffer[offset] == type[0] && buffer[offset + 1] == type[1] &&
481 buffer[offset + 2] == type[2] &&
482 buffer[offset + 3] == type[3];
483 return result;
484 }
485
486 void onStsd(const MP4Parser::Box& box) {
487 LOGI("Box: %s, size: %u bytes", box.type, (unsigned)box.available);
488 if (box.seq == 0) {
489 resize(box.size);
490 buffer.clear();
491 }
492
494
495 if (box.is_complete && buffer.available() >= 8) {
496 // printHexDump(box);
497 uint32_t entryCount = readU32(buffer.data() + 4);
498 // One or more sample entry boxes (e.g. mp4a, .mp3, alac)
499 parser.parseString(buffer.data() + 8, box.data_size - 8,
500 box.file_offset + 8 + 8, box.level + 1);
501 buffer.clear();
502 }
503 }
504
509 void onMp4a(const MP4Parser::Box& box) {
510 LOGI("onMp4a: %s, size: %zu bytes", box.type, box.data_size);
511
512 if (box.is_complete) {
513 // printHexDump(box);
514
515 // use default configuration
516 int aacProfile = 2; // Default: AAC LC
517 int sampleRateIdx = 4; // Default: 44100 Hz
518 int channelCfg = 2; // Default: Stereo
519 setAACConfig(aacProfile, sampleRateIdx, channelCfg);
520 audio_config.codec = Codec::AAC;
521
523 int pos = 36 - 8;
524 parser.parseString(box.data + pos, box.data_size - pos, box.level + 1);
525 }
526 }
527
532 void onEsds(const MP4Parser::Box& box) {
533 LOGI("onEsds: %s, size: %zu bytes", box.type, box.data_size);
534 // printHexDump(box);
535 ESDSParser esdsParser;
536 if (!esdsParser.parse(box.data, box.data_size)) {
537 LOGE("Failed to parse esds box");
538 return;
539 }
540 LOGI(
541 "-> esds: AAC objectType: %u, samplingRateIdx: %u, "
542 "channelCfg: %u",
543 esdsParser.audioObjectType, esdsParser.samplingRateIndex,
544 esdsParser.channelConfiguration);
545 setAACConfig(esdsParser.audioObjectType, esdsParser.samplingRateIndex,
546 esdsParser.channelConfiguration);
547 }
548
549 // void fixALACMagicCookie(uint8_t* cookie, size_t len) {
550 // if (len < 28) {
551 // return;
552 // }
553
554 // // Helper to read/write big-endian
555 // auto read32 = [](uint8_t* p) -> uint32_t {
556 // return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
557 // };
558 // auto write32 = [](uint8_t* p, uint32_t val) {
559 // p[0] = (val >> 24) & 0xFF;
560 // p[1] = (val >> 16) & 0xFF;
561 // p[2] = (val >> 8) & 0xFF;
562 // p[3] = val & 0xFF;
563 // };
564 // auto read16 = [](uint8_t* p) -> uint16_t { return (p[0] << 8) | p[1]; };
565 // auto write16 = [](uint8_t* p, uint16_t val) {
566 // p[0] = (val >> 8) & 0xFF;
567 // p[1] = val & 0xFF;
568 // };
569
570 // // Fix values if zero or invalid
571 // if (read32(cookie + 0) == 0) write32(cookie + 0, 4096); // frameLength
572 // if (cookie[6] == 0) cookie[6] = 16; // bitDepth
573 // if (cookie[7] == 0 || cookie[7] > 32) cookie[7] = 10; // pb
574 // if (cookie[8] == 0 || cookie[8] > 32) cookie[8] = 14; // mb
575 // if (cookie[9] == 0 || cookie[9] > 32) cookie[9] = 10; // kb
576 // if (cookie[10] == 0 || cookie[10] > 8) cookie[10] = 2; // numChannels
577 // if (read16(cookie + 11) == 0) write16(cookie + 11, 255); // maxRun
578 // if (read32(cookie + 13) == 0) write32(cookie + 13, 8192); // maxFrameBytes
579 // if (read32(cookie + 17) == 0) write32(cookie + 17, 512000); // avgBitRate
580 // if (read32(cookie + 21) == 0) write32(cookie + 21, 44100); // sampleRate
581 // }
582
587 void onAlac(const MP4Parser::Box& box) {
588 LOGI("onAlac: %s, size: %zu bytes", box.type, box.data_size);
589 audio_config.codec = Codec::ALAC;
590
591 // only alac box in alac contains magic cookie
592 MP4Parser::Box alac;
593 if (parser.findBox("alac", box.data, box.data_size, alac)) {
594 // fixALACMagicCookie((uint8_t*)alac.data, alac.data_size);
595 audio_config.alacMagicCookie.resize(alac.data_size - 4);
596 std::memcpy(audio_config.alacMagicCookie.data(), alac.data + 4,
597 alac.data_size - 4);
598 }
599 }
600
607 LOGI("onStsz #%u: %s, size: %u of %u bytes", (unsigned) box.seq, box.type, (unsigned) box.available, (unsigned) box.data_size);
608 if (stsz_processed) return;
609 BaseBuffer<stsz_sample_size_t>& sampleSizes =
611
613 size_t written = buffer.writeArray(box.data, box.available);
614 assert(written = box.available);
615
616 // get sample count and size from the box
617 if (sample_count == 0 && buffer.available() > 12) {
618 readU32Buffer(); // skip version + flags
619 uint32_t sampleSize = readU32Buffer();
620 uint32_t sampleCount = readU32Buffer();
621 sample_count = sampleCount;
622 stsz_offset = box.file_offset;
623
624 sampleSizes.resize(sample_count);
625 if (sampleSize != 0) {
626 sampleExtractor.setFixedSampleCount(sampleSize, sampleCount);
627 }
628 }
629
630 // incrementally process sampleSize
631 int count = 0;
632 while (buffer.available() >= 4) {
633 stsz_sample_size_t sampleSize = readU32Buffer();
634 assert(sampleSizes.write(sampleSize));
635 count += 4;
636 }
637 // Remove processed data
638 buffer.trim();
639
640 if (box.is_complete) {
641 stsz_processed = true;
642 }
643 }
644
645 // /**
646 // * @brief Handles the stco (Chunk Offset) box.
647 // * @param box MP4 box.
648 // */
649 // void onStco(MP4Parser::Box& box) {
650 // LOGI("onStco: %s, size: %zu bytes", box.type, box.data_size);
651 // if (stco_processed) return;
652 // BaseBuffer<uint32_t>& chunkOffsets =
653 // sampleExtractor.getChunkOffsetsBuffer();
654
655 // buffer.resize(box.available);
656 // buffer.writeArray(box.data, box.available);
657
658 // // get chunk_offsets_count from the box
659 // if (chunk_offsets_count == 0 && buffer.available() > 12) {
660 // chunk_offsets_count = readU32(buffer.data());
661 // buffer.clearArray(4); // clear version + flags
662 // }
663
664 // // incrementally process sampleSize
665 // int j = 0;
666 // for (j = 0; j < buffer.available(); j += 4) {
667 // uint32_t sampleSize = readU32(buffer.data() + j);
668 // chunkOffsets.write(sampleSize);
669 // }
670 // buffer.clearArray(j);
671
672 // if (box.is_complete) {
673 // stco_processed = true;
674 // }
675 // }
676
677 void printHexDump(const MP4Parser::Box& box) {
678 const uint8_t* data = box.data;
679 size_t len = box.data_size;
680 LOGI("===========================");
681 for (size_t i = 0; i < len; i += 16) {
682 char hex[49] = {0};
683 char ascii[17] = {0};
684 for (size_t j = 0; j < 16 && i + j < len; ++j) {
685 sprintf(hex + j * 3, "%02X ", data[i + j]);
686 ascii[j] = (data[i + j] >= 32 && data[i + j] < 127) ? data[i + j] : '.';
687 }
688 ascii[16] = 0;
689 LOGI("%04zx: %-48s |%s|", i, hex, ascii);
690 }
691 LOGI("===========================");
692 }
693};
694
695} // 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:109
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:165
void setFixedSampleCount(uint32_t sampleSize, uint32_t sampleCount)
Sets a fixed sample size/count instead of using the sampleSizes table.
Definition M4ACommonDemuxer.h:234
void * ref
Reference pointer for callback.
Definition M4ACommonDemuxer.h:285
FrameCallback callback
Frame callback.
Definition M4ACommonDemuxer.h:284
void executeCallback(size_t size)
Executes the callback for a completed frame.
Definition M4ACommonDemuxer.h:298
void setSampleSizesBuffer(BaseBuffer< stsz_sample_size_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:210
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:351
size_t currentSampleSize()
Returns the current sample size.
Definition M4ACommonDemuxer.h:320
SampleExtractor(M4AAudioConfig &cfg)
Constructor. Initializes the extractor.
Definition M4ACommonDemuxer.h:119
size_t sampleIndex
Current sample index.
Definition M4ACommonDemuxer.h:286
size_t box_pos
Current position in the box.
Definition M4ACommonDemuxer.h:292
void resize(size_t newSize)
Resizes the internal buffer if needed.
Definition M4ACommonDemuxer.h:310
SingleBuffer< uint32_t > defaultChunkOffsets
Table of chunk offsets.
Definition M4ACommonDemuxer.h:280
SingleBuffer< stsz_sample_size_t > defaultSampleSizes
Table of sample sizes.
Definition M4ACommonDemuxer.h:279
BaseBuffer< uint32_t > & getChunkOffsetsBuffer()
Returns the buffer of chunk offsets.
Definition M4ACommonDemuxer.h:218
size_t current_size
Current sample size.
Definition M4ACommonDemuxer.h:290
SingleBuffer< uint8_t > buffer
Buffer for accumulating sample data.
Definition M4ACommonDemuxer.h:287
void begin()
Resets the extractor state.
Definition M4ACommonDemuxer.h:124
size_t box_size
Maximum size of the current sample.
Definition M4ACommonDemuxer.h:291
BaseBuffer< stsz_sample_size_t > & getSampleSizesBuffer()
Returns the buffer of sample sizes.
Definition M4ACommonDemuxer.h:202
void setCallback(FrameCallback cb)
Sets the callback to be called for each extracted frame.
Definition M4ACommonDemuxer.h:139
Frame getFrame(size_t size, SingleBuffer< uint8_t > &buffer)
Constructs a Frame object for the current codec.
Definition M4ACommonDemuxer.h:245
void setReference(void *r)
Sets a reference pointer passed to the callback.
Definition M4ACommonDemuxer.h:145
uint32_t fixed_sample_size
Fixed sample size (if used).
Definition M4ACommonDemuxer.h:288
void setChunkOffsetsBuffer(BaseBuffer< uint32_t > &buffer)
Sets the buffer to use for chunk offsets.
Definition M4ACommonDemuxer.h:224
uint32_t fixed_sample_count
Fixed sample count (if used).
Definition M4ACommonDemuxer.h:289
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:153
Abstract base class for M4A/MP4 demuxers. Provides shared functionality for both file-based and strea...
Definition M4ACommonDemuxer.h:25
MP4Parser parser
Underlying MP4 parser.
Definition M4ACommonDemuxer.h:439
void setAACConfig(int profile, int srIdx, int chCfg)
Sets the AAC configuration for ADTS header generation.
Definition M4ACommonDemuxer.h:406
uint32_t sample_count
Number of samples in stsz.
Definition M4ACommonDemuxer.h:445
void onEsds(const MP4Parser::Box &box)
Handles the esds (Elementary Stream Descriptor) box.
Definition M4ACommonDemuxer.h:532
virtual void setCallback(FrameCallback cb)
Sets the callback for extracted audio frames.
Definition M4ACommonDemuxer.h:374
SampleExtractor sampleExtractor
Extractor for audio samples.
Definition M4ACommonDemuxer.h:437
void setSampleSizesBuffer(BaseBuffer< stsz_sample_size_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:379
uint32_t getSampleCount() const
samples in stsz
Definition M4ACommonDemuxer.h:429
void onAlac(const MP4Parser::Box &box)
Handles the alac box.
Definition M4ACommonDemuxer.h:587
void onStsz(MP4Parser::Box &box)
Handles the stsz (Sample Size) box.
Definition M4ACommonDemuxer.h:605
void onMp4a(const MP4Parser::Box &box)
Handles the mp4a box.
Definition M4ACommonDemuxer.h:509
static uint32_t readU32(const uint8_t *p)
Reads a 32-bit big-endian unsigned integer from a buffer.
Definition M4ACommonDemuxer.h:455
SingleBuffer< uint8_t > buffer
Buffer for incremental data.
Definition M4ACommonDemuxer.h:444
size_t default_size
Default buffer size.
Definition M4ACommonDemuxer.h:448
bool stsz_processed
Marks the stsz table as processed.
Definition M4ACommonDemuxer.h:440
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:478
uint32_t getStszFileOffset() const
File offset of stsz box.
Definition M4ACommonDemuxer.h:424
void setChunkOffsetsBuffer(BaseBuffer< uint32_t > &buffer)
Sets the buffer to use for sample sizes.
Definition M4ACommonDemuxer.h:386
bool stco_processed
Marks the stco table as processed.
Definition M4ACommonDemuxer.h:441
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:273
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:206
int available() override
provides the number of entries that are available to read
Definition Buffers.h:233
bool resize(int size)
Resizes the buffer if supported: returns false if not supported.
Definition Buffers.h:305
int writeArray(const T data[], int len) override
Fills the buffer data.
Definition Buffers.h:201
T * data()
Provides address of actual data.
Definition Buffers.h:284
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
uint16_t stsz_sample_size_t
Sample size type optimized for microcontrollers.
Definition M4ACommonDemuxer.h:19
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
A parser for the ESDS segment to extract the relevant aac information.
Definition M4ACommonDemuxer.h:49
Definition M4ACommonDemuxer.h:29
Definition M4ACommonDemuxer.h:36
Vector< uint8_t > alacMagicCookie
ALAC codec config.
Definition M4ACommonDemuxer.h:41
int channelCfg
AAC config.
Definition M4ACommonDemuxer.h:39
Codec codec
Current codec.
Definition M4ACommonDemuxer.h:37
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