SDL是一个跨平台的多媒体库。为了实现跨平台,SDL提供了一个简单的界面库抽象,比如提供了SDL_Window用于表示窗口句柄,SDL_Surface、SDL_Texture、SDL_Renderer用于处理画面刷新及基本的图形绘制,提供各种事件(鼠标、键盘、游戏手柄等)输入事件、窗口消息事件用于模拟基于消息的事件处理机制。同时也提供了线程创建、销毁以及同步的机制,在此基础上上也提供了文件访问、字体渲染、多格式图片加载、混音器等扩展功能。

 

正是由于SDL的跨平台特性,如果你仅仅是希望知道SDL的功能,并能够应用SDL做简单的开发,那这篇文件不适合你,建议去SDL官网上看看Lazy Foo的教程或者Beginning SDL 2.0(1) SDL功能简介

 

撰写本文的主要目的在于,我希望可以在window框架下使用SDL渲染YUV数据,仅仅调用视频渲染有关的函数,其他跨平台的机制不需要,windows平台下都提供了对应的机制。或者你现有基于window框架的程序,希望使用SDL渲染视频,这也是一篇不错的介绍文章。

 

一、准备工作

我使用的开发环境是VS2010,SDL使用V2.0.0.3的发布版本,并且安装在C:\dev-tools\SDL2-2.0.3目录下。请按照其他任何SDL的开发环境配置号vs的包含路径和库路径。

同时创建一个Win32的工程,命名为0_Win32_bmp_render。

编译并运行,会有如下窗口显示: 

 

Beginning SDL 2.0(3) SDL介绍及BMP渲染

 

 

二、SDLVideoRender基类

为了实现抽象化的概念,我们先设定下SDL视频渲染类的对外接口,并给出基本的框架。

#include <SDL.h>
//#include <SDL_main.h>
#pragma comment(lib, "SDL2.lib")

class SDLVideoRender
{
public:
    SDLVideoRender();
    virtual ~SDLVideoRender();

    virtual bool Init(HWND show_wnd, RECT show_rect);
    virtual void Deinit();

    // width x height resolution
    // data[] for Y\U\V, stride is linesize of each raw
    virtual void Update(int width, int height, unsigned char *data[3], int stride[3]) = 0;
    virtual bool Render() = 0;

protected:
    SDL_Window * m_sdl_window;
    SDL_Rect m_show_rect;
};

其中调用Init函数时需要指定绘制的窗口句柄及显示区域(相对于窗口的客户区坐标)。

如果需要刷新窗口(给定YUV)数据,调用Update接口。

Render接口用于实现画面的显示。

m_sdl_window指针是SDL提供的窗口抽象句柄。

SDL_Rect是SDL给出的矩形定义形式,其定义如下:

typedef struct SDL_Rect
{
    int x, y;
    int w, h;
} SDL_Rect;

那么初始化Init函数需要完成哪些功能呢?创建SDL_Window并保存显示区域,其实现代码如下:

bool SDLVideoRender::Init(HWND show_wnd, RECT show_rect)
{
    // 初始化窗口句柄为空或者显示区域为空
    if (nullptr == show_wnd || IsRectEmpty(&show_rect))
    {
        return false;
    }

    if (nullptr != m_sdl_window)
    {
        return true;
    }

    if (SDL_WasInit(SDL_INIT_VIDEO))
    {
        SDL_InitSubSystem(SDL_INIT_VIDEO);
    }

    m_sdl_window = SDL_CreateWindowFrom(show_wnd);
    if (nullptr == m_sdl_window)
    {
        return false;
    }

    m_show_rect.x = show_rect.left;
    m_show_rect.y = show_rect.top;
    m_show_rect.w = show_rect.right - show_rect.left;
    m_show_rect.h = show_rect.bottom - show_rect.top;

    return true;
}

Deinit函数功能正好相反,代码如下:

void SDLVideoRender::Deinit()
{
    if (nullptr != m_sdl_window)
    {
        SDL_DestroyWindow(m_sdl_window);
        m_sdl_window = nullptr;
    }
}
View Code

相关文章: