diff --git a/doc/filters.texi b/doc/filters.texi index f45134bda2..8c83b4e7a2 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1728,6 +1728,20 @@ overlay input width and height @item w, 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 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, # WxH specifies the size of the main input to the overlay filter 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 You can chain together more overlays but the efficiency of such diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 5155573de6..b3591ebea1 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -60,6 +60,16 @@ enum var_name { 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 OVERLAY 1 @@ -72,6 +82,8 @@ typedef struct { char *x_expr, *y_expr; + enum EOFAction eof_action; ///< action to take on EOF from source + AVFrame *main; AVFrame *over_prev, *over_next; } OverlayContext; @@ -145,12 +157,13 @@ static int config_input_overlay(AVFilterLink *inlink) s->x = res; 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, av_get_pix_fmt_name(ctx->inputs[MAIN]->format), s->x, s->y, 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 || 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) { 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); + /* End both streams */ + else if (s->eof_action == EOF_ACTION_ENDALL) + return AVERROR_EOF; return output_frame(ctx); } @@ -311,8 +328,7 @@ static int request_frame(AVFilterLink *outlink) return ret; } - /* get a new frame on the overlay input, on EOF - * reuse previous */ + /* get a new frame on the overlay input, on EOF check setting 'eof_action' */ if (!s->over_next) { ret = ff_request_frame(ctx->inputs[OVERLAY]); 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 }, { "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 }, + { "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 }, };