Mercurial > libavformat.hg
comparison mp3.c @ 2662:08b1ac852321 libavformat
add support for reading duration from Xing-tag in mp3 files
author | andoma |
---|---|
date | Tue, 23 Oct 2007 13:35:20 +0000 |
parents | c63b1bd7be16 |
children | be889462edfc |
comparison
equal
deleted
inserted
replaced
2661:bed166d88f63 | 2662:08b1ac852321 |
---|---|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | 20 */ |
21 #include "avformat.h" | 21 #include "avformat.h" |
22 #include "mpegaudio.h" | 22 #include "mpegaudio.h" |
23 #include "avstring.h" | 23 #include "avstring.h" |
24 #include "mpegaudiodecheader.h" | |
24 | 25 |
25 #define ID3v2_HEADER_SIZE 10 | 26 #define ID3v2_HEADER_SIZE 10 |
26 #define ID3v1_TAG_SIZE 128 | 27 #define ID3v1_TAG_SIZE 128 |
27 | 28 |
28 #define ID3v1_GENRE_MAX 125 | 29 #define ID3v1_GENRE_MAX 125 |
422 else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; | 423 else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; |
423 else if(max_frames>=1) return 1; | 424 else if(max_frames>=1) return 1; |
424 else return 0; | 425 else return 0; |
425 } | 426 } |
426 | 427 |
428 /** | |
429 * Try to extract a xing tag from the stream and if found, decode it | |
430 */ | |
431 static void mp3_parse_xing(AVFormatContext *s, AVStream *st) | |
432 { | |
433 uint32_t v, frames, spf; | |
434 const offset_t offtbl[2][2] = {{32, 17}, {17,9}}; | |
435 MPADecodeContext c; | |
436 | |
437 ff_mpegaudio_decode_header(&c, get_be32(&s->pb)); | |
438 url_fseek(&s->pb, offtbl[c.lsf == 1][c.nb_channels == 1], SEEK_CUR); | |
439 v = get_be32(&s->pb); | |
440 if(c.layer != 3 || | |
441 (v != MKBETAG('X', 'i', 'n', 'g') && | |
442 v != MKBETAG('I', 'n', 'f', 'o'))) | |
443 return; | |
444 | |
445 v = get_be32(&s->pb); | |
446 if(v & 0x1) { | |
447 frames = get_be32(&s->pb); /* Total number of frames in file */ | |
448 spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */ | |
449 | |
450 st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate}, | |
451 st->time_base); | |
452 } | |
453 } | |
454 | |
427 static int mp3_read_header(AVFormatContext *s, | 455 static int mp3_read_header(AVFormatContext *s, |
428 AVFormatParameters *ap) | 456 AVFormatParameters *ap) |
429 { | 457 { |
430 AVStream *st; | 458 AVStream *st; |
431 uint8_t buf[ID3v1_TAG_SIZE]; | 459 uint8_t buf[ID3v1_TAG_SIZE]; |
432 int len, ret, filesize; | 460 int len, ret, filesize; |
461 offset_t off; | |
433 | 462 |
434 st = av_new_stream(s, 0); | 463 st = av_new_stream(s, 0); |
435 if (!st) | 464 if (!st) |
436 return AVERROR(ENOMEM); | 465 return AVERROR(ENOMEM); |
437 | 466 |
466 (buf[9] & 0x7f); | 495 (buf[9] & 0x7f); |
467 id3v2_parse(s, len, buf[3], buf[5]); | 496 id3v2_parse(s, len, buf[3], buf[5]); |
468 } else { | 497 } else { |
469 url_fseek(&s->pb, 0, SEEK_SET); | 498 url_fseek(&s->pb, 0, SEEK_SET); |
470 } | 499 } |
500 | |
501 off = url_ftell(&s->pb); | |
502 mp3_parse_xing(s, st); | |
503 url_fseek(&s->pb, off, SEEK_SET); | |
471 | 504 |
472 /* the parameters will be extracted from the compressed bitstream */ | 505 /* the parameters will be extracted from the compressed bitstream */ |
473 return 0; | 506 return 0; |
474 } | 507 } |
475 | 508 |