changeset 5633:5d3ac5652047 libavformat

Add AVI metadata conversion table. Patch by Anton Khirnov (gmail{wyskas}).
author jai_menon
date Sat, 06 Feb 2010 12:32:44 +0000
parents 4c2b20d0233c
children b280788e1936
files Makefile avi.c avi.h avidec.c avienc.c
diffstat 5 files changed, 90 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Feb 05 23:03:32 2010 +0000
+++ b/Makefile	Sat Feb 06 12:32:44 2010 +0000
@@ -35,8 +35,8 @@
 OBJS-$(CONFIG_ASS_MUXER)                 += assenc.o
 OBJS-$(CONFIG_AU_DEMUXER)                += au.o raw.o
 OBJS-$(CONFIG_AU_MUXER)                  += au.o
-OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o riff.o
-OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o riff.o
+OBJS-$(CONFIG_AVI_DEMUXER)               += avidec.o riff.o avi.o
+OBJS-$(CONFIG_AVI_MUXER)                 += avienc.o riff.o avi.o
 OBJS-$(CONFIG_AVISYNTH)                  += avisynth.o
 OBJS-$(CONFIG_AVM2_MUXER)                += swfenc.o
 OBJS-$(CONFIG_AVS_DEMUXER)               += avs.o vocdec.o voc.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/avi.c	Sat Feb 06 12:32:44 2010 +0000
@@ -0,0 +1,45 @@
+/*
+ * AVI common data
+ * Copyright (c) 2010 Anton Khirnov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; 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}
+};
--- a/avi.h	Fri Feb 05 23:03:32 2010 +0000
+++ b/avi.h	Sat Feb 06 12:32:44 2010 +0000
@@ -21,6 +21,8 @@
 #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
@@ -34,4 +36,11 @@
 /* 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 */
--- a/avidec.c	Fri Feb 05 23:03:32 2010 +0000
+++ b/avidec.c	Sat Feb 06 12:32:44 2010 +0000
@@ -227,10 +227,10 @@
     }
 }
 
-static int avi_read_tag(AVFormatContext *s, AVStream *st, const char *key, unsigned int size)
+static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t size)
 {
     ByteIOContext *pb = s->pb;
-    char *value;
+    char key[5] = {0}, *value;
 
     size += (size & 1);
 
@@ -242,6 +242,8 @@
     get_buffer(pb, value, size);
     value[size]=0;
 
+    AV_WL32(key, tag);
+
     if(st)
         return av_metadata_set2(&st->metadata, key, value,
                                     AV_METADATA_DONT_STRDUP_VAL);
@@ -250,6 +252,15 @@
                                   AV_METADATA_DONT_STRDUP_VAL);
 }
 
+static void avi_read_info(AVFormatContext *s, uint64_t end)
+{
+    while (url_ftell(s->pb) < end) {
+        uint32_t tag  = get_le32(s->pb);
+        uint32_t size = get_le32(s->pb);
+        avi_read_tag(s, NULL, tag, size);
+    }
+}
+
 static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap)
 {
     AVIContext *avi = s->priv_data;
@@ -301,6 +312,9 @@
                 dprintf(NULL, "movi end=%"PRIx64"\n", avi->movi_end);
                 goto end_of_header;
             }
+            else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
+                avi_read_info(s, list_end);
+
             break;
         case MKTAG('d', 'm', 'l', 'h'):
             avi->is_odml = 1;
@@ -606,30 +620,9 @@
             }
             url_fseek(pb, size, SEEK_CUR);
             break;
-        case MKTAG('I', 'N', 'A', 'M'):
-            avi_read_tag(s, NULL, "Title", size);
-            break;
-        case MKTAG('I', 'A', 'R', 'T'):
-            avi_read_tag(s, NULL, "Artist", size);
-            break;
-        case MKTAG('I', 'C', 'O', 'P'):
-            avi_read_tag(s, NULL, "Copyright", size);
-            break;
-        case MKTAG('I', 'C', 'M', 'T'):
-            avi_read_tag(s, NULL, "Comment", size);
-            break;
-        case MKTAG('I', 'G', 'N', 'R'):
-            avi_read_tag(s, NULL, "Genre", size);
-            break;
-        case MKTAG('I', 'P', 'R', 'D'):
-            avi_read_tag(s, NULL, "Album", size);
-            break;
-        case MKTAG('I', 'P', 'R', 'T'):
-            avi_read_tag(s, NULL, "Track", size);
-            break;
         case MKTAG('s', 't', 'r', 'n'):
             if(s->nb_streams){
-                avi_read_tag(s, s->streams[s->nb_streams-1], "Title", size);
+                avi_read_tag(s, s->streams[s->nb_streams-1], tag, size);
                 break;
             }
         default:
@@ -1190,4 +1183,5 @@
     avi_read_packet,
     avi_read_close,
     avi_read_seek,
+    .metadata_conv = ff_avi_metadata_conv,
 };
--- a/avienc.c	Fri Feb 05 23:03:32 2010 +0000
+++ b/avienc.c	Sat Feb 06 12:32:44 2010 +0000
@@ -21,6 +21,7 @@
 #include "avformat.h"
 #include "avi.h"
 #include "riff.h"
+#include "libavutil/intreadwrite.h"
 
 /*
  * TODO:
@@ -114,22 +115,6 @@
     }
 }
 
-static void avi_write_info_tag2(AVFormatContext *s, AVStream *st, const char *fourcc, const char *key1, const char *key2)
-{
-    AVMetadataTag *tag;
-    if(st){
-        tag= av_metadata_get(st->metadata, key1, NULL, 0);
-        if(!tag && key2)
-            tag= av_metadata_get(st->metadata, key2, NULL, 0);
-    }else{
-        tag= av_metadata_get(s->metadata, key1, NULL, 0);
-    if(!tag && key2)
-        tag= av_metadata_get(s->metadata, key2, NULL, 0);
-    }
-    if(tag)
-        avi_write_info_tag(s->pb, fourcc, tag->value);
-}
-
 static int avi_write_counters(AVFormatContext* s, int riff_id)
 {
     ByteIOContext *pb = s->pb;
@@ -171,6 +156,7 @@
     int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
     AVCodecContext *stream, *video_enc;
     int64_t list1, list2, strh, strf;
+    AVMetadataTag *t = NULL;
 
     for(n=0;n<s->nb_streams;n++) {
         s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream));
@@ -301,7 +287,15 @@
             return -1;
         }
         ff_end_tag(pb, strf);
-        avi_write_info_tag2(s, s->streams[i], "strn", "Title", "Description");
+        if ((t = av_metadata_get(s->streams[i]->metadata, "strn", NULL, 0))) {
+            avi_write_info_tag(s->pb, t->key, t->value);
+            t = NULL;
+        }
+        //FIXME a limitation of metadata conversion system
+        else if ((t = av_metadata_get(s->streams[i]->metadata, "INAM", NULL, 0))) {
+            avi_write_info_tag(s->pb, "strn", t->value);
+            t = NULL;
+        }
       }
 
         if (!url_is_streamed(pb)) {
@@ -378,13 +372,10 @@
 
     list2 = ff_start_tag(pb, "LIST");
     put_tag(pb, "INFO");
-    avi_write_info_tag2(s, NULL, "INAM", "Title", NULL);
-    avi_write_info_tag2(s, NULL, "IART", "Artist", "Author");
-    avi_write_info_tag2(s, NULL, "ICOP", "Copyright", NULL);
-    avi_write_info_tag2(s, NULL, "ICMT", "Comment", NULL);
-    avi_write_info_tag2(s, NULL, "IPRD", "Album", NULL);
-    avi_write_info_tag2(s, NULL, "IGNR", "Genre", NULL);
-    avi_write_info_tag2(s, NULL, "IPRT", "Track", NULL);
+    for (i = 0; *ff_avi_tags[i]; i++) {
+        if ((t = av_metadata_get(s->metadata, ff_avi_tags[i], NULL, AV_METADATA_MATCH_CASE)))
+            avi_write_info_tag(s->pb, t->key, t->value);
+    }
     if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT))
         avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT);
     ff_end_tag(pb, list2);
@@ -655,4 +646,5 @@
     avi_write_trailer,
     .codec_tag= (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0},
     .flags= AVFMT_VARIABLE_FPS,
+    .metadata_conv = ff_avi_metadata_conv,
 };