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