[FFmpeg-devel] [PATCH] avformat/mp3dec: Make MP3 seek fast

wm4 nfxjfg at googlemail.com
Sat Sep 5 18:33:40 CEST 2015


On Fri, 4 Sep 2015 13:48:41 -0700
Tsung-Hung Wu <tsunghung at chromium.org> wrote:

> Thanks wm4. I updated the patch according to your comments.
> 
> 
> >* @@ -489,19 +489,21 @@ static int mp3_seek(AVFormatContext *s, int
> *>* stream_index, int64_t timestamp,
> *>*      AVStream *st = s->streams[0];
> *>*      int64_t ret  = av_index_search_timestamp(st, timestamp, flags);
> *>*      int64_t best_pos;
> *>* +    int fast_seek = (s->flags & AVFMT_FLAG_FAST_SEEK) ? 1 : 0;
> *>* +    int64_t filesize = mp3->header_filesize > 0 ? mp3->header_filesize
> *>* +                            : avio_size(s->pb) - s->internal->data_offset;
> *
> > ok. But maybe the avio_size() return value should be checked. It can
> > return an error.
> 
> Done. Please see the patch. Thanks for your comments.
> 
> > >* /*
> *>* Many MP3 files in Podcast does not have VBRI, LAME, or XING tag, so
> *>* header_filesize is not always available. (file size - data offset) could be
> *>* a good estimation.
> *>* */
> *> > >*      if (mp3->usetoc == 2)
> *>*          return -1; // generic index code
> *> >* -    if (   mp3->is_cbr
> *>* +    if (   (mp3->is_cbr || fast_seek)
> *
> > Not sure why you need this. If the file is VBR and has no TOC, then all
> > odds are off. But I guess this is ok on the AVFMT_FLAG_FAST_SEEK code
> > path, if you think it's more useful this way.
> 
> Yes, I really need the seek operation fast, and AVFMT_FLAG_FAST_SEEK
> allows to sacrifice the accuracy in exchange for responsiveness. For
> VBR files without TOC, like you said, it's not accurate. For CBR files
> without INFO tag, it's fast and reasonable accurate. Since
> AVFMT_FLAG_FAST_SEEK is set, we should make it fast instead of make it
> safe.
> 
> >*          && (mp3->usetoc == 0 || !mp3->xing_toc)
> *>*          && st->duration > 0
> *>* -        && mp3->header_filesize > s->internal->data_offset
> *>* -        && mp3->frames) {
> *>* +        && filesize > 0) {
> *>* /*
> *>* Not sure why (mp3->header_filesize > s->internal->data_offset) has to be
> *>* true. What if a MP3 file contains a short audio and a large picture?
> *>* Again, mp3->frames is not always available. Do we really need it here? I
> *>* move the check to below.
> *>* */
> *
> > I can't think of any reason either. Maybe the original intention of
> > this code was actually to check whether header_size is a sane value at
> > all? There are lots of weird corner cases, like incomplete or
> > concatenated mp3 files.
> 
> >*          ie = &ie1;
> *>*          timestamp = av_clip64(timestamp, 0, st->duration);
> *>*          ie->timestamp = timestamp;
> *>* -        ie->pos       = av_rescale(timestamp, mp3->header_filesize,
> *>* st->duration) + s->internal->data_offset;
> *>* +        ie->pos       = av_rescale(timestamp, filesize, st->duration) +
> *>* s->internal->data_offset;
> *>*      } else if (mp3->xing_toc) {
> *>*          if (ret < 0)
> *>*              return ret;
> *>* @@ -515,7 +517,7 @@ static int mp3_seek(AVFormatContext *s, int
> *>* stream_index, int64_t timestamp,
> *>*      if (best_pos < 0)
> *>*          return best_pos;
> *> >* -    if (mp3->is_cbr && ie == &ie1) {
> *>* +    if (mp3->is_cbr && ie == &ie1 && mp3->frames) {
> *
> > Not sure what this does after all.
> 
> This tries to refine the timestamp. Because it may seek to middle of a
> frame, mp3_sync() will align the position to a frame boundary. Thus,
> the timestamp may be a little bit off.
> 
> Since it's the only place using mp3->frames in mp3_seek()*, *I think
> we can check it right before using it.
> 
> >*          int frame_duration = av_rescale(st->duration, 1, mp3->frames);
> *>*          ie1.timestamp = frame_duration * av_rescale(best_pos -
> *>* s->internal->data_offset, mp3->frames, mp3->header_filesize);
> *>*      }*

Applied, thanks.


More information about the ffmpeg-devel mailing list