最近幾個項目視訊進行中,渲染采用SDL2.0,現在封裝一個SDL2.0類,友善大家使用。SDL2.0庫調用流程如下:
Sdl2Handle.h
#ifndef _SDL2HANDLE_H_
#define _SDL2HANDLE_H_
//基于SDL2.0實作的圖檔渲染器
//SDL_Window就是使用SDL的時候彈出的那個視窗。在SDL2.0版本中,可以建立多個視窗。
//SDL_Texture用于顯示YUV資料。一個SDL_Texture對應一幀YUV資料。
//SDL_Renderer用于渲染SDL_Texture至SDL_Window。
//SDL_Rect用于确定SDL_Texture顯示的位置。注意:一個SDL_Texture可以指定多個不同的SDL_Rect,這樣就可以在SDL_Window不同位置顯示相同的内容(使用SDL_RenderCopy()函數)。
extern "C"
{
#include "SDL.h"
};
class CSdl2Handle
{
public:
CSdl2Handle();
~CSdl2Handle();
bool SdlOpen(void *pWndHandle,const char *pTitle,int iWidth,int iHeight);
void SdlClose();
//顯示一幀YV12資料 iLinesize YUV每個分量 每行資料寬度 不一定等于圖檔寬度
void SdlDisplayFrame(uint8_t *pszData[],int iLinesize[],int iFlag);
//YUV顯示BMP圖檔
bool SdlDisplayBmp(char *pFilePath);
public:
static bool SdlInit();
static void SdlUnInit();
private:
//顯示視窗
SDL_Window * m_pWnd;
//圖檔渲染器
SDL_Renderer* m_pRender;
//圖檔裝載器
SDL_Texture* m_pTexture;
//顯示位置(一個視窗可以有多個顯示位置,目前支援一個)
SDL_Rect m_Rect;
//标志視窗是否本層建立
bool m_IsSdlCreate;
};
#endif
Sdl2Handle.cpp
#include "stdafx.h"
#include "Sdl2Handle.h"
#include <stdio.h>
//初始化SDL
bool CSdl2Handle::SdlInit()
{
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))
{
return false;
}
}
//反初始化SDL
void CSdl2Handle::SdlUnInit()
{
SDL_Quit();
}
CSdl2Handle::CSdl2Handle()
{
//顯示視窗
SDL_Window * m_pWnd=NULL;
//圖檔渲染器
SDL_Renderer* m_pRender=NULL;
//圖檔裝載器
SDL_Texture* m_pTexture=NULL;
//标志視窗是否本層建立
m_IsSdlCreate=true;
}
CSdl2Handle::~CSdl2Handle()
{
SdlClose();
}
bool CSdl2Handle::SdlOpen(void *pWndHandle,const char *pTitle,int iWidth,int iHeight)
{
bool bRet=true;
do
{
if(!pWndHandle)
{
m_pWnd =SDL_CreateWindow(pTitle, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, iWidth, iHeight,
SDL_WINDOW_OPENGL);
if(!m_pWnd)
{
printf("SDL: 建立視窗失敗 - 錯誤資訊:%s\n",SDL_GetError());
bRet=false;
break;
}
}
else
{
m_pWnd =SDL_CreateWindowFrom(pWndHandle);
if(!m_pWnd)
{
printf("SDL: 建立視窗失敗 - 錯誤資訊:%s\n",SDL_GetError());
bRet=false;
break;
}
m_IsSdlCreate=false;
}
m_pRender = SDL_CreateRenderer(m_pWnd, -1, 0);
m_pTexture = SDL_CreateTexture(m_pRender, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, iWidth, iHeight);
m_Rect.x=0;
m_Rect.y=0;
m_Rect.w=iWidth;
m_Rect.h=iHeight;
}while(0);
return bRet;
}
void CSdl2Handle::SdlClose()
{
if(m_pTexture)
{
SDL_DestroyTexture(m_pTexture);
m_pTexture=NULL;
}
if(m_pRender)
{
SDL_DestroyRenderer(m_pRender);
m_pRender=NULL;
}
if(m_pWnd)
{
//SDL本身建立 銷毀
if(m_IsSdlCreate)
{
SDL_DestroyWindow(m_pWnd);
}
}
}
void CSdl2Handle::SdlDisplayFrame(uint8_t*pszData[],int iLinesize[],int iFlag)
{
//一幀YV12資料填充到 圖檔裝載器中 顔色反了 可能 U和V反了
if(iFlag)
{
SDL_UpdateYUVTexture(m_pTexture, &m_Rect,
(const Uint8 *)pszData[0], iLinesize[0],
(const Uint8 *)pszData[2], iLinesize[2],
(const Uint8 *)pszData[1], iLinesize[1]);
}
else
{
SDL_UpdateYUVTexture(m_pTexture, &m_Rect,
(const Uint8 *)pszData[0], iLinesize[0],
(const Uint8 *)pszData[1], iLinesize[1],
(const Uint8 *)pszData[2], iLinesize[2]);
}
//清屏
SDL_RenderClear( m_pRender );
//裝載器資料渲染到視窗
SDL_RenderCopy( m_pRender, m_pTexture, NULL, &m_Rect);
//重新整理
SDL_RenderPresent( m_pRender );
}
//YUV顯示BMP圖檔
bool CSdl2Handle::SdlDisplayBmp(char *pFilePath)
{
SDL_Surface *pBmp = NULL;
pBmp = SDL_LoadBMP(pFilePath);
if (pBmp == NULL)
{
printf("SDL_LoadBMP failed: %s", SDL_GetError());
return false;
}
SDL_Texture* pTmpTexture=NULL;
pTmpTexture = SDL_CreateTextureFromSurface(m_pRender, pBmp);
//清屏
SDL_RenderClear( m_pRender );
//裝載器資料渲染到視窗
SDL_RenderCopy( m_pRender, pTmpTexture, NULL, &m_Rect);
//重新整理
SDL_RenderPresent( m_pRender );
//銷毀臨時
SDL_FreeSurface(pBmp);
SDL_DestroyTexture(pTmpTexture);
return true;
}