ffmpeg学习六:avcodec_open2函数源码分析

2024-06-19 15:18

本文主要是介绍ffmpeg学习六:avcodec_open2函数源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一节我们尝试分析了avformat_open_input函数的源码,这个函数的虽然比较复杂,但是它基本是围绕着创建和初始化一些数据结构来展开的,比如,avformat_open_input函数会创建和初始化AVFormatContext,AVClass ,AVOption,URLContext,URLProtocol ,AVInputFormat ,AVStream等数据结构,这些数据结构的关系如下:
这里写图片描述
(这里的箭头是包含关系,不是继承关系)

那么,我们可以推测,同样作为Open系列的函数,avcodec_open2的使命也必然是构建和初始化一系列的数据结构,那么是不是这样呢?
avcodec_open2函数定义在libavcodec/aviocodec.h中:

/*** Initialize the AVCodecContext to use the given AVCodec. Prior to using this* function the context has to be allocated with avcodec_alloc_context3().** The functions avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),* avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for* retrieving a codec.** @warning This function is not thread safe!** @note Always call this function before using decoding routines (such as* @ref avcodec_receive_frame()).** @code* avcodec_register_all();* av_dict_set(&opts, "b", "2.5M", 0);* codec = avcodec_find_decoder(AV_CODEC_ID_H264);* if (!codec)*     exit(1);** context = avcodec_alloc_context3(codec);** if (avcodec_open2(context, codec, opts) < 0)*     exit(1);* @endcode** @param avctx The context to initialize.* @param codec The codec to open this context for. If a non-NULL codec has been*              previously passed to avcodec_alloc_context3() or*              for this context, then this parameter MUST be either NULL or*              equal to the previously passed codec.* @param options A dictionary filled with AVCodecContext and codec-private options.*                On return this object will be filled with options that were not found.** @return zero on success, a negative value on error* @see avcodec_alloc_context3(), avcodec_find_decoder(), avcodec_find_encoder(),*      av_dict_set(), av_opt_find().*/
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

从它的注释中我们可以得到如下信息:
1.使用所给的AVCodec结构体构造AVCodecContext结构体。
2.avcodec_find_decoder_by_name(), avcodec_find_encoder_by_name(),
* avcodec_find_decoder() and avcodec_find_encoder(),这几个函数提供了方便获取AVCodecContext实例的途径。
3.这个函数是线程不安全函数
4.在使用解码程序之前,必须调用此函数。

综上,avcodec_open2函数的核心人物是构造AVCodecContext结构体。
avcodec_open2函数在libavcodec/utils.c中实现:

int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
{int ret = 0;AVDictionary *tmp = NULL;const AVPixFmtDescriptor *pixdesc;if (avcodec_is_open(avctx))return 0;if ((!codec && !avctx->codec)) {av_log(avctx, AV_LOG_ERROR, "No codec provided to avcodec_open2()\n");return AVERROR(EINVAL);}if ((codec && avctx->codec && codec != avctx->codec)) {av_log(avctx, AV_LOG_ERROR, "This AVCodecContext was allocated for %s, ""but %s passed to avcodec_open2()\n", avctx->codec->name, codec->name);return AVERROR(EINVAL);}if (!codec)codec = avctx->codec;if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE)return AVERROR(EINVAL);if (options)av_dict_copy(&tmp, *options, 0);ret = ff_lock_avcodec(avctx, codec);if (ret < 0)return ret;avctx->internal = av_mallocz(sizeof(AVCodecInternal));if (!avctx->internal) {ret = AVERROR(ENOMEM);goto end;}avctx->internal->pool = av_mallocz(sizeof(*avctx->internal->pool));if (!avctx->internal->pool) {ret = AVERROR(ENOMEM);goto free_and_end;}avctx->internal->to_free = av_frame_alloc();if (!avctx->internal->to_free) {ret = AVERROR(ENOMEM);goto free_and_end;}avctx->internal->buffer_frame = av_frame_alloc();if (!avctx->internal->buffer_frame) {ret = AVERROR(ENOMEM);goto free_and_end;}avctx->internal->buffer_pkt = av_packet_alloc();if (!avctx->internal->buffer_pkt) {ret = AVERROR(ENOMEM);goto free_and_end;}if (codec->priv_data_size > 0) {if (!avctx->priv_data) {avctx->priv_data = av_mallocz(codec->priv_data_size);if (!avctx->priv_data) {ret = AVERROR(ENOMEM);goto end;}if (codec->priv_class) {*(const AVClass **)avctx->priv_data = codec->priv_class;av_opt_set_defaults(avctx->priv_data);}}if (codec->priv_class && (ret = av_opt_set_dict(avctx->priv_data, &tmp)) < 0)goto free_and_end;} else {avctx->priv_data = NULL;}if ((ret = av_opt_set_dict(avctx, &tmp)) < 0)goto free_and_end;if (avctx->codec_whitelist && av_match_list(codec->name, avctx->codec_whitelist, ',') <= 0) {av_log(avctx, AV_LOG_ERROR, "Codec (%s) not on whitelist \'%s\'\n", codec->name, avctx->codec_whitelist);ret = AVERROR(EINVAL);goto free_and_end;}// only call ff_set_dimensions() for non H.264/VP6F/DXV codecs so as not to overwrite previously setup dimensionsif (!(avctx->coded_width && avctx->coded_height && avctx->width && avctx->height &&(avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_VP6F || avctx->codec_id == AV_CODEC_ID_DXV))) {if (avctx->coded_width && avctx->coded_height)ret = ff_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);else if (avctx->width && avctx->height)ret = ff_set_dimensions(avctx, avctx->width, avctx->height);if (ret < 0)goto free_and_end;}if ((avctx->coded_width || avctx->coded_height || avctx->width || avctx->height)&& (  av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx) < 0|| av_image_check_size(avctx->width,       avctx->height,       0, avctx) < 0)) {av_log(avctx, AV_LOG_WARNING, "Ignoring invalid width/height values\n");ff_set_dimensions(avctx, 0, 0);}if (avctx->width > 0 && avctx->height > 0) {if (av_image_check_sar(avctx->width, avctx->

这篇关于ffmpeg学习六:avcodec_open2函数源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1075388

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学