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 / Cube / vcdplyer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  14.1 KB  |  568 lines

  1. //------------------------------------------------------------------------------
  2. // File: vcdplyer.cpp
  3. //
  4. // Desc: DirectShow sample code - VMR-based Cube video player
  5. //
  6. // Copyright (c) 1994-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <mmreg.h>
  11. #include <commctrl.h>
  12. #include <atlbase.h>
  13.  
  14. #include "project.h"
  15.  
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18.  
  19. #define MY_USER_ID 0x1234ACDE
  20.  
  21. /******************************Public*Routine******************************\
  22. * CMpegMovie
  23. *
  24. * Constructors and destructors
  25. *
  26. \**************************************************************************/
  27. CMpegMovie::CMpegMovie(HWND hwndApplication)
  28.     : CUnknown(NAME("Allocator Presenter"), NULL),
  29.       m_hwndApp(hwndApplication),
  30.       m_bInitCube(false),
  31.       m_pDDSTextureMirror(NULL),
  32.       m_MediaEvent(NULL),
  33.       m_Mode(MOVIE_NOTOPENED),
  34.       m_Fg(NULL),
  35.       m_Gb(NULL),
  36.       m_Mc(NULL),
  37.       m_Me(NULL),
  38.       m_Wc(NULL),
  39.       m_Ms(NULL),
  40.       m_dwRegister(0),
  41.       m_dwTexMirrorWidth(0),
  42.       m_dwTexMirrorHeight(0)
  43. {
  44.     AddRef();
  45. }
  46.  
  47. CMpegMovie::~CMpegMovie() {
  48.     ;
  49. }
  50.  
  51. /******************************Public*Routine******************************\
  52. * NonDelegatingQueryInterface
  53. *
  54. \**************************************************************************/
  55. STDMETHODIMP
  56. CMpegMovie::NonDelegatingQueryInterface(
  57.     REFIID riid,
  58.     void** ppv
  59.     )
  60. {
  61.     if (riid == IID_IVMRImageCompositor) {
  62.         return GetInterface((IVMRImageCompositor*)this, ppv);
  63.     }
  64.  
  65.     return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  66. }
  67.  
  68. /*****************************Private*Routine******************************\
  69. * SetRenderingMode
  70. *
  71. \**************************************************************************/
  72. HRESULT
  73. SetRenderingMode(
  74.     IBaseFilter* pBaseFilter,
  75.     VMRMode mode,
  76.     int iNumStreams,
  77.     IVMRImageCompositor* lpCompositor
  78.     )
  79. {
  80.     IVMRFilterConfig* pConfig = NULL;
  81.     HRESULT hr = S_OK;
  82.  
  83.     __try {
  84.  
  85.         CHECK_HR(hr = pBaseFilter->QueryInterface(IID_IVMRFilterConfig,
  86.                                                   (LPVOID *)&pConfig));
  87.  
  88.         //
  89.         // If you are pluging in a compositor you have to be in
  90.         // mixing mode, that is, iNumStreams needs to be greater than 0.
  91.         //
  92.         if (lpCompositor && iNumStreams < 1) {
  93.             iNumStreams = 1;
  94.         }
  95.  
  96.         if (iNumStreams) {
  97.             CHECK_HR(hr = pConfig->SetNumberOfStreams(iNumStreams));
  98.         }
  99.  
  100.         if (lpCompositor) {
  101.             CHECK_HR(hr = pConfig->SetImageCompositor(lpCompositor));
  102.         }
  103.  
  104.         CHECK_HR(hr = pConfig->SetRenderingMode(mode));
  105.     }
  106.     __finally {
  107.         RELEASE(pConfig);
  108.     }
  109.  
  110.     return hr;
  111. }
  112.  
  113.  
  114. /*****************************Private*Routine******************************\
  115. * AddVideoMixingRendererToFG()
  116. *
  117. \**************************************************************************/
  118. HRESULT
  119. CMpegMovie::AddVideoMixingRendererToFG(DWORD dwStreams)
  120. {
  121.     IBaseFilter* pBF = NULL;
  122.     HRESULT hRes = S_OK;
  123.  
  124.     __try {
  125.         CHECK_HR(hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
  126.                                 NULL, CLSCTX_INPROC,IID_IBaseFilter,
  127.                                 (LPVOID *)&pBF));
  128.  
  129.         CHECK_HR(hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer"));
  130.         CHECK_HR(hRes = SetRenderingMode(pBF, VMRMode_Windowless,
  131.                                          dwStreams, (IVMRImageCompositor*)this));
  132.  
  133.         CHECK_HR(hRes = pBF->QueryInterface(IID_IVMRWindowlessControl, (LPVOID *)&m_Wc));
  134.         CHECK_HR(hRes = m_Wc->SetVideoClippingWindow(m_hwndApp));
  135.  
  136.         CHECK_HR(hRes = m_Wc->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX));
  137.     }
  138.     __finally {
  139.         RELEASE(pBF);
  140.     }
  141.  
  142.     return hRes;
  143. }
  144.  
  145.  
  146. HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister) 
  147. {
  148.     IMoniker * pMoniker;
  149.     IRunningObjectTable *pROT;
  150.     if (FAILED(GetRunningObjectTable(0, &pROT))) {
  151.         return E_FAIL;
  152.     }
  153.     WCHAR wsz[256];
  154.     wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
  155.     HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
  156.     if (SUCCEEDED(hr)) {
  157.         hr = pROT->Register(0, pUnkGraph, pMoniker, pdwRegister);
  158.         pMoniker->Release();
  159.     }
  160.     pROT->Release();
  161.     return hr;
  162. }
  163.  
  164.  
  165. /******************************Public*Routine******************************\
  166. * OpenMovie
  167. *
  168. \**************************************************************************/
  169. HRESULT
  170. CMpegMovie::OpenMovie(
  171.     TCHAR achFileName[][MAX_PATH],
  172.     DWORD dwNumFiles
  173.     )
  174. {
  175.     USES_CONVERSION;
  176.     IUnknown        *pUnk = NULL;
  177.     HRESULT         hres = S_OK;
  178.     WCHAR           FileName[MAX_PATH];
  179.  
  180.     __try {
  181.         CHECK_HR(hres = CoCreateInstance(CLSID_FilterGraph,
  182.                                          NULL, CLSCTX_INPROC,
  183.                                          IID_IUnknown, (LPVOID *)&pUnk));
  184.         m_Mode = MOVIE_OPENED;
  185.         CHECK_HR(hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg));
  186.         CHECK_HR(hres = AddVideoMixingRendererToFG(4));
  187.  
  188.         CHECK_HR(hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb));
  189.  
  190.         AddToRot(m_Gb, &m_dwRegister);
  191.  
  192.         for (DWORD i = 0; i < dwNumFiles; i++)
  193.         {
  194.             wcscpy(FileName, T2W(achFileName[i]));
  195.             CHECK_HR(hres = m_Gb->RenderFile(FileName, NULL));
  196.         }
  197.         CHECK_HR(hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc));
  198.  
  199.         //
  200.         // Not being able to get the IMediaEvent interface does
  201.         // necessarly mean that we can't play the graph.
  202.         //
  203.         pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
  204.         GetMovieEventHandle();
  205.         pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
  206.     }
  207.     __finally {
  208.  
  209.         if (FAILED(hres)) {
  210.             RELEASE(m_Ms);
  211.             RELEASE(m_Me);
  212.             RELEASE(m_Mc);
  213.             RELEASE(m_Gb);
  214.             RELEASE(m_Fg);
  215.         }
  216.  
  217.         RELEASE(pUnk);
  218.     }
  219.  
  220.     return hres;
  221. }
  222.  
  223.  
  224. void RemoveFromRot(DWORD pdwRegister)
  225. {
  226.     IRunningObjectTable *pROT;
  227.     if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
  228.         pROT->Revoke(pdwRegister);
  229.         pROT->Release();
  230.     }
  231. }
  232.  
  233.  
  234. /******************************Public*Routine******************************\
  235. * CloseMovie
  236. *
  237. \**************************************************************************/
  238. DWORD
  239. CMpegMovie::CloseMovie(
  240.     )
  241. {
  242.     m_Mode = MOVIE_NOTOPENED;
  243.  
  244.     RELEASE(m_Ms);
  245.     RELEASE(m_Mc);
  246.     RELEASE(m_Me);
  247.     RELEASE(m_Gb);
  248.     RELEASE(m_Fg);
  249.     RELEASE(m_Wc);
  250.     RELEASE(m_pDDSTextureMirror);
  251.  
  252.     if (m_dwRegister)
  253.     {
  254.         RemoveFromRot(m_dwRegister);
  255.         m_dwRegister = 0;
  256.     }
  257.  
  258.     return 0L;
  259. }
  260.  
  261.  
  262. /******************************Public*Routine******************************\
  263. * RepaintVideo
  264. *
  265. \**************************************************************************/
  266. BOOL
  267. CMpegMovie::RepaintVideo(
  268.     HWND hwnd,
  269.     HDC hdc
  270.     )
  271. {
  272.     BOOL bRet = FALSE;
  273.     if (m_Wc) {
  274.         bRet = (m_Wc->RepaintVideo(hwnd, hdc) == S_OK);
  275.     }
  276.     return bRet;
  277. }
  278.  
  279.  
  280. /******************************Public*Routine******************************\
  281. * PutMoviePosition
  282. *
  283. \**************************************************************************/
  284. BOOL
  285. CMpegMovie::PutMoviePosition(
  286.     LONG x,
  287.     LONG y,
  288.     LONG cx,
  289.     LONG cy
  290.     )
  291. {
  292.     RECT rc;
  293.     SetRect(&rc, x, y, x + cx, y + cy);
  294.     BOOL bRet = (m_Wc->SetVideoPosition(NULL, &rc) == S_OK);
  295.     return bRet;
  296. }
  297.  
  298.  
  299.  
  300. /******************************Public*Routine******************************\
  301. * PlayMovie
  302. *
  303. \**************************************************************************/
  304. BOOL
  305. CMpegMovie::PlayMovie(
  306.     )
  307. {
  308.     REFTIME rt;
  309.     REFTIME rtAbs;
  310.     REFTIME rtDur;
  311.  
  312.     rt = GetCurrentPosition();
  313.     rtDur = GetDuration();
  314.  
  315.     //
  316.     // If we are near the end of the movie seek to the start, otherwise
  317.     // stay where we are.
  318.     //
  319.     rtAbs = rt - rtDur;
  320.     if (rtAbs < (REFTIME)0) {
  321.         rtAbs = -rtAbs;
  322.     }
  323.  
  324.     if (rtAbs <= (REFTIME)1) {
  325.         SeekToPosition((REFTIME)0,FALSE);
  326.     }
  327.  
  328.     //
  329.     // Change mode after setting m_Mode but before starting the graph
  330.     //
  331.     m_Mode = MOVIE_PLAYING;
  332.     HRESULT hr = m_Mc->Run();
  333.     ASSERT(SUCCEEDED(hr));
  334.     return TRUE;
  335. }
  336.  
  337.  
  338. /******************************Public*Routine******************************\
  339. * PauseMovie
  340. *
  341. \**************************************************************************/
  342. BOOL
  343. CMpegMovie::PauseMovie(
  344.     )
  345. {
  346.     m_Mode = MOVIE_PAUSED;
  347.     HRESULT hr = m_Mc->Pause();
  348.     ASSERT(SUCCEEDED(hr));
  349.     return TRUE;
  350. }
  351.  
  352.  
  353. /******************************Public*Routine******************************\
  354. * GetStateMovie
  355. *
  356. \**************************************************************************/
  357.  
  358. OAFilterState
  359. CMpegMovie::GetStateMovie(
  360.     )
  361. {
  362.     OAFilterState State;
  363.     HRESULT hr = m_Mc->GetState(INFINITE,&State);
  364.     ASSERT(SUCCEEDED(hr));
  365.     return State;
  366. }
  367.  
  368.  
  369. /******************************Public*Routine******************************\
  370. * StopMovie
  371. *
  372. \**************************************************************************/
  373. BOOL
  374. CMpegMovie::StopMovie(
  375.     )
  376. {
  377.     m_Mode = MOVIE_STOPPED;
  378.     HRESULT hr = m_Mc->Stop();
  379.     ASSERT(SUCCEEDED(hr));
  380.     return TRUE;
  381. }
  382.  
  383.  
  384. /******************************Public*Routine******************************\
  385. * GetMediaEventHandle
  386. *
  387. * Returns the IMediaEvent event hamdle for the filter graph iff the
  388. * filter graph exists.
  389. *
  390. \**************************************************************************/
  391. HANDLE
  392. CMpegMovie::GetMovieEventHandle(
  393.     )
  394. {
  395.     HRESULT hr;
  396.  
  397.     if (m_Me != NULL) {
  398.  
  399.         if ( m_MediaEvent == NULL) {
  400.             hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
  401.         }
  402.     }
  403.     else {
  404.         m_MediaEvent = NULL;
  405.     }
  406.  
  407.     return m_MediaEvent;
  408. }
  409.  
  410.  
  411. /******************************Public*Routine******************************\
  412. * GetMovieEventCode
  413. *
  414. \**************************************************************************/
  415. long
  416. CMpegMovie::GetMovieEventCode()
  417. {
  418.     HRESULT hr;
  419.     long    lEventCode;
  420.     LONG_PTR    lParam1, lParam2;
  421.  
  422.     if (m_Me != NULL) {
  423.         hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  424.         if(SUCCEEDED(hr))
  425.         {
  426.             hr = m_Me->FreeEventParams(lEventCode, lParam1, lParam2);
  427.             return lEventCode;
  428.         }
  429.     }
  430.  
  431.     return 0L;
  432. }
  433.  
  434.  
  435. /******************************Public*Routine******************************\
  436. * GetDuration
  437. *
  438. * Returns the duration of the current movie
  439. *
  440. \**************************************************************************/
  441. REFTIME
  442. CMpegMovie::GetDuration()
  443. {
  444.     HRESULT hr;
  445.     LONGLONG Duration;
  446.  
  447.     // Should we seek using IMediaSelection
  448.  
  449.     if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
  450.         hr = m_Ms->GetDuration(&Duration);
  451.         if (SUCCEEDED(hr)) {
  452.             return double(Duration);
  453.         }
  454.     } else if (m_Ms != NULL) {
  455.         hr = m_Ms->GetDuration(&Duration);
  456.         if (SUCCEEDED(hr)) {
  457.             return double(Duration) / UNITS;
  458.         }
  459.     }
  460.     return 0;
  461. }
  462.  
  463.  
  464. /******************************Public*Routine******************************\
  465. * GetCurrentPosition
  466. *
  467. * Returns the duration of the current movie
  468. *
  469. \**************************************************************************/
  470. REFTIME
  471. CMpegMovie::GetCurrentPosition()
  472. {
  473.     REFTIME rt = (REFTIME)0;
  474.     HRESULT hr;
  475.     LONGLONG Position;
  476.  
  477.     // Should we return a media position
  478.  
  479.     if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
  480.         hr = m_Ms->GetPositions(&Position, NULL);
  481.         if (SUCCEEDED(hr)) {
  482.             return double(Position);
  483.         }
  484.     } else if (m_Ms != NULL) {
  485.         hr = m_Ms->GetPositions(&Position, NULL);
  486.         if (SUCCEEDED(hr)) {
  487.             return double(Position) / UNITS;
  488.         }
  489.     }
  490.     return rt;
  491. }
  492.  
  493.  
  494. /*****************************Private*Routine******************************\
  495. * SeekToPosition
  496. *
  497. \**************************************************************************/
  498. BOOL
  499. CMpegMovie::SeekToPosition(
  500.     REFTIME rt,
  501.     BOOL bFlushData
  502.     )
  503. {
  504.     HRESULT hr=S_OK;
  505.     LONGLONG llTime =
  506.         LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt);
  507.  
  508.     if (m_Ms != NULL) {
  509.  
  510.         FILTER_STATE fs;
  511.         hr = m_Mc->GetState(100, (OAFilterState *)&fs);
  512.  
  513.         hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
  514.  
  515.         // This gets new data through to the renderers
  516.         if (fs == State_Stopped && bFlushData){
  517.             hr = m_Mc->Pause();
  518.             hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
  519.             hr = m_Mc->Stop();
  520.         }
  521.  
  522.         if (SUCCEEDED(hr)) {
  523.             return TRUE;
  524.         }
  525.     }
  526.     return FALSE;
  527. }
  528.  
  529.  
  530. /*****************************Private*Routine******************************\
  531. * VerifyVMR
  532. *
  533. \**************************************************************************/
  534. BOOL VerifyVMR(void)
  535. {
  536.     HRESULT hres;
  537.  
  538.     // Verify that the VMR exists on this system
  539.     IBaseFilter* pBF = NULL;
  540.     hres = CoCreateInstance(CLSID_VideoMixingRenderer,
  541.         NULL,
  542.         CLSCTX_INPROC,
  543.         IID_IBaseFilter,
  544.         (LPVOID *)&pBF);
  545.     if(SUCCEEDED(hres))
  546.     {
  547.         pBF->Release();
  548.         return TRUE;
  549.     }
  550.     else
  551.     {
  552.         MessageBox(hwndApp, 
  553.             TEXT("This application requires the Video Mixing Renderer, which is present\r\n")
  554.             TEXT("only on Windows XP.\r\n\r\n")
  555.             TEXT("The Video Mixing Renderer (VMR) is also not enabled when viewing a \r\n")
  556.             TEXT("remote Windows XP machine through a Remote Desktop session.\r\n")
  557.             TEXT("You can run VMR-enabled applications only on your local machine.")
  558.             TEXT("\r\n\r\nThis sample will now exit."),
  559.             TEXT("Video Mixing Renderer capabilities are required"), MB_OK);
  560.  
  561.         return FALSE;
  562.     }
  563. }
  564.  
  565.  
  566.  
  567.  
  568.