Media Foundation学习笔记(八)编程练习:一个通用视频文件播放器

来源:互联网 发布:网络直播赚钱吗 编辑:程序博客网 时间:2024/05/16 15:05

我将有关Media Foundation的函数调用封装到一个类CSpsPlayer中了,CSpsPlayer类的使用方法如下:


1)CSpsPlayer* pPlayer = new CSpsPlayer(hWndPlay);

2)pPlayer->OpenFile("c:\\ttt.asf");

3)获取视频时长pPlayer->GetTimeLen();单位是1/10^4毫秒;

4)pPlayer->Play();

5)暂定pPlayer->Pause();

6)暂停后继续pPlayer->Play();

7)获取播放位置pPlayer->GetCurrentPos();单位是1/10^4毫秒;

8)设置音量pPlayer->SetAudioVolumn(lVolumn);lVolumn取值是0~100

9)Seek操作pPlayer->Move(pos);pos单位是1/10^4毫秒;

10)播放窗口尺寸变化pPlayer->AdjustWindowPosition();

11)停止播放pPlayer->Stop();

12)关闭文件pPlayer->CloseFile();


SpsPlayer.h文件:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  Class:      CSpsPlayer  
  3. //  
  4. //  Compiler:   Visual C++  
  5. //  Tested on:  Visual C++ 2010  
  6. //  
  7. //  Created:    08/March/2014  
  8. //  
  9. //  Author:     Liu Yang        464585657@qq.com  
  10. //  
  11. //  
  12. #ifndef SPSPLAYER_H  
  13. #define SPSPLAYER_H  
  14.   
  15. #include <Windows.h>  
  16. #include <string>  
  17. #include <vector>  
  18. #include <new>  
  19. #include <shobjidl.h>   
  20. #include <shlwapi.h>  
  21. #include <assert.h>  
  22. #include <strsafe.h>  
  23.   
  24. // Media Foundation headers  
  25. #include <mfapi.h>  
  26. #include <mfidl.h>  
  27. #include <mferror.h>  
  28. #include <evr.h>  
  29.   
  30. #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }  
  31. #define SAFE_CLOSE_HANDLE(x) { if (x)CloseHandle(x); x = NULL; }  
  32.   
  33. enum PlayerState//播放器状态  
  34. {  
  35.     Closed = 0,     // No session.  
  36.     Started,        // Session is playing a file.  
  37.     Paused,         // Session is paused.  
  38.     Stopped,        // Session is stopped (ready to play).   
  39. };  
  40.   
  41. class CMyCriticalSection  
  42. {  
  43. public:  
  44.     CMyCriticalSection()  
  45.     {  
  46.         ::InitializeCriticalSection(&m_cs);  
  47.     }  
  48.     virtual ~CMyCriticalSection()  
  49.     {  
  50.         ::DeleteCriticalSection(&m_cs);  
  51.     }  
  52.     void lock()  
  53.     {  
  54.         ::EnterCriticalSection(&m_cs);  
  55.     }  
  56.     void unlock()  
  57.     {  
  58.         ::LeaveCriticalSection(&m_cs);  
  59.     }  
  60. private:  
  61.     CRITICAL_SECTION m_cs;  
  62. };  
  63.   
  64. class CMyAutoLock  
  65. {  
  66. public:  
  67.     CMyAutoLock(CMyCriticalSection * pCrit)  
  68.     {  
  69.         m_pCrit = pCrit;  
  70.         m_pCrit->lock();  
  71.     }  
  72.     virtual ~CMyAutoLock()  
  73.     {  
  74.         m_pCrit->unlock();  
  75.     }  
  76. private:  
  77.     CMyCriticalSection * m_pCrit;  
  78. };  
  79.   
  80.   
  81. class CSpsPlayer : public IMFAsyncCallback  
  82. {  
  83. public:  
  84.     CSpsPlayer(HWND hWndVideo);  
  85.     virtual ~CSpsPlayer();  
  86.   
  87.     // IUnknown methods  
  88.     STDMETHODIMP QueryInterface(REFIID iid, void** ppv);  
  89.     STDMETHODIMP_(ULONG) AddRef();  
  90.     STDMETHODIMP_(ULONG) Release();  
  91.   
  92.     // IMFAsyncCallback methods  
  93.     STDMETHODIMP  GetParameters(DWORD*, DWORD*)  
  94.     {  
  95.         // Implementation of this method is optional.  
  96.         return E_NOTIMPL;  
  97.     }  
  98.     STDMETHODIMP  Invoke(IMFAsyncResult* pAsyncResult);  
  99.   
  100.     //播放控制函数  
  101.     std::string GetSpsFilePathName();//获取文件名  
  102.     BOOL OpenFile(const char * s);//打开文件  
  103.     BOOL CloseFile();//关闭文件  
  104.     long GetPlayStatus();//获取播放器状态,返回:0:停止;1:播放;2:暂停  
  105.     BOOL Play();//播放  
  106.     BOOL Pause();//暂停  
  107.     BOOL Stop();//停止  
  108.     LONGLONG GetTimeLen();//获取时长(单位是1/10^4毫秒)  
  109.     LONGLONG GetCurrentPos();//获取当前播放位置(单位是1/10^4毫秒)  
  110.     BOOL Move(LONGLONG pos);//跳到指定位置播放(单位是1/10^4毫秒)  
  111.     BOOL GetAudioIsOpenedOrClosed();//获取声音是开启还是关闭状态  
  112.     BOOL OpenOrCloseAudio(BOOL bOpen);//打开或关闭声音  
  113.     long GetAudioVolumn();//获取音量  
  114.     BOOL SetAudioVolumn(long lVolumn);//设置音量  
  115.     void AdjustWindowPosition();//播放窗口尺寸发生变化时调用  
  116.     void RepaitVideo();//暂停时,播放窗口重绘后调用  
  117.   
  118. private:  
  119.     BOOL AddBranchToTopology( IMFTopology *pTopology, IMFMediaSource *pSource, IMFPresentationDescriptor *pPD, DWORD iStream);//添加流的分支到topology  
  120.     IMFGetService* GetMFGetService();  
  121.     IMFSimpleAudioVolume* GetSimpleAudioVolume();  
  122.     IMFPresentationClock* GetPresentationClock();  
  123.     IMFVideoDisplayControl* GetVideoDisplayControl();  
  124.   
  125. private:  
  126.     CMyCriticalSection      m_csCrit;//播放器锁  
  127.     HWND                    m_hWndVideo;//播放窗口  
  128.     std::string             m_sSpsFileName;//视频文件  
  129.     //////////////////////////////////////////////////////////////////////////  
  130.     IMFMediaSession*        m_pSession;//Media Session  
  131.     PlayerState             m_state;//播放器状态  
  132.     LONGLONG                m_llTimeLen;//1/10^4毫秒  
  133.     long                    m_nRefCount;        // Reference count.  
  134. };  
  135.   
  136.   
  137. #endif  


SpsPlayer.cpp文件:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //  
  2. //  Class:      CSpsPlayer  
  3. //  
  4. //  Compiler:   Visual C++  
  5. //  Tested on:  Visual C++ 2010  
  6. //  
  7. //  Created:    08/March/2014  
  8. //  
  9. //  Author:     Liu Yang        464585657@qq.com  
  10. //  
  11. //  
  12. #include "SpsPlayer.h"  
  13.   
  14. #include <assert.h>  
  15.   
  16. #pragma comment(lib, "shlwapi")  
  17.   
  18. static const GUID MY_MR_VIDEO_RENDER_SERVICE ={0x1092a86c,0xab1a,0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} };  
  19.   
  20. CSpsPlayer::CSpsPlayer(HWND hWndVideo)  
  21. {  
  22.     m_hWndVideo = hWndVideo;  
  23.     //////////////////////////////////////////////////////////////////////////  
  24.     m_pSession = NULL;  
  25.     m_state = Closed;  
  26.     m_llTimeLen = 0;  
  27. }  
  28.   
  29. CSpsPlayer::~CSpsPlayer()  
  30. {  
  31.     CloseFile();  
  32. }  
  33.   
  34. HRESULT CSpsPlayer::QueryInterface(REFIID riid, void** ppv)  
  35. {  
  36.     static const QITAB qit[] =   
  37.     {  
  38.         QITABENT(CSpsPlayer, IMFAsyncCallback),  
  39.         { 0 }  
  40.     };  
  41.     return QISearch(this, qit, riid, ppv);  
  42. }  
  43.   
  44. ULONG CSpsPlayer::AddRef()  
  45. {  
  46.     return InterlockedIncrement(&m_nRefCount);  
  47. }  
  48.   
  49. ULONG CSpsPlayer::Release()  
  50. {  
  51.     ULONG uCount = InterlockedDecrement(&m_nRefCount);  
  52.     if (uCount == 0)  
  53.     {  
  54.         delete this;  
  55.     }  
  56.     return uCount;  
  57. }  
  58.   
  59. std::string CSpsPlayer::GetSpsFilePathName()  
  60. {  
  61.     CMyAutoLock lock(&m_csCrit);  
  62.   
  63.     return m_sSpsFileName;  
  64. }  
  65.   
  66. BOOL CSpsPlayer::OpenFile(const char * s)  
  67. {  
  68.     CloseFile();  
  69.   
  70.     CMyAutoLock lock(&m_csCrit);  
  71.   
  72.     std::string sSpsFileName;  
  73.     sSpsFileName = s;  
  74.   
  75.     //初始化Media Foundataion平台  
  76.     HRESULT hr = MFStartup(MF_VERSION);  
  77.     if (FAILED(hr))  
  78.     {  
  79.         return FALSE;  
  80.     }  
  81.   
  82.     //创建Media Session对象  
  83.     hr = MFCreateMediaSession(NULL, &m_pSession);  
  84.     if (FAILED(hr))  
  85.     {  
  86.         MFShutdown();  
  87.         return FALSE;  
  88.     }  
  89.   
  90.     //开始从Media Session接收事件  
  91.     hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);  
  92.     if (FAILED(hr))  
  93.     {  
  94.         SAFE_RELEASE(m_pSession);  
  95.         MFShutdown();  
  96.         return FALSE;  
  97.     }  
  98.   
  99.     MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;  
  100.   
  101.     IMFSourceResolver* pSourceResolver = NULL;//Media Source选择器  
  102.     IUnknown* pSource = NULL;  
  103.     IMFMediaSource* pMFMediaSource = NULL;  
  104.   
  105.     //根据给定的文件路径,创建Media Source对象,并获取IMFMediaSource接口  
  106.     hr = MFCreateSourceResolver(&pSourceResolver);  
  107.     if (FAILED(hr))  
  108.     {  
  109.         SAFE_RELEASE(m_pSession);  
  110.         MFShutdown();  
  111.         return FALSE;  
  112.     }  
  113.     WCHAR szwFile[MAX_PATH] = {0};  
  114.     MultiByteToWideChar(CP_ACP, 0, sSpsFileName.c_str(), -1, szwFile, MAX_PATH);  
  115.     hr = pSourceResolver->CreateObjectFromURL( szwFile, MF_RESOLUTION_MEDIASOURCE, NULL, &ObjectType, &pSource );  
  116.     if (FAILED(hr))  
  117.     {  
  118.         SAFE_RELEASE(pSourceResolver);  
  119.         SAFE_RELEASE(m_pSession);  
  120.         MFShutdown();  
  121.         return FALSE;  
  122.     }  
  123.     hr = pSource->QueryInterface(IID_PPV_ARGS(&pMFMediaSource));  
  124.     if (FAILED(hr))  
  125.     {  
  126.         SAFE_RELEASE(pSource);  
  127.         SAFE_RELEASE(pSourceResolver);  
  128.         SAFE_RELEASE(m_pSession);  
  129.         MFShutdown();  
  130.         return FALSE;  
  131.     }     
  132.     SAFE_RELEASE(pSource);  
  133.     SAFE_RELEASE(pSourceResolver);  
  134.   
  135.     IMFPresentationDescriptor* pSourcePD = NULL;  
  136.   
  137.     //创建Presentation描述符  
  138.     hr = pMFMediaSource->CreatePresentationDescriptor(&pSourcePD);  
  139.     if (FAILED(hr))  
  140.     {  
  141.         SAFE_RELEASE(pMFMediaSource);          
  142.         SAFE_RELEASE(m_pSession);  
  143.         MFShutdown();  
  144.         return FALSE;  
  145.     }  
  146.   
  147.     MFTIME mDuration = 0;  
  148.     hr = pSourcePD->GetUINT64(MF_PD_DURATION, (UINT64*)&mDuration);  
  149.     if (FAILED(hr))  
  150.     {  
  151.         SAFE_RELEASE(pSourcePD);   
  152.         SAFE_RELEASE(pMFMediaSource);          
  153.         SAFE_RELEASE(m_pSession);  
  154.         MFShutdown();  
  155.         return FALSE;  
  156.     }  
  157.     m_llTimeLen = mDuration;  
  158.   
  159.     DWORD cSourceStreams = 0;  
  160.   
  161.     //获取Media Source对象的流的数目  
  162.     hr = pSourcePD->GetStreamDescriptorCount(&cSourceStreams);  
  163.     if (FAILED(hr))  
  164.     {  
  165.         SAFE_RELEASE(pSourcePD);     
  166.         SAFE_RELEASE(pMFMediaSource);        
  167.         SAFE_RELEASE(m_pSession);  
  168.         MFShutdown();  
  169.         return FALSE;  
  170.     }  
  171.   
  172.     IMFTopology *pTopology = NULL;  
  173.   
  174.     //创建topology对象  
  175.     hr = MFCreateTopology(&pTopology);  
  176.     if (FAILED(hr))  
  177.     {  
  178.         SAFE_RELEASE(pSourcePD);     
  179.         SAFE_RELEASE(pMFMediaSource);        
  180.         SAFE_RELEASE(m_pSession);  
  181.         MFShutdown();  
  182.         return FALSE;  
  183.     }  
  184.   
  185.     //为每一个流创建节点,并将节点添加到topology中  
  186.     for (DWORD i = 0; i < cSourceStreams; i++)  
  187.     {  
  188.         BOOL bRet = AddBranchToTopology(pTopology, pMFMediaSource, pSourcePD, i);  
  189.         if (!bRet)  
  190.         {  
  191.             SAFE_RELEASE(pTopology);     
  192.             SAFE_RELEASE(pSourcePD);     
  193.             SAFE_RELEASE(pMFMediaSource);        
  194.             SAFE_RELEASE(m_pSession);  
  195.             MFShutdown();  
  196.             return FALSE;  
  197.         }  
  198.     }  
  199.   
  200.     //将topology对象设置到Media Session对象中  
  201.     hr = m_pSession->SetTopology(0, pTopology);  
  202.     if (FAILED(hr))  
  203.     {  
  204.         SAFE_RELEASE(pTopology);     
  205.         SAFE_RELEASE(pSourcePD);     
  206.         SAFE_RELEASE(pMFMediaSource);        
  207.         SAFE_RELEASE(m_pSession);  
  208.         MFShutdown();  
  209.         return FALSE;  
  210.     }  
  211.   
  212.     m_sSpsFileName = sSpsFileName;  
  213.   
  214.     m_state = Stopped;  
  215.   
  216.     return TRUE;  
  217. }  
  218.   
  219. BOOL CSpsPlayer::CloseFile()  
  220. {  
  221.     Stop();  
  222.   
  223.     CMyAutoLock lock(&m_csCrit);  
  224.   
  225.     SAFE_RELEASE(m_pSession);  
  226.     MFShutdown();  
  227.     m_sSpsFileName = "";  
  228.     return TRUE;  
  229. }  
  230.   
  231. long CSpsPlayer::GetPlayStatus()  
  232. {  
  233.     CMyAutoLock lock(&m_csCrit);  
  234.   
  235.     switch(m_state)  
  236.     {  
  237.     case Closed://还没有打开文件  
  238.     case Stopped://停止了--打开文件后就是此状态  
  239.         return 0;  
  240.         break;  
  241.     case Started://开始播放了  
  242.         return 1;  
  243.         break;  
  244.     case Paused://暂停了  
  245.         return 2;  
  246.         break;  
  247.     default:  
  248.         return -1;  
  249.         break;  
  250.     }  
  251. }  
  252.   
  253. BOOL CSpsPlayer::Play()  
  254. {  
  255.     CMyAutoLock lock(&m_csCrit);  
  256.   
  257.     if (m_state != Paused && m_state != Stopped)  
  258.     {  
  259.         return FALSE;  
  260.     }  
  261.   
  262.     PROPVARIANT varStart;  
  263.     PropVariantInit(&varStart);  
  264.   
  265.     HRESULT hr = m_pSession->Start(&GUID_NULL, &varStart);  
  266.   
  267.     PropVariantClear(&varStart);  
  268.   
  269.     if (SUCCEEDED(hr))  
  270.     {  
  271.         // Note: Start is an asynchronous operation. However, we  
  272.         // can treat our state as being already started. If Start  
  273.         // fails later, we'll get an MESessionStarted event with  
  274.         // an error code, and we will update our state then.  
  275.         m_state = Started;  
  276.         return TRUE;  
  277.     }  
  278.   
  279.     return FALSE;  
  280. }  
  281.   
  282. BOOL CSpsPlayer::Pause()  
  283. {  
  284.     CMyAutoLock lock(&m_csCrit);  
  285.   
  286.     if (m_state != Started)  
  287.     {  
  288.         return FALSE;  
  289.     }  
  290.   
  291.     HRESULT hr = m_pSession->Pause();  
  292.     if (SUCCEEDED(hr))  
  293.     {  
  294.         m_state = Paused;  
  295.         return TRUE;  
  296.     }  
  297.     return FALSE;  
  298. }  
  299.   
  300. BOOL CSpsPlayer::Stop()  
  301. {  
  302.     CMyAutoLock lock(&m_csCrit);  
  303.   
  304.     if (m_state != Started && m_state != Paused)  
  305.     {  
  306.         return FALSE;  
  307.     }  
  308.   
  309.     HRESULT hr = m_pSession->Stop();  
  310.     if (SUCCEEDED(hr))  
  311.     {  
  312.         m_state = Stopped;  
  313.         return TRUE;  
  314.     }  
  315.     return FALSE;  
  316. }  
  317.   
  318. LONGLONG CSpsPlayer::GetTimeLen()  
  319. {  
  320.     CMyAutoLock lock(&m_csCrit);  
  321.   
  322.     return m_llTimeLen;  
  323. }  
  324.   
  325. LONGLONG CSpsPlayer::GetCurrentPos()  
  326. {  
  327.     CMyAutoLock lock(&m_csCrit);  
  328.   
  329.     IMFPresentationClock* pPresentationClock = GetPresentationClock();  
  330.     if (!pPresentationClock)  
  331.         return 0;  
  332.   
  333.     MFTIME pos = 0;  
  334.     HRESULT hr = pPresentationClock->GetTime(&pos);  
  335.     SAFE_RELEASE(pPresentationClock);  
  336.     if (FAILED(hr))  
  337.         return 0;  
  338.   
  339.     return pos;  
  340. }  
  341.   
  342. BOOL CSpsPlayer::Move(LONGLONG pos)  
  343. {  
  344.     CMyAutoLock lock(&m_csCrit);  
  345.   
  346.     if (!m_pSession)  
  347.         return FALSE;  
  348.   
  349.     PROPVARIANT varStart;  
  350.     varStart.vt = VT_I8;  
  351.     varStart.hVal.QuadPart = pos;  
  352.   
  353.     HRESULT hr =  m_pSession->Start(NULL, &varStart);  
  354.     if (FAILED(hr))  
  355.         return FALSE;  
  356.   
  357.     return TRUE;  
  358. }  
  359.   
  360. BOOL CSpsPlayer::GetAudioIsOpenedOrClosed()  
  361. {  
  362.     CMyAutoLock lock(&m_csCrit);  
  363.   
  364.     if (!m_pSession)  
  365.     {  
  366.         return FALSE;  
  367.     }  
  368.   
  369.     IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();  
  370.     if(pa)  
  371.     {  
  372.         BOOL bMute = FALSE;  
  373.         HRESULT hr = pa->GetMute(&bMute);  
  374.         if (FAILED(hr))  
  375.             return FALSE;  
  376.         return bMute;  
  377.     }  
  378.     return FALSE;  
  379. }  
  380.   
  381. BOOL CSpsPlayer::OpenOrCloseAudio(BOOL bOpen)  
  382. {  
  383.     CMyAutoLock lock(&m_csCrit);  
  384.   
  385.     if (!m_pSession)  
  386.     {  
  387.         return FALSE;  
  388.     }  
  389.   
  390.     IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();  
  391.     if(pa)  
  392.     {  
  393.         HRESULT hr;  
  394.         if (bOpen)  
  395.         {  
  396.             hr = pa->SetMute(FALSE);  
  397.             if (FAILED(hr))  
  398.                 return FALSE;  
  399.         }  
  400.         else  
  401.         {  
  402.             hr = pa->SetMute(TRUE);  
  403.             if (FAILED(hr))  
  404.                 return FALSE;  
  405.         }  
  406.     }     
  407.     return TRUE;  
  408. }  
  409.   
  410. long CSpsPlayer::GetAudioVolumn()  
  411. {  
  412.     CMyAutoLock lock(&m_csCrit);  
  413.   
  414.     if (!m_pSession)  
  415.     {  
  416.         return 0;  
  417.     }  
  418.   
  419.     IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();  
  420.     if(pa)  
  421.     {  
  422.         HRESULT hr;  
  423.         float f = 0.0f;  
  424.         hr = pa->GetMasterVolume(&f);  
  425.         if (FAILED(hr))  
  426.             return 0;  
  427.         f = (f < 0.0f ? 0.0f : (f > 1.0f ? 1.0f : f));  
  428.         return (long)(f * 100.0f);  
  429.     }  
  430.     return 0;  
  431. }  
  432.   
  433. BOOL CSpsPlayer::SetAudioVolumn(long ll)  
  434. {  
  435.     CMyAutoLock lock(&m_csCrit);  
  436.   
  437.     if (!m_pSession)  
  438.     {  
  439.         return FALSE;  
  440.     }  
  441.   
  442.     IMFSimpleAudioVolume* pa = GetSimpleAudioVolume();  
  443.     if(pa)  
  444.     {  
  445.         HRESULT hr;  
  446.         ll = (ll < 0 ? 0 : (ll > 100 ? 100 : ll));  
  447.         float f = ((float)ll / 100.0f);  
  448.         f = (f < 0.0f ? 0.0f : (f > 1.0f ? 1.0f : f));  
  449.         hr = pa->SetMasterVolume(f);  
  450.         if (FAILED(hr))  
  451.             return FALSE;  
  452.         return TRUE;  
  453.     }  
  454.     return FALSE;  
  455. }  
  456.   
  457. void CSpsPlayer::AdjustWindowPosition()  
  458. {  
  459.     CMyAutoLock lock(&m_csCrit);  
  460.   
  461.     IMFVideoDisplayControl* pVideoDisplayControl = GetVideoDisplayControl();  
  462.     if (pVideoDisplayControl)  
  463.     {  
  464.         RECT rcDest;  
  465.         GetWindowRect(m_hWndVideo, &rcDest);  
  466.         POINT pt;  
  467.         pt.x = rcDest.left;  
  468.         pt.y = rcDest.top;  
  469.         ScreenToClient(m_hWndVideo, &pt);  
  470.         rcDest.left = pt.x;  
  471.         rcDest.top = pt.y;  
  472.         pt.x = rcDest.right;  
  473.         pt.y = rcDest.bottom;  
  474.         ScreenToClient(m_hWndVideo, &pt);  
  475.         rcDest.right = pt.x;  
  476.         rcDest.bottom = pt.y;  
  477.         pVideoDisplayControl->SetVideoPosition(0, &rcDest);  
  478.     }     
  479. }  
  480.   
  481. void CSpsPlayer::RepaitVideo()  
  482. {  
  483.     CMyAutoLock lock(&m_csCrit);  
  484.   
  485.     IMFVideoDisplayControl* pVideoDisplayControl = GetVideoDisplayControl();  
  486.     if (pVideoDisplayControl)  
  487.         pVideoDisplayControl->RepaintVideo();  
  488. }  
  489.   
  490. BOOL CSpsPlayer::AddBranchToTopology( IMFTopology *pTopology, IMFMediaSource *pSource, IMFPresentationDescriptor *pPD, DWORD iStream)  
  491. {  
  492.     IMFStreamDescriptor *pSD = NULL;  
  493.     IMFTopologyNode     *pSourceNode = NULL;  
  494.     IMFTopologyNode     *pOutputNode = NULL;  
  495.   
  496.     BOOL fSelected = FALSE;  
  497.   
  498.     //获取流描述符  
  499.     HRESULT hr = pPD->GetStreamDescriptorByIndex(iStream, &fSelected, &pSD);  
  500.     if (FAILED(hr))  
  501.     {  
  502.         return FALSE;  
  503.     }  
  504.   
  505.     if (fSelected)  
  506.     {  
  507.         // Create the media sink activation object.  
  508.         IMFMediaTypeHandler *pHandler = NULL;  
  509.         IMFActivate         *pActivate = NULL;  
  510.   
  511.         //获取流的IMFMeidaTypeHandle  
  512.         HRESULT hr = pSD->GetMediaTypeHandler(&pHandler);  
  513.         if (FAILED(hr))  
  514.         {  
  515.             SAFE_RELEASE(pSD);  
  516.             return FALSE;  
  517.         }  
  518.   
  519.         //获取流的主类型  
  520.         GUID guidMajorType;  
  521.         hr = pHandler->GetMajorType(&guidMajorType);  
  522.         if (FAILED(hr))  
  523.         {  
  524.             SAFE_RELEASE(pHandler);  
  525.             SAFE_RELEASE(pSD);  
  526.             return FALSE;  
  527.         }  
  528.   
  529.         SAFE_RELEASE(pHandler);  
  530.    
  531.         // 根据流的主类型为Render创建IMFActivate对象  
  532.         if (MFMediaType_Audio == guidMajorType)  
  533.         {  
  534.             hr = MFCreateAudioRendererActivate(&pActivate);  
  535.             if (FAILED(hr))  
  536.             {  
  537.                 SAFE_RELEASE(pSD);  
  538.                 return FALSE;  
  539.             }  
  540.         }  
  541.         else if (MFMediaType_Video == guidMajorType)  
  542.         {  
  543.             hr = MFCreateVideoRendererActivate(m_hWndVideo, &pActivate);  
  544.             if (FAILED(hr))  
  545.             {  
  546.                 SAFE_RELEASE(pSD);  
  547.                 return FALSE;  
  548.             }  
  549.         }         
  550.   
  551.         //创建源节点  
  552.         hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &pSourceNode);  
  553.         if (FAILED(hr))  
  554.         {  
  555.             SAFE_RELEASE(pActivate);  
  556.             SAFE_RELEASE(pSD);  
  557.             return FALSE;  
  558.         }  
  559.   
  560.         //设置源节点的源属性  
  561.         hr = pSourceNode->SetUnknown(MF_TOPONODE_SOURCE, pSource);  
  562.         if (FAILED(hr))  
  563.         {  
  564.             SAFE_RELEASE(pSourceNode);  
  565.             SAFE_RELEASE(pActivate);  
  566.             SAFE_RELEASE(pSD);  
  567.             return FALSE;  
  568.         }  
  569.   
  570.         //设置源节点的Presentation描述符  
  571.         hr = pSourceNode->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pPD);  
  572.         if (FAILED(hr))  
  573.         {  
  574.             SAFE_RELEASE(pSourceNode);  
  575.             SAFE_RELEASE(pActivate);  
  576.             SAFE_RELEASE(pSD);  
  577.             return FALSE;  
  578.         }  
  579.   
  580.         //设置源节点的流的描述符  
  581.         hr = pSourceNode->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR, pSD);  
  582.         if (FAILED(hr))  
  583.         {  
  584.             SAFE_RELEASE(pSourceNode);  
  585.             SAFE_RELEASE(pActivate);  
  586.             SAFE_RELEASE(pSD);  
  587.             return FALSE;  
  588.         }  
  589.       
  590.         //添加源节点到topology.  
  591.         hr = pTopology->AddNode(pSourceNode);  
  592.         if (FAILED(hr))  
  593.         {  
  594.             SAFE_RELEASE(pSourceNode);  
  595.             SAFE_RELEASE(pActivate);  
  596.             SAFE_RELEASE(pSD);  
  597.             return FALSE;  
  598.         }  
  599.   
  600.         //创建输出节点  
  601.         hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &pOutputNode);  
  602.         if (FAILED(hr))  
  603.         {  
  604.             SAFE_RELEASE(pSourceNode);  
  605.             SAFE_RELEASE(pActivate);  
  606.             SAFE_RELEASE(pSD);  
  607.             return FALSE;  
  608.         }  
  609.   
  610.         //设置输出节点的指针  
  611.         hr = pOutputNode->SetObject(pActivate);  
  612.         if (FAILED(hr))  
  613.         {  
  614.             SAFE_RELEASE(pOutputNode);  
  615.             SAFE_RELEASE(pSourceNode);  
  616.             SAFE_RELEASE(pActivate);  
  617.             SAFE_RELEASE(pSD);  
  618.             return FALSE;  
  619.         }  
  620.   
  621.         SAFE_RELEASE(pActivate);  
  622.   
  623.         //设置输出节点所在流的id  
  624.         hr = pOutputNode->SetUINT32(MF_TOPONODE_STREAMID, 0);  
  625.         if (FAILED(hr))  
  626.         {  
  627.             SAFE_RELEASE(pOutputNode);  
  628.             SAFE_RELEASE(pSourceNode);  
  629.             SAFE_RELEASE(pSD);  
  630.             return FALSE;  
  631.         }  
  632.   
  633.         hr = pOutputNode->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);  
  634.         if (FAILED(hr))  
  635.         {  
  636.             SAFE_RELEASE(pOutputNode);  
  637.             SAFE_RELEASE(pSourceNode);  
  638.             SAFE_RELEASE(pSD);  
  639.             return FALSE;  
  640.         }  
  641.   
  642.         //添加输出节点到topology.  
  643.         hr = pTopology->AddNode(pOutputNode);  
  644.         if (FAILED(hr))  
  645.         {  
  646.             SAFE_RELEASE(pOutputNode);  
  647.             SAFE_RELEASE(pSourceNode);  
  648.             SAFE_RELEASE(pSD);  
  649.             return FALSE;  
  650.         }  
  651.   
  652.         hr = pSourceNode->ConnectOutput(0, pOutputNode, 0);  
  653.         if (FAILED(hr))  
  654.         {  
  655.             SAFE_RELEASE(pOutputNode);  
  656.             SAFE_RELEASE(pSourceNode);  
  657.             SAFE_RELEASE(pSD);  
  658.             return FALSE;  
  659.         }  
  660.     }  
  661.   
  662.     SAFE_RELEASE(pOutputNode);  
  663.     SAFE_RELEASE(pSourceNode);  
  664.     SAFE_RELEASE(pSD);  
  665.     return TRUE;  
  666. }  
  667.   
  668. HRESULT CSpsPlayer::Invoke(IMFAsyncResult *pResult)  
  669. {  
  670.     MediaEventType meType = MEUnknown;  // Event type  
  671.   
  672.     IMFMediaEvent *pEvent = NULL;  
  673.   
  674.     m_csCrit.lock();  
  675.   
  676.     // Get the event from the event queue.  
  677.     HRESULT hr = m_pSession->EndGetEvent(pResult, &pEvent);  
  678.     if (FAILED(hr))  
  679.     {  
  680.         m_csCrit.unlock();  
  681.         return S_OK;  
  682.     }  
  683.   
  684.     // Get the event type.   
  685.     hr = pEvent->GetType(&meType);  
  686.     if (FAILED(hr))  
  687.     {  
  688.         SAFE_RELEASE(pEvent);  
  689.         m_csCrit.unlock();  
  690.         return S_OK;  
  691.     }  
  692.   
  693.     if (meType == MEEndOfPresentation)  
  694.     {  
  695.         SAFE_RELEASE(pEvent);  
  696.   
  697.         m_csCrit.unlock();  
  698.   
  699.         Stop();  
  700.   
  701.         return S_OK;  
  702.     }  
  703.     else  
  704.     {  
  705.         SAFE_RELEASE(pEvent);  
  706.         // For all other events, get the next event in the queue.  
  707.         hr = m_pSession->BeginGetEvent(this, NULL);  
  708.         if (FAILED(hr))  
  709.         {  
  710.             //error  
  711.         }  
  712.     }  
  713.   
  714.     m_csCrit.unlock();  
  715.     return S_OK;  
  716. }  
  717.   
  718. IMFGetService* CSpsPlayer::GetMFGetService()  
  719. {  
  720.     if (!m_pSession)  
  721.         return NULL;  
  722.   
  723.     IMFGetService* pGetService = NULL;  
  724.   
  725.     HRESULT hr = m_pSession->QueryInterface(IID_IMFGetService, (void **)&pGetService);  
  726.     if(FAILED(hr))  
  727.         return NULL;  
  728.   
  729.     return pGetService;  
  730. }  
  731.   
  732. IMFSimpleAudioVolume* CSpsPlayer::GetSimpleAudioVolume()  
  733. {  
  734.     if (!m_pSession)  
  735.         return NULL;  
  736.   
  737.     IMFGetService* pGetService = GetMFGetService();  
  738.     if(!pGetService)  
  739.         return NULL;  
  740.   
  741.     IMFSimpleAudioVolume* pa = NULL;  
  742.     HRESULT hr = pGetService->GetService(MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&pa));  
  743.     SAFE_RELEASE(pGetService);  
  744.     if(FAILED(hr))  
  745.         return NULL;  
  746.   
  747.     return pa;  
  748. }  
  749.   
  750. IMFPresentationClock* CSpsPlayer::GetPresentationClock()  
  751. {  
  752.     if (!m_pSession)  
  753.         return NULL;  
  754.   
  755.     IMFClock* pClock = NULL;  
  756.     HRESULT hr = m_pSession->GetClock(&pClock);  
  757.     if(FAILED(hr))  
  758.         return NULL;  
  759.   
  760.     IMFPresentationClock* pPresentationClock = NULL;  
  761.     hr = pClock->QueryInterface(IID_PPV_ARGS(&pPresentationClock));  
  762.     SAFE_RELEASE(pClock);  
  763.     if(FAILED(hr))  
  764.         return NULL;  
  765.   
  766.     return pPresentationClock;  
  767. }  
  768.   
  769. IMFVideoDisplayControl* CSpsPlayer::GetVideoDisplayControl()  
  770. {  
  771.     if (!m_pSession)  
  772.         return NULL;  
  773.   
  774.     IMFVideoDisplayControl* pVideoDisplay = NULL;  
  775.     HRESULT hr = MFGetService(m_pSession, MY_MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&pVideoDisplay));  
  776.     if(FAILED(hr))  
  777.         return NULL;  
  778.   
  779.     return pVideoDisplay;  
0 0