=====================================================

FFmpeg的库函数源代码分析文章列表:

【架构图】

FFmpeg源代码结构图 - 解码

FFmpeg源代码结构图 - 编码

【通用】

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

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

FFmpeg 源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

FFmpeg 源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

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

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

【脚本】

FFmpeg源代码简单分析:makefile

FFmpeg源代码简单分析:configure

【H.264】

FFmpeg的H.264解码器源代码简单分析:概述

=====================================================

本文记录FFmpeg的两个API函数:avcodec_find_encoder()和avcodec_find_decoder()。avcodec_find_encoder()用于查找FFmpeg的编码器,avcodec_find_decoder()用于查找FFmpeg的解码器。

avcodec_find_encoder()的声明位于libavcodec\avcodec.h,如下所示。

  1. /**
  2. * Find a registered encoder with a matching codec ID.
  3. *
  4. * @param id AVCodecID of the requested encoder
  5. * @return An encoder if one was found, NULL otherwise.
  6. */
  7. AVCodec *avcodec_find_encoder(enum AVCodecID id);

函数的参数是一个编码器的ID,返回查找到的编码器(没有找到就返回NULL)。
avcodec_find_decoder()的声明也位于libavcodec\avcodec.h,如下所示。

  1. /**
  2. * Find a registered decoder with a matching codec ID.
  3. *
  4. * @param id AVCodecID of the requested decoder
  5. * @return A decoder if one was found, NULL otherwise.
  6. */
  7. 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,如下所示。

  1. AVCodec *avcodec_find_encoder(enum AVCodecID id)
  2. {
  3. return find_encdec(id, 1);
  4. }

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

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

find_encdec()

find_encdec()的源代码位于libavcodec\utils.c,如下所示。

  1. static AVCodec *first_avcodec;
  2.  
  3. static AVCodec *find_encdec(enum AVCodecID id, int encoder)
  4. {
  5. AVCodec *p, *experimental = NULL;
  6. p = first_avcodec;
  7. id= remap_deprecated_codec_id(id);
  8. while (p) {
  9. if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) &&
  10. p->id == id) {
  11. if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) {
  12. experimental = p;
  13. } else
  14. return p;
  15. }
  16. p = p->next;
  17. }
  18. return experimental;
  19. }

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。

  1. /**
  2. * @return a non-zero number if codec is an encoder, zero otherwise
  3. */
  4. int av_codec_is_encoder(const AVCodec *codec);

av_codec_is_encoder()源代码很简单,如下所示。

  1. int av_codec_is_encoder(const AVCodec *codec)
  2. {
  3. return codec && (codec->encode_sub || codec->encode2);
  4. }

从源代码可以看出,av_codec_is_encoder()判断了一下AVCodec是否包含了encode2()或者encode_sub()接口函数。

av_codec_is_decoder()

av_codec_is_decoder()是一个判断AVCodec是否为解码器的函数。如果是解码器,返回非0值,否则返回0。

  1. /**
  2. * @return a non-zero number if codec is a decoder, zero otherwise
  3. */
  4. int av_codec_is_decoder(const AVCodec *codec);

av_codec_is_decoder()源代码也很简单,如下所示。

  1. int av_codec_is_decoder(const AVCodec *codec)
  2. {
  3. return codec && codec->decode;
  4. }

从源代码可以看出,av_codec_is_decoder()判断了一下AVCodec是否包含了decode()接口函数。

avcodec_find_decoder()

avcodec_find_decoder()的源代码位于libavcodec\utils.c,如下所示。

  1. AVCodec *avcodec_find_decoder(enum AVCodecID id)
  2. {
  3. return find_encdec(id, 0);
  4. }

可以看出avcodec_find_decoder()同样调用了find_encdec(),只是第2个参数设置为0。因此不再详细分析。

雷霄骅
leixiaohua1020@126.com
http://blog.csdn.net/leixiaohua1020

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

  1. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  2. FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  3. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  4. FFmpeg源代码简单分析:makefile

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  5. FFmpeg源代码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  6. FFmpeg源代码简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. FFmpeg源代码简单分析:结构体成员管理系统-AVOption

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  8. FFmpeg源代码简单分析:结构体成员管理系统-AVClass

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFmpeg源代码简单分析:日志输出系统(av_log()等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

随机推荐

  1. hdu5444(模拟)

    题意:建树,给你几个点,要求输出走到各个点的路径(左为E,右为W,树的遍历) 二叉树的模拟题,但是GG了两次. 主要是没注意到直接模拟会爆掉- -,进行下处理就好了 #include <iost ...

  2. Python Django系统

    本节内容 路由系统,视图函数,模板引擎,ORM操作 FBV和CBV ORM操作补充 Cookie和Session Ajax入门 1.  Django基本内容整理 1.1 路由系统 Django中路由系 ...

  3. ubuntu 系统应用安装方式

    转载   ubuntu系统软件安装 来源:http://www.linuxidc.com/Linux/2011-02/32211.htm 首先说明一下 ubuntu 的软件安装大概有几种方式:1. d ...

  4. Centos下出现read-only file system 的解决办法

    Centos下出现这种情况说明磁盘只能读不能写,出现这种情况一般是因为不正常的关机或者硬盘损坏导致磁盘挂载出现问题. 本萌新也遇到了这个问题,尝试了各种命令都不行,最后用了mount -o remou ...

  5. Python中生成器和迭代器的功能介绍

    生成器和迭代器的功能介绍 1. 生成器(generator) 1. 赋值生成器 1. 创建 方法:x = (variable for variable in iterable) 例如:x = (i f ...

  6. C语言程序设计第五次作业——循环结构1

    (一)改错题 输出华氏摄氏温度转换表:输入两个整数lower和upper,输出一张华氏摄氏温度转换表,华氏温度的取值范围是{lower,upper},每次增加2℉.计算公式如下: c = 5×(f-3 ...

  7. jvm(一):总体概述

    我们首先来了解一下jdk,jre,jvm的之间的关系 jvm用于运行字节码,如果我们仅仅用于运行java程序,仅部署jre即可,如果我们需要进行java开发则需要jdk环境 java结构内容: jav ...

  8. Just for mysql

    mysql的下载与安装 由于学校开设了数据库专业,并且最近准备在做一个web端的设计,虽然本人是负责前端(当然,前端技术也很LOW),但因种种原因,准备开始学习数据库相关的知识,以mysql为例. 昨 ...

  9. ExecutorService

    接口 java.util.concurrent.ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行.壹個 ExecutorService 实例因此特别像壹個线程池.事实上, ...

  10. 关于npm run build 报错解决方案

    # 特定的错误 ERROR in statics/mobile/js/vendor.cef13a0e680a5bc0d8b3.js from UglifyJsUnexpected token: pun ...