在Directshow中使用VMR9

来源:互联网 发布:生产流程优化工具 编辑:程序博客网 时间:2024/05/29 18:38

声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息。  

本文链接:http://blog.csdn.net/li_007/archive/2010/03/02/5338976.aspx

开拓进取的小乌龟------->CSDN点滴点点滴滴Blog 

废话就少说了,把这段时间做的某***活动要用播发器的部分Directshow代码发出来,方便大家使用(声明:遵循LGPL协议)。本来同事想用openframeworks使用quicktime来播放这个3084*720的高清AD片子的,可是播放的时候有点卡,所以没办法就只有再次自己用directshow来写,现在分享的代码可以方便大家直接使用,做一个简单的播放器。

[c-sharp] view plaincopyprint?
  1. //  
  2. // CHDPlayerCore.h  
  3. //  
  4. // Written by Leezhm, 3rd Feb, 2010  
  5. // Contact : Leezhm@luxoom.cn  
  6. // Last Modified by Leezhm, 3rd Feb, 2010  
  7. //  
  8.  
  9. #ifndef __CHDPlayerCore_h__  
  10. #define __CHDPlayerCore_h__  
  11.  
  12. #include <DShow.h>  
  13. #include <D3D9.h>  
  14. #include <vmr9.h>  
  15.  
  16. #include "dshowutil.h"  
  17.   
  18. // Filter graph notification to the specified window  
  19. #define WM_GRAPHNOTIFY  (WM_USER+20)  
  20.   
  21. class CHDPlayerCore  
  22. {  
  23. public:  
  24.     CHDPlayerCore(void);  
  25.     virtual ~CHDPlayerCore(void);  
  26.   
  27. public:  
  28.     HRESULT CreateGraph(HWND hWnd);  
  29.   
  30.     HRESULT RenderMovieFile(const wchar_t * file, bool bRenderAudio);  
  31.   
  32.     bool RunMovies(void);  
  33.     bool StopMovies(void);  
  34.     bool PauseMovies(void);  
  35.   
  36.     HRESULT GetNativeMovieSize(CRect & pos);  
  37.     HRESULT SetMoviePosition(CRect & pos);  
  38.     HRESULT GetMoviePosotion(CRect & pos);  
  39.   
  40.     // IMediaSeeking  
  41.     HRESULT GetCurrentPosition(double * outPosition);  
  42.     HRESULT GetStopPosition(double * outPosition);  
  43.     HRESULT SetCurrentPosition(double inPosition);  
  44.     HRESULT SetStartStopPosition(double inStart, double inStop);  
  45.     HRESULT GetDuration(double * outDuration);  
  46.     HRESULT SetPlaybackRate(double inRate);  
  47.   
  48.     HRESULT SetNotifyWindow(HWND inWindows);  
  49.     void    HandleEvent(WPARAM wParam, LPARAM lParam);  
  50.   
  51.     IMediaEventEx * GetEventHandle() const;  
  52.     OAFilterState GetCurrentState();  
  53.   
  54. private:  
  55.     inline void SafeRelease(IUnknown * filter)  
  56.     {  
  57.         if (NULL != filter)  
  58.         {  
  59.             filter->Release();  
  60.             filter = NULL;  
  61.         }  
  62.     }  
  63.   
  64.     HRESULT GetInterface();  
  65.   
  66.     HRESULT UsedVideoMixingRenderer9();  
  67.     BOOL IsWindowsMediaFile(const WCHAR *lpszFile);  
  68.     HRESULT GetUnconnectedPin(IBaseFilter *pFilter,  PIN_DIRECTION PinDir, IPin **ppPin);  
  69.     HRESULT RenderMoivesToVMR9(IGraphBuilder * pGB, const WCHAR * wFileName, BOOL bRenderAudio);  
  70.   
  71.     HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);  
  72.     void RemoveFromRot(DWORD pdwRegister);  
  73.   
  74.     void ShowMsg(TCHAR *szFormat, ...);  
  75.   
  76.     IBaseFilter* CreateEncodec(CString inFriendlyName);  
  77.     HRESULT CreateFilter(REFCLSID clsid, IBaseFilter **ppFilter);  
  78.   
  79. private:  
  80.     IGraphBuilder  *  pGraphBuilder;  
  81.     IMediaControl  *  pMediaControl;  
  82.     IMediaSeeking  *  pMediaSeeking;  
  83.     IMediaEventEx  *  pMediaEventEx;  
  84.   
  85.     IBaseFilter    * pVMR9;  
  86.     IVMRWindowlessControl9 * pVMR9Control;  
  87.   
  88.     DWORD dwRegister;  
  89.     HWND mPlayerHandle;  
  90. };  
  91.  
  92. #endif // __CHDPlayerCore_h__  
[c-sharp] view plaincopyprint?
  1. //  
  2. // CHDPlayerCore.cpp  
  3. //  
  4. // Written by Leezhm, 3rd Feb, 2010  
  5. // Contact : Leezhm@luxoom.cn  
  6. // Last Modified by Leezhm, 3rd Feb, 2010  
  7. //  
  8.  
  9. #include "StdAfx.h"  
  10. #include "HDPlayerCore.h"  
  11.   
  12. CHDPlayerCore::CHDPlayerCore(void)  
  13. {  
  14.     pGraphBuilder = NULL;  
  15.     pMediaControl = NULL;  
  16.     pMediaSeeking = NULL;  
  17.     pVMR9Control  = NULL;  
  18.     pMediaEventEx = NULL;  
  19.     pVMR9         = NULL;  
  20. }  
  21.   
  22. CHDPlayerCore::~CHDPlayerCore(void)  
  23. {  
  24. #ifdef _DEBUG  
  25.     RemoveFromRot(dwRegister);  
  26. #endif  
  27.   
  28.     SafeRelease(pMediaSeeking);  
  29.     SafeRelease(pMediaControl);  
  30.     SafeRelease(pVMR9Control);  
  31.     SafeRelease(pMediaEventEx);  
  32.     SafeRelease(pVMR9);  
  33.     SafeRelease(pGraphBuilder);  
  34.   
  35.     CoUninitialize();  
  36. }  
  37.   
  38. HRESULT CHDPlayerCore::CreateGraph(HWND hWnd)  
  39. {  
  40.     HRESULT hr = NOERROR;  
  41.     mPlayerHandle = hWnd;  
  42.   
  43.     if(S_OK != CoInitializeEx(NULL,COINIT_APARTMENTTHREADED))  
  44.     {  
  45.         return E_FAIL;  
  46.     }  
  47.   
  48.     if (NULL == pGraphBuilder)  
  49.     {  
  50.         hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
  51.                               IID_IGraphBuilder, (void **)&pGraphBuilder);  
  52.   
  53.         if (SUCCEEDED(hr))  
  54.         {  
  55.             hr |= pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);  
  56.             hr |= pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&pMediaSeeking);  
  57.             hr |= pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEventEx);  
  58.   
  59.             if (FAILED(hr))  
  60.             {  
  61.                 return hr;  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     UsedVideoMixingRenderer9();  
  67.   
  68.     return hr;  
  69. }  
  70.   
  71. HRESULT CHDPlayerCore::RenderMovieFile(const wchar_t * file, bool bRenderAudio)  
  72. {  
  73.     if (NULL != file)  
  74.     {  
  75.         if (NULL == pGraphBuilder)  
  76.         {  
  77.             MessageBox(NULL, L"The IGraphBuilder is NULL", L"Error Information", S_OK);  
  78.         }  
  79.   
  80.         HRESULT hr = RenderMoivesToVMR9(pGraphBuilder, file, bRenderAudio);  
  81.   
  82.         CRect rc;  
  83.         SetRect(&rc, 0, 0, 0, 0);  
  84.         hr |= GetNativeMovieSize(rc);  
  85.         hr |= SetMoviePosition(rc);  
  86.   
  87.         if (SUCCEEDED(hr))  
  88.         {  
  89.             return hr;  
  90.         }  
  91.     }  
  92.  
  93. #ifdef _DEBUG  
  94.     AddToRot(pGraphBuilder, &dwRegister);  
  95. #endif  
  96.   
  97.     return E_FAIL;  
  98. }  
  99.   
  100. bool CHDPlayerCore::RunMovies()  
  101. {  
  102.     if (NULL != pGraphBuilder && NULL != pMediaControl)  
  103.     {  
  104.         if (State_Paused == GetCurrentState() || State_Stopped == GetCurrentState())  
  105.         {  
  106.             if (SUCCEEDED(pMediaControl->Run()))  
  107.             {  
  108.                 return true;  
  109.             }  
  110.             else  
  111.             {  
  112.                 return false;  
  113.             }  
  114.         }  
  115.     }  
  116.   
  117.     return false;  
  118. }  
  119.   
  120. bool CHDPlayerCore::StopMovies()  
  121. {  
  122.     if (NULL != pGraphBuilder && NULL != pMediaControl)  
  123.     {  
  124.         if (State_Running == GetCurrentState())  
  125.         {  
  126.             if (SUCCEEDED(pMediaControl->Stop()))  
  127.             {  
  128.                 return true;  
  129.             }  
  130.             else  
  131.             {  
  132.                 return false;  
  133.             }  
  134.         }  
  135.     }  
  136.   
  137.     return false;  
  138. }  
  139.   
  140. bool CHDPlayerCore::PauseMovies()  
  141. {  
  142.     if (NULL != pGraphBuilder && NULL != pMediaControl)  
  143.     {  
  144.         if (State_Running == GetCurrentState())  
  145.         {  
  146.             if (SUCCEEDED(pMediaControl->Pause()))  
  147.             {  
  148.                 return true;  
  149.             }  
  150.             else  
  151.             {  
  152.                 return false;  
  153.             }  
  154.         }  
  155.     }  
  156.   
  157.     return false;  
  158. }  
  159.   
  160. HRESULT CHDPlayerCore::GetNativeMovieSize(CRect & pos)  
  161. {  
  162.     HRESULT hr = NOERROR;  
  163.   
  164.     if (NULL != pVMR9Control)  
  165.     {  
  166.         hr = pVMR9Control->GetNativeVideoSize(&pos.right, &pos.bottom, NULL, NULL);  
  167.   
  168.         if (SUCCEEDED(hr))  
  169.         {  
  170.             return hr;  
  171.         }  
  172.   
  173.         SetRect(&pos, 0, 0, 0, 0);  
  174.     }  
  175.   
  176.     return E_FAIL;  
  177. }  
  178.   
  179. HRESULT CHDPlayerCore::GetMoviePosotion(CRect & pos)  
  180. {  
  181.     HRESULT hr = NOERROR;  
  182.     CRect src;  
  183.   
  184.     if (NULL != pVMR9Control)  
  185.     {  
  186.         hr = pVMR9Control->GetVideoPosition(&src, &pos);  
  187.   
  188.         if (SUCCEEDED(hr))  
  189.         {  
  190.             return hr;  
  191.         }  
  192.   
  193.         SetRect(&pos, 0, 0, 0, 0);  
  194.     }  
  195.   
  196.     return E_FAIL;  
  197. }  
  198.   
  199. HRESULT CHDPlayerCore::SetMoviePosition(CRect & pos)  
  200. {  
  201.     HRESULT hr = NOERROR;  
  202.   
  203.     if (NULL != pVMR9Control)  
  204.     {  
  205.         hr = pVMR9Control->SetVideoPosition(NULL, &pos);  
  206.   
  207.         if (SUCCEEDED(hr))  
  208.         {  
  209.             return hr;  
  210.         }  
  211.     }  
  212.   
  213.     return E_FAIL;  
  214. }  
  215.   
  216. HRESULT CHDPlayerCore::GetCurrentPosition(double * outPosition)  
  217. {  
  218.     HRESULT hr = E_FAIL;  
  219.   
  220.     if (NULL != pMediaSeeking)  
  221.     {  
  222.         __int64 position = (__int64)0.0;  
  223.   
  224.         hr = pMediaSeeking->GetCurrentPosition(&position);  
  225.         if (SUCCEEDED(hr))  
  226.         {  
  227.             *outPosition = ((double)position) / 10000000.0;  
  228.             return hr;  
  229.         }  
  230.     }  
  231.   
  232.     return hr;  
  233. }  
  234.   
  235. HRESULT CHDPlayerCore::GetStopPosition(double *outPosition)  
  236. {  
  237.   
  238.     HRESULT hr = E_FAIL;  
  239.   
  240.     if (NULL != pMediaSeeking)  
  241.     {  
  242.         __int64 position = (__int64)0.0;  
  243.   
  244.         hr = pMediaSeeking->GetStopPosition(&position);  
  245.         if (SUCCEEDED(hr))  
  246.         {  
  247.             *outPosition = ((double)position) / 10000000.0;  
  248.             return hr;  
  249.         }  
  250.     }  
  251.   
  252.     return hr;  
  253. }  
  254.   
  255. HRESULT CHDPlayerCore::SetCurrentPosition(double inPosition)  
  256. {  
  257.     HRESULT hr = E_FAIL;  
  258.   
  259.     if (NULL != pMediaSeeking)  
  260.     {  
  261.         __int64 position = (__int64)(10000000 * inPosition);  
  262.   
  263.         hr = pMediaSeeking->SetPositions(&position, AM_SEEKING_AbsolutePositioning |  
  264.                                          AM_SEEKING_SeekToKeyFrame, 0, AM_SEEKING_NoPositioning);  
  265.   
  266.         if (SUCCEEDED(hr))  
  267.         {  
  268.             return hr;  
  269.         }  
  270.     }  
  271.   
  272.     return hr;  
  273. }  
  274.   
  275. HRESULT CHDPlayerCore::SetStartStopPosition(double inStart, double inStop)  
  276. {  
  277.     HRESULT hr = E_FAIL;  
  278.   
  279.     if (NULL != pMediaSeeking)  
  280.     {  
  281.         __int64 start = (__int64)(10000000 * inStart);  
  282.         __int64 stop  = (__int64)(10000000 * inStop);  
  283.   
  284.         hr = pMediaSeeking->SetPositions(&start, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame,  
  285.                                          &stop, AM_SEEKING_AbsolutePositioning | AM_SEEKING_SeekToKeyFrame);  
  286.   
  287.         if (SUCCEEDED(hr))  
  288.         {  
  289.             return hr;  
  290.         }  
  291.     }  
  292.   
  293.     return hr;  
  294. }  
  295.   
  296. HRESULT CHDPlayerCore::GetDuration(double * outDuration)  
  297. {  
  298.     HRESULT hr = E_FAIL;  
  299.   
  300.     if (NULL != pMediaSeeking)  
  301.     {  
  302.         __int64 length = (__int64)0.0;  
  303.   
  304.         hr = pMediaSeeking->GetDuration(&length);  
  305.   
  306.         if (SUCCEEDED(hr))  
  307.         {  
  308.             *outDuration = ((double)length / 10000000.0);  
  309.   
  310.             return hr;  
  311.         }  
  312.     }  
  313.   
  314.     return hr;  
  315. }  
  316.   
  317. HRESULT CHDPlayerCore::SetPlaybackRate(double inRate)  
  318. {  
  319.     HRESULT hr = E_FAIL;  
  320.   
  321.     if (NULL != pMediaSeeking)  
  322.     {  
  323.         hr = pMediaSeeking->SetRate(inRate);  
  324.   
  325.         if (SUCCEEDED(hr))  
  326.         {  
  327.             return hr;  
  328.         }  
  329.     }  
  330.   
  331.     return hr;  
  332. }  
  333.   
  334. HRESULT CHDPlayerCore::SetNotifyWindow(HWND inWindows)  
  335. {  
  336.     HRESULT hr = E_FAIL;  
  337.   
  338.     if (NULL != pMediaEventEx)  
  339.     {  
  340.         hr = pMediaEventEx->SetNotifyWindow((OAHWND)inWindows, WM_GRAPHNOTIFY, 0);  
  341.   
  342.         if (SUCCEEDED(hr))  
  343.         {  
  344.             return hr;  
  345.         }  
  346.     }  
  347.   
  348.     return hr;  
  349. }  
  350.   
  351. void CHDPlayerCore::HandleEvent(WPARAM wParam, LPARAM lParam)  
  352. {  
  353.     if (NULL != pMediaEventEx)  
  354.     {  
  355.         LONG eventCode = 0;  
  356.         LONG_PTR eventParam1 = 0;  
  357.         LONG_PTR eventParam2 = 0;  
  358.   
  359.         while(SUCCEEDED(pMediaEventEx->GetEvent(&eventCode, &eventParam1, &eventParam2, 0)))  
  360.         {  
  361.             pMediaEventEx->FreeEventParams(eventCode, eventParam1, eventParam2);  
  362.             switch (eventCode)  
  363.             {  
  364.             case EC_COMPLETE:  
  365.                 break;  
  366.   
  367.             case EC_USERABORT:  
  368.             case EC_ERRORABORT:  
  369.                 break;  
  370.   
  371.             default:  
  372.                 break;  
  373.             }  
  374.         }  
  375.     }  
  376. }  
  377.   
  378. IMediaEventEx * CHDPlayerCore::GetEventHandle() const  
  379. {  
  380.     if (NULL != pMediaEventEx)  
  381.     {  
  382.         return pMediaEventEx;  
  383.     }  
  384.   
  385.     return NULL;  
  386. }  
  387.   
  388. HRESULT CHDPlayerCore::UsedVideoMixingRenderer9()  
  389. {  
  390.     HRESULT hr = NOERROR;  
  391.   
  392.     hr |= CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC,  
  393.                            IID_IBaseFilter, (void **)&pVMR9);  
  394.   
  395.     if (SUCCEEDED(hr))  
  396.     {  
  397.         hr |= pGraphBuilder->AddFilter(pVMR9, L"Video Mixing Render 9");  
  398.   
  399.         if (SUCCEEDED(hr))  
  400.         {  
  401.             IVMRFilterConfig9 * pConfig9 = NULL;  
  402.             hr |= pVMR9->QueryInterface(IID_IVMRFilterConfig9, (void **)&pConfig9);  
  403.   
  404.             if (SUCCEEDED(hr))  
  405.             {  
  406.                 hr |= pConfig9->SetNumberOfStreams(2);  
  407.                 hr |= pConfig9->SetRenderingMode(VMR9Mode_Windowless);  
  408.                 hr |= pConfig9->SetRenderingPrefs(RenderPrefs_AllowOverlays);  
  409.   
  410.                 pConfig9->Release();  
  411.             }  
  412.             pConfig9 = NULL;  
  413.   
  414.             IVMRMonitorConfig9 * pMonitorConfig = NULL;  
  415.             hr |= pVMR9->QueryInterface(IID_IVMRMonitorConfig9, (void **)&pMonitorConfig);  
  416.             if(SUCCEEDED(hr))  
  417.             {  
  418.                 UINT iCurrentMonitor;  
  419.                 hr |= pMonitorConfig->GetMonitor(&iCurrentMonitor);  
  420.                 pMonitorConfig->Release();  
  421.             }  
  422.             pMonitorConfig = NULL;  
  423.   
  424.             hr |= pVMR9->QueryInterface(IID_IVMRWindowlessControl9, (void **)&pVMR9Control);  
  425.         }  
  426.     }  
  427.   
  428.     SafeRelease(pVMR9);  
  429.   
  430.     if (SUCCEEDED(hr))  
  431.     {  
  432.         hr |= pVMR9Control->SetVideoClippingWindow(mPlayerHandle);  
  433.         hr |= pVMR9Control->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);  
  434.     }  
  435.     else  
  436.     {  
  437.         SafeRelease(pVMR9Control);  
  438.     }  
  439.   
  440.     return hr;  
  441. }  
  442.   
  443. HRESULT CHDPlayerCore::RenderMoivesToVMR9(IGraphBuilder * pGB, const WCHAR * wFileName, BOOL bRenderAudio = TRUE)  
  444. {  
  445.     HRESULT hr = NOERROR;  
  446.     CComPtr <IPin> pOutputPin;  
  447.     CComPtr <IPin> pInputPin;  
  448.     CComPtr <IBaseFilter> pSource;  
  449.     CComPtr <IBaseFilter> pAudioRenderer;  
  450.     CComPtr <IFilterGraph2> pFG;  
  451.     CComPtr <IFileSourceFilter> pFileSource;  
  452.   
  453.     // Render audio if requested (defaults to TRUE)  
  454.     if (bRenderAudio)  
  455.     {  
  456.         // Because we will be rendering with the RENDERTOEXISTINGRENDERERS flag,  
  457.         // we need to create an audio renderer and add it to the graph.  
  458.         // Create an instance of the DirectSound renderer (for each media file).  
  459.         //  
  460.         // Note that if the system has no sound card (or if the card is disabled),  
  461.         // then creating the DirectShow renderer will fail.  In that case,  
  462.         // handle the failure quietly.  
  463.         if (SUCCEEDED(CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER,  
  464.             IID_IBaseFilter, (void **)&pAudioRenderer)))  
  465.         {  
  466.             // The audio renderer was successfully created, so add it to the graph  
  467.             hr |= pGB->AddFilter(pAudioRenderer, L"Audio Renderer");  
  468.             if (FAILED(hr))  
  469.             {  
  470.                 return hr;  
  471.             }  
  472.         }  
  473.     }  
  474.   
  475.     // Add a file source filter for this media file  
  476.     if (!IsWindowsMediaFile(wFileName))  
  477.     {  
  478.         // Add the source filter to the graph  
  479.         if (FAILED(hr |= pGB->AddSourceFilter(wFileName, L"SOURCE", &pSource)))  
  480.         {  
  481.             USES_CONVERSION;  
  482.             WCHAR szMsg[MAX_PATH + 128] = {0};  
  483.   
  484.             hr = StringCchPrintf(szMsg, NUMELMS(szMsg), TEXT("Failed to add the source filter to the graph!  hr=0x%x/r/n/r/n")  
  485.                 TEXT("Filename: %s/0"), hr, wFileName);  
  486.             MessageBox(NULL, szMsg, TEXT("Failed to render file to VMR9"), MB_OK | MB_ICONERROR);  
  487.   
  488.             return hr;  
  489.         }  
  490.   
  491.         hr |= GetUnconnectedPin(pSource, PINDIR_OUTPUT, &pOutputPin);  
  492.         if (FAILED(hr))  
  493.         {  
  494.             return hr;  
  495.         }  
  496.   
  497.         // Get an IFilterGraph2 interface to assist in building the  
  498.         // multifile graph with the non-default VMR9 renderer  
  499.         hr |= pGB->QueryInterface(IID_IFilterGraph2, (void **)&pFG);  
  500.         if (FAILED(hr))  
  501.         {  
  502.             return hr;  
  503.         }  
  504.   
  505.         // Render the output pin, using the VMR9 as the specified renderer.  This is  
  506.         // necessary in case the GraphBuilder needs to insert a Color Space convertor,  
  507.         // or if multiple filters insist on using multiple allocators.  
  508.         // The audio renderer will also be used, if the media file contains audio.  
  509.         hr |= pFG->RenderEx(pOutputPin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);  
  510.         if (FAILED(hr))  
  511.         {  
  512.             return hr;  
  513.         }  
  514.   
  515.         // If this media file does not contain an audio stream, then the  
  516.         // audio renderer that we created will be unconnected.  If left in the  
  517.         // graph, it could interfere with rate changes and timing.  
  518.         // Therefore, if the audio renderer is unconnected, remove it from the graph.  
  519.         if (pAudioRenderer != NULL)  
  520.         {  
  521.             IPin *pUnconnectedPin=0;  
  522.   
  523.             // Is the audio renderer's input pin connected?  
  524.             HRESULT hrPin = GetUnconnectedPin(pAudioRenderer, PINDIR_INPUT, &pUnconnectedPin);  
  525.   
  526.             // If there is an unconnected pin, then remove the unused filter  
  527.             if (SUCCEEDED(hrPin) && (pUnconnectedPin != NULL))  
  528.             {  
  529.                 // Release the returned IPin interface  
  530.                 pUnconnectedPin->Release();  
  531.   
  532.                 // Remove the audio renderer from the graph  
  533.                 hrPin = pGB->RemoveFilter(pAudioRenderer);  
  534.             }  
  535.         }  
  536.     }  
  537.     else  
  538.     {  
  539.         // Load the improved ASF reader filter by CLSID  
  540.         hr |= CreateFilter(CLSID_WMAsfReader, &pSource);  
  541.         if(FAILED(hr))  
  542.         {  
  543.             ShowMsg(TEXT("Failed to create WMAsfWriter filter!  hr=0x%x/0"), hr);  
  544.             return hr;  
  545.         }  
  546.   
  547.         // Add the ASF reader filter to the graph.  For ASF/WMV/WMA content,  
  548.         // this filter is NOT the default and must be added explicitly.  
  549.         hr |= pGB->AddFilter(pSource, L"WMV ASF Reader");  
  550.         if(FAILED(hr))  
  551.         {  
  552.             ShowMsg(TEXT("Failed to add ASF reader filter to graph!  hr=0x%x/0"), hr);  
  553.             return hr;  
  554.         }  
  555.   
  556.         // Set its source filename  
  557.         hr |= pSource->QueryInterface(IID_IFileSourceFilter, (void **) &pFileSource);  
  558.   
  559.         // Attempt to load this file  
  560.         hr |= pFileSource->Load(wFileName, NULL);  
  561.   
  562.         if (FAILED(hr))  
  563.         {  
  564.             ShowMsg(TEXT("Failed to load file in source filter (pFileSource->Load())!  hr=0x%x/0"), hr);  
  565.             return hr;  
  566.         }  
  567.   
  568.         ULONG count = 0;  
  569.         CountTotalFilterPins(pSource, &count);  
  570.   
  571.         for (ULONG i = 0; i < count; i ++)  
  572.         {  
  573.             pOutputPin = GetOutPin(pSource, i);  
  574.             PIN_INFO info;  
  575.             pOutputPin->QueryPinInfo(&info);  
  576.   
  577.             CComPtr<IBaseFilter> Codec;  
  578.   
  579.             if (_tcsstr(info.achName, TEXT("Video")))  
  580.             {  
  581.                 Codec = CreateEncodec(_T("WMVideo Decoder DMO"));  
  582.                 if (NULL != pGraphBuilder)  
  583.                 {  
  584.                     pGraphBuilder->AddFilter(Codec, _T("WMVideo Decoder DMO"));  
  585.                     pInputPin = GetInPin(Codec, 0);  
  586.   
  587.                     hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);  
  588.                     if (FAILED(hr))  
  589.                     {  
  590.                         ShowMsg(_T("Video Connected Failed.  hr=0x%x/0"), hr);  
  591.                         return hr;  
  592.                     }  
  593.   
  594.                     pOutputPin = GetOutPin(Codec, 0);  
  595.                     pInputPin = GetInPin(pVMR9, 0);  
  596.   
  597.                     hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);  
  598.                     if (FAILED(hr))  
  599.                     {  
  600.                         ShowMsg(_T("Video Connected Failed.  hr=0x%x/0"), hr);  
  601.                         return hr;  
  602.                     }  
  603.                 }  
  604.             }  
  605.             else if (_tcsstr(info.achName, TEXT("Audio")))  
  606.             {  
  607.                 Codec = CreateEncodec(_T("WMAudio Decoder DMO"));  
  608.                 if (NULL != pGraphBuilder)  
  609.                 {  
  610.                     pGraphBuilder->AddFilter(Codec, _T("WMAudio Decoder DMO"));  
  611.                     pInputPin = GetInPin(Codec, 0);  
  612.   
  613.                     hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);  
  614.                     if (FAILED(hr))  
  615.                     {  
  616.                         ShowMsg(_T("Audio Connected Failed.  hr=0x%x/0"), hr);  
  617.                         return hr;  
  618.                     }  
  619.   
  620.                     pOutputPin = GetOutPin(Codec, 0);  
  621.   
  622.                     if (NULL == pAudioRenderer)  
  623.                     {  
  624.                         if (SUCCEEDED(CoCreateInstance(CLSID_DSoundRender, NULL, CLSCTX_INPROC_SERVER,  
  625.                             IID_IBaseFilter, (void **)&pAudioRenderer)))  
  626.                         {  
  627.                             // The audio renderer was successfully created, so add it to the graph  
  628.                             hr |= pGB->AddFilter(pAudioRenderer, L"Audio Renderer");  
  629.                             if (FAILED(hr))  
  630.                             {  
  631.                                 return hr;  
  632.                             }  
  633.                         }  
  634.                     }  
  635.   
  636.                     pInputPin = GetInPin(pAudioRenderer, 0);  
  637.   
  638.                     hr |= pGraphBuilder->Connect(pOutputPin, pInputPin);  
  639.                     if (FAILED(hr))  
  640.                     {  
  641.                         ShowMsg(_T("Audio Connected Failed.  hr=0x%x/0"), hr);  
  642.                         return hr;  
  643.                     }  
  644.                 }  
  645.             }  
  646.         }  
  647.     }  
  648.   
  649.     return hr;  
  650. }  
  651.   
  652. BOOL CHDPlayerCore::IsWindowsMediaFile(const WCHAR *lpszFile)  
  653. {  
  654.     USES_CONVERSION;  
  655.     WCHAR szFilename[MAX_PATH] = {0};  
  656.   
  657.     // Copy the file name to a local string and convert to lowercase  
  658.     (void)StringCchCopy(szFilename,NUMELMS(szFilename), lpszFile);  
  659.     szFilename[MAX_PATH-1] = 0;  
  660.     _tcslwr_s(szFilename, 260);  
  661.   
  662.     if (_tcsstr(szFilename, TEXT(".asf")) ||  
  663.         _tcsstr(szFilename, TEXT(".wma")) ||  
  664.         _tcsstr(szFilename, TEXT(".wmv")))  
  665.     {  
  666.         return TRUE;  
  667.     }  
  668.     else  
  669.     {  
  670.         return FALSE;  
  671.     }  
  672. }  
  673.   
  674. OAFilterState CHDPlayerCore::GetCurrentState()  
  675. {  
  676.     OAFilterState states = 0;  
  677.   
  678.     if (NULL != pGraphBuilder && NULL != pMediaControl)  
  679.     {  
  680.         pMediaControl->GetState(INFINITE, &states);  
  681.     }  
  682.   
  683.     return states;  
  684. }  
  685.   
  686.   
  687. //Register the filter graph to Rot  
  688. HRESULT CHDPlayerCore::AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)  
  689. {  
  690.     HRESULT hr = NOERROR;  
  691.     IMoniker * pMoniker = NULL;  
  692.     IRunningObjectTable * pROT = NULL;  
  693.     if(FAILED(GetRunningObjectTable(0,&pROT)))  
  694.     {  
  695.         return E_FAIL;  
  696.     }  
  697.   
  698.     WCHAR wsz[256];  
  699.     ::memset(wsz,0,256);  
  700.   
  701.     hr = StringCchPrintfW(wsz, NUMELMS(wsz), L"FilterGraph %08x pid %08x",  
  702.         (DWORD_PTR)pUnkGraph,GetCurrentProcessId());  
  703.   
  704.     hr = CreateItemMoniker(L"!",wsz,&pMoniker);  
  705.     if(SUCCEEDED(hr))  
  706.     {  
  707.         hr = pROT->Register(0,pUnkGraph,pMoniker,pdwRegister);  
  708.         pMoniker->Release();  
  709.     }  
  710.     pROT->Release();  
  711.     return hr;  
  712. }  
  713.   
  714. void CHDPlayerCore::RemoveFromRot(DWORD pdwRegister)  
  715. {  
  716.     IRunningObjectTable *pROT = NULL;  
  717.     if(SUCCEEDED(GetRunningObjectTable(0,&pROT)))  
  718.     {  
  719.         pROT->Revoke(pdwRegister);  
  720.         pROT->Release();  
  721.     }  
  722. }  
  723.   
  724. HRESULT CHDPlayerCore::GetUnconnectedPin(  
  725.                                        IBaseFilter *pFilter,   // Pointer to the filter.  
  726.                                        PIN_DIRECTION PinDir,   // Direction of the pin to find.  
  727.                                        IPin **ppPin)           // Receives a pointer to the pin.  
  728. {  
  729.     IEnumPins *pEnum = 0;  
  730.     IPin *pPin = 0;  
  731.   
  732.     if (!ppPin)  
  733.         return E_POINTER;  
  734.     *ppPin = 0;  
  735.   
  736.     // Get a pin enumerator  
  737.     HRESULT hr = pFilter->EnumPins(&pEnum);  
  738.     if (FAILED(hr))  
  739.         return hr;  
  740.   
  741.     // Look for the first unconnected pin  
  742.     while (pEnum->Next(1, &pPin, NULL) == S_OK)  
  743.     {  
  744.         PIN_DIRECTION ThisPinDir;  
  745.   
  746.         pPin->QueryDirection(&ThisPinDir);  
  747.         if (ThisPinDir == PinDir)  
  748.         {  
  749.             IPin *pTmp = 0;  
  750.   
  751.             hr = pPin->ConnectedTo(&pTmp);  
  752.             if (SUCCEEDED(hr))  // Already connected, not the pin we want.  
  753.             {  
  754.                 pTmp->Release();  
  755.             }  
  756.             else  // Unconnected, this is the pin we want.  
  757.             {  
  758.                 pEnum->Release();  
  759.                 *ppPin = pPin;  
  760.                 return S_OK;  
  761.             }  
  762.         }  
  763.         pPin->Release();  
  764.     }  
  765.   
  766.     // Release the enumerator  
  767.     pEnum->Release();  
  768.   
  769.     // Did not find a matching pin  
  770.     return E_FAIL;  
  771. }  
  772.   
  773. IBaseFilter* CHDPlayerCore::CreateEncodec(CString inFriendlyName)  
  774. {  
  775.     HRESULT hr = NOERROR;  
  776.     ICreateDevEnum * enumHardware =NULL;  
  777.     IBaseFilter    * hardwareFilter = NULL;  
  778.   
  779.     hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,  
  780.         IID_ICreateDevEnum,(void **)&enumHardware);  
  781.   
  782.     if(FAILED(hr))  
  783.     {  
  784.         return NULL;  
  785.     }  
  786.   
  787.     IEnumMoniker * enumMoniker = NULL;  
  788.   
  789.     hr = enumHardware->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &enumMoniker,0);  
  790.   
  791.     if(FAILED(hr))  
  792.     {  
  793.         return NULL;  
  794.     }  
  795.   
  796.     if(enumMoniker)  
  797.     {  
  798.         enumMoniker->Reset();  
  799.   
  800.         IMoniker * moniker = NULL;  
  801.         char friendlyName[256];  
  802.         ZeroMemory(friendlyName,256);  
  803.   
  804.         while(S_OK == enumMoniker->Next(1,&moniker,0))  
  805.         {  
  806.             if(moniker)  
  807.             {  
  808.                 IPropertyBag * proBag = NULL;  
  809.                 VARIANT    name;  
  810.   
  811.                 hr = moniker->BindToStorage(NULL,NULL,IID_IPropertyBag,(void **)&proBag);  
  812.   
  813.                 if(SUCCEEDED(hr))  
  814.                 {  
  815.                     name.vt = VT_BSTR;  
  816.                     proBag->Read(L"FriendlyName",&name,NULL);  
  817.                 }  
  818.   
  819.                 if(SUCCEEDED(hr))  
  820.                 {  
  821.                     WideCharToMultiByte(CP_ACP, 0, name.bstrVal, -1,friendlyName, 256,  
  822.                         NULL, NULL);  
  823.                     CString str = (CString)friendlyName;  
  824.                     if(inFriendlyName == str)  
  825.                     {  
  826.                         moniker->BindToObject(NULL,NULL,IID_IBaseFilter,  
  827.                             (void **)&hardwareFilter);  
  828.                     }  
  829.                 }  
  830.                 if(proBag)  
  831.                 {  
  832.                     proBag->Release();  
  833.                     proBag = NULL;  
  834.                 }  
  835.                 moniker->Release();  
  836.             }  
  837.         }  
  838.         enumMoniker->Release();  
  839.     }  
  840.     enumHardware->Release();  
  841.   
  842.     return hardwareFilter;  
  843. }  
  844.   
  845. HRESULT CHDPlayerCore::CreateFilter(REFCLSID clsid, IBaseFilter **ppFilter)  
  846. {  
  847.     HRESULT hr;  
  848.   
  849.     hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,  
  850.         IID_IBaseFilter,  
  851.         (void **) ppFilter);  
  852.   
  853.     if(FAILED(hr))  
  854.     {  
  855.         //MessageBox(TEXT("CreateFilter: Failed to create filter!  hr=0x%x/n"));  
  856.         if (ppFilter)  
  857.             *ppFilter = NULL;  
  858.         return hr;  
  859.     }  
  860.   
  861.     return S_OK;  
  862. }  
  863.   
  864. void CHDPlayerCore::ShowMsg(TCHAR *szFormat, ...)  
  865. {  
  866.     TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs  
  867.     const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);  
  868.     const int LASTCHAR = NUMCHARS - 1;  
  869.   
  870.     // Format the input string  
  871.     va_list pArgs;  
  872.     va_start(pArgs, szFormat);  
  873.   
  874.     // Use a bounded buffer size to prevent buffer overruns.  Limit count to  
  875.     // character size minus one to allow for a NULL terminating character.  
  876.     (void)StringCchVPrintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);  
  877.     va_end(pArgs);  
  878.   
  879.     // Ensure that the formatted string is NULL-terminated  
  880.     szBuffer[LASTCHAR] = TEXT('/0');  
  881.   
  882.     // Display a message box with the formatted string  
  883.     MessageBox(NULL, szBuffer, TEXT("Porsche HD Player"), MB_OK);  
  884. }  
  

 

使用示例代码

[c-sharp] view plaincopyprint?
  1. if (NULL == this->player)  
  2. {  
  3.     this->player = new CHDPlayerCore();  
  4. }  
  5.        this->player->CreateGraph(this->playerDlg->GetSafeHwnd());  
  6.        this->player->RenderMovieFile(filePaths, true);  
  7. this->player->SetNotifyWindow(this->GetSafeHwnd());  
  8. this->player->SetStartStopPosition(0, 117.006);  
  9. this->player->RunMovies();  

 

其实封装好了,使用起来很简单的,我想应该可以方便大家使用,完成一个简单的播放器。当然还可以监听播放器事件,那段代码就没必要贴出来的,很简单,MSDN上就有的

原创粉丝点击