vf_overlay: add eof_action switch

Signed-off-by: Anton Khirnov <anton@khirnov.net>
pull/43/merge
Keith Lawson 11 years ago committed by Anton Khirnov
parent b25e84b739
commit de203abd71
  1. 19
      doc/filters.texi
  2. 32
      libavfilter/vf_overlay.c

@ -1728,6 +1728,20 @@ overlay input width and height
@item w, h @item w, h
same as @var{overlay_w} and @var{overlay_h} same as @var{overlay_w} and @var{overlay_h}
@item eof_action
The action to take when EOF is encountered on the secondary input, accepts one
of the following values:
@table @option
@item repeat
repeat the last frame (the default)
@item endall
end both streams
@item pass
pass through the main input
@end table
@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
@ -1753,6 +1767,11 @@ avconv -i input -i logo1 -i logo2 -filter_complex
# add a transparent color layer on top of the main video, # add a transparent color layer on top of the main video,
# WxH specifies the size of the main input to the overlay filter # WxH specifies the size of the main input to the overlay filter
color=red@.3:WxH [over]; [in][over] overlay [out] color=red@.3:WxH [over]; [in][over] overlay [out]
# mask 10-20 seconds of a video by applying the delogo filter to a section
avconv -i test.avi -codec:v:0 wmv2 -ar 11025 -b:v 9000k
-vf '[in]split[split_main][split_delogo];[split_delogo]trim=start=360:end=371,delogo=0:0:640:480[delogoed];[split_main][delogoed]overlay=eof_action=pass[out]'
masked.avi
@end example @end example
You can chain together more overlays but the efficiency of such You can chain together more overlays but the efficiency of such

@ -60,6 +60,16 @@ enum var_name {
VAR_VARS_NB VAR_VARS_NB
}; };
enum EOFAction {
EOF_ACTION_REPEAT,
EOF_ACTION_ENDALL,
EOF_ACTION_PASS
};
static const char *eof_action_str[] = {
"repeat", "endall", "pass"
};
#define MAIN 0 #define MAIN 0
#define OVERLAY 1 #define OVERLAY 1
@ -72,6 +82,8 @@ typedef struct {
char *x_expr, *y_expr; char *x_expr, *y_expr;
enum EOFAction eof_action; ///< action to take on EOF from source
AVFrame *main; AVFrame *main;
AVFrame *over_prev, *over_next; AVFrame *over_prev, *over_next;
} OverlayContext; } OverlayContext;
@ -145,12 +157,13 @@ static int config_input_overlay(AVFilterLink *inlink)
s->x = res; s->x = res;
av_log(ctx, AV_LOG_VERBOSE, av_log(ctx, AV_LOG_VERBOSE,
"main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s\n", "main w:%d h:%d fmt:%s overlay x:%d y:%d w:%d h:%d fmt:%s eof_action:%s\n",
ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h, ctx->inputs[MAIN]->w, ctx->inputs[MAIN]->h,
av_get_pix_fmt_name(ctx->inputs[MAIN]->format), av_get_pix_fmt_name(ctx->inputs[MAIN]->format),
s->x, s->y, s->x, s->y,
ctx->inputs[OVERLAY]->w, ctx->inputs[OVERLAY]->h, ctx->inputs[OVERLAY]->w, ctx->inputs[OVERLAY]->h,
av_get_pix_fmt_name(ctx->inputs[OVERLAY]->format)); av_get_pix_fmt_name(ctx->inputs[OVERLAY]->format),
eof_action_str[s->eof_action]);
if (s->x < 0 || s->y < 0 || if (s->x < 0 || s->y < 0 ||
s->x + var_values[VAR_OVERLAY_W] > var_values[VAR_MAIN_W] || s->x + var_values[VAR_OVERLAY_W] > var_values[VAR_MAIN_W] ||
@ -291,8 +304,12 @@ static int output_frame(AVFilterContext *ctx)
static int handle_overlay_eof(AVFilterContext *ctx) static int handle_overlay_eof(AVFilterContext *ctx)
{ {
OverlayContext *s = ctx->priv; OverlayContext *s = ctx->priv;
if (s->over_prev) /* Repeat previous frame on secondary input */
if (s->over_prev && s->eof_action == EOF_ACTION_REPEAT)
blend_frame(ctx, s->main, s->over_prev, s->x, s->y); blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
/* End both streams */
else if (s->eof_action == EOF_ACTION_ENDALL)
return AVERROR_EOF;
return output_frame(ctx); return output_frame(ctx);
} }
@ -311,8 +328,7 @@ static int request_frame(AVFilterLink *outlink)
return ret; return ret;
} }
/* get a new frame on the overlay input, on EOF /* get a new frame on the overlay input, on EOF check setting 'eof_action' */
* reuse previous */
if (!s->over_next) { if (!s->over_next) {
ret = ff_request_frame(ctx->inputs[OVERLAY]); ret = ff_request_frame(ctx->inputs[OVERLAY]);
if (ret == AVERROR_EOF) if (ret == AVERROR_EOF)
@ -354,6 +370,12 @@ static const AVOption options[] = {
"main video.", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, "main video.", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
{ "y", "Vertical position of the top edge of the overlaid video on the " { "y", "Vertical position of the top edge of the overlaid video on the "
"main video.", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS }, "main video.", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
{ "eof_action", "Action to take when encountering EOF from secondary input ",
OFFSET(eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT },
EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, "eof_action" },
{ "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, "eof_action" },
{ "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, "eof_action" },
{ "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS }, .flags = FLAGS, "eof_action" },
{ NULL }, { NULL },
}; };

Loading…
Cancel
Save