diff mbox series

[FFmpeg-devel,4/7] avcodec/codec_internal: Use union for FFCodec decode/encode callbacks

Message ID AS1PR01MB956460ABCDE1FC806A71F2F28F1F9@AS1PR01MB9564.eurprd01.prod.exchangelabs.com
State Accepted
Headers show
Series [FFmpeg-devel,1/7] avcodec/options: Fix AVClassCategory of decoders with .receive_frame | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished

Commit Message

Andreas Rheinhardt March 30, 2022, 10:49 p.m. UTC
This is possible, because every given FFCodec has to implement
exactly one of these. Doing so decreases sizeof(FFCodec) and
therefore decreases the size of the binary.
Notice that in case of position-independent code the decrease
is in .data.rel.ro, so that this translates to decreased
memory consumption.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/012v.c                   |   2 +-
 libavcodec/4xm.c                    |   2 +-
 libavcodec/8bps.c                   |   2 +-
 libavcodec/8svx.c                   |   4 +-
 libavcodec/a64multienc.c            |   4 +-
 libavcodec/aacdec.c                 |   4 +-
 libavcodec/aacdec_fixed.c           |   2 +-
 libavcodec/aacenc.c                 |   2 +-
 libavcodec/aasc.c                   |   2 +-
 libavcodec/ac3dec_fixed.c           |   2 +-
 libavcodec/ac3dec_float.c           |   4 +-
 libavcodec/ac3enc_fixed.c           |   2 +-
 libavcodec/ac3enc_float.c           |   2 +-
 libavcodec/adpcm.c                  |   2 +-
 libavcodec/adpcmenc.c               |   2 +-
 libavcodec/adxdec.c                 |   2 +-
 libavcodec/adxenc.c                 |   2 +-
 libavcodec/agm.c                    |   2 +-
 libavcodec/aic.c                    |   2 +-
 libavcodec/alac.c                   |   2 +-
 libavcodec/alacenc.c                |   2 +-
 libavcodec/aliaspixdec.c            |   2 +-
 libavcodec/aliaspixenc.c            |   2 +-
 libavcodec/alsdec.c                 |   2 +-
 libavcodec/amfenc_h264.c            |   2 +-
 libavcodec/amfenc_hevc.c            |   2 +-
 libavcodec/amrnbdec.c               |   2 +-
 libavcodec/amrwbdec.c               |   2 +-
 libavcodec/anm.c                    |   2 +-
 libavcodec/ansi.c                   |   2 +-
 libavcodec/apedec.c                 |   2 +-
 libavcodec/aptxdec.c                |   4 +-
 libavcodec/aptxenc.c                |   4 +-
 libavcodec/arbc.c                   |   2 +-
 libavcodec/argo.c                   |   2 +-
 libavcodec/assdec.c                 |   4 +-
 libavcodec/assenc.c                 |   4 +-
 libavcodec/asvdec.c                 |   4 +-
 libavcodec/asvenc.c                 |   4 +-
 libavcodec/atrac1.c                 |   2 +-
 libavcodec/atrac3.c                 |   4 +-
 libavcodec/atrac3plusdec.c          |   4 +-
 libavcodec/atrac9dec.c              |   2 +-
 libavcodec/audiotoolboxdec.c        |   2 +-
 libavcodec/audiotoolboxenc.c        |   2 +-
 libavcodec/aura.c                   |   2 +-
 libavcodec/av1dec.c                 |   2 +-
 libavcodec/avrndec.c                |   2 +-
 libavcodec/avs.c                    |   2 +-
 libavcodec/avuidec.c                |   2 +-
 libavcodec/avuienc.c                |   2 +-
 libavcodec/bethsoftvideo.c          |   2 +-
 libavcodec/bfi.c                    |   2 +-
 libavcodec/bink.c                   |   2 +-
 libavcodec/binkaudio.c              |   4 +-
 libavcodec/bintext.c                |   6 +-
 libavcodec/bitpacked_dec.c          |   2 +-
 libavcodec/bitpacked_enc.c          |   2 +-
 libavcodec/bmp.c                    |   2 +-
 libavcodec/bmpenc.c                 |   2 +-
 libavcodec/bmvaudio.c               |   2 +-
 libavcodec/bmvvideo.c               |   2 +-
 libavcodec/brenderpix.c             |   2 +-
 libavcodec/c93.c                    |   2 +-
 libavcodec/cavsdec.c                |   2 +-
 libavcodec/ccaption_dec.c           |   2 +-
 libavcodec/cdgraphics.c             |   2 +-
 libavcodec/cdtoons.c                |   2 +-
 libavcodec/cdxl.c                   |   2 +-
 libavcodec/cfhd.c                   |   2 +-
 libavcodec/cfhdenc.c                |   2 +-
 libavcodec/cinepak.c                |   2 +-
 libavcodec/cinepakenc.c             |   2 +-
 libavcodec/clearvideo.c             |   2 +-
 libavcodec/cljrdec.c                |   2 +-
 libavcodec/cljrenc.c                |   2 +-
 libavcodec/cllc.c                   |   2 +-
 libavcodec/cngdec.c                 |   2 +-
 libavcodec/cngenc.c                 |   2 +-
 libavcodec/codec_internal.h         | 153 ++++++++++++++++++++--------
 libavcodec/cook.c                   |   2 +-
 libavcodec/cpia.c                   |   2 +-
 libavcodec/cri.c                    |   2 +-
 libavcodec/crystalhd.c              |   2 +-
 libavcodec/cscd.c                   |   2 +-
 libavcodec/cuviddec.c               |   2 +-
 libavcodec/cyuv.c                   |   4 +-
 libavcodec/dcadec.c                 |   2 +-
 libavcodec/dcaenc.c                 |   2 +-
 libavcodec/dds.c                    |   2 +-
 libavcodec/decode.c                 |   8 +-
 libavcodec/dfa.c                    |   2 +-
 libavcodec/dfpwmdec.c               |   2 +-
 libavcodec/dfpwmenc.c               |   2 +-
 libavcodec/diracdec.c               |   2 +-
 libavcodec/dnxhddec.c               |   2 +-
 libavcodec/dnxhdenc.c               |   2 +-
 libavcodec/dolby_e.c                |   2 +-
 libavcodec/dpcm.c                   |   2 +-
 libavcodec/dpx.c                    |   2 +-
 libavcodec/dpxenc.c                 |   2 +-
 libavcodec/dsddec.c                 |   2 +-
 libavcodec/dsicinaudio.c            |   2 +-
 libavcodec/dsicinvideo.c            |   2 +-
 libavcodec/dss_sp.c                 |   2 +-
 libavcodec/dstdec.c                 |   2 +-
 libavcodec/dvaudiodec.c             |   2 +-
 libavcodec/dvbsubdec.c              |   2 +-
 libavcodec/dvbsubenc.c              |   2 +-
 libavcodec/dvdec.c                  |   2 +-
 libavcodec/dvdsubdec.c              |   2 +-
 libavcodec/dvdsubenc.c              |   2 +-
 libavcodec/dvenc.c                  |   2 +-
 libavcodec/dxa.c                    |   2 +-
 libavcodec/dxtory.c                 |   2 +-
 libavcodec/dxv.c                    |   2 +-
 libavcodec/eac3enc.c                |   2 +-
 libavcodec/eacmv.c                  |   2 +-
 libavcodec/eamad.c                  |   2 +-
 libavcodec/eatgq.c                  |   2 +-
 libavcodec/eatgv.c                  |   2 +-
 libavcodec/eatqi.c                  |   2 +-
 libavcodec/encode.c                 |  10 +-
 libavcodec/escape124.c              |   2 +-
 libavcodec/escape130.c              |   2 +-
 libavcodec/evrcdec.c                |   2 +-
 libavcodec/exr.c                    |   2 +-
 libavcodec/exrenc.c                 |   2 +-
 libavcodec/fastaudio.c              |   2 +-
 libavcodec/ffv1dec.c                |   2 +-
 libavcodec/ffv1enc.c                |   2 +-
 libavcodec/ffwavesynth.c            |   2 +-
 libavcodec/fic.c                    |   2 +-
 libavcodec/fitsdec.c                |   2 +-
 libavcodec/fitsenc.c                |   2 +-
 libavcodec/flacdec.c                |   2 +-
 libavcodec/flacenc.c                |   2 +-
 libavcodec/flashsv.c                |   4 +-
 libavcodec/flashsv2enc.c            |   2 +-
 libavcodec/flashsvenc.c             |   2 +-
 libavcodec/flicvideo.c              |   2 +-
 libavcodec/flvdec.c                 |   2 +-
 libavcodec/flvenc.c                 |   2 +-
 libavcodec/fmvc.c                   |   2 +-
 libavcodec/frame_thread_encoder.c   |   2 +-
 libavcodec/fraps.c                  |   2 +-
 libavcodec/frwu.c                   |   2 +-
 libavcodec/g2meet.c                 |   2 +-
 libavcodec/g722dec.c                |   2 +-
 libavcodec/g722enc.c                |   2 +-
 libavcodec/g723_1dec.c              |   2 +-
 libavcodec/g723_1enc.c              |   2 +-
 libavcodec/g726.c                   |   8 +-
 libavcodec/g729dec.c                |   4 +-
 libavcodec/gdv.c                    |   2 +-
 libavcodec/gemdec.c                 |   2 +-
 libavcodec/gif.c                    |   2 +-
 libavcodec/gifdec.c                 |   2 +-
 libavcodec/gsmdec.c                 |   4 +-
 libavcodec/h261dec.c                |   2 +-
 libavcodec/h261enc.c                |   2 +-
 libavcodec/h263dec.c                |   4 +-
 libavcodec/h264dec.c                |   2 +-
 libavcodec/hapdec.c                 |   2 +-
 libavcodec/hapenc.c                 |   2 +-
 libavcodec/hcadec.c                 |   2 +-
 libavcodec/hcom.c                   |   2 +-
 libavcodec/hevcdec.c                |   2 +-
 libavcodec/hnm4video.c              |   2 +-
 libavcodec/hq_hqa.c                 |   2 +-
 libavcodec/hqx.c                    |   2 +-
 libavcodec/huffyuvdec.c             |   6 +-
 libavcodec/huffyuvenc.c             |   4 +-
 libavcodec/idcinvideo.c             |   2 +-
 libavcodec/iff.c                    |   2 +-
 libavcodec/ilbcdec.c                |   2 +-
 libavcodec/imc.c                    |   4 +-
 libavcodec/imm4.c                   |   2 +-
 libavcodec/imm5.c                   |   2 +-
 libavcodec/imx.c                    |   2 +-
 libavcodec/indeo2.c                 |   2 +-
 libavcodec/indeo3.c                 |   2 +-
 libavcodec/indeo4.c                 |   2 +-
 libavcodec/indeo5.c                 |   2 +-
 libavcodec/intelh263dec.c           |   2 +-
 libavcodec/interplayacm.c           |   2 +-
 libavcodec/interplayvideo.c         |   2 +-
 libavcodec/ituh263enc.c             |   4 +-
 libavcodec/j2kenc.c                 |   2 +-
 libavcodec/jacosubdec.c             |   2 +-
 libavcodec/jpeg2000dec.c            |   2 +-
 libavcodec/jpeglsdec.c              |   2 +-
 libavcodec/jpeglsenc.c              |   2 +-
 libavcodec/jvdec.c                  |   2 +-
 libavcodec/kgv1dec.c                |   2 +-
 libavcodec/kmvc.c                   |   2 +-
 libavcodec/lagarith.c               |   2 +-
 libavcodec/lcldec.c                 |   4 +-
 libavcodec/lclenc.c                 |   2 +-
 libavcodec/libaomdec.c              |   2 +-
 libavcodec/libaomenc.c              |   2 +-
 libavcodec/libaribb24.c             |   2 +-
 libavcodec/libcelt_dec.c            |   2 +-
 libavcodec/libcodec2.c              |   4 +-
 libavcodec/libdav1d.c               |   2 +-
 libavcodec/libdavs2.c               |   2 +-
 libavcodec/libfdk-aacdec.c          |   2 +-
 libavcodec/libfdk-aacenc.c          |   2 +-
 libavcodec/libgsmdec.c              |   4 +-
 libavcodec/libgsmenc.c              |   4 +-
 libavcodec/libilbc.c                |   4 +-
 libavcodec/libkvazaar.c             |   2 +-
 libavcodec/libmp3lame.c             |   2 +-
 libavcodec/libopencore-amr.c        |   6 +-
 libavcodec/libopenh264dec.c         |   2 +-
 libavcodec/libopenh264enc.c         |   2 +-
 libavcodec/libopenjpegdec.c         |   2 +-
 libavcodec/libopenjpegenc.c         |   2 +-
 libavcodec/libopusdec.c             |   2 +-
 libavcodec/libopusenc.c             |   2 +-
 libavcodec/librav1e.c               |   2 +-
 libavcodec/librsvgdec.c             |   2 +-
 libavcodec/libshine.c               |   2 +-
 libavcodec/libspeexdec.c            |   2 +-
 libavcodec/libspeexenc.c            |   2 +-
 libavcodec/libsvtav1.c              |   2 +-
 libavcodec/libtheoraenc.c           |   2 +-
 libavcodec/libtwolame.c             |   2 +-
 libavcodec/libuavs3d.c              |   2 +-
 libavcodec/libvo-amrwbenc.c         |   2 +-
 libavcodec/libvorbisdec.c           |   2 +-
 libavcodec/libvorbisenc.c           |   2 +-
 libavcodec/libvpxdec.c              |   4 +-
 libavcodec/libvpxenc.c              |   4 +-
 libavcodec/libwebpenc.c             |   2 +-
 libavcodec/libwebpenc_animencoder.c |   2 +-
 libavcodec/libx264.c                |   6 +-
 libavcodec/libx265.c                |   2 +-
 libavcodec/libxavs.c                |   2 +-
 libavcodec/libxavs2.c               |   2 +-
 libavcodec/libxvid.c                |   2 +-
 libavcodec/libzvbi-teletextdec.c    |   2 +-
 libavcodec/ljpegenc.c               |   2 +-
 libavcodec/loco.c                   |   2 +-
 libavcodec/lscrdec.c                |   2 +-
 libavcodec/m101.c                   |   2 +-
 libavcodec/mace.c                   |   4 +-
 libavcodec/magicyuv.c               |   2 +-
 libavcodec/magicyuvenc.c            |   2 +-
 libavcodec/mdec.c                   |   2 +-
 libavcodec/mediacodecdec.c          |   2 +-
 libavcodec/metasound.c              |   2 +-
 libavcodec/mfenc.c                  |   2 +-
 libavcodec/microdvddec.c            |   2 +-
 libavcodec/midivid.c                |   2 +-
 libavcodec/mimic.c                  |   2 +-
 libavcodec/mjpegbdec.c              |   2 +-
 libavcodec/mjpegdec.c               |   6 +-
 libavcodec/mjpegenc.c               |   4 +-
 libavcodec/mlpdec.c                 |   4 +-
 libavcodec/mlpenc.c                 |   4 +-
 libavcodec/mmaldec.c                |   2 +-
 libavcodec/mmvideo.c                |   2 +-
 libavcodec/mobiclip.c               |   2 +-
 libavcodec/motionpixels.c           |   2 +-
 libavcodec/movtextdec.c             |   2 +-
 libavcodec/movtextenc.c             |   2 +-
 libavcodec/mpc7.c                   |   2 +-
 libavcodec/mpc8.c                   |   2 +-
 libavcodec/mpeg12dec.c              |   8 +-
 libavcodec/mpeg12enc.c              |   4 +-
 libavcodec/mpeg4videodec.c          |   2 +-
 libavcodec/mpeg4videoenc.c          |   2 +-
 libavcodec/mpegaudiodec_fixed.c     |  10 +-
 libavcodec/mpegaudiodec_float.c     |  10 +-
 libavcodec/mpegaudioenc_fixed.c     |   2 +-
 libavcodec/mpegaudioenc_float.c     |   2 +-
 libavcodec/mpl2dec.c                |   2 +-
 libavcodec/mscc.c                   |   4 +-
 libavcodec/msmpeg4dec.c             |   8 +-
 libavcodec/msmpeg4enc.c             |   6 +-
 libavcodec/msp2dec.c                |   2 +-
 libavcodec/msrle.c                  |   2 +-
 libavcodec/mss1.c                   |   2 +-
 libavcodec/mss2.c                   |   2 +-
 libavcodec/mss3.c                   |   2 +-
 libavcodec/mss4.c                   |   2 +-
 libavcodec/msvideo1.c               |   2 +-
 libavcodec/msvideo1enc.c            |   2 +-
 libavcodec/mv30.c                   |   2 +-
 libavcodec/mvcdec.c                 |   4 +-
 libavcodec/mvha.c                   |   2 +-
 libavcodec/mwsc.c                   |   2 +-
 libavcodec/mxpegdec.c               |   2 +-
 libavcodec/nellymoserdec.c          |   2 +-
 libavcodec/nellymoserenc.c          |   2 +-
 libavcodec/notchlc.c                |   2 +-
 libavcodec/nuv.c                    |   2 +-
 libavcodec/nvenc_h264.c             |   2 +-
 libavcodec/nvenc_hevc.c             |   2 +-
 libavcodec/omx.c                    |   4 +-
 libavcodec/on2avc.c                 |   2 +-
 libavcodec/opusdec.c                |   2 +-
 libavcodec/opusenc.c                |   2 +-
 libavcodec/pafaudio.c               |   2 +-
 libavcodec/pafvideo.c               |   2 +-
 libavcodec/pamenc.c                 |   2 +-
 libavcodec/pcm-bluray.c             |   2 +-
 libavcodec/pcm-blurayenc.c          |   2 +-
 libavcodec/pcm-dvd.c                |   2 +-
 libavcodec/pcm-dvdenc.c             |   2 +-
 libavcodec/pcm.c                    |   4 +-
 libavcodec/pcx.c                    |   2 +-
 libavcodec/pcxenc.c                 |   2 +-
 libavcodec/pgssubdec.c              |   2 +-
 libavcodec/pgxdec.c                 |   2 +-
 libavcodec/photocd.c                |   2 +-
 libavcodec/pictordec.c              |   2 +-
 libavcodec/pixlet.c                 |   2 +-
 libavcodec/pngdec.c                 |   4 +-
 libavcodec/pngenc.c                 |   4 +-
 libavcodec/pnmdec.c                 |  12 +--
 libavcodec/pnmenc.c                 |  10 +-
 libavcodec/proresdec2.c             |   2 +-
 libavcodec/proresenc_anatoliy.c     |   4 +-
 libavcodec/proresenc_kostya.c       |   2 +-
 libavcodec/prosumer.c               |   2 +-
 libavcodec/psd.c                    |   2 +-
 libavcodec/pthread_frame.c          |   2 +-
 libavcodec/ptx.c                    |   2 +-
 libavcodec/qcelpdec.c               |   2 +-
 libavcodec/qdm2.c                   |   2 +-
 libavcodec/qdmc.c                   |   2 +-
 libavcodec/qdrw.c                   |   2 +-
 libavcodec/qpeg.c                   |   2 +-
 libavcodec/qsvdec.c                 |   2 +-
 libavcodec/qsvenc_h264.c            |   2 +-
 libavcodec/qsvenc_hevc.c            |   2 +-
 libavcodec/qsvenc_jpeg.c            |   2 +-
 libavcodec/qsvenc_mpeg2.c           |   2 +-
 libavcodec/qsvenc_vp9.c             |   2 +-
 libavcodec/qtrle.c                  |   2 +-
 libavcodec/qtrleenc.c               |   2 +-
 libavcodec/r210dec.c                |   6 +-
 libavcodec/r210enc.c                |   6 +-
 libavcodec/ra144dec.c               |   2 +-
 libavcodec/ra144enc.c               |   2 +-
 libavcodec/ra288.c                  |   2 +-
 libavcodec/ralf.c                   |   2 +-
 libavcodec/rasc.c                   |   2 +-
 libavcodec/rawdec.c                 |   2 +-
 libavcodec/rawenc.c                 |   2 +-
 libavcodec/realtextdec.c            |   2 +-
 libavcodec/rkmppdec.c               |   2 +-
 libavcodec/rl2.c                    |   2 +-
 libavcodec/roqaudioenc.c            |   2 +-
 libavcodec/roqvideodec.c            |   2 +-
 libavcodec/roqvideoenc.c            |   2 +-
 libavcodec/rpza.c                   |   2 +-
 libavcodec/rpzaenc.c                |   2 +-
 libavcodec/rscc.c                   |   2 +-
 libavcodec/rv10.c                   |   4 +-
 libavcodec/rv10enc.c                |   2 +-
 libavcodec/rv20enc.c                |   2 +-
 libavcodec/rv30.c                   |   2 +-
 libavcodec/rv40.c                   |   2 +-
 libavcodec/s302m.c                  |   2 +-
 libavcodec/s302menc.c               |   2 +-
 libavcodec/samidec.c                |   2 +-
 libavcodec/sanm.c                   |   2 +-
 libavcodec/sbcdec.c                 |   2 +-
 libavcodec/sbcenc.c                 |   2 +-
 libavcodec/scpr.c                   |   2 +-
 libavcodec/screenpresso.c           |   2 +-
 libavcodec/sga.c                    |   2 +-
 libavcodec/sgidec.c                 |   2 +-
 libavcodec/sgienc.c                 |   2 +-
 libavcodec/sgirledec.c              |   2 +-
 libavcodec/sheervideo.c             |   2 +-
 libavcodec/shorten.c                |   2 +-
 libavcodec/sipr.c                   |   2 +-
 libavcodec/siren.c                  |   4 +-
 libavcodec/smacker.c                |   4 +-
 libavcodec/smc.c                    |   2 +-
 libavcodec/smcenc.c                 |   2 +-
 libavcodec/snowdec.c                |   2 +-
 libavcodec/snowenc.c                |   2 +-
 libavcodec/sonic.c                  |   6 +-
 libavcodec/sp5xdec.c                |   4 +-
 libavcodec/speedhq.c                |   2 +-
 libavcodec/speedhqenc.c             |   2 +-
 libavcodec/speexdec.c               |   2 +-
 libavcodec/srtdec.c                 |   4 +-
 libavcodec/srtenc.c                 |   6 +-
 libavcodec/subviewerdec.c           |   2 +-
 libavcodec/sunrast.c                |   2 +-
 libavcodec/sunrastenc.c             |   2 +-
 libavcodec/svq1dec.c                |   2 +-
 libavcodec/svq1enc.c                |   2 +-
 libavcodec/svq3.c                   |   2 +-
 libavcodec/takdec.c                 |   2 +-
 libavcodec/targa.c                  |   2 +-
 libavcodec/targa_y216dec.c          |   2 +-
 libavcodec/targaenc.c               |   2 +-
 libavcodec/tdsc.c                   |   2 +-
 libavcodec/tests/avcodec.c          |  42 +++++---
 libavcodec/textdec.c                |  10 +-
 libavcodec/tiertexseqv.c            |   2 +-
 libavcodec/tiff.c                   |   2 +-
 libavcodec/tiffenc.c                |   2 +-
 libavcodec/tmv.c                    |   2 +-
 libavcodec/truemotion1.c            |   2 +-
 libavcodec/truemotion2.c            |   2 +-
 libavcodec/truemotion2rt.c          |   2 +-
 libavcodec/truespeech.c             |   2 +-
 libavcodec/tscc.c                   |   2 +-
 libavcodec/tscc2.c                  |   2 +-
 libavcodec/tta.c                    |   2 +-
 libavcodec/ttaenc.c                 |   2 +-
 libavcodec/ttmlenc.c                |   2 +-
 libavcodec/twinvqdec.c              |   2 +-
 libavcodec/txd.c                    |   2 +-
 libavcodec/ulti.c                   |   2 +-
 libavcodec/utils.c                  |   8 +-
 libavcodec/utvideodec.c             |   2 +-
 libavcodec/utvideoenc.c             |   2 +-
 libavcodec/v210dec.c                |   2 +-
 libavcodec/v210enc.c                |   2 +-
 libavcodec/v210x.c                  |   2 +-
 libavcodec/v308dec.c                |   2 +-
 libavcodec/v308enc.c                |   2 +-
 libavcodec/v408dec.c                |   4 +-
 libavcodec/v408enc.c                |   4 +-
 libavcodec/v410dec.c                |   2 +-
 libavcodec/v410enc.c                |   2 +-
 libavcodec/v4l2_m2m_dec.c           |   2 +-
 libavcodec/v4l2_m2m_enc.c           |   2 +-
 libavcodec/vaapi_encode_h264.c      |   2 +-
 libavcodec/vaapi_encode_h265.c      |   2 +-
 libavcodec/vaapi_encode_mjpeg.c     |   2 +-
 libavcodec/vaapi_encode_mpeg2.c     |   2 +-
 libavcodec/vaapi_encode_vp8.c       |   2 +-
 libavcodec/vaapi_encode_vp9.c       |   2 +-
 libavcodec/vb.c                     |   2 +-
 libavcodec/vble.c                   |   2 +-
 libavcodec/vc1dec.c                 |   8 +-
 libavcodec/vc2enc.c                 |   2 +-
 libavcodec/vcr1.c                   |   2 +-
 libavcodec/videotoolboxenc.c        |   6 +-
 libavcodec/vima.c                   |   2 +-
 libavcodec/vmdaudio.c               |   2 +-
 libavcodec/vmdvideo.c               |   2 +-
 libavcodec/vmnc.c                   |   2 +-
 libavcodec/vorbisdec.c              |   2 +-
 libavcodec/vorbisenc.c              |   2 +-
 libavcodec/vp3.c                    |   6 +-
 libavcodec/vp5.c                    |   2 +-
 libavcodec/vp6.c                    |   6 +-
 libavcodec/vp8.c                    |   4 +-
 libavcodec/vp9.c                    |   2 +-
 libavcodec/vqavideo.c               |   2 +-
 libavcodec/wavpack.c                |   2 +-
 libavcodec/wavpackenc.c             |   2 +-
 libavcodec/wcmv.c                   |   2 +-
 libavcodec/webp.c                   |   2 +-
 libavcodec/webvttdec.c              |   2 +-
 libavcodec/webvttenc.c              |   2 +-
 libavcodec/wmadec.c                 |   4 +-
 libavcodec/wmaenc.c                 |   4 +-
 libavcodec/wmalosslessdec.c         |   2 +-
 libavcodec/wmaprodec.c              |   6 +-
 libavcodec/wmavoice.c               |   2 +-
 libavcodec/wmv2dec.c                |   2 +-
 libavcodec/wmv2enc.c                |   2 +-
 libavcodec/wnv1.c                   |   2 +-
 libavcodec/wrapped_avframe.c        |   4 +-
 libavcodec/ws-snd1.c                |   2 +-
 libavcodec/xan.c                    |   2 +-
 libavcodec/xbmdec.c                 |   2 +-
 libavcodec/xbmenc.c                 |   2 +-
 libavcodec/xfacedec.c               |   2 +-
 libavcodec/xfaceenc.c               |   2 +-
 libavcodec/xl.c                     |   2 +-
 libavcodec/xpmdec.c                 |   2 +-
 libavcodec/xsubdec.c                |   2 +-
 libavcodec/xsubenc.c                |   2 +-
 libavcodec/xwddec.c                 |   2 +-
 libavcodec/xwdenc.c                 |   2 +-
 libavcodec/xxan.c                   |   2 +-
 libavcodec/y41pdec.c                |   2 +-
 libavcodec/y41penc.c                |   2 +-
 libavcodec/ylc.c                    |   2 +-
 libavcodec/yop.c                    |   2 +-
 libavcodec/yuv4dec.c                |   2 +-
 libavcodec/yuv4enc.c                |   2 +-
 libavcodec/zerocodec.c              |   2 +-
 libavcodec/zmbv.c                   |   2 +-
 libavcodec/zmbvenc.c                |   2 +-
 498 files changed, 758 insertions(+), 673 deletions(-)

Comments

Michael Niedermayer April 30, 2022, 9:50 p.m. UTC | #1
On Thu, Mar 31, 2022 at 12:49:55AM +0200, Andreas Rheinhardt wrote:
> This is possible, because every given FFCodec has to implement
> exactly one of these. Doing so decreases sizeof(FFCodec) and
> therefore decreases the size of the binary.
> Notice that in case of position-independent code the decrease
> is in .data.rel.ro, so that this translates to decreased
> memory consumption.

by how much did the space requirement decrease ?
iam asking because while a single such change isnt a issue
if we accumulate alot of this in the API, the API may become
actually hard to understand by new developers

[...]

thx
Andreas Rheinhardt May 3, 2022, 1:44 p.m. UTC | #2
Michael Niedermayer:
> On Thu, Mar 31, 2022 at 12:49:55AM +0200, Andreas Rheinhardt wrote:
>> This is possible, because every given FFCodec has to implement
>> exactly one of these. Doing so decreases sizeof(FFCodec) and
>> therefore decreases the size of the binary.
>> Notice that in case of position-independent code the decrease
>> is in .data.rel.ro, so that this translates to decreased
>> memory consumption.
> 
> by how much did the space requirement decrease ?

The three patches fb59a42ef, ce7dbd048 and 4243da4ff4 together removed
four pointers from FFCodec; on 64 bit systems this amounts to savings of
32 byte per FFCodec. allcodecs.c contains 796 declarations of FFCodecs,
amounting to savings of at most 25472B. (This number is not attainable
because some codecs are only available for certain platforms.)
I get 488 decoders and 182 encoders in a build without any external
libraries explicitly enabled, leading to savings of 21440B.

> iam asking because while a single such change isnt a issue
> if we accumulate alot of this in the API, the API may become
> actually hard to understand by new developers
diff mbox series

Patch

diff --git a/libavcodec/012v.c b/libavcodec/012v.c
index 4d57b57082..c03afd0bc7 100644
--- a/libavcodec/012v.c
+++ b/libavcodec/012v.c
@@ -150,7 +150,7 @@  const FFCodec ff_zero12v_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_012V,
     .init           = zero12v_decode_init,
-    .decode         = zero12v_decode_frame,
+    FF_CODEC_DECODE_CB(zero12v_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c
index 413b4f9330..3fb3568afd 100644
--- a/libavcodec/4xm.c
+++ b/libavcodec/4xm.c
@@ -1034,7 +1034,7 @@  const FFCodec ff_fourxm_decoder = {
     .priv_data_size = sizeof(FourXContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c
index d5146043ac..95a35159e3 100644
--- a/libavcodec/8bps.c
+++ b/libavcodec/8bps.c
@@ -180,7 +180,7 @@  const FFCodec ff_eightbps_decoder = {
     .p.id           = AV_CODEC_ID_8BPS,
     .priv_data_size = sizeof(EightBpsContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c
index 937800304c..6eb90834b9 100644
--- a/libavcodec/8svx.c
+++ b/libavcodec/8svx.c
@@ -194,7 +194,7 @@  const FFCodec ff_eightsvx_fib_decoder = {
   .p.id           = AV_CODEC_ID_8SVX_FIB,
   .priv_data_size = sizeof (EightSvxContext),
   .init           = eightsvx_decode_init,
-  .decode         = eightsvx_decode_frame,
+  FF_CODEC_DECODE_CB(eightsvx_decode_frame),
   .close          = eightsvx_decode_close,
   .p.capabilities = AV_CODEC_CAP_DR1,
   .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
@@ -210,7 +210,7 @@  const FFCodec ff_eightsvx_exp_decoder = {
   .p.id           = AV_CODEC_ID_8SVX_EXP,
   .priv_data_size = sizeof (EightSvxContext),
   .init           = eightsvx_decode_init,
-  .decode         = eightsvx_decode_frame,
+  FF_CODEC_DECODE_CB(eightsvx_decode_frame),
   .close          = eightsvx_decode_close,
   .p.capabilities = AV_CODEC_CAP_DR1,
   .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c
index b642a575f1..e80139ee51 100644
--- a/libavcodec/a64multienc.c
+++ b/libavcodec/a64multienc.c
@@ -401,7 +401,7 @@  const FFCodec ff_a64multi_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .priv_data_size = sizeof(A64Context),
     .init           = a64multi_encode_init,
-    .encode2        = a64multi_encode_frame,
+    FF_CODEC_ENCODE_CB(a64multi_encode_frame),
     .close          = a64multi_close_encoder,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
@@ -416,7 +416,7 @@  const FFCodec ff_a64multi5_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .priv_data_size = sizeof(A64Context),
     .init           = a64multi_encode_init,
-    .encode2        = a64multi_encode_frame,
+    FF_CODEC_ENCODE_CB(a64multi_encode_frame),
     .close          = a64multi_close_encoder,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE},
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 5fc6738b38..88c128f396 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -560,7 +560,7 @@  const FFCodec ff_aac_decoder = {
     .priv_data_size  = sizeof(AACContext),
     .init            = aac_decode_init,
     .close           = aac_decode_close,
-    .decode          = aac_decode_frame,
+    FF_CODEC_DECODE_CB(aac_decode_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]) {
         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
     },
@@ -588,7 +588,7 @@  const FFCodec ff_aac_latm_decoder = {
     .priv_data_size  = sizeof(struct LATMContext),
     .init            = latm_decode_init,
     .close           = aac_decode_close,
-    .decode          = latm_decode_frame,
+    FF_CODEC_DECODE_CB(latm_decode_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]) {
         AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
     },
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index bdce588b26..c7ac75024f 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -458,7 +458,7 @@  const FFCodec ff_aac_fixed_decoder = {
     .priv_data_size  = sizeof(AACContext),
     .init            = aac_decode_init,
     .close           = aac_decode_close,
-    .decode          = aac_decode_frame,
+    FF_CODEC_DECODE_CB(aac_decode_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]) {
         AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
     },
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 820d9b60cb..eb091326b1 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -1144,7 +1144,7 @@  const FFCodec ff_aac_encoder = {
     .p.id           = AV_CODEC_ID_AAC,
     .priv_data_size = sizeof(AACEncContext),
     .init           = aac_encode_init,
-    .encode2        = aac_encode_frame,
+    FF_CODEC_ENCODE_CB(aac_encode_frame),
     .close          = aac_encode_end,
     .defaults       = aac_encode_defaults,
     .p.supported_samplerates = ff_mpeg4audio_sample_rates,
diff --git a/libavcodec/aasc.c b/libavcodec/aasc.c
index a462e2f05e..d297cfad76 100644
--- a/libavcodec/aasc.c
+++ b/libavcodec/aasc.c
@@ -157,7 +157,7 @@  const FFCodec ff_aasc_decoder = {
     .priv_data_size = sizeof(AascContext),
     .init           = aasc_decode_init,
     .close          = aasc_decode_end,
-    .decode         = aasc_decode_frame,
+    FF_CODEC_DECODE_CB(aasc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c
index de44bf80cf..4c0d4d6f5c 100644
--- a/libavcodec/ac3dec_fixed.c
+++ b/libavcodec/ac3dec_fixed.c
@@ -178,7 +178,7 @@  const FFCodec ff_ac3_fixed_decoder = {
     .priv_data_size = sizeof (AC3DecodeContext),
     .init           = ac3_decode_init,
     .close          = ac3_decode_end,
-    .decode         = ac3_decode_frame,
+    FF_CODEC_DECODE_CB(ac3_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c
index 5aeb378bc6..2147b36afe 100644
--- a/libavcodec/ac3dec_float.c
+++ b/libavcodec/ac3dec_float.c
@@ -66,7 +66,7 @@  const FFCodec ff_ac3_decoder = {
     .priv_data_size = sizeof (AC3DecodeContext),
     .init           = ac3_decode_init,
     .close          = ac3_decode_end,
-    .decode         = ac3_decode_frame,
+    FF_CODEC_DECODE_CB(ac3_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .p.long_name    = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
@@ -84,7 +84,7 @@  const FFCodec ff_eac3_decoder = {
     .priv_data_size = sizeof (AC3DecodeContext),
     .init           = ac3_decode_init,
     .close          = ac3_decode_end,
-    .decode         = ac3_decode_frame,
+    FF_CODEC_DECODE_CB(ac3_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .p.long_name    = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"),
diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index af6b2a20f9..92bf31b039 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -128,7 +128,7 @@  const FFCodec ff_ac3_fixed_encoder = {
     .p.capabilities  = AV_CODEC_CAP_DR1,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ac3_fixed_encode_init,
-    .encode2         = ff_ac3_fixed_encode_frame,
+    FF_CODEC_ENCODE_CB(ff_ac3_fixed_encode_frame),
     .close           = ff_ac3_encode_close,
     .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 1323df74a9..9f5341cf2d 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -132,7 +132,7 @@  const FFCodec ff_ac3_encoder = {
     .p.capabilities  = AV_CODEC_CAP_DR1,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ff_ac3_float_encode_init,
-    .encode2         = ff_ac3_float_encode_frame,
+    FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame),
     .close           = ff_ac3_encode_close,
     .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c
index ccb625ab54..b2ef7dfbec 100644
--- a/libavcodec/adpcm.c
+++ b/libavcodec/adpcm.c
@@ -2294,7 +2294,7 @@  const FFCodec ff_ ## name_ ## _decoder = {                  \
     .p.sample_fmts  = sample_fmts_,                         \
     .priv_data_size = sizeof(ADPCMDecodeContext),           \
     .init           = adpcm_decode_init,                    \
-    .decode         = adpcm_decode_frame,                   \
+    FF_CODEC_DECODE_CB(adpcm_decode_frame),                 \
     .flush          = adpcm_flush,                          \
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,         \
 };
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 0a2e6bb3be..4ff77662b4 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -1007,7 +1007,7 @@  const FFCodec ff_ ## name_ ## _encoder = {                                 \
     .p.priv_class   = &adpcm_encoder_class,                                \
     .priv_data_size = sizeof(ADPCMEncodeContext),                          \
     .init           = adpcm_encode_init,                                   \
-    .encode2        = adpcm_encode_frame,                                  \
+    FF_CODEC_ENCODE_CB(adpcm_encode_frame),                                \
     .close          = adpcm_encode_close,                                  \
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, \
 };
diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c
index 870f485726..1ebc250e47 100644
--- a/libavcodec/adxdec.c
+++ b/libavcodec/adxdec.c
@@ -197,7 +197,7 @@  const FFCodec ff_adpcm_adx_decoder = {
     .p.id           = AV_CODEC_ID_ADPCM_ADX,
     .priv_data_size = sizeof(ADXContext),
     .init           = adx_decode_init,
-    .decode         = adx_decode_frame,
+    FF_CODEC_DECODE_CB(adx_decode_frame),
     .flush          = adx_decode_flush,
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index af8d2861e7..9277cab7c9 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -197,7 +197,7 @@  const FFCodec ff_adpcm_adx_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .priv_data_size = sizeof(ADXContext),
     .init           = adx_encode_init,
-    .encode2        = adx_encode_frame,
+    FF_CODEC_ENCODE_CB(adx_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
                                                       AV_SAMPLE_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/agm.c b/libavcodec/agm.c
index 795b34a415..27438dd1a4 100644
--- a/libavcodec/agm.c
+++ b/libavcodec/agm.c
@@ -1294,7 +1294,7 @@  const FFCodec ff_agm_decoder = {
     .priv_data_size   = sizeof(AGMContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush            = decode_flush,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP |
diff --git a/libavcodec/aic.c b/libavcodec/aic.c
index 7f124f5126..5f0eec6b80 100644
--- a/libavcodec/aic.c
+++ b/libavcodec/aic.c
@@ -503,7 +503,7 @@  const FFCodec ff_aic_decoder = {
     .priv_data_size = sizeof(AICContext),
     .init           = aic_decode_init,
     .close          = aic_decode_close,
-    .decode         = aic_decode_frame,
+    FF_CODEC_DECODE_CB(aic_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/alac.c b/libavcodec/alac.c
index b2d47e27c1..9aaf7066b2 100644
--- a/libavcodec/alac.c
+++ b/libavcodec/alac.c
@@ -618,7 +618,7 @@  const FFCodec ff_alac_decoder = {
     .priv_data_size = sizeof(ALACContext),
     .init           = alac_decode_init,
     .close          = alac_decode_close,
-    .decode         = alac_decode_frame,
+    FF_CODEC_DECODE_CB(alac_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.priv_class   = &alac_class
diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c
index 62ac32e345..72ce65e265 100644
--- a/libavcodec/alacenc.c
+++ b/libavcodec/alacenc.c
@@ -657,7 +657,7 @@  const FFCodec ff_alac_encoder = {
     .priv_data_size = sizeof(AlacEncodeContext),
     .p.priv_class   = &alacenc_class,
     .init           = alac_encode_init,
-    .encode2        = alac_encode_frame,
+    FF_CODEC_ENCODE_CB(alac_encode_frame),
     .close          = alac_encode_close,
     .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
 #if FF_API_OLD_CHANNEL_LAYOUT
diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c
index 8dc579079f..73c83528f5 100644
--- a/libavcodec/aliaspixdec.c
+++ b/libavcodec/aliaspixdec.c
@@ -127,5 +127,5 @@  const FFCodec ff_alias_pix_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_ALIAS_PIX,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode       = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c
index 74b5450132..9c43cfa9e7 100644
--- a/libavcodec/aliaspixenc.c
+++ b/libavcodec/aliaspixenc.c
@@ -106,7 +106,7 @@  const FFCodec ff_alias_pix_encoder = {
     .p.long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"),
     .p.type    = AVMEDIA_TYPE_VIDEO,
     .p.id      = AV_CODEC_ID_ALIAS_PIX,
-    .encode2   = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
     },
diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c
index 1a517916d5..bf961a03f5 100644
--- a/libavcodec/alsdec.c
+++ b/libavcodec/alsdec.c
@@ -2183,7 +2183,7 @@  const FFCodec ff_als_decoder = {
     .priv_data_size = sizeof(ALSDecContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c
index 7df2e8eb1d..efb04589f6 100644
--- a/libavcodec/amfenc_h264.c
+++ b/libavcodec/amfenc_h264.c
@@ -384,7 +384,7 @@  const FFCodec ff_h264_amf_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_H264,
     .init           = amf_encode_init_h264,
-    .receive_packet = ff_amf_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet),
     .close          = ff_amf_encode_close,
     .priv_data_size = sizeof(AmfContext),
     .p.priv_class   = &h264_amf_class,
diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c
index ed7230ee21..8ab9330730 100644
--- a/libavcodec/amfenc_hevc.c
+++ b/libavcodec/amfenc_hevc.c
@@ -316,7 +316,7 @@  const FFCodec ff_hevc_amf_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HEVC,
     .init           = amf_encode_init_hevc,
-    .receive_packet = ff_amf_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet),
     .close          = ff_amf_encode_close,
     .priv_data_size = sizeof(AmfContext),
     .p.priv_class   = &hevc_amf_class,
diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c
index 72482b25e4..f67ed1d02e 100644
--- a/libavcodec/amrnbdec.c
+++ b/libavcodec/amrnbdec.c
@@ -1103,7 +1103,7 @@  const FFCodec ff_amrnb_decoder = {
     .p.id           = AV_CODEC_ID_AMR_NB,
     .priv_data_size = sizeof(AMRChannelsContext),
     .init           = amrnb_decode_init,
-    .decode         = amrnb_decode_frame,
+    FF_CODEC_DECODE_CB(amrnb_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c
index e12078e028..7566f250d2 100644
--- a/libavcodec/amrwbdec.c
+++ b/libavcodec/amrwbdec.c
@@ -1299,7 +1299,7 @@  const FFCodec ff_amrwb_decoder = {
     .p.id           = AV_CODEC_ID_AMR_WB,
     .priv_data_size = sizeof(AMRWBChannelsContext),
     .init           = amrwb_decode_init,
-    .decode         = amrwb_decode_frame,
+    FF_CODEC_DECODE_CB(amrwb_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/anm.c b/libavcodec/anm.c
index 5e07247992..a9006be9c0 100644
--- a/libavcodec/anm.c
+++ b/libavcodec/anm.c
@@ -197,7 +197,7 @@  const FFCodec ff_anm_decoder = {
     .priv_data_size = sizeof(AnmContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c
index 80b3df0d92..909ebe7396 100644
--- a/libavcodec/ansi.c
+++ b/libavcodec/ansi.c
@@ -488,7 +488,7 @@  const FFCodec ff_ansi_decoder = {
     .priv_data_size = sizeof(AnsiContext),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .defaults       = ansi_defaults,
diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c
index 89b6bb04e5..f4000725f1 100644
--- a/libavcodec/apedec.c
+++ b/libavcodec/apedec.c
@@ -1666,7 +1666,7 @@  const FFCodec ff_ape_decoder = {
     .priv_data_size = sizeof(APEContext),
     .init           = ape_decode_init,
     .close          = ape_decode_close,
-    .decode         = ape_decode_frame,
+    FF_CODEC_DECODE_CB(ape_decode_frame),
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY |
                       AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/aptxdec.c b/libavcodec/aptxdec.c
index 03eb27cd5c..6ac070ba99 100644
--- a/libavcodec/aptxdec.c
+++ b/libavcodec/aptxdec.c
@@ -181,7 +181,7 @@  const FFCodec ff_aptx_decoder = {
     .p.id                  = AV_CODEC_ID_APTX,
     .priv_data_size        = sizeof(AptXContext),
     .init                  = ff_aptx_init,
-    .decode                = aptx_decode_frame,
+    FF_CODEC_DECODE_CB(aptx_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
@@ -201,7 +201,7 @@  const FFCodec ff_aptx_hd_decoder = {
     .p.id                  = AV_CODEC_ID_APTX_HD,
     .priv_data_size        = sizeof(AptXContext),
     .init                  = ff_aptx_init,
-    .decode                = aptx_decode_frame,
+    FF_CODEC_DECODE_CB(aptx_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
diff --git a/libavcodec/aptxenc.c b/libavcodec/aptxenc.c
index 206eb439e1..89ab3974c5 100644
--- a/libavcodec/aptxenc.c
+++ b/libavcodec/aptxenc.c
@@ -253,7 +253,7 @@  const FFCodec ff_aptx_encoder = {
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size        = sizeof(AptXContext),
     .init                  = ff_aptx_init,
-    .encode2               = aptx_encode_frame,
+    FF_CODEC_ENCODE_CB(aptx_encode_frame),
     .close                 = aptx_close,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
@@ -275,7 +275,7 @@  const FFCodec ff_aptx_hd_encoder = {
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size        = sizeof(AptXContext),
     .init                  = ff_aptx_init,
-    .encode2               = aptx_encode_frame,
+    FF_CODEC_ENCODE_CB(aptx_encode_frame),
     .close                 = aptx_close,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
diff --git a/libavcodec/arbc.c b/libavcodec/arbc.c
index d5171ee41e..78600963eb 100644
--- a/libavcodec/arbc.c
+++ b/libavcodec/arbc.c
@@ -218,7 +218,7 @@  const FFCodec ff_arbc_decoder = {
     .p.id           = AV_CODEC_ID_ARBC,
     .priv_data_size = sizeof(ARBCContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/argo.c b/libavcodec/argo.c
index 5c52b35b61..efd1056f16 100644
--- a/libavcodec/argo.c
+++ b/libavcodec/argo.c
@@ -740,7 +740,7 @@  const FFCodec ff_argo_decoder = {
     .p.id           = AV_CODEC_ID_ARGO,
     .priv_data_size = sizeof(ArgoContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c
index bf1260a947..b94629ea1d 100644
--- a/libavcodec/assdec.c
+++ b/libavcodec/assdec.c
@@ -68,7 +68,7 @@  const FFCodec ff_ssa_decoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_ASS,
     .init         = ass_decode_init,
-    .decode_sub   = ass_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(ass_decode_frame),
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
 #endif
@@ -80,7 +80,7 @@  const FFCodec ff_ass_decoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_ASS,
     .init         = ass_decode_init,
-    .decode_sub   = ass_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(ass_decode_frame),
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
 #endif
diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c
index 948ccdf083..2ac40d5afe 100644
--- a/libavcodec/assenc.c
+++ b/libavcodec/assenc.c
@@ -75,7 +75,7 @@  const FFCodec ff_ssa_encoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_ASS,
     .init         = ass_encode_init,
-    .encode_sub   = ass_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(ass_encode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
 #endif
@@ -87,7 +87,7 @@  const FFCodec ff_ass_encoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_ASS,
     .init         = ass_encode_init,
-    .encode_sub   = ass_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(ass_encode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
 #endif
diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c
index 0cce79d8b8..5b2c71be82 100644
--- a/libavcodec/asvdec.c
+++ b/libavcodec/asvdec.c
@@ -336,7 +336,7 @@  const FFCodec ff_asv1_decoder = {
     .priv_data_size = sizeof(ASV1Context),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -350,7 +350,7 @@  const FFCodec ff_asv2_decoder = {
     .p.id           = AV_CODEC_ID_ASV2,
     .priv_data_size = sizeof(ASV1Context),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c
index 8dd15f29bd..520173e6c9 100644
--- a/libavcodec/asvenc.c
+++ b/libavcodec/asvenc.c
@@ -350,7 +350,7 @@  const FFCodec ff_asv1_encoder = {
     .p.id           = AV_CODEC_ID_ASV1,
     .priv_data_size = sizeof(ASV1Context),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                      AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -365,7 +365,7 @@  const FFCodec ff_asv2_encoder = {
     .p.id           = AV_CODEC_ID_ASV2,
     .priv_data_size = sizeof(ASV1Context),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                      AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c
index 9c953d8772..7265891ac1 100644
--- a/libavcodec/atrac1.c
+++ b/libavcodec/atrac1.c
@@ -392,7 +392,7 @@  const FFCodec ff_atrac1_decoder = {
     .priv_data_size = sizeof(AT1Ctx),
     .init           = atrac1_decode_init,
     .close          = atrac1_decode_end,
-    .decode         = atrac1_decode_frame,
+    FF_CODEC_DECODE_CB(atrac1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c
index 123acdc7e3..97f59438e1 100644
--- a/libavcodec/atrac3.c
+++ b/libavcodec/atrac3.c
@@ -1023,7 +1023,7 @@  const FFCodec ff_atrac3_decoder = {
     .priv_data_size   = sizeof(ATRAC3Context),
     .init             = atrac3_decode_init,
     .close            = atrac3_decode_close,
-    .decode           = atrac3_decode_frame,
+    FF_CODEC_DECODE_CB(atrac3_decode_frame),
     .p.capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .p.sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                         AV_SAMPLE_FMT_NONE },
@@ -1038,7 +1038,7 @@  const FFCodec ff_atrac3al_decoder = {
     .priv_data_size   = sizeof(ATRAC3Context),
     .init             = atrac3_decode_init,
     .close            = atrac3_decode_close,
-    .decode           = atrac3al_decode_frame,
+    FF_CODEC_DECODE_CB(atrac3al_decode_frame),
     .p.capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .p.sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                         AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c
index 3524ed22e3..f87ffb8938 100644
--- a/libavcodec/atrac3plusdec.c
+++ b/libavcodec/atrac3plusdec.c
@@ -400,7 +400,7 @@  const FFCodec ff_atrac3p_decoder = {
     .priv_data_size = sizeof(ATRAC3PContext),
     .init           = atrac3p_decode_init,
     .close          = atrac3p_decode_close,
-    .decode         = atrac3p_decode_frame,
+    FF_CODEC_DECODE_CB(atrac3p_decode_frame),
 };
 
 const FFCodec ff_atrac3pal_decoder = {
@@ -413,5 +413,5 @@  const FFCodec ff_atrac3pal_decoder = {
     .priv_data_size = sizeof(ATRAC3PContext),
     .init           = atrac3p_decode_init,
     .close          = atrac3p_decode_close,
-    .decode         = atrac3p_decode_frame,
+    FF_CODEC_DECODE_CB(atrac3p_decode_frame),
 };
diff --git a/libavcodec/atrac9dec.c b/libavcodec/atrac9dec.c
index 5d51c23f19..d9ad03140c 100644
--- a/libavcodec/atrac9dec.c
+++ b/libavcodec/atrac9dec.c
@@ -995,7 +995,7 @@  const FFCodec ff_atrac9_decoder = {
     .priv_data_size = sizeof(ATRAC9Context),
     .init           = atrac9_decode_init,
     .close          = atrac9_decode_close,
-    .decode         = atrac9_decode_frame,
+    FF_CODEC_DECODE_CB(atrac9_decode_frame),
     .flush          = atrac9_decode_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c
index 3f6089f29a..b8d0e868f7 100644
--- a/libavcodec/audiotoolboxdec.c
+++ b/libavcodec/audiotoolboxdec.c
@@ -592,7 +592,7 @@  static av_cold int ffat_close_decoder(AVCodecContext *avctx)
         .priv_data_size = sizeof(ATDecodeContext), \
         .init           = ffat_init_decoder, \
         .close          = ffat_close_decoder, \
-        .decode         = ffat_decode, \
+        FF_CODEC_DECODE_CB(ffat_decode), \
         .flush          = ffat_decode_flush, \
         .p.priv_class   = &ffat_##NAME##_dec_class, \
         .bsfs           = bsf_name, \
diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c
index 4e7073064f..f8305ab89b 100644
--- a/libavcodec/audiotoolboxenc.c
+++ b/libavcodec/audiotoolboxenc.c
@@ -621,7 +621,7 @@  static const AVOption options[] = {
         .priv_data_size = sizeof(ATDecodeContext), \
         .init           = ffat_init_encoder, \
         .close          = ffat_close_encoder, \
-        .encode2        = ffat_encode, \
+        FF_CODEC_ENCODE_CB(ffat_encode), \
         .flush          = ffat_encode_flush, \
         .p.priv_class   = &ffat_##NAME##_enc_class, \
         .p.capabilities = AV_CODEC_CAP_DELAY | \
diff --git a/libavcodec/aura.c b/libavcodec/aura.c
index 1896013cfb..b4167cacfd 100644
--- a/libavcodec/aura.c
+++ b/libavcodec/aura.c
@@ -102,7 +102,7 @@  const FFCodec ff_aura2_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AURA2,
     .init           = aura_decode_init,
-    .decode         = aura_decode_frame,
+    FF_CODEC_DECODE_CB(aura_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c
index 517fa701f4..1c09b1d6d6 100644
--- a/libavcodec/av1dec.c
+++ b/libavcodec/av1dec.c
@@ -1246,7 +1246,7 @@  const FFCodec ff_av1_decoder = {
     .priv_data_size        = sizeof(AV1DecContext),
     .init                  = av1_decode_init,
     .close                 = av1_decode_free,
-    .decode                = av1_decode_frame,
+    FF_CODEC_DECODE_CB(av1_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE |
                              FF_CODEC_CAP_INIT_CLEANUP |
diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c
index 8f716a129e..9bb0c1ffa2 100644
--- a/libavcodec/avrndec.c
+++ b/libavcodec/avrndec.c
@@ -96,7 +96,7 @@  const FFCodec ff_avrn_decoder = {
     .p.id           = AV_CODEC_ID_AVRN,
     .priv_data_size = sizeof(AVRnContext),
     .init           = init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/avs.c b/libavcodec/avs.c
index a26a3bbc00..6dda3393b5 100644
--- a/libavcodec/avs.c
+++ b/libavcodec/avs.c
@@ -182,7 +182,7 @@  const FFCodec ff_avs_decoder = {
     .p.id           = AV_CODEC_ID_AVS,
     .priv_data_size = sizeof(AvsContext),
     .init           = avs_decode_init,
-    .decode         = avs_decode_frame,
+    FF_CODEC_DECODE_CB(avs_decode_frame),
     .close          = avs_decode_end,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/avuidec.c b/libavcodec/avuidec.c
index a86b0d5668..f545c41154 100644
--- a/libavcodec/avuidec.c
+++ b/libavcodec/avuidec.c
@@ -126,6 +126,6 @@  const FFCodec ff_avui_decoder = {
     .p.id           = AV_CODEC_ID_AVUI,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = avui_decode_init,
-    .decode       = avui_decode_frame,
+    FF_CODEC_DECODE_CB(avui_decode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/avuienc.c b/libavcodec/avuienc.c
index dccfd65c90..e2bd3181f5 100644
--- a/libavcodec/avuienc.c
+++ b/libavcodec/avuienc.c
@@ -99,6 +99,6 @@  const FFCodec ff_avui_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE },
     .init         = avui_encode_init,
-    .encode2      = avui_encode_frame,
+    FF_CODEC_ENCODE_CB(avui_encode_frame),
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c
index 44175805f1..9fc286fb00 100644
--- a/libavcodec/bethsoftvideo.c
+++ b/libavcodec/bethsoftvideo.c
@@ -166,7 +166,7 @@  const FFCodec ff_bethsoftvid_decoder = {
     .priv_data_size = sizeof(BethsoftvidContext),
     .init           = bethsoftvid_decode_init,
     .close          = bethsoftvid_decode_end,
-    .decode         = bethsoftvid_decode_frame,
+    FF_CODEC_DECODE_CB(bethsoftvid_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c
index fb22b0e1b1..6f9fbb0e96 100644
--- a/libavcodec/bfi.c
+++ b/libavcodec/bfi.c
@@ -183,7 +183,7 @@  const FFCodec ff_bfi_decoder = {
     .priv_data_size = sizeof(BFIContext),
     .init           = bfi_decode_init,
     .close          = bfi_decode_close,
-    .decode         = bfi_decode_frame,
+    FF_CODEC_DECODE_CB(bfi_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/bink.c b/libavcodec/bink.c
index 941c2244a7..ce740ad275 100644
--- a/libavcodec/bink.c
+++ b/libavcodec/bink.c
@@ -1427,7 +1427,7 @@  const FFCodec ff_bink_decoder = {
     .priv_data_size = sizeof(BinkContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c
index c4f3e743e2..fb5233f0ab 100644
--- a/libavcodec/binkaudio.c
+++ b/libavcodec/binkaudio.c
@@ -372,7 +372,7 @@  const FFCodec ff_binkaudio_rdft_decoder = {
     .init           = decode_init,
     .flush          = decode_flush,
     .close          = decode_end,
-    .receive_frame  = binkaudio_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(binkaudio_receive_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
@@ -386,7 +386,7 @@  const FFCodec ff_binkaudio_dct_decoder = {
     .init           = decode_init,
     .flush          = decode_flush,
     .close          = decode_end,
-    .receive_frame  = binkaudio_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(binkaudio_receive_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/bintext.c b/libavcodec/bintext.c
index 183fea5b84..e153198c32 100644
--- a/libavcodec/bintext.c
+++ b/libavcodec/bintext.c
@@ -224,7 +224,7 @@  const FFCodec ff_bintext_decoder = {
     .p.id           = AV_CODEC_ID_BINTEXT,
     .priv_data_size = sizeof(XbinContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -237,7 +237,7 @@  const FFCodec ff_xbin_decoder = {
     .p.id           = AV_CODEC_ID_XBIN,
     .priv_data_size = sizeof(XbinContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -250,7 +250,7 @@  const FFCodec ff_idf_decoder = {
     .p.id           = AV_CODEC_ID_IDF,
     .priv_data_size = sizeof(XbinContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c
index 3b8f2d8fd9..4723a3c7eb 100644
--- a/libavcodec/bitpacked_dec.c
+++ b/libavcodec/bitpacked_dec.c
@@ -149,7 +149,7 @@  const FFCodec ff_bitpacked_decoder = {
     .p.capabilities  = AV_CODEC_CAP_FRAME_THREADS,
     .priv_data_size        = sizeof(struct BitpackedContext),
     .init = bitpacked_init_decoder,
-    .decode = bitpacked_decode,
+    FF_CODEC_DECODE_CB(bitpacked_decode),
     .codec_tags     = (const uint32_t []){
         MKTAG('U', 'Y', 'V', 'Y'),
         FF_CODEC_TAGS_END,
diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c
index c9c0501f39..127f1af59b 100644
--- a/libavcodec/bitpacked_enc.c
+++ b/libavcodec/bitpacked_enc.c
@@ -112,7 +112,7 @@  const FFCodec ff_bitpacked_encoder = {
     .priv_data_size = sizeof(struct BitpackedContext),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10,
                                                     AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c
index c971ff0f59..410065aba1 100644
--- a/libavcodec/bmp.c
+++ b/libavcodec/bmp.c
@@ -370,5 +370,5 @@  const FFCodec ff_bmp_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_BMP,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = bmp_decode_frame,
+    FF_CODEC_DECODE_CB(bmp_decode_frame),
 };
diff --git a/libavcodec/bmpenc.c b/libavcodec/bmpenc.c
index 1f2303c1e0..f28ce01f59 100644
--- a/libavcodec/bmpenc.c
+++ b/libavcodec/bmpenc.c
@@ -162,7 +162,7 @@  const FFCodec ff_bmp_encoder = {
     .p.id           = AV_CODEC_ID_BMP,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = bmp_encode_init,
-    .encode2        = bmp_encode_frame,
+    FF_CODEC_ENCODE_CB(bmp_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR24,
         AV_PIX_FMT_RGB565, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444,
diff --git a/libavcodec/bmvaudio.c b/libavcodec/bmvaudio.c
index d21370938f..f57ece0320 100644
--- a/libavcodec/bmvaudio.c
+++ b/libavcodec/bmvaudio.c
@@ -84,7 +84,7 @@  const FFCodec ff_bmv_audio_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_BMV_AUDIO,
     .init           = bmv_aud_decode_init,
-    .decode         = bmv_aud_decode_frame,
+    FF_CODEC_DECODE_CB(bmv_aud_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/bmvvideo.c b/libavcodec/bmvvideo.c
index baa8e37e46..c492d7fcfa 100644
--- a/libavcodec/bmvvideo.c
+++ b/libavcodec/bmvvideo.c
@@ -292,7 +292,7 @@  const FFCodec ff_bmv_video_decoder = {
     .p.id           = AV_CODEC_ID_BMV_VIDEO,
     .priv_data_size = sizeof(BMVDecContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c
index 98db6e6950..9807a11cf9 100644
--- a/libavcodec/brenderpix.c
+++ b/libavcodec/brenderpix.c
@@ -290,5 +290,5 @@  const FFCodec ff_brender_pix_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_BRENDER_PIX,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode       = pix_decode_frame,
+    FF_CODEC_DECODE_CB(pix_decode_frame),
 };
diff --git a/libavcodec/c93.c b/libavcodec/c93.c
index a5dee1d1a3..050bb42741 100644
--- a/libavcodec/c93.c
+++ b/libavcodec/c93.c
@@ -266,7 +266,7 @@  const FFCodec ff_c93_decoder = {
     .priv_data_size = sizeof(C93DecoderContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index 6e424f4763..7aaf3f2bcf 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -1318,7 +1318,7 @@  const FFCodec ff_cavs_decoder = {
     .priv_data_size = sizeof(AVSContext),
     .init           = ff_cavs_init,
     .close          = ff_cavs_end,
-    .decode         = cavs_decode_frame,
+    FF_CODEC_DECODE_CB(cavs_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .flush          = cavs_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c
index 32ee3a715d..e33fb36824 100644
--- a/libavcodec/ccaption_dec.c
+++ b/libavcodec/ccaption_dec.c
@@ -955,6 +955,6 @@  const FFCodec ff_ccaption_decoder = {
     .init           = init_decoder,
     .close          = close_decoder,
     .flush          = flush_decoder,
-    .decode_sub     = decode,
+    FF_CODEC_DECODE_SUB_CB(decode),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c
index 8d72e6d87c..b851ec430b 100644
--- a/libavcodec/cdgraphics.c
+++ b/libavcodec/cdgraphics.c
@@ -395,7 +395,7 @@  const FFCodec ff_cdgraphics_decoder = {
     .priv_data_size = sizeof(CDGraphicsContext),
     .init           = cdg_decode_init,
     .close          = cdg_decode_end,
-    .decode         = cdg_decode_frame,
+    FF_CODEC_DECODE_CB(cdg_decode_frame),
     .flush          = cdg_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/cdtoons.c b/libavcodec/cdtoons.c
index 1b1c1f827e..eb53a324db 100644
--- a/libavcodec/cdtoons.c
+++ b/libavcodec/cdtoons.c
@@ -451,7 +451,7 @@  const FFCodec ff_cdtoons_decoder = {
     .priv_data_size = sizeof(CDToonsContext),
     .init           = cdtoons_decode_init,
     .close          = cdtoons_decode_end,
-    .decode         = cdtoons_decode_frame,
+    FF_CODEC_DECODE_CB(cdtoons_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .flush          = cdtoons_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c
index 34481fe2a3..1f25d8eb99 100644
--- a/libavcodec/cdxl.c
+++ b/libavcodec/cdxl.c
@@ -344,7 +344,7 @@  const FFCodec ff_cdxl_decoder = {
     .priv_data_size = sizeof(CDXLVideoContext),
     .init           = cdxl_decode_init,
     .close          = cdxl_decode_end,
-    .decode         = cdxl_decode_frame,
+    FF_CODEC_DECODE_CB(cdxl_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c
index ab074043c1..5adb0b2008 100644
--- a/libavcodec/cfhd.c
+++ b/libavcodec/cfhd.c
@@ -1463,7 +1463,7 @@  const FFCodec ff_cfhd_decoder = {
     .priv_data_size   = sizeof(CFHDContext),
     .init             = cfhd_init,
     .close            = cfhd_close,
-    .decode           = cfhd_decode,
+    FF_CODEC_DECODE_CB(cfhd_decode),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/cfhdenc.c b/libavcodec/cfhdenc.c
index f9b8ed2625..6b33b29da9 100644
--- a/libavcodec/cfhdenc.c
+++ b/libavcodec/cfhdenc.c
@@ -854,7 +854,7 @@  const FFCodec ff_cfhd_encoder = {
     .p.priv_class     = &cfhd_class,
     .init             = cfhd_encode_init,
     .close            = cfhd_encode_close,
-    .encode2          = cfhd_encode_frame,
+    FF_CODEC_ENCODE_CB(cfhd_encode_frame),
     .p.capabilities   = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts       = (const enum AVPixelFormat[]) {
                           AV_PIX_FMT_YUV422P10,
diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c
index 9bc7a681e5..e69232efb1 100644
--- a/libavcodec/cinepak.c
+++ b/libavcodec/cinepak.c
@@ -514,7 +514,7 @@  const FFCodec ff_cinepak_decoder = {
     .priv_data_size = sizeof(CinepakContext),
     .init           = cinepak_decode_init,
     .close          = cinepak_decode_end,
-    .decode         = cinepak_decode_frame,
+    FF_CODEC_DECODE_CB(cinepak_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c
index 66baae3a1a..8b32c02780 100644
--- a/libavcodec/cinepakenc.c
+++ b/libavcodec/cinepakenc.c
@@ -1201,7 +1201,7 @@  const FFCodec ff_cinepak_encoder = {
     .p.id           = AV_CODEC_ID_CINEPAK,
     .priv_data_size = sizeof(CinepakEncContext),
     .init           = cinepak_encode_init,
-    .encode2        = cinepak_encode_frame,
+    FF_CODEC_ENCODE_CB(cinepak_encode_frame),
     .close          = cinepak_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE },
     .p.priv_class   = &cinepak_class,
diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c
index 4e54ccb680..37283d4ddd 100644
--- a/libavcodec/clearvideo.c
+++ b/libavcodec/clearvideo.c
@@ -775,7 +775,7 @@  const FFCodec ff_clearvideo_decoder = {
     .priv_data_size = sizeof(CLVContext),
     .init           = clv_decode_init,
     .close          = clv_decode_end,
-    .decode         = clv_decode_frame,
+    FF_CODEC_DECODE_CB(clv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/cljrdec.c b/libavcodec/cljrdec.c
index e3a278f16f..bb7c9bfb65 100644
--- a/libavcodec/cljrdec.c
+++ b/libavcodec/cljrdec.c
@@ -87,7 +87,7 @@  const FFCodec ff_cljr_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_CLJR,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c
index 6bd8537316..2d171a9376 100644
--- a/libavcodec/cljrenc.c
+++ b/libavcodec/cljrenc.c
@@ -115,7 +115,7 @@  const FFCodec ff_cljr_encoder = {
     .p.id           = AV_CODEC_ID_CLJR,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(CLJRContext),
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P,
                                                    AV_PIX_FMT_NONE },
     .p.priv_class   = &cljr_class,
diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c
index f01498310a..f7283ca4f8 100644
--- a/libavcodec/cllc.c
+++ b/libavcodec/cllc.c
@@ -498,7 +498,7 @@  const FFCodec ff_cllc_decoder = {
     .p.id           = AV_CODEC_ID_CLLC,
     .priv_data_size = sizeof(CLLCContext),
     .init           = cllc_decode_init,
-    .decode         = cllc_decode_frame,
+    FF_CODEC_DECODE_CB(cllc_decode_frame),
     .close          = cllc_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c
index f396d5a5d0..d549ff4c05 100644
--- a/libavcodec/cngdec.c
+++ b/libavcodec/cngdec.c
@@ -169,7 +169,7 @@  const FFCodec ff_comfortnoise_decoder = {
     .p.id           = AV_CODEC_ID_COMFORT_NOISE,
     .priv_data_size = sizeof(CNGContext),
     .init           = cng_decode_init,
-    .decode         = cng_decode_frame,
+    FF_CODEC_DECODE_CB(cng_decode_frame),
     .flush          = cng_decode_flush,
     .close          = cng_decode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c
index 650bfa1938..1f5d25e5b3 100644
--- a/libavcodec/cngenc.c
+++ b/libavcodec/cngenc.c
@@ -104,7 +104,7 @@  const FFCodec ff_comfortnoise_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(CNGContext),
     .init           = cng_encode_init,
-    .encode2        = cng_encode_frame,
+    FF_CODEC_ENCODE_CB(cng_encode_frame),
     .close          = cng_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
index 4e8c06a49e..a14f6592fe 100644
--- a/libavcodec/codec_internal.h
+++ b/libavcodec/codec_internal.h
@@ -88,6 +88,27 @@  struct AVCodecContext;
 struct AVSubtitle;
 struct AVPacket;
 
+enum FFCodecType {
+    /* The codec is a decoder using the decode callback;
+     * audio and video codecs only. */
+    FF_CODEC_CB_TYPE_DECODE,
+    /* The codec is a decoder using the decode_sub callback;
+     * subtitle codecs only. */
+    FF_CODEC_CB_TYPE_DECODE_SUB,
+    /* The codec is a decoder using the receive_frame callback;
+     * audio and video codecs only. */
+    FF_CODEC_CB_TYPE_RECEIVE_FRAME,
+    /* The codec is an encoder using the encode callback;
+     * audio and video codecs only. */
+    FF_CODEC_CB_TYPE_ENCODE,
+    /* The codec is an encoder using the encode_sub callback;
+     * subtitle codecs only. */
+    FF_CODEC_CB_TYPE_ENCODE_SUB,
+    /* The codec is an encoder using the receive_packet callback;
+     * audio and video codecs only. */
+    FF_CODEC_CB_TYPE_RECEIVE_PACKET,
+};
+
 typedef struct FFCodec {
     /**
      * The public AVCodec. See codec.h for it.
@@ -97,7 +118,14 @@  typedef struct FFCodec {
     /**
      * Internal codec capabilities FF_CODEC_CAP_*.
      */
-    int caps_internal;
+    unsigned caps_internal:29;
+
+    /**
+     * This field determines the type of the codec (decoder/encoder)
+     * and also the exact callback cb implemented by the codec.
+     * cb_type uses enum FFCodecType values.
+     */
+    unsigned cb_type:3;
 
     int priv_data_size;
     /**
@@ -133,53 +161,69 @@  typedef struct FFCodec {
     void (*init_static_data)(struct FFCodec *codec);
 
     int (*init)(struct AVCodecContext *);
-    int (*encode_sub)(struct AVCodecContext *, uint8_t *buf, int buf_size,
-                      const struct AVSubtitle *sub);
-    /**
-     * Encode data to an AVPacket.
-     *
-     * @param      avctx          codec context
-     * @param      avpkt          output AVPacket
-     * @param[in]  frame          AVFrame containing the raw data to be encoded
-     * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
-     *                            non-empty packet was returned in avpkt.
-     * @return 0 on success, negative error code on failure
-     */
-    int (*encode2)(struct AVCodecContext *avctx, struct AVPacket *avpkt,
-                   const struct AVFrame *frame, int *got_packet_ptr);
-    /**
-     * Decode to an AVFrame.
-     *
-     * @param      avctx          codec context
-     * @param      frame          AVFrame for output
-     * @param[out] got_frame_ptr  decoder sets to 0 or 1 to indicate that a
-     *                            non-empty frame was returned in outdata.
-     * @param[in]  avpkt          AVPacket containing the data to be decoded
-     * @return amount of bytes read from the packet on success, negative error
-     *         code on failure
-     */
-    int (*decode)(struct AVCodecContext *avctx, struct AVFrame *frame,
-                  int *got_frame_ptr, struct AVPacket *avpkt);
-    /**
-     * Decode subtitle data. Same as decode except that it uses
-     * a struct AVSubtitle structure for output.
-     */
-    int (*decode_sub)(struct AVCodecContext *avctx, struct AVSubtitle *sub,
+
+    union {
+        /**
+         * Decode to an AVFrame.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE.
+         *
+         * @param      avctx          codec context
+         * @param[out] frame          AVFrame for output
+         * @param[out] got_frame_ptr  decoder sets to 0 or 1 to indicate that
+         *                            a non-empty frame was returned in frame.
+         * @param[in]  avpkt          AVPacket containing the data to be decoded
+         * @return amount of bytes read from the packet on success,
+         *         negative error code on failure
+         */
+        int (*decode)(struct AVCodecContext *avctx, struct AVFrame *frame,
                       int *got_frame_ptr, struct AVPacket *avpkt);
+        /**
+         * Decode subtitle data to an AVSubtitle.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE_SUB.
+         *
+         * Apart from that this is like the decode callback.
+         */
+        int (*decode_sub)(struct AVCodecContext *avctx, struct AVSubtitle *sub,
+                          int *got_frame_ptr, struct AVPacket *avpkt);
+        /**
+         * Decode API with decoupled packet/frame dataflow.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_FRAME.
+         *
+         * This function is called to get one output frame. It should call
+         * ff_decode_get_packet() to obtain input data.
+         */
+        int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame);
+        /**
+         * Encode data to an AVPacket.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE
+         *
+         * @param      avctx          codec context
+         * @param[out] avpkt          output AVPacket
+         * @param[in]  frame          AVFrame containing the input to be encoded
+         * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
+         *                            non-empty packet was returned in avpkt.
+         * @return 0 on success, negative error code on failure
+         */
+        int (*encode)(struct AVCodecContext *avctx, struct AVPacket *avpkt,
+                      const struct AVFrame *frame, int *got_packet_ptr);
+        /**
+         * Encode subtitles to a raw buffer.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE_SUB.
+         */
+        int (*encode_sub)(struct AVCodecContext *avctx, uint8_t *buf,
+                          int buf_size, const struct AVSubtitle *sub);
+        /**
+         * Encode API with decoupled frame/packet dataflow.
+         * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_PACKET.
+         *
+         * This function is called to get one output packet.
+         * It should call ff_encode_get_frame() to obtain input data.
+         */
+        int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt);
+    } cb;
+
     int (*close)(struct AVCodecContext *);
-    /**
-     * Encode API with decoupled frame/packet dataflow. This function is called
-     * to get one output packet. It should call ff_encode_get_frame() to obtain
-     * input data.
-     */
-    int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt);
 
-    /**
-     * Decode API with decoupled packet/frame dataflow. This function is called
-     * to get one output frame. It should call ff_decode_get_packet() to obtain
-     * input data.
-     */
-    int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame);
     /**
      * Flush buffers.
      * Will be called when seeking
@@ -207,6 +251,25 @@  typedef struct FFCodec {
     const uint32_t *codec_tags;
 } FFCodec;
 
+#define FF_CODEC_DECODE_CB(func)                          \
+    .cb_type           = FF_CODEC_CB_TYPE_DECODE,         \
+    .cb.decode         = (func)
+#define FF_CODEC_DECODE_SUB_CB(func)                      \
+    .cb_type           = FF_CODEC_CB_TYPE_DECODE_SUB,     \
+    .cb.decode_sub     = (func)
+#define FF_CODEC_RECEIVE_FRAME_CB(func)                   \
+    .cb_type           = FF_CODEC_CB_TYPE_RECEIVE_FRAME,  \
+    .cb.receive_frame  = (func)
+#define FF_CODEC_ENCODE_CB(func)                          \
+    .cb_type           = FF_CODEC_CB_TYPE_ENCODE,         \
+    .cb.encode         = (func)
+#define FF_CODEC_ENCODE_SUB_CB(func)                      \
+    .cb_type           = FF_CODEC_CB_TYPE_ENCODE_SUB,     \
+    .cb.encode_sub     = (func)
+#define FF_CODEC_RECEIVE_PACKET_CB(func)                  \
+    .cb_type           = FF_CODEC_CB_TYPE_RECEIVE_PACKET, \
+    .cb.receive_packet = (func)
+
 static av_always_inline const FFCodec *ffcodec(const AVCodec *codec)
 {
     return (const FFCodec*)codec;
diff --git a/libavcodec/cook.c b/libavcodec/cook.c
index 783623d7db..7161209db3 100644
--- a/libavcodec/cook.c
+++ b/libavcodec/cook.c
@@ -1304,7 +1304,7 @@  const FFCodec ff_cook_decoder = {
     .priv_data_size = sizeof(COOKContext),
     .init           = cook_decode_init,
     .close          = cook_decode_close,
-    .decode         = cook_decode_frame,
+    FF_CODEC_DECODE_CB(cook_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c
index 1b50aa9d30..2f4ad1fb5b 100644
--- a/libavcodec/cpia.c
+++ b/libavcodec/cpia.c
@@ -230,7 +230,7 @@  const FFCodec ff_cpia_decoder = {
     .priv_data_size = sizeof(CpiaContext),
     .init           = cpia_decode_init,
     .close          = cpia_decode_end,
-    .decode         = cpia_decode_frame,
+    FF_CODEC_DECODE_CB(cpia_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/cri.c b/libavcodec/cri.c
index b1922d5e9b..728983797a 100644
--- a/libavcodec/cri.c
+++ b/libavcodec/cri.c
@@ -429,7 +429,7 @@  const FFCodec ff_cri_decoder = {
     .p.id           = AV_CODEC_ID_CRI,
     .priv_data_size = sizeof(CRIContext),
     .init           = cri_decode_init,
-    .decode         = cri_decode_frame,
+    FF_CODEC_DECODE_CB(cri_decode_frame),
     .close          = cri_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index d4cf385cbd..cf74f22e7d 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -783,7 +783,7 @@  static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
         .p.priv_class   = &x##_crystalhd_class, \
         .init           = init, \
         .close          = uninit, \
-        .receive_frame  = crystalhd_receive_frame, \
+        FF_CODEC_RECEIVE_FRAME_CB(crystalhd_receive_frame), \
         .flush          = flush, \
         .bsfs           = bsf_name, \
         .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c
index 9b87c1b91d..ea84711299 100644
--- a/libavcodec/cscd.c
+++ b/libavcodec/cscd.c
@@ -175,7 +175,7 @@  const FFCodec ff_cscd_decoder = {
     .priv_data_size = sizeof(CamStudioContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c
index 0060e51c91..81d4c89215 100644
--- a/libavcodec/cuviddec.c
+++ b/libavcodec/cuviddec.c
@@ -1112,7 +1112,7 @@  static const AVCodecHWConfigInternal *const cuvid_hw_configs[] = {
         .p.priv_class   = &x##_cuvid_class, \
         .init           = cuvid_decode_init, \
         .close          = cuvid_decode_end, \
-        .receive_frame  = cuvid_output_frame, \
+        FF_CODEC_RECEIVE_FRAME_CB(cuvid_output_frame), \
         .flush          = cuvid_flush, \
         .bsfs           = bsf_name, \
         .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
diff --git a/libavcodec/cyuv.c b/libavcodec/cyuv.c
index ba20cd02da..8fa4d1f3a7 100644
--- a/libavcodec/cyuv.c
+++ b/libavcodec/cyuv.c
@@ -184,7 +184,7 @@  const FFCodec ff_aura_decoder = {
     .p.id           = AV_CODEC_ID_AURA,
     .priv_data_size = sizeof(CyuvDecodeContext),
     .init           = cyuv_decode_init,
-    .decode         = cyuv_decode_frame,
+    FF_CODEC_DECODE_CB(cyuv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -198,7 +198,7 @@  const FFCodec ff_cyuv_decoder = {
     .p.id           = AV_CODEC_ID_CYUV,
     .priv_data_size = sizeof(CyuvDecodeContext),
     .init           = cyuv_decode_init,
-    .decode         = cyuv_decode_frame,
+    FF_CODEC_DECODE_CB(cyuv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index 62684b8042..38ea8733e4 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -417,7 +417,7 @@  const FFCodec ff_dca_decoder = {
     .p.id           = AV_CODEC_ID_DTS,
     .priv_data_size = sizeof(DCAContext),
     .init           = dcadec_init,
-    .decode         = dcadec_decode_frame,
+    FF_CODEC_DECODE_CB(dcadec_decode_frame),
     .close          = dcadec_close,
     .flush          = dcadec_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c
index 7b92b861e3..aad06adb7e 100644
--- a/libavcodec/dcaenc.c
+++ b/libavcodec/dcaenc.c
@@ -1249,7 +1249,7 @@  const FFCodec ff_dca_encoder = {
     .priv_data_size        = sizeof(DCAEncContext),
     .init                  = encode_init,
     .close                 = encode_close,
-    .encode2               = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
                                                             AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/dds.c b/libavcodec/dds.c
index c5691a4afd..d4f6800ec9 100644
--- a/libavcodec/dds.c
+++ b/libavcodec/dds.c
@@ -753,7 +753,7 @@  const FFCodec ff_dds_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DDS,
-    .decode         = dds_decode,
+    FF_CODEC_DECODE_CB(dds_decode),
     .priv_data_size = sizeof(DDSContext),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index b5b78b9ca2..e51a39e70a 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -322,7 +322,7 @@  static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame,
     if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) {
         ret = ff_thread_decode_frame(avctx, frame, &got_frame, pkt);
     } else {
-        ret = codec->decode(avctx, frame, &got_frame, pkt);
+        ret = codec->cb.decode(avctx, frame, &got_frame, pkt);
 
         if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS))
             frame->pkt_dts = pkt->dts;
@@ -546,8 +546,8 @@  static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
 
     av_assert0(!frame->buf[0]);
 
-    if (codec->receive_frame) {
-        ret = codec->receive_frame(avctx, frame);
+    if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) {
+        ret = codec->cb.receive_frame(avctx, frame);
         if (ret != AVERROR(EAGAIN))
             av_packet_unref(avci->last_pkt_props);
     } else
@@ -862,7 +862,7 @@  int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
         if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE)
             sub->pts = av_rescale_q(avpkt->pts,
                                     avctx->pkt_timebase, AV_TIME_BASE_Q);
-        ret = ffcodec(avctx->codec)->decode_sub(avctx, sub, got_sub_ptr, pkt);
+        ret = ffcodec(avctx->codec)->cb.decode_sub(avctx, sub, got_sub_ptr, pkt);
         if (pkt == avci->buffer_pkt) // did we recode?
             av_packet_unref(avci->buffer_pkt);
         if (ret < 0) {
diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c
index 4625f62ec6..e74fd071d3 100644
--- a/libavcodec/dfa.c
+++ b/libavcodec/dfa.c
@@ -429,7 +429,7 @@  const FFCodec ff_dfa_decoder = {
     .priv_data_size = sizeof(DfaContext),
     .init           = dfa_decode_init,
     .close          = dfa_decode_end,
-    .decode         = dfa_decode_frame,
+    FF_CODEC_DECODE_CB(dfa_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dfpwmdec.c b/libavcodec/dfpwmdec.c
index 4237200c6b..77c6d2cb18 100644
--- a/libavcodec/dfpwmdec.c
+++ b/libavcodec/dfpwmdec.c
@@ -131,7 +131,7 @@  const FFCodec ff_dfpwm_decoder = {
     .p.id           = AV_CODEC_ID_DFPWM,
     .priv_data_size = sizeof(DFPWMState),
     .init           = dfpwm_dec_init,
-    .decode         = dfpwm_dec_frame,
+    FF_CODEC_DECODE_CB(dfpwm_dec_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c
index e3a001aea7..85ee1a980a 100644
--- a/libavcodec/dfpwmenc.c
+++ b/libavcodec/dfpwmenc.c
@@ -114,7 +114,7 @@  const FFCodec ff_dfpwm_encoder = {
     .p.id            = AV_CODEC_ID_DFPWM,
     .priv_data_size  = sizeof(DFPWMState),
     .init            = dfpwm_enc_init,
-    .encode2         = dfpwm_enc_frame,
+    FF_CODEC_ENCODE_CB(dfpwm_enc_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE},
     .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
     .caps_internal   = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c
index 319067bc79..d6d8168bd6 100644
--- a/libavcodec/diracdec.c
+++ b/libavcodec/diracdec.c
@@ -2364,7 +2364,7 @@  const FFCodec ff_dirac_decoder = {
     .priv_data_size = sizeof(DiracContext),
     .init           = dirac_decode_init,
     .close          = dirac_decode_end,
-    .decode         = dirac_decode_frame,
+    FF_CODEC_DECODE_CB(dirac_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .flush          = dirac_decode_flush,
diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c
index 4b22a4134e..65cd6d9398 100644
--- a/libavcodec/dnxhddec.c
+++ b/libavcodec/dnxhddec.c
@@ -732,7 +732,7 @@  const FFCodec ff_dnxhd_decoder = {
     .priv_data_size = sizeof(DNXHDContext),
     .init           = dnxhd_decode_init,
     .close          = dnxhd_decode_close,
-    .decode         = dnxhd_decode_frame,
+    FF_CODEC_DECODE_CB(dnxhd_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
                       AV_CODEC_CAP_SLICE_THREADS,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles),
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index 1795993efe..c6378f8ecb 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -1361,7 +1361,7 @@  const FFCodec ff_dnxhd_encoder = {
                       AV_CODEC_CAP_SLICE_THREADS,
     .priv_data_size = sizeof(DNXHDEncContext),
     .init           = dnxhd_encode_init,
-    .encode2        = dnxhd_encode_picture,
+    FF_CODEC_ENCODE_CB(dnxhd_encode_picture),
     .close          = dnxhd_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_YUV422P,
diff --git a/libavcodec/dolby_e.c b/libavcodec/dolby_e.c
index 6c86f74c94..a734af8d45 100644
--- a/libavcodec/dolby_e.c
+++ b/libavcodec/dolby_e.c
@@ -1305,7 +1305,7 @@  const FFCodec ff_dolby_e_decoder = {
     .priv_data_size = sizeof(DBEDecodeContext),
     .p.priv_class   = &dolby_e_decoder_class,
     .init           = dolby_e_init,
-    .decode         = dolby_e_decode_frame,
+    FF_CODEC_DECODE_CB(dolby_e_decode_frame),
     .close          = dolby_e_close,
     .flush          = dolby_e_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c
index db09ef274b..ad020b52f6 100644
--- a/libavcodec/dpcm.c
+++ b/libavcodec/dpcm.c
@@ -418,7 +418,7 @@  const FFCodec ff_ ## name_ ## _decoder = {                  \
     .p.capabilities = AV_CODEC_CAP_DR1,                     \
     .priv_data_size = sizeof(DPCMContext),                  \
     .init           = dpcm_decode_init,                     \
-    .decode         = dpcm_decode_frame,                    \
+    FF_CODEC_DECODE_CB(dpcm_decode_frame),                  \
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,         \
 }
 
diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c
index 7a3054b140..bb2c5e588e 100644
--- a/libavcodec/dpx.c
+++ b/libavcodec/dpx.c
@@ -765,6 +765,6 @@  const FFCodec ff_dpx_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DPX,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c
index 15023d615e..1f2b1b8f5d 100644
--- a/libavcodec/dpxenc.c
+++ b/libavcodec/dpxenc.c
@@ -282,7 +282,7 @@  const FFCodec ff_dpx_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(DPXContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_GRAY8,
         AV_PIX_FMT_RGB24,    AV_PIX_FMT_RGBA, AV_PIX_FMT_ABGR,
diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c
index e0578bc9cc..f0e54db100 100644
--- a/libavcodec/dsddec.c
+++ b/libavcodec/dsddec.c
@@ -121,7 +121,7 @@  const FFCodec ff_ ## name_ ## _decoder = { \
     .p.type       = AVMEDIA_TYPE_AUDIO, \
     .p.id         = AV_CODEC_ID_##id_, \
     .init         = decode_init, \
-    .decode       = decode_frame, \
+    FF_CODEC_DECODE_CB(decode_frame), \
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \
     .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \
                                                    AV_SAMPLE_FMT_NONE }, \
diff --git a/libavcodec/dsicinaudio.c b/libavcodec/dsicinaudio.c
index 231afb2a69..2cfaebca40 100644
--- a/libavcodec/dsicinaudio.c
+++ b/libavcodec/dsicinaudio.c
@@ -128,7 +128,7 @@  const FFCodec ff_dsicinaudio_decoder = {
     .p.id           = AV_CODEC_ID_DSICINAUDIO,
     .priv_data_size = sizeof(CinAudioContext),
     .init           = cinaudio_decode_init,
-    .decode         = cinaudio_decode_frame,
+    FF_CODEC_DECODE_CB(cinaudio_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c
index b33959ef77..71f6071412 100644
--- a/libavcodec/dsicinvideo.c
+++ b/libavcodec/dsicinvideo.c
@@ -329,7 +329,7 @@  const FFCodec ff_dsicinvideo_decoder = {
     .priv_data_size = sizeof(CinVideoContext),
     .init           = cinvideo_decode_init,
     .close          = cinvideo_decode_end,
-    .decode         = cinvideo_decode_frame,
+    FF_CODEC_DECODE_CB(cinvideo_decode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.capabilities = AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/dss_sp.c b/libavcodec/dss_sp.c
index 4d7a169f26..b465bfe932 100644
--- a/libavcodec/dss_sp.c
+++ b/libavcodec/dss_sp.c
@@ -779,7 +779,7 @@  const FFCodec ff_dss_sp_decoder = {
     .p.id           = AV_CODEC_ID_DSS_SP,
     .priv_data_size = sizeof(DssSpContext),
     .init           = dss_sp_decode_init,
-    .decode         = dss_sp_decode_frame,
+    FF_CODEC_DECODE_CB(dss_sp_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dstdec.c b/libavcodec/dstdec.c
index e1d06a9c36..93642e34b9 100644
--- a/libavcodec/dstdec.c
+++ b/libavcodec/dstdec.c
@@ -386,7 +386,7 @@  const FFCodec ff_dst_decoder = {
     .p.id           = AV_CODEC_ID_DST,
     .priv_data_size = sizeof(DSTContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/dvaudiodec.c b/libavcodec/dvaudiodec.c
index 97851981c5..56d9c3573b 100644
--- a/libavcodec/dvaudiodec.c
+++ b/libavcodec/dvaudiodec.c
@@ -124,7 +124,7 @@  const FFCodec ff_dvaudio_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_DVAUDIO,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(DVAudioContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c
index c5391ea5ad..58e18cfece 100644
--- a/libavcodec/dvbsubdec.c
+++ b/libavcodec/dvbsubdec.c
@@ -1746,7 +1746,7 @@  const FFCodec ff_dvbsub_decoder = {
     .priv_data_size = sizeof(DVBSubContext),
     .init           = dvbsub_init_decoder,
     .close          = dvbsub_close_decoder,
-    .decode_sub     = dvbsub_decode,
+    FF_CODEC_DECODE_SUB_CB(dvbsub_decode),
     .p.priv_class   = &dvbsubdec_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/dvbsubenc.c b/libavcodec/dvbsubenc.c
index 5444dbfa99..06087b058d 100644
--- a/libavcodec/dvbsubenc.c
+++ b/libavcodec/dvbsubenc.c
@@ -512,5 +512,5 @@  const FFCodec ff_dvbsub_encoder = {
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_DVB_SUBTITLE,
     .priv_data_size = sizeof(DVBSubtitleContext),
-    .encode_sub     = dvbsub_encode,
+    FF_CODEC_ENCODE_SUB_CB(dvbsub_encode),
 };
diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c
index 5a1de7a409..a0bae6f57e 100644
--- a/libavcodec/dvdec.c
+++ b/libavcodec/dvdec.c
@@ -688,7 +688,7 @@  const FFCodec ff_dvvideo_decoder = {
     .p.id           = AV_CODEC_ID_DVVIDEO,
     .priv_data_size = sizeof(DVVideoContext),
     .init           = dvvideo_decode_init,
-    .decode         = dvvideo_decode_frame,
+    FF_CODEC_DECODE_CB(dvvideo_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS,
     .p.max_lowres   = 3,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c
index 713170cdc2..2951e74736 100644
--- a/libavcodec/dvdsubdec.c
+++ b/libavcodec/dvdsubdec.c
@@ -760,7 +760,7 @@  const FFCodec ff_dvdsub_decoder = {
     .p.id           = AV_CODEC_ID_DVD_SUBTITLE,
     .priv_data_size = sizeof(DVDSubContext),
     .init           = dvdsub_init,
-    .decode_sub     = dvdsub_decode,
+    FF_CODEC_DECODE_SUB_CB(dvdsub_decode),
     .flush          = dvdsub_flush,
     .p.priv_class   = &dvdsub_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c
index d6960e5f70..fc3b7d1816 100644
--- a/libavcodec/dvdsubenc.c
+++ b/libavcodec/dvdsubenc.c
@@ -500,7 +500,7 @@  const FFCodec ff_dvdsub_encoder = {
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_DVD_SUBTITLE,
     .init           = dvdsub_init,
-    .encode_sub     = dvdsub_encode,
+    FF_CODEC_ENCODE_SUB_CB(dvdsub_encode),
     .p.priv_class   = &dvdsubenc_class,
     .priv_data_size = sizeof(DVDSubtitleContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c
index 2a760465e5..2922829dc5 100644
--- a/libavcodec/dvenc.c
+++ b/libavcodec/dvenc.c
@@ -1215,7 +1215,7 @@  const FFCodec ff_dvvideo_encoder = {
                       AV_CODEC_CAP_SLICE_THREADS,
     .priv_data_size = sizeof(DVVideoContext),
     .init           = dvvideo_encode_init,
-    .encode2        = dvvideo_encode_frame,
+    FF_CODEC_ENCODE_CB(dvvideo_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P,
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
diff --git a/libavcodec/dxa.c b/libavcodec/dxa.c
index 1a383f182e..93a1724743 100644
--- a/libavcodec/dxa.c
+++ b/libavcodec/dxa.c
@@ -369,7 +369,7 @@  const FFCodec ff_dxa_decoder = {
     .priv_data_size = sizeof(DxaDecContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c
index e7aaee7cb6..b7dfff4755 100644
--- a/libavcodec/dxtory.c
+++ b/libavcodec/dxtory.c
@@ -875,6 +875,6 @@  const FFCodec ff_dxtory_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("Dxtory"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DXTORY,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
 };
diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c
index 63fec7a14e..d75f8b0402 100644
--- a/libavcodec/dxv.c
+++ b/libavcodec/dxv.c
@@ -1266,7 +1266,7 @@  const FFCodec ff_dxv_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DXV,
     .init           = dxv_init,
-    .decode         = dxv_decode,
+    FF_CODEC_DECODE_CB(dxv_decode),
     .close          = dxv_close,
     .priv_data_size = sizeof(DXVContext),
     .p.capabilities = AV_CODEC_CAP_DR1 |
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index 5c19d70266..79611cee0c 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -258,7 +258,7 @@  const FFCodec ff_eac3_encoder = {
     .p.capabilities  = AV_CODEC_CAP_DR1,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ff_ac3_float_encode_init,
-    .encode2         = ff_ac3_float_encode_frame,
+    FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame),
     .close           = ff_ac3_encode_close,
     .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/eacmv.c b/libavcodec/eacmv.c
index bd332a9106..0a13a74bb8 100644
--- a/libavcodec/eacmv.c
+++ b/libavcodec/eacmv.c
@@ -237,7 +237,7 @@  const FFCodec ff_eacmv_decoder = {
     .priv_data_size = sizeof(CmvContext),
     .init           = cmv_decode_init,
     .close          = cmv_decode_end,
-    .decode         = cmv_decode_frame,
+    FF_CODEC_DECODE_CB(cmv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c
index e6e90d6bd7..337a9c144a 100644
--- a/libavcodec/eamad.c
+++ b/libavcodec/eamad.c
@@ -348,7 +348,7 @@  const FFCodec ff_eamad_decoder = {
     .priv_data_size = sizeof(MadContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c
index ea5f4386bc..2e9d2fe13c 100644
--- a/libavcodec/eatgq.c
+++ b/libavcodec/eatgq.c
@@ -253,7 +253,7 @@  const FFCodec ff_eatgq_decoder = {
     .p.id           = AV_CODEC_ID_TGQ,
     .priv_data_size = sizeof(TgqContext),
     .init           = tgq_decode_init,
-    .decode         = tgq_decode_frame,
+    FF_CODEC_DECODE_CB(tgq_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/eatgv.c b/libavcodec/eatgv.c
index 525c80a570..23cf7300c6 100644
--- a/libavcodec/eatgv.c
+++ b/libavcodec/eatgv.c
@@ -366,7 +366,7 @@  const FFCodec ff_eatgv_decoder = {
     .priv_data_size = sizeof(TgvContext),
     .init           = tgv_decode_init,
     .close          = tgv_decode_end,
-    .decode         = tgv_decode_frame,
+    FF_CODEC_DECODE_CB(tgv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c
index dad742996c..305ea4ba2c 100644
--- a/libavcodec/eatqi.c
+++ b/libavcodec/eatqi.c
@@ -189,7 +189,7 @@  const FFCodec ff_eatqi_decoder = {
     .priv_data_size = sizeof(TqiContext),
     .init           = tqi_decode_init,
     .close          = tqi_decode_end,
-    .decode         = tqi_decode_frame,
+    FF_CODEC_DECODE_CB(tqi_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 70bd8da81f..3891ebcc91 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -152,7 +152,7 @@  int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size,
         return -1;
     }
 
-    ret = ffcodec(avctx->codec)->encode_sub(avctx, buf, buf_size, sub);
+    ret = ffcodec(avctx->codec)->cb.encode_sub(avctx, buf, buf_size, sub);
     avctx->frame_number++;
     return ret;
 }
@@ -202,7 +202,7 @@  static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt)
 
     got_packet = 0;
 
-    av_assert0(codec->encode2);
+    av_assert0(codec->cb_type == FF_CODEC_CB_TYPE_ENCODE);
 
     if (CONFIG_FRAME_THREAD_ENCODER &&
         avci->frame_thread_encoder && (avctx->active_thread_type & FF_THREAD_FRAME))
@@ -212,7 +212,7 @@  static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt)
          *  no sense to use the properties of the current frame anyway). */
         ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet);
     else {
-        ret = codec->encode2(avctx, avpkt, frame, &got_packet);
+        ret = codec->cb.encode(avctx, avpkt, frame, &got_packet);
         if (avctx->codec->type == AVMEDIA_TYPE_VIDEO && !ret && got_packet &&
             !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
             avpkt->pts = avpkt->dts = frame->pts;
@@ -292,8 +292,8 @@  static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt
             return AVERROR(EINVAL);
     }
 
-    if (ffcodec(avctx->codec)->receive_packet) {
-        ret = ffcodec(avctx->codec)->receive_packet(avctx, avpkt);
+    if (ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET) {
+        ret = ffcodec(avctx->codec)->cb.receive_packet(avctx, avpkt);
         if (ret < 0)
             av_packet_unref(avpkt);
         else
diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c
index f52573107c..2fdffff13a 100644
--- a/libavcodec/escape124.c
+++ b/libavcodec/escape124.c
@@ -383,7 +383,7 @@  const FFCodec ff_escape124_decoder = {
     .priv_data_size = sizeof(Escape124Context),
     .init           = escape124_decode_init,
     .close          = escape124_decode_close,
-    .decode         = escape124_decode_frame,
+    FF_CODEC_DECODE_CB(escape124_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/escape130.c b/libavcodec/escape130.c
index ffa2274ea9..cd6dd7690b 100644
--- a/libavcodec/escape130.c
+++ b/libavcodec/escape130.c
@@ -353,7 +353,7 @@  const FFCodec ff_escape130_decoder = {
     .priv_data_size = sizeof(Escape130Context),
     .init           = escape130_decode_init,
     .close          = escape130_decode_close,
-    .decode         = escape130_decode_frame,
+    FF_CODEC_DECODE_CB(escape130_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/evrcdec.c b/libavcodec/evrcdec.c
index d3703977ba..a6475199cd 100644
--- a/libavcodec/evrcdec.c
+++ b/libavcodec/evrcdec.c
@@ -935,7 +935,7 @@  const FFCodec ff_evrc_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_EVRC,
     .init           = evrc_decode_init,
-    .decode         = evrc_decode_frame,
+    FF_CODEC_DECODE_CB(evrc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .priv_data_size = sizeof(EVRCContext),
     .p.priv_class   = &evrcdec_class,
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 88e7c01488..4af0f4f771 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -2348,7 +2348,7 @@  const FFCodec ff_exr_decoder = {
     .priv_data_size   = sizeof(EXRContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
                         AV_CODEC_CAP_SLICE_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c
index baf29f5912..459afebb82 100644
--- a/libavcodec/exrenc.c
+++ b/libavcodec/exrenc.c
@@ -543,7 +543,7 @@  const FFCodec ff_exr_encoder = {
     .p.id           = AV_CODEC_ID_EXR,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_close,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
                                                  AV_PIX_FMT_GBRPF32,
diff --git a/libavcodec/fastaudio.c b/libavcodec/fastaudio.c
index fc525e58d1..46fffaf8b8 100644
--- a/libavcodec/fastaudio.c
+++ b/libavcodec/fastaudio.c
@@ -194,7 +194,7 @@  const FFCodec ff_fastaudio_decoder = {
     .p.id           = AV_CODEC_ID_FASTAUDIO,
     .priv_data_size = sizeof(FastAudioContext),
     .init           = fastaudio_init,
-    .decode         = fastaudio_decode,
+    FF_CODEC_DECODE_CB(fastaudio_decode),
     .close          = fastaudio_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 81fa249885..365f8b77a7 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -1060,7 +1060,7 @@  const FFCodec ff_ffv1_decoder = {
     .priv_data_size = sizeof(FFV1Context),
     .init           = decode_init,
     .close          = ff_ffv1_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/ |
                       AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS,
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 13af2547a0..cee2627eed 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1284,7 +1284,7 @@  const FFCodec ff_ffv1_encoder = {
     .p.id           = AV_CODEC_ID_FFV1,
     .priv_data_size = sizeof(FFV1Context),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_close,
     .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DELAY,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
diff --git a/libavcodec/ffwavesynth.c b/libavcodec/ffwavesynth.c
index 0426386058..67e867b444 100644
--- a/libavcodec/ffwavesynth.c
+++ b/libavcodec/ffwavesynth.c
@@ -467,7 +467,7 @@  const FFCodec ff_ffwavesynth_decoder = {
     .priv_data_size = sizeof(struct wavesynth_context),
     .init           = wavesynth_init,
     .close          = wavesynth_close,
-    .decode         = wavesynth_decode,
+    FF_CODEC_DECODE_CB(wavesynth_decode),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/fic.c b/libavcodec/fic.c
index 86a5012587..e56a1a323c 100644
--- a/libavcodec/fic.c
+++ b/libavcodec/fic.c
@@ -491,7 +491,7 @@  const FFCodec ff_fic_decoder = {
     .p.id           = AV_CODEC_ID_FIC,
     .priv_data_size = sizeof(FICContext),
     .init           = fic_decode_init,
-    .decode         = fic_decode_frame,
+    FF_CODEC_DECODE_CB(fic_decode_frame),
     .close          = fic_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
     .p.priv_class   = &fic_decoder_class,
diff --git a/libavcodec/fitsdec.c b/libavcodec/fitsdec.c
index 25857a1799..b60c2bd441 100644
--- a/libavcodec/fitsdec.c
+++ b/libavcodec/fitsdec.c
@@ -329,5 +329,5 @@  const FFCodec ff_fits_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"),
     .p.priv_class   = &fits_decoder_class,
     .priv_data_size = sizeof(FITSContext),
-    .decode         = fits_decode_frame,
+    FF_CODEC_DECODE_CB(fits_decode_frame),
 };
diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c
index eebabfb621..5e9100be85 100644
--- a/libavcodec/fitsenc.c
+++ b/libavcodec/fitsenc.c
@@ -116,7 +116,7 @@  const FFCodec ff_fits_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FITS,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = fits_encode_frame,
+    FF_CODEC_ENCODE_CB(fits_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRAP16BE,
                                                      AV_PIX_FMT_GBRP16BE,
                                                      AV_PIX_FMT_GBRP,
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index 11a62daab5..a23d7e2cf1 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -665,7 +665,7 @@  const FFCodec ff_flac_decoder = {
     .priv_data_size = sizeof(FLACContext),
     .init           = flac_decode_init,
     .close          = flac_decode_close,
-    .decode         = flac_decode_frame,
+    FF_CODEC_DECODE_CB(flac_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1 |
                       AV_CODEC_CAP_FRAME_THREADS,
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 6b46664dd9..e9edd8476d 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -1467,7 +1467,7 @@  const FFCodec ff_flac_encoder = {
                       AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(FlacEncodeContext),
     .init           = flac_encode_init,
-    .encode2        = flac_encode_frame,
+    FF_CODEC_ENCODE_CB(flac_encode_frame),
     .close          = flac_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_S32,
diff --git a/libavcodec/flashsv.c b/libavcodec/flashsv.c
index 3cf01336c8..0982161d49 100644
--- a/libavcodec/flashsv.c
+++ b/libavcodec/flashsv.c
@@ -502,7 +502,7 @@  const FFCodec ff_flashsv_decoder = {
     .priv_data_size = sizeof(FlashSVContext),
     .init           = flashsv_decode_init,
     .close          = flashsv_decode_end,
-    .decode         = flashsv_decode_frame,
+    FF_CODEC_DECODE_CB(flashsv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
@@ -569,7 +569,7 @@  const FFCodec ff_flashsv2_decoder = {
     .priv_data_size = sizeof(FlashSVContext),
     .init           = flashsv2_decode_init,
     .close          = flashsv2_decode_end,
-    .decode         = flashsv_decode_frame,
+    FF_CODEC_DECODE_CB(flashsv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c
index 42ae77810c..07fa9945ff 100644
--- a/libavcodec/flashsv2enc.c
+++ b/libavcodec/flashsv2enc.c
@@ -917,7 +917,7 @@  const FFCodec ff_flashsv2_encoder = {
     .p.id           = AV_CODEC_ID_FLASHSV2,
     .priv_data_size = sizeof(FlashSV2Context),
     .init           = flashsv2_encode_init,
-    .encode2        = flashsv2_encode_frame,
+    FF_CODEC_ENCODE_CB(flashsv2_encode_frame),
     .close          = flashsv2_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c
index 0059ea5a46..592bb061cb 100644
--- a/libavcodec/flashsvenc.c
+++ b/libavcodec/flashsvenc.c
@@ -264,7 +264,7 @@  const FFCodec ff_flashsv_encoder = {
     .p.id           = AV_CODEC_ID_FLASHSV,
     .priv_data_size = sizeof(FlashSVContext),
     .init           = flashsv_encode_init,
-    .encode2        = flashsv_encode_frame,
+    FF_CODEC_ENCODE_CB(flashsv_encode_frame),
     .close          = flashsv_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c
index 79e50aa71d..b841050a81 100644
--- a/libavcodec/flicvideo.c
+++ b/libavcodec/flicvideo.c
@@ -1112,7 +1112,7 @@  const FFCodec ff_flic_decoder = {
     .priv_data_size = sizeof(FlicDecodeContext),
     .init           = flic_decode_init,
     .close          = flic_decode_end,
-    .decode         = flic_decode_frame,
+    FF_CODEC_DECODE_CB(flic_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c
index 096f82fa88..cc016d129d 100644
--- a/libavcodec/flvdec.c
+++ b/libavcodec/flvdec.c
@@ -121,7 +121,7 @@  const FFCodec ff_flv_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_h263_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c
index 1796c8a698..74ed321e27 100644
--- a/libavcodec/flvenc.c
+++ b/libavcodec/flvenc.c
@@ -100,7 +100,7 @@  const FFCodec ff_flv_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/fmvc.c b/libavcodec/fmvc.c
index 0dc918bc8c..4abf6d7048 100644
--- a/libavcodec/fmvc.c
+++ b/libavcodec/fmvc.c
@@ -634,7 +634,7 @@  const FFCodec ff_fmvc_decoder = {
     .priv_data_size   = sizeof(FMVCContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c
index c6528dd804..07d310a986 100644
--- a/libavcodec/frame_thread_encoder.c
+++ b/libavcodec/frame_thread_encoder.c
@@ -104,7 +104,7 @@  static void * attribute_align_arg worker(void *v){
         frame = task->indata;
         pkt   = task->outdata;
 
-        ret = ffcodec(avctx->codec)->encode2(avctx, pkt, frame, &got_packet);
+        ret = ffcodec(avctx->codec)->cb.encode(avctx, pkt, frame, &got_packet);
         if(got_packet) {
             int ret2 = av_packet_make_refcounted(pkt);
             if (ret >= 0 && ret2 < 0)
diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c
index 82851e74de..7f695305f1 100644
--- a/libavcodec/fraps.c
+++ b/libavcodec/fraps.c
@@ -347,7 +347,7 @@  const FFCodec ff_fraps_decoder = {
     .priv_data_size = sizeof(FrapsContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/frwu.c b/libavcodec/frwu.c
index 6ec88808df..766fda7455 100644
--- a/libavcodec/frwu.c
+++ b/libavcodec/frwu.c
@@ -122,7 +122,7 @@  const FFCodec ff_frwu_decoder = {
     .p.id           = AV_CODEC_ID_FRWU,
     .priv_data_size = sizeof(FRWUContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.priv_class   = &frwu_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c
index 72368d9f4f..00964369c5 100644
--- a/libavcodec/g2meet.c
+++ b/libavcodec/g2meet.c
@@ -1630,7 +1630,7 @@  const FFCodec ff_g2m_decoder = {
     .priv_data_size = sizeof(G2MContext),
     .init           = g2m_decode_init,
     .close          = g2m_decode_end,
-    .decode         = g2m_decode_frame,
+    FF_CODEC_DECODE_CB(g2m_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/g722dec.c b/libavcodec/g722dec.c
index e7e846b264..8a02ec5230 100644
--- a/libavcodec/g722dec.c
+++ b/libavcodec/g722dec.c
@@ -146,7 +146,7 @@  const FFCodec ff_adpcm_g722_decoder = {
     .p.id           = AV_CODEC_ID_ADPCM_G722,
     .priv_data_size = sizeof(G722Context),
     .init           = g722_decode_init,
-    .decode         = g722_decode_frame,
+    FF_CODEC_DECODE_CB(g722_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.priv_class   = &g722_decoder_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c
index ca6bd46532..325c3927d1 100644
--- a/libavcodec/g722enc.c
+++ b/libavcodec/g722enc.c
@@ -380,7 +380,7 @@  const FFCodec ff_adpcm_g722_encoder = {
     .priv_data_size  = sizeof(G722Context),
     .init            = g722_encode_init,
     .close           = g722_encode_close,
-    .encode2         = g722_encode_frame,
+    FF_CODEC_ENCODE_CB(g722_encode_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, 0 },
diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c
index b025cb2b8e..d095f09fe5 100644
--- a/libavcodec/g723_1dec.c
+++ b/libavcodec/g723_1dec.c
@@ -1118,7 +1118,7 @@  const FFCodec ff_g723_1_decoder = {
     .p.id           = AV_CODEC_ID_G723_1,
     .priv_data_size = sizeof(G723_1_Context),
     .init           = g723_1_decode_init,
-    .decode         = g723_1_decode_frame,
+    FF_CODEC_DECODE_CB(g723_1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .p.priv_class   = &g723_1dec_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c
index 60066ec305..e8fb8429c1 100644
--- a/libavcodec/g723_1enc.c
+++ b/libavcodec/g723_1enc.c
@@ -1246,7 +1246,7 @@  const FFCodec ff_g723_1_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(G723_1_Context),
     .init           = g723_1_encode_init,
-    .encode2        = g723_1_encode_frame,
+    FF_CODEC_ENCODE_CB(g723_1_encode_frame),
     .defaults       = defaults,
     .p.sample_fmts  = (const enum AVSampleFormat[]) {
         AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE
diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index 0e19a2a8fc..3bf0da3949 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -408,7 +408,7 @@  const FFCodec ff_adpcm_g726_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_encode_init,
-    .encode2        = g726_encode_frame,
+    FF_CODEC_ENCODE_CB(g726_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
     .p.priv_class   = &g726_class,
@@ -426,7 +426,7 @@  const FFCodec ff_adpcm_g726le_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_encode_init,
-    .encode2        = g726_encode_frame,
+    FF_CODEC_ENCODE_CB(g726_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
     .p.priv_class   = &g726_class,
@@ -509,7 +509,7 @@  const FFCodec ff_adpcm_g726_decoder = {
     .p.id           = AV_CODEC_ID_ADPCM_G726,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_decode_init,
-    .decode         = g726_decode_frame,
+    FF_CODEC_DECODE_CB(g726_decode_frame),
     .flush          = g726_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -523,7 +523,7 @@  const FFCodec ff_adpcm_g726le_decoder = {
     .p.id           = AV_CODEC_ID_ADPCM_G726LE,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_decode_init,
-    .decode         = g726_decode_frame,
+    FF_CODEC_DECODE_CB(g726_decode_frame),
     .flush          = g726_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.long_name    = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"),
diff --git a/libavcodec/g729dec.c b/libavcodec/g729dec.c
index 0d54f555bd..a306456f0a 100644
--- a/libavcodec/g729dec.c
+++ b/libavcodec/g729dec.c
@@ -759,7 +759,7 @@  const FFCodec ff_g729_decoder = {
     .p.id           = AV_CODEC_ID_G729,
     .priv_data_size = sizeof(G729Context),
     .init           = decoder_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -772,7 +772,7 @@  const FFCodec ff_acelp_kelvin_decoder = {
     .p.id           = AV_CODEC_ID_ACELP_KELVIN,
     .priv_data_size = sizeof(G729Context),
     .init           = decoder_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c
index d4c763cffb..70c2ad4bd1 100644
--- a/libavcodec/gdv.c
+++ b/libavcodec/gdv.c
@@ -568,7 +568,7 @@  const FFCodec ff_gdv_decoder = {
     .priv_data_size = sizeof(GDVContext),
     .init           = gdv_decode_init,
     .close          = gdv_decode_close,
-    .decode         = gdv_decode_frame,
+    FF_CODEC_DECODE_CB(gdv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c
index 0844f8cfb3..0d6acd5303 100644
--- a/libavcodec/gemdec.c
+++ b/libavcodec/gemdec.c
@@ -356,6 +356,6 @@  const FFCodec ff_gem_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_GEM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = gem_decode_frame,
+    FF_CODEC_DECODE_CB(gem_decode_frame),
     .close          = gem_close,
 };
diff --git a/libavcodec/gif.c b/libavcodec/gif.c
index a22cae1f0b..8c52c865a4 100644
--- a/libavcodec/gif.c
+++ b/libavcodec/gif.c
@@ -559,7 +559,7 @@  const FFCodec ff_gif_encoder = {
     .p.id           = AV_CODEC_ID_GIF,
     .priv_data_size = sizeof(GIFContext),
     .init           = gif_encode_init,
-    .encode2        = gif_encode_frame,
+    FF_CODEC_ENCODE_CB(gif_encode_frame),
     .close          = gif_encode_close,
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE,
diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c
index adb8d0cec3..3936de1cd2 100644
--- a/libavcodec/gifdec.c
+++ b/libavcodec/gifdec.c
@@ -564,7 +564,7 @@  const FFCodec ff_gif_decoder = {
     .priv_data_size = sizeof(GifState),
     .init           = gif_decode_init,
     .close          = gif_decode_close,
-    .decode         = gif_decode_frame,
+    FF_CODEC_DECODE_CB(gif_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/gsmdec.c b/libavcodec/gsmdec.c
index 84852c8b11..e5b8d6f41f 100644
--- a/libavcodec/gsmdec.c
+++ b/libavcodec/gsmdec.c
@@ -120,7 +120,7 @@  const FFCodec ff_gsm_decoder = {
     .p.id           = AV_CODEC_ID_GSM,
     .priv_data_size = sizeof(GSMContext),
     .init           = gsm_init,
-    .decode         = gsm_decode_frame,
+    FF_CODEC_DECODE_CB(gsm_decode_frame),
     .flush          = gsm_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -134,7 +134,7 @@  const FFCodec ff_gsm_ms_decoder = {
     .p.id           = AV_CODEC_ID_GSM_MS,
     .priv_data_size = sizeof(GSMContext),
     .init           = gsm_init,
-    .decode         = gsm_decode_frame,
+    FF_CODEC_DECODE_CB(gsm_decode_frame),
     .flush          = gsm_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c
index a826c1ca1c..1699172767 100644
--- a/libavcodec/h261dec.c
+++ b/libavcodec/h261dec.c
@@ -688,7 +688,7 @@  const FFCodec ff_h261_decoder = {
     .priv_data_size = sizeof(H261DecContext),
     .init           = h261_decode_init,
     .close          = h261_decode_end,
-    .decode         = h261_decode_frame,
+    FF_CODEC_DECODE_CB(h261_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .p.max_lowres   = 3,
diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index f18f58b107..007bb4aa30 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -408,7 +408,7 @@  const FFCodec ff_h261_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(H261EncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 731f442b01..1f9f3e5e95 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -762,7 +762,7 @@  const FFCodec ff_h263_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_h263_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                       AV_CODEC_CAP_TRUNCATED |
@@ -784,7 +784,7 @@  const FFCodec ff_h263p_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_h263_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                       AV_CODEC_CAP_TRUNCATED |
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 1dbf136934..d80bc6b17f 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -1070,7 +1070,7 @@  const FFCodec ff_h264_decoder = {
     .priv_data_size        = sizeof(H264Context),
     .init                  = h264_decode_init,
     .close                 = h264_decode_end,
-    .decode                = h264_decode_frame,
+    FF_CODEC_DECODE_CB(h264_decode_frame),
     .p.capabilities        = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 |
                              AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
                              AV_CODEC_CAP_FRAME_THREADS,
diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c
index 1a0472d432..7db3f5fd76 100644
--- a/libavcodec/hapdec.c
+++ b/libavcodec/hapdec.c
@@ -478,7 +478,7 @@  const FFCodec ff_hap_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HAP,
     .init           = hap_init,
-    .decode         = hap_decode,
+    FF_CODEC_DECODE_CB(hap_decode),
     .close          = hap_close,
     .priv_data_size = sizeof(HapContext),
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS |
diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c
index ee03fef449..f3964896d5 100644
--- a/libavcodec/hapenc.c
+++ b/libavcodec/hapenc.c
@@ -357,7 +357,7 @@  const FFCodec ff_hap_encoder = {
     .priv_data_size = sizeof(HapContext),
     .p.priv_class   = &hapenc_class,
     .init           = hap_init,
-    .encode2        = hap_encode,
+    FF_CODEC_ENCODE_CB(hap_encode),
     .close          = hap_close,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE,
diff --git a/libavcodec/hcadec.c b/libavcodec/hcadec.c
index 8539c772d8..4e84942bb9 100644
--- a/libavcodec/hcadec.c
+++ b/libavcodec/hcadec.c
@@ -452,7 +452,7 @@  const FFCodec ff_hca_decoder = {
     .p.id           = AV_CODEC_ID_HCA,
     .priv_data_size = sizeof(HCAContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/hcom.c b/libavcodec/hcom.c
index 4d55360294..74a13e0044 100644
--- a/libavcodec/hcom.c
+++ b/libavcodec/hcom.c
@@ -142,7 +142,7 @@  const FFCodec ff_hcom_decoder = {
     .priv_data_size = sizeof(HCOMContext),
     .init           = hcom_init,
     .close          = hcom_close,
-    .decode         = hcom_decode,
+    FF_CODEC_DECODE_CB(hcom_decode),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 9c2958b643..f782ea6394 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -3884,7 +3884,7 @@  const FFCodec ff_hevc_decoder = {
     .p.priv_class          = &hevc_decoder_class,
     .init                  = hevc_decode_init,
     .close                 = hevc_decode_free,
-    .decode                = hevc_decode_frame,
+    FF_CODEC_DECODE_CB(hevc_decode_frame),
     .flush                 = hevc_decode_flush,
     .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
diff --git a/libavcodec/hnm4video.c b/libavcodec/hnm4video.c
index deba534766..9eb9f3a694 100644
--- a/libavcodec/hnm4video.c
+++ b/libavcodec/hnm4video.c
@@ -505,7 +505,7 @@  const FFCodec ff_hnm4_video_decoder = {
     .priv_data_size = sizeof(Hnm4VideoContext),
     .init           = hnm_decode_init,
     .close          = hnm_decode_end,
-    .decode         = hnm_decode_frame,
+    FF_CODEC_DECODE_CB(hnm_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c
index a53b4641a0..cea2475bb8 100644
--- a/libavcodec/hq_hqa.c
+++ b/libavcodec/hq_hqa.c
@@ -388,7 +388,7 @@  const FFCodec ff_hq_hqa_decoder = {
     .p.id           = AV_CODEC_ID_HQ_HQA,
     .priv_data_size = sizeof(HQContext),
     .init           = hq_hqa_decode_init,
-    .decode         = hq_hqa_decode_frame,
+    FF_CODEC_DECODE_CB(hq_hqa_decode_frame),
     .close          = hq_hqa_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c
index 8c7fc9b1ec..c41fe61387 100644
--- a/libavcodec/hqx.c
+++ b/libavcodec/hqx.c
@@ -541,7 +541,7 @@  const FFCodec ff_hqx_decoder = {
     .p.id           = AV_CODEC_ID_HQX,
     .priv_data_size = sizeof(HQXContext),
     .init           = hqx_decode_init,
-    .decode         = hqx_decode_frame,
+    FF_CODEC_DECODE_CB(hqx_decode_frame),
     .close          = hqx_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
                       AV_CODEC_CAP_FRAME_THREADS,
diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c
index d98156e26d..07fa11e37a 100644
--- a/libavcodec/huffyuvdec.c
+++ b/libavcodec/huffyuvdec.c
@@ -1270,7 +1270,7 @@  const FFCodec ff_huffyuv_decoder = {
     .priv_data_size   = sizeof(HYuvContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                         AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
@@ -1285,7 +1285,7 @@  const FFCodec ff_ffvhuff_decoder = {
     .priv_data_size   = sizeof(HYuvContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                         AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
@@ -1301,7 +1301,7 @@  const FFCodec ff_hymt_decoder = {
     .priv_data_size   = sizeof(HYuvContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                         AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c
index a19cf7efdc..195d45c911 100644
--- a/libavcodec/huffyuvenc.c
+++ b/libavcodec/huffyuvenc.c
@@ -1056,7 +1056,7 @@  const FFCodec ff_huffyuv_encoder = {
     .p.id           = AV_CODEC_ID_HUFFYUV,
     .priv_data_size = sizeof(HYuvContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.priv_class   = &normal_class,
@@ -1076,7 +1076,7 @@  const FFCodec ff_ffvhuff_encoder = {
     .p.id           = AV_CODEC_ID_FFVHUFF,
     .priv_data_size = sizeof(HYuvContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.priv_class   = &ff_class,
diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c
index 1a3792be0e..ecd4ab2fee 100644
--- a/libavcodec/idcinvideo.c
+++ b/libavcodec/idcinvideo.c
@@ -248,7 +248,7 @@  const FFCodec ff_idcin_decoder = {
     .p.id           = AV_CODEC_ID_IDCIN,
     .priv_data_size = sizeof(IdcinContext),
     .init           = idcin_decode_init,
-    .decode         = idcin_decode_frame,
+    FF_CODEC_DECODE_CB(idcin_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .defaults       = idcin_defaults,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/iff.c b/libavcodec/iff.c
index 184e3b865e..36c9535d54 100644
--- a/libavcodec/iff.c
+++ b/libavcodec/iff.c
@@ -1917,7 +1917,7 @@  const FFCodec ff_iff_ilbm_decoder = {
     .priv_data_size = sizeof(IffContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/ilbcdec.c b/libavcodec/ilbcdec.c
index 182a014d11..62a9ad19bf 100644
--- a/libavcodec/ilbcdec.c
+++ b/libavcodec/ilbcdec.c
@@ -1484,7 +1484,7 @@  const FFCodec ff_ilbc_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ILBC,
     .init           = ilbc_decode_init,
-    .decode         = ilbc_decode_frame,
+    FF_CODEC_DECODE_CB(ilbc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .priv_data_size = sizeof(ILBCContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/imc.c b/libavcodec/imc.c
index 7b0e9d3b55..ee12cd913f 100644
--- a/libavcodec/imc.c
+++ b/libavcodec/imc.c
@@ -1092,7 +1092,7 @@  const FFCodec ff_imc_decoder = {
     .priv_data_size = sizeof(IMCContext),
     .init           = imc_decode_init,
     .close          = imc_decode_close,
-    .decode         = imc_decode_frame,
+    FF_CODEC_DECODE_CB(imc_decode_frame),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
@@ -1109,7 +1109,7 @@  const FFCodec ff_iac_decoder = {
     .priv_data_size = sizeof(IMCContext),
     .init           = imc_decode_init,
     .close          = imc_decode_close,
-    .decode         = imc_decode_frame,
+    FF_CODEC_DECODE_CB(imc_decode_frame),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/imm4.c b/libavcodec/imm4.c
index d531bbdc3d..d826818864 100644
--- a/libavcodec/imm4.c
+++ b/libavcodec/imm4.c
@@ -540,7 +540,7 @@  const FFCodec ff_imm4_decoder = {
     .priv_data_size   = sizeof(IMM4Context),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush            = decode_flush,
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/imm5.c b/libavcodec/imm5.c
index eb30cc5509..9b7ac17aa5 100644
--- a/libavcodec/imm5.c
+++ b/libavcodec/imm5.c
@@ -183,7 +183,7 @@  const FFCodec ff_imm5_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_IMM5,
     .init           = imm5_init,
-    .decode         = imm5_decode_frame,
+    FF_CODEC_DECODE_CB(imm5_decode_frame),
     .close          = imm5_close,
     .flush          = imm5_flush,
     .priv_data_size = sizeof(IMM5Context),
diff --git a/libavcodec/imx.c b/libavcodec/imx.c
index 0d8924bf45..4ee6006860 100644
--- a/libavcodec/imx.c
+++ b/libavcodec/imx.c
@@ -187,7 +187,7 @@  const FFCodec ff_simbiosis_imx_decoder = {
     .p.id           = AV_CODEC_ID_SIMBIOSIS_IMX,
     .priv_data_size = sizeof(SimbiosisIMXContext),
     .init           = imx_decode_init,
-    .decode         = imx_decode_frame,
+    FF_CODEC_DECODE_CB(imx_decode_frame),
     .close          = imx_decode_close,
     .flush          = imx_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c
index 8b47b59f79..79028975e5 100644
--- a/libavcodec/indeo2.c
+++ b/libavcodec/indeo2.c
@@ -267,7 +267,7 @@  const FFCodec ff_indeo2_decoder = {
     .priv_data_size = sizeof(Ir2Context),
     .init           = ir2_decode_init,
     .close          = ir2_decode_end,
-    .decode         = ir2_decode_frame,
+    FF_CODEC_DECODE_CB(ir2_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c
index 753f1b2560..43669f46b5 100644
--- a/libavcodec/indeo3.c
+++ b/libavcodec/indeo3.c
@@ -1141,7 +1141,7 @@  const FFCodec ff_indeo3_decoder = {
     .priv_data_size = sizeof(Indeo3DecodeContext),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
index 833be98514..f0cdff0e2f 100644
--- a/libavcodec/indeo4.c
+++ b/libavcodec/indeo4.c
@@ -711,7 +711,7 @@  const FFCodec ff_indeo4_decoder = {
     .priv_data_size = sizeof(IVI45DecContext),
     .init           = decode_init,
     .close          = ff_ivi_decode_close,
-    .decode         = ff_ivi_decode_frame,
+    FF_CODEC_DECODE_CB(ff_ivi_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c
index 9a77cb9fba..aff1102211 100644
--- a/libavcodec/indeo5.c
+++ b/libavcodec/indeo5.c
@@ -691,7 +691,7 @@  const FFCodec ff_indeo5_decoder = {
     .priv_data_size = sizeof(IVI45DecContext),
     .init           = decode_init,
     .close          = ff_ivi_decode_close,
-    .decode         = ff_ivi_decode_frame,
+    FF_CODEC_DECODE_CB(ff_ivi_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c
index ddac619b8f..e7e821d3b3 100644
--- a/libavcodec/intelh263dec.c
+++ b/libavcodec/intelh263dec.c
@@ -137,7 +137,7 @@  const FFCodec ff_h263i_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_h263_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
diff --git a/libavcodec/interplayacm.c b/libavcodec/interplayacm.c
index f669d6cd31..3c482e4c88 100644
--- a/libavcodec/interplayacm.c
+++ b/libavcodec/interplayacm.c
@@ -639,7 +639,7 @@  const FFCodec ff_interplay_acm_decoder = {
     .p.id           = AV_CODEC_ID_INTERPLAY_ACM,
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(InterplayACMContext),
diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c
index ff0efc127c..fe2a9e1e6b 100644
--- a/libavcodec/interplayvideo.c
+++ b/libavcodec/interplayvideo.c
@@ -1364,7 +1364,7 @@  const FFCodec ff_interplay_video_decoder = {
     .priv_data_size = sizeof(IpvideoContext),
     .init           = ipvideo_decode_init,
     .close          = ipvideo_decode_end,
-    .decode         = ipvideo_decode_frame,
+    FF_CODEC_DECODE_CB(ipvideo_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c
index db7cdf1fcb..e99ebfe076 100644
--- a/libavcodec/ituh263enc.c
+++ b/libavcodec/ituh263enc.c
@@ -911,7 +911,7 @@  const FFCodec ff_h263_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
 };
 
@@ -947,6 +947,6 @@  const FFCodec ff_h263p_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
 };
diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index 0658b056cb..0b761d0b00 100644
--- a/libavcodec/j2kenc.c
+++ b/libavcodec/j2kenc.c
@@ -1839,7 +1839,7 @@  const FFCodec ff_jpeg2000_encoder = {
     .p.id           = AV_CODEC_ID_JPEG2000,
     .priv_data_size = sizeof(Jpeg2000EncoderContext),
     .init           = j2kenc_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = j2kenc_destroy,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8,
diff --git a/libavcodec/jacosubdec.c b/libavcodec/jacosubdec.c
index 0d8e601b28..245ae22221 100644
--- a/libavcodec/jacosubdec.c
+++ b/libavcodec/jacosubdec.c
@@ -199,7 +199,7 @@  const FFCodec ff_jacosub_decoder = {
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_JACOSUB,
     .init           = ff_ass_subtitle_header_default,
-    .decode_sub     = jacosub_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(jacosub_decode_frame),
     .flush          = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c
index 23f4cb768b..92966b11f5 100644
--- a/libavcodec/jpeg2000dec.c
+++ b/libavcodec/jpeg2000dec.c
@@ -2578,7 +2578,7 @@  const FFCodec ff_jpeg2000_decoder = {
     .p.capabilities   = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1,
     .priv_data_size   = sizeof(Jpeg2000DecoderContext),
     .init             = jpeg2000_decode_init,
-    .decode           = jpeg2000_decode_frame,
+    FF_CODEC_DECODE_CB(jpeg2000_decode_frame),
     .p.priv_class     = &jpeg2000_class,
     .p.max_lowres     = 5,
     .p.profiles       = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles),
diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c
index 4c747b3919..399837cf2f 100644
--- a/libavcodec/jpeglsdec.c
+++ b/libavcodec/jpeglsdec.c
@@ -558,7 +558,7 @@  const FFCodec ff_jpegls_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
                       FF_CODEC_CAP_SETS_PKT_DTS,
diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c
index dbd7941df2..577e8a19db 100644
--- a/libavcodec/jpeglsenc.c
+++ b/libavcodec/jpeglsenc.c
@@ -482,7 +482,7 @@  const FFCodec ff_jpegls_encoder = {
     .priv_data_size = sizeof(JPEGLSContext),
     .p.priv_class   = &jpegls_class,
     .init           = encode_jpegls_init,
-    .encode2        = encode_picture_ls,
+    FF_CODEC_ENCODE_CB(encode_picture_ls),
     .close          = encode_jpegls_close,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24,
diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c
index 805ff9dda5..06015ba59d 100644
--- a/libavcodec/jvdec.c
+++ b/libavcodec/jvdec.c
@@ -242,7 +242,7 @@  const FFCodec ff_jv_decoder = {
     .priv_data_size = sizeof(JvContext),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/kgv1dec.c b/libavcodec/kgv1dec.c
index 83dbc8291f..08e92c7107 100644
--- a/libavcodec/kgv1dec.c
+++ b/libavcodec/kgv1dec.c
@@ -184,7 +184,7 @@  const FFCodec ff_kgv1_decoder = {
     .priv_data_size = sizeof(KgvContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c
index f031d37b7f..a009ba0ce2 100644
--- a/libavcodec/kmvc.c
+++ b/libavcodec/kmvc.c
@@ -411,7 +411,7 @@  const FFCodec ff_kmvc_decoder = {
     .p.id           = AV_CODEC_ID_KMVC,
     .priv_data_size = sizeof(KmvcContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c
index 2276616bb8..3aeb1c8a99 100644
--- a/libavcodec/lagarith.c
+++ b/libavcodec/lagarith.c
@@ -732,7 +732,7 @@  const FFCodec ff_lagarith_decoder = {
     .p.id           = AV_CODEC_ID_LAGARITH,
     .priv_data_size = sizeof(LagarithContext),
     .init           = lag_decode_init,
-    .decode         = lag_decode_frame,
+    FF_CODEC_DECODE_CB(lag_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c
index 6285e71d6e..ffa2fe5a6d 100644
--- a/libavcodec/lcldec.c
+++ b/libavcodec/lcldec.c
@@ -639,7 +639,7 @@  const FFCodec ff_mszh_decoder = {
     .priv_data_size = sizeof(LclDecContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
 #endif
@@ -654,7 +654,7 @@  const FFCodec ff_zlib_decoder = {
     .priv_data_size = sizeof(LclDecContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
 #endif
diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c
index 4389dcebf3..bd42c155aa 100644
--- a/libavcodec/lclenc.c
+++ b/libavcodec/lclenc.c
@@ -158,7 +158,7 @@  const FFCodec ff_zlib_encoder = {
     .p.id           = AV_CODEC_ID_ZLIB,
     .priv_data_size = sizeof(LclEncContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c
index a083487c33..52a8bf19e2 100644
--- a/libavcodec/libaomdec.c
+++ b/libavcodec/libaomdec.c
@@ -256,7 +256,7 @@  const FFCodec ff_libaom_av1_decoder = {
     .priv_data_size = sizeof(AV1DecodeContext),
     .init           = av1_init,
     .close          = aom_free,
-    .decode         = aom_decode,
+    FF_CODEC_DECODE_CB(aom_decode),
     .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 7dbb6f6f39..054903e6e2 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -1353,7 +1353,7 @@  FFCodec ff_libaom_av1_encoder = {
     .p.wrapper_name = "libaom",
     .priv_data_size = sizeof(AOMContext),
     .init           = av1_init,
-    .encode2        = aom_encode,
+    FF_CODEC_ENCODE_CB(aom_encode),
     .close          = aom_free,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .defaults       = defaults,
diff --git a/libavcodec/libaribb24.c b/libavcodec/libaribb24.c
index ab7e0e02d5..e1a26e5659 100644
--- a/libavcodec/libaribb24.c
+++ b/libavcodec/libaribb24.c
@@ -391,6 +391,6 @@  const FFCodec ff_libaribb24_decoder = {
     .priv_data_size = sizeof(Libaribb24Context),
     .init      = libaribb24_init,
     .close     = libaribb24_close,
-    .decode_sub = libaribb24_decode,
+    FF_CODEC_DECODE_SUB_CB(libaribb24_decode),
     .flush     = libaribb24_flush,
 };
diff --git a/libavcodec/libcelt_dec.c b/libavcodec/libcelt_dec.c
index b5fc391731..d659d80ed2 100644
--- a/libavcodec/libcelt_dec.c
+++ b/libavcodec/libcelt_dec.c
@@ -137,5 +137,5 @@  const FFCodec ff_libcelt_decoder = {
     .priv_data_size = sizeof(struct libcelt_context),
     .init           = libcelt_dec_init,
     .close          = libcelt_dec_close,
-    .decode         = libcelt_dec_decode,
+    FF_CODEC_DECODE_CB(libcelt_dec_decode),
 };
diff --git a/libavcodec/libcodec2.c b/libavcodec/libcodec2.c
index 2cfa1542e4..9064b823ee 100644
--- a/libavcodec/libcodec2.c
+++ b/libavcodec/libcodec2.c
@@ -188,7 +188,7 @@  const FFCodec ff_libcodec2_decoder = {
     .priv_data_size         = sizeof(LibCodec2Context),
     .init                   = libcodec2_init_decoder,
     .close                  = libcodec2_close,
-    .decode                 = libcodec2_decode,
+    FF_CODEC_DECODE_CB(libcodec2_decode),
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts      = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 },
 #endif
@@ -207,7 +207,7 @@  const FFCodec ff_libcodec2_encoder = {
     .priv_data_size         = sizeof(LibCodec2Context),
     .init                   = libcodec2_init_encoder,
     .close                  = libcodec2_close,
-    .encode2                = libcodec2_encode,
+    FF_CODEC_ENCODE_CB(libcodec2_encode),
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts      = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 },
 #endif
diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c
index fb3ccf169e..64014123ce 100644
--- a/libavcodec/libdav1d.c
+++ b/libavcodec/libdav1d.c
@@ -582,7 +582,7 @@  const FFCodec ff_libdav1d_decoder = {
     .init           = libdav1d_init,
     .close          = libdav1d_close,
     .flush          = libdav1d_flush,
-    .receive_frame  = libdav1d_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(libdav1d_receive_frame),
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS |
                       FF_CODEC_CAP_AUTO_THREADS,
diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c
index 564f9fb7c5..a47027d300 100644
--- a/libavcodec/libdavs2.c
+++ b/libavcodec/libdavs2.c
@@ -220,7 +220,7 @@  const FFCodec ff_libdavs2_decoder = {
     .priv_data_size = sizeof(DAVS2Context),
     .init           = davs2_init,
     .close          = davs2_end,
-    .decode         = davs2_decode_frame,
+    FF_CODEC_DECODE_CB(davs2_decode_frame),
     .flush          = davs2_flush,
     .p.capabilities =  AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c
index c90324a3c8..11eee51a98 100644
--- a/libavcodec/libfdk-aacdec.c
+++ b/libavcodec/libfdk-aacdec.c
@@ -483,7 +483,7 @@  const FFCodec ff_libfdk_aac_decoder = {
     .p.id           = AV_CODEC_ID_AAC,
     .priv_data_size = sizeof(FDKAACDecContext),
     .init           = fdk_aac_decode_init,
-    .decode         = fdk_aac_decode_frame,
+    FF_CODEC_DECODE_CB(fdk_aac_decode_frame),
     .close          = fdk_aac_decode_close,
     .flush          = fdk_aac_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF
diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c
index d004ae00c3..a5697bde51 100644
--- a/libavcodec/libfdk-aacenc.c
+++ b/libavcodec/libfdk-aacenc.c
@@ -482,7 +482,7 @@  const FFCodec ff_libfdk_aac_encoder = {
     .p.id                  = AV_CODEC_ID_AAC,
     .priv_data_size        = sizeof(AACContext),
     .init                  = aac_encode_init,
-    .encode2               = aac_encode_frame,
+    FF_CODEC_ENCODE_CB(aac_encode_frame),
     .close                 = aac_encode_close,
     .p.capabilities        = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c
index 88f0a0b3d6..9c2304f7a2 100644
--- a/libavcodec/libgsmdec.c
+++ b/libavcodec/libgsmdec.c
@@ -135,7 +135,7 @@  const FFCodec ff_libgsm_decoder = {
     .priv_data_size = sizeof(LibGSMDecodeContext),
     .init           = libgsm_decode_init,
     .close          = libgsm_decode_close,
-    .decode         = libgsm_decode_frame,
+    FF_CODEC_DECODE_CB(libgsm_decode_frame),
     .flush          = libgsm_flush,
 };
 #endif
@@ -150,7 +150,7 @@  const FFCodec ff_libgsm_ms_decoder = {
     .priv_data_size = sizeof(LibGSMDecodeContext),
     .init           = libgsm_decode_init,
     .close          = libgsm_decode_close,
-    .decode         = libgsm_decode_frame,
+    FF_CODEC_DECODE_CB(libgsm_decode_frame),
     .flush          = libgsm_flush,
 };
 #endif
diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c
index 7d24501b2f..a45b77be95 100644
--- a/libavcodec/libgsmenc.c
+++ b/libavcodec/libgsmenc.c
@@ -124,7 +124,7 @@  const FFCodec ff_libgsm_encoder = {
     .p.id           = AV_CODEC_ID_GSM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = libgsm_encode_init,
-    .encode2        = libgsm_encode_frame,
+    FF_CODEC_ENCODE_CB(libgsm_encode_frame),
     .close          = libgsm_encode_close,
     .defaults       = libgsm_defaults,
 #if FF_API_OLD_CHANNEL_LAYOUT
@@ -144,7 +144,7 @@  const FFCodec ff_libgsm_ms_encoder = {
     .p.id           = AV_CODEC_ID_GSM_MS,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = libgsm_encode_init,
-    .encode2        = libgsm_encode_frame,
+    FF_CODEC_ENCODE_CB(libgsm_encode_frame),
     .close          = libgsm_encode_close,
     .defaults       = libgsm_defaults,
 #if FF_API_OLD_CHANNEL_LAYOUT
diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c
index 0fecbd4bba..a7b1eaf28c 100644
--- a/libavcodec/libilbc.c
+++ b/libavcodec/libilbc.c
@@ -124,7 +124,7 @@  const FFCodec ff_libilbc_decoder = {
     .p.id           = AV_CODEC_ID_ILBC,
     .priv_data_size = sizeof(ILBCDecContext),
     .init           = ilbc_decode_init,
-    .decode         = ilbc_decode_frame,
+    FF_CODEC_DECODE_CB(ilbc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.priv_class   = &ilbc_dec_class,
 };
@@ -206,7 +206,7 @@  const FFCodec ff_libilbc_encoder = {
     .p.id           = AV_CODEC_ID_ILBC,
     .priv_data_size = sizeof(ILBCEncContext),
     .init           = ilbc_encode_init,
-    .encode2        = ilbc_encode_frame,
+    FF_CODEC_ENCODE_CB(ilbc_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
     .defaults       = ilbc_encode_defaults,
diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c
index d6de24845d..7fd0e95233 100644
--- a/libavcodec/libkvazaar.c
+++ b/libavcodec/libkvazaar.c
@@ -332,7 +332,7 @@  const FFCodec ff_libkvazaar_encoder = {
     .defaults         = defaults,
 
     .init             = libkvazaar_init,
-    .encode2          = libkvazaar_encode,
+    FF_CODEC_ENCODE_CB(libkvazaar_encode),
     .close            = libkvazaar_close,
 
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index 14f9872dd6..02a256c766 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -337,7 +337,7 @@  const FFCodec ff_libmp3lame_encoder = {
                              AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size        = sizeof(LAMEContext),
     .init                  = mp3lame_encode_init,
-    .encode2               = mp3lame_encode_frame,
+    FF_CODEC_ENCODE_CB(mp3lame_encode_frame),
     .close                 = mp3lame_encode_close,
     .p.sample_fmts         = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
                                                              AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c
index 8650296113..539f0ded3c 100644
--- a/libavcodec/libopencore-amr.c
+++ b/libavcodec/libopencore-amr.c
@@ -141,7 +141,7 @@  const FFCodec ff_libopencore_amrnb_decoder = {
     .priv_data_size = sizeof(AMRContext),
     .init           = amr_nb_decode_init,
     .close          = amr_nb_decode_close,
-    .decode         = amr_nb_decode_frame,
+    FF_CODEC_DECODE_CB(amr_nb_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
 };
 #endif /* CONFIG_LIBOPENCORE_AMRNB_DECODER */
@@ -295,7 +295,7 @@  const FFCodec ff_libopencore_amrnb_encoder = {
     .p.id           = AV_CODEC_ID_AMR_NB,
     .priv_data_size = sizeof(AMRContext),
     .init           = amr_nb_encode_init,
-    .encode2        = amr_nb_encode_frame,
+    FF_CODEC_ENCODE_CB(amr_nb_encode_frame),
     .close          = amr_nb_encode_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
@@ -382,7 +382,7 @@  const FFCodec ff_libopencore_amrwb_decoder = {
     .priv_data_size = sizeof(AMRWBContext),
     .init           = amr_wb_decode_init,
     .close          = amr_wb_decode_close,
-    .decode         = amr_wb_decode_frame,
+    FF_CODEC_DECODE_CB(amr_wb_decode_frame),
 };
 
 #endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */
diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c
index a88974cc62..b3e522c31f 100644
--- a/libavcodec/libopenh264dec.c
+++ b/libavcodec/libopenh264dec.c
@@ -163,7 +163,7 @@  const FFCodec ff_libopenh264_decoder = {
     .p.id           = AV_CODEC_ID_H264,
     .priv_data_size = sizeof(SVCContext),
     .init           = svc_decode_init,
-    .decode         = svc_decode_frame,
+    FF_CODEC_DECODE_CB(svc_decode_frame),
     .close          = svc_decode_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c
index 7b25eba5d2..f31ed2d4ca 100644
--- a/libavcodec/libopenh264enc.c
+++ b/libavcodec/libopenh264enc.c
@@ -459,7 +459,7 @@  const FFCodec ff_libopenh264_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS,
     .priv_data_size = sizeof(SVCContext),
     .init           = svc_encode_init,
-    .encode2        = svc_encode_frame,
+    FF_CODEC_ENCODE_CB(svc_encode_frame),
     .close          = svc_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
                       FF_CODEC_CAP_AUTO_THREADS,
diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c
index 1458ea3fdf..58715b43ee 100644
--- a/libavcodec/libopenjpegdec.c
+++ b/libavcodec/libopenjpegdec.c
@@ -511,5 +511,5 @@  const FFCodec ff_libopenjpeg_decoder = {
     .p.wrapper_name = "libopenjpeg",
     .priv_data_size = sizeof(LibOpenJPEGContext),
     .init           = libopenjpeg_decode_init,
-    .decode         = libopenjpeg_decode_frame,
+    FF_CODEC_DECODE_CB(libopenjpeg_decode_frame),
 };
diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c
index a07fde9a09..06338e882c 100644
--- a/libavcodec/libopenjpegenc.c
+++ b/libavcodec/libopenjpegenc.c
@@ -761,7 +761,7 @@  const FFCodec ff_libopenjpeg_encoder = {
     .p.id           = AV_CODEC_ID_JPEG2000,
     .priv_data_size = sizeof(LibOpenJPEGContext),
     .init           = libopenjpeg_encode_init,
-    .encode2        = libopenjpeg_encode_frame,
+    FF_CODEC_ENCODE_CB(libopenjpeg_encode_frame),
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48,
diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c
index dcc1599d63..316ab0f2a7 100644
--- a/libavcodec/libopusdec.c
+++ b/libavcodec/libopusdec.c
@@ -238,7 +238,7 @@  const FFCodec ff_libopus_decoder = {
     .priv_data_size = sizeof(struct libopus_context),
     .init           = libopus_decode_init,
     .close          = libopus_decode_close,
-    .decode         = libopus_decode,
+    FF_CODEC_DECODE_CB(libopus_decode),
     .flush          = libopus_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c
index 0573d59736..c884075ffe 100644
--- a/libavcodec/libopusenc.c
+++ b/libavcodec/libopusenc.c
@@ -590,7 +590,7 @@  const FFCodec ff_libopus_encoder = {
     .p.id            = AV_CODEC_ID_OPUS,
     .priv_data_size  = sizeof(LibopusEncContext),
     .init            = libopus_encode_init,
-    .encode2         = libopus_encode,
+    FF_CODEC_ENCODE_CB(libopus_encode),
     .close           = libopus_encode_close,
     .p.capabilities  = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c
index aa8c0c8860..9d811ba81c 100644
--- a/libavcodec/librav1e.c
+++ b/libavcodec/librav1e.c
@@ -620,7 +620,7 @@  const FFCodec ff_librav1e_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AV1,
     .init           = librav1e_encode_init,
-    .receive_packet = librav1e_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(librav1e_receive_packet),
     .close          = librav1e_encode_close,
     .priv_data_size = sizeof(librav1eContext),
     .p.priv_class   = &class,
diff --git a/libavcodec/librsvgdec.c b/libavcodec/librsvgdec.c
index c37fbbb0c9..6e949fe3d5 100644
--- a/libavcodec/librsvgdec.c
+++ b/libavcodec/librsvgdec.c
@@ -126,6 +126,6 @@  const FFCodec ff_librsvg_decoder = {
     .p.id           = AV_CODEC_ID_SVG,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.wrapper_name = "librsvg",
-    .decode         = librsvg_decode_frame,
+    FF_CODEC_DECODE_CB(librsvg_decode_frame),
     .priv_data_size = sizeof(LibRSVGContext),
 };
diff --git a/libavcodec/libshine.c b/libavcodec/libshine.c
index 2274c1aa32..9bc545689a 100644
--- a/libavcodec/libshine.c
+++ b/libavcodec/libshine.c
@@ -139,7 +139,7 @@  const FFCodec ff_libshine_encoder = {
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .priv_data_size        = sizeof(SHINEContext),
     .init                  = libshine_encode_init,
-    .encode2               = libshine_encode_frame,
+    FF_CODEC_ENCODE_CB(libshine_encode_frame),
     .close                 = libshine_encode_close,
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P,
                                                             AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c
index da47b271e0..8c9e05e51d 100644
--- a/libavcodec/libspeexdec.c
+++ b/libavcodec/libspeexdec.c
@@ -200,6 +200,6 @@  const FFCodec ff_libspeex_decoder = {
     .priv_data_size = sizeof(LibSpeexContext),
     .init           = libspeex_decode_init,
     .close          = libspeex_decode_close,
-    .decode         = libspeex_decode_frame,
+    FF_CODEC_DECODE_CB(libspeex_decode_frame),
     .flush          = libspeex_decode_flush,
 };
diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c
index 2c4f4caac9..ec4b3c6a8f 100644
--- a/libavcodec/libspeexenc.c
+++ b/libavcodec/libspeexenc.c
@@ -355,7 +355,7 @@  const FFCodec ff_libspeex_encoder = {
     .p.id           = AV_CODEC_ID_SPEEX,
     .priv_data_size = sizeof(LibSpeexEncContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_close,
     .p.capabilities = AV_CODEC_CAP_DELAY,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
index 6cf280377e..7db789be5e 100644
--- a/libavcodec/libsvtav1.c
+++ b/libavcodec/libsvtav1.c
@@ -614,7 +614,7 @@  const FFCodec ff_libsvtav1_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AV1,
     .init           = eb_enc_init,
-    .receive_packet = eb_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(eb_receive_packet),
     .close          = eb_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c
index af07575482..162d170b0f 100644
--- a/libavcodec/libtheoraenc.c
+++ b/libavcodec/libtheoraenc.c
@@ -377,7 +377,7 @@  const FFCodec ff_libtheora_encoder = {
     .priv_data_size = sizeof(TheoraContext),
     .init           = encode_init,
     .close          = encode_close,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE
     },
diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c
index 4320aa1b8c..1e53cf2257 100644
--- a/libavcodec/libtwolame.c
+++ b/libavcodec/libtwolame.c
@@ -216,7 +216,7 @@  const FFCodec ff_libtwolame_encoder = {
     .p.id           = AV_CODEC_ID_MP2,
     .priv_data_size = sizeof(TWOLAMEContext),
     .init           = twolame_encode_init,
-    .encode2        = twolame_encode_frame,
+    FF_CODEC_ENCODE_CB(twolame_encode_frame),
     .close          = twolame_encode_close,
     .p.capabilities = AV_CODEC_CAP_DELAY,
     .defaults       = twolame_defaults,
diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c
index b5e861bd1f..48333f17d1 100644
--- a/libavcodec/libuavs3d.c
+++ b/libavcodec/libuavs3d.c
@@ -255,7 +255,7 @@  const FFCodec ff_libuavs3d_decoder = {
     .priv_data_size = sizeof(uavs3d_context),
     .init           = libuavs3d_init,
     .close          = libuavs3d_end,
-    .decode         = libuavs3d_decode_frame,
+    FF_CODEC_DECODE_CB(libuavs3d_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .flush          = libuavs3d_flush,
diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c
index a52edbfaac..12ef6d7fe6 100644
--- a/libavcodec/libvo-amrwbenc.c
+++ b/libavcodec/libvo-amrwbenc.c
@@ -150,7 +150,7 @@  const FFCodec ff_libvo_amrwbenc_encoder = {
     .p.wrapper_name = "libvo_amrwbenc",
     .priv_data_size = sizeof(AMRWBContext),
     .init           = amr_wb_encode_init,
-    .encode2        = amr_wb_encode_frame,
+    FF_CODEC_ENCODE_CB(amr_wb_encode_frame),
     .close          = amr_wb_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/libvorbisdec.c b/libavcodec/libvorbisdec.c
index 26bd0c994e..81c4ac1c02 100644
--- a/libavcodec/libvorbisdec.c
+++ b/libavcodec/libvorbisdec.c
@@ -218,6 +218,6 @@  const FFCodec ff_libvorbis_decoder = {
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF,
     .priv_data_size = sizeof(OggVorbisDecContext),
     .init           = oggvorbis_decode_init,
-    .decode         = oggvorbis_decode_frame,
+    FF_CODEC_DECODE_CB(oggvorbis_decode_frame),
     .close          = oggvorbis_decode_close,
 };
diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c
index 5266da8dc0..9460d3267c 100644
--- a/libavcodec/libvorbisenc.c
+++ b/libavcodec/libvorbisenc.c
@@ -384,7 +384,7 @@  const FFCodec ff_libvorbis_encoder = {
                       AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(LibvorbisEncContext),
     .init           = libvorbis_encode_init,
-    .encode2        = libvorbis_encode_frame,
+    FF_CODEC_ENCODE_CB(libvorbis_encode_frame),
     .close          = libvorbis_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c
index 51bdd13832..ef690a7093 100644
--- a/libavcodec/libvpxdec.c
+++ b/libavcodec/libvpxdec.c
@@ -365,7 +365,7 @@  const FFCodec ff_libvpx_vp8_decoder = {
     .priv_data_size = sizeof(VPxContext),
     .init           = vp8_init,
     .close          = vpx_free,
-    .decode         = vpx_decode,
+    FF_CODEC_DECODE_CB(vpx_decode),
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
 };
 #endif /* CONFIG_LIBVPX_VP8_DECODER */
@@ -388,7 +388,7 @@  FFCodec ff_libvpx_vp9_decoder = {
     .priv_data_size = sizeof(VPxContext),
     .init           = vp9_init,
     .close          = vpx_free,
-    .decode         = vpx_decode,
+    FF_CODEC_DECODE_CB(vpx_decode),
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .init_static_data = ff_vp9_init_static,
 };
diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c
index dff1d06b0e..21a02d0b99 100644
--- a/libavcodec/libvpxenc.c
+++ b/libavcodec/libvpxenc.c
@@ -1934,7 +1934,7 @@  const FFCodec ff_libvpx_vp8_encoder = {
                       AV_CODEC_CAP_OTHER_THREADS,
     .priv_data_size = sizeof(VPxContext),
     .init           = vp8_init,
-    .encode2        = vpx_encode,
+    FF_CODEC_ENCODE_CB(vpx_encode),
     .close          = vpx_free,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE },
@@ -1969,7 +1969,7 @@  FFCodec ff_libvpx_vp9_encoder = {
     .p.wrapper_name = "libvpx",
     .priv_data_size = sizeof(VPxContext),
     .init           = vp9_init,
-    .encode2        = vpx_encode,
+    FF_CODEC_ENCODE_CB(vpx_encode),
     .close          = vpx_free,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .defaults       = defaults,
diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c
index 12f15bbf65..c5dc1b160a 100644
--- a/libavcodec/libwebpenc.c
+++ b/libavcodec/libwebpenc.c
@@ -99,6 +99,6 @@  const FFCodec ff_libwebp_encoder = {
     .priv_data_size = sizeof(LibWebPContext),
     .defaults       = ff_libwebp_defaults,
     .init           = libwebp_encode_init,
-    .encode2        = libwebp_encode_frame,
+    FF_CODEC_ENCODE_CB(libwebp_encode_frame),
     .close          = libwebp_encode_close,
 };
diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
index 0f5b524335..c50c2a6a96 100644
--- a/libavcodec/libwebpenc_animencoder.c
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -137,6 +137,6 @@  const FFCodec ff_libwebp_anim_encoder = {
     .priv_data_size = sizeof(LibWebPAnimContext),
     .defaults       = ff_libwebp_defaults,
     .init           = libwebp_anim_encode_init,
-    .encode2        = libwebp_anim_encode_frame,
+    FF_CODEC_ENCODE_CB(libwebp_anim_encode_frame),
     .close          = libwebp_anim_encode_close,
 };
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 989370ef70..4ce3791ae8 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -1228,7 +1228,7 @@  FFCodec ff_libx264_encoder = {
     .p.wrapper_name   = "libx264",
     .priv_data_size   = sizeof(X264Context),
     .init             = X264_init,
-    .encode2          = X264_frame,
+    FF_CODEC_ENCODE_CB(X264_frame),
     .close            = X264_close,
     .defaults         = x264_defaults,
 #if X264_BUILD < 153
@@ -1265,7 +1265,7 @@  const FFCodec ff_libx264rgb_encoder = {
     .p.wrapper_name = "libx264",
     .priv_data_size = sizeof(X264Context),
     .init           = X264_init,
-    .encode2        = X264_frame,
+    FF_CODEC_ENCODE_CB(X264_frame),
     .close          = X264_close,
     .defaults       = x264_defaults,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS
@@ -1297,7 +1297,7 @@  const FFCodec ff_libx262_encoder = {
     .p.wrapper_name   = "libx264",
     .priv_data_size   = sizeof(X264Context),
     .init             = X264_init,
-    .encode2          = X264_frame,
+    FF_CODEC_ENCODE_CB(X264_frame),
     .close            = X264_close,
     .defaults         = x264_defaults,
     .caps_internal    = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS,
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index abe64d69ef..4dcdcd7a77 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -752,7 +752,7 @@  FFCodec ff_libx265_encoder = {
     .p.wrapper_name   = "libx265",
     .init             = libx265_encode_init,
     .init_static_data = libx265_encode_init_csp,
-    .encode2          = libx265_encode_frame,
+    FF_CODEC_ENCODE_CB(libx265_encode_frame),
     .close            = libx265_encode_close,
     .priv_data_size   = sizeof(libx265Context),
     .defaults         = x265_defaults,
diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c
index 609487202d..a3efbcb4a1 100644
--- a/libavcodec/libxavs.c
+++ b/libavcodec/libxavs.c
@@ -430,7 +430,7 @@  const FFCodec ff_libxavs_encoder = {
                       AV_CODEC_CAP_OTHER_THREADS,
     .priv_data_size = sizeof(XavsContext),
     .init           = XAVS_init,
-    .encode2        = XAVS_frame,
+    FF_CODEC_ENCODE_CB(XAVS_frame),
     .close          = XAVS_close,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
diff --git a/libavcodec/libxavs2.c b/libavcodec/libxavs2.c
index f189aaeed2..f77078e3fb 100644
--- a/libavcodec/libxavs2.c
+++ b/libavcodec/libxavs2.c
@@ -295,7 +295,7 @@  const FFCodec ff_libxavs2_encoder = {
                       AV_CODEC_CAP_OTHER_THREADS,
     .priv_data_size = sizeof(XAVS2EContext),
     .init           = xavs2_init,
-    .encode2        = xavs2_encode_frame,
+    FF_CODEC_ENCODE_CB(xavs2_encode_frame),
     .close          = xavs2_close,
     .caps_internal  = FF_CODEC_CAP_AUTO_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index ece7aaaebd..4b3dd71bc5 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -904,7 +904,7 @@  const FFCodec ff_libxvid_encoder = {
     .p.id           = AV_CODEC_ID_MPEG4,
     .priv_data_size = sizeof(struct xvid_context),
     .init           = xvid_encode_init,
-    .encode2        = xvid_encode_frame,
+    FF_CODEC_ENCODE_CB(xvid_encode_frame),
     .close          = xvid_encode_close,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.priv_class   = &xvid_class,
diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c
index 4920c61e0f..79a1237431 100644
--- a/libavcodec/libzvbi-teletextdec.c
+++ b/libavcodec/libzvbi-teletextdec.c
@@ -822,6 +822,6 @@  const FFCodec ff_libzvbi_teletext_decoder = {
     .priv_data_size = sizeof(TeletextContext),
     .init      = teletext_init_decoder,
     .close     = teletext_close_decoder,
-    .decode_sub = teletext_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(teletext_decode_frame),
     .flush     = teletext_flush,
 };
diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c
index fad19cbb76..e0fc417d1f 100644
--- a/libavcodec/ljpegenc.c
+++ b/libavcodec/ljpegenc.c
@@ -329,7 +329,7 @@  const FFCodec ff_ljpeg_encoder = {
     .priv_data_size = sizeof(LJpegEncContext),
     .p.priv_class   = &ljpeg_class,
     .init           = ljpeg_encode_init,
-    .encode2        = ljpeg_encode_frame,
+    FF_CODEC_ENCODE_CB(ljpeg_encode_frame),
     .close          = ljpeg_encode_close,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]){
diff --git a/libavcodec/loco.c b/libavcodec/loco.c
index c21214a626..9cadc9d006 100644
--- a/libavcodec/loco.c
+++ b/libavcodec/loco.c
@@ -343,7 +343,7 @@  const FFCodec ff_loco_decoder = {
     .p.id           = AV_CODEC_ID_LOCO,
     .priv_data_size = sizeof(LOCOContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/lscrdec.c b/libavcodec/lscrdec.c
index dc2c7a51c2..9e7010c288 100644
--- a/libavcodec/lscrdec.c
+++ b/libavcodec/lscrdec.c
@@ -253,7 +253,7 @@  const FFCodec ff_lscr_decoder = {
     .priv_data_size = sizeof(LSCRContext),
     .init           = lscr_decode_init,
     .close          = lscr_decode_close,
-    .decode         = decode_frame_lscr,
+    FF_CODEC_DECODE_CB(decode_frame_lscr),
     .flush          = lscr_decode_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/m101.c b/libavcodec/m101.c
index a635b153f7..fce31956c7 100644
--- a/libavcodec/m101.c
+++ b/libavcodec/m101.c
@@ -111,7 +111,7 @@  const FFCodec ff_m101_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_M101,
     .init           = m101_decode_init,
-    .decode         = m101_decode_frame,
+    FF_CODEC_DECODE_CB(m101_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mace.c b/libavcodec/mace.c
index b32890c578..35af4a6aae 100644
--- a/libavcodec/mace.c
+++ b/libavcodec/mace.c
@@ -292,7 +292,7 @@  const FFCodec ff_mace3_decoder = {
     .p.id           = AV_CODEC_ID_MACE3,
     .priv_data_size = sizeof(MACEContext),
     .init           = mace_decode_init,
-    .decode         = mace_decode_frame,
+    FF_CODEC_DECODE_CB(mace_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
                                                       AV_SAMPLE_FMT_NONE },
@@ -306,7 +306,7 @@  const FFCodec ff_mace6_decoder = {
     .p.id           = AV_CODEC_ID_MACE6,
     .priv_data_size = sizeof(MACEContext),
     .init           = mace_decode_init,
-    .decode         = mace_decode_frame,
+    FF_CODEC_DECODE_CB(mace_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c
index b99905f4ad..634d45ca48 100644
--- a/libavcodec/magicyuv.c
+++ b/libavcodec/magicyuv.c
@@ -701,7 +701,7 @@  const FFCodec ff_magicyuv_decoder = {
     .priv_data_size   = sizeof(MagicYUVContext),
     .init             = magy_decode_init,
     .close            = magy_decode_end,
-    .decode           = magy_decode_frame,
+    FF_CODEC_DECODE_CB(magy_decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 |
                         AV_CODEC_CAP_FRAME_THREADS |
                         AV_CODEC_CAP_SLICE_THREADS,
diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c
index b365739443..ce492368ef 100644
--- a/libavcodec/magicyuvenc.c
+++ b/libavcodec/magicyuvenc.c
@@ -572,7 +572,7 @@  const FFCodec ff_magicyuv_encoder = {
     .p.priv_class     = &magicyuv_class,
     .init             = magy_encode_init,
     .close            = magy_encode_close,
-    .encode2          = magy_encode_frame,
+    FF_CODEC_ENCODE_CB(magy_encode_frame),
     .p.capabilities   = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts       = (const enum AVPixelFormat[]) {
                           AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV422P,
diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c
index 24c0fc1adc..deabebda62 100644
--- a/libavcodec/mdec.c
+++ b/libavcodec/mdec.c
@@ -257,7 +257,7 @@  const FFCodec ff_mdec_decoder = {
     .priv_data_size   = sizeof(MDECContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c
index c8c9f1df08..6b4c39b4e0 100644
--- a/libavcodec/mediacodecdec.c
+++ b/libavcodec/mediacodecdec.c
@@ -540,7 +540,7 @@  const FFCodec ff_ ## short_name ## _mediacodec_decoder = {
     .p.priv_class   = &ff_##short_name##_mediacodec_dec_class,                                 \
     .priv_data_size = sizeof(MediaCodecH264DecContext),                                        \
     .init           = mediacodec_decode_init,                                                  \
-    .receive_frame  = mediacodec_receive_frame,                                                \
+    FF_CODEC_RECEIVE_FRAME_CB(mediacodec_receive_frame),                                       \
     .flush          = mediacodec_decode_flush,                                                 \
     .close          = mediacodec_decode_close,                                                 \
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
diff --git a/libavcodec/metasound.c b/libavcodec/metasound.c
index 3897d42911..9c5d0369c4 100644
--- a/libavcodec/metasound.c
+++ b/libavcodec/metasound.c
@@ -381,7 +381,7 @@  const FFCodec ff_metasound_decoder = {
     .priv_data_size = sizeof(TwinVQContext),
     .init           = metasound_decode_init,
     .close          = ff_twinvq_decode_close,
-    .decode         = ff_twinvq_decode_frame,
+    FF_CODEC_DECODE_CB(ff_twinvq_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c
index f30068985e..280941cf2e 100644
--- a/libavcodec/mfenc.c
+++ b/libavcodec/mfenc.c
@@ -1160,7 +1160,7 @@  static int mf_close(AVCodecContext *avctx)
         .priv_data_size = sizeof(MFContext),                                   \
         .init           = mf_init,                                             \
         .close          = mf_close,                                            \
-        .receive_packet = mf_receive_packet,                                   \
+        FF_CODEC_RECEIVE_PACKET_CB(mf_receive_packet),                         \
         EXTRA                                                                  \
         .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID |           \
                           AV_CODEC_CAP_DR1,                                    \
diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c
index 1cd5d1d5f5..154fd3271b 100644
--- a/libavcodec/microdvddec.c
+++ b/libavcodec/microdvddec.c
@@ -374,7 +374,7 @@  const FFCodec ff_microdvd_decoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_MICRODVD,
     .init         = microdvd_init,
-    .decode_sub   = microdvd_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(microdvd_decode_frame),
     .flush        = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/midivid.c b/libavcodec/midivid.c
index 55fca27085..a21303ab60 100644
--- a/libavcodec/midivid.c
+++ b/libavcodec/midivid.c
@@ -285,7 +285,7 @@  const FFCodec ff_mvdv_decoder = {
     .p.id           = AV_CODEC_ID_MVDV,
     .priv_data_size = sizeof(MidiVidContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c
index 05c193989b..74dd947f88 100644
--- a/libavcodec/mimic.c
+++ b/libavcodec/mimic.c
@@ -445,7 +445,7 @@  const FFCodec ff_mimic_decoder = {
     .priv_data_size        = sizeof(MimicContext),
     .init                  = mimic_decode_init,
     .close                 = mimic_decode_end,
-    .decode                = mimic_decode_frame,
+    FF_CODEC_DECODE_CB(mimic_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context),
     .caps_internal         = FF_CODEC_CAP_ALLOCATE_PROGRESS |
diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c
index b04d61c0e0..8c1809e5fb 100644
--- a/libavcodec/mjpegbdec.c
+++ b/libavcodec/mjpegbdec.c
@@ -164,7 +164,7 @@  const FFCodec ff_mjpegb_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .decode         = mjpegb_decode_frame,
+    FF_CODEC_DECODE_CB(mjpegb_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.max_lowres   = 3,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index 13b56e0b2f..32874a5a19 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -3020,7 +3020,7 @@  const FFCodec ff_mjpeg_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.max_lowres   = 3,
@@ -3048,7 +3048,7 @@  const FFCodec ff_thp_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.max_lowres   = 3,
@@ -3066,7 +3066,7 @@  const FFCodec ff_smvjpeg_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING |
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index a39b990eea..31d794965f 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -658,7 +658,7 @@  const FFCodec ff_mjpeg_encoder = {
     .p.id           = AV_CODEC_ID_MJPEG,
     .priv_data_size = sizeof(MJPEGEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = mjpeg_encode_close,
     .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
@@ -687,7 +687,7 @@  const FFCodec ff_amv_encoder = {
     .p.id           = AV_CODEC_ID_AMV,
     .priv_data_size = sizeof(MJPEGEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = amv_encode_picture,
+    FF_CODEC_ENCODE_CB(amv_encode_picture),
     .close          = mjpeg_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
index a3c1850d33..c5d8f5bde8 100644
--- a/libavcodec/mlpdec.c
+++ b/libavcodec/mlpdec.c
@@ -1424,7 +1424,7 @@  const FFCodec ff_mlp_decoder = {
     .priv_data_size = sizeof(MLPDecodeContext),
     .p.priv_class   = &mlp_decoder_class,
     .init           = mlp_decode_init,
-    .decode         = read_access_unit,
+    FF_CODEC_DECODE_CB(read_access_unit),
     .flush          = mlp_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -1439,7 +1439,7 @@  const FFCodec ff_truehd_decoder = {
     .priv_data_size = sizeof(MLPDecodeContext),
     .p.priv_class   = &truehd_decoder_class,
     .init           = mlp_decode_init,
-    .decode         = read_access_unit,
+    FF_CODEC_DECODE_CB(read_access_unit),
     .flush          = mlp_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c
index bcb479f2a6..da36818169 100644
--- a/libavcodec/mlpenc.c
+++ b/libavcodec/mlpenc.c
@@ -2213,7 +2213,7 @@  const FFCodec ff_mlp_encoder = {
     .p.id                   = AV_CODEC_ID_MLP,
     .priv_data_size         = sizeof(MLPEncodeContext),
     .init                   = mlp_encode_init,
-    .encode2                = mlp_encode_frame,
+    FF_CODEC_ENCODE_CB(mlp_encode_frame),
     .close                  = mlp_encode_close,
     .p.capabilities         = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
     .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
@@ -2233,7 +2233,7 @@  const FFCodec ff_truehd_encoder = {
     .p.id                   = AV_CODEC_ID_TRUEHD,
     .priv_data_size         = sizeof(MLPEncodeContext),
     .init                   = mlp_encode_init,
-    .encode2                = mlp_encode_frame,
+    FF_CODEC_ENCODE_CB(mlp_encode_frame),
     .close                  = mlp_encode_close,
     .p.capabilities         = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
     .p.sample_fmts          = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE},
diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c
index 2a56bcae01..7fd24ad3b7 100644
--- a/libavcodec/mmaldec.c
+++ b/libavcodec/mmaldec.c
@@ -837,7 +837,7 @@  static const AVClass ffmmal_dec_class = {
         .priv_data_size = sizeof(MMALDecodeContext), \
         .init           = ffmmal_init_decoder, \
         .close          = ffmmal_close_decoder, \
-        .receive_frame  = ffmmal_receive_frame, \
+        FF_CODEC_RECEIVE_FRAME_CB(ffmmal_receive_frame), \
         .flush          = ffmmal_flush, \
         .p.priv_class   = &ffmmal_dec_class, \
         .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \
diff --git a/libavcodec/mmvideo.c b/libavcodec/mmvideo.c
index 54ed5fad14..fc80ec4764 100644
--- a/libavcodec/mmvideo.c
+++ b/libavcodec/mmvideo.c
@@ -246,7 +246,7 @@  const FFCodec ff_mmvideo_decoder = {
     .priv_data_size = sizeof(MmContext),
     .init           = mm_decode_init,
     .close          = mm_decode_end,
-    .decode         = mm_decode_frame,
+    FF_CODEC_DECODE_CB(mm_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mobiclip.c b/libavcodec/mobiclip.c
index 0b7230f326..2d09bc1f72 100644
--- a/libavcodec/mobiclip.c
+++ b/libavcodec/mobiclip.c
@@ -1347,7 +1347,7 @@  const FFCodec ff_mobiclip_decoder = {
     .p.id           = AV_CODEC_ID_MOBICLIP,
     .priv_data_size = sizeof(MobiClipContext),
     .init           = mobiclip_init,
-    .decode         = mobiclip_decode,
+    FF_CODEC_DECODE_CB(mobiclip_decode),
     .flush          = mobiclip_flush,
     .close          = mobiclip_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c
index aeea4e6865..29454fd242 100644
--- a/libavcodec/motionpixels.c
+++ b/libavcodec/motionpixels.c
@@ -353,7 +353,7 @@  const FFCodec ff_motionpixels_decoder = {
     .priv_data_size = sizeof(MotionPixelsContext),
     .init           = mp_decode_init,
     .close          = mp_decode_end,
-    .decode         = mp_decode_frame,
+    FF_CODEC_DECODE_CB(mp_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c
index c3e0a75e57..6a71537291 100644
--- a/libavcodec/movtextdec.c
+++ b/libavcodec/movtextdec.c
@@ -599,7 +599,7 @@  const FFCodec ff_movtext_decoder = {
     .priv_data_size = sizeof(MovTextContext),
     .p.priv_class = &mov_text_decoder_class,
     .init         = mov_text_init,
-    .decode_sub   = mov_text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(mov_text_decode_frame),
     .close        = mov_text_decode_close,
     .flush        = mov_text_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c
index 333a23be82..728338f2cc 100644
--- a/libavcodec/movtextenc.c
+++ b/libavcodec/movtextenc.c
@@ -707,7 +707,7 @@  const FFCodec ff_movtext_encoder = {
     .priv_data_size = sizeof(MovTextContext),
     .p.priv_class   = &mov_text_encoder_class,
     .init           = mov_text_encode_init,
-    .encode_sub     = mov_text_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(mov_text_encode_frame),
     .close          = mov_text_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c
index 5d8280ee2e..1b722714f0 100644
--- a/libavcodec/mpc7.c
+++ b/libavcodec/mpc7.c
@@ -317,7 +317,7 @@  const FFCodec ff_mpc7_decoder = {
     .priv_data_size = sizeof(MPCContext),
     .init           = mpc7_decode_init,
     .close          = mpc7_decode_close,
-    .decode         = mpc7_decode_frame,
+    FF_CODEC_DECODE_CB(mpc7_decode_frame),
     .flush          = mpc7_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c
index e876de4813..7903e5df8a 100644
--- a/libavcodec/mpc8.c
+++ b/libavcodec/mpc8.c
@@ -390,7 +390,7 @@  const FFCodec ff_mpc8_decoder = {
     .p.id           = AV_CODEC_ID_MUSEPACK8,
     .priv_data_size = sizeof(MPCContext),
     .init           = mpc8_decode_init,
-    .decode         = mpc8_decode_frame,
+    FF_CODEC_DECODE_CB(mpc8_decode_frame),
     .flush          = mpc8_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 599ee8dcb1..e9bde48f7a 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -2870,7 +2870,7 @@  const FFCodec ff_mpeg1video_decoder = {
     .priv_data_size        = sizeof(Mpeg1Context),
     .init                  = mpeg_decode_init,
     .close                 = mpeg_decode_end,
-    .decode                = mpeg_decode_frame,
+    FF_CODEC_DECODE_CB(mpeg_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                              AV_CODEC_CAP_TRUNCATED |
@@ -2903,7 +2903,7 @@  const FFCodec ff_mpeg2video_decoder = {
     .priv_data_size = sizeof(Mpeg1Context),
     .init           = mpeg_decode_init,
     .close          = mpeg_decode_end,
-    .decode         = mpeg_decode_frame,
+    FF_CODEC_DECODE_CB(mpeg_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                       AV_CODEC_CAP_TRUNCATED |
@@ -2949,7 +2949,7 @@  const FFCodec ff_mpegvideo_decoder = {
     .priv_data_size = sizeof(Mpeg1Context),
     .init           = mpeg_decode_init,
     .close          = mpeg_decode_end,
-    .decode         = mpeg_decode_frame,
+    FF_CODEC_DECODE_CB(mpeg_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                       AV_CODEC_CAP_TRUNCATED |
@@ -3113,7 +3113,7 @@  const FFCodec ff_ipu_decoder = {
     .p.id           = AV_CODEC_ID_IPU,
     .priv_data_size = sizeof(IPUContext),
     .init           = ipu_decode_init,
-    .decode         = ipu_decode_frame,
+    FF_CODEC_DECODE_CB(ipu_decode_frame),
     .close          = ipu_decode_end,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 77cbb60ea1..5ba2828e2f 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -1232,7 +1232,7 @@  const FFCodec ff_mpeg1video_encoder = {
     .p.id                 = AV_CODEC_ID_MPEG1VIDEO,
     .priv_data_size       = sizeof(MPEG12EncContext),
     .init                 = encode_init,
-    .encode2              = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close                = ff_mpv_encode_end,
     .p.supported_framerates = ff_mpeg12_frame_rate_tab + 1,
     .p.pix_fmts           = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
@@ -1249,7 +1249,7 @@  const FFCodec ff_mpeg2video_encoder = {
     .p.id                 = AV_CODEC_ID_MPEG2VIDEO,
     .priv_data_size       = sizeof(MPEG12EncContext),
     .init                 = encode_init,
-    .encode2              = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close                = ff_mpv_encode_end,
     .p.supported_framerates = ff_mpeg2_frame_rate_tab,
     .p.pix_fmts           = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 5c55de3eb8..e2bde73639 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -3670,7 +3670,7 @@  const FFCodec ff_mpeg4_decoder = {
     .priv_data_size        = sizeof(Mpeg4DecContext),
     .init                  = decode_init,
     .close                 = ff_h263_decode_end,
-    .decode                = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 |
 #if FF_API_FLAG_TRUNCATED
                              AV_CODEC_CAP_TRUNCATED |
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index 1140c33a70..89e7ce1260 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -1401,7 +1401,7 @@  const FFCodec ff_mpeg4_encoder = {
     .p.id           = AV_CODEC_ID_MPEG4,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS,
diff --git a/libavcodec/mpegaudiodec_fixed.c b/libavcodec/mpegaudiodec_fixed.c
index 8809fac976..8a5721d383 100644
--- a/libavcodec/mpegaudiodec_fixed.c
+++ b/libavcodec/mpegaudiodec_fixed.c
@@ -68,7 +68,7 @@  const FFCodec ff_mp1_decoder = {
     .p.id           = AV_CODEC_ID_MP1,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -86,7 +86,7 @@  const FFCodec ff_mp2_decoder = {
     .p.id           = AV_CODEC_ID_MP2,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -104,7 +104,7 @@  const FFCodec ff_mp3_decoder = {
     .p.id           = AV_CODEC_ID_MP3,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -122,7 +122,7 @@  const FFCodec ff_mp3adu_decoder = {
     .p.id           = AV_CODEC_ID_MP3ADU,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame_adu,
+    FF_CODEC_DECODE_CB(decode_frame_adu),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -141,7 +141,7 @@  const FFCodec ff_mp3on4_decoder = {
     .priv_data_size = sizeof(MP3On4DecodeContext),
     .init           = decode_init_mp3on4,
     .close          = decode_close_mp3on4,
-    .decode         = decode_frame_mp3on4,
+    FF_CODEC_DECODE_CB(decode_frame_mp3on4),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush_mp3on4,
diff --git a/libavcodec/mpegaudiodec_float.c b/libavcodec/mpegaudiodec_float.c
index c4fd64a85f..bcd55069a0 100644
--- a/libavcodec/mpegaudiodec_float.c
+++ b/libavcodec/mpegaudiodec_float.c
@@ -81,7 +81,7 @@  const FFCodec ff_mp1float_decoder = {
     .p.id           = AV_CODEC_ID_MP1,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -99,7 +99,7 @@  const FFCodec ff_mp2float_decoder = {
     .p.id           = AV_CODEC_ID_MP2,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -117,7 +117,7 @@  const FFCodec ff_mp3float_decoder = {
     .p.id           = AV_CODEC_ID_MP3,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -135,7 +135,7 @@  const FFCodec ff_mp3adufloat_decoder = {
     .p.id           = AV_CODEC_ID_MP3ADU,
     .priv_data_size = sizeof(MPADecodeContext),
     .init           = decode_init,
-    .decode         = decode_frame_adu,
+    FF_CODEC_DECODE_CB(decode_frame_adu),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush,
@@ -154,7 +154,7 @@  const FFCodec ff_mp3on4float_decoder = {
     .priv_data_size = sizeof(MP3On4DecodeContext),
     .init           = decode_init_mp3on4,
     .close          = decode_close_mp3on4,
-    .decode         = decode_frame_mp3on4,
+    FF_CODEC_DECODE_CB(decode_frame_mp3on4),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .flush          = flush_mp3on4,
diff --git a/libavcodec/mpegaudioenc_fixed.c b/libavcodec/mpegaudioenc_fixed.c
index 2eaa933195..74cb4b8d57 100644
--- a/libavcodec/mpegaudioenc_fixed.c
+++ b/libavcodec/mpegaudioenc_fixed.c
@@ -30,7 +30,7 @@  const FFCodec ff_mp2fixed_encoder = {
     .p.id                  = AV_CODEC_ID_MP2,
     .priv_data_size        = sizeof(MpegAudioContext),
     .init                  = MPA_encode_init,
-    .encode2               = MPA_encode_frame,
+    FF_CODEC_ENCODE_CB(MPA_encode_frame),
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                             AV_SAMPLE_FMT_NONE },
     .p.supported_samplerates = (const int[]){
diff --git a/libavcodec/mpegaudioenc_float.c b/libavcodec/mpegaudioenc_float.c
index 9b9c7a442a..0a597b7e07 100644
--- a/libavcodec/mpegaudioenc_float.c
+++ b/libavcodec/mpegaudioenc_float.c
@@ -31,7 +31,7 @@  const FFCodec ff_mp2_encoder = {
     .p.id                  = AV_CODEC_ID_MP2,
     .priv_data_size        = sizeof(MpegAudioContext),
     .init                  = MPA_encode_init,
-    .encode2               = MPA_encode_frame,
+    FF_CODEC_ENCODE_CB(MPA_encode_frame),
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                             AV_SAMPLE_FMT_NONE },
     .p.supported_samplerates = (const int[]){
diff --git a/libavcodec/mpl2dec.c b/libavcodec/mpl2dec.c
index 490a3e6d45..7104670f4d 100644
--- a/libavcodec/mpl2dec.c
+++ b/libavcodec/mpl2dec.c
@@ -86,7 +86,7 @@  const FFCodec ff_mpl2_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("MPL2 subtitle"),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_MPL2,
-    .decode_sub     = mpl2_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(mpl2_decode_frame),
     .init           = ff_ass_subtitle_header_default,
     .flush          = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
diff --git a/libavcodec/mscc.c b/libavcodec/mscc.c
index e7f6015554..ac67ec9c47 100644
--- a/libavcodec/mscc.c
+++ b/libavcodec/mscc.c
@@ -252,7 +252,7 @@  const FFCodec ff_mscc_decoder = {
     .priv_data_size   = sizeof(MSCCContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
@@ -265,7 +265,7 @@  const FFCodec ff_srgc_decoder = {
     .priv_data_size   = sizeof(MSCCContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c
index f0cb11eceb..a03e43f88c 100644
--- a/libavcodec/msmpeg4dec.c
+++ b/libavcodec/msmpeg4dec.c
@@ -872,7 +872,7 @@  const FFCodec ff_msmpeg4v1_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_msmpeg4_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
@@ -891,7 +891,7 @@  const FFCodec ff_msmpeg4v2_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_msmpeg4_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
@@ -910,7 +910,7 @@  const FFCodec ff_msmpeg4v3_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_msmpeg4_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
@@ -929,7 +929,7 @@  const FFCodec ff_wmv1_decoder = {
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_msmpeg4_decode_init,
     .close          = ff_h263_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index dd75cd5746..e597dbbb4e 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -686,7 +686,7 @@  const FFCodec ff_msmpeg4v2_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
 };
 
@@ -700,7 +700,7 @@  const FFCodec ff_msmpeg4v3_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
 };
 
@@ -714,6 +714,6 @@  const FFCodec ff_wmv1_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
 };
diff --git a/libavcodec/msp2dec.c b/libavcodec/msp2dec.c
index 99dcf7e9f9..5374c4be81 100644
--- a/libavcodec/msp2dec.c
+++ b/libavcodec/msp2dec.c
@@ -98,5 +98,5 @@  const FFCodec ff_msp2_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_MSP2,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = msp2_decode_frame,
+    FF_CODEC_DECODE_CB(msp2_decode_frame),
 };
diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c
index 49fd3c86e2..041d0c9493 100644
--- a/libavcodec/msrle.c
+++ b/libavcodec/msrle.c
@@ -167,7 +167,7 @@  const FFCodec ff_msrle_decoder = {
     .priv_data_size = sizeof(MsrleContext),
     .init           = msrle_decode_init,
     .close          = msrle_decode_end,
-    .decode         = msrle_decode_frame,
+    FF_CODEC_DECODE_CB(msrle_decode_frame),
     .flush          = msrle_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c
index 844a6bde9c..bc00a11abb 100644
--- a/libavcodec/mss1.c
+++ b/libavcodec/mss1.c
@@ -227,7 +227,7 @@  const FFCodec ff_mss1_decoder = {
     .priv_data_size = sizeof(MSS1Context),
     .init           = mss1_decode_init,
     .close          = mss1_decode_end,
-    .decode         = mss1_decode_frame,
+    FF_CODEC_DECODE_CB(mss1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c
index 235149b906..ab42d12217 100644
--- a/libavcodec/mss2.c
+++ b/libavcodec/mss2.c
@@ -854,7 +854,7 @@  const FFCodec ff_mss2_decoder = {
     .priv_data_size = sizeof(MSS2Context),
     .init           = mss2_decode_init,
     .close          = mss2_decode_end,
-    .decode         = mss2_decode_frame,
+    FF_CODEC_DECODE_CB(mss2_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mss3.c b/libavcodec/mss3.c
index 3e12ea0399..55d2d10bd6 100644
--- a/libavcodec/mss3.c
+++ b/libavcodec/mss3.c
@@ -868,7 +868,7 @@  const FFCodec ff_msa1_decoder = {
     .priv_data_size = sizeof(MSS3Context),
     .init           = mss3_decode_init,
     .close          = mss3_decode_end,
-    .decode         = mss3_decode_frame,
+    FF_CODEC_DECODE_CB(mss3_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c
index c29d885077..be73e52a91 100644
--- a/libavcodec/mss4.c
+++ b/libavcodec/mss4.c
@@ -613,7 +613,7 @@  const FFCodec ff_mts2_decoder = {
     .priv_data_size = sizeof(MSS4Context),
     .init           = mss4_decode_init,
     .close          = mss4_decode_end,
-    .decode         = mss4_decode_frame,
+    FF_CODEC_DECODE_CB(mss4_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c
index fa08e2cdfd..a39f684b52 100644
--- a/libavcodec/msvideo1.c
+++ b/libavcodec/msvideo1.c
@@ -349,7 +349,7 @@  const FFCodec ff_msvideo1_decoder = {
     .priv_data_size = sizeof(Msvideo1Context),
     .init           = msvideo1_decode_init,
     .close          = msvideo1_decode_end,
-    .decode         = msvideo1_decode_frame,
+    FF_CODEC_DECODE_CB(msvideo1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c
index 917b7ea907..53f4a4b365 100644
--- a/libavcodec/msvideo1enc.c
+++ b/libavcodec/msvideo1enc.c
@@ -309,7 +309,7 @@  const FFCodec ff_msvideo1_encoder = {
     .p.id           = AV_CODEC_ID_MSVIDEO1,
     .priv_data_size = sizeof(Msvideo1EncContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE},
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/mv30.c b/libavcodec/mv30.c
index 75ed23d493..a32fab2b92 100644
--- a/libavcodec/mv30.c
+++ b/libavcodec/mv30.c
@@ -710,7 +710,7 @@  const FFCodec ff_mv30_decoder = {
     .priv_data_size   = sizeof(MV30Context),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush            = decode_flush,
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c
index 2bef903bfa..4ee8d10ca9 100644
--- a/libavcodec/mvcdec.c
+++ b/libavcodec/mvcdec.c
@@ -262,7 +262,7 @@  const FFCodec ff_mvc1_decoder = {
     .p.id           = AV_CODEC_ID_MVC1,
     .priv_data_size = sizeof(MvcContext),
     .init           = mvc_decode_init,
-    .decode         = mvc_decode_frame,
+    FF_CODEC_DECODE_CB(mvc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -276,7 +276,7 @@  const FFCodec ff_mvc2_decoder = {
     .p.id           = AV_CODEC_ID_MVC2,
     .priv_data_size = sizeof(MvcContext),
     .init           = mvc_decode_init,
-    .decode         = mvc_decode_frame,
+    FF_CODEC_DECODE_CB(mvc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/mvha.c b/libavcodec/mvha.c
index 7c312d8562..8a65c42583 100644
--- a/libavcodec/mvha.c
+++ b/libavcodec/mvha.c
@@ -306,7 +306,7 @@  const FFCodec ff_mvha_decoder = {
     .priv_data_size   = sizeof(MVHAContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/mwsc.c b/libavcodec/mwsc.c
index 82d149a295..d89fbde4e2 100644
--- a/libavcodec/mwsc.c
+++ b/libavcodec/mwsc.c
@@ -176,7 +176,7 @@  const FFCodec ff_mwsc_decoder = {
     .priv_data_size   = sizeof(MWSCContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c
index 19a4bfcd8b..e5cdd44fd2 100644
--- a/libavcodec/mxpegdec.c
+++ b/libavcodec/mxpegdec.c
@@ -350,7 +350,7 @@  const FFCodec ff_mxpeg_decoder = {
     .priv_data_size = sizeof(MXpegDecodeContext),
     .init           = mxpeg_decode_init,
     .close          = mxpeg_decode_end,
-    .decode         = mxpeg_decode_frame,
+    FF_CODEC_DECODE_CB(mxpeg_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.max_lowres   = 3,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c
index 1d51b989a5..63b60f202c 100644
--- a/libavcodec/nellymoserdec.c
+++ b/libavcodec/nellymoserdec.c
@@ -194,7 +194,7 @@  const FFCodec ff_nellymoser_decoder = {
     .priv_data_size = sizeof(NellyMoserDecodeContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_tag,
+    FF_CODEC_DECODE_CB(decode_tag),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c
index 35a30b9942..c11dfe504c 100644
--- a/libavcodec/nellymoserenc.c
+++ b/libavcodec/nellymoserenc.c
@@ -422,7 +422,7 @@  const FFCodec ff_nellymoser_encoder = {
                       AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(NellyMoserEncodeContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c
index 36967a6f63..f6d62b8a4b 100644
--- a/libavcodec/notchlc.c
+++ b/libavcodec/notchlc.c
@@ -543,7 +543,7 @@  const FFCodec ff_notchlc_decoder = {
     .priv_data_size   = sizeof(NotchLCContext),
     .init             = decode_init,
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c
index 2fdb023751..71420a62f6 100644
--- a/libavcodec/nuv.c
+++ b/libavcodec/nuv.c
@@ -370,7 +370,7 @@  const FFCodec ff_nuv_decoder = {
     .priv_data_size = sizeof(NuvContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index 101f8ddb4c..1860c60a29 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -225,7 +225,7 @@  const FFCodec ff_h264_nvenc_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_H264,
     .init           = ff_nvenc_encode_init,
-    .receive_packet = ff_nvenc_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(ff_nvenc_receive_packet),
     .close          = ff_nvenc_encode_close,
     .flush          = ff_nvenc_encode_flush,
     .priv_data_size = sizeof(NvencContext),
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 6443e3e145..2c64cce598 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -206,7 +206,7 @@  const FFCodec ff_hevc_nvenc_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HEVC,
     .init           = ff_nvenc_encode_init,
-    .receive_packet = ff_nvenc_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(ff_nvenc_receive_packet),
     .close          = ff_nvenc_encode_close,
     .flush          = ff_nvenc_encode_flush,
     .priv_data_size = sizeof(NvencContext),
diff --git a/libavcodec/omx.c b/libavcodec/omx.c
index 4bf3b4ffdd..d481c0678b 100644
--- a/libavcodec/omx.c
+++ b/libavcodec/omx.c
@@ -943,7 +943,7 @@  const FFCodec ff_mpeg4_omx_encoder = {
     .p.id             = AV_CODEC_ID_MPEG4,
     .priv_data_size   = sizeof(OMXCodecContext),
     .init             = omx_encode_init,
-    .encode2          = omx_encode_frame,
+    FF_CODEC_ENCODE_CB(omx_encode_frame),
     .close            = omx_encode_end,
     .p.pix_fmts       = omx_encoder_pix_fmts,
     .p.capabilities   = AV_CODEC_CAP_DELAY,
@@ -964,7 +964,7 @@  const FFCodec ff_h264_omx_encoder = {
     .p.id             = AV_CODEC_ID_H264,
     .priv_data_size   = sizeof(OMXCodecContext),
     .init             = omx_encode_init,
-    .encode2          = omx_encode_frame,
+    FF_CODEC_ENCODE_CB(omx_encode_frame),
     .close            = omx_encode_end,
     .p.pix_fmts       = omx_encoder_pix_fmts,
     .p.capabilities   = AV_CODEC_CAP_DELAY,
diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c
index 9ba4d764a0..5477f6f87b 100644
--- a/libavcodec/on2avc.c
+++ b/libavcodec/on2avc.c
@@ -1011,7 +1011,7 @@  const FFCodec ff_on2avc_decoder = {
     .p.id           = AV_CODEC_ID_ON2AVC,
     .priv_data_size = sizeof(On2AVCContext),
     .init           = on2avc_decode_init,
-    .decode         = on2avc_decode_frame,
+    FF_CODEC_DECODE_CB(on2avc_decode_frame),
     .close          = on2avc_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c
index ff7dd6c631..8ca99369c6 100644
--- a/libavcodec/opusdec.c
+++ b/libavcodec/opusdec.c
@@ -713,7 +713,7 @@  const FFCodec ff_opus_decoder = {
     .priv_data_size  = sizeof(OpusContext),
     .init            = opus_decode_init,
     .close           = opus_decode_close,
-    .decode          = opus_decode_packet,
+    FF_CODEC_DECODE_CB(opus_decode_packet),
     .flush           = opus_decode_flush,
     .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal   = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c
index 44aa9cbd44..b4b7c472a0 100644
--- a/libavcodec/opusenc.c
+++ b/libavcodec/opusenc.c
@@ -734,7 +734,7 @@  const FFCodec ff_opus_encoder = {
     .p.priv_class   = &opusenc_class,
     .priv_data_size = sizeof(OpusEncContext),
     .init           = opus_encode_init,
-    .encode2        = opus_encode_frame,
+    FF_CODEC_ENCODE_CB(opus_encode_frame),
     .close          = opus_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
diff --git a/libavcodec/pafaudio.c b/libavcodec/pafaudio.c
index 6e8da3d3c4..9f694d2dc8 100644
--- a/libavcodec/pafaudio.c
+++ b/libavcodec/pafaudio.c
@@ -79,7 +79,7 @@  const FFCodec ff_paf_audio_decoder = {
     .p.type       = AVMEDIA_TYPE_AUDIO,
     .p.id         = AV_CODEC_ID_PAF_AUDIO,
     .init         = paf_audio_init,
-    .decode       = paf_audio_decode,
+    FF_CODEC_DECODE_CB(paf_audio_decode),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c
index 3199e7f44c..a0bd22e8fd 100644
--- a/libavcodec/pafvideo.c
+++ b/libavcodec/pafvideo.c
@@ -416,7 +416,7 @@  const FFCodec ff_paf_video_decoder = {
     .priv_data_size = sizeof(PAFVideoDecContext),
     .init           = paf_video_init,
     .close          = paf_video_close,
-    .decode         = paf_video_decode,
+    FF_CODEC_DECODE_CB(paf_video_decode),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/pamenc.c b/libavcodec/pamenc.c
index 8ded835d25..8a94f8a537 100644
--- a/libavcodec/pamenc.c
+++ b/libavcodec/pamenc.c
@@ -133,7 +133,7 @@  const FFCodec ff_pam_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PAM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pam_encode_frame,
+    FF_CODEC_ENCODE_CB(pam_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
         AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE,
diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c
index fb9d06a36f..54338e679f 100644
--- a/libavcodec/pcm-bluray.c
+++ b/libavcodec/pcm-bluray.c
@@ -304,7 +304,7 @@  const FFCodec ff_pcm_bluray_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_PCM_BLURAY,
-    .decode         = pcm_bluray_decode_frame,
+    FF_CODEC_DECODE_CB(pcm_bluray_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]){
         AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE
diff --git a/libavcodec/pcm-blurayenc.c b/libavcodec/pcm-blurayenc.c
index 37b4709df8..99886e8c37 100644
--- a/libavcodec/pcm-blurayenc.c
+++ b/libavcodec/pcm-blurayenc.c
@@ -277,7 +277,7 @@  const FFCodec ff_pcm_bluray_encoder = {
     .p.id                  = AV_CODEC_ID_PCM_BLURAY,
     .priv_data_size        = sizeof(BlurayPCMEncContext),
     .init                  = pcm_bluray_encode_init,
-    .encode2               = pcm_bluray_encode_frame,
+    FF_CODEC_ENCODE_CB(pcm_bluray_encode_frame),
     .p.supported_samplerates = (const int[]) { 48000, 96000, 192000, 0 },
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts = (const uint64_t[]) {
diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c
index f7a5ba6600..57d0ff81d0 100644
--- a/libavcodec/pcm-dvd.c
+++ b/libavcodec/pcm-dvd.c
@@ -302,7 +302,7 @@  const FFCodec ff_pcm_dvd_decoder = {
     .p.id           = AV_CODEC_ID_PCM_DVD,
     .priv_data_size = sizeof(PCMDVDContext),
     .init           = pcm_dvd_decode_init,
-    .decode         = pcm_dvd_decode_frame,
+    FF_CODEC_DECODE_CB(pcm_dvd_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
     .p.sample_fmts  = (const enum AVSampleFormat[]) {
diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index d0c328beb0..f18855cfa7 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -180,7 +180,7 @@  const FFCodec ff_pcm_dvd_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(PCMDVDContext),
     .init           = pcm_dvd_encode_init,
-    .encode2        = pcm_dvd_encode_frame,
+    FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame),
     .p.supported_samplerates = (const int[]) { 48000, 96000, 0},
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index dfb10095c2..471075ad71 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -561,7 +561,7 @@  const FFCodec ff_ ## name_ ## _encoder = {                                  \
     .p.id         = AV_CODEC_ID_ ## id_,                                    \
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,    \
     .init         = pcm_encode_init,                                        \
-    .encode2      = pcm_encode_frame,                                       \
+    FF_CODEC_ENCODE_CB(pcm_encode_frame),                                   \
     .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_,             \
                                                    AV_SAMPLE_FMT_NONE },    \
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,                          \
@@ -583,7 +583,7 @@  const FFCodec ff_ ## name_ ## _decoder = {                                  \
     .p.id           = AV_CODEC_ID_ ## id_,                                  \
     .priv_data_size = sizeof(PCMDecode),                                    \
     .init           = pcm_decode_init,                                      \
-    .decode         = pcm_decode_frame,                                     \
+    FF_CODEC_DECODE_CB(pcm_decode_frame),                                    \
     .p.capabilities = AV_CODEC_CAP_DR1,                                     \
     .p.sample_fmts  = (const enum AVSampleFormat[]){ sample_fmt_,           \
                                                      AV_SAMPLE_FMT_NONE },  \
diff --git a/libavcodec/pcx.c b/libavcodec/pcx.c
index 2831f1bc3b..b21bdce5ce 100644
--- a/libavcodec/pcx.c
+++ b/libavcodec/pcx.c
@@ -254,6 +254,6 @@  const FFCodec ff_pcx_decoder = {
     .p.long_name  = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_PCX,
-    .decode       = pcx_decode_frame,
+    FF_CODEC_DECODE_CB(pcx_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c
index 1ccd7db92f..e6eb387f0d 100644
--- a/libavcodec/pcxenc.c
+++ b/libavcodec/pcxenc.c
@@ -197,7 +197,7 @@  const FFCodec ff_pcx_encoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PCX,
-    .encode2        = pcx_encode_frame,
+    FF_CODEC_ENCODE_CB(pcx_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24,
         AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE,
diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c
index 8b5eb5f816..8441b88d27 100644
--- a/libavcodec/pgssubdec.c
+++ b/libavcodec/pgssubdec.c
@@ -698,7 +698,7 @@  const FFCodec ff_pgssub_decoder = {
     .priv_data_size = sizeof(PGSSubContext),
     .init           = init_decoder,
     .close          = close_decoder,
-    .decode_sub     = decode,
+    FF_CODEC_DECODE_SUB_CB(decode),
     .p.priv_class   = &pgsdec_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/pgxdec.c b/libavcodec/pgxdec.c
index 01cd484da2..899e7a9994 100644
--- a/libavcodec/pgxdec.c
+++ b/libavcodec/pgxdec.c
@@ -164,5 +164,5 @@  const FFCodec ff_pgx_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PGX,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = pgx_decode_frame,
+    FF_CODEC_DECODE_CB(pgx_decode_frame),
 };
diff --git a/libavcodec/photocd.c b/libavcodec/photocd.c
index 48dc1b88c4..0f3001f2e1 100644
--- a/libavcodec/photocd.c
+++ b/libavcodec/photocd.c
@@ -464,7 +464,7 @@  const FFCodec ff_photocd_decoder = {
     .p.priv_class   = &photocd_class,
     .init           = photocd_decode_init,
     .close          = photocd_decode_close,
-    .decode         = photocd_decode_frame,
+    FF_CODEC_DECODE_CB(photocd_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .p.long_name    = NULL_IF_CONFIG_SMALL("Kodak Photo CD"),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/pictordec.c b/libavcodec/pictordec.c
index 3c32cbc4e6..ed0292c797 100644
--- a/libavcodec/pictordec.c
+++ b/libavcodec/pictordec.c
@@ -286,5 +286,5 @@  const FFCodec ff_pictor_decoder = {
     .p.id           = AV_CODEC_ID_PICTOR,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PicContext),
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c
index 12857919fe..18a6587257 100644
--- a/libavcodec/pixlet.c
+++ b/libavcodec/pixlet.c
@@ -699,7 +699,7 @@  const FFCodec ff_pixlet_decoder = {
     .p.id             = AV_CODEC_ID_PIXLET,
     .init             = pixlet_init,
     .close            = pixlet_close,
-    .decode           = pixlet_decode_frame,
+    FF_CODEC_DECODE_CB(pixlet_decode_frame),
     .priv_data_size   = sizeof(PixletContext),
     .p.capabilities   = AV_CODEC_CAP_DR1 |
                         AV_CODEC_CAP_FRAME_THREADS,
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index 59302c898a..6b44af59f2 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -1723,7 +1723,7 @@  const FFCodec ff_apng_decoder = {
     .priv_data_size = sizeof(PNGDecContext),
     .init           = png_dec_init,
     .close          = png_dec_end,
-    .decode         = decode_frame_apng,
+    FF_CODEC_DECODE_CB(decode_frame_apng),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
@@ -1740,7 +1740,7 @@  const FFCodec ff_png_decoder = {
     .priv_data_size = sizeof(PNGDecContext),
     .init           = png_dec_init,
     .close          = png_dec_end,
-    .decode         = decode_frame_png,
+    FF_CODEC_DECODE_CB(decode_frame_png),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/,
     .caps_internal  = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index f67f90cd14..aaa6453218 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -1119,7 +1119,7 @@  const FFCodec ff_png_encoder = {
     .priv_data_size = sizeof(PNGEncContext),
     .init           = png_enc_init,
     .close          = png_enc_close,
-    .encode2        = encode_png,
+    FF_CODEC_ENCODE_CB(encode_png),
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
@@ -1142,7 +1142,7 @@  const FFCodec ff_apng_encoder = {
     .priv_data_size = sizeof(PNGEncContext),
     .init           = png_enc_init,
     .close          = png_enc_close,
-    .encode2        = encode_apng,
+    FF_CODEC_ENCODE_CB(encode_apng),
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
         AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE,
diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
index a6f5d7c55d..f2d9b7e4b6 100644
--- a/libavcodec/pnmdec.c
+++ b/libavcodec/pnmdec.c
@@ -338,7 +338,7 @@  const FFCodec ff_pgm_decoder = {
     .p.id           = AV_CODEC_ID_PGM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
 
@@ -350,7 +350,7 @@  const FFCodec ff_pgmyuv_decoder = {
     .p.id           = AV_CODEC_ID_PGMYUV,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
 
@@ -362,7 +362,7 @@  const FFCodec ff_ppm_decoder = {
     .p.id           = AV_CODEC_ID_PPM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
 
@@ -374,7 +374,7 @@  const FFCodec ff_pbm_decoder = {
     .p.id           = AV_CODEC_ID_PBM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
 
@@ -386,7 +386,7 @@  const FFCodec ff_pam_decoder = {
     .p.id           = AV_CODEC_ID_PAM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
 
@@ -398,6 +398,6 @@  const FFCodec ff_pfm_decoder = {
     .p.id           = AV_CODEC_ID_PFM,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(PNMContext),
-    .decode         = pnm_decode_frame,
+    FF_CODEC_DECODE_CB(pnm_decode_frame),
 };
 #endif
diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c
index 020dbd218c..feb26b8bfa 100644
--- a/libavcodec/pnmenc.c
+++ b/libavcodec/pnmenc.c
@@ -157,7 +157,7 @@  const FFCodec ff_pgm_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PGM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pnm_encode_frame,
+    FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE
     },
@@ -172,7 +172,7 @@  const FFCodec ff_pgmyuv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PGMYUV,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pnm_encode_frame,
+    FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE
     },
@@ -187,7 +187,7 @@  const FFCodec ff_ppm_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PPM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pnm_encode_frame,
+    FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE
     },
@@ -202,7 +202,7 @@  const FFCodec ff_pbm_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PBM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pnm_encode_frame,
+    FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE,
                                                   AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -216,7 +216,7 @@  const FFCodec ff_pfm_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PFM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2        = pnm_encode_frame,
+    FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32,
                                                     AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c
index 46ca26150b..dba64a2489 100644
--- a/libavcodec/proresdec2.c
+++ b/libavcodec/proresdec2.c
@@ -878,7 +878,7 @@  const FFCodec ff_prores_decoder = {
     .priv_data_size = sizeof(ProresContext),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c
index 2f6bd89efd..914c3fb2c2 100644
--- a/libavcodec/proresenc_anatoliy.c
+++ b/libavcodec/proresenc_anatoliy.c
@@ -949,7 +949,7 @@  const FFCodec ff_prores_aw_encoder = {
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
     .close          = prores_encode_close,
-    .encode2        = prores_encode_frame,
+    FF_CODEC_ENCODE_CB(prores_encode_frame),
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.priv_class   = &prores_enc_class,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
@@ -965,7 +965,7 @@  const FFCodec ff_prores_encoder = {
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
     .close          = prores_encode_close,
-    .encode2        = prores_encode_frame,
+    FF_CODEC_ENCODE_CB(prores_encode_frame),
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.priv_class   = &prores_enc_class,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_prores_profiles),
diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c
index 429b623678..1062ca1443 100644
--- a/libavcodec/proresenc_kostya.c
+++ b/libavcodec/proresenc_kostya.c
@@ -1401,7 +1401,7 @@  const FFCodec ff_prores_ks_encoder = {
     .priv_data_size = sizeof(ProresContext),
     .init           = encode_init,
     .close          = encode_close,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
                           AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c
index db17cd5083..8a91d5e110 100644
--- a/libavcodec/prosumer.c
+++ b/libavcodec/prosumer.c
@@ -372,7 +372,7 @@  const FFCodec ff_prosumer_decoder = {
     .p.id           = AV_CODEC_ID_PROSUMER,
     .priv_data_size = sizeof(ProSumerContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .close          = decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/psd.c b/libavcodec/psd.c
index da802a5585..1d92163408 100644
--- a/libavcodec/psd.c
+++ b/libavcodec/psd.c
@@ -551,5 +551,5 @@  const FFCodec ff_psd_decoder = {
     .p.id             = AV_CODEC_ID_PSD,
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .priv_data_size   = sizeof(PSDContext),
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index aa971bd74d..10b84e57b0 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -218,7 +218,7 @@  FF_ENABLE_DEPRECATION_WARNINGS
 
         av_frame_unref(p->frame);
         p->got_frame = 0;
-        p->result = codec->decode(avctx, p->frame, &p->got_frame, p->avpkt);
+        p->result = codec->cb.decode(avctx, p->frame, &p->got_frame, p->avpkt);
 
         if ((p->result < 0 || !p->got_frame) && p->frame->buf[0])
             ff_thread_release_buffer(avctx, p->frame);
diff --git a/libavcodec/ptx.c b/libavcodec/ptx.c
index b782bf1db3..1102049347 100644
--- a/libavcodec/ptx.c
+++ b/libavcodec/ptx.c
@@ -92,5 +92,5 @@  const FFCodec ff_ptx_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PTX,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = ptx_decode_frame,
+    FF_CODEC_DECODE_CB(ptx_decode_frame),
 };
diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c
index 16ece70e63..1a4d308ac1 100644
--- a/libavcodec/qcelpdec.c
+++ b/libavcodec/qcelpdec.c
@@ -796,7 +796,7 @@  const FFCodec ff_qcelp_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_QCELP,
     .init           = qcelp_decode_init,
-    .decode         = qcelp_decode_frame,
+    FF_CODEC_DECODE_CB(qcelp_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .priv_data_size = sizeof(QCELPContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c
index 9d0b541964..427e8e8449 100644
--- a/libavcodec/qdm2.c
+++ b/libavcodec/qdm2.c
@@ -1877,7 +1877,7 @@  const FFCodec ff_qdm2_decoder = {
     .priv_data_size   = sizeof(QDM2Context),
     .init             = qdm2_decode_init,
     .close            = qdm2_decode_close,
-    .decode           = qdm2_decode_frame,
+    FF_CODEC_DECODE_CB(qdm2_decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/qdmc.c b/libavcodec/qdmc.c
index 4ef4be19f5..7c069a8012 100644
--- a/libavcodec/qdmc.c
+++ b/libavcodec/qdmc.c
@@ -736,7 +736,7 @@  const FFCodec ff_qdmc_decoder = {
     .priv_data_size   = sizeof(QDMCContext),
     .init             = qdmc_decode_init,
     .close            = qdmc_decode_close,
-    .decode           = qdmc_decode_frame,
+    FF_CODEC_DECODE_CB(qdmc_decode_frame),
     .flush            = qdmc_flush,
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c
index bf67f8523d..849d4a5cad 100644
--- a/libavcodec/qdrw.c
+++ b/libavcodec/qdrw.c
@@ -519,5 +519,5 @@  const FFCodec ff_qdraw_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_QDRAW,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c
index 0f33e87de1..9e787cb434 100644
--- a/libavcodec/qpeg.c
+++ b/libavcodec/qpeg.c
@@ -359,7 +359,7 @@  const FFCodec ff_qpeg_decoder = {
     .priv_data_size = sizeof(QpegContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 08eda5bc26..de4af1754d 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -984,7 +984,7 @@  const FFCodec ff_##x##_qsv_decoder = { \
     .p.type         = AVMEDIA_TYPE_VIDEO, \
     .p.id           = AV_CODEC_ID_##X, \
     .init           = qsv_decode_init, \
-    .decode         = qsv_decode_frame, \
+    FF_CODEC_DECODE_CB(qsv_decode_frame), \
     .flush          = qsv_decode_flush, \
     .close          = qsv_decode_close, \
     .bsfs           = bsf_name, \
diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c
index 3778fe66c2..b4cf9ea456 100644
--- a/libavcodec/qsvenc_h264.c
+++ b/libavcodec/qsvenc_h264.c
@@ -184,7 +184,7 @@  const FFCodec ff_h264_qsv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_H264,
     .init           = qsv_enc_init,
-    .encode2        = qsv_enc_frame,
+    FF_CODEC_ENCODE_CB(qsv_enc_frame),
     .close          = qsv_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index 5c1571f62f..36c2d484ad 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -298,7 +298,7 @@  const FFCodec ff_hevc_qsv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HEVC,
     .init           = qsv_enc_init,
-    .encode2        = qsv_enc_frame,
+    FF_CODEC_ENCODE_CB(qsv_enc_frame),
     .close          = qsv_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c
index 6bae0a0be9..825eb8dc06 100644
--- a/libavcodec/qsvenc_jpeg.c
+++ b/libavcodec/qsvenc_jpeg.c
@@ -86,7 +86,7 @@  const FFCodec ff_mjpeg_qsv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_MJPEG,
     .init           = qsv_enc_init,
-    .encode2        = qsv_enc_frame,
+    FF_CODEC_ENCODE_CB(qsv_enc_frame),
     .close          = qsv_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c
index 0ab1412abb..3f79b48cb8 100644
--- a/libavcodec/qsvenc_mpeg2.c
+++ b/libavcodec/qsvenc_mpeg2.c
@@ -99,7 +99,7 @@  const FFCodec ff_mpeg2_qsv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_MPEG2VIDEO,
     .init           = qsv_enc_init,
-    .encode2        = qsv_enc_frame,
+    FF_CODEC_ENCODE_CB(qsv_enc_frame),
     .close          = qsv_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
diff --git a/libavcodec/qsvenc_vp9.c b/libavcodec/qsvenc_vp9.c
index 6afbef195d..4b2a6ce77f 100644
--- a/libavcodec/qsvenc_vp9.c
+++ b/libavcodec/qsvenc_vp9.c
@@ -109,7 +109,7 @@  const FFCodec ff_vp9_qsv_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_VP9,
     .init           = qsv_enc_init,
-    .encode2        = qsv_enc_frame,
+    FF_CODEC_ENCODE_CB(qsv_enc_frame),
     .close          = qsv_enc_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c
index b7f114bdec..5e2139cce9 100644
--- a/libavcodec/qtrle.c
+++ b/libavcodec/qtrle.c
@@ -589,7 +589,7 @@  const FFCodec ff_qtrle_decoder = {
     .priv_data_size = sizeof(QtrleContext),
     .init           = qtrle_decode_init,
     .close          = qtrle_decode_end,
-    .decode         = qtrle_decode_frame,
+    FF_CODEC_DECODE_CB(qtrle_decode_frame),
     .flush          = qtrle_decode_flush,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c
index 04e98185e5..21c19eda23 100644
--- a/libavcodec/qtrleenc.c
+++ b/libavcodec/qtrleenc.c
@@ -406,7 +406,7 @@  const FFCodec ff_qtrle_encoder = {
     .p.id           = AV_CODEC_ID_QTRLE,
     .priv_data_size = sizeof(QtrleEncContext),
     .init           = qtrle_encode_init,
-    .encode2        = qtrle_encode_frame,
+    FF_CODEC_ENCODE_CB(qtrle_encode_frame),
     .close          = qtrle_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_ARGB, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
diff --git a/libavcodec/r210dec.c b/libavcodec/r210dec.c
index da20ffe067..b95f663aa5 100644
--- a/libavcodec/r210dec.c
+++ b/libavcodec/r210dec.c
@@ -109,7 +109,7 @@  const FFCodec ff_r210_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_R210,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -121,7 +121,7 @@  const FFCodec ff_r10k_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_R10K,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -133,7 +133,7 @@  const FFCodec ff_avrp_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AVRP,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/r210enc.c b/libavcodec/r210enc.c
index 88bbd4677d..cfff21cb23 100644
--- a/libavcodec/r210enc.c
+++ b/libavcodec/r210enc.c
@@ -98,7 +98,7 @@  const FFCodec ff_r210_encoder = {
     .p.id           = AV_CODEC_ID_R210,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -111,7 +111,7 @@  const FFCodec ff_r10k_encoder = {
     .p.id           = AV_CODEC_ID_R10K,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -124,7 +124,7 @@  const FFCodec ff_avrp_encoder = {
     .p.id           = AV_CODEC_ID_AVRP,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ra144dec.c b/libavcodec/ra144dec.c
index b795e327a2..bef6389bcf 100644
--- a/libavcodec/ra144dec.c
+++ b/libavcodec/ra144dec.c
@@ -133,7 +133,7 @@  const FFCodec ff_ra_144_decoder = {
     .p.id           = AV_CODEC_ID_RA_144,
     .priv_data_size = sizeof(RA144Context),
     .init           = ra144_decode_init,
-    .decode         = ra144_decode_frame,
+    FF_CODEC_DECODE_CB(ra144_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c
index ec65621060..66ac381e60 100644
--- a/libavcodec/ra144enc.c
+++ b/libavcodec/ra144enc.c
@@ -544,7 +544,7 @@  const FFCodec ff_ra_144_encoder = {
                       AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size = sizeof(RA144Context),
     .init           = ra144_encode_init,
-    .encode2        = ra144_encode_frame,
+    FF_CODEC_ENCODE_CB(ra144_encode_frame),
     .close          = ra144_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c
index f904d471a3..24d976fd92 100644
--- a/libavcodec/ra288.c
+++ b/libavcodec/ra288.c
@@ -244,7 +244,7 @@  const FFCodec ff_ra_288_decoder = {
     .p.id           = AV_CODEC_ID_RA_288,
     .priv_data_size = sizeof(RA288Context),
     .init           = ra288_decode_init,
-    .decode         = ra288_decode_frame,
+    FF_CODEC_DECODE_CB(ra288_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ralf.c b/libavcodec/ralf.c
index 3887c29ee9..16cb524a4e 100644
--- a/libavcodec/ralf.c
+++ b/libavcodec/ralf.c
@@ -521,7 +521,7 @@  const FFCodec ff_ralf_decoder = {
     .priv_data_size = sizeof(RALFContext),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush          = decode_flush,
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c
index 6966ada2d0..bcb619f11c 100644
--- a/libavcodec/rasc.c
+++ b/libavcodec/rasc.c
@@ -805,7 +805,7 @@  const FFCodec ff_rasc_decoder = {
     .priv_data_size   = sizeof(RASCContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .flush            = decode_flush,
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index 7ed7492337..c10b20d4f9 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -488,7 +488,7 @@  const FFCodec ff_rawvideo_decoder = {
     .priv_data_size = sizeof(RawVideoContext),
     .init           = raw_init_decoder,
     .close          = raw_close_decoder,
-    .decode         = raw_decode,
+    FF_CODEC_DECODE_CB(raw_decode),
     .p.priv_class   = &rawdec_class,
     .p.capabilities = AV_CODEC_CAP_PARAM_CHANGE,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c
index 1aa88d9db0..34d7a1bef4 100644
--- a/libavcodec/rawenc.c
+++ b/libavcodec/rawenc.c
@@ -88,6 +88,6 @@  const FFCodec ff_rawvideo_encoder = {
     .p.id           = AV_CODEC_ID_RAWVIDEO,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .init           = raw_encode_init,
-    .encode2        = raw_encode,
+    FF_CODEC_ENCODE_CB(raw_encode),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/realtextdec.c b/libavcodec/realtextdec.c
index 1612554461..e058b7494d 100644
--- a/libavcodec/realtextdec.c
+++ b/libavcodec/realtextdec.c
@@ -79,7 +79,7 @@  const FFCodec ff_realtext_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("RealText subtitle"),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_REALTEXT,
-    .decode_sub     = realtext_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(realtext_decode_frame),
     .init           = ff_ass_subtitle_header_default,
     .flush          = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c
index d5eab14c09..d4f09f456d 100644
--- a/libavcodec/rkmppdec.c
+++ b/libavcodec/rkmppdec.c
@@ -569,7 +569,7 @@  static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = {
         .priv_data_size = sizeof(RKMPPDecodeContext), \
         .init           = rkmpp_init_decoder, \
         .close          = rkmpp_close_decoder, \
-        .receive_frame  = rkmpp_receive_frame, \
+        FF_CODEC_RECEIVE_FRAME_CB(rkmpp_receive_frame), \
         .flush          = rkmpp_flush, \
         .p.priv_class   = &rkmpp_##NAME##_dec_class, \
         .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
diff --git a/libavcodec/rl2.c b/libavcodec/rl2.c
index 37c9bf5d82..e76b068970 100644
--- a/libavcodec/rl2.c
+++ b/libavcodec/rl2.c
@@ -225,7 +225,7 @@  const FFCodec ff_rl2_decoder = {
     .priv_data_size = sizeof(Rl2Context),
     .init           = rl2_decode_init,
     .close          = rl2_decode_end,
-    .decode         = rl2_decode_frame,
+    FF_CODEC_DECODE_CB(rl2_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c
index c444c2e635..18a5f23df0 100644
--- a/libavcodec/roqaudioenc.c
+++ b/libavcodec/roqaudioenc.c
@@ -195,7 +195,7 @@  const FFCodec ff_roq_dpcm_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .priv_data_size = sizeof(ROQDPCMContext),
     .init           = roq_dpcm_encode_init,
-    .encode2        = roq_dpcm_encode_frame,
+    FF_CODEC_ENCODE_CB(roq_dpcm_encode_frame),
     .close          = roq_dpcm_encode_close,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
                                                      AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c
index 99aa1ce24c..3e796b18bc 100644
--- a/libavcodec/roqvideodec.c
+++ b/libavcodec/roqvideodec.c
@@ -241,7 +241,7 @@  const FFCodec ff_roq_decoder = {
     .priv_data_size = sizeof(RoqContext),
     .init           = roq_decode_init,
     .close          = roq_decode_end,
-    .decode         = roq_decode_frame,
+    FF_CODEC_DECODE_CB(roq_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index ef7861088d..8cdc9f389c 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -1125,7 +1125,7 @@  const FFCodec ff_roq_encoder = {
     .p.id                 = AV_CODEC_ID_ROQ,
     .priv_data_size       = sizeof(RoqEncContext),
     .init                 = roq_encode_init,
-    .encode2              = roq_encode_frame,
+    FF_CODEC_ENCODE_CB(roq_encode_frame),
     .close                = roq_encode_end,
     .p.pix_fmts           = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P,
                                                         AV_PIX_FMT_NONE },
diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c
index 4482dfc8c8..703f05e7b8 100644
--- a/libavcodec/rpza.c
+++ b/libavcodec/rpza.c
@@ -294,7 +294,7 @@  const FFCodec ff_rpza_decoder = {
     .priv_data_size = sizeof(RpzaContext),
     .init           = rpza_decode_init,
     .close          = rpza_decode_end,
-    .decode         = rpza_decode_frame,
+    FF_CODEC_DECODE_CB(rpza_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/rpzaenc.c b/libavcodec/rpzaenc.c
index c4c3843f1c..50b68bb8b3 100644
--- a/libavcodec/rpzaenc.c
+++ b/libavcodec/rpzaenc.c
@@ -851,7 +851,7 @@  const FFCodec ff_rpza_encoder = {
     .priv_data_size = sizeof(RpzaContext),
     .p.priv_class   = &rpza_class,
     .init           = rpza_encode_init,
-    .encode2        = rpza_encode_frame,
+    FF_CODEC_ENCODE_CB(rpza_encode_frame),
     .close          = rpza_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB555,
diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c
index 3891cf24e4..f4fa786718 100644
--- a/libavcodec/rscc.c
+++ b/libavcodec/rscc.c
@@ -368,7 +368,7 @@  const FFCodec ff_rscc_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RSCC,
     .init           = rscc_init,
-    .decode         = rscc_decode_frame,
+    FF_CODEC_DECODE_CB(rscc_decode_frame),
     .close          = rscc_close,
     .priv_data_size = sizeof(RsccContext),
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c
index 8c2188bc05..8f8a755ac3 100644
--- a/libavcodec/rv10.c
+++ b/libavcodec/rv10.c
@@ -689,7 +689,7 @@  const FFCodec ff_rv10_decoder = {
     .priv_data_size = sizeof(RVDecContext),
     .init           = rv10_decode_init,
     .close          = rv10_decode_end,
-    .decode         = rv10_decode_frame,
+    FF_CODEC_DECODE_CB(rv10_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .p.max_lowres   = 3,
@@ -707,7 +707,7 @@  const FFCodec ff_rv20_decoder = {
     .priv_data_size = sizeof(RVDecContext),
     .init           = rv10_decode_init,
     .close          = rv10_decode_end,
-    .decode         = rv10_decode_frame,
+    FF_CODEC_DECODE_CB(rv10_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .flush          = ff_mpeg_flush,
diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c
index 8df8f0a060..7560e6026a 100644
--- a/libavcodec/rv10enc.c
+++ b/libavcodec/rv10enc.c
@@ -73,7 +73,7 @@  const FFCodec ff_rv10_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c
index 916f505ecc..422188e21a 100644
--- a/libavcodec/rv20enc.c
+++ b/libavcodec/rv20enc.c
@@ -70,7 +70,7 @@  const FFCodec ff_rv20_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c
index 7d5e1acc97..8fd8498d9a 100644
--- a/libavcodec/rv30.c
+++ b/libavcodec/rv30.c
@@ -299,7 +299,7 @@  const FFCodec ff_rv30_decoder = {
     .priv_data_size        = sizeof(RV34DecContext),
     .init                  = rv30_decode_init,
     .close                 = ff_rv34_decode_end,
-    .decode                = ff_rv34_decode_frame,
+    FF_CODEC_DECODE_CB(ff_rv34_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                              AV_CODEC_CAP_FRAME_THREADS,
     .flush                 = ff_mpeg_flush,
diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c
index b95f0d7919..b15f3cddfc 100644
--- a/libavcodec/rv40.c
+++ b/libavcodec/rv40.c
@@ -582,7 +582,7 @@  const FFCodec ff_rv40_decoder = {
     .priv_data_size        = sizeof(RV34DecContext),
     .init                  = rv40_decode_init,
     .close                 = ff_rv34_decode_end,
-    .decode                = ff_rv34_decode_frame,
+    FF_CODEC_DECODE_CB(ff_rv34_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                              AV_CODEC_CAP_FRAME_THREADS,
     .flush                 = ff_mpeg_flush,
diff --git a/libavcodec/s302m.c b/libavcodec/s302m.c
index 68533be6c6..fb7b6e240b 100644
--- a/libavcodec/s302m.c
+++ b/libavcodec/s302m.c
@@ -234,7 +234,7 @@  const FFCodec ff_s302m_decoder = {
     .p.id           = AV_CODEC_ID_S302M,
     .p.priv_class   = &s302m_class,
     .priv_data_size = sizeof(S302Context),
-    .decode         = s302m_decode_frame,
+    FF_CODEC_DECODE_CB(s302m_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
 };
diff --git a/libavcodec/s302menc.c b/libavcodec/s302menc.c
index 737fc94697..b6f9501bf2 100644
--- a/libavcodec/s302menc.c
+++ b/libavcodec/s302menc.c
@@ -179,7 +179,7 @@  const FFCodec ff_s302m_encoder = {
                              AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
     .priv_data_size        = sizeof(S302MEncContext),
     .init                  = s302m_encode_init,
-    .encode2               = s302m_encode2_frame,
+    FF_CODEC_ENCODE_CB(s302m_encode2_frame),
     .p.sample_fmts         = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
                                                             AV_SAMPLE_FMT_S16,
                                                             AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c
index f2cf5783af..b9f6128a3e 100644
--- a/libavcodec/samidec.c
+++ b/libavcodec/samidec.c
@@ -188,7 +188,7 @@  const FFCodec ff_sami_decoder = {
     .priv_data_size = sizeof(SAMIContext),
     .init           = sami_init,
     .close          = sami_close,
-    .decode_sub     = sami_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(sami_decode_frame),
     .flush          = sami_flush,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c
index b5e12fccc1..7f094c8bbf 100644
--- a/libavcodec/sanm.c
+++ b/libavcodec/sanm.c
@@ -1524,7 +1524,7 @@  const FFCodec ff_sanm_decoder = {
     .priv_data_size = sizeof(SANMVideoContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/sbcdec.c b/libavcodec/sbcdec.c
index 6b79136fac..99af7e1652 100644
--- a/libavcodec/sbcdec.c
+++ b/libavcodec/sbcdec.c
@@ -372,7 +372,7 @@  const FFCodec ff_sbc_decoder = {
     .p.id                  = AV_CODEC_ID_SBC,
     .priv_data_size        = sizeof(SBCDecContext),
     .init                  = sbc_decode_init,
-    .decode                = sbc_decode_frame,
+    FF_CODEC_DECODE_CB(sbc_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c
index db1370f1c7..18ac4fb9bd 100644
--- a/libavcodec/sbcenc.c
+++ b/libavcodec/sbcenc.c
@@ -351,7 +351,7 @@  const FFCodec ff_sbc_encoder = {
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
     .priv_data_size        = sizeof(SBCEncContext),
     .init                  = sbc_encode_init,
-    .encode2               = sbc_encode_frame,
+    FF_CODEC_ENCODE_CB(sbc_encode_frame),
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
 #if FF_API_OLD_CHANNEL_LAYOUT
     .p.channel_layouts     = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c
index c744db2539..0623b73c84 100644
--- a/libavcodec/scpr.c
+++ b/libavcodec/scpr.c
@@ -675,7 +675,7 @@  const FFCodec ff_scpr_decoder = {
     .priv_data_size   = sizeof(SCPRContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/screenpresso.c b/libavcodec/screenpresso.c
index b2b71a00b3..8a4a8cde9e 100644
--- a/libavcodec/screenpresso.c
+++ b/libavcodec/screenpresso.c
@@ -189,7 +189,7 @@  const FFCodec ff_screenpresso_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SCREENPRESSO,
     .init           = screenpresso_init,
-    .decode         = screenpresso_decode_frame,
+    FF_CODEC_DECODE_CB(screenpresso_decode_frame),
     .close          = screenpresso_close,
     .priv_data_size = sizeof(ScreenpressoContext),
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/sga.c b/libavcodec/sga.c
index cb6d8db3f4..cdd37feb70 100644
--- a/libavcodec/sga.c
+++ b/libavcodec/sga.c
@@ -526,7 +526,7 @@  const FFCodec ff_sga_decoder = {
     .p.id           = AV_CODEC_ID_SGA_VIDEO,
     .priv_data_size = sizeof(SGAVideoContext),
     .init           = sga_decode_init,
-    .decode         = sga_decode_frame,
+    FF_CODEC_DECODE_CB(sga_decode_frame),
     .close          = sga_decode_end,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c
index a0669590ed..b23e205c3b 100644
--- a/libavcodec/sgidec.c
+++ b/libavcodec/sgidec.c
@@ -292,7 +292,7 @@  const FFCodec ff_sgi_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SGI,
     .priv_data_size = sizeof(SgiState),
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .init           = sgi_decode_init,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c
index 8a3c1ddde1..93cb95f07f 100644
--- a/libavcodec/sgienc.c
+++ b/libavcodec/sgienc.c
@@ -278,7 +278,7 @@  const FFCodec ff_sgi_encoder = {
     .priv_data_size = sizeof(SgiContext),
     .p.priv_class = &sgi_class,
     .init      = encode_init,
-    .encode2   = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
         AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE,
diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c
index 8e00fdf183..e04b9b1cad 100644
--- a/libavcodec/sgirledec.c
+++ b/libavcodec/sgirledec.c
@@ -137,7 +137,7 @@  const FFCodec ff_sgirle_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SGIRLE,
     .init           = sgirle_decode_init,
-    .decode         = sgirle_decode_frame,
+    FF_CODEC_DECODE_CB(sgirle_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/sheervideo.c b/libavcodec/sheervideo.c
index ecde9e1637..327bf85eda 100644
--- a/libavcodec/sheervideo.c
+++ b/libavcodec/sheervideo.c
@@ -2006,5 +2006,5 @@  const FFCodec ff_sheervideo_decoder = {
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .priv_data_size   = sizeof(SheerVideoContext),
     .close            = decode_end,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c
index 96dec88191..27074e930d 100644
--- a/libavcodec/shorten.c
+++ b/libavcodec/shorten.c
@@ -811,7 +811,7 @@  const FFCodec ff_shorten_decoder = {
     .priv_data_size = sizeof(ShortenContext),
     .init           = shorten_decode_init,
     .close          = shorten_decode_close,
-    .decode         = shorten_decode_frame,
+    FF_CODEC_DECODE_CB(shorten_decode_frame),
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DELAY |
                       AV_CODEC_CAP_DR1 |
diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c
index dde39f154a..9d11f2c5c6 100644
--- a/libavcodec/sipr.c
+++ b/libavcodec/sipr.c
@@ -569,7 +569,7 @@  const FFCodec ff_sipr_decoder = {
     .p.id           = AV_CODEC_ID_SIPR,
     .priv_data_size = sizeof(SiprContext),
     .init           = sipr_decoder_init,
-    .decode         = sipr_decode_frame,
+    FF_CODEC_DECODE_CB(sipr_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/siren.c b/libavcodec/siren.c
index 70e8267dad..b613ee113d 100644
--- a/libavcodec/siren.c
+++ b/libavcodec/siren.c
@@ -849,7 +849,7 @@  const FFCodec ff_siren_decoder = {
     .p.id           = AV_CODEC_ID_SIREN,
     .init           = siren_init,
     .close          = siren_close,
-    .decode         = siren_decode,
+    FF_CODEC_DECODE_CB(siren_decode),
     .flush          = siren_flush,
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
@@ -865,7 +865,7 @@  const FFCodec ff_msnsiren_decoder = {
     .p.id           = AV_CODEC_ID_MSNSIREN,
     .init           = siren_init,
     .close          = siren_close,
-    .decode         = siren_decode,
+    FF_CODEC_DECODE_CB(siren_decode),
     .flush          = siren_flush,
     .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF |
                       AV_CODEC_CAP_DR1,
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
index 1ef2161dbb..179c70f1ee 100644
--- a/libavcodec/smacker.c
+++ b/libavcodec/smacker.c
@@ -730,7 +730,7 @@  const FFCodec ff_smacker_decoder = {
     .priv_data_size = sizeof(SmackVContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -741,7 +741,7 @@  const FFCodec ff_smackaud_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_SMACKAUDIO,
     .init           = smka_decode_init,
-    .decode         = smka_decode_frame,
+    FF_CODEC_DECODE_CB(smka_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/smc.c b/libavcodec/smc.c
index 2f87937c49..313d8edba6 100644
--- a/libavcodec/smc.c
+++ b/libavcodec/smc.c
@@ -476,7 +476,7 @@  const FFCodec ff_smc_decoder = {
     .priv_data_size = sizeof(SmcContext),
     .init           = smc_decode_init,
     .close          = smc_decode_end,
-    .decode         = smc_decode_frame,
+    FF_CODEC_DECODE_CB(smc_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c
index a9f6c483a7..e1137098d0 100644
--- a/libavcodec/smcenc.c
+++ b/libavcodec/smcenc.c
@@ -555,7 +555,7 @@  const FFCodec ff_smc_encoder = {
     .p.id           = AV_CODEC_ID_SMC,
     .priv_data_size = sizeof(SMCContext),
     .init           = smc_encode_init,
-    .encode2        = smc_encode_frame,
+    FF_CODEC_ENCODE_CB(smc_encode_frame),
     .close          = smc_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8,
diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c
index 4208707da0..92ff87731c 100644
--- a/libavcodec/snowdec.c
+++ b/libavcodec/snowdec.c
@@ -661,7 +661,7 @@  const FFCodec ff_snow_decoder = {
     .priv_data_size = sizeof(SnowContext),
     .init           = ff_snow_common_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index b5a5e57a91..410aa0f0e5 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -1919,7 +1919,7 @@  const FFCodec ff_snow_encoder = {
     .p.id           = AV_CODEC_ID_SNOW,
     .priv_data_size = sizeof(SnowContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P,
diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c
index f20365485d..dfb055d80e 100644
--- a/libavcodec/sonic.c
+++ b/libavcodec/sonic.c
@@ -1084,7 +1084,7 @@  const FFCodec ff_sonic_decoder = {
     .priv_data_size = sizeof(SonicContext),
     .init           = sonic_decode_init,
     .close          = sonic_decode_close,
-    .decode         = sonic_decode_frame,
+    FF_CODEC_DECODE_CB(sonic_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
@@ -1098,7 +1098,7 @@  const FFCodec ff_sonic_encoder = {
     .p.id           = AV_CODEC_ID_SONIC,
     .priv_data_size = sizeof(SonicContext),
     .init           = sonic_encode_init,
-    .encode2        = sonic_encode_frame,
+    FF_CODEC_ENCODE_CB(sonic_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
     .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
@@ -1114,7 +1114,7 @@  const FFCodec ff_sonic_ls_encoder = {
     .p.id           = AV_CODEC_ID_SONIC_LS,
     .priv_data_size = sizeof(SonicContext),
     .init           = sonic_encode_init,
-    .encode2        = sonic_encode_frame,
+    FF_CODEC_ENCODE_CB(sonic_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
     .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/sp5xdec.c b/libavcodec/sp5xdec.c
index 99647efa52..aa4d3d771b 100644
--- a/libavcodec/sp5xdec.c
+++ b/libavcodec/sp5xdec.c
@@ -100,7 +100,7 @@  const FFCodec ff_sp5x_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.max_lowres   = 3,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
@@ -116,7 +116,7 @@  const FFCodec ff_amv_decoder = {
     .priv_data_size = sizeof(MJpegDecodeContext),
     .init           = ff_mjpeg_decode_init,
     .close          = ff_mjpeg_decode_end,
-    .receive_frame  = ff_mjpeg_receive_frame,
+    FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame),
     .p.max_lowres   = 3,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
diff --git a/libavcodec/speedhq.c b/libavcodec/speedhq.c
index fbe2d584d0..4cfd4ce73d 100644
--- a/libavcodec/speedhq.c
+++ b/libavcodec/speedhq.c
@@ -731,7 +731,7 @@  const FFCodec ff_speedhq_decoder = {
     .p.id           = AV_CODEC_ID_SPEEDHQ,
     .priv_data_size = sizeof(SHQContext),
     .init           = speedhq_decode_init,
-    .decode         = speedhq_decode_frame,
+    FF_CODEC_DECODE_CB(speedhq_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c
index 22213b823d..55b378abce 100644
--- a/libavcodec/speedhqenc.c
+++ b/libavcodec/speedhqenc.c
@@ -278,7 +278,7 @@  const FFCodec ff_speedhq_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c
index 28a6b67a66..3251eda820 100644
--- a/libavcodec/speexdec.c
+++ b/libavcodec/speexdec.c
@@ -1582,7 +1582,7 @@  const FFCodec ff_speex_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_SPEEX,
     .init           = speex_decode_init,
-    .decode         = speex_decode_frame,
+    FF_CODEC_DECODE_CB(speex_decode_frame),
     .close          = speex_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .priv_data_size = sizeof(SpeexContext),
diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c
index aa975d16c7..705df007d6 100644
--- a/libavcodec/srtdec.c
+++ b/libavcodec/srtdec.c
@@ -96,7 +96,7 @@  const FFCodec ff_srt_decoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_SUBRIP,
     .init         = ff_ass_subtitle_header_default,
-    .decode_sub   = srt_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(srt_decode_frame),
     .flush        = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -110,7 +110,7 @@  const FFCodec ff_subrip_decoder = {
     .p.type       = AVMEDIA_TYPE_SUBTITLE,
     .p.id         = AV_CODEC_ID_SUBRIP,
     .init         = ff_ass_subtitle_header_default,
-    .decode_sub   = srt_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(srt_decode_frame),
     .flush        = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c
index 8ff799b684..51456c8b9d 100644
--- a/libavcodec/srtenc.c
+++ b/libavcodec/srtenc.c
@@ -300,7 +300,7 @@  const FFCodec ff_srt_encoder = {
     .p.id           = AV_CODEC_ID_SUBRIP,
     .priv_data_size = sizeof(SRTContext),
     .init           = srt_encode_init,
-    .encode_sub     = srt_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(srt_encode_frame),
     .close          = srt_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -314,7 +314,7 @@  const FFCodec ff_subrip_encoder = {
     .p.id           = AV_CODEC_ID_SUBRIP,
     .priv_data_size = sizeof(SRTContext),
     .init           = srt_encode_init,
-    .encode_sub     = srt_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(srt_encode_frame),
     .close          = srt_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -328,7 +328,7 @@  const FFCodec ff_text_encoder = {
     .p.id           = AV_CODEC_ID_TEXT,
     .priv_data_size = sizeof(SRTContext),
     .init           = srt_encode_init,
-    .encode_sub     = text_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(text_encode_frame),
     .close          = srt_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/subviewerdec.c b/libavcodec/subviewerdec.c
index 9001dd3d45..b6acea93f5 100644
--- a/libavcodec/subviewerdec.c
+++ b/libavcodec/subviewerdec.c
@@ -70,7 +70,7 @@  const FFCodec ff_subviewer_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("SubViewer subtitle"),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_SUBVIEWER,
-    .decode_sub     = subviewer_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(subviewer_decode_frame),
     .init           = ff_ass_subtitle_header_default,
     .flush          = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
diff --git a/libavcodec/sunrast.c b/libavcodec/sunrast.c
index 65b4f359b2..e543757a39 100644
--- a/libavcodec/sunrast.c
+++ b/libavcodec/sunrast.c
@@ -211,5 +211,5 @@  const FFCodec ff_sunrast_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SUNRAST,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = sunrast_decode_frame,
+    FF_CODEC_DECODE_CB(sunrast_decode_frame),
 };
diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c
index acc609c3b6..6245e592c7 100644
--- a/libavcodec/sunrastenc.c
+++ b/libavcodec/sunrastenc.c
@@ -215,7 +215,7 @@  const FFCodec ff_sunrast_encoder = {
     .p.id           = AV_CODEC_ID_SUNRAST,
     .priv_data_size = sizeof(SUNRASTContext),
     .init           = sunrast_encode_init,
-    .encode2        = sunrast_encode_frame,
+    FF_CODEC_ENCODE_CB(sunrast_encode_frame),
     .p.priv_class   = &sunrast_class,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24,
                                                   AV_PIX_FMT_PAL8,
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index e0a599bb36..7cd623ff18 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -851,7 +851,7 @@  const FFCodec ff_svq1_decoder = {
     .priv_data_size = sizeof(SVQ1Context),
     .init           = svq1_decode_init,
     .close          = svq1_decode_end,
-    .decode         = svq1_decode_frame,
+    FF_CODEC_DECODE_CB(svq1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .flush          = svq1_flush,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P,
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index 706bc2e42e..a0205e8bb7 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -684,7 +684,7 @@  const FFCodec ff_svq1_encoder = {
     .priv_data_size = sizeof(SVQ1EncContext),
     .p.priv_class   = &svq1enc_class,
     .init           = svq1_encode_init,
-    .encode2        = svq1_encode_frame,
+    FF_CODEC_ENCODE_CB(svq1_encode_frame),
     .close          = svq1_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P,
                                                      AV_PIX_FMT_NONE },
diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c
index 69949b7e63..f038466922 100644
--- a/libavcodec/svq3.c
+++ b/libavcodec/svq3.c
@@ -1596,7 +1596,7 @@  const FFCodec ff_svq3_decoder = {
     .priv_data_size = sizeof(SVQ3Context),
     .init           = svq3_decode_init,
     .close          = svq3_decode_end,
-    .decode         = svq3_decode_frame,
+    FF_CODEC_DECODE_CB(svq3_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND |
                       AV_CODEC_CAP_DR1             |
                       AV_CODEC_CAP_DELAY,
diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c
index 0ef42adc81..47978fcd4b 100644
--- a/libavcodec/takdec.c
+++ b/libavcodec/takdec.c
@@ -949,7 +949,7 @@  const FFCodec ff_tak_decoder = {
     .priv_data_size   = sizeof(TAKDecContext),
     .init             = tak_decode_init,
     .close            = tak_decode_close,
-    .decode           = tak_decode_frame,
+    FF_CODEC_DECODE_CB(tak_decode_frame),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P,
diff --git a/libavcodec/targa.c b/libavcodec/targa.c
index d6c46f8dce..833576c6b3 100644
--- a/libavcodec/targa.c
+++ b/libavcodec/targa.c
@@ -312,5 +312,5 @@  const FFCodec ff_targa_decoder = {
     .p.id           = AV_CODEC_ID_TARGA,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(TargaContext),
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
 };
diff --git a/libavcodec/targa_y216dec.c b/libavcodec/targa_y216dec.c
index c6339ab92a..bf33dc8a68 100644
--- a/libavcodec/targa_y216dec.c
+++ b/libavcodec/targa_y216dec.c
@@ -79,7 +79,7 @@  const FFCodec ff_targa_y216_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_TARGA_Y216,
     .init         = y216_decode_init,
-    .decode       = y216_decode_frame,
+    FF_CODEC_DECODE_CB(y216_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c
index 9170eff956..84e2086869 100644
--- a/libavcodec/targaenc.c
+++ b/libavcodec/targaenc.c
@@ -210,7 +210,7 @@  const FFCodec ff_targa_encoder = {
     .priv_data_size = sizeof(TargaContext),
     .p.priv_class   = &targa_class,
     .init           = targa_encode_init,
-    .encode2        = targa_encode_frame,
+    FF_CODEC_ENCODE_CB(targa_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8,
         AV_PIX_FMT_NONE
diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c
index 701cd8b9ad..0cf17d75dd 100644
--- a/libavcodec/tdsc.c
+++ b/libavcodec/tdsc.c
@@ -627,7 +627,7 @@  const FFCodec ff_tdsc_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_TDSC,
     .init           = tdsc_init,
-    .decode         = tdsc_decode_frame,
+    FF_CODEC_DECODE_CB(tdsc_decode_frame),
     .close          = tdsc_close,
     .priv_data_size = sizeof(TDSCContext),
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c
index f77d7aebe9..08b5fbede1 100644
--- a/libavcodec/tests/avcodec.c
+++ b/libavcodec/tests/avcodec.c
@@ -64,7 +64,7 @@  int main(void){
     while (codec = av_codec_iterate(&iter)) {
         const FFCodec *const codec2 = ffcodec(codec);
         const AVCodecDescriptor *desc;
-        int is_decoder, is_encoder;
+        int is_decoder = 0, is_encoder = 0;
 
         if (!codec->name) {
             AV_LOG("Codec for format %s has no name\n",
@@ -102,17 +102,38 @@  int main(void){
                                      AV_CODEC_CAP_OTHER_THREADS)))
             ERR("Codec %s has private-only threading support\n");
 
-        is_decoder = av_codec_is_decoder(codec);
-        is_encoder = av_codec_is_encoder(codec);
-        if (!!is_decoder + !!is_encoder != 1) {
-            ERR("Codec %s is decoder and encoder or neither.\n");
+        switch (codec2->cb_type) {
+        case FF_CODEC_CB_TYPE_DECODE:
+        case FF_CODEC_CB_TYPE_DECODE_SUB:
+        case FF_CODEC_CB_TYPE_RECEIVE_FRAME:
+            is_decoder = 1;
+            break;
+        case FF_CODEC_CB_TYPE_ENCODE:
+        case FF_CODEC_CB_TYPE_ENCODE_SUB:
+        case FF_CODEC_CB_TYPE_RECEIVE_PACKET:
+            is_encoder = 1;
+            break;
+        default:
+            ERR("Codec %s has unknown cb_type\n");
             continue;
         }
+        if (is_decoder != av_codec_is_decoder(codec) ||
+            is_encoder != av_codec_is_encoder(codec)) {
+            ERR("Codec %s cb_type and av_codec_is_(de|en)coder inconsistent.\n");
+            continue;
+        }
+#define CHECK(TYPE, type) (codec2->cb_type == FF_CODEC_CB_TYPE_ ## TYPE && !codec2->cb.type)
+        if (CHECK(DECODE, decode) || CHECK(DECODE_SUB, decode_sub) ||
+            CHECK(RECEIVE_PACKET, receive_packet) ||
+            CHECK(ENCODE, encode) || CHECK(ENCODE_SUB, encode_sub) ||
+            CHECK(RECEIVE_FRAME, receive_frame)) {
+            ERR_EXT("Codec %s does not implement its %s callback.\n",
+                    is_decoder ? "decoding" : "encoding");
+        }
+#undef CHECK
         if (is_encoder) {
-            if (codec->type == AVMEDIA_TYPE_SUBTITLE ^ !!codec2->encode_sub)
+            if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB))
                 ERR("Encoder %s is both subtitle encoder and not subtitle encoder.");
-            if (!!codec2->encode_sub + !!codec2->encode2 + !!codec2->receive_packet != 1)
-                ERR("Encoder %s does not implement exactly one encode API.\n");
             if (codec2->update_thread_context || codec2->update_thread_context_for_user || codec2->bsfs)
                 ERR("Encoder %s has decoder-only thread functions or bsf.\n");
             if (codec->type == AVMEDIA_TYPE_AUDIO) {
@@ -135,14 +156,11 @@  int main(void){
                 codec->capabilities & AV_CODEC_CAP_ENCODER_FLUSH)
                 ERR("Frame-threaded encoder %s claims to support flushing\n");
         } else {
-            if (codec->type == AVMEDIA_TYPE_SUBTITLE && !codec2->decode_sub)
+            if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB))
                 ERR("Subtitle decoder %s does not implement decode_sub callback\n");
             if (codec->type == AVMEDIA_TYPE_SUBTITLE && codec2->bsfs)
                 ERR("Automatic bitstream filtering unsupported for subtitles; "
                     "yet decoder %s has it set\n");
-            if (codec->type != AVMEDIA_TYPE_SUBTITLE !=
-                !!codec2->decode + !!codec2->receive_frame)
-                ERR("Decoder %s does not implement exactly one decode API.\n");
             if (codec->capabilities & (AV_CODEC_CAP_SMALL_LAST_FRAME    |
                                        AV_CODEC_CAP_VARIABLE_FRAME_SIZE |
                                        AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE |
diff --git a/libavcodec/textdec.c b/libavcodec/textdec.c
index 48e7e14602..09de0ad8fd 100644
--- a/libavcodec/textdec.c
+++ b/libavcodec/textdec.c
@@ -86,7 +86,7 @@  const FFCodec ff_text_decoder = {
     .priv_data_size = sizeof(TextContext),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_TEXT,
-    .decode_sub     = text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(text_decode_frame),
     .init           = ff_ass_subtitle_header_default,
     .p.priv_class   = &textsub_decoder_class,
     .flush          = text_flush,
@@ -110,7 +110,7 @@  const FFCodec ff_vplayer_decoder = {
     .priv_data_size = sizeof(TextContext),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_VPLAYER,
-    .decode_sub     = text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(text_decode_frame),
     .init           = linebreak_init,
     .p.priv_class   = &textsub_decoder_class,
     .flush          = text_flush,
@@ -125,7 +125,7 @@  const FFCodec ff_stl_decoder = {
     .priv_data_size = sizeof(TextContext),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_STL,
-    .decode_sub     = text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(text_decode_frame),
     .init           = linebreak_init,
     .p.priv_class   = &textsub_decoder_class,
     .flush          = text_flush,
@@ -140,7 +140,7 @@  const FFCodec ff_pjs_decoder = {
     .priv_data_size = sizeof(TextContext),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_PJS,
-    .decode_sub     = text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(text_decode_frame),
     .init           = linebreak_init,
     .p.priv_class   = &textsub_decoder_class,
     .flush          = text_flush,
@@ -155,7 +155,7 @@  const FFCodec ff_subviewer1_decoder = {
     .priv_data_size = sizeof(TextContext),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_SUBVIEWER1,
-    .decode_sub     = text_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(text_decode_frame),
     .init           = linebreak_init,
     .p.priv_class   = &textsub_decoder_class,
     .flush          = text_flush,
diff --git a/libavcodec/tiertexseqv.c b/libavcodec/tiertexseqv.c
index 06d9c39880..618275a57c 100644
--- a/libavcodec/tiertexseqv.c
+++ b/libavcodec/tiertexseqv.c
@@ -269,7 +269,7 @@  const FFCodec ff_tiertexseqvideo_decoder = {
     .priv_data_size = sizeof(SeqVideoContext),
     .init           = seqvideo_decode_init,
     .close          = seqvideo_decode_end,
-    .decode         = seqvideo_decode_frame,
+    FF_CODEC_DECODE_CB(seqvideo_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 3d5b3c28ac..e4a5d3c537 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -2185,7 +2185,7 @@  const FFCodec ff_tiff_decoder = {
     .priv_data_size = sizeof(TiffContext),
     .init           = tiff_init,
     .close          = tiff_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.priv_class   = &tiff_decoder_class,
diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c
index 17ff542354..2f2742e566 100644
--- a/libavcodec/tiffenc.c
+++ b/libavcodec/tiffenc.c
@@ -578,7 +578,7 @@  const FFCodec ff_tiff_encoder = {
     .init           = encode_init,
     .close          = encode_close,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8,
         AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64LE,
diff --git a/libavcodec/tmv.c b/libavcodec/tmv.c
index 263a63aa55..d1685a0ae7 100644
--- a/libavcodec/tmv.c
+++ b/libavcodec/tmv.c
@@ -92,7 +92,7 @@  const FFCodec ff_tmv_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_TMV,
     .init           = tmv_decode_init,
-    .decode         = tmv_decode_frame,
+    FF_CODEC_DECODE_CB(tmv_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/truemotion1.c b/libavcodec/truemotion1.c
index 7ef025b43e..64d9b8fed1 100644
--- a/libavcodec/truemotion1.c
+++ b/libavcodec/truemotion1.c
@@ -918,7 +918,7 @@  const FFCodec ff_truemotion1_decoder = {
     .priv_data_size = sizeof(TrueMotion1Context),
     .init           = truemotion1_decode_init,
     .close          = truemotion1_decode_end,
-    .decode         = truemotion1_decode_frame,
+    FF_CODEC_DECODE_CB(truemotion1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c
index a89f999ce5..3fd956ee1e 100644
--- a/libavcodec/truemotion2.c
+++ b/libavcodec/truemotion2.c
@@ -1016,7 +1016,7 @@  const FFCodec ff_truemotion2_decoder = {
     .priv_data_size = sizeof(TM2Context),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c
index 0383cb090f..a3686fc1ac 100644
--- a/libavcodec/truemotion2rt.c
+++ b/libavcodec/truemotion2rt.c
@@ -226,7 +226,7 @@  const FFCodec ff_truemotion2rt_decoder = {
     .p.id           = AV_CODEC_ID_TRUEMOTION2RT,
     .priv_data_size = sizeof(TrueMotion2RTContext),
     .init           = truemotion2rt_decode_init,
-    .decode         = truemotion2rt_decode_frame,
+    FF_CODEC_DECODE_CB(truemotion2rt_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c
index a8bf43d2a4..e472cb8241 100644
--- a/libavcodec/truespeech.c
+++ b/libavcodec/truespeech.c
@@ -363,7 +363,7 @@  const FFCodec ff_truespeech_decoder = {
     .p.id           = AV_CODEC_ID_TRUESPEECH,
     .priv_data_size = sizeof(TSContext),
     .init           = truespeech_decode_init,
-    .decode         = truespeech_decode_frame,
+    FF_CODEC_DECODE_CB(truespeech_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c
index a841fd2c9d..7343d7aace 100644
--- a/libavcodec/tscc.c
+++ b/libavcodec/tscc.c
@@ -178,7 +178,7 @@  const FFCodec ff_tscc_decoder = {
     .priv_data_size = sizeof(CamtasiaContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c
index 6879f42cd9..136f1f76d9 100644
--- a/libavcodec/tscc2.c
+++ b/libavcodec/tscc2.c
@@ -364,7 +364,7 @@  const FFCodec ff_tscc2_decoder = {
     .priv_data_size = sizeof(TSCC2Context),
     .init           = tscc2_decode_init,
     .close          = tscc2_decode_end,
-    .decode         = tscc2_decode_frame,
+    FF_CODEC_DECODE_CB(tscc2_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/tta.c b/libavcodec/tta.c
index 506a61b881..74be140d51 100644
--- a/libavcodec/tta.c
+++ b/libavcodec/tta.c
@@ -428,7 +428,7 @@  const FFCodec ff_tta_decoder = {
     .priv_data_size = sizeof(TTAContext),
     .init           = tta_decode_init,
     .close          = tta_decode_close,
-    .decode         = tta_decode_frame,
+    FF_CODEC_DECODE_CB(tta_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF,
     .p.priv_class   = &tta_decoder_class,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c
index b52cb21d2c..b7d4aafdc3 100644
--- a/libavcodec/ttaenc.c
+++ b/libavcodec/ttaenc.c
@@ -210,7 +210,7 @@  const FFCodec ff_tta_encoder = {
     .priv_data_size = sizeof(TTAEncContext),
     .init           = tta_encode_init,
     .close          = tta_encode_close,
-    .encode2        = tta_encode_frame,
+    FF_CODEC_ENCODE_CB(tta_encode_frame),
     .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8,
                                                      AV_SAMPLE_FMT_S16,
diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c
index 98a36caf5c..be1d8fb2e8 100644
--- a/libavcodec/ttmlenc.c
+++ b/libavcodec/ttmlenc.c
@@ -390,7 +390,7 @@  const FFCodec ff_ttml_encoder = {
     .p.id           = AV_CODEC_ID_TTML,
     .priv_data_size = sizeof(TTMLContext),
     .init           = ttml_encode_init,
-    .encode_sub     = ttml_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(ttml_encode_frame),
     .close          = ttml_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/twinvqdec.c b/libavcodec/twinvqdec.c
index 7f0eeb0bfb..6dfa57f007 100644
--- a/libavcodec/twinvqdec.c
+++ b/libavcodec/twinvqdec.c
@@ -422,7 +422,7 @@  const FFCodec ff_twinvq_decoder = {
     .priv_data_size = sizeof(TwinVQContext),
     .init           = twinvq_decode_init,
     .close          = ff_twinvq_decode_close,
-    .decode         = ff_twinvq_decode_frame,
+    FF_CODEC_DECODE_CB(ff_twinvq_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/txd.c b/libavcodec/txd.c
index 854ef1522d..8b1da773a3 100644
--- a/libavcodec/txd.c
+++ b/libavcodec/txd.c
@@ -170,5 +170,5 @@  const FFCodec ff_txd_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_TXD,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = txd_decode_frame,
+    FF_CODEC_DECODE_CB(txd_decode_frame),
 };
diff --git a/libavcodec/ulti.c b/libavcodec/ulti.c
index c5be1dffda..a8bec9cce2 100644
--- a/libavcodec/ulti.c
+++ b/libavcodec/ulti.c
@@ -426,7 +426,7 @@  const FFCodec ff_ulti_decoder = {
     .priv_data_size = sizeof(UltimotionDecodeContext),
     .init           = ulti_decode_init,
     .close          = ulti_decode_end,
-    .decode         = ulti_decode_frame,
+    FF_CODEC_DECODE_CB(ulti_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 34d97022b7..eb7e505a62 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -74,13 +74,17 @@  void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size)
 int av_codec_is_encoder(const AVCodec *avcodec)
 {
     const FFCodec *const codec = ffcodec(avcodec);
-    return codec && (codec->encode_sub || codec->encode2 || codec->receive_packet);
+    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_ENCODE     ||
+                     codec->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB ||
+                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET);
 }
 
 int av_codec_is_decoder(const AVCodec *avcodec)
 {
     const FFCodec *const codec = ffcodec(avcodec);
-    return codec && (codec->decode || codec->decode_sub || codec->receive_frame);
+    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_DECODE     ||
+                     codec->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB ||
+                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME);
 }
 
 int ff_set_dimensions(AVCodecContext *s, int width, int height)
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c
index 051f90c9db..03ee8f0b10 100644
--- a/libavcodec/utvideodec.c
+++ b/libavcodec/utvideodec.c
@@ -1058,7 +1058,7 @@  const FFCodec ff_utvideo_decoder = {
     .priv_data_size = sizeof(UtvideoContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c
index e1f7086152..15a53a6094 100644
--- a/libavcodec/utvideoenc.c
+++ b/libavcodec/utvideoenc.c
@@ -651,7 +651,7 @@  const FFCodec ff_utvideo_encoder = {
     .priv_data_size = sizeof(UtvideoContext),
     .p.priv_class   = &utvideo_class,
     .init           = utvideo_encode_init,
-    .encode2        = utvideo_encode_frame,
+    FF_CODEC_ENCODE_CB(utvideo_encode_frame),
     .close          = utvideo_encode_close,
     .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
diff --git a/libavcodec/v210dec.c b/libavcodec/v210dec.c
index f208a0786f..b5e1d728a7 100644
--- a/libavcodec/v210dec.c
+++ b/libavcodec/v210dec.c
@@ -218,7 +218,7 @@  const FFCodec ff_v210_decoder = {
     .p.id           = AV_CODEC_ID_V210,
     .priv_data_size = sizeof(V210DecContext),
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 |
                       AV_CODEC_CAP_SLICE_THREADS |
                       AV_CODEC_CAP_FRAME_THREADS,
diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
index 2582571823..9ac923571c 100644
--- a/libavcodec/v210enc.c
+++ b/libavcodec/v210enc.c
@@ -160,7 +160,7 @@  const FFCodec ff_v210_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .priv_data_size = sizeof(V210EncContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v210x.c b/libavcodec/v210x.c
index 34eb54e447..18d3e637be 100644
--- a/libavcodec/v210x.c
+++ b/libavcodec/v210x.c
@@ -125,7 +125,7 @@  const FFCodec ff_v210x_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_V210X,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v308dec.c b/libavcodec/v308dec.c
index 6c85bc585d..5f8cbc634b 100644
--- a/libavcodec/v308dec.c
+++ b/libavcodec/v308dec.c
@@ -78,7 +78,7 @@  const FFCodec ff_v308_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V308,
     .init         = v308_decode_init,
-    .decode       = v308_decode_frame,
+    FF_CODEC_DECODE_CB(v308_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v308enc.c b/libavcodec/v308enc.c
index 08e6ddaecb..c4f07a123d 100644
--- a/libavcodec/v308enc.c
+++ b/libavcodec/v308enc.c
@@ -77,7 +77,7 @@  const FFCodec ff_v308_encoder = {
     .p.id         = AV_CODEC_ID_V308,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = v308_encode_init,
-    .encode2      = v308_encode_frame,
+    FF_CODEC_ENCODE_CB(v308_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE },
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v408dec.c b/libavcodec/v408dec.c
index 32ea98b724..02024959c7 100644
--- a/libavcodec/v408dec.c
+++ b/libavcodec/v408dec.c
@@ -88,7 +88,7 @@  const FFCodec ff_ayuv_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_AYUV,
     .init         = v408_decode_init,
-    .decode       = v408_decode_frame,
+    FF_CODEC_DECODE_CB(v408_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -100,7 +100,7 @@  const FFCodec ff_v408_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V408,
     .init         = v408_decode_init,
-    .decode       = v408_decode_frame,
+    FF_CODEC_DECODE_CB(v408_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v408enc.c b/libavcodec/v408enc.c
index 52d5e19802..157ed85104 100644
--- a/libavcodec/v408enc.c
+++ b/libavcodec/v408enc.c
@@ -87,7 +87,7 @@  const FFCodec ff_ayuv_encoder = {
     .p.id         = AV_CODEC_ID_AYUV,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = v408_encode_init,
-    .encode2      = v408_encode_frame,
+    FF_CODEC_ENCODE_CB(v408_encode_frame),
     .p.pix_fmts   = pix_fmt,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
@@ -100,7 +100,7 @@  const FFCodec ff_v408_encoder = {
     .p.id         = AV_CODEC_ID_V408,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = v408_encode_init,
-    .encode2      = v408_encode_frame,
+    FF_CODEC_ENCODE_CB(v408_encode_frame),
     .p.pix_fmts   = pix_fmt,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v410dec.c b/libavcodec/v410dec.c
index bb1dd5d0c6..f6d675c508 100644
--- a/libavcodec/v410dec.c
+++ b/libavcodec/v410dec.c
@@ -120,7 +120,7 @@  const FFCodec ff_v410_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V410,
     .init         = v410_decode_init,
-    .decode       = v410_decode_frame,
+    FF_CODEC_DECODE_CB(v410_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
                     AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c
index 32966d9176..88a2ce346b 100644
--- a/libavcodec/v410enc.c
+++ b/libavcodec/v410enc.c
@@ -81,7 +81,7 @@  const FFCodec ff_v410_encoder = {
     .p.id         = AV_CODEC_ID_V410,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = v410_encode_init,
-    .encode2      = v410_encode_frame,
+    FF_CODEC_ENCODE_CB(v410_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE },
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index 4c521eba34..8a51dec3fa 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -248,7 +248,7 @@  static const AVOption options[] = {
         .priv_data_size = sizeof(V4L2m2mPriv), \
         .p.priv_class   = &v4l2_m2m_ ## NAME ## _dec_class, \
         .init           = v4l2_decode_init, \
-        .receive_frame  = v4l2_receive_frame, \
+        FF_CODEC_RECEIVE_FRAME_CB(v4l2_receive_frame), \
         .close          = v4l2_decode_close, \
         .bsfs           = bsf_name, \
         .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c
index 1d90de2b9d..20f81df750 100644
--- a/libavcodec/v4l2_m2m_enc.c
+++ b/libavcodec/v4l2_m2m_enc.c
@@ -429,7 +429,7 @@  static const FFCodecDefault v4l2_m2m_defaults[] = {
         .priv_data_size = sizeof(V4L2m2mPriv), \
         .p.priv_class   = &v4l2_m2m_ ## NAME ##_enc_class, \
         .init           = v4l2_encode_init, \
-        .receive_packet = v4l2_receive_packet, \
+        FF_CODEC_RECEIVE_PACKET_CB(v4l2_receive_packet), \
         .close          = v4l2_encode_close, \
         .defaults       = v4l2_m2m_defaults, \
         .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 69d5abfe55..7a6b54ab6f 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -1332,7 +1332,7 @@  const FFCodec ff_h264_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_H264,
     .priv_data_size = sizeof(VAAPIEncodeH264Context),
     .init           = &vaapi_encode_h264_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &vaapi_encode_h264_close,
     .p.priv_class   = &vaapi_encode_h264_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index a77cb21c82..0be32588c0 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -1309,7 +1309,7 @@  const FFCodec ff_hevc_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_HEVC,
     .priv_data_size = sizeof(VAAPIEncodeH265Context),
     .init           = &vaapi_encode_h265_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &vaapi_encode_h265_close,
     .p.priv_class   = &vaapi_encode_h265_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
index d42c1d7b1e..ddc1d0fc8d 100644
--- a/libavcodec/vaapi_encode_mjpeg.c
+++ b/libavcodec/vaapi_encode_mjpeg.c
@@ -559,7 +559,7 @@  const FFCodec ff_mjpeg_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_MJPEG,
     .priv_data_size = sizeof(VAAPIEncodeMJPEGContext),
     .init           = &vaapi_encode_mjpeg_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &vaapi_encode_mjpeg_close,
     .p.priv_class   = &vaapi_encode_mjpeg_class,
     .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1,
diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c
index ef24dcbbb9..0e30efe119 100644
--- a/libavcodec/vaapi_encode_mpeg2.c
+++ b/libavcodec/vaapi_encode_mpeg2.c
@@ -697,7 +697,7 @@  const FFCodec ff_mpeg2_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_MPEG2VIDEO,
     .priv_data_size = sizeof(VAAPIEncodeMPEG2Context),
     .init           = &vaapi_encode_mpeg2_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &vaapi_encode_mpeg2_close,
     .p.priv_class   = &vaapi_encode_mpeg2_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c
index 9824fff052..0e384d5a58 100644
--- a/libavcodec/vaapi_encode_vp8.c
+++ b/libavcodec/vaapi_encode_vp8.c
@@ -252,7 +252,7 @@  const FFCodec ff_vp8_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_VP8,
     .priv_data_size = sizeof(VAAPIEncodeVP8Context),
     .init           = &vaapi_encode_vp8_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &ff_vaapi_encode_close,
     .p.priv_class   = &vaapi_encode_vp8_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
index dd87825c28..9ca4e451a3 100644
--- a/libavcodec/vaapi_encode_vp9.c
+++ b/libavcodec/vaapi_encode_vp9.c
@@ -294,7 +294,7 @@  const FFCodec ff_vp9_vaapi_encoder = {
     .p.id           = AV_CODEC_ID_VP9,
     .priv_data_size = sizeof(VAAPIEncodeVP9Context),
     .init           = &vaapi_encode_vp9_init,
-    .receive_packet = &ff_vaapi_encode_receive_packet,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &ff_vaapi_encode_close,
     .p.priv_class   = &vaapi_encode_vp9_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
diff --git a/libavcodec/vb.c b/libavcodec/vb.c
index 1a05bd949f..82b4ea85ca 100644
--- a/libavcodec/vb.c
+++ b/libavcodec/vb.c
@@ -286,7 +286,7 @@  const FFCodec ff_vb_decoder = {
     .priv_data_size = sizeof(VBDecContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/vble.c b/libavcodec/vble.c
index 85b1fec855..f7ab17d621 100644
--- a/libavcodec/vble.c
+++ b/libavcodec/vble.c
@@ -209,7 +209,7 @@  const FFCodec ff_vble_decoder = {
     .priv_data_size = sizeof(VBLEContext),
     .init           = vble_decode_init,
     .close          = vble_decode_close,
-    .decode         = vble_decode_frame,
+    FF_CODEC_DECODE_CB(vble_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 0f5a07ff33..3e746e64cb 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -1209,7 +1209,7 @@  const FFCodec ff_vc1_decoder = {
     .priv_data_size = sizeof(VC1Context),
     .init           = vc1_decode_init,
     .close          = ff_vc1_decode_end,
-    .decode         = vc1_decode_frame,
+    FF_CODEC_DECODE_CB(vc1_decode_frame),
     .flush          = ff_mpeg_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -1247,7 +1247,7 @@  const FFCodec ff_wmv3_decoder = {
     .priv_data_size = sizeof(VC1Context),
     .init           = vc1_decode_init,
     .close          = ff_vc1_decode_end,
-    .decode         = vc1_decode_frame,
+    FF_CODEC_DECODE_CB(vc1_decode_frame),
     .flush          = ff_mpeg_flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
@@ -1286,7 +1286,7 @@  const FFCodec ff_wmv3image_decoder = {
     .priv_data_size = sizeof(VC1Context),
     .init           = vc1_decode_init,
     .close          = ff_vc1_decode_end,
-    .decode         = vc1_decode_frame,
+    FF_CODEC_DECODE_CB(vc1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .flush          = vc1_sprite_flush,
@@ -1306,7 +1306,7 @@  const FFCodec ff_vc1image_decoder = {
     .priv_data_size = sizeof(VC1Context),
     .init           = vc1_decode_init,
     .close          = ff_vc1_decode_end,
-    .decode         = vc1_decode_frame,
+    FF_CODEC_DECODE_CB(vc1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
     .flush          = vc1_sprite_flush,
diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c
index e1b8b7ffae..1e3127f080 100644
--- a/libavcodec/vc2enc.c
+++ b/libavcodec/vc2enc.c
@@ -1234,7 +1234,7 @@  const FFCodec ff_vc2_encoder = {
     .priv_data_size = sizeof(VC2EncContext),
     .init           = vc2_encode_init,
     .close          = vc2_encode_end,
-    .encode2        = vc2_encode_frame,
+    FF_CODEC_ENCODE_CB(vc2_encode_frame),
     .p.priv_class   = &vc2enc_class,
     .defaults       = vc2enc_defaults,
     .p.pix_fmts     = allowed_pix_fmts
diff --git a/libavcodec/vcr1.c b/libavcodec/vcr1.c
index d062700259..4aed1eeafb 100644
--- a/libavcodec/vcr1.c
+++ b/libavcodec/vcr1.c
@@ -128,7 +128,7 @@  const FFCodec ff_vcr1_decoder = {
     .p.id           = AV_CODEC_ID_VCR1,
     .priv_data_size = sizeof(VCR1Context),
     .init           = vcr1_decode_init,
-    .decode         = vcr1_decode_frame,
+    FF_CODEC_DECODE_CB(vcr1_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
index 61c24f9110..270496b7a7 100644
--- a/libavcodec/videotoolboxenc.c
+++ b/libavcodec/videotoolboxenc.c
@@ -2732,7 +2732,7 @@  const FFCodec ff_h264_videotoolbox_encoder = {
     .priv_data_size   = sizeof(VTEncContext),
     .p.pix_fmts       = avc_pix_fmts,
     .init             = vtenc_init,
-    .encode2          = vtenc_frame,
+    FF_CODEC_ENCODE_CB(vtenc_frame),
     .close            = vtenc_close,
     .p.priv_class     = &h264_videotoolbox_class,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
@@ -2767,7 +2767,7 @@  const FFCodec ff_hevc_videotoolbox_encoder = {
     .priv_data_size   = sizeof(VTEncContext),
     .p.pix_fmts       = hevc_pix_fmts,
     .init             = vtenc_init,
-    .encode2          = vtenc_frame,
+    FF_CODEC_ENCODE_CB(vtenc_frame),
     .close            = vtenc_close,
     .p.priv_class     = &hevc_videotoolbox_class,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
@@ -2806,7 +2806,7 @@  const FFCodec ff_prores_videotoolbox_encoder = {
     .priv_data_size   = sizeof(VTEncContext),
     .p.pix_fmts       = prores_pix_fmts,
     .init             = vtenc_init,
-    .encode2          = vtenc_frame,
+    FF_CODEC_ENCODE_CB(vtenc_frame),
     .close            = vtenc_close,
     .p.priv_class     = &prores_videotoolbox_class,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/vima.c b/libavcodec/vima.c
index e429855245..73276056c2 100644
--- a/libavcodec/vima.c
+++ b/libavcodec/vima.c
@@ -213,7 +213,7 @@  const FFCodec ff_adpcm_vima_decoder = {
     .p.type       = AVMEDIA_TYPE_AUDIO,
     .p.id         = AV_CODEC_ID_ADPCM_VIMA,
     .init         = decode_init,
-    .decode       = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/vmdaudio.c b/libavcodec/vmdaudio.c
index b81e5b0ced..2e6e358b64 100644
--- a/libavcodec/vmdaudio.c
+++ b/libavcodec/vmdaudio.c
@@ -235,7 +235,7 @@  const FFCodec ff_vmdaudio_decoder = {
     .p.id           = AV_CODEC_ID_VMDAUDIO,
     .priv_data_size = sizeof(VmdAudioContext),
     .init           = vmdaudio_decode_init,
-    .decode         = vmdaudio_decode_frame,
+    FF_CODEC_DECODE_CB(vmdaudio_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/vmdvideo.c b/libavcodec/vmdvideo.c
index fd48dc3255..947f09b73b 100644
--- a/libavcodec/vmdvideo.c
+++ b/libavcodec/vmdvideo.c
@@ -472,7 +472,7 @@  const FFCodec ff_vmdvideo_decoder = {
     .priv_data_size = sizeof(VmdVideoContext),
     .init           = vmdvideo_decode_init,
     .close          = vmdvideo_decode_end,
-    .decode         = vmdvideo_decode_frame,
+    FF_CODEC_DECODE_CB(vmdvideo_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c
index e7db38e85c..cc790984ad 100644
--- a/libavcodec/vmnc.c
+++ b/libavcodec/vmnc.c
@@ -581,7 +581,7 @@  const FFCodec ff_vmnc_decoder = {
     .priv_data_size = sizeof(VmncContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c
index 433fbfc6f9..6ba0e1d811 100644
--- a/libavcodec/vorbisdec.c
+++ b/libavcodec/vorbisdec.c
@@ -1892,7 +1892,7 @@  const FFCodec ff_vorbis_decoder = {
     .priv_data_size  = sizeof(vorbis_context),
     .init            = vorbis_decode_init,
     .close           = vorbis_decode_close,
-    .decode          = vorbis_decode_frame,
+    FF_CODEC_DECODE_CB(vorbis_decode_frame),
     .flush           = vorbis_decode_flush,
     .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal   = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index a6c5cfa8c7..0db8aeb2b5 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -1302,7 +1302,7 @@  const FFCodec ff_vorbis_encoder = {
     .p.id           = AV_CODEC_ID_VORBIS,
     .priv_data_size = sizeof(vorbis_enc_context),
     .init           = vorbis_encode_init,
-    .encode2        = vorbis_encode_frame,
+    FF_CODEC_ENCODE_CB(vorbis_encode_frame),
     .close          = vorbis_encode_close,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 528029203d..1a745331f4 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -3176,7 +3176,7 @@  const FFCodec ff_theora_decoder = {
     .priv_data_size        = sizeof(Vp3DecodeContext),
     .init                  = theora_decode_init,
     .close                 = vp3_decode_end,
-    .decode                = vp3_decode_frame,
+    FF_CODEC_DECODE_CB(vp3_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                              AV_CODEC_CAP_FRAME_THREADS,
     .flush                 = vp3_decode_flush,
@@ -3194,7 +3194,7 @@  const FFCodec ff_vp3_decoder = {
     .priv_data_size        = sizeof(Vp3DecodeContext),
     .init                  = vp3_decode_init,
     .close                 = vp3_decode_end,
-    .decode                = vp3_decode_frame,
+    FF_CODEC_DECODE_CB(vp3_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                              AV_CODEC_CAP_FRAME_THREADS,
     .flush                 = vp3_decode_flush,
@@ -3212,7 +3212,7 @@  const FFCodec ff_vp4_decoder = {
     .priv_data_size        = sizeof(Vp3DecodeContext),
     .init                  = vp3_decode_init,
     .close                 = vp3_decode_end,
-    .decode                = vp3_decode_frame,
+    FF_CODEC_DECODE_CB(vp3_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND |
                              AV_CODEC_CAP_FRAME_THREADS,
     .flush                 = vp3_decode_flush,
diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c
index 167fda4bfc..7ec381b5e5 100644
--- a/libavcodec/vp5.c
+++ b/libavcodec/vp5.c
@@ -311,7 +311,7 @@  const FFCodec ff_vp5_decoder = {
     .priv_data_size = sizeof(VP56Context),
     .init           = vp5_decode_init,
     .close          = vp56_free,
-    .decode         = ff_vp56_decode_frame,
+    FF_CODEC_DECODE_CB(ff_vp56_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index 313b499623..19dc754fee 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -720,7 +720,7 @@  const FFCodec ff_vp6_decoder = {
     .priv_data_size = sizeof(VP56Context),
     .init           = vp6_decode_init,
     .close          = vp6_decode_free,
-    .decode         = ff_vp56_decode_frame,
+    FF_CODEC_DECODE_CB(ff_vp56_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
@@ -734,7 +734,7 @@  const FFCodec ff_vp6f_decoder = {
     .priv_data_size = sizeof(VP56Context),
     .init           = vp6_decode_init,
     .close          = vp6_decode_free,
-    .decode         = ff_vp56_decode_frame,
+    FF_CODEC_DECODE_CB(ff_vp56_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
@@ -748,7 +748,7 @@  const FFCodec ff_vp6a_decoder = {
     .priv_data_size = 2 /* Main context + alpha context */ * sizeof(VP56Context),
     .init           = vp6_decode_init,
     .close          = vp6_decode_free,
-    .decode         = ff_vp56_decode_frame,
+    FF_CODEC_DECODE_CB(ff_vp56_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index acb61ceede..f521f2c9de 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -2947,7 +2947,7 @@  const FFCodec ff_vp7_decoder = {
     .priv_data_size        = sizeof(VP8Context),
     .init                  = vp7_decode_init,
     .close                 = ff_vp8_decode_free,
-    .decode                = vp7_decode_frame,
+    FF_CODEC_DECODE_CB(vp7_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
     .flush                 = vp8_decode_flush,
@@ -2963,7 +2963,7 @@  const FFCodec ff_vp8_decoder = {
     .priv_data_size        = sizeof(VP8Context),
     .init                  = ff_vp8_decode_init,
     .close                 = ff_vp8_decode_free,
-    .decode                = ff_vp8_decode_frame,
+    FF_CODEC_DECODE_CB(ff_vp8_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
                              AV_CODEC_CAP_SLICE_THREADS,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE |
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 8f2c52da87..fee79fb45b 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -1874,7 +1874,7 @@  const FFCodec ff_vp9_decoder = {
     .priv_data_size        = sizeof(VP9Context),
     .init                  = vp9_decode_init,
     .close                 = vp9_decode_free,
-    .decode                = vp9_decode_frame,
+    FF_CODEC_DECODE_CB(vp9_decode_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP |
                              FF_CODEC_CAP_SLICE_THREAD_HAS_MF |
diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c
index e8555e2570..62f930ed94 100644
--- a/libavcodec/vqavideo.c
+++ b/libavcodec/vqavideo.c
@@ -854,7 +854,7 @@  const FFCodec ff_vqa_decoder = {
     .priv_data_size = sizeof(VqaContext),
     .init           = vqa_decode_init,
     .close          = vqa_decode_end,
-    .decode         = vqa_decode_frame,
+    FF_CODEC_DECODE_CB(vqa_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .defaults       = vqa_defaults,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index 8bb03e5b4f..efd9e0fdd0 100644
--- a/libavcodec/wavpack.c
+++ b/libavcodec/wavpack.c
@@ -1710,7 +1710,7 @@  const FFCodec ff_wavpack_decoder = {
     .priv_data_size = sizeof(WavpackContext),
     .init           = wavpack_decode_init,
     .close          = wavpack_decode_end,
-    .decode         = wavpack_decode_frame,
+    FF_CODEC_DECODE_CB(wavpack_decode_frame),
     .flush          = wavpack_decode_flush,
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c
index ac14d0c4f3..1f95768c09 100644
--- a/libavcodec/wavpackenc.c
+++ b/libavcodec/wavpackenc.c
@@ -2969,7 +2969,7 @@  const FFCodec ff_wavpack_encoder = {
     .priv_data_size = sizeof(WavPackEncodeContext),
     .p.priv_class   = &wavpack_encoder_class,
     .init           = wavpack_encode_init,
-    .encode2        = wavpack_encode_frame,
+    FF_CODEC_ENCODE_CB(wavpack_encode_frame),
     .close          = wavpack_encode_close,
     .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
     .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8P,
diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c
index 8dfc1363a5..ac135f6859 100644
--- a/libavcodec/wcmv.c
+++ b/libavcodec/wcmv.c
@@ -248,7 +248,7 @@  const FFCodec ff_wcmv_decoder = {
     .priv_data_size   = sizeof(WCMVContext),
     .init             = decode_init,
     .close            = decode_close,
-    .decode           = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities   = AV_CODEC_CAP_DR1,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE |
                         FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index a0b51ac1e7..1b5e943a6e 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -1562,7 +1562,7 @@  const FFCodec ff_webp_decoder = {
     .p.id           = AV_CODEC_ID_WEBP,
     .priv_data_size = sizeof(WebPContext),
     .init           = webp_decode_init,
-    .decode         = webp_decode_frame,
+    FF_CODEC_DECODE_CB(webp_decode_frame),
     .close          = webp_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/webvttdec.c b/libavcodec/webvttdec.c
index 8cb7fea070..0179fc26d2 100644
--- a/libavcodec/webvttdec.c
+++ b/libavcodec/webvttdec.c
@@ -103,7 +103,7 @@  const FFCodec ff_webvtt_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("WebVTT subtitle"),
     .p.type         = AVMEDIA_TYPE_SUBTITLE,
     .p.id           = AV_CODEC_ID_WEBVTT,
-    .decode_sub     = webvtt_decode_frame,
+    FF_CODEC_DECODE_SUB_CB(webvtt_decode_frame),
     .init           = ff_ass_subtitle_header_default,
     .flush          = ff_ass_decoder_flush,
     .priv_data_size = sizeof(FFASSDecoderContext),
diff --git a/libavcodec/webvttenc.c b/libavcodec/webvttenc.c
index 7f514ed940..e433bb4579 100644
--- a/libavcodec/webvttenc.c
+++ b/libavcodec/webvttenc.c
@@ -218,7 +218,7 @@  const FFCodec ff_webvtt_encoder = {
     .p.id           = AV_CODEC_ID_WEBVTT,
     .priv_data_size = sizeof(WebVTTContext),
     .init           = webvtt_encode_init,
-    .encode_sub     = webvtt_encode_frame,
+    FF_CODEC_ENCODE_SUB_CB(webvtt_encode_frame),
     .close          = webvtt_encode_close,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c
index 945fd8c843..825bd6cdbb 100644
--- a/libavcodec/wmadec.c
+++ b/libavcodec/wmadec.c
@@ -1007,7 +1007,7 @@  const FFCodec ff_wmav1_decoder = {
     .priv_data_size = sizeof(WMACodecContext),
     .init           = wma_decode_init,
     .close          = ff_wma_end,
-    .decode         = wma_decode_superframe,
+    FF_CODEC_DECODE_CB(wma_decode_superframe),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
@@ -1024,7 +1024,7 @@  const FFCodec ff_wmav2_decoder = {
     .priv_data_size = sizeof(WMACodecContext),
     .init           = wma_decode_init,
     .close          = ff_wma_end,
-    .decode         = wma_decode_superframe,
+    FF_CODEC_DECODE_CB(wma_decode_superframe),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index fd1fb8ad97..28a7546eb5 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -440,7 +440,7 @@  const FFCodec ff_wmav1_encoder = {
     .p.id           = AV_CODEC_ID_WMAV1,
     .priv_data_size = sizeof(WMACodecContext),
     .init           = encode_init,
-    .encode2        = encode_superframe,
+    FF_CODEC_ENCODE_CB(encode_superframe),
     .close          = ff_wma_end,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
@@ -455,7 +455,7 @@  const FFCodec ff_wmav2_encoder = {
     .p.id           = AV_CODEC_ID_WMAV2,
     .priv_data_size = sizeof(WMACodecContext),
     .init           = encode_init,
-    .encode2        = encode_superframe,
+    FF_CODEC_ENCODE_CB(encode_superframe),
     .close          = ff_wma_end,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index daa775314d..9a8d6cc276 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -1336,7 +1336,7 @@  const FFCodec ff_wmalossless_decoder = {
     .priv_data_size = sizeof(WmallDecodeCtx),
     .init           = decode_init,
     .close          = decode_close,
-    .decode         = decode_packet,
+    FF_CODEC_DECODE_CB(decode_packet),
     .flush          = flush,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index 245241aa50..9cf763acd4 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -2088,7 +2088,7 @@  const FFCodec ff_wmapro_decoder = {
     .priv_data_size = sizeof(WMAProDecodeCtx),
     .init           = wmapro_decode_init,
     .close          = wmapro_decode_end,
-    .decode         = wmapro_decode_packet,
+    FF_CODEC_DECODE_CB(wmapro_decode_packet),
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1,
     .flush          = wmapro_flush,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
@@ -2104,7 +2104,7 @@  const FFCodec ff_xma1_decoder = {
     .priv_data_size = sizeof(XMADecodeCtx),
     .init           = xma_decode_init,
     .close          = xma_decode_end,
-    .decode         = xma_decode_packet,
+    FF_CODEC_DECODE_CB(xma_decode_packet),
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
@@ -2119,7 +2119,7 @@  const FFCodec ff_xma2_decoder = {
     .priv_data_size = sizeof(XMADecodeCtx),
     .init           = xma_decode_init,
     .close          = xma_decode_end,
-    .decode         = xma_decode_packet,
+    FF_CODEC_DECODE_CB(xma_decode_packet),
     .flush          = xma_flush,
     .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c
index 571dd5803b..c52ab876b2 100644
--- a/libavcodec/wmavoice.c
+++ b/libavcodec/wmavoice.c
@@ -2006,7 +2006,7 @@  const FFCodec ff_wmavoice_decoder = {
     .priv_data_size   = sizeof(WMAVoiceContext),
     .init             = wmavoice_decode_init,
     .close            = wmavoice_decode_end,
-    .decode           = wmavoice_decode_packet,
+    FF_CODEC_DECODE_CB(wmavoice_decode_packet),
     .p.capabilities   = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
     .caps_internal    = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .flush            = wmavoice_flush,
diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c
index 249200bf23..bf0e609c0b 100644
--- a/libavcodec/wmv2dec.c
+++ b/libavcodec/wmv2dec.c
@@ -599,7 +599,7 @@  const FFCodec ff_wmv2_decoder = {
     .priv_data_size = sizeof(WMV2DecContext),
     .init           = wmv2_decode_init,
     .close          = wmv2_decode_end,
-    .decode         = ff_h263_decode_frame,
+    FF_CODEC_DECODE_CB(ff_h263_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index a4d15e1d55..88211ac179 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -241,7 +241,7 @@  const FFCodec ff_wmv2_encoder = {
     .p.priv_class   = &ff_mpv_enc_class,
     .priv_data_size = sizeof(WMV2EncContext),
     .init           = wmv2_encode_init,
-    .encode2        = ff_mpv_encode_picture,
+    FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
diff --git a/libavcodec/wnv1.c b/libavcodec/wnv1.c
index 913b42a78f..0cf2181a48 100644
--- a/libavcodec/wnv1.c
+++ b/libavcodec/wnv1.c
@@ -138,7 +138,7 @@  const FFCodec ff_wnv1_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WNV1,
     .init           = decode_init,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c
index 6794dd2045..3af007d478 100644
--- a/libavcodec/wrapped_avframe.c
+++ b/libavcodec/wrapped_avframe.c
@@ -113,7 +113,7 @@  const FFCodec ff_wrapped_avframe_encoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WRAPPED_AVFRAME,
-    .encode2        = wrapped_avframe_encode,
+    FF_CODEC_ENCODE_CB(wrapped_avframe_encode),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
 
@@ -122,6 +122,6 @@  const FFCodec ff_wrapped_avframe_decoder = {
     .p.long_name    = NULL_IF_CONFIG_SMALL("AVPacket to AVFrame passthrough"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WRAPPED_AVFRAME,
-    .decode         = wrapped_avframe_decode,
+    FF_CODEC_DECODE_CB(wrapped_avframe_decode),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/ws-snd1.c b/libavcodec/ws-snd1.c
index 00e4d91d4f..8d072297ee 100644
--- a/libavcodec/ws-snd1.c
+++ b/libavcodec/ws-snd1.c
@@ -176,7 +176,7 @@  const FFCodec ff_ws_snd1_decoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_WESTWOOD_SND1,
     .init           = ws_snd_decode_init,
-    .decode         = ws_snd_decode_frame,
+    FF_CODEC_DECODE_CB(ws_snd_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xan.c b/libavcodec/xan.c
index e9f6c334a1..3386a702b1 100644
--- a/libavcodec/xan.c
+++ b/libavcodec/xan.c
@@ -642,7 +642,7 @@  const FFCodec ff_xan_wc3_decoder = {
     .priv_data_size = sizeof(XanContext),
     .init           = xan_decode_init,
     .close          = xan_decode_end,
-    .decode         = xan_decode_frame,
+    FF_CODEC_DECODE_CB(xan_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xbmdec.c b/libavcodec/xbmdec.c
index bf9446195f..62ce46f3a7 100644
--- a/libavcodec/xbmdec.c
+++ b/libavcodec/xbmdec.c
@@ -143,5 +143,5 @@  const FFCodec ff_xbm_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_XBM,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode       = xbm_decode_frame,
+    FF_CODEC_DECODE_CB(xbm_decode_frame),
 };
diff --git a/libavcodec/xbmenc.c b/libavcodec/xbmenc.c
index 95db87dba6..60fb169457 100644
--- a/libavcodec/xbmenc.c
+++ b/libavcodec/xbmenc.c
@@ -81,7 +81,7 @@  const FFCodec ff_xbm_encoder = {
     .p.long_name  = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_XBM,
-    .encode2      = xbm_encode_frame,
+    FF_CODEC_ENCODE_CB(xbm_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE,
                                                    AV_PIX_FMT_NONE },
 };
diff --git a/libavcodec/xfacedec.c b/libavcodec/xfacedec.c
index 0542a36a5d..b103b5beda 100644
--- a/libavcodec/xfacedec.c
+++ b/libavcodec/xfacedec.c
@@ -182,7 +182,7 @@  const FFCodec ff_xface_decoder = {
     .p.id           = AV_CODEC_ID_XFACE,
     .priv_data_size = sizeof(XFaceContext),
     .init           = xface_decode_init,
-    .decode         = xface_decode_frame,
+    FF_CODEC_DECODE_CB(xface_decode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE },
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xfaceenc.c b/libavcodec/xfaceenc.c
index c1beb002cf..a46b7133e7 100644
--- a/libavcodec/xfaceenc.c
+++ b/libavcodec/xfaceenc.c
@@ -219,5 +219,5 @@  const FFCodec ff_xface_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE },
     .priv_data_size = sizeof(XFaceContext),
-    .encode2        = xface_encode_frame,
+    FF_CODEC_ENCODE_CB(xface_encode_frame),
 };
diff --git a/libavcodec/xl.c b/libavcodec/xl.c
index d414bcf95d..d2037b9f09 100644
--- a/libavcodec/xl.c
+++ b/libavcodec/xl.c
@@ -132,7 +132,7 @@  const FFCodec ff_xl_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_VIXL,
     .init         = decode_init,
-    .decode       = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c
index 468175fc4b..26d076d2e8 100644
--- a/libavcodec/xpmdec.c
+++ b/libavcodec/xpmdec.c
@@ -444,5 +444,5 @@  const FFCodec ff_xpm_decoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(XPMDecContext),
     .close          = xpm_decode_close,
-    .decode         = xpm_decode_frame,
+    FF_CODEC_DECODE_CB(xpm_decode_frame),
 };
diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c
index c2c1b920cc..f22c5cf3b3 100644
--- a/libavcodec/xsubdec.c
+++ b/libavcodec/xsubdec.c
@@ -160,6 +160,6 @@  const FFCodec ff_xsub_decoder = {
     .p.type    = AVMEDIA_TYPE_SUBTITLE,
     .p.id      = AV_CODEC_ID_XSUB,
     .init      = decode_init,
-    .decode_sub = decode_frame,
+    FF_CODEC_DECODE_SUB_CB(decode_frame),
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xsubenc.c b/libavcodec/xsubenc.c
index 9069a96437..8ca411e5af 100644
--- a/libavcodec/xsubenc.c
+++ b/libavcodec/xsubenc.c
@@ -217,6 +217,6 @@  const FFCodec ff_xsub_encoder = {
     .p.type     = AVMEDIA_TYPE_SUBTITLE,
     .p.id       = AV_CODEC_ID_XSUB,
     .init       = xsub_encoder_init,
-    .encode_sub = xsub_encode,
+    FF_CODEC_ENCODE_SUB_CB(xsub_encode),
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c
index 650a0bf774..f8afab598d 100644
--- a/libavcodec/xwddec.c
+++ b/libavcodec/xwddec.c
@@ -253,5 +253,5 @@  const FFCodec ff_xwd_decoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_XWD,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .decode         = xwd_decode_frame,
+    FF_CODEC_DECODE_CB(xwd_decode_frame),
 };
diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c
index 0bfe5a2970..0c6dfc6569 100644
--- a/libavcodec/xwdenc.c
+++ b/libavcodec/xwdenc.c
@@ -220,7 +220,7 @@  const FFCodec ff_xwd_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_XWD,
     .p.capabilities = AV_CODEC_CAP_DR1,
-    .encode2      = xwd_encode_frame,
+    FF_CODEC_ENCODE_CB(xwd_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA,
                                                  AV_PIX_FMT_RGBA,
                                                  AV_PIX_FMT_ARGB,
diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c
index 9a79e58d8a..d73bd46284 100644
--- a/libavcodec/xxan.c
+++ b/libavcodec/xxan.c
@@ -441,7 +441,7 @@  const FFCodec ff_xan_wc4_decoder = {
     .priv_data_size = sizeof(XanContext),
     .init           = xan_decode_init,
     .close          = xan_decode_end,
-    .decode         = xan_decode_frame,
+    FF_CODEC_DECODE_CB(xan_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/y41pdec.c b/libavcodec/y41pdec.c
index 663a1cc910..ca81dda0e8 100644
--- a/libavcodec/y41pdec.c
+++ b/libavcodec/y41pdec.c
@@ -87,7 +87,7 @@  const FFCodec ff_y41p_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_Y41P,
     .init         = y41p_decode_init,
-    .decode       = y41p_decode_frame,
+    FF_CODEC_DECODE_CB(y41p_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/y41penc.c b/libavcodec/y41penc.c
index 0522de6613..390bd10ba1 100644
--- a/libavcodec/y41penc.c
+++ b/libavcodec/y41penc.c
@@ -84,7 +84,7 @@  const FFCodec ff_y41p_encoder = {
     .p.id         = AV_CODEC_ID_Y41P,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .init         = y41p_encode_init,
-    .encode2      = y41p_encode_frame,
+    FF_CODEC_ENCODE_CB(y41p_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P,
                                                  AV_PIX_FMT_NONE },
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
diff --git a/libavcodec/ylc.c b/libavcodec/ylc.c
index 9b19405b24..94d0388f31 100644
--- a/libavcodec/ylc.c
+++ b/libavcodec/ylc.c
@@ -457,7 +457,7 @@  const FFCodec ff_ylc_decoder = {
     .priv_data_size = sizeof(YLCContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/yop.c b/libavcodec/yop.c
index 3079af061f..5befbb072e 100644
--- a/libavcodec/yop.c
+++ b/libavcodec/yop.c
@@ -274,6 +274,6 @@  const FFCodec ff_yop_decoder = {
     .priv_data_size = sizeof(YopDecContext),
     .init           = yop_decode_init,
     .close          = yop_decode_close,
-    .decode         = yop_decode_frame,
+    FF_CODEC_DECODE_CB(yop_decode_frame),
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/yuv4dec.c b/libavcodec/yuv4dec.c
index 3c6d6eda6e..bbd213e698 100644
--- a/libavcodec/yuv4dec.c
+++ b/libavcodec/yuv4dec.c
@@ -79,7 +79,7 @@  const FFCodec ff_yuv4_decoder = {
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_YUV4,
     .init         = yuv4_decode_init,
-    .decode       = yuv4_decode_frame,
+    FF_CODEC_DECODE_CB(yuv4_decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
 };
diff --git a/libavcodec/yuv4enc.c b/libavcodec/yuv4enc.c
index 3a4d36f40c..8d72382197 100644
--- a/libavcodec/yuv4enc.c
+++ b/libavcodec/yuv4enc.c
@@ -66,5 +66,5 @@  const FFCodec ff_yuv4_encoder = {
     .p.id           = AV_CODEC_ID_YUV4,
     .p.capabilities = AV_CODEC_CAP_DR1,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
-    .encode2      = yuv4_encode_frame,
+    FF_CODEC_ENCODE_CB(yuv4_encode_frame),
 };
diff --git a/libavcodec/zerocodec.c b/libavcodec/zerocodec.c
index b4d189cd7a..08511ca152 100644
--- a/libavcodec/zerocodec.c
+++ b/libavcodec/zerocodec.c
@@ -140,7 +140,7 @@  const FFCodec ff_zerocodec_decoder = {
     .p.id           = AV_CODEC_ID_ZEROCODEC,
     .priv_data_size = sizeof(ZeroCodecContext),
     .init           = zerocodec_decode_init,
-    .decode         = zerocodec_decode_frame,
+    FF_CODEC_DECODE_CB(zerocodec_decode_frame),
     .flush          = zerocodec_decode_flush,
     .close          = zerocodec_decode_close,
     .p.capabilities = AV_CODEC_CAP_DR1,
diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c
index 4a845a333d..37c18e3a14 100644
--- a/libavcodec/zmbv.c
+++ b/libavcodec/zmbv.c
@@ -653,7 +653,7 @@  const FFCodec ff_zmbv_decoder = {
     .priv_data_size = sizeof(ZmbvContext),
     .init           = decode_init,
     .close          = decode_end,
-    .decode         = decode_frame,
+    FF_CODEC_DECODE_CB(decode_frame),
     .p.capabilities = AV_CODEC_CAP_DR1,
     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
 };
diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c
index 89814de800..ef21a189a6 100644
--- a/libavcodec/zmbvenc.c
+++ b/libavcodec/zmbvenc.c
@@ -418,7 +418,7 @@  const FFCodec ff_zmbv_encoder = {
     .p.capabilities = AV_CODEC_CAP_DR1,
     .priv_data_size = sizeof(ZmbvEncContext),
     .init           = encode_init,
-    .encode2        = encode_frame,
+    FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8,
                                                      AV_PIX_FMT_RGB555LE,