av_register_all

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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值