mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
avformat/mov: adjust skip_samples according to seek timestamp
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). Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
parent
c4407a3e00
commit
2e17435480
@ -8122,6 +8122,22 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
|
||||
return sample;
|
||||
}
|
||||
|
||||
static int64_t mov_get_skip_samples(AVStream *st, int sample)
|
||||
{
|
||||
MOVStreamContext *sc = st->priv_data;
|
||||
int64_t first_ts = st->internal->index_entries[0].timestamp;
|
||||
int64_t ts = st->internal->index_entries[sample].timestamp;
|
||||
int64_t off;
|
||||
|
||||
if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||
return 0;
|
||||
|
||||
/* compute skip samples according to stream start_pad, seek ts and first ts */
|
||||
off = av_rescale_q(ts - first_ts, st->time_base,
|
||||
(AVRational){1, st->codecpar->sample_rate});
|
||||
return FFMAX(sc->start_pad - off, 0);
|
||||
}
|
||||
|
||||
static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
|
||||
{
|
||||
MOVContext *mc = s->priv_data;
|
||||
@ -8140,18 +8156,19 @@ static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
|
||||
if (mc->seek_individually) {
|
||||
/* adjust seek timestamp to found sample timestamp */
|
||||
int64_t seek_timestamp = st->internal->index_entries[sample].timestamp;
|
||||
st->internal->skip_samples = mov_get_skip_samples(st, sample);
|
||||
|
||||
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)
|
||||
st->internal->skip_samples = mov_get_skip_samples(st, sample);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user