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() ...
随机推荐
- Linux常用文本处理命令
1.grep命令 echo 'zero\nzo\nzoo' | grep 'z.*o':将匹配以'z'开头以'o'结尾的所有字符串 echo 'zero\nzo\nzoo' | grep 'z.o': ...
- JavaScript 高级系列之节流 [throttle] 与防抖 [debounce]
一.概念 这两个东西都是为了项目优化而出现的,官方是没有具体定义的,他们的出现主要是为了解决一些短时间内连续执行的事件带来性能上的不佳和内存的消耗巨大等问题:像这类事件一般像 scroll keyup ...
- 主线程 Looper.loop() 死循环为何不会ANR
先看下 ActivityThread 中的这段代码: 而 loop() 方法中,存在一个死循环: public static void loop() { ... ... ... for (;;) { ...
- UEP的单步测试
想起了单步测试,在这里就随便说说,本人在海颐软件工作,主要开发工具uep,这里简单说一下uep的单步测试step into;step over:step return.海颐封装的uep开发工具还是很容 ...
- Cortex-M3 异常中断响应与返回
[异常/中断响应]Cortex-M3的异常/中断响应序列包括: 入栈:把8个寄存器的值压入栈. 取向量:从向量表中找出对应的服务程序入口地址. 更新寄存器:更新堆栈指针SP,更新连接寄存器LR,更新程 ...
- 简单配置 docker swarm
#准备三台CentOS7 #IP划分 192.168.1.201 virtualBox1 192168.1.202 virtualBox2 192168.1.204 ...
- java:面向对象(接口(续),Compareble重写,Comparator接口:比较器的重写,内部类,垃圾回收机制)
接口: *接口定义:使用interface关键字 * [修饰符] interface 接口名 [extends 父接口1,父接口2...]{ * //常量的声明 * //方法的声明 * } *接口成员 ...
- 【Web】[原创]ie6,7中td和img之间有间隙
情形描述 开发工具:VS2010: 浏览器版本:IE6以上,火狐,谷歌: 页面布局设计:Table+Img布局: 项目预览问题:火狐,谷歌,IE8以上未出现问题,IE6,IE7图片之间有间隙. 分析原 ...
- Linux删除命令rm
在用Linux的时候,有时分要删除一个文件夹,常常会提示次此文件非空,没法删除,这个时分,必需运用rm -rf命令.关于一些小白用户常常在运用Linux命令,会十分当心,以免搞出一些事情,下面小编将教 ...
- MariaDB(第三章)select
基本查询 ``` --查询基本使用(条件,排序,聚合函数,分组,分页) --创建学生表 create table students ( id int unsigned not null auto_in ...