id3v2: split tables for various ID3v2 versions
authorAnton Khirnov <anton@khirnov.net>
Fri, 21 Jan 2011 19:54:34 +0000 (19:54 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 23 Jan 2011 18:32:07 +0000 (19:32 +0100)
This is needed for upcoming ID3v2.3 muxing support.

Signed-off-by: Janne Grunau <janne-ffmpeg@jannau.net>
(cherry picked from commit cb6bc57681b2ec5232e64db176f41fb2517de146)

libavformat/id3v2.c
libavformat/id3v2.h
libavformat/mp3enc.c

index 62eee15..7cedf6e 100644 (file)
@@ -273,46 +273,67 @@ void ff_id3v2_read(AVFormatContext *s, const char *magic)
             url_fseek(s->pb, off, SEEK_SET);
         }
     } while (found_header);
-    ff_metadata_conv(&s->metadata, NULL, ff_id3v2_metadata_conv);
+    ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
+    ff_metadata_conv(&s->metadata, NULL, ff_id3v2_2_metadata_conv);
+    ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
 }
 
-const AVMetadataConv ff_id3v2_metadata_conv[] = {
+const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
     { "TALB", "album"},
-    { "TAL",  "album"},
     { "TCOM", "composer"},
     { "TCON", "genre"},
-    { "TCO",  "genre"},
     { "TCOP", "copyright"},
-    { "TDRL", "date"},
-    { "TDRC", "date"},
-    { "TDEN", "creation_time"},
     { "TENC", "encoded_by"},
-    { "TEN",  "encoded_by"},
     { "TIT2", "title"},
-    { "TT2",  "title"},
     { "TLAN", "language"},
     { "TPE1", "artist"},
-    { "TP1",  "artist"},
     { "TPE2", "album_artist"},
-    { "TP2",  "album_artist"},
     { "TPE3", "performer"},
-    { "TP3",  "performer"},
     { "TPOS", "disc"},
     { "TPUB", "publisher"},
     { "TRCK", "track"},
-    { "TRK",  "track"},
+    { "TSSE", "encoder"},
+    { 0 }
+};
+
+const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
+    { "TDRL", "date"},
+    { "TDRC", "date"},
+    { "TDEN", "creation_time"},
     { "TSOA", "album-sort"},
     { "TSOP", "artist-sort"},
     { "TSOT", "title-sort"},
-    { "TSSE", "encoder"},
     { 0 }
 };
 
+const AVMetadataConv ff_id3v2_2_metadata_conv[] = {
+    { "TAL",  "album"},
+    { "TCO",  "genre"},
+    { "TT2",  "title"},
+    { "TEN",  "encoded_by"},
+    { "TP1",  "artist"},
+    { "TP2",  "album_artist"},
+    { "TP3",  "performer"},
+    { "TRK",  "track"},
+    { 0 }
+};
+
+
 const char ff_id3v2_tags[][4] = {
-   "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDEN", "TDLY", "TDOR", "TDRC",
-   "TDRL", "TDTG", "TENC", "TEXT", "TFLT", "TIPL", "TIT1", "TIT2", "TIT3",
-   "TKEY", "TLAN", "TLEN", "TMCL", "TMED", "TMOO", "TOAL", "TOFN", "TOLY",
-   "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", "TPE4", "TPOS", "TPRO", "TPUB",
-   "TRCK", "TRSN", "TRSO", "TSOA", "TSOP", "TSOT", "TSRC", "TSSE", "TSST",
+   "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
+   "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
+   "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
+   "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
+   { 0 },
+};
+
+const char ff_id3v2_4_tags[][4] = {
+   "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
+   "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
+   { 0 },
+};
+
+const char ff_id3v2_3_tags[][4] = {
+   "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
    { 0 },
 };
index c2e1add..e429001 100644 (file)
@@ -65,12 +65,25 @@ int ff_id3v2_tag_len(const uint8_t *buf);
  */
 void ff_id3v2_read(AVFormatContext *s, const char *magic);
 
-extern const AVMetadataConv ff_id3v2_metadata_conv[];
+extern const AVMetadataConv ff_id3v2_34_metadata_conv[];
+extern const AVMetadataConv ff_id3v2_4_metadata_conv[];
+extern const AVMetadataConv ff_id3v2_2_metadata_conv[];
 
 /**
- * A list of ID3v2.4 text information frames.
+ * A list of text information frames allowed in both ID3 v2.3 and v2.4
  * http://www.id3.org/id3v2.4.0-frames
+ * http://www.id3.org/id3v2.4.0-changes
  */
 extern const char ff_id3v2_tags[][4];
 
+/**
+ * ID3v2.4-only text information frames.
+ */
+extern const char ff_id3v2_4_tags[][4];
+
+/**
+ * ID3v2.3-only text information frames.
+ */
+extern const char ff_id3v2_3_tags[][4];
+
 #endif /* AVFORMAT_ID3V2_H */
index db180d6..f55e123 100644 (file)
@@ -148,6 +148,20 @@ AVOutputFormat mp2_muxer = {
 #endif
 
 #if CONFIG_MP3_MUXER
+static int id3v2_check_write_tag(AVFormatContext *s, AVMetadataTag *t, const char table[][4])
+{
+    uint32_t tag;
+    int i;
+
+    if (t->key[0] != 'T' || strlen(t->key) != 4)
+        return -1;
+    tag = AV_RB32(t->key);
+    for (i = 0; *table[i]; i++)
+        if (tag == AV_RB32(table[i]))
+            return id3v2_put_ttag(s, t->value, NULL, tag, ID3v2_ENCODING_UTF8);
+    return -1;
+}
+
 /**
  * Write an ID3v2.4 header at beginning of stream
  */
@@ -166,29 +180,25 @@ static int mp3_write_header(struct AVFormatContext *s)
     size_pos = url_ftell(s->pb);
     put_be32(s->pb, 0);
 
-    ff_metadata_conv(&s->metadata, ff_id3v2_metadata_conv, NULL);
+    ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL);
+    ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL);
     while ((t = av_metadata_get(s->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) {
-        uint32_t tag = 0;
         int ret;
 
-        if (t->key[0] == 'T' && strlen(t->key) == 4) {
-            int i;
-            for (i = 0; *ff_id3v2_tags[i]; i++)
-                if (AV_RB32(t->key) == AV_RB32(ff_id3v2_tags[i])) {
-                    tag = AV_RB32(t->key);
-                    if ((ret = id3v2_put_ttag(s, t->value, NULL, tag, ID3v2_ENCODING_UTF8)) < 0)
-                        return ret;
-                    totlen += ret;
-                    break;
-                }
+        if ((ret = id3v2_check_write_tag(s, t, ff_id3v2_tags)) > 0) {
+            totlen += ret;
+            continue;
         }
-
-        if (!tag) { /* unknown tag, write as TXXX frame */
-            tag = MKBETAG('T', 'X', 'X', 'X');
-            if ((ret = id3v2_put_ttag(s, t->key, t->value, tag, ID3v2_ENCODING_UTF8)) < 0)
-                return ret;
+        if ((ret = id3v2_check_write_tag(s, t, ff_id3v2_4_tags)) > 0) {
             totlen += ret;
+            continue;
         }
+
+        /* unknown tag, write as TXXX frame */
+        if ((ret = id3v2_put_ttag(s, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'),
+                                  ID3v2_ENCODING_UTF8)) < 0)
+            return ret;
+        totlen += ret;
     }
 
     cur_pos = url_ftell(s->pb);