摘要:本文主要描述了FFmpeg中用于打开编解码器接口avcodec_open2大致流程的具体调用流程,详细描述了该接口被调用时所作的具体工作。
  关键字ffmpegavcodec_open2大致流程
  注意:读者需要了解FFmpeg的基本使用流程,以及一些FFmpeg的基本常识,了解FFmpegIO相关的内容,以及大致的解码流程。

1 avcodec_open2大致流程

  打开codec(codec和编码器统称为codec)前需要通过avcodec_find_decoder找到具体的codec,该函数的实现本身就是遍历FFmpeg内部的一个全局codec_list,该列表存储了目前FFmpeg设置成的所有codec和编码器的AVCodec指针。
  找到codecAVCodec之后需要自己通过avcodec_alloc_context3创建一个AVCodecContext的对象,该对象描述了当前codec的上下文,包含了一些流相关的信息,而AVCodec仅仅描述codec本身和流无关。一切准备好之后就需要调用avcodec_open2打开codec。

2 调用流程详情

  从上面的流程中能够看出来avcodec_open2主要做了三件事情:

  1. 参数检查与设置;
  2. 初始化codec线程;
  3. 初始化codec。

  参数设置基本上都是一个基本涉及解码过程的参数。首先是进行一些基本的参数设置与检查然后对codec的加锁,该锁是一个全局锁,所以这部分是线程安全的。FFmpeg使用的锁和线程相关都是pthread

static AVMutex codec_mutex = AV_MUTEX_INITIALIZER;

  中间还有一些基本的参数设置与检查就不细细描述了。
  初始化codec时会创建一个AVCodecDescriptorcodec描述,这个也是从一个内部的全局表格codec_descriptors中搜索得到的。之后会根据当前codec的类型分别调用ff_encode_preinitff_decode_preinit做一些基本的初始化,这里面也是对当前codec的一些基本参数设置和一些和codec本身相关的对象的创建。而最终的codec初始化就是调用具体的codec初始化函数指针进行。
  avctx->codec->init就是一个函数指针,每个codec对象都有初始化,编解码相关的接口,这里直接调用的是具体codec内部的函数指针。比如H264解码的AVCodec的指针为如下所示。

const AVCodec ff_h264_decoder = {.name                  = "h264",.long_name             = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),.type                  = AVMEDIA_TYPE_VIDEO,.id                    = AV_CODEC_ID_H264,.priv_data_size        = sizeof(H264Context),.init                  = h264_decode_init,.close                 = h264_decode_end,.decode                = h264_decode_frame,//....
}

  线程初始化ff_thread_init用于初始化codec运行时的解码线程内部会创建多个线程的context并初始化,初始化最终调用的是pthread_***_init接口进行初始化。

err = init_pthread(fctx, thread_ctx_offsets);
if (err < 0) {free_pthread(fctx, thread_ctx_offsets);av_freep(&avctx->internal->thread_ctx);return err;
}fctx->async_lock = 1;
fctx->delaying = 1;if (codec->type == AVMEDIA_TYPE_VIDEO)avctx->delay = src->thread_count - 1;fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext));
if (!fctx->threads) {err = AVERROR(ENOMEM);goto error;
}for (; i < thread_count; ) {PerThreadContext *p  = &fctx->threads[i];int first = !i;err = init_thread(p, &i, fctx, avctx, src, codec, first);if (err < 0)goto error;
}

3 其他细节

  avcodec_open2参数部分针对解码器和编码器的不同有区分,具体的代码就是下面这部分

    if (av_codec_is_decoder(avctx->codec)) {if (!avctx->bit_rate)//这里的码率获取是根据数据源的不同而不同的,非音频流都是返回avtx的bitrate。而音频流则需要根据当前的解码器参数进行计算避免参数不一致avctx->bit_rate = get_bit_rate(avctx);/* validate channel layout from the decoder */if (avctx->channel_layout) {int channels = av_get_channel_layout_nb_channels(avctx->channel_layout);if (!avctx->channels)avctx->channels = channels;else if (channels != avctx->channels) { char buf[512];av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout);av_log(avctx, AV_LOG_WARNING,"Channel layout '%s' with %d channels does not match specified number of channels %d: ""ignoring specified channel layout\n",buf, channels, avctx->channels);avctx->channel_layout = 0;}}if (avctx->channels && avctx->channels < 0 ||avctx->channels > FF_SANE_NB_CHANNELS) {ret = AVERROR(EINVAL);goto free_and_end;}if (avctx->bits_per_coded_sample < 0) {ret = AVERROR(EINVAL);goto free_and_end;}#if FF_API_AVCTX_TIMEBASEif (avctx->framerate.num > 0 && avctx->framerate.den > 0)avctx->time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1}));
#endif}

  预先初始化时解码器和编码器分别调用的ff_decode_preinitff_encode_preinit
  ff_decode_preinit主要就是初始化AVBSFContext,其他都是对参数进行校验。
  ff_encode_preinit中会检查编码器和编码器Context的参数是不是能够对上如果对不上就会尝试校正,这些参数包括音频通道数,视频色彩范围,音频采样率、音频layout等等。

FFmpeg5.0源码阅读—— avcodec_open2相关推荐

  1. FFmpeg5.0源码阅读之AVClass和AVOption

      摘要:本文通过阅读FFmpeg源码来理解FFmpeg中AVOption的实现原理和具体的使用方式.   关键字:AVClss,AVOption,AVOptionRange   版本:FFmpeg5 ...

  2. FFmpeg5.0源码阅读——AVFrame

      摘要:AVFrame是FFmpeg中表示裸数据的结构体,是FFmpeg最重要的结构体之一.本篇文章针对FFmpeg源码理解AVFrame的作用,相关的结构定义以及一些操作API的具体实现.   关 ...

  3. FFmpeg5.0源码阅读——avformat_open_input

      摘要:本文主要描述了FFmpeg中用于打开文件接口avformat_open_input的具体调用流程,详细描述了该接口被调用时所作的具体工作.   关键字:ffmpeg.avformat_ope ...

  4. FFmpeg5.0源码阅读——mov文件格式解析

    摘要:之前在Mp4格式详解中详细描述了Mp4文件格式的具体布局方式.为了更加深入理解mp4文件格式,本文记录了ffmpeg中解封装mp4文件的基本实现. 关键字:mov.FFmpeg.mp4 1 简介 ...

  5. FFmpeg5.0源码阅读—— av_read_frame

      摘要:本文主要描述了FFmpeg中用于打开编解码器接口av_read_frame的具体调用流程,详细描述了该接口被调用时所作的具体工作.   关键字:ffmpeg.av_read_frame    ...

  6. FFmpeg5.0源码阅读——av_interleaved_write_frame

      摘要:本文主要详细描述FFmpeg中封装时写packet到媒体文件的函数av_interleaved_write_frame的实现.   关键字:av_interleaved_write_fram ...

  7. Spring Boot 2.0系列文章(四):Spring Boot 2.0 源码阅读环境搭建

    前提 前几天面试的时候,被问过 Spring Boot 的自动配置源码怎么实现的,没看过源码的我只能投降��了. 这不,赶紧来补补了,所以才有了这篇文章的出现,Spring Boot 2. 0 源码阅 ...

  8. CloudSim 4.0源码阅读笔记(功耗实例)

    文章目录 一.NonPowerAware案例 1.1 基本概述 1.2 云任务/虚机/主机/功耗模型参数设置 1.3 初始化云任务(CloudletList)-如何载入自定义真实数据集中的CPU利用率 ...

  9. AFNetworking 3.0源码阅读 - AFURLResponseSerialization

    这次来说一下AFURLResponseSerialization这个HTTP响应类. 定义了一个协议,该协议返回序列化后的结果.后续的AFHTTPResponseSerializer以及他的子类都遵循 ...

最新文章

  1. Mac 从Makefile 编译 Rocksdb 源码的一些注意事项
  2. python绘制月亮_用python画月亮的代码是什么?
  3. 时代亿信 文件共享访问控制网关
  4. 查看SQL SERVER 加密存储过程,函数,触发器,视图
  5. 详细介绍mysql-bin.000001文件的来源及处理方法
  6. 阿里云+wordpress搭建个人网站及博客
  7. java下载网页所有图片_java 下载网页,图片 | 学步园
  8. 我不捐了!日本前首富孙正义欲提供肺炎检测试剂遭网友攻击:被骂到放弃
  9. [C++]虚函数-同名访问
  10. [转载] python中将str转成数字_python如何将字符转换为数字
  11. Confluence 6 Oracle 创建数据库用户
  12. 夏普Sharp MX-C3581R 一体机驱动
  13. 图片转字符画,GIF动画转GIF字符动画
  14. Jikes 研究虚拟机(RVM)一 设计和实现问题
  15. 流量分类方法设计(一)——参考论文整理
  16. 普利姆(prim)算法与迪杰斯特拉(dijestella)算法
  17. css button自动调整位置_CSS 小技巧
  18. c#Winform代码里中英文切换
  19. springboot websocket 传递 头信息 协议头 token 的前后端解决方案
  20. 打开sw出现无法识别计算机,solidworks不识别step怎么办 solidworks无法打开step解决办法...

热门文章

  1. 特斯拉 开源_特斯拉开源其安全软件,好莱坞开源,更多新闻
  2. 如何在网页上实现音乐播放?
  3. 自媒体前景到底如何?2017下半年十大趋势预测
  4. 遭遇Worm.UsbSpy.a/Worm.Win32.Delf.aj
  5. 俄罗斯方块 c语言期中作业
  6. 几句很有生活哲理的话
  7. oracle动态 returning,[数据库]oracle:RETURNING 子句
  8. 鬼画符门之点点大阵(python)
  9. STM32F103ZET6常用引脚重映射汇总
  10. 7-47 抢红包 (25 分)