[FFmpeg-devel] [PATCH 05/10] lavfi: move AVFilterLink.hw_frames_ctx to FilterLink

Anton Khirnov anton at khirnov.net
Sun Aug 11 17:42:06 EEST 2024


---
 libavfilter/avfilter.c              | 24 +++++++++++++++---------
 libavfilter/avfilter.h              |  6 ------
 libavfilter/buffersink.c            |  7 ++++++-
 libavfilter/buffersrc.c             |  5 +++--
 libavfilter/filters.h               |  8 ++++++++
 libavfilter/opencl.c                | 11 +++++++----
 libavfilter/qsvvpp.c                | 19 ++++++++++++-------
 libavfilter/vaapi_vpp.c             | 23 ++++++++++++++---------
 libavfilter/vf_bilateral_cuda.c     | 14 +++++++++-----
 libavfilter/vf_bwdif_cuda.c         | 16 ++++++++++------
 libavfilter/vf_bwdif_vulkan.c       | 15 +++++++++------
 libavfilter/vf_chromakey_cuda.c     | 15 +++++++++------
 libavfilter/vf_colorspace_cuda.c    | 14 +++++++++-----
 libavfilter/vf_deshake_opencl.c     |  3 ++-
 libavfilter/vf_hwdownload.c         |  6 ++++--
 libavfilter/vf_hwmap.c              | 22 +++++++++++++---------
 libavfilter/vf_hwupload.c           | 17 ++++++++++-------
 libavfilter/vf_hwupload_cuda.c      | 11 +++++++----
 libavfilter/vf_libplacebo.c         |  3 ++-
 libavfilter/vf_libvmaf.c            |  7 +++++--
 libavfilter/vf_overlay_cuda.c       | 11 +++++++----
 libavfilter/vf_overlay_qsv.c        | 10 +++++++---
 libavfilter/vf_overlay_vaapi.c      |  4 +++-
 libavfilter/vf_scale_cuda.c         | 16 ++++++++++------
 libavfilter/vf_scale_npp.c          | 21 +++++++++++++--------
 libavfilter/vf_scale_vt.c           | 14 +++++++++-----
 libavfilter/vf_sharpen_npp.c        | 19 ++++++++++++-------
 libavfilter/vf_stack_qsv.c          | 10 ++++++----
 libavfilter/vf_stack_vaapi.c        | 10 ++++++----
 libavfilter/vf_thumbnail_cuda.c     | 11 +++++++----
 libavfilter/vf_transpose_npp.c      | 24 +++++++++++++++---------
 libavfilter/vf_transpose_opencl.c   |  9 ++++++---
 libavfilter/vf_transpose_vaapi.c    |  7 +++++--
 libavfilter/vf_transpose_vt.c       | 20 +++++++++++++-------
 libavfilter/vf_transpose_vulkan.c   |  8 ++++++--
 libavfilter/vf_vpp_qsv.c            | 16 +++++++++-------
 libavfilter/vf_yadif_cuda.c         | 16 ++++++++++------
 libavfilter/vf_yadif_videotoolbox.m | 15 +++++++++------
 libavfilter/video.c                 |  6 +++---
 libavfilter/vsrc_ddagrab.c          |  6 ++++--
 libavfilter/vsrc_testsrc_vulkan.c   |  5 +++--
 libavfilter/vulkan_filter.c         | 15 +++++++++------
 42 files changed, 326 insertions(+), 193 deletions(-)

diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 75e9bf6724..de74fc2abf 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -206,6 +206,8 @@ static void link_free(AVFilterLink **link)
     ff_frame_pool_uninit(&li->frame_pool);
     av_channel_layout_uninit(&(*link)->ch_layout);
 
+    av_buffer_unref(&li->l.hw_frames_ctx);
+
     av_freep(link);
 }
 
@@ -411,13 +413,18 @@ int ff_filter_config_links(AVFilterContext *filter)
                     link->time_base = (AVRational) {1, link->sample_rate};
             }
 
-            if (link->src->nb_inputs && link->src->inputs[0]->hw_frames_ctx &&
+            if (link->src->nb_inputs &&
                 !(link->src->filter->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) {
-                av_assert0(!link->hw_frames_ctx &&
+                FilterLink *l0 = ff_filter_link(link->src->inputs[0]);
+
+                av_assert0(!li->l.hw_frames_ctx &&
                            "should not be set by non-hwframe-aware filter");
-                link->hw_frames_ctx = av_buffer_ref(link->src->inputs[0]->hw_frames_ctx);
-                if (!link->hw_frames_ctx)
-                    return AVERROR(ENOMEM);
+
+                if (l0->hw_frames_ctx) {
+                    li->l.hw_frames_ctx = av_buffer_ref(l0->hw_frames_ctx);
+                    if (!li->l.hw_frames_ctx)
+                        return AVERROR(ENOMEM);
+                }
             }
 
             if ((config_link = link->dstpad->config_props))
@@ -765,8 +772,6 @@ static void free_link(AVFilterLink *link)
     if (link->dst)
         link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
 
-    av_buffer_unref(&link->hw_frames_ctx);
-
     ff_formats_unref(&link->incfg.formats);
     ff_formats_unref(&link->outcfg.formats);
     ff_formats_unref(&link->incfg.color_spaces);
@@ -1615,12 +1620,13 @@ const AVClass *avfilter_get_class(void)
 int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
                              int default_pool_size)
 {
+    FilterLink *l = ff_filter_link(link);
     AVHWFramesContext *frames;
 
     // Must already be set by caller.
-    av_assert0(link->hw_frames_ctx);
+    av_assert0(l->hw_frames_ctx);
 
-    frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+    frames = (AVHWFramesContext*)l->hw_frames_ctx->data;
 
     if (frames->initial_pool_size == 0) {
         // Dynamic allocation is necessarily supported.
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 2624b0cfca..bf9a682bb7 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -641,12 +641,6 @@ struct AVFilterLink {
      * cleared when a frame is filtered.
      */
     int frame_wanted_out;
-
-    /**
-     * For hwaccel pixel formats, this should be a reference to the
-     * AVHWFramesContext describing the frames.
-     */
-    AVBufferRef *hw_frames_ctx;
 };
 
 /**
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 2c1fa4c293..a184677937 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -188,7 +188,12 @@ MAKE_AVFILTERLINK_ACCESSOR(enum AVColorRange, color_range)
 
 MAKE_AVFILTERLINK_ACCESSOR(int              , sample_rate        )
 
-MAKE_AVFILTERLINK_ACCESSOR(AVBufferRef *    , hw_frames_ctx      )
+AVBufferRef* av_buffersink_get_hw_frames_ctx(const AVFilterContext *ctx)
+{
+    FilterLink *l = ff_filter_link(ctx->inputs[0]);
+    av_assert0(ctx->filter->activate == activate);
+    return l->hw_frames_ctx;
+}
 
 int av_buffersink_get_channels(const AVFilterContext *ctx)
 {
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index a61960310b..b6e8f8036c 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -493,6 +493,7 @@ static int query_formats(AVFilterContext *ctx)
 
 static int config_props(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     BufferSourceContext *c = link->src->priv;
 
     switch (link->type) {
@@ -502,8 +503,8 @@ static int config_props(AVFilterLink *link)
         link->sample_aspect_ratio = c->pixel_aspect;
 
         if (c->hw_frames_ctx) {
-            link->hw_frames_ctx = av_buffer_ref(c->hw_frames_ctx);
-            if (!link->hw_frames_ctx)
+            l->hw_frames_ctx = av_buffer_ref(c->hw_frames_ctx);
+            if (!l->hw_frames_ctx)
                 return AVERROR(ENOMEM);
         }
         break;
diff --git a/libavfilter/filters.h b/libavfilter/filters.h
index 11064aee13..9e230dc987 100644
--- a/libavfilter/filters.h
+++ b/libavfilter/filters.h
@@ -57,6 +57,14 @@ typedef struct FilterLink {
      * May be set by the link destination filter in its config_props().
      */
     int max_samples;
+
+    /**
+     * For hwaccel pixel formats, this should be a reference to the
+     * AVHWFramesContext describing the frames.
+     *
+     * May be set by the link source filter in its config_props().
+     */
+    AVBufferRef *hw_frames_ctx;
 } FilterLink;
 
 static inline FilterLink* ff_filter_link(AVFilterLink *link)
diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c
index 48752e9530..e91610a10e 100644
--- a/libavfilter/opencl.c
+++ b/libavfilter/opencl.c
@@ -23,6 +23,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
 
+#include "filters.h"
 #include "opencl.h"
 
 static int opencl_filter_set_device(AVFilterContext *avctx,
@@ -44,12 +45,13 @@ static int opencl_filter_set_device(AVFilterContext *avctx,
 
 int ff_opencl_filter_config_input(AVFilterLink *inlink)
 {
+    FilterLink            *l = ff_filter_link(inlink);
     AVFilterContext   *avctx = inlink->dst;
     OpenCLFilterContext *ctx = avctx->priv;
     AVHWFramesContext *input_frames;
     int err;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(avctx, AV_LOG_ERROR, "OpenCL filtering requires a "
                "hardware frames context on the input.\n");
         return AVERROR(EINVAL);
@@ -59,7 +61,7 @@ int ff_opencl_filter_config_input(AVFilterLink *inlink)
     if (avctx->inputs[0] != inlink)
         return 0;
 
-    input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    input_frames = (AVHWFramesContext*)l->hw_frames_ctx->data;
     if (input_frames->format != AV_PIX_FMT_OPENCL)
         return AVERROR(EINVAL);
 
@@ -80,13 +82,14 @@ int ff_opencl_filter_config_input(AVFilterLink *inlink)
 
 int ff_opencl_filter_config_output(AVFilterLink *outlink)
 {
+    FilterLink            *l = ff_filter_link(outlink);
     AVFilterContext   *avctx = outlink->src;
     OpenCLFilterContext *ctx = avctx->priv;
     AVBufferRef       *output_frames_ref = NULL;
     AVHWFramesContext *output_frames;
     int err;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
+    av_buffer_unref(&l->hw_frames_ctx);
 
     if (!ctx->device_ref) {
         if (!avctx->hw_device_ctx) {
@@ -119,7 +122,7 @@ int ff_opencl_filter_config_output(AVFilterLink *outlink)
         goto fail;
     }
 
-    outlink->hw_frames_ctx = output_frames_ref;
+    l->hw_frames_ctx = output_frames_ref;
     outlink->w = ctx->output_width;
     outlink->h = ctx->output_height;
 
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 6adf9f6e84..24e15020b2 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -28,6 +28,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "internal.h"
+#include "filters.h"
 #include "qsvvpp.h"
 #include "video.h"
 
@@ -303,10 +304,11 @@ static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
     const AVPixFmtDescriptor *desc;
 
     if (link->format == AV_PIX_FMT_QSV) {
-        if (!link->hw_frames_ctx)
+        FilterLink *l = ff_filter_link(link);
+        if (!l->hw_frames_ctx)
             return AVERROR(EINVAL);
 
-        frames_ctx   = (AVHWFramesContext *)link->hw_frames_ctx->data;
+        frames_ctx   = (AVHWFramesContext *)l->hw_frames_ctx->data;
         frames_hwctx = frames_ctx->hwctx;
         *frameinfo   = frames_hwctx->nb_surfaces ? frames_hwctx->surfaces[0].Info : *frames_hwctx->info;
     } else {
@@ -472,6 +474,7 @@ static QSVFrame *submit_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *p
 /* get the output surface */
 static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFrame *in)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     QSVFrame        *out_frame;
     int              ret;
@@ -489,7 +492,7 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFr
         if (!out_frame->frame)
             return NULL;
 
-        ret = av_hwframe_get_buffer(outlink->hw_frames_ctx, out_frame->frame, 0);
+        ret = av_hwframe_get_buffer(l->hw_frames_ctx, out_frame->frame, 0);
         if (ret < 0) {
             av_log(ctx, AV_LOG_ERROR, "Can't allocate a surface.\n");
             return NULL;
@@ -546,7 +549,9 @@ FF_ENABLE_DEPRECATION_WARNINGS
 static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
 {
     AVFilterLink                 *inlink = avctx->inputs[0];
+    FilterLink                      *inl = ff_filter_link(inlink);
     AVFilterLink                *outlink = avctx->outputs[0];
+    FilterLink                     *outl = ff_filter_link(outlink);
     AVQSVFramesContext  *in_frames_hwctx = NULL;
     AVQSVFramesContext *out_frames_hwctx = NULL;
 
@@ -559,8 +564,8 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
     mfxIMPL impl;
     int ret, i;
 
-    if (inlink->hw_frames_ctx) {
-        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    if (inl->hw_frames_ctx) {
+        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data;
 
         device_ref      = frames_ctx->device_ref;
         in_frames_hwctx = frames_ctx->hwctx;
@@ -657,8 +662,8 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s)
             s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i;
         s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces;
 
-        av_buffer_unref(&outlink->hw_frames_ctx);
-        outlink->hw_frames_ctx = out_frames_ref;
+        av_buffer_unref(&outl->hw_frames_ctx);
+        outl->hw_frames_ctx = out_frames_ref;
     } else
         s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY;
 
diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c
index 9ef7a289fb..496190a844 100644
--- a/libavfilter/vaapi_vpp.c
+++ b/libavfilter/vaapi_vpp.c
@@ -21,6 +21,8 @@
 #include "libavutil/avassert.h"
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
+
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "vaapi_vpp.h"
@@ -74,19 +76,20 @@ void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
 
 int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
 {
+    FilterLink          *l = ff_filter_link(inlink);
     AVFilterContext *avctx = inlink->dst;
     VAAPIVPPContext *ctx   = avctx->priv;
 
     if (ctx->pipeline_uninit)
         ctx->pipeline_uninit(avctx);
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
                "required to associate the processing device.\n");
         return AVERROR(EINVAL);
     }
 
-    ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    ctx->input_frames_ref = av_buffer_ref(l->hw_frames_ctx);
     if (!ctx->input_frames_ref) {
         av_log(avctx, AV_LOG_ERROR, "A input frames reference create "
                "failed.\n");
@@ -99,8 +102,10 @@ int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
 
 int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
 {
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     AVFilterLink   *inlink = avctx->inputs[0];
+    FilterLink        *inl = ff_filter_link(inlink);
     VAAPIVPPContext *ctx   = avctx->priv;
     AVVAAPIHWConfig *hwconfig = NULL;
     AVHWFramesConstraints *constraints = NULL;
@@ -121,8 +126,8 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
     outlink->h = ctx->output_height;
 
     if (ctx->passthrough) {
-        if (inlink->hw_frames_ctx)
-            outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
+        if (inl->hw_frames_ctx)
+            outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
         av_log(ctx, AV_LOG_VERBOSE, "Using VAAPI filter passthrough mode.\n");
 
         return 0;
@@ -189,15 +194,15 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
         goto fail;
     }
 
-    outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref);
-    if (!outlink->hw_frames_ctx) {
+    outl->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref);
+    if (!outl->hw_frames_ctx) {
         av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context "
                "for output.\n");
         err = AVERROR(ENOMEM);
         goto fail;
     }
 
-    output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+    output_frames = (AVHWFramesContext*)outl->hw_frames_ctx->data;
 
     output_frames->format    = AV_PIX_FMT_VAAPI;
     output_frames->sw_format = ctx->output_format;
@@ -213,7 +218,7 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
     if (err < 0)
         goto fail;
 
-    err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
+    err = av_hwframe_ctx_init(outl->hw_frames_ctx);
     if (err < 0) {
         av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
                "context for output: %d\n", err);
@@ -247,7 +252,7 @@ int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
     return 0;
 
 fail:
-    av_buffer_unref(&outlink->hw_frames_ctx);
+    av_buffer_unref(&outl->hw_frames_ctx);
     av_freep(&hwconfig);
     av_hwframe_constraints_free(&constraints);
     return err;
diff --git a/libavfilter/vf_bilateral_cuda.c b/libavfilter/vf_bilateral_cuda.c
index 037227af93..46acec91b9 100644
--- a/libavfilter/vf_bilateral_cuda.c
+++ b/libavfilter/vf_bilateral_cuda.c
@@ -30,6 +30,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 
 #include "cuda/load_helper.h"
@@ -178,16 +179,18 @@ static av_cold void set_format_info(AVFilterContext *ctx, enum AVPixelFormat in_
 
 static av_cold int init_processing_chain(AVFilterContext *ctx, int width, int height)
 {
+    FilterLink         *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink        *outl = ff_filter_link(ctx->outputs[0]);
     CUDABilateralContext *s = ctx->priv;
     AVHWFramesContext *in_frames_ctx;
     int ret;
 
     /* check that we have a hw context */
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
-    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
 
     if (!format_is_supported(in_frames_ctx->sw_format)) {
         av_log(ctx, AV_LOG_ERROR, "Unsupported format: %s\n", av_get_pix_fmt_name(in_frames_ctx->sw_format));
@@ -200,8 +203,8 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int width, int he
     if (ret < 0)
         return ret;
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -248,6 +251,7 @@ static av_cold int cuda_bilateral_config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     CUDABilateralContext *s  = ctx->priv;
     AVHWFramesContext     *frames_ctx;
     AVCUDADeviceContext *device_hwctx;
@@ -257,7 +261,7 @@ static av_cold int cuda_bilateral_config_props(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    frames_ctx   = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    frames_ctx   = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     device_hwctx = frames_ctx->device_ctx->hwctx;
 
     s->hwctx = device_hwctx;
diff --git a/libavfilter/vf_bwdif_cuda.c b/libavfilter/vf_bwdif_cuda.c
index 8c37dc8800..a19d180bdd 100644
--- a/libavfilter/vf_bwdif_cuda.c
+++ b/libavfilter/vf_bwdif_cuda.c
@@ -22,6 +22,8 @@
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_cuda_internal.h"
 #include "libavutil/cuda_check.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "yadif.h"
 
@@ -217,16 +219,17 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx)
 
 static int config_input(AVFilterLink *inlink)
 {
+    FilterLink        *l = ff_filter_link(inlink);
     AVFilterContext *ctx = inlink->dst;
     DeintCUDAContext *s  = ctx->priv;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is "
                "required to associate the processing device.\n");
         return AVERROR(EINVAL);
     }
 
-    s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    s->input_frames_ref = av_buffer_ref(l->hw_frames_ctx);
     if (!s->input_frames_ref) {
         av_log(ctx, AV_LOG_ERROR, "A input frames reference create "
                "failed.\n");
@@ -239,6 +242,7 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     AVHWFramesContext *output_frames;
     AVFilterContext *ctx = link->src;
     DeintCUDAContext *s = ctx->priv;
@@ -257,15 +261,15 @@ static int config_output(AVFilterLink *link)
     s->hwctx = ((AVHWDeviceContext*)s->device_ref->data)->hwctx;
     cu = s->hwctx->internal->cuda_dl;
 
-    link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
-    if (!link->hw_frames_ctx) {
+    l->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context "
                "for output.\n");
         ret = AVERROR(ENOMEM);
         goto exit;
     }
 
-    output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+    output_frames = (AVHWFramesContext*)l->hw_frames_ctx->data;
 
     output_frames->format    = AV_PIX_FMT_CUDA;
     output_frames->sw_format = s->input_frames->sw_format;
@@ -278,7 +282,7 @@ static int config_output(AVFilterLink *link)
     if (ret < 0)
         goto exit;
 
-    ret = av_hwframe_ctx_init(link->hw_frames_ctx);
+    ret = av_hwframe_ctx_init(l->hw_frames_ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failed to initialise CUDA frame "
                "context for output: %d\n", ret);
diff --git a/libavfilter/vf_bwdif_vulkan.c b/libavfilter/vf_bwdif_vulkan.c
index 57711fb672..3599047784 100644
--- a/libavfilter/vf_bwdif_vulkan.c
+++ b/libavfilter/vf_bwdif_vulkan.c
@@ -26,6 +26,7 @@
 #include "vulkan_spirv.h"
 #include "yadif.h"
 #include "internal.h"
+#include "filters.h"
 
 typedef struct BWDIFVulkanContext {
     YADIFContext yadif;
@@ -303,18 +304,19 @@ static void bwdif_vulkan_uninit(AVFilterContext *avctx)
 
 static int bwdif_vulkan_config_input(AVFilterLink *inlink)
 {
+    FilterLink *l = ff_filter_link(inlink);
     AVHWFramesContext *input_frames;
     AVFilterContext *avctx = inlink->dst;
     BWDIFVulkanContext *s = avctx->priv;
     FFVulkanContext *vkctx = &s->vkctx;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
                "hardware frames context on the input.\n");
         return AVERROR(EINVAL);
     }
 
-    input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
     if (input_frames->format != AV_PIX_FMT_VULKAN)
         return AVERROR(EINVAL);
 
@@ -323,7 +325,7 @@ static int bwdif_vulkan_config_input(AVFilterLink *inlink)
         return 0;
 
     /* Save the ref, without reffing it */
-    vkctx->input_frames_ref = inlink->hw_frames_ctx;
+    vkctx->input_frames_ref = l->hw_frames_ctx;
 
     /* Defaults */
     vkctx->output_format = input_frames->sw_format;
@@ -335,13 +337,14 @@ static int bwdif_vulkan_config_input(AVFilterLink *inlink)
 
 static int bwdif_vulkan_config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     int err;
     AVFilterContext *avctx = outlink->src;
     BWDIFVulkanContext *s = avctx->priv;
     YADIFContext *y = &s->yadif;
     FFVulkanContext *vkctx = &s->vkctx;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
+    av_buffer_unref(&l->hw_frames_ctx);
 
     err = ff_vk_filter_init_context(avctx, vkctx, vkctx->input_frames_ref,
                                     vkctx->output_width, vkctx->output_height,
@@ -352,8 +355,8 @@ static int bwdif_vulkan_config_output(AVFilterLink *outlink)
     /* For logging */
     vkctx->class = y->class;
 
-    outlink->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
-    if (!outlink->hw_frames_ctx)
+    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
+    if (!l->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     err = ff_yadif_config_output_common(outlink);
diff --git a/libavfilter/vf_chromakey_cuda.c b/libavfilter/vf_chromakey_cuda.c
index e38521be0d..86da92a4ea 100644
--- a/libavfilter/vf_chromakey_cuda.c
+++ b/libavfilter/vf_chromakey_cuda.c
@@ -30,6 +30,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "cuda/load_helper.h"
 
@@ -180,17 +181,18 @@ static av_cold void set_format_info(AVFilterContext *ctx, enum AVPixelFormat in_
 
 static av_cold int init_processing_chain(AVFilterContext *ctx, int width, int height)
 {
+    FilterLink         *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink        *outl = ff_filter_link(ctx->outputs[0]);
     ChromakeyCUDAContext *s = ctx->priv;
     AVHWFramesContext *in_frames_ctx;
     int ret;
 
     /* check that we have a hw context */
-    if (!ctx->inputs[0]->hw_frames_ctx)
-    {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
-    in_frames_ctx = (AVHWFramesContext *)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data;
 
     if (!format_is_supported(in_frames_ctx->sw_format))
     {
@@ -204,8 +206,8 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int width, int he
     if (ret < 0)
         return ret;
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -258,6 +260,7 @@ static av_cold int cudachromakey_config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     ChromakeyCUDAContext *s = ctx->priv;
     AVHWFramesContext *frames_ctx;
     AVCUDADeviceContext *device_hwctx;
@@ -275,7 +278,7 @@ static av_cold int cudachromakey_config_props(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    frames_ctx = (AVHWFramesContext *)inl->hw_frames_ctx->data;
     device_hwctx = frames_ctx->device_ctx->hwctx;
 
     s->hwctx = device_hwctx;
diff --git a/libavfilter/vf_colorspace_cuda.c b/libavfilter/vf_colorspace_cuda.c
index 3949cb7ed8..f089b20ed7 100644
--- a/libavfilter/vf_colorspace_cuda.c
+++ b/libavfilter/vf_colorspace_cuda.c
@@ -31,6 +31,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 
 #include "cuda/load_helper.h"
@@ -151,17 +152,19 @@ static int format_is_supported(enum AVPixelFormat fmt)
 static av_cold int init_processing_chain(AVFilterContext* ctx, int width,
                                          int height)
 {
+    FilterLink          *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink         *outl = ff_filter_link(ctx->outputs[0]);
     CUDAColorspaceContext* s = ctx->priv;
     AVHWFramesContext* in_frames_ctx;
 
     int ret;
 
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
 
-    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     s->pix_fmt = in_frames_ctx->sw_format;
 
     if (!format_is_supported(s->pix_fmt)) {
@@ -181,8 +184,8 @@ static av_cold int init_processing_chain(AVFilterContext* ctx, int width,
     if (ret < 0)
         return ret;
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -225,6 +228,7 @@ static av_cold int cudacolorspace_config_props(AVFilterLink* outlink)
 {
     AVFilterContext* ctx = outlink->src;
     AVFilterLink* inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     CUDAColorspaceContext* s = ctx->priv;
     AVHWFramesContext* frames_ctx;
     AVCUDADeviceContext* device_hwctx;
@@ -237,7 +241,7 @@ static av_cold int cudacolorspace_config_props(AVFilterLink* outlink)
     if (ret < 0)
         return ret;
 
-    frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     device_hwctx = frames_ctx->device_ctx->hwctx;
 
     s->hwctx = device_hwctx;
diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c
index 5c3848c3ed..9e87007cbb 100644
--- a/libavfilter/vf_deshake_opencl.c
+++ b/libavfilter/vf_deshake_opencl.c
@@ -1112,6 +1112,7 @@ static int deshake_opencl_init(AVFilterContext *avctx)
     DeshakeOpenCLContext *ctx = avctx->priv;
     AVFilterLink *outlink = avctx->outputs[0];
     AVFilterLink *inlink = avctx->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     // Pointer to the host-side pattern buffer to be initialized and then copied
     // to the GPU
     PointPair *pattern_host = NULL;
@@ -1146,7 +1147,7 @@ static int deshake_opencl_init(AVFilterContext *avctx)
     const int descriptor_buf_size = image_grid_32 * (BREIFN / 8);
     const int features_buf_size = image_grid_32 * sizeof(cl_float2);
 
-    const AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    const AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hw_frames_ctx->sw_format);
 
     av_assert0(hw_frames_ctx);
diff --git a/libavfilter/vf_hwdownload.c b/libavfilter/vf_hwdownload.c
index 5ef23cb5d4..75c4b215be 100644
--- a/libavfilter/vf_hwdownload.c
+++ b/libavfilter/vf_hwdownload.c
@@ -24,6 +24,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -50,18 +51,19 @@ static int hwdownload_query_formats(AVFilterContext *avctx)
 
 static int hwdownload_config_input(AVFilterLink *inlink)
 {
+    FilterLink          *l = ff_filter_link(inlink);
     AVFilterContext *avctx = inlink->dst;
     HWDownloadContext *ctx = avctx->priv;
 
     av_buffer_unref(&ctx->hwframes_ref);
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "The input must have a hardware frame "
                "reference.\n");
         return AVERROR(EINVAL);
     }
 
-    ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    ctx->hwframes_ref = av_buffer_ref(l->hw_frames_ctx);
     if (!ctx->hwframes_ref)
         return AVERROR(ENOMEM);
 
diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index 3f37dab2c8..d3e84e39d7 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -23,6 +23,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -52,9 +53,11 @@ static int hwmap_query_formats(AVFilterContext *avctx)
 
 static int hwmap_config_output(AVFilterLink *outlink)
 {
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     HWMapContext      *ctx = avctx->priv;
     AVFilterLink   *inlink = avctx->inputs[0];
+    FilterLink        *inl = ff_filter_link(inlink);
     AVHWFramesContext *hwfc;
     AVBufferRef *device;
     const AVPixFmtDescriptor *desc;
@@ -69,8 +72,8 @@ static int hwmap_config_output(AVFilterLink *outlink)
     device = avctx->hw_device_ctx;
     device_is_derived = 0;
 
-    if (inlink->hw_frames_ctx) {
-        hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    if (inl->hw_frames_ctx) {
+        hwfc = (AVHWFramesContext*)inl->hw_frames_ctx->data;
 
         if (ctx->derive_device_type) {
             enum AVHWDeviceType type;
@@ -114,7 +117,7 @@ static int hwmap_config_output(AVFilterLink *outlink)
             err = av_hwframe_ctx_create_derived(&ctx->hwframes_ref,
                                                 outlink->format,
                                                 device,
-                                                inlink->hw_frames_ctx,
+                                                inl->hw_frames_ctx,
                                                 ctx->mode);
             if (err < 0) {
                 av_log(avctx, AV_LOG_ERROR, "Failed to create derived "
@@ -171,8 +174,8 @@ static int hwmap_config_output(AVFilterLink *outlink)
             // the format it expects.  If there were any additional
             // constraints on the output frames there then this may
             // break nastily.
-            av_buffer_unref(&inlink->hw_frames_ctx);
-            inlink->hw_frames_ctx = source;
+            av_buffer_unref(&inl->hw_frames_ctx);
+            inl->hw_frames_ctx = source;
 
         } else if ((outlink->format == hwfc->format &&
                     inlink->format  == hwfc->sw_format) ||
@@ -180,7 +183,7 @@ static int hwmap_config_output(AVFilterLink *outlink)
             // Map from a hardware format to a software format, or
             // undo an existing such mapping.
 
-            ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
+            ctx->hwframes_ref = av_buffer_ref(inl->hw_frames_ctx);
             if (!ctx->hwframes_ref) {
                 err = AVERROR(ENOMEM);
                 goto fail;
@@ -241,8 +244,8 @@ static int hwmap_config_output(AVFilterLink *outlink)
         return AVERROR(EINVAL);
     }
 
-    outlink->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
-    if (!outlink->hw_frames_ctx) {
+    outl->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
+    if (!outl->hw_frames_ctx) {
         err = AVERROR(ENOMEM);
         goto fail;
     }
@@ -263,11 +266,12 @@ fail:
 
 static AVFrame *hwmap_get_buffer(AVFilterLink *inlink, int w, int h)
 {
+    FilterLink          *l = ff_filter_link(inlink);
     AVFilterContext *avctx = inlink->dst;
     AVFilterLink  *outlink = avctx->outputs[0];
     HWMapContext      *ctx = avctx->priv;
 
-    if (ctx->reverse && !inlink->hw_frames_ctx) {
+    if (ctx->reverse && !l->hw_frames_ctx) {
         AVFrame *src, *dst;
         int err;
 
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
index ef61bb4137..9c11e72759 100644
--- a/libavfilter/vf_hwupload.c
+++ b/libavfilter/vf_hwupload.c
@@ -24,6 +24,7 @@
 #include "libavutil/opt.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -106,8 +107,10 @@ fail:
 
 static int hwupload_config_output(AVFilterLink *outlink)
 {
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     AVFilterLink   *inlink = avctx->inputs[0];
+    FilterLink        *inl = ff_filter_link(inlink);
     HWUploadContext   *ctx = avctx->priv;
     int err;
 
@@ -116,13 +119,13 @@ static int hwupload_config_output(AVFilterLink *outlink)
     if (inlink->format == outlink->format) {
         // The input is already a hardware format, so we just want to
         // pass through the input frames in their own hardware context.
-        if (!inlink->hw_frames_ctx) {
+        if (!inl->hw_frames_ctx) {
             av_log(ctx, AV_LOG_ERROR, "No input hwframe context.\n");
             return AVERROR(EINVAL);
         }
 
-        outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-        if (!outlink->hw_frames_ctx)
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+        if (!outl->hw_frames_ctx)
             return AVERROR(ENOMEM);
 
         return 0;
@@ -138,9 +141,9 @@ static int hwupload_config_output(AVFilterLink *outlink)
            av_get_pix_fmt_name(inlink->format));
 
     ctx->hwframes->format    = outlink->format;
-    if (inlink->hw_frames_ctx) {
+    if (inl->hw_frames_ctx) {
         AVHWFramesContext *in_hwframe_ctx =
-            (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+            (AVHWFramesContext*)inl->hw_frames_ctx->data;
         ctx->hwframes->sw_format = in_hwframe_ctx->sw_format;
     } else {
         ctx->hwframes->sw_format = inlink->format;
@@ -155,8 +158,8 @@ static int hwupload_config_output(AVFilterLink *outlink)
     if (err < 0)
         goto fail;
 
-    outlink->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
-    if (!outlink->hw_frames_ctx) {
+    outl->hw_frames_ctx = av_buffer_ref(ctx->hwframes_ref);
+    if (!outl->hw_frames_ctx) {
         err = AVERROR(ENOMEM);
         goto fail;
     }
diff --git a/libavfilter/vf_hwupload_cuda.c b/libavfilter/vf_hwupload_cuda.c
index f5fe3ddbbe..fa96f06de1 100644
--- a/libavfilter/vf_hwupload_cuda.c
+++ b/libavfilter/vf_hwupload_cuda.c
@@ -22,6 +22,7 @@
 #include "libavutil/opt.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -86,8 +87,10 @@ static int cudaupload_query_formats(AVFilterContext *ctx)
 
 static int cudaupload_config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     CudaUploadContext *s = ctx->priv;
 
     AVHWFramesContext *hwframe_ctx;
@@ -100,8 +103,8 @@ static int cudaupload_config_output(AVFilterLink *outlink)
 
     hwframe_ctx            = (AVHWFramesContext*)s->hwframe->data;
     hwframe_ctx->format    = AV_PIX_FMT_CUDA;
-    if (inlink->hw_frames_ctx) {
-        AVHWFramesContext *in_hwframe_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    if (inl->hw_frames_ctx) {
+        AVHWFramesContext *in_hwframe_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
         hwframe_ctx->sw_format = in_hwframe_ctx->sw_format;
     } else {
         hwframe_ctx->sw_format = inlink->format;
@@ -113,8 +116,8 @@ static int cudaupload_config_output(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    outlink->hw_frames_ctx = av_buffer_ref(s->hwframe);
-    if (!outlink->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->hwframe);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index be9000aa8e..096064022d 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -1188,6 +1188,7 @@ static inline AVRational max_q(AVRational a, AVRational b)
 static int libplacebo_config_output(AVFilterLink *outlink)
 {
     int err;
+    FilterLink          *l = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     LibplaceboContext *s   = avctx->priv;
     AVFilterLink *inlink   = outlink->src->inputs[0];
@@ -1253,7 +1254,7 @@ static int libplacebo_config_output(AVFilterLink *outlink)
         s->vkctx.output_format = s->out_format;
     }
     RET(ff_vk_filter_config_output(outlink));
-    hwfc = (AVHWFramesContext *) outlink->hw_frames_ctx->data;
+    hwfc = (AVHWFramesContext *)l->hw_frames_ctx->data;
     vkfc = hwfc->hwctx;
     vkfc->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
 
diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index 2c99d792af..a54af16000 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -34,6 +34,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "formats.h"
 #include "framesync.h"
 #include "internal.h"
@@ -651,7 +652,8 @@ static int config_props_cuda(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     LIBVMAFContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
-    AVHWFramesContext *frames_ctx = (AVHWFramesContext*) inlink->hw_frames_ctx->data;
+    FilterLink      *inl = ff_filter_link(inlink);
+    AVHWFramesContext *frames_ctx = (AVHWFramesContext*) inl->hw_frames_ctx->data;
     AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
     CUcontext cu_ctx = device_hwctx->cuda_ctx;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frames_ctx->sw_format);
@@ -756,7 +758,8 @@ static int do_vmaf_cuda(FFFrameSync* fs)
     AVFilterContext* ctx = fs->parent;
     LIBVMAFContext* s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
-    AVHWFramesContext *frames_ctx = (AVHWFramesContext*) inlink->hw_frames_ctx->data;
+    FilterLink      *inl = ff_filter_link(inlink);
+    AVHWFramesContext *frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
     VmafPicture pic_ref, pic_dist;
     AVFrame *ref, *dist;
diff --git a/libavfilter/vf_overlay_cuda.c b/libavfilter/vf_overlay_cuda.c
index 77c7f9b4e7..1aee77b17c 100644
--- a/libavfilter/vf_overlay_cuda.c
+++ b/libavfilter/vf_overlay_cuda.c
@@ -436,14 +436,17 @@ static int overlay_cuda_config_output(AVFilterLink *outlink)
     extern const unsigned int ff_vf_overlay_cuda_ptx_len;
 
     int err;
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext* avctx = outlink->src;
     OverlayCUDAContext* ctx = avctx->priv;
 
     AVFilterLink *inlink = avctx->inputs[0];
-    AVHWFramesContext  *frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    FilterLink *inl = ff_filter_link(inlink);
+    AVHWFramesContext  *frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
 
     AVFilterLink *inlink_overlay = avctx->inputs[1];
-    AVHWFramesContext  *frames_ctx_overlay = (AVHWFramesContext*)inlink_overlay->hw_frames_ctx->data;
+    FilterLink *inl_overlay = ff_filter_link(inlink_overlay);
+    AVHWFramesContext  *frames_ctx_overlay = (AVHWFramesContext*)inl_overlay->hw_frames_ctx->data;
 
     CUcontext dummy, cuda_ctx;
     CudaFunctions *cu;
@@ -496,8 +499,8 @@ static int overlay_cuda_config_output(AVFilterLink *outlink)
 
     ctx->cu_stream = ctx->hwctx->stream;
 
-    outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-    if (!outlink->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     // load functions
diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c
index 059602fe03..15dfe4e6f7 100644
--- a/libavfilter/vf_overlay_qsv.c
+++ b/libavfilter/vf_overlay_qsv.c
@@ -29,6 +29,7 @@
 #include "libavutil/hwcontext.h"
 #include "libavutil/mathematics.h"
 
+#include "filters.h"
 #include "internal.h"
 #include "avfilter.h"
 #include "formats.h"
@@ -156,12 +157,13 @@ release:
 
 static int have_alpha_planar(AVFilterLink *link)
 {
+    FilterLink              *l = ff_filter_link(link);
     enum AVPixelFormat pix_fmt = link->format;
     const AVPixFmtDescriptor *desc;
     AVHWFramesContext *fctx;
 
     if (link->format == AV_PIX_FMT_QSV) {
-        fctx    = (AVHWFramesContext *)link->hw_frames_ctx->data;
+        fctx    = (AVHWFramesContext *)l->hw_frames_ctx->data;
         pix_fmt = fctx->sw_format;
     }
 
@@ -273,6 +275,8 @@ static int config_output(AVFilterLink *outlink)
     QSVOverlayContext *vpp = ctx->priv;
     AVFilterLink      *in0 = ctx->inputs[0];
     AVFilterLink      *in1 = ctx->inputs[1];
+    FilterLink         *l0 = ff_filter_link(in0);
+    FilterLink         *l1 = ff_filter_link(in1);
     int ret;
 
     av_log(ctx, AV_LOG_DEBUG, "Output is of %s.\n", av_get_pix_fmt_name(outlink->format));
@@ -282,8 +286,8 @@ static int config_output(AVFilterLink *outlink)
         av_log(ctx, AV_LOG_ERROR, "Mixing hardware and software pixel formats is not supported.\n");
         return AVERROR(EINVAL);
     } else if (in0->format == AV_PIX_FMT_QSV) {
-        AVHWFramesContext *hw_frame0 = (AVHWFramesContext *)in0->hw_frames_ctx->data;
-        AVHWFramesContext *hw_frame1 = (AVHWFramesContext *)in1->hw_frames_ctx->data;
+        AVHWFramesContext *hw_frame0 = (AVHWFramesContext *)l0->hw_frames_ctx->data;
+        AVHWFramesContext *hw_frame1 = (AVHWFramesContext *)l1->hw_frames_ctx->data;
 
         if (hw_frame0->device_ctx != hw_frame1->device_ctx) {
             av_log(ctx, AV_LOG_ERROR, "Inputs with different underlying QSV devices are forbidden.\n");
diff --git a/libavfilter/vf_overlay_vaapi.c b/libavfilter/vf_overlay_vaapi.c
index 9b1e12bdc8..16477ad24b 100644
--- a/libavfilter/vf_overlay_vaapi.c
+++ b/libavfilter/vf_overlay_vaapi.c
@@ -21,6 +21,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "vaapi_vpp.h"
@@ -256,12 +257,13 @@ fail:
 
 static int have_alpha_planar(AVFilterLink *link)
 {
+    FilterLink              *l = ff_filter_link(link);
     enum AVPixelFormat pix_fmt = link->format;
     const AVPixFmtDescriptor *desc;
     AVHWFramesContext *fctx;
 
     if (link->format == AV_PIX_FMT_VAAPI) {
-        fctx    = (AVHWFramesContext *)link->hw_frames_ctx->data;
+        fctx    = (AVHWFramesContext *)l->hw_frames_ctx->data;
         pix_fmt = fctx->sw_format;
     }
 
diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c
index 68d17072e3..83073f8b4b 100644
--- a/libavfilter/vf_scale_cuda.c
+++ b/libavfilter/vf_scale_cuda.c
@@ -32,6 +32,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "scale_eval.h"
 #include "video.h"
@@ -221,6 +222,8 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int
                                          int out_width, int out_height)
 {
     CUDAScaleContext *s = ctx->priv;
+    FilterLink     *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink    *outl = ff_filter_link(ctx->outputs[0]);
 
     AVHWFramesContext *in_frames_ctx;
 
@@ -229,11 +232,11 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int
     int ret;
 
     /* check that we have a hw context */
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
-    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     in_format     = in_frames_ctx->sw_format;
     out_format    = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
 
@@ -251,7 +254,7 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int
     set_format_info(ctx, in_format, out_format);
 
     if (s->passthrough && in_width == out_width && in_height == out_height && in_format == out_format) {
-        s->frames_ctx = av_buffer_ref(ctx->inputs[0]->hw_frames_ctx);
+        s->frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
         if (!s->frames_ctx)
             return AVERROR(ENOMEM);
     } else {
@@ -266,8 +269,8 @@ static av_cold int init_processing_chain(AVFilterContext *ctx, int in_width, int
             s->interp_algo = INTERP_ALGO_NEAREST;
     }
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -348,6 +351,7 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     CUDAScaleContext *s  = ctx->priv;
     AVHWFramesContext     *frames_ctx;
     AVCUDADeviceContext *device_hwctx;
@@ -374,7 +378,7 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    frames_ctx   = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    frames_ctx   = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     device_hwctx = frames_ctx->device_ctx->hwctx;
 
     s->hwctx = device_hwctx;
diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c
index 27e5e584ae..0c4af074c9 100644
--- a/libavfilter/vf_scale_npp.c
+++ b/libavfilter/vf_scale_npp.c
@@ -36,6 +36,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "scale_eval.h"
@@ -536,6 +537,8 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
                                  int out_width, int out_height)
 {
     NPPScaleContext *s = ctx->priv;
+    FilterLink    *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink   *outl = ff_filter_link(ctx->outputs[0]);
 
     AVHWFramesContext *in_frames_ctx;
 
@@ -547,11 +550,11 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
     int i, ret, last_stage = -1;
 
     /* check that we have a hw context */
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
-    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     in_format     = in_frames_ctx->sw_format;
     out_format    = (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
 
@@ -629,11 +632,11 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
     }
 
     if (last_stage >= 0)
-        ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx);
+        outl->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx);
     else
-        ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(ctx->inputs[0]->hw_frames_ctx);
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
 
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -686,8 +689,9 @@ fail:
 
 static int config_props_ref(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterLink *inlink = outlink->src->inputs[1];
-    AVFilterContext *ctx = outlink->src;
+    FilterLink      *inl = ff_filter_link(inlink);
 
     outlink->w = inlink->w;
     outlink->h = inlink->h;
@@ -695,7 +699,7 @@ static int config_props_ref(AVFilterLink *outlink)
     outlink->time_base = inlink->time_base;
     outlink->frame_rate = inlink->frame_rate;
 
-    ctx->outputs[1]->hw_frames_ctx = av_buffer_ref(ctx->inputs[1]->hw_frames_ctx);
+    outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
 
     return 0;
 }
@@ -900,7 +904,8 @@ static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in)
     AVFilterContext              *ctx = link->dst;
     NPPScaleContext                *s = ctx->priv;
     AVFilterLink             *outlink = ctx->outputs[0];
-    AVHWFramesContext     *frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+    FilterLink                     *l = ff_filter_link(outlink);
+    AVHWFramesContext     *frames_ctx = (AVHWFramesContext*)l->hw_frames_ctx->data;
     AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
 
     AVFrame *out = NULL;
diff --git a/libavfilter/vf_scale_vt.c b/libavfilter/vf_scale_vt.c
index af4a8b32c6..7481af1747 100644
--- a/libavfilter/vf_scale_vt.c
+++ b/libavfilter/vf_scale_vt.c
@@ -24,6 +24,8 @@
 #include "libavutil/hwcontext_videotoolbox.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "scale_eval.h"
 #include "video.h"
@@ -174,9 +176,11 @@ fail:
 static int scale_vt_config_output(AVFilterLink *outlink)
 {
     int err;
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     ScaleVtContext *s  = avctx->priv;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink        *inl = ff_filter_link(inlink);
     AVHWFramesContext *hw_frame_ctx_in;
     AVHWFramesContext *hw_frame_ctx_out;
 
@@ -196,11 +200,11 @@ static int scale_vt_config_output(AVFilterLink *outlink)
         outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     }
 
-    hw_frame_ctx_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    hw_frame_ctx_in = (AVHWFramesContext *)inl->hw_frames_ctx->data;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
-    outlink->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref);
-    hw_frame_ctx_out = (AVHWFramesContext *)outlink->hw_frames_ctx->data;
+    av_buffer_unref(&outl->hw_frames_ctx);
+    outl->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref);
+    hw_frame_ctx_out = (AVHWFramesContext *)outl->hw_frames_ctx->data;
     hw_frame_ctx_out->format = AV_PIX_FMT_VIDEOTOOLBOX;
     hw_frame_ctx_out->sw_format = hw_frame_ctx_in->sw_format;
     hw_frame_ctx_out->width = outlink->w;
@@ -210,7 +214,7 @@ static int scale_vt_config_output(AVFilterLink *outlink)
     if (err < 0)
         return err;
 
-    err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
+    err = av_hwframe_ctx_init(outl->hw_frames_ctx);
     if (err < 0) {
         av_log(avctx, AV_LOG_ERROR,
                "Failed to init videotoolbox frame context, %s\n",
diff --git a/libavfilter/vf_sharpen_npp.c b/libavfilter/vf_sharpen_npp.c
index 73c77dd5df..437cfb23cc 100644
--- a/libavfilter/vf_sharpen_npp.c
+++ b/libavfilter/vf_sharpen_npp.c
@@ -24,6 +24,7 @@
 #include <nppi.h>
 #include <nppi_filtering_functions.h>
 
+#include "filters.h"
 #include "internal.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/cuda_check.h"
@@ -31,6 +32,7 @@
 #include "libavutil/hwcontext_cuda_internal.h"
 #include "libavutil/opt.h"
 
+
 #define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, device_hwctx->internal->cuda_dl, x)
 
 static const enum AVPixelFormat supported_formats[] = {
@@ -70,16 +72,18 @@ fail:
 
 static int nppsharpen_config(AVFilterContext* ctx, int width, int height)
 {
+    FilterLink      *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink     *outl = ff_filter_link(ctx->outputs[0]);
     NPPSharpenContext* s = ctx->priv;
     AVHWFramesContext *out_ctx, *in_ctx;
     int i, ret, supported_format = 0;
 
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         goto fail;
     }
 
-    in_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
 
     s->frames_ctx = av_hwframe_ctx_alloc(in_ctx->device_ref);
     if (!s->frames_ctx)
@@ -111,8 +115,8 @@ static int nppsharpen_config(AVFilterContext* ctx, int width, int height)
     if (ret < 0)
         goto fail;
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->frames_ctx);
+    if (!outl->hw_frames_ctx)
         goto fail;
 
     return 0;
@@ -152,8 +156,8 @@ static int nppsharpen_config_props(AVFilterLink* outlink)
 
 static int nppsharpen_sharpen(AVFilterContext* ctx, AVFrame* out, AVFrame* in)
 {
-    AVHWFramesContext* in_ctx =
-        (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    FilterLink *inl = ff_filter_link(ctx->inputs[0]);
+    AVHWFramesContext* in_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     NPPSharpenContext* s = ctx->priv;
 
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(in_ctx->sw_format);
@@ -179,8 +183,9 @@ static int nppsharpen_filter_frame(AVFilterLink* link, AVFrame* in)
     AVFilterContext* ctx = link->dst;
     NPPSharpenContext* s = ctx->priv;
     AVFilterLink* outlink = ctx->outputs[0];
+    FilterLink      *outl = ff_filter_link(outlink);
     AVHWFramesContext* frames_ctx =
-        (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+        (AVHWFramesContext*)outl->hw_frames_ctx->data;
     AVCUDADeviceContext* device_hwctx = frames_ctx->device_ctx->hwctx;
 
     AVFrame* out = NULL;
diff --git a/libavfilter/vf_stack_qsv.c b/libavfilter/vf_stack_qsv.c
index d4c1ac997f..a23e4f3e7e 100644
--- a/libavfilter/vf_stack_qsv.c
+++ b/libavfilter/vf_stack_qsv.c
@@ -100,15 +100,16 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     StackQSVContext *sctx = ctx->priv;
     AVFilterLink *inlink0 = ctx->inputs[0];
+    FilterLink      *inl0 = ff_filter_link(inlink0);
     enum AVPixelFormat in_format;
     int depth = 8, ret;
     mfxVPPCompInputStream *is = sctx->comp_conf.InputStream;
 
     if (inlink0->format == AV_PIX_FMT_QSV) {
-         if (!inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data)
+         if (!inl0->hw_frames_ctx || !inl0->hw_frames_ctx->data)
              return AVERROR(EINVAL);
 
-         in_format = ((AVHWFramesContext*)inlink0->hw_frames_ctx->data)->sw_format;
+         in_format = ((AVHWFramesContext*)inl0->hw_frames_ctx->data)->sw_format;
     } else
         in_format = inlink0->format;
 
@@ -116,10 +117,11 @@ static int config_output(AVFilterLink *outlink)
 
     for (int i = 1; i < sctx->base.nb_inputs; i++) {
         AVFilterLink *inlink = ctx->inputs[i];
+        FilterLink      *inl = ff_filter_link(inlink);
 
         if (inlink0->format == AV_PIX_FMT_QSV) {
-            AVHWFramesContext *hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data;
-            AVHWFramesContext *hwfc = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+            AVHWFramesContext *hwfc0 = (AVHWFramesContext *)inl0->hw_frames_ctx->data;
+            AVHWFramesContext *hwfc = (AVHWFramesContext *)inl->hw_frames_ctx->data;
 
             if (inlink0->format != inlink->format) {
                 av_log(ctx, AV_LOG_ERROR, "Mixing hardware and software pixel formats is not supported.\n");
diff --git a/libavfilter/vf_stack_vaapi.c b/libavfilter/vf_stack_vaapi.c
index 8e9471e6d7..612ef97efe 100644
--- a/libavfilter/vf_stack_vaapi.c
+++ b/libavfilter/vf_stack_vaapi.c
@@ -137,26 +137,28 @@ static int config_output(AVFilterLink *outlink)
     StackVAAPIContext *sctx = avctx->priv;
     VAAPIVPPContext *vppctx = avctx->priv;
     AVFilterLink *inlink0 = avctx->inputs[0];
+    FilterLink      *inl0 = ff_filter_link(inlink0);
     AVHWFramesContext *hwfc0 = NULL;
     int ret;
 
-    if (inlink0->format != AV_PIX_FMT_VAAPI || !inlink0->hw_frames_ctx || !inlink0->hw_frames_ctx->data) {
+    if (inlink0->format != AV_PIX_FMT_VAAPI || !inl0->hw_frames_ctx || !inl0->hw_frames_ctx->data) {
         av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n");
         return AVERROR(EINVAL);
     }
 
-    hwfc0 = (AVHWFramesContext *)inlink0->hw_frames_ctx->data;
+    hwfc0 = (AVHWFramesContext *)inl0->hw_frames_ctx->data;
 
     for (int i = 1; i < sctx->base.nb_inputs; i++) {
         AVFilterLink *inlink = avctx->inputs[i];
+        FilterLink      *inl = ff_filter_link(inlink);
         AVHWFramesContext *hwfc = NULL;
 
-        if (inlink->format != AV_PIX_FMT_VAAPI || !inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) {
+        if (inlink->format != AV_PIX_FMT_VAAPI || !inl->hw_frames_ctx || !inl->hw_frames_ctx->data) {
             av_log(avctx, AV_LOG_ERROR, "Software pixel format is not supported.\n");
             return AVERROR(EINVAL);
         }
 
-        hwfc = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+        hwfc = (AVHWFramesContext *)inl->hw_frames_ctx->data;
 
         if (hwfc0->sw_format != hwfc->sw_format) {
             av_log(avctx, AV_LOG_ERROR, "All inputs should have the same underlying software pixel format.\n");
diff --git a/libavfilter/vf_thumbnail_cuda.c b/libavfilter/vf_thumbnail_cuda.c
index 8efb54f079..be27d85dc7 100644
--- a/libavfilter/vf_thumbnail_cuda.c
+++ b/libavfilter/vf_thumbnail_cuda.c
@@ -28,6 +28,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 
 #include "cuda/load_helper.h"
@@ -358,8 +359,10 @@ static int format_is_supported(enum AVPixelFormat fmt)
 static int config_props(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
+    FilterLink      *inl = ff_filter_link(inlink);
+    FilterLink     *outl = ff_filter_link(ctx->outputs[0]);
     ThumbnailCudaContext *s = ctx->priv;
-    AVHWFramesContext     *hw_frames_ctx = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
+    AVHWFramesContext     *hw_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     AVCUDADeviceContext *device_hwctx = hw_frames_ctx->device_ctx->hwctx;
     CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx;
     CudaFunctions *cu = device_hwctx->internal->cuda_dl;
@@ -401,10 +404,10 @@ static int config_props(AVFilterLink *inlink)
 
     CHECK_CU(cu->cuCtxPopCurrent(&dummy));
 
-    s->hw_frames_ctx = ctx->inputs[0]->hw_frames_ctx;
+    s->hw_frames_ctx = inl->hw_frames_ctx;
 
-    ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->hw_frames_ctx);
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    outl->hw_frames_ctx = av_buffer_ref(s->hw_frames_ctx);
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     s->tb = inlink->time_base;
diff --git a/libavfilter/vf_transpose_npp.c b/libavfilter/vf_transpose_npp.c
index 96c008cda9..2e3a0296f5 100644
--- a/libavfilter/vf_transpose_npp.c
+++ b/libavfilter/vf_transpose_npp.c
@@ -29,6 +29,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -178,6 +179,8 @@ static int format_is_supported(enum AVPixelFormat fmt)
 static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_height,
                                  int out_width, int out_height)
 {
+    FilterLink        *inl = ff_filter_link(ctx->inputs[0]);
+    FilterLink       *outl = ff_filter_link(ctx->outputs[0]);
     NPPTransposeContext *s = ctx->priv;
     AVHWFramesContext *in_frames_ctx;
     enum AVPixelFormat format;
@@ -185,12 +188,12 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
     int rot_width = out_width, rot_height = out_height;
 
     /* check that we have a hw context */
-    if (!ctx->inputs[0]->hw_frames_ctx) {
+    if (!inl->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
         return AVERROR(EINVAL);
     }
 
-    in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
+    in_frames_ctx = (AVHWFramesContext*)inl->hw_frames_ctx->data;
     format        = in_frames_ctx->sw_format;
 
     if (!format_is_supported(format)) {
@@ -235,13 +238,13 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
     }
 
     if (last_stage >= 0) {
-        ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx);
+        outl->hw_frames_ctx = av_buffer_ref(s->stages[last_stage].frames_ctx);
     } else {
-        ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(ctx->inputs[0]->hw_frames_ctx);
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
         s->passthrough = 1;
     }
 
-    if (!ctx->outputs[0]->hw_frames_ctx)
+    if (!outl->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     return 0;
@@ -249,17 +252,19 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig
 
 static int npptranspose_config_props(AVFilterLink *outlink)
 {
+    FilterLink     *outl   = ff_filter_link(outlink);
     AVFilterContext *ctx   = outlink->src;
     AVFilterLink *inlink   = ctx->inputs[0];
+    FilterLink      *inl   = ff_filter_link(inlink);
     NPPTransposeContext *s = ctx->priv;
     int ret;
 
     if ((inlink->w >= inlink->h && s->passthrough == NPP_TRANSPOSE_PT_TYPE_LANDSCAPE) ||
         (inlink->w <= inlink->h && s->passthrough == NPP_TRANSPOSE_PT_TYPE_PORTRAIT))
     {
-        if (inlink->hw_frames_ctx) {
-            outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-            if (!outlink->hw_frames_ctx)
+        if (inl->hw_frames_ctx) {
+            outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+            if (!outl->hw_frames_ctx)
                 return AVERROR(ENOMEM);
         }
 
@@ -387,7 +392,8 @@ static int npptranspose_filter_frame(AVFilterLink *link, AVFrame *in)
     AVFilterContext              *ctx = link->dst;
     NPPTransposeContext            *s = ctx->priv;
     AVFilterLink             *outlink = ctx->outputs[0];
-    AVHWFramesContext     *frames_ctx = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
+    FilterLink                  *outl = ff_filter_link(outlink);
+    AVHWFramesContext     *frames_ctx = (AVHWFramesContext*)outl->hw_frames_ctx->data;
     AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
     AVFrame *out = NULL;
     CUcontext dummy;
diff --git a/libavfilter/vf_transpose_opencl.c b/libavfilter/vf_transpose_opencl.c
index 262dec0a8a..aef880a9a4 100644
--- a/libavfilter/vf_transpose_opencl.c
+++ b/libavfilter/vf_transpose_opencl.c
@@ -23,6 +23,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "opencl.h"
 #include "opencl_source.h"
@@ -71,9 +72,11 @@ fail:
 
 static int transpose_opencl_config_output(AVFilterLink *outlink)
 {
+    FilterLink       *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     TransposeOpenCLContext *s = avctx->priv;
     AVFilterLink *inlink = avctx->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     const AVPixFmtDescriptor *desc_in  = av_pix_fmt_desc_get(inlink->format);
     int ret;
 
@@ -81,9 +84,9 @@ static int transpose_opencl_config_output(AVFilterLink *outlink)
          s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
         (inlink->w <= inlink->h &&
          s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
-        if (inlink->hw_frames_ctx) {
-            outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-            if (!outlink->hw_frames_ctx)
+        if (inl->hw_frames_ctx) {
+            outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+            if (!outl->hw_frames_ctx)
                 return AVERROR(ENOMEM);
         }
         av_log(avctx, AV_LOG_VERBOSE,
diff --git a/libavfilter/vf_transpose_vaapi.c b/libavfilter/vf_transpose_vaapi.c
index 165a97de30..bc8fc3c284 100644
--- a/libavfilter/vf_transpose_vaapi.c
+++ b/libavfilter/vf_transpose_vaapi.c
@@ -21,6 +21,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "transpose.h"
 #include "vaapi_vpp.h"
@@ -185,15 +186,17 @@ static av_cold int transpose_vaapi_init(AVFilterContext *avctx)
 
 static int transpose_vaapi_vpp_config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl           = ff_filter_link(outlink);
     AVFilterContext *avctx     = outlink->src;
     VAAPIVPPContext *vpp_ctx   = avctx->priv;
     TransposeVAAPIContext *ctx = avctx->priv;
     AVFilterLink *inlink       = avctx->inputs[0];
+    FilterLink *inl            = ff_filter_link(inlink);
 
     if ((inlink->w >= inlink->h && ctx->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
         (inlink->w <= inlink->h && ctx->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
-        outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-        if (!outlink->hw_frames_ctx)
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+        if (!outl->hw_frames_ctx)
             return AVERROR(ENOMEM);
         av_log(avctx, AV_LOG_VERBOSE,
                "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
diff --git a/libavfilter/vf_transpose_vt.c b/libavfilter/vf_transpose_vt.c
index e0f35fdb5a..72bab3d53b 100644
--- a/libavfilter/vf_transpose_vt.c
+++ b/libavfilter/vf_transpose_vt.c
@@ -24,6 +24,8 @@
 #include "libavutil/hwcontext_videotoolbox.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "transpose.h"
 #include "video.h"
@@ -105,17 +107,19 @@ fail:
 
 static int transpose_vt_recreate_hw_ctx(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink *inl = ff_filter_link(inlink);
     AVHWFramesContext *hw_frame_ctx_in;
     AVHWFramesContext *hw_frame_ctx_out;
     int err;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
+    av_buffer_unref(&outl->hw_frames_ctx);
 
-    hw_frame_ctx_in = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
-    outlink->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref);
-    hw_frame_ctx_out = (AVHWFramesContext *)outlink->hw_frames_ctx->data;
+    hw_frame_ctx_in = (AVHWFramesContext *)inl->hw_frames_ctx->data;
+    outl->hw_frames_ctx = av_hwframe_ctx_alloc(hw_frame_ctx_in->device_ref);
+    hw_frame_ctx_out = (AVHWFramesContext *)outl->hw_frames_ctx->data;
     hw_frame_ctx_out->format = AV_PIX_FMT_VIDEOTOOLBOX;
     hw_frame_ctx_out->sw_format = hw_frame_ctx_in->sw_format;
     hw_frame_ctx_out->width = outlink->w;
@@ -125,7 +129,7 @@ static int transpose_vt_recreate_hw_ctx(AVFilterLink *outlink)
     if (err < 0)
         return err;
 
-    err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
+    err = av_hwframe_ctx_init(outl->hw_frames_ctx);
     if (err < 0) {
         av_log(avctx, AV_LOG_ERROR,
                "Failed to init videotoolbox frame context, %s\n",
@@ -139,16 +143,18 @@ static int transpose_vt_recreate_hw_ctx(AVFilterLink *outlink)
 static int transpose_vt_config_output(AVFilterLink *outlink)
 {
     int err;
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     TransposeVtContext *s  = avctx->priv;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink *inl = ff_filter_link(inlink);
     CFStringRef rotation = kVTRotation_0;
     CFBooleanRef vflip = kCFBooleanFalse;
     CFBooleanRef hflip = kCFBooleanFalse;
     int swap_w_h = 0;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
-    outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
+    av_buffer_unref(&outl->hw_frames_ctx);
+    outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
 
     if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
         (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c
index 263a934dc5..e04461b3bb 100644
--- a/libavfilter/vf_transpose_vulkan.c
+++ b/libavfilter/vf_transpose_vulkan.c
@@ -23,6 +23,8 @@
 #include "libavutil/opt.h"
 #include "vulkan_filter.h"
 #include "vulkan_spirv.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "transpose.h"
 #include "video.h"
@@ -193,18 +195,20 @@ static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx)
 
 static int config_props_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     TransposeVulkanContext *s = avctx->priv;
     FFVulkanContext *vkctx = &s->vkctx;
     AVFilterLink *inlink = avctx->inputs[0];
+    FilterLink *inlink = ff_filter_link(inlink);
 
     if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
         (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
         av_log(avctx, AV_LOG_VERBOSE,
                "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
                inlink->w, inlink->h, inlink->w, inlink->h);
-        outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
-        return outlink->hw_frames_ctx ? 0 : AVERROR(ENOMEM);
+        outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
+        return outl->hw_frames_ctx ? 0 : AVERROR(ENOMEM);
     } else {
         s->passthrough = TRANSPOSE_PT_TYPE_NONE;
     }
diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
index 6071c46ca1..f368b6ce24 100644
--- a/libavfilter/vf_vpp_qsv.c
+++ b/libavfilter/vf_vpp_qsv.c
@@ -364,13 +364,13 @@ static int config_input(AVFilterLink *inlink)
 
 static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version)
 {
-    const AVFilterLink *inlink = ctx->inputs[0];
+    const FilterLink *l = ff_filter_link(ctx->inputs[0]);
     AVBufferRef *device_ref;
     AVHWDeviceContext *device_ctx;
     AVQSVDeviceContext *device_hwctx;
 
-    if (inlink->hw_frames_ctx) {
-        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    if (l->hw_frames_ctx) {
+        AVHWFramesContext *frames_ctx = (AVHWFramesContext *)l->hw_frames_ctx->data;
         device_ref = frames_ctx->device_ref;
     } else if (ctx->hw_device_ctx) {
         device_ref = ctx->hw_device_ctx;
@@ -524,6 +524,7 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     VPPContext      *vpp = ctx->priv;
     QSVVPPParam     param = { NULL };
@@ -531,6 +532,7 @@ static int config_output(AVFilterLink *outlink)
     mfxExtBuffer    *ext_buf[ENH_FILTERS_COUNT];
     mfxVersion      mfx_version;
     AVFilterLink    *inlink = ctx->inputs[0];
+    FilterLink         *inl = ff_filter_link(inlink);
     enum AVPixelFormat in_format;
 
     outlink->w          = vpp->out_width;
@@ -552,10 +554,10 @@ static int config_output(AVFilterLink *outlink)
     }
 
     if (inlink->format == AV_PIX_FMT_QSV) {
-         if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data)
+         if (!inl->hw_frames_ctx || !inl->hw_frames_ctx->data)
              return AVERROR(EINVAL);
          else
-             in_format = ((AVHWFramesContext*)inlink->hw_frames_ctx->data)->sw_format;
+             in_format = ((AVHWFramesContext*)inl->hw_frames_ctx->data)->sw_format;
     } else
         in_format = inlink->format;
 
@@ -716,8 +718,8 @@ static int config_output(AVFilterLink *outlink)
     else {
         /* No MFX session is created in this case */
         av_log(ctx, AV_LOG_VERBOSE, "qsv vpp pass through mode.\n");
-        if (inlink->hw_frames_ctx)
-            outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx);
+        if (inl->hw_frames_ctx)
+            outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
     }
 
     return 0;
diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c
index 79080e71c2..e74bd87092 100644
--- a/libavfilter/vf_yadif_cuda.c
+++ b/libavfilter/vf_yadif_cuda.c
@@ -22,6 +22,8 @@
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_cuda_internal.h"
 #include "libavutil/cuda_check.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "yadif.h"
 
@@ -209,16 +211,17 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx)
 
 static int config_input(AVFilterLink *inlink)
 {
+    FilterLink        *l = ff_filter_link(inlink);
     AVFilterContext *ctx = inlink->dst;
     DeintCUDAContext *s  = ctx->priv;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is "
                "required to associate the processing device.\n");
         return AVERROR(EINVAL);
     }
 
-    s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    s->input_frames_ref = av_buffer_ref(l->hw_frames_ctx);
     if (!s->input_frames_ref) {
         av_log(ctx, AV_LOG_ERROR, "A input frames reference create "
                "failed.\n");
@@ -231,6 +234,7 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     AVHWFramesContext *output_frames;
     AVFilterContext *ctx = link->src;
     DeintCUDAContext *s = ctx->priv;
@@ -249,15 +253,15 @@ static int config_output(AVFilterLink *link)
     s->hwctx = ((AVHWDeviceContext*)s->device_ref->data)->hwctx;
     cu = s->hwctx->internal->cuda_dl;
 
-    link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
-    if (!link->hw_frames_ctx) {
+    l->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context "
                "for output.\n");
         ret = AVERROR(ENOMEM);
         goto exit;
     }
 
-    output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+    output_frames = (AVHWFramesContext*)l->hw_frames_ctx->data;
 
     output_frames->format    = AV_PIX_FMT_CUDA;
     output_frames->sw_format = s->input_frames->sw_format;
@@ -270,7 +274,7 @@ static int config_output(AVFilterLink *link)
     if (ret < 0)
         goto exit;
 
-    ret = av_hwframe_ctx_init(link->hw_frames_ctx);
+    ret = av_hwframe_ctx_init(l->hw_frames_ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failed to initialise CUDA frame "
                "context for output: %d\n", ret);
diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m
index c47d3edfb8..f77e7e86b5 100644
--- a/libavfilter/vf_yadif_videotoolbox.m
+++ b/libavfilter/vf_yadif_videotoolbox.m
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "filters.h"
 #include "internal.h"
 #include "metal/utils.h"
 #include "yadif.h"
@@ -288,16 +289,17 @@ static av_cold int yadif_videotoolbox_init(AVFilterContext *ctx)
 
 static int do_config_input(AVFilterLink *inlink) API_AVAILABLE(macos(10.11), ios(8.0))
 {
+    FilterLink *l = ff_filter_link(inlink);
     AVFilterContext *ctx = inlink->dst;
     YADIFVTContext *s = ctx->priv;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is "
                "required to associate the processing device.\n");
         return AVERROR(EINVAL);
     }
 
-    s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+    s->input_frames_ref = av_buffer_ref(l->hw_frames_ctx);
     if (!s->input_frames_ref) {
         av_log(ctx, AV_LOG_ERROR, "A input frames reference create "
                "failed.\n");
@@ -321,6 +323,7 @@ static int config_input(AVFilterLink *inlink)
 
 static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(8.0))
 {
+    FilterLink *l = ff_filter_link(link);
     AVHWFramesContext *output_frames;
     AVFilterContext *ctx = link->src;
     YADIFVTContext *s = ctx->priv;
@@ -335,15 +338,15 @@ static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(
         return AVERROR(ENOMEM);
     }
 
-    link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
-    if (!link->hw_frames_ctx) {
+    l->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref);
+    if (!l->hw_frames_ctx) {
         av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context "
                "for output.\n");
         ret = AVERROR(ENOMEM);
         goto exit;
     }
 
-    output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+    output_frames = (AVHWFramesContext*)l->hw_frames_ctx->data;
 
     output_frames->format    = AV_PIX_FMT_VIDEOTOOLBOX;
     output_frames->sw_format = s->input_frames->sw_format;
@@ -354,7 +357,7 @@ static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(
     if (ret < 0)
         goto exit;
 
-    ret = av_hwframe_ctx_init(link->hw_frames_ctx);
+    ret = av_hwframe_ctx_init(l->hw_frames_ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame "
                "context for output: %d\n", ret);
diff --git a/libavfilter/video.c b/libavfilter/video.c
index 89d0797ab5..b09c3bd10a 100644
--- a/libavfilter/video.c
+++ b/libavfilter/video.c
@@ -55,15 +55,15 @@ AVFrame *ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int alig
     int pool_align = 0;
     enum AVPixelFormat pool_format = AV_PIX_FMT_NONE;
 
-    if (link->hw_frames_ctx &&
-        ((AVHWFramesContext*)link->hw_frames_ctx->data)->format == link->format) {
+    if (li->l.hw_frames_ctx &&
+        ((AVHWFramesContext*)li->l.hw_frames_ctx->data)->format == link->format) {
         int ret;
         frame = av_frame_alloc();
 
         if (!frame)
             return NULL;
 
-        ret = av_hwframe_get_buffer(link->hw_frames_ctx, frame, 0);
+        ret = av_hwframe_get_buffer(li->l.hw_frames_ctx, frame, 0);
         if (ret < 0)
             av_frame_free(&frame);
 
diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c
index 2fb109dede..dc53e15c6d 100644
--- a/libavfilter/vsrc_ddagrab.c
+++ b/libavfilter/vsrc_ddagrab.c
@@ -43,6 +43,7 @@
 #include "libavutil/hwcontext_d3d11va.h"
 #include "compat/w32dlfcn.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -854,6 +855,7 @@ fail:
 
 static int ddagrab_config_props(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     DdagrabContext *dda = avctx->priv;
     int ret;
@@ -915,8 +917,8 @@ static int ddagrab_config_props(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
-    outlink->hw_frames_ctx = av_buffer_ref(dda->frames_ref);
-    if (!outlink->hw_frames_ctx)
+    l->hw_frames_ctx = av_buffer_ref(dda->frames_ref);
+    if (!l->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     outlink->w = dda->width;
diff --git a/libavfilter/vsrc_testsrc_vulkan.c b/libavfilter/vsrc_testsrc_vulkan.c
index 480b23ac9f..2b16ee2b6b 100644
--- a/libavfilter/vsrc_testsrc_vulkan.c
+++ b/libavfilter/vsrc_testsrc_vulkan.c
@@ -266,6 +266,7 @@ static int testsrc_vulkan_activate(AVFilterContext *ctx)
 static int testsrc_vulkan_config_props(AVFilterLink *outlink)
 {
     int err;
+    FilterLink *l = ff_filter_link(outlink);
     TestSrcVulkanContext *s = outlink->src->priv;
     FFVulkanContext *vkctx = &s->vkctx;
 
@@ -284,8 +285,8 @@ static int testsrc_vulkan_config_props(AVFilterLink *outlink)
     if (err < 0)
         return err;
 
-    outlink->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
-    if (!outlink->hw_frames_ctx)
+    l->hw_frames_ctx = av_buffer_ref(vkctx->frames_ref);
+    if (!l->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     s->time_base = av_inv_q(s->frame_rate);
diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c
index cef42eeb4d..2878d9063b 100644
--- a/libavfilter/vulkan_filter.c
+++ b/libavfilter/vulkan_filter.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "filters.h"
 #include "vulkan_filter.h"
 #include "libavutil/vulkan_loader.h"
 
@@ -165,17 +166,18 @@ skip:
 
 int ff_vk_filter_config_input(AVFilterLink *inlink)
 {
+    FilterLink *l = ff_filter_link(inlink);
     AVHWFramesContext *input_frames;
     AVFilterContext *avctx = inlink->dst;
     FFVulkanContext *s = inlink->dst->priv;
 
-    if (!inlink->hw_frames_ctx) {
+    if (!l->hw_frames_ctx) {
         av_log(inlink->dst, AV_LOG_ERROR, "Vulkan filtering requires a "
                "hardware frames context on the input.\n");
         return AVERROR(EINVAL);
     }
 
-    input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data;
+    input_frames = (AVHWFramesContext *)l->hw_frames_ctx->data;
     if (input_frames->format != AV_PIX_FMT_VULKAN)
         return AVERROR(EINVAL);
 
@@ -184,7 +186,7 @@ int ff_vk_filter_config_input(AVFilterLink *inlink)
         return 0;
 
     /* Save the ref, without reffing it */
-    s->input_frames_ref = inlink->hw_frames_ctx;
+    s->input_frames_ref = l->hw_frames_ctx;
 
     /* Defaults */
     s->input_format = input_frames->sw_format;
@@ -198,9 +200,10 @@ int ff_vk_filter_config_input(AVFilterLink *inlink)
 int ff_vk_filter_config_output(AVFilterLink *outlink)
 {
     int err;
+    FilterLink *l = ff_filter_link(outlink);
     FFVulkanContext *s = outlink->src->priv;
 
-    av_buffer_unref(&outlink->hw_frames_ctx);
+    av_buffer_unref(&l->hw_frames_ctx);
 
     err = ff_vk_filter_init_context(outlink->src, s, s->input_frames_ref,
                                     s->output_width, s->output_height,
@@ -208,8 +211,8 @@ int ff_vk_filter_config_output(AVFilterLink *outlink)
     if (err < 0)
         return err;
 
-    outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref);
-    if (!outlink->hw_frames_ctx)
+    l->hw_frames_ctx = av_buffer_ref(s->frames_ref);
+    if (!l->hw_frames_ctx)
         return AVERROR(ENOMEM);
 
     outlink->w = s->output_width;
-- 
2.43.0



More information about the ffmpeg-devel mailing list