日期:2016.10.18
作者:isshe
github:github.com/isshe
邮箱:i.sshe@outlook.com
前言
接下来打算学习一下编解码,不过好像很难的样子, 希望能看懂。
1. av_register_all()
- 所在文件:allformats.c
- 主要代码:(每个宏只列举一个)
void av_register_all(void)
{
static int initialized;
if (initialized)
return;
//注册编解码器
avcodec_register_all();
/* (de)muxers */
//注册复用器
REGISTER_MUXER (A64, a64);
//注册解复用器
REGISTER_DEMUXER (AA, aa);
//两个同时注册
REGISTER_MUXDEMUX(AC3, ac3);
1.1 REGISTER_MUXER宏
- 代码:
#define REGISTER_MUXER(X, x) \
{ \
extern AVOutputFormat ff_##x##_muxer; \
if (CONFIG_##X##_MUXER) \
av_register_output_format(&ff_##x##_muxer); \
}
- “##”号起连接作用,例如:a##b = ab.
- ff_##x##_muxer, 一个与x对应的AVOutputFormat.
- 其实这些外部变量,一般定义的时候就赋了初值。(限于篇幅,具体的示例在下面编解码相关的地方)
1.1.1 av_register_output_format()
- 注册一个与该格式相应的AVFormat结构
- 相关代码:
//head of registered output format linked list
static AVOutputFormat *first_oformat = NULL;
static AVOutputFormat **last_oformat = &first_oformat;
void av_register_output_format(AVOutputFormat *format)
{
AVOutputFormat **p = last_oformat;
// Note, format could be added after the first 2 checks but that implies that *p is no longer NULL
//检查链表中有无指定的format,没有就加入。
//在前面两个条件成立后才把format连接到p链表中。
while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
p = &(*p)->next;
if (!format->next)
last_oformat = &format->next;
}
- last_oformat是一个二次指针。
- avpriv_atomic_ptr_cas把format放到p链表中。
- 遍历链表,把指定format加到链表后面。
1.2 REGISTER_DEMUXER 宏
- 和REGISTER_MUXER()类似。
1.3 REGISTER_MUXDEMUX 宏
- #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
2. avcodec_register_all()
- 所在文件:allcodecs.c
- 主要代码:(每种情况列举一个)
void avcodec_register_all(void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
//硬件加速器
/* hardware accelerators */
REGISTER_HWACCEL(H263_CUVID, h263_cuvid);
//注意以下函数适用于视频和音频
//注册编码器
REGISTER_ENCODER(A64MULTI, a64multi);
//注册解码器
REGISTER_DECODER(AASC, aasc);
//两个同时注册
REGISTER_ENCDEC (ALIAS_PIX, alias_pix);
//注册分析器???不懂
REGISTER_PARSER(AAC, aac);
2.1 REGISTER_HWACCEL 宏
- 注册硬件加速器宏
- 代码:
#define REGISTER_HWACCEL(X, x) \
{ \
extern AVHWAccel ff_##x##_hwaccel; \
if (CONFIG_##X##_HWACCEL) \
av_register_hwaccel(&ff_##x##_hwaccel); \
}
- extern的那个变量在源码中没找着…
2.1.1 av_register_hwaccel()
- 注册硬件加速器的函数
- 代码:和前面的muter类似。
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;
}
2.2 REGISTER_ENCODER宏
- 注册编码器的宏
- 代码:
#define REGISTER_ENCODER(X, x) \
{ \
extern AVCodec ff_##x##_encoder; \
if (CONFIG_##X##_ENCODER) \
avcodec_register(&ff_##x##_encoder); \
}
2.2.1 ff_##x##_encoder变量
- 用aac示例:ff_aac_encoder变量
AVCodec ff_aac_encoder = {
.name = "aac",
.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACEncContext),
.init = aac_encode_init, //初始化
.encode2 = aac_encode_frame, //编码函数
.close = aac_encode_end, //
.defaults = aac_encode_defaults,
.supported_samplerates = mpeg4audio_sample_rates,
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.priv_class = &aacenc_class,
};
- 可见,这些外部变量都是已经赋值好的,解码的【或其他】也类似。
- 下面调用的注册函数就是把这么一个结构放到链表中。
2.2.2 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);
}
2.3 REGISTER_DECODER 宏
- 和编码类似
2.4 REGISTER_ENCDEC 宏
- 同时注册解码和编码器
2.5 REGISTER_PARSER 宏
- 代码:
#define REGISTER_PARSER(X, x) \
{ \
extern AVCodecParser ff_##x##_parser; \
if (CONFIG_##X##_PARSER) \
av_register_codec_parser(&ff_##x##_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));
}
参考资料
- 雷神博文:av_register_all()
- 雷神博文:avcodec_register_all()
- ffmpeg-3.1.3源码
代码下载
- ffmpeg-3.1.3源码:http://download.csdn.net/detail/i_scream_/9657369