]>
iEval git - fdkaac.git/blob - src/m4af.c
2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
16 #include "m4af_endian.h"
18 #define m4af_realloc(memory,size) realloc(memory, size)
19 #define m4af_free(memory) free(memory)
21 typedef struct m4af_sample_entry_t
{
24 } m4af_sample_entry_t
;
26 typedef struct m4af_chunk_entry_t
{
29 uint32_t samples_per_chunk
;
33 typedef struct m4af_itmf_entry_t
{
34 uint32_t type
; /* fcc */
43 typedef struct m4af_track_t
{
46 int64_t creation_time
;
47 int64_t modification_time
;
49 uint32_t frame_duration
;
50 uint32_t encoder_delay
;
52 uint8_t *decSpecificInfo
;
53 uint32_t decSpecificInfoSize
;
54 uint32_t bufferSizeDB
;
58 m4af_sample_entry_t
*sample_table
;
60 uint32_t sample_table_capacity
;
62 m4af_chunk_entry_t
*chunk_table
;
64 uint32_t chunk_table_capacity
;
66 uint8_t *chunk_buffer
;
68 uint32_t chunk_capacity
;
71 struct m4af_writer_t
{
73 int64_t creation_time
;
74 int64_t modification_time
;
79 m4af_itmf_entry_t
*itmf_table
;
81 uint32_t itmf_table_capacity
;
83 m4af_io_callbacks_t io
;
87 m4af_track_t track
[1];
91 int64_t m4af_timestamp(void)
93 return (int64_t)(time(0)) + (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
97 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
100 uint32_t m4af_roundup(uint32_t n
)
113 int64_t m4af_tell(m4af_writer_t
*ctx
)
116 if (!ctx
->last_error
&& (pos
= ctx
->io
.tell(ctx
->io_cookie
)) < 0)
117 ctx
->last_error
= M4AF_IO_ERROR
;
122 int m4af_set_pos(m4af_writer_t
*ctx
, int64_t pos
)
125 if (!ctx
->last_error
&&
126 (rc
= ctx
->io
.seek(ctx
->io_cookie
, pos
, SEEK_SET
)) < 0)
127 ctx
->last_error
= M4AF_IO_ERROR
;
132 int m4af_write(m4af_writer_t
*ctx
, const void *data
, uint32_t size
)
135 if (!ctx
->last_error
&&
136 (rc
= ctx
->io
.write(ctx
->io_cookie
, data
, size
)) < 0)
137 ctx
->last_error
= M4AF_IO_ERROR
;
142 int m4af_write32(m4af_writer_t
*ctx
, uint32_t data
)
144 data
= m4af_htob32(data
);
145 return m4af_write(ctx
, &data
, 4);
149 int m4af_write64(m4af_writer_t
*ctx
, uint64_t data
)
151 data
= m4af_htob64(data
);
152 return m4af_write(ctx
, &data
, 8);
156 int m4af_write24(m4af_writer_t
*ctx
, uint32_t data
)
158 data
= m4af_htob32(data
<< 8);
159 return m4af_write(ctx
, &data
, 3);
163 void m4af_write32_at(m4af_writer_t
*ctx
, int64_t pos
, uint32_t value
)
165 int64_t current_pos
= m4af_tell(ctx
);
166 m4af_set_pos(ctx
, pos
);
167 m4af_write32(ctx
, value
);
168 m4af_set_pos(ctx
, current_pos
);
171 m4af_writer_t
*m4af_create(uint32_t codec
, uint32_t timescale
,
172 m4af_io_callbacks_t
*io
, void *io_cookie
)
177 if (codec
!= M4AF_FOURCC('m','p','4','a') &&
178 codec
!= M4AF_FOURCC('a','l','a','c'))
180 if ((ctx
= m4af_realloc(0, sizeof(m4af_writer_t
))) == 0)
182 memset(ctx
, 0, sizeof(m4af_writer_t
));
183 memcpy(&ctx
->io
, io
, sizeof(m4af_io_callbacks_t
));
184 ctx
->io_cookie
= io_cookie
;
185 ctx
->timescale
= timescale
;
186 timestamp
= m4af_timestamp();
187 ctx
->creation_time
= timestamp
;
188 ctx
->modification_time
= timestamp
;
190 ctx
->track
[0].codec
= codec
;
191 ctx
->track
[0].timescale
= timescale
;
192 ctx
->track
[0].creation_time
= timestamp
;
193 ctx
->track
[0].modification_time
= timestamp
;
197 void m4af_set_fixed_frame_duration(m4af_writer_t
*ctx
, int track_idx
,
200 ctx
->track
[track_idx
].frame_duration
= length
;
203 int m4af_decoder_specific_info(m4af_writer_t
*ctx
, int track_idx
,
204 uint8_t *data
, uint32_t size
)
206 m4af_track_t
*track
= &ctx
->track
[track_idx
];
207 if (size
> track
->decSpecificInfoSize
) {
208 uint8_t *memory
= m4af_realloc(track
->decSpecificInfo
, size
);
210 ctx
->last_error
= M4AF_NO_MEMORY
;
213 track
->decSpecificInfo
= memory
;
216 memcpy(track
->decSpecificInfo
, data
, size
);
217 track
->decSpecificInfoSize
= size
;
221 void m4af_set_priming(m4af_writer_t
*ctx
, int track_idx
,
222 uint32_t encoder_delay
, uint32_t padding
)
224 m4af_track_t
*track
= &ctx
->track
[track_idx
];
225 track
->encoder_delay
= encoder_delay
;
226 track
->padding
= padding
;
230 int m4af_add_sample_entry(m4af_writer_t
*ctx
, int track_idx
,
231 uint32_t size
, uint32_t delta
)
233 m4af_track_t
*track
= &ctx
->track
[track_idx
];
234 m4af_sample_entry_t
*entry
;
238 if (track
->num_samples
== track
->sample_table_capacity
) {
239 uint32_t new_size
= track
->sample_table_capacity
;
240 new_size
= new_size
? new_size
* 2 : 1;
241 entry
= m4af_realloc(track
->sample_table
, new_size
* sizeof(*entry
));
243 ctx
->last_error
= M4AF_NO_MEMORY
;
246 track
->sample_table
= entry
;
247 track
->sample_table_capacity
= new_size
;
249 entry
= track
->sample_table
+ track
->num_samples
;
251 entry
->delta
= delta
;
252 ++track
->num_samples
;
257 int m4af_flush_chunk(m4af_writer_t
*ctx
, int track_idx
)
259 m4af_track_t
*track
= &ctx
->track
[track_idx
];
260 m4af_chunk_entry_t
*entry
;
261 if (!track
->num_chunks
|| !track
->chunk_size
)
263 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
264 entry
->offset
= m4af_tell(ctx
);
265 m4af_write(ctx
, track
->chunk_buffer
, track
->chunk_size
);
266 ctx
->mdat_size
+= track
->chunk_size
;
267 track
->chunk_size
= 0;
268 return ctx
->last_error
? -1 : 0;
272 int m4af_update_chunk_table(m4af_writer_t
*ctx
, int track_idx
,
273 uint32_t size
, uint32_t delta
)
275 m4af_track_t
*track
= &ctx
->track
[track_idx
];
276 m4af_chunk_entry_t
*entry
;
277 int add_new_chunk
= 0;
281 if (track
->num_chunks
== 0)
284 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
285 if (entry
->duration
+ delta
> track
->timescale
/ 2)
289 m4af_flush_chunk(ctx
, track_idx
);
290 if (track
->num_chunks
== track
->chunk_table_capacity
) {
291 uint32_t new_size
= track
->chunk_table_capacity
;
292 new_size
= new_size
? new_size
* 2 : 1;
293 entry
= m4af_realloc(track
->chunk_table
, new_size
* sizeof(*entry
));
295 ctx
->last_error
= M4AF_NO_MEMORY
;
298 track
->chunk_table
= entry
;
299 track
->chunk_table_capacity
= new_size
;
301 memset(&track
->chunk_table
[track
->num_chunks
++], 0,
302 sizeof(m4af_chunk_entry_t
));
304 entry
= &track
->chunk_table
[track
->num_chunks
- 1];
306 ++entry
->samples_per_chunk
;
307 entry
->duration
+= delta
;
312 void m4af_update_max_bitrate(m4af_writer_t
*ctx
, int track_idx
)
314 m4af_track_t
*track
= &ctx
->track
[track_idx
];
315 uint32_t duration
= 0, size
= 0, bitrate
;
316 m4af_sample_entry_t
*ent
= track
->sample_table
+ track
->num_samples
- 1;
318 for (; ent
>= track
->sample_table
&& duration
< track
->timescale
; --ent
) {
319 duration
+= ent
->delta
;
322 bitrate
= (uint32_t)(size
* 8.0 * track
->timescale
/ duration
+ .5);
323 if (bitrate
> track
->maxBitrate
)
324 track
->maxBitrate
= bitrate
;
328 int m4af_append_sample_to_chunk(m4af_writer_t
*ctx
, int track_idx
,
329 const void *data
, uint32_t size
)
331 m4af_track_t
*track
= &ctx
->track
[track_idx
];
332 uint32_t newsize
= track
->chunk_size
+ size
;
336 if (track
->chunk_capacity
< newsize
) {
337 uint32_t capacity
= m4af_roundup(newsize
);
338 uint8_t *memory
= realloc(track
->chunk_buffer
, capacity
);
340 ctx
->last_error
= M4AF_NO_MEMORY
;
343 track
->chunk_buffer
= memory
;
344 track
->chunk_capacity
= capacity
;
346 memcpy(track
->chunk_buffer
+ track
->chunk_size
, data
, size
);
347 track
->chunk_size
= newsize
;
351 int m4af_write_sample(m4af_writer_t
*ctx
, int track_idx
, const void *data
,
352 uint32_t size
, uint32_t duration
)
354 m4af_track_t
*track
= &ctx
->track
[track_idx
];
355 if (track
->frame_duration
)
356 duration
= track
->frame_duration
;
357 if (size
> track
->bufferSizeDB
)
358 track
->bufferSizeDB
= size
;
359 track
->duration
+= duration
;
360 m4af_add_sample_entry(ctx
, track_idx
, size
, duration
);
361 m4af_update_chunk_table(ctx
, track_idx
, size
, duration
);
362 m4af_update_max_bitrate(ctx
, track_idx
);
363 m4af_append_sample_to_chunk(ctx
, track_idx
, data
, size
);
364 return ctx
->last_error
? -1 : 0;
368 int m4af_add_itmf_entry(m4af_writer_t
*ctx
)
370 m4af_itmf_entry_t
*entry
;
371 if (ctx
->num_tags
== ctx
->itmf_table_capacity
) {
372 uint32_t new_size
= ctx
->itmf_table_capacity
;
373 new_size
= new_size
? new_size
* 2 : 1;
374 entry
= m4af_realloc(ctx
->itmf_table
, new_size
* sizeof(*entry
));
376 ctx
->last_error
= M4AF_NO_MEMORY
;
379 ctx
->itmf_table
= entry
;
380 ctx
->itmf_table_capacity
= new_size
;
386 int m4af_add_itmf_long_tag(m4af_writer_t
*ctx
, const char *name
,
389 m4af_itmf_entry_t
*entry
;
390 size_t name_len
= strlen(name
);
391 size_t data_len
= strlen(data
);
392 char *name_copy
= m4af_realloc(0, name_len
+ 1);
393 char *data_copy
= m4af_realloc(0, data_len
);
394 if (!name_copy
|| !data_copy
) {
395 ctx
->last_error
= M4AF_NO_MEMORY
;
398 if (m4af_add_itmf_entry(ctx
) < 0)
400 memcpy(name_copy
, name
, name_len
+ 1);
401 memcpy(data_copy
, data
, data_len
);
402 entry
= ctx
->itmf_table
+ ctx
->num_tags
- 1;
403 entry
->type
= M4AF_FOURCC('-','-','-','-');
404 entry
->u
.name
= name_copy
;
405 entry
->data
= data_copy
;
406 entry
->data_size
= data_len
;
410 m4af_free(name_copy
);
412 m4af_free(data_copy
);
416 int m4af_add_itmf_short_tag(m4af_writer_t
*ctx
, uint32_t type
,
417 uint32_t type_code
, const void *data
,
420 m4af_itmf_entry_t
*entry
;
421 char *data_copy
= m4af_realloc(0, data_size
);
423 ctx
->last_error
= M4AF_NO_MEMORY
;
426 if (m4af_add_itmf_entry(ctx
) < 0)
428 entry
= ctx
->itmf_table
+ ctx
->num_tags
- 1;
430 entry
->u
.type_code
= type_code
;
431 memcpy(data_copy
, data
, data_size
);
432 entry
->data
= data_copy
;
433 entry
->data_size
= data_size
;
437 m4af_free(data_copy
);
441 int m4af_add_itmf_string_tag(m4af_writer_t
*ctx
, uint32_t type
,
444 return m4af_add_itmf_short_tag(ctx
, type
, M4AF_UTF8
, data
, strlen(data
));
447 int m4af_add_itmf_int8_tag(m4af_writer_t
*ctx
, uint32_t type
, int value
)
449 uint8_t data
= value
;
450 return m4af_add_itmf_short_tag(ctx
, type
, M4AF_INTEGER
, &data
, 1);
453 int m4af_add_itmf_int16_tag(m4af_writer_t
*ctx
, uint32_t type
, int value
)
455 uint16_t data
= m4af_htob16(value
);
456 return m4af_add_itmf_short_tag(ctx
, type
, M4AF_INTEGER
, &data
, 2);
459 int m4af_add_itmf_int32_tag(m4af_writer_t
*ctx
, uint32_t type
, uint32_t value
)
461 uint32_t data
= m4af_htob32(value
);
462 return m4af_add_itmf_short_tag(ctx
, type
, M4AF_INTEGER
, &data
, 4);
465 int m4af_add_itmf_int64_tag(m4af_writer_t
*ctx
, uint32_t type
, uint64_t value
)
467 uint64_t data
= m4af_htob64(value
);
468 return m4af_add_itmf_short_tag(ctx
, type
, M4AF_INTEGER
, &data
, 8);
471 int m4af_add_itmf_track_tag(m4af_writer_t
*ctx
, int track
, int total
)
473 uint16_t data
[4] = { 0 };
474 data
[1] = m4af_htob16(track
);
475 data
[2] = m4af_htob16(total
);
476 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('t','r','k','n'),
477 M4AF_IMPLICIT
, &data
, 8);
480 int m4af_add_itmf_disk_tag(m4af_writer_t
*ctx
, int disk
, int total
)
482 uint16_t data
[3] = { 0 };
483 data
[1] = m4af_htob16(disk
);
484 data
[2] = m4af_htob16(total
);
485 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('d','i','s','k'),
486 M4AF_IMPLICIT
, &data
, 6);
489 int m4af_add_itmf_genre_tag(m4af_writer_t
*ctx
, int genre
)
491 uint16_t data
= m4af_htob16(genre
);
492 return m4af_add_itmf_short_tag(ctx
, M4AF_FOURCC('g','n','r','e'),
493 M4AF_IMPLICIT
, &data
, 2);
497 int m4af_set_iTunSMPB(m4af_writer_t
*ctx
)
499 const char *template = " 00000000 %08X %08X %08X%08X 00000000 00000000 "
500 "00000000 00000000 00000000 00000000 00000000 00000000";
501 m4af_track_t
*track
= &ctx
->track
[0];
503 uint64_t length
= track
->duration
- track
->encoder_delay
- track
->padding
;
504 sprintf(buf
, template, track
->encoder_delay
, track
->padding
,
505 (uint32_t)(length
>> 32), (uint32_t)length
);
506 return m4af_add_itmf_long_tag(ctx
, "iTunSMPB", buf
);
510 void m4af_update_size(m4af_writer_t
*ctx
, int64_t pos
)
512 int64_t current_pos
= m4af_tell(ctx
);
513 m4af_set_pos(ctx
, pos
);
514 m4af_write32(ctx
, current_pos
- pos
);
515 m4af_set_pos(ctx
, current_pos
);
519 void m4af_descriptor(m4af_writer_t
*ctx
, uint32_t tag
, uint32_t size
)
523 buf
[1] = ((size
>> 21) | 0x80);
524 buf
[2] = ((size
>> 14) | 0x80);
525 buf
[3] = ((size
>> 7) | 0x80);
526 buf
[4] = (size
& 0x7f);
527 m4af_write(ctx
, buf
, 5);
531 void m4af_ftyp_box(m4af_writer_t
*ctx
)
533 m4af_write(ctx
, "\0\0\0\040""ftypM4A \0\0\0\0M4A mp42isom\0\0\0\0", 32);
537 void m4af_free_box(m4af_writer_t
*ctx
, uint32_t size
)
539 int64_t pos
= m4af_tell(ctx
);
540 m4af_write32(ctx
, size
+ 8);
541 m4af_write(ctx
, "free", 4);
543 m4af_set_pos(ctx
, pos
+ size
+ 8);
546 int m4af_begin_write(m4af_writer_t
*ctx
)
549 m4af_free_box(ctx
, 0);
550 m4af_write(ctx
, "\0\0\0\0mdat", 8);
551 ctx
->mdat_pos
= m4af_tell(ctx
);
552 return ctx
->last_error
? -1 : 0;
556 void m4af_stco_box(m4af_writer_t
*ctx
, int track_idx
)
558 m4af_track_t
*track
= &ctx
->track
[track_idx
];
560 m4af_chunk_entry_t
*index
= track
->chunk_table
;
561 int is_co64
= (ctx
->mdat_pos
+ ctx
->mdat_size
> UINT32_MAX
);
562 int64_t pos
= m4af_tell(ctx
);
564 m4af_write32(ctx
, 0); /* size */
565 m4af_write(ctx
, is_co64
? "co64" : "stco", 4);
566 m4af_write32(ctx
, 0); /* version and flags */
567 m4af_write32(ctx
, track
->num_chunks
);
568 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
570 m4af_write64(ctx
, index
->offset
);
572 m4af_write32(ctx
, index
->offset
);
574 m4af_update_size(ctx
, pos
);
578 void m4af_stsz_box(m4af_writer_t
*ctx
, int track_idx
)
580 m4af_track_t
*track
= &ctx
->track
[track_idx
];
581 m4af_sample_entry_t
*index
= track
->sample_table
;
583 int64_t pos
= m4af_tell(ctx
);
585 "\0\0\0\0" /* size */
589 "\0\0\0\0" /* sample_size: 0(variable) */
591 m4af_write32(ctx
, track
->num_samples
);
592 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
)
593 m4af_write32(ctx
, index
->size
);
594 m4af_update_size(ctx
, pos
);
598 void m4af_stsc_box(m4af_writer_t
*ctx
, int track_idx
)
600 m4af_track_t
*track
= &ctx
->track
[track_idx
];
601 m4af_chunk_entry_t
*index
= track
->chunk_table
;
602 uint32_t i
, prev_samples_per_chunk
= 0, entry_count
= 0;
603 int64_t pos
= m4af_tell(ctx
);
605 "\0\0\0\0" /* size */
609 "\0\0\0\0" /* entry_count */
612 for (i
= 0; i
< track
->num_chunks
; ++i
, ++index
) {
613 if (index
->samples_per_chunk
!= prev_samples_per_chunk
) {
615 m4af_write32(ctx
, i
+ 1);
616 m4af_write32(ctx
, index
->samples_per_chunk
);
617 m4af_write32(ctx
, 1); /* sample_description_index */
618 prev_samples_per_chunk
= index
->samples_per_chunk
;
621 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
622 m4af_update_size(ctx
, pos
);
626 void m4af_stts_box(m4af_writer_t
*ctx
, int track_idx
)
628 m4af_track_t
*track
= &ctx
->track
[track_idx
];
629 m4af_sample_entry_t
*index
= track
->sample_table
;
630 uint32_t i
, prev_delta
= 0, entry_count
= 0, sample_count
= 0;
631 int64_t pos
= m4af_tell(ctx
);
633 "\0\0\0\0" /* size */
637 "\0\0\0\0" /* entry_count */
640 for (i
= 0; i
< track
->num_samples
; ++i
, ++index
) {
641 if (index
->delta
== prev_delta
)
646 m4af_write32(ctx
, sample_count
);
647 m4af_write32(ctx
, prev_delta
);
649 prev_delta
= index
->delta
;
654 m4af_write32(ctx
, sample_count
);
655 m4af_write32(ctx
, prev_delta
);
657 m4af_write32_at(ctx
, pos
+ 12, entry_count
);
658 m4af_update_size(ctx
, pos
);
662 void m4af_esds_box(m4af_writer_t
*ctx
, int track_idx
)
664 m4af_track_t
*track
= &ctx
->track
[track_idx
];
665 int64_t pos
= m4af_tell(ctx
);
666 m4af_write(ctx
, "\0\0\0\0esds", 8);
667 m4af_write32(ctx
, 0); /* version + flags */
670 m4af_descriptor(ctx
, 3, 32 + track
->decSpecificInfoSize
);
671 m4af_write(ctx
, "\0\0\0", 3);
672 /* DecoderConfigDescriptor */
673 m4af_descriptor(ctx
, 4, 18 + track
->decSpecificInfoSize
);
675 "\x40" /* objectTypeIndication: 0x40(Audio ISO/IEC 14496-3)*/
676 "\x15" /* streamType(6): 0x05(AudioStream)
681 m4af_write24(ctx
, track
->bufferSizeDB
);
682 m4af_write32(ctx
, track
->maxBitrate
);
683 m4af_write32(ctx
, track
->avgBitrate
);
684 /* DecoderSpecificInfo */
685 m4af_descriptor(ctx
, 5, track
->decSpecificInfoSize
);
686 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
687 /* SLConfigDescriptor */
688 m4af_descriptor(ctx
, 6, 1);
689 m4af_write(ctx
, "\002", 1); /* predefined */
691 m4af_update_size(ctx
, pos
);
695 void m4af_alac_box(m4af_writer_t
*ctx
, int track_idx
)
697 m4af_track_t
*track
= &ctx
->track
[track_idx
];
698 int64_t pos
= m4af_tell(ctx
);
700 "\0\0\0\0" /* size */
705 m4af_write(ctx
, track
->decSpecificInfo
, track
->decSpecificInfoSize
);
706 m4af_update_size(ctx
, pos
);
710 void m4af_mp4a_box(m4af_writer_t
*ctx
, int track_idx
)
712 m4af_track_t
*track
= &ctx
->track
[track_idx
];
713 int64_t pos
= m4af_tell(ctx
);
714 m4af_write32(ctx
, 0); /* size */
715 m4af_write32(ctx
, track
->codec
); /* mp4a or alac */
717 "\0\0\0\0\0\0" /* reserved */
718 "\0\001" /* data_reference_index: 1 */
719 "\0\0\0\0" /* reserved[0] */
720 "\0\0\0\0" /* reserved[1] */
721 "\0\002" /* channelcount: 2 */
722 "\0\020" /* samplesize: 16 */
723 "\0\0" /* pre_defined */
724 "\0\0" /* reserved */
726 if (track
->codec
== M4AF_FOURCC('m','p','4','a')) {
727 m4af_write32(ctx
, track
->timescale
<< 16);
728 m4af_esds_box(ctx
, track_idx
);
730 m4af_write32(ctx
, 44100);
731 m4af_alac_box(ctx
, track_idx
);
733 m4af_update_size(ctx
, pos
);
737 void m4af_stsd_box(m4af_writer_t
*ctx
, int track_idx
)
739 int64_t pos
= m4af_tell(ctx
);
740 m4af_write(ctx
, "\0\0\0\0stsd", 8);
744 "\0\0\0\001" /* entry_count: 1 */
746 m4af_mp4a_box(ctx
, track_idx
);
747 m4af_update_size(ctx
, pos
);
751 void m4af_stbl_box(m4af_writer_t
*ctx
, int track_idx
)
753 int64_t pos
= m4af_tell(ctx
);
754 m4af_write(ctx
, "\0\0\0\0stbl", 8);
755 m4af_stsd_box(ctx
, track_idx
);
756 m4af_stts_box(ctx
, track_idx
);
757 m4af_stsc_box(ctx
, track_idx
);
758 m4af_stsz_box(ctx
, track_idx
);
759 m4af_stco_box(ctx
, track_idx
);
760 m4af_update_size(ctx
, pos
);
764 void m4af_url_box(m4af_writer_t
*ctx
, int track_idx
)
767 "\0\0\0\014" /* size */
770 "\0\0\001" /* flags: 1(in the same file) */
775 void m4af_dref_box(m4af_writer_t
*ctx
, int track_idx
)
777 int64_t pos
= m4af_tell(ctx
);
778 m4af_write(ctx
, "\0\0\0\0dref", 8);
782 "\0\0\0\001" /* entry_count: 1 */
784 m4af_url_box(ctx
, track_idx
);
785 m4af_update_size(ctx
, pos
);
789 void m4af_dinf_box(m4af_writer_t
*ctx
, int track_idx
)
791 int64_t pos
= m4af_tell(ctx
);
792 m4af_write(ctx
, "\0\0\0\0dinf", 8);
793 m4af_dref_box(ctx
, track_idx
);
794 m4af_update_size(ctx
, pos
);
798 void m4af_smhd_box(m4af_writer_t
*ctx
, int track_idx
)
801 "\0\0\0\020" /* size */
806 "\0\0" /* reserved */
811 void m4af_minf_box(m4af_writer_t
*ctx
, int track_idx
)
813 m4af_track_t
*track
= &ctx
->track
[track_idx
];
814 int64_t pos
= m4af_tell(ctx
);
815 m4af_write(ctx
, "\0\0\0\0minf", 8);
816 /* TODO: add TEXT support */
817 if (track
->codec
!= M4AF_CODEC_TEXT
)
818 m4af_smhd_box(ctx
, track_idx
);
819 m4af_dinf_box(ctx
, track_idx
);
820 m4af_stbl_box(ctx
, track_idx
);
821 m4af_update_size(ctx
, pos
);
825 void m4af_mdhd_box(m4af_writer_t
*ctx
, int track_idx
)
827 m4af_track_t
*track
= &ctx
->track
[track_idx
];
828 int64_t pos
= m4af_tell(ctx
);
829 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
830 track
->modification_time
> UINT32_MAX
||
831 track
->duration
> UINT32_MAX
);
833 m4af_write(ctx
, "\0\0\0\0mdhd", 8);
834 m4af_write(ctx
, &version
, 1);
835 m4af_write(ctx
, "\0\0\0", 3); /* flags */
837 m4af_write64(ctx
, track
->creation_time
);
838 m4af_write64(ctx
, track
->modification_time
);
839 m4af_write32(ctx
, track
->timescale
);
840 m4af_write64(ctx
, track
->duration
);
842 m4af_write32(ctx
, track
->creation_time
);
843 m4af_write32(ctx
, track
->modification_time
);
844 m4af_write32(ctx
, track
->timescale
);
845 m4af_write32(ctx
, track
->duration
);
848 "\x55\xc4" /* language: und */
849 "\0\0" /* pre_defined */
851 m4af_update_size(ctx
, pos
);
855 void m4af_hdlr_box(m4af_writer_t
*ctx
, int track_idx
, const char *type
)
857 int64_t pos
= m4af_tell(ctx
);
858 static const char reserved_and_name
[10] = { 0 };
861 "\0\0\0\0" /* size */
865 "\0\0\0\0" /* pre_defined */
867 m4af_write(ctx
, type
, 4); /* handler_type */
869 m4af_write(ctx
, !strcmp(type
, "mdir") ? "appl" : "\0\0\0\0", 4);
870 /* reserved[1], reserved[2], name */
871 m4af_write(ctx
, reserved_and_name
, (pos
& 1) ? 9 : 10);
872 m4af_update_size(ctx
, pos
);
876 void m4af_mdia_box(m4af_writer_t
*ctx
, int track_idx
)
878 m4af_track_t
*track
= &ctx
->track
[track_idx
];
880 (track
->codec
== M4AF_CODEC_TEXT
) ? "text" : "soun";
881 int64_t pos
= m4af_tell(ctx
);
882 m4af_write(ctx
, "\0\0\0\0mdia", 8);
883 m4af_mdhd_box(ctx
, track_idx
);
884 m4af_hdlr_box(ctx
, track_idx
, hdlr
);
885 m4af_minf_box(ctx
, track_idx
);
886 m4af_update_size(ctx
, pos
);
890 void m4af_tkhd_box(m4af_writer_t
*ctx
, int track_idx
)
892 m4af_track_t
*track
= &ctx
->track
[track_idx
];
893 int64_t pos
= m4af_tell(ctx
);
895 (double)track
->duration
/ track
->timescale
* ctx
->timescale
+ .5;
896 uint8_t version
= (track
->creation_time
> UINT32_MAX
||
897 track
->modification_time
> UINT32_MAX
||
898 duration
> UINT32_MAX
);
899 m4af_write(ctx
, "\0\0\0\0tkhd", 8);
900 m4af_write(ctx
, &version
, 1);
901 m4af_write(ctx
, "\0\0\007", 3); /* flags */
903 m4af_write64(ctx
, track
->creation_time
);
904 m4af_write64(ctx
, track
->modification_time
);
905 m4af_write32(ctx
, track_idx
+ 1);
906 m4af_write(ctx
, "\0\0\0\0" /* reserved */
908 m4af_write64(ctx
, duration
);
910 m4af_write32(ctx
, track
->creation_time
);
911 m4af_write32(ctx
, track
->modification_time
);
912 m4af_write32(ctx
, track_idx
+ 1);
913 m4af_write(ctx
, "\0\0\0\0" /* reserved */
915 m4af_write32(ctx
, duration
);
918 "\0\0\0\0" /* reserved[0] */
919 "\0\0\0\0" /* reserved[1] */
921 "\0\0" /* alternate_group */
922 "\001\0" /* volume: 1.0 */
923 "\0\0" /* reserved */
924 "\0\001\0\0" /* matrix[0] */
925 "\0\0\0\0" /* matrix[1] */
926 "\0\0\0\0" /* matrix[2] */
927 "\0\0\0\0" /* matrix[3] */
928 "\0\001\0\0" /* matrix[4] */
929 "\0\0\0\0" /* matrix[5] */
930 "\0\0\0\0" /* matrix[6] */
931 "\0\0\0\0" /* matrix[7] */
932 "\100\0\0\0" /* matrix[8] */
933 "\0\0\0\0" /* width */
934 "\0\0\0\0" /* height */
936 m4af_update_size(ctx
, pos
);
940 void m4af_trak_box(m4af_writer_t
*ctx
, int track_idx
)
942 int64_t pos
= m4af_tell(ctx
);
943 m4af_write(ctx
, "\0\0\0\0trak", 8);
944 m4af_tkhd_box(ctx
, track_idx
);
945 m4af_mdia_box(ctx
, track_idx
);
946 m4af_update_size(ctx
, pos
);
950 int64_t m4af_movie_duration(m4af_writer_t
*ctx
)
952 int64_t movie_duration
= 0;
954 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
955 double x
= ctx
->track
[i
].duration
;
956 int64_t duration
= x
/ ctx
->track
[i
].timescale
* ctx
->timescale
+ .5;
957 if (duration
> movie_duration
)
958 movie_duration
= duration
;
960 return movie_duration
;
964 void m4af_mvhd_box(m4af_writer_t
*ctx
)
966 int64_t pos
= m4af_tell(ctx
);
967 int64_t movie_duration
= m4af_movie_duration(ctx
);
968 uint8_t version
= (ctx
->creation_time
> UINT32_MAX
||
969 ctx
->modification_time
> UINT32_MAX
||
970 movie_duration
> UINT32_MAX
);
972 m4af_write(ctx
, "\0\0\0\0mvhd", 8);
973 m4af_write(ctx
, &version
, 1);
974 m4af_write(ctx
, "\0\0\0", 3); /* flags */
976 m4af_write64(ctx
, ctx
->creation_time
);
977 m4af_write64(ctx
, ctx
->modification_time
);
978 m4af_write32(ctx
, ctx
->timescale
);
979 m4af_write64(ctx
, movie_duration
);
981 m4af_write32(ctx
, ctx
->creation_time
);
982 m4af_write32(ctx
, ctx
->modification_time
);
983 m4af_write32(ctx
, ctx
->timescale
);
984 m4af_write32(ctx
, movie_duration
);
987 "\0\001\0\0" /* rate: 1.0 */
988 "\001\0" /* volume: 1.0 */
989 "\0\0" /* reserved */
990 "\0\0\0\0" /* reserved[0] */
991 "\0\0\0\0" /* reserved[1] */
992 "\0\001\0\0" /* matrix[0] */
993 "\0\0\0\0" /* matrix[1] */
994 "\0\0\0\0" /* matrix[2] */
995 "\0\0\0\0" /* matrix[3] */
996 "\0\001\0\0" /* matrix[4] */
997 "\0\0\0\0" /* matrix[5] */
998 "\0\0\0\0" /* matrix[6] */
999 "\0\0\0\0" /* matrix[7] */
1000 "\100\0\0\0" /* matrix[8] */
1001 "\0\0\0\0" /* pre_defined[0] */
1002 "\0\0\0\0" /* pre_defined[1] */
1003 "\0\0\0\0" /* pre_defined[2] */
1004 "\0\0\0\0" /* pre_defined[3] */
1005 "\0\0\0\0" /* pre_defined[4] */
1006 "\0\0\0\0" /* pre_defined[5] */
1008 m4af_write32(ctx
, ctx
->num_tracks
+ 1);
1009 m4af_update_size(ctx
, pos
);
1013 void m4af_mean_box(m4af_writer_t
*ctx
)
1016 "\0\0\0\034" /* size */
1019 "\0\0\0" /* flags */
1020 "com.apple.iTunes" /* meaning-string */
1025 void m4af_name_box(m4af_writer_t
*ctx
, const char *name
)
1027 int64_t pos
= m4af_tell(ctx
);
1029 "\0\0\0\0" /* size */
1032 "\0\0\0" /* flags */
1034 m4af_write(ctx
, name
, strlen(name
));
1035 m4af_update_size(ctx
, pos
);
1039 void m4af_data_box(m4af_writer_t
*ctx
, uint32_t type_code
,
1040 const char *data
, uint32_t data_size
)
1042 int64_t pos
= m4af_tell(ctx
);
1043 uint8_t code
= type_code
;
1045 "\0\0\0\0" /* size */
1047 "\0\0" /* reserved */
1048 "\0" /* type_set_indifier */
1050 m4af_write(ctx
, &code
, 1);
1051 m4af_write(ctx
, "\0\0\0\0", 4); /* locale */
1052 m4af_write(ctx
, data
, data_size
);
1053 m4af_update_size(ctx
, pos
);
1057 void m4af_write_metadata(m4af_writer_t
*ctx
, m4af_itmf_entry_t
*entry
)
1059 int64_t pos
= m4af_tell(ctx
);
1060 m4af_write(ctx
, "\0\0\0\0", 4);
1061 m4af_write32(ctx
, entry
->type
);
1062 if (entry
->type
!= M4AF_FOURCC('-','-','-','-'))
1063 m4af_data_box(ctx
, entry
->u
.type_code
, entry
->data
, entry
->data_size
);
1066 m4af_name_box(ctx
, entry
->u
.name
);
1067 m4af_data_box(ctx
, 1, entry
->data
, entry
->data_size
);
1069 m4af_update_size(ctx
, pos
);
1073 void m4af_ilst_box(m4af_writer_t
*ctx
)
1076 int64_t pos
= m4af_tell(ctx
);
1077 m4af_write(ctx
, "\0\0\0\0ilst", 8);
1078 for (i
= 0; i
< ctx
->num_tags
; ++i
)
1079 m4af_write_metadata(ctx
, &ctx
->itmf_table
[i
]);
1080 m4af_update_size(ctx
, pos
);
1084 void m4af_meta_box(m4af_writer_t
*ctx
)
1086 int64_t pos
= m4af_tell(ctx
);
1088 "\0\0\0\0" /* size */
1091 "\0\0\0" /* flags */
1093 m4af_hdlr_box(ctx
, 0, "mdir");
1095 m4af_update_size(ctx
, pos
);
1099 void m4af_udta_box(m4af_writer_t
*ctx
)
1101 int64_t pos
= m4af_tell(ctx
);
1102 m4af_write(ctx
, "\0\0\0\0udta", 8);
1104 m4af_update_size(ctx
, pos
);
1108 void m4af_moov_box(m4af_writer_t
*ctx
)
1111 int64_t pos
= m4af_tell(ctx
);
1112 m4af_write(ctx
, "\0\0\0\0moov", 8);
1114 for (i
= 0; i
< ctx
->num_tracks
; ++i
)
1115 m4af_trak_box(ctx
, i
);
1118 m4af_update_size(ctx
, pos
);
1122 void m4af_finalize_mdat(m4af_writer_t
*ctx
)
1124 if (ctx
->mdat_size
+ 8 > UINT32_MAX
) {
1125 m4af_set_pos(ctx
, ctx
->mdat_pos
- 16);
1126 m4af_write32(ctx
, 1);
1127 m4af_write(ctx
, "mdat", 4);
1128 m4af_write64(ctx
, ctx
->mdat_size
+ 16);
1130 m4af_set_pos(ctx
, ctx
->mdat_pos
- 8);
1131 m4af_write32(ctx
, ctx
->mdat_size
+ 8);
1133 m4af_set_pos(ctx
, ctx
->mdat_pos
+ ctx
->mdat_size
);
1136 int m4af_finalize(m4af_writer_t
*ctx
)
1139 m4af_track_t
*track
;
1141 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1142 track
= ctx
->track
+ i
;
1143 if (track
->duration
) {
1144 int64_t track_size
= 0;
1146 for (j
= 0; j
< track
->num_chunks
; ++j
)
1147 track_size
+= track
->chunk_table
[j
].size
;
1149 8.0 * track_size
* track
->timescale
/ track
->duration
+ .5;
1151 m4af_flush_chunk(ctx
, i
);
1153 if (ctx
->track
[0].encoder_delay
|| ctx
->track
[0].padding
)
1154 m4af_set_iTunSMPB(ctx
);
1155 m4af_finalize_mdat(ctx
);
1157 return ctx
->last_error
? -1 : 0;
1161 void m4af_free_itmf_table(m4af_writer_t
*ctx
)
1164 m4af_itmf_entry_t
*entry
= ctx
->itmf_table
;
1165 for (i
= 0; i
< ctx
->num_tags
; ++i
, ++entry
) {
1166 if (entry
->type
== M4AF_FOURCC('-','-','-','-'))
1167 m4af_free(entry
->u
.name
);
1168 m4af_free(entry
->data
);
1170 m4af_free(ctx
->itmf_table
);
1173 void m4af_teardown(m4af_writer_t
**ctxp
)
1176 m4af_writer_t
*ctx
= *ctxp
;
1177 m4af_track_t
*track
;
1178 for (i
= 0; i
< ctx
->num_tracks
; ++i
) {
1179 track
= ctx
->track
+ i
;
1180 if (track
->decSpecificInfo
)
1181 m4af_free(track
->decSpecificInfo
);
1182 if (track
->sample_table
)
1183 m4af_free(track
->sample_table
);
1184 if (track
->chunk_table
)
1185 m4af_free(track
->chunk_table
);
1186 if (track
->chunk_buffer
)
1187 m4af_free(track
->chunk_buffer
);
1189 if (ctx
->itmf_table
)
1190 m4af_free_itmf_table(ctx
);
This page took 0.097087 seconds and 4 git commands to generate.