comparison mp3.c @ 2097:cab3fcb34077 libavformat

id3v2 reader patch by Andreas ?man andreas olebyn nu original thread: [FFmpeg-devel] [Ffmpeg-devel] ID3v2
author benoit
date Tue, 22 May 2007 08:23:45 +0000
parents 85e48ffccf91
children b51b57909b5f
comparison
equal deleted inserted replaced
2096:85e48ffccf91 2097:cab3fcb34077
167 (buf[7] & 0x80) == 0 && 167 (buf[7] & 0x80) == 0 &&
168 (buf[8] & 0x80) == 0 && 168 (buf[8] & 0x80) == 0 &&
169 (buf[9] & 0x80) == 0); 169 (buf[9] & 0x80) == 0);
170 } 170 }
171 171
172 static unsigned int id3v2_get_size(ByteIOContext *s, int len)
173 {
174 int v=0;
175 while(len--)
176 v= (v<<7) + (get_byte(s)&0x7F);
177 return v;
178 }
179
180 static void id3v2_read_ttag(AVFormatContext *s, int taglen, char *dst, int dstlen)
181 {
182 char *q;
183 int len;
184
185 if(taglen < 1)
186 return;
187
188 taglen--; /* account for encoding type byte */
189 dstlen--; /* Leave space for zero terminator */
190
191 switch(get_byte(&s->pb)) { /* encoding type */
192
193 case 0: /* ISO-8859-1 (0 - 255 maps directly into unicode) */
194 q = dst;
195 while(taglen--) {
196 uint8_t tmp;
197 PUT_UTF8(get_byte(&s->pb), tmp, if (q - dst < dstlen - 1) *q++ = tmp;)
198 }
199 *q = '\0';
200 break;
201
202 case 3: /* UTF-8 */
203 len = FFMIN(taglen, dstlen);
204 get_buffer(&s->pb, dst, len);
205 dst[len] = 0;
206 break;
207 }
208 }
209
210 /**
211 * ID3v2 parser
212 *
213 * Handles ID3v2.2, 2.3 and 2.4.
214 *
215 */
216
217 static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
218 {
219 int isv34, tlen;
220 uint32_t tag;
221 offset_t next;
222 char tmp[16];
223 int taghdrlen;
224 const char *reason;
225
226 switch(version) {
227 case 2:
228 if(flags & 0x40) {
229 reason = "compression";
230 goto error;
231 }
232 isv34 = 0;
233 taghdrlen = 6;
234 break;
235
236 case 3 ... 4:
237 isv34 = 1;
238 taghdrlen = 10;
239 break;
240
241 default:
242 reason = "version";
243 goto error;
244 }
245
246 if(flags & 0x80) {
247 reason = "unsynchronization";
248 goto error;
249 }
250
251 if(isv34 && flags & 0x40) /* Extended header present, just skip over it */
252 url_fskip(&s->pb, id3v2_get_size(&s->pb, 4));
253
254 while(len >= taghdrlen) {
255 if(isv34) {
256 tag = get_be32(&s->pb);
257 tlen = id3v2_get_size(&s->pb, 4);
258 get_be16(&s->pb); /* flags */
259 } else {
260 tag = get_be24(&s->pb);
261 tlen = id3v2_get_size(&s->pb, 3);
262 }
263 len -= taghdrlen + tlen;
264
265 if(len < 0)
266 break;
267
268 next = url_ftell(&s->pb) + tlen;
269
270 switch(tag) {
271 case MKBETAG('T', 'I', 'T', '2'):
272 case MKBETAG(0, 'T', 'T', '2'):
273 id3v2_read_ttag(s, tlen, s->title, sizeof(s->title));
274 break;
275 case MKBETAG('T', 'P', 'E', '1'):
276 case MKBETAG(0, 'T', 'P', '1'):
277 id3v2_read_ttag(s, tlen, s->author, sizeof(s->author));
278 break;
279 case MKBETAG('T', 'A', 'L', 'B'):
280 case MKBETAG(0, 'T', 'A', 'L'):
281 id3v2_read_ttag(s, tlen, s->album, sizeof(s->album));
282 break;
283 case MKBETAG('T', 'C', 'O', 'N'):
284 case MKBETAG(0, 'T', 'C', 'O'):
285 id3v2_read_ttag(s, tlen, s->genre, sizeof(s->genre));
286 break;
287 case MKBETAG('T', 'C', 'O', 'P'):
288 case MKBETAG(0, 'T', 'C', 'R'):
289 id3v2_read_ttag(s, tlen, s->copyright, sizeof(s->copyright));
290 break;
291 case MKBETAG('T', 'R', 'C', 'K'):
292 case MKBETAG(0, 'T', 'R', 'K'):
293 id3v2_read_ttag(s, tlen, tmp, sizeof(tmp));
294 s->track = atoi(tmp);
295 break;
296 case 0:
297 /* padding, skip to end */
298 url_fskip(&s->pb, len);
299 len = 0;
300 continue;
301 }
302 /* Skip to end of tag */
303 url_fseek(&s->pb, next, SEEK_SET);
304 }
305
306 if(version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
307 url_fskip(&s->pb, 10);
308 return;
309
310 error:
311 av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
312 url_fskip(&s->pb, len);
313 }
314
172 static void id3v1_get_string(char *str, int str_size, 315 static void id3v1_get_string(char *str, int str_size,
173 const uint8_t *buf, int buf_size) 316 const uint8_t *buf, int buf_size)
174 { 317 {
175 int i, c; 318 int i, c;
176 char *q; 319 char *q;
311 /* if ID3v2 header found, skip it */ 454 /* if ID3v2 header found, skip it */
312 ret = get_buffer(&s->pb, buf, ID3v2_HEADER_SIZE); 455 ret = get_buffer(&s->pb, buf, ID3v2_HEADER_SIZE);
313 if (ret != ID3v2_HEADER_SIZE) 456 if (ret != ID3v2_HEADER_SIZE)
314 return -1; 457 return -1;
315 if (id3v2_match(buf)) { 458 if (id3v2_match(buf)) {
316 /* skip ID3v2 header */ 459 /* parse ID3v2 header */
317 len = ((buf[6] & 0x7f) << 21) | 460 len = ((buf[6] & 0x7f) << 21) |
318 ((buf[7] & 0x7f) << 14) | 461 ((buf[7] & 0x7f) << 14) |
319 ((buf[8] & 0x7f) << 7) | 462 ((buf[8] & 0x7f) << 7) |
320 (buf[9] & 0x7f); 463 (buf[9] & 0x7f);
321 url_fskip(&s->pb, len); 464 id3v2_parse(s, len, buf[3], buf[5]);
322 } else { 465 } else {
323 url_fseek(&s->pb, 0, SEEK_SET); 466 url_fseek(&s->pb, 0, SEEK_SET);
324 } 467 }
325 468
326 /* the parameters will be extracted from the compressed bitstream */ 469 /* the parameters will be extracted from the compressed bitstream */