[FFmpeg-devel] [PATCH] lavf: Make id3v1_create_tag a lavf internal function

James Almer jamrial at gmail.com
Sat Jul 13 20:37:51 CEST 2013


There are more containers than just mp3 with support for id3v1,
and we currently have muxer for at least one of them

Signed-off-by: James Almer <jamrial at gmail.com>
---
 libavformat/Makefile   |  3 ++-
 libavformat/id3v1.h    |  6 +++++
 libavformat/id3v1enc.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
 libavformat/mp3enc.c   | 52 ++++-------------------------------
 4 files changed, 86 insertions(+), 48 deletions(-)
 create mode 100644 libavformat/id3v1enc.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index cc4a4cb..2c59b1d 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -215,7 +215,8 @@ OBJS-$(CONFIG_MOV_MUXER)                 += movenc.o isom.o avc.o \
                                             movenchint.o mov_chan.o rtp.o
 OBJS-$(CONFIG_MP2_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
 OBJS-$(CONFIG_MP3_DEMUXER)               += mp3dec.o
-OBJS-$(CONFIG_MP3_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
+OBJS-$(CONFIG_MP3_MUXER)                 += mp3enc.o rawenc.o id3v1enc.o \
+                                            id3v2enc.o
 OBJS-$(CONFIG_MPC_DEMUXER)               += mpc.o apetag.o img2.o
 OBJS-$(CONFIG_MPC8_DEMUXER)              += mpc8.o apetag.o img2.o
 OBJS-$(CONFIG_MPEG1SYSTEM_MUXER)         += mpegenc.o
diff --git a/libavformat/id3v1.h b/libavformat/id3v1.h
index d5dca35..daf5315 100644
--- a/libavformat/id3v1.h
+++ b/libavformat/id3v1.h
@@ -23,6 +23,7 @@
 #define AVFORMAT_ID3V1_H
 
 #include "avformat.h"
+#include "metadata.h"
 
 #define ID3v1_TAG_SIZE 128
 
@@ -38,4 +39,9 @@ extern const char * const ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1];
  */
 void ff_id3v1_read(AVFormatContext *s);
 
+/**
+ * Write an ID3v1 tag
+ */
+int ff_id3v1_write(AVFormatContext *s);
+
 #endif /* AVFORMAT_ID3V1_H */
diff --git a/libavformat/id3v1enc.c b/libavformat/id3v1enc.c
new file mode 100644
index 0000000..9b7b6a7
--- /dev/null
+++ b/libavformat/id3v1enc.c
@@ -0,0 +1,73 @@
+/*
+ * ID3v1 header writer
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * 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 "libavutil/avstring.h"
+#include "libavutil/dict.h"
+#include "id3v1.h"
+
+static int set_string(AVFormatContext *s, const char *key,
+                      uint8_t *buf, int buf_size)
+{
+    AVDictionaryEntry *tag;
+    if ((tag = av_dict_get(s->metadata, key, NULL, 0)))
+        av_strlcpy(buf, tag->value, buf_size);
+    return !!tag;
+}
+
+int ff_id3v1_write(AVFormatContext *s)
+{
+    AVDictionaryEntry *tag;
+    uint8_t buf[ID3v1_TAG_SIZE];
+    int i, count = 0;
+
+    memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
+    buf[0] = 'T';
+    buf[1] = 'A';
+    buf[2] = 'G';
+    /* we knowingly overspecify each tag length by one byte to compensate for the mandatory null byte added by av_strlcpy */
+    count += set_string(s, "title",   buf +  3, 30 + 1);
+    count += set_string(s, "artist",  buf + 33, 30 + 1);
+    count += set_string(s, "album",   buf + 63, 30 + 1);
+    count += set_string(s, "date",    buf + 93,  4 + 1);
+    count += set_string(s, "comment", buf + 97, 30 + 1);
+    if ((tag = av_dict_get(s->metadata, "track", NULL, 0))) {
+        buf[125] = 0;
+        buf[126] = atoi(tag->value);
+        count++;
+    }
+    buf[127] = 0xFF; /* default to unknown genre */
+    if ((tag = av_dict_get(s->metadata, "genre", NULL, 0))) {
+        for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
+            if (!av_strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
+                buf[127] = i;
+                count++;
+                break;
+            }
+        }
+    }
+    if (!count)
+        return -1;
+
+    avio_write(s->pb, buf, ID3v1_TAG_SIZE);
+
+    return 0;    
+}
+
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index ee0956e..b2b5fad 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -24,7 +24,6 @@
 #include "id3v1.h"
 #include "id3v2.h"
 #include "rawenc.h"
-#include "libavutil/avstring.h"
 #include "libavcodec/mpegaudio.h"
 #include "libavcodec/mpegaudiodata.h"
 #include "libavcodec/mpegaudiodecheader.h"
@@ -34,51 +33,8 @@
 #include "libavcodec/mpegaudiodata.h"
 #include "libavcodec/mpegaudiodecheader.h"
 #include "libavformat/avio_internal.h"
-#include "libavutil/dict.h"
 #include "libavutil/avassert.h"
 
-static int id3v1_set_string(AVFormatContext *s, const char *key,
-                            uint8_t *buf, int buf_size)
-{
-    AVDictionaryEntry *tag;
-    if ((tag = av_dict_get(s->metadata, key, NULL, 0)))
-        av_strlcpy(buf, tag->value, buf_size);
-    return !!tag;
-}
-
-static int id3v1_create_tag(AVFormatContext *s, uint8_t *buf)
-{
-    AVDictionaryEntry *tag;
-    int i, count = 0;
-
-    memset(buf, 0, ID3v1_TAG_SIZE); /* fail safe */
-    buf[0] = 'T';
-    buf[1] = 'A';
-    buf[2] = 'G';
-    /* we knowingly overspecify each tag length by one byte to compensate for the mandatory null byte added by av_strlcpy */
-    count += id3v1_set_string(s, "TIT2",    buf +  3, 30 + 1);       //title
-    count += id3v1_set_string(s, "TPE1",    buf + 33, 30 + 1);       //author|artist
-    count += id3v1_set_string(s, "TALB",    buf + 63, 30 + 1);       //album
-    count += id3v1_set_string(s, "TDRL",    buf + 93,  4 + 1);       //date
-    count += id3v1_set_string(s, "comment", buf + 97, 30 + 1);
-    if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track
-        buf[125] = 0;
-        buf[126] = atoi(tag->value);
-        count++;
-    }
-    buf[127] = 0xFF; /* default to unknown genre */
-    if ((tag = av_dict_get(s->metadata, "TCON", NULL, 0))) { //genre
-        for(i = 0; i <= ID3v1_GENRE_MAX; i++) {
-            if (!av_strcasecmp(tag->value, ff_id3v1_genre_str[i])) {
-                buf[127] = i;
-                count++;
-                break;
-            }
-        }
-    }
-    return count;
-}
-
 #define XING_NUM_BAGS 400
 #define XING_TOC_SIZE 100
 // maximum size of the xing frame: offset/Xing/flags/frames/size/TOC
@@ -349,7 +305,6 @@ static void mp3_update_xing(AVFormatContext *s)
 
 static int mp3_write_trailer(struct AVFormatContext *s)
 {
-    uint8_t buf[ID3v1_TAG_SIZE];
     MP3Context *mp3 = s->priv_data;
 
     if (mp3->pics_to_write) {
@@ -359,8 +314,11 @@ static int mp3_write_trailer(struct AVFormatContext *s)
     }
 
     /* write the id3v1 tag */
-    if (mp3->write_id3v1 && id3v1_create_tag(s, buf) > 0) {
-        avio_write(s->pb, buf, ID3v1_TAG_SIZE);
+    if (mp3->write_id3v1) {
+        /* recover the generic tags */
+        ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
+        ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
+        ff_id3v1_write(s);
     }
 
     if (mp3->xing_offset)
-- 
1.8.1.5



More information about the ffmpeg-devel mailing list