如何在Pocket PC 2005上通过DirectShow直接播放mp3?
我这里所说的“直接播放”是指不借助任何其它应用程序(比如Windows Media Player)或第三方插件,而直接利用PPC2005内置的解码器和Filter进行播放。
首先我在PC上(Windows2000系统)做实验,通过RenderFile接口,比如:
pGraphBuilder-> RenderFile(L "c:\\1.mp3 ", NULL);
可以正常播放。然后枚举该Graph中的所有Filter,发现系统自动帮我加载了3个Filter:
第1个是MPEG1 Stream Splitter;
第2个是MPEG1 Layer-3 Decoder;(我不知道这个mp3解码器是系统内置的还是由于我装了mp3播放器)
第3个是Default DirectSound;
或者通过Render接口半自动构建Graph,比如:
IBaseFilter *pSourceFilter;
pGraphBuilder-> AddSourceFilter(L "c:\\1.mp3 ", L "Source Filter ", &pSourceFilter);
通过枚举pSourceFilter的Pin,得到它的输出Pin--> poutPin;
然后通过查看注册表中MPEG1 Layer-3 Decoder对应的GUID,自己创建mp3解码器的Filter,并加入Graph中,再Render SourceFilter的输出Pin:
pGraphBuilder-> Render(poutPin);
也可以正常播放。然后枚举该Graph中的所有Filter,发现除了上面提到的3个Filter,又多了一个我加入的Source Filter。
由此我假定在PC上通过DirectShow播放mp3,除了SourceFilter和解码器以外,另外2个Filter也是必须的。
回到PPC2005。首先RenderFile不行,我不知道其确切的原因。因为在PPC2005上mp3解码器是以DMO方式提供的,或许系统无法帮我创建这个IDMOWrapperFilter。这样我就只能自己构建Graph了:
首先还是加入Source Filter:
IBaseFilter *pSourceFilter;
pGraphBuilder-> AddSourceFilter(L "\\1.mp3 ", L "Source Filter ", &pSourceFilter);
通过枚举pSourceFilter的Pin,得到它的输出Pin--> poutPin;
然后创建mp3解码器的DMO Filter,并把它加进Graph:
IBaseFilter *pFilter;
CoCreateInstance(CLSID_DMOWrapperFilter, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&pFilter);
IDMOWrapperFilter *pWrap;
pFilter-> QueryInterface(IID_IDMOWrapperFilter, (void **)&pWrap);
DEFINE_GUID(CLSID_MP3DECODERDMO, 0x6b928210, 0x84e7, 0x4930, 0x9b, 0x33, 0x1e, 0xb6, 0xf0, 0x2b, 0x52, 0x6e);
pWrap-> Init(CLSID_MP3DECODERDMO, DMOCATEGORY_AUDIO_DECODER); // CLSID_MP3DECODERDMO的GUID值是在注册表中找到的
pGraphBuilder-> AddFilter(pFilter, L "My MPEG-1 Layer 3 Decoder DMO ");
最后调用pGraphBuilder-> Render(poutPin);
得到的返回值是VFW_E_CANNOT_CONNECT,也就是缺少中间的Filter,无法连接。
我查了一下,在前面Windows2000上系统自动帮我加载的那2个Filter:MPEG1 Splitter和Default DirectSound,在PPC2005上都没有实现甚至没有注册,尽管在WM500自带的uuids.h中能找到这两个Filter的GUID定义:
OUR_GUID_ENTRY(CLSID_MPEG1Splitter,
0x336475d0, 0x942a, 0x11ce, 0xa8, 0x70, 0x00, 0xaa, 0x00, 0x2f, 0xea, 0xb5)
OUR_GUID_ENTRY(CLSID_DSoundRender,
0x79376820, 0x07D0, 0x11CF, 0xA2, 0x4D, 0x0, 0x20, 0xAF, 0xD7, 0x97, 0x67)
所以我想请教的是:在PPC2005上除了Source Filter和mp3解码器的DMO Filter外,还有哪些中间Filter需要加入到Graph?或者不再需要额外的Filter了,只需要一些特殊处理就可以了?
对于能够帮忙彻底解决问题的朋友,将另外开贴再额外送上500分!!!
[解决办法]
我想关键应该是SourceFilter和mp3 decoder DMO之间需要什么样的Filter或者其它特殊处理。继续等待高手。
------------------------------------------------
你上边说过还有一个MPEG1 Stream Splitter的,据我的理解,这是个文件流转换成媒体流的转换器,也就是一个解释媒体文件的FILTER,如果系统没有提供的自己找个开源的库封装一个FILTER不行吗?不过如果你真的用其它开源库来做的话用DIRECT SHOW 的意义也就不大了。架构会变得更清晰、更简单。有一个开源的功能强大的播放器TCPMP,你DOWN来看看。
[解决办法]
首先找到MPEG1 Layer-3 Decoder的CLSID,这里我假定已经找到,称为CLSID_MP3Filter.
IBaseFilter* pFilter= NULL;
hr = CoCreateInstance( CLSID_MP3Filter,
NULL,
CLSCTX_INPROC,
IID_IBaseFilter,
reinterpret_cast <VOID **> (&pFilter)
);
if(SUCCEEDED(hr))
{
IFileSourceFilter* pFileSource = NULL;
if(SUCCEEDED(pFilter-> QueryInterface(IID_IFileSourceFilter,reinterpret_cast <VOID **> (&pFileSource))))
{
hr = pFileSource-> Load( _T( "\\1.mp3 "), NULL );
IEnumPins* pTest = NULL;
IPin* pPin = NULL;
ULONG ulCount = 0;
if(S_OK == (hr = pGraphBuilder-> AddFilter(pFilter,_T( "MP3 "))))
{
if(S_OK == (hr = pFilter-> EnumPins(&pTest)))
{
if(S_OK == (hr = pTest-> Next(1,&pPin,&ulCount)))
{
hr= pGraphBuilder-> Render(pPin);
pPin-> Release();
hr= S_OK;
}
pTest-> Release();
}
}
if( pFileSource )
pFileSource-> Release();
}
if( pFilter )
pFilter-> Release();
}
只随便连了一个pin,如果有多个的话,都要render
[解决办法]
我也碰到了这个问题,我不知道CLSID_AudioRender这个是不是可以直接当成是Rendering filter,我用这个方式进行的时候,也是提示两个filter不能直接连接,还需要一个中间filter。另外,对于CLSID_MPEG1Splitter在platform build里面是有这个的,不知道怎么使用?大家可以一起交流哦!我的MSN:kongpengsh@hotmail.com