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"
18 uint16_t channel_count;
22 uint32_t stsz_sample_size;
23 uint32_t stsz_sample_count;
27 uint32_t stts_entry_count;
28 uint32_t *stts_sample_count;
31 uint32_t stsc_entry_count;
32 uint32_t *stsc_first_chunk;
33 uint32_t *stsc_samples_per_chunk;
36 uint32_t stco_entry_count;
37 uint32_t *stco_chunk_offset;
44 #define MAX_TRACKS 1024
47 const struct mp4_callback *cb;
59 /* incremental track index while reading the file */
62 struct mp4_track *track[MAX_TRACKS];
63 /* the first audio track found */
64 struct mp4_track *audio_track;
67 struct mp4_metadata meta;
71 * Returns -1, 0, or 1 on errors/EOF/success. Partial reads followed by EOF or
72 * read errors are treated as errors.
74 static int read_data(struct mp4 *f, void *data, size_t size)
77 ssize_t ret = f->cb->read(f->cb->user_data, data, size);
78 if (ret < 0 && errno == EINTR)
80 /* regard EAGAIN as an error as reads should be blocking. */
82 return ret < 0? -1 : 0;
88 static int read_int64(struct mp4 *f, uint64_t *result)
91 int ret = read_data(f, data, 8);
94 *result = read_u64_be(data);
98 static int read_int32(struct mp4 *f, uint32_t *result)
101 int ret = read_data(f, data, 4);
104 *result = read_u32_be(data);
108 static int read_int16(struct mp4 *f, uint16_t *result)
111 int ret = read_data(f, data, 2);
114 *result = read_u16_be(data);
119 ATOM_ITEM(MOOV, 'm', 'o', 'o', 'v') \
120 ATOM_ITEM(TRAK, 't', 'r', 'a', 'k') \
121 ATOM_ITEM(MDIA, 'm', 'd', 'i', 'a') \
122 ATOM_ITEM(MINF, 'm', 'i', 'n', 'f') \
123 ATOM_ITEM(STBL, 's', 't', 'b', 'l') \
124 ATOM_ITEM(UDTA, 'u', 'd', 't', 'a') \
125 ATOM_ITEM(ILST, 'i', 'l', 's', 't') /* iTunes Metadata list */ \
126 ATOM_ITEM(ARTIST, 0xa9, 'A', 'R', 'T') \
127 ATOM_ITEM(TITLE, 0xa9, 'n', 'a', 'm') \
128 ATOM_ITEM(ALBUM, 0xa9, 'a', 'l', 'b') \
129 ATOM_ITEM(DATE, 0xa9, 'd', 'a', 'y') \
130 ATOM_ITEM(COMMENT, 0xa9, 'c', 'm', 't') \
131 ATOM_ITEM(MDHD, 'm', 'd', 'h', 'd') /* track header */ \
132 ATOM_ITEM(STSD, 's', 't', 's', 'd') /* sample description box */ \
133 ATOM_ITEM(STTS, 's', 't', 't', 's') /* time to sample box */ \
134 ATOM_ITEM(STSZ, 's', 't', 's', 'z') /* sample size box */ \
135 ATOM_ITEM(STCO, 's', 't', 'c', 'o') /* chunk offset box */ \
136 ATOM_ITEM(STSC, 's', 't', 's', 'c') /* sample to chunk box */ \
137 ATOM_ITEM(MP4A, 'm', 'p', '4', 'a') \
138 ATOM_ITEM(META, 'm', 'e', 't', 'a') /* iTunes Metadata box */ \
139 ATOM_ITEM(DATA, 'd', 'a', 't', 'a') /* iTunes Metadata data box */ \
141 #define ATOM_ITEM(_name, a, b, c, d) ATOM_ ## _name,
142 enum atom {ATOM_ITEMS};
145 static uint8_t atom_name_to_type(uint8_t *p)
147 #define ATOM_VALUE(a, b, c, d) ((a << 24) + (b << 16) + (c << 8) + d)
148 #define ATOM_ITEM(_name, a, b, c, d) \
149 {.name = # _name, .val = ATOM_VALUE(a, b, c, d)},
150 static const struct {
153 } atom_table[] = {ATOM_ITEMS};
155 uint32_t val = read_u32_be(p);
157 for (uint8_t n = 0; n < ARRAY_SIZE(atom_table); n++)
158 if (val == atom_table[n].val)
163 /* read atom header, atom size is returned with header included. */
164 static int atom_read_header(struct mp4 *f, uint8_t *atom_type,
165 uint8_t *header_size, uint64_t *atom_size)
169 uint8_t atom_header[8];
171 ret = read_data(f, atom_header, 8);
174 size = read_u32_be(atom_header);
175 if (size == 1) { /* 64 bit atom size */
178 ret = read_int64(f, atom_size);
187 *atom_type = atom_name_to_type(atom_header + 4);
191 static off_t get_position(const struct mp4 *f)
193 return f->cb->seek(f->cb->user_data, 0, SEEK_CUR);
196 static void set_position(struct mp4 *f, off_t position)
198 f->cb->seek(f->cb->user_data, position, SEEK_SET);
201 static void skip_bytes(struct mp4 *f, off_t num_skip)
203 f->cb->seek(f->cb->user_data, num_skip, SEEK_CUR);
206 static int read_stsz(struct mp4 *f)
212 if (f->total_tracks == 0)
214 t = f->track[f->total_tracks - 1];
215 skip_bytes(f, 4); /* version (1), flags (3) */
216 ret = read_int32(f, &t->stsz_sample_size);
219 ret = read_int32(f, &t->stsz_sample_count);
222 if (t->stsz_sample_size != 0)
224 t->stsz_table = para_malloc(t->stsz_sample_count * sizeof(int32_t));
225 for (i = 0; i < t->stsz_sample_count; i++) {
226 ret = read_int32(f, &t->stsz_table[i]);
233 static int read_stts(struct mp4 *f)
239 if (f->total_tracks == 0)
241 t = f->track[f->total_tracks - 1];
242 if (t->stts_entry_count)
244 skip_bytes(f, 4); /* version (1), flags (3) */
245 ret = read_int32(f, &t->stts_entry_count);
248 t->stts_sample_count = para_malloc(t->stts_entry_count
250 for (i = 0; i < t->stts_entry_count; i++) {
251 ret = read_int32(f, &t->stts_sample_count[i]);
254 skip_bytes(f, 4); /* sample delta */
259 static int read_stsc(struct mp4 *f)
265 if (f->total_tracks == 0)
267 t = f->track[f->total_tracks - 1];
269 skip_bytes(f, 4); /* version (1), flags (3) */
270 ret = read_int32(f, &t->stsc_entry_count);
273 t->stsc_first_chunk = para_malloc(t->stsc_entry_count * sizeof(int32_t));
274 t->stsc_samples_per_chunk = para_malloc(t->stsc_entry_count
276 for (i = 0; i < t->stsc_entry_count; i++) {
277 ret = read_int32(f, &t->stsc_first_chunk[i]);
280 ret = read_int32(f, &t->stsc_samples_per_chunk[i]);
283 skip_bytes(f, 4); /* sample desc index */
288 static int read_stco(struct mp4 *f)
294 if (f->total_tracks == 0)
296 t = f->track[f->total_tracks - 1];
298 skip_bytes(f, 4); /* version (1), flags (3) */
299 ret = read_int32(f, &t->stco_entry_count);
302 t->stco_chunk_offset = para_malloc(t->stco_entry_count
304 for (i = 0; i < t->stco_entry_count; i++) {
305 ret = read_int32(f, &t->stco_chunk_offset[i]);
312 static int read_mp4a(struct mp4 *f)
317 if (f->total_tracks == 0)
319 t = f->track[f->total_tracks - 1];
320 /* reserved (6), data reference index (2), reserved (8) */
322 ret = read_int16(f, &t->channel_count);
326 return read_int16(f, &t->sample_rate);
329 static int read_stsd(struct mp4 *f)
332 uint32_t i, entry_count;
335 if (f->total_tracks == 0)
337 t = f->track[f->total_tracks - 1];
338 skip_bytes(f, 4); /* version (1), flags (3) */
339 ret = read_int32(f, &entry_count);
342 for (i = 0; i < entry_count; i++) {
343 uint64_t skip = get_position(f);
345 uint8_t atom_type = 0;
346 ret = atom_read_header(f, &atom_type, NULL, &size);
350 if (!f->audio_track && atom_type == ATOM_MP4A) {
354 set_position(f, skip);
359 static const char *get_metadata_name(uint8_t atom_type)
362 case ATOM_TITLE: return "title";
363 case ATOM_ARTIST: return "artist";
364 case ATOM_ALBUM: return "album";
365 case ATOM_DATE: return "date";
366 case ATOM_COMMENT: return "comment";
367 default: return "unknown";
371 static int parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
374 uint64_t subsize, sumsize;
383 set_position(f, destpos), sumsize += subsize
386 uint8_t header_size = 0;
387 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
390 destpos = get_position(f) + subsize - header_size;
391 if (atom_type != ATOM_DATA)
393 skip_bytes(f, 8); /* version (1), flags (3), reserved (4) */
394 ret = -ERRNO_TO_PARA_ERROR(EINVAL);
395 if (subsize < header_size + 8 || subsize > UINT_MAX)
397 len = subsize - (header_size + 8);
399 value = para_malloc(len + 1);
400 ret = read_data(f, value, len);
406 return -ERRNO_TO_PARA_ERROR(EINVAL);
407 f->meta.tags = para_realloc(f->meta.tags, (f->meta.count + 1)
408 * sizeof(struct mp4_tag));
409 tag = f->meta.tags + f->meta.count;
410 tag->item = para_strdup(get_metadata_name(parent));
420 static int read_mdhd(struct mp4 *f)
426 if (f->total_tracks == 0)
428 t = f->track[f->total_tracks - 1];
430 ret = read_int32(f, &version);
434 skip_bytes(f, 16); /* creation time (8), modification time (8) */
435 ret = read_int32(f, &t->time_scale);
438 ret = read_int64(f, &t->duration);
441 } else { //version == 0
444 skip_bytes(f, 8); /* creation time (4), modification time (4) */
445 ret = read_int32(f, &t->time_scale);
448 ret = read_int32(f, &temp);
451 t->duration = (temp == (uint32_t) (-1))?
452 (uint64_t) (-1) : (uint64_t) (temp);
458 static int32_t read_ilst(struct mp4 *f, int32_t size)
461 uint64_t sumsize = 0;
463 while (sumsize < size) {
465 uint64_t subsize, destpos;
466 uint8_t header_size = 0;
467 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
470 destpos = get_position(f) + subsize - header_size;
477 ret = parse_tag(f, atom_type, subsize - header_size);
481 set_position(f, destpos);
487 static int32_t read_meta(struct mp4 *f, uint64_t size)
490 uint64_t subsize, sumsize = 0;
492 uint8_t header_size = 0;
494 skip_bytes(f, 4); /* version (1), flags (3) */
495 while (sumsize < (size - (header_size + 4))) {
496 ret = atom_read_header(f, &atom_type, &header_size, &subsize);
499 if (subsize <= header_size + 4)
501 if (atom_type == ATOM_ILST) {
502 f->ilst_offset = get_position(f) - header_size;
503 f->ilst_size = subsize;
504 ret = read_ilst(f, subsize - (header_size + 4));
508 set_position(f, get_position(f) + subsize - header_size);
514 static bool need_atom(uint8_t atom_type, bool meta_only)
516 /* these are needed in any case */
527 /* meta-only opens don't need anything else */
530 /* these are only required for regular opens */
542 /* parse atoms that are sub atoms of other atoms */
543 static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only)
546 uint64_t dest, size, end = get_position(f) + total_size;
548 for (dest = get_position(f); dest < end; set_position(f, dest)) {
549 uint8_t header_size, atom_type;
550 ret = atom_read_header(f, &atom_type, &header_size, &size);
555 dest = get_position(f) + size - header_size;
556 if (atom_type == ATOM_TRAK) {
557 if (f->total_tracks >= MAX_TRACKS)
560 f->track[f->total_tracks - 1] = para_calloc(
561 sizeof(struct mp4_track));
562 } else if (atom_type == ATOM_UDTA) {
563 f->udta_offset = get_position(f) - header_size;
566 if (!need_atom(atom_type, meta_only))
569 case ATOM_STSZ: ret = read_stsz(f); break;
570 case ATOM_STTS: ret = read_stts(f); break;
571 case ATOM_STSC: ret = read_stsc(f); break;
572 case ATOM_STCO: ret = read_stco(f); break;
573 case ATOM_STSD: ret = read_stsd(f); break;
574 case ATOM_MDHD: ret = read_mdhd(f); break;
576 f->meta_offset = get_position(f) - header_size;
578 ret = read_meta(f, size);
581 ret = parse_sub_atoms(f, size - header_size, meta_only);
589 static int open_file(const struct mp4_callback *cb, bool meta_only, struct mp4 **result)
593 uint8_t atom_type, header_size;
594 struct mp4 *f = para_calloc(sizeof(*f));
597 while ((ret = atom_read_header(f, &atom_type, &header_size, &size)) > 0) {
598 f->last_atom = atom_type;
599 if (atom_type != ATOM_MOOV || size <= header_size) { /* skip */
600 set_position(f, get_position(f) + size - header_size);
603 f->moov_offset = get_position(f) - header_size;
605 ret = parse_sub_atoms(f, size - header_size, meta_only);
624 int mp4_open_read(const struct mp4_callback *cb, struct mp4 **result)
626 return open_file(cb, false, result);
629 void mp4_close(struct mp4 *f)
633 for (i = 0; i < f->total_tracks; i++) {
635 free(f->track[i]->stsz_table);
636 free(f->track[i]->stts_sample_count);
637 free(f->track[i]->stsc_first_chunk);
638 free(f->track[i]->stsc_samples_per_chunk);
639 free(f->track[i]->stco_chunk_offset);
643 for (i = 0; i < f->meta.count; i++) {
644 free(f->meta.tags[i].item);
645 free(f->meta.tags[i].value);
651 static int32_t chunk_of_sample(const struct mp4 *f, int32_t sample,
654 const struct mp4_track *t = f->audio_track;
655 uint32_t *fc = t->stsc_first_chunk, *spc = t->stsc_samples_per_chunk;
656 int32_t chunk1, chunk1samples, n, total, i;
658 for (i = 1, total = 0; i < t->stsc_entry_count; i++, total += n) {
659 n = (fc[i] - fc[i - 1]) * spc[i - 1]; /* number of samples */
660 if (sample < total + n)
664 chunk1samples = spc[i - 1];
665 if (chunk1samples != 0)
666 *chunk = (sample - total) / chunk1samples + chunk1;
669 return total + (*chunk - chunk1) * chunk1samples;
673 * Return the number of milliseconds of the audio track.
675 * \param f As returned by \ref mp4_open_read(), must not be NULL.
677 uint64_t mp4_get_duration(const struct mp4 *f)
679 const struct mp4_track *t = f->audio_track;
681 if (t->time_scale == 0)
683 return t->duration * 1000 / t->time_scale;
686 int mp4_set_sample_position(struct mp4 *f, int32_t sample)
688 const struct mp4_track *t = f->audio_track;
689 int32_t offset, chunk, chunk_sample;
690 uint32_t n, srs; /* sample range size */
692 if (sample >= t->stsz_sample_count)
693 return -ERRNO_TO_PARA_ERROR(EINVAL);
694 chunk_sample = chunk_of_sample(f, sample, &chunk);
695 if (t->stsz_sample_size > 0)
696 srs = (sample - chunk_sample) * t->stsz_sample_size;
698 for (srs = 0, n = chunk_sample; n < sample; n++)
699 srs += t->stsz_table[n];
701 if (t->stco_entry_count > 0 && chunk > t->stco_entry_count)
702 offset = t->stco_chunk_offset[t->stco_entry_count - 1];
703 else if (t->stco_entry_count > 0)
704 offset = t->stco_chunk_offset[chunk - 1];
707 set_position(f, offset + srs);
711 int32_t mp4_get_sample_size(const struct mp4 *f, int sample)
713 const struct mp4_track *t = f->audio_track;
715 if (t->stsz_sample_size != 0)
716 return t->stsz_sample_size;
717 return t->stsz_table[sample];
720 uint32_t mp4_get_sample_rate(const struct mp4 *f)
722 return f->audio_track->sample_rate;
725 uint32_t mp4_get_channel_count(const struct mp4 *f)
727 return f->audio_track->channel_count;
730 int32_t mp4_num_samples(const struct mp4 *f)
732 const struct mp4_track *t = f->audio_track;
736 for (i = 0; i < t->stts_entry_count; i++)
737 total += t->stts_sample_count[i];
741 int mp4_open_meta(const struct mp4_callback *cb, struct mp4 **result)
744 int ret = open_file(cb, true, &f);
748 if (f->udta_size == 0 || f->meta_size == 0 || f->ilst_size == 0) {
751 return -E_MP4_MISSING_ATOM;
758 * Return the metadata of an mp4 file.
760 * \param f As returned by either \ref mp4_open_read() or \ref mp4_open_meta().
762 * The caller is allowed to add, delete or modify the entries of the returned
763 * structure in order to pass the modified version to \ref mp4_meta_update().
765 struct mp4_metadata *mp4_get_meta(struct mp4 *f)
770 /** Total length of an on-disk metadata tag. */
771 #define TAG_LEN(_len) (24 + (_len))
772 static void create_ilst(const struct mp4_metadata *meta, uint8_t *out)
774 for (unsigned n = 0; n < meta->count; n++) {
775 struct mp4_tag *tag = meta->tags + n;
776 unsigned len = strlen(tag->value);
777 const char *atom_name;
779 if (!strcasecmp(tag->item, "title"))
780 atom_name = "\xA9" "nam";
781 else if (!strcasecmp(tag->item, "artist"))
782 atom_name = "\xA9" "ART";
783 else if (!strcasecmp(tag->item, "album"))
784 atom_name = "\xA9" "alb";
785 else if (!strcasecmp(tag->item, "date"))
786 atom_name = "\xA9" "day";
787 else if (!strcasecmp(tag->item, "comment"))
788 atom_name = "\xA9" "cmt";
791 write_u32_be(out, TAG_LEN(len));
792 memcpy(out + 4, atom_name, 4);
793 write_u32_be(out + 8, 8 /* data atom header */
794 + 8 /* flags + reserved */
796 memcpy(out + 12, "data", 4);
797 write_u32_be(out + 16, 1); /* flags */
798 write_u32_be(out + 20, 0); /* reserved */
799 memcpy(out + 24, tag->value, len);
804 static void *modify_moov(struct mp4 *f, uint32_t *out_size)
807 uint64_t total_base = f->moov_offset + 8;
808 uint32_t total_size = (uint32_t) (f->moov_size - 8);
809 uint32_t new_ilst_size = 0;
815 for (unsigned n = 0; n < f->meta.count; n++)
816 new_ilst_size += TAG_LEN(strlen(f->meta.tags[n].value));
817 size_delta = new_ilst_size - (f->ilst_size - 8);
818 *out_size = total_size + size_delta;
819 out_buffer = para_malloc(*out_size);
821 set_position(f, total_base);
822 ret = read_data(f, p_out, f->udta_offset - total_base);
825 p_out += f->udta_offset - total_base;
826 ret = read_int32(f, &tmp);
829 write_u32_be(p_out, tmp + size_delta);
831 ret = read_data(f, p_out, 4);
835 ret = read_data(f, p_out, f->meta_offset - f->udta_offset - 8);
838 p_out += f->meta_offset - f->udta_offset - 8;
839 ret = read_int32(f, &tmp);
842 write_u32_be(p_out, tmp + size_delta);
844 ret = read_data(f, p_out, 4);
848 ret = read_data(f, p_out, f->ilst_offset - f->meta_offset - 8);
851 p_out += f->ilst_offset - f->meta_offset - 8;
852 ret = read_int32(f, &tmp);
855 write_u32_be(p_out, tmp + size_delta);
857 ret = read_data(f, p_out, 4);
861 create_ilst(&f->meta, p_out);
862 p_out += new_ilst_size;
863 set_position(f, f->ilst_offset + f->ilst_size);
864 ret = read_data(f, p_out, total_size - (f->ilst_offset - total_base)
871 static int write_data(struct mp4 *f, void *data, size_t size)
874 ssize_t ret = f->cb->write(f->cb->user_data, data, size);
878 return -ERRNO_TO_PARA_ERROR(errno);
885 int mp4_meta_update(struct mp4 *f)
888 uint32_t new_moov_size;
889 uint8_t buf[8] = "----moov";
893 new_moov_data = modify_moov(f, &new_moov_size);
894 if (!new_moov_data ) {
898 if (f->last_atom != ATOM_MOOV) {
899 set_position(f, f->moov_offset + 4);
900 ret = write_data(f, "free", 4); /* rename old moov to free */
903 /* write new moov atom at EOF */
904 f->cb->seek(f->cb->user_data, 0, SEEK_END);
905 } else /* overwrite old moov atom */
906 set_position(f, f->moov_offset);
907 write_u32_be(buf, new_moov_size + 8);
908 ret = write_data(f, buf, sizeof(buf));
911 ret = write_data(f, new_moov_data, new_moov_size);
914 f->cb->truncate(f->cb->user_data);
921 static char *meta_find_by_name(const struct mp4 *f, const char *item)
925 for (i = 0; i < f->meta.count; i++)
926 if (!strcasecmp(f->meta.tags[i].item, item))
927 return para_strdup(f->meta.tags[i].value);
932 * Return the value of the artist meta tag of an mp4 file.
934 * \param f Must not be NULL.
936 * \return If the file does not contain this metadata tag, the function returns
937 * NULL. Otherwise, a copy of the tag value is returned. The caller should free
938 * this memory when it is no longer needed.
940 char *mp4_meta_get_artist(const struct mp4 *f)
942 return meta_find_by_name(f, "artist");
946 * Return the value of the title meta tag of an mp4 file.
948 * \param f See \ref mp4_meta_get_artist().
949 * \return See \ref mp4_meta_get_artist().
951 char *mp4_meta_get_title(const struct mp4 *f)
953 return meta_find_by_name(f, "title");
957 * Return the value of the date meta tag of an mp4 file.
959 * \param f See \ref mp4_meta_get_artist().
960 * \return See \ref mp4_meta_get_artist().
962 char *mp4_meta_get_date(const struct mp4 *f)
964 return meta_find_by_name(f, "date");
968 * Return the value of the album meta tag of an mp4 file.
970 * \param f See \ref mp4_meta_get_artist().
971 * \return See \ref mp4_meta_get_artist().
973 char *mp4_meta_get_album(const struct mp4 *f)
975 return meta_find_by_name(f, "album");
979 * Return the value of the comment meta tag of an mp4 file.
981 * \param f See \ref mp4_meta_get_artist().
982 * \return See \ref mp4_meta_get_artist().
984 char *mp4_meta_get_comment(const struct mp4 *f)
986 return meta_find_by_name(f, "comment");