From 142635c8ad8d98f00247cb1c477c036efdb8a088 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 23 Aug 2021 16:37:33 +0200 Subject: [PATCH] mp4: Avoid duplicating the list of atoms. A little cpp magic can do wonders in this regard. The new atom_name_to_type() should also be more efficient because we replaced four 8-bit comparisons by one 32-bit comparison. --- mp4.c | 133 +++++++++++++++++++--------------------------------------- 1 file changed, 44 insertions(+), 89 deletions(-) diff --git a/mp4.c b/mp4.c index 10ff3bfe..1ab20054 100644 --- a/mp4.c +++ b/mp4.c @@ -137,93 +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, - - /* 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. */ @@ -232,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) @@ -250,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; } -- 2.39.2