FFMPEG录屏(11)---- aresample重采样pcm

2023-10-27

本文利用ffmpeg中的filter对pcm数据进行重采样。
参考官网例子:filtering_audio.c

初始化filter
int filter_aresample::init(const FILTER_CTX & ctx_in, const FILTER_CTX & ctx_out, int index)
	{
		int error = AE_NO;
		int ret = 0;

		if (_inited) return AE_NO;

		_index = index;

		do {
			_ctx_in = ctx_in;
			_ctx_out = ctx_out;

			_filter_graph = avfilter_graph_alloc();
			if (!_filter_graph) {
				error = AE_FILTER_ALLOC_GRAPH_FAILED;
				break;
			}

			char layout_name[256] = { 0 };
			av_get_channel_layout_string(layout_name, 256, ctx_out.nb_channel, ctx_out.channel_layout);


			std::stringstream filter_desrcss;
			filter_desrcss << "aresample=";
			filter_desrcss << ctx_out.sample_rate;
			filter_desrcss << ",aformat=sample_fmts=";
			filter_desrcss << av_get_sample_fmt_name(ctx_out.sample_fmt);
			filter_desrcss << ":channel_layouts=";
			filter_desrcss << layout_name;

			std::string filter_desrc = filter_desrcss.str();

			_ctx_in.inout = avfilter_inout_alloc();
			_ctx_out.inout = avfilter_inout_alloc();

			char pad_args[512] = { 0 };

			format_pad_arg(pad_args, 512, _ctx_in);

			ret = avfilter_graph_create_filter(&_ctx_in.ctx, avfilter_get_by_name("abuffer"), "in", pad_args, NULL, _filter_graph);
			if (ret < 0) {
				error = AE_FILTER_CREATE_FILTER_FAILED;
				break;
			}

			ret = avfilter_graph_create_filter(&_ctx_out.ctx, avfilter_get_by_name("abuffersink"), "out", NULL, NULL, _filter_graph);
			if (ret < 0) {
				error = AE_FILTER_CREATE_FILTER_FAILED;
				break;
			}

			av_opt_set_bin(_ctx_out.ctx, "sample_fmts", (uint8_t*)&_ctx_out.sample_fmt, sizeof(_ctx_out.sample_fmt), AV_OPT_SEARCH_CHILDREN);
			av_opt_set_bin(_ctx_out.ctx, "channel_layouts", (uint8_t*)&_ctx_out.channel_layout, sizeof(_ctx_out.channel_layout), AV_OPT_SEARCH_CHILDREN);
			av_opt_set_bin(_ctx_out.ctx, "sample_rates", (uint8_t*)&_ctx_out.sample_rate, sizeof(_ctx_out.sample_rate), AV_OPT_SEARCH_CHILDREN);

			_ctx_in.inout->name = av_strdup("in");
			_ctx_in.inout->filter_ctx = _ctx_in.ctx;
			_ctx_in.inout->pad_idx = 0;
			_ctx_in.inout->next = NULL;

			_ctx_out.inout->name = av_strdup("out");
			_ctx_out.inout->filter_ctx = _ctx_out.ctx;
			_ctx_out.inout->pad_idx = 0;
			_ctx_out.inout->next = NULL;

			ret = avfilter_graph_parse_ptr(_filter_graph, filter_desrc.c_str(), &_ctx_out.inout, &_ctx_in.inout, NULL);
			if (ret < 0) {
				error = AE_FILTER_PARSE_PTR_FAILED;
				break;
			}

			ret = avfilter_graph_config(_filter_graph, NULL);
			if (ret < 0) {
				error = AE_FILTER_CONFIG_FAILED;
				break;
			}

			_inited = true;
		} while (0);

		if (error != AE_NO) {
			al_debug("filter init failed:%s %d", err2str(error), ret);
			cleanup();
		}

		return error;
	}
工作线程
void filter_aresample::filter_loop()
	{
		AVFrame *frame = av_frame_alloc();

		int ret = 0;
		while (_running) {
			std::unique_lock<std::mutex> lock(_mutex);
			while (!_cond_notify && _running)
				_cond_var.wait_for(lock, std::chrono::milliseconds(300));

			while (_running && _cond_notify) {
				ret = av_buffersink_get_frame(_ctx_out.ctx, frame);
				if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
					break;;
				}

				if (ret < 0) {
					al_fatal("avfilter get frame error:%d", ret);
					if (_on_filter_error) _on_filter_error(ret, _index);
					break;
				}

				if (_on_filter_data)
					_on_filter_data(frame, _index);

				av_frame_unref(frame);
			}

			_cond_notify = false;
		}

		av_frame_free(&frame);
	}
开启工作线程
int filter_aresample::start()
	{
		if (!_inited)
			return AE_NEED_INIT;

		if (_running)
			return AE_NO;

		_running = true;
		_thread = std::thread(std::bind(&filter_aresample::filter_loop, this));

		return 0;
	}
添加一帧数据
int filter_aresample::add_frame(AVFrame * frame)
	{
		std::unique_lock<std::mutex> lock(_mutex);

		int error = AE_NO;
		int ret = 0;

		do {
			int ret = av_buffersrc_add_frame_flags(_ctx_in.ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF);
			if (ret < 0) {
				error = AE_FILTER_ADD_FRAME_FAILED;
				break;
			}

		} while (0);

		if (error != AE_NO) {
			al_debug("add frame failed:%s ,%d", err2str(error), ret);
		}

		_cond_notify = true;
		_cond_var.notify_all();

		return error;
	}

完整源码请查阅: screen-recorder

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FFMPEG录屏(11)---- aresample重采样pcm 的相关文章

  • 在 Web 浏览器中禁用 F5 [重复]

    这个问题在这里已经有答案了 可能的重复 禁用浏览器的后退按钮 https stackoverflow com questions 961188 disable browsers back button 如何禁用浏览器上的 F5 刷新 htt
  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • 通过另一个列表更新列表(linq)

    我有类 Data 的对象列表 如下所示 class Data int code string name DateTime date update 我还有另一个课程列表 例如 class RefCodes int old code int n
  • EventHandler 应该始终用于事件吗?

    我一直在愉快地使用自定义委托类型和通用编写事件Action委托类型 没有真正考虑我在做什么 我有一些很好的扩展助手Action and EventHandler这使我倾向于使用那些预定义的委托类型而不是我自己的委托类型 但除此之外 除了惯例
  • 如何使用 C# 以编程方式编辑 Power BI Desktop 文档参数或数据源?

    我有一个在 Power BI Desktop 中内置的报告模板 并保存为 pbix 或 pbit 文件 该模板使用DirectQuery SQL数据库作为数据源 而服务器地址和数据库名称被提取到参数中 还有一个参数包含一个ReportId
  • 如何调整 Windows 窗体以适应任何屏幕分辨率?

    我知道这是重复的问题 但我检查了所有其他相关问题 他们的答案没有帮助 结果仍然与屏幕截图 2 中所示相同 我是 C Windows 窗体新手 如截图1所示 我有Form1有一些控件 每组控件都放在一个面板中 我在 PC1 中设计了应用程序
  • C++中的类要具备什么条件才能成为容器?

    我是 C 编程新手 偶然发现了这个术语containers举例如下vector deque map etc 一个企业的最低要求应该是什么class应该满足被称为container in C 我将从 范围 这个概念开始 Range 只有两个方
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • 以下 PLINQ 代码没有改进

    我没有看到使用以下代码的处理速度有任何改进 IEnumerable
  • Nhibernate:连接表并从其他表获取单列

    我有以下表格 create table Users Id uniqueidentifier primary key InfoId uniqueidentifier not null unique Password nvarchar 255
  • 关闭整数的最右边设置位

    我只需要关闭最右边的设置位即可 我的方法是找到最右边位的位置 然后离开该位 我编写这段代码是为了这样做 int POS int n int p 0 while n if n 2 0 p else break n n 2 return p i
  • C 类型命名约定,_t 或 ALLCAPS

    我一直想知道是否有任何命名约定 例如何时对类型使用全部大写以及何时追加 t 什么时候不使用任何东西 我知道当时 K R 发布了各种有关如何使用 C 的文档 但我找不到任何相关内容 在 C 标准库类型中 t看起来漂亮占主导地位 time t
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 如何设置消息队列的所有者?

    System Messaging MessageQueue 类不提供设置队列所有权的方法 如何以编程方式设置 MSMQ 消息队列的所有者 简短的答案是 p invoke 对 windows api 函数的调用MQSetQueueSecuri
  • 在 C++ 代码 gdb 中回溯指针

    我在运行 C 应用程序时遇到段错误 在 gdb 中 它显示我的一个指针位置已损坏 但我在应用程序期间创建了 10 万个这样的对象指针 我怎样才能看到导致崩溃的一个 我可以在 bt 命令中执行任何操作来查看该指针的生命周期吗 谢谢 鲁奇 据我
  • 如何对STL向量进行排序?

    我想排序一个vector vector
  • 在 mvc4 中创建通用 mvc 视图

    我以前也提过类似的问题 没有得到答案 如何创建一个通用的 mvc4 视图 该视图可以显示传递给它的模型列表或单个模型 模型可以是个人 组织或团体 无论传递给它的是什么 如果您正在寻找类似的东西 model MyViewModel
  • 在二进制数据文件的标头中放入什么

    我有一个模拟 可以读取我们创建的大型二进制数据文件 10 到 100 GB 出于速度原因 我们使用二进制 这些文件依赖于系统 是从我们运行的每个系统上的文本文件转换而来的 所以我不关心可移植性 当前的文件是 POD 结构的许多实例 使用 f
  • 值和类型的简洁双向静态 1:1 映射

    我将从我想象如何使用我想要创建的代码开始 它不必完全像这样 但它是我在标题中所说的 简洁 的一个很好的例子 就我而言 它是将类型映射到相关的枚举值 struct bar foo
  • 对多个对象使用事件处理程序

    我有 20 件物品List

随机推荐

  • 【机器学习】太香啦!只需一行Python代码就可以自动完成模型训练!

    自动化机器学习 Auto ML 是指数据科学模型开发的管道组件自动化 AutoML 减少了数据科学家的工作量并加快了工作流程 AutoML 可用于自动化各种管道组件 包括数据理解 EDA 数据处理 模型训练 超参数调整等 对于端到端机器学习
  • 小米 adb 驱动_ADB禁用系统应用

    第一步 下载ADB压缩包 并解压到根目录下 自己百度找ADB包 第二步 在ADB目录下 shift 鼠标右键 打开powershell 并输入cmd 第三步 手机进入开发者模式 百度 并打开USB调试 数据线连接电脑和手机 要安装好驱动 在
  • 解决idea项目没有蓝色小方块

    导入项目后 把项目中的几个子moudle复制了一份 作为一个新模块 结果发现 项目右下角没有 蓝色小方块 因此造成maven不能识别 如下图 解决方式 在右边侧栏 maven 面板 点击 选择该项目中的pom xml文件即可
  • linux安装时 dev sda4,VMvare在CentOS7.4安装iscsi共享盘

    VMvare 在 CentOS7 4 安装 iscsi 共享盘 1 在节点 1 上添加一个 20g 的存储并 reboot 1 1 查看新添加的磁盘 root xmc1 fdisk l Disk dev sda 32 2 GB 322122
  • python多进程和多线程看这一篇就够了

    脑海中关于进程和线程的概念一直很模糊 什么时候该用多进程 什么时候该用多线程总是搞不清楚 同时python因为历史遗留问题存在GIL全局锁 就让人更加困惑 这一篇就完整整理一下python中进程和线程的概念和实现 文章目录 进程和线程 GI
  • 逻辑Flask——Flask模板

    文章目录 一 简单模板 二 模板传参 三 jinja2内置过滤器 四 Jinja2自定义过滤器 通用过滤器 自定义时间过滤器 五 控制语句 1 if 语句 2 for in语句 列表 遍历字典 获取当前遍历状态 六 宏 6 0 宏的基本模板
  • Python 基础知识7 集合

    python 集合 创建集合 重复的自动被过滤 parame apple orrange banana pear pear print parame parame1 set bird dog pig print parame1 parame
  • 各平台电脑开启虚拟化的方法

    1 Intel平台笔记本 进入BIOS 选择 Configuration 选项 找到 Intel Virtual Technology 改成Enable 2 AMD平台笔记本 进入BIOS 选择 Configuration 的选项 找到 S
  • 使用非负最小二乘回(NNLS)归进行细胞类型转移

    2019年发表在Nature上的文章 The single cell transcriptional landscape of mammalian organogenesis 在方法部分提到 使用NNLS non negative line
  • 西门子传动系统出现这些故障提示原因分析

    1 F002 Pre charging 预充电故障 对整流单元来说 其可能原因为 主进线开关断开或没有闭合 整流单元 例 复卷机整流单元四个熔断器断路 导致传动点出现F008 直流母线电压过低 在更换熔断器后 启动整流器时出现F002 原因
  • bios sgx需要开启吗_华硕主板BIOS解读:新手装机必备篇(必须收藏)

    史上最全BIOS解读 中英文对译 一字一句解析 让你从此不在BIOS中迷路 本期讲解模板BIOS来自华硕TUF X570 GAMING WIFI 今天讲解的内容为新手装机必须经历的内容 新手装机常用到的BIOS选项 并且附上中英文翻译对照
  • 快速排序算法的三种实现

    1 普通快速排序 快速排序思路 随机取一个标定点 v 将 v 放置到合适的位置 保证 v 左边的元素都小于等于 v v 右边的元素都大于 v 然后再继续分别对左边元素和右边的元素做同样的排序动作 直到整个数组有序 那么怎么实现这个快速排序呢
  • Vue-Loader 打包单文件组件实战

    本文是我在学习过程中记录学习的点点滴滴 目的是为了学完之后巩固一下顺便也和大家分享一下 日后忘记了也可以方便快速的复习 Vue Loader 打包单文件组件 前言 一 webpack 结合 Vue Loader 打包单文件组件基本认识 1
  • java 分配算法

    原文地址 http blog csdn net qq 30085577 article details 52756715 版权声明 本文为博主原创文章 未经博主允许不得转载 java view plain copy 随机分配 public
  • Mathorcup数学建模竞赛第二届-【妈妈杯】A题:最佳飞行队列(附带赛题解析&获奖论文及MATLAB代码)

    目录 赛题描述 论文 摘要 一 问题重述 二 模型假设及符号说明 1 模型假设
  • you need to resolve your current index first 解决办法

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到教程 从一个分支A切换到另一个分支B后 对切换后的B分支进行pull操作 因为pull操作实际上包含了fetch merge操作 在执行 merge
  • Box2D一:基础知识

    一 box2d基础知识 1 关于 Box2D 是一个用于游戏的 2D 刚体仿真库 从游戏的视角来看 物理引擎就是一个程序性动画 procedural animation 的系统 而不是由动画师去移动你的物体 1 核心概念 刚体 rigid
  • 量化建模时常见的数据穿越问题

    这篇文章将会介绍一下量化建模时常见的数据穿越问题 何为数据穿越 对于t时刻训练得到的模型必须用t时刻之前的数据训练 如果t时刻用到t时刻以后的数据则会产生数据穿越问题 我碰到比较多的数据穿越问题主要有三种 1 训练集和测试集有交叉 2 特征
  • Kali 安装之腾讯云经验遇到坑

    目录 一 准备工作 二 制作镜像 导入kail ios镜像 安装KALI系统 KALI系统安装过程中出现报错 安装 cloud init 制作云镜像 VMDK QCOW 腾讯云导入kali镜像 使用问题 1 无法ssh协议登录 2 重新命名
  • FFMPEG录屏(11)---- aresample重采样pcm

    本文利用ffmpeg中的filter对pcm数据进行重采样 参考官网例子 filtering audio c 初始化filter int filter aresample init const FILTER CTX ctx in const