关于在DDraw和D3D显示的视频上作图的问题

方法1,获得surface的DC,然后用GDI、GDI+作图。

用GDI、GDI+作图的好处是比较容易上手,且作图可以比较自由。

DDraw、D3D都可以获取surface的DC(一般是获得off screen surface的DC),从而可以在该DC上用GDI作图,但是,此混合作图的方式效率特别低;

实践了一下,D3D surface的GetDC、ReleaseDC方法要耗时5ms以上,可能在两种绘图框架之间要进行很多适配和转换。注:GetDC对surface的格式有要求,YUV420格式的surface是不支持GetDC的。

用DDraw显示yuv视频,显示前通过GetDC获得DDraw surface的DC,然后用AlphaBlend进行alpha混合,在我笔记本1366*768分辨率大小下,执行该操作需要20ms以上,

如果我用DIB显示视频,该操作耗时不到5ms;另一个实践是通过GetDIBits和SetDIBits来改变HDC的图像数据,用DIB显示视频时,该操作耗时不超过2ms,且能执行成功;

用DDraw和D3D显示视频时,则执行不成功,像素值未被改变,改用StretchDIBits设置像素值,执行能成功,但是耗时非常高,最大化窗口情况下需要耗时100ms以上。

所以混合作图万不得已不要使用,虽然D3D等api是硬件加速的,但是需要在系统和显示框架之间传输数据,这是很耗时的。

方法2,获得surface的数据指针,然后改变像素值。

此方法不灵活。且效率不高。

以D3D为例,获得surface的数据指针用LockRect方法,使用该方法要注意:

1,要想锁定后台缓冲,那么在CreateDevice时需要将显示参数D3DPRESENT_PARAMETERS的Flags指定为D3DPRESENTFLAG_LOCKABLE_BACKBUFFER,使用可锁定的后台缓冲,会降低性能。同时LockRect和UnlockRect操作都会比较耗时。

2,要想锁定off screen surface,要注意如果该表面在LockRect之前执行了StretchRect操作,那么在LockRect方法中使用D3DLOCK_DONOTWAIT可能会产生D3DERR_WASSTILLDRAWING,这是因为设备没能立即锁定该surface,要想阻塞的锁定,那么将LockRect方法的Flags参数置为0即可,但是此操作有可能比较耗时。

总而言之,这种方法在实时性要求高的环境下不推荐使用。


方法3,使用纹理方式显示视频,同时通过纹理混合来将额外的纹理叠加在视频上。

目前看来此方法是最优的。目前本人使用的正是此方法。要处理的就是叠加纹理的来源,一般来源文件。从文件加载纹理是比较耗时的。

猜你喜欢

转载自blog.csdn.net/zhushentian/article/details/74332523