VC+DirectShow对视频进行图片处理之六

本文探讨了GDI与D3D在画图效率上的区别,通过实际编程经验分享了如何有效利用D3DXSprite提高2D绘图性能,同时解决了DirectShow回调函数引发的问题,并讨论了软件开发中的界面设计与资源管理。
程序的效率和其他问题

  1. 性能

  在DS 封装类中我写了几个GDI画图函数,可以比较方便的显示图片,不过效率低下,我曾发现它的效能竟比D3D画 3D场景还差。这是GDI 的问题,大概它没有很好利用显卡而依赖CPU的缘故吧。所以我在使用 D3D 的时候顺便用上了 ID3DXSprite 接口,它是在没有 DirectDraw的情况下很好的2D 画图工具,而应用了DX 的特性使它效率很高,充分使用显卡加速,很容易做到旋转、缩放、透明等功能,效率很高。不过应注意一个问题:通常看到的D3D 初始化程序都是为得到最大的3D 效能,即使没干什么CPU占用率也会直上到100%,而播放视频文件一般都需要解码,CPU 都让D3D 占去后就没法流畅解码视频,所以应该这样创建D3D 设备,完成初始化:

m_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_MULTITHREADED,&d3dpp,&m_pd3dDevice)
  一定要加上一个D3DCREATE_MULTITHREADED,让D3D 解箍 CPU,D3D不忙的时候降至 0%,当然了,3D 效能会减掉一些,不过效果尚可。

  还有一个,我发现程序运行需要占很多内存,但最小化后再打开就只占原来的一半左右,十分想不通。

  2.程序错误的修正

  为了程序正确运行,还要解决另一件事。您还记得回调函数吗?就是它惹起了祸。回调函数带来了灵活性的同时也带来了灾难。到目前为止我发现了两点。一是不能在里面调用DirectShow 对象,例如在里面调用 IMediaPosition 来设置进度条,这样当按下“停止”时会发现 IMediaControl 的Stop 方法不能返回,我认为是递归调用所引起的,因此绝对不能这样做,无法在Filter内采取任何措施防止这种情况。

  第二点直接体现灵活性弱点。想想我需要在回调函数中干些什么,我需要调用函数设置D3D纹理吧,那我就要处理纹理在Filter还运作过程中发生参数改变或被释放的问题,在播放过程中打开新文件或关闭程序都有可能发生这种情况。打开新文件时我们会先释放旧的Filter Graph再重建,释放并创建新的纹理会在启动播放后才进行,因为要得到视频参数,所以有可能Filter已经运作了而使用的纹理还是旧的,引起访问错误。DirectShow 的Filter Chain 有自己的线程,调用IMediaControl 的Stop 并不能让它一下子停下来,突然关闭程序就有可能使纹理释放比真正结束播放早,因为我们不会在回调函数中管理纹理而在D3D类中进行管理,关闭时纹理会随D3D类的释放而释放。

  我刚解决问题的办法很稀奇古怪,也许任何一个大虾都反对,不过它工作的很好。定义一个BOOL变量,在打开文件时先把它设为FALSE,结束打开时再设为TRUE,并重载对话框的OnDestroy函数,在该函数中把BOOL变量设为FALSE,这样在回调函数开始处检查此变量,为FALSE时直接返回。后来发现把回调函数设为NULL也可,而且似乎更好。

  3.与其他实用程序相比

  其实微软为DirectShow新配备的VMR9可以无缝与D3D结合,更有很多强大的功能,绝非我写的Filter可比,不过我懒于学习使用它,自认为写Filter比学习它更容易。从VMR9可以自动提供纹理给D3D使用,我萌生一个想法:能不能在一个D3D中创建纹理给另一个D3D 使用呢?我要进行验证。

  最近得到一个叫做“CamTrack”的软件,它很厉害,自带的人脸跟踪功能自不必说,它还能自动侦测到摄像头的使用,在比Filter更低的层级就接收并处理了数据,并把处理后的数据作为摄像头数据传送下来!我惊呆了,好像要从摄像头的WDM 驱动模型去找突破口,但完全没有头绪。

  4.界面

  除了技术落后、结构混杂之外,我的程序还有很大的一个缺陷:界面丑陋,元素排列不合理。这是因为我不熟悉MFC,也不懂得如何设计界面造成的,所以您看到的我的程序是古板的win98 样式,用起来可能很不就手。我初三暑假开始接触编程,一直用了3年多VB6,鄙视VC,转到VC编程还是近大半年的事,虽已乐不知返却从没想过要努力学MFC,毕竟VC.net的net界面编写已不再依赖MFC了,它更像VB,更易用,只是程序载入到界面显示很慢,我用的VC.net2003 是这样。

  全文总结

  这一刻我期待已久,写点东西真的很苦。整个程序只用了简单的逻辑,但编码却不能说很短,进行试验更是花费了很多精力,真是“成如容易却艰辛”。

  在这次编写中我的体会良多,记得看过这样一句话“没写过一万行代码的项目是不会懂得软件工程的”,此时真的把它奉为真理了,想我这个程序才多大点儿,文件已有七八个,平时我看文件有几个的程序都感到头疼,更不敢想象上万行程序的管理,可能管理上花的精力比编码更多。在标准化工厂里,工人都被分工,他们可能不知道自己在干什么,只有管理人员才对一切了如指掌。如果生产的是软件,单会编码的程序员就只能做埋头的工人了,更高层次由不编码的管理人员掌握,事实也是这样。我还发现有时花在界面的时间比所谓的核心功能还多,正如为了控制发动机和轮子,汽车在控制方面要花费很多,而在舒适的驾驶环境和新潮的外型方面更要努力,因为必须要为人所用、易用、好用。现在回过头看所写的Filter,它的确是各种功能的基础,仅此而已,编码的比重并不大。总的说,我的感想是:现代软件开发应用的是现代工业生产模式,标准化、分工合作、流水线操作。当然,我的认识还很肤浅,请指正。 最让我苦恼的是 DirectShow 不支持 rm 文件,或者说 RealNetworks 不支持 DirectShow,毕竟 rm 的算法是保密的,这导致无法用我的程序欣赏很多美妙的影片,强烈希望大虾们用real sdk 写个 Filter 发布出来,让我等享用,我找不着real sdk。

  总算劳累后也有成果,总体效果没有受技术限制,再请看看几幅效果图,以结全文。程序路上,你我共勉。

 

 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值