/src/apps/mplayerc/EVRAllocatorPresenter.cpp

https://bitbucket.org/Tomasen/splayer/ · C++ · 2247 lines · 1768 code · 314 blank · 165 comment · 304 complexity · 8ff714a04570e941558c3fd88ff9b4c3 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * $Id: EVRAllocatorPresenter.cpp 1260 2009-08-30 07:09:32Z ar-jar $
  3. *
  4. * (C) 2006-2007 see AUTHORS
  5. *
  6. * This file is part of mplayerc.
  7. *
  8. * Mplayerc is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * Mplayerc is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "stdafx.h"
  23. #include "mplayerc.h"
  24. #include <atlbase.h>
  25. #include <atlcoll.h>
  26. #include "..\..\DSUtil\DSUtil.h"
  27. #include <Videoacc.h>
  28. #include <initguid.h>
  29. #include "..\..\SubPic\ISubPic.h"
  30. #include <d3d9.h>
  31. #include <d3dx9.h>
  32. #include <Vmr9.h>
  33. #include <evr.h>
  34. #include <mfapi.h>
  35. #include <Mferror.h>
  36. #include "..\..\SubPic\DX9SubPic.h"
  37. #include "IQTVideoSurface.h"
  38. #include <moreuuids.h>
  39. #include "MacrovisionKicker.h"
  40. #include "IPinHook.h"
  41. #include "PixelShaderCompiler.h"
  42. #include "MainFrm.h"
  43. #include "AllocatorCommon.h"
  44. #include "EVRAllocatorPresenter.h"
  45. //#define SVP_LogMsg5 __noop
  46. //#define SVP_LogMsg6 __noop
  47. typedef enum
  48. {
  49. MSG_MIXERIN,
  50. MSG_MIXEROUT
  51. } EVR_STATS_MSG;
  52. // dxva.dll
  53. typedef HRESULT (__stdcall *PTR_DXVA2CreateDirect3DDeviceManager9)(UINT* pResetToken, IDirect3DDeviceManager9** ppDeviceManager);
  54. // mf.dll
  55. typedef HRESULT (__stdcall *PTR_MFCreatePresentationClock)(IMFPresentationClock** ppPresentationClock);
  56. // evr.dll
  57. typedef HRESULT (__stdcall *PTR_MFCreateDXSurfaceBuffer)(REFIID riid, IUnknown* punkSurface, BOOL fBottomUpWhenLinear, IMFMediaBuffer** ppBuffer);
  58. typedef HRESULT (__stdcall *PTR_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
  59. typedef HRESULT (__stdcall *PTR_MFCreateVideoMediaType)(const MFVIDEOFORMAT* pVideoFormat, IMFVideoMediaType** ppIVideoMediaType);
  60. // avrt.dll
  61. typedef HANDLE (__stdcall *PTR_AvSetMmThreadCharacteristicsW)(LPCWSTR TaskName, LPDWORD TaskIndex);
  62. typedef BOOL (__stdcall *PTR_AvSetMmThreadPriority)(HANDLE AvrtHandle, AVRT_PRIORITY Priority);
  63. typedef BOOL (__stdcall *PTR_AvRevertMmThreadCharacteristics)(HANDLE AvrtHandle);
  64. // Guid to tag IMFSample with DirectX surface index
  65. static const GUID GUID_SURFACE_INDEX = { 0x30c8e9f6, 0x415, 0x4b81, { 0xa3, 0x15, 0x1, 0xa, 0xc6, 0xa9, 0xda, 0x19 } };
  66. #define CheckHR(exp) {if(FAILED(hr = exp)) return hr;}
  67. MFOffset MakeOffset(float v)
  68. {
  69. MFOffset offset;
  70. offset.value = short(v);
  71. offset.fract = WORD(65536 * (v-offset.value));
  72. return offset;
  73. }
  74. MFVideoArea MakeArea(float x, float y, DWORD width, DWORD height)
  75. {
  76. MFVideoArea area;
  77. area.OffsetX = MakeOffset(x);
  78. area.OffsetY = MakeOffset(y);
  79. area.Area.cx = width;
  80. area.Area.cy = height;
  81. return area;
  82. }
  83. class CEVRAllocatorPresenter;
  84. class COuterEVR:
  85. public CUnknown,
  86. public IVMRffdshow9,
  87. public IVMRMixerBitmap9,
  88. public IBaseFilter
  89. {
  90. CComPtr<IUnknown> m_pEVR;
  91. VMR9AlphaBitmap *m_pVMR9AlphaBitmap;
  92. CEVRAllocatorPresenter *m_pAllocatorPresenter;
  93. public:
  94. // IBaseFilter
  95. virtual HRESULT STDMETHODCALLTYPE EnumPins(__out IEnumPins **ppEnum)
  96. {
  97. CComPtr<IBaseFilter> pEVRBase;
  98. if (m_pEVR)
  99. m_pEVR->QueryInterface(&pEVRBase);
  100. if (pEVRBase)
  101. return pEVRBase->EnumPins(ppEnum);
  102. return E_NOTIMPL;
  103. }
  104. virtual HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, __out IPin **ppPin)
  105. {
  106. CComPtr<IBaseFilter> pEVRBase;
  107. if (m_pEVR)
  108. m_pEVR->QueryInterface(&pEVRBase);
  109. if (pEVRBase)
  110. return pEVRBase->FindPin(Id, ppPin);
  111. return E_NOTIMPL;
  112. }
  113. virtual HRESULT STDMETHODCALLTYPE QueryFilterInfo(__out FILTER_INFO *pInfo)
  114. {
  115. CComPtr<IBaseFilter> pEVRBase;
  116. if (m_pEVR)
  117. m_pEVR->QueryInterface(&pEVRBase);
  118. if (pEVRBase)
  119. return pEVRBase->QueryFilterInfo(pInfo);
  120. return E_NOTIMPL;
  121. }
  122. virtual HRESULT STDMETHODCALLTYPE JoinFilterGraph(__in_opt IFilterGraph *pGraph, __in_opt LPCWSTR pName)
  123. {
  124. CComPtr<IBaseFilter> pEVRBase;
  125. if (m_pEVR)
  126. m_pEVR->QueryInterface(&pEVRBase);
  127. if (pEVRBase)
  128. return pEVRBase->JoinFilterGraph(pGraph, pName);
  129. return E_NOTIMPL;
  130. }
  131. virtual HRESULT STDMETHODCALLTYPE QueryVendorInfo(__out LPWSTR *pVendorInfo)
  132. {
  133. CComPtr<IBaseFilter> pEVRBase;
  134. if (m_pEVR)
  135. m_pEVR->QueryInterface(&pEVRBase);
  136. if (pEVRBase)
  137. return pEVRBase->QueryVendorInfo(pVendorInfo);
  138. return E_NOTIMPL;
  139. }
  140. virtual HRESULT STDMETHODCALLTYPE Stop( void)
  141. {
  142. CComPtr<IBaseFilter> pEVRBase;
  143. if (m_pEVR)
  144. m_pEVR->QueryInterface(&pEVRBase);
  145. if (pEVRBase)
  146. return pEVRBase->Stop();
  147. return E_NOTIMPL;
  148. }
  149. virtual HRESULT STDMETHODCALLTYPE Pause( void)
  150. {
  151. CComPtr<IBaseFilter> pEVRBase;
  152. if (m_pEVR)
  153. m_pEVR->QueryInterface(&pEVRBase);
  154. if (pEVRBase)
  155. return pEVRBase->Pause();
  156. return E_NOTIMPL;
  157. }
  158. virtual HRESULT STDMETHODCALLTYPE Run( REFERENCE_TIME tStart)
  159. {
  160. CComPtr<IBaseFilter> pEVRBase;
  161. if (m_pEVR)
  162. m_pEVR->QueryInterface(&pEVRBase);
  163. if (pEVRBase)
  164. return pEVRBase->Run(tStart);
  165. return E_NOTIMPL;
  166. }
  167. virtual HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, __out FILTER_STATE *State);
  168. virtual HRESULT STDMETHODCALLTYPE SetSyncSource(__in_opt IReferenceClock *pClock)
  169. {
  170. CComPtr<IBaseFilter> pEVRBase;
  171. if (m_pEVR)
  172. m_pEVR->QueryInterface(&pEVRBase);
  173. if (pEVRBase)
  174. return pEVRBase->SetSyncSource(pClock);
  175. return E_NOTIMPL;
  176. }
  177. virtual HRESULT STDMETHODCALLTYPE GetSyncSource(__deref_out_opt IReferenceClock **pClock)
  178. {
  179. CComPtr<IBaseFilter> pEVRBase;
  180. if (m_pEVR)
  181. m_pEVR->QueryInterface(&pEVRBase);
  182. if (pEVRBase)
  183. return pEVRBase->GetSyncSource(pClock);
  184. return E_NOTIMPL;
  185. }
  186. virtual HRESULT STDMETHODCALLTYPE GetClassID(__RPC__out CLSID *pClassID)
  187. {
  188. CComPtr<IBaseFilter> pEVRBase;
  189. if (m_pEVR)
  190. m_pEVR->QueryInterface(&pEVRBase);
  191. if (pEVRBase)
  192. return pEVRBase->GetClassID(pClassID);
  193. return E_NOTIMPL;
  194. }
  195. COuterEVR(const TCHAR* pName, LPUNKNOWN pUnk, HRESULT& hr, VMR9AlphaBitmap* pVMR9AlphaBitmap, CEVRAllocatorPresenter *pAllocatorPresenter) : CUnknown(pName, pUnk)
  196. {
  197. hr = m_pEVR.CoCreateInstance(CLSID_EnhancedVideoRenderer, GetOwner());
  198. m_pVMR9AlphaBitmap = pVMR9AlphaBitmap;
  199. m_pAllocatorPresenter = pAllocatorPresenter;
  200. }
  201. ~COuterEVR();
  202. DECLARE_IUNKNOWN;
  203. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv)
  204. {
  205. HRESULT hr;
  206. if(riid == __uuidof(IVMRMixerBitmap9))
  207. return GetInterface((IVMRMixerBitmap9*)this, ppv);
  208. if (riid == __uuidof(IBaseFilter))
  209. {
  210. return GetInterface((IBaseFilter*)this, ppv);
  211. }
  212. if (riid == __uuidof(IMediaFilter))
  213. {
  214. return GetInterface((IMediaFilter*)this, ppv);
  215. }
  216. if (riid == __uuidof(IPersist))
  217. {
  218. return GetInterface((IPersist*)this, ppv);
  219. }
  220. if (riid == __uuidof(IBaseFilter))
  221. {
  222. return GetInterface((IBaseFilter*)this, ppv);
  223. }
  224. hr = m_pEVR ? m_pEVR->QueryInterface(riid, ppv) : E_NOINTERFACE;
  225. if(m_pEVR && FAILED(hr))
  226. {
  227. if(riid == __uuidof(IVMRffdshow9)) // Support ffdshow queueing. We show ffdshow that this is patched Media Player Classic.
  228. return GetInterface((IVMRffdshow9*)this, ppv);
  229. }
  230. return SUCCEEDED(hr) ? hr : __super::NonDelegatingQueryInterface(riid, ppv);
  231. }
  232. // IVMRffdshow9
  233. STDMETHODIMP support_ffdshow()
  234. {
  235. queueu_ffdshow_support = true;
  236. return S_OK;
  237. }
  238. // IVMRMixerBitmap9
  239. STDMETHODIMP GetAlphaBitmapParameters(VMR9AlphaBitmap* pBmpParms);
  240. STDMETHODIMP SetAlphaBitmap(const VMR9AlphaBitmap* pBmpParms);
  241. STDMETHODIMP UpdateAlphaBitmapParameters(const VMR9AlphaBitmap* pBmpParms);
  242. };
  243. class CEVRAllocatorPresenter:
  244. public CDX9AllocatorPresenter,
  245. public IMFGetService,
  246. public IMFTopologyServiceLookupClient,
  247. public IMFVideoDeviceID,
  248. public IMFVideoPresenter,
  249. public IDirect3DDeviceManager9,
  250. public IMFAsyncCallback,
  251. public IQualProp,
  252. public IMFRateSupport,
  253. public IMFVideoDisplayControl,
  254. public IEVRTrustedVideoPlugin
  255. {
  256. public:
  257. CEVRAllocatorPresenter(HWND hWnd, HRESULT& hr );
  258. ~CEVRAllocatorPresenter(void);
  259. void ThreadBeginStreaming();
  260. DECLARE_IUNKNOWN;
  261. STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
  262. STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
  263. STDMETHODIMP_(bool) Paint(bool fAll);
  264. STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
  265. STDMETHODIMP InitializeDevice(AM_MEDIA_TYPE* pMediaType);
  266. // IMFClockStateSink
  267. STDMETHODIMP OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
  268. STDMETHODIMP STDMETHODCALLTYPE OnClockStop(MFTIME hnsSystemTime);
  269. STDMETHODIMP STDMETHODCALLTYPE OnClockPause(MFTIME hnsSystemTime);
  270. STDMETHODIMP STDMETHODCALLTYPE OnClockRestart(MFTIME hnsSystemTime);
  271. STDMETHODIMP STDMETHODCALLTYPE OnClockSetRate(MFTIME hnsSystemTime, float flRate);
  272. // IBaseFilter delegate
  273. bool GetState( DWORD dwMilliSecsTimeout, FILTER_STATE *State, HRESULT &_ReturnValue);
  274. // IQualProp (EVR statistics window). These are incompletely implemented currently
  275. STDMETHODIMP get_FramesDroppedInRenderer(int *pcFrames);
  276. STDMETHODIMP get_FramesDrawn(int *pcFramesDrawn);
  277. STDMETHODIMP get_AvgFrameRate(int *piAvgFrameRate);
  278. STDMETHODIMP get_Jitter(int *iJitter);
  279. STDMETHODIMP get_AvgSyncOffset(int *piAvg);
  280. STDMETHODIMP get_DevSyncOffset(int *piDev);
  281. // IMFRateSupport
  282. STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float *pflRate);
  283. STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float *pflRate);
  284. STDMETHODIMP IsRateSupported(BOOL fThin, float flRate, float *pflNearestSupportedRate);
  285. float GetMaxRate(BOOL bThin);
  286. // IMFVideoPresenter
  287. STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam);
  288. STDMETHODIMP GetCurrentMediaType(__deref_out IMFVideoMediaType **ppMediaType);
  289. // IMFTopologyServiceLookupClient
  290. STDMETHODIMP InitServicePointers(__in IMFTopologyServiceLookup *pLookup);
  291. STDMETHODIMP ReleaseServicePointers();
  292. // IMFVideoDeviceID
  293. STDMETHODIMP GetDeviceID(__out IID *pDeviceID);
  294. // IMFGetService
  295. STDMETHODIMP GetService (__RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID *ppvObject);
  296. // IMFAsyncCallback
  297. STDMETHODIMP GetParameters(__RPC__out DWORD *pdwFlags, /* [out] */ __RPC__out DWORD *pdwQueue);
  298. STDMETHODIMP Invoke(__RPC__in_opt IMFAsyncResult *pAsyncResult);
  299. // IMFVideoDisplayControl
  300. STDMETHODIMP GetNativeVideoSize(SIZE *pszVideo, SIZE *pszARVideo);
  301. STDMETHODIMP GetIdealVideoSize(SIZE *pszMin, SIZE *pszMax);
  302. STDMETHODIMP SetVideoPosition(const MFVideoNormalizedRect *pnrcSource, const LPRECT prcDest);
  303. STDMETHODIMP GetVideoPosition(MFVideoNormalizedRect *pnrcSource, LPRECT prcDest);
  304. STDMETHODIMP SetAspectRatioMode(DWORD dwAspectRatioMode);
  305. STDMETHODIMP GetAspectRatioMode(DWORD *pdwAspectRatioMode);
  306. STDMETHODIMP SetVideoWindow(HWND hwndVideo);
  307. STDMETHODIMP GetVideoWindow(HWND *phwndVideo);
  308. STDMETHODIMP RepaintVideo( void);
  309. STDMETHODIMP GetCurrentImage(BITMAPINFOHEADER *pBih, BYTE **pDib, DWORD *pcbDib, LONGLONG *pTimeStamp);
  310. STDMETHODIMP SetBorderColor(COLORREF Clr);
  311. STDMETHODIMP GetBorderColor(COLORREF *pClr);
  312. STDMETHODIMP SetRenderingPrefs(DWORD dwRenderFlags);
  313. STDMETHODIMP GetRenderingPrefs(DWORD *pdwRenderFlags);
  314. STDMETHODIMP SetFullscreen(BOOL fFullscreen);
  315. STDMETHODIMP GetFullscreen(BOOL *pfFullscreen);
  316. // IEVRTrustedVideoPlugin
  317. STDMETHODIMP IsInTrustedVideoMode(BOOL *pYes);
  318. STDMETHODIMP CanConstrict(BOOL *pYes);
  319. STDMETHODIMP SetConstriction(DWORD dwKPix);
  320. STDMETHODIMP DisableImageExport(BOOL bDisable);
  321. // IDirect3DDeviceManager9
  322. STDMETHODIMP ResetDevice(IDirect3DDevice9 *pDevice,UINT resetToken);
  323. STDMETHODIMP OpenDeviceHandle(HANDLE *phDevice);
  324. STDMETHODIMP CloseDeviceHandle(HANDLE hDevice);
  325. STDMETHODIMP TestDevice(HANDLE hDevice);
  326. STDMETHODIMP LockDevice(HANDLE hDevice, IDirect3DDevice9 **ppDevice, BOOL fBlock);
  327. STDMETHODIMP UnlockDevice(HANDLE hDevice, BOOL fSaveState);
  328. STDMETHODIMP GetVideoService(HANDLE hDevice, REFIID riid, void **ppService);
  329. protected:
  330. void OnResetDevice();
  331. MFCLOCK_STATE m_LastClockState;
  332. private:
  333. typedef enum
  334. {
  335. Started = State_Running,
  336. Stopped = State_Stopped,
  337. Paused = State_Paused,
  338. Shutdown = State_Running + 1
  339. } RENDER_STATE;
  340. COuterEVR *m_pOuterEVR;
  341. CComPtr<IMFClock> m_pClock;
  342. CComPtr<IDirect3DDeviceManager9> m_pD3DManager;
  343. CComPtr<IMFTransform> m_pMixer;
  344. CComPtr<IMediaEventSink> m_pSink;
  345. CComPtr<IMFVideoMediaType> m_pMediaType;
  346. MFVideoAspectRatioMode m_dwVideoAspectRatioMode;
  347. MFVideoRenderPrefs m_dwVideoRenderPrefs;
  348. COLORREF m_BorderColor;
  349. HANDLE m_hEvtQuit; // Stop rendering thread event
  350. HANDLE m_hEvtSampleNotify; // Stop rendering thread event
  351. bool m_SampleNotified;
  352. bool m_HasSampleNotified;
  353. bool m_bEvtQuit;
  354. HANDLE m_hEvtFlush; // Discard all buffers
  355. bool m_bEvtFlush;
  356. HANDLE m_hEvtRenderStart;
  357. bool m_bUseInternalTimer;
  358. int32 m_LastSetOutputRange;
  359. bool m_bPendingRenegotiate;
  360. bool m_bPendingMediaFinished;
  361. bool m_bPrerolled; // true if first sample has been displayed.
  362. HANDLE m_hRenderThread;
  363. HANDLE m_hMixerThread;
  364. RENDER_STATE m_nRenderState;
  365. CCritSec m_SampleQueueLock;
  366. // CCritSec m_FreeSampleQueueLock;
  367. // CCritSec m_ScheduleSampleQueueLock;
  368. CCritSec m_ImageProcessingLock;
  369. CInterfaceList<IMFSample, &IID_IMFSample> m_FreeSamples;
  370. CInterfaceList<IMFSample, &IID_IMFSample> m_ScheduledSamples;
  371. IMFSample *m_pCurrentDisplaydSample;
  372. UINT m_nResetToken;
  373. int m_nStepCount;
  374. HRESULT ProcessOutputSafe( DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus) ;
  375. bool GetSampleFromMixer();
  376. void MixerThread();
  377. static DWORD WINAPI MixerThreadStatic(LPVOID lpParam);
  378. void RenderThread();
  379. static DWORD WINAPI RenderThreadStatic(LPVOID lpParam);
  380. void StartWorkerThreads();
  381. void StopWorkerThreads();
  382. HRESULT CheckShutdown() const;
  383. void CompleteFrameStep(bool bCancel);
  384. void RemoveAllSamples();
  385. HRESULT BeginStreaming();
  386. HRESULT GetFreeSample(IMFSample** ppSample);
  387. HRESULT GetScheduledSample(IMFSample** ppSample, int &_Count);
  388. void MoveToFreeList(IMFSample* pSample, bool bTail);
  389. void MoveToScheduledList(IMFSample* pSample, bool _bSorted);
  390. void FlushSamples();
  391. void FlushSamplesInternal();
  392. HRESULT RenegotiateMediaType();
  393. HRESULT IsMediaTypeSupported(IMFMediaType* pMixerType);
  394. HRESULT CreateProposedOutputType(IMFMediaType* pMixerType, IMFMediaType** pType);
  395. HRESULT SetMediaType(IMFMediaType* pType);
  396. // Functions pointers for Vista/.NET3 specific library
  397. PTR_DXVA2CreateDirect3DDeviceManager9 pfDXVA2CreateDirect3DDeviceManager9;
  398. PTR_MFCreateDXSurfaceBuffer pfMFCreateDXSurfaceBuffer;
  399. PTR_MFCreateVideoSampleFromSurface pfMFCreateVideoSampleFromSurface;
  400. PTR_MFCreateVideoMediaType pfMFCreateVideoMediaType;
  401. PTR_AvSetMmThreadCharacteristicsW pfAvSetMmThreadCharacteristicsW;
  402. PTR_AvSetMmThreadPriority pfAvSetMmThreadPriority;
  403. PTR_AvRevertMmThreadCharacteristics pfAvRevertMmThreadCharacteristics;
  404. };
  405. HRESULT STDMETHODCALLTYPE COuterEVR::GetState( DWORD dwMilliSecsTimeout, __out FILTER_STATE *State)
  406. {
  407. HRESULT ReturnValue;
  408. CComPtr<IBaseFilter> pEVRBase;
  409. if (m_pEVR)
  410. m_pEVR->QueryInterface(&pEVRBase);
  411. if (pEVRBase)
  412. return pEVRBase->GetState(dwMilliSecsTimeout, State);
  413. return E_NOTIMPL;
  414. }
  415. STDMETHODIMP COuterEVR::GetAlphaBitmapParameters(VMR9AlphaBitmap* pBmpParms)
  416. {
  417. CheckPointer(pBmpParms, E_POINTER);
  418. CAutoLock BitMapLock(&m_pAllocatorPresenter->m_VMR9AlphaBitmapLock);
  419. memcpy (pBmpParms, m_pVMR9AlphaBitmap, sizeof(VMR9AlphaBitmap));
  420. return S_OK;
  421. }
  422. STDMETHODIMP COuterEVR::SetAlphaBitmap(const VMR9AlphaBitmap* pBmpParms)
  423. {
  424. CheckPointer(pBmpParms, E_POINTER);
  425. CAutoLock BitMapLock(&m_pAllocatorPresenter->m_VMR9AlphaBitmapLock);
  426. memcpy (m_pVMR9AlphaBitmap, pBmpParms, sizeof(VMR9AlphaBitmap));
  427. m_pVMR9AlphaBitmap->dwFlags |= VMRBITMAP_UPDATE;
  428. m_pAllocatorPresenter->UpdateAlphaBitmap();
  429. return S_OK;
  430. }
  431. STDMETHODIMP COuterEVR::UpdateAlphaBitmapParameters(const VMR9AlphaBitmap* pBmpParms)
  432. {
  433. CheckPointer(pBmpParms, E_POINTER);
  434. CAutoLock BitMapLock(&m_pAllocatorPresenter->m_VMR9AlphaBitmapLock);
  435. memcpy (m_pVMR9AlphaBitmap, pBmpParms, sizeof(VMR9AlphaBitmap));
  436. m_pVMR9AlphaBitmap->dwFlags |= VMRBITMAP_UPDATE;
  437. m_pAllocatorPresenter->UpdateAlphaBitmap();
  438. return S_OK;
  439. }
  440. COuterEVR::~COuterEVR()
  441. {
  442. }
  443. CString GetWindowsErrorMessage(HRESULT _Error, HMODULE _Module);
  444. HRESULT CreateEVR(const CLSID& clsid, HWND hWnd, ISubPicAllocatorPresenterRender** ppAP)
  445. {
  446. HRESULT hr = E_FAIL;
  447. if (clsid == CLSID_EVRAllocatorPresenter)
  448. {
  449. CString Error;
  450. *ppAP = DNew CEVRAllocatorPresenter(hWnd, hr );
  451. (*ppAP)->AddRef();
  452. if(FAILED(hr))
  453. {
  454. Error += L"\n";
  455. Error += GetWindowsErrorMessage(hr, NULL);
  456. //MessageBox(hWnd, Error, L"Error creating EVR Custom renderer", MB_OK | MB_ICONERROR);
  457. (*ppAP)->Release();
  458. *ppAP = NULL;
  459. }
  460. else if (!Error.IsEmpty())
  461. {
  462. //MessageBox(hWnd, Error, L"Warning creating EVR Custom renderer", MB_OK|MB_ICONWARNING);
  463. }
  464. }
  465. return hr;
  466. }
  467. CEVRAllocatorPresenter::CEVRAllocatorPresenter(HWND hWnd, HRESULT& hr )
  468. : CDX9AllocatorPresenter(hWnd, hr, true )
  469. {
  470. HMODULE hLib;
  471. AppSettings& s = AfxGetAppSettings();
  472. m_nResetToken = 0;
  473. m_hRenderThread = INVALID_HANDLE_VALUE;
  474. m_hMixerThread= INVALID_HANDLE_VALUE;
  475. m_hEvtFlush = INVALID_HANDLE_VALUE;
  476. m_hEvtQuit = INVALID_HANDLE_VALUE;
  477. m_hEvtSampleNotify = INVALID_HANDLE_VALUE;
  478. m_bEvtQuit = 0;
  479. m_hEvtRenderStart = INVALID_HANDLE_VALUE;
  480. m_SampleNotified = true;
  481. m_HasSampleNotified = 0;
  482. m_bEvtFlush = 0;
  483. m_bNeedPendingResetDevice = true;
  484. if (FAILED (hr))
  485. {
  486. //_Error += L"DX9AllocatorPresenter failed\n";
  487. return;
  488. }
  489. // Load EVR specifics DLLs
  490. hLib = LoadLibrary (L"dxva2.dll");
  491. pfDXVA2CreateDirect3DDeviceManager9 = hLib ? (PTR_DXVA2CreateDirect3DDeviceManager9) GetProcAddress (hLib, "DXVA2CreateDirect3DDeviceManager9") : NULL;
  492. // Load EVR functions
  493. hLib = LoadLibrary (L"evr.dll");
  494. pfMFCreateDXSurfaceBuffer = hLib ? (PTR_MFCreateDXSurfaceBuffer)GetProcAddress (hLib, "MFCreateDXSurfaceBuffer") : NULL;
  495. pfMFCreateVideoSampleFromSurface = hLib ? (PTR_MFCreateVideoSampleFromSurface)GetProcAddress (hLib, "MFCreateVideoSampleFromSurface") : NULL;
  496. pfMFCreateVideoMediaType = hLib ? (PTR_MFCreateVideoMediaType)GetProcAddress (hLib, "MFCreateVideoMediaType") : NULL;
  497. if (!pfDXVA2CreateDirect3DDeviceManager9 || !pfMFCreateDXSurfaceBuffer || !pfMFCreateVideoSampleFromSurface || !pfMFCreateVideoMediaType)
  498. {
  499. /*
  500. if (!pfDXVA2CreateDirect3DDeviceManager9)
  501. _Error += L"Could not find DXVA2CreateDirect3DDeviceManager9 (dxva2.dll)\n";
  502. if (!pfMFCreateDXSurfaceBuffer)
  503. _Error += L"Could not find MFCreateDXSurfaceBuffer (evr.dll)\n";
  504. if (!pfMFCreateVideoSampleFromSurface)
  505. _Error += L"Could not find MFCreateVideoSampleFromSurface (evr.dll)\n";
  506. if (!pfMFCreateVideoMediaType)
  507. _Error += L"Could not find MFCreateVideoMediaType (evr.dll)\n";*/
  508. hr = E_FAIL;
  509. return;
  510. }
  511. // Load Vista specific DLLs
  512. hLib = LoadLibrary (L"avrt.dll");
  513. pfAvSetMmThreadCharacteristicsW = hLib ? (PTR_AvSetMmThreadCharacteristicsW) GetProcAddress (hLib, "AvSetMmThreadCharacteristicsW") : NULL;
  514. pfAvSetMmThreadPriority = hLib ? (PTR_AvSetMmThreadPriority) GetProcAddress (hLib, "AvSetMmThreadPriority") : NULL;
  515. pfAvRevertMmThreadCharacteristics = hLib ? (PTR_AvRevertMmThreadCharacteristics) GetProcAddress (hLib, "AvRevertMmThreadCharacteristics") : NULL;
  516. // Init DXVA manager
  517. hr = pfDXVA2CreateDirect3DDeviceManager9(&m_nResetToken, &m_pD3DManager);
  518. if (SUCCEEDED (hr))
  519. {
  520. hr = m_pD3DManager->ResetDevice(m_pD3DDev, m_nResetToken);
  521. if (!SUCCEEDED (hr))
  522. {
  523. //_Error += L"m_pD3DManager->ResetDevice failed\n";
  524. }
  525. }
  526. //else
  527. // _Error += L"DXVA2CreateDirect3DDeviceManager9 failed\n";
  528. CComPtr<IDirectXVideoDecoderService> pDecoderService;
  529. HANDLE hDevice;
  530. if (SUCCEEDED (m_pD3DManager->OpenDeviceHandle(&hDevice)) &&
  531. SUCCEEDED (m_pD3DManager->GetVideoService (hDevice, __uuidof(IDirectXVideoDecoderService), (void**)&pDecoderService)))
  532. {
  533. HookDirectXVideoDecoderService (pDecoderService);
  534. m_pD3DManager->CloseDeviceHandle (hDevice);
  535. }
  536. // Bufferize frame only with 3D texture
  537. if (s.iAPSurfaceUsage == VIDRNDT_AP_TEXTURE3D)
  538. m_nDXSurface = max (min (s.iEvrBuffers, MAX_PICTURE_SLOTS-2), 4);
  539. else
  540. m_nDXSurface = 1;
  541. m_nRenderState = Shutdown;
  542. m_bUseInternalTimer = false;
  543. m_LastSetOutputRange = -1;
  544. m_bPendingRenegotiate = false;
  545. m_bPendingMediaFinished = false;
  546. m_pCurrentDisplaydSample = NULL;
  547. m_nStepCount = 0;
  548. m_dwVideoAspectRatioMode = MFVideoARMode_PreservePicture;
  549. m_dwVideoRenderPrefs = (MFVideoRenderPrefs)0;
  550. m_BorderColor = RGB (0,0,0);
  551. m_pOuterEVR = NULL;
  552. m_bPrerolled = false;
  553. }
  554. CEVRAllocatorPresenter::~CEVRAllocatorPresenter(void)
  555. {
  556. StopWorkerThreads();
  557. m_pMediaType = NULL;
  558. m_pClock = NULL;
  559. m_pD3DManager = NULL;
  560. }
  561. HRESULT CEVRAllocatorPresenter::CheckShutdown() const
  562. {
  563. if (m_nRenderState == Shutdown) return MF_E_SHUTDOWN;
  564. else return S_OK;
  565. }
  566. void CEVRAllocatorPresenter::StartWorkerThreads()
  567. {
  568. DWORD dwThreadId;
  569. if (m_nRenderState == Shutdown)
  570. {
  571. m_hEvtQuit = CreateEvent(NULL, TRUE, FALSE, NULL);
  572. m_hEvtFlush = CreateEvent(NULL, TRUE, FALSE, NULL);
  573. m_hEvtRenderStart = CreateEvent(NULL, TRUE, FALSE, NULL);
  574. m_hEvtSampleNotify = CreateEvent(NULL, TRUE, FALSE, NULL);
  575. m_hMixerThread = ::CreateThread(NULL, 0, MixerThreadStatic, (LPVOID)this, 0, &dwThreadId);
  576. SetThreadPriority(m_hMixerThread, THREAD_PRIORITY_HIGHEST);
  577. m_hRenderThread = ::CreateThread(NULL, 0, RenderThreadStatic, (LPVOID)this, 0, &dwThreadId);
  578. SetThreadPriority(m_hRenderThread, THREAD_PRIORITY_TIME_CRITICAL);
  579. m_nRenderState = Stopped;
  580. }
  581. }
  582. void CEVRAllocatorPresenter::StopWorkerThreads()
  583. {
  584. if (m_nRenderState != Shutdown)
  585. {
  586. m_SampleNotified = true;
  587. SetEvent(m_hEvtSampleNotify);
  588. SetEvent (m_hEvtFlush);
  589. m_bEvtFlush = true;
  590. SetEvent (m_hEvtQuit);
  591. m_bEvtQuit = true;
  592. if ((m_hRenderThread != INVALID_HANDLE_VALUE) && (WaitForSingleObject (m_hRenderThread, 1000) == WAIT_TIMEOUT))
  593. {
  594. ASSERT (FALSE);
  595. TerminateThread (m_hRenderThread, 0xDEAD);
  596. }
  597. if (m_hRenderThread != INVALID_HANDLE_VALUE) CloseHandle (m_hRenderThread);
  598. if ((m_hMixerThread != INVALID_HANDLE_VALUE) && (WaitForSingleObject (m_hMixerThread, 1000) == WAIT_TIMEOUT))
  599. {
  600. ASSERT (FALSE);
  601. TerminateThread (m_hMixerThread, 0xDEAD);
  602. }
  603. if (m_hMixerThread != INVALID_HANDLE_VALUE) CloseHandle (m_hMixerThread);
  604. if (m_hEvtSampleNotify != INVALID_HANDLE_VALUE) CloseHandle (m_hEvtSampleNotify);
  605. if (m_hEvtFlush != INVALID_HANDLE_VALUE) CloseHandle (m_hEvtFlush);
  606. if (m_hEvtQuit != INVALID_HANDLE_VALUE) CloseHandle (m_hEvtQuit);
  607. if (m_hEvtRenderStart != INVALID_HANDLE_VALUE) CloseHandle (m_hEvtRenderStart);
  608. m_SampleNotified = true;
  609. m_HasSampleNotified = 0;
  610. m_bEvtFlush = false;
  611. m_bEvtQuit = false;
  612. }
  613. m_nRenderState = Shutdown;
  614. }
  615. STDMETHODIMP CEVRAllocatorPresenter::CreateRenderer(IUnknown** ppRenderer)
  616. {
  617. CheckPointer(ppRenderer, E_POINTER);
  618. *ppRenderer = NULL;
  619. HRESULT hr = E_FAIL;
  620. do
  621. {
  622. CMacrovisionKicker* pMK = DNew CMacrovisionKicker(NAME("CMacrovisionKicker"), NULL);
  623. CComPtr<IUnknown> pUnk = (IUnknown*)(INonDelegatingUnknown*)pMK;
  624. COuterEVR *pOuterEVR = DNew COuterEVR(NAME("COuterEVR"), pUnk, hr, &m_VMR9AlphaBitmap, this);
  625. m_pOuterEVR = pOuterEVR;
  626. pMK->SetInner((IUnknown*)(INonDelegatingUnknown*)pOuterEVR);
  627. CComQIPtr<IBaseFilter> pBF = pUnk;
  628. if (FAILED(hr)) break;
  629. // Set EVR custom presenter
  630. CComPtr<IMFVideoPresenter> pVP;
  631. CComPtr<IMFVideoRenderer> pMFVR;
  632. CComQIPtr<IMFGetService, &__uuidof(IMFGetService)> pMFGS = pBF;
  633. hr = pMFGS->GetService (MR_VIDEO_RENDER_SERVICE, IID_IMFVideoRenderer, (void**)&pMFVR);
  634. if(SUCCEEDED(hr)) hr = QueryInterface(__uuidof(IMFVideoPresenter), (void**)&pVP);
  635. if(SUCCEEDED(hr)) hr = pMFVR->InitializeRenderer(NULL, pVP);
  636. CComPtr<IPin> pPin = GetFirstPin(pBF);
  637. CComQIPtr<IMemInputPin> pMemInputPin = pPin;
  638. m_bUseInternalTimer = HookNewSegmentAndReceive((IPinC*)(IPin*)pPin, (IMemInputPinC*)(IMemInputPin*)pMemInputPin);
  639. if(FAILED(hr))
  640. *ppRenderer = NULL;
  641. else
  642. *ppRenderer = pBF.Detach();
  643. } while (0);
  644. return hr;
  645. }
  646. STDMETHODIMP_(bool) CEVRAllocatorPresenter::Paint(bool fAll)
  647. {
  648. return __super::Paint(fAll);
  649. }
  650. STDMETHODIMP CEVRAllocatorPresenter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  651. {
  652. ////SVP_LogMsg5(CStringFromGUID(riid));
  653. HRESULT hr;
  654. if(riid == __uuidof(IMFClockStateSink))
  655. hr = GetInterface((IMFClockStateSink*)this, ppv);
  656. else if(riid == __uuidof(IMFVideoPresenter))
  657. hr = GetInterface((IMFVideoPresenter*)this, ppv);
  658. else if(riid == __uuidof(IMFTopologyServiceLookupClient))
  659. hr = GetInterface((IMFTopologyServiceLookupClient*)this, ppv);
  660. else if(riid == __uuidof(IMFVideoDeviceID))
  661. hr = GetInterface((IMFVideoDeviceID*)this, ppv);
  662. else if(riid == __uuidof(IMFGetService))
  663. hr = GetInterface((IMFGetService*)this, ppv);
  664. else if(riid == __uuidof(IMFAsyncCallback))
  665. hr = GetInterface((IMFAsyncCallback*)this, ppv);
  666. else if(riid == __uuidof(IMFVideoDisplayControl))
  667. hr = GetInterface((IMFVideoDisplayControl*)this, ppv);
  668. else if(riid == __uuidof(IEVRTrustedVideoPlugin))
  669. hr = GetInterface((IEVRTrustedVideoPlugin*)this, ppv);
  670. else if(riid == IID_IQualProp)
  671. hr = GetInterface((IQualProp*)this, ppv);
  672. else if(riid == __uuidof(IMFRateSupport))
  673. hr = GetInterface((IMFRateSupport*)this, ppv);
  674. else if(riid == __uuidof(IDirect3DDeviceManager9))
  675. hr = m_pD3DManager->QueryInterface (__uuidof(IDirect3DDeviceManager9), (void**) ppv);
  676. else
  677. hr = __super::NonDelegatingQueryInterface(riid, ppv);
  678. return hr;
  679. }
  680. // IMFClockStateSink
  681. STDMETHODIMP CEVRAllocatorPresenter::OnClockStart(MFTIME hnsSystemTime, LONGLONG llClockStartOffset)
  682. {
  683. SetEvent(m_hEvtRenderStart);
  684. SVP_LogMsg5( L"CEVRAllocatorPresenter::OnClockStart");
  685. m_nRenderState = Started;
  686. return S_OK;
  687. }
  688. STDMETHODIMP CEVRAllocatorPresenter::OnClockStop(MFTIME hnsSystemTime)
  689. {
  690. SVP_LogMsg5( L"CEVRAllocatorPresenter::OnClockStop");
  691. m_nRenderState = Stopped;
  692. return S_OK;
  693. }
  694. STDMETHODIMP CEVRAllocatorPresenter::OnClockPause(MFTIME hnsSystemTime)
  695. {
  696. SVP_LogMsg5( L"CEVRAllocatorPresenter::OnClockPause");
  697. m_nRenderState = Paused;
  698. return S_OK;
  699. }
  700. STDMETHODIMP CEVRAllocatorPresenter::OnClockRestart(MFTIME hnsSystemTime)
  701. {
  702. SVP_LogMsg5( L"CEVRAllocatorPresenter::OnClockRestart");
  703. m_nRenderState = Started;
  704. return S_OK;
  705. }
  706. STDMETHODIMP CEVRAllocatorPresenter::OnClockSetRate(MFTIME hnsSystemTime, float flRate)
  707. {
  708. SVP_LogMsg5( L"CEVRAllocatorPresenter::OnClockSetRate");
  709. return E_NOTIMPL;
  710. }
  711. // IBaseFilter delegate
  712. bool CEVRAllocatorPresenter::GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State, HRESULT &_ReturnValue)
  713. {
  714. switch(m_nRenderState)
  715. {
  716. case Started: *State = State_Running; break;
  717. case Paused: *State = State_Paused; break;
  718. case Stopped: *State = State_Stopped; break;
  719. default: *State = State_Stopped; _ReturnValue = E_FAIL;
  720. }
  721. _ReturnValue = S_OK;
  722. return true;
  723. }
  724. // IQualProp
  725. STDMETHODIMP CEVRAllocatorPresenter::get_FramesDroppedInRenderer(int *pcFrames)
  726. {
  727. *pcFrames = m_pcFramesDropped;
  728. return S_OK;
  729. }
  730. STDMETHODIMP CEVRAllocatorPresenter::get_FramesDrawn(int *pcFramesDrawn)
  731. {
  732. *pcFramesDrawn = m_pcFramesDrawn;
  733. return S_OK;
  734. }
  735. STDMETHODIMP CEVRAllocatorPresenter::get_AvgFrameRate(int *piAvgFrameRate)
  736. {
  737. *piAvgFrameRate = (int)(m_fAvrFps * 100);
  738. return S_OK;
  739. }
  740. STDMETHODIMP CEVRAllocatorPresenter::get_Jitter(int *iJitter)
  741. {
  742. *iJitter = (int)((m_fJitterStdDev/10000.0) + 0.5);
  743. return S_OK;
  744. }
  745. STDMETHODIMP CEVRAllocatorPresenter::get_AvgSyncOffset(int *piAvg)
  746. {
  747. *piAvg = (int)((m_fSyncOffsetAvr/10000.0) + 0.5);
  748. return S_OK;
  749. }
  750. STDMETHODIMP CEVRAllocatorPresenter::get_DevSyncOffset(int *piDev)
  751. {
  752. *piDev = (int)((m_fSyncOffsetStdDev/10000.0) + 0.5);
  753. return S_OK;
  754. }
  755. // IMFRateSupport
  756. STDMETHODIMP CEVRAllocatorPresenter::GetSlowestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float *pflRate)
  757. {
  758. *pflRate = 0;
  759. return S_OK;
  760. }
  761. STDMETHODIMP CEVRAllocatorPresenter::GetFastestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float *pflRate)
  762. {
  763. HRESULT hr = S_OK;
  764. float fMaxRate = 0.0f;
  765. CAutoLock lock(this);
  766. CheckPointer(pflRate, E_POINTER);
  767. CheckHR(CheckShutdown());
  768. // Get the maximum forward rate.
  769. fMaxRate = GetMaxRate(fThin);
  770. // For reverse playback, swap the sign.
  771. if (eDirection == MFRATE_REVERSE)
  772. fMaxRate = -fMaxRate;
  773. *pflRate = fMaxRate;
  774. return hr;
  775. }
  776. STDMETHODIMP CEVRAllocatorPresenter::IsRateSupported(BOOL fThin, float flRate, float *pflNearestSupportedRate)
  777. {
  778. // fRate can be negative for reverse playback.
  779. // pfNearestSupportedRate can be NULL.
  780. CAutoLock lock(this);
  781. HRESULT hr = S_OK;
  782. float fMaxRate = 0.0f;
  783. float fNearestRate = flRate; // Default.
  784. CheckPointer (pflNearestSupportedRate, E_POINTER);
  785. CheckHR(hr = CheckShutdown());
  786. // Find the maximum forward rate.
  787. fMaxRate = GetMaxRate(fThin);
  788. if (fabsf(flRate) > fMaxRate)
  789. {
  790. // The (absolute) requested rate exceeds the maximum rate.
  791. hr = MF_E_UNSUPPORTED_RATE;
  792. // The nearest supported rate is fMaxRate.
  793. fNearestRate = fMaxRate;
  794. if (flRate < 0)
  795. {
  796. // For reverse playback, swap the sign.
  797. fNearestRate = -fNearestRate;
  798. }
  799. }
  800. // Return the nearest supported rate if the caller requested it.
  801. if (pflNearestSupportedRate != NULL) *pflNearestSupportedRate = fNearestRate;
  802. return hr;
  803. }
  804. float CEVRAllocatorPresenter::GetMaxRate(BOOL bThin)
  805. {
  806. float fMaxRate = FLT_MAX; // Default.
  807. UINT32 fpsNumerator = 0, fpsDenominator = 0;
  808. UINT MonitorRateHz = 0;
  809. if (!bThin && (m_pMediaType != NULL))
  810. {
  811. // Non-thinned: Use the frame rate and monitor refresh rate.
  812. // Frame rate:
  813. MFGetAttributeRatio(m_pMediaType, MF_MT_FRAME_RATE,
  814. &fpsNumerator, &fpsDenominator);
  815. // Monitor refresh rate:
  816. MonitorRateHz = m_uD3DRefreshRate; // D3DDISPLAYMODE
  817. if (fpsDenominator && fpsNumerator && MonitorRateHz)
  818. {
  819. // Max Rate = Refresh Rate / Frame Rate
  820. fMaxRate = (float)MulDiv(MonitorRateHz, fpsDenominator, fpsNumerator);
  821. }
  822. }
  823. return fMaxRate;
  824. }
  825. void CEVRAllocatorPresenter::CompleteFrameStep(bool bCancel)
  826. {
  827. if (m_nStepCount > 0)
  828. {
  829. if (bCancel || (m_nStepCount == 1))
  830. {
  831. m_pSink->Notify(EC_STEP_COMPLETE, bCancel ? TRUE : FALSE, 0);
  832. m_nStepCount = 0;
  833. }
  834. else
  835. m_nStepCount--;
  836. }
  837. }
  838. // IMFVideoPresenter
  839. STDMETHODIMP CEVRAllocatorPresenter::ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
  840. {
  841. HRESULT hr = S_OK;
  842. AppSettings& s = AfxGetAppSettings();
  843. //SVP_LogMsg6("ProcessMessage %x", eMessage);
  844. switch (eMessage)
  845. {
  846. case MFVP_MESSAGE_BEGINSTREAMING : // The EVR switched from stopped to paused. The presenter should allocate resources
  847. hr = BeginStreaming();
  848. break;
  849. case MFVP_MESSAGE_CANCELSTEP:
  850. CompleteFrameStep (true);
  851. break;
  852. case MFVP_MESSAGE_ENDOFSTREAM :
  853. m_bPendingMediaFinished = true;
  854. break;
  855. case MFVP_MESSAGE_ENDSTREAMING :
  856. {
  857. m_pGenlock->ResetTiming();
  858. m_pRefClock = NULL;
  859. }
  860. break;
  861. case MFVP_MESSAGE_FLUSH :
  862. SetEvent(m_hEvtFlush);
  863. ResetEvent(m_hEvtSampleNotify);
  864. if(m_HasSampleNotified)
  865. m_SampleNotified = 0;
  866. m_bEvtFlush = true;
  867. //SVP_LogMsg6("MFVP_MESSAGE_FLUSH");
  868. while (WaitForSingleObject(m_hEvtFlush, 1) == WAIT_OBJECT_0);
  869. //SVP_LogMsg6("MFVP_MESSAGE_FLUSH OUT");
  870. break;
  871. case MFVP_MESSAGE_INVALIDATEMEDIATYPE:
  872. m_bPendingRenegotiate = true;
  873. while (*((volatile bool *)&m_bPendingRenegotiate)) Sleep(1);
  874. break;
  875. case MFVP_MESSAGE_PROCESSINPUTNOTIFY:
  876. SetEvent(m_hEvtSampleNotify);
  877. m_HasSampleNotified = true;
  878. m_SampleNotified = true;
  879. //SVP_LogMsg6("MFVP_MESSAGE_PROCESSINPUTNOTIFY");
  880. //while (WaitForSingleObject(m_hEvtSampleNotify, 1) == WAIT_OBJECT_0);
  881. break;
  882. case MFVP_MESSAGE_STEP:
  883. m_nStepCount = ulParam;
  884. hr = S_OK;
  885. break;
  886. default :
  887. //SVP_LogMsg6("MFVP_MESSAGE_ UNKNOW MESSAGE %x", eMessage);
  888. ASSERT(FALSE);
  889. break;
  890. }
  891. return hr;
  892. }
  893. HRESULT CEVRAllocatorPresenter::IsMediaTypeSupported(IMFMediaType* pMixerType)
  894. {
  895. HRESULT hr;
  896. AM_MEDIA_TYPE* pAMMedia;
  897. UINT nInterlaceMode;
  898. CheckHR (pMixerType->GetRepresentation(FORMAT_VideoInfo2, (void**)&pAMMedia));
  899. CheckHR (pMixerType->GetUINT32 (MF_MT_INTERLACE_MODE, &nInterlaceMode));
  900. //SVP_LogMsg5(L"MF_MT_INTERLACE_MODE %d",nInterlaceMode);
  901. if ( (pAMMedia->majortype != MEDIATYPE_Video)) hr = MF_E_INVALIDMEDIATYPE;
  902. pMixerType->FreeRepresentation(FORMAT_VideoInfo2, (void*)pAMMedia);
  903. return hr;
  904. }
  905. HRESULT CEVRAllocatorPresenter::CreateProposedOutputType(IMFMediaType* pMixerType, IMFMediaType** pType)
  906. {
  907. HRESULT hr;
  908. AM_MEDIA_TYPE *pAMMedia = NULL;
  909. LARGE_INTEGER i64Size;
  910. MFVIDEOFORMAT *VideoFormat;
  911. CheckHR(pMixerType->GetRepresentation(FORMAT_MFVideoFormat, (void**)&pAMMedia));
  912. VideoFormat = (MFVIDEOFORMAT*)pAMMedia->pbFormat;
  913. hr = pfMFCreateVideoMediaType(VideoFormat, &m_pMediaType);
  914. m_AspectRatio.cx = VideoFormat->videoInfo.PixelAspectRatio.Numerator;
  915. m_AspectRatio.cy = VideoFormat->videoInfo.PixelAspectRatio.Denominator;
  916. if (SUCCEEDED (hr))
  917. {
  918. i64Size.HighPart = VideoFormat->videoInfo.dwWidth;
  919. i64Size.LowPart = VideoFormat->videoInfo.dwHeight;
  920. m_pMediaType->SetUINT64(MF_MT_FRAME_SIZE, i64Size.QuadPart);
  921. m_pMediaType->SetUINT32(MF_MT_PAN_SCAN_ENABLED, 0);
  922. AppSettings& s = AfxGetAppSettings();
  923. if (s.m_RenderSettings.iEVROutputRange == 1)
  924. m_pMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_16_235);
  925. else
  926. m_pMediaType->SetUINT32(MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255);
  927. //m_pMediaType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive );
  928. m_LastSetOutputRange = s.m_RenderSettings.iEVROutputRange;
  929. i64Size.HighPart = m_AspectRatio.cx;
  930. i64Size.LowPart = m_AspectRatio.cy;
  931. m_pMediaType->SetUINT64(MF_MT_PIXEL_ASPECT_RATIO, i64Size.QuadPart);
  932. MFVideoArea Area = MakeArea(0, 0, VideoFormat->videoInfo.dwWidth, VideoFormat->videoInfo.dwHeight);
  933. m_pMediaType->SetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)&Area, sizeof(MFVideoArea));
  934. }
  935. ////SVP_LogMsg6("CreateProposedOutputType %d %d %d %d ", m_AspectRatio.cx , m_AspectRatio.cy, VideoFormat->videoInfo.dwWidth, VideoFormat->videoInfo.dwHeight );
  936. if(min(m_AspectRatio.cx, m_AspectRatio.cy) <= 0){
  937. m_AspectRatio.cx = m_AspectRatio.cy = 1;
  938. }
  939. m_AspectRatio.cx *= VideoFormat->videoInfo.dwWidth;
  940. m_AspectRatio.cy *= VideoFormat->videoInfo.dwHeight;
  941. bool bDoneSomething = true;
  942. //如果 m_AspectRatio.cx 为 0 会无限循环
  943. for(int k = 0; k < 100; k++)
  944. {
  945. if(!bDoneSomething){
  946. break;
  947. }
  948. bDoneSomething = false;
  949. INT MinNum = min(m_AspectRatio.cx, m_AspectRatio.cy);
  950. if(MinNum < 2){
  951. break;
  952. }
  953. INT i;
  954. for (i = 2; i < MinNum+1; ++i)
  955. {
  956. if (m_AspectRatio.cx%i == 0 && m_AspectRatio.cy%i ==0)
  957. break;
  958. }
  959. if (i != MinNum + 1)
  960. {
  961. m_AspectRatio.cx = m_AspectRatio.cx / i;
  962. m_AspectRatio.cy = m_AspectRatio.cy / i;
  963. bDoneSomething = true;
  964. }
  965. }
  966. pMixerType->FreeRepresentation(FORMAT_MFVideoFormat, (void*)pAMMedia);
  967. m_pMediaType->QueryInterface(__uuidof(IMFMediaType), (void**) pType);
  968. return hr;
  969. }
  970. HRESULT CEVRAllocatorPresenter::SetMediaType(IMFMediaType* pType)
  971. {
  972. HRESULT hr;
  973. AM_MEDIA_TYPE* pAMMedia = NULL;
  974. CString strTemp;
  975. CheckPointer(pType, E_POINTER);
  976. CheckHR(pType->GetRepresentation(FORMAT_VideoInfo2, (void**)&pAMMedia));
  977. hr = InitializeDevice(pAMMedia);
  978. if (SUCCEEDED(hr))
  979. {
  980. strTemp = GetMediaTypeName(pAMMedia->subtype);
  981. strTemp.Replace(L"MEDIASUBTYPE_", L"");
  982. m_strStatsMsg[MSG_MIXEROUT].Format (L"Mixer output: %s", strTemp);
  983. }
  984. pType->FreeRepresentation(FORMAT_VideoInfo2, (void*)pAMMedia);
  985. return hr;
  986. }
  987. LONGLONG GetMediaTypeMerit(IMFMediaType *pMediaType)
  988. {
  989. AM_MEDIA_TYPE *pAMMedia = NULL;
  990. MFVIDEOFORMAT *VideoFormat;
  991. HRESULT hr;
  992. CheckHR(pMediaType->GetRepresentation (FORMAT_MFVideoFormat, (void**)&pAMMedia));
  993. VideoFormat = (MFVIDEOFORMAT*)pAMMedia->pbFormat;
  994. LONGLONG Merit = 0;
  995. switch (VideoFormat->surfaceInfo.Format)
  996. {
  997. case FCC('NV12'): Merit = 90000000; break;
  998. case FCC('YV12'): Merit = 80000000; break;
  999. case FCC('YUY2'): Merit = 70000000; break;
  1000. case FCC('UYVY'): Merit = 60000000; break;
  1001. case D3DFMT_X8R8G8B8: // Never opt for RGB
  1002. case D3DFMT_A8R8G8B8:
  1003. case D3DFMT_R8G8B8:
  1004. case D3DFMT_R5G6B5:
  1005. Merit = 0;
  1006. break;
  1007. default: Merit = 1000; break;
  1008. }
  1009. pMediaType->FreeRepresentation(FORMAT_MFVideoFormat, (void*)pAMMedia);
  1010. return Merit;
  1011. }
  1012. typedef struct
  1013. {
  1014. const int Format;
  1015. const LPCTSTR Description;
  1016. } D3DFORMAT_TYPE;
  1017. extern const D3DFORMAT_TYPE D3DFormatType[];
  1018. LPCTSTR FindD3DFormat(const D3DFORMAT Format);
  1019. LPCTSTR GetMediaTypeFormatDesc(IMFMediaType *pMediaType)
  1020. {
  1021. AM_MEDIA_TYPE *pAMMedia = NULL;
  1022. MFVIDEOFORMAT *VideoFormat;
  1023. HRESULT hr;
  1024. hr = pMediaType->GetRepresentation(FORMAT_MFVideoFormat, (void**)&pAMMedia);
  1025. VideoFormat = (MFVIDEOFORMAT*)pAMMedia->pbFormat;
  1026. LPCTSTR Type = FindD3DFormat((D3DFORMAT)VideoFormat->surfaceInfo.Format);
  1027. pMediaType->FreeRepresentation (FORMAT_MFVideoFormat, (void*)pAMMedia);
  1028. return Type;
  1029. }
  1030. HRESULT CEVRAllocatorPresenter::RenegotiateMediaType()
  1031. {
  1032. HRESULT hr = S_OK;
  1033. CComPtr<IMFMediaType> pMixerType;
  1034. CComPtr<IMFMediaType> pType;
  1035. if (!m_pMixer) return MF_E_INVALIDREQUEST;
  1036. CInterfaceArray<IMFMediaType> ValidMixerTypes;
  1037. // Loop through all of the mixer's proposed output types.
  1038. DWORD iTypeIndex = 0;
  1039. while ((hr != MF_E_NO_MORE_TYPES))
  1040. {
  1041. pMixerType = NULL;
  1042. pType = NULL;
  1043. m_pMediaType = NULL;
  1044. // Step 1. Get the next media type supported by mixer.
  1045. hr = m_pMixer->GetOutputAvailableType(0, iTypeIndex++, &pMixerType);
  1046. if (FAILED(hr))
  1047. {
  1048. break;
  1049. }
  1050. // Step 2. Check if we support this media type.
  1051. if (SUCCEEDED(hr))
  1052. hr = IsMediaTypeSupported(pMixerType);
  1053. if (SUCCEEDED(hr))
  1054. hr = CreateProposedOutputType(pMixerType, &pType);
  1055. // Step 4. Check if the mixer will accept this media type.
  1056. if (SUCCEEDED(hr))
  1057. hr = m_pMixer->SetOutputType(0, pType, MFT_SET_TYPE_TEST_ONLY);
  1058. if (SUCCEEDED(hr))
  1059. {
  1060. LONGLONG Merit = GetMediaTypeMerit(pType);
  1061. int nTypes = ValidMixerTypes.GetCount();
  1062. int iInsertPos = 0;
  1063. for (int i = 0; i < nTypes; ++i)
  1064. {
  1065. LONGLONG ThisMerit = GetMediaTypeMerit(ValidMixerTypes[i]);
  1066. if (Merit > ThisMerit)
  1067. {
  1068. iInsertPos = i;
  1069. break;
  1070. }
  1071. else
  1072. iInsertPos = i+1;
  1073. }
  1074. ValidMixerTypes.InsertAt(iInsertPos, pType);
  1075. }
  1076. }
  1077. int nValidTypes = ValidMixerTypes.GetCount();
  1078. for (int i = 0; i < nValidTypes; ++i)
  1079. {
  1080. pType = ValidMixerTypes[i];
  1081. }
  1082. for (int i = 0; i < nValidTypes; ++i)
  1083. {
  1084. pType = ValidMixerTypes[i];
  1085. hr = SetMediaType(pType);
  1086. if (SUCCEEDED(hr))
  1087. {
  1088. hr = m_pMixer->SetOutputType(0, pType, 0);
  1089. // If something went wrong, clear the media type.
  1090. if (FAILED(hr))
  1091. {
  1092. SetMediaType(NULL);
  1093. }
  1094. else
  1095. break;
  1096. }
  1097. }
  1098. pMixerType = NULL;
  1099. pType = NULL;
  1100. return hr;
  1101. }
  1102. HRESULT CEVRAllocatorPresenter::ProcessOutputSafe( DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
  1103. {
  1104. __try{
  1105. return m_pMixer->ProcessOutput(0 , 1, pOutputSamples, pdwStatus);
  1106. }__except(EXCEPTION_EXECUTE_HANDLER){
  1107. //SVP_LogMsg6( "ProcessOutputSafe Crash ");
  1108. return E_FAIL;
  1109. }
  1110. }
  1111. bool CEVRAllocatorPresenter::GetSampleFromMixer()
  1112. {
  1113. MFT_OUTPUT_DATA_BUFFER Buffer;
  1114. HRESULT hr = S_OK;
  1115. DWORD dwStatus;
  1116. UINT dwSurface;
  1117. bool newSample = false;
  1118. while (hr == S_OK) // Get as many frames as there are and that we have samples for
  1119. {
  1120. //SVP_LogMsg6( "GetFreeSample Free Samples Before %d ", m_FreeSamples.GetCount());
  1121. CComPtr<IMFSample> pSample;
  1122. if (FAILED(GetFreeSample(&pSample))) // All samples are taken for the moment. Better luck next time
  1123. {
  1124. //SVP_LogMsg6( "GetFreeSample Failed %d %x", m_FreeSamples.GetCount(), hr);
  1125. hr = E_FAIL;
  1126. break;
  1127. }
  1128. else
  1129. {
  1130. memset(&Buffer, 0, sizeof(Buffer));
  1131. Buffer.pSample = pSample;
  1132. pSample->GetUINT32(GUID_SURFACE_INDEX, &dwSurface);
  1133. hr = ProcessOutputSafe(0 , 1, &Buffer, &dwStatus);
  1134. if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) // There are no samples left in the mixer
  1135. {
  1136. //SVP_LogMsg5(L"MF_E_TRANSFORM_NEED_MORE_INPUT");
  1137. MoveToFreeList(pSample, false);
  1138. break;
  1139. }else if (hr == MF_E_TRANSFORM_TYPE_NOT_SET){
  1140. MoveToFreeList(pSample, true);
  1141. break;
  1142. }
  1143. else if(SUCCEEDED(hr))
  1144. {
  1145. newSample = true;
  1146. if (AfxGetMyApp()->m_fTearingTest)
  1147. {
  1148. RECT rcTearing;
  1149. rcTearing.left = m_nTearingPos;
  1150. rcTearing.top = 0;
  1151. rcTearing.right = rcTearing.left + 4;
  1152. rcTearing.bottom = m_NativeVideoSize.cy;
  1153. m_pD3DDev->ColorFill(m_pVideoSurface[dwSurface], &rcTearing, D3DCOLOR_ARGB (255,255,0,0));
  1154. rcTearing.left = (rcTearing.right + 15) % m_NativeVideoSize.cx;
  1155. rcTearing.right = rcTearing.left + 4;
  1156. m_pD3DDev->ColorFill(m_pVideoSurface[dwSurface], &rcTearing, D3DCOLOR_ARGB (255,255,0,0));
  1157. m_nTearingPos = (m_nTearingPos + 7) % m_NativeVideoSize.cx;
  1158. }
  1159. MoveToScheduledList(pSample, false); // Schedule, then go back to see if there is more where that came from
  1160. }else{
  1161. //SVP_LogMsg5(L"ProcessOutputSafe Failed %x", hr);
  1162. }
  1163. }
  1164. }
  1165. return newSample;
  1166. }
  1167. STDMETHODIMP CEVRAllocatorPresenter::GetCurrentMediaType(__deref_out IMFVideoMediaType **ppMediaType)
  1168. {
  1169. HRESULT hr = S_OK;
  1170. CAutoLock lock(this);
  1171. CheckPointer (ppMediaType, E_POINTER);
  1172. CheckHR (CheckShutdown());
  1173. if (m_pMediaType == NULL)
  1174. CheckHR(MF_E_NOT_INITIALIZED);
  1175. CheckHR(m_pMediaType->QueryInterface( __uuidof(IMFVideoMediaType), (void**)&ppMediaType));
  1176. return hr;
  1177. }
  1178. // IMFTopologyServiceLookupClient
  1179. STDMETHODIMP CEVRAllocatorPresenter::InitServicePointers(/* [in] */ __in IMFTopologyServiceLookup *pLookup)
  1180. {
  1181. HRESULT hr;
  1182. DWORD dwObjects = 1;
  1183. m_llSystemJitter = 0;
  1184. m_systemTime = 0;
  1185. hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_MIXER_SERVICE, __uuidof (IMFTransform), (void**)&m_pMixer, &dwObjects);
  1186. hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, __uuidof (IMediaEventSink ), (void**)&m_pSink, &dwObjects);
  1187. hr = pLookup->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE, __uuidof (IMFClock ), (void**)&m_pClock, &dwObjects);
  1188. //SVP_LogMsg5(L"CEVRAllocatorPresenter::InitServicePointers");
  1189. StartWorkerThreads();
  1190. return S_OK;
  1191. }
  1192. STDMETHODIMP CEVRAllocatorPresenter::ReleaseServicePointers()
  1193. {
  1194. StopWorkerThreads();
  1195. m_pMixer = NULL;
  1196. m_pSink = NULL;
  1197. m_pClock = NULL;
  1198. return S_OK;
  1199. }
  1200. // IMFVideoDeviceID
  1201. STDMETHODIMP CEVRAllocatorPresenter::GetDeviceID( __out IID *pDeviceID)
  1202. {
  1203. CheckPointer(pDeviceID, E_POINTER);
  1204. *pDeviceID = IID_IDirect3DDevice9;
  1205. return S_OK;
  1206. }
  1207. // IMFGetService
  1208. STDMETHODIMP CEVRAllocatorPresenter::GetService( __RPC__in REFGUID guidService, __RPC__in REFIID riid, __RPC__deref_out_opt LPVOID *ppvObject)
  1209. {
  1210. if (guidService == MR_VIDEO_RENDER_SERVICE)
  1211. return NonDelegatingQueryInterface (riid, ppvObject);
  1212. else if (guidService == MR_VIDEO_ACCELERATION_SERVICE)
  1213. return m_pD3DManager->QueryInterface (__uuidof(IDirect3DDeviceManager9), (void**) ppvObject);
  1214. return E_NOINTERFACE;
  1215. }
  1216. // IMFAsyncCallback
  1217. STDMETHODIMP CEVRAllocatorPresenter::GetParameters( __RPC__out DWORD *pdwFlags, __RPC__out DWORD *pdwQueue)
  1218. {
  1219. return E_NOTIMPL;
  1220. }
  1221. STDMETHODIMP CEVRAllocatorPresenter::Invoke( __RPC__in_opt IMFAsyncResult *pAsyncResult)
  1222. {
  1223. return E_NOTIMPL;
  1224. }
  1225. // IMFVideoDisplayControl
  1226. STDMETHODIMP CEVRAllocatorPresenter::GetNativeVideoSize(SIZE *pszVideo, SIZE *pszARVideo)
  1227. {
  1228. if (pszVideo)
  1229. {
  1230. pszVideo->cx = m_NativeVideoSize.cx;
  1231. pszVideo->cy = m_NativeVideoSize.cy;
  1232. }
  1233. if (pszARVideo)
  1234. {
  1235. pszARVideo->cx = m_AspectRatio.cx; //m_NativeVideoSize.cx *
  1236. pszARVideo->cy = m_AspectRatio.cy; //m_NativeVideoSize.cy *
  1237. }
  1238. return S_OK;
  1239. }
  1240. STDMETHODIMP CEVRAllocatorPresenter::GetIdealVideoSize(SIZE *pszMin, SIZE *pszMax)
  1241. {
  1242. if (pszMin)
  1243. {
  1244. pszMin->cx = 1;
  1245. pszMin->cy = 1;
  1246. }
  1247. if (pszMax)
  1248. {
  1249. D3DDISPLAYMODE d3ddm;
  1250. ZeroMemory(&d3ddm, sizeof(d3ddm));
  1251. if(SUCCEEDED(m_pD3D->GetAdapterDisplayMode(GetAdapter(m_pD3D), &d3ddm)))
  1252. {
  1253. pszMax->cx = d3ddm.Width;
  1254. pszMax->cy = d3ddm.Height;
  1255. }
  1256. }
  1257. return S_OK;
  1258. }
  1259. STDMETHODIMP CEVRAllocatorPresenter::SetVideoPosition(const MFVideoNormalizedRect *pnrcSource, const LPRECT prcDest)
  1260. {
  1261. return S_OK;
  1262. }
  1263. STDMETHODIMP CEVRAllocatorPresenter::GetVideoPosition(MFVideoNormalizedRect *pnrcSource, LPRECT prcDest)
  1264. {
  1265. // Always all source rectangle ?
  1266. if (pnrcSource)
  1267. {
  1268. pnrcSource->left = 0.0;
  1269. pnrcSource->top = 0.0;
  1270. pnrcSource->right = 1.0;
  1271. pnrcSource->bottom = 1.0;
  1272. }
  1273. if (prcDest)
  1274. memcpy (prcDest, &m_VideoRect, sizeof(m_VideoRect));//GetClientRect (m_hWnd, prcDest);
  1275. return S_OK;
  1276. }
  1277. STDMETHODIMP CEVRAllocatorPresenter::SetAspectRatioMode(DWORD dwAspectRatioMode)
  1278. {
  1279. m_dwVideoAspectRatioMode = (MFVideoAspectRatioMode)dwAspectRatioMode;
  1280. return S_OK;
  1281. }
  1282. STDMETHODIMP CEVRAllocatorPresenter::GetAspectRatioMode(DWORD *pdwAspectRatioMode)
  1283. {
  1284. CheckPointer (pdwAspectRatioMode, E_POINTER);
  1285. *pdwAspectRatioMode = m_dwVideoAspectRatioMode;
  1286. return S_OK;
  1287. }
  1288. STDMETHODIMP CEVRAllocatorPresenter::SetVideoWindow(HWND hwndVideo)
  1289. {
  1290. ASSERT (m_hWnd == hwndVideo); // What if not ??
  1291. // m_hWnd = hwndVideo;
  1292. return S_OK;
  1293. }
  1294. STDMETHODIMP CEVRAllocatorPresenter::GetVideoWindow(HWND *phwndVideo)
  1295. {
  1296. CheckPointer (phwndVideo, E_POINTER);
  1297. *phwndVideo = m_hWnd;
  1298. return S_OK;
  1299. }
  1300. STDMETHODIMP CEVRAllocatorPresenter::RepaintVideo()
  1301. {
  1302. Paint (true);
  1303. return S_OK;
  1304. }
  1305. STDMETHODIMP CEVRAllocatorPresenter::GetCurrentImage(BITMAPINFOHEADER *pBih, BYTE **pDib, DWORD *pcbDib, LONGLONG *pTimeStamp)
  1306. {
  1307. ASSERT (FALSE);
  1308. return E_NOTIMPL;
  1309. }
  1310. STDMETHODIMP CEVRAllocatorPresenter::SetBorderColor(COLORREF Clr)
  1311. {
  1312. m_BorderColor = Clr;
  1313. return S_OK;
  1314. }
  1315. STDMETHODIMP CEVRAllocatorPresenter::GetBorderColor(COLORREF *pClr)
  1316. {
  1317. CheckPointer (pClr, E_POINTER);
  1318. *pClr = m_BorderColor;
  1319. return S_OK;
  1320. }
  1321. STDMETHODIMP CEVRAllocatorPresenter::SetRenderingPrefs(DWORD dwRenderFlags)
  1322. {
  1323. m_dwVideoRenderPrefs = (MFVideoRenderPrefs)dwRenderFlags;
  1324. return S_OK;
  1325. }
  1326. STDMETHODIMP CEVRAllocatorPresenter::GetRenderingPrefs(DWORD *pdwRenderFlags)
  1327. {
  1328. CheckPointer(pdwRenderFlags, E_POINTER);
  1329. *pdwRenderFlags = m_dwVideoRenderPrefs;
  1330. return S_OK;
  1331. }
  1332. STDMETHODIMP CEVRAllocatorPresenter::SetFullscreen(BOOL fFullscreen)
  1333. {
  1334. ASSERT (FALSE);
  1335. return E_NOTIMPL;
  1336. }
  1337. STDMETHODIMP CEVRAllocatorPresenter::GetFullscreen(BOOL *pfFullscreen)
  1338. {
  1339. ASSERT (FALSE);
  1340. return E_NOTIMPL;
  1341. }
  1342. // IEVRTrustedVideoPlugin
  1343. STDMETHODIMP CEVRAllocatorPresenter::IsInTrustedVideoMode(BOOL *pYes)
  1344. {
  1345. CheckPointer(pYes, E_POINTER);
  1346. *pYes = TRUE;
  1347. return S_OK;
  1348. }
  1349. STDMETHODIMP CEVRAllocatorPresenter::CanConstrict(BOOL *pYes)
  1350. {
  1351. CheckPointer(pYes, E_POINTER);
  1352. *pYes = TRUE;
  1353. return S_OK;
  1354. }
  1355. STDMETHODIMP CEVRAllocatorPresenter::SetConstriction(DWORD dwKPix)
  1356. {
  1357. return S_OK;
  1358. }
  1359. STDMETHODIMP CEVRAllocatorPresenter::DisableImageExport(BOOL bDisable)
  1360. {
  1361. return S_OK;
  1362. }
  1363. // IDirect3DDeviceManager9
  1364. STDMETHODIMP CEVRAllocatorPresenter::ResetDevice(IDirect3DDevice9 *pDevice,UINT resetToken)
  1365. {
  1366. HRESULT hr = m_pD3DManager->ResetDe