[FFmpeg-devel] [PATCH 2/5] metadata: add new conversion API
Anton Khirnov
anton
Sun Oct 3 21:14:23 CEST 2010
From: Anton Khirnov <wyskas at gmail.com>
Track current metadata format in AVMetadata and add av_metadata_clone()
function for copying/replacing metadata.
---
libavformat/asfdec.c | 2 +
libavformat/avformat.h | 16 +++++++++++
libavformat/avidec.c | 1 +
libavformat/id3v2.c | 2 +
libavformat/matroskadec.c | 2 +
libavformat/metadata.c | 59 ++++++++++++++++++++++++++++++++++++++++++
libavformat/metadata.h | 1 +
libavformat/nutdec.c | 2 +
libavformat/oggparsevorbis.c | 3 ++
9 files changed, 88 insertions(+), 0 deletions(-)
diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c
index 6741f8c..59b075c 100644
--- a/libavformat/asfdec.c
+++ b/libavformat/asfdec.c
@@ -204,6 +204,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_byte(pb);
get_byte(pb);
memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
+
+ av_metadata_clone(&s->metadata, &s->metadata, ff_asf_metadata_conv, NULL, 0);
for(;;) {
uint64_t gpos= url_ftell(pb);
get_guid(pb, &g);
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 362a056..a9fb39f 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -198,6 +198,22 @@ void av_metadata_conv(struct AVFormatContext *ctx, const AVMetadataConv *d_conv,
const AVMetadataConv *s_conv);
/**
+ * Copy metadata from src to dst, converting between their respective formats.
+ * dst may be equal to src -- for in-place conversion -- or empty (i.e. a
+ * pointer to NULL), in both cases it is initialized to dst_fmt format.
+ * Otherwise dst_fmt is ignored. src may be a pointer to NULL, in which case
+ * dst is initialized, but nothing is copied.
+ *
+ * @param pattern Used to copy only some keys. If non-NULL, it is passed
+ * directly to av_metadata_get().
+ * @param flags Passed directly to av_metadata_get/set. If pattern is NULL,
+ * defaults to AV_METADATA_IGNORE_SUFFIX|AV_METADATA_DONT_OVERWRITE.
+ * @return >= 0 on success otherwise an error code <0
+ */
+int av_metadata_clone(AVMetadata **src, AVMetadata **dst, const AVMetadataConv *dst_fmt,
+ const char *pattern, int flags);
+
+/**
* Free all the memory allocated for an AVMetadata struct.
*/
void av_metadata_free(AVMetadata **m);
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 84ccaec..6bd4fd9 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -275,6 +275,7 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t
static void avi_read_info(AVFormatContext *s, uint64_t end)
{
+ av_metadata_clone(&s->metadata, &s->metadata, ff_avi_metadata_conv, NULL, 0);
while (url_ftell(s->pb) < end) {
uint32_t tag = get_le32(s->pb);
uint32_t size = get_le32(s->pb);
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 364720f..7b4f950 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -193,6 +193,8 @@ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
goto error;
}
+ av_metadata_clone(&s->metadata, &s->metadata, ff_id3v2_metadata_conv, NULL, 0);
+
unsync = flags & 0x80;
if (isv34 && flags & 0x40) /* Extended header present, just skip over it */
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 0d0285e..964ed8c 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1031,6 +1031,8 @@ static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
char key[1024];
int i;
+ av_metadata_clone(metadata, metadata, ff_mkv_metadata_conv, NULL, 0);
+
for (i=0; i < list->nb_elem; i++) {
const char *lang = strcmp(tags[i].lang, "und") ? tags[i].lang : NULL;
if (prefix) snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
diff --git a/libavformat/metadata.c b/libavformat/metadata.c
index 8fc1771..2a91219 100644
--- a/libavformat/metadata.c
+++ b/libavformat/metadata.c
@@ -152,3 +152,62 @@ void av_metadata_conv(AVFormatContext *ctx, const AVMetadataConv *d_conv,
for (i=0; i<ctx->nb_programs; i++)
metadata_conv(&ctx->programs[i]->metadata, d_conv, s_conv);
}
+
+int av_metadata_clone(AVMetadata **src, AVMetadata **dst, const AVMetadataConv *dst_fmt,
+ const char *pattern, int flags)
+{
+ int ret;
+ AVMetadataTag *mtag = NULL;
+ const AVMetadataConv *d_conv = (*dst && *dst != *src) ? (*dst)->cur_fmt : dst_fmt;
+ const AVMetadataConv *s_conv = *src ? (*src)->cur_fmt : NULL;
+ const AVMetadataConv *sc, *dc;
+ const char *key;
+ AVMetadata *tmp = av_mallocz(sizeof(*tmp));
+
+ if (!tmp)
+ return AVERROR(ENOMEM);
+ tmp->cur_fmt = d_conv;
+
+ if (!pattern && !flags)
+ flags = AV_METADATA_IGNORE_SUFFIX | AV_METADATA_DONT_OVERWRITE;
+
+ if (*src)
+ while ((mtag = av_metadata_get(*src, pattern ? pattern : "", mtag, flags))) {
+ key = mtag->key;
+ if (s_conv)
+ for (sc=s_conv; sc->native; sc++)
+ if (!strcasecmp(key, sc->native)) {
+ key = sc->generic;
+ break;
+ }
+ if (d_conv)
+ for (dc=d_conv; dc->native; dc++)
+ if (!strcasecmp(key, dc->generic)) {
+ key = dc->native;
+ break;
+ }
+ if ((ret = av_metadata_set2(&tmp, key, mtag->value, flags)) < 0) {
+ av_metadata_free(&tmp);
+ return ret;
+ }
+ }
+
+ if (src == dst)
+ av_metadata_free(src);
+ if (!*dst)
+ *dst = tmp;
+ else {
+ mtag = NULL;
+ while ((mtag = av_metadata_get(tmp, "", mtag, AV_METADATA_IGNORE_SUFFIX)))
+ if ((ret = av_metadata_set2(dst, mtag->key, mtag->value, flags)) < 0)
+ break;
+ av_metadata_free(&tmp);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (*dst)
+ (*dst)->cur_fmt = d_conv;
+
+ return 0;
+}
diff --git a/libavformat/metadata.h b/libavformat/metadata.h
index 3706bc4..4e54904 100644
--- a/libavformat/metadata.h
+++ b/libavformat/metadata.h
@@ -33,6 +33,7 @@
struct AVMetadata{
int count;
AVMetadataTag *elems;
+ const AVMetadataConv *cur_fmt;
};
struct AVMetadataConv{
diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c
index 7db06fa..3dc608f 100644
--- a/libavformat/nutdec.c
+++ b/libavformat/nutdec.c
@@ -429,6 +429,8 @@ static int decode_info_header(NUTContext *nut){
} else
metadata = &s->metadata;
+ av_metadata_clone(metadata, metadata, ff_nut_metadata_conv, NULL, 0);
+
for(i=0; i<count; i++){
get_str(bc, name, sizeof(name));
value= get_s(bc);
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index c7f8149..45d3b6d 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -29,6 +29,7 @@
#include "libavcodec/bytestream.h"
#include "avformat.h"
#include "oggdec.h"
+#include "vorbiscomment.h"
static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
{
@@ -84,6 +85,8 @@ ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int
n = bytestream_get_le32(&p);
+ av_metadata_clone(m, m, ff_vorbiscomment_metadata_conv, NULL, 0);
+
while (end - p >= 4 && n > 0) {
const char *t, *v;
int tl, vl;
--
1.7.1
More information about the ffmpeg-devel
mailing list