av_register_all
首先认识一个函数,新版本ffmpeg初始化相关只执行一次的操作,基本都使用了这个函数
//名称thread_once,只初始化一次,多线程有可能会执行多次
//在av_register_all中的av_format_init_next函数中,有锁的存在,但不能保证多线程只执行一次,不过看av_format_init_next实现,就算执行多次也没啥问题
static inline int ff_thread_once(char *control/*是否执行过标记位*/, void (*routine)(void)/*初始化函数*/){
if (!*control) {
routine();
*control = 1;
}
return 0;//无用的返回值
}
av_register_all、av_register_input_format、av_register_output_format都已经声明为过时,而且执行都是同一个函数,现在是线程安全的初始化
void av_register_all(void){
//线程安全函数,pthread
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);
}
av_format_init_next做的事情很简单,初始化四个链表
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,outdev_list,demuxer_list,indev_list是在configure过程中生成的
//通过find_filters_extern 函数遍历对应的文件,找对对应的AVOutputFormat ,AVInputFormat ,AVCodec
//在对应的文件开头可以看见一堆解复用器,编解码器,configure将配置生成数组
MUXER_LIST=$(find_things_extern muxer AVOutputFormat libavformat/allformats.c)
DEMUXER_LIST=$(find_things_extern demuxer AVInputFormat libavformat/allformats.c)
ENCODER_LIST=$(find_things_extern encoder AVCodec libavcodec/allcodecs.c)
//然后生成对应的文件
print_enabled_components libavfilter/filter_list.c AVFilter filter_list $FILTER_LIST
print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST
print_enabled_components libavcodec/parser_list.c AVCodecParser parser_list $PARSER_LIST
avcodec_register_all
void avcodec_register_all(void)
{
//熟悉的ff_thread_once
ff_thread_once(&av_codec_next_init, av_codec_init_next);
}
//初始化codec链表
static void av_codec_init_next(void){
AVCodec *prev = NULL, *p;
void *i = 0;
while ((p = (AVCodec*)av_codec_iterate(&i))) {
if (prev)
prev->next = p;
prev = p;
}
}
//找到处于**opaque 位置的编解码器,如果找到,则
const AVCodec *av_codec_iterate(void **opaque){
uintptr_t i = (uintptr_t)*opaque;
const AVCodec *c = codec_list[i];
ff_thread_once(&av_codec_static_init, av_codec_init_static/*初始化对应编解码器的像素格式*/);
if (c) //只有c为真,opaque才+1
*opaque = (void*)(i + 1);
return c;
}
//初始化对应编解码器的像素格式
static void av_codec_init_static(void){
for (int i = 0; codec_list[i]; i++) {
if (codec_list[i]->init_static_data)
codec_list[i]->init_static_data((AVCodec*)codec_list[i]);
}
}
//如x265的init_static_data方法调用,主要是根据libx265的版本,赋值支持的像素格式枚举,codec->pix_fmts是个枚举类型
static av_cold void libx265_encode_init_csp(AVCodec *codec){
if (x265_api_get(12))
codec->pix_fmts = x265_csp_twelve;/*枚举值*/
else if (x265_api_get(10))
codec->pix_fmts = x265_csp_ten;
else if (x265_api_get(8))
codec->pix_fmts = x265_csp_eight;
}