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

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

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

相关文章

7年经验之谈 —— 浅谈web性能测试

什么是性能测试&#xff1f; web性能应该注意些什么&#xff1f; 性能测试&#xff0c;简而言之就是模仿用户对一个系统进行大批量的操作&#xff0c;得出系统各项性能指标和性能瓶颈&#xff0c;并从中发现存在的问题&#xff0c;通过多方协助调优的过程。而web端的性能测试…

联发科CEO:未获准向华为供货,换机潮已过去,手机需求不会更差

据钜亨网报道&#xff0c;联发科近期召开了业绩说明会。蔡力行&#xff0c;该公司副董事长兼首席执行官&#xff0c;表明当前手机市场需求保持稳定&#xff0c;并且随着过去两年用户更换潮的过去&#xff0c;对手机市场明年有一定期望。 根据蔡力行的指示&#xff0c;联发科正在…

Notepad++工具通过正则表达式批量替换内容

1.每行末尾新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入$&#xff0c;替换为输入特定字符串&#xff1b;选中循环查找&#xff0c;查找模式选正则表达式&#xff1b;最后点击全部替换 2.每行行首新增特定字符串 CtrlH弹出小窗口&#xff1b;查找目标输入^&…

vue2企业级项目(六)

vue2企业级项目&#xff08;六&#xff09; 自定义指令 创建src/directive/index.js const directives require.context("./modules", true, /\.js$/);export default {install: (Vue) > {directives.keys().forEach((key) > {let directive directives(key…

Windows如何安装Django及如何创建项目

目录 1、Windows安装Django--pip命令行 2、创建项目 2.1、终端创建项目 2.2、在Pycharm中创建项目 2.3、二者创建的项目有何不同 2.4、项目目录说明 1、Windows安装Django--pip命令行 安装Django有两种方式&#xff1a; pip命令行【推荐--简单】手动安装【稍微复杂一丢丢…

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

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

【嵌入式Linux系统开发】——系统移植概述

目录 &#x1f349;&#x1f349;一、什么是嵌入式系统 &#x1f349;&#x1f349;二、嵌入式系统操作 &#x1f349;&#x1f349;三、嵌入式Linux的特点 &#x1f349;&#x1f349;四、嵌入式系统的组成 1、硬件和软件 2、硬件层 3、中间层 4、软件层 5、 功能层与执…

如何用Python统计CSDN质量分

文章目录 CSDN质量分查询selenium爬取博客地址单篇测试批量查询分析 CSDN质量分查询 CSDN对博客有一套分数评价标准&#xff0c;其查询入口在这里&#xff1a;质量分查询&#xff0c;效果大致如下 如果质量分太低&#xff0c;就会在博文的标题下面出现黄底黄字&#xff1a; 这…

Redis简介,设置redis内存大小,设置redis淘汰机制,查看内存占用情况,内存占用分析

为什么使用Redis缓存数据库 我们日常的开发&#xff0c;无非是对数据的处理。程序的定义也可以这样狭义的解释&#xff1a;算法数据。可见数据库是多么重要的工具。但是关系型数据库的读写能力在200-1000次/秒不等&#xff0c;服务器好点可能更多&#xff0c;这导致在高并发的…

排序链表——力扣148

文章目录 题目描述法一 自顶向下归并排序法二&#xff09;自底向上归并排序 题目描述 题目的进阶问题要求达到 O(nlogn) 的时间复杂度和 O(1) 的空间复杂度&#xff0c;时间复杂度是 O(nlogn) 的排序算法包括归并排序、堆排序和快速排序&#xff08;快速排序的最差时间复杂度是…

【C#】.Net Framework框架下的Authorize权限类

2023年&#xff0c;第31周&#xff0c;第3篇文章。给自己一个目标&#xff0c;然后坚持总会有收货&#xff0c;不信你试试&#xff01; 在C#的.NET Framework中&#xff0c;你可以使用Authorize类来处理权限认证。Authorize类位于System.Web.Mvc命名空间中&#xff0c;它提供了…

关于Docker的知识点

Docker是一个快速交付应用、运行应用的技术。 Docker基本操作--容器 示例&#xff1a;创建运行一个Nginx容器

Python不是一门伟大的语言

作为一门简洁易用、生态蓬勃且具有高泛用性的编程语言&#xff0c;Python一直以来都被不少人称作“编程语言中的瑞士军刀”。 尤其随着近来AI热潮席卷全球&#xff0c;Python在编程语言圈中的地位也随之水涨船高&#xff0c;甚至一度被视作AI专用语言或大数据专用语言。 然而…

QT第四讲

思维导图 基于QT的网络聊天室 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTcpServer> //服务器类 #include<QTcpSocket> //客户端类 #include<QMessageBox> //对话框类 #include<QList…

css之文字描边

文章目录 传统方式实现第二种方式 传统方式实现 html <p>文字描边效果</p>scss mixin text-stroke($color: #ffffff, $width: 1px) {text-shadow: 0 -#{$width} #{$color},#{$width} -#{$width} #{$color},#{$width} 0 #{$color},#{$width} #{$width} #{$color}…

【AI】roop给视频换脸记录

环境 安装Anaconda3基于Anaconda3创建一个python3.10的环境安装Git安装ffmpeg 我的操作系统版本是Ubuntu 18.04.4 LTS&#xff08;带GPU会快一点&#xff09;&#xff0c;以上所说的 环境请自行百度安装&#xff01;快速使用 拉取项目 git clone gitgithub.com:VoidAndNull…

Spring Cache

什么是Spring Cache&#xff1f; Spring Cache是Spring框架的一个模块&#xff0c;它提供了对应用程序方法级别的缓存支持。通过使用Spring Cache&#xff0c;您可以在方法的结果被计算后&#xff0c;将其缓存起来&#xff0c;从而避免相同输入导致的重复计算。 Spring Cache…

AWS考试认证学习(二)

一、AWS高级 SAP-C01考试 AWS高级考试 AWS Certified Solutions Architect - Professional 报名费&#xff1a;300美金 SAP-C01考试内容主要覆盖的五大领域和对应领域所占权重&#xff1a; 1、组织复杂性设计 12.5% 2、新解决方案设计 31% 3、迁移规划 15% 4、成本控制…

Linux 发行版 CentOS 于 Ubuntu 软件的安装、卸载、查找

CentOS于Ubuntu 内核都是Linux&#xff0c;是一样的。 CentOS 软件格式 .rpm sudo yum [-y] [ install | remove | search ] 软件名称 install 安装 remove 移除 search 搜索 Ubuntu 软件格式 .deb sudo apt [-y] [ install | remove | search ] 软件名称 install 安装 remove…

二叉树的层序遍历(两种方法:迭代+递归)

题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]] 解题思路&#xff1a;迭代法…