当前位置: 首页 > news >正文

ffmpeg的重采样计算

最近在看ffmpeg的重采样计算逻辑,有一句话没大看懂 dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); ,各种请教之后,记录如下。

重采样后的总样本数 为什么要涵盖重采样过程中的延迟 ?

在音频重采样过程中,由于源音频和目标音频的采样率不同,需要对音频数据进行插值或者抽取操作,以使其在时间上对齐。这个过程会引入一定的延迟。

延迟的引入是由于插值或抽取操作的特性决定的。例如,当将音频从低采样率转换为高采样率时,需要通过插值来生成新的样本,这会导致插值过程中的延迟。同样地,将音频从高采样率转换为低采样率时,需要通过抽取来减少样本数,这也会引入抽取过程中的延迟

为了确保重采样后的音频数据能够包含完整的有效音频信息,包括延迟期间的音频数据,我们需要计算重采样后的总样本数。这样可以确保在重采样过程中不会丢失任何音频信息。

因此,在计算重采样后的总样本数时,需要将源音频的样本数与重采样过程中产生的延迟相加。这样可以确保目标音频数据的长度足够容纳重采样过程中产生的延迟期间的音频数据,从而保证音频质量和完整性。

重采样后的总样本数如何计算?

重采样后的总样本数可以通过以下步骤计算:

  • 使用音频重采样上下文(swr_ctx)中的函数 swr_get_delay() 获取重采样引入的延迟(以源音频样本数为单位)。这个函数通常会返回一个浮点数,表示延迟的小数部分。

  • 将获取的延迟与源音频的样本数(src_nb_samples)相加,得到重采样后的未舍入的总样本数。这个值表示重采样后的音频数据中包含的总样本数,包括延迟期间的样本数。

  • 使用 FFmpeg 提供的函数 av_rescale_rnd() 将未舍入的总样本数按比例重新缩放,以适应目标音频的采样频率。

代码解释

这行代码是使用FFmpeg库中的函数进行音频重采样的过程中的一部分。

swr_ctx:这是一个音频重采样上下文(Context),它存储了音频重采样的状态信息和参数。

src_rate:这是源音频的采样率(采样频率),表示每秒钟采样的次数。

src_nb_samples:这是源音频中的样本数,表示要进行重采样的音频数据中包含的样本数。

swr_get_delay(swr_ctx, src_rate):swr_get_delay是一个函数,它返回进行音频重采样所需的延迟(以样本数为单位)。在这里,它返回源音频在重采样过程中产生的延迟。

swr_get_delay(swr_ctx, src_rate) + src_nb_samples:这个表达式将源音频的样本数和重采样过程中的延迟相加,得到重采样后的总样本数。

dst_rate:这是目标音频的采样率,表示重采样后的音频的采样率。

av_rescale_rnd():这是一个函数,用于将一个值按比例重新缩放。它接受要缩放的值、缩放的目标范围和要使用的舍入模式(rounding mode)作为参数,并返回缩放后的结果。

av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) + src_nb_samples, dst_rate, src_rate, AV_ROUND_UP):这个表达式将重采样后的总样本数按比例重新缩放,使其适应目标音频的采样率。AV_ROUND_UP是一个舍入模式,表示采用向上舍入的方式。

dst_nb_samples:这是重采样后的目标音频的样本数。

总而言之,这行代码的目的是计算重采样后的目标音频的样本数。它通过将源音频的样本数和重采样过程中产生的延迟相加,并按比例重新缩放以适应目标音频的采样率来实现。

音频连续时间戳计算逻辑分析

看下这段代码

   ret = avcodec_receive_frame(d->avctx, frame);if (ret >= 0) {AVRational tb = (AVRational){1, frame->sample_rate};if (frame->pts != AV_NOPTS_VALUE)frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb);else if (d->next_pts != AV_NOPTS_VALUE)frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);if (frame->pts != AV_NOPTS_VALUE) {d->next_pts = frame->pts + frame->nb_samples;d->next_pts_tb = tb;}}

frame->pts = av_rescale_q(frame->pts, d->avctx->pkt_timebase, tb)的含义

时间跨度= 当前应出现时间-初始时间 = 源时间戳 * 源时间基数 = 目标时间戳 * 目标时间基数

这行代码是用于将帧的时间戳(PTS)从一个时间基(timebase)转换为另一个时间基的操作。即 目标时间戳 = 源时间戳 * 源时间基数 / 目标时间基数

在这行代码中,frame->pts表示当前帧的时间戳。d->avctx->pkt_timebase表示编码器上下文(AVCodecContext)中的数据包时间基。tb则表示目标时间基。

av_rescale_q函数用于执行时间戳的转换。它接受三个参数:源值(即当前帧的时间戳),源时间基和目标时间基。函数会根据提供的时间基参数,将源值从源时间基转换为目标时间基,并返回转换后的值作为结果。

通过这个操作,可以将帧的时间戳从一个时间基转换为另一个时间基,以适应不同的容器或编解码器要求。这对于正确处理时间轴和时序是非常重要的,特别是在处理音视频同步、编辑和混流等操作时。这种转换可以确保视频和音频的时间信息在不同的上下文中保持一致和准确。

d->next_pts = frame->pts + frame->nb_samples;

假设每个音频样本的持续时间都是1/sample_count_per_second,那么存在等式:当前时间戳(单位秒)+当前音频帧的样本个数 = 下一个音频帧的开始时间戳(单位秒),据此,我们解释一下这行代码。

在这行代码中,frame->pts表示源值,即当前帧的时间戳(Presentation Timestamp,PTS)。d->avctx->pkt_timebase表示源时间基,它是编码器上下文(AVCodecContext)中的数据包时间基。

时间基是一个分数,用于表示时间的单位和精度。它通常用于将时间戳从一种表示方式转换为另一种表示方式。分数的分子表示时间单位,分母表示每秒的时间单位数。

在这里,frame->pts乘以d->avctx->pkt_timebase的目的是将当前帧的时间戳从源时间基转换为目标时间基。乘法运算的结果是一个根据源时间基和目标时间基的比例进行缩放的时间戳值。

通过执行乘法运算,可以将时间戳从一个时间基转换为另一个时间基,以便在不同的容器或编解码器之间进行正确的时间同步和时间轴处理。这种转换可以确保视频和音频的时间信息在不同的上下文中保持一致和准确。

frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb);

根据上面的推算,其实d->next_pts的时间基已经不是解码的时间基了,而是解码后的时间基,即目标采样率1/sample_count_per_second,所以这里有 d->next_pts_tb = tb;

音频序列号分析

d->pkt_serial是一个变量,用于表示音视频数据包的序列号。在音视频处理和同步过程中,使用序列号可以跟踪和标识不同的音视频数据包。

序列号通常用于多线程或并行处理的场景,其中音频和视频数据可能以不同的速度解码和处理。每个数据包都可以被分配一个唯一的序列号,以便在后续的处理过程中进行识别和排序。

通过使用序列号,可以实现以下功能:

  1. 数据包排序:通过比较不同数据包的序列号,可以按正确的顺序对它们进行处理,以确保音视频数据的正确同步。例如,在音视频同步中,可以根据序列号将音频和视频数据包按照时间顺序进行匹配和呈现。

  2. 错误检测:序列号可以用于检测丢失的或乱序的数据包。如果一个或多个数据包的序列号在处理过程中出现间隔或不连续,可能表明存在数据包丢失或乱序的问题。

  3. 数据包关联:序列号还可以用于将音频和视频数据包进行关联。例如,在多个音频和视频流进行混流的情况下,可以通过序列号将对应的音频和视频数据包进行匹配和关联。

综上所述,d->pkt_serial是一个用于标识和跟踪音视频数据包的序列号变量,用于实现数据包的排序、错误检测和关联等功能。

音频包处理

pkt_in_play_range 是一个表示音视频包(packet)是否处于播放范围内的标志。它通常用于音视频播放器或处理器中,以确定是否应该处理给定的音视频包。

在音视频处理中,往往会有一个播放范围(play range),用于指定在特定时间段内播放音视频数据。播放范围可以是整个音视频文件的时间范围,也可以是用户在播放器中指定的某个时间段。

pkt_in_play_range 标志用于判断当前的音视频包是否在播放范围内。如果 pkt_in_play_range 为真(非零),表示音视频包处于播放范围内,应该被处理和播放。如果 pkt_in_play_range 为假(零),表示音视频包不在播放范围内,可以选择跳过处理或忽略该包。

这个标志的设置通常由播放器或相关的音视频处理逻辑根据当前的播放位置和播放范围来决定。它可以帮助控制音视频的播放和处理,以确保只处理和呈现播放范围内的音视频数据。

相关文章:

ffmpeg的重采样计算

最近在看ffmpeg的重采样计算逻辑,有一句话没大看懂 dst_nb_samples av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); ,各种请教之后,记录如下。 重采样后的总样本数 为什么要涵盖重采…...

Go HTTP 调用(上)

哈喽大家好,我是陈明勇,今天分享的内容是 Go HTTP 调用。如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出&am…...

STM32Cube高效开发教程<基础篇>(一)----概述

声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。    本专栏博客参考《STM32Cube高效开发教程(基础篇)》,有意向的读者可以购买正版书籍辅助学习,本书籍由王维波老师、鄢志丹老师、王钊老师倾力打造,书籍内容干货满满。 一、 STM32系列…...

汽车RNC主动降噪算法DSP C程序实现

汽车RNC主动降噪算法C程序 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,车载...

Java21虚拟线程完整用法

方式1 Thread.startVirtualThread(new Task());方式2 Thread virtualThread Thread.ofVirtual().name("Virtual Thread").unstarted(new Task()); virtualThread.start();方式3 Thread.ofVirtual().name("Virtual Thread").start(new Task());方式4 Th…...

Vue 中的 nextTick 方法

nextTick的背景 Vue 使用虚拟 DOM(Virtual DOM)和异步更新策略来实现高效的视图更新。当你修改 Vue 实例的数据时,Vue 并不会立即更新真实的 DOM,而是将更新操作加入到队列中,在下一个事件循环周期(微任务…...

TypeScript React(上)

目录 扩展学习资料 TypeScript设计原则 TypeScript基础 语法基础 变量声明 JavaScript声明变量 TypeScript声明变量 示例 接口 (标准类型-Interface) 类型别名-Type 接口 VS 类型别名 类型断言:欺骗TS&#xff0c;肯定数据符合结构 泛型、<大写字母> 扩展学习…...

Linux 安全 - LSM源码分析

文章目录 前言一、简介1.1 DAC 和 MAC1.2 LSM 调用流程图 二、LSM相关数据结构2.1 struct security_hook_list2.2 union security_list_options2.3 structure security_hook_heads 三、security_bprm_check四、LSM 源码分析3.1 early_security_init3.2 security_init3.2.1 secu…...

第一次汇报相关问题

深度学习现在已经学习到了Mini-Batch&#xff0c;early-stop等针对特定场景优化的算法了。 代码已经实现了一个L层的神经网络的构建了 论文看了一些综述 主要思考的两个方向&#xff1a;云计算和嵌入式 云计算&#xff1a;分布式机器学习、联邦学习、服务器负载均衡等 嵌入式&…...

[产品体验] GPT4识图功能

[产品体验] GPT4识图功能 图片配文字超强的OCR能力知识问答多图解释 打开chatgpt的时候突然发现能用识图了&#xff0c;赶紧去体验一下&#xff0c;大大的震撼… 图片配文字 超强的OCR能力 我传上去的图片并不清晰… 还能准确识别&#xff0c;orz &#xff01; 知识问答 多…...

《3D 数学基础》几何检测-最近点

目录 1. 直线上的最近点 2. 射线上的最近点 3. 点到平面的距离 4. 圆或球上的最近点 5. AABB上的最近点 1. 直线上的最近点 q是距离q的最近点&#xff0c;也就是q在直线上的投影。 其中p是直线上的点&#xff08;向量表示&#xff09;&#xff0c;n是直线的法向量&#x…...

动态规划 -背包问题-详解

问题 注&#xff1a;大佬对此类问题的解法&#xff1a;动态规划背包问题总结 给你一个由 不同 整数组成的数组 nums &#xff0c;和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 示例 1&#xff…...

Bootstrap-- 媒体特性

最大、最小宽度例子&#xff1a; 横屏与竖屏例子&#xff1a; 宽度比与像素比例子&#xff1a;...

c# 用非递归的写法实现递归

最近写代码碰到了一个bug&#xff0c;就是递归次数太多爆堆栈了&#xff0c;然后就写了一个递归工具来解决这个问题。 using System; using System.Collections.Generic;/// <summary> /// 递归工具 /// </summary> public static class RecursionTool {//递归方式…...

nginx之location的优先级和nginx的重定向

一、nginx之location的优先级和匹配方式&#xff08;重点&#xff09; &#xff08;一&#xff09;nginx的正则表达式 nginx的正则表达式 符号 含义 ^ 字符串的起始位置&#xff08;以什么开头&#xff09; $ 字符串的结束位置&#xff08;以什么结尾&#xff09; * 匹…...

【计算机网络】——前言计算机网络发展的历程概述

主页点击直达&#xff1a;个人主页 我的小仓库&#xff1a;代码仓库 C语言偷着笑&#xff1a;C语言专栏 数据结构挨打小记&#xff1a;初阶数据结构专栏 Linux被操作记&#xff1a;Linux专栏 LeetCode刷题掉发记&#xff1a;LeetCode刷题 算法&#xff1a;算法专栏 C头…...

eventfd

1. #include <sys/eventfd.h> int eventfd(unsigned int initval, int flags); //创建eventfd 参数含义&#xff1a; initval&#xff1a;创建eventfd时它所对应的64位计数器的初始值&#xff1b; flags&#xff1a;eventfd文件描述符的标志&#xff0c;可由三种选项组…...

BES耳机空间音频技术实现

BES耳机空间音频技术实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?加我微信hezkz17, 本群提供音频技术答疑服务 音响和耳机在空间音频技术上实现方式是不同的 虚拟现实可谓是空间音频技术最具代表性的应 用领域。虽然虚拟现实的起源可以追溯到1 9 6 8年, …...

day27--AJAX(bootstrap之modal,toast;接口文档的一些用法;AJAX原理)

目录 Bootstrap之Modal&#xff1a; 显示和隐藏方法 通过自定义属性&#xff1a; 使用JS来控制弹框&#xff1a; Bootstrap之Toast&#xff1a; 接口文档一些用法&#xff1a; 删除图书&#xff1a; 图片上传&#xff1a; 图片上传步骤&#xff1a; 修改头像&#xf…...

【ArcGIS Pro二次开发】(70):杂七杂八的记录

本文用于记录一些使用频率较高但归类繁杂&#xff0c;非系统性的一些代码。 主要方便自己使用和查阅&#xff0c;随时更新。 1、从GDB数据库中打开【FeatureDataset\FeatureClass\Table】 using Geodatabase gdb new Geodatabase(new FileGeodatabaseConnectionPath(new Uri…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...