X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=mp4.c;h=d030d62d3e759c81ddfa440a6b47613e87f4d14e;hb=eb369edec255c992294a77b83f981e46c5de7906;hp=1d8af6cb20853c33a4aff5d151eb143951bd5a90;hpb=30fcea984715a12b63aab776fb3080ac1851e43a;p=paraslash.git diff --git a/mp4.c b/mp4.c index 1d8af6cb..d030d62d 100644 --- a/mp4.c +++ b/mp4.c @@ -145,86 +145,34 @@ static bool atom_compare(int8_t a1, int8_t b1, int8_t c1, int8_t d1, 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, + 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_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_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 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) @@ -236,46 +184,18 @@ static uint8_t atom_name_to_type(int8_t a, int8_t b, int8_t c, int8_t d) 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')) @@ -286,97 +206,24 @@ static uint8_t atom_name_to_type(int8_t a, int8_t b, int8_t c, int8_t d) 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')) + 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; } @@ -865,18 +712,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,10 +732,8 @@ 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 */ ret = parse_sub_atoms(f, size - header_size, meta_only); else @@ -1083,68 +926,11 @@ struct mp4_metadata *mp4_get_meta(struct mp4 *f) return &f->meta; } -struct membuffer { - void *data; - unsigned written; - unsigned allocated; -}; - -static struct membuffer *membuffer_create(void) -{ - struct membuffer *buf = para_calloc(sizeof(*buf)); - - buf->allocated = 256; - buf->data = para_malloc(buf->allocated); - return buf; -} - -static void membuffer_write(struct membuffer *buf, const void *ptr, - unsigned bytes) -{ - unsigned dest_size = buf->written + bytes; - - if (dest_size > buf->allocated) { - do { - buf->allocated <<= 1; - } while (dest_size > buf->allocated); - buf->data = para_realloc(buf->data, buf->allocated); - } - - if (ptr) - memcpy((char *) buf->data + buf->written, ptr, bytes); - buf->written += bytes; -} - -static void membuffer_write_atom_name(struct membuffer *buf, const char *data) -{ - membuffer_write(buf, data, 4); -} - -static void membuffer_write_int32(struct membuffer *buf, uint32_t data) -{ - uint8_t temp[4]; - write_u32_be(temp, data); - membuffer_write(buf, temp, 4); -} - -static unsigned membuffer_get_size(const struct membuffer *buf) -{ - return buf->written; -} - -static void *membuffer_detach(struct membuffer *buf) +/** Total length of an on-disk metadata tag. */ +#define TAG_LEN(_len) (24 + (_len)) +static void create_ilst(const struct mp4_metadata *meta, uint8_t *out) { - void *ret = para_realloc(buf->data, buf->written); - free(buf); - return ret; -} - -static void *create_ilst(const struct mp4_metadata *meta, uint32_t *out_size) -{ - struct membuffer *buf = membuffer_create(); - unsigned n; - - for (n = 0; n < meta->count; n++) { + for (unsigned n = 0; n < meta->count; n++) { struct mp4_tag *tag = meta->tags + n; unsigned len = strlen(tag->value); const char *atom_name; @@ -1161,21 +947,17 @@ static void *create_ilst(const struct mp4_metadata *meta, uint32_t *out_size) atom_name = "\xA9" "cmt"; else assert(false); - membuffer_write_int32(buf, 8 /* atom header */ - + 8 /* data atom header */ - + 8 /* flags + reserved */ - + len); - membuffer_write_atom_name(buf, atom_name); - membuffer_write_int32(buf, 8 /* data atom header */ + write_u32_be(out, TAG_LEN(len)); + memcpy(out + 4, atom_name, 4); + write_u32_be(out + 8, 8 /* data atom header */ + 8 /* flags + reserved */ + len); - membuffer_write_atom_name(buf, "data"); - membuffer_write_int32(buf, 1); /* flags */ - membuffer_write_int32(buf, 0); /* reserved */ - membuffer_write(buf, tag->value, len); + memcpy(out + 12, "data", 4); + write_u32_be(out + 16, 1); /* flags */ + write_u32_be(out + 20, 0); /* reserved */ + memcpy(out + 24, tag->value, len); + out += TAG_LEN(len); } - *out_size = membuffer_get_size(buf); - return membuffer_detach(buf); } static uint32_t fix_byte_order_32(uint32_t src) @@ -1188,13 +970,14 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) int ret; uint64_t total_base = f->moov_offset + 8; uint32_t total_size = (uint32_t) (f->moov_size - 8); - uint32_t new_ilst_size; - void *new_ilst_buffer, *out_buffer; + uint32_t new_ilst_size = 0; + void *out_buffer; uint8_t *p_out; int32_t size_delta; uint32_t tmp; - new_ilst_buffer = create_ilst(&f->meta, &new_ilst_size); + for (unsigned n = 0; n < f->meta.count; n++) + new_ilst_size += TAG_LEN(strlen(f->meta.tags[n].value)); size_delta = new_ilst_size - (f->ilst_size - 8); *out_size = total_size + size_delta; out_buffer = para_malloc(*out_size); @@ -1239,14 +1022,13 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) if (ret <= 0) return NULL; p_out += 4; - memcpy(p_out, new_ilst_buffer, new_ilst_size); + create_ilst(&f->meta, p_out); p_out += new_ilst_size; set_position(f, f->ilst_offset + f->ilst_size); ret = read_data(f, p_out, total_size - (f->ilst_offset - total_base) - f->ilst_size); if (ret <= 0) return NULL; - free(new_ilst_buffer); return out_buffer; }