|
还是先说以下我的实现原理原理吧:
1、视频源由一块视频压缩卡提供
//视频设备初始化
BOOL InitDevice()
{
//打开视频设备
hDevice =CreateFile("\\\\.\\HKDS9004_1",GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
NULL ); // no template
if (hDevice == INVALID_HANDLE_VALUE)
return FALSE;
}
//视频数据结构(和视频卡的驱动有关)如下:
typedef struct{
ULONG Width; ULONG Height;
ULONG Depth; ULONG Pitch;
ULONG BitCount; ULONG VirtualAddress;
ULONG OffScreenDepth; ULONG OffScreenPitch;
ULONG OffScreenBitCount; ULONG OffScreenWidth;
ULONG OffScreenHeight;
ULONG OffScreenVirtualAddress;
ULONG OffScreenDepth2; ULONG OffScreenPitch2;
ULONG OffScreenBitCount2; ULONG OffScreenWidth2;
ULONG OffScreenHeight2;
ULONG OffScreenVirtualAddress2;
} DISPLAY_PARAMETER, *PDISPLAY_PARAMETER;
typedef struct{
ULONG Top;ULONG Left;ULONG Right;ULONG Bottom;
ULONG Depth;ULONG Pitch;
ULONG BitCount;ULONG VirtualAddress;
ULONG OpenClose; //1为传输数据,0为不传输
ULONG Depth2;ULONG Pitch2;ULONG BitCount2;
ULONG VirtualAddress2;
ULONG Top2;ULONG Left2;ULONG Right2;ULONG Bottom2;
ULONG OpenClose2;ULONG Mode;
}OVERLAY_WINDOW, *POVERLAY_WINDOW;
DISPLAY_PARAMETER 结构定义两个OffScreen表面存储视频图象数据(程序中为了简单实际只用了一个OffScreen表面,效果稍差)
OVERLAY_WINDOW是接受视频卡数据的结构
通过以下函数接受数据
ULONG bytesWritten;
if(!DeviceIoControl(hDevice,IOCTL_OVERLAY_WINDOW,
&m_overlayWin,
sizeof(m_overlayWin),
NULL,0,&bytesWritten,
NULL))
{
return FALSE;
}
2、DirectDraw 初始化
//DDrawInit()
void DDrawInit()
{
}
3、接受显示数据初始化
//InitParam()
BOOL InitParam()
{
HRESULT hRet;RECT srect,drect;
GetClientRect(hWnd, &clientrect);
ClientToScreen(hWnd, (LPPOINT) &clientrect.left);
ClientToScreen(hWnd, (LPPOINT) &clientrect.right);
drect.top=clientrect.top;
drect.left=clientrect.left;
drect.right=clientrect.left+704;
drect.bottom=clientrect.top+576;
srect.top=0;srect.left=0;srect.right=352;srect.bottom=288;
DWORD dwUpdateFlags;
// Set the flags we'll send to UpdateOverlay
dwUpdateFlags = DDOVER_SHOW ;
hRet = lpDDSOverlay->UpdateOverlay(NULL, lpDDSPrimary, &drect, dwUpdateFlags, NULL);
// get display parameter
if(lpDDSOffscreen1->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK)
return FALSE;
m_displayPara.OffScreenVirtualAddress = (ULONG)ddsd.lpSurface;
m_displayPara.OffScreenPitch = (ULONG)ddsd.lPitch;
m_displayPara.OffScreenBitCount = ddsd.ddpfPixelFormat.dwRGBBitCount;
m_displayPara.OffScreenDepth = (ddsd.ddpfPixelFormat.dwRGBBitCount +7) / 8;
m_displayPara.OffScreenWidth = ddsd.dwWidth;
m_displayPara.OffScreenHeight = ddsd.dwHeight;
// clear offscreen memory
ZeroMemory((PVOID *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight);
lpDDSOffscreen1->Unlock(NULL);
if(lpDDSOffscreen2->Lock(NULL, &ddsd, DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK)
return FALSE;
m_displayPara.OffScreenVirtualAddress2 = (ULONG)ddsd.lpSurface;
m_displayPara.OffScreenPitch2 = (ULONG)ddsd.lPitch;
m_displayPara.OffScreenBitCount2 = ddsd.ddpfPixelFormat.dwRGBBitCount;
m_displayPara.OffScreenDepth2 = (ddsd.ddpfPixelFormat.dwRGBBitCount + 7) / 8;
m_displayPara.OffScreenWidth2 = ddsd.dwWidth;
m_displayPara.OffScreenHeight2 = ddsd.dwHeight;
ZeroMemory((PVOID *)ddsd.lpSurface, ddsd.lPitch * ddsd.dwHeight);
lpDDSOffscreen2->Unlock(NULL);
m_overlayWin.Mode = OVERLAY_MODE | USING_BUFFER; ///cjh
m_overlayWin.OpenClose = 1;
m_overlayWin.Top = 0;
m_overlayWin.Left = 0;
m_overlayWin.Right = 704;
m_overlayWin.Bottom = 576;
m_overlayWin.Depth = m_displayPara.OffScreenDepth;
m_overlayWin.Pitch = m_displayPara.OffScreenPitch;
m_overlayWin.BitCount = m_displayPara.OffScreenBitCount;
m_overlayWin.VirtualAddress = m_displayPara.OffScreenVirtualAddress;
m_overlayWin.Depth2 = m_displayPara.OffScreenDepth2;
m_overlayWin.Pitch2 = m_displayPara.OffScreenPitch2;
m_overlayWin.BitCount2 = m_displayPara.OffScreenBitCount2;
m_overlayWin.VirtualAddress2 = m_displayPara.OffScreenVirtualAddress2 ;
ULONG bytesWritten;
if(!DeviceIoControl(
hDevice,
IOCTL_OVERLAY_WINDOW,
&m_overlayWin,
sizeof(m_overlayWin),
NULL,
0,
&bytesWritten,
NULL))
{
return FALSE;
}
if(hRet != DD_OK) DDrawInitFailed(hWnd, hRet,"Updateoverlay() failed");
// color fill
DDBLTFX ddbltfx;
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = 100;
hRet = lpDDSOverlay->Blt(NULL, // 目标矩形
NULL, NULL, // 源页面和源矩形
DDBLT_COLORFILL, &ddbltfx);
DDOn = 1; // Set refresh switch
return TRUE;
}
4、程序窗口初始化
//InitWindow()就不写了
5、主函数
//WinMain()
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
if(!InitWindow(hInstance,nCmdShow)) return FALSE;
//打开视频设备
InitDevice();
//
DDrawInit();
//
InitParam();
MSG msg;
for(;;)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
6、消息函数:其中重要的是WM_PAINT消息的处理
//WinProc()
LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_PAINT:
if (DDOn)
{
HRESULT hRet;
RECT srect1,srect2,srect3,srect4;
RECT drect1,drect2,drect3,drect4;
srect1.left=0; srect1.top=0;srect1.right=351;srect1.bottom = 287;
srect2.left=352;srect2.top=0;srect2.right=703;srect2.bottom = 287;
srect3.left=0;srect3.top=288;srect3.right=351;srect3.bottom = 575;
srect4.left=352;srect4.top=288;srect4.right=703;srect4.bottom = 575;
drect1.left=0;drect1.top=0;drect1.right=drect1.left+320;drect1.bottom = drect1.top+240;
drect2.left=340;drect2.top=0;drect2.right=drect2.left+320;drect2.bottom = drect2.top+240;
drect3.left=0;drect3.top=260;drect3.right=drect3.left+320;drect3.bottom = drect3.top+240;
drect4.left=340;drect4.top=260;drect4.right=drect4.left+320;drect4.bottom = drect4.top+240;
for (int i=0;i<1;i++)
{
// Blit the bitmap
hRet = lpDDSOverlay->Blt( &drect4, lpDDSOffscreen1, &srect1,DDBLT_WAIT, NULL );
hRet = lpDDSOverlay->Blt( &drect1, lpDDSOffscreen1, &srect4,DDBLT_WAIT, NULL );
hRet = lpDDSOverlay->Blt( &drect2, lpDDSOffscreen1, &srect3,DDBLT_WAIT, NULL );
hRet = lpDDSOverlay->Blt( &drect3, lpDDSOffscreen1, &srect2,DDBLT_WAIT, NULL );
Sleep(40);
}
}
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
//Stop preview
ULONG bytesWritten;
m_overlayWin.Mode = OVERLAY_MODE | USING_BUFFER;
m_overlayWin.OpenClose = 0;
BOOL bRet = DeviceIoControl(hDevice,IOCTL_OVERLAY_WINDOW,&m_overlayWin,sizeof(m_overlayWin),
NULL,0,&bytesWritten,NULL);
DDrawFree();
if (hDevice) CloseHandle(hDevice);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,message,wParam,lParam);
}
7、问题:在上面的WM_PAINT消息的处理中,在从OffScreen表面向Overlay表面传送图象的时候,很明显和实际情况不符合
实际情况应该是OffScreen表面的srect1传送到drect4,srect4传送到drect1,srect2传送到drect3,srect3传送drect2,但显示效果是Blt没有起作用,并且就算你把循环只写如下代码:效果始终一样!
for (int i=0;i<1;i++)
{
// Blit the bitmap
hRet = lpDDSOverlay->Blt( &drect4, lpDDSOffscreen1, &srect1,
DDBLT_WAIT, NULL );
Sleep(40);
}
就是这个问题,也就是Offcreen表面向Overlay表面位块传送有问题,有兴趣的大侠朋友请帮我看看,谢谢!
有些代码因为篇幅的问题删掉了,QQ我,可以给大家发过来的
lon_pin@hotmail.com
QQ:17694215
[em1] [em2] [em3] [em4] [em5] [em8] [em10] [em11] [em24] [em23] [em24] [em24] [em24] [em20] [em20] [em19] [em18] [em18] |
|