Statistics
| Branch: | Revision:

ffmpeg / libavformat / id3v2.c @ c5f4c0fd

History | View | Annotate | Download (10.7 KB)

1 2ea512a6 Alex Converse
/*
2
 * ID3v2 header parser
3
 * Copyright (c) 2003 Fabrice Bellard
4
 *
5 2912e87a Mans Rullgard
 * This file is part of Libav.
6 2ea512a6 Alex Converse
 *
7 2912e87a Mans Rullgard
 * Libav is free software; you can redistribute it and/or
8 2ea512a6 Alex Converse
 * 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 2912e87a Mans Rullgard
 * Libav is distributed in the hope that it will be useful,
13 2ea512a6 Alex Converse
 * 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 2912e87a Mans Rullgard
 * License along with Libav; if not, write to the Free Software
19 2ea512a6 Alex Converse
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "id3v2.h"
23 75411182 Patrick Dehne
#include "id3v1.h"
24
#include "libavutil/avstring.h"
25 3a1350e8 Michael Karcher
#include "libavutil/intreadwrite.h"
26 03700d39 Anton Khirnov
#include "metadata.h"
27 e731b8d8 Anton Khirnov
#include "avio_internal.h"
28 2ea512a6 Alex Converse
29 3a1350e8 Michael Karcher
int ff_id3v2_match(const uint8_t *buf, const char * magic)
30 2ea512a6 Alex Converse
{
31 3a1350e8 Michael Karcher
    return  buf[0]         == magic[0] &&
32
            buf[1]         == magic[1] &&
33
            buf[2]         == magic[2] &&
34 7d7b8c32 Diego Biurrun
            buf[3]         != 0xff &&
35
            buf[4]         != 0xff &&
36
           (buf[6] & 0x80) ==    0 &&
37
           (buf[7] & 0x80) ==    0 &&
38
           (buf[8] & 0x80) ==    0 &&
39 1d4b1bf2 Diego Biurrun
           (buf[9] & 0x80) ==    0;
40 2ea512a6 Alex Converse
}
41 ac3ef4a4 Alex Converse
42
int ff_id3v2_tag_len(const uint8_t * buf)
43
{
44
    int len = ((buf[6] & 0x7f) << 21) +
45 7d7b8c32 Diego Biurrun
              ((buf[7] & 0x7f) << 14) +
46
              ((buf[8] & 0x7f) << 7) +
47
               (buf[9] & 0x7f) +
48
              ID3v2_HEADER_SIZE;
49 ac3ef4a4 Alex Converse
    if (buf[5] & 0x10)
50
        len += ID3v2_HEADER_SIZE;
51
    return len;
52
}
53 75411182 Patrick Dehne
54 ae628ec1 Anton Khirnov
static unsigned int get_size(AVIOContext *s, int len)
55 75411182 Patrick Dehne
{
56 7d7b8c32 Diego Biurrun
    int v = 0;
57
    while (len--)
58 b7effd4e Anton Khirnov
        v = (v << 7) + (avio_r8(s) & 0x7F);
59 75411182 Patrick Dehne
    return v;
60
}
61
62 ae628ec1 Anton Khirnov
static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
63 75411182 Patrick Dehne
{
64
    char *q, dst[512];
65 41770abf Anton Khirnov
    const char *val = NULL;
66 75411182 Patrick Dehne
    int len, dstlen = sizeof(dst) - 1;
67
    unsigned genre;
68 b7effd4e Anton Khirnov
    unsigned int (*get)(AVIOContext*) = avio_rb16;
69 75411182 Patrick Dehne
70 7d7b8c32 Diego Biurrun
    dst[0] = 0;
71
    if (taglen < 1)
72 75411182 Patrick Dehne
        return;
73
74
    taglen--; /* account for encoding type byte */
75
76 b7effd4e Anton Khirnov
    switch (avio_r8(pb)) { /* encoding type */
77 75411182 Patrick Dehne
78 d66eff36 Anton Khirnov
    case ID3v2_ENCODING_ISO8859:
79 75411182 Patrick Dehne
        q = dst;
80 787f8fad Anton Khirnov
        while (taglen-- && q - dst < dstlen - 7) {
81 75411182 Patrick Dehne
            uint8_t tmp;
82 b7effd4e Anton Khirnov
            PUT_UTF8(avio_r8(pb), tmp, *q++ = tmp;)
83 75411182 Patrick Dehne
        }
84 9aa1bcce Anton Khirnov
        *q = 0;
85 75411182 Patrick Dehne
        break;
86
87 d66eff36 Anton Khirnov
    case ID3v2_ENCODING_UTF16BOM:
88 20c68378 Anton Khirnov
        taglen -= 2;
89 b7effd4e Anton Khirnov
        switch (avio_rb16(pb)) {
90 20c68378 Anton Khirnov
        case 0xfffe:
91 b7effd4e Anton Khirnov
            get = avio_rl16;
92 20c68378 Anton Khirnov
        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 d66eff36 Anton Khirnov
    case ID3v2_ENCODING_UTF16BE:
101 20c68378 Anton Khirnov
        q = dst;
102
        while (taglen > 1 && q - dst < dstlen - 7) {
103
            uint32_t ch;
104
            uint8_t tmp;
105
106 18bbe9df Alexander Kojevnikov
            GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;)
107 20c68378 Anton Khirnov
            PUT_UTF8(ch, tmp, *q++ = tmp;)
108
        }
109
        *q = 0;
110
        break;
111
112 d66eff36 Anton Khirnov
    case ID3v2_ENCODING_UTF8:
113 037e9afd Jai Menon
        len = FFMIN(taglen, dstlen);
114 b7effd4e Anton Khirnov
        avio_read(pb, dst, len);
115 75411182 Patrick Dehne
        dst[len] = 0;
116
        break;
117 20c68378 Anton Khirnov
    default:
118 fb61a7c5 Anton Khirnov
        av_log(s, AV_LOG_WARNING, "Unknown encoding in tag %s.\n", key);
119 75411182 Patrick Dehne
    }
120
121 41770abf Anton Khirnov
    if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
122 75411182 Patrick Dehne
        && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
123
        && genre <= ID3v1_GENRE_MAX)
124 41770abf Anton Khirnov
        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 75411182 Patrick Dehne
135 41770abf Anton Khirnov
    if (val)
136 75aded83 Anton Khirnov
        av_metadata_set2(&s->metadata, key, val, AV_METADATA_DONT_OVERWRITE);
137 75411182 Patrick Dehne
}
138
139 56e2ac6b Anton Khirnov
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 46a2da76 Anton Khirnov
static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
186 75411182 Patrick Dehne
{
187 18bbe9df Alexander Kojevnikov
    int isv34, tlen, unsync;
188 41770abf Anton Khirnov
    char tag[5];
189 bca6dee3 Anton Khirnov
    int64_t next, end = avio_tell(s->pb) + len;
190 75411182 Patrick Dehne
    int taghdrlen;
191 eb1e7f78 Anton Khirnov
    const char *reason = NULL;
192 ae628ec1 Anton Khirnov
    AVIOContext pb;
193 18bbe9df Alexander Kojevnikov
    unsigned char *buffer = NULL;
194
    int buffer_size = 0;
195 75411182 Patrick Dehne
196 7d7b8c32 Diego Biurrun
    switch (version) {
197 75411182 Patrick Dehne
    case 2:
198 7d7b8c32 Diego Biurrun
        if (flags & 0x40) {
199 75411182 Patrick Dehne
            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 18bbe9df Alexander Kojevnikov
    unsync = flags & 0x80;
218 75411182 Patrick Dehne
219 7d7b8c32 Diego Biurrun
    if (isv34 && flags & 0x40) /* Extended header present, just skip over it */
220 45a8a02a Anton Khirnov
        avio_skip(s->pb, get_size(s->pb, 4));
221 75411182 Patrick Dehne
222 7d7b8c32 Diego Biurrun
    while (len >= taghdrlen) {
223 18bbe9df Alexander Kojevnikov
        unsigned int tflags;
224
        int tunsync = 0;
225
226 7d7b8c32 Diego Biurrun
        if (isv34) {
227 b7effd4e Anton Khirnov
            avio_read(s->pb, tag, 4);
228 41770abf Anton Khirnov
            tag[4] = 0;
229 3fd5a75b Michael Niedermayer
            if(version==3){
230 b7effd4e Anton Khirnov
                tlen = avio_rb32(s->pb);
231 3fd5a75b Michael Niedermayer
            }else
232
                tlen = get_size(s->pb, 4);
233 b7effd4e Anton Khirnov
            tflags = avio_rb16(s->pb);
234 7a07d158 Anton Khirnov
            tunsync = tflags & ID3v2_FLAG_UNSYNCH;
235 75411182 Patrick Dehne
        } else {
236 b7effd4e Anton Khirnov
            avio_read(s->pb, tag, 3);
237 41770abf Anton Khirnov
            tag[3] = 0;
238 b7effd4e Anton Khirnov
            tlen = avio_rb24(s->pb);
239 75411182 Patrick Dehne
        }
240 c5f4c0fd Anton Khirnov
        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 75411182 Patrick Dehne
            break;
243 c5f4c0fd Anton Khirnov
        }
244
        len -= taghdrlen + tlen;
245 a2704c97 Anton Khirnov
        next = avio_tell(s->pb) + tlen;
246 75411182 Patrick Dehne
247 a152c77f Anton Khirnov
        if (tflags & ID3v2_FLAG_DATALEN) {
248 b7effd4e Anton Khirnov
            avio_rb32(s->pb);
249 a152c77f Anton Khirnov
            tlen -= 4;
250
        }
251
252 407d3d5a Anton Khirnov
        if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) {
253
            av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed ID3v2 frame %s.\n", tag);
254 45a8a02a Anton Khirnov
            avio_skip(s->pb, tlen);
255 407d3d5a Anton Khirnov
        } else if (tag[0] == 'T') {
256 18bbe9df Alexander Kojevnikov
            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 b7effd4e Anton Khirnov
                    buffer[j] = avio_r8(s->pb);
261 18bbe9df Alexander Kojevnikov
                    if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
262
                        /* Unsynchronised byte, skip it */
263
                        j--;
264
                    }
265
                }
266 e731b8d8 Anton Khirnov
                ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
267 18bbe9df Alexander Kojevnikov
                read_ttag(s, &pb, j, tag);
268
            } else {
269
                read_ttag(s, s->pb, tlen, tag);
270
            }
271
        }
272 2e3ca1ff Jai Menon
        else if (!tag[0]) {
273
            if (tag[1])
274
                av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
275 45a8a02a Anton Khirnov
            avio_skip(s->pb, tlen);
276 2e3ca1ff Jai Menon
            break;
277
        }
278 75411182 Patrick Dehne
        /* Skip to end of tag */
279 6b4aa5da Anton Khirnov
        avio_seek(s->pb, next, SEEK_SET);
280 75411182 Patrick Dehne
    }
281
282 7d7b8c32 Diego Biurrun
    if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
283 bca6dee3 Anton Khirnov
        end += 10;
284 18bbe9df Alexander Kojevnikov
285 eb1e7f78 Anton Khirnov
  error:
286
    if (reason)
287
        av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
288 bca6dee3 Anton Khirnov
    avio_seek(s->pb, end, SEEK_SET);
289 18bbe9df Alexander Kojevnikov
    av_free(buffer);
290 75411182 Patrick Dehne
    return;
291
}
292 6378b062 Anton Khirnov
293 46a2da76 Anton Khirnov
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 a2704c97 Anton Khirnov
        off = avio_tell(s->pb);
303 b7effd4e Anton Khirnov
        ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
304 46a2da76 Anton Khirnov
        if (ret != ID3v2_HEADER_SIZE)
305 f7fcd6a2 Anton Khirnov
            break;
306 46a2da76 Anton Khirnov
            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 6b4aa5da Anton Khirnov
            avio_seek(s->pb, off, SEEK_SET);
316 46a2da76 Anton Khirnov
        }
317
    } while (found_header);
318 cb6bc576 Anton Khirnov
    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 56e2ac6b Anton Khirnov
    merge_date(&s->metadata);
322 46a2da76 Anton Khirnov
}
323
324 cb6bc576 Anton Khirnov
const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
325 6378b062 Anton Khirnov
    { "TALB", "album"},
326
    { "TCOM", "composer"},
327
    { "TCON", "genre"},
328
    { "TCOP", "copyright"},
329 ca76a119 Anton Khirnov
    { "TENC", "encoded_by"},
330 6378b062 Anton Khirnov
    { "TIT2", "title"},
331
    { "TLAN", "language"},
332 8a98be1a Michael Niedermayer
    { "TPE1", "artist"},
333 ca76a119 Anton Khirnov
    { "TPE2", "album_artist"},
334
    { "TPE3", "performer"},
335 6378b062 Anton Khirnov
    { "TPOS", "disc"},
336
    { "TPUB", "publisher"},
337
    { "TRCK", "track"},
338 cb6bc576 Anton Khirnov
    { "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 ca76a119 Anton Khirnov
    { "TSOA", "album-sort"},
347
    { "TSOP", "artist-sort"},
348
    { "TSOT", "title-sort"},
349 6378b062 Anton Khirnov
    { 0 }
350
};
351 078d89a2 Anton Khirnov
352 cb6bc576 Anton Khirnov
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 078d89a2 Anton Khirnov
const char ff_id3v2_tags[][4] = {
366 cb6bc576 Anton Khirnov
   "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 078d89a2 Anton Khirnov
   { 0 },
382
};