Hello.
I've problems playing a short clip [1] in a continuous loop using the -loop
option
and I'm not sure, how to fix this.
Running
avconv -loop -1 -i in.mp4 -qscale 2 out.avi
leads to an infinite loop (without any output) after the first iteration.
I narrowed down the problem to a call to av_seek_frame(), looking for a
non-existant
timestamp. See below.
The clip is a stream capture of a live stream containing one video and one
audio track.
Both tracks start with negative stamps:
Video:
ts[0] = -512 (keyframe)
ts[1] = -256 (no keyframe)
ts[2] = 0 (no keyframe)
ts[3] = 256 (no keyframe)
ts[4] = 512 (no keyframe)
Audio:
ts[0] = -1024 (keyframe)
ts[1] = 0 (keyframe)
ts[2] = 1024 (keyframe)
ts[3] = 2048 (keyframe)
ts[4] = 3072 (keyframe)
In libavformat/utils.c:1664 in update_stream_timings(), the smallest timestamp
of all streams of the given format context is calculated and set as
"start_time".
In my case
streams[0].start_time = 0
streams[0].time_base = 1/12800
streams[1].start_time = -1024
streams[1].time_base = 1/48000
leads to
ic->start_time = -21333
due to the smaller timestamp of the audio track.
When the clip ends, seek_to_start() (avtools/avconv.c:2515) is called, which
calls av_seek_frame() with stream_index -1 and this start_time.
And there is the issue: stream_index=-1 indicates no specific stream is
selected, but the given start_time relates to the audio track.
The called seek_frame_internal() then selects the default stream, since no
specific stream was selected, which is in my case stream 0, the video track.
Then the "start_time" timestamp (of the audio track) gets rescaled with the
time_base of the selected stream (the video track).
timestamp = -273
The following call to read_seek (in my case mov_read_seek) then fails to
find a frame with that invalid timestamp and returns AVERROR_INVALIDDATA.
This leads to seek_to_start() to return, as well as process_input() and
the loop starts again with the same result, leading to the described infinite
loop.
My question is now: which of these issues are bugs and how to fix them properly?
Should the AVFormatContext->start_time be set to smallest timestamp of all
streams
or only of the default stream? Maybe also store the stream index the timestamp
refers to?
Should seek_to_start() use stream_index=-1 and the context start_time together?
How should the errors occurring during seek_to_start() be handled? I guess
in the context of live streams restarting the encoding after errors
is nice, but when decoding files any errors should make avconv exit, since
recovering from decoding problems of the same file is not likely.
How should the mov demuxer handle negative timestamps when seeking?
Currently, all negative timestamps are set to 0 in mov_read_seek() (mov.c:4053),
which leads in my case to mov_seek_stream() bailing out with
AVERROR_INVALIDDATA,
since no key frame with that timestamp is found (keyframe is at -512) and the
condition
if (sample < 0 && st->nb_index_entries &&
timestamp < st->index_entries[0].timestamp)
is not met: timestamp=0 is not smaller than the first (negative) timestamp.
Looking through the code, I noticed a time_offset is calculated when parsing
the header
of the clip. Using this offset when seeking for timestamp=0 fixed the immediate
problem,
see attached patch. But I'm not sure, if this is correct and I think the other
issues are
still valid.
I hope the information provided is enough to reproduce the issue.
Regards
Peter
[1] https://trac.ffmpeg.org/raw-attachment/ticket/6139/loop.mp4
>From a643f0fad49672b9b9a5d817212d270359e1307e Mon Sep 17 00:00:00 2001
From: Jonas Licht <jonas.li...@fem.tu-ilmenau.de>
Date: Tue, 27 Jun 2017 20:29:57 +0200
Subject: [PATCH] libavformat/mov.c: use calculated dts offset when seeking in
streams
Subtract the calculated dts offset from the requested timestamp before
seeking. This fixes an infinite loop observed with a short file which
contains only one key frame and starts with negative timestamps.
Then, av_index_search_timestamp() returns a valid negative timestamp,
but mov_seek_stream bails out with AVERROR_INVALIDDATA.
Signed-off-by: Jonas Licht <jonas.li...@fem.tu-ilmenau.de>
---
libavformat/mov.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index bf68fbd46a..3293772226 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -4003,6 +4003,8 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp,
int sample, time_sample;
unsigned int i;
+ timestamp -= sc->time_offset;
+
sample = av_index_search_timestamp(st, timestamp, flags);
av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample);
if (sample < 0 && st->nb_index_entries && timestamp < st->index_entries[0].timestamp)
--
2.13.0
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel