游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2657|回复: 0

用DirecrDraw overlay 实现实时视频显示中的问题

[复制链接]

11

主题

21

帖子

21

积分

注册会员

Rank: 2

积分
21
发表于 2003-9-12 14:13:00 | 显示全部楼层 |阅读模式
还是先说以下我的实现原理原理吧:
    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]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2024-11-25 13:41

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表