]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - mp4.c
mp4: Assume udta, meta and ilst are always present.
[paraslash.git] / mp4.c
diff --git a/mp4.c b/mp4.c
index 2ca4ed8a7235f0ddb42ac8f7e2564602d7a93ef4..1d8af6cb20853c33a4aff5d151eb143951bd5a90 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;
 
@@ -550,7 +557,6 @@ static int read_mp4a(struct mp4 *f)
 {
        int ret;
        int32_t i;
-       uint8_t atom_type = 0;
        struct mp4_track *t;
 
        if (f->total_tracks == 0)
@@ -583,13 +589,7 @@ static int read_mp4a(struct mp4 *f)
        ret = read_int16(f, NULL);
        if (ret <= 0)
                return ret;
-       ret = read_int16(f, &t->sampleRate);
-       if (ret <= 0)
-               return ret;
-       ret = read_int16(f, NULL);
-       if (ret <= 0)
-               return ret;
-       return atom_read_header(f, &atom_type, NULL, NULL);
+       return read_int16(f, &t->sampleRate);
 }
 
 static int read_stsd(struct mp4 *f)
@@ -627,39 +627,6 @@ static int read_stsd(struct mp4 *f)
        return 1;
 }
 
-static int32_t tag_add_field(struct mp4_metadata *meta, const char *item,
-               const char *value, int32_t len)
-{
-       meta->tags = para_realloc(meta->tags,
-               (meta->count + 1) * sizeof(struct mp4_tag));
-       meta->tags[meta->count].item = para_strdup(item);
-       meta->tags[meta->count].len = len;
-       if (len >= 0) {
-               meta->tags[meta->count].value = para_malloc(len + 1);
-               memcpy(meta->tags[meta->count].value, value, len);
-               meta->tags[meta->count].value[len] = 0;
-       } else {
-               meta->tags[meta->count].value = para_strdup(value);
-       }
-       meta->count++;
-       return 1;
-}
-
-static int read_string(struct mp4 *f, uint32_t length, char **result)
-{
-       char *str = para_malloc(length + 1);
-       int ret = read_data(f, str, length);
-
-       if (ret <= 0) {
-               free(str);
-               *result = NULL;
-       } else {
-               str[length] = '\0';
-               *result = str;
-       }
-       return ret;
-}
-
 static const char *get_metadata_name(uint8_t atom_type)
 {
        switch (atom_type) {
@@ -676,9 +643,10 @@ static int parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
 {
        int ret;
        uint64_t subsize, sumsize;
-       char *data = NULL;
+       char *value = NULL;
        uint32_t len = 0;
        uint64_t destpos;
+       struct mp4_tag *tag;
 
        for (
                sumsize = 0;
@@ -689,30 +657,43 @@ static int parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
                uint8_t header_size = 0;
                ret = atom_read_header(f, &atom_type, &header_size, &subsize);
                if (ret <= 0)
-                       return ret;
+                       goto fail;
                destpos = get_position(f) + subsize - header_size;
                if (atom_type != ATOM_DATA)
                        continue;
                ret = read_int8(f, NULL); /* version */
                if (ret <= 0)
-                       return ret;
+                       goto fail;
                ret = read_int24(f, NULL); /* flags */
                if (ret <= 0)
-                       return ret;
+                       goto fail;
                ret = read_int32(f, NULL); /* reserved */
                if (ret <= 0)
-                       return ret;
-               free(data);
-               ret = read_string(f, subsize - (header_size + 8), &data);
-               if (ret <= 0)
-                       return ret;
+                       goto fail;
+               ret = -ERRNO_TO_PARA_ERROR(EINVAL);
+               if (subsize < header_size + 8 || subsize > UINT_MAX)
+                       goto fail;
                len = subsize - (header_size + 8);
+               free(value);
+               value = para_malloc(len + 1);
+               ret = read_data(f, value, len);
+               if (ret <= 0)
+                       goto fail;
+               value[len] = '\0';
        }
-       if (!data)
-               return -1;
-       tag_add_field(&f->meta, get_metadata_name(parent), data, len);
-       free(data);
+       if (!value)
+               return -ERRNO_TO_PARA_ERROR(EINVAL);
+       f->meta.tags = para_realloc(f->meta.tags, (f->meta.count + 1)
+               * sizeof(struct mp4_tag));
+       tag = f->meta.tags + f->meta.count;
+       tag->item = para_strdup(get_metadata_name(parent));
+       tag->value = value;
+       tag->len = len;
+       f->meta.count++;
        return 1;
+fail:
+       free(value);
+       return ret;
 }
 
 static int read_mdhd(struct mp4 *f)
@@ -787,7 +768,9 @@ static int32_t read_ilst(struct mp4 *f, int32_t size)
                case ATOM_ALBUM:
                case ATOM_COMMENT:
                case ATOM_DATE:
-                       parse_tag(f, atom_type, subsize - header_size);
+                       ret = parse_tag(f, atom_type, subsize - header_size);
+                       if (ret <= 0)
+                               return ret;
                }
                set_position(f, destpos);
                sumsize += subsize;
@@ -814,16 +797,21 @@ static int32_t read_meta(struct mp4 *f, uint64_t size)
                        return ret;
                if (subsize <= header_size + 4)
                        return 1;
-               if (atom_type == ATOM_ILST)
-                       read_ilst(f, subsize - (header_size + 4));
-               else
+               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;
+               } else
                        set_position(f, get_position(f) + subsize - header_size);
                sumsize += subsize;
        }
        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 */
@@ -835,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;
@@ -851,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 */
@@ -863,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;
@@ -891,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);
@@ -899,22 +894,21 @@ 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;
        }
        return 1;
 }
 
-static int parse_root_atoms(struct mp4 *f, bool meta_only)
+static int open_file(const struct mp4_callback *cb, bool meta_only, struct mp4 **result)
 {
        int ret;
        uint64_t size;
-       uint8_t atom_type = 0;
-       uint8_t header_size = 0;
-
-       f->file_size = 0;
+       uint8_t atom_type, header_size;
+       struct mp4 *f = para_calloc(sizeof(*f));
 
+       f->cb = cb;
        while ((ret = atom_read_header(f, &atom_type, &header_size, &size)) > 0) {
                f->file_size += size;
                f->last_atom = atom_type;
@@ -928,25 +922,24 @@ static int parse_root_atoms(struct mp4 *f, bool meta_only)
                if (ret <= 0)
                        break;
        }
-       if (ret < 0)
-               return ret;
+       if (ret < 0) {
+               ret = -E_MP4_OPEN;
+               goto fail;
+       }
+       ret = -E_MP4_TRACK;
        if (!f->audio_track)
-               return -E_MP4_TRACK;
+               goto fail;
+       *result = f;
+       return 1;
+fail:
+       *result = NULL;
+       free(f);
        return ret;
 }
 
-struct mp4 *mp4_open_read(const struct mp4_callback *cb)
+int mp4_open_read(const struct mp4_callback *cb, struct mp4 **result)
 {
-       int ret;
-       struct mp4 *f = para_calloc(sizeof(struct mp4));
-
-       f->cb = cb;
-       ret = parse_root_atoms(f, false);
-       if (ret < 0) {
-               free(f);
-               return NULL;
-       }
-       return f;
+       return open_file(cb, false, result);
 }
 
 void mp4_close(struct mp4 *f)
@@ -1061,18 +1054,20 @@ int32_t mp4_num_samples(const struct mp4 *f)
        return total;
 }
 
-struct mp4 *mp4_open_meta(const struct mp4_callback *cb)
+int mp4_open_meta(const struct mp4_callback *cb, struct mp4 **result)
 {
-       int ret;
-       struct mp4 *f = para_calloc(sizeof(struct mp4));
+       struct mp4 *f;
+       int ret = open_file(cb, true, &f);
 
-       f->cb = cb;
-       ret = parse_root_atoms(f, true);
-       if (ret < 0) {
-               free(f);
-               return NULL;
+       if (ret < 0)
+               return ret;
+       if (f->udta_size == 0 || f->meta_size == 0 || f->ilst_size == 0) {
+               mp4_close(f);
+               *result = NULL;
+               return -E_MP4_MISSING_ATOM;
        }
-       return f;
+       *result = f;
+       return 1;
 }
 
 /**
@@ -1088,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;
@@ -1209,24 +1127,6 @@ static void membuffer_write_int32(struct membuffer *buf, uint32_t data)
        membuffer_write(buf, temp, 4);
 }
 
-static void membuffer_write_std_tag(struct membuffer *buf, const char *name,
-               const char *value)
-{
-       uint32_t len = strlen(value);
-       membuffer_write_int32(buf, 8 /* atom header */
-               + 8 /* data atom header */
-               + 8 /* flags + reserved */
-               + len);
-       membuffer_write_atom_name(buf, name);
-       membuffer_write_int32(buf, 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, value, len);
-}
-
 static unsigned membuffer_get_size(const struct membuffer *buf)
 {
        return buf->written;
@@ -1239,115 +1139,43 @@ static void *membuffer_detach(struct membuffer *buf)
        return ret;
 }
 
-struct stdmeta_entry {
-       const char *atom;
-       const char *name;
-};
-
-static const char *find_standard_meta(const char *name)
-{
-       const struct stdmeta_entry stdmetas[] = {
-               {"\xA9" "nam", "title"},
-               {"\xA9" "ART", "artist"},
-               {"\xA9" "alb", "album"},
-               {"\xA9" "day", "date"},
-               {"\xA9" "cmt", "comment"},
-       };
-
-       for (unsigned n = 0; n < ARRAY_SIZE(stdmetas); n++)
-               if (!strcasecmp(name, stdmetas[n].name))
-                       return stdmetas[n].atom;
-       return NULL;
-}
-
-static uint32_t create_ilst(const struct mp4_metadata *meta, void **out_buffer,
-               uint32_t * out_size)
+static void *create_ilst(const struct mp4_metadata *meta, uint32_t *out_size)
 {
        struct membuffer *buf = membuffer_create();
-       unsigned metaptr;
-
-       for (metaptr = 0; metaptr < meta->count; metaptr++) {
-               struct mp4_tag *tag = meta->tags + metaptr;
-               const char *std_meta_atom = find_standard_meta(tag->item);
-               if (std_meta_atom)
-                       membuffer_write_std_tag(buf, std_meta_atom, tag->value);
+       unsigned n;
+
+       for (n = 0; n < meta->count; n++) {
+               struct mp4_tag *tag = meta->tags + n;
+               unsigned len = strlen(tag->value);
+               const char *atom_name;
+
+               if (!strcasecmp(tag->item, "title"))
+                       atom_name = "\xA9" "nam";
+               else if (!strcasecmp(tag->item, "artist"))
+                       atom_name = "\xA9" "ART";
+               else if (!strcasecmp(tag->item, "album"))
+                       atom_name = "\xA9" "alb";
+               else if (!strcasecmp(tag->item, "date"))
+                       atom_name = "\xA9" "day";
+               else if (!strcasecmp(tag->item, "comment"))
+                       atom_name = "\xA9" "cmt";
                else
-                       PARA_ERROR_LOG("invalid tag item: %s\n", tag->item);
-       }
-       *out_size = membuffer_get_size(buf);
-       *out_buffer = membuffer_detach(buf);
-       return 1;
-}
-
-static void membuffer_write_atom(struct membuffer *buf, const char *name, unsigned size,
-                         const void *data)
-{
-       membuffer_write_int32(buf, size + 8);
-       membuffer_write_atom_name(buf, name);
-       membuffer_write(buf, data, size);
-}
-
-static void *membuffer_get_ptr(const struct membuffer *buf)
-{
-       return buf->data;
-}
-
-static bool membuffer_transfer_from_file(struct membuffer *buf, struct mp4 *src,
-               unsigned bytes)
-{
-       unsigned oldsize = membuffer_get_size(buf);
-       char *bufptr;
-
-       membuffer_write(buf, 0, bytes);
-       bufptr = membuffer_get_ptr(buf);
-       if (read_data(src, bufptr + oldsize, bytes) != 1) {
-               free(buf->data);
-               free(buf);
-               return false;
+                       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 */
+                       + 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);
        }
-       return true;
-}
-
-static uint32_t create_meta(const struct mp4_metadata *meta, void **out_buffer,
-               uint32_t * out_size)
-{
-       struct membuffer *buf;
-       uint32_t ilst_size;
-       void *ilst_buffer;
-
-       if (!create_ilst(meta, &ilst_buffer, &ilst_size))
-               return 0;
-
-       buf = membuffer_create();
-
-       membuffer_write_int32(buf, 0);
-       membuffer_write_atom(buf, "ilst", ilst_size, ilst_buffer);
-       free(ilst_buffer);
-
        *out_size = membuffer_get_size(buf);
-       *out_buffer = membuffer_detach(buf);
-       return 1;
-}
-
-static uint32_t create_udta(const struct mp4_metadata *meta, void **out_buffer,
-uint32_t * out_size)
-{
-       struct membuffer *buf;
-       uint32_t meta_size;
-       void *meta_buffer;
-
-       if (!create_meta(meta, &meta_buffer, &meta_size))
-               return 0;
-
-       buf = membuffer_create();
-
-       membuffer_write_atom(buf, "meta", meta_size, meta_buffer);
-
-       free(meta_buffer);
-
-       *out_size = membuffer_get_size(buf);
-       *out_buffer = membuffer_detach(buf);
-       return 1;
+       return membuffer_detach(buf);
 }
 
 static uint32_t fix_byte_order_32(uint32_t src)
@@ -1360,96 +1188,22 @@ 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) {
-               struct membuffer *buf;
-               void *new_udta_buffer;
-               uint32_t new_udta_size;
-               if (!create_udta(&f->meta, &new_udta_buffer, &new_udta_size))
-                       return NULL;
-
-               buf = membuffer_create();
-               set_position(f, total_base);
-               if (!membuffer_transfer_from_file(buf, f, total_size)) {
-                       free(new_udta_buffer);
-                       return NULL;
-               }
-               membuffer_write_atom(buf, "udta", new_udta_size,
-                       new_udta_buffer);
-
-               free(new_udta_buffer);
-
-               *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) {
-               struct membuffer *buf;
-               void *new_meta_buffer;
-               uint32_t new_meta_size;
-
-               if (!create_meta(&f->meta, &new_meta_buffer, &new_meta_size))
-                       return NULL;
-
-               buf = membuffer_create();
-               set_position(f, total_base);
-               if (!membuffer_transfer_from_file(buf, f,
-                               udta_offset - total_base)) {
-                       free(new_meta_buffer);
-                       return NULL;
-               }
-
-               membuffer_write_int32(buf, udta_size + 8 + new_meta_size);
-               membuffer_write_atom_name(buf, "udta");
-               if (!membuffer_transfer_from_file(buf, f, udta_size)) {
-                       free(new_meta_buffer);
-                       return NULL;
-               }
-               membuffer_write_atom(buf, "meta", new_meta_size,
-                       new_meta_buffer);
-               free(new_meta_buffer);
-
-               *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;
-       if (!create_ilst(&f->meta, &new_ilst_buffer, &new_ilst_size))
-               return NULL;
-       size_delta = new_ilst_size - (ilst_size - 8);
+       new_ilst_buffer = create_ilst(&f->meta, &new_ilst_size);
+       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;
@@ -1459,10 +1213,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;
@@ -1472,10 +1226,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;
@@ -1487,9 +1241,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);