948261ad9756315a43eb1dbbf67b487ab364c6fc
[ffmpeg.git] / libavformat / id3v2.c
1 /*
2  * ID3v2 header parser
3  * Copyright (c) 2003 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #include "id3v2.h"
23 #include "id3v1.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/intreadwrite.h"
26 #include "metadata.h"
27 #include "avio_internal.h"
28
29 int ff_id3v2_match(const uint8_t *buf, const char * magic)
30 {
31     return  buf[0]         == magic[0] &&
32             buf[1]         == magic[1] &&
33             buf[2]         == magic[2] &&
34             buf[3]         != 0xff &&
35             buf[4]         != 0xff &&
36            (buf[6] & 0x80) ==    0 &&
37            (buf[7] & 0x80) ==    0 &&
38            (buf[8] & 0x80) ==    0 &&
39            (buf[9] & 0x80) ==    0;
40 }
41
42 int ff_id3v2_tag_len(const uint8_t * buf)
43 {
44     int len = ((buf[6] & 0x7f) << 21) +
45               ((buf[7] & 0x7f) << 14) +
46               ((buf[8] & 0x7f) << 7) +
47                (buf[9] & 0x7f) +
48               ID3v2_HEADER_SIZE;
49     if (buf[5] & 0x10)
50         len += ID3v2_HEADER_SIZE;
51     return len;
52 }
53
54 static unsigned int get_size(AVIOContext *s, int len)
55 {
56     int v = 0;
57     while (len--)
58         v = (v << 7) + (avio_r8(s) & 0x7F);
59     return v;
60 }
61
62 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
63 {
64     char *q, dst[512];
65     const char *val = NULL;
66     int len, dstlen = sizeof(dst) - 1;
67     unsigned genre;
68     unsigned int (*get)(AVIOContext*) = avio_rb16;
69
70     dst[0] = 0;
71     if (taglen < 1)
72         return;
73
74     taglen--; /* account for encoding type byte */
75
76     switch (avio_r8(pb)) { /* encoding type */
77
78     case ID3v2_ENCODING_ISO8859:
79         q = dst;
80         while (taglen-- && q - dst < dstlen - 7) {
81             uint8_t tmp;
82             PUT_UTF8(avio_r8(pb), tmp, *q++ = tmp;)
83         }
84         *q = 0;
85         break;
86
87     case ID3v2_ENCODING_UTF16BOM:
88         taglen -= 2;
89         switch (avio_rb16(pb)) {
90         case 0xfffe:
91             get = avio_rl16;
92         case 0xfeff:
93             break;
94         default:
95             av_log(s, AV_LOG_ERROR, "Incorrect BOM value in tag %s.\n", key);
96             return;
97         }
98         // fall-through
99
100     case ID3v2_ENCODING_UTF16BE:
101         q = dst;
102         while (taglen > 1 && q - dst < dstlen - 7) {
103             uint32_t ch;
104             uint8_t tmp;
105
106             GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;)
107             PUT_UTF8(ch, tmp, *q++ = tmp;)
108         }
109         *q = 0;
110         break;
111
112     case ID3v2_ENCODING_UTF8:
113         len = FFMIN(taglen, dstlen);
114         avio_read(pb, dst, len);
115         dst[len] = 0;
116         break;
117     default:
118         av_log(s, AV_LOG_WARNING, "Unknown encoding in tag %s.\n", key);
119     }
120
121     if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
122         && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
123         && genre <= ID3v1_GENRE_MAX)
124         val = ff_id3v1_genre_str[genre];
125     else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
126         /* dst now contains two 0-terminated strings */
127         dst[dstlen] = 0;
128         len = strlen(dst);
129         key = dst;
130         val = dst + FFMIN(len + 1, dstlen);
131     }
132     else if (*dst)
133         val = dst;
134
135     if (val)
136         av_metadata_set2(&s->metadata, key, val, AV_METADATA_DONT_OVERWRITE);
137 }
138
139 static int is_number(const char *str)
140 {
141     while (*str >= '0' && *str <= '9') str++;
142     return !*str;
143 }
144
145 static AVMetadataTag* get_date_tag(AVMetadata *m, const char *tag)
146 {
147     AVMetadataTag *t;
148     if ((t = av_metadata_get(m, tag, NULL, AV_METADATA_MATCH_CASE)) &&
149         strlen(t->value) == 4 && is_number(t->value))
150         return t;
151     return NULL;
152 }
153
154 static void merge_date(AVMetadata **m)
155 {
156     AVMetadataTag *t;
157     char date[17] = {0};      // YYYY-MM-DD hh:mm
158
159     if (!(t = get_date_tag(*m, "TYER")) &&
160         !(t = get_date_tag(*m, "TYE")))
161         return;
162     av_strlcpy(date, t->value, 5);
163     av_metadata_set2(m, "TYER", NULL, 0);
164     av_metadata_set2(m, "TYE",  NULL, 0);
165
166     if (!(t = get_date_tag(*m, "TDAT")) &&
167         !(t = get_date_tag(*m, "TDA")))
168         goto finish;
169     snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
170     av_metadata_set2(m, "TDAT", NULL, 0);
171     av_metadata_set2(m, "TDA",  NULL, 0);
172
173     if (!(t = get_date_tag(*m, "TIME")) &&
174         !(t = get_date_tag(*m, "TIM")))
175         goto finish;
176     snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2);
177     av_metadata_set2(m, "TIME", NULL, 0);
178     av_metadata_set2(m, "TIM",  NULL, 0);
179
180 finish:
181     if (date[0])
182         av_metadata_set2(m, "date", date, 0);
183 }
184
185 static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
186 {
187     int isv34, tlen, unsync;
188     char tag[5];
189     int64_t next, end = avio_tell(s->pb) + len;
190     int taghdrlen;
191     const char *reason = NULL;
192     AVIOContext pb;
193     unsigned char *buffer = NULL;
194     int buffer_size = 0;
195
196     switch (version) {
197     case 2:
198         if (flags & 0x40) {
199             reason = "compression";
200             goto error;
201         }
202         isv34 = 0;
203         taghdrlen = 6;
204         break;
205
206     case 3:
207     case 4:
208         isv34 = 1;
209         taghdrlen = 10;
210         break;
211
212     default:
213         reason = "version";
214         goto error;
215     }
216
217     unsync = flags & 0x80;
218
219     if (isv34 && flags & 0x40) /* Extended header present, just skip over it */
220         avio_skip(s->pb, get_size(s->pb, 4));
221
222     while (len >= taghdrlen) {
223         unsigned int tflags = 0;
224         int tunsync = 0;
225
226         if (isv34) {
227             avio_read(s->pb, tag, 4);
228             tag[4] = 0;
229             if(version==3){
230                 tlen = avio_rb32(s->pb);
231             }else
232                 tlen = get_size(s->pb, 4);
233             tflags = avio_rb16(s->pb);
234             tunsync = tflags & ID3v2_FLAG_UNSYNCH;
235         } else {
236             avio_read(s->pb, tag, 3);
237             tag[3] = 0;
238             tlen = avio_rb24(s->pb);
239         }
240         if (tlen < 0 || tlen > len - taghdrlen) {
241             av_log(s, AV_LOG_WARNING, "Invalid size in frame %s, skipping the rest of tag.\n", tag);
242             break;
243         }
244         len -= taghdrlen + tlen;
245         next = avio_tell(s->pb) + tlen;
246
247         if (tflags & ID3v2_FLAG_DATALEN) {
248             avio_rb32(s->pb);
249             tlen -= 4;
250         }
251
252         if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) {
253             av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed ID3v2 frame %s.\n", tag);
254             avio_skip(s->pb, tlen);
255         } else if (tag[0] == 'T') {
256             if (unsync || tunsync) {
257                 int i, j;
258                 av_fast_malloc(&buffer, &buffer_size, tlen);
259                 for (i = 0, j = 0; i < tlen; i++, j++) {
260                     buffer[j] = avio_r8(s->pb);
261                     if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
262                         /* Unsynchronised byte, skip it */
263                         j--;
264                     }
265                 }
266                 ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
267                 read_ttag(s, &pb, j, tag);
268             } else {
269                 read_ttag(s, s->pb, tlen, tag);
270             }
271         }
272         else if (!tag[0]) {
273             if (tag[1])
274                 av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
275             avio_skip(s->pb, tlen);
276             break;
277         }
278         /* Skip to end of tag */
279         avio_seek(s->pb, next, SEEK_SET);
280     }
281
282     if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
283         end += 10;
284
285   error:
286     if (reason)
287         av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
288     avio_seek(s->pb, end, SEEK_SET);
289     av_free(buffer);
290     return;
291 }
292
293 void ff_id3v2_read(AVFormatContext *s, const char *magic)
294 {
295     int len, ret;
296     uint8_t buf[ID3v2_HEADER_SIZE];
297     int     found_header;
298     int64_t off;
299
300     do {
301         /* save the current offset in case there's nothing to read/skip */
302         off = avio_tell(s->pb);
303         ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
304         if (ret != ID3v2_HEADER_SIZE)
305             break;
306             found_header = ff_id3v2_match(buf, magic);
307             if (found_header) {
308             /* parse ID3v2 header */
309             len = ((buf[6] & 0x7f) << 21) |
310                   ((buf[7] & 0x7f) << 14) |
311                   ((buf[8] & 0x7f) << 7) |
312                    (buf[9] & 0x7f);
313             ff_id3v2_parse(s, len, buf[3], buf[5]);
314         } else {
315             avio_seek(s->pb, off, SEEK_SET);
316         }
317     } while (found_header);
318     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
319     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_2_metadata_conv);
320     ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
321     merge_date(&s->metadata);
322 }
323
324 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
325     { "TALB", "album"},
326     { "TCOM", "composer"},
327     { "TCON", "genre"},
328     { "TCOP", "copyright"},
329     { "TENC", "encoded_by"},
330     { "TIT2", "title"},
331     { "TLAN", "language"},
332     { "TPE1", "artist"},
333     { "TPE2", "album_artist"},
334     { "TPE3", "performer"},
335     { "TPOS", "disc"},
336     { "TPUB", "publisher"},
337     { "TRCK", "track"},
338     { "TSSE", "encoder"},
339     { 0 }
340 };
341
342 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
343     { "TDRL", "date"},
344     { "TDRC", "date"},
345     { "TDEN", "creation_time"},
346     { "TSOA", "album-sort"},
347     { "TSOP", "artist-sort"},
348     { "TSOT", "title-sort"},
349     { 0 }
350 };
351
352 const AVMetadataConv ff_id3v2_2_metadata_conv[] = {
353     { "TAL",  "album"},
354     { "TCO",  "genre"},
355     { "TT2",  "title"},
356     { "TEN",  "encoded_by"},
357     { "TP1",  "artist"},
358     { "TP2",  "album_artist"},
359     { "TP3",  "performer"},
360     { "TRK",  "track"},
361     { 0 }
362 };
363
364
365 const char ff_id3v2_tags[][4] = {
366    "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
367    "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
368    "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
369    "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
370    { 0 },
371 };
372
373 const char ff_id3v2_4_tags[][4] = {
374    "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
375    "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
376    { 0 },
377 };
378
379 const char ff_id3v2_3_tags[][4] = {
380    "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
381    { 0 },
382 };