/*
* (C) 2006-2014 see Authors.txt
*
* This file is part of MPC-HC.
*
* MPC-HC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MPC-HC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#pragma once
#include "DX9AllocatorPresenter.h"
#include // API Media Foundation
#include
namespace DSObjects
{
// dxva.dll
typedef HRESULT(__stdcall* PTR_DXVA2CreateDirect3DDeviceManager9)(UINT* pResetToken, IDirect3DDeviceManager9** ppDeviceManager);
// mf.dll
typedef HRESULT(__stdcall* PTR_MFCreatePresentationClock)(IMFPresentationClock** ppPresentationClock);
// evr.dll
typedef HRESULT(__stdcall* PTR_MFCreateDXSurfaceBuffer)(REFIID riid, IUnknown* punkSurface, BOOL fBottomUpWhenLinear, IMFMediaBuffer** ppBuffer);
typedef HRESULT(__stdcall* PTR_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
typedef HRESULT(__stdcall* PTR_MFCreateVideoMediaType)(const MFVIDEOFORMAT* pVideoFormat, IMFVideoMediaType** ppIVideoMediaType);
// avrt.dll
typedef HANDLE(__stdcall* PTR_AvSetMmThreadCharacteristicsW)(LPCWSTR TaskName, LPDWORD TaskIndex);
typedef BOOL (__stdcall* PTR_AvSetMmThreadPriority)(HANDLE AvrtHandle, AVRT_PRIORITY Priority);
typedef BOOL (__stdcall* PTR_AvRevertMmThreadCharacteristics)(HANDLE AvrtHandle);
class COuterEVR;
class CEVRAllocatorPresenter :
public CDX9AllocatorPresenter,
public IMFGetService,
public IMFTopologyServiceLookupClient,
public IMFVideoDeviceID,
public IMFVideoPresenter,
public IDirect3DDeviceManager9,
public IMFAsyncCallback,
public IQualProp,
public IMFRateSupport,
public IMFVideoDisplayControl,
public IEVRTrustedVideoPlugin
/* public IMFVideoPositionMapper, // Non mandatory EVR Presenter Interfaces (see later...) */
{
public:
CEVRAllocatorPresenter(HWND hWnd, bool bFullscreen, HRESULT& hr, CString& _Error);
~CEVRAllocatorPresenter();
DECLARE_IUNKNOWN;
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);
STDMETHODIMP CreateRenderer(IUnknown** ppRenderer);
STDMETHODIMP_(bool) Paint(bool bAll);
STDMETHODIMP GetNativeVideoSize(LONG* lpWidth, LONG* lpHeight, LONG* lpARWidth, LONG* lpARHeight);
STDMETHODIMP InitializeDevice(IMFMediaType* pMediaType);
STDMETHODIMP_(bool) ResetDevice();
STDMETHODIMP_(bool) DisplayChange();
// ISubPicAllocatorPresenter2
STDMETHODIMP_(bool) IsRendering() {
return (m_nRenderState == Started);
}
// IMFClockStateSink
STDMETHODIMP OnClockStart(/* [in] */ MFTIME hnsSystemTime, /* [in] */ LONGLONG llClockStartOffset);
STDMETHODIMP OnClockStop(/* [in] */ MFTIME hnsSystemTime);
STDMETHODIMP OnClockPause(/* [in] */ MFTIME hnsSystemTime);
STDMETHODIMP OnClockRestart(/* [in] */ MFTIME hnsSystemTime);
STDMETHODIMP OnClockSetRate(/* [in] */ MFTIME hnsSystemTime, /* [in] */ float flRate);
// IBaseFilter delegate
bool GetState(DWORD dwMilliSecsTimeout, FILTER_STATE* State, HRESULT& _ReturnValue);
// IQualProp (EVR statistics window)
STDMETHODIMP get_FramesDroppedInRenderer(int* pcFrames);
STDMETHODIMP get_FramesDrawn(int* pcFramesDrawn);
STDMETHODIMP get_AvgFrameRate(int* piAvgFrameRate);
STDMETHODIMP get_Jitter(int* iJitter);
STDMETHODIMP get_AvgSyncOffset(int* piAvg);
STDMETHODIMP get_DevSyncOffset(int* piDev);
// IMFRateSupport
STDMETHODIMP GetSlowestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float* pflRate);
STDMETHODIMP GetFastestRate(MFRATE_DIRECTION eDirection, BOOL fThin, float* pflRate);
STDMETHODIMP IsRateSupported(BOOL fThin, float flRate, float* pflNearestSupportedRate);
float GetMaxRate(BOOL bThin);
// IMFVideoPresenter
STDMETHODIMP ProcessMessage(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam);
STDMETHODIMP GetCurrentMediaType(__deref_out IMFVideoMediaType** ppMediaType);
// IMFTopologyServiceLookupClient
STDMETHODIMP InitServicePointers(/* [in] */ __in IMFTopologyServiceLookup* pLookup);
STDMETHODIMP ReleaseServicePointers();
// IMFVideoDeviceID
STDMETHODIMP GetDeviceID(/* [out] */ __out IID* pDeviceID);
// IMFGetService
STDMETHODIMP GetService(/* [in] */ __RPC__in REFGUID guidService,
/* [in] */ __RPC__in REFIID riid,
/* [iid_is][out] */ __RPC__deref_out_opt LPVOID* ppvObject);
// IMFAsyncCallback
STDMETHODIMP GetParameters(/* [out] */ __RPC__out DWORD* pdwFlags, /* [out] */ __RPC__out DWORD* pdwQueue);
STDMETHODIMP Invoke(/* [in] */ __RPC__in_opt IMFAsyncResult* pAsyncResult);
// IMFVideoDisplayControl
STDMETHODIMP GetNativeVideoSize(SIZE* pszVideo, SIZE* pszARVideo);
STDMETHODIMP GetIdealVideoSize(SIZE* pszMin, SIZE* pszMax);
STDMETHODIMP SetVideoPosition(const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest);
STDMETHODIMP GetVideoPosition(MFVideoNormalizedRect* pnrcSource, LPRECT prcDest);
STDMETHODIMP SetAspectRatioMode(DWORD dwAspectRatioMode);
STDMETHODIMP GetAspectRatioMode(DWORD* pdwAspectRatioMode);
STDMETHODIMP SetVideoWindow(HWND hwndVideo);
STDMETHODIMP GetVideoWindow(HWND* phwndVideo);
STDMETHODIMP RepaintVideo();
STDMETHODIMP GetCurrentImage(BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp);
STDMETHODIMP SetBorderColor(COLORREF Clr);
STDMETHODIMP GetBorderColor(COLORREF* pClr);
STDMETHODIMP SetRenderingPrefs(DWORD dwRenderFlags);
STDMETHODIMP GetRenderingPrefs(DWORD* pdwRenderFlags);
STDMETHODIMP SetFullscreen(BOOL fFullscreen);
STDMETHODIMP GetFullscreen(BOOL* pfFullscreen);
// IEVRTrustedVideoPlugin
STDMETHODIMP IsInTrustedVideoMode(BOOL* pYes);
STDMETHODIMP CanConstrict(BOOL* pYes);
STDMETHODIMP SetConstriction(DWORD dwKPix);
STDMETHODIMP DisableImageExport(BOOL bDisable);
// IDirect3DDeviceManager9
STDMETHODIMP ResetDevice(IDirect3DDevice9* pDevice, UINT resetToken);
STDMETHODIMP OpenDeviceHandle(HANDLE* phDevice);
STDMETHODIMP CloseDeviceHandle(HANDLE hDevice);
STDMETHODIMP TestDevice(HANDLE hDevice);
STDMETHODIMP LockDevice(HANDLE hDevice, IDirect3DDevice9** ppDevice, BOOL fBlock);
STDMETHODIMP UnlockDevice(HANDLE hDevice, BOOL fSaveState);
STDMETHODIMP GetVideoService(HANDLE hDevice, REFIID riid, void** ppService);
protected:
void OnResetDevice();
virtual void OnVBlankFinished(bool bAll, LONGLONG PerformanceCounter);
double m_ModeratedTime;
LONGLONG m_ModeratedTimeLast;
LONGLONG m_ModeratedClockLast;
LONGLONG m_ModeratedTimer;
MFCLOCK_STATE m_LastClockState;
LONGLONG GetClockTime(LONGLONG PerformanceCounter);
private:
enum RENDER_STATE {
Started = State_Running,
Stopped = State_Stopped,
Paused = State_Paused,
Shutdown = State_Running + 1
};
COuterEVR* m_pOuterEVR;
CComPtr m_pClock;
CComPtr m_pD3DManager;
CComPtr m_pMixer;
CComPtr m_pSink;
CComPtr m_pMediaType;
MFVideoAspectRatioMode m_dwVideoAspectRatioMode;
MFVideoRenderPrefs m_dwVideoRenderPrefs;
COLORREF m_BorderColor;
HANDLE m_hEvtQuit; // Stop rendering thread event
bool m_bEvtQuit;
HANDLE m_hEvtFlush; // Discard all buffers
bool m_bEvtFlush;
bool m_fUseInternalTimer;
INT32 m_LastSetOutputRange;
bool m_bPendingRenegotiate;
bool m_bPendingMediaFinished;
HANDLE m_hThread;
HANDLE m_hGetMixerThread;
HANDLE m_hVSyncThread;
RENDER_STATE m_nRenderState;
CCritSec m_SampleQueueLock;
CCritSec m_ImageProcessingLock;
CCritSec m_MediaTypeLock;
CInterfaceList m_FreeSamples;
CInterfaceList m_ScheduledSamples;
IMFSample* m_pCurrentDisplaydSample;
bool m_bWaitingSample;
bool m_bLastSampleOffsetValid;
LONGLONG m_LastScheduledSampleTime;
double m_LastScheduledSampleTimeFP;
LONGLONG m_LastScheduledUncorrectedSampleTime;
LONGLONG m_MaxSampleDuration;
LONGLONG m_LastSampleOffset;
LONGLONG m_VSyncOffsetHistory[5];
LONGLONG m_LastPredictedSync;
int m_VSyncOffsetHistoryPos;
UINT m_nResetToken;
int m_nStepCount;
bool m_bSignaledStarvation;
LONGLONG m_StarvationClock;
// Stats variable for IQualProp
UINT m_pcFrames;
UINT m_nDroppedUpdate;
UINT m_pcFramesDrawn; // Retrieves the number of frames drawn since streaming started
UINT m_piAvg;
UINT m_piDev;
void GetMixerThread();
static DWORD WINAPI GetMixerThreadStatic(LPVOID lpParam);
bool GetImageFromMixer();
void RenderThread();
static DWORD WINAPI PresentThread(LPVOID lpParam);
void ResetStats();
void StartWorkerThreads();
void StopWorkerThreads();
HRESULT CheckShutdown() const;
void CompleteFrameStep(bool bCancel);
void CheckWaitingSampleFromMixer();
static DWORD WINAPI VSyncThreadStatic(LPVOID lpParam);
void VSyncThread();
void RemoveAllSamples();
HRESULT GetFreeSample(IMFSample** ppSample);
HRESULT GetScheduledSample(IMFSample** ppSample, int& _Count);
void MoveToFreeList(IMFSample* pSample, bool bTail);
void MoveToScheduledList(IMFSample* pSample, bool _bSorted);
void FlushSamples();
void FlushSamplesInternal();
// === Media type negotiation functions
HRESULT RenegotiateMediaType();
HRESULT IsMediaTypeSupported(IMFMediaType* pMixerType);
HRESULT CreateProposedOutputType(IMFMediaType* pMixerType, IMFMediaType** pType);
HRESULT SetMediaType(IMFMediaType* pType);
HRESULT GetMediaTypeFourCC(IMFMediaType* pType, DWORD* pFourCC);
HRESULT GetMediaTypeMerit(IMFMediaType* pType, int* pMerit);
LPCTSTR GetMediaTypeFormatDesc(IMFMediaType* pMediaType);
// === Functions pointers on Vista+ / .NET Framework 3.5 specific library
HMODULE m_hDXVA2Lib;
HMODULE m_hEVRLib;
HMODULE m_hAVRTLib;
PTR_DXVA2CreateDirect3DDeviceManager9 pfDXVA2CreateDirect3DDeviceManager9;
PTR_MFCreateDXSurfaceBuffer pfMFCreateDXSurfaceBuffer;
PTR_MFCreateVideoSampleFromSurface pfMFCreateVideoSampleFromSurface;
PTR_MFCreateVideoMediaType pfMFCreateVideoMediaType;
#if 0
HRESULT(__stdcall* pMFCreateMediaType)(__deref_out IMFMediaType** ppMFType);
HRESULT(__stdcall* pMFInitMediaTypeFromAMMediaType)(__in IMFMediaType* pMFType, __in const AM_MEDIA_TYPE* pAMType);
HRESULT(__stdcall* pMFInitAMMediaTypeFromMFMediaType)(__in IMFMediaType* pMFType, __in GUID guidFormatBlockType, __inout AM_MEDIA_TYPE* pAMType);
#endif
PTR_AvSetMmThreadCharacteristicsW pfAvSetMmThreadCharacteristicsW;
PTR_AvSetMmThreadPriority pfAvSetMmThreadPriority;
PTR_AvRevertMmThreadCharacteristics pfAvRevertMmThreadCharacteristics;
};
}