请教各位ddraw高手如何实现双缓冲绘制yuv数据

coloriy 2011-04-07 10:17:41
现在有经过ffmpeg解码后的yuv图像数据,目前实现了基于copy模式的ddraw surface绘制,但是感觉效率不高,请教哪位高手:
1)如何使用ddraw实现双缓冲绘制?
2)如何实现ddraw绘制yuv420数据高效绘制,是否双缓冲能够提高效率。
3)如果您有效率较高的绘制yuv数据的ddraw代码,请附在下面,谢谢了。

我目前的代码实现:
附代码:
//------------------------------------------------------------------------
/**
使用directshow方式绘制图像
\param pAVFrame 解码后图像帧数据
\return status 状态码
*/
//------------------------------------------------------------------------
VxInt32 CDisplay::ddshow_draw(int imgWidth, int imgHeight, AVFrame* pAVFrame)
{
VxInt32 status = LIVE_OK;

LPBYTE PtrY = (unsigned char *)pAVFrame->data[0];
LPBYTE PtrU = (unsigned char *)pAVFrame->data[1];
LPBYTE PtrV = (unsigned char *)pAVFrame->data[2];

int ddRval = 0;
do
{
ddRval = m_lpDDSOffScr->Lock(NULL, &m_ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
if ( DDERR_SURFACELOST == ddRval)
{
m_lpDDSOffScr->Restore();
ddRval = m_lpDDSOffScr->Lock(NULL, &m_ddsd, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL);
}
} while(ddRval == DDERR_WASSTILLDRAWING);
if(ddRval != DD_OK)
{
DLL_TRACE(__FILE__, __LINE__, "m_lpDDSOffScr->Lock failed ddRval = %d", ddRval);
return LIVE_FAILED;
}

LPBYTE lpSurf = (LPBYTE)m_ddsd.lpSurface;
if(lpSurf)
{
int i = 0;
for (i = 0; i < imgHeight; i++)
{
memcpy(lpSurf, PtrY, imgWidth);
PtrY += pAVFrame->linesize[0];
lpSurf += m_ddsd.lPitch;
}

for (i = 0; i < imgHeight/2; i++)
{
memcpy(lpSurf, PtrV, imgWidth/2);
PtrV += pAVFrame->linesize[1];
lpSurf += m_ddsd.lPitch/2;
}
for (i = 0; i < imgHeight/2; i++)
{
memcpy(lpSurf, PtrU, imgWidth/2);
PtrU += pAVFrame->linesize[2];
lpSurf += m_ddsd.lPitch/2;
}
}
m_lpDDSOffScr->Unlock(NULL);

DDBLTFX ddbltfx;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwROP = SRCCOPY;

RECT rect;
status = this->GetShowRect(rect);
if (ISFAILED(status))
{
DLL_TRACE(__FILE__, __LINE__, "CDisplay::ddshow_draw GetShowRect failed = %d !!!!!", status);
return status;
}

DWORD dret = m_lpDDSPrimary->Blt(&rect, m_lpDDSOffScr, NULL, DDBLT_ROP, &ddbltfx);
if ( DDERR_SURFACELOST == dret)
{
m_lpDDSPrimary->Restore();
DLL_TRACE(__FILE__, __LINE__, "CDisplay::ddshow_draw m_lpDDSPrimary Restore ");
}

// DLL_TRACE(__FILE__, __LINE__, "CDisplay::ddshow_draw dret=%d !!!!!", dret);
return status;
}


...全文
227 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
LiuYinChina 2011-04-15
  • 打赏
  • 举报
回复
我的方法和你的一样,
http://blog.csdn.net/RobertBaker/archive/2010/03/15/5380946.aspx
我不知道你说的效率不高是什么意思,CPU 很高?还是说想要比 copy 更快的办法?
coloriy 2011-04-15
  • 打赏
  • 举报
回复
请问楼上高手,您是如何使用ddraw显示yv12的,能不能贴段代码参考一下,不甚感激。
我把我的ddraw显示yv12的代码附上了,希望对别人有所帮助,但是觉得不是最优,楼上高手能贴一段您的代码吗,谢谢
coloriy 2011-04-15
  • 打赏
  • 举报
回复
我觉得是否CoreAVCDecoder.ax效率高于ffmpeg还是怎么回事,不得而知,不知道为什么人家接收rtsp视频流的效率高。请问楼上是否能给点提示。
coloriy 2011-04-15
  • 打赏
  • 举报
回复
coloriy 2011-04-15
  • 打赏
  • 举报
回复
copy效率是否低,这个小弟不知道,我觉得是否还有更高的效率,我把参数设置为
DWORD dret = m_lpDDSPrimary->Blt(&rect, m_lpDDSOffScr, NULL, DDBLT_WAIT, NULL);
发现效率似乎高点,但仍然有丢帧现象,
我使用live555接收,然后ffmpeg解码显示,directshow绘制,vfw保存avi,发现如果仅仅使用live555接收vfw保存,同一台笔记本上丢帧效率不明显,偶尔丢一帧,如果添加ffmpeg解码live555+ffmpeg解码,和保存则发现保存的avi文件出现比直接保存丢帧现象较为明显,如果再加上ddshow,则丢帧现象更加明显,据说ffmpeg解码效率提升优化空间较小,所以,我猜想是否应该在ddshow上显示部分优化,所以由原来的
DWORD dret = m_lpDDSPrimary->Blt(&rect, m_lpDDSOffScr, NULL, DDBLT_ROP, &ddbltfx);
copy模式,修改为DDBLT_WAIT等待绘制方式,觉得应该能提升一点,但是似乎效果不明显,有人说d3d能够提升显示效率,而且我在使用别的厂家接收rtsp视频流,然后解码显示,同一台笔记本上,他们的效率明显高,看他们的动态库,是基于media的filter的,解码器似乎也是ff的,渲染不知道是什么,这些是他们厂家的文件:

LiuYinChina 2011-04-12
  • 打赏
  • 举报
回复
我的程序上16路预览(DDraw->yv12),16路解码264显示(DDraw->yv12),16路Jpeg 显示(GDI),都行的
怀疑可能不是 DDraw 问题。
coloriy 2011-04-11
  • 打赏
  • 举报
回复
请问1楼高手,有没有相关示例,我参考一下,新手对这块不熟,谢谢。
CyberLogix 2011-04-07
  • 打赏
  • 举报
回复
双缓冲绘制不已经能提高效率,你可以考虑使用D3DAPI

2,543

社区成员

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

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