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);
}
                    
                
                
            
        
浙公网安备 33010602011771号