FFmpeg4.0笔记:封装ffmpeg的音频重采样功能类CSwr
Github
https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff
CSwr.h
/*******************************************************************
* Copyright(c) 2019
* All rights reserved.
*
* 文件名称: CSwr.h
* 简要描述: 重采样
*
* 作者: gongluck
* 说明:
*
*******************************************************************/
#ifndef __CSWR_H__
#define __CSWR_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <libswresample/swresample.h>
#ifdef __cplusplus
}
#endif
#include <string>
#include <mutex>
class CSwr
{
public:
virtual ~CSwr();
// 状态
enum STATUS { STOP, LOCKED };
// 设置源参数
bool set_src_opt(int64_t layout, int rate, enum AVSampleFormat fmt, std::string& err);
// 设置目标参数
bool set_dst_opt(int64_t layout, int rate, enum AVSampleFormat fmt, std::string& err);
// 锁定设置
bool lock_opt(std::string& err);
// 解除锁定
bool unlock_opt(std::string& err);
// 转换(out_count,in_count is per channel's samples)
int convert(uint8_t** out, int out_count, const uint8_t** in, int in_count, std::string& err);
private:
STATUS status_ = STOP;
std::recursive_mutex mutex_;
SwrContext* swrctx_ = nullptr;
AVSampleFormat src_sam_fmt_ = AV_SAMPLE_FMT_NONE;
AVSampleFormat dst_sam_fmt_ = AV_SAMPLE_FMT_NONE;
int64_t src_layout_ = AV_CH_LAYOUT_MONO;
int64_t dst_layout_ = AV_CH_LAYOUT_MONO;
int src_rate_ = 0;
int dst_rate_ = 0;
};
#endif//__CSWR_H__
CSwr.cpp
/*******************************************************************
* Copyright(c) 2019
* All rights reserved.
*
* 文件名称: CSwr.cpp
* 简要描述: 重采样
*
* 作者: gongluck
* 说明:
*
*******************************************************************/
#include "common.h"
#include "CSwr.h"
CSwr::~CSwr()
{
std::string err;
unlock_opt(err);
}
bool CSwr::set_src_opt(int64_t layout, int rate, enum AVSampleFormat fmt, std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
src_layout_ = layout;
src_rate_ = rate;
src_sam_fmt_ = fmt;
return true;
}
bool CSwr::set_dst_opt(int64_t layout, int rate, enum AVSampleFormat fmt, std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
dst_layout_ = layout;
dst_rate_ = rate;
dst_sam_fmt_ = fmt;
return true;
}
bool CSwr::lock_opt(std::string& err)
{
LOCK();
CHECKSTOP(err);
err = "opt succeed.";
swrctx_ = swr_alloc_set_opts(swrctx_, dst_layout_, dst_sam_fmt_, dst_rate_, src_layout_, src_sam_fmt_, src_rate_, 0, nullptr);
if (swrctx_ == nullptr)
{
err = "swr_alloc_set_opts return nullptr.";
return false;
}
int ret = swr_init(swrctx_);
CHECKFFRET(ret);
status_ = LOCKED;
return true;
}
bool CSwr::unlock_opt(std::string& err)
{
LOCK();
err = "opt succeed.";
swr_free(&swrctx_);
status_ = STOP;
src_sam_fmt_ = AV_SAMPLE_FMT_NONE;
dst_sam_fmt_ = AV_SAMPLE_FMT_NONE;
src_layout_ = AV_CH_LAYOUT_MONO;
dst_layout_ = AV_CH_LAYOUT_MONO;
src_rate_ = 0;
dst_rate_ = 0;
return true;
}
int CSwr::convert(uint8_t** out, int out_count, const uint8_t** in, int in_count, std::string& err)
{
LOCK();
CHECKNOTSTOP(err);
err = "opt succeed.";
int ret = swr_convert(swrctx_, out, out_count, in, in_count);
CHECKFFRET(ret);
return ret;
}
测试
// 音频重采样
void test_swr()
{
bool ret = false;
std::string err;
std::ifstream pcm("in.pcm", std::ios::binary);
CSwr swr;
// 分配音频数据内存
uint8_t** src = nullptr;
int srclinesize = 0;
uint8_t** dst = nullptr;
int dstlinesize = 0;
// 分配音频数据内存
int srcsize = av_samples_alloc_array_and_samples(&src, &srclinesize, 2, 44100, AV_SAMPLE_FMT_S16, 1);
int dstsize = av_samples_alloc_array_and_samples(&dst, &dstlinesize, 2, 48000, AV_SAMPLE_FMT_S16P, 1);
// 获取样本格式对应的每个样本大小(Byte)
int persize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16P);
// 获取布局对应的通道数
int channel = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
ret = swr.set_src_opt(AV_CH_LAYOUT_STEREO, 44100, AV_SAMPLE_FMT_S16, err);
TESTCHECKRET(ret);
ret = swr.set_dst_opt(AV_CH_LAYOUT_STEREO, 48000, AV_SAMPLE_FMT_S16P, err);
TESTCHECKRET(ret);
ret = swr.lock_opt(err);
TESTCHECKRET(ret);
std::ofstream outpcm("out.pcm", std::ios::binary);
while (!pcm.eof())
{
pcm.read(reinterpret_cast<char*>(src[0]), srcsize);
int size = swr.convert(dst, dstlinesize, (const uint8_t**)(src), 44100, err);
// 拷贝音频数据
for (int i = 0; i < size; ++i) // 每个样本
{
for (int j = 0; j < channel; ++j) // 每个通道
{
outpcm.write(reinterpret_cast<const char*>(dst[j] + persize * i), persize);
}
}
}
ret = swr.unlock_opt(err);
TESTCHECKRET(ret);
// 清理
if (src != nullptr)
{
av_freep(&src[0]);
}
av_freep(&src);
if (dst != nullptr)
{
av_freep(&dst[0]);
}
av_freep(&dst);
}
FFmpeg4.0笔记:封装ffmpeg的音频重采样功能类CSwr的更多相关文章
- FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装、转封装、avio、硬解码等例子
Github https://github.com/gongluck/FFmpeg4.0-study/blob/master/official%20example/my_example.cpp #in ...
- FFmpeg(11)-基于FFmpeg进行音频重采样(swr_init(), swr_convert())
一.包含头文件和库文件 修改CMakeLists # swresample add_library(swresample SHARED IMPORTED) set_target_properties( ...
- FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...
- FFmpeg4.0笔记:封装ffmpeg的解码功能类CDecode
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDecode.h /********************** ...
- FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CSws.h /************************* ...
- FFmpeg4.0笔记:rtsp2rtmp
Github https://github.com/gongluck/FFmpeg4.0-study.git #include <iostream> using namespace std ...
- FFmpeg4.0笔记:file2rtmp
Github: https://github.com/gongluck/FFmpeg4.0-study.git #include <iostream> using namespace st ...
- FFmpeg4.0笔记:VS2019编译FFmpeg4.0源码
0.下载TDM.msys和yasm 1.安装TDM-GCC-64 2.安装msys到TDM-GCC的安装目录中 3.将call "C:\Program Files (x86)\Microso ...
- FFmpeg4.0笔记:采集系统声音
Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff // 采集系统声音 void test_systemsound() ...
随机推荐
- ZAP-Queries【luogu3455】
题目大意 有不超过\(50000\)个询问,每次询问有多少正整数对\(x\),\(y\),满足\(x\leqslant a\),\(y \leqslant b\),并且\(gcd(x,y)=c\).其 ...
- Vue_(组件)计算属性
Vue计算属性中文文档 传送门 Vue计算属性:更强大的属性声明方式,可以对定义的属性进行逻辑处理与数据监视; 注意:模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑 ...
- [题解] [CF518D] Ilya and Escalator
题面 题解 期望dp入门题 设\(f[i][j]\)为到\(i\)时间有\(j\)个人上了电梯的概率, 我们可以得到转移方程 \[ f[i][j]=\begin{cases}f[i-1][j]\cdo ...
- Rust格式化输出
打印操作由 https://doc.rust-lang.org/std/fmt/ 里面所定义的一系列宏来处理,包括: format!:将格式化文本写到字符串(String).(译注:字符串是返 回值不 ...
- TCP时间戳选项Timestamp
时间戳选项发送方在每个报文段中放置一个时间戳值.接收方在确认中返回这个数值,从而允许发送方为每一个收到的ACK计算RTT(我们必须说“每一个收到的ACK”而不是“每一个收到的报文段”,是因为TCP通常 ...
- centos6.5和centos7如何搭建php环境(包括php7)
查看下centos的版本信息: #适用于所有的linux lsb_release -a #或者 cat /etc/redhat-release #又或者 rpm -q centos-release 安 ...
- weblogic性能调优
1.设置java参数: a) 编辑Weblogic Server启动脚本文件: /user_projects/domains/Domain_jgbs/bin/startWebLogic.sh /use ...
- Cortex-M3 异常中断响应与返回
[异常/中断响应]Cortex-M3的异常/中断响应序列包括: 入栈:把8个寄存器的值压入栈. 取向量:从向量表中找出对应的服务程序入口地址. 更新寄存器:更新堆栈指针SP,更新连接寄存器LR,更新程 ...
- ASP.NET Core-Docs:在 ASP.NET Core 中启用跨域请求(CORS)
ylbtech-ASP.NET Core-Docs:在 ASP.NET Core 中启用跨域请求(CORS) 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 1. ...
- ControlTemplate in WPF —— DataGrid
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...