Unused so far.
Anton Khirnov authored on 2012/02/28 06:51:28... | ... |
@@ -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); |