我需要在Windows Mobile上面播放3gp文件, 本来是用系统自带的WMP播放的, 但是客户认为这样子显得不专业, 一定要在自己的程序中播放视频.
我以前在windows xp上做过 WMP 控件的播放器, 所以也希望能在Windows Mobile的程序中插入WMP控件来实现, 但是经过一番探索失败了, 总是在窗口初始化的时候出现异常.
后来, 我决定用DirectShow来做, 其实用DiretShow来做并不麻烦, 而且很灵活.
1 首先要在工程中引入头文件 streams.h.
2 程序初始化的时候调用 CoInitialize , 因为DirectShow是以COM组件的形式调用的. 当然, 程序退出的时候也要调用CoUninitialize.
3 然后就可以调用接口播放视频了, 具体代码如下:
/* 创建过滤器图管理程序并提交文件 */
if( S_OK != (hResult = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&m_pGraph)) )
{
WRITE_LOG1("Play3GPVideo error 1 , hResult is 0x%x !/r/n", hResult);
return FALSE;
}
if( S_OK != (hResult = m_pGraph->RenderFile(m_szVideoFile, NULL)) )
{
WRITE_LOG1("Play3GPVideo error 2 , hResult is 0x%x !/r/n", hResult);
DestroyWindow();
return FALSE;
}
/* 指定所有者窗口 */
if( S_OK != (hResult = m_pGraph->QueryInterface(IID_IVideoWindow, (void **)&m_pVidWin)) )
{
WRITE_LOG1("Play3GPVideo error 3 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
if( S_OK != (hResult = m_pVidWin->put_Owner((OAHWND)this->GetSafeHwnd())) )
{
WRITE_LOG1("Play3GPVideo error 5 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
if( S_OK != (hResult = m_pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS)) )
{
WRITE_LOG1("Play3GPVideo error 4 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
RECT grc;
::GetClientRect(this->GetSafeHwnd(), &grc);
if( S_OK != (hResult = m_pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom/4*3)) )
{
WRITE_LOG1("Play3GPVideo error 6 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
if( S_OK != (hResult = m_pVidWin->put_Visible( OATRUE )) )
{
WRITE_LOG1("Play3GPVideo error 7 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
/* 设置所有者窗口使其接收事件通知 */
if( S_OK != (hResult = m_pGraph->QueryInterface(IID_IMediaEventEx, (void **)&m_pEvent)) )
{
WRITE_LOG1("Play3GPVideo error 8 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
if( S_OK != (hResult = m_pEvent->SetNotifyWindow((OAHWND)this->GetSafeHwnd(), WM_GRAPHNOTIFY, 0)) )
{
WRITE_LOG1("Play3GPVideo error 9 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
/* MediaControl接口 */
if ( S_OK != (hResult = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMediaControl)) )
{
WRITE_LOG1("Play3GPVideo error 10 , hResult is 0x%x !/r/n", hResult);
m_pGraph->Release();
return FALSE;
}
// Run the graph.
if( FAILED (hResult = m_pMediaControl->Run()) )
{
WRITE_LOG1("PlayVideoFile error , hResult is 0x%x !/r/n", hResult);
DestroyWindow();
return FALSE;
}
处理消息
long evCode, param1, param2;
HRESULT hr;
if (m_pEvent == NULL) // 避免在关闭图时发生紊乱情况
{
return;
}
while (hr = m_pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0), SUCCEEDED(hr))
{
hr = m_pEvent->FreeEventParams(evCode, param1, param2);
if (EC_COMPLETE == evCode)
{
CleanUp();
ShowPlayMenu();
DestroyWindow();
break;
}
else if(EC_USERABORT == evCode)
{
CleanUp();
DestroyWindow();
break;
}
}
使用完之后清理的过程
m_pVidWin->put_Visible( OAFALSE );
m_pVidWin->put_Owner(NULL);
// 在释放图以前禁止事件通知
m_pEvent->SetNotifyWindow(NULL, 0, 0);
m_pEvent->Release();
m_pEvent = NULL;
// 停止图的运行
m_pMediaControl->Stop();
m_pMediaControl->Release();
m_pVidWin->Release();
m_pGraph->Release();
http://hi.baidu.com/mikenoodle/blog/item/581a044fcadba33cafc3abd1.html