Browse code

id3v2enc: add a function for writing attached pictures.

Unused so far.

Anton Khirnov authored on 2012/02/28 06:51:28
Showing 2 changed files
... ...
@@ -108,6 +108,11 @@ void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
108 108
 int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3);
109 109
 
110 110
 /**
111
+ * Write an attached picture from pkt into an ID3v2 tag.
112
+ */
113
+int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt);
114
+
115
+/**
111 116
  * Finalize an opened ID3v2 tag.
112 117
  */
113 118
 void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb);
... ...
@@ -19,6 +19,7 @@
19 19
  */
20 20
 
21 21
 #include <stdint.h>
22
+#include <string.h>
22 23
 
23 24
 #include "libavutil/dict.h"
24 25
 #include "libavutil/intreadwrite.h"
... ...
@@ -40,6 +41,20 @@ static int string_is_ascii(const uint8_t *str)
40 40
     return !*str;
41 41
 }
42 42
 
43
+static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str,
44
+                               enum ID3v2Encoding enc)
45
+{
46
+    int (*put)(AVIOContext*, const char*);
47
+
48
+    if (enc == ID3v2_ENCODING_UTF16BOM) {
49
+        avio_wl16(pb, 0xFEFF);      /* BOM */
50
+        put = avio_put_str16le;
51
+    } else
52
+        put = avio_put_str;
53
+
54
+    put(pb, str);
55
+}
56
+
43 57
 /**
44 58
  * Write a text frame with one (normal frames) or two (TXXX frames) strings
45 59
  * according to encoding (only UTF-8 or UTF-16+BOM supported).
... ...
@@ -50,7 +65,6 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *
50 50
 {
51 51
     int len;
52 52
     uint8_t *pb;
53
-    int (*put)(AVIOContext*, const char*);
54 53
     AVIOContext *dyn_buf;
55 54
     if (avio_open_dyn_buf(&dyn_buf) < 0)
56 55
         return AVERROR(ENOMEM);
... ...
@@ -62,15 +76,9 @@ static int id3v2_put_ttag(ID3v2EncContext *id3, AVIOContext *avioc, const char *
62 62
         enc = ID3v2_ENCODING_ISO8859;
63 63
 
64 64
     avio_w8(dyn_buf, enc);
65
-    if (enc == ID3v2_ENCODING_UTF16BOM) {
66
-        avio_wl16(dyn_buf, 0xFEFF);      /* BOM */
67
-        put = avio_put_str16le;
68
-    } else
69
-        put = avio_put_str;
70
-
71
-    put(dyn_buf, str1);
65
+    id3v2_encode_string(dyn_buf, str1, enc);
72 66
     if (str2)
73
-        put(dyn_buf, str2);
67
+        id3v2_encode_string(dyn_buf, str2, enc);
74 68
     len = avio_close_dyn_buf(dyn_buf, &pb);
75 69
 
76 70
     avio_wb32(avioc, tag);
... ...
@@ -147,6 +155,71 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
147 147
     return 0;
148 148
 }
149 149
 
150
+int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
151
+{
152
+    AVStream *st = s->streams[pkt->stream_index];
153
+    AVDictionaryEntry *e;
154
+
155
+    AVIOContext *dyn_buf;
156
+    uint8_t     *buf;
157
+    const CodecMime *mime = ff_id3v2_mime_tags;
158
+    const char  *mimetype = NULL, *desc = "";
159
+    int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
160
+                                  ID3v2_ENCODING_UTF8;
161
+    int i, len, type = 0;
162
+
163
+    /* get the mimetype*/
164
+    while (mime->id != CODEC_ID_NONE) {
165
+        if (mime->id == st->codec->codec_id) {
166
+            mimetype = mime->str;
167
+            break;
168
+        }
169
+        mime++;
170
+    }
171
+    if (!mimetype) {
172
+        av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
173
+               "write an attached picture.\n", st->index);
174
+        return AVERROR(EINVAL);
175
+    }
176
+
177
+    /* get the picture type */
178
+    e = av_dict_get(st->metadata, "comment", NULL, 0);
179
+    for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
180
+        if (strstr(ff_id3v2_picture_types[i], e->value) == ff_id3v2_picture_types[i]) {
181
+            type = i;
182
+            break;
183
+        }
184
+    }
185
+
186
+    /* get the description */
187
+    if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
188
+        desc = e->value;
189
+
190
+    /* start writing */
191
+    if (avio_open_dyn_buf(&dyn_buf) < 0)
192
+        return AVERROR(ENOMEM);
193
+
194
+    avio_w8(dyn_buf, enc);
195
+    avio_put_str(dyn_buf, mimetype);
196
+    avio_w8(dyn_buf, type);
197
+    id3v2_encode_string(dyn_buf, desc, enc);
198
+    avio_write(dyn_buf, pkt->data, pkt->size);
199
+    len = avio_close_dyn_buf(dyn_buf, &buf);
200
+
201
+    avio_wb32(s->pb, MKBETAG('A', 'P', 'I', 'C'));
202
+    if (id3->version == 3)
203
+        avio_wb32(s->pb, len);
204
+    else
205
+        id3v2_put_size(s->pb, len);
206
+    avio_wb16(s->pb, 0);
207
+    avio_write(s->pb, buf, len);
208
+    av_freep(&buf);
209
+
210
+    id3->len += len + ID3v2_HEADER_SIZE;
211
+
212
+    return 0;
213
+}
214
+
150 215
 void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb)
151 216
 {
152 217
     int64_t cur_pos = avio_tell(pb);