2 #include "AudioTools/AudioCodecs/AudioCodecsBase.h"
3 #include "AudioTools/AudioCodecs/CodecAACHelix.h"
4 #include "AudioTools/CoreAudio/AudioBasic/Net.h"
5 #include "AudioLogger.h"
20 strncpy(this->atom,
atom, 4);
21 this->container = container;
33 const uint8_t *data =
nullptr;
41 void setHeader(uint8_t *data,
int total);
44 bool is(
const char *
atom) {
return strncmp(this->atom,
atom, 4) == 0; }
53 return isalpha(
atom[0]) && isalpha(
atom[1]) && isalpha(
atom[2]) &&
58 void setData(
const uint8_t *data,
int len_data) {
60 this->data_size = len_data;
75 uint16_t read16(
int pos) {
76 if (data_size < pos)
return 0;
77 uint16_t *ptr = (uint16_t *)(data + pos);
80 uint32_t read32(
int pos) {
81 if (data_size < pos)
return 0;
82 uint32_t *ptr = (uint32_t *)(data + pos);
96 size_t write(
const uint8_t *data,
size_t len) {
98 if (buffer.
size() == 0) buffer.resize(len);
105 int available() {
return buffer.
available(); }
107 size_t readArray(uint8_t *data,
size_t len) {
137 p_decoder = &decoder;
148 assert(p_print!=
nullptr);
150 bool rc = p_decoder->begin();
161 operator bool()
override {
return is_active; }
164 size_t write(
const uint8_t *data,
size_t len)
override {
170 if (stream_out_open > 0) {
171 int len = min(stream_out_open, (
int)len);
173 MP4Atom atom{
this, stream_atom};
174 atom.total_size = len;
175 atom.data_size = len;
177 atom.start_pos = current_pos;
179 if (data_callback !=
nullptr) data_callback(atom, *
this);
181 stream_out_open -= result;
186 size_t result = buffer.write(data, len);
191 atom = buffer.
parse();
204 is_header_callback = cb;
212 return is_header_callback(atom, data);
224 int stream_out_open = 0;
225 bool is_sound =
false;
226 bool is_active =
false;
227 AACDecoderHelix aac_decoder;
228 AudioDecoder* p_decoder = &aac_decoder;
229 const char *stream_atom;
231 const char *current_atom =
nullptr;
232 void (*data_callback)(MP4Atom &atom,
234 bool (*is_header_callback)(MP4Atom *atom,
238 size_t decode(
const uint8_t *data,
size_t len) {
239 return p_decoder->write(data, len);
248 bool is_header_atom = isalpha(data[12]) && isalpha(data[13]) &&
249 isalpha(data[14]) && isalpha(data[15]) &&
251 return is_header_atom;
259 LOGI(
"%s: 0x%06x-0x%06x %d %s", atom.
atom, (
int)atom.start_pos,
265 if (atom.
is(
"ftyp") && atom.data !=
nullptr) {
267 memcpy(subtype, atom.data, 4);
269 LOGI(
" subtype: %s", subtype);
273 if (atom.
is(
"hdlr") && atom.data !=
nullptr) {
274 const uint8_t *sound = atom.data + 8;
275 container.is_sound = memcmp(
"soun", sound, 4) == 0;
276 LOGI(
" is_sound: %s", container.is_sound ?
"true" :
"false");
280 if (atom.
is(
"stsd")) {
293 if (container.is_sound){
295 int open = atom.data_size;
297 int processed = container.
decode(atom.data+pos, open);
303 LOGD(
"%s: %d bytes ignored", container.stream_atom, atom.data_size);
313 void MP4Atom::setHeader(uint8_t *data,
int len) {
314 uint32_t *p_size = (uint32_t *)data;
317 memcpy(
atom, data + 4, 4);
334 result.start_pos = container->current_pos;
338 buffer.peekArray(header, 16);
339 result.setHeader(header, 16);
340 result.is_stream =
false;
341 container->current_atom = result.atom;
345 LOGE(
"Invalid atom");
350 if (result.data_size > buffer.
available() &&
357 uint8_t data[min(result.data_size, buffer.
available())];
359 if (result.is_header_atom) {
362 container->current_pos += 8;
364 if (result.total_size > buffer.
available()) {
366 LOGI(
"total %s: 0x%06x-0x%06x - %d", container->current_atom,
367 container->current_pos, container->current_pos + result.total_size,
374 result.setData(data, avail);
375 result.total_size = avail;
376 result.data_size = avail - 8;
377 result.is_stream =
true;
379 container->current_pos += result.total_size;
382 buffer.
readArray(data, result.data_size);
383 result.setData(data, result.data_size);
384 container->current_pos += result.total_size;
389 if (result && container->data_callback !=
nullptr)
390 container->data_callback(result, *container);