记下一个修正的bug——关于GDI在不同模式下的绘图

播放网络摄像头采集到的视频流,今天遇到了一个问题,已经解决,所以贴上来做个记录,方便日后察看和同辈们互相学习。

问题描述:播放video frame采用DDraw和GDI混合的方式。当DDraw不能成功使用时,改换成GDI绘图。但是如果有播放器(MideaPlayer 等)全屏播放时,因为其改变了显示模式,可能也换成了独占模式使用,所以此时DDraw是不能创建起来的,程序就自动采用GDI来进行绘图了。但问题出现了,当播放推出全屏时,摄像头video frame的播放色度大概只有256色或者更低,看效果是肯定没有256色的。只有重新启动播放video frame才可以。

使用混合方式的原因:程序中同时有采用mircosoft mirror driver进行屏幕录像的模块,当mirror driver 起作用时,DDraw就失去了硬件操作能力或者说硬件加速能力,检测到的display memory大小都是0,所以在mirror driver作用时自动切换到GDI绘图方式。但我没想到媒体播放器(其实还有其他很多的程序都会)全屏时剥夺了程序对显卡的控制权,这时同样会导致DDraw不能使用。

解决办法:在每次Paint的时候创建Device和MemoryDevice,然后销毁。本来我是在初始化的时候创建一个Device和MemoryDevice,然后取得数据时将它Strech进MemoryDevice里面,最后Paint时将MemoryDevice  Blt 到Device里面,这样就导致Device的能力不能随状态的变化而改变了。采用每次Paint创建和销毁的方法就消除了这个问题。其实在Msdn的介绍例子中也是提倡这种做法的,或许本来就该这么做,我想着一次创建一次销毁应该更省CPU消耗,看来是多此一举了。

Code:代码很简单,基本上与MSDN例子相同。

 

BOOL CDxDraw::GDIBltSingle(RECT  * srcRect, RECT  * destRect)
{
    INT destw 
= destRect->right - destRect->left;
    INT desth 
= destRect->bottom - destRect->top;
    INT srcw 
= srcRect->right - srcRect->left;
    INT srch 
= srcRect->bottom - srcRect->top;
    
//get the window DC
    m_hParentDC = ::GetWindowDC(m_hParent);
    
//create a memory DC
    m_hDCMem = CreateCompatibleDC(m_hParentDC);
    
if(NULL == m_hDCMem)
    
{
        
return FALSE;
    }

    
//the bmp which will be draw
    m_hBmp = CreateCompatibleBitmap(m_hParentDC, 320240);
    
if(NULL == m_hBmp)
    
{
        
return FALSE;
    }

    
//save the default bmp in the DCMem.
    m_hOldBmp = (HBITMAP)SelectObject(m_hDCMem, m_hBmp);
    
if (!m_hParentDC || !m_hDCMem)
    
{
        CM_ERROR_TRACE(
"CDxRGBVideoRender::GDIBltSingle, the DC is no exist.");
        
return FALSE;
    }

    SetStretchBltMode(m_hDCMem, COLORONCOLOR);
    
if (m_RgbData)
    
{
        StretchDIBits(m_hDCMem, 
0,0,
            m_bi.bmiHeader.biWidth,m_bi.bmiHeader.biHeight,
0,0,
            m_bi.bmiHeader.biWidth,m_bi.bmiHeader.biHeight,
            m_RgbData, 
&m_bi, DIB_RGB_COLORS, SRCCOPY);
    }


//     BitBlt( m_hParentDC, 0, 0, width, height, 
//             m_hDCMem, 0, 0, SRCCOPY);
    StretchBlt(
        m_hParentDC,        
// handle to destination DC
        0,            // x-coord of destination upper-left corner
        0,            // y-coord of destination upper-left corner
        destw,            // width of destination rectangle
        desth,            // height of destination rectangle
        m_hDCMem,            // handle to source DC
        0,            // x-coord of source upper-left corner
        0,            // y-coord of source upper-left corner
        srcw,            // width of source rectangle
        srch,            // height of source rectangle
        SRCCOPY            // raster operation code
        );
    ReleaseGDI();
//Release the Device
    return TRUE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值