该函数用于初始化一个视音频编解码器的AVCodecContext。
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
];
  • snprintf(buf, sizeof(buf), "%d", avctx->pix_fmt);
  • av_log(avctx, AV_LOG_ERROR, "Specified pixel format %s is invalid or not supported\n",
  • (char *)av_x_if_null(av_get_pix_fmt_name(avctx->pix_fmt), buf));
  • ret = AVERROR(EINVAL);
  • goto free_and_end;
  • }
  • if (avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ420P ||
  • avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ411P ||
  • avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ422P ||
  • avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ440P ||
  • avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P)
  • avctx->color_range = AVCOL_RANGE_JPEG;
  • }
  • 可以看出,该代码首先进入了一个for()循环,将AVCodecContext中设定的pix_fmt与编码器AVCodec中的pix_fmts数组中的元素逐一比较。
    先简单介绍一下AVCodec中的pix_fmts数组。AVCodec中的pix_fmts数组存储了该种编码器支持的像素格式,并且规定以AV_PIX_FMT_NONE(AV_PIX_FMT_NONE取值为-1)为结尾。例如,libx264的pix_fmts数组的定义位于libavcodec\libx264.c,如下所示。
    1. staticconstenum AVPixelFormat pix_fmts_8bit[] = {
    2. AV_PIX_FMT_YUV420P,
    3. AV_PIX_FMT_YUVJ420P,
    4. AV_PIX_FMT_YUV422P,
    5. AV_PIX_FMT_YUVJ422P,
    6. AV_PIX_FMT_YUV444P,
    7. AV_PIX_FMT_YUVJ444P,
    8. AV_PIX_FMT_NV12,
    9. AV_PIX_FMT_NV16,
    10. AV_PIX_FMT_NONE
    11. };
    从pix_fmts_8bit的定义可以看出libx264主要支持的是以YUV为主的像素格式。
    现在回到“检查输入pix_fmt是否符合编码器的要求”的那段代码。如果for()循环从AVCodec->pix_fmts数组中找到了符合AVCodecContext->pix_fmt的像素格式,或者完成了AVCodec->pix_fmts数组的遍历,都会跳出循环。如果发现AVCodec->pix_fmts数组中索引为i的元素是AV_PIX_FMT_NONE(即最后一个元素,取值为-1)的时候,就认为没有找到合适的像素格式,并且最终提示错误信息。
    AVCodec->init()
    avcodec_open2()中最关键的一步就是调用AVCodec的init()方法初始化具体的编码器。AVCodec的init()是一个函数指针,指向具体编解码器中的初始化函数。这里我们以libx264为例,看一下它对应的AVCodec的定义。libx264对应的AVCodec的定义位于libavcodec\libx264.c,如下所示。
    1. AVCodec ff_libx264_encoder = {
    2. .name = "libx264",
    3. .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
    4. .type = AVMEDIA_TYPE_VIDEO,
    5. .id = AV_CODEC_ID_H264,
    6. .priv_data_size = sizeof(X264Context),
    7. .init = X264_init,
    8. .encode2 = X264_frame,
    9. .close = X264_close,
    10. .capabilities = CODEC_CAP_DELAY | CODEC_CAP_AUTO_THREADS,
    11. .priv_class = &x264_class,
    12. .defaults = x264_defaults,
    13. .init_static_data = X264_init_static,
    14. };
    可以看出在ff_libx264_encoder中init()指向X264_init()。X264_init()的定义同样位于libavcodec\libx264.c,
    X264_init()的代码以后研究X264的时候再进行细节的分析,在这里简单记录一下它做的两项工作:
    (1)设置X264Context的参数。X264Context主要完成了libx264和FFmpeg对接的功能。可以看出代码主要在设置一个params结构体变量,该变量的类型即是x264中存储参数的结构体x264_param_t。
    (2)调用libx264的API进行编码器的初始化工作。例如调用x264_param_default()设置默认参数,调用x264_param_apply_profile()设置profile,调用x264_encoder_open()打开编码器等等。
    X264Context的定义,位于libavcodec\libx264.c,

    avcodec_open2()分析的更多相关文章

    1. FFmpeg 学习(四):FFmpeg API 介绍与通用 API 分析

      一.FFmpeg 相关术语 1. 容器/文件(Container/File):即特定格式的多媒体文件,比如MP4,flv,mov等. 2. 媒体流(Stream):表示在时间轴上的一段连续的数据,比如 ...

    2. FFmpeg源代码简单分析:avcodec_open2()

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

    3. 转:LAV Filter 源代码分析

      1: 总体结构 LAV Filter 是一款视频分离和解码软件,他的分离器封装了FFMPEG中的libavformat,解码器则封装了FFMPEG中的libavcodec.它支持十分广泛的视音频格式. ...

    4. 转:XBMC源代码分析

      1:整体结构以及编译方法 XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0 ...

    5. 转:ffdshow 源代码分析

      ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...

    6. 最新版ffmpeg源码分析

      最新版ffmpeg源码分析一:框架 (ffmpeg v0.9) 框架 最新版的ffmpeg中发现了一个新的东西:avconv,而且ffmpeg.c与avconv.c一个模样,一研究才发现是libav下 ...

    7. FFmpeg资料来源简单分析:libswscale的sws_getContext()

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

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

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

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

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

    随机推荐

    1. MySql(十三):MySql架构设计——可扩展性设计之 MySQL Replication

      一.前言 MySQL Replication能够将一个 MySQL Server 的 Instance 中的数据完整的复制到另外一个 MySQL Server 的 Instance 中.虽然复制过程并 ...

    2. POJ 1200 Crazy Search(字符串简单的hash)

      题目:http://poj.org/problem?id=1200 最近看了一个关于hash的问题,不是很明白,于是乎就找了些关于这方面的题目,这道题是一道简单的hash 字符串题目,就先从他入手吧. ...

    3. 菜鸟学SSH(十六)——Struts2内部是如何工作的

      前面说完了Spring.Hibernate,很自然今天轮到struts了.struts的核心原理就是通过拦截器来处理客户端的请求,经过拦截器一系列的处理后,再交给Action.下面先看看struts官 ...

    4. AsyncContext简介

      为了支持异步处理,在Servlet 3.0中,在ServletRequest上提供了startAsync()方法: AsyncContext startAsync() throws Java.lang ...

    5. 每日英语:Apple Unveils New iPads

      Apple Inc. 's answer to the increasingly cutthroat tablet-computer market: more product choices and ...

    6. vim学习日志(8):linux查看和修改文件编码

      查看文件的编码 方法一: 1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.注:如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱码的问题,那么你可 ...

    7. COMPILING ACTIONSCRIPT 3.0 WITH SUBLIME TEXT 2

      At Clock we typically spend our time developing JavaScript and PHP, however, occasionally Flash pres ...

    8. C# JAVA 记录代码运行时间

      C# System.Diagnostics.Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // 开始监视代码运行时间 // cod ...

    9. JAVA-JSP内置对象之response对象实现页面自动跳转

      相关资料:<21天学通Java Web开发> response对象 实现页面自动跳转1.可以通过response对象的addHeader()方法添加一个标题为Refresh的标头,并指定页 ...

    10. C#学习笔记(16)——C#中重写(override)和覆盖(new)的区别

      说明(2017-7-17 23:04:45): 原文: C#中重写(override)和覆盖(new)的区别 重写 用关键字 virtual 修饰的方法,叫虚方法.可以在子类中用override 声明 ...