头文件:
#pragma once
#include "ddraw.h"
#include <time.h>
#pragma comment (lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")
class display
{
public:
display(void);
public:
~display(void);
public:
unsigned __int64 init(HWND hwnd);
void uninit();
unsigned __int64 inputsource(unsigned char * src, long nwidth, long nheight, long ntype, long nrate, unsigned __int64 npts);
static BOOL WINAPI DDEnumCallBack( GUID *pguid, LPTSTR pszdesc, LPTSTR pszdevicename, LPVOID pcontext, HMONITOR hmonior );
unsigned __int64 createoffscreen(LPDIRECTDRAWSURFACE7 * offscreen, DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype);
unsigned __int64 createddsd(DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype);
unsigned __int64 wait_ctrl(unsigned __int64 npts);
void refrush();
void reinit();
private:
struct MONITOR_INFO
{
LPDIRECTDRAW7 lpDD; // DirectDraw 对象指针
HMONITOR hMon;
};
LPDIRECTDRAW7 m_lpddraw; // DirectDraw 对象指针
LPDIRECTDRAWSURFACE7 m_lpddsprimary; // DirectDraw 主表面指针
LPDIRECTDRAWSURFACE7 m_lpddsoffscr; // DirectDraw 离屏表面指针
LPDIRECTDRAWSURFACE7 m_lpddsoffscr2; // DirectDraw 离屏表面指针
LPDIRECTDRAWCLIPPER m_lpclipper;
HWND m_hwnd;
DDSURFACEDESC2 m_ddsd;
bool m_init;
long m_lastwidth;
long m_lastheight;
RECT m_rctDest; // 目标区域
RECT m_rctSour; // 源区域
RECT m_rctDestLast;
DDBLTFX m_ddbltfx;
};
cpp文件:
#include "StdAfx.h"
#include "display.h"
display::display(void)
{
m_lpddraw = NULL;
m_lpddsprimary = NULL;
m_lpddsoffscr = NULL;
m_lpddsoffscr2 = NULL;
m_lpclipper = NULL;
m_init = false;
memset(&m_ddsd, 0, sizeof(m_ddsd));
m_lastwidth = 0;
m_lastheight = 0;
}
display::~display(void)
{
}
BOOL WINAPI display::DDEnumCallBack( GUID *pguid, LPTSTR pszdesc, LPTSTR pszdevicename, LPVOID pcontext, HMONITOR hmonior )
{
LPDIRECTDRAW7 lpDD = NULL; // DirectDraw 对象指针
MONITOR_INFO *pthis = ( MONITOR_INFO *)pcontext;
if ( !pthis )
{
return FALSE;
}
if ( pthis->hMon == hmonior )
{
OutputDebugStringA("创建DirectDraw begin
");
if (DirectDrawCreateEx(pguid, (void**)&lpDD, IID_IDirectDraw7, NULL) != DD_OK)
{
OutputDebugStringA("创建lpDD error!
");
}
pthis->lpDD = lpDD;
lpDD = NULL;
}
OutputDebugStringA("创建DirectDraw end
");
// 创建DirectDraw对象
return TRUE;
}
void display::reinit()
{
uninit();
init(m_hwnd);
}
unsigned __int64 display::init(HWND hwnd)
{
if (m_init)
{
return 0;
}
m_hwnd = hwnd;
MONITOR_INFO mi_lpdd;
mi_lpdd.hMon = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
// 枚举监视器并创建DirectDraw对象
DirectDrawEnumerateExA( display::DDEnumCallBack,
&mi_lpdd,
DDENUM_ATTACHEDSECONDARYDEVICES |
DDENUM_DETACHEDSECONDARYDEVICES |
DDENUM_NONDISPLAYDEVICES
);
m_lpddraw = mi_lpdd.lpDD;
if(m_lpddraw == NULL)
{
if (DirectDrawCreateEx(NULL, (VOID**)&m_lpddraw,IID_IDirectDraw7,NULL) != DD_OK)
{
OutputDebugStringA("display::init 创建DirectDraw NOK
");
}
if (!m_lpddraw)
{
OutputDebugStringA("display::init 2创建DirectDraw NOK
");
return -1;
}
}
if (m_lpddraw->SetCooperativeLevel(/*pcd->hRenderWnd*/NULL,
DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES | DDSCL_ALLOWREBOOT ) != DD_OK)
{
OutputDebugStringA("display::init 创建lpDDxiezuo error!
");
if (m_lpddraw)
{
m_lpddraw->Release();
m_lpddraw = NULL;
}
return -1;
}
// 创建主表面
DDSURFACEDESC2 ddsd; // DirectDraw 表面描述
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;// | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
//ddsd.dwBackBufferCount = 1;
if (m_lpddraw->CreateSurface(&ddsd, &m_lpddsprimary, NULL) != DD_OK)
{
OutputDebugStringA("display::init 创建m_lpddsprimary error!
");
if (m_lpddraw)
{
m_lpddraw->Release();
m_lpddraw = NULL;
}
return -1;
}
if(m_lpddraw->CreateClipper(0, &m_lpclipper, NULL) != DD_OK)
{
if (m_lpddraw)
{
m_lpddraw->Release();
m_lpddraw = NULL;
}
OutputDebugStringA("display::init 创建m_lpclipper error!
");
return -1;
}
m_lpclipper->SetHWnd(0, hwnd);
m_lpddsprimary->SetClipper(m_lpclipper);
m_init = true;
return 0;
}
void display::uninit()
{
if (m_lpddsoffscr)
{
m_lpddsoffscr->Release();
m_lpddsoffscr = NULL;
}
if (m_lpddsoffscr2)
{
m_lpddsoffscr2->Release();
m_lpddsoffscr2 = NULL;
}
if (m_lpddsprimary)
{
m_lpddsprimary->Release();
m_lpddsprimary = NULL;
}
if (m_lpclipper)
{
m_lpclipper->Release();
m_lpclipper = NULL;
}
if (m_lpddraw)
{
m_lpddraw->Release();
m_lpddraw = NULL;
}
m_init = false;
}
unsigned __int64 display::createddsd(DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype)
{
ddsd->dwSize = sizeof(*ddsd);
ddsd->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY ; //DDSCAPS_OVERLAY DDSCAPS_OFFSCREENPLAIN;
ddsd->dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;// | DDSD_PITCH | DDSD_LPSURFACE;
ddsd->dwWidth = nwidth;
ddsd->dwHeight = nheight;
ddsd->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd->ddpfPixelFormat.dwFlags = DDPF_FOURCC;
if ( ntype == 2)
{
ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('R','G','B',' ');
ddsd->ddpfPixelFormat.dwFlags |= DDPF_RGB;
ddsd->ddpfPixelFormat.dwRGBBitCount = 32;
}
else if ( ntype == 3)
{
ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','1','2');
ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
ddsd->ddpfPixelFormat.dwYUVBitCount = 12;
}
else if ( ntype == 4)
{
ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('U','Y','V','Y');
ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
ddsd->ddpfPixelFormat.dwYUVBitCount = 16;
}
else if ( ntype == 5)
{
ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC(/*'I','4','2','0'*/'Y','V','1','2');
ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
ddsd->ddpfPixelFormat.dwYUVBitCount = 12;
}
else if ( ntype == 6)
{
ddsd->ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2'); //or YUYV. the same format.
ddsd->ddpfPixelFormat.dwFlags |= DDPF_YUV;
ddsd->ddpfPixelFormat.dwYUVBitCount = 16;
}
else
{
OutputDebugStringA("************LOG_RTM, unsupported pixel format: %d, pcd->m_bdInRender.nType
");
return -1;
}
return 0;
}
void display::refrush()
{
//m_lpddsprimary->Blt(&m_rctDest, m_lpddsoffscr, &m_rctSour, DDBLT_WAIT, &m_ddbltfx);
}
unsigned __int64 display::createoffscreen(LPDIRECTDRAWSURFACE7 * offscreen, DDSURFACEDESC2 * ddsd, long nwidth, long nheight, long ntype)
{
unsigned __int64 nerror = 0;
//DDERR_UNSUPPORTEDMODE;
HRESULT result = m_lpddraw->CreateSurface(ddsd, offscreen, NULL);
if(FAILED (result))
{
if (result == DDERR_NODIRECTDRAWHW)
{
reinit();
}
return -1;
}
return 0;
}
unsigned __int64 display::wait_ctrl(unsigned __int64 npts)
{
return 0;
}
unsigned __int64 display::inputsource(unsigned char * src, long nwidth, long nheight, long ntype, long nrate, unsigned __int64 npts)
{
if (!m_init)
{
return -1;
}
unsigned __int64 nerror = 0;
if (!m_lpddsoffscr || m_lastwidth != nwidth || m_lastheight != nheight)
{
if (m_lpddsoffscr)
{
m_lpddsoffscr->Release();
m_lpddsoffscr = NULL;
}
nerror = createddsd(&m_ddsd, nwidth, nheight, ntype);
if (nerror)
{
OutputDebugStringA("display::inputsource createddsd error[m_lpddsoffscr equ null]
");
return -1;
}
nerror = createoffscreen(&m_lpddsoffscr, &m_ddsd, nwidth, nheight, ntype);
if (nerror)
{
OutputDebugStringA("display::inputsource createoffscreen error[m_lpddsoffscr equ null]
");
return -1;
}
}
if (!m_lpddsoffscr)
{
OutputDebugStringA("display::inputsource error[m_lpddsoffscr equ null]
");
return -1;
}
HRESULT hr = m_lpddsoffscr->Lock(NULL,&m_ddsd, DDLOCK_WAIT |DDLOCK_WRITEONLY,NULL);
if (hr == DDERR_SURFACELOST)
{
OutputDebugStringA("DDERR_SURFACELOST DDERR_SURFACELOST DDERR_SURFACELOST...1
");
hr = m_lpddsoffscr->Restore();
hr = (hr != DD_OK)? hr : m_lpddsoffscr->Lock(NULL,&m_ddsd,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL);
}
if (hr != DD_OK)
{
OutputDebugStringA("display::inputsource Lock error
");
return -1;
}
m_lastwidth = nwidth;
m_lastheight = nheight;
LPBYTE lpSurf = (LPBYTE)m_ddsd.lpSurface;
LPBYTE lpSurfV = lpSurf + m_ddsd.dwHeight*m_ddsd.lPitch;
LPBYTE lpSurfU = lpSurfV + (m_ddsd.dwHeight*m_ddsd.lPitch>>2);
if (3 == ntype || 5 == ntype)
{
LPBYTE lpY = src;
LPBYTE lpU;
LPBYTE lpV;
if (3 == ntype)
{
lpV = lpY + nwidth * nheight;
lpU = lpV + (nwidth * nheight>>2);
}
else
{
lpU = lpY + nwidth * nheight;
lpV = lpU + (nwidth * nheight>>2);
}
// 填充离屏表面
long lddsdHeightHalf = m_ddsd.dwHeight>>1;
long lddsdlPitchHalf = m_ddsd.lPitch>>1;
long lWidhtHalf = nwidth>>1;
for(unsigned int i = 0; i < m_ddsd.dwHeight; i++)
{
memcpy(lpSurf, lpY, nwidth);
lpY += nwidth;
lpSurf += m_ddsd.lPitch;
if (i < lddsdHeightHalf)
{
memcpy(lpSurfU, lpU, lWidhtHalf);
lpU += lWidhtHalf;
lpSurfU += lddsdlPitchHalf;
memcpy(lpSurfV, lpV, lWidhtHalf);
lpV += lWidhtHalf;
lpSurfV += lddsdlPitchHalf;
}
}
}
m_lpddsoffscr->Unlock(NULL);
// RECT rctDest;
// GetClientRect(m_hwnd, &rctDest);
// ClientToScreen(m_hwnd,(LPPOINT)&rctDest.left);
// ClientToScreen(m_hwnd,(LPPOINT)&rctDest.right);
// if (rctDest.left != m_rctDestLast.left || rctDest.top != m_rctDestLast.top
// || rctDest.right != m_rctDestLast.right || rctDest.bottom != m_rctDestLast.bottom)
{
//m_rctDestLast = rctDest;
m_rctSour.left = 0;
m_rctSour.top = 0;
m_rctSour.right = m_ddsd.dwWidth;
m_rctSour.bottom = m_ddsd.dwHeight;
GetClientRect(m_hwnd, &m_rctDest);
MONITORINFO mi;
memset(&mi, 0, sizeof(MONITORINFO));
mi.cbSize = sizeof(MONITORINFO);
HMONITOR hmon = ::MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
if (!hmon)
{
OutputDebugStringA("display::inputsource MonitorFromWindow error[hmon equ null]
");
return -1;
}
::GetMonitorInfo(hmon, &mi);
m_rctDest.left -= mi.rcMonitor.left;
m_rctDest.right -= mi.rcMonitor.left;
m_rctDest.top -= mi.rcMonitor.top;
m_rctDest.bottom -= mi.rcMonitor.top;
ClientToScreen(m_hwnd, (LPPOINT)&m_rctDest.left);
ClientToScreen(m_hwnd, (LPPOINT)&m_rctDest.right);
memset(&m_ddbltfx, 0, sizeof(m_ddbltfx));
m_ddbltfx.dwSize = sizeof(m_ddbltfx);
m_ddbltfx.dwROP = SRCCOPY;
}
// Blt到主表面上
HRESULT hr2 = m_lpddsprimary->Blt(&m_rctDest, m_lpddsoffscr, &m_rctSour, DDBLT_WAIT, &m_ddbltfx);
if (hr2 == DDERR_SURFACELOST)
{
OutputDebugStringA("DDERR_SURFACELOST DDERR_SURFACELOST DDERR_SURFACELOST...
");
hr2 = m_lpddsprimary->Restore();
}
if (hr2 != DD_OK)
{
OutputDebugStringA("display::inputsource Blt error
");
return -1;
}
return 0;
}