home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / VMRPlayer / vcdplyer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  23.1 KB  |  979 lines

  1. //------------------------------------------------------------------------------
  2. // File: vcdplyer.cpp
  3. //
  4. // Desc: DirectShow sample code
  5. //       - A VMR-enabled player application
  6. //
  7. // Copyright (c) 1994 - 2001, Microsoft Corporation.  All rights reserved.
  8. //------------------------------------------------------------------------------
  9.  
  10. #include <streams.h>
  11. #include <mmreg.h>
  12. #include <commctrl.h>
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #include <atlbase.h>
  16.  
  17. #include "project.h"
  18.  
  19. #include <initguid.h>
  20.  
  21. extern int FrameStepCount;
  22.  
  23.  
  24. /******************************Public*Routine******************************\
  25. * CMpegMovie
  26. *
  27. * Constructors and destructors
  28. *
  29. \**************************************************************************/
  30. CMpegMovie::CMpegMovie(HWND hwndApplication) :
  31.       m_hwndApp(hwndApplication),
  32.       m_MediaEvent(NULL),
  33.       m_Mode(MOVIE_NOTOPENED),
  34.       m_Fg(NULL),
  35.       m_Gb(NULL),
  36.       m_Mc(NULL),
  37.       m_Ms(NULL),
  38.       m_Me(NULL),
  39.       m_Wc(NULL),
  40.       m_pMixControl(NULL),
  41.       m_TimeFormat(TIME_FORMAT_MEDIA_TIME)
  42. {
  43. }
  44. CMpegMovie::~CMpegMovie()
  45. {
  46. }
  47.  
  48.  
  49. /******************************Public*Routine******************************\
  50. * SetRenderingMode
  51. *
  52. \**************************************************************************/
  53. static HRESULT SetRenderingMode( IBaseFilter* pBaseFilter, VMRMode mode )
  54. {
  55.     // Test VMRConfig, VMRMonitorConfig
  56.     IVMRFilterConfig* pConfig;
  57.  
  58.     HRESULT hr = pBaseFilter->QueryInterface(IID_IVMRFilterConfig, (LPVOID *)&pConfig);
  59.     if(SUCCEEDED(hr))
  60.     {
  61.         hr = pConfig->SetRenderingMode(mode);
  62.         hr = pConfig->SetRenderingPrefs(RenderPrefs_ForceOverlays|RenderPrefs_AllowOverlays);
  63.         pConfig->Release();
  64.     }
  65.     return hr;
  66. }
  67.  
  68.  
  69. /******************************Public*Routine******************************\
  70. * AddVideoMixingRendererToFG
  71. *
  72. \**************************************************************************/
  73. HRESULT
  74. CMpegMovie::AddVideoMixingRendererToFG()
  75. {
  76.     IBaseFilter* pBF = NULL;
  77.     HRESULT hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
  78.         NULL,
  79.         CLSCTX_INPROC,
  80.         IID_IBaseFilter,
  81.         (LPVOID *)&pBF);
  82.  
  83.     if(SUCCEEDED(hRes))
  84.     {
  85.         hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer");
  86.  
  87.         if(SUCCEEDED(hRes))
  88.         {
  89.             // Test VMRConfig, VMRMonitorConfig
  90.             IVMRFilterConfig* pConfig;
  91.             HRESULT hRes2 = pBF->QueryInterface(IID_IVMRFilterConfig, (LPVOID *)&pConfig);
  92.             if(SUCCEEDED(hRes2))
  93.             {
  94.                 hRes2 = pConfig->SetNumberOfStreams(2);
  95.                 hRes2 = pConfig->SetRenderingMode(VMRMode_Windowless);
  96.                 hRes2 = pConfig->SetRenderingPrefs(RenderPrefs_AllowOverlays);
  97.                 //                         RenderPrefs_ForceOverlays);
  98.                 //                         RenderPrefs_ForceOffscreen);
  99.                 //                         RenderPrefs_DoNotRenderColorKeyAndBorder);
  100.                 pConfig->Release();
  101.             }
  102.  
  103.             IVMRMonitorConfig* pMonitorConfig;
  104.             HRESULT hRes3 = pBF->QueryInterface(IID_IVMRMonitorConfig, (LPVOID *)&pMonitorConfig);
  105.             if(SUCCEEDED(hRes3))
  106.             {
  107.                 // STDMETHODIMP SetMonitor( const VMRGUID *pGUID );
  108.                 // STDMETHODIMP GetMonitor( VMRGUID *pGUID );
  109.                 // STDMETHODIMP SetDefaultMonitor( const VMRGUID *pGUID );
  110.                 // STDMETHODIMP GetDefaultMonitor( VMRGUID *pGUID );
  111.                 // STDMETHODIMP GetAvailableMonitors( VMRMONITORINFO* pInfo, DWORD dwMaxInfoArraySize, DWORD* pdwNumDevices );
  112.                 VMRGUID guid;
  113.                 HRESULT hr4 = pMonitorConfig->GetMonitor(&guid);
  114.                 pMonitorConfig->Release();
  115.             }
  116.  
  117.             hRes = pBF->QueryInterface(IID_IVMRWindowlessControl, (LPVOID *)&m_Wc);
  118.         }
  119.     }
  120.  
  121.     if(pBF)
  122.     {
  123.         pBF->Release();
  124.     }
  125.  
  126.     if(SUCCEEDED(hRes))
  127.     {
  128.         HRESULT hr = m_Wc->SetVideoClippingWindow(m_hwndApp);
  129.         hr = m_Wc->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
  130.     }
  131.     else
  132.     {
  133.         if(m_Wc)
  134.         {
  135.             m_Wc->Release();
  136.             m_Wc = NULL;
  137.         }
  138.     }
  139.  
  140.     return hRes;
  141. }
  142.  
  143.  
  144. /******************************Public*Routine******************************\
  145. * RenderSecondFile
  146. *
  147. \**************************************************************************/
  148. HRESULT
  149. CMpegMovie::RenderSecondFile(
  150.     TCHAR* lpFileName
  151.     )
  152. {
  153.     USES_CONVERSION;
  154.     HRESULT hRes;
  155.     WCHAR FileName[MAX_PATH];
  156.  
  157.     // Since the user might have already rendered the second file,
  158.     // free it if it has been rendered
  159.     if (m_Gb)
  160.     {
  161.         m_Gb->Release();
  162.         m_Gb = NULL;
  163.  
  164.         hRes = m_Fg->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb);
  165.         if(FAILED(hRes))
  166.         {
  167.             MessageBeep(0);
  168.             return hRes;
  169.         }
  170.     }
  171.     
  172.     wcscpy(FileName, T2W(lpFileName));
  173.  
  174.     hRes = m_Gb->RenderFile(FileName, NULL);
  175.     if(SUCCEEDED(hRes) && m_pMixControl)
  176.     {
  177.         hRes = m_pMixControl->SetAlpha(1, 0.5f);
  178.         g_bSecondFileLoaded = TRUE;
  179.     }
  180.  
  181.     return hRes;
  182. }
  183.  
  184.  
  185. /******************************Public*Routine******************************\
  186. * OpenMovie
  187. *
  188. \**************************************************************************/
  189. HRESULT
  190. CMpegMovie::OpenMovie(
  191.     TCHAR *lpFileName
  192.     )
  193. {
  194.     USES_CONVERSION;
  195.     IUnknown        *pUnk;
  196.     HRESULT         hres;
  197.     WCHAR           FileName[MAX_PATH];
  198.  
  199.     wcscpy(FileName, T2W(lpFileName));
  200.  
  201.     hres = CoInitialize(NULL);
  202.     if(hres == S_FALSE)
  203.         CoUninitialize();
  204.  
  205.     hres = CoCreateInstance(
  206.         CLSID_FilterGraph,
  207.         NULL,
  208.         CLSCTX_INPROC,
  209.         IID_IUnknown,
  210.         (LPVOID *)&pUnk);
  211.  
  212.     if(SUCCEEDED(hres))
  213.     {
  214.         m_Mode = MOVIE_OPENED;
  215.         hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg);
  216.         if(FAILED(hres))
  217.         {
  218.             pUnk->Release();
  219.             return hres;
  220.         }
  221.  
  222.         hres = AddVideoMixingRendererToFG();
  223.         if(FAILED(hres))
  224.         {
  225.             m_Fg->Release(); m_Fg = NULL;
  226.             return hres;
  227.         }
  228.  
  229.         hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb);
  230.         if(FAILED(hres))
  231.         {
  232.             pUnk->Release();
  233.             m_Fg->Release(); m_Fg = NULL;
  234.             m_Wc->Release(); m_Wc = NULL;
  235.             return hres;
  236.         }
  237.  
  238.         hres = m_Gb->RenderFile(FileName, NULL);
  239.         if(FAILED(hres))
  240.         {
  241.             pUnk->Release();
  242.             m_Fg->Release(); m_Fg = NULL;
  243.             m_Wc->Release(); m_Wc = NULL;
  244.             m_Gb->Release(); m_Gb = NULL;
  245.             return hres;
  246.         }
  247.  
  248.         hres = m_Wc->QueryInterface(IID_IVMRMixerControl, (LPVOID *) &m_pMixControl);
  249.         if(FAILED(hres))
  250.         {
  251.             pUnk->Release();
  252.             m_Fg->Release(); m_Fg = NULL;
  253.             m_Wc->Release(); m_Wc = NULL;
  254.             m_Gb->Release(); m_Gb = NULL;
  255.             m_pMixControl = NULL;
  256.             return hres;
  257.         }
  258.  
  259.         hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc);
  260.         if(FAILED(hres))
  261.         {
  262.             pUnk->Release();
  263.             m_Fg->Release(); m_Fg = NULL;
  264.             m_Wc->Release(); m_Wc = NULL;
  265.             m_Gb->Release(); m_Gb = NULL;
  266.             return hres;
  267.         }
  268.  
  269.         //
  270.         // Not being able to get the IMediaEvent interface doesn't
  271.         // necessarly mean that we can't play the graph.
  272.         //
  273.         pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
  274.         GetMovieEventHandle();
  275.  
  276.         pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
  277.         pUnk->Release();
  278.         return S_OK;
  279.     }
  280.     else
  281.     {
  282.         m_Fg = NULL;
  283.     }
  284.  
  285.     return hres;
  286. }
  287.  
  288.  
  289. /******************************Public*Routine******************************\
  290. * CloseMovie
  291. *
  292. \**************************************************************************/
  293. DWORD
  294. CMpegMovie::CloseMovie(
  295.     )
  296. {
  297.     m_Mode = MOVIE_NOTOPENED;
  298.  
  299.     if(m_Mc)
  300.     {
  301.         if(m_Me)
  302.         {
  303.             m_MediaEvent = NULL;
  304.             m_Me->Release();
  305.             m_Me = NULL;
  306.         }
  307.  
  308.         if(m_pMixControl)
  309.         {
  310.             m_pMixControl->Release();
  311.             m_pMixControl = NULL;
  312.         }
  313.  
  314.         if(m_Ms)
  315.         {
  316.             m_Ms->Release();
  317.             m_Ms = NULL;
  318.         }
  319.  
  320.         if(m_Wc)
  321.         {
  322.             m_Wc->Release();
  323.             m_Wc = NULL;
  324.         }
  325.  
  326.         m_Mc->Release();
  327.         m_Mc = NULL;
  328.  
  329.         if(m_Gb)
  330.         {
  331.             m_Gb->Release();
  332.             m_Gb = NULL;
  333.         }
  334.  
  335.         if(m_Fg)
  336.         {
  337.             m_Fg->Release();
  338.             m_Fg = NULL;
  339.         }
  340.     }
  341.  
  342.     QzUninitialize();
  343.     return 0L;
  344. }
  345.  
  346.  
  347. /******************************Public*Routine******************************\
  348. * CMpegMovie::GetNativeMovieSize
  349. *
  350. \**************************************************************************/
  351. BOOL
  352. CMpegMovie::GetNativeMovieSize(
  353.     LONG *pcx,
  354.     LONG *pcy
  355.     )
  356. {
  357.     BOOL    bRet = FALSE;
  358.     if(m_Wc)
  359.     {
  360.         bRet = (m_Wc->GetNativeVideoSize(pcx, pcy, NULL, NULL) == S_OK);
  361.     }
  362.  
  363.     return bRet;
  364. }
  365.  
  366.  
  367. /******************************Public*Routine******************************\
  368. * GetMoviePosition
  369. *
  370. \**************************************************************************/
  371. BOOL
  372. CMpegMovie::GetMoviePosition(
  373.     LONG *px,
  374.     LONG *py,
  375.     LONG *pcx,
  376.     LONG *pcy
  377.     )
  378. {
  379.     BOOL    bRet = FALSE;
  380.  
  381.     if(m_Wc)
  382.     {
  383.         RECT src={0}, dest={0};
  384.         HRESULT hr = m_Wc->GetVideoPosition(&src, &dest);
  385.         *px = dest.left;
  386.         *py = dest.right;
  387.         *pcx = dest.right - dest.left;
  388.         *pcy = dest.bottom - dest.top;
  389.     }
  390.     
  391.     return bRet;
  392. }
  393.  
  394. /******************************Public*Routine******************************\
  395. * PutMoviePosition
  396. *
  397. \**************************************************************************/
  398. BOOL
  399. CMpegMovie::PutMoviePosition(
  400.     LONG x,
  401.     LONG y,
  402.     LONG cx,
  403.     LONG cy
  404.     )
  405. {
  406.     BOOL    bRet = FALSE;
  407.  
  408.     RECT rc;
  409.     SetRect(&rc, x, y, x + cx, y + cy);
  410.     if(m_Wc)
  411.     {
  412.         bRet = (m_Wc->SetVideoPosition(NULL, &rc) == S_OK);
  413.     }
  414.  
  415.     return bRet;
  416. }
  417.  
  418.  
  419. /******************************Public*Routine******************************\
  420. * PlayMovie
  421. *
  422. \**************************************************************************/
  423. BOOL
  424. CMpegMovie::PlayMovie(
  425.     )
  426. {
  427.     REFTIME rt, rtAbs, rtDur;
  428.     HRESULT hr=S_OK;
  429.  
  430.     rt = GetCurrentPosition();
  431.     rtDur = GetDuration();
  432.  
  433.     //
  434.     // If we are near the end of the movie seek to the start, otherwise
  435.     // stay where we are.
  436.     //
  437.     rtAbs = rt - rtDur;
  438.     if(rtAbs < (REFTIME)0)
  439.     {
  440.         rtAbs = -rtAbs;
  441.     }
  442.  
  443.     if(rtAbs < (REFTIME)1)
  444.     {
  445.         SeekToPosition((REFTIME)0,FALSE);
  446.     }
  447.  
  448.     //
  449.     // Change mode after setting m_Mode but before starting the graph
  450.     //
  451.     m_Mode = MOVIE_PLAYING;
  452.     hr = m_Mc->Run();
  453.     return TRUE;
  454. }
  455.  
  456.  
  457. /******************************Public*Routine******************************\
  458. * PauseMovie
  459. *
  460. \**************************************************************************/
  461. BOOL
  462. CMpegMovie::PauseMovie(
  463.     )
  464. {
  465.     m_Mode = MOVIE_PAUSED;
  466.  
  467.     HRESULT hr = m_Mc->Pause();
  468.     return TRUE;
  469. }
  470.  
  471.  
  472. /******************************Public*Routine******************************\
  473. * GetStateMovie
  474. *
  475. \**************************************************************************/
  476.  
  477. OAFilterState
  478. CMpegMovie::GetStateMovie(
  479.     )
  480. {
  481.     OAFilterState State;
  482.  
  483.     HRESULT hr = m_Mc->GetState(INFINITE,&State);
  484.     return State;
  485. }
  486.  
  487.  
  488. /******************************Public*Routine******************************\
  489. * StopMovie
  490. *
  491. \**************************************************************************/
  492. BOOL
  493. CMpegMovie::StopMovie(
  494.     )
  495. {
  496.     m_Mode = MOVIE_STOPPED;
  497.     HRESULT hr = m_Mc->Stop();
  498.     return TRUE;
  499. }
  500.  
  501.  
  502. /******************************Public*Routine******************************\
  503. * StatusMovie
  504. *
  505. \**************************************************************************/
  506. EMpegMovieMode
  507. CMpegMovie::StatusMovie(
  508.     )
  509. {
  510.     if(m_Mc)
  511.     {
  512.         FILTER_STATE    fs;
  513.         HRESULT         hr;
  514.  
  515.         hr = m_Mc->GetState(100, (OAFilterState *)&fs);
  516.  
  517.         // Don't know what the state is so just stay at old state.
  518.         if(hr == VFW_S_STATE_INTERMEDIATE)
  519.         {
  520.             return m_Mode;
  521.         }
  522.  
  523.         switch(fs)
  524.         {
  525.             case State_Stopped:
  526.                 m_Mode = MOVIE_STOPPED;
  527.                 break;
  528.  
  529.             case State_Paused:
  530.                 m_Mode = MOVIE_PAUSED;
  531.                 break;
  532.  
  533.             case State_Running:
  534.                 m_Mode = MOVIE_PLAYING;
  535.                 break;
  536.         }
  537.     }
  538.  
  539.     return m_Mode;
  540. }
  541.  
  542.  
  543. /******************************Public*Routine******************************\
  544. * CanMovieFrameStep
  545. *
  546. \**************************************************************************/
  547. BOOL
  548. CMpegMovie::CanMovieFrameStep()
  549. {
  550.     IVideoFrameStep* lpFS;
  551.     HRESULT hr;
  552.  
  553.     hr = m_Fg->QueryInterface(__uuidof(IVideoFrameStep), (LPVOID *)&lpFS);
  554.     if(SUCCEEDED(hr))
  555.     {
  556.         hr = lpFS->CanStep(0L, NULL);
  557.         lpFS->Release();
  558.     }
  559.  
  560.     return SUCCEEDED(hr);
  561. }
  562.  
  563.  
  564. /******************************Public*Routine******************************\
  565. * FrameStepMovie
  566. *
  567. \**************************************************************************/
  568. BOOL
  569. CMpegMovie::FrameStepMovie()
  570. {
  571.     IVideoFrameStep* lpFS;
  572.     HRESULT hr;
  573.  
  574.     hr = m_Fg->QueryInterface(__uuidof(IVideoFrameStep), (LPVOID *)&lpFS);
  575.     if(SUCCEEDED(hr))
  576.     {
  577.         FrameStepCount++;
  578.  
  579.         hr = lpFS->Step(1, NULL);
  580.         lpFS->Release();
  581.     }
  582.  
  583.     return SUCCEEDED(hr);
  584. }
  585.  
  586.  
  587. /******************************Public*Routine******************************\
  588. * GetMediaEventHandle
  589. *
  590. * Returns the IMediaEvent event hamdle for the filter graph iff the
  591. * filter graph exists.
  592. *
  593. \**************************************************************************/
  594. HANDLE
  595. CMpegMovie::GetMovieEventHandle(
  596.     )
  597. {
  598.     HRESULT     hr;
  599.  
  600.     if(m_Me != NULL)
  601.     {
  602.         if(m_MediaEvent == NULL)
  603.         {
  604.             hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
  605.         }
  606.     }
  607.     else
  608.     {
  609.         m_MediaEvent = NULL;
  610.     }
  611.  
  612.     return m_MediaEvent;
  613. }
  614.  
  615.  
  616. /******************************Public*Routine******************************\
  617. * GetMovieEventCode
  618. *
  619. \**************************************************************************/
  620. long
  621. CMpegMovie::GetMovieEventCode()
  622. {
  623.     HRESULT hr;
  624.     long    lEventCode;
  625.     LONG_PTR    lParam1, lParam2;
  626.  
  627.     if(m_Me != NULL)
  628.     {
  629.         hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  630.         if(SUCCEEDED(hr))
  631.         {
  632.             hr = m_Me->FreeEventParams(lEventCode, lParam1, lParam2);
  633.             return lEventCode;
  634.         }
  635.     }
  636.  
  637.     return 0L;
  638. }
  639.  
  640.  
  641. /******************************Public*Routine******************************\
  642. * GetDuration
  643. *
  644. * Returns the duration of the current movie
  645. *
  646. \**************************************************************************/
  647. REFTIME
  648. CMpegMovie::GetDuration()
  649. {
  650.     HRESULT hr;
  651.     LONGLONG Duration;
  652.  
  653.     // Should we seek using IMediaSelection
  654.     if(m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  655.     {
  656.         hr = m_Ms->GetDuration(&Duration);
  657.         if(SUCCEEDED(hr))
  658.         {
  659.             return double(Duration);
  660.         }
  661.     }
  662.     else if(m_Ms != NULL)
  663.     {
  664.         hr = m_Ms->GetDuration(&Duration);
  665.         if(SUCCEEDED(hr))
  666.         {
  667.             return double(Duration) / UNITS;
  668.         }
  669.     }
  670.     return 0;
  671. }
  672.  
  673.  
  674. /******************************Public*Routine******************************\
  675. * GetCurrentPosition
  676. *
  677. * Returns the duration of the current movie
  678. *
  679. \**************************************************************************/
  680. REFTIME
  681. CMpegMovie::GetCurrentPosition()
  682. {
  683.     REFTIME rt = (REFTIME)0;
  684.     HRESULT hr;
  685.     LONGLONG Position;
  686.  
  687.     // Should we return a media position
  688.     if(m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  689.     {
  690.         hr = m_Ms->GetPositions(&Position, NULL);
  691.         if(SUCCEEDED(hr))
  692.         {
  693.             return double(Position);
  694.         }
  695.     }
  696.     else if(m_Ms != NULL)
  697.     {
  698.         hr = m_Ms->GetPositions(&Position, NULL);
  699.         if(SUCCEEDED(hr))
  700.         {
  701.             return double(Position) / UNITS;
  702.         }
  703.     }
  704.     return rt;
  705. }
  706.  
  707.  
  708. /*****************************Private*Routine******************************\
  709. * SeekToPosition
  710. *
  711. \**************************************************************************/
  712. BOOL
  713. CMpegMovie::SeekToPosition(
  714.     REFTIME rt,
  715.     BOOL bFlushData
  716.     )
  717. {
  718.     HRESULT hr;
  719.     LONGLONG llTime = LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt );
  720.  
  721.     if(m_Ms != NULL)
  722.     {
  723.         FILTER_STATE fs;
  724.         hr = m_Mc->GetState(100, (OAFilterState *)&fs);
  725.  
  726.         hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
  727.  
  728.         // This gets new data through to the renderers
  729.         if(fs == State_Stopped && bFlushData)
  730.         {
  731.             hr = m_Mc->Pause();
  732.             hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
  733.             hr = m_Mc->Stop();
  734.         }
  735.  
  736.         if(SUCCEEDED(hr))
  737.         {
  738.             return TRUE;
  739.         }
  740.     }
  741.     return FALSE;
  742. }
  743.  
  744.  
  745. /*****************************Public*Routine******************************\
  746. * FindInterfaceFromFilterGraph
  747. *
  748. \**************************************************************************/
  749. HRESULT
  750. CMpegMovie::FindInterfaceFromFilterGraph(
  751.     REFIID iid, // interface to look for
  752.     LPVOID *lp  // place to return interface pointer in
  753.     )
  754. {
  755.     IEnumFilters*   pEF;    
  756.     IBaseFilter*        pFilter;
  757.  
  758.     // Grab an enumerator for the filter graph.
  759.     HRESULT hr = m_Fg->EnumFilters(&pEF);
  760.  
  761.     if(FAILED(hr))
  762.     {
  763.         return hr;
  764.     }
  765.  
  766.     // Check out each filter.
  767.     while(pEF->Next(1, &pFilter, NULL) == S_OK)
  768.     {
  769.         hr = pFilter->QueryInterface(iid, lp);
  770.         pFilter->Release();
  771.  
  772.         if(SUCCEEDED(hr))
  773.         {
  774.             break;
  775.         }
  776.     }
  777.  
  778.     pEF->Release();
  779.  
  780.     return hr;
  781. }
  782.  
  783.  
  784. /*****************************Public*Routine******************************\
  785. * IsTimeFormatSupported
  786. *
  787. \**************************************************************************/
  788. BOOL
  789. CMpegMovie::IsTimeFormatSupported(GUID Format)
  790. {
  791.     return m_Ms != NULL && m_Ms->IsFormatSupported(&Format) == S_OK;
  792. }
  793.  
  794.  
  795. /*****************************Public*Routine******************************\
  796. * IsTimeSupported
  797. *
  798. \**************************************************************************/
  799. BOOL
  800. CMpegMovie::IsTimeSupported()
  801. {
  802.     return m_Ms != NULL && m_Ms->IsFormatSupported(&TIME_FORMAT_MEDIA_TIME) == S_OK;
  803. }
  804.  
  805.  
  806. /*****************************Public*Routine******************************\
  807. * GetTimeFormat
  808. *
  809. \**************************************************************************/
  810. GUID
  811. CMpegMovie::GetTimeFormat()
  812. {
  813.     return m_TimeFormat;
  814. }
  815.  
  816. /*****************************Public*Routine******************************\
  817. * SetTimeFormat
  818. *
  819. \**************************************************************************/
  820. BOOL
  821. CMpegMovie::SetTimeFormat(GUID Format)
  822. {
  823.     HRESULT hr = m_Ms->SetTimeFormat(&Format);
  824.     if(SUCCEEDED(hr))
  825.     {
  826.         m_TimeFormat = Format;
  827.     }
  828.     return SUCCEEDED(hr);
  829. }
  830.  
  831. /******************************Public*Routine******************************\
  832. * SetFocus
  833. *
  834. \**************************************************************************/
  835. void
  836. CMpegMovie::SetFocus()
  837. {
  838.     if(m_Fg)
  839.     {
  840.         // Tell the resource manager that we are being made active.  This
  841.         // will then cause the sound to switch to us.  This is especially
  842.         // important when playing audio only files as there is no other
  843.         // playback window.
  844.         IResourceManager* pResourceManager;
  845.  
  846.         HRESULT hr = m_Fg->QueryInterface(IID_IResourceManager, (void**)&pResourceManager);
  847.  
  848.         if(SUCCEEDED(hr))
  849.         {
  850.             IUnknown* pUnknown;
  851.  
  852.             hr = m_Fg->QueryInterface(IID_IUnknown, (void**)&pUnknown);
  853.  
  854.             if(SUCCEEDED(hr))
  855.             {
  856.                 hr = pResourceManager->SetFocus(pUnknown);
  857.                 pUnknown->Release();
  858.             }
  859.  
  860.             pResourceManager->Release();
  861.         }
  862.     }
  863. }
  864.  
  865.  
  866. /******************************Public*Routine******************************\
  867. * RepaintVideo
  868. *
  869. \**************************************************************************/
  870. BOOL
  871. CMpegMovie::RepaintVideo(
  872.     HWND hwnd,
  873.     HDC hdc
  874.     )
  875. {
  876.     BOOL bRet = FALSE;
  877.  
  878.     if(m_Wc)
  879.     {
  880.         bRet = (m_Wc->RepaintVideo(hwnd, hdc) == S_OK);
  881.     }
  882.  
  883.     return bRet;
  884. }
  885.  
  886.  
  887. /******************************Public*Routine******************************\
  888. * SetAppImage
  889. *
  890. \**************************************************************************/
  891. BOOL
  892. CMpegMovie::SetAppImage(
  893.     VMRALPHABITMAP* lpBmpInfo
  894.     )
  895. {
  896.     IVMRMixerBitmap* pBmp;
  897.     HRESULT hres = m_Wc->QueryInterface(IID_IVMRMixerBitmap, (LPVOID *)&pBmp);
  898.     if(SUCCEEDED(hres))
  899.     {
  900.         hres = pBmp->SetAlphaBitmap(lpBmpInfo);
  901.         pBmp->Release();
  902.     }
  903.  
  904.     return hres;
  905. }
  906.  
  907.  
  908. /******************************Public*Routine******************************\
  909. * UpdateAppImage
  910. *
  911. \**************************************************************************/
  912. BOOL
  913. CMpegMovie::UpdateAppImage(VMRALPHABITMAP* lpBmpInfo)
  914. {
  915.     IVMRMixerBitmap* pBmp;
  916.  
  917.     if (!m_Wc)
  918.         return FALSE;
  919.  
  920.     HRESULT hres = m_Wc->QueryInterface(IID_IVMRMixerBitmap, (LPVOID *)&pBmp);
  921.     if(SUCCEEDED(hres))
  922.     {
  923.         hres = pBmp->UpdateAlphaBitmapParameters(lpBmpInfo);
  924.         pBmp->Release();
  925.     }
  926.  
  927.     return hres;
  928. }
  929.  
  930.  
  931. /*****************************Private*Routine******************************\
  932. * SetBorderClr
  933. *
  934. \**************************************************************************/
  935. void
  936. CMpegMovie::SetBorderClr(COLORREF clr)
  937. {
  938.     m_Wc->SetBorderColor(clr);
  939. }
  940.  
  941.  
  942. /*****************************Private*Routine******************************\
  943. * VerifyVMR
  944. *
  945. \**************************************************************************/
  946. BOOL VerifyVMR(void)
  947. {
  948.     HRESULT hres;
  949.  
  950.     // Verify that the VMR exists on this system
  951.     IBaseFilter* pBF = NULL;
  952.     hres = CoCreateInstance(CLSID_VideoMixingRenderer,
  953.         NULL,
  954.         CLSCTX_INPROC,
  955.         IID_IBaseFilter,
  956.         (LPVOID *)&pBF);
  957.  
  958.     if(SUCCEEDED(hres))
  959.     {
  960.         pBF->Release();
  961.         return TRUE;
  962.     }
  963.     else
  964.     {
  965.         MessageBox(hwndApp, 
  966.             TEXT("This application requires the Video Mixing Renderer, which is present\r\n")
  967.             TEXT("only on Windows XP.\r\n\r\n")
  968.             TEXT("The Video Mixing Renderer (VMR) is also not enabled when viewing a \r\n")
  969.             TEXT("remote Windows XP machine through a Remote Desktop session.\r\n")
  970.             TEXT("You can run VMR-enabled applications only on your local machine.")
  971.             TEXT("\r\n\r\nThis sample will now exit."),
  972.             TEXT("Video Mixing Renderer capabilities are required"), MB_OK);
  973.  
  974.         return FALSE;
  975.     }
  976. }
  977.  
  978.  
  979.