lavfi/overlay: implement shortest option

Force termination when the overlay stream ends. Simplify scripting logic,
for example when an infinite source is used to generate a background for
a composite video.
This commit is contained in:
Stefano Sabatini 2013-02-15 00:26:22 +01:00
parent 7f07c61c2f
commit 3d77a27548
3 changed files with 21 additions and 1 deletions

View File

@ -3881,6 +3881,10 @@ same as @var{overlay_w} and @var{overlay_h}
@item rgb @item rgb
If set to 1, force the filter to accept inputs in the RGB If set to 1, force the filter to accept inputs in the RGB
color space. Default value is 0. 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 @end table
Be aware that frames are taken from each input video in timestamp 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' ffplay input.avi -vf 'split[b], pad=iw*2[src], [b]deshake, [src]overlay=w'
@end example @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 @item
Chain several overlays in cascade: Chain several overlays in cascade:
@example @example

View File

@ -30,7 +30,7 @@
#define LIBAVFILTER_VERSION_MAJOR 3 #define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 38 #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, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
LIBAVFILTER_VERSION_MINOR, \ LIBAVFILTER_VERSION_MINOR, \

View File

@ -91,6 +91,7 @@ typedef struct {
int main_pix_step[4]; ///< steps per pixel for each plane of the main output 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 overlay_pix_step[4]; ///< steps per pixel for each plane of the overlay
int hsub, vsub; ///< chroma subsampling values int hsub, vsub; ///< chroma subsampling values
int shortest; ///< terminate stream when the shortest input terminates
char *x_expr, *y_expr; char *x_expr, *y_expr;
} OverlayContext; } 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 }, { "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 }, { "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 }, {"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}, {NULL},
}; };
@ -560,6 +562,8 @@ static int request_frame(AVFilterLink *outlink)
/* EOF on main is reported immediately */ /* EOF on main is reported immediately */
if (ret == AVERROR_EOF && input == OVERLAY) { if (ret == AVERROR_EOF && input == OVERLAY) {
over->overlay_eof = 1; over->overlay_eof = 1;
if (over->shortest)
return ret;
if ((ret = try_filter_next_frame(ctx)) != AVERROR(EAGAIN)) if ((ret = try_filter_next_frame(ctx)) != AVERROR(EAGAIN))
return ret; return ret;
ret = 0; /* continue requesting frames on main */ ret = 0; /* continue requesting frames on main */