最近有一个C++视频开发项目,写个心得稍稍记录一下,以免以后忘记了。本文虽然是原创,但是整合了网上所有遇见的情况做了一个中和以及个人的一些经历写了这篇,请阅读者多多指教。
1.简介:
DirectShow是一个windows平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。它支持多种多样的媒体文件格式,包括ASF、MPEG、AVI、MP3和WAV文件,同时支持使用WDM驱动或早期的VFW驱动来进行多媒体流的采集。DirectShow整合了其它的DirectX技术,能自动地侦测并使用可利用的音视频硬件加速,也能支持没有硬件加速的系统。
2.环境安装:
因为我系统比较多,所以我在三个系统上做了个简单的配置,我每套系统的配置都写下来,以方便读者自己参考:
1.Windows XP x32下:(中文)
OS版本:Windows XP SP3 Professional
Windows SDK版本:Windows XP SP2 FULL版
DirectX SDK:DirectX 9.0 SDK Update - (Summer 2004)
2.Windows Vista x64:(英文)
OS版本:Windows Vista x64 SP1 Ultimate
Windows SDK版本:Windows 2003 SP1 RTM版
DirectX SDK:DirectX 9.0 SDK Update - (Summer 2004)
3.Windows Server 2008:(英文)
OS版本:Windows Server 2008 Enterprise Edition x32:
Windows SDK版本:Windows SDK for Windows 2008 and .NET Framework 3.5 SP1
DirectX SDK:DirectX 9.0 SDK Update - (Summer 2004)
注:这里选择DirectX 9.0 SDK Update - (Summer 2004)的版本是因为这个版本是DirectX SDK中最后一个整合了DirectShow的版本,我个人觉得这个版本配置稍稍简单,其他版本我没有尝试过,应该问题不会太大。
还有,开发平台都是VC6.0,这个平台我测试过,在Windows XP,Windows Vista,Windows Server 2008以及Windows 7下边都可以安装,只是有一点需要注意,在下边三个系统安装的时候需要注意一点:
Windows Vista,Windows 2008,Windows 7
在安装VC6.0的时候需要让你选择需要安装的组件,在选择安装组件的时候,有一个选项是“企业工具”
(英文“Enterprise Toos”),选中过后点击右边的“修改选项”或者“Change Option”,里面有一个项是:Visual Studio Analyzer,去掉这个选项就可以在这三个平台安装VC6.0了。当然一般不会有人在这三个系统安装VC6.0,但对于怀念这个平台的人可以试试,嘿嘿,仅作为参考。
3.编译BaseClasses:
单独提取编译BaseClasses的章节,希望对所有编译BaseClasses的兄弟有帮助。
1)首先打开VC6.0,新建一个项目,项目类型选择Win32 Static Library,这里需要说明一下,如果要使用VC6.0的来编译BaseClasses,因为该版本下边没有VC6.0的工程文件,所以最好自己创建工程文件,来完成编译过程,创建一个Win32 Static Library项目;
2)设置相关参数:
这里应该是不需要,为了保证编译好的Lib的名字和网上大部分配置相同,点击Project->Settings,在Library标签里面设置相关的输出,Output file name:默认是项目名称,本人是这样修改的:
Debug版本:Debug\strmbasd.lib
Release版本:Release\strmbase.lib
然后就可以编译了!!兴奋中,期待的版本吻合的baseclasses的lib快出来了。
3)错误信息:
别高兴太早,这里会有一个编译错误,错误信息如下:
wxutil.cpp(277) : error C2065: 'COINIT_DISABLE_OLE1DDE' : undeclared identifier
这个问题我搜了网上很多地方,后来发现了一个替代解决方案,变量未定义,但是有办法解决,找到源代码wxutil.cpp的277行:
hr = (*pCoInitializeEx)(0,COINIT_DISABLE_OLE1DDE );
将变量COINIT_DISABLE_OLE1DDE改成整数4;
hr = (*pCoInitializeEx)(0,4);
这样就可以编译通过了,在编译的时候记得编译两个版本,版本的切换在菜单Build->Set Active Configuration里面可以切换激活版本,就可以编译两个不同的版本到项目对应的目录下。然后把编译好的两个文件夹Debug和Release放到对应的BaseClasses文件夹下边:
DirectX SDK安装目录\Samples\C++\DirectShow\BaseClasses下边就可以了。
4.配置DirectShow针对所有项目的环境:
因为有些头文件是Windows SDK下边的,所以建议最好装一个Windows SDK,否则缺少头文件会在Link过程报错。
打开Tools->Option…->Directories里面:
首先选择Include files
DirectX SDK安装目录\Include
DirectX SDK安装目录\Samples\C++\Common
DirectX SDK安装目录\Samples\C++\DirectShow\BaseClasses
Windows SDK安装目录\Include
VS6.0 安装目录\VC98\INCLUDE
VS6.0 安装目录\VC98\MFC\INCLUDE
VS6.0 安装目录\VC98\ALT\INCLUDE
然后选择Library files
DirectX SDK安装目录\Lib
DirectX SDK安装目录\Samples\C++\DirectShow\BaseClasses\Debug
DirectX SDK安装目录\Samples\C++\DirectShow\BaseClasses\Release
Windows SDK 安装目录\LIB
VS6.0 安装目录\VC98\LIB
VS6.0 安装目录\VC98\MFC\LIB
网上很多文章都写了这段,但是我不清楚Debug版本和Release版本为什么都要放上去,索性就和他们一样放了两个版本的目录。
注:顺序不能错,蓝色部分是原来就有的,红色是添加的,Include中第二项Common那个好像可以不需要,我只是一个个例,做参考,所以写上去。
5.项目设置
创建一个项目过后,首先要引入项目所需要的库文件:
选择Project->Settings->Link标签,然后在选项Object/library modules:中输入以下的几个Lib
Debug:strmbasd.lib strmiids.lib quartz.lib
Release:strmbase.lib strmiids.lib quartz.lib
注:网上参考资料如果要引用头文件streams.h才需要BaseClasses相关内容,如果不引用不需要前面两个库,我没有验证过,而且如果引入头文件streams.h,还需要另外两个库uuid.lib和winmm.lib,我的基本配置:strmbasd.lib strmiids.lib quartz.lib uuid.lib winmm.lib几个库文件
然后随便找个例子试试,我使用的例子是一个采集摄像头视频数据的例子,如果编译通过可以运行就证明环境没有问题。
6.遇到的问题
1)winnt.h(222) : error C2146: syntax error : missing ';' before identifier 'PVOID64'
2)error C4430: missing type specifier - int assumed. Note: C++ does not support
default-int:
3)error C2065: 'Count' : undeclared identifier
这三个问题是在VS2005中编译的时候遇到的,这个参考BLOG:
http://hi.baidu.com/jsufcz/blog/item/f2bfb18f9f2bddfc503d92ee.html
第一类问题的解决:project->BaseClasses properties->configuration->C/C++ -> General-
>Additional Include Directories里面的内容(.,..\..\..\..\include)删掉,重新编译,
PVOID64的错误消失,原因如下:
POINTER_64 是一个宏,在64位编译下起作用,它包含在SDK目录下的BASETSD.H中(Microsoft Visual Studio 8\VC\PlatformSDK\Include\basetsd.h(23):#define POINTER_64 __ptr64),但
DXSDK自己也带了一个basetsd.h,里面没有定义POINTER_64,从而导致出错,只需要改变include
files的优先级即可。。当然,也可以改写winnt.h中的代码,将
typedef void *PVOID;
typedef void * POINTER_64 PVOID64;
改成
typedef void *PVOID;
typedef void * POINTER_64;
typedef void * PVOID64;
第二类问题的解决:错误发生在:operator=(LONG);函数定义中,这是因为在VC6中,如果没有显示的指定返回值类型,编译器将其视为默认整形;但是vs2005不支持默认整形,解决这个问题不能修改每个没有显示指示返回值类型的函数地方,可以用wd4430来解决;具体的在工程选项中的c++/Command Line中添加/wd4430即可。
第三个错误发生在for循环中,vc6中for循环中定义的变量相当于在for外面定义,可以在for之外地方使用;但是vs2005for循环中定义变量相当于域{}变量,只能在for循环中使用。要解决这个问题,可以通过修改vs2005的工程选项:”Project Option”——“ C++ ”——“Language”——“Force Comformance in For Loop Scrope” 设置为No即可。完成上面的设置,BaseClass工程基本可以编译通过了。
4)wxutil.cpp(277) : error C2065: 'COINIT_DISABLE_OLE1DDE' : undeclared identifier,
此问题见上边的解决方案,是使用VC6.0在编译BaseClasses的时候遇到的错误。
本人在配置过程是以AVChat例子来进行的环境测试:
5)uuid.lib(objidl_i.obj) : fatal error LNK1103: debugging information corrupt; recompile module
这个问题是因为两个uuid.lib的冲突
解决:
把WindowsSDK的uuid.lib移除并备份,注:不要移错了,DirectXSDK下的uuid.lib不要移除,否则编译又会有错,移除或者重命名uuid.lib,改掉其后缀名,反正使得uuid.lib文件不在Windows SDK下边就可以了。
6)注:这是警告信息,不是错误:
LINK : warning LNK4098: defaultlib "LIBCD" conflicts with use of other libs; use /NODEFAULTLIB:library
总结一下,消除这种警告信息就在同样的位置:
选择Project->Settings->Link标签,下拉选择Input在ignore libraries中加上报警告的lib名称。
7)strmif.h(1018) : error C2146: syntax error : missing ';' before identifier 'HSEMAPHORE'
此问题比较常见,此问题是Include配置的时候的顺序问题,如果把Windows SDK的顺序配置到了前边那么这个问题就会存在,如果顺序严格按照上边的配置顺序来,此问题就有可能没有了,这个问题会导致编译通不过,是一个很常见的问题。
8)error LNK2001: unresolved external symbol _CLSID_FilterGraph
此问题是因为链接下边缺少库文件:strmiids.lib和quartz.lib,这个问题追溯到上边引入头文件streams.h的时候没有添加此库就可能出现此问题。
9)error LNK2001: unresolved external symbol "class ATL::CAtlBaseModule ATL::_AtlBaseModule" (?_AtlBaseModule@ATL@@3VCAtlBaseModule@1@A)
此问题是因为头文件#include <initguid.h>过后,缺少了包atls.lib,把atls.lib包引入就应该可以编译通过。
另编译时出现了DWORD_PTR或者其他什么类型未定义之类的错误,是因为微软把BASETSD.H从DirectX SDK发行包里拿掉了,这个文件在Platform SDK里有,在VC的Include路径中把Platform SDK的include路径提到最前面就可以了。Platform SDK,最后一个支持VC6的Platform SDK是February 2003 Edition。
7.总结:
此篇为本人在配置DirectShow里面的全过程,希望对大家有帮助,里面的错误,有些错误是我自己碰到的,有些错误是我自己碰到的,有些错误是在别人BLOG里面看到了过后做了个试验。如果还有些什么问题或者其他错误的话希望大家发我邮件:[email protected]