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() ...
随机推荐
- js获取当前页面url信息
<html> <head> <meta charset="utf-8" /> <title></title> <s ...
- pl/sql 过程 函数(写一个过程,输入部门编号,在控制台打印这个部门的名称,总人数,平均工资(基本工资+奖金))
1.编写过程,输入三角形三个表的长度.在控制台打印三角形的面积. create or replace procedure pro_s(v_a number,v_b number,v_c number) ...
- kafka 性能测试脚本
[参考文章]:Kafka自带的性能测试脚本 1. 生产消息压测脚本 1.1 脚本及参数 bin/kafka-producer-perf-test.sh --topic kafka-test-0 -- ...
- IP输出 之 ip_local_out
概述 将要从本地发出的数据包,会在构造了ip头之后,调用ip_local_out函数,该函数设置数据包的总长度和校验和,然后经过netfilter的LOCAL_OUT钩子点进行检查过滤,如果通过,则调 ...
- Visual Studio Code 编辑器使用
image.png 之前一直都是用 sublime text 作为开发工具,用久了自然而然会觉得生活无趣,而且当时用sublime text 装了很多插件,有些插件不能用,于是决定试试微软的新产品 ...
- vue问题六:计算属性,依赖发生变化时,重新计算computed:
<el-form-item label="单价:" prop="price" > <el-input v-model="addfor ...
- 【转】composer proc_open(NUL)报错问题
composer 执行的时候报错错误信息如下: [ErrorException] proc_open(NUL): failed to open stream: No such file or dir ...
- 【例3】设有关系模式R(A, B, C, D, E)与它的函数依赖集F={A→BC, CD→E, B→D, E→A},求R的所有候选键。 解题思路:
通过分析F发现,其所有的属性A.B.C.D.E都是LR类属性,没有L类.R类.N类属性. 因此,先从这些属性中依次取出一个属性,分别求它们的闭包:=ABCDE,=BD,=C,=D, =ABCDE.由于 ...
- centos6密钥验证
密钥验证: 公钥(服务器上)私钥(客户端)在远程登录软件上可生成SSH密钥对.在服务器上建目录.SSH 再在其中建文件authorized_keys,复制公钥到服务器上此文件中. (1)selinux ...
- SQL学习(二)SQL基础的增删改查
在测试时使用数据库时,用的比较多的就是增删改查SQL了. 一.增加(insert into ...values) 用于向表中插入新记录 1.不指定列(表示:依次插入所有列的值) insert into ...