程序员人生 网站导航

FFmpeg源代码简单分析:av_find_decoder()和av_find_encoder()

栏目:php教程时间:2015-03-10 08:08:49
本文记录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

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐