FFmpeg-swresample的更新
auto convert的创建
在FFmpeg/libavfilter/formats.c中定义了negotiate_video和negotiate_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_layouts,merge_samplerates,merge_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_count和in_count,buf_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_fmt,int_sample_fmt,out_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,在格式协商,对于video如果需要scale,那么就会自动创建scale作为convert,对于audio,如果需要重采样,则会创建…...
回答网友 修改一个exe
网友说:他有个很多年前的没有源码的exe,在win10上没法用,让俺看一下。 俺看了一下,发现是窗体设计的背景色的问题。这个程序的背景色用的是clInactiveCaptionText。clInactiveCaptionText 在win10之前的系统上是灰色,但…...
数据可视化 - 动态柱状图
基础柱状图 通过Bar构建基础柱状图 from pyecharts.charts import Bar from pyecharts.options import LabelOpts # 使用Bar构建基础柱状图 bar Bar() # 添加X轴 bar.add_xaxis(["中国", "美国", "英国"]) # 添加Y轴 # 设置数值标签在右侧 b…...
【JVM】JVM五大内存区域介绍
目录 一、程序计数器(线程私有) 二、java虚拟机栈(线程私有) 2.1、虚拟机栈 2.2、栈相关测试 2.2.1、栈溢出 三、本地方法栈(线程私有) 四、java堆(线程共享) 五、方法区&…...
自动驾驶感知系统--惯性导航定位系统
惯性导航定位 惯性是所有质量体本身的基本属性,所以建立在牛顿定律基础上的惯性导航系统(Inertial Navigation System,INS)(简称惯导系统)不与外界发生任何光电联系,仅靠系统本身就能对车辆进行连续的三维定位和三维定向。卫星导…...
Netty简介
Netty Netty初体验基础概念Reactor模型传统的阻塞IO模型基础Reactor模型多线程Reactor模型 为什么要使用Netty? (NIO的框架,用于解决高并发出现的问题) *BIO:同步且阻塞的IO NIO:同步且非阻塞的IO(不是说线程&#x…...
基于TCP/IP对等模型对计算机网络知识点的整合
目录 前言 应用层 Telnet SSH FTP/TFTP SNMP:简单的网络管理协议 HTTP:超文本传输协议 SMTP:电子邮件传输协议 DNS:域名解析协议 DHCP:动态主机配置协议 NTP:网络时钟协议 传输层 TCP UDP 端…...
【SQL应知应会】表分区(一)• Oracle版
欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 分区表 • Oracle版 前言一、分区表1.什么是表分区…...
PostgreSQL 常用空间处理函数
1.OGC标准函数 管理函数: 添加几何字段 AddGeometryColumn(, , , , , ) 删除几何字段 DropGeometryColumn(, , ) 检查数据库几何字段并在geometry_columns中归档 Probe_Geometry_Columns() 给几何对象设置空间参考(在通过一个范围做空间查询时常用&…...
ubuntu初始化/修改root密码
1.登录ubuntu后,使用sudo passwd root命令,进行root密码的初始化/修改,注:这里需要保证两次输入的密码都是同一个,才可成功 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模型之前,我们先讲解一个钓鱼例子。 有一条大河,河里有很多鱼,分布均匀。张三是一个钓鱼新手,他钓鱼的时候很紧张&a…...
支持向量机(iris)
代码: 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考研数据结构-第二章:线性表
目录 第二章:线性表2.1线性表的定义(逻辑结构)2.2 线性表的基本操作(运算)2.3 线性表的物理/存储结构(确定了才确定数据结构)2.3.1 顺序表的定义2.3.1.1 静态分配2.3.1.2 动态分配2.3.1.3 mallo…...
Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述动态 sql 的执行原理不?
OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,它旨在提供一个更高的更抽象的层次来对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 简单数据管理-模式匹配操作符 数据库提供了三种独立的实现模式匹配的方法:SQL LIKE操作符、SIMILAR TO操作符…...
JAVASE---数据类型与变量
1. 字面常量 常量即程序运行期间,固定不变的量称为常量,比如:一个礼拜七天,一年12个月等。 public class Demo{ public static void main(String[] args){ System.Out.println("hello world!"); System.Out.println(…...
IDEA Groovy 脚本一键生成实体类<mybatisplus>
配置数据库(mysql) 一键生成(右键点击table) 配置自己的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一起使用。通过按比例放大元素并同时隐藏它,可以形成粉扑效果。 Puff - 语法 selector.hide|show|toggle( "puff", {arguments}, speed ); 这是所有参数的描述- model - 效果的模式。可以是"显…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
