[libav-devel] [PATCH] [GCI] Implement WAV INFO tag reading

Victor Vasiliev vasilvv at gmail.com
Mon Nov 21 22:12:41 CET 2011


---
 libavformat/wav.c |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 69 insertions(+), 1 deletions(-)

diff --git a/libavformat/wav.c b/libavformat/wav.c
index 298880d..3147093 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -378,6 +378,66 @@ static const AVMetadataConv wav_metadata_conv[] = {
     {0},
 };

+static const AVMetadataConv wav_info_tag_conv[] = {
+    {"IART", "artist"       },
+    {"ICMT", "comment"      },
+    {"ICOP", "copyright"    },
+    {"ICRD", "creation_date"},
+    {"IGNR", "genre"        },
+    {"INAM", "title"        },
+    {"ISFT", "encoder"      },
+    {0},
+};
+
+static int wav_parse_info_tags(AVFormatContext *s, int64_t size,
AVStream **stream)
+{
+    int64_t start, end, cur;
+    AVIOContext *pb = s->pb;
+
+    start = avio_tell(pb);
+    end = start + size;
+
+    while ( (cur = avio_tell(pb)) < end) {
+        unsigned int chunk_code;
+        int64_t chunk_size;
+        char *key, *value;
+
+        chunk_size = next_tag(pb, &chunk_code);
+        if (chunk_size > end || end - chunk_size < cur) {
+            av_log(s, AV_LOG_ERROR, "too big INFO subchunk\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        key = av_malloc(4 + 1);
+        value = av_malloc(chunk_size + 1);
+        if (!key || !value) {
+            av_log(s, AV_LOG_ERROR, "out of memory, unable to read
INFO tag\n");
+            return AVERROR(ENOMEM);
+        }
+
+#ifdef HAVE_BIG_ENDIAN
+        chunk_code = av_bswap32(chunk_code);
+#endif
+        snprintf( key, 5, "%4.4s", &chunk_code );
+
+        if (avio_read(pb, value, chunk_size) != chunk_size) {
+            av_freep(key);
+            av_freep(value);
+            av_log(s, AV_LOG_ERROR, "premature end of file while
reading INFO tag\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        key[4] = '\0';
+        value[chunk_size] = '\0';
+
+        av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
+    }
+
+    ff_metadata_conv_ctx(s, NULL, wav_info_tag_conv);
+
+    return 0;
+}
+
 /* wav input */
 static int wav_read_header(AVFormatContext *s,
                            AVFormatParameters *ap)
@@ -385,7 +445,7 @@ static int wav_read_header(AVFormatContext *s,
     int64_t size, av_uninit(data_size);
     int64_t sample_count=0;
     int rf64;
-    unsigned int tag;
+    unsigned int tag, list_type;
     AVIOContext *pb = s->pb;
     AVStream *st;
     WAVContext *wav = s->priv_data;
@@ -467,6 +527,14 @@ static int wav_read_header(AVFormatContext *s,
             if ((ret = wav_parse_bext_tag(s, size)) < 0)
                 return ret;
             break;
+        case MKTAG('L', 'I', 'S', 'T'):
+            list_type = avio_rl32(pb);
+            switch (list_type) {
+            case MKTAG('I', 'N', 'F', 'O'):
+                if ((ret = wav_parse_info_tags(s, size - 4, &st)) < 0)
+                    return ret;
+            }
+            break;
         }

         /* seek to next tag unless we know that we'll run into EOF */
-- 
1.7.5.4


More information about the libav-devel mailing list