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

本文记录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。因此不再详细分析。

雷霄骅
[email protected]
http://blog.csdn.net/leixiaohua1020

时间: 2024-10-21 02:42:44

FFmpeg源代码简单分析:av_find_decoder()和av_find_encoder()的相关文章

(转)FFmpeg源代码简单分析:avformat_find_stream_info()

目录(?)[+] ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 FFmpeg源代码结构图 - 编码 [通用] FFmpeg 源代码简单分析:av_register_all() FFmpeg 源代码简单分析:avcodec_register_all() FFmpeg 源代码简单分析:内存的分配和释放(av_malloc().av_free()等)

FFmpeg源代码简单分析:avio_open2() (转载)

FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 FFmpeg源代码结构图 - 编码 [通用] FFmpeg 源代码简单分析:av_register_all() FFmpeg 源代码简单分析:avcodec_register_all() FFmpeg 源代码简单分析:内存的分配和释放(av_malloc().av_free()等) FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等) FFmpeg 源代

(转)FFmpeg源代码简单分析:avformat_open_input()

目录(?)[+] ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 FFmpeg源代码结构图 - 编码 [通用] FFmpeg 源代码简单分析:av_register_all() FFmpeg 源代码简单分析:avcodec_register_all() FFmpeg 源代码简单分析:内存的分配和释放(av_malloc().av_free()等)

FFmpeg源代码简单分析:avformat_open_input()

本文简单分析FFmpeg中一个常用的函数:avformat_open_input().该函数用于打开多媒体数据并且获得一些相关的信息.它的声明位于libavformat\avformat.h,如下所示. /** * Open an input stream and read the header. The codecs are not opened. * The stream must be closed with avformat_close_input(). * * @param ps Po

Ffmpeg解析media容器过程/ ffmpeg 源代码简单分析 : av_read_frame()

ffmpeg 源代码简单分析 : av_read_frame() http://blog.csdn.net/leixiaohua1020/article/details/12678577 ffmpeg中的av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧.例如,解码视频的时候,每解码一个视频帧,需要先调 用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码(例如H.264中一帧压缩数据通常对应一个NAL). 对该函数源代码的分析是很久之前做的了

FFmpeg源代码简单分析:av_write_trailer()

打算写两篇文章简单分析FFmpeg的写文件用到的3个函数avformat_write_header(),av_write_frame()以及av_write_trailer().这篇文章继续分析av_write_trailer(). av_write_trailer()用于输出文件尾,它的声明位于libavformat\avformat.h,如下所示. /** * Write the stream trailer to an output media file and free the * fi

FFmpeg源代码简单分析:avformat_close_input()

本文简单分析FFmpeg的avformat_close_input()函数.该函数用于关闭一个AVFormatContext,一般情况下是和avformat_open_input()成对使用的. avformat_close_input()的声明位于libavformat\avformat.h,如下所示. /** * Close an opened input AVFormatContext. Free it and all its contents * and set *s to NULL.

FFmpeg源代码简单分析——sws_getContext()

FFmpeg源代码简单分析——sws_getContext() 转载地址:http://www.ithtw.com/2032.html FFmpeg sws_scale分析1 转载地址:http://www.w2bc.com/Article/19701

FFmpeg源代码简单分析:avformat_find_stream_info()

本文简单分析FFmpeg中一个常用的函数:avformat_find_stream_info().该函数可以读取一部分视音频数据并且获得一些相关的信息.avformat_find_stream_info()的声明位于libavformat\avformat.h,如下所示. /** * Read packets of a media file to get stream information. This * is useful for file formats with no headers s