zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    微信小程序——gulp处理文件
    小程序开发经验总结
    微信小程序入门之构建一个简单TODOS应用
    3元体验腾讯云小程序后端解决方案
    C++笔记:面向对象编程(Handle类)
    你真的知道你看到的UTF-8字符是什么吗?
    Unity3D游戏开发之在Unity3D中视频播放功能的实现
    vb.net机房收费系统——存储过程
    Oracle基础学习4--Oracle权限传递
    我与京东的那些事儿
  • 原文地址:https://www.cnblogs.com/gongluck/p/11023760.html
Copyright © 2011-2022 走看看