From: Keith Lawson <[email protected]>

---
I created this patch to make the action for EOF on the secondary input 
configurable with the overlay filter so I could use a filtergraph that combines 
the trim, delogo and overlay filters into a filtergraph to "mask" a portion of 
a video like this:

avconv -y -i test.avi -codec:v:0 wmv2 -ar 11025 -b 9000k -vf 
'[in]split[split_main][split_delogo];[split_delogo]trim=start=5:end=10,delogo=0:0:640:480[delogoed];[split_main][delogoed]overlay=seofact=pass[out]'
 outfile.avi

I've tested the command above and it works for masking most portions of videos 
however I'm encountering problems masking near the end of videos. avconv 
quickly consumes all memory and swap sometimes when the trim range is near the 
end of the video. The process eventually finishes but there's obviously a 
memory issue. I'm hoping someone can assist me in troubleshooting that problem.

I'd like to complete the work required to have the new switch added to the 
master repository so I'm submitting it here for review. I haven't documented 
the new switch yet so pointers to how to do that would be helpful.


 libavfilter/vf_overlay.c | 40 +++++++++++++++++++++++++++++++++-------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index 41940d0..d0b3c48 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -60,6 +60,16 @@ enum var_name {
     VAR_VARS_NB
 };
 
+enum SEOFAct {
+    SEOFACT_REP,
+    SEOFACT_ENDALL,
+    SEOFACT_PASS
+};
+
+static const char *seofact_str[] = {
+        "rep", "endall", "pass"
+};
+
 #define MAIN    0
 #define OVERLAY 1
 
@@ -72,6 +82,8 @@ typedef struct {
 
     char *x_expr, *y_expr;
 
+    enum SEOFAct seofact;       ///< 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 
seofact:%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),
+           seofact_str[s->seofact]);
 
     if (s->x < 0 || s->y < 0 ||
         s->x + var_values[VAR_OVERLAY_W] > var_values[VAR_MAIN_W] ||
@@ -291,8 +304,16 @@ 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->seofact == SEOFACT_REP)
         blend_frame(ctx, s->main, s->over_prev, s->x, s->y);
+    /* End both streams */
+    else if (s->over_prev && s->seofact == SEOFACT_ENDALL)
+        return AVERROR_EOF;
+    /* Pass through main input */
+    else if (s->over_prev && s->seofact == SEOFACT_PASS)
+        return output_frame(ctx);
+
     return output_frame(ctx);
 }
 
@@ -311,8 +332,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 'seofact' */
     if (!s->over_next) {
         ret = ff_request_frame(ctx->inputs[OVERLAY]);
         if (ret == AVERROR_EOF)
@@ -351,9 +371,15 @@ static int request_frame(AVFilterLink *outlink)
 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM
 static const AVOption options[] = {
     { "x", "Horizontal position of the left edge of the overlaid video on the "
-        "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 "
-        "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 },
+    { "seofact", "Action to take when encountering EOF from secondary input ",
+                       OFFSET(seofact), AV_OPT_TYPE_INT, { .i64 = SEOFACT_REP 
},
+                       SEOFACT_REP, SEOFACT_PASS, .flags = FLAGS, "seofact" },
+    { "rep", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = 
SEOFACT_REP }, .flags = FLAGS, "seofact" },
+    { "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = 
SEOFACT_ENDALL }, .flags = FLAGS, "seofact" },
+    { "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = 
SEOFACT_PASS }, .flags = FLAGS, "seofact" },
     { NULL },
 };
 
-- 
1.8.4.3

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to