本文记录FFmpeg的两个API函数:avcodec_find_encoder()和avcodec_find_decoder()。avcodec_find_encoder()用于查找FFmpeg的编码器,avcodec_find_decoder()用于查找FFmpeg的解码器。
avcodec_find_encoder()的声明位于libavcodecavcodec.h,以下所示。
/**
* Find a registered encoder with a matching codec ID.
*
* @param id AVCodecID of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_encoder(enum AVCodecID id);
函数的参数是1个编码器的ID,返回查找到的编码器(没有找到就返回NULL)。
avcodec_find_decoder()的声明也位于libavcodecavcodec.h,以下所示。
/**
* Find a registered decoder with a matching codec ID.
*
* @param id AVCodecID of the requested decoder
* @return A decoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_decoder(enum AVCodecID id);
函数的参数是1个解码器的ID,返回查找到的解码器(没有找到就返回NULL)。
avcodec_find_encoder()函数最典型的例子可以参考:
最简单的基于FFMPEG的视频编码器(YUV编码为H.264)
avcodec_find_decoder()函数最典型的例子可以参考:
最简单的基于FFMPEG+SDL的视频播放器 ver2 (采取SDL2.0)
其实这两个函数的实质就是遍历AVCodec链表并且取得符合条件的元素。有关AVCodec链表的建立可以参考文章:
ffmpeg 源代码简单分析 : av_register_all()
函数调用关系图
avcodec_find_encoder()和avcodec_find_decoder()的函数调用关系图以下所示。
avcodec_find_encoder()
avcodec_find_encoder()的源代码位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
return find_encdec(id, 1);
}
从源代码可以看出avcodec_find_encoder()调用了1个find_encdec(),注意它的第2个参数是0。
下面我们看1下find_encdec()的定义。
find_encdec()
find_encdec()的源代码位于libavcodecutils.c,以下所示。
static AVCodec *first_avcodec;
static AVCodec *find_encdec(enum AVCodecID id, int encoder)
{
AVCodec *p, *experimental = NULL;
p = first_avcodec;
id= remap_deprecated_codec_id(id);
while (p) {
if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) &&
p->id == id) {
if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return p;
}
p = p->next;
}
return experimental;
}
find_encdec()中有1个循环,该循环会遍历AVCodec结构的链表,逐1比较输入的ID和每个编码器的ID,直到找到ID取值相等的编码器。
在这里有几点需要注意:
(1)first_avcodec是1个全局变量,存储AVCodec链表的第1个元素。
(2)remap_deprecated_codec_id()用于将1些过时的编码器ID映照到新的编码器ID。
(3)函数的第2个参数encoder用于肯定查找编码器还是解码器。当该值为1的时候,用于查找编码器,此时会调用av_codec_is_encoder()判断AVCodec是不是为编码器;当该值为0的时候,用于查找解码器,此时会调用av_codec_is_decoder()判断AVCodec是不是为解码器。
av_codec_is_encoder()
av_codec_is_encoder()是1个判断AVCodec是不是为编码器的函数。如果是编码器,返回非0值,否则返回0。
/**
* @return a non-zero number if codec is an encoder, zero otherwise
*/
int av_codec_is_encoder(const AVCodec *codec);
av_codec_is_encoder()源代码很简单,以下所示。
int av_codec_is_encoder(const AVCodec *codec)
{
return codec && (codec->encode_sub || codec->encode2);
}
从源代码可以看出,av_codec_is_encoder()判断了1下AVCodec是不是包括了encode2()或encode_sub()接口函数。
av_codec_is_decoder()
av_codec_is_decoder()是1个判断AVCodec是不是为解码器的函数。如果是解码器,返回非0值,否则返回0。
/**
* @return a non-zero number if codec is a decoder, zero otherwise
*/
int av_codec_is_decoder(const AVCodec *codec);
av_codec_is_decoder()源代码也很简单,以下所示。
int av_codec_is_decoder(const AVCodec *codec)
{
return codec && codec->decode;
}
从源代码可以看出,av_codec_is_decoder()判断了1下AVCodec是不是包括了decode()接口函数。
avcodec_find_decoder()
avcodec_find_decoder()的源代码位于libavcodecutils.c,以下所示。
AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
return find_encdec(id, 0);
}
可以看出avcodec_find_decoder()一样调用了find_encdec(),只是第2个参数设置为0。因此不再详细分析。
雷霄骅
leixiaohua1020@126.com
http://blog.csdn.net/leixiaohua1020