Commit 28fc1c56c8 for ffmpeg

commit 28fc1c56c8055358b5d6a1e3e35ff89c558f9f69
Author: Michael Niedermayer <michael@niedermayer.cc>
Date:   Tue Oct 6 00:13:03 2026 +0200

    avfilter: add flags for filters handling changed frame parameters

    A filter declares with FF_FILTER_FLAG_DYNAMIC_FRAME_SIZE or
    FF_FILTER_FLAG_DYNAMIC_FRAME_PARAMS that it handles input frames whose
    size, or size and pixel format, differ from what its input link was
    configured with. ff_inlink_check_frame_params() checks a frame against
    that configuration.

diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 46068719b1..c696d37aab 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -450,6 +450,9 @@ int ff_filter_config_links(AVFilterContext *filter)
                     return ret;
                 }

+            li->cfg_format = link->format;
+            li->cfg_w      = link->w;
+            li->cfg_h      = link->h;
             li->init_state = AVLINK_INIT;
         }
     }
@@ -1569,6 +1572,22 @@ AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx)
     return ff_framequeue_peek(&li->fifo, idx);
 }

+int ff_inlink_check_frame_params(AVFilterLink *link, const AVFrame *frame,
+                                 int dynamic_flags)
+{
+    const FilterLinkInternal *li = ff_link_internal(link);
+
+    if ((frame->format == li->cfg_format ||
+         dynamic_flags & FF_FILTER_FLAG_DYNAMIC_FRAME_FORMAT) &&
+        (frame->width == li->cfg_w && frame->height == li->cfg_h ||
+         dynamic_flags & FF_FILTER_FLAG_DYNAMIC_FRAME_SIZE))
+        return 0;
+
+    av_log(link->dst, AV_LOG_ERROR,
+           "Frame size or format changed without filter graph reinitialization\n");
+    return AVERROR(EINVAL);
+}
+
 int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
 {
     AVFrame *frame = *rframe;
diff --git a/libavfilter/avfilter_internal.h b/libavfilter/avfilter_internal.h
index 808dd6af38..3056b2edc3 100644
--- a/libavfilter/avfilter_internal.h
+++ b/libavfilter/avfilter_internal.h
@@ -45,6 +45,11 @@ typedef struct FilterLinkInternal {
      */
     FFFrameQueue fifo;

+    /**
+     * Format and size of the video frames the link was configured with.
+     */
+    int cfg_format, cfg_w, cfg_h;
+
     /**
      * If set, the source filter can not generate a frame as is.
      * The goal is to avoid repeatedly calling the request_frame() method on
diff --git a/libavfilter/filters.h b/libavfilter/filters.h
index 57540d7698..2df05a727a 100644
--- a/libavfilter/filters.h
+++ b/libavfilter/filters.h
@@ -207,6 +207,21 @@ static inline FilterLink* ff_filter_link(AVFilterLink *link)
  */
 #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0)

+/**
+ * The filter handles input frames whose size differs from the one its input
+ * link was configured with.
+ */
+#define FF_FILTER_FLAG_DYNAMIC_FRAME_SIZE   (1 << 1)
+
+/**
+ * The filter handles input frames whose pixel format differs from the one its
+ * input link was configured with.
+ */
+#define FF_FILTER_FLAG_DYNAMIC_FRAME_FORMAT (1 << 2)
+
+#define FF_FILTER_FLAG_DYNAMIC_FRAME_PARAMS (FF_FILTER_FLAG_DYNAMIC_FRAME_SIZE | \
+                                             FF_FILTER_FLAG_DYNAMIC_FRAME_FORMAT)
+
 /**
  * Find the index of a link.
  *
@@ -556,6 +571,17 @@ int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max,
  */
 AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx);

+/**
+ * Check that a video frame has the size and pixel format its link was
+ * configured with.
+ *
+ * @param dynamic_flags FF_FILTER_FLAG_DYNAMIC_* flags of the parameters
+ *                      allowed to differ
+ * @return 0 if the frame matches, AVERROR(EINVAL) otherwise
+ */
+int ff_inlink_check_frame_params(AVFilterLink *link, const AVFrame *frame,
+                                 int dynamic_flags);
+
 /**
  * Make sure a frame is writable.
  * This is similar to av_frame_make_writable() except it uses the link's