[FFmpeg-devel] [PATCH 2/2] lavf/concatdec: add outpoint_interleave_delay option

Marton Balint cus at passwd.hu
Wed Dec 30 01:25:40 CET 2015

Wait at most outpoint_interleave_delay at outpoint before considering it an
end of file condition.

Signed-off-by: Marton Balint <cus at passwd.hu>
 doc/demuxers.texi       | 20 ++++++++++++++++----
 libavformat/concatdec.c | 13 ++++++++++---
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index fb1e4fb..b178195 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -137,8 +137,7 @@ may overlap between two concatenated files.
 @item @code{outpoint @var{timestamp}}
 Out point of the file. When the demuxer reaches the specified decoding
-timestamp in any of the streams, it handles it as an end of file condition and
-skips the current and all the remaining packets from all streams.
+timestamp it drops the current and all the remaining packets in the stream.
 Out point is exclusive, which means that the demuxer will not output packets
 with a decoding timestamp greater or equal to Out point.
@@ -148,12 +147,25 @@ are tightly interleaved. For non-intra frame codecs you will usually get
 additional packets with presentation timestamp after Out point therefore the
 decoded content will most likely contain frames after Out point too. If your
 streams are not tightly interleaved you may not get all the packets from all
-streams before Out point and you may only will be able to decode the earliest
-stream until Out point.
+streams before Out point, see @code{outpoint_interleave_delay}.
 The duration of the files (if not specified by the @code{duration}
 directive) will be reduced based on their specified Out point.
+ at item @code{outpoint_interleave_delay @var{dur}}
+With this directive you can specify how long the demuxer should wait before it
+assumes that packets with timestamps before outpoint have appeared form all
+streams, so there is no need to read the remaining packets from the input.
+If an Out point is specified and a packet timestamp is greater or equal to
+ at code{outpoint} plus the specified @code{outpoint_interleave_delay} in any of
+the streams, the demuxer handles it as an end of file condition and skips the
+current and all the remaining packets from all streams.
+The default value is 0. If your streams are not tightly interleaved, you should
+increase this, otherwise you will only be able to decode the earliest stream
+until Out point.
 @item @code{file_packet_metadata @var{key=value}}
 Metadata of the packets of the file. The specified metadata will be set for
 each file packet. You can specify this directive multiple times to add multiple
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index d226e15..afa822d 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -48,6 +48,7 @@ typedef struct {
     int64_t inpoint;
     int64_t outpoint;
     AVDictionary *metadata;
+    int64_t outpoint_interleave_delay;
     int nb_streams;
 } ConcatFile;
@@ -378,7 +379,7 @@ static int concat_read_header(AVFormatContext *avf)
             if ((ret = add_file(avf, filename, &file, &nb_files_alloc)) < 0)
                 goto fail;
-        } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint") || !strcmp(keyword, "outpoint")) {
+        } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "inpoint") || !strcmp(keyword, "outpoint") || !strcmp(keyword, "outpoint_interleave_delay")) {
             char *dur_str = get_keyword(&cursor);
             int64_t dur;
             if (!file) {
@@ -397,6 +398,8 @@ static int concat_read_header(AVFormatContext *avf)
                 file->inpoint = dur;
             else if (!strcmp(keyword, "outpoint"))
                 file->outpoint = dur;
+            else if (!strcmp(keyword, "outpoint_interleave_delay"))
+                file->outpoint_interleave_delay = dur;
         } else if (!strcmp(keyword, "file_packet_metadata")) {
             char *metadata;
             if (!file) {
@@ -567,9 +570,13 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
             return ret;
         if (packet_after_outpoint(cat, pkt)) {
+            int after_max_delay = av_compare_ts(pkt->dts, cat->avf->streams[pkt->stream_index]->time_base,
+                                                cat->cur_file->outpoint + cat->cur_file->outpoint_interleave_delay, AV_TIME_BASE_Q) >= 0;
-            if ((ret = open_next_file(avf)) < 0)
-                return ret;
+            if (after_max_delay) {
+                if ((ret = open_next_file(avf)) < 0)
+                    return ret;
+            }
         cs = &cat->cur_file->streams[pkt->stream_index];

More information about the ffmpeg-devel mailing list