X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=mp4.c;h=1ab200545180be77722b511afd6aaf1c86006faa;hb=142635c8ad8d98f00247cb1c477c036efdb8a088;hp=e2512db17de21c0fd20286860a0e6861f9542b2d;hpb=18ea2d87153bfcf386905b7c36b425d8e7bcc592;p=paraslash.git diff --git a/mp4.c b/mp4.c index e2512db1..1ab20054 100644 --- a/mp4.c +++ b/mp4.c @@ -137,95 +137,49 @@ static uint8_t read_int8(struct mp4 *f, uint8_t *result) return ret; } -static bool atom_compare(int8_t a1, int8_t b1, int8_t c1, int8_t d1, - int8_t a2, int8_t b2, int8_t c2, int8_t d2) +#define ATOM_ITEMS \ + ATOM_ITEM(MOOV, 'm', 'o', 'o', 'v') \ + ATOM_ITEM(TRAK, 't', 'r', 'a', 'k') \ + ATOM_ITEM(MDIA, 'm', 'd', 'i', 'a') \ + ATOM_ITEM(MINF, 'm', 'i', 'n', 'f') \ + ATOM_ITEM(STBL, 's', 't', 'b', 'l') \ + ATOM_ITEM(UDTA, 'u', 'd', 't', 'a') \ + ATOM_ITEM(ILST, 'i', 'l', 's', 't') /* iTunes Metadata list */ \ + ATOM_ITEM(ARTIST, 0xa9, 'A', 'R', 'T') \ + ATOM_ITEM(TITLE, 0xa9, 'n', 'a', 'm') \ + ATOM_ITEM(ALBUM, 0xa9, 'a', 'l', 'b') \ + ATOM_ITEM(DATE, 0xa9, 'd', 'a', 'y') \ + ATOM_ITEM(COMMENT, 0xa9, 'c', 'm', 't') \ + ATOM_ITEM(MDHD, 'm', 'd', 'h', 'd') /* track header */ \ + ATOM_ITEM(STSD, 's', 't', 's', 'd') /* sample description box */ \ + ATOM_ITEM(STTS, 's', 't', 't', 's') /* time to sample box */ \ + ATOM_ITEM(STSZ, 's', 't', 's', 'z') /* sample size box */ \ + ATOM_ITEM(STCO, 's', 't', 'c', 'o') /* chunk offset box */ \ + ATOM_ITEM(STSC, 's', 't', 's', 'c') /* sample to chunk box */ \ + ATOM_ITEM(MP4A, 'm', 'p', '4', 'a') \ + ATOM_ITEM(META, 'm', 'e', 't', 'a') /* iTunes Metadata box */ \ + ATOM_ITEM(DATA, 'd', 'a', 't', 'a') /* iTunes Metadata data box */ \ + +#define ATOM_ITEM(_name, a, b, c, d) ATOM_ ## _name, +enum atom {ATOM_ITEMS}; +#undef ATOM_ITEM + +static uint8_t atom_name_to_type(uint8_t *p) { - return a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2; -} - -enum atoms { - /* atoms with subatoms */ - ATOM_MOOV, - ATOM_TRAK, - ATOM_MDIA, - ATOM_MINF, - ATOM_STBL, - ATOM_UDTA, - ATOM_ILST, /* iTunes Metadata list */ - ATOM_TITLE, - ATOM_ARTIST, - ATOM_ALBUM, - ATOM_DATE, - ATOM_COMMENT, - - SUBATOMIC = 128, - - /* atoms without subatoms */ - ATOM_MDHD, /* track header */ - ATOM_STSD, /* sample description box */ - ATOM_STTS, /* time to sample box */ - ATOM_STSZ, /* sample size box */ - ATOM_STCO, /* chunk offset box */ - ATOM_STSC, /* sample to chunk box */ - ATOM_MP4A, - ATOM_META, /* iTunes Metadata box */ - ATOM_DATA, /* iTunes Metadata data box */ - ATOM_UNKNOWN = 255 -}; - -#define COPYRIGHT_SYMBOL ((int8_t)0xA9) - -static uint8_t atom_name_to_type(int8_t a, int8_t b, int8_t c, int8_t d) -{ - if (a == 'm') { - if (atom_compare(a, b, c, d, 'm', 'o', 'o', 'v')) - return ATOM_MOOV; - else if (atom_compare(a, b, c, d, 'm', 'i', 'n', 'f')) - return ATOM_MINF; - else if (atom_compare(a, b, c, d, 'm', 'd', 'i', 'a')) - return ATOM_MDIA; - else if (atom_compare(a, b, c, d, 'm', 'd', 'h', 'd')) - return ATOM_MDHD; - else if (atom_compare(a, b, c, d, 'm', 'p', '4', 'a')) - return ATOM_MP4A; - else if (atom_compare(a, b, c, d, 'm', 'e', 't', 'a')) - return ATOM_META; - } else if (a == 't') { - if (atom_compare(a, b, c, d, 't', 'r', 'a', 'k')) - return ATOM_TRAK; - } else if (a == 's') { - if (atom_compare(a, b, c, d, 's', 't', 'b', 'l')) - return ATOM_STBL; - else if (atom_compare(a, b, c, d, 's', 't', 's', 'd')) - return ATOM_STSD; - else if (atom_compare(a, b, c, d, 's', 't', 't', 's')) - return ATOM_STTS; - else if (atom_compare(a, b, c, d, 's', 't', 'c', 'o')) - return ATOM_STCO; - else if (atom_compare(a, b, c, d, 's', 't', 's', 'c')) - return ATOM_STSC; - else if (atom_compare(a, b, c, d, 's', 't', 's', 'z')) - return ATOM_STSZ; - } else if (a == COPYRIGHT_SYMBOL) { - if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'n', 'a', 'm')) - return ATOM_TITLE; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'A', 'R', 'T')) - return ATOM_ARTIST; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'a', 'l', 'b')) - return ATOM_ALBUM; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'd', 'a', 'y')) - return ATOM_DATE; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'c', 'm', 't')) - return ATOM_COMMENT; - } - if (atom_compare(a, b, c, d, 'u', 'd', 't', 'a')) - return ATOM_UDTA; - else if (atom_compare(a, b, c, d, 'i', 'l', 's', 't')) - return ATOM_ILST; - else if (atom_compare(a, b, c, d, 'd', 'a', 't', 'a')) - return ATOM_DATA; - else - return ATOM_UNKNOWN; + #define ATOM_VALUE(a, b, c, d) ((a << 24) + (b << 16) + (c << 8) + d) + #define ATOM_ITEM(_name, a, b, c, d) \ + {.name = # _name, .val = ATOM_VALUE(a, b, c, d)}, + static const struct { + const char *name; + uint32_t val; + } atom_table[] = {ATOM_ITEMS}; + #undef ATOM_ITEM + uint32_t val = read_u32_be(p); + + for (uint8_t n = 0; n < ARRAY_SIZE(atom_table); n++) + if (val == atom_table[n].val) + return n; + return 255; } /* read atom header, atom size is returned with header included. */ @@ -234,7 +188,7 @@ static int atom_read_header(struct mp4 *f, uint8_t *atom_type, { uint32_t size; int ret; - int8_t atom_header[8]; + uint8_t atom_header[8]; ret = read_data(f, atom_header, 8); if (ret <= 0) @@ -252,8 +206,7 @@ static int atom_read_header(struct mp4 *f, uint8_t *atom_type, if (atom_size) *atom_size = size; } - *atom_type = atom_name_to_type(atom_header[4], atom_header[5], - atom_header[6], atom_header[7]); + *atom_type = atom_name_to_type(atom_header + 4); return 1; } @@ -657,29 +610,6 @@ static int32_t read_meta(struct mp4 *f, uint64_t size) return 1; } -static int parse_leaf_atom(struct mp4 *f, uint64_t size, uint8_t header_size, - uint8_t atom_type) -{ - uint64_t dest_position = get_position(f) + size - 8; - int ret = 1; /* return success for atoms we don't care about */ - - switch (atom_type) { - case ATOM_STSZ: ret = read_stsz(f); break; - case ATOM_STTS: ret = read_stts(f); break; - case ATOM_STSC: ret = read_stsc(f); break; - case ATOM_STCO: ret = read_stco(f); break; - case ATOM_STSD: ret = read_stsd(f); break; - case ATOM_MDHD: ret = read_mdhd(f); break; - case ATOM_META: - f->meta_offset = get_position(f) - header_size; - f->meta_size = size; - ret = read_meta(f, size); - break; - } - set_position(f, dest_position); - return ret; -} - static bool need_atom(uint8_t atom_type, bool meta_only) { /* these are needed in any case */ @@ -712,18 +642,16 @@ static bool need_atom(uint8_t atom_type, bool meta_only) static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only) { int ret; - uint64_t size; - uint8_t atom_type = 0; - uint64_t counted_size = 0; - uint8_t header_size = 0; + uint64_t dest, size, end = get_position(f) + total_size; - while (counted_size < total_size) { + for (dest = get_position(f); dest < end; set_position(f, dest)) { + uint8_t header_size, atom_type; ret = atom_read_header(f, &atom_type, &header_size, &size); if (ret <= 0) return ret; if (size == 0) return -1; - counted_size += size; + dest = get_position(f) + size - header_size; if (atom_type == ATOM_TRAK) { if (f->total_tracks >= MAX_TRACKS) return -1; @@ -734,14 +662,23 @@ static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only) f->udta_offset = get_position(f) - header_size; f->udta_size = size; } - if (!need_atom(atom_type, meta_only)) { - set_position(f, get_position(f) + size - header_size); + if (!need_atom(atom_type, meta_only)) continue; - } - if (atom_type < SUBATOMIC) /* atom contains subatoms */ + switch (atom_type) { + case ATOM_STSZ: ret = read_stsz(f); break; + case ATOM_STTS: ret = read_stts(f); break; + case ATOM_STSC: ret = read_stsc(f); break; + case ATOM_STCO: ret = read_stco(f); break; + case ATOM_STSD: ret = read_stsd(f); break; + case ATOM_MDHD: ret = read_mdhd(f); break; + case ATOM_META: + f->meta_offset = get_position(f) - header_size; + f->meta_size = size; + ret = read_meta(f, size); + break; + default: ret = parse_sub_atoms(f, size - header_size, meta_only); - else - ret = parse_leaf_atom(f, size, header_size, atom_type); + } if (ret <= 0) return ret; }