diff --git a/doc/filters.texi b/doc/filters.texi index 75d17594af..6b7ee89ac3 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -3881,6 +3881,10 @@ same as @var{overlay_w} and @var{overlay_h} @item rgb If set to 1, force the filter to accept inputs in the RGB color space. Default value is 0. + +@item shortest +If set to 1, force the output to terminate when the shortest input +terminates. Default value is 0. @end table Be aware that frames are taken from each input video in timestamp @@ -3940,6 +3944,18 @@ The above command is the same as: ffplay input.avi -vf 'split[b], pad=iw*2[src], [b]deshake, [src]overlay=w' @end example +@item +Compose output by putting two input videos side to side: +@example +ffmpeg -i left.avi -i right.avi -filter_complex " +nullsrc=size=200x100 [background]; +[0:v] setpts=PTS-STARTPTS, scale=100x100 [left]; +[1:v] setpts=PTS-STARTPTS, scale=100x100 [right]; +[background][left] overlay=shortest=1 [background+left]; +[background+left][right] overlay=shortest=1:x=100 [left+right] +" +@end example + @item Chain several overlays in cascade: @example diff --git a/libavfilter/version.h b/libavfilter/version.h index 3a2db17f5d..9f01e85695 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MINOR 38 -#define LIBAVFILTER_VERSION_MICRO 104 +#define LIBAVFILTER_VERSION_MICRO 105 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 7c615b4f20..857fbafb06 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -91,6 +91,7 @@ typedef struct { int main_pix_step[4]; ///< steps per pixel for each plane of the main output int overlay_pix_step[4]; ///< steps per pixel for each plane of the overlay int hsub, vsub; ///< chroma subsampling values + int shortest; ///< terminate stream when the shortest input terminates char *x_expr, *y_expr; } OverlayContext; @@ -102,6 +103,7 @@ static const AVOption overlay_options[] = { { "x", "set the x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, { "y", "set the y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str = "0"}, CHAR_MIN, CHAR_MAX, FLAGS }, {"rgb", "force packed RGB in input and output", OFFSET(allow_packed_rgb), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS }, + { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS }, {NULL}, }; @@ -560,6 +562,8 @@ static int request_frame(AVFilterLink *outlink) /* EOF on main is reported immediately */ if (ret == AVERROR_EOF && input == OVERLAY) { over->overlay_eof = 1; + if (over->shortest) + return ret; if ((ret = try_filter_next_frame(ctx)) != AVERROR(EAGAIN)) return ret; ret = 0; /* continue requesting frames on main */