播放网络摄像头采集到的视频流,今天遇到了一个问题,已经解决,所以贴上来做个记录,方便日后察看和同辈们互相学习。
问题描述:播放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例子相同。
... {
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, 320, 240);
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;
}