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