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]
