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