本篇主要解析av_register_all()所在文件libavformat–allformats.c及av_register_all()在调用过程中引用到的libavcodec–allcodecs.c。
ffmpeg注册复用器,编码器等的函数av_register_all()。该函数在所有基于ffmpeg的应用程序中几乎都是第一个被调用的。只有调用了该函数,才能使用复用器,编码器等。
这个函数在下面的源码中出现频率很高
// package:libavutil->atomic.c
// 类似CAS操作:当前值为旧值时,才赋新值
#if HAVE_PTHREADS
#include <pthread.h>
// 互斥锁pthread_mutex_t
static pthread_mutex_t atomic_lock = PTHREAD_MUTEX_INITIALIZER;
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
{
void *ret;
pthread_mutex_lock(&atomic_lock);
ret = *ptr;
if (ret == oldval)
*ptr = newval;
pthread_mutex_unlock(&atomic_lock);
return ret;
}
#elif !HAVE_THREADS
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
{
if (*ptr == oldval) {
*ptr = newval;
return oldval;
}
return *ptr;
}
对主要代码进行了注释
对大量的注册信息进行了精简,留下了一部分常见的
/*
* Register all the formats and protocols
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/thread.h"
#include "avformat.h"
#include "rtp.h"
#include "rdt.h"
#include "url.h"
#include "version.h"
/**
* ##的含义就是拼接两个字符串
*
* 例如:REGISTER_MUXER(A64,a64)
*
* extern AVOutputFormat ff_a64_muxer;
* if (CONFIG_A64_MUXER)
* av_register_output_format(&ff_a64_muxer);
*
* -----------------------------------------------
*
* av_register_output_format在format.c中
* void av_register_output_format(AVOutputFormat *format) {
* AVOutputFormat **p = last_oformat;
*
* // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
* while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
* p = &(*p)->next;
*
* if (!format->next)
* last_oformat = &format->next;
* }
*
* // head of registered output format linked list (Output Format链表)
* static AVOutputFormat*first_oformat=NULL;
*
* 故这段代码的作用是,遍历OutputFormat链表,将当前format插入到链表尾部。Input部分与此逻辑相同。
*
*/
#define REGISTER_MUXER(X, x) \
{ \
extern AVOutputFormat ff_##x##_muxer; \
if (CONFIG_##X##_MUXER) \
av_register_output_format(&ff_##x##_muxer); \
}
#define REGISTER_DEMUXER(X, x) \
{ \
extern AVInputFormat ff_##x##_demuxer; \
if (CONFIG_##X##_DEMUXER) \
av_register_input_format(&ff_##x##_demuxer); \
}
#define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
static void register_all(void)
{
// allcodecs.c中,注册编解码器
avcodec_register_all();
/* (de)muxers */
// MUXER:复用器 DEMUXER:解复用器 MUXDEMUX:复用与解复用
REGISTER_MUXER (A64, a64);
REGISTER_DEMUXER (AA, aa);
REGISTER_DEMUXER (AAC, aac);
REGISTER_MUXDEMUX(AC3, ac3);
REGISTER_DEMUXER (ACM, acm);
REGISTER_DEMUXER (ACT, act);
...
REGISTER_MUXDEMUX(AVI, avi);
...
REGISTER_DEMUXER (BMV, bmv);
...
REGISTER_MUXDEMUX(DASH, dash);
REGISTER_MUXDEMUX(DATA, data);
...
REGISTER_MUXER (FIFO, fifo);
...
REGISTER_MUXDEMUX(FLV, flv);
REGISTER_DEMUXER (LIVE_FLV, live_flv);
...
REGISTER_MUXDEMUX(GIF, gif);
...
REGISTER_MUXDEMUX(H264, h264);
REGISTER_MUXER (HASH, hash);
REGISTER_MUXER (HDS, hds);
REGISTER_MUXDEMUX(HEVC, hevc);
REGISTER_MUXDEMUX(HLS, hls);
REGISTER_DEMUXER (HNM, hnm);
REGISTER_MUXDEMUX(ICO, ico);
...
REGISTER_MUXDEMUX(IMAGE2, image2);
...
REGISTER_DEMUXER (LVF, lvf);
REGISTER_DEMUXER (LXF, lxf);
...
REGISTER_MUXDEMUX(MJPEG, mjpeg);
REGISTER_DEMUXER (MJPEG_2000, mjpeg_2000);
...
REGISTER_MUXDEMUX(MOV, mov);
REGISTER_MUXER (MP2, mp2);
REGISTER_MUXDEMUX(MP3, mp3);
REGISTER_MUXER (MP4, mp4);
...
REGISTER_DEMUXER (MPEGPS, mpegps);
REGISTER_MUXDEMUX(MPEGTS, mpegts);
REGISTER_DEMUXER (MPEGTSRAW, mpegtsraw);
REGISTER_DEMUXER (MPEGVIDEO, mpegvideo);
REGISTER_MUXDEMUX(MPJPEG, mpjpeg);
...
REGISTER_DEMUXER (MV, mv);
REGISTER_DEMUXER (MVI, mvi);
...
REGISTER_MUXER (NULL, null);
REGISTER_MUXDEMUX(NUT, nut);
REGISTER_DEMUXER (NUV, nuv);
REGISTER_MUXER (OGA, oga);
REGISTER_MUXDEMUX(OGG, ogg);
...
REGISTER_MUXDEMUX(PCM_U8, pcm_u8);
...
REGISTER_MUXDEMUX(RTP, rtp);
REGISTER_MUXER (RTP_MPEGTS, rtp_mpegts);
REGISTER_MUXDEMUX(RTSP, rtsp);
...
#if CONFIG_RTPDEC
ff_register_rtp_dynamic_payload_handlers();
ff_register_rdt_dynamic_payload_handlers();
#endif
REGISTER_DEMUXER (SEGAFILM, segafilm);
REGISTER_MUXER (SEGMENT, segment);
REGISTER_MUXER (SEGMENT, stream_segment);
REGISTER_DEMUXER (SHORTEN, shorten);
REGISTER_DEMUXER (SIFF, siff);
REGISTER_MUXER (SINGLEJPEG, singlejpeg);
REGISTER_DEMUXER (SLN, sln);
REGISTER_DEMUXER (SMACKER, smacker);
REGISTER_MUXDEMUX(SMJPEG, smjpeg);
...
REGISTER_DEMUXER (SVAG, svag);
...
REGISTER_MUXDEMUX(WAV, wav);
...
REGISTER_MUXER (WEBM_CHUNK, webm_chunk);
REGISTER_MUXER (WEBP, webp);
...
REGISTER_MUXDEMUX(YUV4MPEGPIPE, yuv4mpegpipe);
/* image demuxers */
REGISTER_DEMUXER (IMAGE_BMP_PIPE, image_bmp_pipe);
...
REGISTER_DEMUXER (IMAGE_JPEG_PIPE, image_jpeg_pipe);
...
REGISTER_DEMUXER (IMAGE_SVG_PIPE, image_svg_pipe);
...
REGISTER_DEMUXER (IMAGE_WEBP_PIPE, image_webp_pipe);
REGISTER_DEMUXER (IMAGE_XPM_PIPE, image_xpm_pipe);
/* external libraries */
REGISTER_MUXER (CHROMAPRINT, chromaprint);
REGISTER_DEMUXER (LIBGME, libgme);
REGISTER_DEMUXER (LIBMODPLUG, libmodplug);
REGISTER_DEMUXER (LIBOPENMPT, libopenmpt);
}
void av_register_all(void)
{
static AVOnce control = AV_ONCE_INIT;
// ff_thread_once的作用是保证register_all只会被调用一次
ff_thread_once(&control, register_all);
}
分析器(Parser)
BSF(bitstream filters,比特流滤镜,有一个常用:h264_mp4toannexb)
HWACCEL(hardware accelerators,硬件加速器)
/*
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
* Copyright (c) 2002 Fabrice Bellard
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* Provide registration of all codecs, parsers and bitstream filters for libavcodec.
*/
#include "config.h"
#include "libavutil/thread.h"
#include "avcodec.h"
#include "version.h"
#define REGISTER_HWACCEL(X, x) \
{ \
extern AVHWAccel ff_##x##_hwaccel; \
if (CONFIG_##X##_HWACCEL) \
/**
* libavcodec-util.c
* 该接口的功能是用来注册硬件加速器
*
* static AVHWAccel *first_hwaccel = NULL;
* static AVHWAccel **last_hwaccel = &first_hwaccel;
*
* void av_register_hwaccel(AVHWAccel *hwaccel)
* {
* AVHWAccel **p = last_hwaccel;
* hwaccel->next = NULL;
* while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel))
* p = &(*p)->next;
* last_hwaccel = &hwaccel->next;
* }
*
* -----------------------------------------------------------
*
* 当*p不为null时,向后遍历;为null时,将hwaccel放入
* 最后保存尾部索引
*/
av_register_hwaccel(&ff_##x##_hwaccel); \
}
#define REGISTER_ENCODER(X, x) \
{ \
extern AVCodec ff_##x##_encoder; \
if (CONFIG_##X##_ENCODER) \
/**
* libavcodec->util.c
*
* static AVCodec *first_avcodec = NULL;
* static AVCodec **last_avcodec = &first_avcodec;
*
* av_cold void avcodec_register(AVCodec *codec)
* {
* AVCodec **p;
* avcodec_init();
* p = last_avcodec;
* codec->next = NULL;
*
* while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec))
* p = &(*p)->next;
* last_avcodec = &codec->next;
*
* if (codec->init_static_data)
* codec->init_static_data(codec);
* }
*/
avcodec_register(&ff_##x##_encoder); \
}
#define REGISTER_DECODER(X, x) \
{ \
extern AVCodec ff_##x##_decoder; \
if (CONFIG_##X##_DECODER) \
avcodec_register(&ff_##x##_decoder); \
}
#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x)
#define REGISTER_PARSER(X, x) \
{ \
extern AVCodecParser ff_##x##_parser; \
if (CONFIG_##X##_PARSER) \
/**
* libavcodec->util.c
*
* static AVCodecParser *av_first_parser = NULL;
*
* void av_register_codec_parser(AVCodecParser *parser)
* {
* do {
* parser->next = av_first_parser;
* } while (parser->next != avpriv_atomic_ptr_cas((void * volatile *)&av_first_parser, parser->next, parser));
* }
*/
av_register_codec_parser(&ff_##x##_parser); \
}
static void register_all(void)
{
/* hardware accelerators */
...
REGISTER_HWACCEL(H264_MEDIACODEC, h264_mediacodec);
...
REGISTER_HWACCEL(HEVC_MEDIACODEC, hevc_mediacodec);
...
REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox);
...
REGISTER_HWACCEL(MPEG2_MEDIACODEC, mpeg2_mediacodec);
REGISTER_HWACCEL(MPEG4_CUVID, mpeg4_cuvid);
REGISTER_HWACCEL(MPEG4_MEDIACODEC, mpeg4_mediacodec);
...
REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
...
/* video codecs */
...
REGISTER_ENCDEC (APNG, apng);
REGISTER_ENCDEC (ASV1, asv1);
REGISTER_ENCDEC (ASV2, asv2);
REGISTER_DECODER(AURA, aura);
REGISTER_DECODER(AURA2, aura2);
REGISTER_ENCDEC (AVRP, avrp);
REGISTER_DECODER(AVRN, avrn);
REGISTER_DECODER(AVS, avs);
REGISTER_ENCDEC (AVUI, avui);
REGISTER_ENCDEC (AYUV, ayuv);
...
REGISTER_ENCDEC (BMP, bmp);
...
REGISTER_ENCDEC (FLASHSV, flashsv);
...
REGISTER_ENCDEC (FLV, flv);
...
REGISTER_ENCDEC (GIF, gif);
...
REGISTER_DECODER(H264, h264);
...
#if FF_API_VDPAU
REGISTER_DECODER(H264_VDPAU, h264_vdpau);
#endif
REGISTER_ENCDEC (HAP, hap);
REGISTER_DECODER(HEVC, hevc);
...
REGISTER_ENCDEC (JPEG2000, jpeg2000);
...
REGISTER_DECODER(KMVC, kmvc);
...
REGISTER_ENCDEC (MJPEG, mjpeg);
...
#if FF_API_XVMC
REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc);
#endif /* FF_API_XVMC */
REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
...
#if FF_API_VDPAU
REGISTER_DECODER(MPEG4_VDPAU, mpeg4_vdpau);
#endif
REGISTER_DECODER(MPEGVIDEO, mpegvideo);
#if FF_API_VDPAU
REGISTER_DECODER(MPEG_VDPAU, mpeg_vdpau);
REGISTER_DECODER(MPEG1_VDPAU, mpeg1_vdpau);
#endif
...
REGISTER_DECODER(MPEG2_MEDIACODEC, mpeg2_mediacodec);
...
REGISTER_ENCDEC (PCX, pcx);
...
REGISTER_ENCDEC (RV10, rv10);
...
REGISTER_ENCDEC (SVQ1, svq1);
REGISTER_DECODER(SVQ3, svq3);
REGISTER_ENCDEC (TARGA, targa);
...
REGISTER_ENCDEC (V210, v210);
...
#if FF_API_VDPAU
REGISTER_DECODER(VC1_VDPAU, vc1_vdpau);
#endif
REGISTER_DECODER(VC1IMAGE, vc1image);
...
REGISTER_DECODER(VMDVIDEO, vmdvideo);
REGISTER_DECODER(VMNC, vmnc);
REGISTER_DECODER(VP3, vp3);
...
REGISTER_ENCDEC (WMV1, wmv1);
...
#if FF_API_VDPAU
REGISTER_DECODER(WMV3_VDPAU, wmv3_vdpau);
#endif
REGISTER_DECODER(WMV3IMAGE, wmv3image);
...
REGISTER_ENCDEC (YUV4, yuv4);
...
/* audio codecs */
REGISTER_ENCDEC (AAC, aac);
REGISTER_DECODER(AAC_FIXED, aac_fixed);
REGISTER_DECODER(AAC_LATM, aac_latm);
REGISTER_ENCDEC (AC3, ac3);
...
REGISTER_DECODER(BMV_AUDIO, bmv_audio);
...
REGISTER_ENCDEC (FLAC, flac);
...
REGISTER_DECODER(MP3, mp3);
...
REGISTER_ENCDEC (WAVPACK, wavpack);
...
/* PCM codecs */
...
REGISTER_ENCDEC (PCM_U8, pcm_u8);
...
/* DPCM codecs */
REGISTER_DECODER(GREMLIN_DPCM, gremlin_dpcm);
...
/* ADPCM codecs */
...
REGISTER_DECODER(ADPCM_IMA_AMV, adpcm_ima_amv);
REGISTER_DECODER(ADPCM_IMA_APC, adpcm_ima_apc);
...
REGISTER_ENCDEC (ADPCM_IMA_QT, adpcm_ima_qt);
REGISTER_DECODER(ADPCM_IMA_RAD, adpcm_ima_rad);
REGISTER_DECODER(ADPCM_IMA_SMJPEG, adpcm_ima_smjpeg);
REGISTER_ENCDEC (ADPCM_IMA_WAV, adpcm_ima_wav);
...
REGISTER_ENCDEC (ADPCM_SWF, adpcm_swf);
...
/* subtitles */
REGISTER_ENCDEC (SSA, ssa);
REGISTER_ENCDEC (ASS, ass);
...
REGISTER_DECODER(REALTEXT, realtext);
...
REGISTER_ENCDEC (TEXT, text);
REGISTER_DECODER(VPLAYER, vplayer);
REGISTER_ENCDEC (WEBVTT, webvtt);
REGISTER_ENCDEC (XSUB, xsub);
/* external libraries */
REGISTER_ENCDEC (AAC_AT, aac_at);
REGISTER_DECODER(AC3_AT, ac3_at);
...
REGISTER_DECODER(LIBRSVG, librsvg);
...
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
...
/* text */
REGISTER_DECODER(BINTEXT, bintext);
REGISTER_DECODER(XBIN, xbin);
REGISTER_DECODER(IDF, idf);
/* external libraries, that shouldn't be used by default if one of the
* above is available */
...
REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox);
#if FF_API_NVENC_OLD_NAME
REGISTER_ENCODER(NVENC, nvenc);
REGISTER_ENCODER(NVENC_H264, nvenc_h264);
REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc);
#endif
REGISTER_DECODER(HEVC_CUVID, hevc_cuvid);
REGISTER_DECODER(HEVC_MEDIACODEC, hevc_mediacodec);
...
REGISTER_DECODER(MPEG4_MEDIACODEC, mpeg4_mediacodec);
REGISTER_ENCODER(MPEG4_V4L2M2M, mpeg4_v4l2m2m);
...
REGISTER_DECODER(VP9_MEDIACODEC, vp9_mediacodec);
REGISTER_ENCODER(VP9_VAAPI, vp9_vaapi);
/* parsers */
REGISTER_PARSER(AAC, aac);
...
REGISTER_PARSER(BMP, bmp);
...
REGISTER_PARSER(H264, h264);
REGISTER_PARSER(HEVC, hevc);
...
REGISTER_PARSER(MPEGVIDEO, mpegvideo);
...
}
void avcodec_register_all(void)
{
static AVOnce control = AV_ONCE_INIT;
// ff_thread_once的作用是保证register_all只会被调用一次
ff_thread_once(&control, register_all);
}
/*
* filter registration
* Copyright (c) 2008 Vitor Sessak
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/thread.h"
#include "avfilter.h"
#include "config.h"
#include "opencl_allkernels.h"
/**
* libavfilter->avfilter.c
* 注册滤镜
*
* static AVFilter *first_filter;
* static AVFilter **last_filter = &first_filter;
*
* int avfilter_register(AVFilter *filter)
* {
* AVFilter **f = last_filter;
*
* // the filter must select generic or internal exclusively
* av_assert0((filter->flags&AVFILTER_FLAG_SUPPORT_TIMELINE)!=AVFILTER_FLAG_SUPPORT_TIMELINE);
*
* filter->next=NULL;
*
* while(*f||avpriv_atomic_ptr_cas((void*volatile *)f,NULL,filter))
* f=&(*f)->next;
* last_filter=&filter->next;
*
* return 0;
* }
*/
#define REGISTER_FILTER(X, x, y) \
{ \
extern AVFilter ff_##y##_##x; \
if (CONFIG_##X##_FILTER) \
avfilter_register(&ff_##y##_##x); \
}
/**
* 与上面相比,少了检查CONFIG的步骤
*/
#define REGISTER_FILTER_UNCONDITIONAL(x) \
{ \
extern AVFilter ff_##x; \
avfilter_register(&ff_##x); \
}
static void register_all(void)
{
REGISTER_FILTER(ABENCH, abench, af);
REGISTER_FILTER(ACOMPRESSOR, acompressor, af);
REGISTER_FILTER(ACOPY, acopy, af);
REGISTER_FILTER(ACROSSFADE, acrossfade, af);
REGISTER_FILTER(ACRUSHER, acrusher, af);
REGISTER_FILTER(ADELAY, adelay, af);
REGISTER_FILTER(AECHO, aecho, af);
...
REGISTER_FILTER(AMERGE, amerge, af);
REGISTER_FILTER(AMETADATA, ametadata, af);
...
REGISTER_FILTER(AREALTIME, arealtime, af);
...
REGISTER_FILTER(BANDPASS, bandpass, af);
...
REGISTER_FILTER(CROSSFEED, crossfeed, af);
...
REGISTER_FILTER(JOIN, join, af);
...
REGISTER_FILTER(VOLUME, volume, af);
...
REGISTER_FILTER(BENCH, bench, vf);
...
REGISTER_FILTER(COPY, copy, vf);
REGISTER_FILTER(COREIMAGE, coreimage, vf);
REGISTER_FILTER(COVER_RECT, cover_rect, vf);
REGISTER_FILTER(CROP, crop, vf);
...
REGISTER_FILTER(DRAWBOX, drawbox, vf);
REGISTER_FILTER(DRAWGRAPH, drawgraph, vf);
REGISTER_FILTER(DRAWGRID, drawgrid, vf);
REGISTER_FILTER(DRAWTEXT, drawtext, vf);
...
REGISTER_FILTER(FORMAT, format, vf);
...
REGISTER_FILTER(INFLATE, inflate, vf);
...
...
REGISTER_FILTER(METADATA, metadata, vf);
...
REGISTER_FILTER(NOISE, noise, vf);
REGISTER_FILTER(NULL, null, vf);
REGISTER_FILTER(OCR, ocr, vf);
REGISTER_FILTER(OCV, ocv, vf);
REGISTER_FILTER(OSCILLOSCOPE, oscilloscope, vf);
REGISTER_FILTER(OVERLAY, overlay, vf);
...
REGISTER_FILTER(RANDOM, random, vf);
...
REGISTER_FILTER(REALTIME, realtime, vf);
REGISTER_FILTER(REMAP, remap, vf);
REGISTER_FILTER(REMOVEGRAIN, removegrain, vf);
REGISTER_FILTER(REMOVELOGO, removelogo, vf);
REGISTER_FILTER(REPEATFIELDS, repeatfields, vf);
REGISTER_FILTER(REVERSE, reverse, vf);
REGISTER_FILTER(ROBERTS, roberts, vf);
REGISTER_FILTER(ROTATE, rotate, vf);
REGISTER_FILTER(SAB, sab, vf);
REGISTER_FILTER(SCALE, scale, vf);
...
REGISTER_FILTER(SELECT, select, vf);
...
REGISTER_FILTER(SUBTITLES, subtitles, vf);
...
REGISTER_FILTER(TRIM, trim, vf);
...
REGISTER_FILTER(VFLIP, vflip, vf);
...
REGISTER_FILTER(ZSCALE, zscale, vf);
REGISTER_FILTER(ALLRGB, allrgb, vsrc);
REGISTER_FILTER(ALLYUV, allyuv, vsrc);
REGISTER_FILTER(CELLAUTO, cellauto, vsrc);
REGISTER_FILTER(COLOR, color, vsrc);
...
REGISTER_FILTER(MPTESTSRC, mptestsrc, vsrc);
REGISTER_FILTER(NULLSRC, nullsrc, vsrc);
REGISTER_FILTER(RGBTESTSRC, rgbtestsrc, vsrc);
...
REGISTER_FILTER(YUVTESTSRC, yuvtestsrc, vsrc);
REGISTER_FILTER(NULLSINK, nullsink, vsink);
/* multimedia filters */
REGISTER_FILTER(ABITSCOPE, abitscope, avf);
...
REGISTER_FILTER(CONCAT, concat, avf);
...
/* multimedia sources */
REGISTER_FILTER(AMOVIE, amovie, avsrc);
REGISTER_FILTER(MOVIE, movie, avsrc);
/* those filters are part of public or internal API => registered
* unconditionally */
REGISTER_FILTER_UNCONDITIONAL(asrc_abuffer);
...
ff_opencl_register_filter_kernel_code_all();
}
void avfilter_register_all(void)
{
static AVOnce control = AV_ONCE_INIT;
// ff_thread_once的作用是保证register_all只会被调用一次
ff_thread_once(&control, register_all);
}