码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2015-03-06 12:44:00      阅读:480      评论:0      收藏:0      [点我收藏+]

标签:ffmpeg   源代码   编码器   解码器   

本文记录FFmpeg的两个API函数:avcodec_find_encoder()和avcodec_find_decoder()。avcodec_find_encoder()用于查找FFmpeg的编码器,avcodec_find_decoder()用于查找FFmpeg的解码器。
avcodec_find_encoder()的声明位于libavcodec\avcodec.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);
函数的参数是一个编码器的ID,返回查找到的编码器(没有找到就返回NULL)。
avcodec_find_decoder()的声明也位于libavcodec\avcodec.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);

函数的参数是一个解码器的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()的源代码位于libavcodec\utils.c,如下所示。
AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
    return find_encdec(id, 1);
}

从源代码可以看出avcodec_find_encoder()调用了一个find_encdec(),注意它的第二个参数是0。

下面我们看一下find_encdec()的定义。


find_encdec()

find_encdec()的源代码位于libavcodec\utils.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()中有一个循环,该循环会遍历AVCodec结构的链表,逐一比较输入的ID和每一个编码器的ID,直到找到ID取值相等的编码器。
在这里有几点需要注意:
(1)first_avcodec是一个全局变量,存储AVCodec链表的第一个元素。
(2)remap_deprecated_codec_id()用于将一些过时的编码器ID映射到新的编码器ID。
(3)函数的第二个参数encoder用于确定查找编码器还是解码器。当该值为1的时候,用于查找编码器,此时会调用av_codec_is_encoder()判断AVCodec是否为编码器;当该值为0的时候,用于查找解码器,此时会调用av_codec_is_decoder()判断AVCodec是否为解码器。

av_codec_is_encoder()

av_codec_is_encoder()是一个判断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()判断了一下AVCodec是否包含了encode2()或者encode_sub()接口函数。


av_codec_is_decoder()

av_codec_is_decoder()是一个判断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()判断了一下AVCodec是否包含了decode()接口函数。

avcodec_find_decoder()

avcodec_find_decoder()的源代码位于libavcodec\utils.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

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

标签:ffmpeg   源代码   编码器   解码器   

原文地址:http://blog.csdn.net/leixiaohua1020/article/details/44084557

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!