[FFmpeg-devel] [PATCH] avformat/mov: adjust skip_samples according to seek timestamp

Matthieu Bouron matthieu.bouron at gmail.com
Mon Jan 4 11:32:16 EET 2021


On Mon, Nov 23, 2020 at 05:43:06PM +0100, Matthieu Bouron wrote:
> On Tue, Nov 17, 2020 at 02:18:46PM +0100, Matthieu Bouron wrote:
> > On Mon, Nov 09, 2020 at 06:26:46PM +0100, Matthieu Bouron wrote:
> > > On Mon, Nov 02, 2020 at 12:42:19PM +0100, Matthieu Bouron wrote:
> > > > Currently skip_samples is set to start_pad if sample_time is lesser or
> > > > equal to 0. This can cause issues if the stream starts with packets that
> > > > have negative pts. Calling avformat_seek_file() with ts set to 0 on such
> > > > streams makes the mov demuxer return the right corresponding packets
> > > > (near the 0 timestamp) but set skip_samples to start_pad which is
> > > > incorrect as the audio decoder will discard the returned samples
> > > > according to skip_samples from the first packet it receives (which has
> > > > its timestamp near 0).
> > > > 
> > > > For example, considering the following audio stream with start_pad=1344:
> > > > 
> > > >  [PKT pts=-1344] [PKT pts=-320] [PKT pts=704] [PKT pts=1728] [...]
> > > > 
> > > > Calling avformat_seek_file() with ts=0 makes the next call to
> > > > av_read_frame() return the packet with pts=-320 and a skip samples
> > > > side data set to 1344 (start_pad). This makes the audio decoder
> > > > incorrectly discard (1344 - 320) samples.
> > > > 
> > > > This commit makes the move demuxer adjust skip_samples according to the
> > > > stream start_pad, seek timestamp and first sample timestamp.
> > > > 
> > > > The above example will now result in av_read_frame() still returning the
> > > > packet with pts=-320 but with a skip samples side data set to 320
> > > > (src_pad - (seek_timestamp - first_timestamp)). This makes the audio
> > > > decoder only discard 320 samples (from pts=-320 to pts=0).
> > > > ---
> > > >  libavformat/mov.c | 18 ++++++++++++++++--
> > > >  1 file changed, 16 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/libavformat/mov.c b/libavformat/mov.c
> > > > index dd0db6bca79..f99cb0df25a 100644
> > > > --- a/libavformat/mov.c
> > > > +++ b/libavformat/mov.c
> > > > @@ -8098,20 +8098,34 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
> > > >          return sample;
> > > >  
> > > >      if (mc->seek_individually) {
> > > > +        MOVStreamContext *sc = s->streams[stream_index]->priv_data;
> > > > +
> > > >          /* adjust seek timestamp to found sample timestamp */
> > > > +        int64_t first_timestamp = st->internal->index_entries[0].timestamp;
> > > >          int64_t seek_timestamp = st->internal->index_entries[sample].timestamp;
> > > >  
> > > > +        /* adjust skip samples according to stream start_pad, seek timestamp and first timestamp */
> > > > +        int64_t skip_samples = FFMAX(sc->start_pad - (seek_timestamp - first_timestamp), 0);
> > > > +        st->internal->skip_samples = skip_samples;
> > > > +
> > > >          for (i = 0; i < s->nb_streams; i++) {
> > > >              int64_t timestamp;
> > > >              MOVStreamContext *sc = s->streams[i]->priv_data;
> > > >              st = s->streams[i];
> > > > -            st->internal->skip_samples = (sample_time <= 0) ? sc->start_pad : 0;
> > > >  
> > > >              if (stream_index == i)
> > > >                  continue;
> > > >  
> > > >              timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
> > > > -            mov_seek_stream(s, st, timestamp, flags);
> > > > +            sample = mov_seek_stream(s, st, timestamp, flags);
> > > > +            if (sample >= 0) {
> > > > +                first_timestamp = st->internal->index_entries[0].timestamp;
> > > > +                seek_timestamp = st->internal->index_entries[sample].timestamp;
> > > > +
> > > > +                /* adjust skip samples according to stream start_pad, seek timestamp and first timestamp */
> > > > +                skip_samples = FFMAX(sc->start_pad - (seek_timestamp - first_timestamp), 0);
> > > > +                st->internal->skip_samples = skip_samples;
> > > > +            }
> > > >          }
> > > >      } else {
> > > >          for (i = 0; i < s->nb_streams; i++) {
> > > > -- 
> > > > 2.29.2
> > > > 
> > > 
> > > Ping.
> > > 
> > 
> > Ping.
> > 
> 
> Ping.
> 

Ping.

-- 
Matthieu B.


More information about the ffmpeg-devel mailing list