This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 3a8c1f29b7a154bf5cfc9600e8d58d3adeda4f44
Author:     Julius Bairaktaris <[email protected]>
AuthorDate: Sun Aug 30 16:53:59 2026 +0200
Commit:     ArazIusubov <[email protected]>
CommitDate: Wed Sep 16 22:05:28 2026 +0000

    avfilter/amf: flush the component at EOF with an activate callback
    
    The AMF filters ran off a filter_frame callback, which has no way to tell
    a component that no more input is coming. Anything a component still held
    when the input link ended was lost, and there was nowhere to call
    AMFComponent::Drain(). The output side also assumed that every submission
    completes before the next one: the component was queried once per input,
    AMF_INPUT_FULL was fatal for the scaler, the enhancer and the converter
    and accepted as success by the frame rate converter, which released the
    surface and lost the frame, and every output produced during a call was
    given the properties of the frame submitted in that call.
    
    Convert all four filters to an activate callback that follows the
    component contract from AMD's programming guides. Every activation first
    polls the component for output that is already waiting, so output that
    arrives after the activation that submitted it is delivered without
    another input; then one input frame is consumed, and a submission that
    produces nothing forwards the request for input upstream instead of
    waiting for the sink to ask again. A submission that returns
    AMF_INPUT_FULL is repeated after the output side has been emptied, and
    the same surface is kept until the component accepts it. On EOF the
    pre-converter is drained first, with every surface it still returns
    handed to the scaler, then the component, and the status is forwarded
    only once QueryOutput() reports AMF_EOF; an empty AMF_REPEAT in between
    means the component is still working and is polled again. Drain() itself
    is repeated on AMF_INPUT_FULL the same way.
    
    Output frames take their properties from a queue of property copies of
    the submitted frames, so an output that arrives a submission late or
    during the drain still carries the right metadata and side data. The
    scaler, the converter and the enhancer return one output per input in
    submission order, so each output takes the oldest queued entry, and
    repeated or missing timestamps cannot pair it with another input. The
    frame rate converter emits two outputs per input, so it matches by pts,
    taking the newest queued input not after the output; its interpolated
    frame inherits from the preceding input and halves its duration as
    before. The copies keep the input dimensions, since
    av_frame_copy_props() drops pan-scan side data when they differ; the
    copy onto the output frame then drops it only when the filter resizes.
    
    vf_frc_amf.c moves onto the shared submission and output path instead of
    duplicating it. The FRC mode is set once after Init() rather than before
    every submission, and the output frame rate is doubled only when the
    converter is enabled; it was doubled unconditionally before, so enable=0
    advertised twice the rate it emitted. color_profile is set to unknown so
    the shared path leaves its output untagged, as before.
    
    Tested on Windows 11, RX 9070 XT, driver 32.0.31041.1004. Every
    component answers Drain() with AMF_OK and the next QueryOutput() with
    AMF_EOF, and the frame rate converter returns its interpolated frame with
    AMF_REPEAT and data attached, so data has to be checked independently of
    the result code. sr_amf with every algorithm, with and without the
    pre-converter, vpp_amf and vqe_amf are byte identical by framecrc to the
    previous revision over AMF, D3D11VA and DXVA2 surfaces and with software
    input; frc_amf returns the same 2N-1 frames with the same timestamps,
    durations and sizes, with colour tags present on every frame including
    the interpolated ones, and its pixels are not comparable because the
    component is not deterministic between runs. Pan-scan side data from an
    MPEG-2 decode is present on every frame out of vqe_amf, vpp_amf and
    frc_amf and dropped by a resizing sr_amf. A truncated read with -frames:v
    still terminates. AMF_INPUT_FULL and output delayed past the submitting
    activation do not occur on this device, so those paths are exercised by
    inspection only.
    
    Assisted-by: Claude Opus 5
    Assisted-by: Claude Fable 5.1
    Signed-off-by: Julius Bairaktaris <[email protected]>
---
 libavfilter/vf_amf_common.c | 307 ++++++++++++++++++++++++++++++++++----------
 libavfilter/vf_amf_common.h |   8 ++
 libavfilter/vf_frc_amf.c    |  87 ++-----------
 libavfilter/vf_sr_amf.c     |   2 +-
 libavfilter/vf_vpp_amf.c    |   2 +-
 libavfilter/vf_vqe_amf.c    |   2 +-
 6 files changed, 257 insertions(+), 151 deletions(-)

diff --git a/libavfilter/vf_amf_common.c b/libavfilter/vf_amf_common.c
index b3a18ed9b1..5cd93aef2b 100644
--- a/libavfilter/vf_amf_common.c
+++ b/libavfilter/vf_amf_common.c
@@ -21,6 +21,7 @@
 #include "libavutil/avassert.h"
 #include "avfilter.h"
 #include "avfilter_internal.h"
+#include "filters.h"
 #include "formats.h"
 #include "libavutil/mem.h"
 #include "libavutil/imgutils.h"
@@ -76,6 +77,13 @@ void amf_filter_uninit(AVFilterContext *avctx)
         ctx->pre_converter = NULL;
     }
 
+    if (ctx->pending) {
+        AVFrame *props;
+        while (av_fifo_read(ctx->pending, &props, 1) >= 0)
+            av_frame_free(&props);
+        av_fifo_freep2(&ctx->pending);
+    }
+
     if (ctx->master_display)
         av_freep(&ctx->master_display);
 
@@ -88,79 +96,85 @@ void amf_filter_uninit(AVFilterContext *avctx)
     av_buffer_unref(&ctx->hwframes_out_ref);
 }
 
-int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in)
+static int amf_queue_props(AVFilterContext *avctx, const AVFrame *in)
 {
-    AVFilterContext             *avctx = inlink->dst;
-    AMFFilterContext             *ctx = avctx->priv;
-    AVFilterLink                *outlink = avctx->outputs[0];
-    AMF_RESULT  res;
-    AMFSurface *surface_in;
-    AMFSurface *surface_out;
-    AMFData *data_out = NULL;
-    enum AVColorSpace out_colorspace;
-    enum AVColorRange out_color_range;
-
-    AVFrame *out = NULL;
-    int got_frame = 0;
-    int ret = 0;
-
-    if (!ctx->component)
-        return AVERROR(EINVAL);
+    AMFFilterContext *ctx = avctx->priv;
+    AVFrame *props = av_frame_alloc();
+    int ret;
 
-    ret = amf_avframe_to_amfsurface(avctx, in, &surface_in);
+    if (!props)
+        return AVERROR(ENOMEM);
+    props->width  = in->width;
+    props->height = in->height;
+    ret = av_frame_copy_props(props, in);
+    if (ret >= 0)
+        ret = av_fifo_write(ctx->pending, &props, 1);
     if (ret < 0)
-        goto fail;
-
-    if (ctx->pre_converter) {
-        AMFGuid guid = IID_AMFSurface();
-        AMFData *data_conv = NULL;
-        AMFSurface *surface_conv = NULL;
-
-        do {
-            res = ctx->pre_converter->pVtbl->SubmitInput(ctx->pre_converter, 
(AMFData*)surface_in);
-            if (res == AMF_INPUT_FULL)
-                av_usleep(100);
-        } while (res == AMF_INPUT_FULL);
-        surface_in->pVtbl->Release(surface_in);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"Converter SubmitInput() failed with error %d\n", res);
-
-        do {
-            res = ctx->pre_converter->pVtbl->QueryOutput(ctx->pre_converter, 
&data_conv);
-            if (res == AMF_REPEAT && !data_conv)
-                av_usleep(100);
-        } while (res == AMF_REPEAT && !data_conv);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK && data_conv, 
AVERROR_UNKNOWN, "Converter QueryOutput() failed with error %d\n", res);
-
-        res = data_conv->pVtbl->QueryInterface(data_conv, &guid, 
(void**)&surface_conv);
-        data_conv->pVtbl->Release(data_conv);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"Converter QueryInterface(IID_AMFSurface) failed with error %d\n", res);
-        surface_in = surface_conv;
-    }
+        av_frame_free(&props);
+    return ret;
+}
 
-    res = ctx->component->pVtbl->SubmitInput(ctx->component, 
(AMFData*)surface_in);
-    surface_in->pVtbl->Release(surface_in); // release surface after use
-    AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"SubmitInput() failed with error %d\n", res);
+static int amf_receive_surface(AVFilterContext *avctx, AMFComponent 
*component, AMFSurface **surface)
+{
+    AMFGuid guid = IID_AMFSurface();
+    AMFData *data = NULL;
+    AMF_RESULT res;
 
-    while (1) {
-        AMFGuid guid = IID_AMFSurface();
+    *surface = NULL;
+    res = component->pVtbl->QueryOutput(component, &data);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK || res == AMF_REPEAT || res == 
AMF_EOF,
+                        AVERROR_UNKNOWN, "QueryOutput() failed with error 
%d\n", res);
+    if (!data)
+        return res == AMF_EOF ? AVERROR_EOF : 0;
 
-        res = ctx->component->pVtbl->QueryOutput(ctx->component, &data_out);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK || res == AMF_REPEAT, 
AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res);
-        if (!data_out)
-            break;
+    res = data->pVtbl->QueryInterface(data, &guid, (void**)surface);
+    data->pVtbl->Release(data);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
+    return 1;
+}
 
-        res = data_out->pVtbl->QueryInterface(data_out, &guid, 
(void**)&surface_out); // query for buffer interface
-        data_out->pVtbl->Release(data_out);
-        data_out = NULL;
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
+static int amf_deliver_output(AVFilterContext *avctx)
+{
+    AMFFilterContext             *ctx = avctx->priv;
+    AVFilterLink             *outlink = avctx->outputs[0];
+    AMFSurface *surface;
+    AVFrame *props, *out;
+    enum AVColorSpace out_colorspace;
+    enum AVColorRange out_color_range;
+    int64_t pts;
+    int ret, count = 0;
 
-        out = amf_amfsurface_to_avframe(avctx, surface_out);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to 
convert AMFSurface to AVFrame\n");
+    while ((ret = amf_receive_surface(avctx, ctx->component, &surface)) > 0) {
+        pts = surface->pVtbl->GetPts(surface);
+        out = amf_amfsurface_to_avframe(avctx, surface);
+        if (!out)
+            return AVERROR(ENOMEM);
 
-        ret = av_frame_copy_props(out, in);
-        if (ret < 0)
-            goto fail;
-        out->pts = surface_out->pVtbl->GetPts(surface_out);
+        if (ctx->outputs_per_input > 1) {
+            while (av_fifo_can_read(ctx->pending) > 1) {
+                av_fifo_peek(ctx->pending, &props, 1, 1);
+                if (props->pts > pts)
+                    break;
+                av_fifo_read(ctx->pending, &props, 1);
+                av_frame_free(&props);
+            }
+            props = NULL;
+            if (av_fifo_can_read(ctx->pending))
+                av_fifo_peek(ctx->pending, &props, 1, 0);
+            ret = props ? av_frame_copy_props(out, props) : 0;
+        } else {
+            props = NULL;
+            av_fifo_read(ctx->pending, &props, 1);
+            ret = props ? av_frame_copy_props(out, props) : 0;
+            av_frame_free(&props);
+        }
+        if (ret < 0) {
+            av_frame_free(&out);
+            return ret;
+        }
+        out->pts = pts;
+        if (ctx->outputs_per_input > 1)
+            out->duration /= ctx->outputs_per_input;
 
         out_colorspace = AVCOL_SPC_UNSPECIFIED;
 
@@ -204,21 +218,168 @@ int amf_filter_filter_frame(AVFilterLink *inlink, 
AVFrame *in)
             out->colorspace = AVCOL_SPC_RGB;
 
         ret = ff_filter_frame(outlink, out);
-        out = NULL;
         if (ret < 0)
-            goto fail;
-        got_frame = 1;
+            return ret;
+        count++;
     }
 
-    av_frame_free(&in);
-    return got_frame ? ret : 0;
+    return ret < 0 ? ret : count;
+}
+
+static int amf_submit_surface(AVFilterContext *avctx, AMFComponent *component, 
AMFSurface *surface,
+                              int (*deliver)(AVFilterContext *avctx))
+{
+    AMF_RESULT res;
+    int ret = 0;
+
+    while ((res = component->pVtbl->SubmitInput(component, (AMFData*)surface)) 
== AMF_INPUT_FULL) {
+        ret = deliver(avctx);
+        if (ret < 0)
+            break;
+        if (!ret)
+            av_usleep(100);
+    }
+    surface->pVtbl->Release(surface);
+    if (ret < 0)
+        return ret;
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() 
failed with error %d\n", res);
+    return 0;
+}
+
+static int amf_forward_converted(AVFilterContext *avctx)
+{
+    AMFFilterContext *ctx = avctx->priv;
+    AMFSurface *surface;
+    int ret, count = 0;
+
+    while ((ret = amf_receive_surface(avctx, ctx->pre_converter, &surface)) > 
0) {
+        ret = amf_submit_surface(avctx, ctx->component, surface, 
amf_deliver_output);
+        if (ret < 0)
+            return ret;
+        count++;
+    }
+
+    return ret < 0 ? ret : count;
+}
+
+static int amf_drain_component(AVFilterContext *avctx, AMFComponent *component,
+                               int (*deliver)(AVFilterContext *avctx))
+{
+    AMF_RESULT res;
+    int ret;
+
+    while ((res = component->pVtbl->Drain(component)) == AMF_INPUT_FULL) {
+        ret = deliver(avctx);
+        if (ret < 0)
+            return ret;
+        if (!ret)
+            av_usleep(100);
+    }
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed 
with error %d\n", res);
+
+    while ((ret = deliver(avctx)) >= 0)
+        if (!ret)
+            av_usleep(100);
+
+    return ret == AVERROR_EOF ? 0 : ret;
+}
+
+int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext             *avctx = inlink->dst;
+    AMFFilterContext             *ctx = avctx->priv;
+    AMFSurface *surface_in;
+    int ret;
+
+    if (!ctx->component) {
+        av_frame_free(&in);
+        return AVERROR(EINVAL);
+    }
+
+    ret = amf_avframe_to_amfsurface(avctx, in, &surface_in);
+    if (ret < 0)
+        goto fail;
+
+    ret = amf_queue_props(avctx, in);
+    if (ret < 0) {
+        surface_in->pVtbl->Release(surface_in);
+        goto fail;
+    }
+
+    if (ctx->pre_converter) {
+        ret = amf_submit_surface(avctx, ctx->pre_converter, surface_in, 
amf_forward_converted);
+        if (ret >= 0)
+            ret = amf_forward_converted(avctx);
+    } else
+        ret = amf_submit_surface(avctx, ctx->component, surface_in, 
amf_deliver_output);
+    if (ret >= 0)
+        ret = amf_deliver_output(avctx);
 fail:
     av_frame_free(&in);
-    av_frame_free(&out);
     return ret;
 }
 
+static int amf_poll_output(AVFilterContext *avctx)
+{
+    AMFFilterContext *ctx = avctx->priv;
+    int ret = 0;
 
+    if (!av_fifo_can_read(ctx->pending))
+        return 0;
+    if (ctx->pre_converter)
+        ret = amf_forward_converted(avctx);
+    if (ret >= 0)
+        ret = amf_deliver_output(avctx);
+    return ret;
+}
+
+int amf_filter_activate(AVFilterContext *avctx)
+{
+    AMFFilterContext             *ctx = avctx->priv;
+    AVFilterLink              *inlink = avctx->inputs[0];
+    AVFilterLink             *outlink = avctx->outputs[0];
+    AVFrame *in = NULL;
+    int ret;
+
+    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+    if (!ctx->eof) {
+        if (ctx->component) {
+            ret = amf_poll_output(avctx);
+            if (ret < 0)
+                return ret;
+        }
+        ret = ff_inlink_consume_frame(inlink, &in);
+        if (ret < 0)
+            return ret;
+        if (in) {
+            ret = amf_filter_filter_frame(inlink, in);
+            if (ret < 0)
+                return ret;
+        } else if (ff_inlink_acknowledge_status(inlink, &ctx->status, 
&ctx->status_pts))
+            ctx->eof = 1;
+    }
+
+    if (ctx->eof) {
+        if (ctx->component && !ctx->drained) {
+            ctx->drained = 1;
+            if (ctx->pre_converter) {
+                ret = amf_drain_component(avctx, ctx->pre_converter, 
amf_forward_converted);
+                if (ret < 0)
+                    return ret;
+            }
+            ret = amf_drain_component(avctx, ctx->component, 
amf_deliver_output);
+            if (ret < 0)
+                return ret;
+        }
+        ff_outlink_set_status(outlink, ctx->status, ctx->status_pts);
+        return 0;
+    }
+
+    FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+    return FFERROR_NOT_READY;
+}
 
 int amf_setup_input_output_formats(AVFilterContext *avctx,
                                     const enum AVPixelFormat *input_pix_fmts)
@@ -356,6 +517,12 @@ int amf_init_filter_config(AVFilterLink *outlink, enum 
AVPixelFormat *in_format)
     if (err < 0)
         return err;
 
+    if (!ctx->pending) {
+        ctx->pending = av_fifo_alloc2(1, sizeof(AVFrame*), 
AV_FIFO_FLAG_AUTO_GROW);
+        if (!ctx->pending)
+            return AVERROR(ENOMEM);
+    }
+
     av_buffer_unref(&ctx->amf_device_ref);
     av_buffer_unref(&ctx->hwframes_in_ref);
     av_buffer_unref(&ctx->hwframes_out_ref);
diff --git a/libavfilter/vf_amf_common.h b/libavfilter/vf_amf_common.h
index 4910b23e9b..9af3d2ddda 100644
--- a/libavfilter/vf_amf_common.h
+++ b/libavfilter/vf_amf_common.h
@@ -20,6 +20,7 @@
 #define AVFILTER_AMF_COMMON_H
 
 #include "avfilter.h"
+#include "libavutil/fifo.h"
 
 #include "AMF/core/Surface.h"
 #include "AMF/components/Component.h"
@@ -32,6 +33,12 @@ typedef struct AMFFilterContext {
     int width, height;
     enum AVPixelFormat format;
     enum AVPixelFormat format_opt;
+    int                eof;
+    int                drained;
+    int                status;
+    int64_t            status_pts;
+    AVFifo            *pending;
+    int                outputs_per_input;
     int scale_type;
     int in_color_range;
     int in_primaries;
@@ -81,5 +88,6 @@ AVFrame *amf_amfsurface_to_avframe(AVFilterContext *avctx, 
AMFSurface* pSurface)
 int amf_avframe_to_amfsurface(AVFilterContext *avctx, const AVFrame *frame, 
AMFSurface** ppSurface);
 int amf_setup_input_output_formats(AVFilterContext *avctx, const enum 
AVPixelFormat *input_pix_fmts);
 int amf_filter_filter_frame(AVFilterLink *inlink, AVFrame *in);
+int amf_filter_activate(AVFilterContext *avctx);
 
 #endif /* AVFILTER_AMF_COMMON_H */
diff --git a/libavfilter/vf_frc_amf.c b/libavfilter/vf_frc_amf.c
index c05ab818e8..c7ef58b429 100644
--- a/libavfilter/vf_frc_amf.c
+++ b/libavfilter/vf_frc_amf.c
@@ -61,6 +61,7 @@ static int amf_frc_init(AVFilterContext *avctx) {
     AMFFRCFilterContext *ctx = avctx->priv;
 
     ctx->common.format = AV_PIX_FMT_NONE;
+    ctx->common.color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
 
     return 0;
 }
@@ -113,7 +114,10 @@ static int amf_frc_filter_config_output(AVFilterLink 
*outlink)
 
     outlink->time_base = inlink->time_base;
     ol->frame_rate = il->frame_rate;
-    ol->frame_rate.num *= 2;
+    if (frc_ctx->enable) {
+        ol->frame_rate.num *= 2;
+        amf_ctx->outputs_per_input = 2;
+    }
 
     // Possible bug: FRC must be initialized enabled to be toggleable on the 
fly after init.
     AMF_FRC_ASSIGN_PROPERTY_INT64_CHECK(avctx, amf_filter, AMF_FRC_MODE, 
FRC_x2_PRESENT);
@@ -134,6 +138,9 @@ static int amf_frc_filter_config_output(AVFilterLink 
*outlink)
     res = AMF_IFACE_CALL(amf_filter, Init, av_av_to_amf_format(in_format), 
inlink->w, inlink->h);
     AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "AMFFRC->Init() 
failed with error %d\n", res);
 
+    AMF_ASSIGN_PROPERTY_INT64(res, amf_filter, AMF_FRC_MODE, frc_ctx->enable ? 
FRC_x2_PRESENT : FRC_OFF);
+    AMF_RETURN_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, "Failed to %s 
FRC, error:%d\n", frc_ctx->enable ? "enable" : "disable", res);
+
     return 0;
 }
 
@@ -171,87 +178,10 @@ static const AVOption frc_amf_options[] = {
 
 AVFILTER_DEFINE_CLASS(frc_amf);
 
-static int amf_frc_filter_avframe(AVFilterLink *inlink, AVFrame *in)
-{
-    AVFilterContext     *avctx = inlink->dst;
-    AMFFRCFilterContext *frc_ctx = avctx->priv;
-    AMFFilterContext *amf_ctx = &frc_ctx->common;
-    AMFComponent     *amf_filter = amf_ctx->component;
-    AVFilterLink     *outlink = avctx->outputs[0];
-    AMFSurface       *surface_out = NULL;
-    AMFSurface       *surface_in = NULL;
-    FilterLink       *il = ff_filter_link(inlink);
-    FilterLink       *ol = ff_filter_link(outlink);
-    AMF_RESULT       res = AMF_FAIL;
-    AMFData          *data_out = NULL;
-    AVFrame          *out = NULL;
-    int              ret = 0;
-
-    if (!amf_filter)
-        return AVERROR(EINVAL);
-
-    ret = amf_avframe_to_amfsurface(avctx, in, &surface_in);
-    if (ret < 0)
-        goto fail;
-
-    if (frc_ctx->enable) {
-        AMF_ASSIGN_PROPERTY_INT64(res, amf_filter, AMF_FRC_MODE, 
FRC_x2_PRESENT);
-        ol->frame_rate.num = il->frame_rate.num * 2;
-    } else {
-        AMF_ASSIGN_PROPERTY_INT64(res, amf_filter, AMF_FRC_MODE, FRC_OFF);
-        ol->frame_rate.num = il->frame_rate.num;
-    }
-    AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"SubmitInput(): Failed to %s FRC, error:%d\n", frc_ctx->enable ? "enable" : 
"disable", res);
-
-    res = AMF_IFACE_CALL(amf_filter, SubmitInput, (AMFData*)surface_in);
-    AMF_IFACE_CALL(surface_in, Release);
-    surface_in = NULL;
-    AMF_GOTO_FAIL_IF_FALSE(avctx, (res == AMF_OK || res == AMF_INPUT_FULL), 
AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
-
-    while (true) {
-        res = AMF_IFACE_CALL(amf_filter, QueryOutput, &data_out);
-
-        AMF_GOTO_FAIL_IF_FALSE(avctx, (res == AMF_OK || res == AMF_REPEAT), 
AVERROR_UNKNOWN, "QueryOutput() failed with error %d\n", res);
-        if (data_out == NULL)
-            break;
-
-        AMFGuid guid = IID_AMFSurface();
-        res = AMF_IFACE_CALL(data_out, QueryInterface, &guid, 
(void**)&surface_out);
-        AMF_IFACE_CALL(data_out, Release);
-        data_out = NULL;
-        AMF_GOTO_FAIL_IF_FALSE(avctx, res == AMF_OK, AVERROR_UNKNOWN, 
"QueryInterface(IID_AMFSurface) failed with error %d\n", res);
-
-        out = amf_amfsurface_to_avframe(avctx, surface_out);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, out != NULL, AVERROR(ENOMEM), "Failed to 
convert AMFSurface to AVFrame\n");
-
-        ret = av_frame_copy_props(out, in);
-        AMF_GOTO_FAIL_IF_FALSE(avctx, ret >= 0, AVERROR(ENOMEM), "Failed to 
copy frame properties\n");
-
-        out->pts = AMF_IFACE_CALL(surface_out, GetPts);
-
-        if (frc_ctx->enable)
-            out->duration /= 2;
-
-        ret = ff_filter_frame(outlink, out);
-        out = NULL;
-        if (ret < 0)
-            goto fail;
-    }
-
-fail:
-    av_frame_unref(in);
-    av_frame_free(&in);
-    if (out != NULL)
-        av_frame_free(&out);
-
-    return ret;
-}
-
 static const AVFilterPad amf_filter_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = amf_frc_filter_avframe,
     }
 };
 
@@ -272,6 +202,7 @@ FFFilter ff_vf_frc_amf = {
     .priv_size     = sizeof(AMFFRCFilterContext),
     .init          = amf_frc_init,
     .uninit        = amf_filter_uninit,
+    .activate      = amf_filter_activate,
     FILTER_INPUTS(amf_filter_inputs),
     FILTER_OUTPUTS(amf_filter_outputs),
     FILTER_QUERY_FUNC(amf_filter_query_formats),
diff --git a/libavfilter/vf_sr_amf.c b/libavfilter/vf_sr_amf.c
index 0d8ba40b31..d589fa9970 100644
--- a/libavfilter/vf_sr_amf.c
+++ b/libavfilter/vf_sr_amf.c
@@ -250,7 +250,6 @@ static const AVFilterPad amf_filter_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = amf_filter_filter_frame,
     }
 };
 
@@ -271,6 +270,7 @@ FFFilter ff_vf_sr_amf = {
 
     .init          = amf_filter_init,
     .uninit        = amf_filter_uninit,
+    .activate      = amf_filter_activate,
     FILTER_INPUTS(amf_filter_inputs),
     FILTER_OUTPUTS(amf_filter_outputs),
     FILTER_QUERY_FUNC(&amf_filter_query_formats),
diff --git a/libavfilter/vf_vpp_amf.c b/libavfilter/vf_vpp_amf.c
index 970bb770a1..1369c40012 100644
--- a/libavfilter/vf_vpp_amf.c
+++ b/libavfilter/vf_vpp_amf.c
@@ -266,7 +266,6 @@ static const AVFilterPad amf_filter_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = amf_filter_filter_frame,
     }
 };
 
@@ -286,6 +285,7 @@ FFFilter ff_vf_vpp_amf = {
     .priv_size = sizeof(AMFFilterContext),
     .init          = amf_filter_init,
     .uninit        = amf_filter_uninit,
+    .activate      = amf_filter_activate,
     FILTER_INPUTS(amf_filter_inputs),
     FILTER_OUTPUTS(amf_filter_outputs),
     FILTER_QUERY_FUNC(amf_filter_query_formats),
diff --git a/libavfilter/vf_vqe_amf.c b/libavfilter/vf_vqe_amf.c
index e36492645d..d54661fafb 100644
--- a/libavfilter/vf_vqe_amf.c
+++ b/libavfilter/vf_vqe_amf.c
@@ -141,7 +141,6 @@ static const AVFilterPad amf_filter_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
-        .filter_frame = amf_filter_filter_frame,
     }
 };
 
@@ -161,6 +160,7 @@ FFFilter ff_vf_vqe_amf = {
     .priv_size      = sizeof(AMFVQEFilterContext),
     .init           = amf_vqe_init,
     .uninit         = amf_filter_uninit,
+    .activate      = amf_filter_activate,
     FILTER_INPUTS(amf_filter_inputs),
     FILTER_OUTPUTS(amf_filter_outputs),
     FILTER_QUERY_FUNC(&amf_filter_query_formats),

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to