FFmpeg中av_register_all()函数用于注册所有muxers、demuxers与protocols。FFmpeg4.0以前是用链表存储muxer/demuxer,FFmpeg4.0以后改为数组存储,并且av_register_all方法已被标记为过时,av_register_input_format和av_register_output_format也被标记为过时。
av_register_all()的声明位于libavformat/avformat.h头文件中,在新版本4.0以后,不需要调用该方法,可以直接使用所有模块。声明如下:
#if FF_API_NEXT
/**
* Initialize libavformat and register all the muxers, demuxers and
* protocols. If you do not call this function, then you can select
* exactly which formats you want to support.
*
* @see av_register_input_format()
* @see av_register_output_format()
*/
attribute_deprecated
void av_register_all(void);
attribute_deprecated
void av_register_input_format(AVInputFormat *format);
attribute_deprecated
void av_register_output_format(AVOutputFormat *format);
#endif
并且在APIChanges文档中也有说明,FFmpeg4.0的部分API改动如下:
2018-04-01 - f1805d160d - lavfi 7.14.100 - avfilter.h
Deprecate use of avfilter_register(), avfilter_register_all(),
avfilter_next(). Add av_filter_iterate().
2018-02-06 - 0694d87024 - lavf 58.9.100 - avformat.h
Deprecate use of av_register_input_format(), av_register_output_format(),
av_register_all(), av_iformat_next(), av_oformat_next().
Add av_demuxer_iterate(), and av_muxer_iterate().
2018-02-06 - 36c85d6e77 - lavc 58.10.100 - avcodec.h
Deprecate use of avcodec_register(), avcodec_register_all(),
av_codec_next(), av_register_codec_parser(), and av_parser_next().
Add av_codec_iterate() and av_parser_iterate().
文档提到avfilter模块:avfilter_register()、avfilter_register_all()和avfilter_next()已过时,添加av_filter_iterate()来迭代遍历。avformat模块:av_register_input_format()、av_register_output_format()、av_register_all()等已过时,添加av_demuxer_iterate()和av_muxer_iterate()来迭代遍历。avcodec模块:avcodec_register()、avcodec_register_all()、av_register_codec_parser()等已过时,添加av_codec_iterae()和av_parser_iterate()来迭代遍历。
我们主要看下avformat模块的注册函数,位于libavformat/allformats.c文件:
void av_register_all(void)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
void av_register_input_format(AVInputFormat *format)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
void av_register_output_format(AVOutputFormat *format)
{
ff_thread_once(&av_format_next_init, av_format_init_next);
}
函数体改为运行单例线程,ff_thread_once()位于libavutil/thread.h,代码如下:
#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
......
#define ff_thread_once(control, routine) pthread_once(control, routine)
#else
......
static inline int ff_thread_once(char *control, void (*routine)(void))
{
if (!*control) {
routine();
*control = 1;
}
return 0;
}
#endif
ff_thread_once()的函数指针avformat_init_next()也位于libavformat/allformats.c,代码如下:
static void av_format_init_next(void)
{
AVOutputFormat *prevout = NULL, *out;
AVInputFormat *previn = NULL, *in;
ff_mutex_lock(&avpriv_register_devices_mutex);
for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) {
if (prevout)
prevout->next = out;
prevout = out;
}
if (outdev_list) {
for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) {
if (prevout)
prevout->next = out;
prevout = out;
}
}
for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) {
if (previn)
previn->next = in;
previn = in;
}
if (indev_list) {
for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) {
if (previn)
previn->next = in;
previn = in;
}
}
ff_mutex_unlock(&avpriv_register_devices_mutex);
}
这里主要是把muxer_list和demuxer_list数组的元素取出来,添加到链表中。如果有开启avdevice模块,有index_list和outdev_list数组,也添加到链表中。这几个数组都是编译源码后,自动生成,来自allformats.c声明的muxers与demuxers全局变量:
/* (de)muxers */
extern AVInputFormat ff_aac_demuxer;
extern AVInputFormat ff_ac3_demuxer;
extern AVOutputFormat ff_ac3_muxer;
extern AVInputFormat ff_amr_demuxer;
extern AVOutputFormat ff_amr_muxer;
extern AVInputFormat ff_amrnb_demuxer;
extern AVInputFormat ff_amrwb_demuxer;
extern AVInputFormat ff_asf_demuxer;
extern AVOutputFormat ff_asf_muxer;
extern AVInputFormat ff_av1_demuxer;
extern AVInputFormat ff_avi_demuxer;
extern AVOutputFormat ff_avi_muxer;
extern AVInputFormat ff_dash_demuxer;
extern AVOutputFormat ff_dash_muxer;
extern AVInputFormat ff_eac3_demuxer;
extern AVOutputFormat ff_eac3_muxer;
extern AVInputFormat ff_flac_demuxer;
extern AVOutputFormat ff_flac_muxer;
extern AVInputFormat ff_flv_demuxer;
extern AVOutputFormat ff_flv_muxer;
extern AVInputFormat ff_hls_demuxer;
extern AVOutputFormat ff_hls_muxer;
extern AVOutputFormat ff_ipod_muxer;
extern AVInputFormat ff_matroska_demuxer;
extern AVOutputFormat ff_matroska_muxer;
extern AVInputFormat ff_mov_demuxer;
extern AVOutputFormat ff_mov_muxer;
extern AVInputFormat ff_mp3_demuxer;
extern AVOutputFormat ff_mp3_muxer;
extern AVOutputFormat ff_mp4_muxer;
extern AVInputFormat ff_ogg_demuxer;
extern AVOutputFormat ff_ogg_muxer;
extern AVInputFormat ff_rtp_demuxer;
extern AVOutputFormat ff_rtp_muxer;
extern AVInputFormat ff_rtsp_demuxer;
extern AVOutputFormat ff_rtsp_muxer;
extern AVInputFormat ff_wav_demuxer;
extern AVOutputFormat ff_wav_muxer;
/* image demuxers */
extern AVInputFormat ff_image_bmp_pipe_demuxer;
extern AVInputFormat ff_image_gif_pipe_demuxer;
extern AVInputFormat ff_image_jpeg_pipe_demuxer;
extern AVInputFormat ff_image_png_pipe_demuxer;
extern AVInputFormat ff_image_webp_pipe_demuxer;
muxer_list位于libavformat/muxer_list.c,生成的muxers数组如下(有删减):
static const AVOutputFormat * const muxer_list[] = {
&ff_ac3_muxer,
&ff_amr_muxer,
&ff_asf_muxer,
&ff_avi_muxer,
&ff_eac3_muxer,
&ff_flac_muxer,
&ff_flv_muxer,
&ff_gif_muxer,
&ff_h264_muxer,
&ff_hevc_muxer,
&ff_hls_muxer,
&ff_image2_muxer,
&ff_ipod_muxer,
&ff_matroska_muxer,
&ff_mov_muxer,
&ff_mp3_muxer,
&ff_mp4_muxer,
&ff_mpeg1video_muxer,
&ff_mpeg2video_muxer,
&ff_mpegts_muxer,
&ff_mpjpeg_muxer,
&ff_ogg_muxer,
&ff_opus_muxer,
&ff_wav_muxer,
&ff_webm_muxer,
NULL };
demuxer_list位于libavformat/demuxer_list.c,生成的demuxers数组如下(有删减):
static const AVInputFormat * const demuxer_list[] = {
&ff_aac_demuxer,
&ff_ac3_demuxer,
&ff_amr_demuxer,
&ff_amrnb_demuxer,
&ff_amrwb_demuxer,
&ff_asf_demuxer,
&ff_avi_demuxer,
&ff_eac3_demuxer,
&ff_flac_demuxer,
&ff_flv_demuxer,
&ff_h264_demuxer,
&ff_hevc_demuxer,
&ff_hls_demuxer,
&ff_image2_demuxer,
&ff_matroska_demuxer,
&ff_mov_demuxer,
&ff_mp3_demuxer,
&ff_ogg_demuxer,
&ff_wav_demuxer,
NULL };
总结avformat模块的注册函数改动,链表存储改为数组存储,在运行期添加muxer与demuxer到链表,改为编译期自动生成保存于数组。