]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
mp4: Provide whence parameter for the seek callback.
authorAndre Noll <maan@tuebingen.mpg.de>
Tue, 24 Aug 2021 18:47:03 +0000 (20:47 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Mon, 30 May 2022 19:37:36 +0000 (21:37 +0200)
This adds a parameter to make ->seek() work like the lseek(2) system
call. This is easy to implement in both the memory-mapped callback
case used to retrieve the file information and the metadata update
case where ->seek() is a trivial wrapper for lseek(2).

With the additional functionality in place we don't need to track
the file size and the current file offset any more in mp4.c as these
values can now be obtained by calling ->seek() with a zero offset and
whence set to SEEK_END and SEEK_CUR, respectively. This also makes
the code more robust against corrupt mp4 files because we no longer
rely on the values from the atom headers to compute the file size.

The way mp4.c calls ->seek() should never cause the underlying lseek(2)
system call to fail. Therefore it suffices to check the return value
only in the callback wrapper and abort on failure.

aac_afh.c
mp4.c
mp4.h

index 0a80bfcf3a44205ea7d42f9ac260c03f910ba199..b6c90d59009a3315f9249e5e3b200429132d6296 100644 (file)
--- a/aac_afh.c
+++ b/aac_afh.c
@@ -41,11 +41,19 @@ static ssize_t aac_afh_read_cb(void *user_data, void *dest, size_t want)
        return rv;
 }
 
-static uint32_t aac_afh_seek_cb(void *user_data, uint64_t pos)
+static off_t aac_afh_seek_cb(void *user_data, off_t offset, int whence)
 {
        struct aac_afh_context *c = user_data;
-       c->fpos = pos;
-       return 0;
+
+       if (whence == SEEK_SET)
+               c->fpos = offset;
+       else if (whence == SEEK_CUR)
+               c->fpos += offset;
+       else if (whence == SEEK_END)
+               c->fpos = c->mapsize + offset;
+       else
+               assert(false);
+       return c->fpos;
 }
 
 static int aac_afh_open(const void *map, size_t mapsize, void **afh_context)
@@ -167,10 +175,13 @@ static ssize_t aac_afh_meta_read_cb(void *user_data, void *dest, size_t want)
        return read(fd, dest, want);
 }
 
-static uint32_t aac_afh_meta_seek_cb(void *user_data, uint64_t pos)
+static off_t aac_afh_meta_seek_cb(void *user_data, off_t offset, int whence)
 {
        int fd = *(int *)user_data;
-       return lseek(fd, pos, SEEK_SET);
+       off_t ret = lseek(fd, offset, whence);
+
+       assert(ret != (off_t)-1);
+       return ret;
 }
 
 static ssize_t aac_afh_meta_write_cb(void *user_data, void *dest, size_t count)
diff --git a/mp4.c b/mp4.c
index fc8c41b4af919358350812cae68033611c5d33c4..08812c89b18345bb238ae117572ea9fc8c67b3d6 100644 (file)
--- a/mp4.c
+++ b/mp4.c
@@ -45,7 +45,6 @@ struct mp4_track {
 
 struct mp4 {
        const struct mp4_callback *cb;
-       int64_t current_position;
 
        uint64_t moov_offset;
        uint64_t moov_size;
@@ -57,8 +56,6 @@ struct mp4 {
        uint32_t udta_size;
 
        uint8_t last_atom;
-       uint64_t file_size;
-
        /* incremental track index while reading the file */
        int32_t total_tracks;
        /* track data */
@@ -83,7 +80,6 @@ static int read_data(struct mp4 *f, void *data, size_t size)
                /* regard EAGAIN as an error as reads should be blocking. */
                if (ret <= 0)
                        return ret < 0? -1 : 0;
-               f->current_position += ret;
                size -= ret;
        }
        return 1;
@@ -212,17 +208,14 @@ static int atom_read_header(struct mp4 *f, uint8_t *atom_type,
        return 1;
 }
 
-static int64_t get_position(const struct mp4 *f)
+static off_t get_position(const struct mp4 *f)
 {
-       return f->current_position;
+       return f->cb->seek(f->cb->user_data, 0, SEEK_CUR);
 }
 
-static int32_t set_position(struct mp4 *f, int64_t position)
+static void set_position(struct mp4 *f, off_t position)
 {
-       f->cb->seek(f->cb->user_data, position);
-       f->current_position = position;
-
-       return 0;
+       f->cb->seek(f->cb->user_data, position, SEEK_SET);
 }
 
 static int read_stsz(struct mp4 *f)
@@ -696,7 +689,6 @@ static int open_file(const struct mp4_callback *cb, bool meta_only, struct mp4 *
 
        f->cb = cb;
        while ((ret = atom_read_header(f, &atom_type, &header_size, &size)) > 0) {
-               f->file_size += size;
                f->last_atom = atom_type;
                if (atom_type != ATOM_MOOV || size <= header_size) { /* skip */
                        set_position(f, get_position(f) + size - header_size);
@@ -979,7 +971,6 @@ static int write_data(struct mp4 *f, void *data, size_t size)
                                continue;
                        return -ERRNO_TO_PARA_ERROR(errno);
                }
-               f->current_position += ret;
                size -= ret;
        }
        return 1;
@@ -1003,7 +994,8 @@ int mp4_meta_update(struct mp4 *f)
                ret = write_data(f, "free", 4); /* rename old moov to free */
                if (ret < 0)
                        goto free_moov;
-               set_position(f, f->file_size); /* write new moov atom at EOF */
+               /* write new moov atom at EOF */
+               f->cb->seek(f->cb->user_data, 0, SEEK_END);
        } else /* overwrite old moov atom */
                set_position(f, f->moov_offset);
        write_u32_be(buf, new_moov_size + 8);
diff --git a/mp4.h b/mp4.h
index 30a609f38c108d0306ccc18ea68596cf64647c96..243b75ca369e988b84083853829ef2c24bb4d424 100644 (file)
--- a/mp4.h
+++ b/mp4.h
@@ -1,7 +1,7 @@
 struct mp4_callback {
        ssize_t (*read)(void *user_data, void *buffer, size_t length);
        ssize_t (*write)(void *user_data, void *buffer, size_t count);
-       uint32_t (*seek)(void *user_data, uint64_t position);
+       off_t (*seek)(void *user_data, off_t offset, int whence);
        uint32_t (*truncate)(void *user_data);
        void *user_data;
 };