ffmpeg原始碼簡析(二)av_register_all(),avcodec_register_all()
阿新 • • 發佈:2019-01-08
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;
}
圖結: