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