200分请教Directdraw MFC 对话框上显示Yuv 视频问题

smilestone322 2011-06-10 05:52:17
请教一个问题,我用yuv overlay在MFC界面上显示视频时,能够显示正常,但是当我拖动MFC对话框时,视频跟不上对话框的拖动,拖动过程中,有一些拖离了我的picture控件,拖动结束后,又可以显示正常,但是当对话框脱离屏幕范围时,比如只有一半在屏幕里面,这次视频显示在原来的位置,而不是部分显示在对话框的picture控件里面,困扰我很久,另外还有一个问题,yuv overlay 怎是显示在最上层,上个东西都不能覆盖它。
现象如下:
这是我的另外一个100分的帖子:
http://topic.csdn.net/u/20110603/11/bb9c673b-fa05-42f8-8086-3b72b66788f8.html

(1)yuv overlay 时,显示在mfc的picture控件上,然后我拖动对话框,发现yuv overlay的表面有时会拖出picture控件,即图像出现晃动现象;

(2)还有一个问题就是当我将MFC对话框拖出屏幕范围,yuv overlay的表面还是在屏幕的范围内;即当MFC对话框部分拖出屏幕范围时,overlay的图像不会跟踪只显示部分图像;

(3)还有就是当切换到另一个页面的时候,此时对话框看不到,但是yuv overlay的表面还是显示在屏幕上;

我用的函数是UpdateOverlay函数;源码如下:
//初始化表面函数
HRESULT CDirectDrawSurface::DirectDrawInit(HWND hWnd, int width, int height)
{

HRESULT hr=S_FALSE;
hr=CoInitialize(0);
DDSURFACEDESC2 ddsd;

//store width, height
m_width = width;
m_height = height;

hr = CoCreateInstance(CLSID_DirectDraw,
NULL, CLSCTX_ALL, IID_IDirectDraw7, (LPVOID *)&m_lpDD);

if(!FAILED(hr))
hr = IDirectDraw7_Initialize(m_lpDD, NULL);
if (hr!=DD_OK)
{
printf("create directdraw object failed\n");
}

if(m_lpDD->SetCooperativeLevel(m_hWnd,DDSCL_NORMAL)!=DD_OK)
return S_FALSE;

memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
ddsd.dwSize = sizeof(DDSURFACEDESC2);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// The primary surface is not a page flipping surface this time
hr = m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL );

if (hr!=DD_OK)
{
printf("create directdraw surface failed\n");
}
else
{
DDCAPS capsDrv;
memset(&capsDrv,0,sizeof(capsDrv));
capsDrv.dwSize=sizeof(DDCAPS);
hr=m_lpDD-> GetCaps(&capsDrv,NULL);
if(hr==DD_OK && (capsDrv.dwCaps & DDCAPS_OVERLAY))
{ // determine Overlay support.
DDPIXELFORMAT PixelFormat[] = {
//{ sizeof(DDPIXELFORMAT), DDPF_FOURCC, FOURCC_YV12, 0, 0, 0, 0, 0 }, // YV12
//{ sizeof(DDPIXELFORMAT), DDPF_FOURCC, FOURCC_Y411, 0, 0, 0, 0, 0 }, // Y411
{ sizeof(DDPIXELFORMAT), DDPF_FOURCC, FOURCC_YUY2, 0, 0, 0, 0, 0 }, // YUY2
{ sizeof(DDPIXELFORMAT), DDPF_FOURCC, FOURCC_UYVY, 0, 0, 0, 0, 0 } // UYVY
};

int i, nPixelFormat=sizeof(PixelFormat)/sizeof(DDPIXELFORMAT);

//创建覆盖表面
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY|DDSCAPS_VIDEOMEMORY; // Overlay related APIs will fail without hardware support.
ddsd.dwWidth=1628;
ddsd.dwHeight=1236;
for(i=0;i <nPixelFormat;i++)
{
memcpy(&ddsd.ddpfPixelFormat,&PixelFormat[i],sizeof(DDPIXELFORMAT));

hr=m_lpDD-> CreateSurface(&ddsd,&m_lpDDSOverlay,NULL);
if(hr==DD_OK) {
char tmpBuf[256];
sprintf(tmpBuf, "创建第%d种OVERLAY表面成功 ! ",i);
::MessageBox(NULL,tmpBuf, "DirectDraw初始化 ",MB_ICONINFORMATION);
break;
}
}
}

}


if ((hr = m_lpDD->CreateClipper(0, &m_lpClipper, NULL)) != DD_OK ||
(hr = m_lpClipper->SetHWnd(0, hWnd) ) != DD_OK ||
(hr = m_lpDDSPrimary->SetClipper(m_lpClipper) ) != DD_OK)
{
if (m_lpDDSPrimary != NULL)
{
m_lpDDSPrimary->Release();
m_lpDDSPrimary = NULL;
}
m_hWnd = hWnd;
return DD_OK;
}

m_hWnd = hWnd;

return hr;
}

//UpdateOverlay更新刷新表面函数:
RECT PicRect,ScreenRect; //图像区域与屏幕显示区域;
HRESULT CDirectDrawSurface::DrawYuvToOverlaySurface(RECT ScreenRect,BYTE *YuvBuf,int width,int height)
{
BYTE *pSurf;
DDSURFACEDESC2 ddsd;
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
POINT p = {0, 0};

TRACE("lpitch%d\n",ddsd.lPitch);
GetClientRect(m_hWnd, &ScreenRect);
ClientToScreen(m_hWnd, &p);
OffsetRect(&ScreenRect, p.x, p.y);


if(FAILED(m_lpDDSOverlay->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL)))
return S_FALSE; //锁定DirectDraw表面;

pSurf=(LPBYTE)ddsd.lpSurface; //获得Overlay表面被锁区域左上角的地址;

if (pSurf)
{
int i;
for (i=0;i<height;i++)
{
memcpy(pSurf,YuvBuf,ddsd.dwWidth*2);
YuvBuf+=ddsd.dwWidth*2;
pSurf+=ddsd.lPitch;
}
}

//如何填充YUV2的数据
m_lpDDSOverlay->Unlock(NULL); //解锁对DirectDraw表面的锁定;

PicRect.bottom=1236;
PicRect.right=1628;
PicRect.left=0;
PicRect.top=0;

/*
GetClientRect(&ScreenRect); //获得屏幕绘图区域的客户坐标;
ClientToScreen((LPPOINT)&ScreenRect.left);
ClientToScreen((LPPOINT)&ScreenRect.right); //转换客户坐标为屏幕坐标;
*/

m_lpDDSOverlay->UpdateOverlay(&PicRect,m_lpDDSPrimary,&ScreenRect,DDOVER_SHOW,NULL); //实现图像更新 DDOVER_KEYDESTOVERRIDE

return DD_OK;
};

请路过的高手指点下;
...全文
445 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyp1003 2011-09-15
  • 打赏
  • 举报
回复
Yuv overlay 本来就是在最上一层的,无论你怎样切换页面都是这样,且一般只能有一个overlay,如果你要解决这个问题,必须采用离屏表面,呵呵!
smilestone322 2011-09-15
  • 打赏
  • 举报
回复
呵呵,继续顶下!
fandrom207 2011-08-22
  • 打赏
  • 举报
回复
我也遇到相同的问题。谁有解决方法啊
smilestone322 2011-06-13
  • 打赏
  • 举报
回复
不行,是有2个参数,一个是全屏,一个是窗口,我用的是窗口,所以用DDSCL_NORMAL 没错
smilestone322 2011-06-13
  • 打赏
  • 举报
回复
还没呢,明天去试一下你的方法,那个flag是不是设置一下就行
surepretty 2011-06-13
  • 打赏
  • 举报
回复
Device displayDevice = new Device();
displayDevice.SetCooperativeLevel(this.splitContainer1.Panel1, CooperativeLevelFlags.Normal| CooperativeLevelFlags.NoWindowChanges);


还没搞定???this.splitContainer1.Panel1这个是控件,CooperativeLevelFlags.Normal| CooperativeLevelFlags.NoWindowChanges这两个是mode,我这里是C#,你可以查一下MSDN。
smilestone322 2011-06-12
  • 打赏
  • 举报
回复
ddsd.dwFlags 吗,怎么设置,我想让它和picture控件绑定在一起
CyberLogix 2011-06-12
  • 打赏
  • 举报
回复
YUVoverlay默认是显示在最上面的,你可以设置写属性FLAG让他显示在指定的窗口里
「已注销」 2011-06-11
  • 打赏
  • 举报
回复
问题3可以拦截wm_activate消息,如果窗口不在最上层,就不要显示图像了。
其它两个问题我这里怎么没出现,我用的SetDIBitsToDevice
smilestone322 2011-06-11
  • 打赏
  • 举报
回复
分不够还可以继续加,呵呵
smilestone322 2011-06-11
  • 打赏
  • 举报
回复
继续顶下,希望有人能帮助我在directdraw下解决这个问题,因为我对D3D不熟悉,而且一些播放器也支持DirectDraw啊
「已注销」 2011-06-11
  • 打赏
  • 举报
回复
我的是rgb,没用overlay
smilestone322 2011-06-11
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 smilestone322 的回复:]
分不够还可以继续加,呵呵
[/Quote]

你可以贴部分代码吗,SetDIBitsToDevice是采用GDI进行显示的,可以传一个GetDc给它,所以picture控件就和要显示的图像绑定起来了。你是显示yuv还是显示RGB呢,用的是overlay吗
dengzikun 2011-06-10
  • 打赏
  • 举报
回复
directdraw运行时库对窗口消息处理有问题,可以在应用程序中响应
窗口消息,做视频裁剪,不过效果也不是很理想。
可以考虑用D3D做视频显示,D3D运行时库对窗口消息支持的比较好。

2,543

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧