当前位置: 移动技术网 > IT编程>开发语言>C/C++ > FFmpeg4.0笔记:封装ffmpeg的视频帧转换功能类CSws

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

2019年06月15日  | 移动技术网IT编程  | 我要评论

云南高考状元刘涵,日亚,三国好孩子 笔趣阁

github

https://github.com/gongluck/ffmpeg4.0-study/tree/master/cff

csws.h

#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:
    ~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);
    // 转换
    bool 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

#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);
    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);
    dst_pix_fmt_ = pixfmt;
    dst_w_ = w;
    dst_h_ = h;
    return true;
}

bool csws::lock_opt(std::string& err)
{
    lock();
    checkstop(err);
    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(src_w_, src_h_, src_pix_fmt_, dst_w_, dst_h_, dst_pix_fmt_, sws_fast_bilinear, nullptr, nullptr, nullptr) return nullptr.";
        return false;
    }
    status_ = locked;
    return true;
}

bool csws::unlock_opt(std::string& err)
{
    lock();
    sws_freecontext(swsctx_);
    swsctx_ = nullptr;
    status_ = stop;
    src_w_ = 0;
    src_h_ = 0;
    dst_w_ = 0;
    dst_h_ = 0;
    return true;
}

bool 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);
    int ret = sws_scale(swsctx_, srcslice, srcstride, srcslicey, srcsliceh, dst, dststride);
    checkffret(ret);
    return true;
}

测试

#include "cdecode.h"
#include "csws.h"
#include <iostream>
#include <fstream>

csws g_sws;
uint8_t* g_pointers[4] = { 0 };
int g_linesizes[4] = { 0 };

void decstatuscb(cdecode::status status, std::string err, void* param)
{
    std::cout << std::this_thread::get_id() << " got a status " << status << std::endl;
}

void decframecb(const avframe* frame, cdecode::frametype frametype, void* param)
{
    //std::cout << std::this_thread::get_id() << " got a frame." << frametype << std::endl;
    if (frametype == cdecode::frametype::video)
    {
        if (frame->format == av_pix_fmt_yuv420p)
        {
            static std::ofstream video("out.rgb", std::ios::binary | std::ios::trunc);
            static int i = 0;
            if (++i > 9)
                return; 

            /*
            video.write(reinterpret_cast<const char*>(frame->data[0]), frame->linesize[0] * frame->height);
            video.write(reinterpret_cast<const char*>(frame->data[1]), frame->linesize[1] * frame->height / 2);
            video.write(reinterpret_cast<const char*>(frame->data[2]), frame->linesize[2] * frame->height / 2);
            */

            std::string err;
            // 将输出翻转
            g_pointers[0] += g_linesizes[0] * (240 - 1);
            g_linesizes[0] *= -1;
            // 转换
            g_sws.scale(frame->data, frame->linesize, 0, frame->height, g_pointers, g_linesizes, err);
            // 还原指针,以便拷贝数据
            g_linesizes[0] *= -1;
            g_pointers[0] -= g_linesizes[0] * (240 - 1);
            video.write(reinterpret_cast<const char*>(g_pointers[0]), g_linesizes[0] * 240);
        }
    }
}

int main(int argc, char* argv[])
{
    std::string err;
    bool ret = false;

    ret = g_sws.set_src_opt(av_pix_fmt_yuv420p, 576, 432, err);
    ret = g_sws.set_dst_opt(av_pix_fmt_rgb24, 320, 240, err);
    ret = g_sws.lock_opt(err);
    int size = av_image_alloc(g_pointers, g_linesizes, 320, 240, av_pix_fmt_rgb24, 1);

    cdecode decode;
    ret = decode.set_input("in.flv", err);
    ret = decode.set_dec_callback(decframecb, nullptr, err);
    ret = decode.set_dec_status_callback(decstatuscb, nullptr, err);

    int i = 0;
    while (i++ < 1)
    {
        ret = decode.begindecode(err);

        std::cout << "input to stop decoding." << std::endl;
        getchar();

        ret = decode.stopdecode(err);
    }

    ret = g_sws.unlock_opt(err);
    av_freep(&g_pointers[0]);

    return 0;
}

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网