Windows Mobile 下使用DirectShow播放视频文件

来源:互联网 发布:android 淘宝订单效果 编辑:程序博客网 时间:2024/04/30 11:04

我需要在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, &param1, &param2, 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