SDL在windows下使用 – YUV图片显示在窗口。
1. 从SDK官网下载windows下SDL运行库,链接http://www.libsdl.org/download-2.0.php,网页下面有Development Libraries -> windows,下载对应的库。
2. 导入SDL到工程项目(当前使用vs2015)。
#include "./SDL2-devel-2.0.4-VC/SDL2-2.0.4/include/SDL.h"
#include "./SDL2-devel-2.0.4-VC/SDL2-2.0.4/include/SDL_main.h"
#pragma comment(lib,"./SDL2-devel-2.0.4-VC/SDL2-2.0.4/lib/x86/SDL2.lib")
3.使用步骤,以MFC窗口为例
BOOL SDL_init_all(CVideoTestDlg *pDlg, int width, int height);
void SDL_Show_Image(unsigned char* buffer, int width, int height, CVideoTestDlg *pDlg);
BOOL SDL_init_all(CVideoTestDlg *pDlg, int width, int height)
{
if (SDL_Init(SDL_INIT_VIDEO))
{
return false;
}
// pSDL_Win = SDL_CreateWindow("Simplest Video", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
// 800, 600, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); //win32创建窗口方式
pSDL_Win = SDL_CreateWindowFrom((void *)(pDlg->GetDlgItem(IDC_STATIC)->GetSafeHwnd()));
if (!pSDL_Win)
return false;
pSDL_Renderer = SDL_CreateRenderer(pSDL_Win, -1, 0);
Uint32 pixformat = 0;
#if LOAD_BGRA
//Note: ARGB8888 in "Little Endian" system stores as B|G|R|A
pixformat = SDL_PIXELFORMAT_ARGB8888;
#elif LOAD_RGB24
pixformat = SDL_PIXELFORMAT_RGB888;
#elif LOAD_BGR24
pixformat = SDL_PIXELFORMAT_BGR888;
#elif LOAD_YUV420P
//IYUV: Y + U + V (3 planes)
//YV12: Y + V + U (3 planes)
pixformat = SDL_PIXELFORMAT_IYUV;
#endif
pSDL_Texture = SDL_CreateTexture(pSDL_Renderer, pixformat, SDL_TEXTUREACCESS_STREAMING, width, height);
return true;
}
void SDL_Show_Image(unsigned char* buffer, int width, int height, CVideoTestDlg *pDlg)
{
SDL_UpdateTexture(pSDL_Texture, NULL, buffer, width);
CRect rt; //获取当前显示控件的大小
pDlg->GetDlgItem(IDC_STATIC)->GetWindowRect(&rt);
SDL_Rect sdlrect;
sdlrect.x = 0;
sdlrect.y = 0;
sdlrect.w = rt.Width();
sdlrect.h = rt.Width() * height / width; //匹配窗口大小
SDL_RenderClear(pSDL_Renderer);
SDL_RenderCopy(pSDL_Renderer, pSDL_Texture, NULL, &sdlrect);
SDL_RenderPresent(pSDL_Renderer);
delete[] buffer; //由于传过来的buffer是new的空间,用完释放。
buffer = NULL;
}
ps: SDL直接贴YUV,在窗口显示缩放的时候效果较好。而YUV->RGB再用GDI(StretchDIBits)贴图,在缩放的时候画面上会出现水纹,猜测应该是缩放像素的处理问题,暂时没解决。
//YUV转成RGB以后使用GDI贴图
VOID RGB_Render(uint8_t *pRGBBuffer, int width, int height, CVideoTestDlg *pDlg)
{
if (pRGBBuffer == NULL)
return;
//构建BMP Header
BITMAPINFO m_bmphdr = { 0 };
DWORD dwBmpHdr = sizeof(BITMAPINFO); //24bit
m_bmphdr.bmiHeader.biBitCount = 24;
m_bmphdr.bmiHeader.biClrImportant = 0;
m_bmphdr.bmiHeader.biSize = dwBmpHdr;
m_bmphdr.bmiHeader.biSizeImage = 0;
m_bmphdr.bmiHeader.biWidth = width;
m_bmphdr.bmiHeader.biHeight = -height; //bmp数据是从下往上存储的
m_bmphdr.bmiHeader.biXPelsPerMeter = 0;
m_bmphdr.bmiHeader.biYPelsPerMeter = 0;
m_bmphdr.bmiHeader.biClrUsed = 0;
m_bmphdr.bmiHeader.biPlanes = 1;
m_bmphdr.bmiHeader.biCompression = BI_RGB;
HDC hdc = pDlg->GetDC()->GetSafeHdc();
CRect rt ;
pDlg->GetDlgItem(IDC_STATIC)->GetWindowRect(&rt); //获取窗口大小
int nResult = StretchDIBits(hdc,
0, 0,
// rt.Width(), rt.Width() * height / width, //匹配窗口缩小图片
width, height, // 按原图大小显示
0, 0,
width, height,
pRGBBuffer,
&m_bmphdr,
DIB_RGB_COLORS,
SRCCOPY);
HWND hwn = pDlg->GetSafeHwnd();
ReleaseDC(hwn, hdc);
delete[] pRGBBuffer; //由于传进来的buffer是new的空间,所以处理完需要释放。
pRGBBuffer = NULL;
}