diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c
index 7bd9e37e43..9704a9e0a3 100644
--- a/libavfilter/af_aiir.c
+++ b/libavfilter/af_aiir.c
@@ -27,6 +27,7 @@
 #include "libavutil/xga_font_data.h"
 #include "audio.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -1434,14 +1435,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
 static int config_video(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AudioIIRContext *s = ctx->priv;
 
     outlink->sample_aspect_ratio = (AVRational){1,1};
     outlink->w = s->w;
     outlink->h = s->h;
-    outlink->frame_rate = s->rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     return 0;
 }
diff --git a/libavfilter/avf_a3dscope.c b/libavfilter/avf_a3dscope.c
index d7fe2dcb75..27eb73effb 100644
--- a/libavfilter/avf_a3dscope.c
+++ b/libavfilter/avf_a3dscope.c
@@ -115,13 +115,14 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     Audio3dScopeContext *s = outlink->src->priv;
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     return 0;
 }
diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c
index 13c704ff27..749c78fe14 100644
--- a/libavfilter/avf_abitscope.c
+++ b/libavfilter/avf_abitscope.c
@@ -139,12 +139,13 @@ static int config_input(AVFilterLink *inlink)
 static int config_output(AVFilterLink *outlink)
 {
     AudioBitScopeContext *s = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     return 0;
 }
diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c
index 6fb3f64ac9..23239b1b72 100644
--- a/libavfilter/avf_ahistogram.c
+++ b/libavfilter/avf_ahistogram.c
@@ -161,12 +161,13 @@ static int get_log_bin_sign(float in, int w)
 static int config_output(AVFilterLink *outlink)
 {
     AudioHistogramContext *s = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     s->histogram_h = s->h * s->phisto;
     s->ypos = s->h * s->phisto;
diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c
index 6632bae3ec..bf7ae0823f 100644
--- a/libavfilter/avf_aphasemeter.c
+++ b/libavfilter/avf_aphasemeter.c
@@ -142,14 +142,15 @@ static int config_video_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AudioPhaseMeterContext *s = ctx->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     s->last_pts = AV_NOPTS_VALUE;
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     if (!strcmp(s->mpc_str, "none"))
         s->draw_median_phase = 0;
diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c
index 1b3461d91d..be5656f13b 100644
--- a/libavfilter/avf_avectorscope.c
+++ b/libavfilter/avf_avectorscope.c
@@ -271,12 +271,13 @@ static int config_input(AVFilterLink *inlink)
 static int config_output(AVFilterLink *outlink)
 {
     AudioVectorScopeContext *s = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     s->prev_x = s->hw = s->w / 2;
     s->prev_y = s->hh = s->mode == POLAR ? s->h - 1 : s->h / 2;
diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c
index 5d11631798..67cdc39fd8 100644
--- a/libavfilter/avf_concat.c
+++ b/libavfilter/avf_concat.c
@@ -120,11 +120,13 @@ static int query_formats(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl     = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     ConcatContext *cat   = ctx->priv;
     unsigned out_no = FF_OUTLINK_IDX(outlink);
     unsigned in_no  = out_no, seg;
     AVFilterLink *inlink = ctx->inputs[in_no];
+    FilterLink *inl = ff_filter_link(inlink);
 
     /* enhancement: find a common one */
     outlink->time_base           = AV_TIME_BASE_Q;
@@ -132,15 +134,16 @@ static int config_output(AVFilterLink *outlink)
     outlink->h                   = inlink->h;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     outlink->format              = inlink->format;
-    outlink->frame_rate          = inlink->frame_rate;
+    outl->frame_rate             = inl->frame_rate;
 
     for (seg = 1; seg < cat->nb_segments; seg++) {
         inlink = ctx->inputs[in_no + seg * ctx->nb_outputs];
-        if (outlink->frame_rate.num != inlink->frame_rate.num ||
-            outlink->frame_rate.den != inlink->frame_rate.den) {
+        inl    = ff_filter_link(inlink);
+        if (outl->frame_rate.num != inl->frame_rate.num ||
+            outl->frame_rate.den != inl->frame_rate.den) {
             av_log(ctx, AV_LOG_VERBOSE,
                     "Video inputs have different frame rates, output will be VFR\n");
-            outlink->frame_rate = av_make_q(1, 0);
+            outl->frame_rate = av_make_q(1, 0);
             break;
         }
     }
diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c
index 249b6245ca..fa0c82e996 100644
--- a/libavfilter/avf_showcqt.c
+++ b/libavfilter/avf_showcqt.c
@@ -1353,6 +1353,7 @@ static int query_formats(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowCQTContext *s = ctx->priv;
@@ -1365,7 +1366,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = s->height;
     s->format = outlink->format;
     outlink->sample_aspect_ratio = av_make_q(1, 1);
-    outlink->frame_rate = s->rate;
+    l->frame_rate = s->rate;
     outlink->time_base = av_inv_q(s->rate);
     av_log(ctx, AV_LOG_VERBOSE, "video: %dx%d %s %d/%d fps, bar_h = %d, axis_h = %d, sono_h = %d.\n",
            s->width, s->height, av_get_pix_fmt_name(s->format), s->rate.num, s->rate.den,
diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c
index 89a019a0d4..c6fa8ac821 100644
--- a/libavfilter/avf_showcwt.c
+++ b/libavfilter/avf_showcwt.c
@@ -810,6 +810,7 @@ static int compute_kernel(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowCWTContext *s = ctx->priv;
@@ -1033,8 +1034,8 @@ static int config_output(AVFilterLink *outlink)
     } else {
         s->frame_rate = s->auto_frame_rate;
     }
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     ret = compute_kernel(ctx);
     if (ret < 0)
diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c
index 23083ad50a..f5b86a7f17 100644
--- a/libavfilter/avf_showfreqs.c
+++ b/libavfilter/avf_showfreqs.c
@@ -150,6 +150,7 @@ static int query_formats(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowFreqsContext *s = ctx->priv;
@@ -223,8 +224,8 @@ static int config_output(AVFilterLink *outlink)
     if (!s->window)
         return AVERROR(ENOMEM);
 
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
     outlink->sample_aspect_ratio = (AVRational){1,1};
     outlink->w = s->w;
     outlink->h = s->h;
diff --git a/libavfilter/avf_showspatial.c b/libavfilter/avf_showspatial.c
index ec85f90635..ef67340465 100644
--- a/libavfilter/avf_showspatial.c
+++ b/libavfilter/avf_showspatial.c
@@ -128,6 +128,7 @@ static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowSpatialContext *s = ctx->priv;
@@ -138,8 +139,8 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
 
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     /* (re-)configuration if the video output changed (or first init) */
     if (s->win_size != s->buf_size) {
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index 3a4b489af3..cb2a5a6ae3 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -1061,6 +1061,7 @@ static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_j
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowSpectrumContext *s = ctx->priv;
@@ -1283,8 +1284,8 @@ static int config_output(AVFilterLink *outlink)
     } else {
         s->frame_rate = s->auto_frame_rate;
     }
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     if (s->orientation == VERTICAL) {
         s->combine_buffer =
diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c
index 2ae43de211..06550157fd 100644
--- a/libavfilter/avf_showvolume.c
+++ b/libavfilter/avf_showvolume.c
@@ -196,6 +196,7 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink        *l = ff_filter_link(outlink);
     ShowVolumeContext *s = outlink->src->priv;
     AVFilterLink *inlink = outlink->src->inputs[0];
     int ch;
@@ -209,8 +210,8 @@ static int config_output(AVFilterLink *outlink)
     }
 
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
 
     for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
         int i;
diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
index 63e0b36e09..823f1c6fd3 100644
--- a/libavfilter/avf_showwaves.c
+++ b/libavfilter/avf_showwaves.c
@@ -409,6 +409,7 @@ static void draw_sample_cline_gray(uint8_t *buf, int height, int linesize,
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     ShowWavesContext *showwaves = ctx->priv;
@@ -422,14 +423,14 @@ static int config_output(AVFilterLink *outlink)
 
     if (showwaves->single_pic) {
         showwaves->n = av_make_q(1, 1);
-        outlink->frame_rate = av_make_q(1, 1);
+        l->frame_rate = av_make_q(1, 1);
     } else {
         if (!showwaves->n.num || !showwaves->n.den) {
             showwaves->n = av_mul_q(av_make_q(inlink->sample_rate,
                                               showwaves->w), av_inv_q(showwaves->rate));
-            outlink->frame_rate = showwaves->rate;
+            l->frame_rate = showwaves->rate;
         } else {
-            outlink->frame_rate = av_div_q(av_make_q(inlink->sample_rate, showwaves->w), showwaves->n);
+            l->frame_rate = av_div_q(av_make_q(inlink->sample_rate, showwaves->w), showwaves->n);
         }
     }
 
@@ -448,13 +449,13 @@ static int config_output(AVFilterLink *outlink)
     if (!showwaves->history)
         return AVERROR(ENOMEM);
 
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    outlink->time_base = av_inv_q(l->frame_rate);
     outlink->w = showwaves->w;
     outlink->h = showwaves->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
 
     av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%f\n",
-           showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), av_q2d(showwaves->n));
+           showwaves->w, showwaves->h, av_q2d(l->frame_rate), av_q2d(showwaves->n));
 
     switch (outlink->format) {
     case AV_PIX_FMT_GRAY8:
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 9b72b6162f..66dda6584d 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -340,6 +340,7 @@ int ff_filter_config_links(AVFilterContext *filter)
         AVFilterLink *link = filter->inputs[i];
         AVFilterLink *inlink;
         FilterLinkInternal *li = ff_link_internal(link);
+        FilterLinkInternal *li_in;
 
         if (!link) continue;
         if (!link->src || !link->dst) {
@@ -349,6 +350,7 @@ int ff_filter_config_links(AVFilterContext *filter)
         }
 
         inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL;
+        li_in  = inlink ? ff_link_internal(inlink) : NULL;
         li->l.current_pts =
         li->l.current_pts_us = AV_NOPTS_VALUE;
 
@@ -389,8 +391,8 @@ int ff_filter_config_links(AVFilterContext *filter)
                         inlink->sample_aspect_ratio : (AVRational){1,1};
 
                 if (inlink) {
-                    if (!link->frame_rate.num && !link->frame_rate.den)
-                        link->frame_rate = inlink->frame_rate;
+                    if (!li->l.frame_rate.num && !li->l.frame_rate.den)
+                        li->l.frame_rate = li_in->l.frame_rate;
                     if (!link->w)
                         link->w = inlink->w;
                     if (!link->h)
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 0d1fdf980b..3498514459 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -600,19 +600,6 @@ struct AVFilterLink {
      */
     struct AVFilterGraph *graph;
 
-    /**
-     * Frame rate of the stream on the link, or 1/0 if unknown or variable;
-     * if left to 0/0, will be automatically copied from the first input
-     * of the source filter if it exists.
-     *
-     * Sources should set it to the best estimation of the real frame rate.
-     * If the source frame rate is unknown or variable, set this to 1/0.
-     * Filters should update it if necessary depending on their function.
-     * Sinks can use it to set a default output frame rate.
-     * It is similar to the r_frame_rate field in AVStream.
-     */
-    AVRational frame_rate;
-
     /**
      * Number of past frames sent through the link.
      */
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index a184677937..f76d0af7ff 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -179,7 +179,6 @@ MAKE_AVFILTERLINK_ACCESSOR(enum AVMediaType , type               )
 MAKE_AVFILTERLINK_ACCESSOR(AVRational       , time_base          )
 MAKE_AVFILTERLINK_ACCESSOR(int              , format             )
 
-MAKE_AVFILTERLINK_ACCESSOR(AVRational       , frame_rate         )
 MAKE_AVFILTERLINK_ACCESSOR(int              , w                  )
 MAKE_AVFILTERLINK_ACCESSOR(int              , h                  )
 MAKE_AVFILTERLINK_ACCESSOR(AVRational       , sample_aspect_ratio)
@@ -188,6 +187,13 @@ MAKE_AVFILTERLINK_ACCESSOR(enum AVColorRange, color_range)
 
 MAKE_AVFILTERLINK_ACCESSOR(int              , sample_rate        )
 
+AVRational av_buffersink_get_frame_rate(const AVFilterContext *ctx)
+{
+    FilterLink *l = ff_filter_link(ctx->inputs[0]);
+    av_assert0(ctx->filter->activate == activate);
+    return l->frame_rate;
+}
+
 AVBufferRef* av_buffersink_get_hw_frames_ctx(const AVFilterContext *ctx)
 {
     FilterLink *l = ff_filter_link(ctx->inputs[0]);
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index b6e8f8036c..2743493d5d 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -520,7 +520,7 @@ static int config_props(AVFilterLink *link)
     }
 
     link->time_base = c->time_base;
-    link->frame_rate = c->frame_rate;
+    l->frame_rate = c->frame_rate;
     return 0;
 }
 
diff --git a/libavfilter/f_drawgraph.c b/libavfilter/f_drawgraph.c
index 1109780550..8144a9c385 100644
--- a/libavfilter/f_drawgraph.c
+++ b/libavfilter/f_drawgraph.c
@@ -26,6 +26,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -424,13 +425,14 @@ static int request_frame(AVFilterLink *outlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     DrawGraphContext *s = outlink->src->priv;
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = s->frame_rate;
+    outlink->time_base = av_inv_q(l->frame_rate);
     s->prev_pts = AV_NOPTS_VALUE;
 
     return 0;
diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
index 436a9eb7a9..b2495aed9b 100644
--- a/libavfilter/f_ebur128.c
+++ b/libavfilter/f_ebur128.c
@@ -294,6 +294,7 @@ static int config_video_output(AVFilterLink *outlink)
 {
     int i, x, y;
     uint8_t *p;
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     EBUR128Context *ebur128 = ctx->priv;
     AVFrame *outpicref;
@@ -307,8 +308,8 @@ static int config_video_output(AVFilterLink *outlink)
     outlink->w = ebur128->w;
     outlink->h = ebur128->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = av_make_q(10, 1);
-    outlink->time_base = av_inv_q(outlink->frame_rate);
+    l->frame_rate = av_make_q(10, 1);
+    outlink->time_base = av_inv_q(l->frame_rate);
 
 #define PAD 8
 
diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c
index 06573dbb96..72ca5cea15 100644
--- a/libavfilter/f_graphmonitor.c
+++ b/libavfilter/f_graphmonitor.c
@@ -288,7 +288,7 @@ static int draw_items(AVFilterContext *ctx,
     }
     if (flags & FLAG_RATE) {
         if (l->type == AVMEDIA_TYPE_VIDEO) {
-            len = snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", l->frame_rate.num, l->frame_rate.den);
+            len = snprintf(buffer, sizeof(buffer)-1, " | fps: %d/%d", fl->frame_rate.num, fl->frame_rate.den);
         } else if (l->type == AVMEDIA_TYPE_AUDIO) {
             len = snprintf(buffer, sizeof(buffer)-1, " | samplerate: %d", l->sample_rate);
         }
@@ -538,6 +538,7 @@ static int activate(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     GraphMonitorContext *s = outlink->src->priv;
 
     s->white[0] = s->white[1] = s->white[2] = 255;
@@ -551,7 +552,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = (AVRational){1,1};
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
     outlink->time_base = av_inv_q(s->frame_rate);
 
     return 0;
diff --git a/libavfilter/f_interleave.c b/libavfilter/f_interleave.c
index 93ad548826..e989fbc927 100644
--- a/libavfilter/f_interleave.c
+++ b/libavfilter/f_interleave.c
@@ -183,6 +183,7 @@ static av_cold int init(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink0 = ctx->inputs[0];
     int i;
@@ -193,7 +194,7 @@ static int config_output(AVFilterLink *outlink)
         outlink->h                   = inlink0->h;
         outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
         outlink->format              = inlink0->format;
-        outlink->frame_rate = (AVRational) {1, 0};
+        l->frame_rate = (AVRational) {1, 0};
         for (i = 1; i < ctx->nb_inputs; i++) {
             AVFilterLink *inlink = ctx->inputs[i];
 
diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c
index f58436e679..9c9c03fb05 100644
--- a/libavfilter/f_loop.c
+++ b/libavfilter/f_loop.c
@@ -376,6 +376,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 {
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink *outl = ff_filter_link(outlink);
     LoopContext *s = ctx->priv;
     int64_t duration;
     int ret = 0;
@@ -394,7 +395,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
             if (frame->duration)
                 duration = frame->duration;
             else
-                duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+                duration = av_rescale_q(1, av_inv_q(outl->frame_rate), outlink->time_base);
             s->duration += duration;
             s->pts_offset = s->duration;
             ret = ff_filter_frame(outlink, frame);
diff --git a/libavfilter/f_streamselect.c b/libavfilter/f_streamselect.c
index c17b019969..285e7d7315 100644
--- a/libavfilter/f_streamselect.c
+++ b/libavfilter/f_streamselect.c
@@ -98,11 +98,13 @@ static int activate(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl     = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     StreamSelectContext *s = ctx->priv;
     const int outlink_idx = FF_OUTLINK_IDX(outlink);
     const int inlink_idx  = s->map[outlink_idx];
     AVFilterLink *inlink = ctx->inputs[inlink_idx];
+    FilterLink      *inl = ff_filter_link(inlink);
     FFFrameSyncIn *in;
     int i, ret;
 
@@ -115,7 +117,7 @@ static int config_output(AVFilterLink *outlink)
         outlink->w = inlink->w;
         outlink->h = inlink->h;
         outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-        outlink->frame_rate = inlink->frame_rate;
+        outl->frame_rate = inl->frame_rate;
         break;
     case AVMEDIA_TYPE_AUDIO:
         outlink->sample_rate    = inlink->sample_rate;
diff --git a/libavfilter/filters.h b/libavfilter/filters.h
index 98b2442389..fc65f1df20 100644
--- a/libavfilter/filters.h
+++ b/libavfilter/filters.h
@@ -70,6 +70,21 @@ typedef struct FilterLink {
      */
     int max_samples;
 
+    /**
+     * Frame rate of the stream on the link, or 1/0 if unknown or variable.
+     *
+     * May be set by the link source filter in its config_props(); if left to
+     * 0/0, will be automatically copied from the first input of the source
+     * filter if it exists.
+     *
+     * Sources should set it to the best estimation of the real frame rate.
+     * If the source frame rate is unknown or variable, set this to 1/0.
+     * Filters should update it if necessary depending on their function.
+     * Sinks can use it to set a default output frame rate.
+     * It is similar to the r_frame_rate field in AVStream.
+     */
+    AVRational frame_rate;
+
     /**
      * For hwaccel pixel formats, this should be a reference to the
      * AVHWFramesContext describing the frames.
diff --git a/libavfilter/qrencode.c b/libavfilter/qrencode.c
index 1c7ce23e6e..f308de7646 100644
--- a/libavfilter/qrencode.c
+++ b/libavfilter/qrencode.c
@@ -41,6 +41,7 @@
 #include "avfilter.h"
 #include "drawutils.h"
 #include "internal.h"
+#include "filters.h"
 #include "formats.h"
 #include "textutils.h"
 #include "video.h"
@@ -586,6 +587,7 @@ AVFILTER_DEFINE_CLASS(qrencodesrc);
 
 static int qrencodesrc_config_props(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     QREncodeContext *qr = ctx->priv;
     int ret;
@@ -645,7 +647,7 @@ static int qrencodesrc_config_props(AVFilterLink *outlink)
     outlink->w = qr->rendered_padded_qrcode_width;
     outlink->h = qr->rendered_padded_qrcode_width;
     outlink->time_base = av_inv_q(qr->frame_rate);
-    outlink->frame_rate = qr->frame_rate;
+    l->frame_rate = qr->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c
index 24e15020b2..3f6f4620b6 100644
--- a/libavfilter/qsvvpp.c
+++ b/libavfilter/qsvvpp.c
@@ -298,13 +298,13 @@ static int map_frame_to_surface(AVFrame *frame, mfxFrameSurface1 *surface)
 /* fill the surface info */
 static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     enum AVPixelFormat        pix_fmt;
     AVHWFramesContext        *frames_ctx;
     AVQSVFramesContext       *frames_hwctx;
     const AVPixFmtDescriptor *desc;
 
     if (link->format == AV_PIX_FMT_QSV) {
-        FilterLink *l = ff_filter_link(link);
         if (!l->hw_frames_ctx)
             return AVERROR(EINVAL);
 
@@ -336,8 +336,8 @@ static int fill_frameinfo_by_link(mfxFrameInfo *frameinfo, AVFilterLink *link)
 
     frameinfo->CropW          = link->w;
     frameinfo->CropH          = link->h;
-    frameinfo->FrameRateExtN  = link->frame_rate.num;
-    frameinfo->FrameRateExtD  = link->frame_rate.den;
+    frameinfo->FrameRateExtN  = l->frame_rate.num;
+    frameinfo->FrameRateExtD  = l->frame_rate.den;
 
     /* Apparently VPP in the SDK requires the frame rate to be set to some value, otherwise
      * init will fail */
@@ -514,8 +514,8 @@ static QSVFrame *query_frame(QSVVPPContext *s, AVFilterLink *outlink, const AVFr
             return NULL;
     }
 
-    if (outlink->frame_rate.num && outlink->frame_rate.den)
-        out_frame->frame->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+    if (l->frame_rate.num && l->frame_rate.den)
+        out_frame->frame->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
     else
         out_frame->frame->duration = 0;
 
diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c
index 60cf2b642e..9931387c61 100644
--- a/libavfilter/setpts.c
+++ b/libavfilter/setpts.c
@@ -131,6 +131,7 @@ static av_cold int init(AVFilterContext *ctx)
 
 static int config_input(AVFilterLink *inlink)
 {
+    FilterLink *l = ff_filter_link(inlink);
     AVFilterContext *ctx = inlink->dst;
     SetPTSContext *setpts = ctx->priv;
 
@@ -142,8 +143,8 @@ static int config_input(AVFilterLink *inlink)
         setpts->type == AVMEDIA_TYPE_AUDIO ? inlink->sample_rate : NAN;
 
     V(FRAME_RATE) = V(FR) =
-        inlink->frame_rate.num && inlink->frame_rate.den ?
-        av_q2d(inlink->frame_rate) : NAN;
+        l->frame_rate.num && l->frame_rate.den ?
+        av_q2d(l->frame_rate) : NAN;
 
     av_log(inlink->src, AV_LOG_VERBOSE, "TB:%f FRAME_RATE:%f SAMPLE_RATE:%f\n",
            V(TB), V(FRAME_RATE), V(SAMPLE_RATE));
@@ -152,7 +153,9 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output_video(AVFilterLink *outlink)
 {
-    outlink->frame_rate = (AVRational){ 1, 0 };
+    FilterLink *l = ff_filter_link(outlink);
+
+    l->frame_rate = (AVRational){ 1, 0 };
 
     return 0;
 }
diff --git a/libavfilter/src_avsynctest.c b/libavfilter/src_avsynctest.c
index 9fd0b590c1..f69ae08b84 100644
--- a/libavfilter/src_avsynctest.c
+++ b/libavfilter/src_avsynctest.c
@@ -145,13 +145,14 @@ static av_cold int aconfig_props(AVFilterLink *outlink)
 
 static av_cold int config_props(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVSyncTestContext *s = ctx->priv;
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->frame_rate);
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
     outlink->sample_aspect_ratio = (AVRational) {1, 1};
     s->delay_min = av_mul_q(s->frame_rate, av_make_q(-1, 2));
     s->delay_max = av_mul_q(s->delay_min, av_make_q(-1, 1));
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index e2cdcf17db..e6e08cdda4 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -450,6 +450,7 @@ static int movie_query_formats(AVFilterContext *ctx)
 
 static int movie_config_output_props(AVFilterLink *outlink)
 {
+    FilterLink *l = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     MovieContext *movie  = ctx->priv;
     unsigned out_id = FF_OUTLINK_IDX(outlink);
@@ -462,7 +463,7 @@ static int movie_config_output_props(AVFilterLink *outlink)
     case AVMEDIA_TYPE_VIDEO:
         outlink->w          = c->width;
         outlink->h          = c->height;
-        outlink->frame_rate = st->st->r_frame_rate;
+        l->frame_rate = st->st->r_frame_rate;
         break;
     case AVMEDIA_TYPE_AUDIO:
         break;
diff --git a/libavfilter/stack_internal.c b/libavfilter/stack_internal.c
index 1ee20d66cf..b473fa982d 100644
--- a/libavfilter/stack_internal.c
+++ b/libavfilter/stack_internal.c
@@ -52,9 +52,11 @@ static int init_framesync(AVFilterContext *avctx)
 
 static int config_comm_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     StackBaseContext *sctx = avctx->priv;
     AVFilterLink *inlink0 = avctx->inputs[0];
+    FilterLink *inl0 = ff_filter_link(inlink0);
     int width, height, ret;
 
     if (sctx->mode == STACK_H) {
@@ -197,16 +199,16 @@ static int config_comm_output(AVFilterLink *outlink)
 
     outlink->w = width;
     outlink->h = height;
-    outlink->frame_rate = inlink0->frame_rate;
+    outl->frame_rate = inl0->frame_rate;
     outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
 
     for (int i = 1; i < sctx->nb_inputs; i++) {
-        AVFilterLink *inlink = avctx->inputs[i];
-        if (outlink->frame_rate.num != inlink->frame_rate.num ||
-            outlink->frame_rate.den != inlink->frame_rate.den) {
+        FilterLink *inlink = ff_filter_link(avctx->inputs[i]);
+        if (outl->frame_rate.num != inlink->frame_rate.num ||
+            outl->frame_rate.den != inlink->frame_rate.den) {
             av_log(avctx, AV_LOG_VERBOSE,
                     "Video inputs have different frame rates, output will be VFR\n");
-            outlink->frame_rate = av_make_q(1, 0);
+            outl->frame_rate = av_make_q(1, 0);
             break;
         }
     }
diff --git a/libavfilter/vaf_spectrumsynth.c b/libavfilter/vaf_spectrumsynth.c
index f4bc0f3025..027b9c6842 100644
--- a/libavfilter/vaf_spectrumsynth.c
+++ b/libavfilter/vaf_spectrumsynth.c
@@ -140,10 +140,12 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     SpectrumSynthContext *s = ctx->priv;
+    FilterLink *inl0 = ff_filter_link(ctx->inputs[0]);
+    FilterLink *inl1 = ff_filter_link(ctx->inputs[1]);
     int width = ctx->inputs[0]->w;
     int height = ctx->inputs[0]->h;
     AVRational time_base  = ctx->inputs[0]->time_base;
-    AVRational frame_rate = ctx->inputs[0]->frame_rate;
+    AVRational frame_rate = inl0->frame_rate;
     float factor, overlap, scale;
     int i, ch, ret;
 
@@ -164,12 +166,12 @@ static int config_output(AVFilterLink *outlink)
                ctx->inputs[1]->time_base.num,
                ctx->inputs[1]->time_base.den);
         return AVERROR_INVALIDDATA;
-    } else if (av_cmp_q(frame_rate, ctx->inputs[1]->frame_rate) != 0) {
+    } else if (av_cmp_q(frame_rate, inl1->frame_rate) != 0) {
         av_log(ctx, AV_LOG_ERROR,
                "Magnitude and Phase framerates differ (%d/%d vs %d/%d).\n",
                frame_rate.num, frame_rate.den,
-               ctx->inputs[1]->frame_rate.num,
-               ctx->inputs[1]->frame_rate.den);
+               inl1->frame_rate.num,
+               inl1->frame_rate.den);
         return AVERROR_INVALIDDATA;
     }
 
diff --git a/libavfilter/vf_alphamerge.c b/libavfilter/vf_alphamerge.c
index a5f5baf77e..f3fc1529aa 100644
--- a/libavfilter/vf_alphamerge.c
+++ b/libavfilter/vf_alphamerge.c
@@ -128,9 +128,11 @@ static int config_input_main(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AlphaMergeContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *ml = ff_filter_link(mainlink);
     AVFilterLink *alphalink = ctx->inputs[1];
     int ret;
 
@@ -149,7 +151,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    outl->frame_rate = ml->frame_rate;
 
     return ff_framesync_configure(&s->fs);
 }
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index 5ea6df2e75..d93daa1fac 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -25,6 +25,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixfmt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "vf_blend_init.h"
@@ -339,8 +340,10 @@ static int config_params(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *toplink = ctx->inputs[TOP];
+    FilterLink *tl = ff_filter_link(toplink);
     BlendContext *s = ctx->priv;
     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(toplink->format);
     int ret;
@@ -362,7 +365,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = toplink->h;
     outlink->time_base = toplink->time_base;
     outlink->sample_aspect_ratio = toplink->sample_aspect_ratio;
-    outlink->frame_rate = toplink->frame_rate;
+    outl->frame_rate = tl->frame_rate;
 
     s->hsub = pix_desc->log2_chroma_w;
     s->vsub = pix_desc->log2_chroma_h;
diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c
index 417be766b8..05ecfa0830 100644
--- a/libavfilter/vf_blend_vulkan.c
+++ b/libavfilter/vf_blend_vulkan.c
@@ -25,6 +25,8 @@
 #include "libavutil/opt.h"
 #include "vulkan_filter.h"
 #include "vulkan_spirv.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "framesync.h"
 #include "blend.h"
@@ -299,9 +301,11 @@ static av_cold void uninit(AVFilterContext *avctx)
 static int config_props_output(AVFilterLink *outlink)
 {
     int err;
+    FilterLink *outl       = ff_filter_link(outlink);
     AVFilterContext *avctx = outlink->src;
     BlendVulkanContext *s = avctx->priv;
     AVFilterLink *toplink = avctx->inputs[IN_TOP];
+    FilterLink   *tl      = ff_filter_link(toplink);
     AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM];
 
     if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) {
@@ -314,7 +318,7 @@ static int config_props_output(AVFilterLink *outlink)
     }
 
     outlink->sample_aspect_ratio = toplink->sample_aspect_ratio;
-    outlink->frame_rate = toplink->frame_rate;
+    outl->frame_rate = tl->frame_rate;
 
     RET(ff_vk_filter_config_output(outlink));
 
diff --git a/libavfilter/vf_bm3d.c b/libavfilter/vf_bm3d.c
index eb7f6d34d9..408ce20891 100644
--- a/libavfilter/vf_bm3d.c
+++ b/libavfilter/vf_bm3d.c
@@ -953,9 +953,11 @@ static av_cold int init(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl     = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     BM3DContext *s = ctx->priv;
     AVFilterLink *src = ctx->inputs[0];
+    FilterLink  *srcl = ff_filter_link(src);
     AVFilterLink *ref;
     FFFrameSyncIn *in;
     int ret;
@@ -978,7 +980,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = src->h;
     outlink->time_base = src->time_base;
     outlink->sample_aspect_ratio = src->sample_aspect_ratio;
-    outlink->frame_rate = src->frame_rate;
+    outl->frame_rate = srcl->frame_rate;
 
     if (!s->ref)
         return 0;
diff --git a/libavfilter/vf_ccrepack.c b/libavfilter/vf_ccrepack.c
index 5213eab82b..a6aad87864 100644
--- a/libavfilter/vf_ccrepack.c
+++ b/libavfilter/vf_ccrepack.c
@@ -30,6 +30,7 @@
  */
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "ccfifo.h"
 #include "video.h"
@@ -49,9 +50,10 @@ AVFILTER_DEFINE_CLASS(ccrepack);
 
 static int config_input(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     CCRepackContext *ctx = link->dst->priv;
 
-    int ret = ff_ccfifo_init(&ctx->cc_fifo, link->frame_rate, ctx);
+    int ret = ff_ccfifo_init(&ctx->cc_fifo, l->frame_rate, ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
         return ret;
diff --git a/libavfilter/vf_colormap.c b/libavfilter/vf_colormap.c
index 31f33e7ebd..aa09d0cf67 100644
--- a/libavfilter/vf_colormap.c
+++ b/libavfilter/vf_colormap.c
@@ -28,6 +28,7 @@
 #include "libavutil/common.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "framesync.h"
 #include "video.h"
@@ -482,16 +483,18 @@ static int process_frame(FFFrameSync *fs)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl     = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     ColorMapContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     AVFilterLink *source = ctx->inputs[1];
     AVFilterLink *target = ctx->inputs[2];
     FFFrameSyncIn *in;
     int ret;
 
     outlink->time_base = inlink->time_base;
-    outlink->frame_rate = inlink->frame_rate;
+    outl->frame_rate   = inl->frame_rate;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     outlink->w = inlink->w;
     outlink->h = inlink->h;
diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c
index 971494f3d5..eb83794b88 100644
--- a/libavfilter/vf_convolve.c
+++ b/libavfilter/vf_convolve.c
@@ -28,6 +28,7 @@
 #include "libavutil/tx.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 
@@ -744,10 +745,12 @@ static int do_convolve(FFFrameSync *fs)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     AVFilterContext *ctx = outlink->src;
     ConvolveContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink         *ml = ff_filter_link(mainlink);
     AVFilterLink *secondlink = ctx->inputs[1];
     int ret, i, j;
 
@@ -769,7 +772,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    outl->frame_rate = ml->frame_rate;
 
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
diff --git a/libavfilter/vf_coreimage.m b/libavfilter/vf_coreimage.m
index 4d4cdfb7c7..5c77e8a554 100644
--- a/libavfilter/vf_coreimage.m
+++ b/libavfilter/vf_coreimage.m
@@ -27,6 +27,7 @@
 #import <AppKit/AppKit.h>
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -65,12 +66,13 @@ typedef struct CoreImageContext {
 
 static int config_output(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     CoreImageContext *ctx = link->src->priv;
 
     link->w                   = ctx->w;
     link->h                   = ctx->h;
     link->sample_aspect_ratio = ctx->sar;
-    link->frame_rate          = ctx->frame_rate;
+    l->frame_rate             = ctx->frame_rate;
     link->time_base           = ctx->time_base;
 
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
diff --git a/libavfilter/vf_corr.c b/libavfilter/vf_corr.c
index 27e01b8775..928eafff96 100644
--- a/libavfilter/vf_corr.c
+++ b/libavfilter/vf_corr.c
@@ -27,6 +27,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 
@@ -330,9 +331,11 @@ static int config_input_ref(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     CorrContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *ml = ff_filter_link(mainlink);
     int ret;
 
     ret = ff_framesync_init_dualinput(&s->fs, ctx);
@@ -342,7 +345,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    outl->frame_rate = ml->frame_rate;
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
 
diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c
index 30910bd0c4..d3b03e76f6 100644
--- a/libavfilter/vf_decimate.c
+++ b/libavfilter/vf_decimate.c
@@ -381,10 +381,12 @@ static const enum AVPixelFormat pix_fmts[] = {
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink *outl     = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     DecimateContext *dm = ctx->priv;
     const AVFilterLink *inlink = ctx->inputs[INPUT_MAIN];
-    AVRational fps = inlink->frame_rate;
+    FilterLink *inl = ff_filter_link(ctx->inputs[INPUT_MAIN]);
+    AVRational fps = inl->frame_rate;
     int max_value;
     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
     const int w = inlink->w;
@@ -426,9 +428,9 @@ static int config_output(AVFilterLink *outlink)
             fps.num, fps.den, outlink->time_base.den, outlink->time_base.num);
     } else {
         outlink->time_base = dm->dec_tb;
-        outlink->frame_rate = av_inv_q(outlink->time_base);
+        outl->frame_rate = av_inv_q(outlink->time_base);
         av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
-            fps.num, fps.den, outlink->frame_rate.num, outlink->frame_rate.den);
+            fps.num, fps.den, outl->frame_rate.num, outl->frame_rate.den);
     }
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     if (dm->ppsrc) {
diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c
index dbaba26ab4..5a64e5f33a 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -23,6 +23,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "vaapi_vpp.h"
@@ -158,7 +159,9 @@ static int deint_vaapi_build_filter_params(AVFilterContext *avctx)
 
 static int deint_vaapi_config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
     AVFilterContext *avctx = outlink->src;
     DeintVAAPIContext *ctx = avctx->priv;
     int err;
@@ -168,8 +171,8 @@ static int deint_vaapi_config_output(AVFilterLink *outlink)
         return err;
     outlink->time_base  = av_mul_q(inlink->time_base,
                                    (AVRational) { 1, ctx->field_rate });
-    outlink->frame_rate = av_mul_q(inlink->frame_rate,
-                                   (AVRational) { ctx->field_rate, 1 });
+    outl->frame_rate = av_mul_q(inl->frame_rate,
+                                (AVRational) { ctx->field_rate, 1 });
 
     return 0;
 }
diff --git a/libavfilter/vf_dejudder.c b/libavfilter/vf_dejudder.c
index f8c35ae34c..0a4a68bd8d 100644
--- a/libavfilter/vf_dejudder.c
+++ b/libavfilter/vf_dejudder.c
@@ -52,6 +52,7 @@
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 
 typedef struct DejudderContext {
@@ -78,12 +79,14 @@ AVFILTER_DEFINE_CLASS(dejudder);
 
 static int config_out_props(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     DejudderContext *s = ctx->priv;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink      *inl = ff_filter_link(inlink);
 
     outlink->time_base = av_mul_q(inlink->time_base, av_make_q(1, 2 * s->cycle));
-    outlink->frame_rate = av_mul_q(inlink->frame_rate, av_make_q(2 * s->cycle, 1));
+    outl->frame_rate = av_mul_q(inl->frame_rate, av_make_q(2 * s->cycle, 1));
 
     av_log(ctx, AV_LOG_VERBOSE, "cycle:%d\n", s->cycle);
 
diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c
index 9e87007cbb..47b74a8606 100644
--- a/libavfilter/vf_deshake_opencl.c
+++ b/libavfilter/vf_deshake_opencl.c
@@ -1156,7 +1156,7 @@ static int deshake_opencl_init(AVFilterContext *avctx)
     ff_framequeue_global_init(&fqg);
     ff_framequeue_init(&ctx->fq, &fqg);
     ctx->eof = 0;
-    ctx->smooth_window = (int)(av_q2d(avctx->inputs[0]->frame_rate) * ctx->smooth_window_multiplier);
+    ctx->smooth_window = (int)(av_q2d(inl->frame_rate) * ctx->smooth_window_multiplier);
     ctx->curr_frame = 0;
 
     memset(&zeroed_ulong8, 0, sizeof(cl_ulong8));
@@ -1370,6 +1370,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *input_frame)
 {
     AVFilterContext *avctx = link->dst;
     AVFilterLink *outlink = avctx->outputs[0];
+    FilterLink      *outl = ff_filter_link(outlink);
     DeshakeOpenCLContext *deshake_ctx = avctx->priv;
     AVFrame *cropped_frame = NULL, *transformed_frame = NULL;
     int err;
@@ -1416,7 +1417,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *input_frame)
     if (input_frame->duration) {
         duration = input_frame->duration;
     } else {
-        duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+        duration = av_rescale_q(1, av_inv_q(outl->frame_rate), outlink->time_base);
     }
     deshake_ctx->duration = input_frame->pts + duration;
 
diff --git a/libavfilter/vf_detelecine.c b/libavfilter/vf_detelecine.c
index 255126da4e..eb81e3424e 100644
--- a/libavfilter/vf_detelecine.c
+++ b/libavfilter/vf_detelecine.c
@@ -28,6 +28,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -162,10 +163,12 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     DetelecineContext *s = ctx->priv;
     const AVFilterLink *inlink = ctx->inputs[0];
-    AVRational fps = inlink->frame_rate;
+    const FilterLink      *inl = ff_filter_link(ctx->inputs[0]);
+    AVRational fps = inl->frame_rate;
 
     if (!fps.num || !fps.den) {
         av_log(ctx, AV_LOG_ERROR, "The input needs a constant frame rate; "
@@ -174,9 +177,9 @@ static int config_output(AVFilterLink *outlink)
     }
     fps = av_mul_q(fps, av_inv_q(s->pts));
     av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
-           inlink->frame_rate.num, inlink->frame_rate.den, fps.num, fps.den);
+           inl->frame_rate.num, inl->frame_rate.den, fps.num, fps.den);
 
-    outlink->frame_rate = fps;
+    outl->frame_rate = fps;
     outlink->time_base = av_mul_q(inlink->time_base, s->pts);
     av_log(ctx, AV_LOG_VERBOSE, "TB: %d/%d -> %d/%d\n",
            inlink->time_base.num, inlink->time_base.den, outlink->time_base.num, outlink->time_base.den);
diff --git a/libavfilter/vf_displace.c b/libavfilter/vf_displace.c
index 93de62fb5c..c243d422d8 100644
--- a/libavfilter/vf_displace.c
+++ b/libavfilter/vf_displace.c
@@ -21,6 +21,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "video.h"
@@ -318,9 +319,11 @@ static int config_input(AVFilterLink *inlink)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl = ff_filter_link(outlink);
     AVFilterContext *ctx = outlink->src;
     DisplaceContext *s = ctx->priv;
     AVFilterLink *srclink = ctx->inputs[0];
+    FilterLink        *sl = ff_filter_link(srclink);
     AVFilterLink *xlink = ctx->inputs[1];
     AVFilterLink *ylink = ctx->inputs[2];
     FFFrameSyncIn *in;
@@ -343,7 +346,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = srclink->w;
     outlink->h = srclink->h;
     outlink->sample_aspect_ratio = srclink->sample_aspect_ratio;
-    outlink->frame_rate = srclink->frame_rate;
+    outl->frame_rate = sl->frame_rate;
 
     ret = ff_framesync_init(&s->fs, ctx, 3);
     if (ret < 0)
diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c
index 30ff976940..38a13b0cfb 100644
--- a/libavfilter/vf_eq.c
+++ b/libavfilter/vf_eq.c
@@ -31,6 +31,8 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+
+#include "filters.h"
 #include "internal.h"
 #include "vf_eq.h"
 #include "video.h"
@@ -197,11 +199,12 @@ static av_cold void uninit(AVFilterContext *ctx)
 
 static int config_props(AVFilterLink *inlink)
 {
+    FilterLink *l = ff_filter_link(inlink);
     EQContext *eq = inlink->dst->priv;
 
     eq->var_values[VAR_N] = 0;
-    eq->var_values[VAR_R] = inlink->frame_rate.num == 0 || inlink->frame_rate.den == 0 ?
-        NAN : av_q2d(inlink->frame_rate);
+    eq->var_values[VAR_R] = l->frame_rate.num == 0 || l->frame_rate.den == 0 ?
+        NAN : av_q2d(l->frame_rate);
 
     return 0;
 }
diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c
index b785c290ff..fccbec7853 100644
--- a/libavfilter/vf_estdif.c
+++ b/libavfilter/vf_estdif.c
@@ -23,6 +23,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -133,13 +134,15 @@ static const enum AVPixelFormat pix_fmts[] = {
 
 static int 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);
     ESTDIFContext *s = ctx->priv;
 
     outlink->time_base = av_mul_q(inlink->time_base, (AVRational){1, 2});
     if (s->mode)
-        outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1});
+        outl->frame_rate = av_mul_q(inl->frame_rate, (AVRational){2, 1});
 
     return 0;
 }
@@ -526,6 +529,7 @@ static int config_input(AVFilterLink *inlink)
 
 static int request_frame(AVFilterLink *link)
 {
+    FilterLink *l = ff_filter_link(link);
     AVFilterContext *ctx = link->src;
     ESTDIFContext *s = ctx->priv;
     int ret;
@@ -541,7 +545,7 @@ static int request_frame(AVFilterLink *link)
         if (!next)
             return AVERROR(ENOMEM);
 
-        next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(ctx->outputs[0]->frame_rate),
+        next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(l->frame_rate),
                                                 ctx->outputs[0]->time_base);
         s->eof = 1;
         ret = filter_frame(ctx->inputs[0], next);
diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index ffa36c9449..1625c08306 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -1046,16 +1046,18 @@ static av_cold void fieldmatch_uninit(AVFilterContext *ctx)
 
 static int config_output(AVFilterLink *outlink)
 {
+    FilterLink     *outl  = ff_filter_link(outlink);
     AVFilterContext *ctx  = outlink->src;
     FieldMatchContext *fm = ctx->priv;
     const AVFilterLink *inlink =
         ctx->inputs[fm->ppsrc ? INPUT_CLEANSRC : INPUT_MAIN];
+    FilterLink *inl = ff_filter_link(ctx->inputs[fm->ppsrc ? INPUT_CLEANSRC : INPUT_MAIN]);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 
     fm->bpc = (desc->comp[0].depth + 7) / 8;
     outlink->time_base = inlink->time_base;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-    outlink->frame_rate = inlink->frame_rate;
+    outl->frame_rate = inl->frame_rate;
     outlink->w = inlink->w;
     outlink->h = inlink->h;
     return 0;
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index 02636d0f78..c422c5e9a6 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -178,12 +178,14 @@ static int config_props(AVFilterLink* outlink)
 {
     AVFilterContext *ctx    = outlink->src;
     AVFilterLink    *inlink = ctx->inputs[0];
+    FilterLink      *il     = ff_filter_link(inlink);
+    FilterLink      *ol     = ff_filter_link(outlink);
     FPSContext      *s      = ctx->priv;
 
     double var_values[VARS_NB], res;
     int ret;
 
-    var_values[VAR_SOURCE_FPS]    = av_q2d(inlink->frame_rate);
+    var_values[VAR_SOURCE_FPS]    = av_q2d(il->frame_rate);
     var_values[VAR_FPS_NTSC]      = ntsc_fps;
     var_values[VAR_FPS_PAL]       = pal_fps;
     var_values[VAR_FPS_FILM]      = film_fps;
@@ -194,8 +196,8 @@ static int config_props(AVFilterLink* outlink)
     if (ret < 0)
         return ret;
 
-    outlink->frame_rate = av_d2q(res, INT_MAX);
-    outlink->time_base  = av_inv_q(outlink->frame_rate);
+    ol->frame_rate      = av_d2q(res, INT_MAX);
+    outlink->time_base  = av_inv_q(ol->frame_rate);
 
     /* Calculate the input and output pts offsets for start_time */
     if (s->start_time != DBL_MAX && s->start_time != AV_NOPTS_VALUE) {
@@ -214,13 +216,13 @@ static int config_props(AVFilterLink* outlink)
                s->in_pts_off, s->out_pts_off, s->start_time);
     }
 
-    ret = ff_ccfifo_init(&s->cc_fifo, outlink->frame_rate, ctx);
+    ret = ff_ccfifo_init(&s->cc_fifo, ol->frame_rate, ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
         return ret;
     }
 
-    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", outlink->frame_rate.num, outlink->frame_rate.den);
+    av_log(ctx, AV_LOG_VERBOSE, "fps=%d/%d\n", ol->frame_rate.num, ol->frame_rate.den);
 
     return 0;
 }
diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c
index 3b915ddddf..d3a195c024 100644
--- a/libavfilter/vf_framepack.c
+++ b/libavfilter/vf_framepack.c
@@ -91,11 +91,14 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx  = outlink->src;
     FramepackContext *s   = outlink->src->priv;
+    FilterLink     *leftl = ff_filter_link(ctx->inputs[LEFT]);
+    FilterLink    *rightl = ff_filter_link(ctx->inputs[RIGHT]);
+    FilterLink        *ol = ff_filter_link(outlink);
 
     int width             = ctx->inputs[LEFT]->w;
     int height            = ctx->inputs[LEFT]->h;
     AVRational time_base  = ctx->inputs[LEFT]->time_base;
-    AVRational frame_rate = ctx->inputs[LEFT]->frame_rate;
+    AVRational frame_rate = leftl->frame_rate;
 
     // check size and fps match on the other input
     if (width  != ctx->inputs[RIGHT]->w ||
@@ -112,12 +115,12 @@ static int config_output(AVFilterLink *outlink)
                ctx->inputs[RIGHT]->time_base.num,
                ctx->inputs[RIGHT]->time_base.den);
         return AVERROR_INVALIDDATA;
-    } else if (av_cmp_q(frame_rate, ctx->inputs[RIGHT]->frame_rate) != 0) {
+    } else if (av_cmp_q(frame_rate, rightl->frame_rate) != 0) {
         av_log(ctx, AV_LOG_ERROR,
                "Left and right framerates differ (%d/%d vs %d/%d).\n",
                frame_rate.num, frame_rate.den,
-               ctx->inputs[RIGHT]->frame_rate.num,
-               ctx->inputs[RIGHT]->frame_rate.den);
+               rightl->frame_rate.num,
+               rightl->frame_rate.den);
         return AVERROR_INVALIDDATA;
     }
 
@@ -148,7 +151,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w          = width;
     outlink->h          = height;
     outlink->time_base  = time_base;
-    outlink->frame_rate = frame_rate;
+    ol->frame_rate      = frame_rate;
 
     return 0;
 }
@@ -312,6 +315,7 @@ static int try_push_frame(AVFilterContext *ctx)
 {
     FramepackContext *s = ctx->priv;
     AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink       *l = ff_filter_link(outlink);
     AVStereo3D *stereo;
     int ret, i;
 
@@ -323,8 +327,8 @@ static int try_push_frame(AVFilterContext *ctx)
         for (i = 0; i < 2; i++) {
             // set correct timestamps
             if (pts != AV_NOPTS_VALUE) {
-                s->input_views[i]->pts = i == 0 ? pts * 2 : pts * 2 + av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
-                s->input_views[i]->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+                s->input_views[i]->pts = i == 0 ? pts * 2 : pts * 2 + av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
+                s->input_views[i]->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
             }
 
             // set stereo3d side data
diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c
index 0c31f77cc4..f525ab1b65 100644
--- a/libavfilter/vf_framerate.c
+++ b/libavfilter/vf_framerate.c
@@ -374,6 +374,7 @@ retry:
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     FrameRateContext *s = ctx->priv;
     int exact;
 
@@ -399,7 +400,7 @@ static int config_output(AVFilterLink *outlink)
         av_log(ctx, AV_LOG_WARNING, "Timebase conversion is not exact\n");
     }
 
-    outlink->frame_rate = s->dest_frame_rate;
+    l->frame_rate = s->dest_frame_rate;
     outlink->time_base = s->dest_time_base;
 
     ff_dlog(ctx,
diff --git a/libavfilter/vf_framestep.c b/libavfilter/vf_framestep.c
index b8eee53b59..da69e2ba6c 100644
--- a/libavfilter/vf_framestep.c
+++ b/libavfilter/vf_framestep.c
@@ -25,6 +25,7 @@
 
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -48,14 +49,16 @@ static int config_output_props(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     FrameStepContext *framestep = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink       *il = ff_filter_link(inlink);
+    FilterLink       *ol = ff_filter_link(outlink);
 
-    outlink->frame_rate =
-        av_div_q(inlink->frame_rate, (AVRational){framestep->frame_step, 1});
+    ol->frame_rate =
+        av_div_q(il->frame_rate, (AVRational){framestep->frame_step, 1});
 
     av_log(ctx, AV_LOG_VERBOSE, "step:%d frame_rate:%d/%d(%f) -> frame_rate:%d/%d(%f)\n",
            framestep->frame_step,
-           inlink->frame_rate.num, inlink->frame_rate.den, av_q2d(inlink->frame_rate),
-           outlink->frame_rate.num, outlink->frame_rate.den, av_q2d(outlink->frame_rate));
+           il->frame_rate.num, il->frame_rate.den, av_q2d(il->frame_rate),
+           ol->frame_rate.num, ol->frame_rate.den, av_q2d(ol->frame_rate));
     return 0;
 }
 
diff --git a/libavfilter/vf_freezedetect.c b/libavfilter/vf_freezedetect.c
index 18d392d9ae..ef04a2764c 100644
--- a/libavfilter/vf_freezedetect.c
+++ b/libavfilter/vf_freezedetect.c
@@ -146,6 +146,7 @@ static int activate(AVFilterContext *ctx)
     int ret;
     AVFilterLink *inlink = ctx->inputs[0];
     AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink         *l = ff_filter_link(inlink);
     FreezeDetectContext *s = ctx->priv;
     AVFrame *frame;
 
@@ -162,7 +163,7 @@ static int activate(AVFilterContext *ctx)
         if (s->reference_frame) {
             int64_t duration;
             if (s->reference_frame->pts == AV_NOPTS_VALUE || frame->pts == AV_NOPTS_VALUE || frame->pts < s->reference_frame->pts)     // Discontinuity?
-                duration = inlink->frame_rate.num > 0 ? av_rescale_q(s->n - s->reference_n, av_inv_q(inlink->frame_rate), AV_TIME_BASE_Q) : 0;
+                duration = l->frame_rate.num > 0 ? av_rescale_q(s->n - s->reference_n, av_inv_q(l->frame_rate), AV_TIME_BASE_Q) : 0;
             else
                 duration = av_rescale_q(frame->pts - s->reference_frame->pts, inlink->time_base, AV_TIME_BASE_Q);
 
diff --git a/libavfilter/vf_freezeframes.c b/libavfilter/vf_freezeframes.c
index a272336ff2..b630ad85fe 100644
--- a/libavfilter/vf_freezeframes.c
+++ b/libavfilter/vf_freezeframes.c
@@ -52,6 +52,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *sourcelink = ctx->inputs[0];
     AVFilterLink *replacelink = ctx->inputs[1];
+    FilterLink       *il = ff_filter_link(sourcelink);
+    FilterLink       *ol = ff_filter_link(outlink);
 
     if (sourcelink->w != replacelink->w || sourcelink->h != replacelink->h) {
         av_log(ctx, AV_LOG_ERROR,
@@ -65,7 +67,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = sourcelink->h;
     outlink->time_base = sourcelink->time_base;
     outlink->sample_aspect_ratio = sourcelink->sample_aspect_ratio;
-    outlink->frame_rate = sourcelink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c
index 7dccd5946f..eeaf7ad2b4 100644
--- a/libavfilter/vf_frei0r.c
+++ b/libavfilter/vf_frei0r.c
@@ -39,6 +39,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -450,6 +451,7 @@ static av_cold int source_init(AVFilterContext *ctx)
 static int source_config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink        *l = ff_filter_link(outlink);
     Frei0rContext *s = ctx->priv;
 
     if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
@@ -457,7 +459,7 @@ static int source_config_props(AVFilterLink *outlink)
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->time_base = s->time_base;
-    outlink->frame_rate = av_inv_q(s->time_base);
+    l->frame_rate = av_inv_q(s->time_base);
     outlink->sample_aspect_ratio = (AVRational){1,1};
 
     if (s->destruct && s->instance)
diff --git a/libavfilter/vf_fsync.c b/libavfilter/vf_fsync.c
index 63a5446fa3..8636ada0f8 100644
--- a/libavfilter/vf_fsync.c
+++ b/libavfilter/vf_fsync.c
@@ -224,6 +224,7 @@ end:
 static int fsync_config_props(AVFilterLink* outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink      *l   = ff_filter_link(outlink);
     FsyncContext    *s   = ctx->priv;
     int ret;
 
@@ -235,7 +236,7 @@ static int fsync_config_props(AVFilterLink* outlink)
         return AVERROR_INVALIDDATA;
     }
 
-    outlink->frame_rate = av_make_q(1, 0); // unknown or dynamic
+    l->frame_rate = av_make_q(1, 0); // unknown or dynamic
     outlink->time_base  = av_make_q(s->tb_num, s->tb_den);
 
     return 0;
diff --git a/libavfilter/vf_guided.c b/libavfilter/vf_guided.c
index 68a1b97d1c..262d1df996 100644
--- a/libavfilter/vf_guided.c
+++ b/libavfilter/vf_guided.c
@@ -337,6 +337,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     GuidedContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink         *il = ff_filter_link(mainlink);
+    FilterLink         *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int w, h, ret;
 
@@ -352,7 +354,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     s->I      = av_calloc(w * h, sizeof(*s->I));
     s->II     = av_calloc(w * h, sizeof(*s->II));
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index bf390a03fc..049f835c61 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -33,6 +33,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -265,6 +266,7 @@ static const enum AVPixelFormat pix_fmts[] = {
 static int config_props(AVFilterLink *inlink)
 {
     HueContext *hue = inlink->dst->priv;
+    FilterLink   *l = ff_filter_link(inlink);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
 
     hue->hsub = desc->log2_chroma_w;
@@ -272,8 +274,8 @@ static int config_props(AVFilterLink *inlink)
 
     hue->var_values[VAR_N]  = 0;
     hue->var_values[VAR_TB] = av_q2d(inlink->time_base);
-    hue->var_values[VAR_R]  = inlink->frame_rate.num == 0 || inlink->frame_rate.den == 0 ?
-        NAN : av_q2d(inlink->frame_rate);
+    hue->var_values[VAR_R]  = l->frame_rate.num == 0 || l->frame_rate.den == 0 ?
+        NAN : av_q2d(l->frame_rate);
 
     return 0;
 }
diff --git a/libavfilter/vf_hysteresis.c b/libavfilter/vf_hysteresis.c
index 42678a034c..70df8b4375 100644
--- a/libavfilter/vf_hysteresis.c
+++ b/libavfilter/vf_hysteresis.c
@@ -24,6 +24,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -287,6 +288,8 @@ static int config_output(AVFilterLink *outlink)
     HysteresisContext *s = ctx->priv;
     AVFilterLink *base = ctx->inputs[0];
     AVFilterLink *alt = ctx->inputs[1];
+    FilterLink   *il = ff_filter_link(base);
+    FilterLink   *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -303,7 +306,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = base->w;
     outlink->h = base->h;
     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
-    outlink->frame_rate = base->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
         return ret;
diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c
index ed94069647..2446658bb9 100644
--- a/libavfilter/vf_identity.c
+++ b/libavfilter/vf_identity.c
@@ -31,6 +31,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "scene_sad.h"
@@ -316,6 +317,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     IdentityContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     int ret;
 
     ret = ff_framesync_init_dualinput(&s->fs, ctx);
@@ -325,7 +328,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
 
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 096064022d..64c1ad6d4d 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -886,7 +886,9 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
     opts->params.blend_params = NULL;
     for (int i = 0; i < s->nb_inputs; i++) {
         LibplaceboInput *in = &s->inputs[i];
-        int high_fps = av_cmp_q(in->link->frame_rate, outlink->frame_rate) >= 0;
+        FilterLink *il = ff_filter_link(in->link);
+        FilterLink *ol = ff_filter_link(outlink);
+        int high_fps = av_cmp_q(il->frame_rate, ol->frame_rate) >= 0;
         if (in->qstatus != PL_QUEUE_OK)
             continue;
         opts->params.skip_caching_single_frame = high_fps;
@@ -1031,6 +1033,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
         /* Update all input queues to the chosen out_pts */
         for (int i = 0; i < s->nb_inputs; i++) {
             LibplaceboInput *in = &s->inputs[i];
+            FilterLink *l = ff_filter_link(outlink);
             if (in->status && out_pts >= in->status_pts) {
                 in->qstatus = PL_QUEUE_EOF;
                 continue;
@@ -1039,7 +1042,7 @@ static int libplacebo_activate(AVFilterContext *ctx)
             in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
                 .pts            = out_pts * av_q2d(outlink->time_base),
                 .radius         = pl_frame_mix_radius(&s->opts->params),
-                .vsync_duration = av_q2d(av_inv_q(outlink->frame_rate)),
+                .vsync_duration = av_q2d(av_inv_q(l->frame_rate)),
             ));
 
             switch (in->qstatus) {
@@ -1192,6 +1195,7 @@ static int libplacebo_config_output(AVFilterLink *outlink)
     AVFilterContext *avctx = outlink->src;
     LibplaceboContext *s   = avctx->priv;
     AVFilterLink *inlink   = outlink->src->inputs[0];
+    FilterLink       *ol   = ff_filter_link(outlink);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format);
     AVHWFramesContext *hwfc;
@@ -1218,14 +1222,15 @@ static int libplacebo_config_output(AVFilterLink *outlink)
 
     /* Frame rate */
     if (s->fps.num) {
-        outlink->frame_rate = s->fps;
+        ol->frame_rate = s->fps;
         outlink->time_base = av_inv_q(s->fps);
     } else {
-        outlink->frame_rate = avctx->inputs[0]->frame_rate;
+        FilterLink *il = ff_filter_link(avctx->inputs[0]);
+        ol->frame_rate = il->frame_rate;
         outlink->time_base = avctx->inputs[0]->time_base;
         for (int i = 1; i < s->nb_inputs; i++) {
-            outlink->frame_rate = max_q(outlink->frame_rate,
-                                        avctx->inputs[i]->frame_rate);
+            il = ff_filter_link(avctx->inputs[i]);
+            ol->frame_rate = max_q(ol->frame_rate, il->frame_rate);
             outlink->time_base = av_gcd_q(outlink->time_base,
                                           avctx->inputs[i]->time_base,
                                           AV_TIME_BASE / 2, AV_TIME_BASE_Q);
diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index a54af16000..b06f09e834 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -498,6 +498,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     LIBVMAFContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     int ret;
 
     ret = ff_framesync_init_dualinput(&s->fs, ctx);
@@ -507,7 +509,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
 
diff --git a/libavfilter/vf_limitdiff.c b/libavfilter/vf_limitdiff.c
index 1e903d45a8..b30b3bc93b 100644
--- a/libavfilter/vf_limitdiff.c
+++ b/libavfilter/vf_limitdiff.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -243,6 +244,8 @@ static int config_output(AVFilterLink *outlink)
     LimitDiffContext *s = ctx->priv;
     AVFilterLink *filtered = ctx->inputs[0];
     AVFilterLink *source = ctx->inputs[1];
+    FilterLink *il = ff_filter_link(filtered);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -271,7 +274,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = filtered->w;
     outlink->h = filtered->h;
     outlink->sample_aspect_ratio = filtered->sample_aspect_ratio;
-    outlink->frame_rate = filtered->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 2 + !!s->reference)) < 0)
         return ret;
diff --git a/libavfilter/vf_lut2.c b/libavfilter/vf_lut2.c
index 1f0661a0f5..e1bcadb101 100644
--- a/libavfilter/vf_lut2.c
+++ b/libavfilter/vf_lut2.c
@@ -27,6 +27,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -406,6 +407,8 @@ static int lut2_config_output(AVFilterLink *outlink)
     LUT2Context *s = ctx->priv;
     AVFilterLink *srcx = ctx->inputs[0];
     AVFilterLink *srcy = ctx->inputs[1];
+    FilterLink *il = ff_filter_link(srcx);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     int hsub = desc->log2_chroma_w;
@@ -416,7 +419,7 @@ static int lut2_config_output(AVFilterLink *outlink)
     outlink->h = srcx->h;
     outlink->time_base = srcx->time_base;
     outlink->sample_aspect_ratio = srcx->sample_aspect_ratio;
-    outlink->frame_rate = srcx->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
     s->height[1] = s->height[2] = AV_CEIL_RSHIFT(outlink->h, vsub);
diff --git a/libavfilter/vf_maskedclamp.c b/libavfilter/vf_maskedclamp.c
index e6fbb1a6d5..787d7493fd 100644
--- a/libavfilter/vf_maskedclamp.c
+++ b/libavfilter/vf_maskedclamp.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -222,6 +223,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *base = ctx->inputs[0];
     AVFilterLink *dark = ctx->inputs[1];
     AVFilterLink *bright = ctx->inputs[2];
+    FilterLink *il = ff_filter_link(base);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -240,7 +243,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = base->w;
     outlink->h = base->h;
     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
-    outlink->frame_rate = base->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 3)) < 0)
         return ret;
diff --git a/libavfilter/vf_maskedmerge.c b/libavfilter/vf_maskedmerge.c
index 4ca0c571c8..aa5aebb0f8 100644
--- a/libavfilter/vf_maskedmerge.c
+++ b/libavfilter/vf_maskedmerge.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "maskedmerge.h"
@@ -215,6 +216,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *base = ctx->inputs[0];
     AVFilterLink *overlay = ctx->inputs[1];
     AVFilterLink *mask = ctx->inputs[2];
+    FilterLink *il = ff_filter_link(base);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -233,7 +236,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = base->w;
     outlink->h = base->h;
     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
-    outlink->frame_rate = base->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, outlink->w)) < 0)
         return ret;
diff --git a/libavfilter/vf_maskedminmax.c b/libavfilter/vf_maskedminmax.c
index b1c309cc7d..dd439f5424 100644
--- a/libavfilter/vf_maskedminmax.c
+++ b/libavfilter/vf_maskedminmax.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -220,6 +221,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *source = ctx->inputs[0];
     AVFilterLink *f1 = ctx->inputs[1];
     AVFilterLink *f2 = ctx->inputs[2];
+    FilterLink *il = ff_filter_link(source);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -238,7 +241,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = source->w;
     outlink->h = source->h;
     outlink->sample_aspect_ratio = source->sample_aspect_ratio;
-    outlink->frame_rate = source->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 3)) < 0)
         return ret;
diff --git a/libavfilter/vf_maskedthreshold.c b/libavfilter/vf_maskedthreshold.c
index e78e11810e..a79063b980 100644
--- a/libavfilter/vf_maskedthreshold.c
+++ b/libavfilter/vf_maskedthreshold.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -220,6 +221,8 @@ static int config_output(AVFilterLink *outlink)
     MaskedThresholdContext *s = ctx->priv;
     AVFilterLink *source = ctx->inputs[0];
     AVFilterLink *ref = ctx->inputs[1];
+    FilterLink *il = ff_filter_link(source);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -235,7 +238,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = source->w;
     outlink->h = source->h;
     outlink->sample_aspect_ratio = source->sample_aspect_ratio;
-    outlink->frame_rate = source->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
         return ret;
diff --git a/libavfilter/vf_mergeplanes.c b/libavfilter/vf_mergeplanes.c
index 91bc0d2c55..e74c12407f 100644
--- a/libavfilter/vf_mergeplanes.c
+++ b/libavfilter/vf_mergeplanes.c
@@ -24,6 +24,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "framesync.h"
@@ -185,6 +186,8 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     MergePlanesContext *s = ctx->priv;
+    FilterLink *il = ff_filter_link(ctx->inputs[0]);
+    FilterLink *ol = ff_filter_link(outlink);
     InputParam inputsp[4];
     FFFrameSyncIn *in;
     int i, ret;
@@ -199,7 +202,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = ctx->inputs[0]->w;
     outlink->h = ctx->inputs[0]->h;
     outlink->time_base = ctx->inputs[0]->time_base;
-    outlink->frame_rate = ctx->inputs[0]->frame_rate;
+    ol->frame_rate = il->frame_rate;
     outlink->sample_aspect_ratio = ctx->inputs[0]->sample_aspect_ratio;
 
     s->planewidth[1]  =
diff --git a/libavfilter/vf_midequalizer.c b/libavfilter/vf_midequalizer.c
index 37a4df7105..89917847b8 100644
--- a/libavfilter/vf_midequalizer.c
+++ b/libavfilter/vf_midequalizer.c
@@ -23,6 +23,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -297,13 +298,15 @@ static int config_output(AVFilterLink *outlink)
     MidEqualizerContext *s = ctx->priv;
     AVFilterLink *in0 = ctx->inputs[0];
     AVFilterLink *in1 = ctx->inputs[1];
+    FilterLink    *il = ff_filter_link(in0);
+    FilterLink    *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
     outlink->w = in0->w;
     outlink->h = in0->h;
     outlink->sample_aspect_ratio = in0->sample_aspect_ratio;
-    outlink->frame_rate = in0->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
         return ret;
diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c
index 27743d2f46..f39e514100 100644
--- a/libavfilter/vf_minterpolate.c
+++ b/libavfilter/vf_minterpolate.c
@@ -26,6 +26,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "scene_sad.h"
@@ -398,8 +399,9 @@ static int config_input(AVFilterLink *inlink)
 static int config_output(AVFilterLink *outlink)
 {
     MIContext *mi_ctx = outlink->src->priv;
+    FilterLink     *l = ff_filter_link(outlink);
 
-    outlink->frame_rate = mi_ctx->frame_rate;
+    l->frame_rate       = mi_ctx->frame_rate;
     outlink->time_base  = av_inv_q(mi_ctx->frame_rate);
 
     return 0;
diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c
index bfbdc2c83e..13a0dc43f6 100644
--- a/libavfilter/vf_mix.c
+++ b/libavfilter/vf_mix.c
@@ -27,6 +27,7 @@
 #include "libavutil/pixdesc.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "framesync.h"
@@ -316,7 +317,8 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     MixContext *s = ctx->priv;
-    AVRational frame_rate = ctx->inputs[0]->frame_rate;
+    FilterLink *il = ff_filter_link(ctx->inputs[0]);
+    FilterLink *ol = ff_filter_link(outlink);
     AVRational sar = ctx->inputs[0]->sample_aspect_ratio;
     AVFilterLink *inlink = ctx->inputs[0];
     int height = ctx->inputs[0]->h;
@@ -366,7 +368,7 @@ static int config_output(AVFilterLink *outlink)
 
     outlink->w          = width;
     outlink->h          = height;
-    outlink->frame_rate = frame_rate;
+    ol->frame_rate     = il->frame_rate;
     outlink->sample_aspect_ratio = sar;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0)
diff --git a/libavfilter/vf_morpho.c b/libavfilter/vf_morpho.c
index ce0f01c9c0..bd1723b906 100644
--- a/libavfilter/vf_morpho.c
+++ b/libavfilter/vf_morpho.c
@@ -30,6 +30,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "video.h"
@@ -1002,6 +1003,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     MorphoContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     int ret;
 
     s->fs.on_event = do_morpho;
@@ -1012,7 +1015,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
diff --git a/libavfilter/vf_multiply.c b/libavfilter/vf_multiply.c
index 54fbeff483..9ebcb85b6b 100644
--- a/libavfilter/vf_multiply.c
+++ b/libavfilter/vf_multiply.c
@@ -22,6 +22,7 @@
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "framesync.h"
@@ -164,6 +165,8 @@ static int config_output(AVFilterLink *outlink)
     MultiplyContext *s = ctx->priv;
     AVFilterLink *source = ctx->inputs[0];
     AVFilterLink *ref = ctx->inputs[1];
+    FilterLink *il = ff_filter_link(source);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -179,7 +182,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = source->w;
     outlink->h = source->h;
     outlink->sample_aspect_ratio = source->sample_aspect_ratio;
-    outlink->frame_rate = source->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
         return ret;
diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c
index 2168c5dbc5..4b8b11a722 100644
--- a/libavfilter/vf_nnedi.c
+++ b/libavfilter/vf_nnedi.c
@@ -30,6 +30,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -173,9 +174,11 @@ static int config_output(AVFilterLink *outlink)
     outlink->w             = ctx->inputs[0]->w;
     outlink->h             = ctx->inputs[0]->h;
 
-    if (s->field == -2 || s->field > 1)
-        outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate,
-                                       (AVRational){2, 1});
+    if (s->field == -2 || s->field > 1) {
+        FilterLink *il = ff_filter_link(ctx->inputs[0]);
+        FilterLink *ol = ff_filter_link(outlink);
+        ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){2, 1});
+    }
 
     return 0;
 }
@@ -729,11 +732,12 @@ static int request_frame(AVFilterLink *link)
 
     if (ret == AVERROR_EOF && s->prev) {
         AVFrame *next = av_frame_clone(s->prev);
+        FilterLink *l = ff_filter_link(ctx->outputs[0]);
 
         if (!next)
             return AVERROR(ENOMEM);
 
-        next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(ctx->outputs[0]->frame_rate),
+        next->pts = s->prev->pts + av_rescale_q(1, av_inv_q(l->frame_rate),
                                                 ctx->outputs[0]->time_base);
         s->eof = 1;
 
diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c
index 15dfe4e6f7..37a0d4c2c8 100644
--- a/libavfilter/vf_overlay_qsv.c
+++ b/libavfilter/vf_overlay_qsv.c
@@ -277,6 +277,7 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink      *in1 = ctx->inputs[1];
     FilterLink         *l0 = ff_filter_link(in0);
     FilterLink         *l1 = ff_filter_link(in1);
+    FilterLink         *ol = ff_filter_link(outlink);
     int ret;
 
     av_log(ctx, AV_LOG_DEBUG, "Output is of %s.\n", av_get_pix_fmt_name(outlink->format));
@@ -298,8 +299,8 @@ static int config_output(AVFilterLink *outlink)
 
     outlink->w          = vpp->var_values[VAR_MW];
     outlink->h          = vpp->var_values[VAR_MH];
-    outlink->frame_rate = in0->frame_rate;
-    outlink->time_base  = av_inv_q(outlink->frame_rate);
+    ol->frame_rate      = l0->frame_rate;
+    outlink->time_base  = av_inv_q(ol->frame_rate);
 
     ret = init_framesync(ctx);
     if (ret < 0)
diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c
index 5e97c2000f..c9fabf7ae7 100644
--- a/libavfilter/vf_premultiply.c
+++ b/libavfilter/vf_premultiply.c
@@ -696,6 +696,8 @@ static int config_output(AVFilterLink *outlink)
     PreMultiplyContext *s = ctx->priv;
     AVFilterLink *base = ctx->inputs[0];
     AVFilterLink *alpha;
+    FilterLink *il = ff_filter_link(base);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -717,7 +719,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = base->h;
     outlink->time_base = base->time_base;
     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
-    outlink->frame_rate = base->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if (s->inplace)
         return 0;
diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c
index 413d1fa1ee..b1488effde 100644
--- a/libavfilter/vf_psnr.c
+++ b/libavfilter/vf_psnr.c
@@ -32,6 +32,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "psnr.h"
@@ -383,6 +384,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     PSNRContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     int ret;
 
     ret = ff_framesync_init_dualinput(&s->fs, ctx);
@@ -392,7 +395,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
 
diff --git a/libavfilter/vf_remap.c b/libavfilter/vf_remap.c
index 7cc56fa5f0..1b23a3ac86 100644
--- a/libavfilter/vf_remap.c
+++ b/libavfilter/vf_remap.c
@@ -42,6 +42,7 @@
 #include "libavutil/opt.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "formats.h"
 #include "framesync.h"
 #include "internal.h"
@@ -313,6 +314,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *srclink = ctx->inputs[0];
     AVFilterLink *xlink = ctx->inputs[1];
     AVFilterLink *ylink = ctx->inputs[2];
+    FilterLink *il = ff_filter_link(srclink);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -328,7 +331,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = xlink->w;
     outlink->h = xlink->h;
     outlink->sample_aspect_ratio = srclink->sample_aspect_ratio;
-    outlink->frame_rate = srclink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     ret = ff_framesync_init(&s->fs, ctx, 3);
     if (ret < 0)
diff --git a/libavfilter/vf_remap_opencl.c b/libavfilter/vf_remap_opencl.c
index 8da48096de..852c88d44c 100644
--- a/libavfilter/vf_remap_opencl.c
+++ b/libavfilter/vf_remap_opencl.c
@@ -23,6 +23,7 @@
 #include "libavutil/opt.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "opencl.h"
@@ -233,6 +234,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *srclink = ctx->inputs[0];
     AVFilterLink *xlink = ctx->inputs[1];
     AVFilterLink *ylink = ctx->inputs[2];
+    FilterLink *il = ff_filter_link(srclink);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -248,7 +251,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = xlink->w;
     outlink->h = xlink->h;
     outlink->sample_aspect_ratio = srclink->sample_aspect_ratio;
-    outlink->frame_rate = srclink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     ret = ff_framesync_init(&s->fs, ctx, 3);
     if (ret < 0)
diff --git a/libavfilter/vf_repeatfields.c b/libavfilter/vf_repeatfields.c
index bf0edb5440..612c2f9049 100644
--- a/libavfilter/vf_repeatfields.c
+++ b/libavfilter/vf_repeatfields.c
@@ -69,7 +69,9 @@ static int config_input(AVFilterLink *inlink)
 
 static void update_pts(AVFilterLink *link, AVFrame *f, int64_t pts, int fields)
 {
-    if (av_cmp_q(link->frame_rate, (AVRational){30000, 1001}) == 0 &&
+    FilterLink *l = ff_filter_link(link);
+
+    if (av_cmp_q(l->frame_rate, (AVRational){30000, 1001}) == 0 &&
          av_cmp_q(link->time_base, (AVRational){1001, 60000}) <= 0
     ) {
         f->pts = pts + av_rescale_q(fields, (AVRational){1001, 60000}, link->time_base);
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index 680d264ec9..febb3178de 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -28,6 +28,7 @@
 #include <string.h>
 
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "framesync.h"
 #include "internal.h"
@@ -800,12 +801,14 @@ fail:
 static int config_props_ref(AVFilterLink *outlink)
 {
     AVFilterLink *inlink = outlink->src->inputs[1];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
 
     outlink->w = inlink->w;
     outlink->h = inlink->h;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     outlink->time_base = inlink->time_base;
-    outlink->frame_rate = inlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     outlink->colorspace = inlink->colorspace;
     outlink->color_range = inlink->color_range;
 
diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c
index 0c4af074c9..7b67d33296 100644
--- a/libavfilter/vf_scale_npp.c
+++ b/libavfilter/vf_scale_npp.c
@@ -692,12 +692,13 @@ static int config_props_ref(AVFilterLink *outlink)
     FilterLink     *outl = ff_filter_link(outlink);
     AVFilterLink *inlink = outlink->src->inputs[1];
     FilterLink      *inl = ff_filter_link(inlink);
+    FilterLink       *ol = ff_filter_link(outlink);
 
     outlink->w = inlink->w;
     outlink->h = inlink->h;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     outlink->time_base = inlink->time_base;
-    outlink->frame_rate = inlink->frame_rate;
+    ol->frame_rate = inl->frame_rate;
 
     outl->hw_frames_ctx = av_buffer_ref(inl->hw_frames_ctx);
 
diff --git a/libavfilter/vf_separatefields.c b/libavfilter/vf_separatefields.c
index b7ddb26377..91df45980f 100644
--- a/libavfilter/vf_separatefields.c
+++ b/libavfilter/vf_separatefields.c
@@ -34,6 +34,8 @@ static int config_props_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     SeparateFieldsContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink       *il = ff_filter_link(inlink);
+    FilterLink       *ol = ff_filter_link(outlink);
 
     s->nb_planes = av_pix_fmt_count_planes(inlink->format);
 
@@ -44,8 +46,8 @@ static int config_props_output(AVFilterLink *outlink)
 
     outlink->time_base.num = inlink->time_base.num;
     outlink->time_base.den = inlink->time_base.den * 2;
-    outlink->frame_rate.num = inlink->frame_rate.num * 2;
-    outlink->frame_rate.den = inlink->frame_rate.den;
+    ol->frame_rate.num = il->frame_rate.num * 2;
+    ol->frame_rate.den = il->frame_rate.den;
     outlink->w = inlink->w;
     outlink->h = inlink->h / 2;
 
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index d79707ce49..f6ffcc39bb 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -47,6 +47,7 @@
 #include "libavutil/uuid.h"
 
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -114,8 +115,9 @@ static void dump_stereo3d(AVFilterContext *ctx, const AVFrameSideData *sd)
         av_log(ctx, AV_LOG_INFO, ", horizontal_field_of_view: %0.3f", av_q2d(stereo->horizontal_field_of_view));
 }
 
-static void dump_s12m_timecode(AVFilterContext *ctx, AVRational frame_rate, const AVFrameSideData *sd)
+static void dump_s12m_timecode(AVFilterContext *ctx, AVFilterLink *inlink, const AVFrameSideData *sd)
 {
+    FilterLink      *l = ff_filter_link(inlink);
     const uint32_t *tc = (const uint32_t *)sd->data;
 
     if ((sd->size != sizeof(uint32_t) * 4) || (tc[0] > 3)) {
@@ -125,7 +127,7 @@ static void dump_s12m_timecode(AVFilterContext *ctx, AVRational frame_rate, cons
 
     for (int j = 1; j <= tc[0]; j++) {
         char tcbuf[AV_TIMECODE_STR_SIZE];
-        av_timecode_make_smpte_tc_string2(tcbuf, frame_rate, tc[j], 0, 0);
+        av_timecode_make_smpte_tc_string2(tcbuf, l->frame_rate, tc[j], 0, 0);
         av_log(ctx, AV_LOG_INFO, "timecode - %s%s", tcbuf, j != tc[0]  ? ", " : "");
     }
 }
@@ -806,7 +808,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
             dump_stereo3d(ctx, sd);
             break;
         case AV_FRAME_DATA_S12M_TIMECODE: {
-            dump_s12m_timecode(ctx, inlink->frame_rate, sd);
+            dump_s12m_timecode(ctx, inlink, sd);
             break;
         }
         case AV_FRAME_DATA_DISPLAYMATRIX:
@@ -875,11 +877,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
 
 static int config_props(AVFilterContext *ctx, AVFilterLink *link, int is_out)
 {
+    FilterLink *l = ff_filter_link(link);
 
     av_log(ctx, AV_LOG_INFO, "config %s time_base: %d/%d, frame_rate: %d/%d\n",
            is_out ? "out" : "in",
            link->time_base.num, link->time_base.den,
-           link->frame_rate.num, link->frame_rate.den);
+           l->frame_rate.num, l->frame_rate.den);
 
     return 0;
 }
diff --git a/libavfilter/vf_signature.c b/libavfilter/vf_signature.c
index d5c0df57e6..d5df683642 100644
--- a/libavfilter/vf_signature.c
+++ b/libavfilter/vf_signature.c
@@ -31,6 +31,7 @@
 #include "libavutil/avstring.h"
 #include "libavutil/file_open.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "signature.h"
 #include "signature_lookup.c"
@@ -726,9 +727,11 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink       *il = ff_filter_link(inlink);
+    FilterLink       *ol = ff_filter_link(outlink);
 
     outlink->time_base = inlink->time_base;
-    outlink->frame_rate = inlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
     outlink->w = inlink->w;
     outlink->h = inlink->h;
diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c
index 2210ea40ec..609d082ef7 100644
--- a/libavfilter/vf_ssim.c
+++ b/libavfilter/vf_ssim.c
@@ -41,6 +41,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "ssim.h"
@@ -507,6 +508,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     SSIMContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     int ret;
 
     ret = ff_framesync_init_dualinput(&s->fs, ctx);
@@ -516,7 +519,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_configure(&s->fs)) < 0)
         return ret;
diff --git a/libavfilter/vf_ssim360.c b/libavfilter/vf_ssim360.c
index 33606ea599..ca0545e178 100644
--- a/libavfilter/vf_ssim360.c
+++ b/libavfilter/vf_ssim360.c
@@ -51,6 +51,7 @@
 
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "internal.h"
 #include "framesync.h"
 
@@ -1594,6 +1595,8 @@ static int config_output(AVFilterLink *outlink)
     SSIM360Context      *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
     AVFilterLink  *reflink = ctx->inputs[0];
+    FilterLink         *il = ff_filter_link(mainlink);
+    FilterLink         *ol = ff_filter_link(outlink);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     int ret;
 
@@ -1643,7 +1646,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     s->fs.opt_shortest   = 1;
     s->fs.opt_repeatlast = 1;
diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index 5bb50148a7..4d42d9b5c5 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -29,6 +29,7 @@
 
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "framesync.h"
@@ -196,7 +197,9 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     StackContext *s = ctx->priv;
-    AVRational frame_rate = ctx->inputs[0]->frame_rate;
+    FilterLink *il = ff_filter_link(ctx->inputs[0]);
+    FilterLink *ol = ff_filter_link(outlink);
+    AVRational frame_rate = il->frame_rate;
     AVRational sar = ctx->inputs[0]->sample_aspect_ratio;
     int height = ctx->inputs[0]->h;
     int width = ctx->inputs[0]->w;
@@ -383,16 +386,16 @@ static int config_output(AVFilterLink *outlink)
 
     outlink->w          = width;
     outlink->h          = height;
-    outlink->frame_rate = frame_rate;
+    ol->frame_rate      = frame_rate;
     outlink->sample_aspect_ratio = sar;
 
     for (i = 1; i < s->nb_inputs; i++) {
-        AVFilterLink *inlink = ctx->inputs[i];
-        if (outlink->frame_rate.num != inlink->frame_rate.num ||
-            outlink->frame_rate.den != inlink->frame_rate.den) {
+        il = ff_filter_link(ctx->inputs[i]);
+        if (ol->frame_rate.num != il->frame_rate.num ||
+            ol->frame_rate.den != il->frame_rate.den) {
             av_log(ctx, AV_LOG_VERBOSE,
                     "Video inputs have different frame rates, output will be VFR\n");
-            outlink->frame_rate = av_make_q(1, 0);
+            ol->frame_rate = av_make_q(1, 0);
             break;
         }
     }
diff --git a/libavfilter/vf_stereo3d.c b/libavfilter/vf_stereo3d.c
index 6bd4158f6d..67c34bccb0 100644
--- a/libavfilter/vf_stereo3d.c
+++ b/libavfilter/vf_stereo3d.c
@@ -27,6 +27,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -364,7 +365,9 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     Stereo3DContext *s = ctx->priv;
-    AVRational fps = inlink->frame_rate;
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
+    AVRational fps = il->frame_rate;
     AVRational tb = inlink->time_base;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     int ret;
@@ -577,7 +580,7 @@ static int config_output(AVFilterLink *outlink)
 
     outlink->w = s->out.width;
     outlink->h = s->out.height;
-    outlink->frame_rate = fps;
+    ol->frame_rate = fps;
     outlink->time_base = tb;
     outlink->sample_aspect_ratio = s->aspect;
 
diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c
index 44ef2b74d9..fee3e43aff 100644
--- a/libavfilter/vf_telecine.c
+++ b/libavfilter/vf_telecine.c
@@ -139,8 +139,10 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     TelecineContext *s = ctx->priv;
-    const AVFilterLink *inlink = ctx->inputs[0];
-    AVRational fps = inlink->frame_rate;
+    AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
+    AVRational fps = il->frame_rate;
 
     if (!fps.num || !fps.den) {
         av_log(ctx, AV_LOG_ERROR, "The input needs a constant frame rate; "
@@ -149,9 +151,9 @@ static int config_output(AVFilterLink *outlink)
     }
     fps = av_mul_q(fps, av_inv_q(s->pts));
     av_log(ctx, AV_LOG_VERBOSE, "FPS: %d/%d -> %d/%d\n",
-           inlink->frame_rate.num, inlink->frame_rate.den, fps.num, fps.den);
+           il->frame_rate.num, il->frame_rate.den, fps.num, fps.den);
 
-    outlink->frame_rate = fps;
+    ol->frame_rate = fps;
     outlink->time_base = av_mul_q(inlink->time_base, s->pts);
     av_log(ctx, AV_LOG_VERBOSE, "TB: %d/%d -> %d/%d\n",
            inlink->time_base.num, inlink->time_base.den, outlink->time_base.num, outlink->time_base.den);
diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c
index dc73c277d3..2ec35eed51 100644
--- a/libavfilter/vf_threshold.c
+++ b/libavfilter/vf_threshold.c
@@ -28,6 +28,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "video.h"
@@ -181,6 +182,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterLink *threshold = ctx->inputs[1];
     AVFilterLink *min = ctx->inputs[2];
     AVFilterLink *max = ctx->inputs[3];
+    FilterLink *il = ff_filter_link(base);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -205,7 +208,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = base->w;
     outlink->h = base->h;
     outlink->sample_aspect_ratio = base->sample_aspect_ratio;
-    outlink->frame_rate = base->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, 4)) < 0)
         return ret;
diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c
index b45e739bb6..ca382f748d 100644
--- a/libavfilter/vf_tile.c
+++ b/libavfilter/vf_tile.c
@@ -28,6 +28,7 @@
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
 #include "drawutils.h"
+#include "filters.h"
 #include "formats.h"
 #include "video.h"
 #include "internal.h"
@@ -121,6 +122,8 @@ static int config_props(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     TileContext *tile    = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
     const unsigned total_margin_w = (tile->w - 1) * tile->padding + 2*tile->margin;
     const unsigned total_margin_h = (tile->h - 1) * tile->padding + 2*tile->margin;
 
@@ -137,8 +140,7 @@ static int config_props(AVFilterLink *outlink)
     outlink->w = tile->w * inlink->w + total_margin_w;
     outlink->h = tile->h * inlink->h + total_margin_h;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-    outlink->frame_rate = av_mul_q(inlink->frame_rate,
-                                   av_make_q(1, tile->nb_frames - tile->overlap));
+    ol->frame_rate = av_mul_q(il->frame_rate, av_make_q(1, tile->nb_frames - tile->overlap));
     ff_draw_init2(&tile->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
     ff_draw_color(&tile->draw, &tile->blank, tile->rgba_color);
 
diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
index 89af1b89c5..9c976eddd9 100644
--- a/libavfilter/vf_tinterlace.c
+++ b/libavfilter/vf_tinterlace.c
@@ -31,6 +31,7 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/avassert.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "tinterlace.h"
 #include "video.h"
@@ -212,6 +213,8 @@ static int config_out_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = outlink->src->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     TInterlaceContext *tinterlace = ctx->priv;
     int ret, i;
@@ -256,13 +259,13 @@ static int config_out_props(AVFilterLink *outlink)
     tinterlace->preout_time_base = inlink->time_base;
     if (tinterlace->mode == MODE_INTERLACEX2) {
         tinterlace->preout_time_base.den *= 2;
-        outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1});
+        ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){2,1});
         outlink->time_base  = av_mul_q(inlink->time_base , (AVRational){1,2});
     } else if (tinterlace->mode == MODE_MERGEX2) {
-        outlink->frame_rate = inlink->frame_rate;
+        ol->frame_rate = il->frame_rate;
         outlink->time_base  = inlink->time_base;
     } else if (tinterlace->mode != MODE_PAD) {
-        outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2});
+        ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){1,2});
         outlink->time_base  = av_mul_q(inlink->time_base , (AVRational){2,1});
     }
 
@@ -293,7 +296,7 @@ static int config_out_props(AVFilterLink *outlink)
 #endif
     }
 
-    ret = ff_ccfifo_init(&tinterlace->cc_fifo, outlink->frame_rate, ctx);
+    ret = ff_ccfifo_init(&tinterlace->cc_fifo, ol->frame_rate, ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
         return ret;
@@ -375,6 +378,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref)
 {
     AVFilterContext *ctx = inlink->dst;
     AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink *l = ff_filter_link(outlink);
     TInterlaceContext *tinterlace = ctx->priv;
     AVFrame *cur, *next, *out;
     int field, tff, full, ret;
@@ -560,7 +564,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
     }
 
     out->pts = av_rescale_q(out->pts, tinterlace->preout_time_base, outlink->time_base);
-    out->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+    out->duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
     ff_ccfifo_inject(&tinterlace->cc_fifo, out);
     ret = ff_filter_frame(outlink, out);
 
diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c
index 72d0bf338f..2df99e75f0 100644
--- a/libavfilter/vf_tpad.c
+++ b/libavfilter/vf_tpad.c
@@ -90,6 +90,7 @@ static int activate(AVFilterContext *ctx)
 {
     AVFilterLink *inlink = ctx->inputs[0];
     AVFilterLink *outlink = ctx->outputs[0];
+    FilterLink *l = ff_filter_link(outlink);
     TPadContext *s = ctx->priv;
     AVFrame *frame = NULL;
     int ret, status;
@@ -116,7 +117,7 @@ static int activate(AVFilterContext *ctx)
         ff_fill_rectangle(&s->draw, &s->color,
                           frame->data, frame->linesize,
                           0, 0, frame->width, frame->height);
-        duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+        duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
         frame->pts = s->pts;
         frame->duration = duration;
         s->pts += duration;
@@ -136,7 +137,7 @@ static int activate(AVFilterContext *ctx)
         frame = av_frame_clone(s->cache_start);
         if (!frame)
             return AVERROR(ENOMEM);
-        duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+        duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
         frame->pts = s->pts;
         frame->duration = duration;
         s->pts += duration;
@@ -182,7 +183,7 @@ static int activate(AVFilterContext *ctx)
             if (!frame)
                 return AVERROR(ENOMEM);
         }
-        duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+        duration = av_rescale_q(1, av_inv_q(l->frame_rate), outlink->time_base);
         frame->pts = s->pts;
         frame->duration = duration;
         s->pts += duration;
@@ -200,6 +201,7 @@ static int activate(AVFilterContext *ctx)
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
+    FilterLink *l = ff_filter_link(inlink);
     TPadContext *s = ctx->priv;
 
     if (needs_drawing(s)) {
@@ -208,9 +210,9 @@ static int config_input(AVFilterLink *inlink)
     }
 
     if (s->start_duration)
-        s->pad_start = av_rescale_q(s->start_duration, inlink->frame_rate, av_inv_q(AV_TIME_BASE_Q));
+        s->pad_start = av_rescale_q(s->start_duration, l->frame_rate, av_inv_q(AV_TIME_BASE_Q));
     if (s->stop_duration)
-        s->pad_stop = av_rescale_q(s->stop_duration, inlink->frame_rate, av_inv_q(AV_TIME_BASE_Q));
+        s->pad_stop = av_rescale_q(s->stop_duration, l->frame_rate, av_inv_q(AV_TIME_BASE_Q));
 
     return 0;
 }
diff --git a/libavfilter/vf_untile.c b/libavfilter/vf_untile.c
index f32f3e186b..486cce31ee 100644
--- a/libavfilter/vf_untile.c
+++ b/libavfilter/vf_untile.c
@@ -75,6 +75,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     UntileContext *s = ctx->priv;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
     AVRational dt;
 
     s->desc = av_pix_fmt_desc_get(outlink->format);
@@ -88,9 +90,9 @@ static int config_output(AVFilterLink *outlink)
     outlink->w = inlink->w / s->w;
     outlink->h = inlink->h / s->h;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-    outlink->frame_rate = av_mul_q(inlink->frame_rate, av_make_q(s->nb_frames, 1));
-    if (outlink->frame_rate.num)
-        dt = av_inv_q(outlink->frame_rate);
+    ol->frame_rate = av_mul_q(il->frame_rate, av_make_q(s->nb_frames, 1));
+    if (ol->frame_rate.num)
+        dt = av_inv_q(ol->frame_rate);
     else
         dt = av_mul_q(inlink->time_base, av_make_q(1, s->nb_frames));
     outlink->time_base = av_gcd_q(inlink->time_base, dt, AV_TIME_BASE / 2, AV_TIME_BASE_Q);
diff --git a/libavfilter/vf_varblur.c b/libavfilter/vf_varblur.c
index 7a022099e9..5f0126fccf 100644
--- a/libavfilter/vf_varblur.c
+++ b/libavfilter/vf_varblur.c
@@ -23,6 +23,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 #include "video.h"
@@ -320,6 +321,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
     AVFilterLink *radiuslink = ctx->inputs[1];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
     VarBlurContext *s = ctx->priv;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
     int ret;
@@ -337,7 +340,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = inlink->h;
     outlink->time_base = inlink->time_base;
     outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
-    outlink->frame_rate = inlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     s->depth = desc->comp[0].depth;
     s->blur_plane = s->depth <= 8 ? blur_plane8 : s->depth <= 16 ? blur_plane16 : blur_plane32;
diff --git a/libavfilter/vf_vif.c b/libavfilter/vf_vif.c
index 38b6a32365..3def065e84 100644
--- a/libavfilter/vf_vif.c
+++ b/libavfilter/vf_vif.c
@@ -31,6 +31,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "framesync.h"
 #include "internal.h"
 
@@ -550,6 +551,8 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     VIFContext *s = ctx->priv;
     AVFilterLink *mainlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(mainlink);
+    FilterLink *ol = ff_filter_link(outlink);
     FFFrameSyncIn *in;
     int ret;
 
@@ -557,7 +560,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = mainlink->h;
     outlink->time_base = mainlink->time_base;
     outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio;
-    outlink->frame_rate = mainlink->frame_rate;
+    ol->frame_rate = il->frame_rate;
     if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0)
         return ret;
 
diff --git a/libavfilter/vf_vignette.c b/libavfilter/vf_vignette.c
index 13c511fdc7..9d35ea8b13 100644
--- a/libavfilter/vf_vignette.c
+++ b/libavfilter/vf_vignette.c
@@ -25,6 +25,7 @@
 #include "libavutil/eval.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -283,14 +284,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 static int config_props(AVFilterLink *inlink)
 {
     VignetteContext *s = inlink->dst->priv;
+    FilterLink *l = ff_filter_link(inlink);
     AVRational sar = inlink->sample_aspect_ratio;
 
     s->desc = av_pix_fmt_desc_get(inlink->format);
     s->var_values[VAR_W]  = inlink->w;
     s->var_values[VAR_H]  = inlink->h;
     s->var_values[VAR_TB] = av_q2d(inlink->time_base);
-    s->var_values[VAR_R]  = inlink->frame_rate.num == 0 || inlink->frame_rate.den == 0 ?
-        NAN : av_q2d(inlink->frame_rate);
+    s->var_values[VAR_R]  = l->frame_rate.num == 0 || l->frame_rate.den == 0 ?
+        NAN : av_q2d(l->frame_rate);
 
     if (!sar.num || !sar.den)
         sar.num = sar.den = 1;
diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
index f368b6ce24..7de3b6dda3 100644
--- a/libavfilter/vf_vpp_qsv.c
+++ b/libavfilter/vf_vpp_qsv.c
@@ -297,18 +297,19 @@ static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
     VPPContext      *vpp = ctx->priv;
+    FilterLink      *inl = ff_filter_link(inlink);
     int              ret;
     int64_t          ow, oh;
 
     if (vpp->framerate.den == 0 || vpp->framerate.num == 0) {
-        vpp->framerate = inlink->frame_rate;
+        vpp->framerate = inl->frame_rate;
 
         if (vpp->deinterlace && vpp->field_rate)
-            vpp->framerate = av_mul_q(inlink->frame_rate,
+            vpp->framerate = av_mul_q(inl->frame_rate,
                                       (AVRational){ 2, 1 });
     }
 
-    if (av_cmp_q(vpp->framerate, inlink->frame_rate))
+    if (av_cmp_q(vpp->framerate, inl->frame_rate))
         vpp->use_frc = 1;
 
     ret = eval_expr(ctx);
@@ -533,11 +534,12 @@ static int config_output(AVFilterLink *outlink)
     mfxVersion      mfx_version;
     AVFilterLink    *inlink = ctx->inputs[0];
     FilterLink         *inl = ff_filter_link(inlink);
+    FilterLink          *ol = ff_filter_link(outlink);
     enum AVPixelFormat in_format;
 
     outlink->w          = vpp->out_width;
     outlink->h          = vpp->out_height;
-    outlink->frame_rate = vpp->framerate;
+    ol->frame_rate      = vpp->framerate;
     if (vpp->framerate.num == 0 || vpp->framerate.den == 0)
         outlink->time_base = inlink->time_base;
     else
@@ -768,11 +770,12 @@ static int activate(AVFilterContext *ctx)
     } else {
         /* No MFX session is created in pass-through mode */
         if (in) {
+            FilterLink *ol = ff_filter_link(outlink);
             if (in->pts != AV_NOPTS_VALUE)
                 in->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base);
 
-            if (outlink->frame_rate.num && outlink->frame_rate.den)
-                in->duration = av_rescale_q(1, av_inv_q(outlink->frame_rate), outlink->time_base);
+            if (ol->frame_rate.num && ol->frame_rate.den)
+                in->duration = av_rescale_q(1, av_inv_q(ol->frame_rate), outlink->time_base);
             else
                 in->duration = 0;
 
diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c
index a5a9cdd5cb..bbb4ea3c47 100644
--- a/libavfilter/vf_w3fdif.c
+++ b/libavfilter/vf_w3fdif.c
@@ -27,6 +27,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "w3fdif.h"
@@ -328,11 +329,13 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
     W3FDIFContext *s = ctx->priv;
 
     outlink->time_base = av_mul_q(inlink->time_base, (AVRational){1, 2});
     if (s->mode)
-        outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1});
+        ol->frame_rate = av_mul_q(il->frame_rate, (AVRational){2, 1});
 
     return 0;
 }
diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c
index f0e8b0927a..84e8e3dab5 100644
--- a/libavfilter/vf_weave.c
+++ b/libavfilter/vf_weave.c
@@ -22,6 +22,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -68,10 +69,12 @@ static int config_props_output(AVFilterLink *outlink)
     int ret;
 
     if (!s->double_weave) {
+        FilterLink *il = ff_filter_link(inlink);
+        FilterLink *ol = ff_filter_link(outlink);
         outlink->time_base.num = inlink->time_base.num * 2;
         outlink->time_base.den = inlink->time_base.den;
-        outlink->frame_rate.num = inlink->frame_rate.num;
-        outlink->frame_rate.den = inlink->frame_rate.den * 2;
+        ol->frame_rate.num = il->frame_rate.num;
+        ol->frame_rate.den = il->frame_rate.den * 2;
     }
     outlink->w = inlink->w;
     outlink->h = inlink->h * 2;
diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c
index f61c7083dc..c9d6388475 100644
--- a/libavfilter/vf_xfade.c
+++ b/libavfilter/vf_xfade.c
@@ -2041,6 +2041,9 @@ static int config_output(AVFilterLink *outlink)
     AVFilterContext *ctx = outlink->src;
     AVFilterLink *inlink0 = ctx->inputs[0];
     AVFilterLink *inlink1 = ctx->inputs[1];
+    FilterLink      *inl0 = ff_filter_link(inlink0);
+    FilterLink      *inl1 = ff_filter_link(inlink1);
+    FilterLink        *ol = ff_filter_link(outlink);
     XFadeContext *s = ctx->priv;
     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink0->format);
 
@@ -2063,19 +2066,19 @@ static int config_output(AVFilterLink *outlink)
         return AVERROR(EINVAL);
     }
 
-    if (!inlink0->frame_rate.num || !inlink0->frame_rate.den) {
+    if (!inl0->frame_rate.num || !inl0->frame_rate.den) {
         av_log(ctx, AV_LOG_ERROR, "The inputs needs to be a constant frame rate; "
-               "current rate of %d/%d is invalid\n", inlink0->frame_rate.num, inlink0->frame_rate.den);
+               "current rate of %d/%d is invalid\n", inl0->frame_rate.num, inl0->frame_rate.den);
         return AVERROR(EINVAL);
     }
 
-    if (inlink0->frame_rate.num != inlink1->frame_rate.num ||
-        inlink0->frame_rate.den != inlink1->frame_rate.den) {
+    if (inl0->frame_rate.num != inl1->frame_rate.num ||
+        inl0->frame_rate.den != inl1->frame_rate.den) {
         av_log(ctx, AV_LOG_ERROR, "First input link %s frame rate "
                "(%d/%d) do not match the corresponding "
                "second input link %s frame rate (%d/%d)\n",
-               ctx->input_pads[0].name, inlink0->frame_rate.num, inlink0->frame_rate.den,
-               ctx->input_pads[1].name, inlink1->frame_rate.num, inlink1->frame_rate.den);
+               ctx->input_pads[0].name, inl0->frame_rate.num, inl0->frame_rate.den,
+               ctx->input_pads[1].name, inl1->frame_rate.num, inl1->frame_rate.den);
         return AVERROR(EINVAL);
     }
 
@@ -2083,7 +2086,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = inlink0->h;
     outlink->time_base = inlink0->time_base;
     outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
-    outlink->frame_rate = inlink0->frame_rate;
+    ol->frame_rate = inl0->frame_rate;
 
     s->depth = pix_desc->comp[0].depth;
     s->is_rgb = !!(pix_desc->flags & AV_PIX_FMT_FLAG_RGB);
diff --git a/libavfilter/vf_xfade_opencl.c b/libavfilter/vf_xfade_opencl.c
index 2368c046b4..3d568a9a17 100644
--- a/libavfilter/vf_xfade_opencl.c
+++ b/libavfilter/vf_xfade_opencl.c
@@ -216,6 +216,8 @@ static int xfade_opencl_config_output(AVFilterLink *outlink)
     XFadeOpenCLContext *ctx = avctx->priv;
     AVFilterLink *inlink0 = avctx->inputs[0];
     AVFilterLink *inlink1 = avctx->inputs[1];
+    FilterLink *il = ff_filter_link(inlink0);
+    FilterLink *ol = ff_filter_link(outlink);
     int err;
 
     err = ff_opencl_filter_config_output(outlink);
@@ -245,7 +247,7 @@ static int xfade_opencl_config_output(AVFilterLink *outlink)
 
     outlink->time_base = inlink0->time_base;
     outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio;
-    outlink->frame_rate = inlink0->frame_rate;
+    ol->frame_rate = il->frame_rate;
 
     if (ctx->duration)
         ctx->duration_pts = av_rescale_q(ctx->duration, AV_TIME_BASE_Q, outlink->time_base);
diff --git a/libavfilter/vf_xfade_vulkan.c b/libavfilter/vf_xfade_vulkan.c
index be041eaef4..2076f3e7a4 100644
--- a/libavfilter/vf_xfade_vulkan.c
+++ b/libavfilter/vf_xfade_vulkan.c
@@ -460,6 +460,8 @@ static int config_props_output(AVFilterLink *outlink)
     XFadeVulkanContext *s = avctx->priv;
     AVFilterLink *inlink_a = avctx->inputs[IN_A];
     AVFilterLink *inlink_b = avctx->inputs[IN_B];
+    FilterLink *il = ff_filter_link(inlink_a);
+    FilterLink *ol = ff_filter_link(outlink);
 
     if (inlink_a->w != inlink_b->w || inlink_a->h != inlink_b->h) {
         av_log(avctx, AV_LOG_ERROR, "First input link %s parameters "
@@ -483,7 +485,7 @@ static int config_props_output(AVFilterLink *outlink)
     s->start_pts = s->inputs_offset_pts = AV_NOPTS_VALUE;
 
     outlink->time_base = inlink_a->time_base;
-    outlink->frame_rate = inlink_a->frame_rate;
+    ol->frame_rate = il->frame_rate;
     outlink->sample_aspect_ratio = inlink_a->sample_aspect_ratio;
 
     if (s->duration)
diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c
index 4e83b48843..e86920cb1a 100644
--- a/libavfilter/vf_xmedian.c
+++ b/libavfilter/vf_xmedian.c
@@ -29,6 +29,7 @@
 
 #include "avfilter.h"
 #include "internal.h"
+#include "filters.h"
 #include "framesync.h"
 #include "video.h"
 
@@ -239,9 +240,11 @@ static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     XMedianContext *s = ctx->priv;
-    AVRational frame_rate = ctx->inputs[0]->frame_rate;
-    AVRational sar = ctx->inputs[0]->sample_aspect_ratio;
     AVFilterLink *inlink = ctx->inputs[0];
+    FilterLink *il = ff_filter_link(inlink);
+    FilterLink *ol = ff_filter_link(outlink);
+    AVRational frame_rate = il->frame_rate;
+    AVRational sar = ctx->inputs[0]->sample_aspect_ratio;
     int height = ctx->inputs[0]->h;
     int width = ctx->inputs[0]->w;
     FFFrameSyncIn *in;
@@ -288,7 +291,7 @@ static int config_output(AVFilterLink *outlink)
 
     outlink->w          = width;
     outlink->h          = height;
-    outlink->frame_rate = frame_rate;
+    ol->frame_rate      = frame_rate;
     outlink->sample_aspect_ratio = sar;
 
     if ((ret = ff_framesync_init(&s->fs, ctx, s->nb_inputs)) < 0)
diff --git a/libavfilter/vf_zoompan.c b/libavfilter/vf_zoompan.c
index e729bda56d..e50484cbef 100644
--- a/libavfilter/vf_zoompan.c
+++ b/libavfilter/vf_zoompan.c
@@ -125,13 +125,14 @@ static av_cold int init(AVFilterContext *ctx)
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     ZPContext *s = ctx->priv;
     int ret;
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->framerate);
-    outlink->frame_rate = s->framerate;
+    l->frame_rate = s->framerate;
     s->desc = av_pix_fmt_desc_get(outlink->format);
     s->finished = 1;
 
diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c
index f9223fd848..0159d1e508 100644
--- a/libavfilter/vsrc_cellauto.c
+++ b/libavfilter/vsrc_cellauto.c
@@ -33,6 +33,7 @@
 #include "libavutil/random_seed.h"
 #include "libavutil/avstring.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -217,11 +218,12 @@ static av_cold void uninit(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     CellAutoContext *s = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->frame_rate);
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_ddagrab.c b/libavfilter/vsrc_ddagrab.c
index dc53e15c6d..c900e123b6 100644
--- a/libavfilter/vsrc_ddagrab.c
+++ b/libavfilter/vsrc_ddagrab.c
@@ -924,7 +924,7 @@ static int ddagrab_config_props(AVFilterLink *outlink)
     outlink->w = dda->width;
     outlink->h = dda->height;
     outlink->time_base = (AVRational){1, TIMER_RES};
-    outlink->frame_rate = dda->framerate;
+    l->frame_rate = dda->framerate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c
index 567a4a311d..02c4965df6 100644
--- a/libavfilter/vsrc_gradients.c
+++ b/libavfilter/vsrc_gradients.c
@@ -334,6 +334,7 @@ static int draw_gradients_slice32_planar(AVFilterContext *ctx, void *arg, int jo
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     GradientsContext *s = ctx->priv;
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
 
@@ -344,7 +345,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->frame_rate);
     outlink->sample_aspect_ratio = (AVRational) {1, 1};
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
     if (s->seed == -1)
         s->seed = av_get_random_seed();
     av_lfg_init(&s->lfg, s->seed);
diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c
index 65e510dbdb..79200a6d0e 100644
--- a/libavfilter/vsrc_life.c
+++ b/libavfilter/vsrc_life.c
@@ -35,6 +35,7 @@
 #include "libavutil/avstring.h"
 #include "avfilter.h"
 #include "internal.h"
+#include "filters.h"
 #include "formats.h"
 #include "video.h"
 
@@ -280,11 +281,12 @@ static av_cold void uninit(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     LifeContext *life = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = life->w;
     outlink->h = life->h;
     outlink->time_base = av_inv_q(life->frame_rate);
-    outlink->frame_rate = life->frame_rate;
+    l->frame_rate = life->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_mandelbrot.c b/libavfilter/vsrc_mandelbrot.c
index 982ef71814..c1a59fea6d 100644
--- a/libavfilter/vsrc_mandelbrot.c
+++ b/libavfilter/vsrc_mandelbrot.c
@@ -27,6 +27,7 @@
  */
 
 #include "avfilter.h"
+#include "filters.h"
 #include "video.h"
 #include "internal.h"
 #include "libavutil/imgutils.h"
@@ -151,6 +152,7 @@ static av_cold void uninit(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     MBContext *s = ctx->priv;
 
     if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
@@ -159,7 +161,7 @@ static int config_props(AVFilterLink *outlink)
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->frame_rate);
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_mptestsrc.c b/libavfilter/vsrc_mptestsrc.c
index 0395af35e8..3b9be4c8ed 100644
--- a/libavfilter/vsrc_mptestsrc.c
+++ b/libavfilter/vsrc_mptestsrc.c
@@ -26,6 +26,7 @@
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 
@@ -274,6 +275,7 @@ static av_cold int init(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     MPTestContext *test = ctx->priv;
     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(outlink->format);
 
@@ -283,7 +285,7 @@ static int config_props(AVFilterLink *outlink)
     outlink->w = WIDTH;
     outlink->h = HEIGHT;
     outlink->time_base = av_inv_q(test->frame_rate);
-    outlink->frame_rate = test->frame_rate;
+    l->frame_rate = test->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_perlin.c b/libavfilter/vsrc_perlin.c
index fb2eb4c9bb..8fd140f225 100644
--- a/libavfilter/vsrc_perlin.c
+++ b/libavfilter/vsrc_perlin.c
@@ -28,6 +28,7 @@
 #include "libavutil/opt.h"
 #include "avfilter.h"
 #include "internal.h"
+#include "filters.h"
 #include "formats.h"
 #include "video.h"
 
@@ -95,11 +96,12 @@ static av_cold int init(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     PerlinContext *perlin = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = perlin->w;
     outlink->h = perlin->h;
     outlink->time_base = av_inv_q(perlin->frame_rate);
-    outlink->frame_rate = perlin->frame_rate;
+    l->frame_rate = perlin->frame_rate;
 
     return 0;
 }
diff --git a/libavfilter/vsrc_sierpinski.c b/libavfilter/vsrc_sierpinski.c
index 2f31081901..e982422549 100644
--- a/libavfilter/vsrc_sierpinski.c
+++ b/libavfilter/vsrc_sierpinski.c
@@ -24,6 +24,7 @@
  */
 
 #include "avfilter.h"
+#include "filters.h"
 #include "video.h"
 #include "internal.h"
 #include "libavutil/imgutils.h"
@@ -138,6 +139,7 @@ static int draw_carpet_slice(AVFilterContext *ctx, void *arg, int job, int nb_jo
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *l = ff_filter_link(outlink);
     SierpinskiContext *s = ctx->priv;
 
     if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
@@ -147,7 +149,7 @@ static int config_output(AVFilterLink *outlink)
     outlink->h = s->h;
     outlink->time_base = av_inv_q(s->frame_rate);
     outlink->sample_aspect_ratio = (AVRational) {1, 1};
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
     if (s->seed == -1)
         s->seed = av_get_random_seed();
     av_lfg_init(&s->lfg, s->seed);
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 4dc12c8a01..ce4013643c 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -46,6 +46,7 @@
 #include "avfilter.h"
 #include "drawutils.h"
 #include "filters.h"
+#include "filters.h"
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
@@ -148,11 +149,12 @@ static av_cold void uninit(AVFilterContext *ctx)
 static int config_props(AVFilterLink *outlink)
 {
     TestSourceContext *test = outlink->src->priv;
+    FilterLink *l = ff_filter_link(outlink);
 
     outlink->w = test->w;
     outlink->h = test->h;
     outlink->sample_aspect_ratio = test->sar;
-    outlink->frame_rate = test->frame_rate;
+    l->frame_rate = test->frame_rate;
     outlink->time_base  = test->time_base;
 
     return 0;
diff --git a/libavfilter/vsrc_testsrc_vulkan.c b/libavfilter/vsrc_testsrc_vulkan.c
index 2b16ee2b6b..4b297af158 100644
--- a/libavfilter/vsrc_testsrc_vulkan.c
+++ b/libavfilter/vsrc_testsrc_vulkan.c
@@ -298,7 +298,7 @@ static int testsrc_vulkan_config_props(AVFilterLink *outlink)
     outlink->w = s->w;
     outlink->h = s->h;
     outlink->sample_aspect_ratio = s->sar;
-    outlink->frame_rate = s->frame_rate;
+    l->frame_rate = s->frame_rate;
     outlink->time_base  = s->time_base;
 
     return 0;
diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c
index 35be87e8d5..3f5e0ebfb8 100644
--- a/libavfilter/yadif_common.c
+++ b/libavfilter/yadif_common.c
@@ -21,6 +21,7 @@
 
 #include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
+#include "filters.h"
 #include "internal.h"
 #include "video.h"
 #include "yadif.h"
@@ -218,6 +219,8 @@ int ff_yadif_request_frame(AVFilterLink *link)
 int ff_yadif_config_output_common(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
+    FilterLink *il = ff_filter_link(ctx->inputs[0]);
+    FilterLink *ol = ff_filter_link(outlink);
     YADIFContext *yadif = ctx->priv;
     AVRational tb = ctx->inputs[0]->time_base;
     int ret;
@@ -239,12 +242,12 @@ int ff_yadif_config_output_common(AVFilterLink *outlink)
     }
 
     if(yadif->mode & 1)
-        outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate,
+        ol->frame_rate = av_mul_q(il->frame_rate,
                                     (AVRational){2, 1});
     else
-        outlink->frame_rate = ctx->inputs[0]->frame_rate;
+        ol->frame_rate = il->frame_rate;
 
-    ret = ff_ccfifo_init(&yadif->cc_fifo, outlink->frame_rate, ctx);
+    ret = ff_ccfifo_init(&yadif->cc_fifo, ol->frame_rate, ctx);
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Failure to setup CC FIFO queue\n");
         return ret;
