ffmpeg关于读取av_read_frame音频数据时,AVPacket字段的说明

2024-04-27 16:48

本文主要是介绍ffmpeg关于读取av_read_frame音频数据时,AVPacket字段的说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用ffmpeg读取系统声音时,如下所示
av_read_frame(pFormatCtx_Audio, &packet) ;
packet中pts,dts,duration都是基于pFormatCtx_Audio里面对应AVStream的time_base。

下面我们看下AVStream里面的time_base是1000 0000,即1千万一秒。
在这里插入图片描述
然后我们读取一个packet,其值如下所示:
在这里插入图片描述
pts和dts都是1303426380000,这个值太大,我们先不管,我们看下duration字段,值100000,1千万的百分之一,所以读取到的这个音频包是10ms的长度。

我们再通过下面的语句对packet进行解码,解码器的time_base是48000(根据解码器的采样率进行设置)
ret = avcodec_send_packet(pReadCodecContext, &packet);
ret = avcodec_receive_frame(pReadCodecContext, pFrame);
我们观察下pFrame的值,如下:
在这里插入图片描述
可以看到转换成AVFrame结构后的样例数nb_samples为480,而解码器的time_base是48000,故AVFrame中的480个样例数刚好代表着10ms,与AVPacket中的duration能够对应上。
同时,我们可以看到,pts和dts相对于AVPacket没有发现变化,都是以AVStream的time_base为时间基。

我们接着取第二包数据,AVPacket的数据如下所示:
在这里插入图片描述
同样根据duration为100000,判断其为10ms。pts和dts的值为1303426480000,而第一包AVPacket的pts为1303426380000,两者相减,值刚好为100000,代表着10ms,即两个包间距为10ms。
接着用下面语句进行解码。
ret = avcodec_send_packet(pReadCodecContext, &packet);
ret = avcodec_receive_frame(pReadCodecContext, pFrame);
我们观察下pFrame的值,如下:
在这里插入图片描述
很明显,样例数还是480,这个是正常的,pts的值跟AVPacket的值一样。

我们接着取第三包数据,AVPacket的数据如下所示:
在这里插入图片描述
此时的duration为300000,代表着30ms,pts为1305752680000。与第二包的pts 1303426480000相减,并不是30ms的差值,这个跟我调试时,时间过去太长有关,导致系统对中间停顿的地方没有采集相关声音。
接着用下面语句进行解码。
ret = avcodec_send_packet(pReadCodecContext, &packet);
ret = avcodec_receive_frame(pReadCodecContext, pFrame);
我们观察下pFrame的值,如下:
在这里插入图片描述
可以看到nb_samples为1440,相对于采样率48000,刚好也代表着30ms。

这篇关于ffmpeg关于读取av_read_frame音频数据时,AVPacket字段的说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python+FFmpeg实现视频自动化处理的完整指南

《Python+FFmpeg实现视频自动化处理的完整指南》本文总结了一套在Python中使用subprocess.run调用FFmpeg进行视频自动化处理的解决方案,涵盖了跨平台硬件加速、中间素材处理... 目录一、 跨平台硬件加速:统一接口设计1. 核心映射逻辑2. python 实现代码二、 中间素材处

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

详解C++ 存储二进制数据容器的几种方法

《详解C++存储二进制数据容器的几种方法》本文主要介绍了详解C++存储二进制数据容器,包括std::vector、std::array、std::string、std::bitset和std::ve... 目录1.std::vector<uint8_t>(最常用)特点:适用场景:示例:2.std::arra

MySQL中的DELETE删除数据及注意事项

《MySQL中的DELETE删除数据及注意事项》MySQL的DELETE语句是数据库操作中不可或缺的一部分,通过合理使用索引、批量删除、避免全表删除、使用TRUNCATE、使用ORDERBY和LIMI... 目录1. 基本语法单表删除2. 高级用法使用子查询删除删除多表3. 性能优化策略使用索引批量删除避免

Java之ServerSocket使用及说明

《Java之ServerSocket使用及说明》本文介绍了Java中ServerSocket类的使用方法,包括创建ServerSocket对象、绑定端口、监听连接请求、接受连接、关闭连接等常用方法,还... 目录前言常用方法使用案例1.实现TCP2.实现UDP总结前言Java中的ServerSocket

MySQL 数据库进阶之SQL 数据操作与子查询操作大全

《MySQL数据库进阶之SQL数据操作与子查询操作大全》本文详细介绍了SQL中的子查询、数据添加(INSERT)、数据修改(UPDATE)和数据删除(DELETE、TRUNCATE、DROP)操作... 目录一、子查询:嵌套在查询中的查询1.1 子查询的基本语法1.2 子查询的实战示例二、数据添加:INSE

在C#中读取文件的六种主流方法详解

《在C#中读取文件的六种主流方法详解》在C#中读取文件有多种方法,不同方式适用于不同场景(小型文件、大型文件、文本文件或二进制文件),本文给大家介绍了6种主流方法以及其适用场景,需要的朋友可以参考下... 目录方法1:File.ReadAllText(读取整个文本文件)方法2:File.ReadAllLin

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

使用MyBatis TypeHandler实现数据加密与解密的具体方案

《使用MyBatisTypeHandler实现数据加密与解密的具体方案》在我们日常的开发工作中,经常会遇到一些敏感数据需要存储,比如用户的手机号、身份证号、银行卡号等,为了保障数据安全,我们通常会对... 目录1. 核心概念:什么是 TypeHandler?2. 实战场景3. 代码实现步骤步骤 1:定义 E

使用C#导出Excel数据并保存多种格式的完整示例

《使用C#导出Excel数据并保存多种格式的完整示例》在现代企业信息化管理中,Excel已经成为最常用的数据存储和分析工具,从员工信息表、销售数据报表到财务分析表,几乎所有部门都离不开Excel,本文... 目录引言1. 安装 Spire.XLS2. 创建工作簿和填充数据3. 保存为不同格式4. 效果展示5