【FFmpeg】avformat_alloc_output_context2函数

【FFmpeg】avformat_alloc_output_context2函数

  • 1.avformat_alloc_output_context2
    • 1.1 初始化AVFormatContext(avformat_alloc_context)
    • 1.2 格式猜测(av_guess_format)
      • 1.2.1 遍历可用的fmt(av_muxer_iterate)
      • 1.2.2 name匹配检查(av_match_name)
      • 1.2.3 扩展匹配检查(av_match_ext)
  • 2.小结

参考:
FFmpeg源代码简单分析:avformat_alloc_output_context2()

示例工程:
【FFmpeg】调用ffmpeg库实现264软编
【FFmpeg】调用ffmpeg库实现264软解
【FFmpeg】调用ffmpeg库进行RTMP推流和拉流
【FFmpeg】调用ffmpeg库进行SDL2解码后渲染

流程分析:
【FFmpeg】编码链路上主要函数的简单分析
【FFmpeg】解码链路上主要函数的简单分析

结构体分析:
【FFmpeg】AVCodec结构体
【FFmpeg】AVCodecContext结构体
【FFmpeg】AVStream结构体
【FFmpeg】AVFormatContext结构体
【FFmpeg】AVIOContext结构体
【FFmpeg】AVPacket结构体

函数分析:
【FFmpeg】avformat_open_input函数
【FFmpeg】avformat_find_stream_info函数

avformat_alloc_output_context2内函数调用关系如下
在这里插入图片描述

1.avformat_alloc_output_context2

函数的主要功能是分配一个输出的context,利用输入的format和filename来确定output format,主要工作流程为:
(1)初始化AVFormatContext(avformat_alloc_context)
(2)如果没有指定输出format,需要根据输入信息来猜测一个format(av_guess_format)
(3)根据输出的format,来对AVFormatContext中的priv_data初始化

int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat *oformat,const char *format, const char *filename)
{AVFormatContext *s = avformat_alloc_context();int ret = 0;*avctx = NULL;if (!s)goto nomem;// 没有指定输出formatif (!oformat) {// 但是指定了格式名称,例如rtp,flv,udp等,则进行输出format的猜测if (format) {oformat = av_guess_format(format, NULL, NULL);if (!oformat) {av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not known.\n", format);ret = AVERROR(EINVAL);goto error;}} else {	// 也没有指定格式名称,使用filename进行输出format的猜测oformat = av_guess_format(NULL, filename, NULL);if (!oformat) {ret = AVERROR(EINVAL);av_log(s, AV_LOG_ERROR,"Unable to choose an output format for '%s'; ""use a standard extension for the filename or specify ""the format manually.\n", filename);goto error;}}}// 根据确定的输出format,对AVFormatContext中priv_data信息进行初始化s->oformat = oformat;if (ffofmt(s->oformat)->priv_data_size > 0) {s->priv_data = av_mallocz(ffofmt(s->oformat)->priv_data_size);if (!s->priv_data)goto nomem;if (s->oformat->priv_class) {*(const AVClass**)s->priv_data= s->oformat->priv_class;av_opt_set_defaults(s->priv_data);}} elses->priv_data = NULL;if (filename) {if (!(s->url = av_strdup(filename)))goto nomem;}*avctx = s;return 0;
nomem:av_log(s, AV_LOG_ERROR, "Out of memory\n");ret = AVERROR(ENOMEM);
error:avformat_free_context(s);return ret;
}

1.1 初始化AVFormatContext(avformat_alloc_context)

函数用于初始化AVFormatContext结构体

AVFormatContext *avformat_alloc_context(void)
{FFFormatContext *const si = av_mallocz(sizeof(*si));AVFormatContext *s;if (!si)return NULL;s = &si->pub;// 初始化函数指针s->av_class = &av_format_context_class;s->io_open  = io_open_default;s->io_close2= io_close2_default;av_opt_set_defaults(s);// 分配packet的空间si->pkt = av_packet_alloc();si->parse_pkt = av_packet_alloc();if (!si->pkt || !si->parse_pkt) {avformat_free_context(s);return NULL;}#if FF_API_LAVF_SHORTESTsi->shortest_end = AV_NOPTS_VALUE;
#endifreturn s;
}

1.2 格式猜测(av_guess_format)

该函数用于猜测一个format,类型为AVOutputFormat,

const AVOutputFormat *av_guess_format(const char *short_name, const char *filename,const char *mime_type)
{const AVOutputFormat *fmt = NULL;const AVOutputFormat *fmt_found = NULL;void *i = 0;int score_max, score;/* specific test for image sequences */// 用于图像序列的特定测试
#if CONFIG_IMAGE2_MUXERif (!short_name && filename &&av_filename_number_test(filename) &&ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) {return av_guess_format("image2", NULL, NULL);}
#endif/* Find the proper file type. */// 寻找合适的文件类型score_max = 0;// 遍历每个可用的fmtwhile ((fmt = av_muxer_iterate(&i))) {score = 0;// 如果当前封装格式匹配,则置信度增加100if (fmt->name && short_name && av_match_name(short_name, fmt->name))score += 100;// 如果fmt的mime类型与mime_type匹配,则置信度增加10if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))score += 10;if (filename && fmt->extensions &&av_match_ext(filename, fmt->extensions)) {// 如果扩展名匹配,则置信度增加5score += 5;}if (score > score_max) {score_max = score;fmt_found = fmt;}}return fmt_found;
}

其中,fmt中name、mime_type和extension的定义如下(以FLV格式为例)。在新版本FFmpeg中,FLV级别封装的格式不再是AVOutputFormat而是FFOutputFormat,但是FFOutputFormat之中的信息可以转换成AVOutputFormat,下面的.p就是AVOutputFormat的指针。对于FLV格式而言,name=“flv”,mime_type=“video/x-flv”,extensions=“flv”

const FFOutputFormat ff_flv_muxer = {.p.name         = "flv",.p.long_name    = NULL_IF_CONFIG_SMALL("FLV (Flash Video)"),.p.mime_type    = "video/x-flv",.p.extensions   = "flv",.priv_data_size = sizeof(FLVContext),.p.audio_codec  = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_ADPCM_SWF,.p.video_codec  = AV_CODEC_ID_FLV1,.init           = flv_init,.write_header   = flv_write_header,.write_packet   = flv_write_packet,.write_trailer  = flv_write_trailer,.deinit         = flv_deinit,.check_bitstream= flv_check_bitstream,.p.codec_tag    = (const AVCodecTag* const []) {flv_video_codec_ids, flv_audio_codec_ids, 0},.p.flags        = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |AVFMT_TS_NONSTRICT,.p.priv_class   = &flv_muxer_class,
};

1.2.1 遍历可用的fmt(av_muxer_iterate)

const AVOutputFormat *av_muxer_iterate(void **opaque)
{static const uintptr_t size = sizeof(muxer_list)/sizeof(muxer_list[0]) - 1;uintptr_t i = (uintptr_t)*opaque;const FFOutputFormat *f = NULL;uintptr_t tmp;// 从muxer的list中获取一个fmt,list当中有180个muxerif (i < size) {f = muxer_list[i];} else if (tmp = atomic_load_explicit(&outdev_list_intptr, memory_order_relaxed)) {const FFOutputFormat *const *outdev_list = (const FFOutputFormat *const *)tmp;f = outdev_list[i - size];}// 如果找到了fmt,i = i + 1if (f) {*opaque = (void*)(i + 1);return &f->p;}return NULL;
}

1.2.2 name匹配检查(av_match_name)

/*** Match instances of a name in a comma-separated list of names.* List entries are checked from the start to the end of the names list,* the first match ends further processing. If an entry prefixed with '-'* matches, then 0 is returned. The "ALL" list entry is considered to* match all names.** @param name  Name to look for.* @param names List of names.* @return 1 on match, 0 otherwise.*/
// 在逗号分隔的名称列表中匹配名称的实例(字符串匹配)
// 从名字列表的开始到结束检查列表条目,第一个匹配结束进一步处理。
//		如果匹配前缀为'-'的条目,则返回0。“ALL”列表项被认为匹配所有名称
int av_match_name(const char *name, const char *names)
{const char *p;size_t len, namelen;if (!name || !names)return 0;namelen = strlen(name);while (*names) {int negate = '-' == *names;p = strchr(names, ','); // 因为有多个,分隔的字号if (!p)p = names + strlen(names);names += negate;len = FFMAX(p - names, namelen);if (!av_strncasecmp(name, names, len) || !strncmp("ALL", names, FFMAX(3, p - names)))return !negate;names = p + (*p == ',');}return 0;
}

1.2.3 扩展匹配检查(av_match_ext)

函数会提取出扩展名,然后调用av_match_name进行扩展名的匹配

/*** @file* Format register and lookup*/int av_match_ext(const char *filename, const char *extensions)
{const char *ext;if (!filename)return 0;ext = strrchr(filename, '.');if (ext)return av_match_name(ext + 1, extensions);return 0;
}

2.小结

avformat_alloc_output_context2函数是FFmpeg使用过程中重要的函数,它创建了输出的AVFormatContext,能够用于数据的输出,需要注意的是,新版本的FFmpeg中对上层格式的封装不再使用AVOutputFormat而是使用FFOutputFormat,将AVOutputFormat封装到了FFOutputFormat之中

CSDN : https://blog.csdn.net/weixin_42877471
Github : https://github.com/DoFulangChen

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VTK----深入理解3D坐标系统和相机

对于有3D开发经验的工作者来说,3D坐标系统和相机是再熟悉不过的内容了,所以这篇文字并不是对它们基本概念的的介绍,而是结合自身对于3D坐标系统和相机中一些似懂非懂问题(如下面的列表)的解答以及详细说明VTK是如何实现3D坐标系统和相机的。 1. 下面这组用于绘制立方体的顶…

【C++PCL】点云处理点云密度计算优化

作者:迅卓科技 简介:本人从事过多项点云项目,并且负责的项目均已得到好评! 公众号:迅卓科技,一个可以让您可以学习点云的好地方 重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的…

jenkins下后台运行链接Jenkins服务脚本方法

为了编写一个用于在后台运行 Jenkins agent 的批处理脚本&#xff0c;你可以使用 start 命令来启动 Java 进程并将其设置为在后台运行。以下是一个示例批处理脚本 run_agent.bat&#xff1a; bat echo off setlocalREM Set the path to the Jenkins agent JAR file set AGENT…

TEMU全/半托管订单如何避免错发/漏发?用妙手ERP扫描发货功能!

这两年&#xff0c;因为全托管/半托管模式的火爆&#xff0c;跨境卖家纷纷加入全托管和半托管&#xff0c;许多卖家在加入后&#xff0c;店铺频频爆单。 以为是泼天富贵&#xff0c;没想到却因为发货问题亏麻了&#xff1a;发货效率低&#xff0c;导致超过平台发货时效&#x…

C#面:可以在C#静态类中使用“this”吗 ?

在C#中&#xff0c;静态类是一种特殊类型的类&#xff0c;它只能包含静态成员&#xff08;静态字段、静态方法、静态属性等&#xff09;&#xff0c;并且不能被实例化。由于静态类没有实例&#xff0c;因此在静态类中不能使用关键字“this”来引用当前对象。 关键字“this”用…

ActiViz实战:基于ActiViz 9.3读取分割后的心脏模型并实现面绘制

文章目录 一、效果预览二、实现代码三、源码地址 一、效果预览 20240627_150614 二、实现代码 public partial class Form1 : Form {private int _organCount;//组织数量private List<vtkPolyDataMapper> _multOrganMapper new List<vtkPolyDataMapper>();//多组…

第30课 绘制原理图——放置网络标签

什么是网络标签&#xff1f; 我们在很多电路图中都能看到&#xff0c;为了让图纸更加简洁&#xff0c;并不是每一根导线都要确确实实地画出来。可以在导线悬空的一端添加一个名称标签&#xff0c;接着在另一根导线的悬空一端添加上一个同名的名称标签&#xff0c;那么就可以让…

Qt 基于FFmpeg的视频播放器 - 播放、暂停以及拖动滑动条跳转

Qt 基于FFmpeg的视频转换器 - 播放、暂停以及拖动进度条跳转 引言一、设计思路二、核心源码以及相关参考链接 引言 本文基于FFmpeg&#xff0c;使用Qt制作了一个极简的视频播放器. 相比之前的版本&#xff0c;加入了播放、暂停、拖动滑动条跳转功能&#xff0c;如上所示 (左图)…

SpringSecutrity原理

一、基于RBAC实现的权限管理通常需要涉及以下几张表&#xff1a; 1. 用户表&#xff08;user&#xff09;&#xff1a;记录系统中的所有用户&#xff0c;包括用户ID、用户名、密码等信息。 2. 角色表&#xff08;role&#xff09;&#xff1a;记录系统中的所有角色&#xff0…

基于51单片机太阳能风能风光互补路灯控制器

一.硬件方案 本设计由STC89C52单片机电路太阳能电池板电路风机发电电路锂电池充电保护电路升压电路稳压电路光敏电阻电路4位高亮LED灯电路2档拨动开关电路电源电路设计而成。 二.设计功能 &#xff08;1&#xff09;采用风机和太阳能电池板给锂电池充电&#xff0c;具有充电…

系统架构设计师 - 数据库系统(2)

数据库系统 数据库系统规范化理论 ★ ★ ★ ★ ★函数依赖求候选键Armstrong公理范式判断第一范式 1NF第二范式 2NF第三范式 3NFBC 范式 BCNF 模式分解保持函数依赖分解无损分解 并发控制 ★事务的 ACID 特性并发存在的问题并发解决方案 - 封锁协议 数据库的安全性 ★安全性的分…

MySQL入门学习-索引.创建索引

索引是 MySQL 中用于加速查询的一种数据结构。它通过在表的列上创建索引来加快数据的检索速度。 一、索引的概念 索引类似于书的目录&#xff0c;可以快速定位到表中的数据。当在表中的列上创建索引后&#xff0c;MySQL 会根据索引列的值对数据进行排序&#xff0c;并建立一个…

【C++STL基础入门】wstring类基础使用

文章目录 前言C STL基础入门&#xff1a;wstring类的基础使用前言正文wstring是什么常用的构造函数常用的操作函数 总结 前言 在C的标准模板库(STL)中&#xff0c;wstring是一个重要的类&#xff0c;它是string的宽字符版本&#xff0c;用于存储和操作宽字符序列。本文将详细介…

十三、Maven(1)

&#x1f33b;&#x1f33b;目录 一、maven价绍二、maven的功能1、项目自动化构建2、管理jar、war包3、实现项目结构设计 三、maven安装1、maven的安装环境需要jdk2、Maven的安装路径中不能出现中文和空格3、压缩包解压即可4、配置环境变量 四、maven的仓库1. Maven仓库配置2. …

选型手册:Bosch Sensortec 博世 微机电系统(MEMS)传感器和方案

前言 博世传感器公司&#xff08;Bosch Sensortec&#xff09; 是全球领先的微机电系统&#xff08;MEMS&#xff09;传感器和解决方案供应商。公司成立于2005年&#xff0c;是德国罗伯特博世有限公司&#xff08;Robert Bosch GmbH&#xff09;旗下的全资子公司。博世传感器公…

SpringBoot【3】集成 Swagger

SpringBoot 集成 Swagger 前言pom.xml 配置文件application.yml 配置文件config 包Swagger2Config entity 包UserEntity service 包impl 包SwaggerServiceImpl SwaggerService controller 包SwaggerController SwaggerApplication验证 前言 创建项目步骤、及版本选择等&#x…

展开说说:Android列表之RecyclerView

RecyclerView 它是从Android5.0出现的全新列表组件&#xff0c;更加强大和灵活。用于显示列表形式 (list) 或者网格形式 (grid) 的数据&#xff0c;替代ListView和GridView成为Android主流的列表组件。可以说Android客户端只要有表格的地方就有RecyclerView。 RecyclerView 内…

【Android】Material TabLayout使用详解

基本用法 TabItem可以设置text&#xff0c;icon&#xff0c;layout三个属性 其它属性都通过TabLayout来统一设置 <com.google.android.material.tabs.TabLayout><com.google.android.material.tabs.TabItem/><com.google.android.material.tabs.TabItem/>…

VCS编译bug汇总

‘typedef’ is not expected to be used in this contex 注册前少了分号。 Scope resolution error resolution : 声明指针时 不能与类名同名&#xff0c;即 不能声明为adapter. cannot find member "type_id" 忘记注册了 拼接运算符使用 关键要加上1b&#xff0…

[MySQL]购物管理系统—简略版

本文内容需以MySQL支持 特别感谢baidu comate AI提供的少量虚拟数据 0.建库(建立数据库——utf8字符集&#xff0c;utf8_general_ci排序规则) 1.此项目ER图如下 2.DDLDML(共九表&#xff0c;27数据) SET FOREIGN_KEY_CHECKS 0;DROP TABLE IF EXISTS goods; CREATE TABLE g…