[FFmpeg-cvslog] apetag: add support for writing APE tags

Anton Khirnov git at videolan.org
Wed May 29 10:51:35 CEST 2013


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Tue May 28 17:43:22 2013 +0200| [88de0c7901ee2bd6021cf32def87ce98ce63155c] | committer: Anton Khirnov

apetag: add support for writing APE tags

This will be useful in the WavPack muxer.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=88de0c7901ee2bd6021cf32def87ce98ce63155c
---

 libavformat/apetag.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/apetag.h |    5 +++++
 2 files changed, 61 insertions(+)

diff --git a/libavformat/apetag.c b/libavformat/apetag.c
index 0d2cb97..68f2df6 100644
--- a/libavformat/apetag.c
+++ b/libavformat/apetag.c
@@ -23,12 +23,14 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/dict.h"
 #include "avformat.h"
+#include "avio_internal.h"
 #include "apetag.h"
 #include "internal.h"
 
 #define APE_TAG_VERSION               2000
 #define APE_TAG_FOOTER_BYTES          32
 #define APE_TAG_FLAG_CONTAINS_HEADER  (1 << 31)
+#define APE_TAG_FLAG_CONTAINS_FOOTER  (1 << 30)
 #define APE_TAG_FLAG_IS_HEADER        (1 << 29)
 #define APE_TAG_FLAG_IS_BINARY        (1 << 1)
 
@@ -169,3 +171,57 @@ int64_t ff_ape_parse_tag(AVFormatContext *s)
 
     return tag_start;
 }
+
+int ff_ape_write_tag(AVFormatContext *s)
+{
+    AVDictionaryEntry *e = NULL;
+    int64_t start, end;
+    int size, count = 0;
+
+    if (!s->pb->seekable)
+        return 0;
+
+    start = avio_tell(s->pb);
+
+    // header
+    avio_write(s->pb, "APETAGEX", 8);   // id
+    avio_wl32 (s->pb, APE_TAG_VERSION); // version
+    avio_wl32(s->pb, 0);                // reserve space for size
+    avio_wl32(s->pb, 0);                // reserve space for tag count
+
+    // flags
+    avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER |
+                     APE_TAG_FLAG_IS_HEADER);
+    ffio_fill(s->pb, 0, 8);             // reserved
+
+    while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
+        int val_len = strlen(e->value);
+
+        avio_wl32(s->pb, val_len);            // value length
+        avio_wl32(s->pb, 0);                  // item flags
+        avio_put_str(s->pb, e->key);          // key
+        avio_write(s->pb, e->value, val_len); // value
+        count++;
+    }
+
+    size = avio_tell(s->pb) - start;
+
+    // footer
+    avio_write(s->pb, "APETAGEX", 8);   // id
+    avio_wl32 (s->pb, APE_TAG_VERSION); // version
+    avio_wl32(s->pb, size);             // size
+    avio_wl32(s->pb, count);            // tag count
+
+    // flags
+    avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER);
+    ffio_fill(s->pb, 0, 8);             // reserved
+
+    // update values in the header
+    end = avio_tell(s->pb);
+    avio_seek(s->pb, start + 12, SEEK_SET);
+    avio_wl32(s->pb, size);
+    avio_wl32(s->pb, count);
+    avio_seek(s->pb, end, SEEK_SET);
+
+    return 0;
+}
diff --git a/libavformat/apetag.h b/libavformat/apetag.h
index 279972f..36e3211 100644
--- a/libavformat/apetag.h
+++ b/libavformat/apetag.h
@@ -32,4 +32,9 @@
  */
 int64_t ff_ape_parse_tag(AVFormatContext *s);
 
+/**
+ * Write an APE tag into a file.
+ */
+int ff_ape_write_tag(AVFormatContext *s);
+
 #endif /* AVFORMAT_APETAG_H */



More information about the ffmpeg-cvslog mailing list