update m4af
[fdkaac.git] / src / m4af.c
1 /*
2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
4 */
5 #if HAVE_CONFIG_H
6 # include "config.h"
7 #endif
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <time.h>
13 #if HAVE_STDINT_H
14 # include <stdint.h>
15 #endif
16 #if HAVE_INTTYPES_H
17 # include <inttypes.h>
18 #elif defined _MSC_VER
19 # define PRId64 "I64d"
20 #endif
21 #include "m4af.h"
22 #include "m4af_endian.h"
23
24 #define m4af_realloc(memory,size) realloc(memory, size)
25 #define m4af_free(memory) free(memory)
26
27 #define M4AF_ATOM_WILD 0xffffffff
28
29 typedef struct m4af_sample_entry_t {
30 uint32_t size;
31 uint32_t delta;
32 } m4af_sample_entry_t;
33
34 typedef struct m4af_chunk_entry_t {
35 int64_t offset;
36 uint32_t size;
37 uint32_t samples_per_chunk;
38 uint32_t duration;
39 } m4af_chunk_entry_t;
40
41 typedef struct m4af_track_t {
42 uint32_t codec;
43 uint32_t timescale;
44 int64_t creation_time;
45 int64_t modification_time;
46 int64_t duration;
47 uint32_t frame_duration;
48 uint32_t encoder_delay;
49 uint32_t padding;
50 uint8_t *decSpecificInfo;
51 uint32_t decSpecificInfoSize;
52 uint32_t bufferSizeDB;
53 uint32_t maxBitrate;
54 uint32_t avgBitrate;
55
56 m4af_sample_entry_t *sample_table;
57 uint32_t num_samples;
58 uint32_t sample_table_capacity;
59
60 m4af_chunk_entry_t *chunk_table;
61 uint32_t num_chunks;
62 uint32_t chunk_table_capacity;
63
64 uint8_t *chunk_buffer;
65 uint32_t chunk_size;
66 uint32_t chunk_capacity;
67
68 /* temporary, to help parsing */
69 uint64_t stsc_pos;
70 uint64_t stsc_size;
71
72 uint64_t stts_pos;
73 uint64_t stts_size;
74 } m4af_track_t;
75
76 struct m4af_ctx_t {
77 uint32_t timescale;
78 int64_t creation_time;
79 int64_t modification_time;
80 int64_t mdat_pos;
81 int64_t mdat_size;
82 int last_error;
83
84 m4af_itmf_entry_t *itmf_table;
85 uint32_t num_tags;
86 uint32_t itmf_table_capacity;
87
88 m4af_io_callbacks_t io;
89 void *io_cookie;
90
91 uint16_t num_tracks;
92 m4af_track_t track[2];
93
94 m4af_itmf_entry_t current_tag;
95 };
96
97 typedef struct m4af_box_parser_t {
98 uint32_t name;
99 int (*handler)(m4af_ctx_t *ctx, uint32_t name, uint64_t size);
100 } m4af_box_parser_t;
101
102 static
103 int64_t m4af_timestamp(void)
104 {
105 return (int64_t)(time(0)) + (((1970 - 1904) * 365) + 17) * 24 * 60 * 60;
106 }
107
108 /*
109 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
110 */
111 static
112 uint32_t m4af_roundup(uint32_t n)
113 {
114 n--;
115 n |= n >> 1;
116 n |= n >> 2;
117 n |= n >> 4;
118 n |= n >> 8;
119 n |= n >> 16;
120 n++;
121 return n;
122 }
123
124 static
125 int64_t m4af_tell(m4af_ctx_t *ctx)
126 {
127 int64_t pos = -1;
128 if ((pos = ctx->io.tell(ctx->io_cookie)) < 0)
129 ctx->last_error = M4AF_IO_ERROR;
130 return pos;
131 }
132
133 static
134 int m4af_set_pos(m4af_ctx_t *ctx, int64_t pos)
135 {
136 int rc = -1;
137 if ((rc = ctx->io.seek(ctx->io_cookie, pos, SEEK_SET)) < 0)
138 ctx->last_error = M4AF_IO_ERROR;
139 return rc;
140 }
141
142 static
143 int m4af_write(m4af_ctx_t *ctx, const void *data, uint32_t size)
144 {
145 int rc = -1;
146 if ((rc = ctx->io.write(ctx->io_cookie, data, size)) < 0)
147 ctx->last_error = M4AF_IO_ERROR;
148 return rc;
149 }
150
151 static
152 int m4af_write32(m4af_ctx_t *ctx, uint32_t data)
153 {
154 data = m4af_htob32(data);
155 return m4af_write(ctx, &data, 4);
156 }
157
158 static
159 int m4af_write64(m4af_ctx_t *ctx, uint64_t data)
160 {
161 data = m4af_htob64(data);
162 return m4af_write(ctx, &data, 8);
163 }
164
165 static
166 int m4af_write24(m4af_ctx_t *ctx, uint32_t data)
167 {
168 data = m4af_htob32(data << 8);
169 return m4af_write(ctx, &data, 3);
170 }
171
172 static
173 void m4af_write32_at(m4af_ctx_t *ctx, int64_t pos, uint32_t value)
174 {
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);
179 }
180
181 m4af_ctx_t *m4af_create(uint32_t codec, uint32_t timescale,
182 m4af_io_callbacks_t *io, void *io_cookie)
183 {
184 m4af_ctx_t *ctx;
185 int64_t timestamp;
186
187 if (codec != M4AF_FOURCC('m','p','4','a') &&
188 codec != M4AF_FOURCC('a','l','a','c'))
189 return 0;
190 if ((ctx = m4af_realloc(0, sizeof(m4af_ctx_t))) == 0)
191 return 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;
199 ctx->num_tracks = 1;
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;
204 return ctx;
205 }
206
207 static
208 void m4af_free_itmf_table(m4af_ctx_t *ctx)
209 {
210 uint32_t i;
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);
216 }
217 m4af_free(ctx->itmf_table);
218 }
219
220 static
221 void m4af_clear_track(m4af_ctx_t *ctx, int track_idx)
222 {
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));
233 }
234
235 void m4af_teardown(m4af_ctx_t **ctxp)
236 {
237 unsigned i;
238 m4af_ctx_t *ctx = *ctxp;
239 for (i = 0; i < ctx->num_tracks; ++i)
240 m4af_clear_track(ctx, i);
241 if (ctx->itmf_table)
242 m4af_free_itmf_table(ctx);
243 m4af_free(ctx);
244 *ctxp = 0;
245 }
246
247 void m4af_set_fixed_frame_duration(m4af_ctx_t *ctx, uint32_t track_idx,
248 uint32_t length)
249 {
250 ctx->track[track_idx].frame_duration = length;
251 }
252
253 int m4af_set_decoder_specific_info(m4af_ctx_t *ctx, uint32_t track_idx,
254 uint8_t *data, uint32_t size)
255 {
256 m4af_track_t *track = &ctx->track[track_idx];
257 if (size > track->decSpecificInfoSize) {
258 uint8_t *memory = m4af_realloc(track->decSpecificInfo, size);
259 if (memory == 0) {
260 ctx->last_error = M4AF_NO_MEMORY;
261 goto DONE;
262 }
263 track->decSpecificInfo = memory;
264 }
265 if (size > 0)
266 memcpy(track->decSpecificInfo, data, size);
267 track->decSpecificInfoSize = size;
268 DONE:
269 return ctx->last_error;
270 }
271
272 void m4af_set_priming(m4af_ctx_t *ctx, uint32_t track_idx,
273 uint32_t encoder_delay, uint32_t padding)
274 {
275 m4af_track_t *track = &ctx->track[track_idx];
276 track->encoder_delay = encoder_delay;
277 track->padding = padding;
278 }
279
280 static
281 int m4af_add_sample_entry(m4af_ctx_t *ctx, uint32_t track_idx,
282 uint32_t size, uint32_t delta)
283 {
284 m4af_track_t *track = &ctx->track[track_idx];
285 m4af_sample_entry_t *entry;
286
287 if (ctx->last_error)
288 return -1;
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));
293 if (entry == 0) {
294 ctx->last_error = M4AF_NO_MEMORY;
295 return -1;
296 }
297 track->sample_table = entry;
298 track->sample_table_capacity = new_size;
299 }
300 entry = track->sample_table + track->num_samples;
301 entry->size = size;
302 entry->delta = delta;
303 ++track->num_samples;
304 return 0;
305 }
306
307 static
308 int m4af_flush_chunk(m4af_ctx_t *ctx, uint32_t track_idx)
309 {
310 m4af_track_t *track = &ctx->track[track_idx];
311 m4af_chunk_entry_t *entry;
312 if (!track->num_chunks || !track->chunk_size)
313 return 0;
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;
320 }
321
322 static
323 int m4af_add_chunk_entry(m4af_ctx_t *ctx, uint32_t track_idx)
324 {
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));
331 if (entry == 0) {
332 ctx->last_error = M4AF_NO_MEMORY;
333 return -1;
334 }
335 track->chunk_table = entry;
336 track->chunk_table_capacity = new_size;
337 }
338 memset(&track->chunk_table[track->num_chunks++], 0,
339 sizeof(m4af_chunk_entry_t));
340 return 0;
341 }
342
343 static
344 int m4af_update_chunk_table(m4af_ctx_t *ctx, uint32_t track_idx,
345 uint32_t size, uint32_t delta)
346 {
347 m4af_track_t *track = &ctx->track[track_idx];
348 m4af_chunk_entry_t *entry;
349 int add_new_chunk = 0;
350
351 if (ctx->last_error)
352 return -1;
353 if (track->num_chunks == 0)
354 add_new_chunk = 1;
355 else {
356 entry = &track->chunk_table[track->num_chunks - 1];
357 if (entry->duration + delta > track->timescale / 2)
358 add_new_chunk = 1;
359 }
360 if (add_new_chunk) {
361 m4af_flush_chunk(ctx, track_idx);
362 if (m4af_add_chunk_entry(ctx, track_idx) < 0)
363 return -1;
364 }
365 entry = &track->chunk_table[track->num_chunks - 1];
366 entry->size += size;
367 ++entry->samples_per_chunk;
368 entry->duration += delta;
369 return 0;
370 }
371
372 static
373 void m4af_update_max_bitrate(m4af_ctx_t *ctx, uint32_t track_idx)
374 {
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;
378
379 for (; ent >= track->sample_table && duration < track->timescale; --ent) {
380 duration += ent->delta;
381 size += ent->size;
382 }
383 bitrate = (uint32_t)(size * 8.0 * track->timescale / duration + .5);
384 if (bitrate > track->maxBitrate)
385 track->maxBitrate = bitrate;
386 }
387
388 static
389 int m4af_append_sample_to_chunk(m4af_ctx_t *ctx, uint32_t track_idx,
390 const void *data, uint32_t size)
391 {
392 m4af_track_t *track = &ctx->track[track_idx];
393 uint32_t newsize = track->chunk_size + size;
394
395 if (ctx->last_error)
396 return -1;
397 if (track->chunk_capacity < newsize) {
398 uint32_t capacity = m4af_roundup(newsize);
399 uint8_t *memory = realloc(track->chunk_buffer, capacity);
400 if (!memory) {
401 ctx->last_error = M4AF_NO_MEMORY;
402 return -1;
403 }
404 track->chunk_buffer = memory;
405 track->chunk_capacity = capacity;
406 }
407 memcpy(track->chunk_buffer + track->chunk_size, data, size);
408 track->chunk_size = newsize;
409 return 0;
410 }
411
412 int m4af_write_sample(m4af_ctx_t *ctx, uint32_t track_idx, const void *data,
413 uint32_t size, uint32_t duration)
414 {
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;
426 }
427
428 static
429 int m4af_add_itmf_entry(m4af_ctx_t *ctx)
430 {
431 m4af_itmf_entry_t *entry;
432 if (ctx->num_tags == ctx->itmf_table_capacity) {
433 uint32_t new_size = ctx->itmf_table_capacity;
434 new_size = new_size ? new_size * 2 : 1;
435 entry = m4af_realloc(ctx->itmf_table, new_size * sizeof(*entry));
436 if (entry == 0) {
437 ctx->last_error = M4AF_NO_MEMORY;
438 return -1;
439 }
440 ctx->itmf_table = entry;
441 ctx->itmf_table_capacity = new_size;
442 }
443 ++ctx->num_tags;
444 return 0;
445 }
446
447 int m4af_add_itmf_long_tag(m4af_ctx_t *ctx, const char *name,
448 const char *data)
449 {
450 m4af_itmf_entry_t *entry;
451 size_t name_len = strlen(name);
452 size_t data_len = strlen(data);
453 char *name_copy = m4af_realloc(0, name_len + 1);
454 char *data_copy = m4af_realloc(0, data_len);
455 if (!name_copy || !data_copy) {
456 ctx->last_error = M4AF_NO_MEMORY;
457 goto FAIL;
458 }
459 if (m4af_add_itmf_entry(ctx) < 0)
460 goto FAIL;
461 memcpy(name_copy, name, name_len + 1);
462 memcpy(data_copy, data, data_len);
463 entry = ctx->itmf_table + ctx->num_tags - 1;
464 entry->fcc = M4AF_FOURCC('-','-','-','-');
465 entry->name = name_copy;
466 entry->type_code = M4AF_UTF8;
467 entry->data = data_copy;
468 entry->data_size = data_len;
469 return 0;
470 FAIL:
471 if (name_copy)
472 m4af_free(name_copy);
473 if (data_copy)
474 m4af_free(data_copy);
475 return ctx->last_error;
476 }
477
478 int m4af_add_itmf_short_tag(m4af_ctx_t *ctx, uint32_t fcc,
479 uint32_t type_code, const void *data,
480 uint32_t data_size)
481 {
482 m4af_itmf_entry_t *entry;
483 char *data_copy = m4af_realloc(0, data_size);
484 if (!data_copy) {
485 ctx->last_error = M4AF_NO_MEMORY;
486 goto FAIL;
487 }
488 if (m4af_add_itmf_entry(ctx) < 0)
489 goto FAIL;
490 entry = ctx->itmf_table + ctx->num_tags - 1;
491 entry->fcc = fcc;
492 entry->name = 0;
493 entry->type_code = type_code;
494 memcpy(data_copy, data, data_size);
495 entry->data = data_copy;
496 entry->data_size = data_size;
497 return 0;
498 FAIL:
499 if (data_copy)
500 m4af_free(data_copy);
501 return ctx->last_error;
502 }
503
504 int m4af_add_itmf_string_tag(m4af_ctx_t *ctx, uint32_t fcc, const char *data)
505 {
506 return m4af_add_itmf_short_tag(ctx, fcc, M4AF_UTF8, data, strlen(data));
507 }
508
509 int m4af_add_itmf_int8_tag(m4af_ctx_t *ctx, uint32_t fcc, int value)
510 {
511 uint8_t data = value;
512 return m4af_add_itmf_short_tag(ctx, fcc, M4AF_INTEGER, &data, 1);
513 }
514
515 int m4af_add_itmf_int16_tag(m4af_ctx_t *ctx, uint32_t fcc, int value)
516 {
517 uint16_t data = m4af_htob16(value);
518 return m4af_add_itmf_short_tag(ctx, fcc, M4AF_INTEGER, &data, 2);
519 }
520
521 int m4af_add_itmf_int32_tag(m4af_ctx_t *ctx, uint32_t fcc, uint32_t value)
522 {
523 uint32_t data = m4af_htob32(value);
524 return m4af_add_itmf_short_tag(ctx, fcc, M4AF_INTEGER, &data, 4);
525 }
526
527 int m4af_add_itmf_int64_tag(m4af_ctx_t *ctx, uint32_t fcc, uint64_t value)
528 {
529 uint64_t data = m4af_htob64(value);
530 return m4af_add_itmf_short_tag(ctx, fcc, M4AF_INTEGER, &data, 8);
531 }
532
533 int m4af_add_itmf_track_tag(m4af_ctx_t *ctx, int track, int total)
534 {
535 uint16_t data[4] = { 0 };
536 data[1] = m4af_htob16(track);
537 data[2] = m4af_htob16(total);
538 return m4af_add_itmf_short_tag(ctx, M4AF_FOURCC('t','r','k','n'),
539 M4AF_IMPLICIT, &data, 8);
540 }
541
542 int m4af_add_itmf_disk_tag(m4af_ctx_t *ctx, int disk, int total)
543 {
544 uint16_t data[3] = { 0 };
545 data[1] = m4af_htob16(disk);
546 data[2] = m4af_htob16(total);
547 return m4af_add_itmf_short_tag(ctx, M4AF_FOURCC('d','i','s','k'),
548 M4AF_IMPLICIT, &data, 6);
549 }
550
551 int m4af_add_itmf_genre_tag(m4af_ctx_t *ctx, int genre)
552 {
553 uint16_t data = m4af_htob16(genre);
554 return m4af_add_itmf_short_tag(ctx, M4AF_FOURCC('g','n','r','e'),
555 M4AF_IMPLICIT, &data, 2);
556 }
557
558 static
559 int m4af_set_iTunSMPB(m4af_ctx_t *ctx)
560 {
561 const char *fmt = " 00000000 %08X %08X %08X%08X 00000000 00000000 "
562 "00000000 00000000 00000000 00000000 00000000 00000000";
563 m4af_track_t *track = &ctx->track[0];
564 char buf[256];
565 uint64_t length = track->duration - track->encoder_delay - track->padding;
566 sprintf(buf, fmt, track->encoder_delay, track->padding,
567 (uint32_t)(length >> 32), (uint32_t)length);
568 return m4af_add_itmf_long_tag(ctx, "iTunSMPB", buf);
569 }
570
571 static
572 void m4af_update_box_size(m4af_ctx_t *ctx, int64_t pos)
573 {
574 int64_t current_pos = m4af_tell(ctx);
575 m4af_set_pos(ctx, pos);
576 m4af_write32(ctx, current_pos - pos);
577 m4af_set_pos(ctx, current_pos);
578 }
579
580 static
581 void m4af_write_descriptor(m4af_ctx_t *ctx, uint32_t tag, uint32_t size)
582 {
583 uint8_t buf[5];
584 buf[0] = tag;
585 buf[1] = ((size >> 21) | 0x80);
586 buf[2] = ((size >> 14) | 0x80);
587 buf[3] = ((size >> 7) | 0x80);
588 buf[4] = (size & 0x7f);
589 m4af_write(ctx, buf, 5);
590 }
591
592 static
593 void m4af_write_ftyp_box(m4af_ctx_t *ctx)
594 {
595 m4af_write(ctx, "\0\0\0\040""ftypM4A \0\0\0\0M4A mp42isom\0\0\0\0", 32);
596 }
597
598 static
599 void m4af_write_free_box(m4af_ctx_t *ctx, uint32_t size)
600 {
601 int64_t pos = m4af_tell(ctx);
602 m4af_write32(ctx, size + 8);
603 m4af_write(ctx, "free", 4);
604 if (size > 0)
605 m4af_set_pos(ctx, pos + size + 8);
606 }
607
608 int m4af_begin_write(m4af_ctx_t *ctx)
609 {
610 m4af_write_ftyp_box(ctx);
611 m4af_write_free_box(ctx, 0);
612 m4af_write(ctx, "\0\0\0\0mdat", 8);
613 ctx->mdat_pos = m4af_tell(ctx);
614 return ctx->last_error;
615 }
616
617 static
618 void m4af_write_stco_box(m4af_ctx_t *ctx, uint32_t track_idx)
619 {
620 m4af_track_t *track = &ctx->track[track_idx];
621 uint32_t i;
622 m4af_chunk_entry_t *index = track->chunk_table;
623 int is_co64 = (ctx->mdat_pos + ctx->mdat_size > UINT32_MAX);
624 int64_t pos = m4af_tell(ctx);
625
626 m4af_write32(ctx, 0); /* size */
627 m4af_write(ctx, is_co64 ? "co64" : "stco", 4);
628 m4af_write32(ctx, 0); /* version and flags */
629 m4af_write32(ctx, track->num_chunks);
630 for (i = 0; i < track->num_chunks; ++i, ++index) {
631 if (is_co64)
632 m4af_write64(ctx, index->offset);
633 else
634 m4af_write32(ctx, index->offset);
635 }
636 m4af_update_box_size(ctx, pos);
637 }
638
639 static
640 void m4af_write_stsz_box(m4af_ctx_t *ctx, uint32_t track_idx)
641 {
642 m4af_track_t *track = &ctx->track[track_idx];
643 m4af_sample_entry_t *index = track->sample_table;
644 uint32_t i;
645 int64_t pos = m4af_tell(ctx);
646 m4af_write(ctx,
647 "\0\0\0\0" /* size */
648 "stsz" /* type */
649 "\0" /* version */
650 "\0\0\0" /* flags */
651 "\0\0\0\0" /* sample_size: 0(variable) */
652 , 16);
653 m4af_write32(ctx, track->num_samples);
654 for (i = 0; i < track->num_samples; ++i, ++index)
655 m4af_write32(ctx, index->size);
656 m4af_update_box_size(ctx, pos);
657 }
658
659 static
660 void m4af_write_stsc_box(m4af_ctx_t *ctx, uint32_t track_idx)
661 {
662 m4af_track_t *track = &ctx->track[track_idx];
663 m4af_chunk_entry_t *index = track->chunk_table;
664 uint32_t i, prev_samples_per_chunk = 0, entry_count = 0;
665 int64_t pos = m4af_tell(ctx);
666 m4af_write(ctx,
667 "\0\0\0\0" /* size */
668 "stsc" /* type */
669 "\0" /* version */
670 "\0\0\0" /* flags */
671 "\0\0\0\0" /* entry_count */
672 , 16);
673
674 for (i = 0; i < track->num_chunks; ++i, ++index) {
675 if (index->samples_per_chunk != prev_samples_per_chunk) {
676 ++entry_count;
677 m4af_write32(ctx, i + 1);
678 m4af_write32(ctx, index->samples_per_chunk);
679 m4af_write32(ctx, 1); /* sample_description_index */
680 prev_samples_per_chunk = index->samples_per_chunk;
681 }
682 }
683 m4af_write32_at(ctx, pos + 12, entry_count);
684 m4af_update_box_size(ctx, pos);
685 }
686
687 static
688 void m4af_write_stts_box(m4af_ctx_t *ctx, uint32_t track_idx)
689 {
690 m4af_track_t *track = &ctx->track[track_idx];
691 m4af_sample_entry_t *index = track->sample_table;
692 uint32_t i, prev_delta = 0, entry_count = 0, sample_count = 0;
693 int64_t pos = m4af_tell(ctx);
694 m4af_write(ctx,
695 "\0\0\0\0" /* size */
696 "stts" /* type */
697 "\0" /* version */
698 "\0\0\0" /* flags */
699 "\0\0\0\0" /* entry_count */
700 , 16);
701
702 for (i = 0; i < track->num_samples; ++i, ++index) {
703 if (index->delta == prev_delta)
704 ++sample_count;
705 else {
706 ++entry_count;
707 if (sample_count) {
708 m4af_write32(ctx, sample_count);
709 m4af_write32(ctx, prev_delta);
710 }
711 prev_delta = index->delta;
712 sample_count = 1;
713 }
714 }
715 if (sample_count) {
716 m4af_write32(ctx, sample_count);
717 m4af_write32(ctx, prev_delta);
718 }
719 m4af_write32_at(ctx, pos + 12, entry_count);
720 m4af_update_box_size(ctx, pos);
721 }
722
723 static
724 void m4af_write_esds_box(m4af_ctx_t *ctx, uint32_t track_idx)
725 {
726 m4af_track_t *track = &ctx->track[track_idx];
727 int64_t pos = m4af_tell(ctx);
728 m4af_write(ctx, "\0\0\0\0esds", 8);
729 m4af_write32(ctx, 0); /* version + flags */
730
731 /* ES_Descriptor */
732 m4af_write_descriptor(ctx, 3, 32 + track->decSpecificInfoSize);
733 m4af_write(ctx, "\0\0\0", 3);
734 /* DecoderConfigDescriptor */
735 m4af_write_descriptor(ctx, 4, 18 + track->decSpecificInfoSize);
736 m4af_write(ctx,
737 "\x40" /* objectTypeIndication: 0x40(Audio ISO/IEC 14496-3)*/
738 "\x15" /* streamType(6): 0x05(AudioStream)
739 * upStream(1) : 0
740 * reserved(1) : 1
741 */
742 , 2);
743 m4af_write24(ctx, track->bufferSizeDB);
744 m4af_write32(ctx, track->maxBitrate);
745 m4af_write32(ctx, track->avgBitrate);
746 /* DecoderSpecificInfo */
747 m4af_write_descriptor(ctx, 5, track->decSpecificInfoSize);
748 m4af_write(ctx, track->decSpecificInfo, track->decSpecificInfoSize);
749 /* SLConfigDescriptor */
750 m4af_write_descriptor(ctx, 6, 1);
751 m4af_write(ctx, "\002", 1); /* predefined */
752
753 m4af_update_box_size(ctx, pos);
754 }
755
756 static
757 void m4af_write_alac_box(m4af_ctx_t *ctx, uint32_t track_idx)
758 {
759 m4af_track_t *track = &ctx->track[track_idx];
760 int64_t pos = m4af_tell(ctx);
761 m4af_write(ctx,
762 "\0\0\0\0" /* size */
763 "alac" /* type */
764 "\0" /* version */
765 "\0\0\0" /* flags */
766 , 12);
767 m4af_write(ctx, track->decSpecificInfo, track->decSpecificInfoSize);
768 m4af_update_box_size(ctx, pos);
769 }
770
771 static
772 void m4af_write_mp4a_box(m4af_ctx_t *ctx, uint32_t track_idx)
773 {
774 m4af_track_t *track = &ctx->track[track_idx];
775 int64_t pos = m4af_tell(ctx);
776 m4af_write32(ctx, 0); /* size */
777 m4af_write32(ctx, track->codec); /* mp4a or alac */
778 m4af_write(ctx,
779 "\0\0\0\0\0\0" /* reserved */
780 "\0\001" /* data_reference_index: 1 */
781 "\0\0\0\0" /* reserved[0] */
782 "\0\0\0\0" /* reserved[1] */
783 "\0\002" /* channelcount: 2 */
784 "\0\020" /* samplesize: 16 */
785 "\0\0" /* pre_defined */
786 "\0\0" /* reserved */
787 ,24);
788 if (track->codec == M4AF_FOURCC('m','p','4','a')) {
789 m4af_write32(ctx, track->timescale << 16);
790 m4af_write_esds_box(ctx, track_idx);
791 } else {
792 m4af_write32(ctx, 44100 << 16);
793 m4af_write_alac_box(ctx, track_idx);
794 }
795 m4af_update_box_size(ctx, pos);
796 }
797
798 static
799 void m4af_write_stsd_box(m4af_ctx_t *ctx, uint32_t track_idx)
800 {
801 int64_t pos = m4af_tell(ctx);
802 m4af_write(ctx, "\0\0\0\0stsd", 8);
803 m4af_write(ctx,
804 "\0" /* version */
805 "\0\0\0" /* flags */
806 "\0\0\0\001" /* entry_count: 1 */
807 , 8);
808 m4af_write_mp4a_box(ctx, track_idx);
809 m4af_update_box_size(ctx, pos);
810 }
811
812 static
813 void m4af_write_stbl_box(m4af_ctx_t *ctx, uint32_t track_idx)
814 {
815 int64_t pos = m4af_tell(ctx);
816 m4af_write(ctx, "\0\0\0\0stbl", 8);
817 m4af_write_stsd_box(ctx, track_idx);
818 m4af_write_stts_box(ctx, track_idx);
819 m4af_write_stsc_box(ctx, track_idx);
820 m4af_write_stsz_box(ctx, track_idx);
821 m4af_write_stco_box(ctx, track_idx);
822 m4af_update_box_size(ctx, pos);
823 }
824
825 static
826 void m4af_write_url_box(m4af_ctx_t *ctx, uint32_t track_idx)
827 {
828 m4af_write(ctx,
829 "\0\0\0\014" /* size */
830 "url " /* type */
831 "\0" /* version */
832 "\0\0\001" /* flags: 1(in the same file) */
833 , 12);
834 }
835
836 static
837 void m4af_write_dref_box(m4af_ctx_t *ctx, uint32_t track_idx)
838 {
839 int64_t pos = m4af_tell(ctx);
840 m4af_write(ctx, "\0\0\0\0dref", 8);
841 m4af_write(ctx,
842 "\0" /* version */
843 "\0\0\0" /* flags */
844 "\0\0\0\001" /* entry_count: 1 */
845 ,8);
846 m4af_write_url_box(ctx, track_idx);
847 m4af_update_box_size(ctx, pos);
848 }
849
850 static
851 void m4af_write_dinf_box(m4af_ctx_t *ctx, uint32_t track_idx)
852 {
853 int64_t pos = m4af_tell(ctx);
854 m4af_write(ctx, "\0\0\0\0dinf", 8);
855 m4af_write_dref_box(ctx, track_idx);
856 m4af_update_box_size(ctx, pos);
857 }
858
859 static
860 void m4af_write_smhd_box(m4af_ctx_t *ctx, uint32_t track_idx)
861 {
862 m4af_write(ctx,
863 "\0\0\0\020" /* size */
864 "smhd" /* type */
865 "\0" /* version */
866 "\0\0\0" /* flags */
867 "\0\0" /* balance */
868 "\0\0" /* reserved */
869 , 16);
870 }
871
872 static
873 void m4af_write_minf_box(m4af_ctx_t *ctx, uint32_t track_idx)
874 {
875 m4af_track_t *track = &ctx->track[track_idx];
876 int64_t pos = m4af_tell(ctx);
877 m4af_write(ctx, "\0\0\0\0minf", 8);
878 /* TODO: add TEXT support */
879 if (track->codec != M4AF_CODEC_TEXT)
880 m4af_write_smhd_box(ctx, track_idx);
881 m4af_write_dinf_box(ctx, track_idx);
882 m4af_write_stbl_box(ctx, track_idx);
883 m4af_update_box_size(ctx, pos);
884 }
885
886 static
887 void m4af_write_mdhd_box(m4af_ctx_t *ctx, uint32_t track_idx)
888 {
889 m4af_track_t *track = &ctx->track[track_idx];
890 int64_t pos = m4af_tell(ctx);
891 uint8_t version = (track->creation_time > UINT32_MAX ||
892 track->modification_time > UINT32_MAX ||
893 track->duration > UINT32_MAX);
894
895 m4af_write(ctx, "\0\0\0\0mdhd", 8);
896 m4af_write(ctx, &version, 1);
897 m4af_write(ctx, "\0\0\0", 3); /* flags */
898 if (version) {
899 m4af_write64(ctx, track->creation_time);
900 m4af_write64(ctx, track->modification_time);
901 m4af_write32(ctx, track->timescale);
902 m4af_write64(ctx, track->duration);
903 } else {
904 m4af_write32(ctx, track->creation_time);
905 m4af_write32(ctx, track->modification_time);
906 m4af_write32(ctx, track->timescale);
907 m4af_write32(ctx, track->duration);
908 }
909 m4af_write(ctx,
910 "\x55\xc4" /* language: und */
911 "\0\0" /* pre_defined */
912 , 4);
913 m4af_update_box_size(ctx, pos);
914 }
915
916 static
917 void m4af_write_hdlr_box(m4af_ctx_t *ctx, uint32_t track_idx, const char *type)
918 {
919 int64_t pos = m4af_tell(ctx);
920 static const char reserved_and_name[10] = { 0 };
921
922 m4af_write(ctx,
923 "\0\0\0\0" /* size */
924 "hdlr" /* type */
925 "\0" /* version */
926 "\0\0\0" /* flags */
927 "\0\0\0\0" /* pre_defined */
928 , 16);
929 m4af_write(ctx, type, 4); /* handler_type */
930 /* reserved[0] */
931 m4af_write(ctx, !strcmp(type, "mdir") ? "appl" : "\0\0\0\0", 4);
932 /* reserved[1], reserved[2], name */
933 m4af_write(ctx, reserved_and_name, (pos & 1) ? 9 : 10);
934 m4af_update_box_size(ctx, pos);
935 }
936
937 static
938 void m4af_write_mdia_box(m4af_ctx_t *ctx, uint32_t track_idx)
939 {
940 m4af_track_t *track = &ctx->track[track_idx];
941 const char *hdlr =
942 (track->codec == M4AF_CODEC_TEXT) ? "text" : "soun";
943 int64_t pos = m4af_tell(ctx);
944 m4af_write(ctx, "\0\0\0\0mdia", 8);
945 m4af_write_mdhd_box(ctx, track_idx);
946 m4af_write_hdlr_box(ctx, track_idx, hdlr);
947 m4af_write_minf_box(ctx, track_idx);
948 m4af_update_box_size(ctx, pos);
949 }
950
951 static
952 void m4af_write_tkhd_box(m4af_ctx_t *ctx, uint32_t track_idx)
953 {
954 m4af_track_t *track = &ctx->track[track_idx];
955 int64_t pos = m4af_tell(ctx);
956 int64_t duration =
957 (double)track->duration / track->timescale * ctx->timescale + .5;
958 uint8_t version = (track->creation_time > UINT32_MAX ||
959 track->modification_time > UINT32_MAX ||
960 duration > UINT32_MAX);
961 m4af_write(ctx, "\0\0\0\0tkhd", 8);
962 m4af_write(ctx, &version, 1);
963 m4af_write(ctx, "\0\0\007", 3); /* flags */
964 if (version) {
965 m4af_write64(ctx, track->creation_time);
966 m4af_write64(ctx, track->modification_time);
967 m4af_write32(ctx, track_idx + 1);
968 m4af_write(ctx, "\0\0\0\0" /* reserved */
969 , 4);
970 m4af_write64(ctx, duration);
971 } else {
972 m4af_write32(ctx, track->creation_time);
973 m4af_write32(ctx, track->modification_time);
974 m4af_write32(ctx, track_idx + 1);
975 m4af_write(ctx, "\0\0\0\0" /* reserved */
976 , 4);
977 m4af_write32(ctx, duration);
978 }
979 m4af_write(ctx,
980 "\0\0\0\0" /* reserved[0] */
981 "\0\0\0\0" /* reserved[1] */
982 "\0\0" /* layer */
983 "\0\0" /* alternate_group */
984 "\001\0" /* volume: 1.0 */
985 "\0\0" /* reserved */
986 "\0\001\0\0" /* matrix[0] */
987 "\0\0\0\0" /* matrix[1] */
988 "\0\0\0\0" /* matrix[2] */
989 "\0\0\0\0" /* matrix[3] */
990 "\0\001\0\0" /* matrix[4] */
991 "\0\0\0\0" /* matrix[5] */
992 "\0\0\0\0" /* matrix[6] */
993 "\0\0\0\0" /* matrix[7] */
994 "\100\0\0\0" /* matrix[8] */
995 "\0\0\0\0" /* width */
996 "\0\0\0\0" /* height */
997 , 60);
998 m4af_update_box_size(ctx, pos);
999 }
1000
1001 static
1002 void m4af_write_trak_box(m4af_ctx_t *ctx, uint32_t track_idx)
1003 {
1004 int64_t pos = m4af_tell(ctx);
1005 m4af_write(ctx, "\0\0\0\0trak", 8);
1006 m4af_write_tkhd_box(ctx, track_idx);
1007 m4af_write_mdia_box(ctx, track_idx);
1008 m4af_update_box_size(ctx, pos);
1009 }
1010
1011 static
1012 int64_t m4af_movie_duration(m4af_ctx_t *ctx)
1013 {
1014 int64_t movie_duration = 0;
1015 unsigned i;
1016 for (i = 0; i < ctx->num_tracks; ++i) {
1017 double x = ctx->track[i].duration;
1018 int64_t duration = x / ctx->track[i].timescale * ctx->timescale + .5;
1019 if (duration > movie_duration)
1020 movie_duration = duration;
1021 }
1022 return movie_duration;
1023 }
1024
1025 static
1026 void m4af_write_mvhd_box(m4af_ctx_t *ctx)
1027 {
1028 int64_t pos = m4af_tell(ctx);
1029 int64_t movie_duration = m4af_movie_duration(ctx);
1030 uint8_t version = (ctx->creation_time > UINT32_MAX ||
1031 ctx->modification_time > UINT32_MAX ||
1032 movie_duration > UINT32_MAX);
1033
1034 m4af_write(ctx, "\0\0\0\0mvhd", 8);
1035 m4af_write(ctx, &version, 1);
1036 m4af_write(ctx, "\0\0\0", 3); /* flags */
1037 if (version) {
1038 m4af_write64(ctx, ctx->creation_time);
1039 m4af_write64(ctx, ctx->modification_time);
1040 m4af_write32(ctx, ctx->timescale);
1041 m4af_write64(ctx, movie_duration);
1042 } else {
1043 m4af_write32(ctx, ctx->creation_time);
1044 m4af_write32(ctx, ctx->modification_time);
1045 m4af_write32(ctx, ctx->timescale);
1046 m4af_write32(ctx, movie_duration);
1047 }
1048 m4af_write(ctx,
1049 "\0\001\0\0" /* rate: 1.0 */
1050 "\001\0" /* volume: 1.0 */
1051 "\0\0" /* reserved */
1052 "\0\0\0\0" /* reserved[0] */
1053 "\0\0\0\0" /* reserved[1] */
1054 "\0\001\0\0" /* matrix[0] */
1055 "\0\0\0\0" /* matrix[1] */
1056 "\0\0\0\0" /* matrix[2] */
1057 "\0\0\0\0" /* matrix[3] */
1058 "\0\001\0\0" /* matrix[4] */
1059 "\0\0\0\0" /* matrix[5] */
1060 "\0\0\0\0" /* matrix[6] */
1061 "\0\0\0\0" /* matrix[7] */
1062 "\100\0\0\0" /* matrix[8] */
1063 "\0\0\0\0" /* pre_defined[0] */
1064 "\0\0\0\0" /* pre_defined[1] */
1065 "\0\0\0\0" /* pre_defined[2] */
1066 "\0\0\0\0" /* pre_defined[3] */
1067 "\0\0\0\0" /* pre_defined[4] */
1068 "\0\0\0\0" /* pre_defined[5] */
1069 , 76);
1070 m4af_write32(ctx, ctx->num_tracks + 1);
1071 m4af_update_box_size(ctx, pos);
1072 }
1073
1074 static
1075 void m4af_write_mean_box(m4af_ctx_t *ctx)
1076 {
1077 m4af_write(ctx,
1078 "\0\0\0\034" /* size */
1079 "mean"
1080 "\0" /* version */
1081 "\0\0\0" /* flags */
1082 "com.apple.iTunes" /* meaning-string */
1083 , 28);
1084 }
1085
1086 static
1087 void m4af_write_name_box(m4af_ctx_t *ctx, const char *name)
1088 {
1089 int64_t pos = m4af_tell(ctx);
1090 m4af_write(ctx,
1091 "\0\0\0\0" /* size */
1092 "name" /* type */
1093 "\0" /* version */
1094 "\0\0\0" /* flags */
1095 , 12);
1096 m4af_write(ctx, name, strlen(name));
1097 m4af_update_box_size(ctx, pos);
1098 }
1099
1100 static
1101 void m4af_write_data_box(m4af_ctx_t *ctx, uint32_t type_code,
1102 const char *data, uint32_t data_size)
1103 {
1104 int64_t pos = m4af_tell(ctx);
1105 uint8_t code = type_code;
1106 m4af_write(ctx,
1107 "\0\0\0\0" /* size */
1108 "data" /* type */
1109 "\0\0" /* reserved */
1110 "\0" /* type_set_indifier */
1111 ,11);
1112 m4af_write(ctx, &code, 1);
1113 m4af_write(ctx, "\0\0\0\0", 4); /* locale */
1114 m4af_write(ctx, data, data_size);
1115 m4af_update_box_size(ctx, pos);
1116 }
1117
1118 static
1119 void m4af_write_metadata(m4af_ctx_t *ctx, m4af_itmf_entry_t *entry)
1120 {
1121 int64_t pos = m4af_tell(ctx);
1122 m4af_write(ctx, "\0\0\0\0", 4);
1123 m4af_write32(ctx, entry->fcc);
1124 if (entry->fcc != M4AF_FOURCC('-','-','-','-'))
1125 m4af_write_data_box(ctx, entry->type_code,
1126 entry->data, entry->data_size);
1127 else {
1128 m4af_write_mean_box(ctx);
1129 m4af_write_name_box(ctx, entry->name);
1130 m4af_write_data_box(ctx, 1, entry->data, entry->data_size);
1131 }
1132 m4af_update_box_size(ctx, pos);
1133 }
1134
1135 static
1136 void m4af_write_ilst_box(m4af_ctx_t *ctx)
1137 {
1138 uint32_t i;
1139 int64_t pos = m4af_tell(ctx);
1140 m4af_write(ctx, "\0\0\0\0ilst", 8);
1141 for (i = 0; i < ctx->num_tags; ++i)
1142 m4af_write_metadata(ctx, &ctx->itmf_table[i]);
1143 m4af_update_box_size(ctx, pos);
1144 }
1145
1146 static
1147 void m4af_write_meta_box(m4af_ctx_t *ctx)
1148 {
1149 int64_t pos = m4af_tell(ctx);
1150 m4af_write(ctx,
1151 "\0\0\0\0" /* size */
1152 "meta" /* type */
1153 "\0" /* version */
1154 "\0\0\0" /* flags */
1155 , 12);
1156 m4af_write_hdlr_box(ctx, 0, "mdir");
1157 m4af_write_ilst_box(ctx);
1158 m4af_update_box_size(ctx, pos);
1159 }
1160
1161 static
1162 void m4af_write_udta_box(m4af_ctx_t *ctx)
1163 {
1164 int64_t pos = m4af_tell(ctx);
1165 m4af_write(ctx, "\0\0\0\0udta", 8);
1166 m4af_write_meta_box(ctx);
1167 m4af_update_box_size(ctx, pos);
1168 }
1169
1170 static
1171 void m4af_write_moov_box(m4af_ctx_t *ctx)
1172 {
1173 unsigned i;
1174 int64_t pos = m4af_tell(ctx);
1175 m4af_write(ctx, "\0\0\0\0moov", 8);
1176 m4af_write_mvhd_box(ctx);
1177 for (i = 0; i < ctx->num_tracks; ++i)
1178 m4af_write_trak_box(ctx, i);
1179 if (ctx->num_tags)
1180 m4af_write_udta_box(ctx);
1181 m4af_update_box_size(ctx, pos);
1182 }
1183
1184 static
1185 void m4af_finalize_mdat(m4af_ctx_t *ctx)
1186 {
1187 if (ctx->mdat_size + 8 > UINT32_MAX) {
1188 m4af_set_pos(ctx, ctx->mdat_pos - 16);
1189 m4af_write32(ctx, 1);
1190 m4af_write(ctx, "mdat", 4);
1191 m4af_write64(ctx, ctx->mdat_size + 16);
1192 } else {
1193 m4af_set_pos(ctx, ctx->mdat_pos - 8);
1194 m4af_write32(ctx, ctx->mdat_size + 8);
1195 }
1196 m4af_set_pos(ctx, ctx->mdat_pos + ctx->mdat_size);
1197 }
1198
1199 int m4af_finalize(m4af_ctx_t *ctx)
1200 {
1201 unsigned i;
1202 m4af_track_t *track;
1203
1204 for (i = 0; i < ctx->num_tracks; ++i) {
1205 track = ctx->track + i;
1206 if (track->duration) {
1207 int64_t track_size = 0;
1208 unsigned j;
1209 for (j = 0; j < track->num_chunks; ++j)
1210 track_size += track->chunk_table[j].size;
1211 track->avgBitrate =
1212 8.0 * track_size * track->timescale / track->duration + .5;
1213 }
1214 m4af_flush_chunk(ctx, i);
1215 }
1216 if (ctx->track[0].encoder_delay || ctx->track[0].padding)
1217 m4af_set_iTunSMPB(ctx);
1218 m4af_finalize_mdat(ctx);
1219 m4af_write_moov_box(ctx);
1220 return ctx->last_error;
1221 }
This page took 0.057126 seconds and 4 git commands to generate.