[FFmpeg-cvslog] avfilter/vf_extractplanes: switch to activate()

Paul B Mahol git at videolan.org
Mon Mar 7 16:30:49 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Mon Mar  7 14:01:11 2022 +0100| [7238541d3969f3ddfede80e01da7a82ad7d69190] | committer: Paul B Mahol

avfilter/vf_extractplanes: switch to activate()

Fixes hang at end of input with this command:

ffmpeg -f lavfi -i testsrc2=d=50,format=yuv444p -lavfi \
"extractplanes=y+u+v[y][u][v];[y]tpad=start=0[y];[u]tpad=start=0[u];[v]negate[v];[y][u][v]vstack=3" -f null -

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=7238541d3969f3ddfede80e01da7a82ad7d69190
---

 libavfilter/vf_extractplanes.c | 105 ++++++++++++++++++++++++++---------------
 1 file changed, 68 insertions(+), 37 deletions(-)

diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 5b5fd6e232..0b26d92269 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -288,52 +288,82 @@ static void extract_from_packed(uint8_t *dst, int dst_linesize,
     }
 }
 
-static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
+static int extract_plane(AVFilterLink *outlink, AVFrame *frame)
 {
-    AVFilterContext *ctx = inlink->dst;
+    AVFilterContext *ctx = outlink->src;
     ExtractPlanesContext *s = ctx->priv;
-    int i, eof = 0, ret = 0;
+    const int idx = s->map[FF_OUTLINK_IDX(outlink)];
+    AVFrame *out;
+
+    out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out)
+        return AVERROR(ENOMEM);
+    av_frame_copy_props(out, frame);
+
+    if (s->is_packed) {
+        extract_from_packed(out->data[0], out->linesize[0],
+                            frame->data[0], frame->linesize[0],
+                            outlink->w, outlink->h,
+                            s->depth,
+                            s->step, idx);
+    } else {
+        av_image_copy_plane(out->data[0], out->linesize[0],
+                            frame->data[idx], frame->linesize[idx],
+                            s->linesize[idx], outlink->h);
+    }
 
-    for (i = 0; i < ctx->nb_outputs; i++) {
-        AVFilterLink *outlink = ctx->outputs[i];
-        const int idx = s->map[i];
-        AVFrame *out;
+    return ff_filter_frame(outlink, out);
+}
 
-        if (ff_outlink_get_status(outlink))
-            continue;
+static int activate(AVFilterContext *ctx)
+{
+    AVFilterLink *inlink = ctx->inputs[0];
+    int status, ret;
+    AVFrame *in;
+    int64_t pts;
 
-        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
-        if (!out) {
-            ret = AVERROR(ENOMEM);
-            break;
+    for (int i = 0; i < ctx->nb_outputs; i++) {
+        FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx);
+    }
+
+    ret = ff_inlink_consume_frame(inlink, &in);
+    if (ret < 0)
+        return ret;
+    if (ret > 0) {
+        for (int i = 0; i < ctx->nb_outputs; i++) {
+            if (ff_outlink_get_status(ctx->outputs[i]))
+                continue;
+
+            ret = extract_plane(ctx->outputs[i], in);
+            if (ret < 0)
+                break;
         }
-        av_frame_copy_props(out, frame);
-
-        if (s->is_packed) {
-            extract_from_packed(out->data[0], out->linesize[0],
-                                frame->data[0], frame->linesize[0],
-                                outlink->w, outlink->h,
-                                s->depth,
-                                s->step, idx);
-        } else {
-            av_image_copy_plane(out->data[0], out->linesize[0],
-                                frame->data[idx], frame->linesize[idx],
-                                s->linesize[idx], outlink->h);
+
+        av_frame_free(&in);
+        if (ret < 0)
+            return ret;
+    }
+
+    if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
+        for (int i = 0; i < ctx->nb_outputs; i++) {
+            if (ff_outlink_get_status(ctx->outputs[i]))
+                continue;
+            ff_outlink_set_status(ctx->outputs[i], status, pts);
         }
+        return 0;
+    }
 
-        ret = ff_filter_frame(outlink, out);
-        if (ret == AVERROR_EOF)
-            eof++;
-        else if (ret < 0)
-            break;
+    for (int i = 0; i < ctx->nb_outputs; i++) {
+        if (ff_outlink_get_status(ctx->outputs[i]))
+            continue;
+
+        if (ff_outlink_frame_wanted(ctx->outputs[i])) {
+            ff_inlink_request_frame(inlink);
+            return 0;
+        }
     }
-    av_frame_free(&frame);
 
-    if (eof == ctx->nb_outputs)
-        ret = AVERROR_EOF;
-    else if (ret == AVERROR_EOF)
-        ret = 0;
-    return ret;
+    return FFERROR_NOT_READY;
 }
 
 static av_cold int init(AVFilterContext *ctx)
@@ -368,7 +398,6 @@ static const AVFilterPad extractplanes_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = filter_frame,
         .config_props = config_input,
     },
 };
@@ -379,6 +408,7 @@ const AVFilter ff_vf_extractplanes = {
     .priv_size     = sizeof(ExtractPlanesContext),
     .priv_class    = &extractplanes_class,
     .init          = init,
+    .activate      = activate,
     FILTER_INPUTS(extractplanes_inputs),
     .outputs       = NULL,
     FILTER_QUERY_FUNC(query_formats),
@@ -411,6 +441,7 @@ const AVFilter ff_vf_alphaextract = {
                       "grayscale image component."),
     .priv_size      = sizeof(ExtractPlanesContext),
     .init           = init_alphaextract,
+    .activate       = activate,
     FILTER_INPUTS(extractplanes_inputs),
     FILTER_OUTPUTS(alphaextract_outputs),
     FILTER_QUERY_FUNC(query_formats),



More information about the ffmpeg-cvslog mailing list