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
;
84 m4af_itmf_entry_t
*itmf_table
;
86 uint32_t itmf_table_capacity
;
88 m4af_io_callbacks_t io
;
92 m4af_track_t track
[2];
94 m4af_itmf_entry_t current_tag
;
97 typedef struct m4af_box_parser_t
{
99 int (*handler
)(m4af_ctx_t
*ctx
, uint32_t name
, uint64_t size
);
103 int64_t m4af_timestamp(void)
105 return (int64_t)(time(0)) + (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
109 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
112 uint32_t m4af_roundup(uint32_t n
)
125 int64_t m4af_tell(m4af_ctx_t
*ctx
)
128 if ((pos
= ctx
->io
.tell(ctx
->io_cookie
)) < 0)
129 ctx
->last_error
= M4AF_IO_ERROR
;
134 int m4af_set_pos(m4af_ctx_t
*ctx
, int64_t pos
)
137 if ((rc
= ctx
->io
.seek(ctx
->io_cookie
, pos
, SEEK_SET
)) < 0)
138 ctx
->last_error
= M4AF_IO_ERROR
;
143 int m4af_write(m4af_ctx_t
*ctx
, const void *data
, uint32_t size
)
146 if ((rc
= ctx
->io
.write(ctx
->io_cookie
, data
, size
)) < 0)
147 ctx
->last_error
= M4AF_IO_ERROR
;
152 int m4af_write32(m4af_ctx_t
*ctx
, uint32_t data
)
154 data
= m4af_htob32(data
);
155 return m4af_write(ctx
, &data
, 4);
159 int m4af_write64(m4af_ctx_t
*ctx
, uint64_t data
)
161 data
= m4af_htob64(data
);
162 return m4af_write(ctx
, &data
, 8);
166 int m4af_write24(m4af_ctx_t
*ctx
, uint32_t data
)
168 data
= m4af_htob32(data
<< 8);
169 return m4af_write(ctx
, &data
, 3);
173 void m4af_write32_at(m4af_ctx_t
*ctx
, int64_t pos
, uint32_t value
)
175 int64_t current_pos
= m4af_tell(ctx
);
176 m4af_set_pos(ctx
, pos
);
177 m4af_write32(ctx
, value
);
178 m4af_set_pos(ctx
, current_pos
);
181 m4af_ctx_t
*m4af_create(uint32_t codec
, uint32_t timescale
,
182 m4af_io_callbacks_t
*io
, void *io_cookie
)
187 if (codec
!= M4AF_FOURCC('m','p','4','a') &&
188 codec
!= M4AF_FOURCC('a','l','a','c'))
190 if ((ctx
= m4af_realloc(0, sizeof(m4af_ctx_t
))) == 0)
192 memset(ctx
, 0, sizeof(m4af_ctx_t
));
193 memcpy(&ctx
->io
, io
, sizeof(m4af_io_callbacks_t
));
194 ctx
->io_cookie
= io_cookie
;
195 ctx
->timescale
= timescale
;
196 timestamp
= m4af_timestamp();
197 ctx
->creation_time
= timestamp
;
198 ctx
->modification_time
= timestamp
;
200 ctx
->track
[0].codec
= codec
;
201 ctx
->track
[0].timescale
= timescale
;
202 ctx
->track
[0].creation_time
= timestamp
;
203 ctx
->track
[0].modification_time
= timestamp
;
208 void m4af_free_itmf_table(m4af_ctx_t
*ctx
)
211 m4af_itmf_entry_t
*entry
= ctx
->itmf_table
;
212 for (i
= 0; i
< ctx
->num_tags
; ++i
, ++entry
) {
213 if (entry
->fcc
== M4AF_FOURCC('-','-','-','-'))
214 m4af_free(entry
->name
);
215 m4af_free(entry
->data
);
217 m4af_free(ctx
->itmf_table
);
221 void m4af_clear_track(m4af_ctx_t
*ctx
, int track_idx
)
223 m4af_track_t
*track
= ctx
->track
+ track_idx
;
224 if (track
->decSpecificInfo
)
225 m4af_free(track
->decSpecificInfo
);
226 if (track
->sample_table
)
227 m4af_free(track
->sample_table
);
228 if (track
->chunk_table
)
229 m4af_free(track
->chunk_table
);
230 if (track
->chunk_buffer
)
231 m4af_free(track
->chunk_buffer
);
232 memset(track
, 0, sizeof(m4af_track_t
));
235 void m4af_teardown(m4af_ctx_t
**ctxp
)
238 m4af_ctx_t
*ctx
= *ctxp
;
239 for (i
= 0; i
< ctx
->num_tracks
; ++i
)
240 m4af_clear_track(ctx
, i
);
242 m4af_free_itmf_table(ctx
);
247 void m4af_set_fixed_frame_duration(m4af_ctx_t
*ctx
, uint32_t track_idx
,
250 ctx
->track
[track_idx
].frame_duration
= length
;
253 int m4af_set_decoder_specific_info(m4af_ctx_t
*ctx
, uint32_t track_idx
,
254 uint8_t *data
, uint32_t size
)
256 m4af_track_t
*track
= &ctx
->track
[track_idx
];
257 if (size
> track
->decSpecificInfoSize
) {
258 uint8_t *memory
= m4af_realloc(track
->decSpecificInfo
, size
);
260 ctx
->last_error
= M4AF_NO_MEMORY
;
263 track
->decSpecificInfo
= memory
;
266 memcpy(track
->decSpecificInfo
, data
, size
);
267 track
->decSpecificInfoSize
= size
;
269 return ctx
->last_error
;
272 void m4af_set_priming(m4af_ctx_t
*ctx
, uint32_t track_idx
,
273 uint32_t encoder_delay
, uint32_t padding
)
275 m4af_track_t
*track
= &ctx
->track
[track_idx
];
276 track
->encoder_delay
= encoder_delay
;
277 track
->padding
= padding
;
281 int m4af_add_sample_entry(m4af_ctx_t
*ctx
, uint32_t track_idx
,
282 uint32_t size
, uint32_t delta
)
284 m4af_track_t
*track
= &ctx
->track
[track_idx
];
285 m4af_sample_entry_t
*entry
;
289 if (track
->num_samples
== track
->sample_table_capacity
) {
290 uint32_t new_size
= track
->sample_table_capacity
;
291 new_size
= new_size
? new_size
* 2 : 1;
292 entry
= m4af_realloc(track
->sample_table
, new_size
* sizeof(*entry
));
294 ctx
->last_error
= M4AF_NO_MEMORY
;
297 track
->sample_table
= entry
;
298 track
->sample_table_capacity
= new_size
;
300 entry
= track
->sample_table
+ track
->num_samples
;
302 entry
->delta
= delta
;
303 ++track
->num_samples
;
308 int m4af_flush_chunk(m4af_ctx_t
*ctx
, uint32_t track_idx
)
310 m4af_track_t
*track
= &ctx
->track
[track_idx
];
311 m4af_chunk_entry_t
*entry
;
312 if (!track
->num_chunks
|| !track
->chunk_size
)
314 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
315 entry
->offset
= m4af_tell(ctx
);
316 m4af_write(ctx
, track
->chunk_buffer
, track
->chunk_size
);
317 ctx
->mdat_size
+= track
->chunk_size
;
318 track
->chunk_size
= 0;
319 return ctx
->last_error
? -1 : 0;
323 int m4af_add_chunk_entry(m4af_ctx_t
*ctx
, uint32_t track_idx
)
325 m4af_track_t
*track
= &ctx
->track
[track_idx
];
326 m4af_chunk_entry_t
*entry
;
327 if (track
->num_chunks
== track
->chunk_table_capacity
) {
328 uint32_t new_size
= track
->chunk_table_capacity
;
329 new_size
= new_size
? new_size
* 2 : 1;
330 entry
= m4af_realloc(track
->chunk_table
, new_size
* sizeof(*entry
));
332 ctx
->last_error
= M4AF_NO_MEMORY
;
335 track
->chunk_table
= entry
;
336 track
->chunk_table_capacity
= new_size
;
338 memset(&track
->chunk_table
[track
->num_chunks
++], 0,
339 sizeof(m4af_chunk_entry_t
));
344 int m4af_update_chunk_table(m4af_ctx_t
*ctx
, uint32_t track_idx
,
345 uint32_t size
, uint32_t delta
)
347 m4af_track_t
*track
= &ctx
->track
[track_idx
];
348 m4af_chunk_entry_t
*entry
;
349 int add_new_chunk
= 0;
353 if (track
->num_chunks
== 0)
356 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
357 if (entry
->duration
+ delta
> track
->timescale
/ 2)
361 m4af_flush_chunk(ctx
, track_idx
);
362 if (m4af_add_chunk_entry(ctx
, track_idx
) < 0)
365 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
367 ++entry
->samples_per_chunk
;
368 entry
->duration
+= delta
;
373 void m4af_update_max_bitrate(m4af_ctx_t
*ctx
, uint32_t track_idx
)
375 m4af_track_t
*track
= &ctx
->track
[track_idx
];
376 uint32_t duration
= 0, size
= 0, bitrate
;
377 m4af_sample_entry_t
*ent
= track
->sample_table
+ track
->num_samples
- 1;
379 for (; ent
>= track
->sample_table
&& duration
< track
->timescale
; --ent
) {
380 duration
+= ent
->delta
;
383 bitrate
= (uint32_t)(size
* 8.0 * track
->timescale
/ duration
+ .5);
384 if (bitrate
> track
->maxBitrate
)
385 track
->maxBitrate
= bitrate
;
389 int m4af_append_sample_to_chunk(m4af_ctx_t
*ctx
, uint32_t track_idx
,
390 const void *data
, uint32_t size
)
392 m4af_track_t
*track
= &ctx
->track
[track_idx
];
393 uint32_t newsize
= track
->chunk_size
+ size
;
397 if (track
->chunk_capacity
< newsize
) {
398 uint32_t capacity
= m4af_roundup(newsize
);
399 uint8_t *memory
= realloc(track
->chunk_buffer
, capacity
);
401 ctx
->last_error
= M4AF_NO_MEMORY
;
404 track
->chunk_buffer
= memory
;
405 track
->chunk_capacity
= capacity
;
407 memcpy(track
->chunk_buffer
+ track
->chunk_size
, data
, size
);
408 track
->chunk_size
= newsize
;
412 int m4af_write_sample(m4af_ctx_t
*ctx
, uint32_t track_idx
, const void *data
,
413 uint32_t size
, uint32_t duration
)
415 m4af_track_t
*track
= &ctx
->track
[track_idx
];
416 if (track
->frame_duration
)
417 duration
= track
->frame_duration
;
418 if (size
> track
->bufferSizeDB
)
419 track
->bufferSizeDB
= size
;
420 track
->duration
+= duration
;
421 m4af_add_sample_entry(ctx
, track_idx
, size
, duration
);
422 m4af_update_chunk_table(ctx
, track_idx
, size
, duration
);
423 m4af_update_max_bitrate(ctx
, track_idx
);
424 m4af_append_sample_to_chunk(ctx
, track_idx
, data
, size
);
425 return ctx
->last_error
;
429 m4af_itmf_entry_t
*m4af_find_itmf_slot(m4af_ctx_t
*ctx
, uint32_t fcc
,
432 m4af_itmf_entry_t
*entry
= ctx
->itmf_table
;
435 fcc
= M4AF_FOURCC('-','-','-','-');
437 if (fcc
!= M4AF_TAG_ARTWORK
)
438 for (; entry
!= ctx
->itmf_table
+ ctx
->num_tags
; ++entry
)
439 if (fcc
== entry
->fcc
&& (!name
|| !strcmp(name
, entry
->name
)))
442 if (ctx
->num_tags
== ctx
->itmf_table_capacity
) {
443 uint32_t new_size
= ctx
->itmf_table_capacity
;
444 new_size
= new_size
? new_size
* 2 : 1;
445 entry
= m4af_realloc(ctx
->itmf_table
, new_size
* sizeof(*entry
));
447 ctx
->last_error
= M4AF_NO_MEMORY
;
450 ctx
->itmf_table
= entry
;
451 ctx
->itmf_table_capacity
= new_size
;
453 entry
= &ctx
->itmf_table
[ctx
->num_tags
++];
454 memset(entry
, 0, sizeof(m4af_itmf_entry_t
));
457 char *name_copy
= m4af_realloc(0, strlen(name
) + 1);
459 ctx
->last_error
= M4AF_NO_MEMORY
;
463 strcpy(name_copy
, name
);
464 entry
->name
= name_copy
;
469 int m4af_add_itmf_long_tag(m4af_ctx_t
*ctx
, const char *name
,
472 m4af_itmf_entry_t
*entry
;
474 size_t name_len
= strlen(name
);
475 size_t data_len
= strlen(data
);
476 if (!name_len
|| !data_len
)
479 if ((entry
= m4af_find_itmf_slot(ctx
, 0, name
)) == 0)
481 entry
->type_code
= M4AF_UTF8
;
482 if ((data_copy
= m4af_realloc(entry
->data
, data_len
)) == 0) {
483 ctx
->last_error
= M4AF_NO_MEMORY
;
486 memcpy(data_copy
, data
, data_len
);
487 entry
->data
= data_copy
;
488 entry
->data_size
= data_len
;
491 return ctx
->last_error
;
494 int m4af_add_itmf_short_tag(m4af_ctx_t
*ctx
, uint32_t fcc
,
495 uint32_t type_code
, const void *data
,
498 m4af_itmf_entry_t
*entry
;
503 if ((entry
= m4af_find_itmf_slot(ctx
, fcc
, 0)) == 0)
505 entry
->type_code
= type_code
;
506 if ((data_copy
= m4af_realloc(entry
->data
, data_size
)) == 0) {
507 ctx
->last_error
= M4AF_NO_MEMORY
;
510 memcpy(data_copy
, data
, data_size
);
511 entry
->data
= data_copy
;
512 entry
->data_size
= data_size
;
515 return ctx
->last_error
;
518 int m4af_add_itmf_string_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, const char *data
)
520 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_UTF8
, data
, strlen(data
));
523 int m4af_add_itmf_int8_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, int value
)
525 uint8_t data
= value
;
526 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 1);
529 int m4af_add_itmf_int16_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, int value
)
531 uint16_t data
= m4af_htob16(value
);
532 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 2);
535 int m4af_add_itmf_int32_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, uint32_t value
)
537 uint32_t data
= m4af_htob32(value
);
538 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 4);
541 int m4af_add_itmf_int64_tag(m4af_ctx_t
*ctx
, uint32_t fcc
, uint64_t value
)
543 uint64_t data
= m4af_htob64(value
);
544 return m4af_add_itmf_short_tag(ctx
, fcc
, M4AF_INTEGER
, &data
, 8);
547 int m4af_add_itmf_track_tag(m4af_ctx_t
*ctx
, int track
, int total
)
549 uint16_t data
[4] = { 0 };
550 data
[1] = m4af_htob16(track
);
551 data
[2] = m4af_htob16(total
);
552 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('t','r','k','n'),
553 M4AF_IMPLICIT
, &data
, 8);
556 int m4af_add_itmf_disk_tag(m4af_ctx_t
*ctx
, int disk
, int total
)
558 uint16_t data
[3] = { 0 };
559 data
[1] = m4af_htob16(disk
);
560 data
[2] = m4af_htob16(total
);
561 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('d','i','s','k'),
562 M4AF_IMPLICIT
, &data
, 6);
565 int m4af_add_itmf_genre_tag(m4af_ctx_t
*ctx
, int genre
)
567 uint16_t data
= m4af_htob16(genre
);
568 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('g','n','r','e'),
569 M4AF_IMPLICIT
, &data
, 2);
573 int m4af_set_iTunSMPB(m4af_ctx_t
*ctx
)
575 const char *fmt
= " 00000000 %08X %08X %08X%08X 00000000 00000000 "
576 "00000000 00000000 00000000 00000000 00000000 00000000";
577 m4af_track_t
*track
= &ctx
->track
[0];
579 uint64_t length
= track
->duration
- track
->encoder_delay
- track
->padding
;
580 sprintf(buf
, fmt
, track
->encoder_delay
, track
->padding
,
581 (uint32_t)(length
>> 32), (uint32_t)length
);
582 return m4af_add_itmf_long_tag(ctx
, "iTunSMPB", buf
);
586 void m4af_update_box_size(m4af_ctx_t
*ctx
, int64_t pos
)
588 int64_t current_pos
= m4af_tell(ctx
);
589 m4af_set_pos(ctx
, pos
);
590 m4af_write32(ctx
, current_pos
- pos
);
591 m4af_set_pos(ctx
, current_pos
);
595 void m4af_write_descriptor(m4af_ctx_t
*ctx
, uint32_t tag
, uint32_t size
)
599 buf
[1] = ((size
>> 21) | 0x80);
600 buf
[2] = ((size
>> 14) | 0x80);
601 buf
[3] = ((size
>> 7) | 0x80);
602 buf
[4] = (size
& 0x7f);
603 m4af_write(ctx
, buf
, 5);
607 void m4af_write_ftyp_box(m4af_ctx_t
*ctx
)
609 m4af_write(ctx
, "\0\0\0\040""ftypM4A \0\0\0\0M4A mp42isom\0\0\0\0", 32);
613 void m4af_write_free_box(m4af_ctx_t
*ctx
, uint32_t size
)
615 int64_t pos
= m4af_tell(ctx
);
616 m4af_write32(ctx
, size
+ 8);
617 m4af_write(ctx
, "free", 4);
619 m4af_set_pos(ctx
, pos
+ size
+ 8);
622 int m4af_begin_write(m4af_ctx_t
*ctx
)
624 m4af_write_ftyp_box(ctx
);
625 m4af_write_free_box(ctx
, 0);
626 m4af_write(ctx
, "\0\0\0\0mdat", 8);
627 ctx
->mdat_pos
= m4af_tell(ctx
);
628 return ctx
->last_error
;
632 void m4af_write_stco_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
634 m4af_track_t
*track
= &ctx
->track
[track_idx
];
636 m4af_chunk_entry_t
*index
= track
->chunk_table
;
637 int is_co64
= (ctx
->mdat_pos
+ ctx
->mdat_size
> UINT32_MAX
);
638 int64_t pos
= m4af_tell(ctx
);
640 m4af_write32(ctx
, 0); /* size */
641 m4af_write(ctx
, is_co64
? "co64" : "stco", 4);
642 m4af_write32(ctx
, 0); /* version and flags */
643 m4af_write32(ctx
, track
->num_chunks
);
644 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
646 m4af_write64(ctx
, index
->offset
);
648 m4af_write32(ctx
, index
->offset
);
650 m4af_update_box_size(ctx
, pos
);
654 void m4af_write_stsz_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
656 m4af_track_t
*track
= &ctx
->track
[track_idx
];
657 m4af_sample_entry_t
*index
= track
->sample_table
;
659 int64_t pos
= m4af_tell(ctx
);
661 "\0\0\0\0" /* size */
665 "\0\0\0\0" /* sample_size: 0(variable) */
667 m4af_write32(ctx
, track
->num_samples
);
668 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
)
669 m4af_write32(ctx
, index
->size
);
670 m4af_update_box_size(ctx
, pos
);
674 void m4af_write_stsc_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
676 m4af_track_t
*track
= &ctx
->track
[track_idx
];
677 m4af_chunk_entry_t
*index
= track
->chunk_table
;
678 uint32_t i
, prev_samples_per_chunk
= 0, entry_count
= 0;
679 int64_t pos
= m4af_tell(ctx
);
681 "\0\0\0\0" /* size */
685 "\0\0\0\0" /* entry_count */
688 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
689 if (index
->samples_per_chunk
!= prev_samples_per_chunk
) {
691 m4af_write32(ctx
, i
+ 1);
692 m4af_write32(ctx
, index
->samples_per_chunk
);
693 m4af_write32(ctx
, 1); /* sample_description_index */
694 prev_samples_per_chunk
= index
->samples_per_chunk
;
697 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
698 m4af_update_box_size(ctx
, pos
);
702 void m4af_write_stts_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
704 m4af_track_t
*track
= &ctx
->track
[track_idx
];
705 m4af_sample_entry_t
*index
= track
->sample_table
;
706 uint32_t i
, prev_delta
= 0, entry_count
= 0, sample_count
= 0;
707 int64_t pos
= m4af_tell(ctx
);
709 "\0\0\0\0" /* size */
713 "\0\0\0\0" /* entry_count */
716 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
) {
717 if (index
->delta
== prev_delta
)
722 m4af_write32(ctx
, sample_count
);
723 m4af_write32(ctx
, prev_delta
);
725 prev_delta
= index
->delta
;
730 m4af_write32(ctx
, sample_count
);
731 m4af_write32(ctx
, prev_delta
);
733 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
734 m4af_update_box_size(ctx
, pos
);
738 void m4af_write_esds_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
740 m4af_track_t
*track
= &ctx
->track
[track_idx
];
741 int64_t pos
= m4af_tell(ctx
);
742 m4af_write(ctx
, "\0\0\0\0esds", 8);
743 m4af_write32(ctx
, 0); /* version + flags */
746 m4af_write_descriptor(ctx
, 3, 32 + track
->decSpecificInfoSize
);
747 m4af_write(ctx
, "\0\0\0", 3);
748 /* DecoderConfigDescriptor */
749 m4af_write_descriptor(ctx
, 4, 18 + track
->decSpecificInfoSize
);
751 "\x40" /* objectTypeIndication: 0x40(Audio ISO/IEC 14496-3)*/
752 "\x15" /* streamType(6): 0x05(AudioStream)
757 m4af_write24(ctx
, track
->bufferSizeDB
);
758 m4af_write32(ctx
, track
->maxBitrate
);
759 m4af_write32(ctx
, track
->avgBitrate
);
760 /* DecoderSpecificInfo */
761 m4af_write_descriptor(ctx
, 5, track
->decSpecificInfoSize
);
762 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
763 /* SLConfigDescriptor */
764 m4af_write_descriptor(ctx
, 6, 1);
765 m4af_write(ctx
, "\002", 1); /* predefined */
767 m4af_update_box_size(ctx
, pos
);
771 void m4af_write_alac_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
773 m4af_track_t
*track
= &ctx
->track
[track_idx
];
774 int64_t pos
= m4af_tell(ctx
);
776 "\0\0\0\0" /* size */
781 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
782 m4af_update_box_size(ctx
, pos
);
786 void m4af_write_mp4a_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
788 m4af_track_t
*track
= &ctx
->track
[track_idx
];
789 int64_t pos
= m4af_tell(ctx
);
790 m4af_write32(ctx
, 0); /* size */
791 m4af_write32(ctx
, track
->codec
); /* mp4a or alac */
793 "\0\0\0\0\0\0" /* reserved */
794 "\0\001" /* data_reference_index: 1 */
795 "\0\0\0\0" /* reserved[0] */
796 "\0\0\0\0" /* reserved[1] */
797 "\0\002" /* channelcount: 2 */
798 "\0\020" /* samplesize: 16 */
799 "\0\0" /* pre_defined */
800 "\0\0" /* reserved */
802 if (track
->codec
== M4AF_FOURCC('m','p','4','a')) {
803 m4af_write32(ctx
, track
->timescale
<< 16);
804 m4af_write_esds_box(ctx
, track_idx
);
806 m4af_write32(ctx
, 44100 << 16);
807 m4af_write_alac_box(ctx
, track_idx
);
809 m4af_update_box_size(ctx
, pos
);
813 void m4af_write_stsd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
815 int64_t pos
= m4af_tell(ctx
);
816 m4af_write(ctx
, "\0\0\0\0stsd", 8);
820 "\0\0\0\001" /* entry_count: 1 */
822 m4af_write_mp4a_box(ctx
, track_idx
);
823 m4af_update_box_size(ctx
, pos
);
827 void m4af_write_stbl_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
829 int64_t pos
= m4af_tell(ctx
);
830 m4af_write(ctx
, "\0\0\0\0stbl", 8);
831 m4af_write_stsd_box(ctx
, track_idx
);
832 m4af_write_stts_box(ctx
, track_idx
);
833 m4af_write_stsc_box(ctx
, track_idx
);
834 m4af_write_stsz_box(ctx
, track_idx
);
835 m4af_write_stco_box(ctx
, track_idx
);
836 m4af_update_box_size(ctx
, pos
);
840 void m4af_write_url_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
843 "\0\0\0\014" /* size */
846 "\0\0\001" /* flags: 1(in the same file) */
851 void m4af_write_dref_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
853 int64_t pos
= m4af_tell(ctx
);
854 m4af_write(ctx
, "\0\0\0\0dref", 8);
858 "\0\0\0\001" /* entry_count: 1 */
860 m4af_write_url_box(ctx
, track_idx
);
861 m4af_update_box_size(ctx
, pos
);
865 void m4af_write_dinf_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
867 int64_t pos
= m4af_tell(ctx
);
868 m4af_write(ctx
, "\0\0\0\0dinf", 8);
869 m4af_write_dref_box(ctx
, track_idx
);
870 m4af_update_box_size(ctx
, pos
);
874 void m4af_write_smhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
877 "\0\0\0\020" /* size */
882 "\0\0" /* reserved */
887 void m4af_write_minf_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
889 m4af_track_t
*track
= &ctx
->track
[track_idx
];
890 int64_t pos
= m4af_tell(ctx
);
891 m4af_write(ctx
, "\0\0\0\0minf", 8);
892 /* TODO: add TEXT support */
893 if (track
->codec
!= M4AF_CODEC_TEXT
)
894 m4af_write_smhd_box(ctx
, track_idx
);
895 m4af_write_dinf_box(ctx
, track_idx
);
896 m4af_write_stbl_box(ctx
, track_idx
);
897 m4af_update_box_size(ctx
, pos
);
901 void m4af_write_mdhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
903 m4af_track_t
*track
= &ctx
->track
[track_idx
];
904 int64_t pos
= m4af_tell(ctx
);
905 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
906 track
->modification_time
> UINT32_MAX
||
907 track
->duration
> UINT32_MAX
);
909 m4af_write(ctx
, "\0\0\0\0mdhd", 8);
910 m4af_write(ctx
, &version
, 1);
911 m4af_write(ctx
, "\0\0\0", 3); /* flags */
913 m4af_write64(ctx
, track
->creation_time
);
914 m4af_write64(ctx
, track
->modification_time
);
915 m4af_write32(ctx
, track
->timescale
);
916 m4af_write64(ctx
, track
->duration
);
918 m4af_write32(ctx
, track
->creation_time
);
919 m4af_write32(ctx
, track
->modification_time
);
920 m4af_write32(ctx
, track
->timescale
);
921 m4af_write32(ctx
, track
->duration
);
924 "\x55\xc4" /* language: und */
925 "\0\0" /* pre_defined */
927 m4af_update_box_size(ctx
, pos
);
931 void m4af_write_hdlr_box(m4af_ctx_t
*ctx
, uint32_t track_idx
, const char *type
)
933 int64_t pos
= m4af_tell(ctx
);
934 static const char reserved_and_name
[10] = { 0 };
937 "\0\0\0\0" /* size */
941 "\0\0\0\0" /* pre_defined */
943 m4af_write(ctx
, type
, 4); /* handler_type */
945 m4af_write(ctx
, !strcmp(type
, "mdir") ? "appl" : "\0\0\0\0", 4);
946 /* reserved[1], reserved[2], name */
947 m4af_write(ctx
, reserved_and_name
, (pos
& 1) ? 9 : 10);
948 m4af_update_box_size(ctx
, pos
);
952 void m4af_write_mdia_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
954 m4af_track_t
*track
= &ctx
->track
[track_idx
];
956 (track
->codec
== M4AF_CODEC_TEXT
) ? "text" : "soun";
957 int64_t pos
= m4af_tell(ctx
);
958 m4af_write(ctx
, "\0\0\0\0mdia", 8);
959 m4af_write_mdhd_box(ctx
, track_idx
);
960 m4af_write_hdlr_box(ctx
, track_idx
, hdlr
);
961 m4af_write_minf_box(ctx
, track_idx
);
962 m4af_update_box_size(ctx
, pos
);
966 void m4af_write_tkhd_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
968 m4af_track_t
*track
= &ctx
->track
[track_idx
];
969 int64_t pos
= m4af_tell(ctx
);
971 (double)track
->duration
/ track
->timescale
* ctx
->timescale
+ .5;
972 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
973 track
->modification_time
> UINT32_MAX
||
974 duration
> UINT32_MAX
);
975 m4af_write(ctx
, "\0\0\0\0tkhd", 8);
976 m4af_write(ctx
, &version
, 1);
977 m4af_write(ctx
, "\0\0\007", 3); /* flags */
979 m4af_write64(ctx
, track
->creation_time
);
980 m4af_write64(ctx
, track
->modification_time
);
981 m4af_write32(ctx
, track_idx
+ 1);
982 m4af_write(ctx
, "\0\0\0\0" /* reserved */
984 m4af_write64(ctx
, duration
);
986 m4af_write32(ctx
, track
->creation_time
);
987 m4af_write32(ctx
, track
->modification_time
);
988 m4af_write32(ctx
, track_idx
+ 1);
989 m4af_write(ctx
, "\0\0\0\0" /* reserved */
991 m4af_write32(ctx
, duration
);
994 "\0\0\0\0" /* reserved[0] */
995 "\0\0\0\0" /* reserved[1] */
997 "\0\0" /* alternate_group */
998 "\001\0" /* volume: 1.0 */
999 "\0\0" /* reserved */
1000 "\0\001\0\0" /* matrix[0] */
1001 "\0\0\0\0" /* matrix[1] */
1002 "\0\0\0\0" /* matrix[2] */
1003 "\0\0\0\0" /* matrix[3] */
1004 "\0\001\0\0" /* matrix[4] */
1005 "\0\0\0\0" /* matrix[5] */
1006 "\0\0\0\0" /* matrix[6] */
1007 "\0\0\0\0" /* matrix[7] */
1008 "\100\0\0\0" /* matrix[8] */
1009 "\0\0\0\0" /* width */
1010 "\0\0\0\0" /* height */
1012 m4af_update_box_size(ctx
, pos
);
1016 void m4af_write_trak_box(m4af_ctx_t
*ctx
, uint32_t track_idx
)
1018 int64_t pos
= m4af_tell(ctx
);
1019 m4af_write(ctx
, "\0\0\0\0trak", 8);
1020 m4af_write_tkhd_box(ctx
, track_idx
);
1021 m4af_write_mdia_box(ctx
, track_idx
);
1022 m4af_update_box_size(ctx
, pos
);
1026 int64_t m4af_movie_duration(m4af_ctx_t
*ctx
)
1028 int64_t movie_duration
= 0;
1030 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1031 double x
= ctx
->track
[i
].duration
;
1032 int64_t duration
= x
/ ctx
->track
[i
].timescale
* ctx
->timescale
+ .5;
1033 if (duration
> movie_duration
)
1034 movie_duration
= duration
;
1036 return movie_duration
;
1040 void m4af_write_mvhd_box(m4af_ctx_t
*ctx
)
1042 int64_t pos
= m4af_tell(ctx
);
1043 int64_t movie_duration
= m4af_movie_duration(ctx
);
1044 uint8_t version
= (ctx
->creation_time
> UINT32_MAX
||
1045 ctx
->modification_time
> UINT32_MAX
||
1046 movie_duration
> UINT32_MAX
);
1048 m4af_write(ctx
, "\0\0\0\0mvhd", 8);
1049 m4af_write(ctx
, &version
, 1);
1050 m4af_write(ctx
, "\0\0\0", 3); /* flags */
1052 m4af_write64(ctx
, ctx
->creation_time
);
1053 m4af_write64(ctx
, ctx
->modification_time
);
1054 m4af_write32(ctx
, ctx
->timescale
);
1055 m4af_write64(ctx
, movie_duration
);
1057 m4af_write32(ctx
, ctx
->creation_time
);
1058 m4af_write32(ctx
, ctx
->modification_time
);
1059 m4af_write32(ctx
, ctx
->timescale
);
1060 m4af_write32(ctx
, movie_duration
);
1063 "\0\001\0\0" /* rate: 1.0 */
1064 "\001\0" /* volume: 1.0 */
1065 "\0\0" /* reserved */
1066 "\0\0\0\0" /* reserved[0] */
1067 "\0\0\0\0" /* reserved[1] */
1068 "\0\001\0\0" /* matrix[0] */
1069 "\0\0\0\0" /* matrix[1] */
1070 "\0\0\0\0" /* matrix[2] */
1071 "\0\0\0\0" /* matrix[3] */
1072 "\0\001\0\0" /* matrix[4] */
1073 "\0\0\0\0" /* matrix[5] */
1074 "\0\0\0\0" /* matrix[6] */
1075 "\0\0\0\0" /* matrix[7] */
1076 "\100\0\0\0" /* matrix[8] */
1077 "\0\0\0\0" /* pre_defined[0] */
1078 "\0\0\0\0" /* pre_defined[1] */
1079 "\0\0\0\0" /* pre_defined[2] */
1080 "\0\0\0\0" /* pre_defined[3] */
1081 "\0\0\0\0" /* pre_defined[4] */
1082 "\0\0\0\0" /* pre_defined[5] */
1084 m4af_write32(ctx
, ctx
->num_tracks
+ 1);
1085 m4af_update_box_size(ctx
, pos
);
1089 void m4af_write_mean_box(m4af_ctx_t
*ctx
)
1092 "\0\0\0\034" /* size */
1095 "\0\0\0" /* flags */
1096 "com.apple.iTunes" /* meaning-string */
1101 void m4af_write_name_box(m4af_ctx_t
*ctx
, const char *name
)
1103 int64_t pos
= m4af_tell(ctx
);
1105 "\0\0\0\0" /* size */
1108 "\0\0\0" /* flags */
1110 m4af_write(ctx
, name
, strlen(name
));
1111 m4af_update_box_size(ctx
, pos
);
1115 void m4af_write_data_box(m4af_ctx_t
*ctx
, uint32_t type_code
,
1116 const char *data
, uint32_t data_size
)
1118 int64_t pos
= m4af_tell(ctx
);
1119 uint8_t code
= type_code
;
1121 "\0\0\0\0" /* size */
1123 "\0\0" /* reserved */
1124 "\0" /* type_set_indifier */
1126 m4af_write(ctx
, &code
, 1);
1127 m4af_write(ctx
, "\0\0\0\0", 4); /* locale */
1128 m4af_write(ctx
, data
, data_size
);
1129 m4af_update_box_size(ctx
, pos
);
1133 void m4af_write_metadata(m4af_ctx_t
*ctx
, m4af_itmf_entry_t
*entry
)
1135 int64_t pos
= m4af_tell(ctx
);
1136 m4af_write(ctx
, "\0\0\0\0", 4);
1137 m4af_write32(ctx
, entry
->fcc
);
1138 if (entry
->fcc
!= M4AF_FOURCC('-','-','-','-'))
1139 m4af_write_data_box(ctx
, entry
->type_code
,
1140 entry
->data
, entry
->data_size
);
1142 m4af_write_mean_box(ctx
);
1143 m4af_write_name_box(ctx
, entry
->name
);
1144 m4af_write_data_box(ctx
, 1, entry
->data
, entry
->data_size
);
1146 m4af_update_box_size(ctx
, pos
);
1150 void m4af_write_ilst_box(m4af_ctx_t
*ctx
)
1153 int64_t pos
= m4af_tell(ctx
);
1154 m4af_write(ctx
, "\0\0\0\0ilst", 8);
1155 for (i
= 0; i
< ctx
->num_tags
; ++i
)
1156 m4af_write_metadata(ctx
, &ctx
->itmf_table
[i
]);
1157 m4af_update_box_size(ctx
, pos
);
1161 void m4af_write_meta_box(m4af_ctx_t
*ctx
)
1163 int64_t pos
= m4af_tell(ctx
);
1165 "\0\0\0\0" /* size */
1168 "\0\0\0" /* flags */
1170 m4af_write_hdlr_box(ctx
, 0, "mdir");
1171 m4af_write_ilst_box(ctx
);
1172 m4af_update_box_size(ctx
, pos
);
1176 void m4af_write_udta_box(m4af_ctx_t
*ctx
)
1178 int64_t pos
= m4af_tell(ctx
);
1179 m4af_write(ctx
, "\0\0\0\0udta", 8);
1180 m4af_write_meta_box(ctx
);
1181 m4af_update_box_size(ctx
, pos
);
1185 void m4af_write_moov_box(m4af_ctx_t
*ctx
)
1188 int64_t pos
= m4af_tell(ctx
);
1189 m4af_write(ctx
, "\0\0\0\0moov", 8);
1190 m4af_write_mvhd_box(ctx
);
1191 for (i
= 0; i
< ctx
->num_tracks
; ++i
)
1192 m4af_write_trak_box(ctx
, i
);
1194 m4af_write_udta_box(ctx
);
1195 m4af_update_box_size(ctx
, pos
);
1199 void m4af_finalize_mdat(m4af_ctx_t
*ctx
)
1201 if (ctx
->mdat_size
+ 8 > UINT32_MAX
) {
1202 m4af_set_pos(ctx
, ctx
->mdat_pos
- 16);
1203 m4af_write32(ctx
, 1);
1204 m4af_write(ctx
, "mdat", 4);
1205 m4af_write64(ctx
, ctx
->mdat_size
+ 16);
1207 m4af_set_pos(ctx
, ctx
->mdat_pos
- 8);
1208 m4af_write32(ctx
, ctx
->mdat_size
+ 8);
1210 m4af_set_pos(ctx
, ctx
->mdat_pos
+ ctx
->mdat_size
);
1213 int m4af_finalize(m4af_ctx_t
*ctx
)
1216 m4af_track_t
*track
;
1218 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1219 track
= ctx
->track
+ i
;
1220 if (track
->duration
) {
1221 int64_t track_size
= 0;
1223 for (j
= 0; j
< track
->num_chunks
; ++j
)
1224 track_size
+= track
->chunk_table
[j
].size
;
1226 8.0 * track_size
* track
->timescale
/ track
->duration
+ .5;
1228 m4af_flush_chunk(ctx
, i
);
1230 if (ctx
->track
[0].encoder_delay
|| ctx
->track
[0].padding
)
1231 m4af_set_iTunSMPB(ctx
);
1232 m4af_finalize_mdat(ctx
);
1233 m4af_write_moov_box(ctx
);
1234 return ctx
->last_error
;