FFmpeg源码:avformat_new_stream函数分析
一、avformat_new_stream函数的声明
avformat_new_stream函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavformat/avformat.h中:
/*** Add a new stream to a media file.** When demuxing, it is called by the demuxer in read_header(). If the* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also* be called in read_packet().** When muxing, should be called by the user before avformat_write_header().** User is required to call avformat_free_context() to clean up the allocation* by avformat_new_stream().** @param s media file handle* @param c unused, does nothing** @return newly created stream or NULL on error.*/
AVStream *avformat_new_stream(AVFormatContext *s, const struct AVCodec *c);
该函数作用是:给一个媒体文件增加新流。即给形参s的streams数组增加新的元素,新元素会被初始化。
形参s:输出型参数,指向一个AVFormatContext对象。AVFormatContext结构体中有一个成员变量streams,为指针的指针。streams指向一个AVStream指针数组,该数组的每个元素都指向一个AVStream结构,每一个AVStream结构都存贮媒体文件/媒体流中一路流的信息,流的类型可以为视频流、音频流、字幕流等。
AVFormatContext结构体中的nb_streams成员存放该媒体文件/媒体流中流的个数,也是AVStream指针数组(形参s的streams数组)的元素个数。
执行avformat_new_stream函数后,形参s的streams数组会增加新的元素,也就是会给媒体文件增加新流:
typedef struct AVFormatContext {
//.../*** Number of elements in AVFormatContext.streams.** Set by avformat_new_stream(), must not be modified by any other code.*/unsigned int nb_streams;/*** A list of all streams in the file. New streams are created with* avformat_new_stream().** - demuxing: streams are created by libavformat in avformat_open_input().* If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams may also* appear in av_read_frame().* - muxing: streams are created by the user before avformat_write_header().** Freed by libavformat in avformat_free_context().*/AVStream **streams;
//...
} AVFormatContext;
形参c:该参数没有被用到,可忽略。
返回值:成功返回新流对应的AVStream结构,失败返回NULL。
二、avformat_new_stream函数的定义
avformat_new_stream函数定义在源文件libavformat/options.c中:
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{FFFormatContext *const si = ffformatcontext(s);FFStream *sti;AVStream *st;AVStream **streams;if (s->nb_streams >= s->max_streams) {av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter"" (%d), see the documentation if you wish to increase it\n",s->max_streams);return NULL;}streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));if (!streams)return NULL;s->streams = streams;sti = av_mallocz(sizeof(*sti));if (!sti)return NULL;st = &sti->pub;st->av_class = &stream_class;st->codecpar = avcodec_parameters_alloc();if (!st->codecpar)goto fail;sti->fmtctx = s;if (s->iformat) {sti->avctx = avcodec_alloc_context3(NULL);if (!sti->avctx)goto fail;sti->info = av_mallocz(sizeof(*sti->info));if (!sti->info)goto fail;#if FF_API_R_FRAME_RATEsti->info->last_dts = AV_NOPTS_VALUE;
#endifsti->info->fps_first_dts = AV_NOPTS_VALUE;sti->info->fps_last_dts = AV_NOPTS_VALUE;/* default pts setting is MPEG-like */avpriv_set_pts_info(st, 33, 1, 90000);/* we set the current DTS to 0 so that formats without any timestamps* but durations get some timestamps, formats with some unknown* timestamps have their first few packets buffered and the* timestamps corrected before they are returned to the user */sti->cur_dts = RELATIVE_TS_BASE;} else {sti->cur_dts = AV_NOPTS_VALUE;}st->index = s->nb_streams;st->start_time = AV_NOPTS_VALUE;st->duration = AV_NOPTS_VALUE;sti->first_dts = AV_NOPTS_VALUE;sti->probe_packets = s->max_probe_packets;sti->pts_wrap_reference = AV_NOPTS_VALUE;sti->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;sti->last_IP_pts = AV_NOPTS_VALUE;sti->last_dts_for_order_check = AV_NOPTS_VALUE;for (int i = 0; i < MAX_REORDER_DELAY + 1; i++)sti->pts_buffer[i] = AV_NOPTS_VALUE;st->sample_aspect_ratio = (AVRational) { 0, 1 };sti->transferred_mux_tb = (AVRational) { 0, 1 };;#if FF_API_AVSTREAM_SIDE_DATAsti->inject_global_side_data = si->inject_global_side_data;
#endifsti->need_context_update = 1;s->streams[s->nb_streams++] = st;return st;
fail:ff_free_stream(&st);return NULL;
}
三、avformat_new_stream函数的内部实现分析
avformat_new_stream函数内部,首先会判断该媒体文件/媒体流中已经存在的流的个数是否超过“限制的最大数量”,“限制的最大数量”(s->max_streams)默认是1000,该值可以设置。如果超过,打印日志:“Number of streams exceeds max_streams parameter”,avformat_new_stream函数返回NULL:
if (s->nb_streams >= s->max_streams) {av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter"" (%d), see the documentation if you wish to increase it\n",s->max_streams);return NULL;}
通过下面语句,给新流对应的AVStream指针分配内存,给形参s的streams数组增加新的元素(即增加新流对应的AVStream指针)。注意:这一步只会给AVStream的指针分配内存,不会给AVStream本身分配内存。关于av_realloc_array函数的用法可以参考:《FFmpeg源码:av_malloc_array、av_realloc_array函数分析》:
streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));if (!streams)return NULL;s->streams = streams;
给新流对应的FFStream和AVStream结构本身分配内存:
sti = av_mallocz(sizeof(*sti));if (!sti)return NULL;st = &sti->pub;
//...s->streams[s->nb_streams++] = st;
给新流对应的AVStream结构的其它成员分配内存和初始化。语句:avpriv_set_pts_info(st, 33, 1, 90000)是给AVStream的time_base设置一个默认值,关于avpriv_set_pts_info函数的用法可以参考:《FFmpeg源码:avpriv_set_pts_info函数分析》:
st->av_class = &stream_class;st->codecpar = avcodec_parameters_alloc();if (!st->codecpar)goto fail;sti->fmtctx = s;if (s->iformat) {sti->avctx = avcodec_alloc_context3(NULL);if (!sti->avctx)goto fail;sti->info = av_mallocz(sizeof(*sti->info));if (!sti->info)goto fail;#if FF_API_R_FRAME_RATEsti->info->last_dts = AV_NOPTS_VALUE;
#endifsti->info->fps_first_dts = AV_NOPTS_VALUE;sti->info->fps_last_dts = AV_NOPTS_VALUE;/* default pts setting is MPEG-like */avpriv_set_pts_info(st, 33, 1, 90000);/* we set the current DTS to 0 so that formats without any timestamps* but durations get some timestamps, formats with some unknown* timestamps have their first few packets buffered and the* timestamps corrected before they are returned to the user */sti->cur_dts = RELATIVE_TS_BASE;} else {sti->cur_dts = AV_NOPTS_VALUE;}st->index = s->nb_streams;st->start_time = AV_NOPTS_VALUE;st->duration = AV_NOPTS_VALUE;sti->first_dts = AV_NOPTS_VALUE;sti->probe_packets = s->max_probe_packets;sti->pts_wrap_reference = AV_NOPTS_VALUE;sti->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;sti->last_IP_pts = AV_NOPTS_VALUE;sti->last_dts_for_order_check = AV_NOPTS_VALUE;for (int i = 0; i < MAX_REORDER_DELAY + 1; i++)sti->pts_buffer[i] = AV_NOPTS_VALUE;st->sample_aspect_ratio = (AVRational) { 0, 1 };sti->transferred_mux_tb = (AVRational) { 0, 1 };;#if FF_API_AVSTREAM_SIDE_DATAsti->inject_global_side_data = si->inject_global_side_data;
#endifsti->need_context_update = 1;
相关文章:

FFmpeg源码:avformat_new_stream函数分析
一、avformat_new_stream函数的声明 avformat_new_stream函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavformat/avformat.h中: /*** Add a new stream to a media file.** When demuxing, it is called by the dem…...

【java】深入解析Lambda表达式
Lambda表达式是Java 8引入的一项重要特性,它提供了一种简洁的方式来实现函数式编程。Lambda表达式的使用广泛而且灵活,可以简化代码并提高可读性。本篇文章将深入解析Lambda表达式,包括使用场景、基础学习、代码案例、实现方法和注意事项等方…...

Chromium html<img>对应c++接口定义
<img src"tulip.jpg" alt"上海鲜花港 - 郁金香" /> 1、html_tag_names.json5中接口定义: (third_party\blink\renderer\core\html\html_tag_names.json5) {name: "img",constructorNeedsCreateElementF…...

卸载Python
1、查看安装框架位置并删除 Sudo rm -rf /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8 2、查看应用并删除 在 /Applications/Python 3.x 看是否存在,如果存在并删除。 3、删除软连接 ls -l /usr/bin/py* 或 ls -…...

算法剖析:二分查找
文章目录 前言二分查找模板朴素模板左右查找模板 一、二分查找二、 在排序数组中查找元素的第一个和最后一个位置三、搜索插入位置四、x 的平方根五、山脉数组的峰顶索引六、寻找峰值七、寻找旋转排序数组中的最小值八、 点名总结 前言 二分查找是一种高效的查找算法ÿ…...

Invoke 和 InvokeRequired以及他们两个的区别
在.NET中,Invoke和InvokeRequired是Windows Forms编程中用于确保线程安全的关键方法和属性。它们通常用在多线程环境中,以确保UI控件的更新操作在创建控件的线程上执行,避免因跨线程操作导致的异常。 InvokeRequired 属性 InvokeRequired属…...

SpringBoot概览及核心原理
Spring Boot 是由Pivotal 团队设计的全新框架,其目的是用来简化 Spring 应用开发过程。该框架使用了特定的方式来进行配置,从而使得开发人员不再需要定义一系列样板化的配置文件,而专注于核心业务开发,项目涉及的一些基础设施则交…...

根据basic auth请求https获取token
根据basic auth请求https获取token 对接第三方接口,给了接口文档,但是没有示例代码,postman一直可请求成功,java就是不行。百思不得其解,最后请求公司大神,得到一套秘籍。 第一步 第二步 Authorization&am…...

【基础版】React缓存路由
前言 项目背景 Reactumireact-router5 需求 用户在某一页面操作后点击跳转到其详情页,返回到列表页还是之前操作过的页面,即把页面缓存下来(基础版先处理路由缓存,tab页展示先不处理) 实践 在布局页面对页面进行…...

Java基础15-Java高级
十五、Java高级 单元测试、反射、注解、动态代理。 1、单元测试 定义:就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。 1.1 Junit单元测试框架 可以用来对方 法进行测试,它是第三方公司开源出来的(很多开发工具已经集成了Junit框架&…...

selenium工具的几种截屏方法介绍(9)
在使用selenium做自动化的时候,可以对于某些场景截图保存当时的执行情况,方便后续定位问题或者作为一些证据保留现场。 获取元素后将元素截屏 我们获取元素后,使用函数screenshot将元素截屏,参数filename传入完整的png文件名路径…...

【设计模式】深入理解Python中的过滤器模式(Filter Pattern)
深入理解Python中的过滤器模式(Filter Pattern) 在软件设计中,面对复杂的数据处理需求时,我们常常需要从一组数据中筛选出符合特定条件的子集。**过滤器模式(Filter Pattern)**是一种能够简化这种操作的设…...

vue的动态组件 keep-alive
1. 什么是动态组件 动态组件指的是 动态切换组件的显示与隐藏 2. 如何实现动态组件渲染 vue提供了一个内置的<component>组件,专门用来实现动态组件的渲染。 作用:组件的占位符is的值表示要渲染的组件 示例代码如下: Left.vue的代…...

现代框架开发官网
一、项目背景 维护过 灵犀官网、企业邮官网、免费邮官网 均使用 jquery webpack多页面打包的方式 开发起来较为繁琐 新的官网项目,想使用现代前端框架,但SPA应用不利于SEO 使用SSR方案又依赖运维,增加维护和沟通成本 二、SSG vs 预渲染 S…...

一篇文章快速认识YOLO11 | 关键改进点 | 安装使用 | 模型训练和推理
前言 本文分享YOLO11的关键改进点、性能对比、安装使用、模型训练和推理等内容。 YOLO11 是 Ultralytics 最新的实时目标检测器,凭借更高的精度、速度和效率重新定义了可能性。 除了传统的目标检测外,YOLO11 还支持目标跟踪、实例分割、姿态估计、OBB…...

AtCoder Beginner Contest 375(A,B,C,D,E,F)(大模拟,前缀和,dp,离线处理,Floyd)
比赛链接 AtCoder Beginner Contest 375 A题 代码 #pragma GCC optimize("O2") #pragma GCC optimize("O3") #include <bits/stdc.h> using namespace std; #define int long long const int N 2e5 5, M 1e6 5; const int inf 0x3f3f3f3f3f…...

认识maven
什么是 Maven? Maven 是一个开源的项目管理工具,主要用于 Java 项目的构建、依赖管理和项目生命周期管理。它提供了一种标准的项目结构和管理流程,使得开发人员能够更轻松地管理项目的构建过程,提高代码的可重用性和可维护性。 …...

OSINT技术情报精选·2024年10月第2周
OSINT技术情报精选2024年10月第2周 2024.10.16版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、亿欧智库:《2024中国高精定位服务产业白皮书》 报告的主要内容如下: 产业背景:在“北斗”发展态势的…...

中企通信赋能中信戴卡入选工信部颁发的2023年工业互联网试点示范名单
2024年10月17日,北京-随着工业互联网的迅猛发展,网络安全已成为国家关注的重点议题之一。日前,工业和信息化部(工信部)公布了2023年工业互联网试点示范名单,中企网络通信技术有限公司(简称“中企…...

【C语言】函数的声明与定义
函数的声明 用户自定义函数需要在main函数之前进行声明,用分号结尾。 函数的定义 用户自定义函数在main函数之后进行定义,需要写出具体形参的变量名。注意函数的返回值和返回值类型要一一对应。 函数的调用 调用时,直接使用函数名进行调用&am…...

游戏如何应对薅羊毛问题
在大众眼里,“薅羊毛”是指在电商领域,“羊毛党”利用平台、商家的促销规则,低价获取商品和服务的行为。如前不久“小天鹅被一夜薅走7000万”的案例震惊全网。 然而实际上,“薅羊毛”现象不仅存在于电商场景,在游戏中…...

Chromium html<script>对应c++接口定义
<script>:脚本元素 <script> 元素用于嵌入可执行代码或数据,这通常用作嵌入或者引用 JavaScript 代码。<script> 元素也能在其他语言中使用,比如 WebGL 的 GLSL 着色器语言和 JSON。 更多参考:<script>&…...

ollama + fastgpt+m3e本地部署
ollama fastgptm3e本地部署 开启WSL更新wsl安装ubuntu docker下载修改docker镜像源开启WSL integration 安装fastgpt先创建一个文件夹来放置一些配置文件用命令下载fastgpt配置文件用命令下载docker的部署文件 启动容器M3E下载ollama下载oneapi配置登录oneapi配置ollama渠道配…...

Linux执行source /etc/profile命令报错:权限不够问(已解决)
1.问题 明明以root账号登录Linux系统,在终端执行命令source /etc/profile时 显示权限不够 如下图: 2.问题原因 可能在编辑 /etc/profile 这个文件时不小心把开头的 井号 ‘#’ 给删除了 如图: 这里一定要有# 3.解决办法 进入/etc/pro…...

Windows 11开发全解析
Windows 11开发全解析 一、搭建开发环境 在开始Windows 11开发之前,搭建一个高效的开发环境是至关重要的。Windows 11提供了多种工具和框架,可以帮助开发者快速搭建起一个强大的开发环境。 1. Visual Studio 2024 Visual Studio 2024是微软为Windows…...
如何进行数学家式的学习思考?
如何进行数学家式的学习思考? 学生阶段的数学学习是非常重要的,对这一点很少有人质疑。一提起数学学习,一些学生、家长甚至一些教师认为,学生的数学学习往往侧重于掌握基本概念、公式和解题技巧,通过做题来巩固知识和提…...

自定义类型--结构体
目录 1. 结构体类型的声明 1.1结构的声明 1.2 结构体变量的创建和初始化 1.3不完全结构体 1.4结构的⾃引⽤ 2 结构体的内存对齐 2.1offsetof 2.2 对⻬规则 2.3 为什么存在内存对⻬? 2.4修改默认对⻬数 3. 结构体传参 4 结构体实现位段 4.1什么是位段 4.2 位段的内…...

笔试练习day7
目录 OR59 字符串中找出连续最长的数字串题目解析解法(双指针遍历)代码 NC109 岛屿数量题目解析解法代码(dfs)dfs的实现 拼三角题目解析解法(枚举)代码 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 🐒🐒🐒 个人主页 &…...

python 爬虫 入门 一、基础工具
目录 一,网页开发者工具的使用 二、通过python发送请求 (一)、get (二)、带参数的get (三)、post 后续:数据解析 一,网页开发者工具的使用 我们可以用 requests 库…...

金融衍生品中的风险对冲策略分析
金融衍生品是现代金融市场中不可或缺的一部分,它们通过标的资产的价格波动为投资者提供了多样的风险管理工具。随着市场的不确定性和复杂性增加,风险对冲成为企业和个人投资者的首要任务。本文将深入探讨金融衍生品中的常见风险对冲策略,分析…...