[FFmpeg-devel] [PATCH 3/4] concatdec: add support for specifying outpoint of files
Marton Balint
cus at passwd.hu
Mon Jul 6 02:28:50 CEST 2015
Signed-off-by: Marton Balint <cus at passwd.hu>
---
doc/demuxers.texi | 13 +++++++++++++
libavformat/concatdec.c | 22 ++++++++++++++++++++--
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 4bad1c8..4ba797e 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -129,6 +129,19 @@ directive) will be reduced based on their specified In point.
Because of potential packets before the specified In point, packet timestamps
may overlap between two concatenated files.
+ at item @code{out @var{timestamp}}
+Out point of the file. When the demuxer reaches the specified timestamp in any
+of the streams, it handles it as an end of file condition. Out point is
+exclusive, which means that the demuxer will not output packets which has a
+timestamp greater or equal to Out point.
+
+This directive works best with intra frame codecs, because for non-intra frame
+ones you will usually not get enough packets to decode the last few frames
+before the specified Out point.
+
+The duration of the files (if not specified by the @code{duration}
+directive) will be reduced based on their specified Out point.
+
@item @code{stream}
Introduce a stream in the virtual file.
All subsequent stream-related directives apply to the last introduced
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index 11e6759..eaf34b0 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -44,6 +44,7 @@ typedef struct {
int64_t duration;
ConcatStream *streams;
int64_t inpoint;
+ int64_t outpoint;
int nb_streams;
} ConcatFile;
@@ -145,6 +146,7 @@ static int add_file(AVFormatContext *avf, char *filename, ConcatFile **rfile,
file->start_time = AV_NOPTS_VALUE;
file->duration = AV_NOPTS_VALUE;
file->inpoint = AV_NOPTS_VALUE;
+ file->outpoint = AV_NOPTS_VALUE;
return 0;
@@ -360,7 +362,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, "in")) {
+ } else if (!strcmp(keyword, "duration") || !strcmp(keyword, "in") || !strcmp(keyword, "out")) {
char *dur_str = get_keyword(&cursor);
int64_t dur;
if (!file) {
@@ -377,6 +379,8 @@ static int concat_read_header(AVFormatContext *avf)
file->duration = dur;
else if (!strcmp(keyword, "in"))
file->inpoint = dur;
+ else if (!strcmp(keyword, "out"))
+ file->outpoint = dur;
} else if (!strcmp(keyword, "stream")) {
if (!avformat_new_stream(avf, NULL))
FAIL(AVERROR(ENOMEM));
@@ -443,6 +447,8 @@ static int open_next_file(AVFormatContext *avf)
cat->cur_file->duration = cat->avf->duration;
if (cat->cur_file->inpoint != AV_NOPTS_VALUE)
cat->cur_file->duration -= (cat->cur_file->inpoint - file_start_time);
+ if (cat->cur_file->outpoint != AV_NOPTS_VALUE)
+ cat->cur_file->duration -= cat->avf->duration - (cat->cur_file->outpoint - file_start_time);
}
if (++fileno >= cat->nb_files) {
@@ -504,6 +510,16 @@ static int64_t get_cur_file_inpoint(ConcatContext *cat)
return file_inpoint;
}
+/* Returns true if the packet pts is greater or equal to the specified outpoint. */
+static int packet_after_outpoint(ConcatContext *cat, AVPacket *pkt)
+{
+ if (cat->cur_file->outpoint != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE) {
+ return av_compare_ts(pkt->pts, cat->avf->streams[pkt->stream_index]->time_base,
+ cat->cur_file->outpoint, AV_TIME_BASE_Q) >= 0;
+ }
+ return 0;
+}
+
static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
{
ConcatContext *cat = avf->priv_data;
@@ -520,7 +536,9 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt)
while (1) {
ret = av_read_frame(cat->avf, pkt);
- if (ret == AVERROR_EOF) {
+ if (ret == AVERROR_EOF || packet_after_outpoint(cat, pkt)) {
+ if (ret == 0)
+ av_packet_unref(pkt);
if ((ret = open_next_file(avf)) < 0)
return ret;
continue;
--
2.1.4
More information about the ffmpeg-devel
mailing list