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 |
