FFmpeg源代码简单分析:av_find_decoder()和av_find_encoder()
=====================================================
FFmpeg的库函数源代码分析文章列表:
【架构图】
【通用】
FFmpeg 源代码简单分析:av_register_all()
FFmpeg 源代码简单分析:avcodec_register_all()
FFmpeg 源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)
FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)
FFmpeg 源代码简单分析:av_find_decoder()和av_find_encoder()
FFmpeg 源代码简单分析:avcodec_open2()
FFmpeg 源代码简单分析:avcodec_close()
【解码】
图解FFMPEG打开媒体的函数avformat_open_input
FFmpeg 源代码简单分析:avformat_open_input()
FFmpeg 源代码简单分析:avformat_find_stream_info()
FFmpeg 源代码简单分析:av_read_frame()
FFmpeg 源代码简单分析:avcodec_decode_video2()
FFmpeg 源代码简单分析:avformat_close_input()
【编码】
FFmpeg 源代码简单分析:avformat_alloc_output_context2()
FFmpeg 源代码简单分析:avformat_write_header()
FFmpeg 源代码简单分析:avcodec_encode_video()
FFmpeg 源代码简单分析:av_write_frame()
FFmpeg 源代码简单分析:av_write_trailer()
【其它】
FFmpeg源代码简单分析:日志输出系统(av_log()等)
FFmpeg源代码简单分析:结构体成员管理系统-AVClass
FFmpeg源代码简单分析:结构体成员管理系统-AVOption
FFmpeg源代码简单分析:libswscale的sws_getContext()
FFmpeg源代码简单分析:libswscale的sws_scale()
FFmpeg源代码简单分析:libavdevice的avdevice_register_all()
FFmpeg源代码简单分析:libavdevice的gdigrab
【脚本】
【H.264】
=====================================================
本文记录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源代码简单分析:libavdevice的gdigrab
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:libavdevice的avdevice_register_all()
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:configure
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:makefile
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:libswscale的sws_scale()
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:libswscale的sws_getContext()
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:结构体成员管理系统-AVOption
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:结构体成员管理系统-AVClass
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
- FFmpeg源代码简单分析:日志输出系统(av_log()等)
===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...
随机推荐
- hdu 5521 最短路
Meeting Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- hdu 5607 BestCoder Round #68 (矩阵快速幂)
graph Accepts: 9 Submissions: 61 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 ...
- Codeforces Round #430 B. Gleb And Pizza
Gleb ordered pizza home. When the courier delivered the pizza, he was very upset, because several pi ...
- Java多线程基础总结
一.线程和进程关系 二.创建方式1.继承Thread类,重写run方法2.实现Runable接口,重写run方法3.使用匿名内部类 三.API接口start()currentThread() 获取当前 ...
- Java文件操作(新建,遍历,删除)
//创建文件 private static void createFile(File file){ try { if(!file.exists()){ if(file.getParentFile() ...
- Amazon新一代云端关系数据库Aurora(上)
本文由 网易云发布. 在2017年5月芝加哥举办的世界顶级数据库会议SIGMOD/PODS上,作为全球最大的公有云服务提供商,Amazon首次系统的总结 了新一代云端关系数据库Aurora的设计实现 ...
- C++符号优先级
C++符号优先级 优先级 操作符 功能 用法 结合性 1 ()[]->.::++-- Grouping operatorArray accessMember access from a poin ...
- 关于惠普hp服务器开机时F10菜单变成F10 Function Disabled的解决方法
今天笔者由于在Intelligent Provisioning智能配置里不小心将"启动Intelligent Provisioning"选项钩选成禁用了,如下 结果就造成,在之后服 ...
- 手写JAVA虚拟机(二)——实现java命令行
查看手写JAVA虚拟机系列可以进我的博客园主页查看. 我们知道,我们编译.java并运行.class文件时,需要一些java命令,如最简单的helloworld程序. 这里的程序最好不要加包名,因为加 ...
- VGG网路结构
VGG网络的基本结构 如图所示,从A到E网络的深度是逐渐增加的,在A中有11个权重层(8个卷积层,3个全连接层),在E中有19个权重层(16个卷积层,3个全连接层),卷积层的宽度是十分小的,开始时在第 ...