static int32_t tag_add_field(struct mp4_metadata *tags, const char *item,
const char *value, int32_t len)
{
- if (!item || (item && !*item) || !value)
- return 0;
tags->tags = para_realloc(tags->tags,
(tags->count + 1) * sizeof(struct mp4_tag));
tags->tags[tags->count].item = para_strdup(item);
static void parse_tag(struct mp4 *f, uint8_t parent, int32_t size)
{
uint64_t subsize, sumsize;
- char *name = NULL;
char *data = NULL;
uint32_t len = 0;
uint64_t destpos;
uint8_t header_size = 0;
subsize = atom_read_header(f, &atom_type, &header_size);
destpos = get_position(f) + subsize - header_size;
- if (atom_type == ATOM_NAME) {
- read_char(f); /* version */
- read_int24(f); /* flags */
- free(name);
- name = read_string(f, subsize - (header_size + 4));
- continue;
- }
if (atom_type != ATOM_DATA)
continue;
read_char(f); /* version */
data = read_string(f, subsize - (header_size + 8));
len = subsize - (header_size + 8);
}
- if (data) {
- if (!name)
- name = para_strdup(get_metadata_name(parent));
- tag_add_field(&(f->tags), name, data, len);
- free(data);
- }
- free(name);
+ if (!data)
+ return;
+ tag_add_field(&f->tags, get_metadata_name(parent), data, len);
+ free(data);
}
static int32_t read_mdhd(struct mp4 *f)
return f;
}
-int32_t mp4_meta_get_num_items(const struct mp4 *f)
-{
- return f->tags.count;
-}
-
-int32_t mp4_meta_get_by_index(const struct mp4 *f, uint32_t index,
- char **item, char **value)
+/**
+ * Return the metadata of an mp4 file.
+ *
+ * \param f As returned by either \ref mp4_open_read() or \ref mp4_open_meta().
+ *
+ * The caller is allowed to add, delete or modify the entries of the returned
+ * structure in order to pass the modified version to \ref mp4_meta_update().
+ */
+struct mp4_metadata *mp4_get_meta(struct mp4 *f)
{
- if (index >= f->tags.count) {
- *item = NULL;
- *value = NULL;
- return 0;
- } else {
- *item = para_strdup(f->tags.tags[index].item);
- *value = para_strdup(f->tags.tags[index].value);
- return 1;
- }
+ return &f->tags;
}
static uint32_t find_atom(struct mp4 *f, uint64_t base, uint32_t size,
return read_u32_be(&src);
}
-static uint32_t modify_moov(struct mp4 *f, const struct mp4_metadata *data,
- void **out_buffer, uint32_t * out_size)
+static uint32_t modify_moov(struct mp4 *f, void **out_buffer,
+ uint32_t *out_size)
{
uint64_t total_base = f->moov_offset + 8;
uint32_t total_size = (uint32_t) (f->moov_size - 8);
struct membuffer *buf;
void *new_udta_buffer;
uint32_t new_udta_size;
- if (!create_udta(data, &new_udta_buffer, &new_udta_size))
+ if (!create_udta(&f->tags, &new_udta_buffer, &new_udta_size))
return 0;
buf = membuffer_create();
struct membuffer *buf;
void *new_meta_buffer;
uint32_t new_meta_size;
- if (!create_meta(data, &new_meta_buffer, &new_meta_size))
+
+ if (!create_meta(&f->tags, &new_meta_buffer, &new_meta_size))
return 0;
buf = membuffer_create();
ilst_offset = get_position(f);
ilst_size = read_int32(f);
- if (!create_ilst(data, &new_ilst_buffer, &new_ilst_size))
+ if (!create_ilst(&f->tags, &new_ilst_buffer, &new_ilst_size))
return 0;
size_delta = new_ilst_size - (ilst_size - 8);
return write_data(f, temp, sizeof(temp));
}
-int32_t mp4_meta_update(const struct mp4_callback *cb,
- const struct mp4_metadata *data)
+int32_t mp4_meta_update(struct mp4 *f)
{
void *new_moov_data;
uint32_t new_moov_size;
- struct mp4 *f = para_calloc(sizeof(struct mp4));
- f->cb = cb;
set_position(f, 0);
- parse_atoms(f, 1);
- if (!modify_moov(f, data, &new_moov_data, &new_moov_size)) {
+ if (!modify_moov(f, &new_moov_data, &new_moov_size)) {
mp4_close(f);
return 0;
}
-
/* copy moov atom to end of the file */
if (f->last_atom != ATOM_MOOV) {
char *free_data = "free";
write_data(f, "moov", 4);
write_data(f, new_moov_data, new_moov_size);
}
- cb->truncate(cb->user_data);
- mp4_close(f);
+ free(new_moov_data);
+ f->cb->truncate(f->cb->user_data);
return 1;
}
-/* find a metadata item by name */
-/* returns 0 if item found, 1 if no such item */
-static int32_t meta_find_by_name(const struct mp4 *f, const char *item,
- char **value)
+static char *meta_find_by_name(const struct mp4 *f, const char *item)
{
uint32_t i;
- for (i = 0; i < f->tags.count; i++) {
- if (!strcasecmp(f->tags.tags[i].item, item)) {
- *value = para_strdup(f->tags.tags[i].value);
- return 1;
- }
- }
-
- *value = NULL;
-
- /* not found */
- return 0;
+ for (i = 0; i < f->tags.count; i++)
+ if (!strcasecmp(f->tags.tags[i].item, item))
+ return para_strdup(f->tags.tags[i].value);
+ return NULL;
}
-int32_t mp4_meta_get_artist(const struct mp4 *f, char **value)
+/**
+ * Return the value of the artist meta tag of an mp4 file.
+ *
+ * \param f Must not be NULL.
+ *
+ * \return If the file does not contain this metadata tag, the function returns
+ * NULL. Otherwise, a copy of the tag value is returned. The caller should free
+ * this memory when it is no longer needed.
+ */
+char *mp4_meta_get_artist(const struct mp4 *f)
{
- return meta_find_by_name(f, "artist", value);
+ return meta_find_by_name(f, "artist");
}
-int32_t mp4_meta_get_title(const struct mp4 *f, char **value)
+/**
+ * Return the value of the title meta tag of an mp4 file.
+ *
+ * \param f See \ref mp4_meta_get_artist().
+ * \return See \ref mp4_meta_get_artist().
+ */
+char *mp4_meta_get_title(const struct mp4 *f)
{
- return meta_find_by_name(f, "title", value);
+ return meta_find_by_name(f, "title");
}
-int32_t mp4_meta_get_date(const struct mp4 *f, char **value)
+/**
+ * Return the value of the date meta tag of an mp4 file.
+ *
+ * \param f See \ref mp4_meta_get_artist().
+ * \return See \ref mp4_meta_get_artist().
+ */
+char *mp4_meta_get_date(const struct mp4 *f)
{
- return meta_find_by_name(f, "date", value);
+ return meta_find_by_name(f, "date");
}
-int32_t mp4_meta_get_album(const struct mp4 *f, char **value)
+/**
+ * Return the value of the album meta tag of an mp4 file.
+ *
+ * \param f See \ref mp4_meta_get_artist().
+ * \return See \ref mp4_meta_get_artist().
+ */
+char *mp4_meta_get_album(const struct mp4 *f)
{
- return meta_find_by_name(f, "album", value);
+ return meta_find_by_name(f, "album");
}
-int32_t mp4_meta_get_comment(const struct mp4 *f, char **value)
+/**
+ * Return the value of the comment meta tag of an mp4 file.
+ *
+ * \param f See \ref mp4_meta_get_artist().
+ * \return See \ref mp4_meta_get_artist().
+ */
+char *mp4_meta_get_comment(const struct mp4 *f)
{
- return meta_find_by_name(f, "comment", value);
+ return meta_find_by_name(f, "comment");
}