本来我并非多媒体软件工程师,但因为项目需要一时也找不到其他人,只好自己顶上去,到昨天为止,项目基本上算是功能都实现了。我个人的习惯是每经历过一次开发,就要总结一次,主要是技术总结。
参考资料都来自于陆老师的《Directshow编程指南》和google搜索。
1. Directshow开发环境的搭建
对于VS2005,VS2003及VC6的开发环境,必须具备
DirectX SDK : 包含了ddraw.h和一些runtime)
dxsdk extras : 包含了strmiids.lib,quartz.lib和一些视音频的头文件,包括DVD的定义,复合视频的定义等等
然后你还需要一个BaseClasses,提供strmbase.lib(调试版本为strmbasd.lib)
对于VS2008,安装时自动包含了Microsoft SDK里面包含了ddraw.h及extras里面的一些内容,只需要BaseClasses即可,我把BaseClasses打个包,放在这里,方便大家使用。
2. DirectShow程序的部署
我用的VS2008开发,因此在部署到其他未安装开发环境的机器上,必须要先下载vcredist_x86.exe(我的是x86平台)。
在VS2008中选择release版本进行生成,此处千万要注意DirectShow应用程序一定要引用strmbase.lib,而不是strmbasd.lib,因为strmbasd.lib必然依赖于调试库,而vcredist_x86.exe则不带调试库支持
此外为了获取strmbase.lib,你必须要用和应用程序相同的VS版本来编译BaseClasses。
我犯的第一个错误是:用VS2008编译BaseClasses生成strmbase.lib和strmbasd.lib,用VS2005编译我的应用程序得到.exe,结果部署到其他机器时出错
我犯的第二个错误是:用VS2008编译BaseClasses生成strmbase.lib和strmbasd.lib,用VS2008编译我的应用程序得到.exe,但是引用了strmbasd.lib,结果部署到其他机器时出错
3. 关于DirectShow的Pin查找
一般的DirectShow程序开发,都要用到GraphEdit这个程序,将一系列的filter拖进工作区,然后一个一个连起来,形成一个完整的从输入到输出的数据流链条。
在使用GraphEdit验证你的思路正确之后,你就得在程序中来逐渐实现这个链条。其中我总结几点经验:
1) 在GraphEdit中实现的连接图一定能用程序实现
2)在GraphEdit中使用智能链接生成的图可能不是最简单的链接
3)在GraphEdit中,一个filter引脚的名字是”ABC“,如果你在程序中创建一个Filter,然后调用FindPin函数去找这个Pin不一定能找得到,更为奇特的是,你用EnumPins方法去枚举这个Filter上的Pins,却又能真正找到具有这个名字的Pin。我在CSDN上发现很多人也都碰到过这个问题。这个应该是Filter的编写者不负责任的一种做法。后来我偶然之间发现可以通过序号去找到Pin。代码如下:
Line1是根据名称去查找,如果失败,则可采用序号去查找。这个序号是字符串,可以是0, 1, 2, 3等,你可以逐个尝试,直到找到你要的Pin。
4) 在GraphEdit中,如果两个Filter之间的Pin无法连接,你别以为你的思路走不通了。这个时候你应该仔细查看Pin的Properties,注意是Pin的属性,不是Filter的属性。在Pin的属性中修改一下输出视频的格式,压缩方式,分辨率,说不定就能连上了。
在程序中,我们通过IAMStreamConfig这个接口来进行输出流格式的设置。代码请参考陆老师的书。
5) 常用的几种参数设置和控制接口:
IAMStreamConfig: 设置某个Caputre型的Filter的音视频输出格式
IAMCrossbar: 设置电视卡的输入源,比如可以来自电视信号,SVideo或者复合AV等
IVideoWindow: 设置视频显示的窗口,窗口大小,显示风格等
IMediaControl: 控制媒体的播放,停止,暂停等
IAMAudioInputMixer: 选择音频采集数据源,可以有CD,麦克风,线路输入,立体声等输入
6) 一般电视卡都是带有音频输出的,你直接插上耳机就可以听得到声音。可有的时候我们想对这些声音做一些处理,比如通过另外一个通道输出到其它设备,或者是写入到文件等等。在我的项目中,就需要把音频信号通过SDI通道进行输出。此时我们必须先把音频信号采集进来,然后再输出。一般的声卡都能做采集工作,只要带有Line In接口或者麦克风接口都可以。采集的第一步是把电视卡的音频输出用硬线连接到声卡的Line In,然后在程序中创建声卡采集的Filter,在Filter上获得IAMAudioInputMixer接口,并用该接口选择音频输入源为Line In,然后把Capture端连接到其他的音频输入通道。一般不采用Mic作为采集接口,因为Mic阻抗大,噪声很高,Line In相对而言质量更加好一点。
选择音频输入源的代码如下:
用DirectShow编程,最大的困惑就是不知道什么功能通过什么接口来实现,这个需要去搜索或者去查资料书。等有一定经验之后,难点就转向了视频格式的匹配、各种特定硬件编写的filter的使用,如果越学越深入,那么难点就转向了如何写健壮的各种filter等。
我无意在DirectShow的路上走下去,只是依循自己的习惯,简单地总结了下这一小段开发经历,如果能给大家提供帮助,那就是意外之喜了。
hyruur@163.com