Skip to content

Commit f50ea4a

Browse files
committed
MP4 container with data
1 parent 930bcee commit f50ea4a

File tree

1 file changed

+41
-33
lines changed

1 file changed

+41
-33
lines changed

src/AudioTools/AudioCodecs/MP4Parser.h

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ class MP4Parser {
3232
*/
3333
struct Box {
3434
friend class MP4Parser; ///< Allow MP4Parser to access private members
35-
friend class MP4ParserExt; ///< Allow MP4ParserExt to access private members
35+
friend class MP4ParserExt; ///< Allow MP4ParserExt to access private
36+
///< members
3637
size_t id = 0; ///< Unique box ID
3738
char type[5]; ///< 4-character box type (null-terminated)
38-
const uint8_t* data = nullptr; ///< Pointer to box payload (not including header)
39-
size_t data_size = 0; ///< Size of payload (not including header)
40-
size_t size = 0; ///< Size of payload (not including header)
41-
int level = 0; ///< Nesting depth
42-
uint64_t offset = 0; ///< File offset where box starts
39+
const uint8_t* data =
40+
nullptr; ///< Pointer to box payload (not including header)
41+
size_t data_size = 0; ///< Size of payload (not including header)
42+
size_t size = 0; ///< Size of payload (not including header)
43+
int level = 0; ///< Nesting depth
44+
uint64_t offset = 0; ///< File offset where box starts
4345
bool is_complete = false; ///< True if the box data is complete
4446
bool is_container = false; ///< True if the box is a container
4547
};
@@ -52,7 +54,8 @@ class MP4Parser {
5254
struct CallbackEntry {
5355
char type[5]; ///< 4-character box type
5456
BoxCallback cb; ///< Callback function
55-
bool callGeneric = true; ///< If true, also call the generic callback after this one
57+
bool callGeneric =
58+
true; ///< If true, also call the generic callback after this one
5659
};
5760

5861
/**
@@ -71,7 +74,8 @@ class MP4Parser {
7174
* @brief Defines a specific callback for a box type.
7275
* @param type 4-character box type (e.g. "moov", "mdat").
7376
* @param cb Callback function for this box type.
74-
* @param callGeneric If true, the generic callback will also be called after the type-specific callback.
77+
* @param callGeneric If true, the generic callback will also be called after
78+
* the type-specific callback.
7579
*/
7680
void setCallback(const char* type, BoxCallback cb, bool callGeneric = true) {
7781
CallbackEntry entry;
@@ -179,24 +183,24 @@ class MP4Parser {
179183
}
180184

181185
protected:
182-
BoxCallback callback = defaultCallback; ///< Generic callback for all boxes
183-
Vector<CallbackEntry> callbacks; ///< List of type-specific callbacks
184-
SingleBuffer<uint8_t> buffer; ///< Buffer for incoming data
185-
Vector<size_t> levelStack; ///< Stack for container box levels
186-
size_t parseOffset = 0; ///< Current parse offset in buffer
187-
uint64_t fileOffset = 0; ///< Current file offset
188-
void* ref = this; ///< Reference pointer for callbacks
189-
Box box; ///< Current box being processed
190-
bool is_error = false; ///< True if an error occurred
186+
BoxCallback callback = defaultCallback; ///< Generic callback for all boxes
187+
Vector<CallbackEntry> callbacks; ///< List of type-specific callbacks
188+
SingleBuffer<uint8_t> buffer; ///< Buffer for incoming data
189+
Vector<size_t> levelStack; ///< Stack for container box levels
190+
size_t parseOffset = 0; ///< Current parse offset in buffer
191+
uint64_t fileOffset = 0; ///< Current file offset
192+
void* ref = this; ///< Reference pointer for callbacks
193+
Box box; ///< Current box being processed
194+
bool is_error = false; ///< True if an error occurred
191195

192196
/**
193197
* @brief Structure for container box information.
194198
*/
195199
struct ContainerInfo {
196-
const char* name = nullptr; ///< Name of the container box
197-
int start = 0; ///< Offset of child boxes
200+
const char* name = nullptr; ///< Name of the container box
201+
int start = 0; ///< Offset of child boxes
198202
};
199-
Vector<ContainerInfo> containers; ///< List of container box info
203+
Vector<ContainerInfo> containers; ///< List of container box info
200204

201205
/**
202206
* @brief Returns the current file offset (absolute position in file).
@@ -292,10 +296,10 @@ class MP4Parser {
292296
box.is_complete = (parseOffset + boxSize <= bufferSize);
293297
box.is_container = is_container;
294298

295-
// Special logic for container: no data
299+
// Special logic for container: usually no data
296300
if (box.is_container) {
297-
box.data = nullptr;
298-
box.data_size = 0;
301+
box.data_size = getContainerDataLength(box.type);
302+
if (box.data_size == 0) box.data = nullptr;
299303
box.is_complete = true;
300304
}
301305

@@ -305,7 +309,7 @@ class MP4Parser {
305309
// Recurse into container
306310
if (box.is_container) {
307311
levelStack.push_back(absBoxOffset + boxSize);
308-
parseOffset += headerSize;
312+
parseOffset += (headerSize + box.data_size);
309313
continue;
310314
}
311315

@@ -334,7 +338,8 @@ class MP4Parser {
334338

335339
/**
336340
* @brief Processes the callback for a box.
337-
* Calls the type-specific callback if present, and the generic callback if allowed.
341+
* Calls the type-specific callback if present, and the generic callback if
342+
* allowed.
338343
* @param box The box being processed.
339344
*/
340345
void processCallback(Box& box) {
@@ -360,15 +365,18 @@ class MP4Parser {
360365
// fill with default values if nothing has been defined
361366
if (containers.empty()) {
362367
static const char* containers_str[] = {
363-
"moov", "trak", "mdia", "minf", "stbl", "edts",
364-
"dinf", "udta", "meta", "ilst", "moof", "traf",
365-
"mfra", "tref", "iprp", "sinf", "schi"};
368+
"moov", "trak", "mdia", "minf", "stbl", "edts", "dinf", "udta",
369+
"ilst", "moof", "traf", "mfra", "tref", "iprp", "sinf", "schi"};
366370
for (const char* c : containers_str) {
367371
ContainerInfo info;
368372
info.name = c;
369373
info.start = 0;
370374
containers.push_back(info);
371375
}
376+
ContainerInfo info;
377+
info.name = "meta";
378+
info.start = 4; // 4 bytes: version (1 byte) + flags (3 bytes)
379+
containers.push_back(info);
372380
}
373381
// find the container by name
374382
for (auto& cont : containers) {
@@ -382,7 +390,7 @@ class MP4Parser {
382390
* @param type Box type string.
383391
* @return Offset of the subcontainer.
384392
*/
385-
int getSubcontainerStart(const char* type) {
393+
int getContainerDataLength(const char* type) {
386394
for (auto& cont : containers) {
387395
if (StrView(type) == cont.name) return cont.start;
388396
}
@@ -407,11 +415,11 @@ class MP4Parser {
407415
* @param offset Offset in the string.
408416
* @return true if valid, false otherwise.
409417
*/
410-
bool isValidType(const char* type, int offset=0) const {
418+
bool isValidType(const char* type, int offset = 0) const {
411419
// Check if the type is a valid 4-character string
412-
return (type != nullptr &&
413-
isalnum(type[offset]) && isalnum(type[offset+1]) &&
414-
isalnum(type[offset+2]) && isalnum(type[offset+3]));
420+
return (type != nullptr && isalnum(type[offset]) &&
421+
isalnum(type[offset + 1]) && isalnum(type[offset + 2]) &&
422+
isalnum(type[offset + 3]));
415423
}
416424

417425
/**

0 commit comments

Comments
 (0)