From 839eb1c77da9309477e5e51bdc1194de3d8dcfa4 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 24 Oct 2015 21:06:38 +0200 Subject: [PATCH] lavfi/select: add support for concatdec_select option This option can be used to select useful frames from an ffconcat file which is using inpoints and outpoints but where the source files are not intra frame only. Reviewed-by: Stefano Sabatini Signed-off-by: Marton Balint --- doc/filters.texi | 26 ++++++++++++++++++++++++++ libavfilter/f_select.c | 27 +++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/doc/filters.texi b/doc/filters.texi index f351390e28..25134fd886 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -13196,6 +13196,25 @@ value between 0 and 1 to indicate a new scene; a low value reflects a low probability for the current frame to introduce a new scene, while a higher value means the current frame is more likely to be one (see the example below) +@item concatdec_select +The concat demuxer can select only part of a concat input file by setting an +inpoint and an outpoint, but the output packets may not be entirely contained +in the selected interval. By using this variable, it is possible to skip frames +generated by the concat demuxer which are not exactly contained in the selected +interval. + +This works by comparing the frame pts against the @var{lavf.concat.start_time} +and the @var{lavf.concat.duration} packet metadata values which are also +present in the decoded frames. + +The @var{concatdec_select} variable is -1 if the frame pts is at least +start_time and either the duration metadata is missing or the frame pts is less +than start_time + duration, 0 otherwise, and NaN if the start_time metadata is +missing. + +That basically means that an input frame is selected if its pts is within the +interval set by the concat demuxer. + @end table The default value of the select expression is "1". @@ -13270,6 +13289,13 @@ Send even and odd frames to separate outputs, and compose them: @example select=n=2:e='mod(n, 2)+1' [odd][even]; [odd] pad=h=2*ih [tmp]; [tmp][even] overlay=y=h @end example + +@item +Select useful frames from an ffconcat file which is using inpoints and +outpoints but where the source files are not intra frame only. +@example +ffmpeg -copyts -vsync 0 -segment_time_metadata 1 -i input.ffconcat -vf select=concatdec_select -af aselect=concatdec_select output.avi +@end example @end itemize @section selectivecolor diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 2b926e1e14..52f474eb93 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -82,6 +82,8 @@ static const char *const var_names[] = { "scene", + "concatdec_select", ///< frame is within the interval set by the concat demuxer + NULL }; @@ -132,6 +134,8 @@ enum var_name { VAR_SCENE, + VAR_CONCATDEC_SELECT, + VAR_VARS_NB }; @@ -278,6 +282,28 @@ static double get_scene_score(AVFilterContext *ctx, AVFrame *frame) return ret; } +static double get_concatdec_select(AVFrame *frame, int64_t pts) +{ + AVDictionary *metadata = av_frame_get_metadata(frame); + AVDictionaryEntry *start_time_entry = av_dict_get(metadata, "lavf.concatdec.start_time", NULL, 0); + AVDictionaryEntry *duration_entry = av_dict_get(metadata, "lavf.concatdec.duration", NULL, 0); + if (start_time_entry) { + int64_t start_time = strtoll(start_time_entry->value, NULL, 10); + if (pts >= start_time) { + if (duration_entry) { + int64_t duration = strtoll(duration_entry->value, NULL, 10); + if (pts < start_time + duration) + return -1; + else + return 0; + } + return -1; + } + return 0; + } + return NAN; +} + #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) @@ -297,6 +323,7 @@ static void select_frame(AVFilterContext *ctx, AVFrame *frame) select->var_values[VAR_T ] = TS2D(frame->pts) * av_q2d(inlink->time_base); select->var_values[VAR_POS] = av_frame_get_pkt_pos(frame) == -1 ? NAN : av_frame_get_pkt_pos(frame); select->var_values[VAR_KEY] = frame->key_frame; + select->var_values[VAR_CONCATDEC_SELECT] = get_concatdec_select(frame, av_rescale_q(frame->pts, inlink->time_base, AV_TIME_BASE_Q)); switch (inlink->type) { case AVMEDIA_TYPE_AUDIO: