diff mbox series

[FFmpeg-devel,2/4] avfilter/avfilter: Add numbers of (in|out)pads directly to AVFilter

Message ID AM7PR03MB666071C4E6B212F3A73C48EA8FF99@AM7PR03MB6660.eurprd03.prod.outlook.com
State Superseded
Headers show
Series [FFmpeg-devel,1/4] fftools/cmdutils: Use avfilter_pad_count() for AVFilter's number of pads | expand

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Andreas Rheinhardt Aug. 12, 2021, 5:12 p.m. UTC
Up until now, an AVFilter's lists of input and output AVFilterPads
were terminated by a sentinel and the only way for the user to get
the length of these lists was by using avfilter_pad_count(). This
has two drawbacks: first, sizeof(AVFilterPad) is not negligible
(i.e. 64B on 64bit systems); second, getting the size involves
a function call instead of just reading the data.

This commit therefore changes this. The sentinels are removed and new
fields nb_inputs and nb_outputs are added to AVFilter that contain the
number of elements of the respective AVFilterPad array.
Given that AVFilter.(in|out)puts are the only arrays of zero-terminated
AVFilterPads an API user has access to (AVFilterContext.(in|out)put_pads
are not zero-terminated and they already have a size field) the argument
to avfilter_pad_count() is always one of these lists, so it just has to
find the filter the list belongs to and read said number. This is slower
than before, but users are expected to switch to AVFilter.nb_(in|out)puts;
and furthermore, avfilter_pad_count() is probably never called in hot
loops anyway.

This saves about 49KiB from the binary; notice that these sentinels are
not in .bss despite being zeroed; in fact, they are in .data.rel.ro
due to the non-sentinels.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavfilter/aeval.c                 |  6 +++---
 libavfilter/af_acontrast.c          |  4 ++--
 libavfilter/af_acopy.c              |  4 ++--
 libavfilter/af_acrossover.c         |  2 +-
 libavfilter/af_acrusher.c           |  4 ++--
 libavfilter/af_adeclick.c           |  6 ++++--
 libavfilter/af_adelay.c             |  4 ++--
 libavfilter/af_adenorm.c            |  4 ++--
 libavfilter/af_aderivative.c        |  6 ++++--
 libavfilter/af_aecho.c              |  4 ++--
 libavfilter/af_aemphasis.c          |  4 ++--
 libavfilter/af_aexciter.c           |  4 ++--
 libavfilter/af_afade.c              |  8 ++++----
 libavfilter/af_afftdn.c             |  4 ++--
 libavfilter/af_afftfilt.c           |  4 ++--
 libavfilter/af_aformat.c            |  4 ++--
 libavfilter/af_afreqshift.c         |  6 ++++--
 libavfilter/af_afwtdn.c             |  4 ++--
 libavfilter/af_agate.c              |  8 ++++----
 libavfilter/af_aiir.c               |  2 +-
 libavfilter/af_alimiter.c           |  4 ++--
 libavfilter/af_amerge.c             |  2 +-
 libavfilter/af_amix.c               |  2 +-
 libavfilter/af_amultiply.c          |  4 ++--
 libavfilter/af_anequalizer.c        |  2 +-
 libavfilter/af_anlmdn.c             |  4 ++--
 libavfilter/af_anlms.c              |  4 ++--
 libavfilter/af_anull.c              |  4 ++--
 libavfilter/af_apad.c               |  4 ++--
 libavfilter/af_aphaser.c            |  4 ++--
 libavfilter/af_apulsator.c          |  4 ++--
 libavfilter/af_aresample.c          |  4 ++--
 libavfilter/af_arnndn.c             |  4 ++--
 libavfilter/af_asetnsamples.c       |  4 ++--
 libavfilter/af_asetrate.c           |  4 ++--
 libavfilter/af_ashowinfo.c          |  4 ++--
 libavfilter/af_asoftclip.c          |  4 ++--
 libavfilter/af_asr.c                |  4 ++--
 libavfilter/af_astats.c             |  4 ++--
 libavfilter/af_asubboost.c          |  4 ++--
 libavfilter/af_asupercut.c          | 10 ++++++++--
 libavfilter/af_atempo.c             |  4 ++--
 libavfilter/af_axcorrelate.c        |  4 ++--
 libavfilter/af_biquads.c            |  4 ++--
 libavfilter/af_bs2b.c               |  4 ++--
 libavfilter/af_channelmap.c         |  4 ++--
 libavfilter/af_channelsplit.c       |  2 +-
 libavfilter/af_chorus.c             |  4 ++--
 libavfilter/af_compand.c            |  4 ++--
 libavfilter/af_compensationdelay.c  |  4 ++--
 libavfilter/af_crossfeed.c          |  4 ++--
 libavfilter/af_crystalizer.c        |  4 ++--
 libavfilter/af_dcshift.c            |  4 ++--
 libavfilter/af_deesser.c            |  4 ++--
 libavfilter/af_drmeter.c            |  4 ++--
 libavfilter/af_dynaudnorm.c         |  4 ++--
 libavfilter/af_earwax.c             |  4 ++--
 libavfilter/af_extrastereo.c        |  4 ++--
 libavfilter/af_firequalizer.c       |  4 ++--
 libavfilter/af_flanger.c            |  4 ++--
 libavfilter/af_haas.c               |  4 ++--
 libavfilter/af_hdcd.c               |  4 ++--
 libavfilter/af_headphone.c          |  2 +-
 libavfilter/af_join.c               |  2 +-
 libavfilter/af_ladspa.c             |  2 +-
 libavfilter/af_loudnorm.c           |  4 ++--
 libavfilter/af_lv2.c                |  2 +-
 libavfilter/af_mcompand.c           |  4 ++--
 libavfilter/af_pan.c                |  4 ++--
 libavfilter/af_replaygain.c         |  4 ++--
 libavfilter/af_rubberband.c         |  4 ++--
 libavfilter/af_sidechaincompress.c  |  8 ++++----
 libavfilter/af_silencedetect.c      |  4 ++--
 libavfilter/af_silenceremove.c      |  4 ++--
 libavfilter/af_sofalizer.c          |  4 ++--
 libavfilter/af_speechnorm.c         |  4 ++--
 libavfilter/af_stereotools.c        |  4 ++--
 libavfilter/af_stereowiden.c        |  4 ++--
 libavfilter/af_superequalizer.c     |  4 ++--
 libavfilter/af_surround.c           |  4 ++--
 libavfilter/af_tremolo.c            |  4 ++--
 libavfilter/af_vibrato.c            |  4 ++--
 libavfilter/af_volume.c             |  4 ++--
 libavfilter/af_volumedetect.c       |  4 ++--
 libavfilter/asink_anullsink.c       |  2 +-
 libavfilter/asrc_afirsrc.c          |  2 +-
 libavfilter/asrc_anoisesrc.c        |  2 +-
 libavfilter/asrc_anullsrc.c         |  2 +-
 libavfilter/asrc_flite.c            |  2 +-
 libavfilter/asrc_hilbert.c          |  2 +-
 libavfilter/asrc_sinc.c             |  2 +-
 libavfilter/asrc_sine.c             |  2 +-
 libavfilter/avf_abitscope.c         |  4 ++--
 libavfilter/avf_ahistogram.c        |  4 ++--
 libavfilter/avf_aphasemeter.c       |  2 +-
 libavfilter/avf_avectorscope.c      |  4 ++--
 libavfilter/avf_showcqt.c           |  4 ++--
 libavfilter/avf_showfreqs.c         |  4 ++--
 libavfilter/avf_showspatial.c       |  4 ++--
 libavfilter/avf_showspectrum.c      |  8 ++++----
 libavfilter/avf_showvolume.c        |  4 ++--
 libavfilter/avf_showwaves.c         |  8 ++++----
 libavfilter/avfilter.c              | 14 ++++++++++----
 libavfilter/avfilter.h              | 18 ++++++++++++++----
 libavfilter/buffersink.c            |  4 ++--
 libavfilter/buffersrc.c             |  4 ++--
 libavfilter/f_bench.c               |  8 ++++----
 libavfilter/f_cue.c                 |  8 ++++----
 libavfilter/f_drawgraph.c           |  8 ++++----
 libavfilter/f_ebur128.c             |  2 +-
 libavfilter/f_graphmonitor.c        |  8 ++++----
 libavfilter/f_interleave.c          |  4 ++--
 libavfilter/f_loop.c                |  8 ++++----
 libavfilter/f_metadata.c            |  8 ++++----
 libavfilter/f_perms.c               |  8 ++++----
 libavfilter/f_realtime.c            |  8 ++++----
 libavfilter/f_reverse.c             |  8 ++++----
 libavfilter/f_select.c              |  4 ++--
 libavfilter/f_sendcmd.c             |  8 ++++----
 libavfilter/f_sidedata.c            |  8 ++++----
 libavfilter/f_zmq.c                 |  8 ++++----
 libavfilter/fifo.c                  |  8 ++++----
 libavfilter/setpts.c                |  8 ++++----
 libavfilter/settb.c                 |  8 ++++----
 libavfilter/split.c                 |  4 ++--
 libavfilter/trim.c                  |  8 ++++----
 libavfilter/vaf_spectrumsynth.c     |  4 ++--
 libavfilter/vf_addroi.c             |  4 ++--
 libavfilter/vf_alphamerge.c         |  4 ++--
 libavfilter/vf_amplify.c            |  4 ++--
 libavfilter/vf_aspect.c             |  8 ++++----
 libavfilter/vf_atadenoise.c         |  4 ++--
 libavfilter/vf_avgblur.c            |  4 ++--
 libavfilter/vf_avgblur_opencl.c     |  6 ++++--
 libavfilter/vf_avgblur_vulkan.c     |  4 ++--
 libavfilter/vf_bbox.c               |  4 ++--
 libavfilter/vf_bilateral.c          |  4 ++--
 libavfilter/vf_bitplanenoise.c      |  4 ++--
 libavfilter/vf_blackdetect.c        |  4 ++--
 libavfilter/vf_blackframe.c         |  4 ++--
 libavfilter/vf_blend.c              |  8 ++++----
 libavfilter/vf_bm3d.c               |  2 +-
 libavfilter/vf_boxblur.c            |  4 ++--
 libavfilter/vf_bwdif.c              |  4 ++--
 libavfilter/vf_cas.c                |  4 ++--
 libavfilter/vf_chromaber_vulkan.c   |  4 ++--
 libavfilter/vf_chromakey.c          |  8 ++++----
 libavfilter/vf_chromanr.c           |  4 ++--
 libavfilter/vf_chromashift.c        |  6 ++++--
 libavfilter/vf_ciescope.c           |  4 ++--
 libavfilter/vf_codecview.c          |  4 ++--
 libavfilter/vf_colorbalance.c       |  4 ++--
 libavfilter/vf_colorchannelmixer.c  |  4 ++--
 libavfilter/vf_colorconstancy.c     |  4 ++--
 libavfilter/vf_colorcontrast.c      |  4 ++--
 libavfilter/vf_colorcorrect.c       |  4 ++--
 libavfilter/vf_colorize.c           |  4 ++--
 libavfilter/vf_colorkey.c           |  6 ++++--
 libavfilter/vf_colorkey_opencl.c    |  4 ++--
 libavfilter/vf_colorlevels.c        |  4 ++--
 libavfilter/vf_colormatrix.c        |  4 ++--
 libavfilter/vf_colorspace.c         |  4 ++--
 libavfilter/vf_colortemperature.c   |  4 ++--
 libavfilter/vf_convolution.c        | 12 ++++++++++--
 libavfilter/vf_convolution_opencl.c | 10 ++++++++--
 libavfilter/vf_convolve.c           |  6 ++++--
 libavfilter/vf_copy.c               |  4 ++--
 libavfilter/vf_cover_rect.c         |  4 ++--
 libavfilter/vf_crop.c               |  4 ++--
 libavfilter/vf_cropdetect.c         |  4 ++--
 libavfilter/vf_curves.c             |  4 ++--
 libavfilter/vf_datascope.c          | 12 ++++++------
 libavfilter/vf_dblur.c              |  4 ++--
 libavfilter/vf_dctdnoiz.c           |  4 ++--
 libavfilter/vf_deband.c             |  4 ++--
 libavfilter/vf_deblock.c            |  4 ++--
 libavfilter/vf_decimate.c           |  2 +-
 libavfilter/vf_dedot.c              |  4 ++--
 libavfilter/vf_deflicker.c          |  4 ++--
 libavfilter/vf_deinterlace_qsv.c    |  4 ++--
 libavfilter/vf_deinterlace_vaapi.c  |  4 ++--
 libavfilter/vf_dejudder.c           |  4 ++--
 libavfilter/vf_delogo.c             |  4 ++--
 libavfilter/vf_derain.c             |  4 ++--
 libavfilter/vf_deshake.c            |  4 ++--
 libavfilter/vf_deshake_opencl.c     |  4 ++--
 libavfilter/vf_despill.c            |  4 ++--
 libavfilter/vf_detelecine.c         |  4 ++--
 libavfilter/vf_displace.c           |  4 ++--
 libavfilter/vf_dnn_classify.c       |  4 ++--
 libavfilter/vf_dnn_detect.c         |  4 ++--
 libavfilter/vf_dnn_processing.c     |  4 ++--
 libavfilter/vf_drawbox.c            |  8 ++++----
 libavfilter/vf_drawtext.c           |  4 ++--
 libavfilter/vf_edgedetect.c         |  4 ++--
 libavfilter/vf_elbg.c               |  4 ++--
 libavfilter/vf_entropy.c            |  4 ++--
 libavfilter/vf_epx.c                |  4 ++--
 libavfilter/vf_eq.c                 |  4 ++--
 libavfilter/vf_estdif.c             |  4 ++--
 libavfilter/vf_exposure.c           |  4 ++--
 libavfilter/vf_extractplanes.c      |  3 ++-
 libavfilter/vf_fade.c               |  4 ++--
 libavfilter/vf_fftdnoiz.c           |  4 ++--
 libavfilter/vf_fftfilt.c            |  4 ++--
 libavfilter/vf_field.c              |  4 ++--
 libavfilter/vf_fieldhint.c          |  4 ++--
 libavfilter/vf_fieldmatch.c         |  2 +-
 libavfilter/vf_fieldorder.c         |  4 ++--
 libavfilter/vf_fillborders.c        |  4 ++--
 libavfilter/vf_find_rect.c          |  4 ++--
 libavfilter/vf_floodfill.c          |  4 ++--
 libavfilter/vf_format.c             |  8 ++++----
 libavfilter/vf_fps.c                |  4 ++--
 libavfilter/vf_framepack.c          |  4 ++--
 libavfilter/vf_framerate.c          |  4 ++--
 libavfilter/vf_framestep.c          |  4 ++--
 libavfilter/vf_freezedetect.c       |  4 ++--
 libavfilter/vf_freezeframes.c       |  4 ++--
 libavfilter/vf_frei0r.c             |  6 +++---
 libavfilter/vf_fspp.c               |  4 ++--
 libavfilter/vf_gblur.c              |  4 ++--
 libavfilter/vf_geq.c                |  4 ++--
 libavfilter/vf_gradfun.c            |  4 ++--
 libavfilter/vf_guided.c             |  2 +-
 libavfilter/vf_hflip.c              |  4 ++--
 libavfilter/vf_histeq.c             |  4 ++--
 libavfilter/vf_histogram.c          |  6 ++++--
 libavfilter/vf_hqdn3d.c             |  4 ++--
 libavfilter/vf_hqx.c                |  4 ++--
 libavfilter/vf_hue.c                |  4 ++--
 libavfilter/vf_hwdownload.c         |  4 ++--
 libavfilter/vf_hwmap.c              |  4 ++--
 libavfilter/vf_hwupload.c           |  4 ++--
 libavfilter/vf_hwupload_cuda.c      |  4 ++--
 libavfilter/vf_hysteresis.c         |  4 ++--
 libavfilter/vf_identity.c           |  6 ++++--
 libavfilter/vf_idet.c               |  4 ++--
 libavfilter/vf_il.c                 |  4 ++--
 libavfilter/vf_kerndeint.c          |  4 ++--
 libavfilter/vf_lagfun.c             |  4 ++--
 libavfilter/vf_lenscorrection.c     |  4 ++--
 libavfilter/vf_lensfun.c            |  4 ++--
 libavfilter/vf_libopencv.c          |  4 ++--
 libavfilter/vf_libvmaf.c            |  4 ++--
 libavfilter/vf_limiter.c            |  4 ++--
 libavfilter/vf_lumakey.c            |  4 ++--
 libavfilter/vf_lut.c                |  4 ++--
 libavfilter/vf_lut2.c               |  8 ++++----
 libavfilter/vf_lut3d.c              | 12 ++++++------
 libavfilter/vf_maskedclamp.c        |  4 ++--
 libavfilter/vf_maskedmerge.c        |  4 ++--
 libavfilter/vf_maskedminmax.c       |  6 ++++--
 libavfilter/vf_maskedthreshold.c    |  4 ++--
 libavfilter/vf_maskfun.c            |  4 ++--
 libavfilter/vf_mcdeint.c            |  4 ++--
 libavfilter/vf_median.c             |  4 ++--
 libavfilter/vf_mergeplanes.c        |  2 +-
 libavfilter/vf_mestimate.c          |  4 ++--
 libavfilter/vf_midequalizer.c       |  4 ++--
 libavfilter/vf_minterpolate.c       |  4 ++--
 libavfilter/vf_misc_vaapi.c         |  6 ++++--
 libavfilter/vf_mix.c                |  5 +++--
 libavfilter/vf_monochrome.c         |  4 ++--
 libavfilter/vf_mpdecimate.c         |  4 ++--
 libavfilter/vf_neighbor.c           |  4 ++--
 libavfilter/vf_neighbor_opencl.c    |  6 ++++--
 libavfilter/vf_nlmeans.c            |  4 ++--
 libavfilter/vf_nlmeans_opencl.c     |  4 ++--
 libavfilter/vf_nnedi.c              |  4 ++--
 libavfilter/vf_noise.c              |  4 ++--
 libavfilter/vf_normalize.c          |  4 ++--
 libavfilter/vf_null.c               |  4 ++--
 libavfilter/vf_ocr.c                |  4 ++--
 libavfilter/vf_overlay.c            |  4 ++--
 libavfilter/vf_overlay_cuda.c       |  4 ++--
 libavfilter/vf_overlay_opencl.c     |  4 ++--
 libavfilter/vf_overlay_qsv.c        |  4 ++--
 libavfilter/vf_overlay_vulkan.c     |  4 ++--
 libavfilter/vf_owdenoise.c          |  4 ++--
 libavfilter/vf_pad.c                |  4 ++--
 libavfilter/vf_pad_opencl.c         |  4 ++--
 libavfilter/vf_palettegen.c         |  4 ++--
 libavfilter/vf_paletteuse.c         |  4 ++--
 libavfilter/vf_perspective.c        |  4 ++--
 libavfilter/vf_phase.c              |  4 ++--
 libavfilter/vf_photosensitivity.c   |  4 ++--
 libavfilter/vf_pixdesctest.c        |  4 ++--
 libavfilter/vf_pp.c                 |  4 ++--
 libavfilter/vf_pp7.c                |  4 ++--
 libavfilter/vf_premultiply.c        |  3 ++-
 libavfilter/vf_procamp_vaapi.c      |  4 ++--
 libavfilter/vf_program_opencl.c     |  4 ++--
 libavfilter/vf_pseudocolor.c        |  4 ++--
 libavfilter/vf_psnr.c               |  4 ++--
 libavfilter/vf_pullup.c             |  4 ++--
 libavfilter/vf_qp.c                 |  4 ++--
 libavfilter/vf_random.c             |  4 ++--
 libavfilter/vf_readeia608.c         |  4 ++--
 libavfilter/vf_readvitc.c           |  4 ++--
 libavfilter/vf_remap.c              |  4 ++--
 libavfilter/vf_removegrain.c        |  4 ++--
 libavfilter/vf_removelogo.c         |  4 ++--
 libavfilter/vf_repeatfields.c       |  4 ++--
 libavfilter/vf_rotate.c             |  4 ++--
 libavfilter/vf_sab.c                |  4 ++--
 libavfilter/vf_scale.c              |  8 ++++----
 libavfilter/vf_scale_cuda.c         |  4 ++--
 libavfilter/vf_scale_npp.c          |  4 ++--
 libavfilter/vf_scale_qsv.c          |  4 ++--
 libavfilter/vf_scale_vaapi.c        |  4 ++--
 libavfilter/vf_scale_vulkan.c       |  4 ++--
 libavfilter/vf_scdet.c              |  4 ++--
 libavfilter/vf_scroll.c             |  4 ++--
 libavfilter/vf_selectivecolor.c     |  4 ++--
 libavfilter/vf_separatefields.c     |  4 ++--
 libavfilter/vf_setparams.c          |  8 ++++++--
 libavfilter/vf_shear.c              |  4 ++--
 libavfilter/vf_showinfo.c           |  4 ++--
 libavfilter/vf_showpalette.c        |  4 ++--
 libavfilter/vf_shuffleframes.c      |  4 ++--
 libavfilter/vf_shufflepixels.c      |  4 ++--
 libavfilter/vf_shuffleplanes.c      |  4 ++--
 libavfilter/vf_signalstats.c        |  4 ++--
 libavfilter/vf_signature.c          |  2 +-
 libavfilter/vf_smartblur.c          |  4 ++--
 libavfilter/vf_spp.c                |  4 ++--
 libavfilter/vf_sr.c                 |  4 ++--
 libavfilter/vf_ssim.c               |  4 ++--
 libavfilter/vf_stack.c              |  4 +++-
 libavfilter/vf_stereo3d.c           |  4 ++--
 libavfilter/vf_subtitles.c          |  6 ++++--
 libavfilter/vf_super2xsai.c         |  4 ++--
 libavfilter/vf_swaprect.c           |  4 ++--
 libavfilter/vf_swapuv.c             |  4 ++--
 libavfilter/vf_telecine.c           |  4 ++--
 libavfilter/vf_threshold.c          |  4 ++--
 libavfilter/vf_thumbnail.c          |  4 ++--
 libavfilter/vf_thumbnail_cuda.c     |  4 ++--
 libavfilter/vf_tile.c               |  4 ++--
 libavfilter/vf_tinterlace.c         |  6 ++++--
 libavfilter/vf_tmidequalizer.c      |  4 ++--
 libavfilter/vf_tonemap.c            |  4 ++--
 libavfilter/vf_tonemap_opencl.c     |  4 ++--
 libavfilter/vf_tonemap_vaapi.c      |  4 ++--
 libavfilter/vf_tpad.c               |  4 ++--
 libavfilter/vf_transpose.c          |  4 ++--
 libavfilter/vf_transpose_npp.c      |  4 ++--
 libavfilter/vf_transpose_opencl.c   |  4 ++--
 libavfilter/vf_transpose_vaapi.c    |  4 ++--
 libavfilter/vf_unsharp.c            |  4 ++--
 libavfilter/vf_unsharp_opencl.c     |  4 ++--
 libavfilter/vf_untile.c             |  4 ++--
 libavfilter/vf_uspp.c               |  4 ++--
 libavfilter/vf_v360.c               |  4 ++--
 libavfilter/vf_vaguedenoiser.c      |  4 ++--
 libavfilter/vf_vectorscope.c        |  4 ++--
 libavfilter/vf_vflip.c              |  4 ++--
 libavfilter/vf_vfrdet.c             |  4 ++--
 libavfilter/vf_vibrance.c           |  4 ++--
 libavfilter/vf_vidstabdetect.c      |  4 ++--
 libavfilter/vf_vidstabtransform.c   |  4 ++--
 libavfilter/vf_vif.c                |  4 ++--
 libavfilter/vf_vignette.c           |  4 ++--
 libavfilter/vf_vmafmotion.c         |  4 ++--
 libavfilter/vf_vpp_qsv.c            |  4 ++--
 libavfilter/vf_w3fdif.c             |  4 ++--
 libavfilter/vf_waveform.c           |  4 ++--
 libavfilter/vf_weave.c              |  6 ++++--
 libavfilter/vf_xbr.c                |  4 ++--
 libavfilter/vf_xfade.c              |  4 ++--
 libavfilter/vf_xfade_opencl.c       |  4 ++--
 libavfilter/vf_xmedian.c            |  6 +++---
 libavfilter/vf_yadif.c              |  4 ++--
 libavfilter/vf_yadif_cuda.c         |  4 ++--
 libavfilter/vf_yaepblur.c           |  4 ++--
 libavfilter/vf_zoompan.c            |  4 ++--
 libavfilter/vf_zscale.c             |  4 ++--
 libavfilter/vsink_nullsink.c        |  2 +-
 libavfilter/vsrc_cellauto.c         |  2 +-
 libavfilter/vsrc_gradients.c        |  2 +-
 libavfilter/vsrc_life.c             |  2 +-
 libavfilter/vsrc_mandelbrot.c       |  2 +-
 libavfilter/vsrc_mptestsrc.c        |  2 +-
 libavfilter/vsrc_sierpinski.c       |  2 +-
 libavfilter/vsrc_testsrc.c          | 23 +++++++++++++----------
 386 files changed, 893 insertions(+), 815 deletions(-)

Comments

Nicolas George Aug. 14, 2021, 9:12 a.m. UTC | #1
Andreas Rheinhardt (12021-08-12):
> Up until now, an AVFilter's lists of input and output AVFilterPads
> were terminated by a sentinel and the only way for the user to get
> the length of these lists was by using avfilter_pad_count(). This
> has two drawbacks: first, sizeof(AVFilterPad) is not negligible
> (i.e. 64B on 64bit systems); second, getting the size involves
> a function call instead of just reading the data.
> 
> This commit therefore changes this. The sentinels are removed and new
> fields nb_inputs and nb_outputs are added to AVFilter that contain the
> number of elements of the respective AVFilterPad array.
> Given that AVFilter.(in|out)puts are the only arrays of zero-terminated
> AVFilterPads an API user has access to (AVFilterContext.(in|out)put_pads
> are not zero-terminated and they already have a size field) the argument
> to avfilter_pad_count() is always one of these lists, so it just has to
> find the filter the list belongs to and read said number. This is slower
> than before, but users are expected to switch to AVFilter.nb_(in|out)puts;
> and furthermore, avfilter_pad_count() is probably never called in hot
> loops anyway.
> 
> This saves about 49KiB from the binary; notice that these sentinels are
> not in .bss despite being zeroed; in fact, they are in .data.rel.ro
> due to the non-sentinels.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>

I think it is a good change.

We could shave ~3.5k extra by making the fields uint16_t; lavfi is
absolutely not ready to handle filters with thousands of inputs, there
are loops everywhere.

OTOH, I do not like the fact that it requires more boilerplate code.

> @@ -330,6 +329,7 @@ const AVFilter ff_asrc_aevalsrc = {
>      .priv_size     = sizeof(EvalContext),
>      .inputs        = NULL,
>      .outputs       = aevalsrc_outputs,
> +    .nb_outputs    = FF_ARRAY_ELEMS(aevalsrc_outputs),
>      .priv_class    = &aevalsrc_class,
>  };

A macro would solve that:

#define FILTER_INPUTS(array) \
    .inputs = (array),
    .nb_inputs = FF_ARRAY_ELEMS(array)

Also, I am rather not for using these fields directly. Keeping them
private and leaving avfilter_pad_count() gives us more freedom,
including the freedom to change the type from uint16_t to unsigned later
without break.

Regards,
Andreas Rheinhardt Aug. 14, 2021, 1:54 p.m. UTC | #2
Nicolas George:
> Andreas Rheinhardt (12021-08-12):
>> Up until now, an AVFilter's lists of input and output AVFilterPads
>> were terminated by a sentinel and the only way for the user to get
>> the length of these lists was by using avfilter_pad_count(). This
>> has two drawbacks: first, sizeof(AVFilterPad) is not negligible
>> (i.e. 64B on 64bit systems); second, getting the size involves
>> a function call instead of just reading the data.
>>
>> This commit therefore changes this. The sentinels are removed and new
>> fields nb_inputs and nb_outputs are added to AVFilter that contain the
>> number of elements of the respective AVFilterPad array.
>> Given that AVFilter.(in|out)puts are the only arrays of zero-terminated
>> AVFilterPads an API user has access to (AVFilterContext.(in|out)put_pads
>> are not zero-terminated and they already have a size field) the argument
>> to avfilter_pad_count() is always one of these lists, so it just has to
>> find the filter the list belongs to and read said number. This is slower
>> than before, but users are expected to switch to AVFilter.nb_(in|out)puts;
>> and furthermore, avfilter_pad_count() is probably never called in hot
>> loops anyway.
>>
>> This saves about 49KiB from the binary; notice that these sentinels are
>> not in .bss despite being zeroed; in fact, they are in .data.rel.ro
>> due to the non-sentinels.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> 
> I think it is a good change.
> 
> We could shave ~3.5k extra by making the fields uint16_t; lavfi is
> absolutely not ready to handle filters with thousands of inputs, there
> are loops everywhere.
> 
> OTOH, I do not like the fact that it requires more boilerplate code.

When I made this I found it acceptable because it also removed the
boilerplate { NULL } at the end of the structures. And because it could
be easily automated.

> 
>> @@ -330,6 +329,7 @@ const AVFilter ff_asrc_aevalsrc = {
>>      .priv_size     = sizeof(EvalContext),
>>      .inputs        = NULL,
>>      .outputs       = aevalsrc_outputs,
>> +    .nb_outputs    = FF_ARRAY_ELEMS(aevalsrc_outputs),
>>      .priv_class    = &aevalsrc_class,
>>  };
> 
> A macro would solve that:
> 
> #define FILTER_INPUTS(array) \
>     .inputs = (array),
>     .nb_inputs = FF_ARRAY_ELEMS(array)

That would indeed be even better.

> 
> Also, I am rather not for using these fields directly. Keeping them
> private and leaving avfilter_pad_count() gives us more freedom,
> including the freedom to change the type from uint16_t to unsigned later
> without break.
> 
But then I'd rather replace avfilter_pad_count() with something that
does not require to loop over all filters. Something like unsigned
avfilter_pads_count(const AVFilter *filter, int is_input).

- Andreas
diff mbox series

Patch

diff --git a/libavfilter/aeval.c b/libavfilter/aeval.c
index 007758bf57..b6906454a6 100644
--- a/libavfilter/aeval.c
+++ b/libavfilter/aeval.c
@@ -318,7 +318,6 @@  static const AVFilterPad aevalsrc_outputs[] = {
         .config_props  = config_props,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_aevalsrc = {
@@ -330,6 +329,7 @@  const AVFilter ff_asrc_aevalsrc = {
     .priv_size     = sizeof(EvalContext),
     .inputs        = NULL,
     .outputs       = aevalsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aevalsrc_outputs),
     .priv_class    = &aevalsrc_class,
 };
 
@@ -460,7 +460,6 @@  static const AVFilterPad aeval_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aeval_outputs[] = {
@@ -469,7 +468,6 @@  static const AVFilterPad aeval_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = aeval_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aeval = {
@@ -480,7 +478,9 @@  const AVFilter ff_af_aeval = {
     .uninit        = uninit,
     .priv_size     = sizeof(EvalContext),
     .inputs        = aeval_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aeval_inputs),
     .outputs       = aeval_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aeval_outputs),
     .priv_class    = &aeval_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/af_acontrast.c b/libavfilter/af_acontrast.c
index 69fe6b7e22..b1eab4e187 100644
--- a/libavfilter/af_acontrast.c
+++ b/libavfilter/af_acontrast.c
@@ -197,7 +197,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -205,7 +204,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acontrast = {
@@ -215,5 +213,7 @@  const AVFilter ff_af_acontrast = {
     .priv_size      = sizeof(AudioContrastContext),
     .priv_class     = &acontrast_class,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_acopy.c b/libavfilter/af_acopy.c
index 29551996d9..022a3a4dcc 100644
--- a/libavfilter/af_acopy.c
+++ b/libavfilter/af_acopy.c
@@ -51,7 +51,6 @@  static const AVFilterPad acopy_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad acopy_outputs[] = {
@@ -59,12 +58,13 @@  static const AVFilterPad acopy_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acopy = {
     .name          = "acopy",
     .description   = NULL_IF_CONFIG_SMALL("Copy the input audio unchanged to the output."),
     .inputs        = acopy_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(acopy_inputs),
     .outputs       = acopy_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(acopy_outputs),
 };
diff --git a/libavfilter/af_acrossover.c b/libavfilter/af_acrossover.c
index 3ba67b30e1..5687f74380 100644
--- a/libavfilter/af_acrossover.c
+++ b/libavfilter/af_acrossover.c
@@ -566,7 +566,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acrossover = {
@@ -578,6 +577,7 @@  const AVFilter ff_af_acrossover = {
     .uninit         = uninit,
     .query_formats  = query_formats,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = NULL,
     .flags          = AVFILTER_FLAG_DYNAMIC_OUTPUTS |
                       AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_acrusher.c b/libavfilter/af_acrusher.c
index ce337013ab..5213980e6d 100644
--- a/libavfilter/af_acrusher.c
+++ b/libavfilter/af_acrusher.c
@@ -353,7 +353,6 @@  static const AVFilterPad avfilter_af_acrusher_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_acrusher_outputs[] = {
@@ -361,7 +360,6 @@  static const AVFilterPad avfilter_af_acrusher_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acrusher = {
@@ -372,6 +370,8 @@  const AVFilter ff_af_acrusher = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_acrusher_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_acrusher_inputs),
     .outputs       = avfilter_af_acrusher_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_acrusher_outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/af_adeclick.c b/libavfilter/af_adeclick.c
index 798838f522..89afa72f88 100644
--- a/libavfilter/af_adeclick.c
+++ b/libavfilter/af_adeclick.c
@@ -751,7 +751,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -759,7 +758,6 @@  static const AVFilterPad outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_adeclick = {
@@ -772,7 +770,9 @@  const AVFilter ff_af_adeclick = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
 
@@ -808,6 +808,8 @@  const AVFilter ff_af_adeclip = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c
index c6450cb2b9..c7b165b4ed 100644
--- a/libavfilter/af_adelay.c
+++ b/libavfilter/af_adelay.c
@@ -339,7 +339,6 @@  static const AVFilterPad adelay_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad adelay_outputs[] = {
@@ -347,7 +346,6 @@  static const AVFilterPad adelay_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_adelay = {
@@ -359,6 +357,8 @@  const AVFilter ff_af_adelay = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = adelay_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(adelay_inputs),
     .outputs       = adelay_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(adelay_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_adenorm.c b/libavfilter/af_adenorm.c
index ee8d26ee73..fed7268174 100644
--- a/libavfilter/af_adenorm.c
+++ b/libavfilter/af_adenorm.c
@@ -291,7 +291,6 @@  static const AVFilterPad adenorm_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad adenorm_outputs[] = {
@@ -300,7 +299,6 @@  static const AVFilterPad adenorm_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ADenormContext, x)
@@ -324,7 +322,9 @@  const AVFilter ff_af_adenorm = {
     .query_formats   = query_formats,
     .priv_size       = sizeof(ADenormContext),
     .inputs          = adenorm_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(adenorm_inputs),
     .outputs         = adenorm_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(adenorm_outputs),
     .priv_class      = &adenorm_class,
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
diff --git a/libavfilter/af_aderivative.c b/libavfilter/af_aderivative.c
index 6b3e4dd0e4..1f53146d7d 100644
--- a/libavfilter/af_aderivative.c
+++ b/libavfilter/af_aderivative.c
@@ -175,7 +175,6 @@  static const AVFilterPad aderivative_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad aderivative_outputs[] = {
@@ -183,7 +182,6 @@  static const AVFilterPad aderivative_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aderivative = {
@@ -193,7 +191,9 @@  const AVFilter ff_af_aderivative = {
     .priv_size     = sizeof(ADerivativeContext),
     .uninit        = uninit,
     .inputs        = aderivative_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aderivative_inputs),
     .outputs       = aderivative_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aderivative_outputs),
 };
 
 const AVFilter ff_af_aintegral = {
@@ -203,5 +203,7 @@  const AVFilter ff_af_aintegral = {
     .priv_size     = sizeof(ADerivativeContext),
     .uninit        = uninit,
     .inputs        = aderivative_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aderivative_inputs),
     .outputs       = aderivative_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aderivative_outputs),
 };
diff --git a/libavfilter/af_aecho.c b/libavfilter/af_aecho.c
index 4e45ab9a8b..67f92b5ad8 100644
--- a/libavfilter/af_aecho.c
+++ b/libavfilter/af_aecho.c
@@ -364,7 +364,6 @@  static const AVFilterPad aecho_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad aecho_outputs[] = {
@@ -373,7 +372,6 @@  static const AVFilterPad aecho_outputs[] = {
         .config_props  = config_output,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aecho = {
@@ -386,5 +384,7 @@  const AVFilter ff_af_aecho = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = aecho_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aecho_inputs),
     .outputs       = aecho_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aecho_outputs),
 };
diff --git a/libavfilter/af_aemphasis.c b/libavfilter/af_aemphasis.c
index 66fe7036fa..d423ea94d6 100644
--- a/libavfilter/af_aemphasis.c
+++ b/libavfilter/af_aemphasis.c
@@ -389,7 +389,6 @@  static const AVFilterPad avfilter_af_aemphasis_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_aemphasis_outputs[] = {
@@ -397,7 +396,6 @@  static const AVFilterPad avfilter_af_aemphasis_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aemphasis = {
@@ -408,7 +406,9 @@  const AVFilter ff_af_aemphasis = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_aemphasis_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_aemphasis_inputs),
     .outputs       = avfilter_af_aemphasis_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_aemphasis_outputs),
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                      AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_aexciter.c b/libavfilter/af_aexciter.c
index e7f72cca38..f9bee525b3 100644
--- a/libavfilter/af_aexciter.c
+++ b/libavfilter/af_aexciter.c
@@ -292,7 +292,6 @@  static const AVFilterPad avfilter_af_aexciter_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_aexciter_outputs[] = {
@@ -300,7 +299,6 @@  static const AVFilterPad avfilter_af_aexciter_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aexciter = {
@@ -311,7 +309,9 @@  const AVFilter ff_af_aexciter = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_aexciter_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_aexciter_inputs),
     .outputs       = avfilter_af_aexciter_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_aexciter_outputs),
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c
index b22432f2e7..a74359327f 100644
--- a/libavfilter/af_afade.c
+++ b/libavfilter/af_afade.c
@@ -353,7 +353,6 @@  static const AVFilterPad avfilter_af_afade_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_afade_outputs[] = {
@@ -362,7 +361,6 @@  static const AVFilterPad avfilter_af_afade_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afade = {
@@ -372,7 +370,9 @@  const AVFilter ff_af_afade = {
     .priv_size     = sizeof(AudioFadeContext),
     .init          = init,
     .inputs        = avfilter_af_afade_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_afade_inputs),
     .outputs       = avfilter_af_afade_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_afade_outputs),
     .priv_class    = &afade_class,
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
@@ -641,7 +641,6 @@  static const AVFilterPad avfilter_af_acrossfade_inputs[] = {
         .name         = "crossfade1",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_acrossfade_outputs[] = {
@@ -650,7 +649,6 @@  static const AVFilterPad avfilter_af_acrossfade_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = acrossfade_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acrossfade = {
@@ -661,7 +659,9 @@  const AVFilter ff_af_acrossfade = {
     .activate      = activate,
     .priv_class    = &acrossfade_class,
     .inputs        = avfilter_af_acrossfade_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_acrossfade_inputs),
     .outputs       = avfilter_af_acrossfade_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_acrossfade_outputs),
 };
 
 #endif /* CONFIG_ACROSSFADE_FILTER */
diff --git a/libavfilter/af_afftdn.c b/libavfilter/af_afftdn.c
index 693585439b..69c7335341 100644
--- a/libavfilter/af_afftdn.c
+++ b/libavfilter/af_afftdn.c
@@ -1412,7 +1412,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1420,7 +1419,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afftdn = {
@@ -1432,7 +1430,9 @@  const AVFilter ff_af_afftdn = {
     .activate        = activate,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c
index 877ccc5be0..4ea3e8667b 100644
--- a/libavfilter/af_afftfilt.c
+++ b/libavfilter/af_afftfilt.c
@@ -479,7 +479,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -487,7 +486,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afftfilt = {
@@ -496,7 +494,9 @@  const AVFilter ff_af_afftfilt = {
     .priv_size       = sizeof(AFFTFiltContext),
     .priv_class      = &afftfilt_class,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .activate        = activate,
     .query_formats   = query_formats,
     .uninit          = uninit,
diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
index e9cc4738fd..9395f7bf9d 100644
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -146,7 +146,6 @@  static const AVFilterPad avfilter_af_aformat_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_aformat_outputs[] = {
@@ -154,7 +153,6 @@  static const AVFilterPad avfilter_af_aformat_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aformat = {
@@ -166,5 +164,7 @@  const AVFilter ff_af_aformat = {
     .priv_size     = sizeof(AFormatContext),
     .priv_class    = &aformat_class,
     .inputs        = avfilter_af_aformat_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_aformat_inputs),
     .outputs       = avfilter_af_aformat_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_aformat_outputs),
 };
diff --git a/libavfilter/af_afreqshift.c b/libavfilter/af_afreqshift.c
index 85a1e65a96..9fcccabf13 100644
--- a/libavfilter/af_afreqshift.c
+++ b/libavfilter/af_afreqshift.c
@@ -379,7 +379,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -387,7 +386,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afreqshift = {
@@ -398,7 +396,9 @@  const AVFilter ff_af_afreqshift = {
     .priv_class      = &afreqshift_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = ff_filter_process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
@@ -420,7 +420,9 @@  const AVFilter ff_af_aphaseshift = {
     .priv_class      = &aphaseshift_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = ff_filter_process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_afwtdn.c b/libavfilter/af_afwtdn.c
index a23bb902ea..48ebafc744 100644
--- a/libavfilter/af_afwtdn.c
+++ b/libavfilter/af_afwtdn.c
@@ -1323,7 +1323,6 @@  static const AVFilterPad inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1332,7 +1331,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afwtdn = {
@@ -1344,7 +1342,9 @@  const AVFilter ff_af_afwtdn = {
     .activate        = activate,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c
index 3c858021d1..b7ef6c697f 100644
--- a/libavfilter/af_agate.c
+++ b/libavfilter/af_agate.c
@@ -248,7 +248,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = agate_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -256,7 +255,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_agate = {
@@ -266,7 +264,9 @@  const AVFilter ff_af_agate = {
     .priv_size      = sizeof(AudioGateContext),
     .priv_class     = &agate_class,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = ff_filter_process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
@@ -424,7 +424,6 @@  static const AVFilterPad sidechaingate_inputs[] = {
         .name           = "sidechain",
         .type           = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad sidechaingate_outputs[] = {
@@ -433,7 +432,6 @@  static const AVFilterPad sidechaingate_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = scconfig_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_sidechaingate = {
@@ -445,7 +443,9 @@  const AVFilter ff_af_sidechaingate = {
     .activate       = activate,
     .uninit         = uninit,
     .inputs         = sidechaingate_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(sidechaingate_inputs),
     .outputs        = sidechaingate_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(sidechaingate_outputs),
     .process_command = ff_filter_process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c
index 6ac39872ef..3875f144b2 100644
--- a/libavfilter/af_aiir.c
+++ b/libavfilter/af_aiir.c
@@ -1528,7 +1528,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(AudioIIRContext, x)
@@ -1585,6 +1584,7 @@  const AVFilter ff_af_aiir = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS |
                      AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/af_alimiter.c b/libavfilter/af_alimiter.c
index 30f1a4cba5..8c43785bb0 100644
--- a/libavfilter/af_alimiter.c
+++ b/libavfilter/af_alimiter.c
@@ -350,7 +350,6 @@  static const AVFilterPad alimiter_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad alimiter_outputs[] = {
@@ -358,7 +357,6 @@  static const AVFilterPad alimiter_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_alimiter = {
@@ -370,5 +368,7 @@  const AVFilter ff_af_alimiter = {
     .uninit         = uninit,
     .query_formats  = query_formats,
     .inputs         = alimiter_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(alimiter_inputs),
     .outputs        = alimiter_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(alimiter_outputs),
 };
diff --git a/libavfilter/af_amerge.c b/libavfilter/af_amerge.c
index 2e45b7c277..3c04438dac 100644
--- a/libavfilter/af_amerge.c
+++ b/libavfilter/af_amerge.c
@@ -344,7 +344,6 @@  static const AVFilterPad amerge_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_amerge = {
@@ -358,6 +357,7 @@  const AVFilter ff_af_amerge = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = amerge_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(amerge_outputs),
     .priv_class    = &amerge_class,
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index 2296b49243..04374db146 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -634,7 +634,6 @@  static const AVFilterPad avfilter_af_amix_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_amix = {
@@ -648,6 +647,7 @@  const AVFilter ff_af_amix = {
     .query_formats  = query_formats,
     .inputs         = NULL,
     .outputs        = avfilter_af_amix_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_amix_outputs),
     .process_command = process_command,
     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_amultiply.c b/libavfilter/af_amultiply.c
index b50bbfb6ce..da78d19c59 100644
--- a/libavfilter/af_amultiply.c
+++ b/libavfilter/af_amultiply.c
@@ -192,7 +192,6 @@  static const AVFilterPad inputs[] = {
         .name = "multiply1",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -201,7 +200,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_amultiply = {
@@ -213,5 +211,7 @@  const AVFilter ff_af_amultiply = {
     .activate       = activate,
     .query_formats  = query_formats,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_anequalizer.c b/libavfilter/af_anequalizer.c
index faa0e2a230..f61ee6c648 100644
--- a/libavfilter/af_anequalizer.c
+++ b/libavfilter/af_anequalizer.c
@@ -761,7 +761,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_anequalizer = {
@@ -773,6 +772,7 @@  const AVFilter ff_af_anequalizer = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = NULL,
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS |
diff --git a/libavfilter/af_anlmdn.c b/libavfilter/af_anlmdn.c
index 05e84282f0..ac117ccd9d 100644
--- a/libavfilter/af_anlmdn.c
+++ b/libavfilter/af_anlmdn.c
@@ -400,7 +400,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -410,7 +409,6 @@  static const AVFilterPad outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_anlmdn = {
@@ -421,7 +419,9 @@  const AVFilter ff_af_anlmdn = {
     .priv_class    = &anlmdn_class,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c
index 26df40107f..510751463a 100644
--- a/libavfilter/af_anlms.c
+++ b/libavfilter/af_anlms.c
@@ -301,7 +301,6 @@  static const AVFilterPad inputs[] = {
         .name = "desired",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -310,7 +309,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_anlms = {
@@ -323,7 +321,9 @@  const AVFilter ff_af_anlms = {
     .activate       = activate,
     .query_formats  = query_formats,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags          = AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/af_anull.c b/libavfilter/af_anull.c
index 74f915778f..eda47d7296 100644
--- a/libavfilter/af_anull.c
+++ b/libavfilter/af_anull.c
@@ -32,7 +32,6 @@  static const AVFilterPad avfilter_af_anull_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_anull_outputs[] = {
@@ -40,12 +39,13 @@  static const AVFilterPad avfilter_af_anull_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_anull = {
     .name          = "anull",
     .description   = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."),
     .inputs        = avfilter_af_anull_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_anull_inputs),
     .outputs       = avfilter_af_anull_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_anull_outputs),
 };
diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c
index 8628c0c2e2..bd9329a013 100644
--- a/libavfilter/af_apad.c
+++ b/libavfilter/af_apad.c
@@ -155,7 +155,6 @@  static const AVFilterPad apad_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad apad_outputs[] = {
@@ -165,7 +164,6 @@  static const AVFilterPad apad_outputs[] = {
         .config_props  = config_output,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_apad = {
@@ -174,7 +172,9 @@  const AVFilter ff_af_apad = {
     .init          = init,
     .priv_size     = sizeof(APadContext),
     .inputs        = apad_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(apad_inputs),
     .outputs       = apad_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(apad_outputs),
     .priv_class    = &apad_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_aphaser.c b/libavfilter/af_aphaser.c
index e033a6d904..588d304552 100644
--- a/libavfilter/af_aphaser.c
+++ b/libavfilter/af_aphaser.c
@@ -278,7 +278,6 @@  static const AVFilterPad aphaser_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aphaser_outputs[] = {
@@ -287,7 +286,6 @@  static const AVFilterPad aphaser_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aphaser = {
@@ -298,6 +296,8 @@  const AVFilter ff_af_aphaser = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = aphaser_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aphaser_inputs),
     .outputs       = aphaser_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aphaser_outputs),
     .priv_class    = &aphaser_class,
 };
diff --git a/libavfilter/af_apulsator.c b/libavfilter/af_apulsator.c
index 56ff4579d6..eb61e5f173 100644
--- a/libavfilter/af_apulsator.c
+++ b/libavfilter/af_apulsator.c
@@ -236,7 +236,6 @@  static const AVFilterPad inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -244,7 +243,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_apulsator = {
@@ -254,5 +252,7 @@  const AVFilter ff_af_apulsator = {
     .priv_class    = &apulsator_class,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index 1127ad2718..4fd5c1287c 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -329,7 +329,6 @@  static const AVFilterPad aresample_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aresample_outputs[] = {
@@ -339,7 +338,6 @@  static const AVFilterPad aresample_outputs[] = {
         .request_frame = request_frame,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aresample = {
@@ -351,5 +349,7 @@  const AVFilter ff_af_aresample = {
     .priv_size     = sizeof(AResampleContext),
     .priv_class    = &aresample_class,
     .inputs        = aresample_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(aresample_inputs),
     .outputs       = aresample_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aresample_outputs),
 };
diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c
index 0c70a32271..d081209266 100644
--- a/libavfilter/af_arnndn.c
+++ b/libavfilter/af_arnndn.c
@@ -1596,7 +1596,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1604,7 +1603,6 @@  static const AVFilterPad outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(AudioRNNContext, x)
@@ -1629,7 +1627,9 @@  const AVFilter ff_af_arnndn = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c
index 9987eff8a2..82d7cc7beb 100644
--- a/libavfilter/af_asetnsamples.c
+++ b/libavfilter/af_asetnsamples.c
@@ -106,7 +106,6 @@  static const AVFilterPad asetnsamples_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad asetnsamples_outputs[] = {
@@ -114,7 +113,6 @@  static const AVFilterPad asetnsamples_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asetnsamples = {
@@ -123,6 +121,8 @@  const AVFilter ff_af_asetnsamples = {
     .priv_size   = sizeof(ASNSContext),
     .priv_class  = &asetnsamples_class,
     .inputs      = asetnsamples_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(asetnsamples_inputs),
     .outputs     = asetnsamples_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(asetnsamples_outputs),
     .activate    = activate,
 };
diff --git a/libavfilter/af_asetrate.c b/libavfilter/af_asetrate.c
index f89185d936..379654c0d2 100644
--- a/libavfilter/af_asetrate.c
+++ b/libavfilter/af_asetrate.c
@@ -94,7 +94,6 @@  static const AVFilterPad asetrate_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad asetrate_outputs[] = {
@@ -103,7 +102,6 @@  static const AVFilterPad asetrate_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asetrate = {
@@ -113,6 +111,8 @@  const AVFilter ff_af_asetrate = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ASetRateContext),
     .inputs        = asetrate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(asetrate_inputs),
     .outputs       = asetrate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(asetrate_outputs),
     .priv_class    = &asetrate_class,
 };
diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c
index 72d795f8ee..53192e62df 100644
--- a/libavfilter/af_ashowinfo.c
+++ b/libavfilter/af_ashowinfo.c
@@ -243,7 +243,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -251,7 +250,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_ashowinfo = {
@@ -260,5 +258,7 @@  const AVFilter ff_af_ashowinfo = {
     .priv_size   = sizeof(AShowInfoContext),
     .uninit      = uninit,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_asoftclip.c b/libavfilter/af_asoftclip.c
index 17361ba3a2..942bb02456 100644
--- a/libavfilter/af_asoftclip.c
+++ b/libavfilter/af_asoftclip.c
@@ -463,7 +463,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -471,7 +470,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asoftclip = {
@@ -481,7 +479,9 @@  const AVFilter ff_af_asoftclip = {
     .priv_size      = sizeof(ASoftClipContext),
     .priv_class     = &asoftclip_class,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .uninit         = uninit,
     .process_command = ff_filter_process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
diff --git a/libavfilter/af_asr.c b/libavfilter/af_asr.c
index b34cdd38ee..fd277c033d 100644
--- a/libavfilter/af_asr.c
+++ b/libavfilter/af_asr.c
@@ -156,7 +156,6 @@  static const AVFilterPad asr_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad asr_outputs[] = {
@@ -164,7 +163,6 @@  static const AVFilterPad asr_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asr = {
@@ -176,5 +174,7 @@  const AVFilter ff_af_asr = {
     .uninit        = asr_uninit,
     .query_formats = query_formats,
     .inputs        = asr_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(asr_inputs),
     .outputs       = asr_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(asr_outputs),
 };
diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c
index 23a5785d5a..0c821ac67a 100644
--- a/libavfilter/af_astats.c
+++ b/libavfilter/af_astats.c
@@ -827,7 +827,6 @@  static const AVFilterPad astats_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad astats_outputs[] = {
@@ -836,7 +835,6 @@  static const AVFilterPad astats_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_astats = {
@@ -847,6 +845,8 @@  const AVFilter ff_af_astats = {
     .priv_class    = &astats_class,
     .uninit        = uninit,
     .inputs        = astats_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(astats_inputs),
     .outputs       = astats_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(astats_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/af_asubboost.c b/libavfilter/af_asubboost.c
index f36ce81552..f5f88c0ba4 100644
--- a/libavfilter/af_asubboost.c
+++ b/libavfilter/af_asubboost.c
@@ -233,7 +233,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -241,7 +240,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asubboost = {
@@ -252,7 +250,9 @@  const AVFilter ff_af_asubboost = {
     .priv_class     = &asubboost_class,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                        AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_asupercut.c b/libavfilter/af_asupercut.c
index 54921cf4c3..bbc341a310 100644
--- a/libavfilter/af_asupercut.c
+++ b/libavfilter/af_asupercut.c
@@ -357,7 +357,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -365,7 +364,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asupercut = {
@@ -376,7 +374,9 @@  const AVFilter ff_af_asupercut = {
     .priv_class      = &asupercut_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
@@ -399,7 +399,9 @@  const AVFilter ff_af_asubcut = {
     .priv_class      = &asubcut_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
@@ -424,7 +426,9 @@  const AVFilter ff_af_asuperpass = {
     .priv_class      = &asuperpass_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
@@ -441,7 +445,9 @@  const AVFilter ff_af_asuperstop = {
     .priv_class      = &asuperstop_class,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
                        AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c
index 80a33c43ed..d410ac9513 100644
--- a/libavfilter/af_atempo.c
+++ b/libavfilter/af_atempo.c
@@ -1190,7 +1190,6 @@  static const AVFilterPad atempo_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad atempo_outputs[] = {
@@ -1199,7 +1198,6 @@  static const AVFilterPad atempo_outputs[] = {
         .request_frame = request_frame,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_atempo = {
@@ -1212,5 +1210,7 @@  const AVFilter ff_af_atempo = {
     .priv_size       = sizeof(ATempoContext),
     .priv_class      = &atempo_class,
     .inputs          = atempo_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(atempo_inputs),
     .outputs         = atempo_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(atempo_outputs),
 };
diff --git a/libavfilter/af_axcorrelate.c b/libavfilter/af_axcorrelate.c
index cec39dee76..04f76f8ef2 100644
--- a/libavfilter/af_axcorrelate.c
+++ b/libavfilter/af_axcorrelate.c
@@ -339,7 +339,6 @@  static const AVFilterPad inputs[] = {
         .name = "axcorrelate1",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -348,7 +347,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
@@ -373,5 +371,7 @@  const AVFilter ff_af_axcorrelate = {
     .activate       = activate,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c
index 0baf5541fd..efef5e8115 100644
--- a/libavfilter/af_biquads.c
+++ b/libavfilter/af_biquads.c
@@ -853,7 +853,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -862,7 +861,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(BiquadsContext, x)
@@ -886,7 +884,9 @@  const AVFilter ff_af_##name_ = {                               \
     .uninit        = uninit,                             \
     .query_formats = query_formats,                      \
     .inputs        = inputs,                             \
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),           \
     .outputs       = outputs,                            \
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),          \
     .priv_class    = &name_##_class,                     \
     .process_command = process_command,                  \
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, \
diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c
index 7b9958325f..9552649ceb 100644
--- a/libavfilter/af_bs2b.c
+++ b/libavfilter/af_bs2b.c
@@ -199,7 +199,6 @@  static const AVFilterPad bs2b_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad bs2b_outputs[] = {
@@ -208,7 +207,6 @@  static const AVFilterPad bs2b_outputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .config_props   = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_bs2b = {
@@ -220,5 +218,7 @@  const AVFilter ff_af_bs2b = {
     .init           = init,
     .uninit         = uninit,
     .inputs         = bs2b_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(bs2b_inputs),
     .outputs        = bs2b_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(bs2b_outputs),
 };
diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c
index 3cdf8b2bd8..6fa2335203 100644
--- a/libavfilter/af_channelmap.c
+++ b/libavfilter/af_channelmap.c
@@ -387,7 +387,6 @@  static const AVFilterPad avfilter_af_channelmap_inputs[] = {
         .config_props   = channelmap_config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_channelmap_outputs[] = {
@@ -395,7 +394,6 @@  static const AVFilterPad avfilter_af_channelmap_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO
     },
-    { NULL }
 };
 
 const AVFilter ff_af_channelmap = {
@@ -406,5 +404,7 @@  const AVFilter ff_af_channelmap = {
     .priv_size     = sizeof(ChannelMapContext),
     .priv_class    = &channelmap_class,
     .inputs        = avfilter_af_channelmap_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_channelmap_inputs),
     .outputs       = avfilter_af_channelmap_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_channelmap_outputs),
 };
diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c
index 3bd3355d88..63a86e8106 100644
--- a/libavfilter/af_channelsplit.c
+++ b/libavfilter/af_channelsplit.c
@@ -165,7 +165,6 @@  static const AVFilterPad avfilter_af_channelsplit_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_channelsplit = {
@@ -176,6 +175,7 @@  const AVFilter ff_af_channelsplit = {
     .init           = init,
     .query_formats  = query_formats,
     .inputs         = avfilter_af_channelsplit_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(avfilter_af_channelsplit_inputs),
     .outputs        = NULL,
     .flags          = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
diff --git a/libavfilter/af_chorus.c b/libavfilter/af_chorus.c
index 72e684bd3a..7d636af778 100644
--- a/libavfilter/af_chorus.c
+++ b/libavfilter/af_chorus.c
@@ -356,7 +356,6 @@  static const AVFilterPad chorus_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad chorus_outputs[] = {
@@ -366,7 +365,6 @@  static const AVFilterPad chorus_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_chorus = {
@@ -378,5 +376,7 @@  const AVFilter ff_af_chorus = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = chorus_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(chorus_inputs),
     .outputs       = chorus_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(chorus_outputs),
 };
diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c
index 62d9c2e941..0b1319ce8a 100644
--- a/libavfilter/af_compand.c
+++ b/libavfilter/af_compand.c
@@ -571,7 +571,6 @@  static const AVFilterPad compand_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad compand_outputs[] = {
@@ -581,7 +580,6 @@  static const AVFilterPad compand_outputs[] = {
         .config_props  = config_output,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 
@@ -595,5 +593,7 @@  const AVFilter ff_af_compand = {
     .init           = init,
     .uninit         = uninit,
     .inputs         = compand_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(compand_inputs),
     .outputs        = compand_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(compand_outputs),
 };
diff --git a/libavfilter/af_compensationdelay.c b/libavfilter/af_compensationdelay.c
index f2e0dcd467..88f3f6eaaa 100644
--- a/libavfilter/af_compensationdelay.c
+++ b/libavfilter/af_compensationdelay.c
@@ -175,7 +175,6 @@  static const AVFilterPad compensationdelay_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad compensationdelay_outputs[] = {
@@ -183,7 +182,6 @@  static const AVFilterPad compensationdelay_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_compensationdelay = {
@@ -194,5 +192,7 @@  const AVFilter ff_af_compensationdelay = {
     .priv_class    = &compensationdelay_class,
     .uninit        = uninit,
     .inputs        = compensationdelay_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(compensationdelay_inputs),
     .outputs       = compensationdelay_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(compensationdelay_outputs),
 };
diff --git a/libavfilter/af_crossfeed.c b/libavfilter/af_crossfeed.c
index 7ad9c4f483..e37bfe45f5 100644
--- a/libavfilter/af_crossfeed.c
+++ b/libavfilter/af_crossfeed.c
@@ -164,7 +164,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -172,7 +171,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_crossfeed = {
@@ -182,7 +180,9 @@  const AVFilter ff_af_crossfeed = {
     .priv_size      = sizeof(CrossfeedContext),
     .priv_class     = &crossfeed_class,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = process_command,
 };
diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c
index f4ad326ede..71b1d10f07 100644
--- a/libavfilter/af_crystalizer.c
+++ b/libavfilter/af_crystalizer.c
@@ -445,7 +445,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -453,7 +452,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_crystalizer = {
@@ -464,7 +462,9 @@  const AVFilter ff_af_crystalizer = {
     .priv_class     = &crystalizer_class,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                       AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/af_dcshift.c b/libavfilter/af_dcshift.c
index 1384ad87bf..e2e12a218d 100644
--- a/libavfilter/af_dcshift.c
+++ b/libavfilter/af_dcshift.c
@@ -149,7 +149,6 @@  static const AVFilterPad dcshift_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad dcshift_outputs[] = {
@@ -157,7 +156,6 @@  static const AVFilterPad dcshift_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_dcshift = {
@@ -168,6 +166,8 @@  const AVFilter ff_af_dcshift = {
     .priv_class     = &dcshift_class,
     .init           = init,
     .inputs         = dcshift_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(dcshift_inputs),
     .outputs        = dcshift_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(dcshift_outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/af_deesser.c b/libavfilter/af_deesser.c
index e05ee9f10b..e4455c81b1 100644
--- a/libavfilter/af_deesser.c
+++ b/libavfilter/af_deesser.c
@@ -220,7 +220,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -228,7 +227,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_deesser = {
@@ -239,6 +237,8 @@  const AVFilter ff_af_deesser = {
     .priv_class    = &deesser_class,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c
index 58932fe6c5..9e046f1a6a 100644
--- a/libavfilter/af_drmeter.c
+++ b/libavfilter/af_drmeter.c
@@ -214,7 +214,6 @@  static const AVFilterPad drmeter_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad drmeter_outputs[] = {
@@ -223,7 +222,6 @@  static const AVFilterPad drmeter_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_drmeter = {
@@ -234,5 +232,7 @@  const AVFilter ff_af_drmeter = {
     .priv_class    = &drmeter_class,
     .uninit        = uninit,
     .inputs        = drmeter_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(drmeter_inputs),
     .outputs       = drmeter_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(drmeter_outputs),
 };
diff --git a/libavfilter/af_dynaudnorm.c b/libavfilter/af_dynaudnorm.c
index 01c99788af..021e41ee41 100644
--- a/libavfilter/af_dynaudnorm.c
+++ b/libavfilter/af_dynaudnorm.c
@@ -857,7 +857,6 @@  static const AVFilterPad avfilter_af_dynaudnorm_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_dynaudnorm_outputs[] = {
@@ -865,7 +864,6 @@  static const AVFilterPad avfilter_af_dynaudnorm_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_dynaudnorm = {
@@ -877,7 +875,9 @@  const AVFilter ff_af_dynaudnorm = {
     .uninit        = uninit,
     .activate      = activate,
     .inputs        = avfilter_af_dynaudnorm_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_dynaudnorm_inputs),
     .outputs       = avfilter_af_dynaudnorm_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_dynaudnorm_outputs),
     .priv_class    = &dynaudnorm_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = process_command,
diff --git a/libavfilter/af_earwax.c b/libavfilter/af_earwax.c
index a5a7e6a5d2..7133c3defb 100644
--- a/libavfilter/af_earwax.c
+++ b/libavfilter/af_earwax.c
@@ -220,7 +220,6 @@  static const AVFilterPad earwax_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad earwax_outputs[] = {
@@ -228,7 +227,6 @@  static const AVFilterPad earwax_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_earwax = {
@@ -238,5 +236,7 @@  const AVFilter ff_af_earwax = {
     .priv_size      = sizeof(EarwaxContext),
     .uninit         = uninit,
     .inputs         = earwax_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(earwax_inputs),
     .outputs        = earwax_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(earwax_outputs),
 };
diff --git a/libavfilter/af_extrastereo.c b/libavfilter/af_extrastereo.c
index 0555aa6610..3b3f4d1aa4 100644
--- a/libavfilter/af_extrastereo.c
+++ b/libavfilter/af_extrastereo.c
@@ -109,7 +109,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -117,7 +116,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_extrastereo = {
@@ -127,7 +125,9 @@  const AVFilter ff_af_extrastereo = {
     .priv_size      = sizeof(ExtraStereoContext),
     .priv_class     = &extrastereo_class,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/af_firequalizer.c b/libavfilter/af_firequalizer.c
index 77de69e3ef..bc3f918c6e 100644
--- a/libavfilter/af_firequalizer.c
+++ b/libavfilter/af_firequalizer.c
@@ -957,7 +957,6 @@  static const AVFilterPad firequalizer_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad firequalizer_outputs[] = {
@@ -966,7 +965,6 @@  static const AVFilterPad firequalizer_outputs[] = {
         .request_frame  = request_frame,
         .type           = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_firequalizer = {
@@ -977,6 +975,8 @@  const AVFilter ff_af_firequalizer = {
     .process_command    = process_command,
     .priv_size          = sizeof(FIREqualizerContext),
     .inputs             = firequalizer_inputs,
+    .nb_inputs          = FF_ARRAY_ELEMS(firequalizer_inputs),
     .outputs            = firequalizer_outputs,
+    .nb_outputs         = FF_ARRAY_ELEMS(firequalizer_outputs),
     .priv_class         = &firequalizer_class,
 };
diff --git a/libavfilter/af_flanger.c b/libavfilter/af_flanger.c
index 6984ab12d3..183e5d39ed 100644
--- a/libavfilter/af_flanger.c
+++ b/libavfilter/af_flanger.c
@@ -222,7 +222,6 @@  static const AVFilterPad flanger_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad flanger_outputs[] = {
@@ -230,7 +229,6 @@  static const AVFilterPad flanger_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_flanger = {
@@ -242,5 +240,7 @@  const AVFilter ff_af_flanger = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = flanger_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(flanger_inputs),
     .outputs       = flanger_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(flanger_outputs),
 };
diff --git a/libavfilter/af_haas.c b/libavfilter/af_haas.c
index b1a207f808..d339491421 100644
--- a/libavfilter/af_haas.c
+++ b/libavfilter/af_haas.c
@@ -205,7 +205,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -213,7 +212,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_haas = {
@@ -224,5 +222,7 @@  const AVFilter ff_af_haas = {
     .priv_class     = &haas_class,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c
index 144c0d31ed..f5eacc127b 100644
--- a/libavfilter/af_hdcd.c
+++ b/libavfilter/af_hdcd.c
@@ -1762,7 +1762,6 @@  static const AVFilterPad avfilter_af_hdcd_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_hdcd_outputs[] = {
@@ -1770,7 +1769,6 @@  static const AVFilterPad avfilter_af_hdcd_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_hdcd = {
@@ -1782,5 +1780,7 @@  const AVFilter ff_af_hdcd = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_hdcd_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_hdcd_inputs),
     .outputs       = avfilter_af_hdcd_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_hdcd_outputs),
 };
diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c
index 5e8fadb6cd..9b2f62c379 100644
--- a/libavfilter/af_headphone.c
+++ b/libavfilter/af_headphone.c
@@ -762,7 +762,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_headphone = {
@@ -776,5 +775,6 @@  const AVFilter ff_af_headphone = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c
index 6a4b449021..269f34a043 100644
--- a/libavfilter/af_join.c
+++ b/libavfilter/af_join.c
@@ -536,7 +536,6 @@  static const AVFilterPad avfilter_af_join_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = join_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_join = {
@@ -551,5 +550,6 @@  const AVFilter ff_af_join = {
     .query_formats  = join_query_formats,
     .inputs         = NULL,
     .outputs        = avfilter_af_join_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(avfilter_af_join_outputs),
     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_ladspa.c b/libavfilter/af_ladspa.c
index 4060251670..d9e55bfc8f 100644
--- a/libavfilter/af_ladspa.c
+++ b/libavfilter/af_ladspa.c
@@ -788,7 +788,6 @@  static const AVFilterPad ladspa_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_ladspa = {
@@ -802,5 +801,6 @@  const AVFilter ff_af_ladspa = {
     .process_command = process_command,
     .inputs        = 0,
     .outputs       = ladspa_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ladspa_outputs),
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c
index a07e8a3c93..f57e51990b 100644
--- a/libavfilter/af_loudnorm.c
+++ b/libavfilter/af_loudnorm.c
@@ -905,7 +905,6 @@  static const AVFilterPad avfilter_af_loudnorm_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_loudnorm_outputs[] = {
@@ -914,7 +913,6 @@  static const AVFilterPad avfilter_af_loudnorm_outputs[] = {
         .request_frame = request_frame,
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_loudnorm = {
@@ -926,5 +924,7 @@  const AVFilter ff_af_loudnorm = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = avfilter_af_loudnorm_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_loudnorm_inputs),
     .outputs       = avfilter_af_loudnorm_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_loudnorm_outputs),
 };
diff --git a/libavfilter/af_lv2.c b/libavfilter/af_lv2.c
index 28b729691d..71677da07c 100644
--- a/libavfilter/af_lv2.c
+++ b/libavfilter/af_lv2.c
@@ -584,7 +584,6 @@  static const AVFilterPad lv2_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_lv2 = {
@@ -597,5 +596,6 @@  const AVFilter ff_af_lv2 = {
     .query_formats = query_formats,
     .inputs        = 0,
     .outputs       = lv2_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(lv2_outputs),
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/af_mcompand.c b/libavfilter/af_mcompand.c
index 08d93f8c6a..27793e5967 100644
--- a/libavfilter/af_mcompand.c
+++ b/libavfilter/af_mcompand.c
@@ -651,7 +651,6 @@  static const AVFilterPad mcompand_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad mcompand_outputs[] = {
@@ -661,7 +660,6 @@  static const AVFilterPad mcompand_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 
@@ -674,5 +672,7 @@  const AVFilter ff_af_mcompand = {
     .priv_class     = &mcompand_class,
     .uninit         = uninit,
     .inputs         = mcompand_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(mcompand_inputs),
     .outputs        = mcompand_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(mcompand_outputs),
 };
diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c
index 7ae18e9bfe..116be53c4f 100644
--- a/libavfilter/af_pan.c
+++ b/libavfilter/af_pan.c
@@ -437,7 +437,6 @@  static const AVFilterPad pan_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad pan_outputs[] = {
@@ -445,7 +444,6 @@  static const AVFilterPad pan_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_pan = {
@@ -457,5 +455,7 @@  const AVFilter ff_af_pan = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = pan_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(pan_inputs),
     .outputs       = pan_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(pan_outputs),
 };
diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c
index fd642297f8..aa56ff4a71 100644
--- a/libavfilter/af_replaygain.c
+++ b/libavfilter/af_replaygain.c
@@ -592,7 +592,6 @@  static const AVFilterPad replaygain_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad replaygain_outputs[] = {
@@ -600,7 +599,6 @@  static const AVFilterPad replaygain_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_replaygain = {
@@ -610,5 +608,7 @@  const AVFilter ff_af_replaygain = {
     .uninit        = uninit,
     .priv_size     = sizeof(ReplayGainContext),
     .inputs        = replaygain_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(replaygain_inputs),
     .outputs       = replaygain_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(replaygain_outputs),
 };
diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c
index bfacbcd245..cff0f85797 100644
--- a/libavfilter/af_rubberband.c
+++ b/libavfilter/af_rubberband.c
@@ -223,7 +223,6 @@  static const AVFilterPad rubberband_inputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad rubberband_outputs[] = {
@@ -231,7 +230,6 @@  static const AVFilterPad rubberband_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_rubberband = {
@@ -243,6 +241,8 @@  const AVFilter ff_af_rubberband = {
     .uninit        = uninit,
     .activate      = activate,
     .inputs        = rubberband_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(rubberband_inputs),
     .outputs       = rubberband_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(rubberband_outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/af_sidechaincompress.c b/libavfilter/af_sidechaincompress.c
index 71e27d4530..1f1a3a1623 100644
--- a/libavfilter/af_sidechaincompress.c
+++ b/libavfilter/af_sidechaincompress.c
@@ -374,7 +374,6 @@  static const AVFilterPad sidechaincompress_inputs[] = {
         .name           = "sidechain",
         .type           = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad sidechaincompress_outputs[] = {
@@ -383,7 +382,6 @@  static const AVFilterPad sidechaincompress_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_sidechaincompress = {
@@ -395,7 +393,9 @@  const AVFilter ff_af_sidechaincompress = {
     .activate       = activate,
     .uninit         = uninit,
     .inputs         = sidechaincompress_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(sidechaincompress_inputs),
     .outputs        = sidechaincompress_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(sidechaincompress_outputs),
     .process_command = process_command,
 };
 #endif  /* CONFIG_SIDECHAINCOMPRESS_FILTER */
@@ -470,7 +470,6 @@  static const AVFilterPad acompressor_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = acompressor_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad acompressor_outputs[] = {
@@ -479,7 +478,6 @@  static const AVFilterPad acompressor_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = compressor_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acompressor = {
@@ -489,7 +487,9 @@  const AVFilter ff_af_acompressor = {
     .priv_class     = &acompressor_class,
     .query_formats  = acompressor_query_formats,
     .inputs         = acompressor_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(acompressor_inputs),
     .outputs        = acompressor_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(acompressor_outputs),
     .process_command = process_command,
 };
 #endif  /* CONFIG_ACOMPRESSOR_FILTER */
diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c
index 53f54d1834..82bc7325f7 100644
--- a/libavfilter/af_silencedetect.c
+++ b/libavfilter/af_silencedetect.c
@@ -247,7 +247,6 @@  static const AVFilterPad silencedetect_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad silencedetect_outputs[] = {
@@ -255,7 +254,6 @@  static const AVFilterPad silencedetect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_silencedetect = {
@@ -265,6 +263,8 @@  const AVFilter ff_af_silencedetect = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = silencedetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(silencedetect_inputs),
     .outputs       = silencedetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(silencedetect_outputs),
     .priv_class    = &silencedetect_class,
 };
diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c
index 9d6d683688..8ba373dc15 100644
--- a/libavfilter/af_silenceremove.c
+++ b/libavfilter/af_silenceremove.c
@@ -936,7 +936,6 @@  static const AVFilterPad silenceremove_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad silenceremove_outputs[] = {
@@ -945,7 +944,6 @@  static const AVFilterPad silenceremove_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_silenceremove = {
@@ -957,5 +955,7 @@  const AVFilter ff_af_silenceremove = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = silenceremove_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(silenceremove_inputs),
     .outputs       = silenceremove_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(silenceremove_outputs),
 };
diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c
index 1bffd57de9..42f7875a6a 100644
--- a/libavfilter/af_sofalizer.c
+++ b/libavfilter/af_sofalizer.c
@@ -1102,7 +1102,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1110,7 +1109,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_sofalizer = {
@@ -1123,6 +1121,8 @@  const AVFilter ff_af_sofalizer = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/af_speechnorm.c b/libavfilter/af_speechnorm.c
index d044177352..677d355540 100644
--- a/libavfilter/af_speechnorm.c
+++ b/libavfilter/af_speechnorm.c
@@ -555,7 +555,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -563,7 +562,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_speechnorm = {
@@ -575,6 +573,8 @@  const AVFilter ff_af_speechnorm = {
     .activate        = activate,
     .uninit          = uninit,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/af_stereotools.c b/libavfilter/af_stereotools.c
index d60fa55ccd..be743024d0 100644
--- a/libavfilter/af_stereotools.c
+++ b/libavfilter/af_stereotools.c
@@ -364,7 +364,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -372,7 +371,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_stereotools = {
@@ -383,7 +381,9 @@  const AVFilter ff_af_stereotools = {
     .priv_class     = &stereotools_class,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .process_command = process_command,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/af_stereowiden.c b/libavfilter/af_stereowiden.c
index 1fbb635841..27f516a46d 100644
--- a/libavfilter/af_stereowiden.c
+++ b/libavfilter/af_stereowiden.c
@@ -145,7 +145,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -153,7 +152,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_stereowiden = {
@@ -164,7 +162,9 @@  const AVFilter ff_af_stereowiden = {
     .priv_class     = &stereowiden_class,
     .uninit         = uninit,
     .inputs         = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/af_superequalizer.c b/libavfilter/af_superequalizer.c
index aa8b6376b0..eceba41482 100644
--- a/libavfilter/af_superequalizer.c
+++ b/libavfilter/af_superequalizer.c
@@ -335,7 +335,6 @@  static const AVFilterPad superequalizer_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad superequalizer_outputs[] = {
@@ -344,7 +343,6 @@  static const AVFilterPad superequalizer_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
@@ -384,5 +382,7 @@  const AVFilter ff_af_superequalizer = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = superequalizer_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(superequalizer_inputs),
     .outputs       = superequalizer_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(superequalizer_outputs),
 };
diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c
index 3fb7a1bbba..024864991a 100644
--- a/libavfilter/af_surround.c
+++ b/libavfilter/af_surround.c
@@ -1773,7 +1773,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1782,7 +1781,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_surround = {
@@ -1795,6 +1793,8 @@  const AVFilter ff_af_surround = {
     .uninit         = uninit,
     .activate       = activate,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .flags          = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/af_tremolo.c b/libavfilter/af_tremolo.c
index 8f9e310040..b87cad86d7 100644
--- a/libavfilter/af_tremolo.c
+++ b/libavfilter/af_tremolo.c
@@ -149,7 +149,6 @@  static const AVFilterPad avfilter_af_tremolo_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_tremolo_outputs[] = {
@@ -157,7 +156,6 @@  static const AVFilterPad avfilter_af_tremolo_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_tremolo = {
@@ -168,5 +166,7 @@  const AVFilter ff_af_tremolo = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_tremolo_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_tremolo_inputs),
     .outputs       = avfilter_af_tremolo_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_tremolo_outputs),
 };
diff --git a/libavfilter/af_vibrato.c b/libavfilter/af_vibrato.c
index fe4d194531..cd8a1156fe 100644
--- a/libavfilter/af_vibrato.c
+++ b/libavfilter/af_vibrato.c
@@ -187,7 +187,6 @@  static const AVFilterPad avfilter_af_vibrato_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_vibrato_outputs[] = {
@@ -195,7 +194,6 @@  static const AVFilterPad avfilter_af_vibrato_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_vibrato = {
@@ -206,5 +204,7 @@  const AVFilter ff_af_vibrato = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_af_vibrato_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_af_vibrato_inputs),
     .outputs       = avfilter_af_vibrato_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_af_vibrato_outputs),
 };
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 844ddbeff7..b746a76e80 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -465,7 +465,6 @@  static const AVFilterPad avfilter_af_volume_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_volume_outputs[] = {
@@ -474,7 +473,6 @@  static const AVFilterPad avfilter_af_volume_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_volume = {
@@ -486,7 +484,9 @@  const AVFilter ff_af_volume = {
     .init           = init,
     .uninit         = uninit,
     .inputs         = avfilter_af_volume_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_af_volume_inputs),
     .outputs        = avfilter_af_volume_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_af_volume_outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = process_command,
 };
diff --git a/libavfilter/af_volumedetect.c b/libavfilter/af_volumedetect.c
index 61af21797c..e15361e4bc 100644
--- a/libavfilter/af_volumedetect.c
+++ b/libavfilter/af_volumedetect.c
@@ -144,7 +144,6 @@  static const AVFilterPad volumedetect_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad volumedetect_outputs[] = {
@@ -152,7 +151,6 @@  static const AVFilterPad volumedetect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_volumedetect = {
@@ -162,5 +160,7 @@  const AVFilter ff_af_volumedetect = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = volumedetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(volumedetect_inputs),
     .outputs       = volumedetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(volumedetect_outputs),
 };
diff --git a/libavfilter/asink_anullsink.c b/libavfilter/asink_anullsink.c
index dce0204839..e0cc13630d 100644
--- a/libavfilter/asink_anullsink.c
+++ b/libavfilter/asink_anullsink.c
@@ -34,7 +34,6 @@  static const AVFilterPad avfilter_asink_anullsink_inputs[] = {
         .type           = AVMEDIA_TYPE_AUDIO,
         .filter_frame   = null_filter_frame,
     },
-    { NULL },
 };
 
 const AVFilter ff_asink_anullsink = {
@@ -42,5 +41,6 @@  const AVFilter ff_asink_anullsink = {
     .description = NULL_IF_CONFIG_SMALL("Do absolutely nothing with the input audio."),
     .priv_size   = 0,
     .inputs      = avfilter_asink_anullsink_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_asink_anullsink_inputs),
     .outputs     = NULL,
 };
diff --git a/libavfilter/asrc_afirsrc.c b/libavfilter/asrc_afirsrc.c
index 0ede722ba1..54a2b0fa30 100644
--- a/libavfilter/asrc_afirsrc.c
+++ b/libavfilter/asrc_afirsrc.c
@@ -315,7 +315,6 @@  static const AVFilterPad afirsrc_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_afirsrc = {
@@ -327,5 +326,6 @@  const AVFilter ff_asrc_afirsrc = {
     .priv_size     = sizeof(AudioFIRSourceContext),
     .inputs        = NULL,
     .outputs       = afirsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(afirsrc_outputs),
     .priv_class    = &afirsrc_class,
 };
diff --git a/libavfilter/asrc_anoisesrc.c b/libavfilter/asrc_anoisesrc.c
index 0aab14b58f..1af82bd849 100644
--- a/libavfilter/asrc_anoisesrc.c
+++ b/libavfilter/asrc_anoisesrc.c
@@ -244,7 +244,6 @@  static const AVFilterPad anoisesrc_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_anoisesrc = {
@@ -255,5 +254,6 @@  const AVFilter ff_asrc_anoisesrc = {
     .inputs        = NULL,
     .activate      = activate,
     .outputs       = anoisesrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(anoisesrc_outputs),
     .priv_class    = &anoisesrc_class,
 };
diff --git a/libavfilter/asrc_anullsrc.c b/libavfilter/asrc_anullsrc.c
index 45d830e3a2..74b208276e 100644
--- a/libavfilter/asrc_anullsrc.c
+++ b/libavfilter/asrc_anullsrc.c
@@ -134,7 +134,6 @@  static const AVFilterPad avfilter_asrc_anullsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_anullsrc = {
@@ -145,6 +144,7 @@  const AVFilter ff_asrc_anullsrc = {
     .priv_size     = sizeof(ANullContext),
     .inputs        = NULL,
     .outputs       = avfilter_asrc_anullsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_asrc_anullsrc_outputs),
     .activate      = activate,
     .priv_class    = &anullsrc_class,
 };
diff --git a/libavfilter/asrc_flite.c b/libavfilter/asrc_flite.c
index 1478cc07fa..6095b3f972 100644
--- a/libavfilter/asrc_flite.c
+++ b/libavfilter/asrc_flite.c
@@ -271,7 +271,6 @@  static const AVFilterPad flite_outputs[] = {
         .config_props  = config_props,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_flite = {
@@ -283,5 +282,6 @@  const AVFilter ff_asrc_flite = {
     .priv_size     = sizeof(FliteContext),
     .inputs        = NULL,
     .outputs       = flite_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(flite_outputs),
     .priv_class    = &flite_class,
 };
diff --git a/libavfilter/asrc_hilbert.c b/libavfilter/asrc_hilbert.c
index e7d596ee46..b04bedcd5d 100644
--- a/libavfilter/asrc_hilbert.c
+++ b/libavfilter/asrc_hilbert.c
@@ -185,7 +185,6 @@  static const AVFilterPad hilbert_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_hilbert = {
@@ -197,5 +196,6 @@  const AVFilter ff_asrc_hilbert = {
     .priv_size     = sizeof(HilbertContext),
     .inputs        = NULL,
     .outputs       = hilbert_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(hilbert_outputs),
     .priv_class    = &hilbert_class,
 };
diff --git a/libavfilter/asrc_sinc.c b/libavfilter/asrc_sinc.c
index 5397d89c77..f7c002e48c 100644
--- a/libavfilter/asrc_sinc.c
+++ b/libavfilter/asrc_sinc.c
@@ -421,7 +421,6 @@  static const AVFilterPad sinc_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
@@ -454,4 +453,5 @@  const AVFilter ff_asrc_sinc = {
     .uninit        = uninit,
     .inputs        = NULL,
     .outputs       = sinc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(sinc_outputs),
 };
diff --git a/libavfilter/asrc_sine.c b/libavfilter/asrc_sine.c
index f75a5fc728..7b95efd79d 100644
--- a/libavfilter/asrc_sine.c
+++ b/libavfilter/asrc_sine.c
@@ -266,7 +266,6 @@  static const AVFilterPad sine_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_sine = {
@@ -278,5 +277,6 @@  const AVFilter ff_asrc_sine = {
     .priv_size     = sizeof(SineContext),
     .inputs        = NULL,
     .outputs       = sine_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(sine_outputs),
     .priv_class    = &sine_class,
 };
diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c
index 481a218e6e..b835c1b860 100644
--- a/libavfilter/avf_abitscope.c
+++ b/libavfilter/avf_abitscope.c
@@ -248,7 +248,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -257,7 +256,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_abitscope = {
@@ -266,7 +264,9 @@  const AVFilter ff_avf_abitscope = {
     .query_formats = query_formats,
     .priv_size     = sizeof(AudioBitScopeContext),
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .activate      = activate,
     .priv_class    = &abitscope_class,
 };
diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c
index 864c061c2f..1c370bca13 100644
--- a/libavfilter/avf_ahistogram.c
+++ b/libavfilter/avf_ahistogram.c
@@ -412,7 +412,6 @@  static const AVFilterPad ahistogram_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad ahistogram_outputs[] = {
@@ -421,7 +420,6 @@  static const AVFilterPad ahistogram_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_ahistogram = {
@@ -432,6 +430,8 @@  const AVFilter ff_avf_ahistogram = {
     .priv_size     = sizeof(AudioHistogramContext),
     .activate      = activate,
     .inputs        = ahistogram_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ahistogram_inputs),
     .outputs       = ahistogram_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ahistogram_outputs),
     .priv_class    = &ahistogram_class,
 };
diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c
index a31805f204..7ddea3bd79 100644
--- a/libavfilter/avf_aphasemeter.c
+++ b/libavfilter/avf_aphasemeter.c
@@ -380,7 +380,6 @@  static const AVFilterPad inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_aphasemeter = {
@@ -391,6 +390,7 @@  const AVFilter ff_avf_aphasemeter = {
     .query_formats = query_formats,
     .priv_size     = sizeof(AudioPhaseMeterContext),
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = NULL,
     .priv_class    = &aphasemeter_class,
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c
index a0011fe33b..9db86e82b0 100644
--- a/libavfilter/avf_avectorscope.c
+++ b/libavfilter/avf_avectorscope.c
@@ -403,7 +403,6 @@  static const AVFilterPad audiovectorscope_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad audiovectorscope_outputs[] = {
@@ -412,7 +411,6 @@  static const AVFilterPad audiovectorscope_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_avectorscope = {
@@ -423,6 +421,8 @@  const AVFilter ff_avf_avectorscope = {
     .priv_size     = sizeof(AudioVectorScopeContext),
     .activate      = activate,
     .inputs        = audiovectorscope_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(audiovectorscope_inputs),
     .outputs       = audiovectorscope_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(audiovectorscope_outputs),
     .priv_class    = &avectorscope_class,
 };
diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c
index aa9900ebe0..b3ce81e9e2 100644
--- a/libavfilter/avf_showcqt.c
+++ b/libavfilter/avf_showcqt.c
@@ -1577,7 +1577,6 @@  static const AVFilterPad showcqt_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad showcqt_outputs[] = {
@@ -1587,7 +1586,6 @@  static const AVFilterPad showcqt_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showcqt = {
@@ -1598,6 +1596,8 @@  const AVFilter ff_avf_showcqt = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowCQTContext),
     .inputs        = showcqt_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showcqt_inputs),
     .outputs       = showcqt_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showcqt_outputs),
     .priv_class    = &showcqt_class,
 };
diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c
index 5dee3445a8..c49749f20d 100644
--- a/libavfilter/avf_showfreqs.c
+++ b/libavfilter/avf_showfreqs.c
@@ -552,7 +552,6 @@  static const AVFilterPad showfreqs_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad showfreqs_outputs[] = {
@@ -561,7 +560,6 @@  static const AVFilterPad showfreqs_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showfreqs = {
@@ -573,6 +571,8 @@  const AVFilter ff_avf_showfreqs = {
     .priv_size     = sizeof(ShowFreqsContext),
     .activate      = activate,
     .inputs        = showfreqs_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showfreqs_inputs),
     .outputs       = showfreqs_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showfreqs_outputs),
     .priv_class    = &showfreqs_class,
 };
diff --git a/libavfilter/avf_showspatial.c b/libavfilter/avf_showspatial.c
index 82d202a817..070edf87a0 100644
--- a/libavfilter/avf_showspatial.c
+++ b/libavfilter/avf_showspatial.c
@@ -346,7 +346,6 @@  static const AVFilterPad showspatial_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad showspatial_outputs[] = {
@@ -355,7 +354,6 @@  static const AVFilterPad showspatial_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showspatial = {
@@ -365,7 +363,9 @@  const AVFilter ff_avf_showspatial = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowSpatialContext),
     .inputs        = showspatial_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showspatial_inputs),
     .outputs       = showspatial_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showspatial_outputs),
     .activate      = spatial_activate,
     .priv_class    = &showspatial_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index 1c94a06e3f..2f5161b204 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -1608,7 +1608,6 @@  static const AVFilterPad showspectrum_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad showspectrum_outputs[] = {
@@ -1617,7 +1616,6 @@  static const AVFilterPad showspectrum_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showspectrum = {
@@ -1627,7 +1625,9 @@  const AVFilter ff_avf_showspectrum = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowSpectrumContext),
     .inputs        = showspectrum_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showspectrum_inputs),
     .outputs       = showspectrum_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showspectrum_outputs),
     .activate      = activate,
     .priv_class    = &showspectrum_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
@@ -1792,7 +1792,6 @@  static const AVFilterPad showspectrumpic_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = showspectrumpic_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad showspectrumpic_outputs[] = {
@@ -1802,7 +1801,6 @@  static const AVFilterPad showspectrumpic_outputs[] = {
         .config_props  = config_output,
         .request_frame = showspectrumpic_request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showspectrumpic = {
@@ -1812,7 +1810,9 @@  const AVFilter ff_avf_showspectrumpic = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowSpectrumContext),
     .inputs        = showspectrumpic_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showspectrumpic_inputs),
     .outputs       = showspectrumpic_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showspectrumpic_outputs),
     .priv_class    = &showspectrumpic_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c
index d4b8c48297..c15e17b8ff 100644
--- a/libavfilter/avf_showvolume.c
+++ b/libavfilter/avf_showvolume.c
@@ -486,7 +486,6 @@  static const AVFilterPad showvolume_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad showvolume_outputs[] = {
@@ -495,7 +494,6 @@  static const AVFilterPad showvolume_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showvolume = {
@@ -507,6 +505,8 @@  const AVFilter ff_avf_showvolume = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowVolumeContext),
     .inputs        = showvolume_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showvolume_inputs),
     .outputs       = showvolume_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showvolume_outputs),
     .priv_class    = &showvolume_class,
 };
diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
index b3639f46a5..3e2787df38 100644
--- a/libavfilter/avf_showwaves.c
+++ b/libavfilter/avf_showwaves.c
@@ -763,7 +763,6 @@  static const AVFilterPad showwaves_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad showwaves_outputs[] = {
@@ -772,7 +771,6 @@  static const AVFilterPad showwaves_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showwaves = {
@@ -783,8 +781,10 @@  const AVFilter ff_avf_showwaves = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowWavesContext),
     .inputs        = showwaves_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showwaves_inputs),
     .activate      = activate,
     .outputs       = showwaves_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showwaves_outputs),
     .priv_class    = &showwaves_class,
 };
 
@@ -877,7 +877,6 @@  static const AVFilterPad showwavespic_inputs[] = {
         .config_props = showwavespic_config_input,
         .filter_frame = showwavespic_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad showwavespic_outputs[] = {
@@ -887,7 +886,6 @@  static const AVFilterPad showwavespic_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_showwavespic = {
@@ -898,7 +896,9 @@  const AVFilter ff_avf_showwavespic = {
     .query_formats = query_formats,
     .priv_size     = sizeof(ShowWavesContext),
     .inputs        = showwavespic_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showwavespic_inputs),
     .outputs       = showwavespic_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showwavespic_outputs),
     .priv_class    = &showwavespic_class,
 };
 
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index f9d7226386..85fbba8080 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -547,14 +547,20 @@  int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha
 
 int avfilter_pad_count(const AVFilterPad *pads)
 {
-    int count;
+    const AVFilter *filter;
+    void *opaque = NULL;
 
     if (!pads)
         return 0;
 
-    for (count = 0; pads->name; count++)
-        pads++;
-    return count;
+    while (filter = av_filter_iterate(&opaque)) {
+        if (pads == filter->inputs)
+            return filter->nb_inputs;
+        if (pads == filter->outputs)
+            return filter->nb_outputs;
+    }
+
+    av_assert0(!"AVFilterPad list not from a filter");
 }
 
 static const char *default_filter_name(void *filter_ctx)
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 360f63bc45..f436110b19 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -71,8 +71,7 @@  typedef struct AVFilterFormats AVFilterFormats;
 typedef struct AVFilterChannelLayouts AVFilterChannelLayouts;
 
 /**
- * Get the number of elements in a NULL-terminated array of AVFilterPads (e.g.
- * AVFilter.inputs/outputs).
+ * Get the number of elements in an AVFilter's inputs or outputs array.
  */
 int avfilter_pad_count(const AVFilterPad *pads);
 
@@ -156,15 +155,26 @@  typedef struct AVFilter {
     const char *description;
 
     /**
-     * List of inputs, terminated by a zeroed element.
+     * List of static inputs.
      *
      * NULL if there are no (static) inputs. Instances of filters with
      * AVFILTER_FLAG_DYNAMIC_INPUTS set may have more inputs than present in
      * this list.
      */
     const AVFilterPad *inputs;
+
+    /**
+     * The number of entries in the above list of inputs.
+     */
+    unsigned nb_inputs;
+
+    /**
+     * The number of entries in the list of outputs below.
+     */
+    unsigned nb_outputs;
+
     /**
-     * List of outputs, terminated by a zeroed element.
+     * List of static outputs.
      *
      * NULL if there are no (static) outputs. Instances of filters with
      * AVFILTER_FLAG_DYNAMIC_OUTPUTS set may have more outputs than present in
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 07c4812f29..be356943ff 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -331,7 +331,6 @@  static const AVFilterPad avfilter_vsink_buffer_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsink_buffer = {
@@ -343,6 +342,7 @@  const AVFilter ff_vsink_buffer = {
     .query_formats = vsink_query_formats,
     .activate      = activate,
     .inputs        = avfilter_vsink_buffer_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vsink_buffer_inputs),
     .outputs       = NULL,
 };
 
@@ -351,7 +351,6 @@  static const AVFilterPad avfilter_asink_abuffer_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_asink_abuffer = {
@@ -363,5 +362,6 @@  const AVFilter ff_asink_abuffer = {
     .query_formats = asink_query_formats,
     .activate      = activate,
     .inputs        = avfilter_asink_abuffer_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_asink_abuffer_inputs),
     .outputs       = NULL,
 };
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 4d0bb4f91d..adad5dc928 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -434,7 +434,6 @@  static const AVFilterPad avfilter_vsrc_buffer_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_buffer = {
@@ -448,6 +447,7 @@  const AVFilter ff_vsrc_buffer = {
 
     .inputs    = NULL,
     .outputs   = avfilter_vsrc_buffer_outputs,
+    .nb_outputs = FF_ARRAY_ELEMS(avfilter_vsrc_buffer_outputs),
     .priv_class = &buffer_class,
 };
 
@@ -458,7 +458,6 @@  static const AVFilterPad avfilter_asrc_abuffer_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_asrc_abuffer = {
@@ -472,5 +471,6 @@  const AVFilter ff_asrc_abuffer = {
 
     .inputs    = NULL,
     .outputs   = avfilter_asrc_abuffer_outputs,
+    .nb_outputs = FF_ARRAY_ELEMS(avfilter_asrc_abuffer_outputs),
     .priv_class = &abuffer_class,
 };
diff --git a/libavfilter/f_bench.c b/libavfilter/f_bench.c
index e7d7c5e299..28bd424041 100644
--- a/libavfilter/f_bench.c
+++ b/libavfilter/f_bench.c
@@ -96,7 +96,6 @@  static const AVFilterPad bench_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad bench_outputs[] = {
@@ -104,7 +103,6 @@  static const AVFilterPad bench_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bench = {
@@ -113,7 +111,9 @@  const AVFilter ff_vf_bench = {
     .priv_size     = sizeof(BenchContext),
     .init          = init,
     .inputs        = bench_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(bench_inputs),
     .outputs       = bench_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(bench_outputs),
     .priv_class    = &bench_class,
 };
 #endif /* CONFIG_BENCH_FILTER */
@@ -128,7 +128,6 @@  static const AVFilterPad abench_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad abench_outputs[] = {
@@ -136,7 +135,6 @@  static const AVFilterPad abench_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_abench = {
@@ -145,7 +143,9 @@  const AVFilter ff_af_abench = {
     .priv_size     = sizeof(BenchContext),
     .init          = init,
     .inputs        = abench_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(abench_inputs),
     .outputs       = abench_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(abench_outputs),
     .priv_class    = &abench_class,
 };
 #endif /* CONFIG_ABENCH_FILTER */
diff --git a/libavfilter/f_cue.c b/libavfilter/f_cue.c
index 03804f1667..a9c736b2ef 100644
--- a/libavfilter/f_cue.c
+++ b/libavfilter/f_cue.c
@@ -103,7 +103,6 @@  static const AVFilterPad cue_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad cue_outputs[] = {
@@ -111,7 +110,6 @@  static const AVFilterPad cue_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_cue = {
@@ -120,7 +118,9 @@  const AVFilter ff_vf_cue = {
     .priv_size   = sizeof(CueContext),
     .priv_class  = &cue_class,
     .inputs      = cue_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(cue_inputs),
     .outputs     = cue_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(cue_outputs),
     .activate    = activate,
 };
 #endif /* CONFIG_CUE_FILTER */
@@ -134,7 +134,6 @@  static const AVFilterPad acue_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad acue_outputs[] = {
@@ -142,7 +141,6 @@  static const AVFilterPad acue_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_acue = {
@@ -151,7 +149,9 @@  const AVFilter ff_af_acue = {
     .priv_size   = sizeof(CueContext),
     .priv_class  = &acue_class,
     .inputs      = acue_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(acue_inputs),
     .outputs     = acue_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(acue_outputs),
     .activate    = activate,
 };
 #endif /* CONFIG_ACUE_FILTER */
diff --git a/libavfilter/f_drawgraph.c b/libavfilter/f_drawgraph.c
index 70701e330e..93811ca6ac 100644
--- a/libavfilter/f_drawgraph.c
+++ b/libavfilter/f_drawgraph.c
@@ -458,7 +458,6 @@  static const AVFilterPad drawgraph_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad drawgraph_outputs[] = {
@@ -468,7 +467,6 @@  static const AVFilterPad drawgraph_outputs[] = {
         .config_props = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_drawgraph = {
@@ -480,7 +478,9 @@  const AVFilter ff_vf_drawgraph = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = drawgraph_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(drawgraph_inputs),
     .outputs       = drawgraph_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(drawgraph_outputs),
 };
 
 #endif // CONFIG_DRAWGRAPH_FILTER
@@ -496,7 +496,6 @@  static const AVFilterPad adrawgraph_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad adrawgraph_outputs[] = {
@@ -506,7 +505,6 @@  static const AVFilterPad adrawgraph_outputs[] = {
         .config_props = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_adrawgraph = {
@@ -518,6 +516,8 @@  const AVFilter ff_avf_adrawgraph = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = adrawgraph_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(adrawgraph_inputs),
     .outputs       = adrawgraph_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(adrawgraph_outputs),
 };
 #endif // CONFIG_ADRAWGRAPH_FILTER
diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c
index 47ea9b59d7..b8979db834 100644
--- a/libavfilter/f_ebur128.c
+++ b/libavfilter/f_ebur128.c
@@ -1017,7 +1017,6 @@  static const AVFilterPad ebur128_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_audio_input,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_ebur128 = {
@@ -1028,6 +1027,7 @@  const AVFilter ff_af_ebur128 = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = ebur128_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ebur128_inputs),
     .outputs       = NULL,
     .priv_class    = &ebur128_class,
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c
index 90e93a4ac3..cdfe7c2232 100644
--- a/libavfilter/f_graphmonitor.c
+++ b/libavfilter/f_graphmonitor.c
@@ -395,7 +395,6 @@  static const AVFilterPad graphmonitor_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad graphmonitor_outputs[] = {
@@ -404,7 +403,6 @@  static const AVFilterPad graphmonitor_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_graphmonitor = {
@@ -415,7 +413,9 @@  const AVFilter ff_vf_graphmonitor = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = graphmonitor_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(graphmonitor_inputs),
     .outputs       = graphmonitor_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(graphmonitor_outputs),
 };
 
 #endif // CONFIG_GRAPHMONITOR_FILTER
@@ -430,7 +430,6 @@  static const AVFilterPad agraphmonitor_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad agraphmonitor_outputs[] = {
@@ -439,7 +438,6 @@  static const AVFilterPad agraphmonitor_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_avf_agraphmonitor = {
@@ -450,6 +448,8 @@  const AVFilter ff_avf_agraphmonitor = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = agraphmonitor_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(agraphmonitor_inputs),
     .outputs       = agraphmonitor_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(agraphmonitor_outputs),
 };
 #endif // CONFIG_AGRAPHMONITOR_FILTER
diff --git a/libavfilter/f_interleave.c b/libavfilter/f_interleave.c
index 259952b591..97b523573f 100644
--- a/libavfilter/f_interleave.c
+++ b/libavfilter/f_interleave.c
@@ -235,7 +235,6 @@  static const AVFilterPad interleave_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_interleave = {
@@ -246,6 +245,7 @@  const AVFilter ff_vf_interleave = {
     .uninit      = uninit,
     .activate    = activate,
     .outputs     = interleave_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(interleave_outputs),
     .priv_class  = &interleave_class,
     .flags       = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
@@ -263,7 +263,6 @@  static const AVFilterPad ainterleave_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_ainterleave = {
@@ -274,6 +273,7 @@  const AVFilter ff_af_ainterleave = {
     .uninit      = uninit,
     .activate    = activate,
     .outputs     = ainterleave_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(ainterleave_outputs),
     .priv_class  = &ainterleave_class,
     .flags       = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c
index a06e8172d3..a3f91b51e8 100644
--- a/libavfilter/f_loop.c
+++ b/libavfilter/f_loop.c
@@ -269,7 +269,6 @@  static const AVFilterPad ainputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = aconfig_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad aoutputs[] = {
@@ -277,7 +276,6 @@  static const AVFilterPad aoutputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aloop = {
@@ -288,7 +286,9 @@  const AVFilter ff_af_aloop = {
     .activate      = aactivate,
     .uninit        = auninit,
     .inputs        = ainputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ainputs),
     .outputs       = aoutputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aoutputs),
 };
 #endif /* CONFIG_ALOOP_FILTER */
 
@@ -442,7 +442,6 @@  static const AVFilterPad inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -450,7 +449,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_loop = {
@@ -462,6 +460,8 @@  const AVFilter ff_vf_loop = {
     .uninit      = uninit,
     .activate    = activate,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
 };
 #endif /* CONFIG_LOOP_FILTER */
diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c
index d0a78b00d0..45c319a1d9 100644
--- a/libavfilter/f_metadata.c
+++ b/libavfilter/f_metadata.c
@@ -373,7 +373,6 @@  static const AVFilterPad ainputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aoutputs[] = {
@@ -381,7 +380,6 @@  static const AVFilterPad aoutputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_ametadata = {
@@ -392,7 +390,9 @@  const AVFilter ff_af_ametadata = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = ainputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ainputs),
     .outputs       = aoutputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aoutputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
 #endif /* CONFIG_AMETADATA_FILTER */
@@ -408,7 +408,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -416,7 +415,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_metadata = {
@@ -427,7 +425,9 @@  const AVFilter ff_vf_metadata = {
     .init        = init,
     .uninit      = uninit,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
 #endif /* CONFIG_METADATA_FILTER */
diff --git a/libavfilter/f_perms.c b/libavfilter/f_perms.c
index 0302ed765b..aaa466d717 100644
--- a/libavfilter/f_perms.c
+++ b/libavfilter/f_perms.c
@@ -122,7 +122,6 @@  static const AVFilterPad aperms_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aperms_outputs[] = {
@@ -130,7 +129,6 @@  static const AVFilterPad aperms_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aperms = {
@@ -139,7 +137,9 @@  const AVFilter ff_af_aperms = {
     .init        = init,
     .priv_size   = sizeof(PermsContext),
     .inputs      = aperms_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(aperms_inputs),
     .outputs     = aperms_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(aperms_outputs),
     .priv_class  = &aperms_class,
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
@@ -156,7 +156,6 @@  static const AVFilterPad perms_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad perms_outputs[] = {
@@ -164,7 +163,6 @@  static const AVFilterPad perms_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_perms = {
@@ -173,7 +171,9 @@  const AVFilter ff_vf_perms = {
     .init        = init,
     .priv_size   = sizeof(PermsContext),
     .inputs      = perms_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(perms_inputs),
     .outputs     = perms_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(perms_outputs),
     .priv_class  = &perms_class,
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/f_realtime.c b/libavfilter/f_realtime.c
index 332ef21ac5..19002d8265 100644
--- a/libavfilter/f_realtime.c
+++ b/libavfilter/f_realtime.c
@@ -81,7 +81,6 @@  static const AVFilterPad avfilter_vf_realtime_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_realtime_outputs[] = {
@@ -89,7 +88,6 @@  static const AVFilterPad avfilter_vf_realtime_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_realtime = {
@@ -98,7 +96,9 @@  const AVFilter ff_vf_realtime = {
     .priv_size   = sizeof(RealtimeContext),
     .priv_class  = &realtime_class,
     .inputs      = avfilter_vf_realtime_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_realtime_inputs),
     .outputs     = avfilter_vf_realtime_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_realtime_outputs),
 };
 #endif /* CONFIG_REALTIME_FILTER */
 
@@ -113,7 +113,6 @@  static const AVFilterPad arealtime_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad arealtime_outputs[] = {
@@ -121,7 +120,6 @@  static const AVFilterPad arealtime_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_arealtime = {
@@ -130,6 +128,8 @@  const AVFilter ff_af_arealtime = {
     .priv_size   = sizeof(RealtimeContext),
     .priv_class  = &arealtime_class,
     .inputs      = arealtime_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(arealtime_inputs),
     .outputs     = arealtime_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(arealtime_outputs),
 };
 #endif /* CONFIG_AREALTIME_FILTER */
diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c
index 2a85e6966e..f59d114a57 100644
--- a/libavfilter/f_reverse.c
+++ b/libavfilter/f_reverse.c
@@ -121,7 +121,6 @@  static const AVFilterPad reverse_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad reverse_outputs[] = {
@@ -130,7 +129,6 @@  static const AVFilterPad reverse_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_reverse = {
@@ -140,7 +138,9 @@  const AVFilter ff_vf_reverse = {
     .init        = init,
     .uninit      = uninit,
     .inputs      = reverse_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(reverse_inputs),
     .outputs     = reverse_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(reverse_outputs),
 };
 
 #endif /* CONFIG_REVERSE_FILTER */
@@ -282,7 +282,6 @@  static const AVFilterPad areverse_inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad areverse_outputs[] = {
@@ -291,7 +290,6 @@  static const AVFilterPad areverse_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .request_frame = areverse_request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_areverse = {
@@ -302,7 +300,9 @@  const AVFilter ff_af_areverse = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = areverse_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(areverse_inputs),
     .outputs       = areverse_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(areverse_outputs),
 };
 
 #endif /* CONFIG_AREVERSE_FILTER */
diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c
index f0468078e8..594b2c85f2 100644
--- a/libavfilter/f_select.c
+++ b/libavfilter/f_select.c
@@ -473,7 +473,6 @@  static const AVFilterPad avfilter_af_aselect_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_aselect = {
@@ -483,6 +482,7 @@  const AVFilter ff_af_aselect = {
     .uninit      = uninit,
     .priv_size   = sizeof(SelectContext),
     .inputs      = avfilter_af_aselect_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_af_aselect_inputs),
     .priv_class  = &aselect_class,
     .flags       = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
@@ -537,7 +537,6 @@  static const AVFilterPad avfilter_vf_select_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_select = {
@@ -549,6 +548,7 @@  const AVFilter ff_vf_select = {
     .priv_size     = sizeof(SelectContext),
     .priv_class    = &select_class,
     .inputs        = avfilter_vf_select_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_select_inputs),
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
 #endif /* CONFIG_SELECT_FILTER */
diff --git a/libavfilter/f_sendcmd.c b/libavfilter/f_sendcmd.c
index 71b0a5c411..c5b05ec503 100644
--- a/libavfilter/f_sendcmd.c
+++ b/libavfilter/f_sendcmd.c
@@ -583,7 +583,6 @@  static const AVFilterPad sendcmd_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad sendcmd_outputs[] = {
@@ -591,7 +590,6 @@  static const AVFilterPad sendcmd_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_sendcmd = {
@@ -601,7 +599,9 @@  const AVFilter ff_vf_sendcmd = {
     .uninit      = uninit,
     .priv_size   = sizeof(SendCmdContext),
     .inputs      = sendcmd_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(sendcmd_inputs),
     .outputs     = sendcmd_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(sendcmd_outputs),
     .priv_class  = &sendcmd_class,
 };
 
@@ -618,7 +618,6 @@  static const AVFilterPad asendcmd_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad asendcmd_outputs[] = {
@@ -626,7 +625,6 @@  static const AVFilterPad asendcmd_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asendcmd = {
@@ -636,7 +634,9 @@  const AVFilter ff_af_asendcmd = {
     .uninit      = uninit,
     .priv_size   = sizeof(SendCmdContext),
     .inputs      = asendcmd_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(asendcmd_inputs),
     .outputs     = asendcmd_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(asendcmd_outputs),
     .priv_class  = &asendcmd_class,
 };
 
diff --git a/libavfilter/f_sidedata.c b/libavfilter/f_sidedata.c
index 9133fcb1e3..4fa6572e73 100644
--- a/libavfilter/f_sidedata.c
+++ b/libavfilter/f_sidedata.c
@@ -130,7 +130,6 @@  static const AVFilterPad ainputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad aoutputs[] = {
@@ -138,7 +137,6 @@  static const AVFilterPad aoutputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asidedata = {
@@ -148,7 +146,9 @@  const AVFilter ff_af_asidedata = {
     .priv_class    = &asidedata_class,
     .init          = init,
     .inputs        = ainputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ainputs),
     .outputs       = aoutputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(aoutputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
 #endif /* CONFIG_ASIDEDATA_FILTER */
@@ -164,7 +164,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -172,7 +171,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_sidedata = {
@@ -182,7 +180,9 @@  const AVFilter ff_vf_sidedata = {
     .priv_class  = &sidedata_class,
     .init        = init,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
 #endif /* CONFIG_SIDEDATA_FILTER */
diff --git a/libavfilter/f_zmq.c b/libavfilter/f_zmq.c
index 774a890871..a14843c6bf 100644
--- a/libavfilter/f_zmq.c
+++ b/libavfilter/f_zmq.c
@@ -214,7 +214,6 @@  static const AVFilterPad zmq_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad zmq_outputs[] = {
@@ -222,7 +221,6 @@  static const AVFilterPad zmq_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_zmq = {
@@ -232,7 +230,9 @@  const AVFilter ff_vf_zmq = {
     .uninit      = uninit,
     .priv_size   = sizeof(ZMQContext),
     .inputs      = zmq_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(zmq_inputs),
     .outputs     = zmq_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(zmq_outputs),
     .priv_class  = &zmq_class,
 };
 
@@ -249,7 +249,6 @@  static const AVFilterPad azmq_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad azmq_outputs[] = {
@@ -257,7 +256,6 @@  static const AVFilterPad azmq_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_azmq = {
@@ -267,7 +265,9 @@  const AVFilter ff_af_azmq = {
     .uninit      = uninit,
     .priv_size   = sizeof(ZMQContext),
     .inputs      = azmq_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(azmq_inputs),
     .outputs     = azmq_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(azmq_outputs),
     .priv_class  = &azmq_class,
 };
 
diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c
index e0996ba501..f5ec7505de 100644
--- a/libavfilter/fifo.c
+++ b/libavfilter/fifo.c
@@ -116,7 +116,6 @@  static const AVFilterPad avfilter_vf_fifo_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = add_to_queue,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_fifo_outputs[] = {
@@ -125,7 +124,6 @@  static const AVFilterPad avfilter_vf_fifo_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fifo = {
@@ -135,7 +133,9 @@  const AVFilter ff_vf_fifo = {
     .uninit      = uninit,
     .priv_size   = sizeof(FifoContext),
     .inputs      = avfilter_vf_fifo_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_fifo_inputs),
     .outputs     = avfilter_vf_fifo_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_fifo_outputs),
 };
 
 static const AVFilterPad avfilter_af_afifo_inputs[] = {
@@ -144,7 +144,6 @@  static const AVFilterPad avfilter_af_afifo_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = add_to_queue,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_afifo_outputs[] = {
@@ -153,7 +152,6 @@  static const AVFilterPad avfilter_af_afifo_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_afifo = {
@@ -163,5 +161,7 @@  const AVFilter ff_af_afifo = {
     .uninit      = uninit,
     .priv_size   = sizeof(FifoContext),
     .inputs      = avfilter_af_afifo_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_af_afifo_inputs),
     .outputs     = avfilter_af_afifo_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_af_afifo_outputs),
 };
diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c
index ac98974312..03a3759a38 100644
--- a/libavfilter/setpts.c
+++ b/libavfilter/setpts.c
@@ -279,7 +279,6 @@  static const AVFilterPad avfilter_vf_setpts_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_setpts_outputs[] = {
@@ -287,7 +286,6 @@  static const AVFilterPad avfilter_vf_setpts_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_setpts = {
@@ -301,7 +299,9 @@  const AVFilter ff_vf_setpts = {
     .priv_class = &setpts_class,
 
     .inputs    = avfilter_vf_setpts_inputs,
+    .nb_inputs  = FF_ARRAY_ELEMS(avfilter_vf_setpts_inputs),
     .outputs   = avfilter_vf_setpts_outputs,
+    .nb_outputs = FF_ARRAY_ELEMS(avfilter_vf_setpts_outputs),
 };
 #endif /* CONFIG_SETPTS_FILTER */
 
@@ -319,7 +319,6 @@  static const AVFilterPad asetpts_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad asetpts_outputs[] = {
@@ -327,7 +326,6 @@  static const AVFilterPad asetpts_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asetpts = {
@@ -339,6 +337,8 @@  const AVFilter ff_af_asetpts = {
     .priv_size   = sizeof(SetPTSContext),
     .priv_class  = &asetpts_class,
     .inputs      = asetpts_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(asetpts_inputs),
     .outputs     = asetpts_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(asetpts_outputs),
 };
 #endif /* CONFIG_ASETPTS_FILTER */
diff --git a/libavfilter/settb.c b/libavfilter/settb.c
index 2f68e44c5b..93d88cad5e 100644
--- a/libavfilter/settb.c
+++ b/libavfilter/settb.c
@@ -167,7 +167,6 @@  static const AVFilterPad avfilter_vf_settb_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_settb_outputs[] = {
@@ -176,7 +175,6 @@  static const AVFilterPad avfilter_vf_settb_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_settb = {
@@ -185,7 +183,9 @@  const AVFilter ff_vf_settb = {
     .priv_size   = sizeof(SetTBContext),
     .priv_class  = &settb_class,
     .inputs      = avfilter_vf_settb_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_settb_inputs),
     .outputs     = avfilter_vf_settb_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_settb_outputs),
     .activate    = activate,
 };
 #endif /* CONFIG_SETTB_FILTER */
@@ -200,7 +200,6 @@  static const AVFilterPad avfilter_af_asettb_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_af_asettb_outputs[] = {
@@ -209,7 +208,6 @@  static const AVFilterPad avfilter_af_asettb_outputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .config_props = config_output_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asettb = {
@@ -217,7 +215,9 @@  const AVFilter ff_af_asettb = {
     .description = NULL_IF_CONFIG_SMALL("Set timebase for the audio output link."),
     .priv_size   = sizeof(SetTBContext),
     .inputs      = avfilter_af_asettb_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_af_asettb_inputs),
     .outputs     = avfilter_af_asettb_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_af_asettb_outputs),
     .priv_class  = &asettb_class,
     .activate    = activate,
 };
diff --git a/libavfilter/split.c b/libavfilter/split.c
index da5f681af8..9723160ed5 100644
--- a/libavfilter/split.c
+++ b/libavfilter/split.c
@@ -116,7 +116,6 @@  static const AVFilterPad avfilter_vf_split_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_split = {
@@ -127,6 +126,7 @@  const AVFilter ff_vf_split = {
     .init        = split_init,
     .uninit      = split_uninit,
     .inputs      = avfilter_vf_split_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_split_inputs),
     .outputs     = NULL,
     .flags       = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
@@ -137,7 +137,6 @@  static const AVFilterPad avfilter_af_asplit_inputs[] = {
         .type         = AVMEDIA_TYPE_AUDIO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_asplit = {
@@ -148,6 +147,7 @@  const AVFilter ff_af_asplit = {
     .init        = split_init,
     .uninit      = split_uninit,
     .inputs      = avfilter_af_asplit_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_af_asplit_inputs),
     .outputs     = NULL,
     .flags       = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
diff --git a/libavfilter/trim.c b/libavfilter/trim.c
index 261dacbc5c..a867373732 100644
--- a/libavfilter/trim.c
+++ b/libavfilter/trim.c
@@ -195,7 +195,6 @@  static const AVFilterPad trim_inputs[] = {
         .filter_frame = trim_filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad trim_outputs[] = {
@@ -203,7 +202,6 @@  static const AVFilterPad trim_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_trim = {
@@ -213,7 +211,9 @@  const AVFilter ff_vf_trim = {
     .priv_size   = sizeof(TrimContext),
     .priv_class  = &trim_class,
     .inputs      = trim_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(trim_inputs),
     .outputs     = trim_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(trim_outputs),
 };
 #endif // CONFIG_TRIM_FILTER
 
@@ -350,7 +350,6 @@  static const AVFilterPad atrim_inputs[] = {
         .filter_frame = atrim_filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad atrim_outputs[] = {
@@ -358,7 +357,6 @@  static const AVFilterPad atrim_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_AUDIO,
     },
-    { NULL }
 };
 
 const AVFilter ff_af_atrim = {
@@ -368,6 +366,8 @@  const AVFilter ff_af_atrim = {
     .priv_size   = sizeof(TrimContext),
     .priv_class  = &atrim_class,
     .inputs      = atrim_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(atrim_inputs),
     .outputs     = atrim_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(atrim_outputs),
 };
 #endif // CONFIG_ATRIM_FILTER
diff --git a/libavfilter/vaf_spectrumsynth.c b/libavfilter/vaf_spectrumsynth.c
index d44d01cd33..78b822df57 100644
--- a/libavfilter/vaf_spectrumsynth.c
+++ b/libavfilter/vaf_spectrumsynth.c
@@ -532,7 +532,6 @@  static const AVFilterPad spectrumsynth_inputs[] = {
         .name         = "phase",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad spectrumsynth_outputs[] = {
@@ -541,7 +540,6 @@  static const AVFilterPad spectrumsynth_outputs[] = {
         .type          = AVMEDIA_TYPE_AUDIO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vaf_spectrumsynth = {
@@ -552,6 +550,8 @@  const AVFilter ff_vaf_spectrumsynth = {
     .activate      = activate,
     .priv_size     = sizeof(SpectrumSynthContext),
     .inputs        = spectrumsynth_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(spectrumsynth_inputs),
     .outputs       = spectrumsynth_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(spectrumsynth_outputs),
     .priv_class    = &spectrumsynth_class,
 };
diff --git a/libavfilter/vf_addroi.c b/libavfilter/vf_addroi.c
index 1d09f31879..08901db2c7 100644
--- a/libavfilter/vf_addroi.c
+++ b/libavfilter/vf_addroi.c
@@ -244,7 +244,6 @@  static const AVFilterPad addroi_inputs[] = {
         .config_props = addroi_config_input,
         .filter_frame = addroi_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad addroi_outputs[] = {
@@ -252,7 +251,6 @@  static const AVFilterPad addroi_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_addroi = {
@@ -265,5 +263,7 @@  const AVFilter ff_vf_addroi = {
     .priv_class  = &addroi_class,
 
     .inputs      = addroi_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(addroi_inputs),
     .outputs     = addroi_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(addroi_outputs),
 };
diff --git a/libavfilter/vf_alphamerge.c b/libavfilter/vf_alphamerge.c
index 9b01db6605..f58a70dc11 100644
--- a/libavfilter/vf_alphamerge.c
+++ b/libavfilter/vf_alphamerge.c
@@ -170,7 +170,6 @@  static const AVFilterPad alphamerge_inputs[] = {
         .name             = "alpha",
         .type             = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad alphamerge_outputs[] = {
@@ -179,7 +178,6 @@  static const AVFilterPad alphamerge_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 static const AVOption alphamerge_options[] = {
@@ -198,7 +196,9 @@  const AVFilter ff_vf_alphamerge = {
     .init           = init,
     .query_formats  = query_formats,
     .inputs         = alphamerge_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(alphamerge_inputs),
     .outputs        = alphamerge_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(alphamerge_outputs),
     .uninit         = uninit,
     .activate       = activate,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
diff --git a/libavfilter/vf_amplify.c b/libavfilter/vf_amplify.c
index e9e0a90b41..a8544434ae 100644
--- a/libavfilter/vf_amplify.c
+++ b/libavfilter/vf_amplify.c
@@ -299,7 +299,6 @@  static const AVFilterPad inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -308,7 +307,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(amplify);
@@ -320,7 +318,9 @@  const AVFilter ff_vf_amplify = {
     .priv_class    = &amplify_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .init          = init,
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c
index f0467b5247..8e7a08777f 100644
--- a/libavfilter/vf_aspect.c
+++ b/libavfilter/vf_aspect.c
@@ -173,7 +173,6 @@  static const AVFilterPad avfilter_vf_setdar_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_setdar_outputs[] = {
@@ -182,7 +181,6 @@  static const AVFilterPad avfilter_vf_setdar_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = setdar_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_setdar = {
@@ -191,7 +189,9 @@  const AVFilter ff_vf_setdar = {
     .priv_size   = sizeof(AspectContext),
     .priv_class  = &setdar_class,
     .inputs      = avfilter_vf_setdar_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_setdar_inputs),
     .outputs     = avfilter_vf_setdar_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_setdar_outputs),
 };
 
 #endif /* CONFIG_SETDAR_FILTER */
@@ -237,7 +237,6 @@  static const AVFilterPad avfilter_vf_setsar_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_setsar_outputs[] = {
@@ -246,7 +245,6 @@  static const AVFilterPad avfilter_vf_setsar_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = setsar_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_setsar = {
@@ -255,7 +253,9 @@  const AVFilter ff_vf_setsar = {
     .priv_size   = sizeof(AspectContext),
     .priv_class  = &setsar_class,
     .inputs      = avfilter_vf_setsar_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_setsar_inputs),
     .outputs     = avfilter_vf_setsar_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_setsar_outputs),
 };
 
 #endif /* CONFIG_SETSAR_FILTER */
diff --git a/libavfilter/vf_atadenoise.c b/libavfilter/vf_atadenoise.c
index 6b2f4a4e50..834e42ae79 100644
--- a/libavfilter/vf_atadenoise.c
+++ b/libavfilter/vf_atadenoise.c
@@ -560,7 +560,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -569,7 +568,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_atadenoise = {
@@ -581,7 +579,9 @@  const AVFilter ff_vf_atadenoise = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_avgblur.c b/libavfilter/vf_avgblur.c
index 361801e8fd..cb2f2cebc2 100644
--- a/libavfilter/vf_avgblur.c
+++ b/libavfilter/vf_avgblur.c
@@ -302,7 +302,6 @@  static const AVFilterPad avgblur_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avgblur_outputs[] = {
@@ -310,7 +309,6 @@  static const AVFilterPad avgblur_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_avgblur = {
@@ -321,7 +319,9 @@  const AVFilter ff_vf_avgblur = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avgblur_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avgblur_inputs),
     .outputs       = avgblur_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avgblur_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c
index 3b9e56b879..8197dde723 100644
--- a/libavfilter/vf_avgblur_opencl.c
+++ b/libavfilter/vf_avgblur_opencl.c
@@ -311,7 +311,6 @@  static const AVFilterPad avgblur_opencl_inputs[] = {
         .filter_frame = &avgblur_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 
@@ -321,7 +320,6 @@  static const AVFilterPad avgblur_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 
@@ -349,7 +347,9 @@  const AVFilter ff_vf_avgblur_opencl = {
     .uninit         = &avgblur_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = avgblur_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(avgblur_opencl_inputs),
     .outputs        = avgblur_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(avgblur_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -388,7 +388,9 @@  const AVFilter ff_vf_boxblur_opencl = {
     .uninit         = &avgblur_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = avgblur_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(avgblur_opencl_inputs),
     .outputs        = avgblur_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(avgblur_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c
index 1e485061cd..354070deed 100644
--- a/libavfilter/vf_avgblur_vulkan.c
+++ b/libavfilter/vf_avgblur_vulkan.c
@@ -386,7 +386,6 @@  static const AVFilterPad avgblur_vulkan_inputs[] = {
         .filter_frame = &avgblur_vulkan_filter_frame,
         .config_props = &ff_vk_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avgblur_vulkan_outputs[] = {
@@ -395,7 +394,6 @@  static const AVFilterPad avgblur_vulkan_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vk_filter_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_avgblur_vulkan = {
@@ -406,7 +404,9 @@  const AVFilter ff_vf_avgblur_vulkan = {
     .uninit         = &avgblur_vulkan_uninit,
     .query_formats  = &ff_vk_filter_query_formats,
     .inputs         = avgblur_vulkan_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(avgblur_vulkan_inputs),
     .outputs        = avgblur_vulkan_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(avgblur_vulkan_outputs),
     .priv_class     = &avgblur_vulkan_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_bbox.c b/libavfilter/vf_bbox.c
index 849e75646b..e710c9b94a 100644
--- a/libavfilter/vf_bbox.c
+++ b/libavfilter/vf_bbox.c
@@ -141,7 +141,6 @@  static const AVFilterPad bbox_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad bbox_outputs[] = {
@@ -150,7 +149,6 @@  static const AVFilterPad bbox_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bbox = {
@@ -160,7 +158,9 @@  const AVFilter ff_vf_bbox = {
     .priv_class    = &bbox_class,
     .query_formats = query_formats,
     .inputs        = bbox_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(bbox_inputs),
     .outputs       = bbox_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(bbox_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c
index 7b9bd9737a..1081a5450d 100644
--- a/libavfilter/vf_bilateral.c
+++ b/libavfilter/vf_bilateral.c
@@ -368,7 +368,6 @@  static const AVFilterPad bilateral_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad bilateral_outputs[] = {
@@ -376,7 +375,6 @@  static const AVFilterPad bilateral_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bilateral = {
@@ -387,7 +385,9 @@  const AVFilter ff_vf_bilateral = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = bilateral_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(bilateral_inputs),
     .outputs       = bilateral_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(bilateral_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_bitplanenoise.c b/libavfilter/vf_bitplanenoise.c
index 284c2966cf..494f93b558 100644
--- a/libavfilter/vf_bitplanenoise.c
+++ b/libavfilter/vf_bitplanenoise.c
@@ -203,7 +203,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -211,7 +210,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bitplanenoise = {
@@ -220,7 +218,9 @@  const AVFilter ff_vf_bitplanenoise = {
     .priv_size      = sizeof(BPNContext),
     .query_formats  = query_formats,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .priv_class     = &bitplanenoise_class,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c
index 9f6b293b54..3ab4789162 100644
--- a/libavfilter/vf_blackdetect.c
+++ b/libavfilter/vf_blackdetect.c
@@ -247,7 +247,6 @@  static const AVFilterPad blackdetect_inputs[] = {
         .config_props  = config_input,
         .filter_frame  = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad blackdetect_outputs[] = {
@@ -255,7 +254,6 @@  static const AVFilterPad blackdetect_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_blackdetect = {
@@ -264,7 +262,9 @@  const AVFilter ff_vf_blackdetect = {
     .priv_size     = sizeof(BlackDetectContext),
     .query_formats = query_formats,
     .inputs        = blackdetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(blackdetect_inputs),
     .outputs       = blackdetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(blackdetect_outputs),
     .uninit        = uninit,
     .priv_class    = &blackdetect_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c
index b82c044f3e..aa72451ebe 100644
--- a/libavfilter/vf_blackframe.c
+++ b/libavfilter/vf_blackframe.c
@@ -121,7 +121,6 @@  static const AVFilterPad avfilter_vf_blackframe_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_blackframe_outputs[] = {
@@ -129,7 +128,6 @@  static const AVFilterPad avfilter_vf_blackframe_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_blackframe = {
@@ -139,5 +137,7 @@  const AVFilter ff_vf_blackframe = {
     .priv_class    = &blackframe_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_blackframe_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_blackframe_inputs),
     .outputs       = avfilter_vf_blackframe_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_blackframe_outputs),
 };
diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c
index 0b33107b79..a4c30787ac 100644
--- a/libavfilter/vf_blend.c
+++ b/libavfilter/vf_blend.c
@@ -894,7 +894,6 @@  static const AVFilterPad blend_inputs[] = {
         .name          = "bottom",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad blend_outputs[] = {
@@ -903,7 +902,6 @@  static const AVFilterPad blend_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_blend = {
@@ -916,7 +914,9 @@  const AVFilter ff_vf_blend = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = blend_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(blend_inputs),
     .outputs       = blend_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(blend_outputs),
     .priv_class    = &blend_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
@@ -956,7 +956,6 @@  static const AVFilterPad tblend_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = tblend_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tblend_outputs[] = {
@@ -965,7 +964,6 @@  static const AVFilterPad tblend_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tblend = {
@@ -977,7 +975,9 @@  const AVFilter ff_vf_tblend = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = tblend_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(tblend_inputs),
     .outputs       = tblend_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(tblend_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_bm3d.c b/libavfilter/vf_bm3d.c
index f719e79cb0..d809024d1f 100644
--- a/libavfilter/vf_bm3d.c
+++ b/libavfilter/vf_bm3d.c
@@ -1051,7 +1051,6 @@  static const AVFilterPad bm3d_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bm3d = {
@@ -1064,6 +1063,7 @@  const AVFilter ff_vf_bm3d = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = bm3d_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(bm3d_outputs),
     .priv_class    = &bm3d_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_DYNAMIC_INPUTS |
diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c
index bebbd4ef08..108710b8e0 100644
--- a/libavfilter/vf_boxblur.c
+++ b/libavfilter/vf_boxblur.c
@@ -293,7 +293,6 @@  static const AVFilterPad avfilter_vf_boxblur_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_boxblur_outputs[] = {
@@ -301,7 +300,6 @@  static const AVFilterPad avfilter_vf_boxblur_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_boxblur = {
@@ -312,6 +310,8 @@  const AVFilter ff_vf_boxblur = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_boxblur_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_boxblur_inputs),
     .outputs       = avfilter_vf_boxblur_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_boxblur_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c
index 228067c8e5..ab7560b985 100644
--- a/libavfilter/vf_bwdif.c
+++ b/libavfilter/vf_bwdif.c
@@ -395,7 +395,6 @@  static const AVFilterPad avfilter_vf_bwdif_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = ff_yadif_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_bwdif_outputs[] = {
@@ -405,7 +404,6 @@  static const AVFilterPad avfilter_vf_bwdif_outputs[] = {
         .request_frame = ff_yadif_request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_bwdif = {
@@ -416,6 +414,8 @@  const AVFilter ff_vf_bwdif = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_bwdif_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_bwdif_inputs),
     .outputs       = avfilter_vf_bwdif_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_bwdif_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_cas.c b/libavfilter/vf_cas.c
index c5a53adfe9..3698d062ac 100644
--- a/libavfilter/vf_cas.c
+++ b/libavfilter/vf_cas.c
@@ -264,7 +264,6 @@  static const AVFilterPad cas_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad cas_outputs[] = {
@@ -272,7 +271,6 @@  static const AVFilterPad cas_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(CASContext, x)
@@ -293,7 +291,9 @@  const AVFilter ff_vf_cas = {
     .priv_class    = &cas_class,
     .query_formats = query_formats,
     .inputs        = cas_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(cas_inputs),
     .outputs       = cas_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(cas_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c
index 2f5bf7bbb9..ac2d22074d 100644
--- a/libavfilter/vf_chromaber_vulkan.c
+++ b/libavfilter/vf_chromaber_vulkan.c
@@ -321,7 +321,6 @@  static const AVFilterPad chromaber_vulkan_inputs[] = {
         .filter_frame = &chromaber_vulkan_filter_frame,
         .config_props = &ff_vk_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad chromaber_vulkan_outputs[] = {
@@ -330,7 +329,6 @@  static const AVFilterPad chromaber_vulkan_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vk_filter_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_chromaber_vulkan = {
@@ -341,7 +339,9 @@  const AVFilter ff_vf_chromaber_vulkan = {
     .uninit         = &chromaber_vulkan_uninit,
     .query_formats  = &ff_vk_filter_query_formats,
     .inputs         = chromaber_vulkan_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(chromaber_vulkan_inputs),
     .outputs        = chromaber_vulkan_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(chromaber_vulkan_outputs),
     .priv_class     = &chromaber_vulkan_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_chromakey.c b/libavfilter/vf_chromakey.c
index 45d8e43c2c..3d93e67dc0 100644
--- a/libavfilter/vf_chromakey.c
+++ b/libavfilter/vf_chromakey.c
@@ -373,7 +373,6 @@  static const AVFilterPad chromakey_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad chromakey_outputs[] = {
@@ -382,7 +381,6 @@  static const AVFilterPad chromakey_outputs[] = {
         .type           = AVMEDIA_TYPE_VIDEO,
         .config_props   = config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ChromakeyContext, x)
@@ -405,7 +403,9 @@  const AVFilter ff_vf_chromakey = {
     .priv_class    = &chromakey_class,
     .query_formats = query_formats,
     .inputs        = chromakey_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(chromakey_inputs),
     .outputs       = chromakey_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(chromakey_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -426,7 +426,6 @@  static const AVFilterPad chromahold_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad chromahold_outputs[] = {
@@ -435,7 +434,6 @@  static const AVFilterPad chromahold_outputs[] = {
         .type           = AVMEDIA_TYPE_VIDEO,
         .config_props   = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(chromahold);
@@ -447,7 +445,9 @@  const AVFilter ff_vf_chromahold = {
     .priv_class    = &chromahold_class,
     .query_formats = query_formats,
     .inputs        = chromahold_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(chromahold_inputs),
     .outputs       = chromahold_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(chromahold_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_chromanr.c b/libavfilter/vf_chromanr.c
index 810fd2ce9d..a6dabc5e46 100644
--- a/libavfilter/vf_chromanr.c
+++ b/libavfilter/vf_chromanr.c
@@ -267,7 +267,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -275,7 +274,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(chromanr);
@@ -287,7 +285,9 @@  const AVFilter ff_vf_chromanr = {
     .priv_class    = &chromanr_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_chromashift.c b/libavfilter/vf_chromashift.c
index 3f172a8e2b..d4d5f136fb 100644
--- a/libavfilter/vf_chromashift.c
+++ b/libavfilter/vf_chromashift.c
@@ -433,7 +433,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -441,7 +440,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(chromashift);
@@ -453,7 +451,9 @@  const AVFilter ff_vf_chromashift = {
     .priv_class    = &chromashift_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -482,7 +482,9 @@  const AVFilter ff_vf_rgbashift = {
     .priv_class    = &rgbashift_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c
index cafdb915ea..2723e3d662 100644
--- a/libavfilter/vf_ciescope.c
+++ b/libavfilter/vf_ciescope.c
@@ -1492,7 +1492,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1501,7 +1500,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_ciescope = {
@@ -1512,5 +1510,7 @@  const AVFilter ff_vf_ciescope = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c
index e3c613f10c..6eeb9c2f33 100644
--- a/libavfilter/vf_codecview.c
+++ b/libavfilter/vf_codecview.c
@@ -307,7 +307,6 @@  static const AVFilterPad codecview_inputs[] = {
         .config_props   = config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad codecview_outputs[] = {
@@ -315,7 +314,6 @@  static const AVFilterPad codecview_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_codecview = {
@@ -324,7 +322,9 @@  const AVFilter ff_vf_codecview = {
     .priv_size     = sizeof(CodecViewContext),
     .query_formats = query_formats,
     .inputs        = codecview_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(codecview_inputs),
     .outputs       = codecview_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(codecview_outputs),
     .priv_class    = &codecview_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_colorbalance.c b/libavfilter/vf_colorbalance.c
index 4e13ce97b9..2d83cc4bc2 100644
--- a/libavfilter/vf_colorbalance.c
+++ b/libavfilter/vf_colorbalance.c
@@ -427,7 +427,6 @@  static const AVFilterPad colorbalance_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorbalance_outputs[] = {
@@ -436,7 +435,6 @@  static const AVFilterPad colorbalance_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_colorbalance = {
@@ -446,7 +444,9 @@  const AVFilter ff_vf_colorbalance = {
     .priv_class    = &colorbalance_class,
     .query_formats = query_formats,
     .inputs        = colorbalance_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorbalance_inputs),
     .outputs       = colorbalance_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorbalance_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colorchannelmixer.c b/libavfilter/vf_colorchannelmixer.c
index 9a538ddf5f..0146fb6ee3 100644
--- a/libavfilter/vf_colorchannelmixer.c
+++ b/libavfilter/vf_colorchannelmixer.c
@@ -787,7 +787,6 @@  static const AVFilterPad colorchannelmixer_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorchannelmixer_outputs[] = {
@@ -796,7 +795,6 @@  static const AVFilterPad colorchannelmixer_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_colorchannelmixer = {
@@ -807,7 +805,9 @@  const AVFilter ff_vf_colorchannelmixer = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = colorchannelmixer_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorchannelmixer_inputs),
     .outputs       = colorchannelmixer_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorchannelmixer_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_colorconstancy.c b/libavfilter/vf_colorconstancy.c
index e44d9afa01..c5ca6ba0f4 100644
--- a/libavfilter/vf_colorconstancy.c
+++ b/libavfilter/vf_colorconstancy.c
@@ -725,7 +725,6 @@  static const AVFilterPad colorconstancy_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorconstancy_outputs[] = {
@@ -733,7 +732,6 @@  static const AVFilterPad colorconstancy_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #if CONFIG_GREYEDGE_FILTER
@@ -755,7 +753,9 @@  const AVFilter ff_vf_greyedge = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = colorconstancy_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(colorconstancy_inputs),
     .outputs       = colorconstancy_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(colorconstancy_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
 
diff --git a/libavfilter/vf_colorcontrast.c b/libavfilter/vf_colorcontrast.c
index b5b547b46f..6e981709d6 100644
--- a/libavfilter/vf_colorcontrast.c
+++ b/libavfilter/vf_colorcontrast.c
@@ -368,7 +368,6 @@  static const AVFilterPad colorcontrast_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorcontrast_outputs[] = {
@@ -376,7 +375,6 @@  static const AVFilterPad colorcontrast_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorContrastContext, x)
@@ -402,7 +400,9 @@  const AVFilter ff_vf_colorcontrast = {
     .priv_class    = &colorcontrast_class,
     .query_formats = query_formats,
     .inputs        = colorcontrast_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorcontrast_inputs),
     .outputs       = colorcontrast_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorcontrast_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colorcorrect.c b/libavfilter/vf_colorcorrect.c
index 13ef50ad1d..f86811369f 100644
--- a/libavfilter/vf_colorcorrect.c
+++ b/libavfilter/vf_colorcorrect.c
@@ -179,7 +179,6 @@  static const AVFilterPad colorcorrect_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorcorrect_outputs[] = {
@@ -187,7 +186,6 @@  static const AVFilterPad colorcorrect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorCorrectContext, x)
@@ -211,7 +209,9 @@  const AVFilter ff_vf_colorcorrect = {
     .priv_class    = &colorcorrect_class,
     .query_formats = query_formats,
     .inputs        = colorcorrect_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorcorrect_inputs),
     .outputs       = colorcorrect_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorcorrect_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colorize.c b/libavfilter/vf_colorize.c
index 653832ab92..b5bd24419f 100644
--- a/libavfilter/vf_colorize.c
+++ b/libavfilter/vf_colorize.c
@@ -269,7 +269,6 @@  static const AVFilterPad colorize_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorize_outputs[] = {
@@ -277,7 +276,6 @@  static const AVFilterPad colorize_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorizeContext, x)
@@ -300,7 +298,9 @@  const AVFilter ff_vf_colorize = {
     .priv_class    = &colorize_class,
     .query_formats = query_formats,
     .inputs        = colorize_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorize_inputs),
     .outputs       = colorize_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorize_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colorkey.c b/libavfilter/vf_colorkey.c
index e0b4372842..ea14ef4dbe 100644
--- a/libavfilter/vf_colorkey.c
+++ b/libavfilter/vf_colorkey.c
@@ -186,7 +186,6 @@  static const AVFilterPad colorkey_inputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorkey_outputs[] = {
@@ -195,7 +194,6 @@  static const AVFilterPad colorkey_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorkeyContext, x)
@@ -220,7 +218,9 @@  const AVFilter ff_vf_colorkey = {
     .query_formats = query_formats,
     .init          = init_filter,
     .inputs        = colorkey_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorkey_inputs),
     .outputs       = colorkey_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorkey_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
@@ -245,7 +245,9 @@  const AVFilter ff_vf_colorhold = {
     .query_formats = query_formats,
     .init          = init_filter,
     .inputs        = colorkey_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorkey_inputs),
     .outputs       = colorkey_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorkey_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colorkey_opencl.c b/libavfilter/vf_colorkey_opencl.c
index cd312ea53e..e14204de8f 100644
--- a/libavfilter/vf_colorkey_opencl.c
+++ b/libavfilter/vf_colorkey_opencl.c
@@ -206,7 +206,6 @@  static const AVFilterPad colorkey_opencl_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorkey_opencl_outputs[] = {
@@ -215,7 +214,6 @@  static const AVFilterPad colorkey_opencl_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorkeyOpenCLContext, x)
@@ -239,6 +237,8 @@  const AVFilter ff_vf_colorkey_opencl = {
     .uninit         = &colorkey_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = colorkey_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(colorkey_opencl_inputs),
     .outputs        = colorkey_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(colorkey_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE
 };
diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c
index 8bc0d96df0..8b126295de 100644
--- a/libavfilter/vf_colorlevels.c
+++ b/libavfilter/vf_colorlevels.c
@@ -304,7 +304,6 @@  static const AVFilterPad colorlevels_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad colorlevels_outputs[] = {
@@ -312,7 +311,6 @@  static const AVFilterPad colorlevels_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_colorlevels = {
@@ -322,7 +320,9 @@  const AVFilter ff_vf_colorlevels = {
     .priv_class    = &colorlevels_class,
     .query_formats = query_formats,
     .inputs        = colorlevels_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(colorlevels_inputs),
     .outputs       = colorlevels_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(colorlevels_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_colormatrix.c b/libavfilter/vf_colormatrix.c
index c304f2dba8..cdd4d11ff4 100644
--- a/libavfilter/vf_colormatrix.c
+++ b/libavfilter/vf_colormatrix.c
@@ -496,7 +496,6 @@  static const AVFilterPad colormatrix_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad colormatrix_outputs[] = {
@@ -504,7 +503,6 @@  static const AVFilterPad colormatrix_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_colormatrix = {
@@ -514,7 +512,9 @@  const AVFilter ff_vf_colormatrix = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = colormatrix_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(colormatrix_inputs),
     .outputs       = colormatrix_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(colormatrix_outputs),
     .priv_class    = &colormatrix_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c
index 65e072d137..0c23cf3cda 100644
--- a/libavfilter/vf_colorspace.c
+++ b/libavfilter/vf_colorspace.c
@@ -1057,7 +1057,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1066,7 +1065,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_colorspace = {
@@ -1078,6 +1076,8 @@  const AVFilter ff_vf_colorspace = {
     .priv_size       = sizeof(ColorSpaceContext),
     .priv_class      = &colorspace_class,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_colortemperature.c b/libavfilter/vf_colortemperature.c
index 1a4c9261f6..b0cfa85556 100644
--- a/libavfilter/vf_colortemperature.c
+++ b/libavfilter/vf_colortemperature.c
@@ -334,7 +334,6 @@  static const AVFilterPad inputs[] = {
         .config_props   = config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -342,7 +341,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ColorTemperatureContext, x)
@@ -364,7 +362,9 @@  const AVFilter ff_vf_colortemperature = {
     .priv_class    = &colortemperature_class,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index c0fc7356bd..3123cd523e 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -889,7 +889,6 @@  static const AVFilterPad convolution_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad convolution_outputs[] = {
@@ -897,7 +896,6 @@  static const AVFilterPad convolution_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #if CONFIG_CONVOLUTION_FILTER
@@ -910,7 +908,9 @@  const AVFilter ff_vf_convolution = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = convolution_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(convolution_inputs),
     .outputs       = convolution_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(convolution_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -939,7 +939,9 @@  const AVFilter ff_vf_prewitt = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = convolution_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(convolution_inputs),
     .outputs       = convolution_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(convolution_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -959,7 +961,9 @@  const AVFilter ff_vf_sobel = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = convolution_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(convolution_inputs),
     .outputs       = convolution_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(convolution_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -979,7 +983,9 @@  const AVFilter ff_vf_roberts = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = convolution_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(convolution_inputs),
     .outputs       = convolution_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(convolution_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -999,7 +1005,9 @@  const AVFilter ff_vf_kirsch = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = convolution_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(convolution_inputs),
     .outputs       = convolution_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(convolution_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_convolution_opencl.c b/libavfilter/vf_convolution_opencl.c
index c6218d3cd6..ef525e7e94 100644
--- a/libavfilter/vf_convolution_opencl.c
+++ b/libavfilter/vf_convolution_opencl.c
@@ -327,7 +327,6 @@  static const AVFilterPad convolution_opencl_inputs[] = {
         .filter_frame = &convolution_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad convolution_opencl_outputs[] = {
@@ -336,7 +335,6 @@  static const AVFilterPad convolution_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ConvolutionOpenCLContext, x)
@@ -371,7 +369,9 @@  const AVFilter ff_vf_convolution_opencl = {
     .uninit         = &convolution_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = convolution_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(convolution_opencl_inputs),
     .outputs        = convolution_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(convolution_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -397,7 +397,9 @@  const AVFilter ff_vf_sobel_opencl = {
     .uninit         = &convolution_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = convolution_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(convolution_opencl_inputs),
     .outputs        = convolution_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(convolution_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -423,7 +425,9 @@  const AVFilter ff_vf_prewitt_opencl = {
     .uninit         = &convolution_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = convolution_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(convolution_opencl_inputs),
     .outputs        = convolution_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(convolution_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -449,7 +453,9 @@  const AVFilter ff_vf_roberts_opencl = {
     .uninit         = &convolution_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = convolution_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(convolution_opencl_inputs),
     .outputs        = convolution_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(convolution_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c
index a0066bbd39..62a2798215 100644
--- a/libavfilter/vf_convolve.c
+++ b/libavfilter/vf_convolve.c
@@ -609,7 +609,6 @@  static const AVFilterPad convolve_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_input_impulse,
     },
-    { NULL }
 };
 
 static const AVFilterPad convolve_outputs[] = {
@@ -618,7 +617,6 @@  static const AVFilterPad convolve_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_CONVOLVE_FILTER
@@ -636,7 +634,9 @@  const AVFilter ff_vf_convolve = {
     .priv_size     = sizeof(ConvolveContext),
     .priv_class    = &convolve_class,
     .inputs        = convolve_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(convolve_inputs),
     .outputs       = convolve_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(convolve_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
 
@@ -666,7 +666,9 @@  const AVFilter ff_vf_deconvolve = {
     .priv_size     = sizeof(ConvolveContext),
     .priv_class    = &deconvolve_class,
     .inputs        = convolve_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(convolve_inputs),
     .outputs       = convolve_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(convolve_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
 
diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c
index f50ac70c92..2d243fa155 100644
--- a/libavfilter/vf_copy.c
+++ b/libavfilter/vf_copy.c
@@ -70,7 +70,6 @@  static const AVFilterPad avfilter_vf_copy_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_copy_outputs[] = {
@@ -78,13 +77,14 @@  static const AVFilterPad avfilter_vf_copy_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_copy = {
     .name        = "copy",
     .description = NULL_IF_CONFIG_SMALL("Copy the input video unchanged to the output."),
     .inputs      = avfilter_vf_copy_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_copy_inputs),
     .outputs     = avfilter_vf_copy_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_copy_outputs),
     .query_formats = query_formats,
 };
diff --git a/libavfilter/vf_cover_rect.c b/libavfilter/vf_cover_rect.c
index 337778224d..0b7f6169de 100644
--- a/libavfilter/vf_cover_rect.c
+++ b/libavfilter/vf_cover_rect.c
@@ -236,7 +236,6 @@  static const AVFilterPad cover_rect_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad cover_rect_outputs[] = {
@@ -244,7 +243,6 @@  static const AVFilterPad cover_rect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_cover_rect = {
@@ -255,6 +253,8 @@  const AVFilter ff_vf_cover_rect = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = cover_rect_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(cover_rect_inputs),
     .outputs         = cover_rect_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(cover_rect_outputs),
     .priv_class      = &cover_rect_class,
 };
diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index 9cc9ec2844..b2e2a5b23a 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -380,7 +380,6 @@  static const AVFilterPad avfilter_vf_crop_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_crop_outputs[] = {
@@ -389,7 +388,6 @@  static const AVFilterPad avfilter_vf_crop_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_crop = {
@@ -400,6 +398,8 @@  const AVFilter ff_vf_crop = {
     .query_formats   = query_formats,
     .uninit          = uninit,
     .inputs          = avfilter_vf_crop_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_crop_inputs),
     .outputs         = avfilter_vf_crop_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_crop_outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c
index deeb9e480a..35f03f5995 100644
--- a/libavfilter/vf_cropdetect.c
+++ b/libavfilter/vf_cropdetect.c
@@ -263,7 +263,6 @@  static const AVFilterPad avfilter_vf_cropdetect_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_cropdetect_outputs[] = {
@@ -271,7 +270,6 @@  static const AVFilterPad avfilter_vf_cropdetect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_cropdetect = {
@@ -282,6 +280,8 @@  const AVFilter ff_vf_cropdetect = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_cropdetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_cropdetect_inputs),
     .outputs       = avfilter_vf_cropdetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_cropdetect_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 64cfea1527..e309354c36 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -802,7 +802,6 @@  static const AVFilterPad curves_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad curves_outputs[] = {
@@ -810,7 +809,6 @@  static const AVFilterPad curves_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_curves = {
@@ -821,7 +819,9 @@  const AVFilter ff_vf_curves = {
     .uninit        = curves_uninit,
     .query_formats = query_formats,
     .inputs        = curves_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(curves_inputs),
     .outputs       = curves_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(curves_outputs),
     .priv_class    = &curves_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c
index 63c93fd98d..d45cd2d659 100644
--- a/libavfilter/vf_datascope.c
+++ b/libavfilter/vf_datascope.c
@@ -437,7 +437,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -446,7 +445,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_datascope = {
@@ -456,7 +454,9 @@  const AVFilter ff_vf_datascope = {
     .priv_class    = &datascope_class,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
@@ -727,7 +727,6 @@  static const AVFilterPad pixscope_inputs[] = {
         .filter_frame   = pixscope_filter_frame,
         .config_props   = pixscope_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad pixscope_outputs[] = {
@@ -735,7 +734,6 @@  static const AVFilterPad pixscope_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pixscope = {
@@ -745,7 +743,9 @@  const AVFilter ff_vf_pixscope = {
     .priv_class    = &pixscope_class,
     .query_formats = query_formats,
     .inputs        = pixscope_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(pixscope_inputs),
     .outputs       = pixscope_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(pixscope_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = pixscope_process_command,
 };
@@ -1133,7 +1133,6 @@  static const AVFilterPad oscilloscope_inputs[] = {
         .config_props   = oscilloscope_config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad oscilloscope_outputs[] = {
@@ -1141,7 +1140,6 @@  static const AVFilterPad oscilloscope_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_oscilloscope = {
@@ -1152,7 +1150,9 @@  const AVFilter ff_vf_oscilloscope = {
     .query_formats = query_formats,
     .uninit        = oscilloscope_uninit,
     .inputs        = oscilloscope_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(oscilloscope_inputs),
     .outputs       = oscilloscope_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(oscilloscope_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = oscilloscope_process_command,
 };
diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c
index dcb6635c95..ee1ff56c61 100644
--- a/libavfilter/vf_dblur.c
+++ b/libavfilter/vf_dblur.c
@@ -281,7 +281,6 @@  static const AVFilterPad dblur_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad dblur_outputs[] = {
@@ -289,7 +288,6 @@  static const AVFilterPad dblur_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dblur = {
@@ -300,7 +298,9 @@  const AVFilter ff_vf_dblur = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = dblur_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(dblur_inputs),
     .outputs       = dblur_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(dblur_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_dctdnoiz.c b/libavfilter/vf_dctdnoiz.c
index c7f949f9f5..f200ff87bd 100644
--- a/libavfilter/vf_dctdnoiz.c
+++ b/libavfilter/vf_dctdnoiz.c
@@ -814,7 +814,6 @@  static const AVFilterPad dctdnoiz_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad dctdnoiz_outputs[] = {
@@ -822,7 +821,6 @@  static const AVFilterPad dctdnoiz_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dctdnoiz = {
@@ -833,7 +831,9 @@  const AVFilter ff_vf_dctdnoiz = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = dctdnoiz_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(dctdnoiz_inputs),
     .outputs       = dctdnoiz_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(dctdnoiz_outputs),
     .priv_class    = &dctdnoiz_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_deband.c b/libavfilter/vf_deband.c
index aa560bd9fb..611397a6d2 100644
--- a/libavfilter/vf_deband.c
+++ b/libavfilter/vf_deband.c
@@ -460,7 +460,6 @@  static const AVFilterPad avfilter_vf_deband_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_deband_outputs[] = {
@@ -468,7 +467,6 @@  static const AVFilterPad avfilter_vf_deband_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_deband = {
@@ -479,7 +477,9 @@  const AVFilter ff_vf_deband = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_deband_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_deband_inputs),
     .outputs       = avfilter_vf_deband_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_deband_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_deblock.c b/libavfilter/vf_deblock.c
index 2d91fe358b..05bb98a463 100644
--- a/libavfilter/vf_deblock.c
+++ b/libavfilter/vf_deblock.c
@@ -401,7 +401,6 @@  static const AVFilterPad inputs[] = {
         .type           = AVMEDIA_TYPE_VIDEO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -410,7 +409,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(deblock);
@@ -422,7 +420,9 @@  const AVFilter ff_vf_deblock = {
     .priv_class    = &deblock_class,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c
index 72ed349427..bbd7e1955f 100644
--- a/libavfilter/vf_decimate.c
+++ b/libavfilter/vf_decimate.c
@@ -431,7 +431,6 @@  static const AVFilterPad decimate_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_decimate = {
@@ -443,6 +442,7 @@  const AVFilter ff_vf_decimate = {
     .priv_size     = sizeof(DecimateContext),
     .query_formats = query_formats,
     .outputs       = decimate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(decimate_outputs),
     .priv_class    = &decimate_class,
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/vf_dedot.c b/libavfilter/vf_dedot.c
index b79d4a51c4..df60dc1dbe 100644
--- a/libavfilter/vf_dedot.c
+++ b/libavfilter/vf_dedot.c
@@ -387,7 +387,6 @@  static const AVFilterPad inputs[] = {
         .name           = "default",
         .type           = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -396,7 +395,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(dedot);
@@ -410,6 +408,8 @@  const AVFilter ff_vf_dedot = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_deflicker.c b/libavfilter/vf_deflicker.c
index 1ce8a482e8..51dbadb715 100644
--- a/libavfilter/vf_deflicker.c
+++ b/libavfilter/vf_deflicker.c
@@ -454,7 +454,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -463,7 +462,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_deflicker = {
@@ -474,5 +472,7 @@  const AVFilter ff_vf_deflicker = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_deinterlace_qsv.c b/libavfilter/vf_deinterlace_qsv.c
index 3c2d87c7c8..b51dc598fc 100644
--- a/libavfilter/vf_deinterlace_qsv.c
+++ b/libavfilter/vf_deinterlace_qsv.c
@@ -581,7 +581,6 @@  static const AVFilterPad qsvdeint_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = qsvdeint_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad qsvdeint_outputs[] = {
@@ -591,7 +590,6 @@  static const AVFilterPad qsvdeint_outputs[] = {
         .config_props  = qsvdeint_config_props,
         .request_frame = qsvdeint_request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_deinterlace_qsv = {
@@ -605,7 +603,9 @@  const AVFilter ff_vf_deinterlace_qsv = {
     .priv_class = &qsvdeint_class,
 
     .inputs    = qsvdeint_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(qsvdeint_inputs),
     .outputs   = qsvdeint_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(qsvdeint_outputs),
 
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c
index fa71947098..3f60f40b94 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -369,7 +369,6 @@  static const AVFilterPad deint_vaapi_inputs[] = {
         .filter_frame = &deint_vaapi_filter_frame,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad deint_vaapi_outputs[] = {
@@ -378,7 +377,6 @@  static const AVFilterPad deint_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &deint_vaapi_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_deinterlace_vaapi = {
@@ -389,7 +387,9 @@  const AVFilter ff_vf_deinterlace_vaapi = {
     .uninit         = &ff_vaapi_vpp_ctx_uninit,
     .query_formats  = &ff_vaapi_vpp_query_formats,
     .inputs         = deint_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(deint_vaapi_inputs),
     .outputs        = deint_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(deint_vaapi_outputs),
     .priv_class     = &deint_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_dejudder.c b/libavfilter/vf_dejudder.c
index 5816f82322..f18158ff62 100644
--- a/libavfilter/vf_dejudder.c
+++ b/libavfilter/vf_dejudder.c
@@ -163,7 +163,6 @@  static const AVFilterPad dejudder_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad dejudder_outputs[] = {
@@ -172,7 +171,6 @@  static const AVFilterPad dejudder_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = config_out_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dejudder = {
@@ -181,7 +179,9 @@  const AVFilter ff_vf_dejudder = {
     .priv_size   = sizeof(DejudderContext),
     .priv_class  = &dejudder_class,
     .inputs      = dejudder_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(dejudder_inputs),
     .outputs     = dejudder_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(dejudder_outputs),
     .init        = dejudder_init,
     .uninit      = dejudder_uninit,
 };
diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c
index 9838301702..ba814bdeac 100644
--- a/libavfilter/vf_delogo.c
+++ b/libavfilter/vf_delogo.c
@@ -387,7 +387,6 @@  static const AVFilterPad avfilter_vf_delogo_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_delogo_outputs[] = {
@@ -395,7 +394,6 @@  static const AVFilterPad avfilter_vf_delogo_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_delogo = {
@@ -407,6 +405,8 @@  const AVFilter ff_vf_delogo = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_delogo_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_delogo_inputs),
     .outputs       = avfilter_vf_delogo_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_delogo_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_derain.c b/libavfilter/vf_derain.c
index 5037f3a5f7..4d93232640 100644
--- a/libavfilter/vf_derain.c
+++ b/libavfilter/vf_derain.c
@@ -115,7 +115,6 @@  static const AVFilterPad derain_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad derain_outputs[] = {
@@ -123,7 +122,6 @@  static const AVFilterPad derain_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_derain = {
@@ -134,7 +132,9 @@  const AVFilter ff_vf_derain = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = derain_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(derain_inputs),
     .outputs       = derain_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(derain_outputs),
     .priv_class    = &derain_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c
index 4ff6a94702..bd8531ba13 100644
--- a/libavfilter/vf_deshake.c
+++ b/libavfilter/vf_deshake.c
@@ -540,7 +540,6 @@  static const AVFilterPad deshake_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad deshake_outputs[] = {
@@ -548,7 +547,6 @@  static const AVFilterPad deshake_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_deshake = {
@@ -559,6 +557,8 @@  const AVFilter ff_vf_deshake = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = deshake_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(deshake_inputs),
     .outputs       = deshake_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(deshake_outputs),
     .priv_class    = &deshake_class,
 };
diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c
index 2fd682003f..cecca78249 100644
--- a/libavfilter/vf_deshake_opencl.c
+++ b/libavfilter/vf_deshake_opencl.c
@@ -2141,7 +2141,6 @@  static const AVFilterPad deshake_opencl_inputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad deshake_opencl_outputs[] = {
@@ -2150,7 +2149,6 @@  static const AVFilterPad deshake_opencl_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(DeshakeOpenCLContext, x)
@@ -2197,6 +2195,8 @@  const AVFilter ff_vf_deshake_opencl = {
     .query_formats  = &ff_opencl_filter_query_formats,
     .activate       = activate,
     .inputs         = deshake_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(deshake_opencl_inputs),
     .outputs        = deshake_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(deshake_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE
 };
diff --git a/libavfilter/vf_despill.c b/libavfilter/vf_despill.c
index e0990d7443..8eaede1dad 100644
--- a/libavfilter/vf_despill.c
+++ b/libavfilter/vf_despill.c
@@ -140,7 +140,6 @@  static const AVFilterPad despill_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad despill_outputs[] = {
@@ -149,7 +148,6 @@  static const AVFilterPad despill_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(DespillContext, x)
@@ -178,7 +176,9 @@  const AVFilter ff_vf_despill = {
     .priv_class    = &despill_class,
     .query_formats = query_formats,
     .inputs        = despill_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(despill_inputs),
     .outputs       = despill_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(despill_outputs),
     .process_command = ff_filter_process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_detelecine.c b/libavfilter/vf_detelecine.c
index e345e3062a..fdda60954b 100644
--- a/libavfilter/vf_detelecine.c
+++ b/libavfilter/vf_detelecine.c
@@ -360,7 +360,6 @@  static const AVFilterPad detelecine_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad detelecine_outputs[] = {
@@ -369,7 +368,6 @@  static const AVFilterPad detelecine_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_detelecine = {
@@ -381,5 +379,7 @@  const AVFilter ff_vf_detelecine = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = detelecine_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(detelecine_inputs),
     .outputs       = detelecine_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(detelecine_outputs),
 };
diff --git a/libavfilter/vf_displace.c b/libavfilter/vf_displace.c
index 9c310e1740..71da73a022 100644
--- a/libavfilter/vf_displace.c
+++ b/libavfilter/vf_displace.c
@@ -388,7 +388,6 @@  static const AVFilterPad displace_inputs[] = {
         .name         = "ymap",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad displace_outputs[] = {
@@ -397,7 +396,6 @@  static const AVFilterPad displace_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_displace = {
@@ -408,7 +406,9 @@  const AVFilter ff_vf_displace = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = displace_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(displace_inputs),
     .outputs       = displace_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(displace_outputs),
     .priv_class    = &displace_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_dnn_classify.c b/libavfilter/vf_dnn_classify.c
index 7900255cfe..14ad008265 100644
--- a/libavfilter/vf_dnn_classify.c
+++ b/libavfilter/vf_dnn_classify.c
@@ -309,7 +309,6 @@  static const AVFilterPad dnn_classify_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad dnn_classify_outputs[] = {
@@ -317,7 +316,6 @@  static const AVFilterPad dnn_classify_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dnn_classify = {
@@ -328,7 +326,9 @@  const AVFilter ff_vf_dnn_classify = {
     .uninit        = dnn_classify_uninit,
     .query_formats = dnn_classify_query_formats,
     .inputs        = dnn_classify_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(dnn_classify_inputs),
     .outputs       = dnn_classify_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(dnn_classify_outputs),
     .priv_class    = &dnn_classify_class,
     .activate      = dnn_classify_activate,
 };
diff --git a/libavfilter/vf_dnn_detect.c b/libavfilter/vf_dnn_detect.c
index d23e30aedd..43f3003d07 100644
--- a/libavfilter/vf_dnn_detect.c
+++ b/libavfilter/vf_dnn_detect.c
@@ -519,7 +519,6 @@  static const AVFilterPad dnn_detect_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad dnn_detect_outputs[] = {
@@ -527,7 +526,6 @@  static const AVFilterPad dnn_detect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dnn_detect = {
@@ -538,7 +536,9 @@  const AVFilter ff_vf_dnn_detect = {
     .uninit        = dnn_detect_uninit,
     .query_formats = dnn_detect_query_formats,
     .inputs        = dnn_detect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(dnn_detect_inputs),
     .outputs       = dnn_detect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(dnn_detect_outputs),
     .priv_class    = &dnn_detect_class,
     .activate      = dnn_detect_activate,
 };
diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c
index e1d9d24683..eeb5c356e4 100644
--- a/libavfilter/vf_dnn_processing.c
+++ b/libavfilter/vf_dnn_processing.c
@@ -435,7 +435,6 @@  static const AVFilterPad dnn_processing_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad dnn_processing_outputs[] = {
@@ -444,7 +443,6 @@  static const AVFilterPad dnn_processing_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_dnn_processing = {
@@ -455,7 +453,9 @@  const AVFilter ff_vf_dnn_processing = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = dnn_processing_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(dnn_processing_inputs),
     .outputs       = dnn_processing_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(dnn_processing_outputs),
     .priv_class    = &dnn_processing_class,
     .activate      = activate,
 };
diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c
index 1e9e028650..4b5e1a58f6 100644
--- a/libavfilter/vf_drawbox.c
+++ b/libavfilter/vf_drawbox.c
@@ -391,7 +391,6 @@  static const AVFilterPad drawbox_inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad drawbox_outputs[] = {
@@ -399,7 +398,6 @@  static const AVFilterPad drawbox_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_drawbox = {
@@ -410,7 +408,9 @@  const AVFilter ff_vf_drawbox = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = drawbox_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(drawbox_inputs),
     .outputs       = drawbox_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(drawbox_outputs),
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
@@ -475,7 +475,6 @@  static const AVFilterPad drawgrid_inputs[] = {
         .filter_frame   = drawgrid_filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad drawgrid_outputs[] = {
@@ -483,7 +482,6 @@  static const AVFilterPad drawgrid_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_drawgrid = {
@@ -494,7 +492,9 @@  const AVFilter ff_vf_drawgrid = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = drawgrid_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(drawgrid_inputs),
     .outputs       = drawgrid_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(drawgrid_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index c4c09894e4..9fabdc665d 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -1619,7 +1619,6 @@  static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
         .config_props   = config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_drawtext_outputs[] = {
@@ -1627,7 +1626,6 @@  static const AVFilterPad avfilter_vf_drawtext_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_drawtext = {
@@ -1639,7 +1637,9 @@  const AVFilter ff_vf_drawtext = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_drawtext_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_drawtext_inputs),
     .outputs       = avfilter_vf_drawtext_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_drawtext_outputs),
     .process_command = command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c
index e21d341fd2..9283f77738 100644
--- a/libavfilter/vf_edgedetect.c
+++ b/libavfilter/vf_edgedetect.c
@@ -420,7 +420,6 @@  static const AVFilterPad edgedetect_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad edgedetect_outputs[] = {
@@ -428,7 +427,6 @@  static const AVFilterPad edgedetect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_edgedetect = {
@@ -439,7 +437,9 @@  const AVFilter ff_vf_edgedetect = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = edgedetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(edgedetect_inputs),
     .outputs       = edgedetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(edgedetect_outputs),
     .priv_class    = &edgedetect_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_elbg.c b/libavfilter/vf_elbg.c
index 008f470068..d4d02487da 100644
--- a/libavfilter/vf_elbg.c
+++ b/libavfilter/vf_elbg.c
@@ -242,7 +242,6 @@  static const AVFilterPad elbg_inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad elbg_outputs[] = {
@@ -250,7 +249,6 @@  static const AVFilterPad elbg_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_elbg = {
@@ -262,5 +260,7 @@  const AVFilter ff_vf_elbg = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = elbg_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(elbg_inputs),
     .outputs       = elbg_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(elbg_outputs),
 };
diff --git a/libavfilter/vf_entropy.c b/libavfilter/vf_entropy.c
index 32f4bac95d..87b4edd37f 100644
--- a/libavfilter/vf_entropy.c
+++ b/libavfilter/vf_entropy.c
@@ -182,7 +182,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -190,7 +189,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_entropy = {
@@ -200,7 +198,9 @@  const AVFilter ff_vf_entropy = {
     .uninit         = uninit,
     .query_formats  = query_formats,
     .inputs         = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs        = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .priv_class     = &entropy_class,
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_epx.c b/libavfilter/vf_epx.c
index 676513c302..df6b2c2632 100644
--- a/libavfilter/vf_epx.c
+++ b/libavfilter/vf_epx.c
@@ -262,7 +262,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -271,14 +270,15 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_epx = {
     .name          = "epx",
     .description   = NULL_IF_CONFIG_SMALL("Scale the input using EPX algorithm."),
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .query_formats = query_formats,
     .priv_size     = sizeof(EPXContext),
     .priv_class    = &epx_class,
diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c
index 7d740d501a..5f33b564dd 100644
--- a/libavfilter/vf_eq.c
+++ b/libavfilter/vf_eq.c
@@ -338,7 +338,6 @@  static const AVFilterPad eq_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad eq_outputs[] = {
@@ -346,7 +345,6 @@  static const AVFilterPad eq_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(EQContext, x)
@@ -383,7 +381,9 @@  const AVFilter ff_vf_eq = {
     .priv_size       = sizeof(EQContext),
     .priv_class      = &eq_class,
     .inputs          = eq_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(eq_inputs),
     .outputs         = eq_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(eq_outputs),
     .process_command = process_command,
     .query_formats   = query_formats,
     .init            = initialize,
diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c
index 863d453775..724c5e43bb 100644
--- a/libavfilter/vf_estdif.c
+++ b/libavfilter/vf_estdif.c
@@ -562,7 +562,6 @@  static const AVFilterPad estdif_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad estdif_outputs[] = {
@@ -572,7 +571,6 @@  static const AVFilterPad estdif_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_estdif = {
@@ -583,7 +581,9 @@  const AVFilter ff_vf_estdif = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = estdif_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(estdif_inputs),
     .outputs       = estdif_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(estdif_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_exposure.c b/libavfilter/vf_exposure.c
index 5374a8396e..e7520405dc 100644
--- a/libavfilter/vf_exposure.c
+++ b/libavfilter/vf_exposure.c
@@ -109,7 +109,6 @@  static const AVFilterPad exposure_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad exposure_outputs[] = {
@@ -117,7 +116,6 @@  static const AVFilterPad exposure_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(ExposureContext, x)
@@ -138,7 +136,9 @@  const AVFilter ff_vf_exposure = {
     .priv_class    = &exposure_class,
     .query_formats = query_formats,
     .inputs        = exposure_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(exposure_inputs),
     .outputs       = exposure_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(exposure_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index cede3d669e..68cbfe374a 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -376,7 +376,6 @@  static const AVFilterPad extractplanes_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_extractplanes = {
@@ -388,6 +387,7 @@  const AVFilter ff_vf_extractplanes = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = extractplanes_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(extractplanes_inputs),
     .outputs       = NULL,
     .flags         = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
@@ -412,6 +412,7 @@  const AVFilter ff_vf_alphaextract = {
     .uninit         = uninit,
     .query_formats  = query_formats,
     .inputs         = extractplanes_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(extractplanes_inputs),
     .outputs        = NULL,
     .flags          = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
 };
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index 3c65b0f2ac..d00277ed4e 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -557,7 +557,6 @@  static const AVFilterPad avfilter_vf_fade_inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_fade_outputs[] = {
@@ -565,7 +564,6 @@  static const AVFilterPad avfilter_vf_fade_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fade = {
@@ -576,7 +574,9 @@  const AVFilter ff_vf_fade = {
     .priv_class    = &fade_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_fade_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_fade_inputs),
     .outputs       = avfilter_vf_fade_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_fade_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS |
                      AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_fftdnoiz.c b/libavfilter/vf_fftdnoiz.c
index 78dde44e80..3fbb65e4f1 100644
--- a/libavfilter/vf_fftdnoiz.c
+++ b/libavfilter/vf_fftdnoiz.c
@@ -672,7 +672,6 @@  static const AVFilterPad fftdnoiz_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad fftdnoiz_outputs[] = {
@@ -681,7 +680,6 @@  static const AVFilterPad fftdnoiz_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fftdnoiz = {
@@ -692,7 +690,9 @@  const AVFilter ff_vf_fftdnoiz = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = fftdnoiz_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(fftdnoiz_inputs),
     .outputs       = fftdnoiz_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(fftdnoiz_outputs),
     .priv_class    = &fftdnoiz_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_fftfilt.c b/libavfilter/vf_fftfilt.c
index bcef9ff7d2..fd3aa88420 100644
--- a/libavfilter/vf_fftfilt.c
+++ b/libavfilter/vf_fftfilt.c
@@ -417,7 +417,6 @@  static const AVFilterPad fftfilt_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad fftfilt_outputs[] = {
@@ -425,7 +424,6 @@  static const AVFilterPad fftfilt_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fftfilt = {
@@ -434,7 +432,9 @@  const AVFilter ff_vf_fftfilt = {
     .priv_size       = sizeof(FFTFILTContext),
     .priv_class      = &fftfilt_class,
     .inputs          = fftfilt_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(fftfilt_inputs),
     .outputs         = fftfilt_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(fftfilt_outputs),
     .query_formats   = query_formats,
     .init            = initialize,
     .uninit          = uninit,
diff --git a/libavfilter/vf_field.c b/libavfilter/vf_field.c
index 555e615d2e..75b67f2f5d 100644
--- a/libavfilter/vf_field.c
+++ b/libavfilter/vf_field.c
@@ -89,7 +89,6 @@  static const AVFilterPad field_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad field_outputs[] = {
@@ -98,7 +97,6 @@  static const AVFilterPad field_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_props_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_field = {
@@ -106,6 +104,8 @@  const AVFilter ff_vf_field = {
     .description = NULL_IF_CONFIG_SMALL("Extract a field from the input video."),
     .priv_size   = sizeof(FieldContext),
     .inputs      = field_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(field_inputs),
     .outputs     = field_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(field_outputs),
     .priv_class  = &field_class,
 };
diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c
index a6c0237f02..64ca640611 100644
--- a/libavfilter/vf_fieldhint.c
+++ b/libavfilter/vf_fieldhint.c
@@ -284,7 +284,6 @@  static const AVFilterPad inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -293,7 +292,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fieldhint = {
@@ -305,5 +303,7 @@  const AVFilter ff_vf_fieldhint = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index 9626737b40..782f424631 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -1037,7 +1037,6 @@  static const AVFilterPad fieldmatch_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fieldmatch = {
@@ -1050,6 +1049,7 @@  const AVFilter ff_vf_fieldmatch = {
     .uninit         = fieldmatch_uninit,
     .inputs         = NULL,
     .outputs        = fieldmatch_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(fieldmatch_outputs),
     .priv_class     = &fieldmatch_class,
     .flags          = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c
index eefa417fb3..57b9aab197 100644
--- a/libavfilter/vf_fieldorder.c
+++ b/libavfilter/vf_fieldorder.c
@@ -173,7 +173,6 @@  static const AVFilterPad avfilter_vf_fieldorder_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_fieldorder_outputs[] = {
@@ -181,7 +180,6 @@  static const AVFilterPad avfilter_vf_fieldorder_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fieldorder = {
@@ -191,6 +189,8 @@  const AVFilter ff_vf_fieldorder = {
     .priv_class    = &fieldorder_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_fieldorder_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_fieldorder_inputs),
     .outputs       = avfilter_vf_fieldorder_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_fieldorder_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_fillborders.c b/libavfilter/vf_fillborders.c
index 2515bc9de9..6fb4a20255 100644
--- a/libavfilter/vf_fillborders.c
+++ b/libavfilter/vf_fillborders.c
@@ -712,7 +712,6 @@  static const AVFilterPad fillborders_inputs[] = {
         .filter_frame   = filter_frame,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad fillborders_outputs[] = {
@@ -720,7 +719,6 @@  static const AVFilterPad fillborders_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fillborders = {
@@ -730,7 +728,9 @@  const AVFilter ff_vf_fillborders = {
     .priv_class    = &fillborders_class,
     .query_formats = query_formats,
     .inputs        = fillborders_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(fillborders_inputs),
     .outputs       = fillborders_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(fillborders_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_find_rect.c b/libavfilter/vf_find_rect.c
index 1a94655b6b..64d6e3532e 100644
--- a/libavfilter/vf_find_rect.c
+++ b/libavfilter/vf_find_rect.c
@@ -292,7 +292,6 @@  static const AVFilterPad foc_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad foc_outputs[] = {
@@ -300,7 +299,6 @@  static const AVFilterPad foc_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_find_rect = {
@@ -311,6 +309,8 @@  const AVFilter ff_vf_find_rect = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = foc_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(foc_inputs),
     .outputs         = foc_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(foc_outputs),
     .priv_class      = &find_rect_class,
 };
diff --git a/libavfilter/vf_floodfill.c b/libavfilter/vf_floodfill.c
index 3b17b04c61..fba5cf5d81 100644
--- a/libavfilter/vf_floodfill.c
+++ b/libavfilter/vf_floodfill.c
@@ -390,7 +390,6 @@  static const AVFilterPad floodfill_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad floodfill_outputs[] = {
@@ -398,7 +397,6 @@  static const AVFilterPad floodfill_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(FloodfillContext, x)
@@ -428,6 +426,8 @@  const AVFilter ff_vf_floodfill = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = floodfill_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(floodfill_inputs),
     .outputs       = floodfill_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(floodfill_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c
index 960d4b0acf..d5cf0cd275 100644
--- a/libavfilter/vf_format.c
+++ b/libavfilter/vf_format.c
@@ -155,7 +155,6 @@  static const AVFilterPad avfilter_vf_format_inputs[] = {
         .type             = AVMEDIA_TYPE_VIDEO,
         .get_video_buffer = ff_null_get_video_buffer,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_format_outputs[] = {
@@ -163,7 +162,6 @@  static const AVFilterPad avfilter_vf_format_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_format = {
@@ -179,7 +177,9 @@  const AVFilter ff_vf_format = {
     .priv_class    = &format_class,
 
     .inputs        = avfilter_vf_format_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_format_inputs),
     .outputs       = avfilter_vf_format_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_format_outputs),
 };
 #endif /* CONFIG_FORMAT_FILTER */
 
@@ -194,7 +194,6 @@  static const AVFilterPad avfilter_vf_noformat_inputs[] = {
         .type             = AVMEDIA_TYPE_VIDEO,
         .get_video_buffer = ff_null_get_video_buffer,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_noformat_outputs[] = {
@@ -202,7 +201,6 @@  static const AVFilterPad avfilter_vf_noformat_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_noformat = {
@@ -218,6 +216,8 @@  const AVFilter ff_vf_noformat = {
     .priv_class    = &noformat_class,
 
     .inputs        = avfilter_vf_noformat_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_noformat_inputs),
     .outputs       = avfilter_vf_noformat_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_noformat_outputs),
 };
 #endif /* CONFIG_NOFORMAT_FILTER */
diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c
index fbc845da1b..7ef1ac8a61 100644
--- a/libavfilter/vf_fps.c
+++ b/libavfilter/vf_fps.c
@@ -370,7 +370,6 @@  static const AVFilterPad avfilter_vf_fps_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_fps_outputs[] = {
@@ -379,7 +378,6 @@  static const AVFilterPad avfilter_vf_fps_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fps = {
@@ -391,5 +389,7 @@  const AVFilter ff_vf_fps = {
     .priv_class  = &fps_class,
     .activate    = activate,
     .inputs      = avfilter_vf_fps_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_fps_inputs),
     .outputs     = avfilter_vf_fps_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_fps_outputs),
 };
diff --git a/libavfilter/vf_framepack.c b/libavfilter/vf_framepack.c
index 4fa9b4d144..d671ee7a55 100644
--- a/libavfilter/vf_framepack.c
+++ b/libavfilter/vf_framepack.c
@@ -457,7 +457,6 @@  static const AVFilterPad framepack_inputs[] = {
         .name         = "right",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad framepack_outputs[] = {
@@ -466,7 +465,6 @@  static const AVFilterPad framepack_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_framepack = {
@@ -476,7 +474,9 @@  const AVFilter ff_vf_framepack = {
     .priv_class    = &framepack_class,
     .query_formats = query_formats,
     .inputs        = framepack_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(framepack_inputs),
     .outputs       = framepack_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(framepack_outputs),
     .activate      = activate,
     .uninit        = framepack_uninit,
 };
diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c
index 6b509443a6..e5839e18a5 100644
--- a/libavfilter/vf_framerate.c
+++ b/libavfilter/vf_framerate.c
@@ -429,7 +429,6 @@  static const AVFilterPad framerate_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad framerate_outputs[] = {
@@ -438,7 +437,6 @@  static const AVFilterPad framerate_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_framerate = {
@@ -450,7 +448,9 @@  const AVFilter ff_vf_framerate = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = framerate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(framerate_inputs),
     .outputs       = framerate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(framerate_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
     .activate      = activate,
 };
diff --git a/libavfilter/vf_framestep.c b/libavfilter/vf_framestep.c
index d61ce0dc56..a187b71cac 100644
--- a/libavfilter/vf_framestep.c
+++ b/libavfilter/vf_framestep.c
@@ -77,7 +77,6 @@  static const AVFilterPad framestep_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad framestep_outputs[] = {
@@ -86,7 +85,6 @@  static const AVFilterPad framestep_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_framestep = {
@@ -95,6 +93,8 @@  const AVFilter ff_vf_framestep = {
     .priv_size   = sizeof(FrameStepContext),
     .priv_class  = &framestep_class,
     .inputs      = framestep_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(framestep_inputs),
     .outputs     = framestep_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(framestep_outputs),
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_freezedetect.c b/libavfilter/vf_freezedetect.c
index 9cf8fbab15..0e7219223c 100644
--- a/libavfilter/vf_freezedetect.c
+++ b/libavfilter/vf_freezedetect.c
@@ -210,7 +210,6 @@  static const AVFilterPad freezedetect_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad freezedetect_outputs[] = {
@@ -218,7 +217,6 @@  static const AVFilterPad freezedetect_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_freezedetect = {
@@ -229,6 +227,8 @@  const AVFilter ff_vf_freezedetect = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = freezedetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(freezedetect_inputs),
     .outputs       = freezedetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(freezedetect_outputs),
     .activate      = activate,
 };
diff --git a/libavfilter/vf_freezeframes.c b/libavfilter/vf_freezeframes.c
index e29eb07cec..11875aad2b 100644
--- a/libavfilter/vf_freezeframes.c
+++ b/libavfilter/vf_freezeframes.c
@@ -142,7 +142,6 @@  static const AVFilterPad freezeframes_inputs[] = {
         .name = "replace",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL },
 };
 
 static const AVFilterPad freezeframes_outputs[] = {
@@ -151,7 +150,6 @@  static const AVFilterPad freezeframes_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL },
 };
 
 const AVFilter ff_vf_freezeframes = {
@@ -160,7 +158,9 @@  const AVFilter ff_vf_freezeframes = {
     .priv_size     = sizeof(FreezeFramesContext),
     .priv_class    = &freezeframes_class,
     .inputs        = freezeframes_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(freezeframes_inputs),
     .outputs       = freezeframes_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(freezeframes_outputs),
     .activate      = activate,
     .uninit        = uninit,
 };
diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c
index 00e5ff2444..b2fc6152c7 100644
--- a/libavfilter/vf_frei0r.c
+++ b/libavfilter/vf_frei0r.c
@@ -402,7 +402,6 @@  static const AVFilterPad avfilter_vf_frei0r_inputs[] = {
         .config_props = config_input_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_frei0r_outputs[] = {
@@ -410,7 +409,6 @@  static const AVFilterPad avfilter_vf_frei0r_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_frei0r = {
@@ -422,7 +420,9 @@  const AVFilter ff_vf_frei0r = {
     .priv_size     = sizeof(Frei0rContext),
     .priv_class    = &frei0r_class,
     .inputs        = avfilter_vf_frei0r_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_frei0r_inputs),
     .outputs       = avfilter_vf_frei0r_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_frei0r_outputs),
     .process_command = process_command,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
@@ -498,7 +498,6 @@  static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = {
         .request_frame = source_request_frame,
         .config_props  = source_config_props
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_frei0r_src = {
@@ -511,4 +510,5 @@  const AVFilter ff_vsrc_frei0r_src = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_frei0r_src_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_frei0r_src_outputs),
 };
diff --git a/libavfilter/vf_fspp.c b/libavfilter/vf_fspp.c
index 44d22fc1e4..60bd56ae54 100644
--- a/libavfilter/vf_fspp.c
+++ b/libavfilter/vf_fspp.c
@@ -656,7 +656,6 @@  static const AVFilterPad fspp_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad fspp_outputs[] = {
@@ -664,7 +663,6 @@  static const AVFilterPad fspp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_fspp = {
@@ -674,7 +672,9 @@  const AVFilter ff_vf_fspp = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = fspp_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(fspp_inputs),
     .outputs         = fspp_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(fspp_outputs),
     .priv_class      = &fspp_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_gblur.c b/libavfilter/vf_gblur.c
index 3f61275658..c5cc4dca68 100644
--- a/libavfilter/vf_gblur.c
+++ b/libavfilter/vf_gblur.c
@@ -382,7 +382,6 @@  static const AVFilterPad gblur_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad gblur_outputs[] = {
@@ -390,7 +389,6 @@  static const AVFilterPad gblur_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_gblur = {
@@ -401,7 +399,9 @@  const AVFilter ff_vf_gblur = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = gblur_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(gblur_inputs),
     .outputs       = gblur_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(gblur_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
index d9bb6ac256..a5f32f1d6b 100644
--- a/libavfilter/vf_geq.c
+++ b/libavfilter/vf_geq.c
@@ -481,7 +481,6 @@  static const AVFilterPad geq_inputs[] = {
         .config_props = geq_config_props,
         .filter_frame = geq_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad geq_outputs[] = {
@@ -489,7 +488,6 @@  static const AVFilterPad geq_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_geq = {
@@ -500,7 +498,9 @@  const AVFilter ff_vf_geq = {
     .uninit        = geq_uninit,
     .query_formats = geq_query_formats,
     .inputs        = geq_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(geq_inputs),
     .outputs       = geq_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(geq_outputs),
     .priv_class    = &geq_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c
index af77b13d4d..dcbe1658d6 100644
--- a/libavfilter/vf_gradfun.c
+++ b/libavfilter/vf_gradfun.c
@@ -240,7 +240,6 @@  static const AVFilterPad avfilter_vf_gradfun_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_gradfun_outputs[] = {
@@ -248,7 +247,6 @@  static const AVFilterPad avfilter_vf_gradfun_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_gradfun = {
@@ -260,6 +258,8 @@  const AVFilter ff_vf_gradfun = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_gradfun_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_gradfun_inputs),
     .outputs       = avfilter_vf_gradfun_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_gradfun_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_guided.c b/libavfilter/vf_guided.c
index 202a6a0586..7ef05b8ab3 100644
--- a/libavfilter/vf_guided.c
+++ b/libavfilter/vf_guided.c
@@ -486,7 +486,6 @@  static const AVFilterPad guided_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_guided = {
@@ -500,6 +499,7 @@  const AVFilter ff_vf_guided = {
     .activate        = activate,
     .inputs          = NULL,
     .outputs         = guided_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(guided_outputs),
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index 2a0defda6c..2ecd26a975 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -234,7 +234,6 @@  static const AVFilterPad avfilter_vf_hflip_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_hflip_outputs[] = {
@@ -242,7 +241,6 @@  static const AVFilterPad avfilter_vf_hflip_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hflip = {
@@ -252,6 +250,8 @@  const AVFilter ff_vf_hflip = {
     .priv_class    = &hflip_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_hflip_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_hflip_inputs),
     .outputs       = avfilter_vf_hflip_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_hflip_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_histeq.c b/libavfilter/vf_histeq.c
index dea819e672..46f03008ac 100644
--- a/libavfilter/vf_histeq.c
+++ b/libavfilter/vf_histeq.c
@@ -259,7 +259,6 @@  static const AVFilterPad histeq_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad histeq_outputs[] = {
@@ -267,7 +266,6 @@  static const AVFilterPad histeq_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_histeq = {
@@ -277,7 +275,9 @@  const AVFilter ff_vf_histeq = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = histeq_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(histeq_inputs),
     .outputs       = histeq_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(histeq_outputs),
     .priv_class    = &histeq_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c
index bd9408c42d..3137bb805d 100644
--- a/libavfilter/vf_histogram.c
+++ b/libavfilter/vf_histogram.c
@@ -488,7 +488,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -497,7 +496,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_HISTOGRAM_FILTER
@@ -508,7 +506,9 @@  const AVFilter ff_vf_histogram = {
     .priv_size     = sizeof(HistogramContext),
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .priv_class    = &histogram_class,
 };
 
@@ -550,7 +550,9 @@  const AVFilter ff_vf_thistogram = {
     .priv_size     = sizeof(HistogramContext),
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .uninit        = uninit,
     .priv_class    = &thistogram_class,
 };
diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c
index bd3eb2d01c..2f8b72510f 100644
--- a/libavfilter/vf_hqdn3d.c
+++ b/libavfilter/vf_hqdn3d.c
@@ -386,7 +386,6 @@  static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 
@@ -395,7 +394,6 @@  static const AVFilterPad avfilter_vf_hqdn3d_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hqdn3d = {
@@ -407,7 +405,9 @@  const AVFilter ff_vf_hqdn3d = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_hqdn3d_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_hqdn3d_inputs),
     .outputs       = avfilter_vf_hqdn3d_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_hqdn3d_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_hqx.c b/libavfilter/vf_hqx.c
index 8b0d794b6e..36e16d6446 100644
--- a/libavfilter/vf_hqx.c
+++ b/libavfilter/vf_hqx.c
@@ -541,7 +541,6 @@  static const AVFilterPad hqx_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad hqx_outputs[] = {
@@ -550,7 +549,6 @@  static const AVFilterPad hqx_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hqx = {
@@ -560,7 +558,9 @@  const AVFilter ff_vf_hqx = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = hqx_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(hqx_inputs),
     .outputs       = hqx_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(hqx_outputs),
     .priv_class    = &hqx_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
index 3d250dbe25..c8f9a8c4ac 100644
--- a/libavfilter/vf_hue.c
+++ b/libavfilter/vf_hue.c
@@ -505,7 +505,6 @@  static const AVFilterPad hue_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad hue_outputs[] = {
@@ -513,7 +512,6 @@  static const AVFilterPad hue_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hue = {
@@ -525,7 +523,9 @@  const AVFilter ff_vf_hue = {
     .query_formats   = query_formats,
     .process_command = process_command,
     .inputs          = hue_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(hue_inputs),
     .outputs         = hue_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(hue_outputs),
     .priv_class      = &hue_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_hwdownload.c b/libavfilter/vf_hwdownload.c
index 4a8fed0688..8e5689ca15 100644
--- a/libavfilter/vf_hwdownload.c
+++ b/libavfilter/vf_hwdownload.c
@@ -180,7 +180,6 @@  static const AVFilterPad hwdownload_inputs[] = {
         .config_props = hwdownload_config_input,
         .filter_frame = hwdownload_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad hwdownload_outputs[] = {
@@ -189,7 +188,6 @@  static const AVFilterPad hwdownload_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = hwdownload_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hwdownload = {
@@ -200,6 +198,8 @@  const AVFilter ff_vf_hwdownload = {
     .priv_size     = sizeof(HWDownloadContext),
     .priv_class    = &hwdownload_class,
     .inputs        = hwdownload_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(hwdownload_inputs),
     .outputs       = hwdownload_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(hwdownload_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index d829b47b44..898837ad3b 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -407,7 +407,6 @@  static const AVFilterPad hwmap_inputs[] = {
         .get_video_buffer = hwmap_get_buffer,
         .filter_frame     = hwmap_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad hwmap_outputs[] = {
@@ -416,7 +415,6 @@  static const AVFilterPad hwmap_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = hwmap_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hwmap = {
@@ -427,6 +425,8 @@  const AVFilter ff_vf_hwmap = {
     .priv_class     = &hwmap_class,
     .query_formats  = hwmap_query_formats,
     .inputs         = hwmap_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(hwmap_inputs),
     .outputs        = hwmap_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(hwmap_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
index 8263829a39..4aaec3633f 100644
--- a/libavfilter/vf_hwupload.c
+++ b/libavfilter/vf_hwupload.c
@@ -238,7 +238,6 @@  static const AVFilterPad hwupload_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = hwupload_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad hwupload_outputs[] = {
@@ -247,7 +246,6 @@  static const AVFilterPad hwupload_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = hwupload_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hwupload = {
@@ -258,6 +256,8 @@  const AVFilter ff_vf_hwupload = {
     .priv_size     = sizeof(HWUploadContext),
     .priv_class    = &hwupload_class,
     .inputs        = hwupload_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(hwupload_inputs),
     .outputs       = hwupload_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(hwupload_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_hwupload_cuda.c b/libavfilter/vf_hwupload_cuda.c
index 138949a5ed..3a400c45db 100644
--- a/libavfilter/vf_hwupload_cuda.c
+++ b/libavfilter/vf_hwupload_cuda.c
@@ -171,7 +171,6 @@  static const AVFilterPad cudaupload_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = cudaupload_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad cudaupload_outputs[] = {
@@ -180,7 +179,6 @@  static const AVFilterPad cudaupload_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = cudaupload_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hwupload_cuda = {
@@ -196,7 +194,9 @@  const AVFilter ff_vf_hwupload_cuda = {
     .priv_class = &cudaupload_class,
 
     .inputs    = cudaupload_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(cudaupload_inputs),
     .outputs   = cudaupload_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(cudaupload_outputs),
 
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_hysteresis.c b/libavfilter/vf_hysteresis.c
index 3732ed5c22..b62abce49e 100644
--- a/libavfilter/vf_hysteresis.c
+++ b/libavfilter/vf_hysteresis.c
@@ -362,7 +362,6 @@  static const AVFilterPad hysteresis_inputs[] = {
         .name         = "alt",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad hysteresis_outputs[] = {
@@ -371,7 +370,6 @@  static const AVFilterPad hysteresis_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_hysteresis = {
@@ -383,7 +381,9 @@  const AVFilter ff_vf_hysteresis = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = hysteresis_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(hysteresis_inputs),
     .outputs       = hysteresis_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(hysteresis_outputs),
     .priv_class    = &hysteresis_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c
index f47611924e..265698c961 100644
--- a/libavfilter/vf_identity.c
+++ b/libavfilter/vf_identity.c
@@ -392,7 +392,6 @@  static const AVFilterPad identity_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad identity_outputs[] = {
@@ -401,7 +400,6 @@  static const AVFilterPad identity_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 static const AVOption options[] = {
@@ -424,7 +422,9 @@  const AVFilter ff_vf_identity = {
     .priv_size     = sizeof(IdentityContext),
     .priv_class    = &identity_class,
     .inputs        = identity_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(identity_inputs),
     .outputs       = identity_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(identity_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
 
@@ -446,7 +446,9 @@  const AVFilter ff_vf_msad = {
     .priv_size     = sizeof(IdentityContext),
     .priv_class    = &msad_class,
     .inputs        = identity_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(identity_inputs),
     .outputs       = identity_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(identity_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
 
diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c
index 54fc08e915..1d62032835 100644
--- a/libavfilter/vf_idet.c
+++ b/libavfilter/vf_idet.c
@@ -428,7 +428,6 @@  static const AVFilterPad idet_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad idet_outputs[] = {
@@ -437,7 +436,6 @@  static const AVFilterPad idet_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_idet = {
@@ -448,6 +446,8 @@  const AVFilter ff_vf_idet = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = idet_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(idet_inputs),
     .outputs       = idet_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(idet_outputs),
     .priv_class    = &idet_class,
 };
diff --git a/libavfilter/vf_il.c b/libavfilter/vf_il.c
index 9b21f2e7a7..059166907f 100644
--- a/libavfilter/vf_il.c
+++ b/libavfilter/vf_il.c
@@ -187,7 +187,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -195,7 +194,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_il = {
@@ -204,7 +202,9 @@  const AVFilter ff_vf_il = {
     .priv_size     = sizeof(IlContext),
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .priv_class    = &il_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = ff_filter_process_command,
diff --git a/libavfilter/vf_kerndeint.c b/libavfilter/vf_kerndeint.c
index a86407beb0..2b59e13129 100644
--- a/libavfilter/vf_kerndeint.c
+++ b/libavfilter/vf_kerndeint.c
@@ -295,7 +295,6 @@  static const AVFilterPad kerndeint_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad kerndeint_outputs[] = {
@@ -303,7 +302,6 @@  static const AVFilterPad kerndeint_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 
@@ -315,5 +313,7 @@  const AVFilter ff_vf_kerndeint = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = kerndeint_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(kerndeint_inputs),
     .outputs       = kerndeint_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(kerndeint_outputs),
 };
diff --git a/libavfilter/vf_lagfun.c b/libavfilter/vf_lagfun.c
index e147479671..c3870d84b6 100644
--- a/libavfilter/vf_lagfun.c
+++ b/libavfilter/vf_lagfun.c
@@ -205,7 +205,6 @@  static const AVFilterPad inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -214,7 +213,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(lagfun);
@@ -227,7 +225,9 @@  const AVFilter ff_vf_lagfun = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_lenscorrection.c b/libavfilter/vf_lenscorrection.c
index 7bd008d3d8..2125562cee 100644
--- a/libavfilter/vf_lenscorrection.c
+++ b/libavfilter/vf_lenscorrection.c
@@ -345,7 +345,6 @@  static const AVFilterPad lenscorrection_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad lenscorrection_outputs[] = {
@@ -354,7 +353,6 @@  static const AVFilterPad lenscorrection_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_lenscorrection = {
@@ -363,7 +361,9 @@  const AVFilter ff_vf_lenscorrection = {
     .priv_size     = sizeof(LenscorrectionCtx),
     .query_formats = query_formats,
     .inputs        = lenscorrection_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(lenscorrection_inputs),
     .outputs       = lenscorrection_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(lenscorrection_outputs),
     .priv_class    = &lenscorrection_class,
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c
index f34add961a..6321ad13b0 100644
--- a/libavfilter/vf_lensfun.c
+++ b/libavfilter/vf_lensfun.c
@@ -524,7 +524,6 @@  static const AVFilterPad lensfun_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad lensfun_outputs[] = {
@@ -532,7 +531,6 @@  static const AVFilterPad lensfun_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_lensfun = {
@@ -543,7 +541,9 @@  const AVFilter ff_vf_lensfun = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = lensfun_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(lensfun_inputs),
     .outputs       = lensfun_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(lensfun_outputs),
     .priv_class    = &lensfun_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c
index 221a8ac4c2..1932552c05 100644
--- a/libavfilter/vf_libopencv.c
+++ b/libavfilter/vf_libopencv.c
@@ -416,7 +416,6 @@  static const AVFilterPad avfilter_vf_ocv_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_ocv_outputs[] = {
@@ -424,7 +423,6 @@  static const AVFilterPad avfilter_vf_ocv_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_ocv = {
@@ -436,5 +434,7 @@  const AVFilter ff_vf_ocv = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = avfilter_vf_ocv_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_ocv_inputs),
     .outputs       = avfilter_vf_ocv_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_ocv_outputs),
 };
diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c
index d2621c7a9f..6d753b2e36 100644
--- a/libavfilter/vf_libvmaf.c
+++ b/libavfilter/vf_libvmaf.c
@@ -353,7 +353,6 @@  static const AVFilterPad libvmaf_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad libvmaf_outputs[] = {
@@ -362,7 +361,6 @@  static const AVFilterPad libvmaf_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_libvmaf = {
@@ -376,5 +374,7 @@  const AVFilter ff_vf_libvmaf = {
     .priv_size     = sizeof(LIBVMAFContext),
     .priv_class    = &libvmaf_class,
     .inputs        = libvmaf_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(libvmaf_inputs),
     .outputs       = libvmaf_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(libvmaf_outputs),
 };
diff --git a/libavfilter/vf_limiter.c b/libavfilter/vf_limiter.c
index 04bfbb63d1..71475804ec 100644
--- a/libavfilter/vf_limiter.c
+++ b/libavfilter/vf_limiter.c
@@ -249,7 +249,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -257,7 +256,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_limiter = {
@@ -268,7 +266,9 @@  const AVFilter ff_vf_limiter = {
     .init          = init,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_lumakey.c b/libavfilter/vf_lumakey.c
index 3f98d5077d..b7f4161225 100644
--- a/libavfilter/vf_lumakey.c
+++ b/libavfilter/vf_lumakey.c
@@ -182,7 +182,6 @@  static const AVFilterPad lumakey_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad lumakey_outputs[] = {
@@ -190,7 +189,6 @@  static const AVFilterPad lumakey_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(LumakeyContext, x)
@@ -212,7 +210,9 @@  const AVFilter ff_vf_lumakey = {
     .priv_class    = &lumakey_class,
     .query_formats = query_formats,
     .inputs        = lumakey_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(lumakey_inputs),
     .outputs       = lumakey_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(lumakey_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index 47c2416da7..71caec4f7e 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -583,13 +583,11 @@  static const AVFilterPad inputs[] = {
       .filter_frame = filter_frame,
       .config_props = config_props,
     },
-    { NULL }
 };
 static const AVFilterPad outputs[] = {
     { .name = "default",
       .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define DEFINE_LUT_FILTER(name_, description_)                          \
@@ -602,7 +600,9 @@  static const AVFilterPad outputs[] = {
         .uninit        = uninit,                                        \
         .query_formats = query_formats,                                 \
         .inputs        = inputs,                                        \
+        .nb_inputs       = FF_ARRAY_ELEMS(inputs),                        \
         .outputs       = outputs,                                       \
+        .nb_outputs      = FF_ARRAY_ELEMS(outputs),                       \
         .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |       \
                          AVFILTER_FLAG_SLICE_THREADS,                   \
         .process_command = process_command,                             \
diff --git a/libavfilter/vf_lut2.c b/libavfilter/vf_lut2.c
index 658a0bfa56..de98334f83 100644
--- a/libavfilter/vf_lut2.c
+++ b/libavfilter/vf_lut2.c
@@ -533,7 +533,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_inputy,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -542,7 +541,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = lut2_config_output,
     },
-    { NULL }
 };
 
 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
@@ -570,7 +568,9 @@  const AVFilter ff_vf_lut2 = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
@@ -640,7 +640,6 @@  static const AVFilterPad tlut2_inputs[] = {
         .filter_frame  = tlut2_filter_frame,
         .config_props  = config_inputx,
     },
-    { NULL }
 };
 
 static const AVFilterPad tlut2_outputs[] = {
@@ -649,7 +648,6 @@  static const AVFilterPad tlut2_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tlut2 = {
@@ -661,7 +659,9 @@  const AVFilter ff_vf_tlut2 = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = tlut2_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(tlut2_inputs),
     .outputs       = tlut2_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(tlut2_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c
index c86585cf09..ec238c46d7 100644
--- a/libavfilter/vf_lut3d.c
+++ b/libavfilter/vf_lut3d.c
@@ -1342,7 +1342,6 @@  static const AVFilterPad lut3d_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad lut3d_outputs[] = {
@@ -1350,7 +1349,6 @@  static const AVFilterPad lut3d_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_lut3d = {
@@ -1361,7 +1359,9 @@  const AVFilter ff_vf_lut3d = {
     .uninit        = lut3d_uninit,
     .query_formats = query_formats,
     .inputs        = lut3d_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(lut3d_inputs),
     .outputs       = lut3d_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(lut3d_outputs),
     .priv_class    = &lut3d_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
@@ -1608,7 +1608,6 @@  static const AVFilterPad haldclut_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_clut,
     },
-    { NULL }
 };
 
 static const AVFilterPad haldclut_outputs[] = {
@@ -1617,7 +1616,6 @@  static const AVFilterPad haldclut_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_haldclut = {
@@ -1630,7 +1628,9 @@  const AVFilter ff_vf_haldclut = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = haldclut_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(haldclut_inputs),
     .outputs       = haldclut_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(haldclut_outputs),
     .priv_class    = &haldclut_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
@@ -2274,7 +2274,6 @@  static const AVFilterPad lut1d_inputs[] = {
         .filter_frame = filter_frame_1d,
         .config_props = config_input_1d,
     },
-    { NULL }
 };
 
 static const AVFilterPad lut1d_outputs[] = {
@@ -2282,7 +2281,6 @@  static const AVFilterPad lut1d_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_lut1d = {
@@ -2292,7 +2290,9 @@  const AVFilter ff_vf_lut1d = {
     .init          = lut1d_init,
     .query_formats = query_formats,
     .inputs        = lut1d_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(lut1d_inputs),
     .outputs       = lut1d_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(lut1d_outputs),
     .priv_class    = &lut1d_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = lut1d_process_command,
diff --git a/libavfilter/vf_maskedclamp.c b/libavfilter/vf_maskedclamp.c
index 050e3ae6e4..40430dd12e 100644
--- a/libavfilter/vf_maskedclamp.c
+++ b/libavfilter/vf_maskedclamp.c
@@ -304,7 +304,6 @@  static const AVFilterPad maskedclamp_inputs[] = {
         .name         = "bright",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad maskedclamp_outputs[] = {
@@ -313,7 +312,6 @@  static const AVFilterPad maskedclamp_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_maskedclamp = {
@@ -324,7 +322,9 @@  const AVFilter ff_vf_maskedclamp = {
     .activate      = activate,
     .query_formats = query_formats,
     .inputs        = maskedclamp_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskedclamp_inputs),
     .outputs       = maskedclamp_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskedclamp_outputs),
     .priv_class    = &maskedclamp_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
diff --git a/libavfilter/vf_maskedmerge.c b/libavfilter/vf_maskedmerge.c
index 28ac0dd52d..0283b5c094 100644
--- a/libavfilter/vf_maskedmerge.c
+++ b/libavfilter/vf_maskedmerge.c
@@ -305,7 +305,6 @@  static const AVFilterPad maskedmerge_inputs[] = {
         .name         = "mask",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad maskedmerge_outputs[] = {
@@ -314,7 +313,6 @@  static const AVFilterPad maskedmerge_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_maskedmerge = {
@@ -325,7 +323,9 @@  const AVFilter ff_vf_maskedmerge = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = maskedmerge_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskedmerge_inputs),
     .outputs       = maskedmerge_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskedmerge_outputs),
     .priv_class    = &maskedmerge_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
diff --git a/libavfilter/vf_maskedminmax.c b/libavfilter/vf_maskedminmax.c
index 0d79fc177f..932cea0d8f 100644
--- a/libavfilter/vf_maskedminmax.c
+++ b/libavfilter/vf_maskedminmax.c
@@ -313,7 +313,6 @@  static const AVFilterPad maskedminmax_inputs[] = {
         .name         = "filter2",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad maskedminmax_outputs[] = {
@@ -322,7 +321,6 @@  static const AVFilterPad maskedminmax_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #define maskedmin_options maskedminmax_options
@@ -338,7 +336,9 @@  const AVFilter ff_vf_maskedmin = {
     .activate      = activate,
     .query_formats = query_formats,
     .inputs        = maskedminmax_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskedminmax_inputs),
     .outputs       = maskedminmax_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskedminmax_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
@@ -356,7 +356,9 @@  const AVFilter ff_vf_maskedmax = {
     .activate      = activate,
     .query_formats = query_formats,
     .inputs        = maskedminmax_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskedminmax_inputs),
     .outputs       = maskedminmax_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskedminmax_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_maskedthreshold.c b/libavfilter/vf_maskedthreshold.c
index 518ab54546..cf59fede57 100644
--- a/libavfilter/vf_maskedthreshold.c
+++ b/libavfilter/vf_maskedthreshold.c
@@ -270,7 +270,6 @@  static const AVFilterPad maskedthreshold_inputs[] = {
         .name         = "reference",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad maskedthreshold_outputs[] = {
@@ -279,7 +278,6 @@  static const AVFilterPad maskedthreshold_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(maskedthreshold);
@@ -293,7 +291,9 @@  const AVFilter ff_vf_maskedthreshold = {
     .activate      = activate,
     .query_formats = query_formats,
     .inputs        = maskedthreshold_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskedthreshold_inputs),
     .outputs       = maskedthreshold_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskedthreshold_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_maskfun.c b/libavfilter/vf_maskfun.c
index 0f3e3545b3..d23a65c40b 100644
--- a/libavfilter/vf_maskfun.c
+++ b/libavfilter/vf_maskfun.c
@@ -298,7 +298,6 @@  static const AVFilterPad maskfun_inputs[] = {
         .config_props   = config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad maskfun_outputs[] = {
@@ -306,7 +305,6 @@  static const AVFilterPad maskfun_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_maskfun = {
@@ -316,7 +314,9 @@  const AVFilter ff_vf_maskfun = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = maskfun_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(maskfun_inputs),
     .outputs       = maskfun_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(maskfun_outputs),
     .priv_class    = &maskfun_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_mcdeint.c b/libavfilter/vf_mcdeint.c
index 1a49829d5b..ad7f38e575 100644
--- a/libavfilter/vf_mcdeint.c
+++ b/libavfilter/vf_mcdeint.c
@@ -293,7 +293,6 @@  static const AVFilterPad mcdeint_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad mcdeint_outputs[] = {
@@ -301,7 +300,6 @@  static const AVFilterPad mcdeint_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_mcdeint = {
@@ -311,6 +309,8 @@  const AVFilter ff_vf_mcdeint = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = mcdeint_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(mcdeint_inputs),
     .outputs       = mcdeint_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mcdeint_outputs),
     .priv_class    = &mcdeint_class,
 };
diff --git a/libavfilter/vf_median.c b/libavfilter/vf_median.c
index 1e66ab87ff..8189503f20 100644
--- a/libavfilter/vf_median.c
+++ b/libavfilter/vf_median.c
@@ -273,7 +273,6 @@  static const AVFilterPad median_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad median_outputs[] = {
@@ -281,7 +280,6 @@  static const AVFilterPad median_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_median = {
@@ -292,7 +290,9 @@  const AVFilter ff_vf_median = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = median_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(median_inputs),
     .outputs       = median_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(median_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_mergeplanes.c b/libavfilter/vf_mergeplanes.c
index 30888f62af..6803d57feb 100644
--- a/libavfilter/vf_mergeplanes.c
+++ b/libavfilter/vf_mergeplanes.c
@@ -293,7 +293,6 @@  static const AVFilterPad mergeplanes_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_mergeplanes = {
@@ -307,5 +306,6 @@  const AVFilter ff_vf_mergeplanes = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = mergeplanes_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mergeplanes_outputs),
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/vf_mestimate.c b/libavfilter/vf_mestimate.c
index f57f2578ec..af094b0ac1 100644
--- a/libavfilter/vf_mestimate.c
+++ b/libavfilter/vf_mestimate.c
@@ -356,7 +356,6 @@  static const AVFilterPad mestimate_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad mestimate_outputs[] = {
@@ -364,7 +363,6 @@  static const AVFilterPad mestimate_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_mestimate = {
@@ -375,5 +373,7 @@  const AVFilter ff_vf_mestimate = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = mestimate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(mestimate_inputs),
     .outputs       = mestimate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mestimate_outputs),
 };
diff --git a/libavfilter/vf_midequalizer.c b/libavfilter/vf_midequalizer.c
index ba50fa0a82..c727b828e9 100644
--- a/libavfilter/vf_midequalizer.c
+++ b/libavfilter/vf_midequalizer.c
@@ -363,7 +363,6 @@  static const AVFilterPad midequalizer_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input1,
     },
-    { NULL }
 };
 
 static const AVFilterPad midequalizer_outputs[] = {
@@ -372,7 +371,6 @@  static const AVFilterPad midequalizer_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_midequalizer = {
@@ -383,7 +381,9 @@  const AVFilter ff_vf_midequalizer = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = midequalizer_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(midequalizer_inputs),
     .outputs       = midequalizer_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(midequalizer_outputs),
     .priv_class    = &midequalizer_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c
index c6aed7755f..a96f50db36 100644
--- a/libavfilter/vf_minterpolate.c
+++ b/libavfilter/vf_minterpolate.c
@@ -1245,7 +1245,6 @@  static const AVFilterPad minterpolate_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad minterpolate_outputs[] = {
@@ -1254,7 +1253,6 @@  static const AVFilterPad minterpolate_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_minterpolate = {
@@ -1265,5 +1263,7 @@  const AVFilter ff_vf_minterpolate = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = minterpolate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(minterpolate_inputs),
     .outputs       = minterpolate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(minterpolate_outputs),
 };
diff --git a/libavfilter/vf_misc_vaapi.c b/libavfilter/vf_misc_vaapi.c
index ca0d46ff19..9b6452595a 100644
--- a/libavfilter/vf_misc_vaapi.c
+++ b/libavfilter/vf_misc_vaapi.c
@@ -222,7 +222,6 @@  static const AVFilterPad misc_vaapi_inputs[] = {
         .filter_frame = &misc_vaapi_filter_frame,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad misc_vaapi_outputs[] = {
@@ -231,7 +230,6 @@  static const AVFilterPad misc_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vaapi_vpp_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_denoise_vaapi = {
@@ -242,7 +240,9 @@  const AVFilter ff_vf_denoise_vaapi = {
     .uninit        = &ff_vaapi_vpp_ctx_uninit,
     .query_formats = &ff_vaapi_vpp_query_formats,
     .inputs        = misc_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(misc_vaapi_inputs),
     .outputs       = misc_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(misc_vaapi_outputs),
     .priv_class    = &denoise_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
@@ -255,7 +255,9 @@  const AVFilter ff_vf_sharpness_vaapi = {
     .uninit        = &ff_vaapi_vpp_ctx_uninit,
     .query_formats = &ff_vaapi_vpp_query_formats,
     .inputs        = misc_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(misc_vaapi_inputs),
     .outputs       = misc_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(misc_vaapi_outputs),
     .priv_class    = &sharpness_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c
index 0ca60d5522..9992cdf9f0 100644
--- a/libavfilter/vf_mix.c
+++ b/libavfilter/vf_mix.c
@@ -352,7 +352,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_MIX_FILTER
@@ -365,6 +364,7 @@  const AVFilter ff_vf_mix = {
     .priv_class    = &mix_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .init          = init,
     .uninit        = uninit,
     .activate      = activate,
@@ -430,7 +430,6 @@  static const AVFilterPad inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = tmix_filter_frame,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(tmix);
@@ -442,7 +441,9 @@  const AVFilter ff_vf_tmix = {
     .priv_class    = &tmix_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .init          = init,
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/vf_monochrome.c b/libavfilter/vf_monochrome.c
index 29e70f8c25..f393ca764b 100644
--- a/libavfilter/vf_monochrome.c
+++ b/libavfilter/vf_monochrome.c
@@ -277,7 +277,6 @@  static const AVFilterPad monochrome_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad monochrome_outputs[] = {
@@ -285,7 +284,6 @@  static const AVFilterPad monochrome_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(MonochromeContext, x)
@@ -308,7 +306,9 @@  const AVFilter ff_vf_monochrome = {
     .priv_class    = &monochrome_class,
     .query_formats = query_formats,
     .inputs        = monochrome_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(monochrome_inputs),
     .outputs       = monochrome_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(monochrome_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_mpdecimate.c b/libavfilter/vf_mpdecimate.c
index 53f5a56ef4..558087317b 100644
--- a/libavfilter/vf_mpdecimate.c
+++ b/libavfilter/vf_mpdecimate.c
@@ -231,7 +231,6 @@  static const AVFilterPad mpdecimate_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad mpdecimate_outputs[] = {
@@ -239,7 +238,6 @@  static const AVFilterPad mpdecimate_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_mpdecimate = {
@@ -251,5 +249,7 @@  const AVFilter ff_vf_mpdecimate = {
     .priv_class    = &mpdecimate_class,
     .query_formats = query_formats,
     .inputs        = mpdecimate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(mpdecimate_inputs),
     .outputs       = mpdecimate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mpdecimate_outputs),
 };
diff --git a/libavfilter/vf_neighbor.c b/libavfilter/vf_neighbor.c
index a2e9a51165..ffc9a9842c 100644
--- a/libavfilter/vf_neighbor.c
+++ b/libavfilter/vf_neighbor.c
@@ -341,7 +341,6 @@  static const AVFilterPad neighbor_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad neighbor_outputs[] = {
@@ -349,7 +348,6 @@  static const AVFilterPad neighbor_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(NContext, x)
@@ -365,7 +363,9 @@  const AVFilter ff_vf_##name_ = {                                   \
     .priv_class    = &name_##_class,                         \
     .query_formats = query_formats,                          \
     .inputs        = neighbor_inputs,                        \
+    .nb_inputs     = FF_ARRAY_ELEMS(neighbor_inputs),        \
     .outputs       = neighbor_outputs,                       \
+    .nb_outputs    = FF_ARRAY_ELEMS(neighbor_outputs),       \
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC| \
                      AVFILTER_FLAG_SLICE_THREADS,            \
     .process_command = ff_filter_process_command,            \
diff --git a/libavfilter/vf_neighbor_opencl.c b/libavfilter/vf_neighbor_opencl.c
index e00245089d..bf46cf6a62 100644
--- a/libavfilter/vf_neighbor_opencl.c
+++ b/libavfilter/vf_neighbor_opencl.c
@@ -245,7 +245,6 @@  static const AVFilterPad neighbor_opencl_inputs[] = {
         .filter_frame = &neighbor_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad neighbor_opencl_outputs[] = {
@@ -254,7 +253,6 @@  static const AVFilterPad neighbor_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(NeighborOpenCLContext, x)
@@ -282,7 +280,9 @@  const AVFilter ff_vf_erosion_opencl = {
     .uninit         = &neighbor_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = neighbor_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(neighbor_opencl_inputs),
     .outputs        = neighbor_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(neighbor_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -310,7 +310,9 @@  const AVFilter ff_vf_dilation_opencl = {
     .uninit         = &neighbor_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = neighbor_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(neighbor_opencl_inputs),
     .outputs        = neighbor_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(neighbor_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c
index 7451bec4ae..4ef172be21 100644
--- a/libavfilter/vf_nlmeans.c
+++ b/libavfilter/vf_nlmeans.c
@@ -566,7 +566,6 @@  static const AVFilterPad nlmeans_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad nlmeans_outputs[] = {
@@ -574,7 +573,6 @@  static const AVFilterPad nlmeans_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_nlmeans = {
@@ -585,7 +583,9 @@  const AVFilter ff_vf_nlmeans = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = nlmeans_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(nlmeans_inputs),
     .outputs       = nlmeans_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(nlmeans_outputs),
     .priv_class    = &nlmeans_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_nlmeans_opencl.c b/libavfilter/vf_nlmeans_opencl.c
index 0f16b2fe49..174314f885 100644
--- a/libavfilter/vf_nlmeans_opencl.c
+++ b/libavfilter/vf_nlmeans_opencl.c
@@ -417,7 +417,6 @@  static const AVFilterPad nlmeans_opencl_inputs[] = {
         .filter_frame = &nlmeans_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad nlmeans_opencl_outputs[] = {
@@ -426,7 +425,6 @@  static const AVFilterPad nlmeans_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_nlmeans_opencl = {
@@ -438,6 +436,8 @@  const AVFilter ff_vf_nlmeans_opencl = {
     .uninit         = &nlmeans_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = nlmeans_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(nlmeans_opencl_inputs),
     .outputs        = nlmeans_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(nlmeans_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c
index b802ca5433..9b79b50a35 100644
--- a/libavfilter/vf_nnedi.c
+++ b/libavfilter/vf_nnedi.c
@@ -1143,7 +1143,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1153,7 +1152,6 @@  static const AVFilterPad outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_nnedi = {
@@ -1165,7 +1163,9 @@  const AVFilter ff_vf_nnedi = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c
index 73e88063e9..3deacd2f51 100644
--- a/libavfilter/vf_noise.c
+++ b/libavfilter/vf_noise.c
@@ -326,7 +326,6 @@  static const AVFilterPad noise_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad noise_outputs[] = {
@@ -334,7 +333,6 @@  static const AVFilterPad noise_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_noise = {
@@ -345,7 +343,9 @@  const AVFilter ff_vf_noise = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = noise_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(noise_inputs),
     .outputs       = noise_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(noise_outputs),
     .priv_class    = &noise_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_normalize.c b/libavfilter/vf_normalize.c
index 3a2127ade3..c6a42c9862 100644
--- a/libavfilter/vf_normalize.c
+++ b/libavfilter/vf_normalize.c
@@ -519,7 +519,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -527,7 +526,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_normalize = {
@@ -538,7 +536,9 @@  const AVFilter ff_vf_normalize = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_null.c b/libavfilter/vf_null.c
index 1f0e85e900..422152a4ed 100644
--- a/libavfilter/vf_null.c
+++ b/libavfilter/vf_null.c
@@ -31,7 +31,6 @@  static const AVFilterPad avfilter_vf_null_inputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_null_outputs[] = {
@@ -39,12 +38,13 @@  static const AVFilterPad avfilter_vf_null_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_null = {
     .name        = "null",
     .description = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."),
     .inputs      = avfilter_vf_null_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_null_inputs),
     .outputs     = avfilter_vf_null_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_null_outputs),
 };
diff --git a/libavfilter/vf_ocr.c b/libavfilter/vf_ocr.c
index 6de474025a..46042bc460 100644
--- a/libavfilter/vf_ocr.c
+++ b/libavfilter/vf_ocr.c
@@ -135,7 +135,6 @@  static const AVFilterPad ocr_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad ocr_outputs[] = {
@@ -143,7 +142,6 @@  static const AVFilterPad ocr_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_ocr = {
@@ -155,5 +153,7 @@  const AVFilter ff_vf_ocr = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = ocr_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ocr_inputs),
     .outputs       = ocr_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ocr_outputs),
 };
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index 9155de3736..d31d4575d6 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -1094,7 +1094,6 @@  static const AVFilterPad avfilter_vf_overlay_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_overlay,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_overlay_outputs[] = {
@@ -1103,7 +1102,6 @@  static const AVFilterPad avfilter_vf_overlay_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_overlay = {
@@ -1118,7 +1116,9 @@  const AVFilter ff_vf_overlay = {
     .activate      = activate,
     .process_command = process_command,
     .inputs        = avfilter_vf_overlay_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_overlay_inputs),
     .outputs       = avfilter_vf_overlay_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_overlay_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_overlay_cuda.c b/libavfilter/vf_overlay_cuda.c
index 37af4e2fa0..d952e72834 100644
--- a/libavfilter/vf_overlay_cuda.c
+++ b/libavfilter/vf_overlay_cuda.c
@@ -567,7 +567,6 @@  static const AVFilterPad overlay_cuda_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_overlay,
     },
-    { NULL }
 };
 
 static const AVFilterPad overlay_cuda_outputs[] = {
@@ -576,7 +575,6 @@  static const AVFilterPad overlay_cuda_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = &overlay_cuda_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_overlay_cuda = {
@@ -589,7 +587,9 @@  const AVFilter ff_vf_overlay_cuda = {
     .activate        = &overlay_cuda_activate,
     .query_formats   = &overlay_cuda_query_formats,
     .inputs          = overlay_cuda_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(overlay_cuda_inputs),
     .outputs         = overlay_cuda_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(overlay_cuda_outputs),
     .preinit         = overlay_cuda_framesync_preinit,
     .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_overlay_opencl.c b/libavfilter/vf_overlay_opencl.c
index 6ba622baaa..430a0871cd 100644
--- a/libavfilter/vf_overlay_opencl.c
+++ b/libavfilter/vf_overlay_opencl.c
@@ -300,7 +300,6 @@  static const AVFilterPad overlay_opencl_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad overlay_opencl_outputs[] = {
@@ -309,7 +308,6 @@  static const AVFilterPad overlay_opencl_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = &overlay_opencl_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_overlay_opencl = {
@@ -322,6 +320,8 @@  const AVFilter ff_vf_overlay_opencl = {
     .query_formats   = &ff_opencl_filter_query_formats,
     .activate        = &overlay_opencl_activate,
     .inputs          = overlay_opencl_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(overlay_opencl_inputs),
     .outputs         = overlay_opencl_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(overlay_opencl_outputs),
     .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_overlay_qsv.c b/libavfilter/vf_overlay_qsv.c
index 14c4c37a3c..eb2f2660a4 100644
--- a/libavfilter/vf_overlay_qsv.c
+++ b/libavfilter/vf_overlay_qsv.c
@@ -403,7 +403,6 @@  static const AVFilterPad overlay_qsv_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_overlay_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad overlay_qsv_outputs[] = {
@@ -412,7 +411,6 @@  static const AVFilterPad overlay_qsv_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_overlay_qsv = {
@@ -425,7 +423,9 @@  const AVFilter ff_vf_overlay_qsv = {
     .uninit         = overlay_qsv_uninit,
     .activate       = activate,
     .inputs         = overlay_qsv_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(overlay_qsv_inputs),
     .outputs        = overlay_qsv_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(overlay_qsv_outputs),
     .priv_class     = &overlay_qsv_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c
index 8dd3bd2092..a1ebea8c13 100644
--- a/libavfilter/vf_overlay_vulkan.c
+++ b/libavfilter/vf_overlay_vulkan.c
@@ -463,7 +463,6 @@  static const AVFilterPad overlay_vulkan_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vk_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad overlay_vulkan_outputs[] = {
@@ -472,7 +471,6 @@  static const AVFilterPad overlay_vulkan_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &overlay_vulkan_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_overlay_vulkan = {
@@ -484,7 +482,9 @@  const AVFilter ff_vf_overlay_vulkan = {
     .query_formats  = &ff_vk_filter_query_formats,
     .activate       = &overlay_vulkan_activate,
     .inputs         = overlay_vulkan_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(overlay_vulkan_inputs),
     .outputs        = overlay_vulkan_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(overlay_vulkan_outputs),
     .priv_class     = &overlay_vulkan_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_owdenoise.c b/libavfilter/vf_owdenoise.c
index f16a06e3b8..20d0d2d443 100644
--- a/libavfilter/vf_owdenoise.c
+++ b/libavfilter/vf_owdenoise.c
@@ -354,7 +354,6 @@  static const AVFilterPad owdenoise_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad owdenoise_outputs[] = {
@@ -362,7 +361,6 @@  static const AVFilterPad owdenoise_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_owdenoise = {
@@ -372,7 +370,9 @@  const AVFilter ff_vf_owdenoise = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = owdenoise_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(owdenoise_inputs),
     .outputs       = owdenoise_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(owdenoise_outputs),
     .priv_class    = &owdenoise_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index 871f2930af..dc78593289 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -441,7 +441,6 @@  static const AVFilterPad avfilter_vf_pad_inputs[] = {
         .get_video_buffer = get_video_buffer,
         .filter_frame     = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_pad_outputs[] = {
@@ -450,7 +449,6 @@  static const AVFilterPad avfilter_vf_pad_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pad = {
@@ -460,5 +458,7 @@  const AVFilter ff_vf_pad = {
     .priv_class    = &pad_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_pad_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_pad_inputs),
     .outputs       = avfilter_vf_pad_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_pad_outputs),
 };
diff --git a/libavfilter/vf_pad_opencl.c b/libavfilter/vf_pad_opencl.c
index 8155a96e03..cf2e95f314 100644
--- a/libavfilter/vf_pad_opencl.c
+++ b/libavfilter/vf_pad_opencl.c
@@ -354,7 +354,6 @@  static const AVFilterPad pad_opencl_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad pad_opencl_outputs[] = {
@@ -363,7 +362,6 @@  static const AVFilterPad pad_opencl_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &pad_opencl_config_output,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(PadOpenCLContext, x)
@@ -392,6 +390,8 @@  const AVFilter ff_vf_pad_opencl = {
     .uninit         = &pad_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = pad_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(pad_opencl_inputs),
     .outputs        = pad_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(pad_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE
 };
diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c
index ef8bc181c5..bfd462f9ae 100644
--- a/libavfilter/vf_palettegen.c
+++ b/libavfilter/vf_palettegen.c
@@ -557,7 +557,6 @@  static const AVFilterPad palettegen_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad palettegen_outputs[] = {
@@ -567,7 +566,6 @@  static const AVFilterPad palettegen_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_palettegen = {
@@ -577,6 +575,8 @@  const AVFilter ff_vf_palettegen = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = palettegen_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(palettegen_inputs),
     .outputs       = palettegen_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(palettegen_outputs),
     .priv_class    = &palettegen_class,
 };
diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c
index f07ef5d760..01e35aede7 100644
--- a/libavfilter/vf_paletteuse.c
+++ b/libavfilter/vf_paletteuse.c
@@ -1122,7 +1122,6 @@  static const AVFilterPad paletteuse_inputs[] = {
         .type           = AVMEDIA_TYPE_VIDEO,
         .config_props   = config_input_palette,
     },
-    { NULL }
 };
 
 static const AVFilterPad paletteuse_outputs[] = {
@@ -1131,7 +1130,6 @@  static const AVFilterPad paletteuse_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_paletteuse = {
@@ -1143,6 +1141,8 @@  const AVFilter ff_vf_paletteuse = {
     .uninit        = uninit,
     .activate      = activate,
     .inputs        = paletteuse_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(paletteuse_inputs),
     .outputs       = paletteuse_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(paletteuse_outputs),
     .priv_class    = &paletteuse_class,
 };
diff --git a/libavfilter/vf_perspective.c b/libavfilter/vf_perspective.c
index a3fa080f21..461acace74 100644
--- a/libavfilter/vf_perspective.c
+++ b/libavfilter/vf_perspective.c
@@ -500,7 +500,6 @@  static const AVFilterPad perspective_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad perspective_outputs[] = {
@@ -508,7 +507,6 @@  static const AVFilterPad perspective_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_perspective = {
@@ -519,7 +517,9 @@  const AVFilter ff_vf_perspective = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = perspective_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(perspective_inputs),
     .outputs       = perspective_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(perspective_outputs),
     .priv_class    = &perspective_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_phase.c b/libavfilter/vf_phase.c
index 556620d36c..40f15accd5 100644
--- a/libavfilter/vf_phase.c
+++ b/libavfilter/vf_phase.c
@@ -224,7 +224,6 @@  static const AVFilterPad phase_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad phase_outputs[] = {
@@ -232,7 +231,6 @@  static const AVFilterPad phase_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_phase = {
@@ -243,7 +241,9 @@  const AVFilter ff_vf_phase = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = phase_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(phase_inputs),
     .outputs       = phase_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(phase_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_photosensitivity.c b/libavfilter/vf_photosensitivity.c
index dd3d957bfa..f95324fed4 100644
--- a/libavfilter/vf_photosensitivity.c
+++ b/libavfilter/vf_photosensitivity.c
@@ -318,7 +318,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -326,7 +325,6 @@  static const AVFilterPad outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_photosensitivity = {
@@ -337,5 +335,7 @@  const AVFilter ff_vf_photosensitivity = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_pixdesctest.c b/libavfilter/vf_pixdesctest.c
index b56839d994..f8adee65e3 100644
--- a/libavfilter/vf_pixdesctest.c
+++ b/libavfilter/vf_pixdesctest.c
@@ -113,7 +113,6 @@  static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_pixdesctest_outputs[] = {
@@ -121,7 +120,6 @@  static const AVFilterPad avfilter_vf_pixdesctest_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pixdesctest = {
@@ -130,5 +128,7 @@  const AVFilter ff_vf_pixdesctest = {
     .priv_size   = sizeof(PixdescTestContext),
     .uninit      = uninit,
     .inputs      = avfilter_vf_pixdesctest_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_pixdesctest_inputs),
     .outputs     = avfilter_vf_pixdesctest_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_pixdesctest_outputs),
 };
diff --git a/libavfilter/vf_pp.c b/libavfilter/vf_pp.c
index 5cd89932f8..e125289663 100644
--- a/libavfilter/vf_pp.c
+++ b/libavfilter/vf_pp.c
@@ -180,7 +180,6 @@  static const AVFilterPad pp_inputs[] = {
         .config_props = pp_config_props,
         .filter_frame = pp_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad pp_outputs[] = {
@@ -188,7 +187,6 @@  static const AVFilterPad pp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pp = {
@@ -199,7 +197,9 @@  const AVFilter ff_vf_pp = {
     .uninit          = pp_uninit,
     .query_formats   = pp_query_formats,
     .inputs          = pp_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(pp_inputs),
     .outputs         = pp_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(pp_outputs),
     .process_command = pp_process_command,
     .priv_class      = &pp_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
diff --git a/libavfilter/vf_pp7.c b/libavfilter/vf_pp7.c
index a9a2fa3d19..1c080c870e 100644
--- a/libavfilter/vf_pp7.c
+++ b/libavfilter/vf_pp7.c
@@ -390,7 +390,6 @@  static const AVFilterPad pp7_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad pp7_outputs[] = {
@@ -398,7 +397,6 @@  static const AVFilterPad pp7_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pp7 = {
@@ -408,7 +406,9 @@  const AVFilter ff_vf_pp7 = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = pp7_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(pp7_inputs),
     .outputs         = pp7_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(pp7_outputs),
     .priv_class      = &pp7_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c
index b5d0ca6d67..8670fcf88b 100644
--- a/libavfilter/vf_premultiply.c
+++ b/libavfilter/vf_premultiply.c
@@ -819,7 +819,6 @@  static const AVFilterPad premultiply_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_PREMULTIPLY_FILTER
@@ -834,6 +833,7 @@  const AVFilter ff_vf_premultiply = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = premultiply_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(premultiply_outputs),
     .priv_class    = &premultiply_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_DYNAMIC_INPUTS |
@@ -857,6 +857,7 @@  const AVFilter ff_vf_unpremultiply = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = premultiply_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(premultiply_outputs),
     .priv_class    = &unpremultiply_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
                      AVFILTER_FLAG_DYNAMIC_INPUTS |
diff --git a/libavfilter/vf_procamp_vaapi.c b/libavfilter/vf_procamp_vaapi.c
index 5527556d09..5327fcfd35 100644
--- a/libavfilter/vf_procamp_vaapi.c
+++ b/libavfilter/vf_procamp_vaapi.c
@@ -219,7 +219,6 @@  static const AVFilterPad procamp_vaapi_inputs[] = {
         .filter_frame = &procamp_vaapi_filter_frame,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad procamp_vaapi_outputs[] = {
@@ -228,7 +227,6 @@  static const AVFilterPad procamp_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vaapi_vpp_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_procamp_vaapi = {
@@ -239,7 +237,9 @@  const AVFilter ff_vf_procamp_vaapi = {
     .uninit        = &ff_vaapi_vpp_ctx_uninit,
     .query_formats = &ff_vaapi_vpp_query_formats,
     .inputs        = procamp_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(procamp_vaapi_inputs),
     .outputs       = procamp_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(procamp_vaapi_outputs),
     .priv_class    = &procamp_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c
index 4b38baeb3c..b76c589258 100644
--- a/libavfilter/vf_program_opencl.c
+++ b/libavfilter/vf_program_opencl.c
@@ -359,7 +359,6 @@  static const AVFilterPad program_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &program_opencl_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_program_opencl = {
@@ -374,6 +373,7 @@  const AVFilter ff_vf_program_opencl = {
     .activate       = &program_opencl_activate,
     .inputs         = NULL,
     .outputs        = program_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(program_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
@@ -412,7 +412,6 @@  static const AVFilterPad openclsrc_outputs[] = {
         .config_props  = &program_opencl_config_output,
         .request_frame = &program_opencl_request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_openclsrc = {
@@ -425,6 +424,7 @@  const AVFilter ff_vsrc_openclsrc = {
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = NULL,
     .outputs        = openclsrc_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(openclsrc_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
 
diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c
index ec14a0c363..eb0f956182 100644
--- a/libavfilter/vf_pseudocolor.c
+++ b/libavfilter/vf_pseudocolor.c
@@ -896,7 +896,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -904,7 +903,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static av_cold void uninit(AVFilterContext *ctx)
@@ -928,7 +926,9 @@  const AVFilter ff_vf_pseudocolor = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c
index e5459d3f34..3d470c058c 100644
--- a/libavfilter/vf_psnr.c
+++ b/libavfilter/vf_psnr.c
@@ -455,7 +455,6 @@  static const AVFilterPad psnr_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad psnr_outputs[] = {
@@ -464,7 +463,6 @@  static const AVFilterPad psnr_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_psnr = {
@@ -478,6 +476,8 @@  const AVFilter ff_vf_psnr = {
     .priv_size     = sizeof(PSNRContext),
     .priv_class    = &psnr_class,
     .inputs        = psnr_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(psnr_inputs),
     .outputs       = psnr_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(psnr_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_pullup.c b/libavfilter/vf_pullup.c
index 00d3a8dc51..57e1b81aed 100644
--- a/libavfilter/vf_pullup.c
+++ b/libavfilter/vf_pullup.c
@@ -753,7 +753,6 @@  static const AVFilterPad pullup_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad pullup_outputs[] = {
@@ -761,7 +760,6 @@  static const AVFilterPad pullup_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_pullup = {
@@ -772,5 +770,7 @@  const AVFilter ff_vf_pullup = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = pullup_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(pullup_inputs),
     .outputs       = pullup_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(pullup_outputs),
 };
diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c
index c932d45a76..761f3447e7 100644
--- a/libavfilter/vf_qp.c
+++ b/libavfilter/vf_qp.c
@@ -182,7 +182,6 @@  static const AVFilterPad qp_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad qp_outputs[] = {
@@ -190,7 +189,6 @@  static const AVFilterPad qp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_qp = {
@@ -198,7 +196,9 @@  const AVFilter ff_vf_qp = {
     .description   = NULL_IF_CONFIG_SMALL("Change video quantization parameters."),
     .priv_size     = sizeof(QPContext),
     .inputs        = qp_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(qp_inputs),
     .outputs       = qp_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(qp_outputs),
     .priv_class    = &qp_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_random.c b/libavfilter/vf_random.c
index 5e4c30a3b5..ffe1bb2b17 100644
--- a/libavfilter/vf_random.c
+++ b/libavfilter/vf_random.c
@@ -127,7 +127,6 @@  static const AVFilterPad random_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad random_outputs[] = {
@@ -136,7 +135,6 @@  static const AVFilterPad random_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_random = {
@@ -147,5 +145,7 @@  const AVFilter ff_vf_random = {
     .init        = init,
     .uninit      = uninit,
     .inputs      = random_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(random_inputs),
     .outputs     = random_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(random_outputs),
 };
diff --git a/libavfilter/vf_readeia608.c b/libavfilter/vf_readeia608.c
index 9558e938ab..0852946e7a 100644
--- a/libavfilter/vf_readeia608.c
+++ b/libavfilter/vf_readeia608.c
@@ -545,7 +545,6 @@  static const AVFilterPad readeia608_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad readeia608_outputs[] = {
@@ -553,7 +552,6 @@  static const AVFilterPad readeia608_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_readeia608 = {
@@ -563,7 +561,9 @@  const AVFilter ff_vf_readeia608 = {
     .priv_class    = &readeia608_class,
     .query_formats = query_formats,
     .inputs        = readeia608_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(readeia608_inputs),
     .outputs       = readeia608_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(readeia608_outputs),
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_readvitc.c b/libavfilter/vf_readvitc.c
index 25cfa5f32d..82b764a2a9 100644
--- a/libavfilter/vf_readvitc.c
+++ b/libavfilter/vf_readvitc.c
@@ -235,7 +235,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -243,7 +242,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_readvitc = {
@@ -252,7 +250,9 @@  const AVFilter ff_vf_readvitc = {
     .priv_size     = sizeof(ReadVitcContext),
     .priv_class    = &readvitc_class,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .init          = init,
     .query_formats = query_formats,
 };
diff --git a/libavfilter/vf_remap.c b/libavfilter/vf_remap.c
index 5ab6199d71..9d05434599 100644
--- a/libavfilter/vf_remap.c
+++ b/libavfilter/vf_remap.c
@@ -386,7 +386,6 @@  static const AVFilterPad remap_inputs[] = {
         .name         = "ymap",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad remap_outputs[] = {
@@ -395,7 +394,6 @@  static const AVFilterPad remap_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_remap = {
@@ -406,7 +404,9 @@  const AVFilter ff_vf_remap = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = remap_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(remap_inputs),
     .outputs       = remap_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(remap_outputs),
     .priv_class    = &remap_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_removegrain.c b/libavfilter/vf_removegrain.c
index 75b3ec35bb..532b8a5d39 100644
--- a/libavfilter/vf_removegrain.c
+++ b/libavfilter/vf_removegrain.c
@@ -637,7 +637,6 @@  static const AVFilterPad removegrain_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad removegrain_outputs[] = {
@@ -645,7 +644,6 @@  static const AVFilterPad removegrain_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_removegrain = {
@@ -654,7 +652,9 @@  const AVFilter ff_vf_removegrain = {
     .priv_size     = sizeof(RemoveGrainContext),
     .query_formats = query_formats,
     .inputs        = removegrain_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(removegrain_inputs),
     .outputs       = removegrain_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(removegrain_outputs),
     .priv_class    = &removegrain_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_removelogo.c b/libavfilter/vf_removelogo.c
index 4bb81a8a5b..c7425fd628 100644
--- a/libavfilter/vf_removelogo.c
+++ b/libavfilter/vf_removelogo.c
@@ -562,7 +562,6 @@  static const AVFilterPad removelogo_inputs[] = {
         .config_props = config_props_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad removelogo_outputs[] = {
@@ -570,7 +569,6 @@  static const AVFilterPad removelogo_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_removelogo = {
@@ -581,7 +579,9 @@  const AVFilter ff_vf_removelogo = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = removelogo_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(removelogo_inputs),
     .outputs       = removelogo_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(removelogo_outputs),
     .priv_class    = &removelogo_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_repeatfields.c b/libavfilter/vf_repeatfields.c
index 1e2abd3a82..741f9de492 100644
--- a/libavfilter/vf_repeatfields.c
+++ b/libavfilter/vf_repeatfields.c
@@ -170,7 +170,6 @@  static const AVFilterPad repeatfields_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad repeatfields_outputs[] = {
@@ -178,7 +177,6 @@  static const AVFilterPad repeatfields_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_repeatfields = {
@@ -187,6 +185,8 @@  const AVFilter ff_vf_repeatfields = {
     .priv_size     = sizeof(RepeatFieldsContext),
     .uninit        = uninit,
     .inputs        = repeatfields_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(repeatfields_inputs),
     .outputs       = repeatfields_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(repeatfields_outputs),
     .query_formats = query_formats,
 };
diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c
index f16207cbff..f8da37e538 100644
--- a/libavfilter/vf_rotate.c
+++ b/libavfilter/vf_rotate.c
@@ -588,7 +588,6 @@  static const AVFilterPad rotate_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad rotate_outputs[] = {
@@ -597,7 +596,6 @@  static const AVFilterPad rotate_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_rotate = {
@@ -609,7 +607,9 @@  const AVFilter ff_vf_rotate = {
     .query_formats = query_formats,
     .process_command = process_command,
     .inputs        = rotate_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(rotate_inputs),
     .outputs       = rotate_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(rotate_outputs),
     .priv_class    = &rotate_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_sab.c b/libavfilter/vf_sab.c
index 12fbe40655..405dbbafec 100644
--- a/libavfilter/vf_sab.c
+++ b/libavfilter/vf_sab.c
@@ -312,7 +312,6 @@  static const AVFilterPad sab_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad sab_outputs[] = {
@@ -320,7 +319,6 @@  static const AVFilterPad sab_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_sab = {
@@ -331,7 +329,9 @@  const AVFilter ff_vf_sab = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = sab_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(sab_inputs),
     .outputs       = sab_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(sab_outputs),
     .priv_class    = &sab_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index 160ad8b584..0f074595c4 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -957,7 +957,6 @@  static const AVFilterPad avfilter_vf_scale_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_scale_outputs[] = {
@@ -966,7 +965,6 @@  static const AVFilterPad avfilter_vf_scale_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale = {
@@ -978,7 +976,9 @@  const AVFilter ff_vf_scale = {
     .priv_size       = sizeof(ScaleContext),
     .priv_class      = &scale_class,
     .inputs          = avfilter_vf_scale_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_scale_inputs),
     .outputs         = avfilter_vf_scale_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_scale_outputs),
     .process_command = process_command,
 };
 
@@ -1002,7 +1002,6 @@  static const AVFilterPad avfilter_vf_scale2ref_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_scale2ref_outputs[] = {
@@ -1018,7 +1017,6 @@  static const AVFilterPad avfilter_vf_scale2ref_outputs[] = {
         .config_props = config_props_ref,
         .request_frame= request_frame_ref,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale2ref = {
@@ -1030,6 +1028,8 @@  const AVFilter ff_vf_scale2ref = {
     .priv_size       = sizeof(ScaleContext),
     .priv_class      = &scale2ref_class,
     .inputs          = avfilter_vf_scale2ref_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_scale2ref_inputs),
     .outputs         = avfilter_vf_scale2ref_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_scale2ref_outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c
index f3ea01634b..1d2415f618 100644
--- a/libavfilter/vf_scale_cuda.c
+++ b/libavfilter/vf_scale_cuda.c
@@ -628,7 +628,6 @@  static const AVFilterPad cudascale_inputs[] = {
         .filter_frame = cudascale_filter_frame,
         .get_video_buffer = cudascale_get_video_buffer,
     },
-    { NULL }
 };
 
 static const AVFilterPad cudascale_outputs[] = {
@@ -637,7 +636,6 @@  static const AVFilterPad cudascale_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = cudascale_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale_cuda = {
@@ -652,7 +650,9 @@  const AVFilter ff_vf_scale_cuda = {
     .priv_class = &cudascale_class,
 
     .inputs    = cudascale_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(cudascale_inputs),
     .outputs   = cudascale_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(cudascale_outputs),
 
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c
index 8d2ad3aab7..75a2a23c66 100644
--- a/libavfilter/vf_scale_npp.c
+++ b/libavfilter/vf_scale_npp.c
@@ -579,7 +579,6 @@  static const AVFilterPad nppscale_inputs[] = {
         .type        = AVMEDIA_TYPE_VIDEO,
         .filter_frame = nppscale_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad nppscale_outputs[] = {
@@ -588,7 +587,6 @@  static const AVFilterPad nppscale_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = nppscale_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale_npp = {
@@ -604,7 +602,9 @@  const AVFilter ff_vf_scale_npp = {
     .priv_class = &nppscale_class,
 
     .inputs    = nppscale_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(nppscale_inputs),
     .outputs   = nppscale_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(nppscale_outputs),
 
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index 189223a58a..126412fc68 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -655,7 +655,6 @@  static const AVFilterPad qsvscale_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = qsvscale_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad qsvscale_outputs[] = {
@@ -664,7 +663,6 @@  static const AVFilterPad qsvscale_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = qsvscale_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale_qsv = {
@@ -679,7 +677,9 @@  const AVFilter ff_vf_scale_qsv = {
     .priv_class = &qsvscale_class,
 
     .inputs    = qsvscale_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(qsvscale_inputs),
     .outputs   = qsvscale_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(qsvscale_outputs),
 
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 41ff93156d..91650456ac 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -269,7 +269,6 @@  static const AVFilterPad scale_vaapi_inputs[] = {
         .filter_frame = &scale_vaapi_filter_frame,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad scale_vaapi_outputs[] = {
@@ -278,7 +277,6 @@  static const AVFilterPad scale_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &scale_vaapi_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale_vaapi = {
@@ -289,7 +287,9 @@  const AVFilter ff_vf_scale_vaapi = {
     .uninit        = &ff_vaapi_vpp_ctx_uninit,
     .query_formats = &ff_vaapi_vpp_query_formats,
     .inputs        = scale_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(scale_vaapi_inputs),
     .outputs       = scale_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(scale_vaapi_outputs),
     .priv_class    = &scale_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c
index 95503480ef..9f541015dc 100644
--- a/libavfilter/vf_scale_vulkan.c
+++ b/libavfilter/vf_scale_vulkan.c
@@ -512,7 +512,6 @@  static const AVFilterPad scale_vulkan_inputs[] = {
         .filter_frame = &scale_vulkan_filter_frame,
         .config_props = &ff_vk_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad scale_vulkan_outputs[] = {
@@ -521,7 +520,6 @@  static const AVFilterPad scale_vulkan_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &scale_vulkan_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scale_vulkan = {
@@ -532,7 +530,9 @@  const AVFilter ff_vf_scale_vulkan = {
     .uninit         = &scale_vulkan_uninit,
     .query_formats  = &ff_vk_filter_query_formats,
     .inputs         = scale_vulkan_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(scale_vulkan_inputs),
     .outputs        = scale_vulkan_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(scale_vulkan_outputs),
     .priv_class     = &scale_vulkan_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c
index ff8bf21a9c..a65e7b6ebc 100644
--- a/libavfilter/vf_scdet.c
+++ b/libavfilter/vf_scdet.c
@@ -199,7 +199,6 @@  static const AVFilterPad scdet_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad scdet_outputs[] = {
@@ -207,7 +206,6 @@  static const AVFilterPad scdet_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scdet = {
@@ -218,6 +216,8 @@  const AVFilter ff_vf_scdet = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = scdet_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(scdet_inputs),
     .outputs       = scdet_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(scdet_outputs),
     .activate      = activate,
 };
diff --git a/libavfilter/vf_scroll.c b/libavfilter/vf_scroll.c
index 4b7b45f52a..b8a6308fe9 100644
--- a/libavfilter/vf_scroll.c
+++ b/libavfilter/vf_scroll.c
@@ -200,7 +200,6 @@  static const AVFilterPad scroll_inputs[] = {
         .config_props   = config_input,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad scroll_outputs[] = {
@@ -208,7 +207,6 @@  static const AVFilterPad scroll_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_scroll = {
@@ -218,7 +216,9 @@  const AVFilter ff_vf_scroll = {
     .priv_class    = &scroll_class,
     .query_formats = query_formats,
     .inputs        = scroll_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(scroll_inputs),
     .outputs       = scroll_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(scroll_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_selectivecolor.c b/libavfilter/vf_selectivecolor.c
index 4733cc48f2..25b44607a0 100644
--- a/libavfilter/vf_selectivecolor.c
+++ b/libavfilter/vf_selectivecolor.c
@@ -459,7 +459,6 @@  static const AVFilterPad selectivecolor_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad selectivecolor_outputs[] = {
@@ -467,7 +466,6 @@  static const AVFilterPad selectivecolor_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_selectivecolor = {
@@ -476,7 +474,9 @@  const AVFilter ff_vf_selectivecolor = {
     .priv_size     = sizeof(SelectiveColorContext),
     .query_formats = query_formats,
     .inputs        = selectivecolor_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(selectivecolor_inputs),
     .outputs       = selectivecolor_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(selectivecolor_outputs),
     .priv_class    = &selectivecolor_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_separatefields.c b/libavfilter/vf_separatefields.c
index c2c7352ad1..7b6e324f1f 100644
--- a/libavfilter/vf_separatefields.c
+++ b/libavfilter/vf_separatefields.c
@@ -161,7 +161,6 @@  static const AVFilterPad separatefields_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad separatefields_outputs[] = {
@@ -170,7 +169,6 @@  static const AVFilterPad separatefields_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_separatefields = {
@@ -180,5 +178,7 @@  const AVFilter ff_vf_separatefields = {
     .activate    = activate,
     .uninit      = uninit,
     .inputs      = separatefields_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(separatefields_inputs),
     .outputs     = separatefields_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(separatefields_outputs),
 };
diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c
index 0cb3af33ed..e049c64126 100644
--- a/libavfilter/vf_setparams.c
+++ b/libavfilter/vf_setparams.c
@@ -151,7 +151,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -159,7 +158,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_setparams = {
@@ -168,7 +166,9 @@  const AVFilter ff_vf_setparams = {
     .priv_size   = sizeof(SetParamsContext),
     .priv_class  = &setparams_class,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
 };
 
 #if CONFIG_SETRANGE_FILTER
@@ -207,7 +207,9 @@  const AVFilter ff_vf_setrange = {
     .init        = init_setrange,
     .priv_class  = &setrange_class,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
 };
 #endif /* CONFIG_SETRANGE_FILTER */
 
@@ -241,6 +243,8 @@  const AVFilter ff_vf_setfield = {
     .init        = init_setfield,
     .priv_class  = &setfield_class,
     .inputs      = inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(inputs),
     .outputs     = outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(outputs),
 };
 #endif /* CONFIG_SETFIELD_FILTER */
diff --git a/libavfilter/vf_shear.c b/libavfilter/vf_shear.c
index 6b9db161d9..b09f2684ac 100644
--- a/libavfilter/vf_shear.c
+++ b/libavfilter/vf_shear.c
@@ -304,7 +304,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -313,7 +312,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_shear = {
@@ -323,7 +321,9 @@  const AVFilter ff_vf_shear = {
     .init            = init,
     .query_formats   = query_formats,
     .inputs          = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs         = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .priv_class      = &shear_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index dfb7f86359..f51e4c7ca6 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -661,7 +661,6 @@  static const AVFilterPad avfilter_vf_showinfo_inputs[] = {
         .filter_frame     = filter_frame,
         .config_props     = config_props_in,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_showinfo_outputs[] = {
@@ -670,14 +669,15 @@  static const AVFilterPad avfilter_vf_showinfo_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props_out,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_showinfo = {
     .name        = "showinfo",
     .description = NULL_IF_CONFIG_SMALL("Show textual information for each video frame."),
     .inputs      = avfilter_vf_showinfo_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_showinfo_inputs),
     .outputs     = avfilter_vf_showinfo_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_showinfo_outputs),
     .priv_size   = sizeof(ShowInfoContext),
     .priv_class  = &showinfo_class,
 };
diff --git a/libavfilter/vf_showpalette.c b/libavfilter/vf_showpalette.c
index 2455af687c..24de335929 100644
--- a/libavfilter/vf_showpalette.c
+++ b/libavfilter/vf_showpalette.c
@@ -100,7 +100,6 @@  static const AVFilterPad showpalette_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad showpalette_outputs[] = {
@@ -109,7 +108,6 @@  static const AVFilterPad showpalette_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_showpalette = {
@@ -118,6 +116,8 @@  const AVFilter ff_vf_showpalette = {
     .priv_size     = sizeof(ShowPaletteContext),
     .query_formats = query_formats,
     .inputs        = showpalette_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(showpalette_inputs),
     .outputs       = showpalette_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(showpalette_outputs),
     .priv_class    = &showpalette_class,
 };
diff --git a/libavfilter/vf_shuffleframes.c b/libavfilter/vf_shuffleframes.c
index cdc70f552e..4b935732a8 100644
--- a/libavfilter/vf_shuffleframes.c
+++ b/libavfilter/vf_shuffleframes.c
@@ -144,7 +144,6 @@  static const AVFilterPad shuffleframes_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL },
 };
 
 static const AVFilterPad shuffleframes_outputs[] = {
@@ -152,7 +151,6 @@  static const AVFilterPad shuffleframes_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL },
 };
 
 const AVFilter ff_vf_shuffleframes = {
@@ -163,6 +161,8 @@  const AVFilter ff_vf_shuffleframes = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = shuffleframes_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(shuffleframes_inputs),
     .outputs       = shuffleframes_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(shuffleframes_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_shufflepixels.c b/libavfilter/vf_shufflepixels.c
index b5e757c929..0776d308ae 100644
--- a/libavfilter/vf_shufflepixels.c
+++ b/libavfilter/vf_shufflepixels.c
@@ -436,7 +436,6 @@  static const AVFilterPad shufflepixels_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL },
 };
 
 static const AVFilterPad shufflepixels_outputs[] = {
@@ -445,7 +444,6 @@  static const AVFilterPad shufflepixels_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL },
 };
 
 const AVFilter ff_vf_shufflepixels = {
@@ -456,6 +454,8 @@  const AVFilter ff_vf_shufflepixels = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = shufflepixels_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(shufflepixels_inputs),
     .outputs       = shufflepixels_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(shufflepixels_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_shuffleplanes.c b/libavfilter/vf_shuffleplanes.c
index d1e1d11074..2f916c92cf 100644
--- a/libavfilter/vf_shuffleplanes.c
+++ b/libavfilter/vf_shuffleplanes.c
@@ -151,7 +151,6 @@  static const AVFilterPad shuffleplanes_inputs[] = {
         .config_props     = shuffleplanes_config_input,
         .filter_frame     = shuffleplanes_filter_frame,
     },
-    { NULL },
 };
 
 static const AVFilterPad shuffleplanes_outputs[] = {
@@ -159,7 +158,6 @@  static const AVFilterPad shuffleplanes_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL },
 };
 
 const AVFilter ff_vf_shuffleplanes = {
@@ -169,6 +167,8 @@  const AVFilter ff_vf_shuffleplanes = {
     .priv_class   = &shuffleplanes_class,
     .query_formats = query_formats,
     .inputs       = shuffleplanes_inputs,
+    .nb_inputs    = FF_ARRAY_ELEMS(shuffleplanes_inputs),
     .outputs      = shuffleplanes_outputs,
+    .nb_outputs   = FF_ARRAY_ELEMS(shuffleplanes_outputs),
     .flags        = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_signalstats.c b/libavfilter/vf_signalstats.c
index 6f0ff53029..5c0f2d667c 100644
--- a/libavfilter/vf_signalstats.c
+++ b/libavfilter/vf_signalstats.c
@@ -1000,7 +1000,6 @@  static const AVFilterPad signalstats_inputs[] = {
         .type           = AVMEDIA_TYPE_VIDEO,
         .filter_frame   = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad signalstats_outputs[] = {
@@ -1009,7 +1008,6 @@  static const AVFilterPad signalstats_outputs[] = {
         .config_props   = config_output,
         .type           = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_signalstats = {
@@ -1020,7 +1018,9 @@  const AVFilter ff_vf_signalstats = {
     .query_formats = query_formats,
     .priv_size     = sizeof(SignalstatsContext),
     .inputs        = signalstats_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(signalstats_inputs),
     .outputs       = signalstats_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(signalstats_outputs),
     .priv_class    = &signalstats_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_signature.c b/libavfilter/vf_signature.c
index a345ad6ebd..8adc69477a 100644
--- a/libavfilter/vf_signature.c
+++ b/libavfilter/vf_signature.c
@@ -755,7 +755,6 @@  static const AVFilterPad signature_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_signature = {
@@ -767,6 +766,7 @@  const AVFilter ff_vf_signature = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .outputs       = signature_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(signature_outputs),
     .inputs        = NULL,
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
diff --git a/libavfilter/vf_smartblur.c b/libavfilter/vf_smartblur.c
index 36ed72a12c..a346170635 100644
--- a/libavfilter/vf_smartblur.c
+++ b/libavfilter/vf_smartblur.c
@@ -280,7 +280,6 @@  static const AVFilterPad smartblur_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad smartblur_outputs[] = {
@@ -288,7 +287,6 @@  static const AVFilterPad smartblur_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_smartblur = {
@@ -299,7 +297,9 @@  const AVFilter ff_vf_smartblur = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = smartblur_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(smartblur_inputs),
     .outputs       = smartblur_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(smartblur_outputs),
     .priv_class    = &smartblur_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_spp.c b/libavfilter/vf_spp.c
index cfa1cb77c4..a4aa7ba65a 100644
--- a/libavfilter/vf_spp.c
+++ b/libavfilter/vf_spp.c
@@ -498,7 +498,6 @@  static const AVFilterPad spp_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad spp_outputs[] = {
@@ -506,7 +505,6 @@  static const AVFilterPad spp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_spp = {
@@ -517,7 +515,9 @@  const AVFilter ff_vf_spp = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = spp_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(spp_inputs),
     .outputs         = spp_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(spp_outputs),
     .process_command = process_command,
     .priv_class      = &spp_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
diff --git a/libavfilter/vf_sr.c b/libavfilter/vf_sr.c
index f930b38748..42785bcab1 100644
--- a/libavfilter/vf_sr.c
+++ b/libavfilter/vf_sr.c
@@ -181,7 +181,6 @@  static const AVFilterPad sr_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad sr_outputs[] = {
@@ -190,7 +189,6 @@  static const AVFilterPad sr_outputs[] = {
         .config_props = config_output,
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_sr = {
@@ -201,6 +199,8 @@  const AVFilter ff_vf_sr = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = sr_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(sr_inputs),
     .outputs       = sr_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(sr_outputs),
     .priv_class    = &sr_class,
 };
diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c
index c6e4fe286a..81b26a9848 100644
--- a/libavfilter/vf_ssim.c
+++ b/libavfilter/vf_ssim.c
@@ -581,7 +581,6 @@  static const AVFilterPad ssim_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad ssim_outputs[] = {
@@ -590,7 +589,6 @@  static const AVFilterPad ssim_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_ssim = {
@@ -604,6 +602,8 @@  const AVFilter ff_vf_ssim = {
     .priv_size     = sizeof(SSIMContext),
     .priv_class    = &ssim_class,
     .inputs        = ssim_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ssim_inputs),
     .outputs       = ssim_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ssim_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index 3368e25c9c..a99496ca52 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -401,7 +401,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_HSTACK_FILTER
@@ -416,6 +415,7 @@  const AVFilter ff_vf_hstack = {
     .priv_class    = &hstack_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .init          = init,
     .uninit        = uninit,
     .activate      = activate,
@@ -436,6 +436,7 @@  const AVFilter ff_vf_vstack = {
     .priv_class    = &vstack_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .init          = init,
     .uninit        = uninit,
     .activate      = activate,
@@ -463,6 +464,7 @@  const AVFilter ff_vf_xstack = {
     .priv_class    = &xstack_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .init          = init,
     .uninit        = uninit,
     .activate      = activate,
diff --git a/libavfilter/vf_stereo3d.c b/libavfilter/vf_stereo3d.c
index ec7d410f76..b99a4e43a0 100644
--- a/libavfilter/vf_stereo3d.c
+++ b/libavfilter/vf_stereo3d.c
@@ -1100,7 +1100,6 @@  static const AVFilterPad stereo3d_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad stereo3d_outputs[] = {
@@ -1109,7 +1108,6 @@  static const AVFilterPad stereo3d_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_stereo3d = {
@@ -1119,7 +1117,9 @@  const AVFilter ff_vf_stereo3d = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = stereo3d_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(stereo3d_inputs),
     .outputs       = stereo3d_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(stereo3d_outputs),
     .priv_class    = &stereo3d_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index ab32e1b7f3..07fef01da3 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -202,7 +202,6 @@  static const AVFilterPad ass_inputs[] = {
         .config_props     = config_input,
         .needs_writable   = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad ass_outputs[] = {
@@ -210,7 +209,6 @@  static const AVFilterPad ass_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #if CONFIG_ASS_FILTER
@@ -255,7 +253,9 @@  const AVFilter ff_vf_ass = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = ass_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ass_inputs),
     .outputs       = ass_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ass_outputs),
     .priv_class    = &ass_class,
 };
 #endif
@@ -489,7 +489,9 @@  const AVFilter ff_vf_subtitles = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = ass_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(ass_inputs),
     .outputs       = ass_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(ass_outputs),
     .priv_class    = &subtitles_class,
 };
 #endif
diff --git a/libavfilter/vf_super2xsai.c b/libavfilter/vf_super2xsai.c
index 00e88eafe3..c24b5e02a1 100644
--- a/libavfilter/vf_super2xsai.c
+++ b/libavfilter/vf_super2xsai.c
@@ -347,7 +347,6 @@  static const AVFilterPad super2xsai_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad super2xsai_outputs[] = {
@@ -356,7 +355,6 @@  static const AVFilterPad super2xsai_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_super2xsai = {
@@ -365,6 +363,8 @@  const AVFilter ff_vf_super2xsai = {
     .priv_size     = sizeof(Super2xSaIContext),
     .query_formats = query_formats,
     .inputs        = super2xsai_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(super2xsai_inputs),
     .outputs       = super2xsai_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(super2xsai_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_swaprect.c b/libavfilter/vf_swaprect.c
index 3b96790798..a29849ff79 100644
--- a/libavfilter/vf_swaprect.c
+++ b/libavfilter/vf_swaprect.c
@@ -232,7 +232,6 @@  static const AVFilterPad inputs[] = {
         .config_props   = config_input,
         .needs_writable = 1,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -240,7 +239,6 @@  static const AVFilterPad outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_swaprect = {
@@ -251,7 +249,9 @@  const AVFilter ff_vf_swaprect = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_swapuv.c b/libavfilter/vf_swapuv.c
index 34868eb0c9..b00e7ec790 100644
--- a/libavfilter/vf_swapuv.c
+++ b/libavfilter/vf_swapuv.c
@@ -100,7 +100,6 @@  static const AVFilterPad swapuv_inputs[] = {
         .get_video_buffer = get_video_buffer,
         .filter_frame     = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad swapuv_outputs[] = {
@@ -108,7 +107,6 @@  static const AVFilterPad swapuv_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_swapuv = {
@@ -118,6 +116,8 @@  const AVFilter ff_vf_swapuv = {
     .priv_size     = sizeof(SwapUVContext),
     .priv_class    = &swapuv_class,
     .inputs        = swapuv_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(swapuv_inputs),
     .outputs       = swapuv_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(swapuv_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_telecine.c b/libavfilter/vf_telecine.c
index 52a3f2f353..3aee0fcd9f 100644
--- a/libavfilter/vf_telecine.c
+++ b/libavfilter/vf_telecine.c
@@ -275,7 +275,6 @@  static const AVFilterPad telecine_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad telecine_outputs[] = {
@@ -284,7 +283,6 @@  static const AVFilterPad telecine_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_telecine = {
@@ -296,5 +294,7 @@  const AVFilter ff_vf_telecine = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = telecine_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(telecine_inputs),
     .outputs       = telecine_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(telecine_outputs),
 };
diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c
index 0c8787e331..d5d43e38d5 100644
--- a/libavfilter/vf_threshold.c
+++ b/libavfilter/vf_threshold.c
@@ -342,7 +342,6 @@  static const AVFilterPad inputs[] = {
         .name         = "max",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -351,7 +350,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_threshold = {
@@ -363,7 +361,9 @@  const AVFilter ff_vf_threshold = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_thumbnail.c b/libavfilter/vf_thumbnail.c
index 825e536e67..c22f697183 100644
--- a/libavfilter/vf_thumbnail.c
+++ b/libavfilter/vf_thumbnail.c
@@ -275,7 +275,6 @@  static const AVFilterPad thumbnail_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad thumbnail_outputs[] = {
@@ -284,7 +283,6 @@  static const AVFilterPad thumbnail_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_thumbnail = {
@@ -295,7 +293,9 @@  const AVFilter ff_vf_thumbnail = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = thumbnail_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(thumbnail_inputs),
     .outputs       = thumbnail_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(thumbnail_outputs),
     .priv_class    = &thumbnail_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_thumbnail_cuda.c b/libavfilter/vf_thumbnail_cuda.c
index ceac10f72f..09ef551d03 100644
--- a/libavfilter/vf_thumbnail_cuda.c
+++ b/libavfilter/vf_thumbnail_cuda.c
@@ -431,7 +431,6 @@  static const AVFilterPad thumbnail_cuda_inputs[] = {
         .config_props = config_props,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad thumbnail_cuda_outputs[] = {
@@ -440,7 +439,6 @@  static const AVFilterPad thumbnail_cuda_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_thumbnail_cuda = {
@@ -451,7 +449,9 @@  const AVFilter ff_vf_thumbnail_cuda = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = thumbnail_cuda_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(thumbnail_cuda_inputs),
     .outputs       = thumbnail_cuda_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(thumbnail_cuda_outputs),
     .priv_class    = &thumbnail_cuda_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c
index 11392169e4..ff500aa11b 100644
--- a/libavfilter/vf_tile.c
+++ b/libavfilter/vf_tile.c
@@ -272,7 +272,6 @@  static const AVFilterPad tile_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tile_outputs[] = {
@@ -282,7 +281,6 @@  static const AVFilterPad tile_outputs[] = {
         .config_props  = config_props,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tile = {
@@ -293,6 +291,8 @@  const AVFilter ff_vf_tile = {
     .query_formats = query_formats,
     .priv_size     = sizeof(TileContext),
     .inputs        = tile_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tile_inputs),
     .outputs       = tile_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tile_outputs),
     .priv_class    = &tile_class,
 };
diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
index 40d8879871..9311590af8 100644
--- a/libavfilter/vf_tinterlace.c
+++ b/libavfilter/vf_tinterlace.c
@@ -543,7 +543,6 @@  static const AVFilterPad tinterlace_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tinterlace_outputs[] = {
@@ -552,7 +551,6 @@  static const AVFilterPad tinterlace_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_out_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tinterlace = {
@@ -562,7 +560,9 @@  const AVFilter ff_vf_tinterlace = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = tinterlace_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tinterlace_inputs),
     .outputs       = tinterlace_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tinterlace_outputs),
     .priv_class    = &tinterlace_class,
 };
 
@@ -575,6 +575,8 @@  const AVFilter ff_vf_interlace = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = tinterlace_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tinterlace_inputs),
     .outputs       = tinterlace_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tinterlace_outputs),
     .priv_class    = &interlace_class,
 };
diff --git a/libavfilter/vf_tmidequalizer.c b/libavfilter/vf_tmidequalizer.c
index 24e1d557e2..680776192f 100644
--- a/libavfilter/vf_tmidequalizer.c
+++ b/libavfilter/vf_tmidequalizer.c
@@ -415,7 +415,6 @@  static const AVFilterPad tmidequalizer_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tmidequalizer_outputs[] = {
@@ -424,7 +423,6 @@  static const AVFilterPad tmidequalizer_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tmidequalizer = {
@@ -434,7 +432,9 @@  const AVFilter ff_vf_tmidequalizer = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = tmidequalizer_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tmidequalizer_inputs),
     .outputs       = tmidequalizer_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tmidequalizer_outputs),
     .priv_class    = &tmidequalizer_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c
index 4d04118eac..fe4da6e438 100644
--- a/libavfilter/vf_tonemap.c
+++ b/libavfilter/vf_tonemap.c
@@ -323,7 +323,6 @@  static const AVFilterPad tonemap_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tonemap_outputs[] = {
@@ -331,7 +330,6 @@  static const AVFilterPad tonemap_outputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tonemap = {
@@ -342,6 +340,8 @@  const AVFilter ff_vf_tonemap = {
     .priv_size       = sizeof(TonemapContext),
     .priv_class      = &tonemap_class,
     .inputs          = tonemap_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(tonemap_inputs),
     .outputs         = tonemap_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(tonemap_outputs),
     .flags           = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c
index 8cf7c099ee..5533a5bf8a 100644
--- a/libavfilter/vf_tonemap_opencl.c
+++ b/libavfilter/vf_tonemap_opencl.c
@@ -527,7 +527,6 @@  static const AVFilterPad tonemap_opencl_inputs[] = {
         .filter_frame = &tonemap_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad tonemap_opencl_outputs[] = {
@@ -536,7 +535,6 @@  static const AVFilterPad tonemap_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &tonemap_opencl_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tonemap_opencl = {
@@ -548,6 +546,8 @@  const AVFilter ff_vf_tonemap_opencl = {
     .uninit         = &tonemap_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = tonemap_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(tonemap_opencl_inputs),
     .outputs        = tonemap_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(tonemap_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_tonemap_vaapi.c b/libavfilter/vf_tonemap_vaapi.c
index d33c4f8f6d..401b541cef 100644
--- a/libavfilter/vf_tonemap_vaapi.c
+++ b/libavfilter/vf_tonemap_vaapi.c
@@ -391,7 +391,6 @@  static const AVFilterPad tonemap_vaapi_inputs[] = {
         .filter_frame = &tonemap_vaapi_filter_frame,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad tonemap_vaapi_outputs[] = {
@@ -400,7 +399,6 @@  static const AVFilterPad tonemap_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_vaapi_vpp_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tonemap_vaapi = {
@@ -411,7 +409,9 @@  const AVFilter ff_vf_tonemap_vaapi = {
     .uninit         = &ff_vaapi_vpp_ctx_uninit,
     .query_formats  = &ff_vaapi_vpp_query_formats,
     .inputs         = tonemap_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(tonemap_vaapi_inputs),
     .outputs        = tonemap_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(tonemap_vaapi_outputs),
     .priv_class     = &tonemap_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c
index d23869f3e2..c88da1cd40 100644
--- a/libavfilter/vf_tpad.c
+++ b/libavfilter/vf_tpad.c
@@ -193,7 +193,6 @@  static const AVFilterPad tpad_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad tpad_outputs[] = {
@@ -201,7 +200,6 @@  static const AVFilterPad tpad_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_tpad = {
@@ -213,5 +211,7 @@  const AVFilter ff_vf_tpad = {
     .activate      = activate,
     .uninit        = uninit,
     .inputs        = tpad_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tpad_inputs),
     .outputs       = tpad_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tpad_outputs),
 };
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index 6affbed0a6..e8a976dbaf 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -385,7 +385,6 @@  static const AVFilterPad avfilter_vf_transpose_inputs[] = {
         .get_video_buffer = get_video_buffer,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_transpose_outputs[] = {
@@ -394,7 +393,6 @@  static const AVFilterPad avfilter_vf_transpose_outputs[] = {
         .config_props = config_props_output,
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_transpose = {
@@ -404,6 +402,8 @@  const AVFilter ff_vf_transpose = {
     .priv_class    = &transpose_class,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_transpose_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_transpose_inputs),
     .outputs       = avfilter_vf_transpose_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_transpose_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_transpose_npp.c b/libavfilter/vf_transpose_npp.c
index 2a68a832ff..bddca86fb4 100644
--- a/libavfilter/vf_transpose_npp.c
+++ b/libavfilter/vf_transpose_npp.c
@@ -461,7 +461,6 @@  static const AVFilterPad npptranspose_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = npptranspose_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad npptranspose_outputs[] = {
@@ -470,7 +469,6 @@  static const AVFilterPad npptranspose_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = npptranspose_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_transpose_npp = {
@@ -482,6 +480,8 @@  const AVFilter ff_vf_transpose_npp = {
     .priv_size      = sizeof(NPPTransposeContext),
     .priv_class     = &npptranspose_class,
     .inputs         = npptranspose_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(npptranspose_inputs),
     .outputs        = npptranspose_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(npptranspose_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_transpose_opencl.c b/libavfilter/vf_transpose_opencl.c
index 2877d3c826..5203c09b5c 100644
--- a/libavfilter/vf_transpose_opencl.c
+++ b/libavfilter/vf_transpose_opencl.c
@@ -260,7 +260,6 @@  static const AVFilterPad transpose_opencl_inputs[] = {
         .filter_frame = &transpose_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad transpose_opencl_outputs[] = {
@@ -269,7 +268,6 @@  static const AVFilterPad transpose_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &transpose_opencl_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_transpose_opencl = {
@@ -281,6 +279,8 @@  const AVFilter ff_vf_transpose_opencl = {
     .uninit         = &transpose_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = transpose_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(transpose_opencl_inputs),
     .outputs        = transpose_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(transpose_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_transpose_vaapi.c b/libavfilter/vf_transpose_vaapi.c
index 79413e0eeb..b95db576d6 100644
--- a/libavfilter/vf_transpose_vaapi.c
+++ b/libavfilter/vf_transpose_vaapi.c
@@ -260,7 +260,6 @@  static const AVFilterPad transpose_vaapi_inputs[] = {
         .get_video_buffer = get_video_buffer,
         .config_props = &ff_vaapi_vpp_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad transpose_vaapi_outputs[] = {
@@ -269,7 +268,6 @@  static const AVFilterPad transpose_vaapi_outputs[] = {
         .type = AVMEDIA_TYPE_VIDEO,
         .config_props = &transpose_vaapi_vpp_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_transpose_vaapi = {
@@ -280,7 +278,9 @@  const AVFilter ff_vf_transpose_vaapi = {
     .uninit         = &ff_vaapi_vpp_ctx_uninit,
     .query_formats  = &ff_vaapi_vpp_query_formats,
     .inputs         = transpose_vaapi_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(transpose_vaapi_inputs),
     .outputs        = transpose_vaapi_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(transpose_vaapi_outputs),
     .priv_class     = &transpose_vaapi_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c
index 0bf72169a9..7143068991 100644
--- a/libavfilter/vf_unsharp.c
+++ b/libavfilter/vf_unsharp.c
@@ -345,7 +345,6 @@  static const AVFilterPad avfilter_vf_unsharp_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_unsharp_outputs[] = {
@@ -353,7 +352,6 @@  static const AVFilterPad avfilter_vf_unsharp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_unsharp = {
@@ -365,6 +363,8 @@  const AVFilter ff_vf_unsharp = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_unsharp_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_unsharp_inputs),
     .outputs       = avfilter_vf_unsharp_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_unsharp_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_unsharp_opencl.c b/libavfilter/vf_unsharp_opencl.c
index 200350de9f..a580487412 100644
--- a/libavfilter/vf_unsharp_opencl.c
+++ b/libavfilter/vf_unsharp_opencl.c
@@ -386,7 +386,6 @@  static const AVFilterPad unsharp_opencl_inputs[] = {
         .filter_frame = &unsharp_opencl_filter_frame,
         .config_props = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad unsharp_opencl_outputs[] = {
@@ -395,7 +394,6 @@  static const AVFilterPad unsharp_opencl_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = &ff_opencl_filter_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_unsharp_opencl = {
@@ -407,6 +405,8 @@  const AVFilter ff_vf_unsharp_opencl = {
     .uninit         = &unsharp_opencl_uninit,
     .query_formats  = &ff_opencl_filter_query_formats,
     .inputs         = unsharp_opencl_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(unsharp_opencl_inputs),
     .outputs        = unsharp_opencl_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(unsharp_opencl_outputs),
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_untile.c b/libavfilter/vf_untile.c
index 9035e819d4..9e872bffa7 100644
--- a/libavfilter/vf_untile.c
+++ b/libavfilter/vf_untile.c
@@ -172,7 +172,6 @@  static const AVFilterPad untile_inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad untile_outputs[] = {
@@ -181,7 +180,6 @@  static const AVFilterPad untile_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_untile = {
@@ -193,6 +191,8 @@  const AVFilter ff_vf_untile = {
     .activate      = activate,
     .priv_size     = sizeof(UntileContext),
     .inputs        = untile_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(untile_inputs),
     .outputs       = untile_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(untile_outputs),
     .priv_class    = &untile_class,
 };
diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c
index 7029963e29..fe0fb43dc6 100644
--- a/libavfilter/vf_uspp.c
+++ b/libavfilter/vf_uspp.c
@@ -483,7 +483,6 @@  static const AVFilterPad uspp_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad uspp_outputs[] = {
@@ -491,7 +490,6 @@  static const AVFilterPad uspp_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_uspp = {
@@ -501,7 +499,9 @@  const AVFilter ff_vf_uspp = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = uspp_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(uspp_inputs),
     .outputs         = uspp_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(uspp_outputs),
     .priv_class      = &uspp_class,
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
 };
diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c
index 692fa43c4d..b79773ac0e 100644
--- a/libavfilter/vf_v360.c
+++ b/libavfilter/vf_v360.c
@@ -4969,7 +4969,6 @@  static const AVFilterPad inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -4978,7 +4977,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_v360 = {
@@ -4989,7 +4987,9 @@  const AVFilter ff_vf_v360 = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .priv_class    = &v360_class,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
     .process_command = process_command,
diff --git a/libavfilter/vf_vaguedenoiser.c b/libavfilter/vf_vaguedenoiser.c
index 481fc774e5..69daee0d7b 100644
--- a/libavfilter/vf_vaguedenoiser.c
+++ b/libavfilter/vf_vaguedenoiser.c
@@ -598,7 +598,6 @@  static const AVFilterPad vaguedenoiser_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 
@@ -607,7 +606,6 @@  static const AVFilterPad vaguedenoiser_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vaguedenoiser = {
@@ -619,6 +617,8 @@  const AVFilter ff_vf_vaguedenoiser = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = vaguedenoiser_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(vaguedenoiser_inputs),
     .outputs       = vaguedenoiser_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(vaguedenoiser_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_vectorscope.c b/libavfilter/vf_vectorscope.c
index 0669230890..75eeb91e9d 100644
--- a/libavfilter/vf_vectorscope.c
+++ b/libavfilter/vf_vectorscope.c
@@ -1575,7 +1575,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -1584,7 +1583,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vectorscope = {
@@ -1595,5 +1593,7 @@  const AVFilter ff_vf_vectorscope = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_vflip.c b/libavfilter/vf_vflip.c
index 95a693a7e1..53fc3e1df2 100644
--- a/libavfilter/vf_vflip.c
+++ b/libavfilter/vf_vflip.c
@@ -133,7 +133,6 @@  static const AVFilterPad avfilter_vf_vflip_inputs[] = {
         .filter_frame     = filter_frame,
         .config_props     = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_vflip_outputs[] = {
@@ -141,7 +140,6 @@  static const AVFilterPad avfilter_vf_vflip_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vflip = {
@@ -150,6 +148,8 @@  const AVFilter ff_vf_vflip = {
     .priv_size   = sizeof(FlipContext),
     .priv_class  = &vflip_class,
     .inputs      = avfilter_vf_vflip_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vf_vflip_inputs),
     .outputs     = avfilter_vf_vflip_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(avfilter_vf_vflip_outputs),
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_vfrdet.c b/libavfilter/vf_vfrdet.c
index 7e37036aef..7f551cb687 100644
--- a/libavfilter/vf_vfrdet.c
+++ b/libavfilter/vf_vfrdet.c
@@ -93,7 +93,6 @@  static const AVFilterPad vfrdet_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad vfrdet_outputs[] = {
@@ -101,7 +100,6 @@  static const AVFilterPad vfrdet_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vfrdet = {
@@ -111,5 +109,7 @@  const AVFilter ff_vf_vfrdet = {
     .init        = init,
     .uninit      = uninit,
     .inputs      = vfrdet_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(vfrdet_inputs),
     .outputs     = vfrdet_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(vfrdet_outputs),
 };
diff --git a/libavfilter/vf_vibrance.c b/libavfilter/vf_vibrance.c
index cca677ee78..1340069100 100644
--- a/libavfilter/vf_vibrance.c
+++ b/libavfilter/vf_vibrance.c
@@ -350,7 +350,6 @@  static const AVFilterPad vibrance_inputs[] = {
         .filter_frame   = filter_frame,
         .config_props   = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad vibrance_outputs[] = {
@@ -358,7 +357,6 @@  static const AVFilterPad vibrance_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(VibranceContext, x)
@@ -385,7 +383,9 @@  const AVFilter ff_vf_vibrance = {
     .priv_class    = &vibrance_class,
     .query_formats = query_formats,
     .inputs        = vibrance_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(vibrance_inputs),
     .outputs       = vibrance_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(vibrance_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c
index 475d0381bc..2dbd009a5e 100644
--- a/libavfilter/vf_vidstabdetect.c
+++ b/libavfilter/vf_vidstabdetect.c
@@ -196,7 +196,6 @@  static const AVFilterPad avfilter_vf_vidstabdetect_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_vidstabdetect_outputs[] = {
@@ -204,7 +203,6 @@  static const AVFilterPad avfilter_vf_vidstabdetect_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vidstabdetect = {
@@ -217,6 +215,8 @@  const AVFilter ff_vf_vidstabdetect = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_vidstabdetect_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_vidstabdetect_inputs),
     .outputs       = avfilter_vf_vidstabdetect_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_vidstabdetect_outputs),
     .priv_class    = &vidstabdetect_class,
 };
diff --git a/libavfilter/vf_vidstabtransform.c b/libavfilter/vf_vidstabtransform.c
index 79e62c1f58..02c2a64cca 100644
--- a/libavfilter/vf_vidstabtransform.c
+++ b/libavfilter/vf_vidstabtransform.c
@@ -297,7 +297,6 @@  static const AVFilterPad avfilter_vf_vidstabtransform_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_vidstabtransform_outputs[] = {
@@ -305,7 +304,6 @@  static const AVFilterPad avfilter_vf_vidstabtransform_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vidstabtransform = {
@@ -318,6 +316,8 @@  const AVFilter ff_vf_vidstabtransform = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_vidstabtransform_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_vidstabtransform_inputs),
     .outputs       = avfilter_vf_vidstabtransform_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_vidstabtransform_outputs),
     .priv_class    = &vidstabtransform_class,
 };
diff --git a/libavfilter/vf_vif.c b/libavfilter/vf_vif.c
index c21bd40f44..471a054156 100644
--- a/libavfilter/vf_vif.c
+++ b/libavfilter/vf_vif.c
@@ -630,7 +630,6 @@  static const AVFilterPad vif_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad vif_outputs[] = {
@@ -639,7 +638,6 @@  static const AVFilterPad vif_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vif = {
@@ -651,6 +649,8 @@  const AVFilter ff_vf_vif = {
     .priv_class    = &vif_class,
     .activate      = activate,
     .inputs        = vif_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(vif_inputs),
     .outputs       = vif_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(vif_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_vignette.c b/libavfilter/vf_vignette.c
index 91754306ae..efb657f818 100644
--- a/libavfilter/vf_vignette.c
+++ b/libavfilter/vf_vignette.c
@@ -330,7 +330,6 @@  static const AVFilterPad vignette_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 static const AVFilterPad vignette_outputs[] = {
@@ -338,7 +337,6 @@  static const AVFilterPad vignette_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vignette = {
@@ -349,7 +347,9 @@  const AVFilter ff_vf_vignette = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = vignette_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(vignette_inputs),
     .outputs       = vignette_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(vignette_outputs),
     .priv_class    = &vignette_class,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
 };
diff --git a/libavfilter/vf_vmafmotion.c b/libavfilter/vf_vmafmotion.c
index 454ebb8afa..feb063ef21 100644
--- a/libavfilter/vf_vmafmotion.c
+++ b/libavfilter/vf_vmafmotion.c
@@ -347,7 +347,6 @@  static const AVFilterPad vmafmotion_inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input_ref,
     },
-    { NULL }
 };
 
 static const AVFilterPad vmafmotion_outputs[] = {
@@ -355,7 +354,6 @@  static const AVFilterPad vmafmotion_outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vmafmotion = {
@@ -367,5 +365,7 @@  const AVFilter ff_vf_vmafmotion = {
     .priv_size     = sizeof(VMAFMotionContext),
     .priv_class    = &vmafmotion_class,
     .inputs        = vmafmotion_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(vmafmotion_inputs),
     .outputs       = vmafmotion_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(vmafmotion_outputs),
 };
diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c
index ee9317a49e..8ebefcaef0 100644
--- a/libavfilter/vf_vpp_qsv.c
+++ b/libavfilter/vf_vpp_qsv.c
@@ -600,7 +600,6 @@  static const AVFilterPad vpp_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad vpp_outputs[] = {
@@ -609,7 +608,6 @@  static const AVFilterPad vpp_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_vpp_qsv = {
@@ -620,7 +618,9 @@  const AVFilter ff_vf_vpp_qsv = {
     .init          = vpp_init,
     .uninit        = vpp_uninit,
     .inputs        = vpp_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(vpp_inputs),
     .outputs       = vpp_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(vpp_outputs),
     .activate      = activate,
     .priv_class    = &vpp_class,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c
index 5edb826f0a..f0fe0985ed 100644
--- a/libavfilter/vf_w3fdif.c
+++ b/libavfilter/vf_w3fdif.c
@@ -600,7 +600,6 @@  static const AVFilterPad w3fdif_inputs[] = {
         .filter_frame  = filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad w3fdif_outputs[] = {
@@ -610,7 +609,6 @@  static const AVFilterPad w3fdif_outputs[] = {
         .config_props  = config_output,
         .request_frame = request_frame,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_w3fdif = {
@@ -621,7 +619,9 @@  const AVFilter ff_vf_w3fdif = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = w3fdif_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(w3fdif_inputs),
     .outputs       = w3fdif_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(w3fdif_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c
index 977ebad9ce..7bf997f2f2 100644
--- a/libavfilter/vf_waveform.c
+++ b/libavfilter/vf_waveform.c
@@ -3477,7 +3477,6 @@  static const AVFilterPad inputs[] = {
         .filter_frame = filter_frame,
         .config_props = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -3486,7 +3485,6 @@  static const AVFilterPad outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_waveform = {
@@ -3497,6 +3495,8 @@  const AVFilter ff_vf_waveform = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c
index 98b8d0bd06..54b19b1e86 100644
--- a/libavfilter/vf_weave.c
+++ b/libavfilter/vf_weave.c
@@ -178,7 +178,6 @@  static const AVFilterPad weave_inputs[] = {
         .type             = AVMEDIA_TYPE_VIDEO,
         .filter_frame     = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad weave_outputs[] = {
@@ -187,7 +186,6 @@  static const AVFilterPad weave_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_weave = {
@@ -198,7 +196,9 @@  const AVFilter ff_vf_weave = {
     .query_formats = query_formats,
     .uninit        = uninit,
     .inputs        = weave_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(weave_inputs),
     .outputs       = weave_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(weave_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
 
@@ -224,6 +224,8 @@  const AVFilter ff_vf_doubleweave = {
     .init          = init,
     .uninit        = uninit,
     .inputs        = weave_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(weave_inputs),
     .outputs       = weave_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(weave_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_xbr.c b/libavfilter/vf_xbr.c
index 1300693bac..36288b970f 100644
--- a/libavfilter/vf_xbr.c
+++ b/libavfilter/vf_xbr.c
@@ -412,7 +412,6 @@  static const AVFilterPad xbr_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad xbr_outputs[] = {
@@ -421,14 +420,15 @@  static const AVFilterPad xbr_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_xbr = {
     .name          = "xbr",
     .description   = NULL_IF_CONFIG_SMALL("Scale the input using xBR algorithm."),
     .inputs        = xbr_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(xbr_inputs),
     .outputs       = xbr_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(xbr_outputs),
     .query_formats = query_formats,
     .priv_size     = sizeof(XBRContext),
     .priv_class    = &xbr_class,
diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c
index 2e075cfb9a..1564db4530 100644
--- a/libavfilter/vf_xfade.c
+++ b/libavfilter/vf_xfade.c
@@ -1944,7 +1944,6 @@  static const AVFilterPad xfade_inputs[] = {
         .name          = "xfade",
         .type          = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad xfade_outputs[] = {
@@ -1953,7 +1952,6 @@  static const AVFilterPad xfade_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_xfade = {
@@ -1965,6 +1963,8 @@  const AVFilter ff_vf_xfade = {
     .activate      = xfade_activate,
     .uninit        = uninit,
     .inputs        = xfade_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(xfade_inputs),
     .outputs       = xfade_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(xfade_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_xfade_opencl.c b/libavfilter/vf_xfade_opencl.c
index 5b64ea2f08..e00c1ed40e 100644
--- a/libavfilter/vf_xfade_opencl.c
+++ b/libavfilter/vf_xfade_opencl.c
@@ -411,7 +411,6 @@  static const AVFilterPad xfade_opencl_inputs[] = {
         .get_video_buffer = get_video_buffer,
         .config_props     = &ff_opencl_filter_config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad xfade_opencl_outputs[] = {
@@ -420,7 +419,6 @@  static const AVFilterPad xfade_opencl_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = &xfade_opencl_config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_xfade_opencl = {
@@ -433,6 +431,8 @@  const AVFilter ff_vf_xfade_opencl = {
     .query_formats   = &ff_opencl_filter_query_formats,
     .activate        = &xfade_opencl_activate,
     .inputs          = xfade_opencl_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(xfade_opencl_inputs),
     .outputs         = xfade_opencl_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(xfade_opencl_outputs),
     .flags_internal  = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c
index 168a5944db..ed83b37f39 100644
--- a/libavfilter/vf_xmedian.c
+++ b/libavfilter/vf_xmedian.c
@@ -385,7 +385,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 #if CONFIG_XMEDIAN_FILTER
@@ -398,6 +397,7 @@  const AVFilter ff_vf_xmedian = {
     .priv_class    = &xmedian_class,
     .query_formats = query_formats,
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
     .preinit       = xmedian_framesync_preinit,
     .init          = init,
     .uninit        = uninit,
@@ -461,7 +461,6 @@  static const AVFilterPad tmedian_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = tmedian_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad tmedian_outputs[] = {
@@ -470,7 +469,6 @@  static const AVFilterPad tmedian_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(tmedian);
@@ -482,7 +480,9 @@  const AVFilter ff_vf_tmedian = {
     .priv_class    = &tmedian_class,
     .query_formats = query_formats,
     .inputs        = tmedian_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(tmedian_inputs),
     .outputs       = tmedian_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(tmedian_outputs),
     .init          = init,
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c
index 17269d6b96..3800179b43 100644
--- a/libavfilter/vf_yadif.c
+++ b/libavfilter/vf_yadif.c
@@ -339,7 +339,6 @@  static const AVFilterPad avfilter_vf_yadif_inputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .filter_frame  = ff_yadif_filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_yadif_outputs[] = {
@@ -349,7 +348,6 @@  static const AVFilterPad avfilter_vf_yadif_outputs[] = {
         .request_frame = ff_yadif_request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_yadif = {
@@ -360,6 +358,8 @@  const AVFilter ff_vf_yadif = {
     .uninit        = uninit,
     .query_formats = query_formats,
     .inputs        = avfilter_vf_yadif_inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(avfilter_vf_yadif_inputs),
     .outputs       = avfilter_vf_yadif_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vf_yadif_outputs),
     .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c
index 95267d6a1c..fd29defa20 100644
--- a/libavfilter/vf_yadif_cuda.c
+++ b/libavfilter/vf_yadif_cuda.c
@@ -363,7 +363,6 @@  static const AVFilterPad deint_cuda_inputs[] = {
         .filter_frame  = ff_yadif_filter_frame,
         .config_props  = config_input,
     },
-    { NULL }
 };
 
 static const AVFilterPad deint_cuda_outputs[] = {
@@ -373,7 +372,6 @@  static const AVFilterPad deint_cuda_outputs[] = {
         .request_frame = ff_yadif_request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_yadif_cuda = {
@@ -384,7 +382,9 @@  const AVFilter ff_vf_yadif_cuda = {
     .uninit         = deint_cuda_uninit,
     .query_formats  = deint_cuda_query_formats,
     .inputs         = deint_cuda_inputs,
+    .nb_inputs      = FF_ARRAY_ELEMS(deint_cuda_inputs),
     .outputs        = deint_cuda_outputs,
+    .nb_outputs     = FF_ARRAY_ELEMS(deint_cuda_outputs),
     .flags          = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
     .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
 };
diff --git a/libavfilter/vf_yaepblur.c b/libavfilter/vf_yaepblur.c
index 3380f7112a..5ae43fc36f 100644
--- a/libavfilter/vf_yaepblur.c
+++ b/libavfilter/vf_yaepblur.c
@@ -309,7 +309,6 @@  static const AVFilterPad yaep_inputs[] = {
         .config_props = config_input,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad yaep_outputs[] = {
@@ -317,7 +316,6 @@  static const AVFilterPad yaep_outputs[] = {
         .name = "default",
         .type = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 #define OFFSET(x) offsetof(YAEPContext, x)
@@ -343,7 +341,9 @@  const AVFilter ff_vf_yaepblur = {
     .uninit          = uninit,
     .query_formats   = query_formats,
     .inputs          = yaep_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(yaep_inputs),
     .outputs         = yaep_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(yaep_outputs),
     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS,
     .process_command = ff_filter_process_command,
 };
diff --git a/libavfilter/vf_zoompan.c b/libavfilter/vf_zoompan.c
index 9115c23dc4..8bc56ced91 100644
--- a/libavfilter/vf_zoompan.c
+++ b/libavfilter/vf_zoompan.c
@@ -364,7 +364,6 @@  static const AVFilterPad inputs[] = {
         .name         = "default",
         .type         = AVMEDIA_TYPE_VIDEO,
     },
-    { NULL }
 };
 
 static const AVFilterPad outputs[] = {
@@ -373,7 +372,6 @@  static const AVFilterPad outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_zoompan = {
@@ -386,5 +384,7 @@  const AVFilter ff_vf_zoompan = {
     .query_formats = query_formats,
     .activate      = activate,
     .inputs        = inputs,
+    .nb_inputs     = FF_ARRAY_ELEMS(inputs),
     .outputs       = outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(outputs),
 };
diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c
index d21de8d9db..a8469ddc15 100644
--- a/libavfilter/vf_zscale.c
+++ b/libavfilter/vf_zscale.c
@@ -914,7 +914,6 @@  static const AVFilterPad avfilter_vf_zscale_inputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL }
 };
 
 static const AVFilterPad avfilter_vf_zscale_outputs[] = {
@@ -923,7 +922,6 @@  static const AVFilterPad avfilter_vf_zscale_outputs[] = {
         .type         = AVMEDIA_TYPE_VIDEO,
         .config_props = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vf_zscale = {
@@ -935,6 +933,8 @@  const AVFilter ff_vf_zscale = {
     .priv_class      = &zscale_class,
     .uninit          = uninit,
     .inputs          = avfilter_vf_zscale_inputs,
+    .nb_inputs       = FF_ARRAY_ELEMS(avfilter_vf_zscale_inputs),
     .outputs         = avfilter_vf_zscale_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(avfilter_vf_zscale_outputs),
     .process_command = process_command,
 };
diff --git a/libavfilter/vsink_nullsink.c b/libavfilter/vsink_nullsink.c
index 1c796b7cb8..db30834af0 100644
--- a/libavfilter/vsink_nullsink.c
+++ b/libavfilter/vsink_nullsink.c
@@ -32,7 +32,6 @@  static const AVFilterPad avfilter_vsink_nullsink_inputs[] = {
         .type        = AVMEDIA_TYPE_VIDEO,
         .filter_frame = filter_frame,
     },
-    { NULL },
 };
 
 const AVFilter ff_vsink_nullsink = {
@@ -40,5 +39,6 @@  const AVFilter ff_vsink_nullsink = {
     .description = NULL_IF_CONFIG_SMALL("Do absolutely nothing with the input video."),
     .priv_size   = 0,
     .inputs      = avfilter_vsink_nullsink_inputs,
+    .nb_inputs   = FF_ARRAY_ELEMS(avfilter_vsink_nullsink_inputs),
     .outputs     = NULL,
 };
diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c
index 250c88c8da..e9dfa7aff5 100644
--- a/libavfilter/vsrc_cellauto.c
+++ b/libavfilter/vsrc_cellauto.c
@@ -324,7 +324,6 @@  static const AVFilterPad cellauto_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_cellauto = {
@@ -337,4 +336,5 @@  const AVFilter ff_vsrc_cellauto = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = cellauto_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(cellauto_outputs),
 };
diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c
index 904baf1360..c378283a74 100644
--- a/libavfilter/vsrc_gradients.c
+++ b/libavfilter/vsrc_gradients.c
@@ -295,7 +295,6 @@  static const AVFilterPad gradients_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_gradients = {
@@ -306,6 +305,7 @@  const AVFilter ff_vsrc_gradients = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = gradients_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(gradients_outputs),
     .activate      = activate,
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c
index ca12f294b8..ea5f63fdb8 100644
--- a/libavfilter/vsrc_life.c
+++ b/libavfilter/vsrc_life.c
@@ -438,7 +438,6 @@  static const AVFilterPad life_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL}
 };
 
 const AVFilter ff_vsrc_life = {
@@ -451,4 +450,5 @@  const AVFilter ff_vsrc_life = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = life_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(life_outputs),
 };
diff --git a/libavfilter/vsrc_mandelbrot.c b/libavfilter/vsrc_mandelbrot.c
index 88c14f0d48..ee96cea82e 100644
--- a/libavfilter/vsrc_mandelbrot.c
+++ b/libavfilter/vsrc_mandelbrot.c
@@ -416,7 +416,6 @@  static const AVFilterPad mandelbrot_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_mandelbrot = {
@@ -429,4 +428,5 @@  const AVFilter ff_vsrc_mandelbrot = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = mandelbrot_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mandelbrot_outputs),
 };
diff --git a/libavfilter/vsrc_mptestsrc.c b/libavfilter/vsrc_mptestsrc.c
index 8aa75a24ac..ae2f11fac1 100644
--- a/libavfilter/vsrc_mptestsrc.c
+++ b/libavfilter/vsrc_mptestsrc.c
@@ -354,7 +354,6 @@  static const AVFilterPad mptestsrc_outputs[] = {
         .request_frame = request_frame,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_mptestsrc = {
@@ -366,4 +365,5 @@  const AVFilter ff_vsrc_mptestsrc = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = mptestsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(mptestsrc_outputs),
 };
diff --git a/libavfilter/vsrc_sierpinski.c b/libavfilter/vsrc_sierpinski.c
index 7db4852892..a3cd4f05c9 100644
--- a/libavfilter/vsrc_sierpinski.c
+++ b/libavfilter/vsrc_sierpinski.c
@@ -220,7 +220,6 @@  static const AVFilterPad sierpinski_outputs[] = {
         .request_frame = sierpinski_request_frame,
         .config_props  = config_output,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_sierpinski = {
@@ -231,5 +230,6 @@  const AVFilter ff_vsrc_sierpinski = {
     .query_formats = query_formats,
     .inputs        = NULL,
     .outputs       = sierpinski_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(sierpinski_outputs),
     .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 08686938db..82b01640ce 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -263,7 +263,6 @@  static const AVFilterPad color_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = color_config_props,
     },
-    {  NULL }
 };
 
 const AVFilter ff_vsrc_color = {
@@ -277,6 +276,7 @@  const AVFilter ff_vsrc_color = {
     .query_formats   = color_query_formats,
     .inputs          = NULL,
     .outputs         = color_outputs,
+    .nb_outputs      = FF_ARRAY_ELEMS(color_outputs),
     .process_command = color_process_command,
 };
 
@@ -397,7 +397,6 @@  static const AVFilterPad haldclutsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = haldclutsrc_config_props,
     },
-    {  NULL }
 };
 
 const AVFilter ff_vsrc_haldclutsrc = {
@@ -411,6 +410,7 @@  const AVFilter ff_vsrc_haldclutsrc = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = haldclutsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(haldclutsrc_outputs),
 };
 #endif /* CONFIG_HALDCLUTSRC_FILTER */
 
@@ -435,7 +435,6 @@  static const AVFilterPad nullsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props,
     },
-    { NULL },
 };
 
 const AVFilter ff_vsrc_nullsrc = {
@@ -448,6 +447,7 @@  const AVFilter ff_vsrc_nullsrc = {
     .priv_class  = &nullsrc_class,
     .inputs      = NULL,
     .outputs     = nullsrc_outputs,
+    .nb_outputs  = FF_ARRAY_ELEMS(nullsrc_outputs),
 };
 
 #endif /* CONFIG_NULLSRC_FILTER */
@@ -671,7 +671,6 @@  static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_testsrc = {
@@ -685,6 +684,7 @@  const AVFilter ff_vsrc_testsrc = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_testsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_testsrc_outputs),
 };
 
 #endif /* CONFIG_TESTSRC_FILTER */
@@ -944,7 +944,6 @@  static const AVFilterPad avfilter_vsrc_testsrc2_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = test2_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_testsrc2 = {
@@ -958,6 +957,7 @@  const AVFilter ff_vsrc_testsrc2 = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_testsrc2_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_testsrc2_outputs),
 };
 
 #endif /* CONFIG_TESTSRC2_FILTER */
@@ -1119,7 +1119,6 @@  static const AVFilterPad avfilter_vsrc_rgbtestsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = rgbtest_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_rgbtestsrc = {
@@ -1133,6 +1132,7 @@  const AVFilter ff_vsrc_rgbtestsrc = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_rgbtestsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_rgbtestsrc_outputs),
 };
 
 #endif /* CONFIG_RGBTESTSRC_FILTER */
@@ -1295,7 +1295,6 @@  static const AVFilterPad avfilter_vsrc_yuvtestsrc_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = yuvtest_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_yuvtestsrc = {
@@ -1309,6 +1308,7 @@  const AVFilter ff_vsrc_yuvtestsrc = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_yuvtestsrc_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_yuvtestsrc_outputs),
 };
 
 #endif /* CONFIG_YUVTESTSRC_FILTER */
@@ -1438,7 +1438,6 @@  static const AVFilterPad smptebars_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 #if CONFIG_PAL75BARS_FILTER
@@ -1486,6 +1485,7 @@  const AVFilter ff_vsrc_pal75bars = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = smptebars_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(smptebars_outputs),
 };
 
 #endif  /* CONFIG_PAL75BARS_FILTER */
@@ -1533,6 +1533,7 @@  const AVFilter ff_vsrc_pal100bars = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = smptebars_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(smptebars_outputs),
 };
 
 #endif  /* CONFIG_PAL100BARS_FILTER */
@@ -1601,6 +1602,7 @@  const AVFilter ff_vsrc_smptebars = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = smptebars_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(smptebars_outputs),
 };
 
 #endif  /* CONFIG_SMPTEBARS_FILTER */
@@ -1707,6 +1709,7 @@  const AVFilter ff_vsrc_smptehdbars = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = smptebars_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(smptebars_outputs),
 };
 
 #endif  /* CONFIG_SMPTEHDBARS_FILTER */
@@ -1771,7 +1774,6 @@  static const AVFilterPad avfilter_vsrc_allyuv_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_allyuv = {
@@ -1785,6 +1787,7 @@  const AVFilter ff_vsrc_allyuv = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_allyuv_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_allyuv_outputs),
 };
 
 #endif /* CONFIG_ALLYUV_FILTER */
@@ -1848,7 +1851,6 @@  static const AVFilterPad avfilter_vsrc_allrgb_outputs[] = {
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = allrgb_config_props,
     },
-    { NULL }
 };
 
 const AVFilter ff_vsrc_allrgb = {
@@ -1862,6 +1864,7 @@  const AVFilter ff_vsrc_allrgb = {
     .activate      = activate,
     .inputs        = NULL,
     .outputs       = avfilter_vsrc_allrgb_outputs,
+    .nb_outputs    = FF_ARRAY_ELEMS(avfilter_vsrc_allrgb_outputs),
 };
 
 #endif /* CONFIG_ALLRGB_FILTER */