2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
17 # include <inttypes.h>
18 #elif defined _MSC_VER
19 # define PRId64 "I64d"
22 #include "m4af_endian.h"
24 #define m4af_realloc(memory,size) realloc(memory, size)
25 #define m4af_free(memory) free(memory)
27 #define M4AF_ATOM_WILD 0xffffffff
29 typedef struct m4af_sample_entry_t
{
32 } m4af_sample_entry_t
;
34 typedef struct m4af_chunk_entry_t
{
37 uint32_t samples_per_chunk
;
41 typedef struct m4af_track_t
{
44 int64_t creation_time
;
45 int64_t modification_time
;
47 uint32_t frame_duration
;
48 uint32_t encoder_delay
;
50 uint8_t *decSpecificInfo
;
51 uint32_t decSpecificInfoSize
;
52 uint32_t bufferSizeDB
;
56 m4af_sample_entry_t
*sample_table
;
58 uint32_t sample_table_capacity
;
60 m4af_chunk_entry_t
*chunk_table
;
62 uint32_t chunk_table_capacity
;
64 uint8_t *chunk_buffer
;
66 uint32_t chunk_capacity
;
68 /* temporary, to help parsing */
78 int64_t creation_time
;
79 int64_t modification_time
;
85 m4af_itmf_entry_t
*itmf_table
;
87 uint32_t itmf_table_capacity
;
89 m4af_io_callbacks_t io
;
93 m4af_track_t track
[2];
95 m4af_itmf_entry_t current_tag
;
98 typedef struct m4af_box_parser_t
{
100 int (*handler
)(m4af_ctx_t
*ctx
, uint32_t name
, uint64_t size
);
104 int64_t m4af_timestamp(void)
106 return (int64_t)(time(0)) + (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
110 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
113 uint32_t m4af_roundup(uint32_t n
)
126 int64_t m4af_tell(m4af_ctx_t
*ctx
)
129 if ((pos
= ctx
->io
.tell(ctx
->io_cookie
)) < 0)
130 ctx
->last_error
= M4AF_IO_ERROR
;
135 int m4af_set_pos(m4af_ctx_t
*ctx
, int64_t pos
)
138 if ((rc
= ctx
->io
.seek(ctx
->io_cookie
, pos
, SEEK_SET
)) < 0)
139 ctx
->last_error
= M4AF_IO_ERROR
;
144 int m4af_write(m4af_ctx_t
*ctx
, const void *data
, uint32_t size
)
147 if ((rc
= ctx
->io
.write(ctx
->io_cookie
, data
, size
)) < 0)
148 ctx
->last_error
= M4AF_IO_ERROR
;
153 int m4af_write16(m4af_ctx_t
*ctx
, uint32_t data
)
155 data
= m4af_htob16(data
);
156 return m4af_write(ctx
, &data
, 2);
160 int m4af_write32(m4af_ctx_t
*ctx
, uint32_t data
)
162 data
= m4af_htob32(data
);
163 return m4af_write(ctx
, &data
, 4);
167 int m4af_write64(m4af_ctx_t
*ctx
, uint64_t data
)
169 data
= m4af_htob64(data
);
170 return m4af_write(ctx
, &data
, 8);
174 int m4af_write24(m4af_ctx_t
*ctx
, uint32_t data
)
176 data
= m4af_htob32(data
<< 8);
177 return m4af_write(ctx
, &data
, 3);
181 void m4af_write32_at(m4af_ctx_t
*ctx
, int64_t pos
, uint32_t value
)
183 int64_t current_pos
= m4af_tell(ctx
);
184 m4af_set_pos(ctx
, pos
);
185 m4af_write32(ctx
, value
);
186 m4af_set_pos(ctx
, current_pos
);
189 m4af_ctx_t
*m4af_create(uint32_t codec
, uint32_t timescale
,
190 m4af_io_callbacks_t
*io
, void *io_cookie
)
195 if (codec
!= M4AF_FOURCC('m','p','4','a') &&
196 codec
!= M4AF_FOURCC('a','l','a','c'))
198 if ((ctx
= m4af_realloc(0, sizeof(m4af_ctx_t
))) == 0)
200 memset(ctx
, 0, sizeof(m4af_ctx_t
));
201 memcpy(&ctx
->io
, io
, sizeof(m4af_io_callbacks_t
));
202 ctx
->io_cookie
= io_cookie
;
203 ctx
->timescale
= timescale
;
204 timestamp
= m4af_timestamp();
205 ctx
->creation_time
= timestamp
;
206 ctx
->modification_time
= timestamp
;
208 ctx
->track
[0].codec
= codec
;
209 ctx
->track
[0].timescale
= timescale
;
210 ctx
->track
[0].creation_time
= timestamp
;
211 ctx
->track
[0].modification_time
= timestamp
;
216 void m4af_free_itmf_table(m4af_ctx_t
*ctx
)
219 m4af_itmf_entry_t
*entry
= ctx
->itmf_table
;
220 for (i
= 0; i
< ctx
->num_tags
; ++i
, ++entry
) {
221 if (entry
->fcc
== M4AF_FOURCC('-','-','-','-'))
222 m4af_free(entry
->name
);
223 m4af_free(entry
->data
);
225 m4af_free(ctx
->itmf_table
);
229 void m4af_clear_track(m4af_ctx_t
*ctx
, int track_idx
)
231 m4af_track_t
*track
= ctx
->track
+ track_idx
;
232 if (track
->decSpecificInfo
)
233 m4af_free(track
->decSpecificInfo
);
234 if (track
->sample_table
)
235 m4af_free(track
->sample_table
);
236 if (track
->chunk_table
)
237 m4af_free(track
->chunk_table
);
238 if (track
->chunk_buffer
)
239 m4af_free(track
->chunk_buffer
);
240 memset(track
, 0, sizeof(m4af_track_t
));
243 void m4af_teardown(m4af_ctx_t
**ctxp
)
246 m4af_ctx_t
*ctx
= *ctxp
;
247 for (i
= 0; i
< ctx
->num_tracks
; ++i
)
248 m4af_clear_track(ctx
, i
);
250 m4af_free_itmf_table(ctx
);
255 void m4af_set_fixed_frame_duration(m4af_ctx_t
*ctx
, uint32_t track_idx
,
258 ctx
->track
[track_idx
].frame_duration
= length
;
261 int m4af_set_decoder_specific_info(m4af_ctx_t
*ctx
, uint32_t track_idx
,
262 uint8_t *data
, uint32_t size
)
264 m4af_track_t
*track
= &ctx
->track
[track_idx
];
265 if (size
> track
->decSpecificInfoSize
) {
266 uint8_t *memory
= m4af_realloc(track
->decSpecificInfo
, size
);
268 ctx
->last_error
= M4AF_NO_MEMORY
;
271 track
->decSpecificInfo
= memory
;
274 memcpy(track
->decSpecificInfo
, data
, size
);
275 track
->decSpecificInfoSize
= size
;
277 return ctx
->last_error
;
280 void m4af_set_priming(m4af_ctx_t
*ctx
, uint32_t track_idx
,
281 uint32_t encoder_delay
, uint32_t padding
)
283 m4af_track_t
*track
= &ctx
->track
[track_idx
];
284 track
->encoder_delay
= encoder_delay
;
285 track
->padding
= padding
;
288 void m4af_set_priming_mode(m4af_ctx_t
*ctx
, int mode
)
290 ctx
->priming_mode
= mode
;
294 int m4af_add_sample_entry(m4af_ctx_t
*ctx
, uint32_t track_idx
,
295 uint32_t size
, uint32_t delta
)
297 m4af_track_t
*track
= &ctx
->track
[track_idx
];
298 m4af_sample_entry_t
*entry
;
302 if (track
->num_samples
== track
->sample_table_capacity
) {
303 uint32_t new_size
= track
->sample_table_capacity
;
304 new_size
= new_size
? new_size
* 2 : 1;
305 entry
= m4af_realloc(track
->sample_table
, new_size
* sizeof(*entry
));
307 ctx
->last_error
= M4AF_NO_MEMORY
;
310 track
->sample_table
= entry
;
311 track
->sample_table_capacity
= new_size
;
313 entry
= track
->sample_table
+ track
->num_samples
;
315 entry
->delta
= delta
;
316 ++track
->num_samples
;
321 int m4af_flush_chunk(m4af_ctx_t
*ctx
, uint32_t track_idx
)
323 m4af_track_t
*track
= &ctx
->track
[track_idx
];
324 m4af_chunk_entry_t
*entry
;
325 if (!track
->num_chunks
|| !track
->chunk_size
)
327 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
328 entry
->offset
= m4af_tell(ctx
);
329 m4af_write(ctx
, track
->chunk_buffer
, track
->chunk_size
);
330 ctx
->mdat_size
+= track
->chunk_size
;
331 track
->chunk_size
= 0;
332 return ctx
->last_error
? -1 : 0;
336 int m4af_add_chunk_entry(m4af_ctx_t
*ctx
, uint32_t track_idx
)
338 m4af_track_t
*track
= &ctx
->track
[track_idx
];
339 m4af_chunk_entry_t
*entry
;
340 if (track
->num_chunks
== track
->chunk_table_capacity
) {
341 uint32_t new_size
= track
->chunk_table_capacity
;
342 new_size
= new_size
? new_size
* 2 : 1;
343 entry
= m4af_realloc(track
->chunk_table
, new_size
* sizeof(*entry
));
345 ctx
->last_error
= M4AF_NO_MEMORY
;
348 track
->chunk_table
= entry
;
349 track
->chunk_table_capacity
= new_size
;
351 memset(&track
->chunk_table
[track
->num_chunks
++], 0,
352 sizeof(m4af_chunk_entry_t
));
357 int m4af_update_chunk_table(m4af_ctx_t
*ctx
, uint32_t track_idx
,
358 uint32_t size
, uint32_t delta
)
360 m4af_track_t
*track
= &ctx
->track
[track_idx
];
361 m4af_chunk_entry_t
*entry
;
362 int add_new_chunk
= 0;
366 if (track
->num_chunks
== 0)
369 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
370 if (entry
->duration
+ delta
> track
->timescale
/ 2)
374 m4af_flush_chunk(ctx
, track_idx
);
375 if (m4af_add_chunk_entry(ctx
, track_idx
) < 0)
378 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
380 ++entry
->samples_per_chunk
;
381 entry
->duration
+= delta
;
386 void m4af_update_max_bitrate(m4af_ctx_t
*ctx
, uint32_t track_idx
)
388 m4af_track_t
*track
= &ctx
->track
[track_idx
];
389 uint32_t duration
= 0, size
= 0, bitrate
;
390 m4af_sample_entry_t
*ent
= track
->sample_table
+ track
->num_samples
- 1;
392 for (; ent
>= track
->sample_table
&& duration
< track
->timescale
; --ent
) {
393 duration
+= ent
->delta
;
396 bitrate
= (uint32_t)(size
* 8.0 * track
->timescale
/ duration
+ .5);
397 if (bitrate
> track
->maxBitrate
)
398 track
->maxBitrate
= bitrate
;
402 int m4af_append_sample_to_chunk(m4af_ctx_t
*ctx
, uint32_t track_idx
,
403 const void *data
, uint32_t size
)
405 m4af_track_t
*track
= &ctx
->track
[track_idx
];
406 uint32_t newsize
= track
->chunk_size
+ size
;
410 if (track
->chunk_capacity
< newsize
) {
411 uint32_t capacity
= m4af_roundup(newsize
);
412 uint8_t *memory
= realloc(track
->chunk_buffer
, capacity
);
414 ctx
->last_error
= M4AF_NO_MEMORY
;
417 track
->chunk_buffer
= memory
;
418 track
->chunk_capacity
= capacity
;
420 memcpy(track
->chunk_buffer
+ track
->chunk_size
, data
, size
);
421 track
->chunk_size
= newsize
;
425 int m4af_write_sample(m4af_ctx_t
*ctx
, uint32_t track_idx
, const void *data
,
426 uint32_t size
, uint32_t duration
)
428 m4af_track_t
*track
= &ctx
->track
[track_idx
];
429 if (track
->frame_duration
)
430 duration
= track
->frame_duration
;
431 if (size
> track
->bufferSizeDB
)
432 track
->bufferSizeDB
= size
;
433 track
->duration
+= duration
;
434 m4af_add_sample_entry(ctx
, track_idx
, size
, duration
);
435 m4af_update_chunk_table(ctx
, track_idx
, size
, duration
);
436 m4af_update_max_bitrate(ctx
, track_idx
);
437 m4af_append_sample_to_chunk(ctx
, track_idx
, data
, size
);
438 return ctx
->last_error
;
442 m4af_itmf_entry_t
*m4af_find_itmf_slot(m4af_ctx_t
*ctx
, uint32_t fcc
,
445 m4af_itmf_entry_t
*entry
= ctx
->itmf_table
;
448 fcc
= M4AF_FOURCC('-','-','-','-');
450 if (fcc
!= M4AF_TAG_ARTWORK
)
451 for (; entry
!= ctx
->itmf_table
+ ctx
->num_tags
; ++entry
)
452 if (fcc
== entry
->fcc
&& (!name
|| !strcmp(name
, entry
->name
)))
455 if (ctx
->num_tags
== ctx
->itmf_table_capacity
) {
456 uint32_t new_size
= ctx
->itmf_table_capacity
;
457 new_size
= new_size
? new_size
* 2 : 1;
458 entry
= m4af_realloc(ctx
->itmf_table
, new_size
* sizeof(*entry
));
460 ctx
->last_error
= M4AF_NO_MEMORY
;
463 ctx
->itmf_table
= entry
;
464 ctx
->itmf_table_capacity
= new_size
;
466 entry
= &ctx
->itmf_table
[ctx
->num_tags
++];
467 memset(entry
, 0, sizeof(m4af_itmf_entry_t
));
470 char *name_copy
= m4af_realloc(0, strlen(name
) + 1);
472 ctx
->last_error
= M4AF_NO_MEMORY
;
476 strcpy(name_copy
, name
);
477 entry
->name
= name_copy
;
482 int m4af_add_itmf_long_tag(m4af_ctx_t
*ctx
, const char *name
,
485 m4af_itmf_entry_t
*entry
;
487 size_t name_len
= strlen(name
);
488 size_t data_len
= strlen(data
);
489 if (!name_len
|| !data_len
)
492 if ((entry
= m4af_find_itmf_slot(ctx
, 0, name
)) == 0)
494 entry
->type_code
= M4AF_UTF8
;
495 if ((data_copy
= m4af_realloc(entry
->data
, data_len
)) == 0) {
496 ctx
->last_error
= M4AF_NO_MEMORY
;
499 memcpy(data_copy
, data
, data_len
);
500 entry
->data
= data_copy
;
501 entry
->data_size
= data_len
;
504 return ctx
->last_error
;
507 int m4af_add_itmf_short_tag(m4af_ctx_t
*ctx
, uint32_t fcc
,
508 uint32_t type_code
, const void *data
,
511 m4af_itmf_entry_t
*entry
;
516 if ((entry
= m4af_find_itmf_slot(ctx
, fcc
, 0)) == 0)
518 entry
->type_code
= type_code
;
519 if ((data_copy
= m4af_realloc(entry
->data
, data_size
)) == 0) {
520 ctx
->last_error
= M4AF_NO_MEMORY
;
523 memcpy(data_copy
, data
, data_size
);
524 entry
->data
= data_copy
;
525 entry
->data_size
= data_size
;
528 return ctx
->last_error
;
531 int m4af_add_itmf_string_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, const char *data
)
533 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_UTF8
, data
, strlen(data
));
536 int m4af_add_itmf_int8_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, int value
)
538 uint8_t data
= value
;
539 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 1);
542 int m4af_add_itmf_int16_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, int value
)
544 uint16_t data
= m4af_htob16(value
);
545 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 2);
548 int m4af_add_itmf_int32_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, uint32_t value
)
550 uint32_t data
= m4af_htob32(value
);
551 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 4);
554 int m4af_add_itmf_int64_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, uint64_t value
)
556 uint64_t data
= m4af_htob64(value
);
557 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 8);
560 int m4af_add_itmf_track_tag(m4af_ctx_t
*ctx
, int track
, int total
)
562 uint16_t data
[4] = { 0 };
563 data
[1] = m4af_htob16(track
);
564 data
[2] = m4af_htob16(total
);
565 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('t','r','k','n'),
566 M4AF_IMPLICIT
, &data
, 8);
569 int m4af_add_itmf_disk_tag(m4af_ctx_t
*ctx
, int disk
, int total
)
571 uint16_t data
[3] = { 0 };
572 data
[1] = m4af_htob16(disk
);
573 data
[2] = m4af_htob16(total
);
574 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('d','i','s','k'),
575 M4AF_IMPLICIT
, &data
, 6);
578 int m4af_add_itmf_genre_tag(m4af_ctx_t
*ctx
, int genre
)
580 uint16_t data
= m4af_htob16(genre
);
581 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('g','n','r','e'),
582 M4AF_IMPLICIT
, &data
, 2);
586 int m4af_set_iTunSMPB(m4af_ctx_t
*ctx
)
588 const char *fmt
= " 00000000 %08X %08X %08X%08X 00000000 00000000 "
589 "00000000 00000000 00000000 00000000 00000000 00000000";
590 m4af_track_t
*track
= &ctx
->track
[0];
592 uint64_t length
= track
->duration
- track
->encoder_delay
- track
->padding
;
593 sprintf(buf
, fmt
, track
->encoder_delay
, track
->padding
,
594 (uint32_t)(length
>> 32), (uint32_t)length
);
595 return m4af_add_itmf_long_tag(ctx
, "iTunSMPB", buf
);
599 void m4af_update_box_size(m4af_ctx_t
*ctx
, int64_t pos
)
601 int64_t current_pos
= m4af_tell(ctx
);
602 m4af_set_pos(ctx
, pos
);
603 m4af_write32(ctx
, current_pos
- pos
);
604 m4af_set_pos(ctx
, current_pos
);
608 void m4af_write_descriptor(m4af_ctx_t
*ctx
, uint32_t tag
, uint32_t size
)
612 buf
[1] = ((size
>> 21) | 0x80);
613 buf
[2] = ((size
>> 14) | 0x80);
614 buf
[3] = ((size
>> 7) | 0x80);
615 buf
[4] = (size
& 0x7f);
616 m4af_write(ctx
, buf
, 5);
620 void m4af_write_ftyp_box(m4af_ctx_t
*ctx
)
622 m4af_write(ctx
, "\0\0\0\040""ftypM4A \0\0\0\0M4A mp42isom\0\0\0\0", 32);
626 void m4af_write_free_box(m4af_ctx_t
*ctx
, uint32_t size
)
628 int64_t pos
= m4af_tell(ctx
);
629 m4af_write32(ctx
, size
+ 8);
630 m4af_write(ctx
, "free", 4);
632 m4af_set_pos(ctx
, pos
+ size
+ 8);
635 int m4af_begin_write(m4af_ctx_t
*ctx
)
637 m4af_write_ftyp_box(ctx
);
638 m4af_write_free_box(ctx
, 0);
639 m4af_write(ctx
, "\0\0\0\0mdat", 8);
640 ctx
->mdat_pos
= m4af_tell(ctx
);
641 return ctx
->last_error
;
645 void m4af_write_stco_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
647 m4af_track_t
*track
= &ctx
->track
[track_idx
];
649 m4af_chunk_entry_t
*index
= track
->chunk_table
;
650 int is_co64
= (ctx
->mdat_pos
+ ctx
->mdat_size
> UINT32_MAX
);
651 int64_t pos
= m4af_tell(ctx
);
653 m4af_write32(ctx
, 0); /* size */
654 m4af_write(ctx
, is_co64
? "co64" : "stco", 4);
655 m4af_write32(ctx
, 0); /* version and flags */
656 m4af_write32(ctx
, track
->num_chunks
);
657 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
659 m4af_write64(ctx
, index
->offset
);
661 m4af_write32(ctx
, index
->offset
);
663 m4af_update_box_size(ctx
, pos
);
667 void m4af_write_stsz_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
669 m4af_track_t
*track
= &ctx
->track
[track_idx
];
670 m4af_sample_entry_t
*index
= track
->sample_table
;
672 int64_t pos
= m4af_tell(ctx
);
674 "\0\0\0\0" /* size */
678 "\0\0\0\0" /* sample_size: 0(variable) */
680 m4af_write32(ctx
, track
->num_samples
);
681 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
)
682 m4af_write32(ctx
, index
->size
);
683 m4af_update_box_size(ctx
, pos
);
687 void m4af_write_stsc_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
689 m4af_track_t
*track
= &ctx
->track
[track_idx
];
690 m4af_chunk_entry_t
*index
= track
->chunk_table
;
691 uint32_t i
, prev_samples_per_chunk
= 0, entry_count
= 0;
692 int64_t pos
= m4af_tell(ctx
);
694 "\0\0\0\0" /* size */
698 "\0\0\0\0" /* entry_count */
701 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
702 if (index
->samples_per_chunk
!= prev_samples_per_chunk
) {
704 m4af_write32(ctx
, i
+ 1);
705 m4af_write32(ctx
, index
->samples_per_chunk
);
706 m4af_write32(ctx
, 1); /* sample_description_index */
707 prev_samples_per_chunk
= index
->samples_per_chunk
;
710 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
711 m4af_update_box_size(ctx
, pos
);
715 void m4af_write_stts_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
717 m4af_track_t
*track
= &ctx
->track
[track_idx
];
718 m4af_sample_entry_t
*index
= track
->sample_table
;
719 uint32_t i
, prev_delta
= 0, entry_count
= 0, sample_count
= 0;
720 int64_t pos
= m4af_tell(ctx
);
722 "\0\0\0\0" /* size */
726 "\0\0\0\0" /* entry_count */
729 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
) {
730 if (index
->delta
== prev_delta
)
735 m4af_write32(ctx
, sample_count
);
736 m4af_write32(ctx
, prev_delta
);
738 prev_delta
= index
->delta
;
743 m4af_write32(ctx
, sample_count
);
744 m4af_write32(ctx
, prev_delta
);
746 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
747 m4af_update_box_size(ctx
, pos
);
751 void m4af_write_esds_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
753 m4af_track_t
*track
= &ctx
->track
[track_idx
];
754 int64_t pos
= m4af_tell(ctx
);
755 m4af_write(ctx
, "\0\0\0\0esds", 8);
756 m4af_write32(ctx
, 0); /* version + flags */
759 m4af_write_descriptor(ctx
, 3, 32 + track
->decSpecificInfoSize
);
760 m4af_write(ctx
, "\0\0\0", 3);
761 /* DecoderConfigDescriptor */
762 m4af_write_descriptor(ctx
, 4, 18 + track
->decSpecificInfoSize
);
764 "\x40" /* objectTypeIndication: 0x40(Audio ISO/IEC 14496-3)*/
765 "\x15" /* streamType(6): 0x05(AudioStream)
770 m4af_write24(ctx
, track
->bufferSizeDB
);
771 m4af_write32(ctx
, track
->maxBitrate
);
772 m4af_write32(ctx
, track
->avgBitrate
);
773 /* DecoderSpecificInfo */
774 m4af_write_descriptor(ctx
, 5, track
->decSpecificInfoSize
);
775 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
776 /* SLConfigDescriptor */
777 m4af_write_descriptor(ctx
, 6, 1);
778 m4af_write(ctx
, "\002", 1); /* predefined */
780 m4af_update_box_size(ctx
, pos
);
784 void m4af_write_alac_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
786 m4af_track_t
*track
= &ctx
->track
[track_idx
];
787 int64_t pos
= m4af_tell(ctx
);
789 "\0\0\0\0" /* size */
794 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
795 m4af_update_box_size(ctx
, pos
);
799 void m4af_write_mp4a_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
801 m4af_track_t
*track
= &ctx
->track
[track_idx
];
802 int64_t pos
= m4af_tell(ctx
);
803 m4af_write32(ctx
, 0); /* size */
804 m4af_write32(ctx
, track
->codec
); /* mp4a or alac */
806 "\0\0\0\0\0\0" /* reserved */
807 "\0\001" /* data_reference_index: 1 */
808 "\0\0\0\0" /* reserved[0] */
809 "\0\0\0\0" /* reserved[1] */
810 "\0\002" /* channelcount: 2 */
811 "\0\020" /* samplesize: 16 */
812 "\0\0" /* pre_defined */
813 "\0\0" /* reserved */
815 if (track
->codec
== M4AF_FOURCC('m','p','4','a')) {
816 m4af_write32(ctx
, track
->timescale
<< 16);
817 m4af_write_esds_box(ctx
, track_idx
);
819 m4af_write32(ctx
, 44100 << 16);
820 m4af_write_alac_box(ctx
, track_idx
);
822 m4af_update_box_size(ctx
, pos
);
826 void m4af_write_stsd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
828 int64_t pos
= m4af_tell(ctx
);
829 m4af_write(ctx
, "\0\0\0\0stsd", 8);
833 "\0\0\0\001" /* entry_count: 1 */
835 m4af_write_mp4a_box(ctx
, track_idx
);
836 m4af_update_box_size(ctx
, pos
);
840 void m4af_write_sbgp_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
842 m4af_track_t
*track
= &ctx
->track
[track_idx
];
844 "\0\0\0\034" /* size: 28 */
848 "roll" /* grouping_type */
849 "\0\0\0\001" /* entry_count: 1 */
851 m4af_write32(ctx
, track
->num_samples
);
852 m4af_write32(ctx
, 1); /* group_description_index */
856 void m4af_write_sgpd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
858 m4af_track_t
*track
= &ctx
->track
[track_idx
];
860 "\0\0\0\032" /* size */
864 "roll" /* grouping_type */
865 "\0\0\0\002" /* default_length: 2 */
866 "\0\0\0\001" /* entry_count: 1 */
867 "\377\377" /* payload_data: -1 */
872 void m4af_write_stbl_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
874 m4af_track_t
*track
= &ctx
->track
[track_idx
];
875 int64_t pos
= m4af_tell(ctx
);
876 m4af_write(ctx
, "\0\0\0\0stbl", 8);
877 m4af_write_stsd_box(ctx
, track_idx
);
878 if ((ctx
->priming_mode
& M4AF_PRIMING_MODE_EDTS
) &&
879 (track
->encoder_delay
|| track
->padding
)) {
880 m4af_write_sbgp_box(ctx
, track_idx
);
881 m4af_write_sgpd_box(ctx
, track_idx
);
883 m4af_write_stts_box(ctx
, track_idx
);
884 m4af_write_stsc_box(ctx
, track_idx
);
885 m4af_write_stsz_box(ctx
, track_idx
);
886 m4af_write_stco_box(ctx
, track_idx
);
887 m4af_update_box_size(ctx
, pos
);
891 void m4af_write_url_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
894 "\0\0\0\014" /* size */
897 "\0\0\001" /* flags: 1(in the same file) */
902 void m4af_write_dref_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
904 int64_t pos
= m4af_tell(ctx
);
905 m4af_write(ctx
, "\0\0\0\0dref", 8);
909 "\0\0\0\001" /* entry_count: 1 */
911 m4af_write_url_box(ctx
, track_idx
);
912 m4af_update_box_size(ctx
, pos
);
916 void m4af_write_dinf_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
918 int64_t pos
= m4af_tell(ctx
);
919 m4af_write(ctx
, "\0\0\0\0dinf", 8);
920 m4af_write_dref_box(ctx
, track_idx
);
921 m4af_update_box_size(ctx
, pos
);
925 void m4af_write_smhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
928 "\0\0\0\020" /* size */
933 "\0\0" /* reserved */
938 void m4af_write_minf_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
940 m4af_track_t
*track
= &ctx
->track
[track_idx
];
941 int64_t pos
= m4af_tell(ctx
);
942 m4af_write(ctx
, "\0\0\0\0minf", 8);
943 /* TODO: add TEXT support */
944 if (track
->codec
!= M4AF_CODEC_TEXT
)
945 m4af_write_smhd_box(ctx
, track_idx
);
946 m4af_write_dinf_box(ctx
, track_idx
);
947 m4af_write_stbl_box(ctx
, track_idx
);
948 m4af_update_box_size(ctx
, pos
);
952 void m4af_write_mdhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
954 m4af_track_t
*track
= &ctx
->track
[track_idx
];
955 int64_t pos
= m4af_tell(ctx
);
956 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
957 track
->modification_time
> UINT32_MAX
||
958 track
->duration
> UINT32_MAX
);
960 m4af_write(ctx
, "\0\0\0\0mdhd", 8);
961 m4af_write(ctx
, &version
, 1);
962 m4af_write(ctx
, "\0\0\0", 3); /* flags */
964 m4af_write64(ctx
, track
->creation_time
);
965 m4af_write64(ctx
, track
->modification_time
);
966 m4af_write32(ctx
, track
->timescale
);
967 m4af_write64(ctx
, track
->duration
);
969 m4af_write32(ctx
, track
->creation_time
);
970 m4af_write32(ctx
, track
->modification_time
);
971 m4af_write32(ctx
, track
->timescale
);
972 m4af_write32(ctx
, track
->duration
);
975 "\x55\xc4" /* language: und */
976 "\0\0" /* pre_defined */
978 m4af_update_box_size(ctx
, pos
);
982 void m4af_write_hdlr_box(m4af_ctx_t
*ctx
, uint32_t track_idx
, const char *type
)
984 int64_t pos
= m4af_tell(ctx
);
985 static const char reserved_and_name
[10] = { 0 };
988 "\0\0\0\0" /* size */
992 "\0\0\0\0" /* pre_defined */
994 m4af_write(ctx
, type
, 4); /* handler_type */
996 m4af_write(ctx
, !strcmp(type
, "mdir") ? "appl" : "\0\0\0\0", 4);
997 /* reserved[1], reserved[2], name */
998 m4af_write(ctx
, reserved_and_name
, (pos
& 1) ? 9 : 10);
999 m4af_update_box_size(ctx
, pos
);
1003 void m4af_write_mdia_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1005 m4af_track_t
*track
= &ctx
->track
[track_idx
];
1007 (track
->codec
== M4AF_CODEC_TEXT
) ? "text" : "soun";
1008 int64_t pos
= m4af_tell(ctx
);
1009 m4af_write(ctx
, "\0\0\0\0mdia", 8);
1010 m4af_write_mdhd_box(ctx
, track_idx
);
1011 m4af_write_hdlr_box(ctx
, track_idx
, hdlr
);
1012 m4af_write_minf_box(ctx
, track_idx
);
1013 m4af_update_box_size(ctx
, pos
);
1017 void m4af_write_elst_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1019 m4af_track_t
*track
= &ctx
->track
[track_idx
];
1021 int64_t duration
= track
->duration
- track
->encoder_delay
- track
->padding
;
1022 int64_t pos
= m4af_tell(ctx
);
1023 duration
= (double)duration
/ track
->timescale
* ctx
->timescale
+ .5;
1024 version
= (duration
> UINT32_MAX
);
1026 m4af_write(ctx
, "\0\0\0\0elst", 8);
1027 m4af_write(ctx
, &version
, 1);
1028 m4af_write(ctx
, "\0\0\0", 3); /* flags */
1029 m4af_write32(ctx
, 1); /* entry_count: 1 */
1031 m4af_write64(ctx
, duration
);
1032 m4af_write64(ctx
, track
->encoder_delay
);
1034 m4af_write32(ctx
, duration
);
1035 m4af_write32(ctx
, track
->encoder_delay
);
1037 m4af_write16(ctx
, 1); /* media_rate_integer */
1038 m4af_write16(ctx
, 0); /* media_rate_fraction */
1039 m4af_update_box_size(ctx
, pos
);
1043 void m4af_write_edts_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1045 m4af_track_t
*track
= &ctx
->track
[track_idx
];
1046 int64_t pos
= m4af_tell(ctx
);
1047 m4af_write(ctx
, "\0\0\0\0edts", 8);
1048 m4af_write_elst_box(ctx
, track_idx
);
1049 m4af_update_box_size(ctx
, pos
);
1053 void m4af_write_tkhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1055 m4af_track_t
*track
= &ctx
->track
[track_idx
];
1056 int64_t pos
= m4af_tell(ctx
);
1058 (double)track
->duration
/ track
->timescale
* ctx
->timescale
+ .5;
1059 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
1060 track
->modification_time
> UINT32_MAX
||
1061 duration
> UINT32_MAX
);
1062 m4af_write(ctx
, "\0\0\0\0tkhd", 8);
1063 m4af_write(ctx
, &version
, 1);
1064 m4af_write(ctx
, "\0\0\007", 3); /* flags */
1066 m4af_write64(ctx
, track
->creation_time
);
1067 m4af_write64(ctx
, track
->modification_time
);
1068 m4af_write32(ctx
, track_idx
+ 1);
1069 m4af_write(ctx
, "\0\0\0\0" /* reserved */
1071 m4af_write64(ctx
, duration
);
1073 m4af_write32(ctx
, track
->creation_time
);
1074 m4af_write32(ctx
, track
->modification_time
);
1075 m4af_write32(ctx
, track_idx
+ 1);
1076 m4af_write(ctx
, "\0\0\0\0" /* reserved */
1078 m4af_write32(ctx
, duration
);
1081 "\0\0\0\0" /* reserved[0] */
1082 "\0\0\0\0" /* reserved[1] */
1084 "\0\0" /* alternate_group */
1085 "\001\0" /* volume: 1.0 */
1086 "\0\0" /* reserved */
1087 "\0\001\0\0" /* matrix[0] */
1088 "\0\0\0\0" /* matrix[1] */
1089 "\0\0\0\0" /* matrix[2] */
1090 "\0\0\0\0" /* matrix[3] */
1091 "\0\001\0\0" /* matrix[4] */
1092 "\0\0\0\0" /* matrix[5] */
1093 "\0\0\0\0" /* matrix[6] */
1094 "\0\0\0\0" /* matrix[7] */
1095 "\100\0\0\0" /* matrix[8] */
1096 "\0\0\0\0" /* width */
1097 "\0\0\0\0" /* height */
1099 m4af_update_box_size(ctx
, pos
);
1103 void m4af_write_trak_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1105 m4af_track_t
*track
= &ctx
->track
[track_idx
];
1106 int64_t pos
= m4af_tell(ctx
);
1107 m4af_write(ctx
, "\0\0\0\0trak", 8);
1108 m4af_write_tkhd_box(ctx
, track_idx
);
1109 if ((ctx
->priming_mode
& M4AF_PRIMING_MODE_EDTS
) &&
1110 (track
->encoder_delay
|| track
->padding
))
1111 m4af_write_edts_box(ctx
, track_idx
);
1112 m4af_write_mdia_box(ctx
, track_idx
);
1113 m4af_update_box_size(ctx
, pos
);
1117 int64_t m4af_movie_duration(m4af_ctx_t
*ctx
)
1119 int64_t movie_duration
= 0;
1121 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1122 double x
= ctx
->track
[i
].duration
;
1123 int64_t duration
= x
/ ctx
->track
[i
].timescale
* ctx
->timescale
+ .5;
1124 if (duration
> movie_duration
)
1125 movie_duration
= duration
;
1127 return movie_duration
;
1131 void m4af_write_mvhd_box(m4af_ctx_t
*ctx
)
1133 int64_t pos
= m4af_tell(ctx
);
1134 int64_t movie_duration
= m4af_movie_duration(ctx
);
1135 uint8_t version
= (ctx
->creation_time
> UINT32_MAX
||
1136 ctx
->modification_time
> UINT32_MAX
||
1137 movie_duration
> UINT32_MAX
);
1139 m4af_write(ctx
, "\0\0\0\0mvhd", 8);
1140 m4af_write(ctx
, &version
, 1);
1141 m4af_write(ctx
, "\0\0\0", 3); /* flags */
1143 m4af_write64(ctx
, ctx
->creation_time
);
1144 m4af_write64(ctx
, ctx
->modification_time
);
1145 m4af_write32(ctx
, ctx
->timescale
);
1146 m4af_write64(ctx
, movie_duration
);
1148 m4af_write32(ctx
, ctx
->creation_time
);
1149 m4af_write32(ctx
, ctx
->modification_time
);
1150 m4af_write32(ctx
, ctx
->timescale
);
1151 m4af_write32(ctx
, movie_duration
);
1154 "\0\001\0\0" /* rate: 1.0 */
1155 "\001\0" /* volume: 1.0 */
1156 "\0\0" /* reserved */
1157 "\0\0\0\0" /* reserved[0] */
1158 "\0\0\0\0" /* reserved[1] */
1159 "\0\001\0\0" /* matrix[0] */
1160 "\0\0\0\0" /* matrix[1] */
1161 "\0\0\0\0" /* matrix[2] */
1162 "\0\0\0\0" /* matrix[3] */
1163 "\0\001\0\0" /* matrix[4] */
1164 "\0\0\0\0" /* matrix[5] */
1165 "\0\0\0\0" /* matrix[6] */
1166 "\0\0\0\0" /* matrix[7] */
1167 "\100\0\0\0" /* matrix[8] */
1168 "\0\0\0\0" /* pre_defined[0] */
1169 "\0\0\0\0" /* pre_defined[1] */
1170 "\0\0\0\0" /* pre_defined[2] */
1171 "\0\0\0\0" /* pre_defined[3] */
1172 "\0\0\0\0" /* pre_defined[4] */
1173 "\0\0\0\0" /* pre_defined[5] */
1175 m4af_write32(ctx
, ctx
->num_tracks
+ 1);
1176 m4af_update_box_size(ctx
, pos
);
1180 void m4af_write_mean_box(m4af_ctx_t
*ctx
)
1183 "\0\0\0\034" /* size */
1186 "\0\0\0" /* flags */
1187 "com.apple.iTunes" /* meaning-string */
1192 void m4af_write_name_box(m4af_ctx_t
*ctx
, const char *name
)
1194 int64_t pos
= m4af_tell(ctx
);
1196 "\0\0\0\0" /* size */
1199 "\0\0\0" /* flags */
1201 m4af_write(ctx
, name
, strlen(name
));
1202 m4af_update_box_size(ctx
, pos
);
1206 void m4af_write_data_box(m4af_ctx_t
*ctx
, uint32_t type_code
,
1207 const char *data
, uint32_t data_size
)
1209 int64_t pos
= m4af_tell(ctx
);
1210 uint8_t code
= type_code
;
1212 "\0\0\0\0" /* size */
1214 "\0\0" /* reserved */
1215 "\0" /* type_set_indifier */
1217 m4af_write(ctx
, &code
, 1);
1218 m4af_write(ctx
, "\0\0\0\0", 4); /* locale */
1219 m4af_write(ctx
, data
, data_size
);
1220 m4af_update_box_size(ctx
, pos
);
1224 void m4af_write_metadata(m4af_ctx_t
*ctx
, m4af_itmf_entry_t
*entry
)
1226 int64_t pos
= m4af_tell(ctx
);
1227 m4af_write(ctx
, "\0\0\0\0", 4);
1228 m4af_write32(ctx
, entry
->fcc
);
1229 if (entry
->fcc
!= M4AF_FOURCC('-','-','-','-'))
1230 m4af_write_data_box(ctx
, entry
->type_code
,
1231 entry
->data
, entry
->data_size
);
1233 m4af_write_mean_box(ctx
);
1234 m4af_write_name_box(ctx
, entry
->name
);
1235 m4af_write_data_box(ctx
, 1, entry
->data
, entry
->data_size
);
1237 m4af_update_box_size(ctx
, pos
);
1241 void m4af_write_ilst_box(m4af_ctx_t
*ctx
)
1244 int64_t pos
= m4af_tell(ctx
);
1245 m4af_write(ctx
, "\0\0\0\0ilst", 8);
1246 for (i
= 0; i
< ctx
->num_tags
; ++i
)
1247 m4af_write_metadata(ctx
, &ctx
->itmf_table
[i
]);
1248 m4af_update_box_size(ctx
, pos
);
1252 void m4af_write_meta_box(m4af_ctx_t
*ctx
)
1254 int64_t pos
= m4af_tell(ctx
);
1256 "\0\0\0\0" /* size */
1259 "\0\0\0" /* flags */
1261 m4af_write_hdlr_box(ctx
, 0, "mdir");
1262 m4af_write_ilst_box(ctx
);
1263 m4af_update_box_size(ctx
, pos
);
1267 void m4af_write_udta_box(m4af_ctx_t
*ctx
)
1269 int64_t pos
= m4af_tell(ctx
);
1270 m4af_write(ctx
, "\0\0\0\0udta", 8);
1271 m4af_write_meta_box(ctx
);
1272 m4af_update_box_size(ctx
, pos
);
1276 void m4af_write_moov_box(m4af_ctx_t
*ctx
)
1279 int64_t pos
= m4af_tell(ctx
);
1280 m4af_write(ctx
, "\0\0\0\0moov", 8);
1281 m4af_write_mvhd_box(ctx
);
1282 for (i
= 0; i
< ctx
->num_tracks
; ++i
)
1283 m4af_write_trak_box(ctx
, i
);
1285 m4af_write_udta_box(ctx
);
1286 m4af_update_box_size(ctx
, pos
);
1290 void m4af_finalize_mdat(m4af_ctx_t
*ctx
)
1292 if (ctx
->mdat_size
+ 8 > UINT32_MAX
) {
1293 m4af_set_pos(ctx
, ctx
->mdat_pos
- 16);
1294 m4af_write32(ctx
, 1);
1295 m4af_write(ctx
, "mdat", 4);
1296 m4af_write64(ctx
, ctx
->mdat_size
+ 16);
1298 m4af_set_pos(ctx
, ctx
->mdat_pos
- 8);
1299 m4af_write32(ctx
, ctx
->mdat_size
+ 8);
1301 m4af_set_pos(ctx
, ctx
->mdat_pos
+ ctx
->mdat_size
);
1304 int m4af_finalize(m4af_ctx_t
*ctx
)
1307 m4af_track_t
*track
;
1309 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1310 track
= ctx
->track
+ i
;
1311 if (track
->duration
) {
1312 int64_t track_size
= 0;
1314 for (j
= 0; j
< track
->num_chunks
; ++j
)
1315 track_size
+= track
->chunk_table
[j
].size
;
1317 8.0 * track_size
* track
->timescale
/ track
->duration
+ .5;
1319 m4af_flush_chunk(ctx
, i
);
1322 if ((ctx
->priming_mode
& M4AF_PRIMING_MODE_ITUNSMPB
) &&
1323 (track
->encoder_delay
|| track
->padding
))
1324 m4af_set_iTunSMPB(ctx
);
1325 m4af_finalize_mdat(ctx
);
1326 m4af_write_moov_box(ctx
);
1327 return ctx
->last_error
;