From: Andre Noll Date: Sat, 21 Aug 2021 14:23:05 +0000 (+0200) Subject: mp4: Remove find_atom() and find_atom_v2(). X-Git-Tag: v0.7.1~7^2~39 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=f3e604aba139ae764a9606bc4aad3399143ae256;p=paraslash.git mp4: Remove find_atom() and find_atom_v2(). During mp4_open_meta() we encounter the ILST, META and UDTA atoms but don't record the size and the location of these atoms. Doing so allows us to use this information later in mp4_meta_update() instead of calling find_atom() or find_atom_v2() to search the file again. This removes some ugly code and speeds up the operation. --- diff --git a/mp4.c b/mp4.c index 92be4c76..ca70bd20 100644 --- a/mp4.c +++ b/mp4.c @@ -47,6 +47,13 @@ struct mp4 { uint64_t moov_offset; uint64_t moov_size; + uint64_t meta_offset; + uint32_t meta_size; + uint64_t ilst_offset; + uint32_t ilst_size; + uint64_t udta_offset; + uint32_t udta_size; + uint8_t last_atom; uint64_t file_size; @@ -791,6 +798,8 @@ static int32_t read_meta(struct mp4 *f, uint64_t size) if (subsize <= header_size + 4) return 1; if (atom_type == ATOM_ILST) { + f->ilst_offset = get_position(f) - header_size; + f->ilst_size = subsize; ret = read_ilst(f, subsize - (header_size + 4)); if (ret <= 0) return ret; @@ -801,7 +810,8 @@ 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 atom_type) +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 */ @@ -813,7 +823,11 @@ static int parse_leaf_atom(struct mp4 *f, uint64_t size, uint8_t atom_type) 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: ret = read_meta(f, size); 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; @@ -829,6 +843,7 @@ static bool need_atom(uint8_t atom_type, bool meta_only) case ATOM_MDIA: case ATOM_MINF: case ATOM_STBL: + case ATOM_UDTA: return true; } /* meta-only opens don't need anything else */ @@ -841,7 +856,6 @@ static bool need_atom(uint8_t atom_type, bool meta_only) case ATOM_STCO: case ATOM_STSC: case ATOM_MDHD: - case ATOM_UDTA: return true; } return false; @@ -869,6 +883,9 @@ static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only) f->total_tracks++; f->track[f->total_tracks - 1] = para_calloc( sizeof(struct mp4_track)); + } else if (atom_type == ATOM_UDTA) { + 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); @@ -877,7 +894,7 @@ static int parse_sub_atoms(struct mp4 *f, uint64_t total_size, bool meta_only) if (atom_type < SUBATOMIC) /* atom contains subatoms */ ret = parse_sub_atoms(f, size - header_size, meta_only); else - ret = parse_leaf_atom(f, size, atom_type); + ret = parse_leaf_atom(f, size, header_size, atom_type); if (ret <= 0) return ret; } @@ -1066,83 +1083,6 @@ struct mp4_metadata *mp4_get_meta(struct mp4 *f) return &f->meta; } -static int find_atom(struct mp4 *f, uint64_t base, uint32_t size, - const char *name) -{ - uint32_t remaining = size; - uint64_t atom_offset = base; - - for (;;) { - int ret; - char atom_name[4]; - uint32_t atom_size; - - set_position(f, atom_offset); - - if (remaining < 8) - return -1; - ret = read_int32(f, &atom_size); - if (ret <= 0) - return ret; - if (atom_size > remaining || atom_size < 8) - return -1; - ret = read_data(f, atom_name, 4); - if (ret <= 0) - return ret; - if (!memcmp(atom_name, name, 4)) { - set_position(f, atom_offset); - return 1; - } - remaining -= atom_size; - atom_offset += atom_size; - } -} - -/* - * Try to find atom with atom in it. Besides -1/0/1 for - * error, EOF and success, this function may return 2 to indicate that the - * desired atoms were not found. - */ -static int find_atom_v2(struct mp4 *f, uint64_t base, uint32_t size, - const char *name, uint32_t extraheaders, const char *name_inside) -{ - uint64_t first_base = (uint64_t) (-1); - - for (;;) { - uint64_t mybase; - uint32_t mysize; - int ret = find_atom(f, base, size, name); - - if (ret <= 0) - return ret; - mybase = get_position(f); - ret = read_int32(f, &mysize); - if (ret <= 0) - return ret; - if (first_base == (uint64_t) (-1)) - first_base = mybase; - - if (mysize < 8 + extraheaders) - break; - - if (find_atom (f, mybase + (8 + extraheaders), - mysize - (8 + extraheaders), name_inside)) { - set_position(f, mybase); - return 1; - } - base += mysize; - if (size <= mysize) - break; - size -= mysize; - } - if (first_base != (uint64_t)(-1)) { - set_position(f, first_base); - return 1; - } - /* wanted atom inside not found */ - return 2; -} - struct membuffer { void *data; unsigned written; @@ -1322,18 +1262,13 @@ 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); - uint64_t udta_offset, meta_offset, ilst_offset; - uint32_t udta_size, meta_size, ilst_size; uint32_t new_ilst_size; void *new_ilst_buffer, *out_buffer; uint8_t *p_out; int32_t size_delta; uint32_t tmp; - ret = find_atom_v2(f, total_base, total_size, "udta", 0, "meta"); - if (ret <= 0) - return NULL; - if (ret == 2) { + if (f->udta_size == 0) { struct membuffer *buf; void *new_udta_buffer; uint32_t new_udta_size; @@ -1354,14 +1289,7 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) *out_size = membuffer_get_size(buf); return membuffer_detach(buf); } - udta_offset = get_position(f); - ret = read_int32(f, &udta_size); - if (ret <= 0) - return NULL; - ret = find_atom_v2(f, udta_offset + 8, udta_size - 8, "meta", 4, "ilst"); - if (ret <= 0) - return NULL; - if (ret == 2) { + if (f->meta_size == 0 || f->ilst_size == 0) { struct membuffer *buf; void *new_meta_buffer; uint32_t new_meta_size; @@ -1372,14 +1300,14 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) buf = membuffer_create(); set_position(f, total_base); if (!membuffer_transfer_from_file(buf, f, - udta_offset - total_base)) { + f->udta_offset - total_base)) { free(new_meta_buffer); return NULL; } - membuffer_write_int32(buf, udta_size + 8 + new_meta_size); + membuffer_write_int32(buf, f->udta_size + 8 + new_meta_size); membuffer_write_atom_name(buf, "udta"); - if (!membuffer_transfer_from_file(buf, f, udta_size)) { + if (!membuffer_transfer_from_file(buf, f, f->udta_size)) { free(new_meta_buffer); return NULL; } @@ -1390,27 +1318,16 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) *out_size = membuffer_get_size(buf); return membuffer_detach(buf); } - meta_offset = get_position(f); - ret = read_int32(f, &meta_size); - if (ret <= 0) - return NULL; - /* shouldn't happen, find_atom_v2 above takes care of it */ - if (!find_atom(f, meta_offset + 12, meta_size - 12, "ilst")) - return NULL; - ilst_offset = get_position(f); - ret = read_int32(f, &ilst_size); - if (ret <= 0) - return NULL; new_ilst_buffer = create_ilst(&f->meta, &new_ilst_size); - size_delta = new_ilst_size - (ilst_size - 8); + size_delta = new_ilst_size - (f->ilst_size - 8); *out_size = total_size + size_delta; out_buffer = para_malloc(*out_size); p_out = out_buffer; set_position(f, total_base); - ret = read_data(f, p_out, udta_offset - total_base); + ret = read_data(f, p_out, f->udta_offset - total_base); if (ret <= 0) return NULL; - p_out += (uint32_t) (udta_offset - total_base); + p_out += f->udta_offset - total_base; ret = read_int32(f, &tmp); if (ret <= 0) return NULL; @@ -1420,10 +1337,10 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) if (ret <= 0) return NULL; p_out += 4; - ret = read_data(f, p_out, meta_offset - udta_offset - 8); + ret = read_data(f, p_out, f->meta_offset - f->udta_offset - 8); if (ret <= 0) return NULL; - p_out += (uint32_t) (meta_offset - udta_offset - 8); + p_out += f->meta_offset - f->udta_offset - 8; ret = read_int32(f, &tmp); if (ret <= 0) return NULL; @@ -1433,10 +1350,10 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) if (ret <= 0) return NULL; p_out += 4; - ret = read_data(f, p_out, ilst_offset - meta_offset - 8); + ret = read_data(f, p_out, f->ilst_offset - f->meta_offset - 8); if (ret <= 0) return NULL; - p_out += (uint32_t) (ilst_offset - meta_offset - 8); + p_out += f->ilst_offset - f->meta_offset - 8; ret = read_int32(f, &tmp); if (ret <= 0) return NULL; @@ -1448,9 +1365,9 @@ static void *modify_moov(struct mp4 *f, uint32_t *out_size) p_out += 4; memcpy(p_out, new_ilst_buffer, new_ilst_size); p_out += new_ilst_size; - set_position(f, ilst_offset + ilst_size); - ret = read_data(f, p_out, total_size - - (ilst_offset - total_base) - 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);