请教各位ddraw高手如何实现双缓冲绘制yuv数据
现在有经过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;
}
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;
}
...全文
相关推荐
yuv ddraw Simple application
创建Surface:为YUV数据创建DirectDraw Surface对象,通常会创建两个表面,一个用于前台显示,一个用于后台缓冲,以实现双缓冲。3.
DirectDraw显示demo
创建双缓冲表面:双缓冲技术可以避免闪烁,通过在后台缓冲区绘制图像,然后交换缓冲区来实现平滑的画面更新。3. 加载YUV420数据:读取YUV文件或接收网络流,并将其解码为适当的格式。4.
DIRECTDRAW源码
**双缓冲技术**:这是避免屏幕闪烁和图像撕裂的关键。通过在内存中创建一个后台缓冲区,开发者可以在缓冲区上绘制图像,完成后一次性将整个缓冲区内容显示到屏幕上,从而避免了连续刷新导致的闪烁。2.
directdraw中文手册
**DirectDraw剪辑器**:允许开发者控制图形的绘制区域,实现裁剪或遮罩效果。
Direct Draw 中文编程手册
创建背面缓冲:为实现双缓冲,你需要创建一个与主表面同样大小的背面缓冲。5. 绘制操作:在背面缓冲上进行所有绘图操作,完成后交换主表面和背面缓冲。6.


多媒体/流媒体开发
