diff --git a/libavfilter/af_anequalizer.c b/libavfilter/af_anequalizer.c
index 9aab577079..b9d02e28ff 100644
--- a/libavfilter/af_anequalizer.c
+++ b/libavfilter/af_anequalizer.c
@@ -757,9 +757,9 @@ static const AVFilterPad inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_AUDIO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c
index f77bba363c..82df3ace15 100644
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -383,9 +383,9 @@ static const AVFilterPad avfilter_af_channelmap_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_AUDIO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = channelmap_filter_frame,
         .config_props   = channelmap_config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/af_firequalizer.c b/libavfilter/af_firequalizer.c
index 7e18db5517..d2114a515a 100644
--- a/libavfilter/af_firequalizer.c
+++ b/libavfilter/af_firequalizer.c
@@ -939,10 +939,10 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
 static const AVFilterPad firequalizer_inputs[] = {
     {
         .name           = "default",
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
         .type           = AVMEDIA_TYPE_AUDIO,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 843b5947e5..24184ed1ed 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -950,7 +950,7 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
     if (!(filter_frame = dst->filter_frame))
         filter_frame = default_filter_frame;
 
-    if (dst->needs_writable) {
+    if (dst->flags & AVFILTERPAD_FLAG_NEEDS_WRITABLE) {
         ret = ff_inlink_make_frame_writable(link, &frame);
         if (ret < 0)
             goto fail;
diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c
index 2b3ffd28de..29ba5fe9eb 100644
--- a/libavfilter/f_reverse.c
+++ b/libavfilter/f_reverse.c
@@ -269,8 +269,8 @@ static const AVFilterPad areverse_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_AUDIO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index c2be4a18fc..e7a9275114 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -60,6 +60,19 @@ struct AVFilterPad {
      */
     enum AVMediaType type;
 
+    /**
+     * The filter expects writable frames from its input link,
+     * duplicating data buffers if needed.
+     *
+     * input pads only.
+     */
+#define AVFILTERPAD_FLAG_NEEDS_WRITABLE                  (1 << 0)
+
+    /**
+     * A combination of AVFILTERPAD_FLAG_* flags.
+     */
+    int flags;
+
     /**
      * Callback function to get a video buffer. If NULL, the filter system will
      * use ff_default_get_video_buffer().
@@ -112,14 +125,6 @@ struct AVFilterPad {
      * and another value on error.
      */
     int (*config_props)(AVFilterLink *link);
-
-    /**
-     * The filter expects writable frames from its input link,
-     * duplicating data buffers if needed.
-     *
-     * input pads only.
-     */
-    int needs_writable;
 };
 
 struct AVFilterGraphInternal {
diff --git a/libavfilter/vf_chromakey.c b/libavfilter/vf_chromakey.c
index a3d4caf411..185b3980bc 100644
--- a/libavfilter/vf_chromakey.c
+++ b/libavfilter/vf_chromakey.c
@@ -367,7 +367,7 @@ static const AVFilterPad chromakey_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
@@ -420,7 +420,7 @@ static const AVFilterPad chromahold_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c
index 1b5c67e7d4..944d8fb303 100644
--- a/libavfilter/vf_codecview.c
+++ b/libavfilter/vf_codecview.c
@@ -300,9 +300,9 @@ static const AVFilterPad codecview_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_colorcontrast.c b/libavfilter/vf_colorcontrast.c
index 8975033760..1f4c0db43c 100644
--- a/libavfilter/vf_colorcontrast.c
+++ b/libavfilter/vf_colorcontrast.c
@@ -358,7 +358,7 @@ static const AVFilterPad colorcontrast_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_colorcorrect.c b/libavfilter/vf_colorcorrect.c
index 3fb2798256..f28409fa44 100644
--- a/libavfilter/vf_colorcorrect.c
+++ b/libavfilter/vf_colorcorrect.c
@@ -303,7 +303,7 @@ static const AVFilterPad colorcorrect_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_colorize.c b/libavfilter/vf_colorize.c
index 84876b78da..14c29d6486 100644
--- a/libavfilter/vf_colorize.c
+++ b/libavfilter/vf_colorize.c
@@ -259,7 +259,7 @@ static const AVFilterPad colorize_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_colorkey.c b/libavfilter/vf_colorkey.c
index dea7f89e28..2ebd470e6e 100644
--- a/libavfilter/vf_colorkey.c
+++ b/libavfilter/vf_colorkey.c
@@ -176,8 +176,8 @@ static const AVFilterPad colorkey_inputs[] = {
     {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
+        .flags        = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_colortemperature.c b/libavfilter/vf_colortemperature.c
index a5ba4a7b6c..9cf3767925 100644
--- a/libavfilter/vf_colortemperature.c
+++ b/libavfilter/vf_colortemperature.c
@@ -324,9 +324,9 @@ static const AVFilterPad inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c
index 70857ea491..6a9349d0d8 100644
--- a/libavfilter/vf_datascope.c
+++ b/libavfilter/vf_datascope.c
@@ -1130,9 +1130,9 @@ static const AVFilterPad oscilloscope_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = oscilloscope_filter_frame,
         .config_props   = oscilloscope_config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_despill.c b/libavfilter/vf_despill.c
index 5fe9b79dd0..3d56659149 100644
--- a/libavfilter/vf_despill.c
+++ b/libavfilter/vf_despill.c
@@ -131,8 +131,8 @@ static const AVFilterPad despill_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
+        .flags        = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c
index 373a6f45dd..c729ed577a 100644
--- a/libavfilter/vf_drawbox.c
+++ b/libavfilter/vf_drawbox.c
@@ -384,9 +384,9 @@ static const AVFilterPad drawbox_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
@@ -468,9 +468,9 @@ static const AVFilterPad drawgrid_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = drawgrid_filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index c4c09894e4..c274166b9b 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -1615,9 +1615,9 @@ static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_elbg.c b/libavfilter/vf_elbg.c
index afaa6225d2..d07b0cf0cb 100644
--- a/libavfilter/vf_elbg.c
+++ b/libavfilter/vf_elbg.c
@@ -235,9 +235,9 @@ static const AVFilterPad elbg_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_exposure.c b/libavfilter/vf_exposure.c
index f8bcf28e6a..b61d90658b 100644
--- a/libavfilter/vf_exposure.c
+++ b/libavfilter/vf_exposure.c
@@ -99,7 +99,7 @@ static const AVFilterPad exposure_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index d801bf8c95..07bb05478d 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -551,9 +551,9 @@ static const AVFilterPad avfilter_vf_fade_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_fillborders.c b/libavfilter/vf_fillborders.c
index 8ceac44c76..8653611393 100644
--- a/libavfilter/vf_fillborders.c
+++ b/libavfilter/vf_fillborders.c
@@ -705,9 +705,9 @@ static const AVFilterPad fillborders_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .config_props   = config_input,
         .filter_frame   = filter_frame,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_lumakey.c b/libavfilter/vf_lumakey.c
index d59ad2d5ba..b556f7ab7a 100644
--- a/libavfilter/vf_lumakey.c
+++ b/libavfilter/vf_lumakey.c
@@ -172,9 +172,9 @@ static const AVFilterPad lumakey_inputs[] = {
     {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
+        .flags        = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame = filter_frame,
         .config_props = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_maskfun.c b/libavfilter/vf_maskfun.c
index 0a6d17f7af..da1cfe91cb 100644
--- a/libavfilter/vf_maskfun.c
+++ b/libavfilter/vf_maskfun.c
@@ -294,9 +294,9 @@ static const AVFilterPad maskfun_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_monochrome.c b/libavfilter/vf_monochrome.c
index 0471c7d237..825a869707 100644
--- a/libavfilter/vf_monochrome.c
+++ b/libavfilter/vf_monochrome.c
@@ -267,7 +267,7 @@ static const AVFilterPad monochrome_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index ab32e1b7f3..2f7f927d8d 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -198,9 +198,9 @@ static const AVFilterPad ass_inputs[] = {
     {
         .name             = "default",
         .type             = AVMEDIA_TYPE_VIDEO,
+        .flags            = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame     = filter_frame,
         .config_props     = config_input,
-        .needs_writable   = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_swaprect.c b/libavfilter/vf_swaprect.c
index 3b96790798..7829f2f852 100644
--- a/libavfilter/vf_swaprect.c
+++ b/libavfilter/vf_swaprect.c
@@ -228,9 +228,9 @@ static const AVFilterPad inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
-        .needs_writable = 1,
     },
     { NULL }
 };
diff --git a/libavfilter/vf_vibrance.c b/libavfilter/vf_vibrance.c
index b8f9fa0198..bc53f47a7b 100644
--- a/libavfilter/vf_vibrance.c
+++ b/libavfilter/vf_vibrance.c
@@ -340,7 +340,7 @@ static const AVFilterPad vibrance_inputs[] = {
     {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
-        .needs_writable = 1,
+        .flags          = AVFILTERPAD_FLAG_NEEDS_WRITABLE,
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
