• FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws


    Github

    https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff

    CSws.h

    /*******************************************************************
    *  Copyright(c) 2019
    *  All rights reserved.
    *
    *  文件名称:    CSws.h
    *  简要描述:    帧转换
    *
    *  作者:  gongluck
    *  说明:
    *
    *******************************************************************/
    
    #ifndef __CSWS_H__
    #define __CSWS_H__
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    #include <libswscale/swscale.h>
    #include <libavutil/imgutils.h> // av_image_alloc
    
    #ifdef __cplusplus
    }
    #endif
    
    #include <string>
    #include <mutex>
    
    class CSws
    {
    public:
        virtual ~CSws();
    
        // 状态
        enum STATUS { STOP, LOCKED };
        // 设置源参数
        bool set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
        // 设置目标参数
        bool set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err);
        // 锁定设置
        bool lock_opt(std::string& err);
        // 解除锁定
        bool unlock_opt(std::string& err);
        // 转换
        int scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err);
    
    private:
        STATUS status_ = STOP;
        std::recursive_mutex mutex_;
    
        SwsContext* swsctx_ = nullptr;
    
        AVPixelFormat src_pix_fmt_ = AV_PIX_FMT_NONE;
        AVPixelFormat dst_pix_fmt_ = AV_PIX_FMT_NONE;
        int src_w_ = 0;
        int src_h_ = 0;
        int dst_w_ = 0;
        int dst_h_ = 0;
    };
    
    #endif//__CSWS_H__
    

    CSws.cpp

    /*******************************************************************
    *  Copyright(c) 2019
    *  All rights reserved.
    *
    *  文件名称:    CSws.cpp
    *  简要描述:    帧转换
    *
    *  作者:  gongluck
    *  说明:
    *
    *******************************************************************/
    
    #include "common.h"
    #include "CSws.h"
    
    CSws::~CSws()
    {
        std::string err;
        unlock_opt(err);
    }
    
    bool CSws::set_src_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
    {
        LOCK();
        CHECKSTOP(err);
        err = "opt succeed.";
    
        src_pix_fmt_ = pixfmt;
        src_w_ = w;
        src_h_ = h;
    
        return true;
    }
    
    bool CSws::set_dst_opt(AVPixelFormat pixfmt, int w, int h, std::string& err)
    {
        LOCK();
        CHECKSTOP(err);
        err = "opt succeed.";
    
        dst_pix_fmt_ = pixfmt;
        dst_w_ = w;
        dst_h_ = h;
    
        return true;
    }
    
    bool CSws::lock_opt(std::string& err)
    {
        LOCK();
        CHECKSTOP(err);
        err = "opt succeed.";
    
        swsctx_ = sws_getContext(src_w_, src_h_, src_pix_fmt_, dst_w_, dst_h_, dst_pix_fmt_, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr);
        if (swsctx_ == nullptr)
        {
            err = "sws_getContext return nullptr.";
            return false;
        }
        status_ = LOCKED;
    
        return true;
    }
    
    bool CSws::unlock_opt(std::string& err)
    {
        LOCK();
        err = "opt succeed.";
    
        sws_freeContext(swsctx_);
        swsctx_ = nullptr;
        status_ = STOP;
        src_w_ = 0;
        src_h_ = 0;
        dst_w_ = 0;
        dst_h_ = 0;
    
        return true;
    }
    
    int CSws::scale(const uint8_t* const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t* const dst[], const int dstStride[], std::string& err)
    {
        LOCK();
        CHECKNOTSTOP(err);
        err = "opt succeed.";
    
        int ret = sws_scale(swsctx_, srcSlice, srcStride, srcSliceY, srcSliceH, dst, dstStride);
        CHECKFFRET(ret);
    
        return ret;
    }
    

    测试

    // 视频帧转换
    void test_sws()
    {
        bool ret = false;
        std::string err;
        std::ifstream yuv("in.yuv", std::ios::binary);
        CSws sws;
    
        // 分配图像数据内存
        uint8_t* src[4] = { 0 };
        int srclinesize[4] = { 0 };
        uint8_t* dst[4] = { 0 };
        int dstlinesize[4] = { 0 };
    
        int srcsize = av_image_alloc(src, srclinesize, 640, 432, AV_PIX_FMT_YUV420P, 1);
        int dstsize = av_image_alloc(dst, dstlinesize, 320, 240, AV_PIX_FMT_BGR24, 1);
        yuv.read(reinterpret_cast<char*>(src[0]), 640 * 432);
        yuv.read(reinterpret_cast<char*>(src[1]), 640 * 432 / 4);
        yuv.read(reinterpret_cast<char*>(src[2]), 640 * 432 / 4);
    
        ret = sws.set_src_opt(AV_PIX_FMT_YUV420P, 640, 432, err);
        TESTCHECKRET(ret);
        ret = sws.set_dst_opt(AV_PIX_FMT_BGR24, 320, 240, err);
        TESTCHECKRET(ret);
        ret = sws.lock_opt(err);
        TESTCHECKRET(ret);
        int size = sws.scale(src, srclinesize, 0, 432, dst, dstlinesize, err);
        std::cout << "sws " << size << " line" << std::endl;
        std::ofstream bgr("out.bgr", std::ios::binary);
        bgr.write(reinterpret_cast<char*>(dst[0]), dstsize);
        ret = sws.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);
    }
    
  • 相关阅读:
    【第五周读书笔记】我是一只IT小小鸟
    【第三周读书笔记】浅谈node.js中的异步回调和用jsxlsx操作Excel表格
    【第四周读书笔记】读构建之法第11到第16章
    【第一次个人作业】一条咸鱼的词频统计
    win10连接无线网,开启移动热点,手机连接它手机一直显示获取ip地址中。
    每月一次,免费领取小米云服务会员
    Spring Day 1
    oracle闪回查询和闪回数据库
    oracle异库同表名的两个数据库中数据合并或数据表结构的修改
    oracle使用SQL来生成SQL
  • 原文地址:https://www.cnblogs.com/gongluck/p/11022228.html
Copyright © 2020-2023  润新知