diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2013-07-07 13:15:32 +0200 |
---|---|---|
committer | Carl Eugen Hoyos <cehoyos@ag.or.at> | 2013-07-09 00:15:38 +0200 |
commit | 18900381e2d36b1b28d8f39148e6a799bf7336bd (patch) | |
tree | d3ceb04cc07af1c0e41d480cc1615582fdadc70e /libavformat | |
parent | ce74b92c0981663754a5bf5edad59f9d2ea91e3d (diff) | |
download | ffmpeg-18900381e2d36b1b28d8f39148e6a799bf7336bd.tar.gz |
mp3dec: detect CBR and use CBR axiom to seek
This should also work reasonable with truncated and growing mp3s.
Fixes Ticket2590
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit e096283ea55bc36a637b47329e19ddb26fb1440b)
Conflicts:
libavformat/mp3dec.c
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/mp3dec.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index d599c9c489..05cbece529 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -37,9 +37,11 @@ typedef struct { int64_t filesize; + int64_t header_filesize; int xing_toc; int start_pad; int end_pad; + int is_cbr; } MP3DecContext; /* mp3 read */ @@ -185,6 +187,9 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) if (size && frames && !is_cbr) st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); + mp3->is_cbr = is_cbr; + mp3->header_filesize = size; + return 0; } @@ -274,21 +279,33 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { MP3DecContext *mp3 = s->priv_data; - AVIndexEntry *ie; + AVIndexEntry *ie, ie1; AVStream *st = s->streams[0]; int64_t ret = av_index_search_timestamp(st, timestamp, flags); int i, j; - if (!mp3->xing_toc) { + if (mp3->is_cbr && st->duration > 0 && mp3->header_filesize > s->data_offset) { + int64_t filesize = avio_size(s->pb); + int64_t duration; + if (filesize <= s->data_offset) + filesize = mp3->header_filesize; + filesize -= s->data_offset; + duration = av_rescale(st->duration, filesize, mp3->header_filesize - s->data_offset); + ie = &ie1; + timestamp = av_clip64(timestamp, 0, duration); + ie->timestamp = timestamp; + ie->pos = av_rescale(timestamp, filesize, duration) + s->data_offset; + } else if (mp3->xing_toc) { + if (ret < 0) + return ret; + + ie = &st->index_entries[ret]; + } else { st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; return -1; } - if (ret < 0) - return ret; - - ie = &st->index_entries[ret]; ret = avio_seek(s->pb, ie->pos, SEEK_SET); if (ret < 0) return ret; |