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

FFmpeg-swresample的更新

auto convert的创建

在FFmpeg/libavfilter/formats.c中定义了negotiate_videonegotiate_audio,在格式协商,对于video如果需要scale,那么就会自动创建scale作为convert,对于audio,如果需要重采样,则会创建aresample

static const AVFilterNegotiation negotiate_video = {.nb_mergers = FF_ARRAY_ELEMS(mergers_video),.mergers = mergers_video,.conversion_filter = "scale",.conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
};static const AVFilterNegotiation negotiate_audio = {.nb_mergers = FF_ARRAY_ELEMS(mergers_audio),.mergers = mergers_audio,.conversion_filter = "aresample",.conversion_opts_offset = offsetof(AVFilterGraph, aresample_swr_opts),
};

merge相关

格式协商merge的时候,video有merge_pix_fmts,audio有merge_channel_layoutsmerge_sampleratesmerge_sample_fmts

static const AVFilterFormatsMerger mergers_video[] = {{.offset     = offsetof(AVFilterFormatsConfig, formats),.merge      = merge_pix_fmts,.can_merge  = can_merge_pix_fmts,},
};static const AVFilterFormatsMerger mergers_audio[] = {{.offset     = offsetof(AVFilterFormatsConfig, channel_layouts),.merge      = merge_channel_layouts,.can_merge  = NULL,},{.offset     = offsetof(AVFilterFormatsConfig, samplerates),.merge      = merge_samplerates,.can_merge  = can_merge_samplerates,},{.offset     = offsetof(AVFilterFormatsConfig, formats),.merge      = merge_sample_fmts,.can_merge  = can_merge_sample_fmts,},
};

ffmpeg的auto conversion开关

在ffmpeg_opt.c中有这个定义:

int auto_conversion_filters = 1;

如果是0,那么audio conversion是都可以关掉的,这段代码在configure_filtergraph()函数中,flag设置为AVFILTER_AUTO_CONVERT_NONE,所有的自动转换会被禁用。

if (!auto_conversion_filters)avfilter_graph_set_auto_convert(fg->graph, AVFILTER_AUTO_CONVERT_NONE);

ffmpeg使用soxr

  • -af aresample=resampler=soxr
ffmpeg -i chd-44100.wav -af aresample=resampler=soxr -ar 48000 chd-48000.wav -v 56

FFmpeg命令中,默认不指定aresample的时候是swr采样,使用soxr,就需要手动指定-af aresample=resampler=soxr

ffmpeg resample函数中的buf_set

ret= s->resampler->multiple_resample(s->resample, &out, out_count, &in, FFMAX(in_count-padless, 0), &consumed);
out_count -= ret;
ret_sum += ret;
buf_set(&out, &out, ret);
in_count -= consumed;
buf_set(&in, &in, consumed);

s->resampler->multiple_resample返回实际resample的sample数,consumed返回实际消耗的input sample数。

然后buf_set(&out, &out, ret)对out数据进行有效的长度设置,同时也重新计算了out_countin_countbuf_set(&in, &in, consumed)设置了输入数据的有效长度。

internal format的选择

首先要看下internal format的来历:

struct SwrContext {const AVClass *av_class;                        ///< AVClass used for AVOption and av_log()int log_level_offset;                           ///< logging level offsetvoid *log_ctx;                                  ///< parent logging contextenum AVSampleFormat  in_sample_fmt;             ///< input sample formatenum AVSampleFormat int_sample_fmt;             ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P)enum AVSampleFormat out_sample_fmt;             ///< output sample format

SwrContext中,定义了in_sample_fmtint_sample_fmtout_sample_fmt,其中int_sample_fmt就表示internal format,顾名思义,就是用于swresample内部的sample format格式。并且有四种取值:

AV_SAMPLE_FMT_S16P
AV_SAMPLE_FMT_S32P
AV_SAMPLE_FMT_FLTP
AV_SAMPLE_FMT_DBLP

实际的代码是:

    if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2&& av_get_bytes_per_sample(s->out_sample_fmt) <= 2){s->int_sample_fmt= AV_SAMPLE_FMT_S16P;}else if(   av_get_bytes_per_sample(s-> in_sample_fmt) <= 2&& !s->rematrix&& s->out_sample_rate==s->in_sample_rate&& !(s->flags & SWR_FLAG_RESAMPLE)){s->int_sample_fmt= AV_SAMPLE_FMT_S16P;}else if(   av_get_planar_sample_fmt(s-> in_sample_fmt) == AV_SAMPLE_FMT_S32P&& av_get_planar_sample_fmt(s->out_sample_fmt) == AV_SAMPLE_FMT_S32P&& !s->rematrix&& s->out_sample_rate == s->in_sample_rate&& !(s->flags & SWR_FLAG_RESAMPLE)&& s->engine != SWR_ENGINE_SOXR){s->int_sample_fmt= AV_SAMPLE_FMT_S32P;}else if(av_get_bytes_per_sample(s->in_sample_fmt) <= 4){s->int_sample_fmt= AV_SAMPLE_FMT_FLTP;}else{s->int_sample_fmt= AV_SAMPLE_FMT_DBLP;}}
  • 这段代码检查int_sample_fmt是否指定,如果未指定,则根据一些规则来选择一个合适的内部采样格式为:
    • 第一个if语句块中,如果输入和输出采样格式的每个采样点的字节数都小于等于2,则选择AV_SAMPLE_FMT_S16P作为内部采样格式。
    • 第二个else if语句块中,如果输入采样格式的每个采样点的字节数小于等于2,且不需要重新混音(rematrix为false)、输出采样率等于输入采样率、不需要重新采样(SWR_FLAG_RESAMPLE为false),则选择AV_SAMPLE_FMT_S16P作为内部采样格式。
    • 第三个else if语句块中,如果输入和输出采样格式都是32位平面格式(AV_SAMPLE_FMT_S32P),且不需要重新混音、输出采样率等于输入采样率、不需要重新采样、使用的引擎不是SOXR,则选择AV_SAMPLE_FMT_S32P作为内部采样格式。
    • 第四个else if语句块中,如果输入采样格式的每个采样点的字节数小于等于4,则选择AV_SAMPLE_FMT_FLTP作为内部采样格式。
    • 最后一个else语句块中,如果以上条件都不满足,则选择AV_SAMPLE_FMT_DBLP作为内部采样格式。

resample输入输出convert

    s->in_convert = swri_audio_convert_alloc(s->int_sample_fmt,s-> in_sample_fmt, s->used_ch_count, s->channel_map, 0);s->out_convert = swri_audio_convert_alloc(s->out_sample_fmt,s->int_sample_fmt, s->out.ch_count, NULL, 0);

比如internal sample fmt是fltp,输入输出sample fmt没有指定,输入文件是s16,那么输入输出默认就是s16,那么in_convert和out_convert的conv_f值如下:

s->in_convert

  • conv_f: <conv_AV_SAMPLE_FMT_S16_to_AV_SAMPLE_FMT_FLT>

s->out_convert

  • conv_f: <conv_AV_SAMPLE_FMT_FLT_to_AV_SAMPLE_FMT_S16>

convert初始化,不同的平台对应不同的版本:

#if ARCH_X86 && HAVE_X86ASM && HAVE_MMXswri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);
#elif ARCH_ARMswri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);
#elif ARCH_AARCH64swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);
#endif

ffmpeg swreample命令

resampler=swr

    ffmpeg -y -i 2ch-16k.wav -af aresample=resampler=swr -ac 2 -ar 48000 -f f32le out.pcm

不写aresample,默认会走swr

ffmpeg -y -i 2ch-16k.wav -ac 2 -ar 48000 -f f32le out.pcm

-f f32le:指定了保存的文件格式是PCM,不是wav,所以保存出来的文件按wav来解析是不对的,即使文件名为out.wav也不行。

resampler=soxr

ffmpeg -y -i 2ch-16k.wav -af aresample=resampler=soxr -ac 2 -ar 48000 -f f32le out.pcm

resampler=src

ffmpeg -y -i 2ch-16k.wav  -af "aresample=resampler=src" -filter_type sinc_best \
-ac 2 -ar 48000 -acodec pcm_f32le out.wavffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src" -ac 2 -ar 48000 -f f32le out.pcm -v 56

-acodec pcm_f32le:指定输出的格式是pcm_f32le,没有显示指定-f wav,实际上会根据输出文件名使用wav muxer.

-f f32le:f32le参数指定了输出的格式的同时,也保证了src重采样使用的内部数据格式是fltp

指定-acodec pcm_f32le,输出的格式codec格式是pcm_f32le,所以aresample的输出格式会设置为f32le:

./ffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src:filter_type=sinc_best" -ac 2 -ar 48000 -acodec pcm_f32le out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src:filter_type=sinc_fast" -ac 2 -ar 48000 -acodec pcm_f32le out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src:filter_type=sinc_fast:internal_sample_fmt=fltp" -ac 2 -ar 48000 out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src:filter_type=linear:internal_sample_fmt=fltp" -ac 2 -ar 48000 out.wav -v 56./ffmpeg -y -i 2ch-16k.wav -af "aresample=resampler=src:filter_type=zoh:internal_sample_fmt=fltp" -ac 2 -ar 48000 out.wav -v 56

如果没有指定-acodec pcm_f32le,而是通过aresample的option指定out_sample_fmt=flt,这时候,flt只是一个中间格式,最后会转换和输入格式一样的s16le

ffmpeg -y -i 2ch-16k.wav  -af "aresample=resampler=src:filter_type=sinc_best:out_sample_fmt=flt" \
-ac 2 -ar 48000 out.wav -v 56

可以看到如下log:

[ap] ch:2 chl:stereo fmt:s16 r:16000Hz -> ch:2 chl:stereo fmt:flt r:48000Hz
[ap] Using fltp internally between filters
[ap] ch:2 chl:stereo fmt:flt r:48000Hz -> ch:2 chl:stereo fmt:s16 r:48000Hz

相关文章:

FFmpeg-swresample的更新

auto convert的创建 在FFmpeg/libavfilter/formats.c中定义了negotiate_video和negotiate_audio&#xff0c;在格式协商&#xff0c;对于video如果需要scale&#xff0c;那么就会自动创建scale作为convert&#xff0c;对于audio&#xff0c;如果需要重采样&#xff0c;则会创建…...

回答网友 修改一个exe

网友说&#xff1a;他有个很多年前的没有源码的exe&#xff0c;在win10上没法用&#xff0c;让俺看一下。 俺看了一下&#xff0c;发现是窗体设计的背景色的问题。这个程序的背景色用的是clInactiveCaptionText。clInactiveCaptionText 在win10之前的系统上是灰色&#xff0c;但…...

数据可视化 - 动态柱状图

基础柱状图 通过Bar构建基础柱状图 from pyecharts.charts import Bar from pyecharts.options import LabelOpts # 使用Bar构建基础柱状图 bar Bar() # 添加X轴 bar.add_xaxis(["中国", "美国", "英国"]) # 添加Y轴 # 设置数值标签在右侧 b…...

【JVM】JVM五大内存区域介绍

目录 一、程序计数器&#xff08;线程私有&#xff09; 二、java虚拟机栈&#xff08;线程私有&#xff09; 2.1、虚拟机栈 2.2、栈相关测试 2.2.1、栈溢出 三、本地方法栈&#xff08;线程私有&#xff09; 四、java堆&#xff08;线程共享&#xff09; 五、方法区&…...

自动驾驶感知系统--惯性导航定位系统

惯性导航定位 惯性是所有质量体本身的基本属性&#xff0c;所以建立在牛顿定律基础上的惯性导航系统&#xff08;Inertial Navigation System,INS&#xff09;(简称惯导系统)不与外界发生任何光电联系&#xff0c;仅靠系统本身就能对车辆进行连续的三维定位和三维定向。卫星导…...

Netty简介

Netty Netty初体验基础概念Reactor模型传统的阻塞IO模型基础Reactor模型多线程Reactor模型 为什么要使用Netty&#xff1f; &#xff08;NIO的框架&#xff0c;用于解决高并发出现的问题&#xff09; *BIO:同步且阻塞的IO NIO:同步且非阻塞的IO&#xff08;不是说线程&#x…...

基于TCP/IP对等模型对计算机网络知识点的整合

目录 前言 应用层 Telnet SSH FTP/TFTP SNMP&#xff1a;简单的网络管理协议 HTTP&#xff1a;超文本传输协议 SMTP&#xff1a;电子邮件传输协议 DNS&#xff1a;域名解析协议 DHCP&#xff1a;动态主机配置协议 NTP&#xff1a;网络时钟协议 传输层 TCP UDP 端…...

【SQL应知应会】表分区(一)• Oracle版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • Oracle版 前言一、分区表1.什么是表分区…...

PostgreSQL 常用空间处理函数

1.OGC标准函数 管理函数&#xff1a; 添加几何字段 AddGeometryColumn(, , , , , ) 删除几何字段 DropGeometryColumn(, , ) 检查数据库几何字段并在geometry_columns中归档 Probe_Geometry_Columns() 给几何对象设置空间参考&#xff08;在通过一个范围做空间查询时常用&…...

ubuntu初始化/修改root密码

1.登录ubuntu后&#xff0c;使用sudo passwd root命令&#xff0c;进行root密码的初始化/修改&#xff0c;注&#xff1a;这里需要保证两次输入的密码都是同一个&#xff0c;才可成功 ubuntugt-ubuntu22-04-cmd-v1-0-32gb-100m:~/ocr$ sudo passwd root New password: Retype…...

【Linux后端服务器开发】select多路转接IO服务器

目录 一、高级IO 二、fcntl 三、select函数接口 四、select实现多路转接IO服务器 一、高级IO 在介绍五种IO模型之前&#xff0c;我们先讲解一个钓鱼例子。 有一条大河&#xff0c;河里有很多鱼&#xff0c;分布均匀。张三是一个钓鱼新手&#xff0c;他钓鱼的时候很紧张&a…...

支持向量机(iris)

代码&#xff1a; import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn import svm import numpy as np# 定义每一列的属性 colnames [sepal-length, sepal-width, petal-length, petal-width, class] # 读取数据 iris pd.read_csv(data\\i…...

24考研数据结构-第二章:线性表

目录 第二章&#xff1a;线性表2.1线性表的定义&#xff08;逻辑结构&#xff09;2.2 线性表的基本操作&#xff08;运算&#xff09;2.3 线性表的物理/存储结构&#xff08;确定了才确定数据结构&#xff09;2.3.1 顺序表的定义2.3.1.1 静态分配2.3.1.2 动态分配2.3.1.3 mallo…...

Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述动态 sql 的执行原理不?

OGNL表达式 OGNL&#xff0c;全称为Object-Graph Navigation Language&#xff0c;它是一个功能强大的表达式语言&#xff0c;用来获取和设置Java对象的属性&#xff0c;它旨在提供一个更高的更抽象的层次来对Java对象图进行导航。 OGNL表达式的基本单位是"导航链"&a…...

250_C++_typedef std::function<int(std::vector<int> vtBits)> fnChkSstStt

假设我们需要定义一个函数类型来表示一个能够计算整数向量中所有元素之和的函数。 首先,我们定义一个函数,它的参数是一个 std::vector 类型的整数向量,返回值是 int 类型,表示所有元素之和: int sumVectorElements(std::vector<int> vt) {int sum = 0;for (int n…...

无涯教程-jQuery - Transfer方法函数

Transfer 效果可以与effect()方法一起使用。这会将元素的轮廓转移到另一个元素。尝试可视化两个元素之间的交互时非常有用。 Transfer - 语法 selector.effect( "transfer", {arguments}, speed ); 这是所有参数的描述- className - 传输元素将收到的可选类名。…...

openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符

文章目录 openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符24.1 LIKE24.2 SIMILAR TO24.3 POSIX正则表达式 openGauss学习笔记-24 openGauss 简单数据管理-模式匹配操作符 数据库提供了三种独立的实现模式匹配的方法&#xff1a;SQL LIKE操作符、SIMILAR TO操作符…...

JAVASE---数据类型与变量

1. 字面常量 常量即程序运行期间&#xff0c;固定不变的量称为常量&#xff0c;比如&#xff1a;一个礼拜七天&#xff0c;一年12个月等。 public class Demo{ public static void main(String[] args){ System.Out.println("hello world!"); System.Out.println(…...

IDEA Groovy 脚本一键生成实体类<mybatisplus>

配置数据库&#xff08;mysql&#xff09; 一键生成&#xff08;右键点击table&#xff09; 配置自己的groovy脚本 import com.intellij.database.model.DasTable import com.intellij.database.util.Case import com.intellij.database.util.DasUtil import com.intellij.data…...

无涯教程-jQuery - Puff方法函数

吹气效果可以与show/hide/toggle一起使用。通过按比例放大元素并同时隐藏它&#xff0c;可以形成粉扑效果。 Puff - 语法 selector.hide|show|toggle( "puff", {arguments}, speed ); 这是所有参数的描述- model - 效果的模式。可以是"显…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...