[FFmpeg-cvslog] Generalize RIFF INFO tag support; support reading INFO tag in wav

Victor Vasiliev git at videolan.org
Mon Nov 28 01:14:15 CET 2011


ffmpeg | branch: master | Victor Vasiliev <vasilvv at gmail.com> | Fri Nov 25 00:02:43 2011 +0400| [12bc20502ad9124b4d922985b82edc45aa4064cb] | committer: Ronald S. Bultje

Generalize RIFF INFO tag support; support reading INFO tag in wav

Signed-off-by: Ronald S. Bultje <rsbultje at gmail.com>

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

 libavformat/Makefile |    4 +-
 libavformat/avi.c    |   45 ---------------------------------
 libavformat/avi.h    |    9 ------
 libavformat/avidec.c |   19 ++++++--------
 libavformat/avienc.c |    6 ++--
 libavformat/riff.c   |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/riff.h   |    6 ++++
 libavformat/wav.c    |   18 +++++++++++--
 8 files changed, 102 insertions(+), 73 deletions(-)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3419148..64b2d82 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -39,8 +39,8 @@ OBJS-$(CONFIG_ASS_DEMUXER)               += assdec.o
 OBJS-$(CONFIG_ASS_MUXER)                 += assenc.o
 OBJS-$(CONFIG_AU_DEMUXER)                += au.o pcm.o
 OBJS-$(CONFIG_AU_MUXER)                  += au.o
-OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o riff.o avi.o
-OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o riff.o avi.o
+OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o riff.o
+OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o riff.o
 OBJS-$(CONFIG_AVISYNTH)                  += avisynth.o
 OBJS-$(CONFIG_AVM2_MUXER)                += swfenc.o
 OBJS-$(CONFIG_AVS_DEMUXER)               += avs.o vocdec.o voc.o
diff --git a/libavformat/avi.c b/libavformat/avi.c
deleted file mode 100644
index 9f36b27..0000000
--- a/libavformat/avi.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * AVI common data
- * Copyright (c) 2010 Anton Khirnov
- *
- * This file is part of Libav.
- *
- * Libav is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * Libav is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "avi.h"
-
-const AVMetadataConv ff_avi_metadata_conv[] = {
-    { "IART", "artist"    },
-    { "ICMT", "comment"   },
-    { "ICOP", "copyright" },
-    { "ICRD", "date"      },
-    { "IGNR", "genre"     },
-    { "ILNG", "language"  },
-    { "INAM", "title"     },
-    { "IPRD", "album"     },
-    { "IPRT", "track"     },
-    { "ISFT", "encoder"   },
-    { "ITCH", "encoded_by"},
-    { "strn", "title"     },
-    { 0 },
-};
-
-const char ff_avi_tags[][5] = {
-    "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
-    "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
-    "IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH",
-    {0}
-};
diff --git a/libavformat/avi.h b/libavformat/avi.h
index 05e0297..e05db9c 100644
--- a/libavformat/avi.h
+++ b/libavformat/avi.h
@@ -21,8 +21,6 @@
 #ifndef AVFORMAT_AVI_H
 #define AVFORMAT_AVI_H
 
-#include "metadata.h"
-
 #define AVIF_HASINDEX           0x00000010        // Index at end of file?
 #define AVIF_MUSTUSEINDEX       0x00000020
 #define AVIF_ISINTERLEAVED      0x00000100
@@ -37,11 +35,4 @@
 /* index flags */
 #define AVIIF_INDEX             0x10
 
-extern const AVMetadataConv ff_avi_metadata_conv[];
-
-/**
- * A list of AVI info tags.
- */
-extern const char ff_avi_tags[][5];
-
 #endif /* AVFORMAT_AVI_H */
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 0cd84c0..ee42655 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -79,6 +79,11 @@ static const char avi_headers[][8] = {
     { 0 }
 };
 
+static const AVMetadataConv avi_metadata_conv[] = {
+    { "strn", "title" },
+    { 0 },
+};
+
 static int avi_load_index(AVFormatContext *s);
 static int guess_ni_flag(AVFormatContext *s);
 
@@ -261,15 +266,6 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t
                             AV_DICT_DONT_STRDUP_VAL);
 }
 
-static void avi_read_info(AVFormatContext *s, uint64_t end)
-{
-    while (avio_tell(s->pb) < end) {
-        uint32_t tag  = avio_rl32(s->pb);
-        uint32_t size = avio_rl32(s->pb);
-        avi_read_tag(s, NULL, tag, size);
-    }
-}
-
 static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
@@ -380,7 +376,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
                 goto end_of_header;
             }
             else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
-                avi_read_info(s, list_end);
+                ff_read_riff_info(s, size - 4);
             else if (tag1 == MKTAG('n', 'c', 'd', 't'))
                 avi_read_nikon(s, list_end);
 
@@ -745,7 +741,8 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
         clean_index(s);
     }
 
-    ff_metadata_conv_ctx(s, NULL, ff_avi_metadata_conv);
+    ff_metadata_conv_ctx(s, NULL, avi_metadata_conv);
+    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
 
     return 0;
 }
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index cf2e1d6..b4521cd 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -378,9 +378,9 @@ static int avi_write_header(AVFormatContext *s)
 
     list2 = ff_start_tag(pb, "LIST");
     ffio_wfourcc(pb, "INFO");
-    ff_metadata_conv(&s->metadata, ff_avi_metadata_conv, NULL);
-    for (i = 0; *ff_avi_tags[i]; i++) {
-        if ((t = av_dict_get(s->metadata, ff_avi_tags[i], NULL, AV_DICT_MATCH_CASE)))
+    ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL);
+    for (i = 0; *ff_riff_tags[i]; i++) {
+        if ((t = av_dict_get(s->metadata, ff_riff_tags[i], NULL, AV_DICT_MATCH_CASE)))
             avi_write_info_tag(s->pb, t->key, t->value);
     }
     ff_end_tag(pb, list2);
diff --git a/libavformat/riff.c b/libavformat/riff.c
index 29c3803..2a989cd 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -342,6 +342,28 @@ const AVCodecTag ff_codec_wav_tags[] = {
     { CODEC_ID_NONE,      0 },
 };
 
+const AVMetadataConv ff_riff_info_conv[] = {
+    { "IART", "artist"    },
+    { "ICMT", "comment"   },
+    { "ICOP", "copyright" },
+    { "ICRD", "date"      },
+    { "IGNR", "genre"     },
+    { "ILNG", "language"  },
+    { "INAM", "title"     },
+    { "IPRD", "album"     },
+    { "IPRT", "track"     },
+    { "ISFT", "encoder"   },
+    { "ITCH", "encoded_by"},
+    { 0 },
+};
+
+const char ff_riff_tags[][5] = {
+    "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
+    "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
+    "IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH",
+    {0}
+};
+
 #if CONFIG_MUXERS
 int64_t ff_start_tag(AVIOContext *pb, const char *tag)
 {
@@ -613,3 +635,49 @@ void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssiz
     *au_scale /= gcd;
     *au_rate /= gcd;
 }
+
+int ff_read_riff_info(AVFormatContext *s, int64_t size)
+{
+    int64_t start, end, cur;
+    AVIOContext *pb = s->pb;
+
+    start = avio_tell(pb);
+    end = start + size;
+
+    while ((cur = avio_tell(pb)) >= 0 && cur <= end - 8 /* = tag + size */) {
+        uint32_t chunk_code;
+        int64_t chunk_size;
+        char key[5] = {0};
+        char *value;
+
+        chunk_code = avio_rl32(pb);
+        chunk_size = avio_rl32(pb);
+        if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) {
+            av_log(s, AV_LOG_ERROR, "too big INFO subchunk\n");
+            return AVERROR_INVALIDDATA;
+        }
+
+        chunk_size += (chunk_size & 1);
+
+        value = av_malloc(chunk_size + 1);
+        if (!value) {
+            av_log(s, AV_LOG_ERROR, "out of memory, unable to read INFO tag\n");
+            return AVERROR(ENOMEM);
+        }
+
+        AV_WL32(key, 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;
+        }
+
+        value[chunk_size] = 0;
+
+        av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
+    }
+
+    return 0;
+}
diff --git a/libavformat/riff.h b/libavformat/riff.h
index a2fa8b7..3bd309f 100644
--- a/libavformat/riff.h
+++ b/libavformat/riff.h
@@ -31,6 +31,10 @@
 #include "libavcodec/avcodec.h"
 #include "avio.h"
 #include "internal.h"
+#include "metadata.h"
+
+extern const AVMetadataConv ff_riff_info_conv[];
+extern const char ff_riff_tags[][5];
 
 int64_t ff_start_tag(AVIOContext *pb, const char *tag);
 void ff_end_tag(AVIOContext *pb, int64_t start);
@@ -54,4 +58,6 @@ unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum CodecID id);
 enum CodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag);
 void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, int *au_ssize, int *au_scale);
 
+int ff_read_riff_info(AVFormatContext *s, int64_t size);
+
 #endif /* AVFORMAT_RIFF_H */
diff --git a/libavformat/wav.c b/libavformat/wav.c
index 298880d..3e03037 100644
--- a/libavformat/wav.c
+++ b/libavformat/wav.c
@@ -33,7 +33,6 @@
 #include "pcm.h"
 #include "riff.h"
 #include "avio.h"
-#include "avio_internal.h"
 #include "metadata.h"
 
 typedef struct {
@@ -224,7 +223,7 @@ AVOutputFormat ff_wav_muxer = {
 
 #if CONFIG_WAV_DEMUXER
 
-static int64_t next_tag(AVIOContext *pb, unsigned int *tag)
+static int64_t next_tag(AVIOContext *pb, uint32_t *tag)
 {
     *tag = avio_rl32(pb);
     return avio_rl32(pb);
@@ -385,7 +384,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;
+    uint32_t tag, list_type;
     AVIOContext *pb = s->pb;
     AVStream *st;
     WAVContext *wav = s->priv_data;
@@ -467,6 +466,18 @@ 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);
+            if (size <= 4) {
+                av_log(s, AV_LOG_ERROR, "too short LIST");
+                return AVERROR_INVALIDDATA;
+            }
+            switch (list_type) {
+            case MKTAG('I', 'N', 'F', 'O'):
+                if ((ret = ff_read_riff_info(s, size - 4)) < 0)
+                    return ret;
+            }
+            break;
         }
 
         /* seek to next tag unless we know that we'll run into EOF */
@@ -489,6 +500,7 @@ break_loop:
         st->duration = sample_count;
 
     ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
+    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);
 
     return 0;
 }



More information about the ffmpeg-cvslog mailing list