AVFormatContext 再分析

说明 :将 avfromatContext 的变量依次打印分析,根据ffmpeg 给的说明,猜测,结合网上的文章字节写测试代码分析。

从常用到不常用依次分析

1. unsigned int nb_streams;

代表 avfromatContext 中 AVStream **streams 的个数

    /**
     * Number of elements in AVFormatContext.streams.
     *
     * Set by avformat_new_stream(), must not be modified by any other code.
     */
    unsigned int nb_streams;

//打印在解复用时候,avformatContext的主要参数
void PrintfDeMuxingAVFormatContextMainParamter(AVFormatContext* avformatContext) {if (avformatContext == NULL) {cout << "func PrintfDeMuxingAVFormatContextMainParamter error because AVFormatContext == nullptr  " << endl;return;}cout << "avformat中有的avstream的个数为:avformatContext->nb_streams = " << avformatContext->nb_streams << endl;}

2. int64_t bit_rate;

在 AVFormatContext 结构体中,‌bit_rate 字段表示媒体文件的全局平均比特率‌(单位为 bps,即 bits per second)

    /**
     * Total stream bitrate in bit/s, 0 if not
     * available. Never set it directly if the file_size and the
     * duration are known as FFmpeg can compute it automatically.
     */
    int64_t bit_rate;

2.1 含义再说明1

从说明中可以看出来,代表的是所有 stream 的 平均比特率。啥意思呢?比如这是一个mp4文件,既有视频也有音频,我们假设有一个视频两个音频(粤语和普通话),假设视频是300kbps,普通话音频是128kbps,粤语音频是100kbps。那么 AVFormatContext 中的 bit_rate就应该等于 300 +128+100 = 628kbps,注意单位是kbps。

// 遍历所有流,计算总比特率
int64_t total_bit_rate = 0;
for (int i = 0; i < avformat_ctx->nb_streams; i++) {AVStream *stream = avformat_ctx->streams[i];total_bit_rate += stream->codecpar->bit_rate;
}

2.2 含义再说明2,在TS下无效

0 if not available

这个意思是说,这个值有可能是0,代表不可使用。

部分封装格式(如 TS 流)可能不记录全局比特率,此时 bit_rate 字段无效

2.3 含义再说明3,当文件大小和duration都知道的时候,user不要设置,ffmepg会自动计算

Never set it directly if the file_size and the duration are known as FFmpeg can compute it automatically.

2.5 动态码率场景


VBR 编码的文件中,该字段仅代表平均值,无法反映瞬时码率波动

CBR 是 (恒定比特率)

VBR(可变比特率),

mp4文件只能是 VBR。

也就是说:如果我们解析的是mp4文件,那么这个值是平均值。无法反映瞬时码率波动

2.6 典型应用场景

  • 带宽估算‌:
    结合容器和流的比特率,判断网络传输是否满足实时播放需求56。
  • 文件分析工具‌:
    统计媒体文件的码率分布,辅助编码参数优化6。

3. int64_t duration

只能用于解复用,

是 ‌AVFormatContext 结构体‌的关键成员,用于表示 ‌媒体文件的总时长‌。其数据类型为 int64_t,单位为 ‌AV_TIME_BASE‌(即微秒的倒数,通常为 1,000,000)。

该字段在 ‌成功解析媒体文件流信息后‌(调用 avformat_find_stream_info())才会被正确赋值

    /**
     * Duration of the stream, in AV_TIME_BASE fractional
     * seconds. Only set this value if you know none of the individual stream
     * durations and also do not set any of them. This is deduced from the
     * AVStream values if not set.
     *
     * Demuxing only, set by libavformat.
     */
    int64_t duration;

主要使用场景,通过 duration 计算文件时长。

换算为秒‌:

double duration_sec = (double)avformatContext->duration / AV_TIME_BASE;
 

转换为时分秒格式‌:

int64_t total_us = avformatContext->duration + 5000;  // 四舍五入修正
int hours = total_us / (3600 * AV_TIME_BASE);
int mins = (total_us % (3600 * AV_TIME_BASE)) / (60 * AV_TIME_BASE);
int secs = (total_us % (60 * AV_TIME_BASE)) / AV_TIME_BASE;

常见问题与解决方案

问题原因解决方案
返回负值或极大值未正确解析流信息或文件不完整调用 avformat_find_stream_info() 前设置 max_analyze_duration 参数
单位换算错误未使用 AV_TIME_BASE 进行转换确保除以 AV_TIME_BASE(或使用 av_rescale_q() 函数)
时间精度丢失直接截断未四舍五入添加 5000 微秒偏移(如 +5000)后再计算

AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, filename, NULL, NULL);  // 打开文件
fmt_ctx->max_analyze_duration = 5 * AV_TIME_BASE;     // 限制解析时长避免卡顿
avformat_find_stream_info(fmt_ctx, NULL);              // 解析流信息if (fmt_ctx->duration != AV_NOPTS_VALUE) {int64_t duration = fmt_ctx->duration + 5000;      // 修正精度int hours = duration / (3600 * AV_TIME_BASE);int mins = (duration % (3600 * AV_TIME_BASE)) / (60 * AV_TIME_BASE);int secs = (duration % (60 * AV_TIME_BASE)) / AV_TIME_BASE;printf("Duration: %02d:%02d:%02d\n", hours, mins, secs);
} else {printf("Duration unavailable\n");
}
avformat_close_input(&fmt_ctx);                       // 释放资源

适用场景

  • 媒体信息分析工具‌:如 ffprobe 使用该字段输出文件时长。
  • 播放器开发‌:用于显示进度条总时长。
  • 流媒体处理‌:结合 AVStream 中各流时长进行同步控制。

注意‌:在网络流或实时流中,duration 可能无法获取(值为 AV_NOPTS_VALUE),需动态计算

cout << "avformat中duration为:avformatContext->duration = " << avformatContext->duration << endl;double duration_sec = (double)avformatContext->duration / AV_TIME_BASE;
cout << "avformat中秒数为:duration_sec = " << duration_sec << endl;if (avformatContext->duration != AV_NOPTS_VALUE) {int64_t duration = avformatContext->duration + 5000;      // 修正精度int hours = duration / (3600 * AV_TIME_BASE);int mins = (duration % (3600 * AV_TIME_BASE)) / (60 * AV_TIME_BASE);int secs = (duration % (60 * AV_TIME_BASE)) / AV_TIME_BASE;printf("Duration: %02d:%02d:%02d\n", hours, mins, secs);
}else {printf("Duration unavailable\n");
}avformat中duration为:avformatContext->duration = 60024000
avformat中秒数为:duration_sec = 60.024
Duration: 00:01:00

4. char *url;

    /**
     * input or output URL. Unlike the old filename field, this field has no
     * length restriction.
     *
     * - demuxing: set by avformat_open_input(), initialized to an empty
     *             string if url parameter was NULL in avformat_open_input().
     * - muxing: may be set by the caller before calling avformat_write_header()
     *           (or avformat_init_output() if that is called first) to a string
     *           which is freeable by av_free(). Set to an empty string if it
     *           was NULL in avformat_init_output().
     *
     * Freed by libavformat in avformat_free_context().
     */
    char *url;

和之前的filename不同,url是没有长度限制的。

在解码时,通过 avformat_open_input 方法 会将url 记录到 AVFormatContext ,可能会nullptr。

在编码时,需要在 调用 avformat_write_header 方法之前设置。

   char * url =  avformatContext->url;cout << "avformat中duration为 url = " << url << endl;结果为:avformat中duration为 url = ./120/400_300_25.mp4

5. int64_t start_time;

    /**
     * Position of the first frame of the component, in
     * AV_TIME_BASE fractional seconds. NEVER set this value directly:
     * It is deduced from the AVStream values.
     *
     * Demuxing only, set by libavformat.
     */
    int64_t start_time;

组件第一帧的位置,以AV_TIME_BASE  为单位。 
切勿直接设置此值:它是从AVStream值推断出来的。

这玩意有啥用呢?表示该avformatContext 第一帧的开始时间,那么应该都是0。

可能的点:todo

如果我们从文件的中间位置读取的,那么这个值就不是0?

在网络流的时候用?

   int64_t starttime = avformatContext->start_time;cout << "avformat中duration为 starttime = " << starttime << endl;avformat中duration为 starttime = 0

6. 接下来都是非重点 AVCodec* audio_codec;

    /**
     * Forced audio codec.
     * This allows forcing a specific decoder, even when there are multiple with the same codec_id.
     * Demuxing: Set by user
     */
    AVCodec *audio_codec;

这里从翻译来看,意思是该变量是为了 音频的编解码。

允许在解码的时候,允许强制使用特定的解码器,即使存在多个具有相同codec_id的解码器

/**
 * Forced audio codec.
 * This allows forcing a specific decoder, even when there are multiple with the same codec_id.
 * Demuxing: Set by user
 * AVCodec* audio_codec;
 * 在 音频 编解码器 的时候使用,
 * 在解复用的时候,允许强制使用特定的解码器,即使存在多个具有相同codec_id的解码器
 * 我们使用test02测试
 */

avformatContext->audio_codec;cout << "avformatContext->audio_codec = " << avformatContext->audio_codec << endl;


 * 在 音频 编解码器 的时候使用,
 * 在解复用的时候,允许强制使用特定的解码器,即使存在多个具有相同codec_id的解码器

   AVCodec* audioavcodec = avformatContext->audio_codec;if (audioavcodec == nullptr) {cout << "audioavcodec == nullptr" << endl;}else {cout << "audioavcodec != nullptr  audioavcodec->id = " << audioavcodec->id << endl;}log 为:audioavcodec == nullptr

last

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

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

相关文章

计算机网络-运输层(1)

计算机网络-运输层(1) 文章目录 计算机网络-运输层(1)5.1 运输层概述5.2 运输层端口号、复用与分用端口号基本概念端口号特性端口号分类重要说明 5.3 UDP与TCP协议对比关键区别说明 5.1 运输层概述 计算机网络体系结构中的物理层、数据链路层以及网络层共同解决了主机通过异构…

2025 FIC wp

这次比赛计算机和手机大部分题目都比较常规 第一和第四部分有点让人摸不着头脑 比赛的时候第一部分有四个题没出 第四部分基本都没怎么出 现在复盘一下 把我当时做题的心得和获取的新知识记录一下 互联网取证的部分就先学习一下别的师傅 检材 链接&#xff1a;https://pan.bai…

【大数据技术-联邦集群RBF】DFSRouter日志一直打印修改Membership为EXPIRED状态的日志分析

生产环境遇到下面报错 2025-04-23 17:44:15,780 INFO store.CachedRecordStore (CachedRecordStore.java:overrideExpiredRecords(192)) - Override State Store record MembershipState: router1:8888->hh-fed-sub25:nn2:nn2:8020-EXPIRED 2025-04-23 17:44:15,781 INFO …

【HarmonyOS 5】鸿蒙检测系统完整性

【HarmonyOS 5】鸿蒙检测系统完整性 一、前言 从现实安全威胁来看&#xff0c;设备系统完整性风险已影响至移动应用的各个场景。不少用户因使用越狱设备&#xff08;Jailbreak&#xff09;或非真实设备&#xff08;Emulator&#xff09;&#xff0c;导致应用安全防护机制失效…

学习spark-streaming收获

1.流处理的核心概念 •实时 vs微批处理&#xff1a;理解了 Spark Streaming 的微批处理&#xff08;Micro-Batch&#xff09;模型&#xff0c;将流数据切分为小批次&#xff08;如1秒间隔&#xff09;进行处理&#xff0c;与真正的流处理&#xff08;如Flink&#xff09;的区…

Redis一些小记录

Redis一些小记录 SpringData Redis&#xff1a;RedisTemplate配置与数据操作 操作String类型数据 String是Redis中最基本的数据类型&#xff0c;可以存储字符串、整数或浮点数。RedisTemplate提供了ValueOperations接口来操作String类型的数据&#xff0c;支持设置值、获取值、…

5G融合消息PaaS项目深度解析 - Java架构师面试实战

5G融合消息PaaS项目深度解析 - Java架构师面试实战 场景&#xff1a;互联网大厂Java求职者面试&#xff0c;面试官针对5G融合消息PaaS项目进行提问。 第一轮提问 面试官&#xff1a;马架构&#xff0c;请简要介绍5G融合消息PaaS平台的核心功能和应用场景。 马架构&#xff…

【C语言极简自学笔记】C 语言数组详解:一维数组与二维数组

在 C 语言中&#xff0c;数组是一种非常重要的数据结构&#xff0c;它可以将多个相同类型的元素组织在一起&#xff0c;以便于我们进行批量处理和操作。本文将详细介绍 C 语言中的一维数组和二维数组&#xff0c;包括它们的定义、初始化、元素访问以及内存存储等方面的内容。 …

04.通过OpenAPI-Swagger规范让Dify玩转Agent

dify安装 cd dify cd docker cp .env.example .env docker compose up -d准备自定义工具 我自建的PowerDNS&#xff0c;它的swagger如下&#xff1a; https://github.com/PowerDNS/pdns/blob/master/docs/http-api/swagger/authoritative-api-swagger.yaml 但需要加上&#x…

汽车产业链主表及类别表设计

&#xff08;提前设计&#xff0c;备用&#xff09; 一、汽车产业链类别表&#xff08;industry_chain_category&#xff09; 设计要点 1、核心字段&#xff1a;定义产业链分类&#xff08;如零部件、整车制造、销售服务等&#xff09; 2、主键约束&#xff1a;自增ID作为唯一标…

‌RISC-V架构的低功耗MCU多电压域优化设计

RISC-V核低功耗MCU的多电压域设计是一种优化电源管理以降低功耗的技术方案。该设计通过电源域划分、电压转换和时序管理等手段&#xff0c;有效降低了系统功耗并提升能效&#xff0c;适用于物联网和嵌入式系统等场景。 多电压域设计的基本原理是将芯片划分为多个独立供电区域&…

基于STM32、HAL库的AD7616BSTZ模数转换器ADC驱动程序设计

一、简介: AD7616BSTZ是Analog Devices公司生产的一款16位、双通道、同步采样SAR型ADC芯片,主要特点包括: 16位分辨率 双通道同步采样 最高采样率:1MSPS/通道 输入范围:10V, 5V或2.5V(软件可编程) 串行(SPI)和并行接口选项 低功耗:典型值100mW 工作温度范围:-40C至+8…

CUDA Stream 回调函数示例代码

文章目录 CUDA Stream 回调函数示例代码基本概念示例代码代码解释回调函数的特点更复杂的示例&#xff1a;多个回调注意事项 CUDA Stream 回调函数中使用 MPI 或 NCCL示例程序注意事项 CUDA Stream 回调函数示例代码 CUDA 中的流回调函数(stream callback)是一种在 CUDA 流中插…

全栈黑暗物质:可观测性之外的非确定性调试

一、量子计算的测不准Bug 1. 经典 vs. 量子系统的错误模式 量子程序崩溃的观测影响&#xff1a; 调试方法崩溃复现率观测干扰度日志打印12%35%断点调试5%78%无侵入跟踪27%9%量子态层析成像63%2% 二、量子调试工具箱 1. 非破坏性观测协议 # 量子程序的无干扰快照 from qiski…

ASP.NET8.0入门与实战

1、项目初始化 创建一个ASP.NET Core Web API的项目&#xff0c;取消Https和身份验证。 API项目实际上是一个控制台程序&#xff0c;这点可以在项目的属性的输出类型中看到。 launchSettings.json&#xff0c;在这里可以配置运行项目的名称&#xff0c;端口号&#xff0c;路…

Synopsys 逻辑综合的整体架构概览

目录 一、DC Shell 逻辑综合的整体架构概览 ⛓️ 逻辑综合的主要阶段&#xff08;Pipeline&#xff09; 二、核心架构模块详解 1. Internal Database&#xff08;设计对象数据库&#xff09; 2. Scheduler&#xff08;调度器&#xff09; 3. Rewriting Engine&#xff08…

低压电工常见知识点

一.工厂用电 1.工厂一般有电源380V和220V。 三相:黄绿红 蓝 双色 助记符:王力宏 分别对应第一相(R),第二相(S)&#xff0c;第三相(T)&#xff0c;零线(N),地线(PE) 单相:红 黑 对应火线(L) 零线(N) 左零右火 二.人体安全电压是36V 三.变压器的讲解 变压器的符号…

【沉浸式求职学习day27】

沉浸式求职学习 家人们谁懂啊&#xff01;明天下午又实习笔试了&#xff0c;所以今天大部分时间还是在搞一些行测之类的东西&#xff0c;所以今天没什么分享给大家的&#xff0c;明晚会简单的和大家分享一下关于数据库的一些东西&#xff0c;以及和大家聊聊我笔试的感觉哈哈哈哈…

进入救援模式(物理服务器)

目录 **📌 准备工作****🚀 进入救援模式(物理服务器)****方法 1:直接修改启动参数****适用情况****操作步骤****方法 2:通过GRUB引导菜单进入(系统未完全崩溃时)****适用情况****操作步骤****两者的核心区别****如何选择?****注意事项****总结**当物理服务器无法正常…

基于Pytest接口自动化的requests模块项目实战以及接口关联方法详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、基于pytest单元测试框架的规则 1.1 模块名&#xff08;即文件名&#xff09;必须以test_开头或者_test结尾 1.2 类名必须以Test开头且不能有init方法 1.3 用…