1. 程式人生 > >ffmpeg原始碼簡析(二)av_register_all(),avcodec_register_all()

ffmpeg原始碼簡析(二)av_register_all(),avcodec_register_all()

av_register_all()

該函式在所有基於ffmpeg的應用程式中幾乎都是第一個被呼叫的。只有呼叫了該函式,才能使用複用器,編碼器等。

av_register_all()呼叫了avcodec_register_all()。avcodec_register_all()註冊了和編解碼器有關的元件:硬體加速器,解碼器,編碼器,Parser,Bitstream Filter。av_register_all()除了呼叫avcodec_register_all()之外,還註冊了複用器,解複用器,協議處理器。

下面附上覆用器,解複用器,協議處理器的程式碼。

註冊複用器的函式是av_register_output_format()。


    void av_register_output_format(AVOutputFormat *format)  
    {  
        AVOutputFormat **p;  
        p = &first_oformat;  
        while (*p != NULL) p = &(*p)->next;  
        *p = format;  
        format->next = NULL;  
    }  

註冊解複用器的函式是av_register_input_format()。

//遍歷連結串列並把當前的Input Format加到連結串列的尾部。
    void av_register_input_format(AVInputFormat *format
) { AVInputFormat **p; p = &first_iformat; while (*p != NULL) p = &(*p)->next; *p = format; format->next = NULL; }

註冊協議處理器的函式是ffurl_register_protocol()。

   int ffurl_register_protocol(URLProtocol *protocol)  
    {  
        URLProtocol **
p; p = &first_protocol; while (*p) p = &(*p)->next; *p = protocol; protocol->next = NULL; return 0; }

下面貼出它的原始碼(allformats.c)

#include "avformat.h"  
#include "rtp.h"  
#include "rdt.h"  
#include "url.h"  
//定義的巨集?巨集的速度會快一點?註冊AVOutputFormat  
//define中,#用來把引數轉換成字串,##則用來連線前後兩個引數,把它們變成一個字串。    
#define REGISTER_MUXER(X,x) { \  
    extern AVOutputFormat ff_##x##_muxer; \  
    if(CONFIG_##X##_MUXER) av_register_output_format(&ff_##x##_muxer); }  
//註冊AVInputFormat  
#define REGISTER_DEMUXER(X,x) { \  
    extern AVInputFormat ff_##x##_demuxer; \  
    if(CONFIG_##X##_DEMUXER) av_register_input_format(&ff_##x##_demuxer); }  
//註冊函式av_register_input_format  

//兩個一起註冊!  
#define REGISTER_MUXDEMUX(X,x)  REGISTER_MUXER(X,x); REGISTER_DEMUXER(X,x)  
//註冊URLProtocol  
//extern URLProtocol ff_##x##_protocol;  
//在librtmp中,對應的就是ff_rtmp_protocol  
//這樣就把librtmp整合起來了  
//由此可見URLProtocol的名字是固定的  
#define REGISTER_PROTOCOL(X,x) { \  
    extern URLProtocol ff_##x##_protocol; \  
    if(CONFIG_##X##_PROTOCOL) ffurl_register_protocol(&ff_##x##_protocol, sizeof(ff_##x##_protocol)); }  
//註冊函式ffurl_register_protocol  
void av_register_all(void)  
{  
    static int initialized;  

    if (initialized)  
        return;  
    initialized = 1;  
    //註冊所有的codec  
    avcodec_register_all();  
    //註冊所有的MUXER(複用器和解複用器)  
    /* (de)muxers */  
    REGISTER_MUXER    (A64, a64);  
    REGISTER_DEMUXER  (AAC, aac);  
    REGISTER_MUXDEMUX (AC3, ac3);  
    REGISTER_DEMUXER  (ACT, act);  
    REGISTER_DEMUXER  (ADF, adf);  

avcodec_register_all()

avcodec_register_all()註冊了和編解碼器有關的元件:硬體加速器,解碼器,編碼器,Parser,Bitstream Filter

avcodec_register()的原始碼:

//註冊所有的AVCodec  遍歷連結串列並把當前的AVCodec加到連結串列的尾部。
void avcodec_register(AVCodec *codec)  
{  
    AVCodec **p;  
    //初始化  
    avcodec_init();  
    //從第一個開始  
    p = &first_avcodec;  
    while (*p != NULL) p = &(*p)->next;  
    *p = codec;  
    codec->next = NULL;  

    if (codec->init_static_data)  
        codec->init_static_data(codec);  
} 

下面附上硬體加速器,編碼器/解碼器,parser,Bitstream Filter的註冊程式碼。

硬體加速器註冊函式是av_register_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;  
    }  

編解碼器註冊函式是avcodec_register()。

    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);  
    } 

parser註冊函式是av_register_codec_parser()。


    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));  
    } 

Bitstream Filter註冊函式是av_register_bitstream_filter()。


    void av_register_bitstream_filter(AVBitStreamFilter *bsf)  
    {  
        do {  
            bsf->next = first_bitstream_filter;  
        } while(bsf->next != avpriv_atomic_ptr_cas((void * volatile *)&first_bitstream_filter, bsf->next, bsf));  
    } 

後兩個函式中的avpriv_atomic_ptr_cas()定義如下。


    void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)  
    {  
        if (*ptr == oldval) {  
            *ptr = newval;  
            return oldval;  
        }  
        return *ptr;  
    }  

圖結:
這裡寫圖片描述