C++-ffmpeg-2-2-工厂模式封装SDL

1.工厂模式的封装
2.封装完窗口渲染器和材质的初始化+渲染画面随窗口大小缩放并解决锯齿问题


1.工厂模式封装 类图

 

1.1图像窗口初始化Init()可能只一次,而渲染Draw()很多次,所以封装不同线程。
都用的锁。
1.2锁的使用如下图所示:

static bool InitVideo()
{
    static bool is_first = true;          
    static mutex mux;                   //1.定义锁的变量  
    unique_lock<mutex> sdl_lock(mux);   //2.调用函数
    if (!is_first)return true;
    is_first = false;
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        cout << SDL_GetError() << endl;
        return false;
    }
    return true;
}

2.封装完窗口渲染器和材质的初始化+渲染画面随窗口大小缩放并解决锯齿问题
其实就是用C++代码实现上面的类图
xvideo_view.h
xvideo_view.cpp
xsdl.h
xsdl.cpp

 

#ifndef XVIDEO_VIEW_H
#define XVIDEO_VIEW_H
#include <mutex>

class XVideoView
{
public:
    enum Format
    {
        RGBA = 0,
        ARGB,
        YUV420P
    };
    enum RenderType
    {
        SDL = 0
    };
    static XVideoView* Create(RenderType type=SDL);
    virtual bool Init(int w, int h,Format fmt = RGBA,void* win_id = nullptr) = 0;  
    virtual bool Draw(const unsigned  char* data, int linesize = 0) = 0;

    //显示缩放
    void Scale(int w, int h)
    {
        scale_w_ = w;
        scale_h_ = h;
    }
protected:
    int width_ = 0;     //材质宽高
    int height_ = 0;
    Format fmt_ = RGBA;  //像素格式
    std::mutex mtx_;    //确保线程安全
    int scale_w_ = 0;   //显示大小
    int scale_h_ = 0;
};

#endif

xvideo_view.cpp


#include "xsdl.h"

XVideoView* XVideoView::Create(RenderType type)
{
	switch (type)
	{
	case XVideoView::SDL:
		return new XSDL();
		break;
	default:
		break;
	}
	return nullptr;
}

xsdl.h

#pragma once
#include "xvideo_view.h"
struct SDL_Window;
struct SDL_Renderer;
struct SDL_Texture;
class XSDL :public XVideoView
{
public:
      bool Init(int w, int h,Format fmt = RGBA,void* win_id = nullptr) override;
      bool Draw(const unsigned  char* data,int linesize = 0) override;
private:
    SDL_Window* win_ = nullptr;
    SDL_Renderer* render_ = nullptr;
    SDL_Texture* texture_ = nullptr;
};

xsdl.cpp

#include "xsdl.h"
#include <sdl/SDL.h>
#include <iostream>
using namespace std;

static bool InitVideo()
{
    static bool is_first = true;
    static mutex mux;
    unique_lock<mutex> sdl_lock(mux);
    if (!is_first)return true;
    is_first = false;
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        cout << SDL_GetError() << endl;
        return false;
    }
    //设定缩放算法,解决锯齿问题,线性插值算法
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
    return true;
}
bool XSDL::Init(int w, int h,Format fmt,void* win_id)
{
    if (w <= 0 || h <= 0)return false;
    //1.初始化SDL 视频库
    InitVideo();
    //确保线程安全
    unique_lock<mutex> sdl_lock(mtx_);
    width_ = w;
    height_ = h;
    fmt_ = fmt;

    ///2.创建窗口 渲染器 材质  
    win_ = SDL_CreateWindow("",
                SDL_WINDOWPOS_UNDEFINED,
                SDL_WINDOWPOS_UNDEFINED,
                w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
            );
    render_ = SDL_CreateRenderer(win_, -1, SDL_RENDERER_ACCELERATED);
    //创建材质 (显存)
    unsigned int sdl_fmt = SDL_PIXELFORMAT_RGBA8888;
    switch (fmt)
    {
    case XVideoView::RGBA:
        break;
    case XVideoView::ARGB:
        sdl_fmt = SDL_PIXELFORMAT_ARGB32;
        break;
    case XVideoView::YUV420P:
        sdl_fmt = SDL_PIXELFORMAT_IYUV;
        break;
    default:
        break;
    }
    texture_ = SDL_CreateTexture(render_,
        sdl_fmt,                        //像素格式
        SDL_TEXTUREACCESS_STREAMING,    //频繁修改的渲染(带锁)
        w, h                            //材质大小
    );

    if ((!win_)||(!render_)||(!texture_))
    {
        cerr << SDL_GetError() << endl;
        return false;
    }
    render_ = SDL_CreateRenderer(win_, -1, SDL_RENDERER_ACCELERATED);
    if (!render_)
    {
        cerr << SDL_GetError() << endl;
        return false;
    }
    return true;
}

bool XSDL::Draw(const unsigned char* data,int linesize)
{
    if (!data)return false;
    unique_lock<mutex> sdl_lock(mtx_);//只要是线程调用就创建线程变量。
    if (!texture_ || !render_ || !win_ || width_ <= 0 || height_ <= 0)
        return false;
    if (linesize <= 0)
    {
        switch (fmt_)
        {
        case XVideoView::RGBA:
        case XVideoView::ARGB:
            linesize = width_ * 4;
            break;
        case XVideoView::YUV420P:
            linesize = width_;
            break;
        default:
            break;
        }
    }
    if (linesize <= 0)
        return false;
    //1.渲染器清空,复制内存到显存,材质复制到渲染器,显示
    SDL_RenderClear(render_);
    auto re = SDL_UpdateTexture(texture_, NULL, data, linesize);
    if (re != 0)
    {
        cout << SDL_GetError() << endl;
        return false;
    }
    SDL_RenderClear(render_);
    if (scale_w_ <= 0)scale_w_ = width_;
    if (scale_h_ <= 0)scale_h_ = height_;

    SDL_Rect rect;
    rect.x = 0; rect.y = 0;
    rect.w = scale_w_;//渲染的宽高,可缩放
    rect.h = scale_h_;
    re = SDL_RenderCopy(render_, texture_, NULL, &rect);
    if (re != 0)
    {
        cout << SDL_GetError() << endl;
        return false;
    }
    SDL_RenderPresent(render_);
    return true;
}

调用的时候:
 

 view = XVideoView::Create();
 view->Init(sdl_width, sdl_height,
        XVideoView::YUV420P,(void*)ui.label->winId());
view->Draw(yuv);



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值