X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=mp4.c;h=1ab200545180be77722b511afd6aaf1c86006faa;hb=142635c8ad8d98f00247cb1c477c036efdb8a088;hp=1f504fc30ee06231cd442cb4bceafe32497792b6;hpb=eac096021cc916a4fdddf87dc71548e141c208cf;p=paraslash.git diff --git a/mp4.c b/mp4.c index 1f504fc3..1ab20054 100644 --- a/mp4.c +++ b/mp4.c @@ -137,248 +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 = 1, - ATOM_TRAK = 2, - ATOM_EDTS = 3, - ATOM_MDIA = 4, - ATOM_MINF = 5, - ATOM_STBL = 6, - ATOM_UDTA = 7, - ATOM_ILST = 8, /* iTunes Metadata list */ - ATOM_TITLE = 9, - ATOM_ARTIST = 10, - ATOM_WRITER = 11, - ATOM_ALBUM = 12, - ATOM_DATE = 13, - ATOM_TOOL = 14, - ATOM_COMMENT = 15, - ATOM_GENRE1 = 16, - ATOM_TRACK = 17, - ATOM_DISC = 18, - ATOM_COMPILATION = 19, - ATOM_GENRE2 = 20, - ATOM_TEMPO = 21, - ATOM_COVER = 22, - ATOM_DRMS = 23, - ATOM_SINF = 24, - ATOM_SCHI = 25, - - SUBATOMIC = 128, - - /* atoms without subatoms */ - ATOM_FTYP = 129, - ATOM_MDAT = 130, - ATOM_MVHD = 131, - ATOM_TKHD = 132, - ATOM_TREF = 133, - ATOM_MDHD = 134, /* track header */ - ATOM_VMHD = 135, - ATOM_SMHD = 136, - ATOM_HMHD = 137, - ATOM_STSD = 138, /* sample description box */ - ATOM_STTS = 139, /* time to sample box */ - ATOM_STSZ = 140, /* sample size box */ - ATOM_STZ2 = 141, - ATOM_STCO = 142, /* chunk offset box */ - ATOM_STSC = 143, /* sample to chunk box */ - ATOM_MP4A = 144, - ATOM_MP4V = 145, - ATOM_MP4S = 146, - ATOM_ESDS = 147, - ATOM_META = 148, /* iTunes Metadata box */ - ATOM_NAME = 149, /* iTunes Metadata name box */ - ATOM_DATA = 150, /* iTunes Metadata data box */ - ATOM_CTTS = 151, - ATOM_FRMA = 152, - ATOM_IVIV = 153, - ATOM_PRIV = 154, - ATOM_USER = 155, - ATOM_KEY = 156, - ATOM_ALBUM_ARTIST = 157, - ATOM_CONTENTGROUP = 158, - ATOM_LYRICS = 159, - ATOM_DESCRIPTION = 160, - ATOM_NETWORK = 161, - ATOM_SHOW = 162, - ATOM_EPISODENAME = 163, - ATOM_SORTTITLE = 164, - ATOM_SORTALBUM = 165, - ATOM_SORTARTIST = 166, - ATOM_SORTALBUMARTIST = 167, - ATOM_SORTWRITER = 168, - ATOM_SORTSHOW = 169, - ATOM_SEASON = 170, - ATOM_EPISODE = 171, - ATOM_PODCAST = 172, - - ATOM_UNKNOWN = 255 -}; - -#define ATOM_FREE ATOM_UNKNOWN -#define ATOM_SKIP ATOM_UNKNOWN - -#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', 'a', 't')) - return ATOM_MDAT; - else if (atom_compare(a, b, c, d, 'm', 'd', 'h', 'd')) - return ATOM_MDHD; - else if (atom_compare(a, b, c, d, 'm', 'v', 'h', 'd')) - return ATOM_MVHD; - else if (atom_compare(a, b, c, d, 'm', 'p', '4', 'a')) - return ATOM_MP4A; - else if (atom_compare(a, b, c, d, 'm', 'p', '4', 'v')) - return ATOM_MP4V; - else if (atom_compare(a, b, c, d, 'm', 'p', '4', 's')) - return ATOM_MP4S; - 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 (atom_compare(a, b, c, d, 't', 'k', 'h', 'd')) - return ATOM_TKHD; - else if (atom_compare(a, b, c, d, 't', 'r', 'e', 'f')) - return ATOM_TREF; - else if (atom_compare(a, b, c, d, 't', 'r', 'k', 'n')) - return ATOM_TRACK; - else if (atom_compare(a, b, c, d, 't', 'm', 'p', 'o')) - return ATOM_TEMPO; - else if (atom_compare(a, b, c, d, 't', 'v', 'n', 'n')) - return ATOM_NETWORK; - else if (atom_compare(a, b, c, d, 't', 'v', 's', 'h')) - return ATOM_SHOW; - else if (atom_compare(a, b, c, d, 't', 'v', 'e', 'n')) - return ATOM_EPISODENAME; - else if (atom_compare(a, b, c, d, 't', 'v', 's', 'n')) - return ATOM_SEASON; - else if (atom_compare(a, b, c, d, 't', 'v', 'e', 's')) - return ATOM_EPISODE; - } 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', 'm', 'h', 'd')) - return ATOM_SMHD; - 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 (atom_compare(a, b, c, d, 's', 't', 'z', '2')) - return ATOM_STZ2; - else if (atom_compare(a, b, c, d, 's', 'k', 'i', 'p')) - return ATOM_SKIP; - else if (atom_compare(a, b, c, d, 's', 'i', 'n', 'f')) - return ATOM_SINF; - else if (atom_compare(a, b, c, d, 's', 'c', 'h', 'i')) - return ATOM_SCHI; - else if (atom_compare(a, b, c, d, 's', 'o', 'n', 'm')) - return ATOM_SORTTITLE; - else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'l')) - return ATOM_SORTALBUM; - else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'r')) - return ATOM_SORTARTIST; - else if (atom_compare(a, b, c, d, 's', 'o', 'a', 'a')) - return ATOM_SORTALBUMARTIST; - else if (atom_compare(a, b, c, d, 's', 'o', 'c', 'o')) - return ATOM_SORTWRITER; - else if (atom_compare(a, b, c, d, 's', 'o', 's', 'n')) - return ATOM_SORTSHOW; - } 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, 'w', 'r', 't')) - return ATOM_WRITER; - 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, 't', 'o', 'o')) - return ATOM_TOOL; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'c', 'm', 't')) - return ATOM_COMMENT; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'e', 'n')) - return ATOM_GENRE1; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'g', 'r', 'p')) - return ATOM_CONTENTGROUP; - else if (atom_compare(a, b, c, d, COPYRIGHT_SYMBOL, 'l', 'y', 'r')) - return ATOM_LYRICS; - } - - if (atom_compare(a, b, c, d, 'e', 'd', 't', 's')) - return ATOM_EDTS; - else if (atom_compare(a, b, c, d, 'e', 's', 'd', 's')) - return ATOM_ESDS; - else if (atom_compare(a, b, c, d, 'f', 't', 'y', 'p')) - return ATOM_FTYP; - else if (atom_compare(a, b, c, d, 'f', 'r', 'e', 'e')) - return ATOM_FREE; - else if (atom_compare(a, b, c, d, 'h', 'm', 'h', 'd')) - return ATOM_HMHD; - else if (atom_compare(a, b, c, d, 'v', 'm', 'h', 'd')) - return ATOM_VMHD; - else 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, 'n', 'a', 'm', 'e')) - return ATOM_NAME; - else if (atom_compare(a, b, c, d, 'd', 'a', 't', 'a')) - return ATOM_DATA; - else if (atom_compare(a, b, c, d, 'd', 'i', 's', 'k')) - return ATOM_DISC; - else if (atom_compare(a, b, c, d, 'g', 'n', 'r', 'e')) - return ATOM_GENRE2; - else if (atom_compare(a, b, c, d, 'c', 'o', 'v', 'r')) - return ATOM_COVER; - else if (atom_compare(a, b, c, d, 'c', 'p', 'i', 'l')) - return ATOM_COMPILATION; - else if (atom_compare(a, b, c, d, 'c', 't', 't', 's')) - return ATOM_CTTS; - else if (atom_compare(a, b, c, d, 'd', 'r', 'm', 's')) - return ATOM_DRMS; - else if (atom_compare(a, b, c, d, 'f', 'r', 'm', 'a')) - return ATOM_FRMA; - else if (atom_compare(a, b, c, d, 'p', 'r', 'i', 'v')) - return ATOM_PRIV; - else if (atom_compare(a, b, c, d, 'i', 'v', 'i', 'v')) - return ATOM_IVIV; - else if (atom_compare(a, b, c, d, 'u', 's', 'e', 'r')) - return ATOM_USER; - else if (atom_compare(a, b, c, d, 'k', 'e', 'y', ' ')) - return ATOM_KEY; - else if (atom_compare(a, b, c, d, 'a', 'A', 'R', 'T')) - return ATOM_ALBUM_ARTIST; - else if (atom_compare(a, b, c, d, 'd', 'e', 's', 'c')) - return ATOM_DESCRIPTION; - else if (atom_compare(a, b, c, d, 'p', 'c', 's', 't')) - return ATOM_PODCAST; - 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. */ @@ -387,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) @@ -405,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; } @@ -810,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 */ @@ -865,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; @@ -887,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; }