ffmpeg分析系列之一(註冊編解碼器)

一. 調用av_register_all函數註冊所有的格式和編碼解碼器.

1.1 先調用avcodec_register_all函數註冊所有的編碼解碼器.

1. 下面列出與H264相關的註冊:

    // 註冊硬件加速器
    REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
    REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);

    // 註冊解碼器
    REGISTER_DECODER (H264, h264);
    REGISTER_DECODER (H264_VDPAU, h264_vdpau);

    // 註冊編碼器
    REGISTER_ENCODER (LIBX264, libx264);

    // 註冊分析器
    REGISTER_PARSER (H264, h264);

    // 註冊位流分離器
    REGISTER_BSF (H264_MP4TOANNEXB, h264_mp4toannexb);


2. 下面列出註冊宏:

#define REGISTER_HWACCEL(X,x) { \
          extern AVHWAccel x##_hwaccel; \
          if(CONFIG_##X##_HWACCEL) av_register_hwaccel(&x##_hwaccel); }

#define REGISTER_ENCODER(X,x) { \
          extern AVCodec x##_encoder; \
          if(CONFIG_##X##_ENCODER) avcodec_register(&x##_encoder); }

#define REGISTER_DECODER(X,x) { \
          extern AVCodec x##_decoder; \
          if(CONFIG_##X##_DECODER) avcodec_register(&x##_decoder); }

#define REGISTER_ENCDEC(X,x) REGISTER_ENCODER(X,x); REGISTER_DECODER(X,x)

#define REGISTER_PARSER(X,x) { \
          extern AVCodecParser x##_parser; \
          if(CONFIG_##X##_PARSER) av_register_codec_parser(&x##_parser); }

#define REGISTER_BSF(X,x) { \
          extern AVBitStreamFilter x##_bsf; \
          if(CONFIG_##X##_BSF) av_register_bitstream_filter(&x##_bsf); }

以MPEG2VEDIO的解碼器註冊爲例來說明:#define REGISTER_DECODER(MPEG2VEDIO,mpeg2video) { \
          extern AVCodecmpeg2video_decoder; \
          if(CONFIG_MPEG2VEDIO_DECODER) avcodec_register(&mpeg2video_decoder); 

調用:void  avcodec_register(AVCodec*codec)

{

    AVCodec **p;

    avcodec_init();

    p = &first_avcodec;     //初始化公共變量first_avcodec   

while(*p != NULL) p = &(*p)->next;

    *p = codec;

    codec->next = NULL;

}

此處就會將mpeg2video_decoder註冊到first_iformat結構體鏈表中,

mpeg2video_decoder結構體在Mpeg12.c中定義。

AVCodec mpegvideo_decoder = {
    "mpegvideo",
    CODEC_TYPE_VIDEO,
    CODEC_ID_MPEG2VIDEO,
    sizeof(Mpeg1Context),
    mpeg_decode_init,
    NULL,
    mpeg_decode_end,
    mpeg_decode_frame,
    CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY,
    .flush= ff_mpeg_flush,
    .long_name= NULL_IF_CONFIG_SMALL("MPEG-1 video"),
};


3. 分析一下注冊函數, 以avcodec_register函數爲例:

void avcodec_register(AVCodec *codec)
{
    AVCodec **p;
    avcodec_init();
    p = &first_avcodec;
    while (*!= NULL) p = &(*p)->next;
    *= codec;
    codec->next = NULL;
}


    可以看到avcodec_register函數把輸入的AVCodec連成一個鏈表, 其它註冊函數與之類似, 就不多言了.

4. 上面調用了avcodec_init函數:

void avcodec_init(void)
{
    static int initialized = 0;

     if (initialized != 0)
        return;
    initialized = 1;

    dsputil_static_init ();
}


    這個函數只會真正執行一次.

5. 上面調用了dsputil_static_init函數:

av_cold void dsputil_static_init(void)
{
    int i;

     for(i=0;i<256;i++) ff_cropTbl[+ MAX_NEG_CROP] = i;
    for(i=0;i<MAX_NEG_CROP;i++) {
        ff_cropTbl[i] = 0;
        ff_cropTbl[+ MAX_NEG_CROP + 256] = 255;
    }

     for(i=0;i<512;i++) {
        ff_squareTbl[i] = (- 256) * (- 256);
    }

     for(i=0; i<64; i++) inv_zigzag_direct16[ff_zigzag_direct[i]]= i+1;
}

    
    可以看到, 它初始化了一些靜態數據.

1.2 註冊所有的格式和外部庫及協議.

1. 下面列出與H264相關的註冊:

    // 註冊分離器和混合器
    REGISTER_MUXDEMUX (H264, h264);

    // 註冊文件協議
    REGISTER_PROTOCOL (FILE, file);


2. 下面列出註冊宏:

#define REGISTER_MUXER(X,x) { \
    extern AVOutputFormat x##_muxer; \
    if(CONFIG_##X##_MUXER) av_register_output_format(&x##_muxer); }

#define REGISTER_DEMUXER(X,x) { \
    extern AVInputFormat x##_demuxer; \
    if(CONFIG_##X##_DEMUXER) av_register_input_format(&x##_demuxer); }

#define REGISTER_MUXDEMUX(X,x) REGISTER_MUXER(X,x); REGISTER_DEMUXER(X,x)

#define REGISTER_PROTOCOL(X,x) { \
    extern URLProtocol x##_protocol; \
    if(CONFIG_##X##_PROTOCOL) av_register_protocol(&x##_protocol); }

 

av_register_input_format (AVInputFormat  *format)

  {

    AVInputFormat **p;

    p = &first_iformat;   //初始化公共變量first_iformat,這裏包含了輸入流的格式

    while (*p != NULL) p = &(*p)->next;

    *p = format;

    format->next = NULL;

}

voidav_register_output_format(AVOutputFormat *format)

{

    AVOutputFormat **p;

    p = &first_oformat;   //初始化公共變量first_oformat,這裏包含了輸出流的格式

    while (*p != NULL) p = &(*p)->next;

    *p = format;

    format->next = NULL;

}

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


 //以mpegts流爲例,x_demuxer將會被mpegts_demux所代替。而mpegts_demux爲一個AVInputFormat結構體,其定義在mpegts.c中。


AVInputFormat mpegts_demuxer = {

   "mpegts",

   NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"),

   sizeof(MpegTSContext),

   mpegts_probe,

   mpegts_read_header,

   mpegts_read_packet,

   mpegts_read_close,

   read_seek,

   mpegts_get_pcr,

   .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT,

}; 

此處的註冊會將使所有的複用和解複用註冊到first_iformat鏈表當中。

first_avcodec:全局的變量,將所有的編解碼器鏈接成一個鏈表:REGISTER_ENCODER(X,x) + REGISTER_DECODER  ---> avcodec_register();

first_iformat:全局的變量,將所有的解複用鏈接一個鏈表              REGISTER_MUXER(X,x)         --->   av_register_input_format()  

first_oformat:全局的變量,將所以的複用鏈接成一個鏈表 。       REGISTER_MUXER(X,x)         ---->   av_register_output_format()  

first_protocol:全局的變量,將所有支持的協議鏈接成鏈表。       REGISTER_PROTOCOL(X,x)  ---->  av_register_protocol




ffmpeg支持協議:  file , Gopher , HTTP , PIPE, RTP , TCP , UDP.定義在  Allformats.c中:

   REGISTER_PROTOCOL (FILE, file);   

    REGISTER_PROTOCOL (GOPHER, gopher);
    REGISTER_PROTOCOL (HTTP, http);
    REGISTER_PROTOCOL (PIPE, pipe);
    REGISTER_PROTOCOL (RTP, rtp);
    REGISTER_PROTOCOL (TCP, tcp);
    REGISTER_PROTOCOL (UDP, udp);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章