-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;
- 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 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;
-}
-
-static void *membuffer_detach(struct membuffer *buf)
-{
- void *ret = para_realloc(buf->data, buf->written);
- free(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)
-{
- 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);