心情不好,突然想写博客了,嘿嘿!其实这一个程序是差不多一年前实现的,那时正好着手一个项目,同时后来也因为这一个项目买了一款多普达手机,呵呵!
    这一个项目大概实现这么一个功能:电脑(服务器端)安装一个用于抓取摄像头与麦克风的数据,Windows Mobile手机客户端通过无线连接到电脑,读取这一些数据然后显示在手机界面上面,并能听到声音。其实这一个项目是关于远程教学的,简单的说是把客户端移到手机平台上面。其实还有一个功能是用手机实时看到电脑的桌面界面,这一个这里就略过了。
    我大概的思路是想用Directshow的技术,电脑的服务器端通过它来抓取到视音视频的数据,直接传到手机上面。然后手机也可以通过Directshow的技术再把它显示出来。对于手机客户端来说,它主要的工作只是新开发出一个用于网络播放的Source Filter便可以了。
    如果这一个程序想在电脑上面实现的话,相对是比较简单的。首先推荐一本书《DirectShow开发指南》,这本书的源码里面有这一个源码叫 AVChat它可以实现服务器端与客户端的视频聊天。针对这一个项目来说,其实是在那一个源码的基础上,把服务器端与客户端的功能各实现一半,然后再增加上客户端可以有多个连接就可以了。服务器端抓取视音频,客户端播放视音频,靠socket来通信。只是把源码改动一些,删一些该删的便可以了,似乎都没有什么可以讲的。但若你拿到手机上编译的话,你便会发现跟本编译不过。这就是最大的问题。
    对于window mobile上的directshow的开发与pc平台上的directshow开发有着很多细节上的不同(思想都是一样的)。首先在pc机上,你得安装一个SDK。然后你还得自己编译生成strmbasd.lib/strmbase.lib(若在vs2005上会有一些小错误,难免,改下就好了)。但若在window mobile上,你会发现,它提供了strmbase.lib,还有相应的一些头文件,你根本不用装SDK。但若你是作简单的一些directshow的开发,你可能不会发现有什么问题(若你只有strmbase.lib,还是有一个问题,就是好像不可以debug,这一个不记得清楚了),但若你得自己开发filter,你源码可以编译的情况下,你会出现几个LINK21的错误:
     error LNK2019: unresolved external symbol "public: __cdecl CBaseFilter::CBaseFilter(wchar_t const *,struct IUnknown *,class CCritSec *,struct _GUID const &)" (??0CBaseFilter@@QAA@PB_WPAUIUnknown@@PAVCCritSec@@ABU_GUID@@@Z)
    error LNK2001: unresolved external symbol "public: __cdecl CBaseFilter::CBaseFilter(wchar_t const *,struct IUnknown *,class CCritSec *,struct _GUID const &)" (??0CBaseFilter@@QAA@PB_WPAUIUnknown@@PAVCCritSec@@ABU_GUID@@@Z)
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::FindPin(wchar_t const *,struct IPin * *)" (?FindPin@CBaseFilter@@UAAJPB_WPAPAUIPin@@@Z)
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::FindPin(wchar_t const *,struct IPin * *)" (?
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::JoinFilterGraph(struct IFilterGraph *,wchar_t const *)" (?
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::JoinFilterGraph(struct IFilterGraph *,wchar_t const *)"
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::QueryVendorInfo(wchar_t * *)" (?
    error LNK2001: unresolved external symbol "public: virtual long __cdecl CBaseFilter::QueryVendorInfo(wchar_t * *)" ( ?QueryVendorInfo@CBaseFilter@@UAAJPAPA_W@Z)
    刚开始发现这一个心情还很郁闷,但后来静下心来分析,很简单。是因为在包含的文件里面有CBaseFilter的定义,所以可以编译通过,但在strmbase.lib里面,却没有它的实现,所以在链接的时候,发生了link21的错误。
    对于上面这一个问题怎么办呢?我在通过上网疯狂找的时候,在绝望的时候,终于找到了方法。就是通过源码, 自己编绎生成一对strmbasd.lib/strmbase.lib(注意在windows mobile里面是wchar)。而这一个源码,发布在***\WINCE500\PUBLIC\DIRECTX\SDK\SAMPLES\DSHOW\BASECLASSES(在安装了Windows CE Platform Builder 5.0之后便可以得到这一个源码)。也许还有人想直接到过PC上面的SKD来编译,我觉得应该很难,因为它是win32平台上的。如果真的可以,也应该得改很多个地方。所以直接把platform builder 里面的源码baseclasses重新编绎才是最好的方法。若怕影响到platform builder,你可以复制出上面那一个路径的代码进行编绎,注意一定得把CBaseFilter这一个类的实现加上。 然后再引用自己的strmbasd.lib/strmbase.lib便可以了。哈哈!
    但若你都把代码改好了,并且也编译成功,你会发现你手机可以实时播放电脑的摄像头了,但却还听不到声音,那是 因为在window mobile里的Audio Renderer只能用CLSID_AudioRender,而不是CLSID_DSoundRender(AVChat源码里面用的是这一个)。把它改成CLSID_AudioRender这一个便可以了
    这只是一个大概的思路与讲解,其实我现在也是事后诸葛亮,很多具体的麻烦的编译问题我都不记得了。如在你编译出strmbasd.lib后,你在debug模式下也还有link21的错误,这一些都是编绎过程中的细节问题,以后我会一一道来!希望这可以对某一些朋友有用...