]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
mp4: Remove find_atom() and find_atom_v2().
authorAndre Noll <maan@tuebingen.mpg.de>
Sat, 21 Aug 2021 14:23:05 +0000 (16:23 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Mon, 30 May 2022 19:37:35 +0000 (21:37 +0200)
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.

mp4.c

diff --git a/mp4.c b/mp4.c
index 92be4c766724b471c7d31036b41b3408f3e36406..ca70bd20b8468f0d5a170fc9e67292e681617ceb 100644 (file)
--- 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 <name> with atom <name_inside> 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);