2 * Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
3 * FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
12 #include "portable_io.h"
17 uint16_t channelCount;
21 uint32_t stsz_sample_size;
22 uint32_t stsz_sample_count;
26 uint32_t stts_entry_count;
27 uint32_t *stts_sample_count;
30 uint32_t stsc_entry_count;
31 uint32_t *stsc_first_chunk;
32 uint32_t *stsc_samples_per_chunk;
35 uint32_t stco_entry_count;
36 uint32_t *stco_chunk_offset;
42 #define MAX_TRACKS 1024
45 const struct mp4_callback *cb;
46 int64_t current_position;
60 /* incremental track index while reading the file */
63 struct mp4_track *track[MAX_TRACKS];
64 /* the first audio track found */
65 struct mp4_track *audio_track;
68 struct mp4_metadata meta;
72 * Returns -1, 0, or 1 on errors/EOF/success. Partial reads followed by EOF or
73 * read errors are treated as errors.
75 static int read_data(struct mp4 *f, void *data, size_t size)
78 ssize_t ret = f->cb->read(f->cb->user_data, data, size);
79 if (ret < 0 && errno == EINTR)
81 /* regard EAGAIN as an error as reads should be blocking. */
83 return ret < 0? -1 : 0;
84 f->current_position += ret;
90 static int read_int64(struct mp4 *f, uint64_t *result)
93 int ret = read_data(f, data, 8);
95 if (ret > 0 && result)
96 *result = read_u64_be(data);
100 static int read_int32(struct mp4 *f, uint32_t *result)
103 int ret = read_data(f, data, 4);
105 if (ret > 0 && result)
106 *result = read_u32_be(data);
110 static int read_int24(struct mp4 *f, uint32_t *result)
113 int ret = read_data(f, data, 3);
115 if (ret > 0 && result)
116 *result = read_u24_be(data);
120 static int read_int16(struct mp4 *f, uint16_t *result)
123 int ret = read_data(f, data, 2);
125 if (ret > 0 && result)
126 *result = read_u16_be(data);
130 static uint8_t read_int8(struct mp4 *f, uint8_t *result)
133 int ret = read_data(f, data, 1);
135 if (ret > 0 && result)
141 ATOM_ITEM(MOOV, 'm', 'o', 'o', 'v') \
142 ATOM_ITEM(TRAK, 't', 'r', 'a', 'k') \
143 ATOM_ITEM(MDIA, 'm', 'd', 'i', 'a') \
144 ATOM_ITEM(MINF, 'm', 'i', 'n', 'f') \
145 ATOM_ITEM(STBL, 's', 't', 'b', 'l') \
146 ATOM_ITEM(UDTA, 'u', 'd', 't', 'a') \
147 ATOM_ITEM(ILST, 'i', 'l', 's', 't') /* iTunes Metadata list */ \
148 ATOM_ITEM(ARTIST, 0xa9, 'A', 'R', 'T') \
149 ATOM_ITEM(TITLE, 0xa9, 'n', 'a', 'm') \
150 ATOM_ITEM(ALBUM, 0xa9, 'a', 'l', 'b') \
151 ATOM_ITEM(DATE, 0xa9, 'd', 'a', 'y') \
152 ATOM_ITEM(COMMENT, 0xa9, 'c', 'm', 't') \
153 ATOM_ITEM(MDHD, 'm', 'd', 'h', 'd') /* track header */ \
154 ATOM_ITEM(STSD, 's', 't', 's', 'd') /* sample description box */ \
155 ATOM_ITEM(STTS, 's', 't', 't', 's') /* time to sample box */ \
156 ATOM_ITEM(STSZ, 's', 't', 's', 'z') /* sample size box */ \
157 ATOM_ITEM(STCO, 's', 't', 'c', 'o') /* chunk offset box */ \
158 ATOM_ITEM(STSC, 's', 't', 's', 'c') /* sample to chunk box */ \
159 ATOM_ITEM(MP4A, 'm', 'p', '4', 'a') \
160 ATOM_ITEM(META, 'm', 'e', 't', 'a') /* iTunes Metadata box */ \
161 ATOM_ITEM(DATA, 'd', 'a', 't', 'a') /* iTunes Metadata data box */ \
163 #define ATOM_ITEM(_name, a, b, c, d) ATOM_ ## _name,
164 enum atom {ATOM_ITEMS};
167 static uint8_t atom_name_to_type(uint8_t *p)
169 #define ATOM_VALUE(a, b, c, d) ((a << 24) + (b << 16) + (c << 8) + d)
170 #define ATOM_ITEM(_name, a, b, c, d) \
171 {.name = # _name, .val = ATOM_VALUE(a, b, c, d)},
172 static const struct {
175 } atom_table[] = {ATOM_ITEMS};
177 uint32_t val = read_u32_be(p);
179 for (uint8_t n = 0; n < ARRAY_SIZE(atom_table); n++)
180 if (val == atom_table[n].val)
185 /* read atom header, atom size is returned with header included. */
186 static int atom_read_header(struct mp4 *f, uint8_t *atom_type,
187 uint8_t *header_size, uint64_t *atom_size)
191 uint8_t atom_header[8];
193 ret = read_data(f, atom_header, 8);
196 size = read_u32_be(atom_header);
197 if (size == 1) { /* 64 bit atom size */
200 ret = read_int64(f, atom_size);
209 *atom_type = atom_name_to_type(atom_header + 4);
213 static int64_t get_position(const struct mp4 *f)
215 return f->current_position;
218 static int32_t set_position(struct mp4 *f, int64_t position)
220 f->cb->seek(f->cb->user_data, position);
221 f->current_position = position;
226 static int read_stsz(struct mp4 *f)
232 if (f->total_tracks == 0)
234 t = f->track[f->total_tracks - 1];
235 ret = read_int8(f, NULL); /* version */
238 ret = read_int24(f, NULL); /* flags */
241 ret = read_int32(f, &t->stsz_sample_size);
244 ret = read_int32(f, &t->stsz_sample_count);
247 if (t->stsz_sample_size != 0)
249 t->stsz_table = para_malloc(t->stsz_sample_count * sizeof(int32_t));
250 for (i = 0; i < t->stsz_sample_count; i++) {
251 ret = read_int32(f, &t->stsz_table[i]);
258 static int read_stts(struct mp4 *f)
264 if (f->total_tracks == 0)
266 t = f->track[f->total_tracks - 1];
267 if (t->stts_entry_count)
269 ret = read_int8(f, NULL); /* version */
272 ret = read_int24(f, NULL); /* flags */
275 ret = read_int32(f, &t->stts_entry_count);
278 t->stts_sample_count = para_malloc(t->stts_entry_count
280 for (i = 0; i < t->stts_entry_count; i++) {
281 ret = read_int32(f, &t->stts_sample_count[i]);
284 ret = read_int32(f, NULL); /* sample delta */
291 static int read_stsc(struct mp4 *f)
297 if (f->total_tracks == 0)
299 t = f->track[f->total_tracks - 1];
301 ret = read_int8(f, NULL); /* version */
304 ret = read_int24(f, NULL); /* flags */
307 ret = read_int32(f, &t->stsc_entry_count);
310 t->stsc_first_chunk = para_malloc(t->stsc_entry_count * sizeof(int32_t));
311 t->stsc_samples_per_chunk = para_malloc(t->stsc_entry_count
313 for (i = 0; i < t->stsc_entry_count; i++) {
314 ret = read_int32(f, &t->stsc_first_chunk[i]);
317 ret = read_int32(f, &t->stsc_samples_per_chunk[i]);
320 ret = read_int32(f, NULL); /* sample desc index */
327 static int read_stco(struct mp4 *f)
333 if (f->total_tracks == 0)
335 t = f->track[f->total_tracks - 1];
337 ret = read_int8(f, NULL); /* version */
340 ret = read_int24(f, NULL); /* flags */
343 ret = read_int32(f, &t->stco_entry_count);
346 t->stco_chunk_offset = para_malloc(t->stco_entry_count
348 for (i = 0; i < t->stco_entry_count; i++) {
349 ret = read_int32(f, &t->stco_chunk_offset[i]);
356 static int read_mp4a(struct mp4 *f)
362 if (f->total_tracks == 0)
364 t = f->track[f->total_tracks - 1];
366 for (i = 0; i < 6; i++) {
367 ret = read_int8(f, NULL); /* reserved */
371 ret = read_int16(f, NULL); /* data_reference_index */
374 ret = read_int32(f, NULL); /* reserved */
377 ret = read_int32(f, NULL); /* reserved */
380 ret = read_int16(f, &t->channelCount);
383 ret = read_int16(f, NULL);
386 ret = read_int16(f, NULL);
389 ret = read_int16(f, NULL);
392 return read_int16(f, &t->sampleRate);
395 static int read_stsd(struct mp4 *f)
398 uint32_t i, entry_count;
401 if (f->total_tracks == 0)
403 t = f->track[f->total_tracks - 1];
404 ret = read_int8(f, NULL); /* version */
407 ret = read_int24(f, NULL); /* flags */
410 ret = read_int32(f, &entry_count);
413 for (i = 0; i < entry_count; i++) {
414 uint64_t skip = get_position(f);
416 uint8_t atom_type = 0;
417 ret = atom_read_header(f, &atom_type, NULL, &size);
421 if (!f->audio_track && atom_type == ATOM_MP4A) {
425 set_position(f, skip);
430 static const char *get_metadata_name(uint8_t atom_type)
433 case ATOM_TITLE: return "title";
434 case ATOM_ARTIST: return "artist";
435 case ATOM_ALBUM: return "album";
436 case ATOM_DATE: return "date";
437 case ATOM_COMMENT: return "comment";
438 default: return "unknown";
442 static int parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
445 uint64_t subsize, sumsize;
454 set_position(f, destpos), sumsize += subsize
457 uint8_t header_size = 0;
458 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
461 destpos = get_position(f) + subsize - header_size;
462 if (atom_type != ATOM_DATA)
464 ret = read_int8(f, NULL); /* version */
467 ret = read_int24(f, NULL); /* flags */
470 ret = read_int32(f, NULL); /* reserved */
473 ret = -ERRNO_TO_PARA_ERROR(EINVAL);
474 if (subsize < header_size + 8 || subsize > UINT_MAX)
476 len = subsize - (header_size + 8);
478 value = para_malloc(len + 1);
479 ret = read_data(f, value, len);
485 return -ERRNO_TO_PARA_ERROR(EINVAL);
486 f->meta.tags = para_realloc(f->meta.tags, (f->meta.count + 1)
487 * sizeof(struct mp4_tag));
488 tag = f->meta.tags + f->meta.count;
489 tag->item = para_strdup(get_metadata_name(parent));
499 static int read_mdhd(struct mp4 *f)
505 if (f->total_tracks == 0)
507 t = f->track[f->total_tracks - 1];
509 ret = read_int32(f, &version);
513 ret = read_int64(f, NULL); /* creation-time */
516 ret = read_int64(f, NULL); /* modification-time */
519 ret = read_int32(f, &t->timeScale);
522 ret = read_int64(f, &t->duration);
525 } else { //version == 0
528 ret = read_int32(f, NULL); /* creation-time */
531 ret = read_int32(f, NULL); /* modification-time */
534 ret = read_int32(f, &t->timeScale);
537 ret = read_int32(f, &temp);
540 t->duration = (temp == (uint32_t) (-1))?
541 (uint64_t) (-1) : (uint64_t) (temp);
543 ret = read_int16(f, NULL);
546 ret = read_int16(f, NULL);
552 static int32_t read_ilst(struct mp4 *f, int32_t size)
555 uint64_t sumsize = 0;
557 while (sumsize < size) {
559 uint64_t subsize, destpos;
560 uint8_t header_size = 0;
561 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
564 destpos = get_position(f) + subsize - header_size;
571 ret = parse_tag(f, atom_type, subsize - header_size);
575 set_position(f, destpos);
581 static int32_t read_meta(struct mp4 *f, uint64_t size)
584 uint64_t subsize, sumsize = 0;
586 uint8_t header_size = 0;
588 ret = read_int8(f, NULL); /* version */
591 ret = read_int24(f, NULL); /* flags */
594 while (sumsize < (size - (header_size + 4))) {
595 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
598 if (subsize <= header_size + 4)
600 if (atom_type == ATOM_ILST) {
601 f->ilst_offset = get_position(f) - header_size;
602 f->ilst_size = subsize;
603 ret = read_ilst(f, subsize - (header_size + 4));
607 set_position(f, get_position(f) + subsize - header_size);
613 static bool need_atom(uint8_t atom_type, bool meta_only)
615 /* these are needed in any case */
626 /* meta-only opens don't need anything else */
629 /* these are only required for regular opens */
641 /* parse atoms that are sub atoms of other atoms */
642 static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only)
645 uint64_t dest, size, end = get_position(f) + total_size;
647 for (dest = get_position(f); dest < end; set_position(f, dest)) {
648 uint8_t header_size, atom_type;
649 ret = atom_read_header(f, &atom_type, &header_size, &size);
654 dest = get_position(f) + size - header_size;
655 if (atom_type == ATOM_TRAK) {
656 if (f->total_tracks >= MAX_TRACKS)
659 f->track[f->total_tracks - 1] = para_calloc(
660 sizeof(struct mp4_track));
661 } else if (atom_type == ATOM_UDTA) {
662 f->udta_offset = get_position(f) - header_size;
665 if (!need_atom(atom_type, meta_only))
668 case ATOM_STSZ: ret = read_stsz(f); break;
669 case ATOM_STTS: ret = read_stts(f); break;
670 case ATOM_STSC: ret = read_stsc(f); break;
671 case ATOM_STCO: ret = read_stco(f); break;
672 case ATOM_STSD: ret = read_stsd(f); break;
673 case ATOM_MDHD: ret = read_mdhd(f); break;
675 f->meta_offset = get_position(f) - header_size;
677 ret = read_meta(f, size);
680 ret = parse_sub_atoms(f, size - header_size, meta_only);
688 static int open_file(const struct mp4_callback *cb, bool meta_only, struct mp4 **result)
692 uint8_t atom_type, header_size;
693 struct mp4 *f = para_calloc(sizeof(*f));
696 while ((ret = atom_read_header(f, &atom_type, &header_size, &size)) > 0) {
697 f->file_size += size;
698 f->last_atom = atom_type;
699 if (atom_type != ATOM_MOOV || size <= header_size) { /* skip */
700 set_position(f, get_position(f) + size - header_size);
703 f->moov_offset = get_position(f) - header_size;
705 ret = parse_sub_atoms(f, size - header_size, meta_only);
724 int mp4_open_read(const struct mp4_callback *cb, struct mp4 **result)
726 return open_file(cb, false, result);
729 void mp4_close(struct mp4 *f)
733 for (i = 0; i < f->total_tracks; i++) {
735 free(f->track[i]->stsz_table);
736 free(f->track[i]->stts_sample_count);
737 free(f->track[i]->stsc_first_chunk);
738 free(f->track[i]->stsc_samples_per_chunk);
739 free(f->track[i]->stco_chunk_offset);
743 for (i = 0; i < f->meta.count; i++) {
744 free(f->meta.tags[i].item);
745 free(f->meta.tags[i].value);
751 static int32_t chunk_of_sample(const struct mp4 *f, int32_t sample,
754 const struct mp4_track *t = f->audio_track;
755 uint32_t *fc = t->stsc_first_chunk, *spc = t->stsc_samples_per_chunk;
756 int32_t chunk1, chunk1samples, n, total, i;
758 for (i = 1, total = 0; i < t->stsc_entry_count; i++, total += n) {
759 n = (fc[i] - fc[i - 1]) * spc[i - 1]; /* number of samples */
760 if (sample < total + n)
764 chunk1samples = spc[i - 1];
765 if (chunk1samples != 0)
766 *chunk = (sample - total) / chunk1samples + chunk1;
769 return total + (*chunk - chunk1) * chunk1samples;
773 * Return the number of milliseconds of the audio track.
775 * \param f As returned by \ref mp4_open_read(), must not be NULL.
777 uint64_t mp4_get_duration(const struct mp4 *f)
779 const struct mp4_track *t = f->audio_track;
781 if (t->timeScale == 0)
783 return t->duration * 1000 / t->timeScale;
786 int mp4_set_sample_position(struct mp4 *f, int32_t sample)
788 const struct mp4_track *t = f->audio_track;
789 int32_t offset, chunk, chunk_sample;
790 uint32_t n, srs; /* sample range size */
792 if (sample >= t->stsz_sample_count)
793 return -ERRNO_TO_PARA_ERROR(EINVAL);
794 chunk_sample = chunk_of_sample(f, sample, &chunk);
795 if (t->stsz_sample_size > 0)
796 srs = (sample - chunk_sample) * t->stsz_sample_size;
798 for (srs = 0, n = chunk_sample; n < sample; n++)
799 srs += t->stsz_table[n];
801 if (t->stco_entry_count > 0 && chunk > t->stco_entry_count)
802 offset = t->stco_chunk_offset[t->stco_entry_count - 1];
803 else if (t->stco_entry_count > 0)
804 offset = t->stco_chunk_offset[chunk - 1];
807 set_position(f, offset + srs);
811 int32_t mp4_get_sample_size(const struct mp4 *f, int sample)
813 const struct mp4_track *t = f->audio_track;
815 if (t->stsz_sample_size != 0)
816 return t->stsz_sample_size;
817 return t->stsz_table[sample];
820 uint32_t mp4_get_sample_rate(const struct mp4 *f)
822 return f->audio_track->sampleRate;
825 uint32_t mp4_get_channel_count(const struct mp4 *f)
827 return f->audio_track->channelCount ;
830 int32_t mp4_num_samples(const struct mp4 *f)
832 const struct mp4_track *t = f->audio_track;
836 for (i = 0; i < t->stts_entry_count; i++)
837 total += t->stts_sample_count[i];
841 int mp4_open_meta(const struct mp4_callback *cb, struct mp4 **result)
844 int ret = open_file(cb, true, &f);
848 if (f->udta_size == 0 || f->meta_size == 0 || f->ilst_size == 0) {
851 return -E_MP4_MISSING_ATOM;
858 * Return the metadata of an mp4 file.
860 * \param f As returned by either \ref mp4_open_read() or \ref mp4_open_meta().
862 * The caller is allowed to add, delete or modify the entries of the returned
863 * structure in order to pass the modified version to \ref mp4_meta_update().
865 struct mp4_metadata *mp4_get_meta(struct mp4 *f)
870 /** Total length of an on-disk metadata tag. */
871 #define TAG_LEN(_len) (24 + (_len))
872 static void create_ilst(const struct mp4_metadata *meta, uint8_t *out)
874 for (unsigned n = 0; n < meta->count; n++) {
875 struct mp4_tag *tag = meta->tags + n;
876 unsigned len = strlen(tag->value);
877 const char *atom_name;
879 if (!strcasecmp(tag->item, "title"))
880 atom_name = "\xA9" "nam";
881 else if (!strcasecmp(tag->item, "artist"))
882 atom_name = "\xA9" "ART";
883 else if (!strcasecmp(tag->item, "album"))
884 atom_name = "\xA9" "alb";
885 else if (!strcasecmp(tag->item, "date"))
886 atom_name = "\xA9" "day";
887 else if (!strcasecmp(tag->item, "comment"))
888 atom_name = "\xA9" "cmt";
891 write_u32_be(out, TAG_LEN(len));
892 memcpy(out + 4, atom_name, 4);
893 write_u32_be(out + 8, 8 /* data atom header */
894 + 8 /* flags + reserved */
896 memcpy(out + 12, "data", 4);
897 write_u32_be(out + 16, 1); /* flags */
898 write_u32_be(out + 20, 0); /* reserved */
899 memcpy(out + 24, tag->value, len);
904 static void *modify_moov(struct mp4 *f, uint32_t *out_size)
907 uint64_t total_base = f->moov_offset + 8;
908 uint32_t total_size = (uint32_t) (f->moov_size - 8);
909 uint32_t new_ilst_size = 0;
915 for (unsigned n = 0; n < f->meta.count; n++)
916 new_ilst_size += TAG_LEN(strlen(f->meta.tags[n].value));
917 size_delta = new_ilst_size - (f->ilst_size - 8);
918 *out_size = total_size + size_delta;
919 out_buffer = para_malloc(*out_size);
921 set_position(f, total_base);
922 ret = read_data(f, p_out, f->udta_offset - total_base);
925 p_out += f->udta_offset - total_base;
926 ret = read_int32(f, &tmp);
929 write_u32_be(p_out, tmp + size_delta);
931 ret = read_data(f, p_out, 4);
935 ret = read_data(f, p_out, f->meta_offset - f->udta_offset - 8);
938 p_out += f->meta_offset - f->udta_offset - 8;
939 ret = read_int32(f, &tmp);
942 write_u32_be(p_out, tmp + size_delta);
944 ret = read_data(f, p_out, 4);
948 ret = read_data(f, p_out, f->ilst_offset - f->meta_offset - 8);
951 p_out += f->ilst_offset - f->meta_offset - 8;
952 ret = read_int32(f, &tmp);
955 write_u32_be(p_out, tmp + size_delta);
957 ret = read_data(f, p_out, 4);
961 create_ilst(&f->meta, p_out);
962 p_out += new_ilst_size;
963 set_position(f, f->ilst_offset + f->ilst_size);
964 ret = read_data(f, p_out, total_size - (f->ilst_offset - total_base)
971 static int32_t write_data(struct mp4 *f, void *data, uint32_t size)
975 result = f->cb->write(f->cb->user_data, data, size);
977 f->current_position += size;
982 static int32_t write_int32(struct mp4 *f, uint32_t data)
985 write_u32_be(temp, data);
986 return write_data(f, temp, sizeof(temp));
989 int32_t mp4_meta_update(struct mp4 *f)
992 uint32_t new_moov_size;
995 new_moov_data = modify_moov(f, &new_moov_size);
996 if (!new_moov_data ) {
1000 /* copy moov atom to end of the file */
1001 if (f->last_atom != ATOM_MOOV) {
1002 char *free_data = "free";
1004 /* rename old moov to free */
1005 set_position(f, f->moov_offset + 4);
1006 write_data(f, free_data, 4);
1008 set_position(f, f->file_size);
1009 write_int32(f, new_moov_size + 8);
1010 write_data(f, "moov", 4);
1011 write_data(f, new_moov_data, new_moov_size);
1013 set_position(f, f->moov_offset);
1014 write_int32(f, new_moov_size + 8);
1015 write_data(f, "moov", 4);
1016 write_data(f, new_moov_data, new_moov_size);
1018 free(new_moov_data);
1019 f->cb->truncate(f->cb->user_data);
1023 static char *meta_find_by_name(const struct mp4 *f, const char *item)
1027 for (i = 0; i < f->meta.count; i++)
1028 if (!strcasecmp(f->meta.tags[i].item, item))
1029 return para_strdup(f->meta.tags[i].value);
1034 * Return the value of the artist meta tag of an mp4 file.
1036 * \param f Must not be NULL.
1038 * \return If the file does not contain this metadata tag, the function returns
1039 * NULL. Otherwise, a copy of the tag value is returned. The caller should free
1040 * this memory when it is no longer needed.
1042 char *mp4_meta_get_artist(const struct mp4 *f)
1044 return meta_find_by_name(f, "artist");
1048 * Return the value of the title meta tag of an mp4 file.
1050 * \param f See \ref mp4_meta_get_artist().
1051 * \return See \ref mp4_meta_get_artist().
1053 char *mp4_meta_get_title(const struct mp4 *f)
1055 return meta_find_by_name(f, "title");
1059 * Return the value of the date meta tag of an mp4 file.
1061 * \param f See \ref mp4_meta_get_artist().
1062 * \return See \ref mp4_meta_get_artist().
1064 char *mp4_meta_get_date(const struct mp4 *f)
1066 return meta_find_by_name(f, "date");
1070 * Return the value of the album meta tag of an mp4 file.
1072 * \param f See \ref mp4_meta_get_artist().
1073 * \return See \ref mp4_meta_get_artist().
1075 char *mp4_meta_get_album(const struct mp4 *f)
1077 return meta_find_by_name(f, "album");
1081 * Return the value of the comment meta tag of an mp4 file.
1083 * \param f See \ref mp4_meta_get_artist().
1084 * \return See \ref mp4_meta_get_artist().
1086 char *mp4_meta_get_comment(const struct mp4 *f)
1088 return meta_find_by_name(f, "comment");