250 lines
9.5 KiB
C++
250 lines
9.5 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Presenter.h : Defines the presenter object.
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#pragma once
|
|
|
|
// RENDER_STATE: Defines the state of the presenter.
|
|
enum RENDER_STATE
|
|
{
|
|
RENDER_STATE_STARTED = 1,
|
|
RENDER_STATE_STOPPED,
|
|
RENDER_STATE_PAUSED,
|
|
RENDER_STATE_SHUTDOWN, // Initial state.
|
|
|
|
// State transitions:
|
|
|
|
// InitServicePointers -> STOPPED
|
|
// ReleaseServicePointers -> SHUTDOWN
|
|
// IMFClockStateSink::OnClockStart -> STARTED
|
|
// IMFClockStateSink::OnClockRestart -> STARTED
|
|
// IMFClockStateSink::OnClockPause -> PAUSED
|
|
// IMFClockStateSink::OnClockStop -> STOPPED
|
|
};
|
|
|
|
// FRAMESTEP_STATE: Defines the presenter's state with respect to frame-stepping.
|
|
enum FRAMESTEP_STATE
|
|
{
|
|
FRAMESTEP_NONE, // Not frame stepping.
|
|
FRAMESTEP_WAITING_START, // Frame stepping, but the clock is not started.
|
|
FRAMESTEP_PENDING, // Clock is started. Waiting for samples.
|
|
FRAMESTEP_SCHEDULED, // Submitted a sample for rendering.
|
|
FRAMESTEP_COMPLETE // Sample was rendered.
|
|
|
|
// State transitions:
|
|
|
|
// MFVP_MESSAGE_STEP -> WAITING_START
|
|
// OnClockStart/OnClockRestart -> PENDING
|
|
// MFVP_MESSAGE_PROCESSINPUTNOTIFY -> SUBMITTED
|
|
// OnSampleFree -> COMPLETE
|
|
// MFVP_MESSAGE_CANCEL -> NONE
|
|
// OnClockStop -> NONE
|
|
// OnClockSetRate( non-zero ) -> NONE
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// EVRCustomPresenter class
|
|
// Description: Implements the custom presenter.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class EVRCustomPresenter :
|
|
BaseObject,
|
|
RefCountedObject,
|
|
// COM interfaces:
|
|
public IMFVideoDeviceID,
|
|
public IMFVideoPresenter, // Inherits IMFClockStateSink
|
|
public IMFRateSupport,
|
|
public IMFGetService,
|
|
public IMFTopologyServiceLookupClient,
|
|
public IMFVideoDisplayControl
|
|
{
|
|
|
|
public:
|
|
static HRESULT CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppv);
|
|
|
|
// IUnknown methods
|
|
STDMETHOD(QueryInterface)(REFIID riid, void ** ppv);
|
|
STDMETHOD_(ULONG, AddRef)();
|
|
STDMETHOD_(ULONG, Release)();
|
|
|
|
// IMFGetService methods
|
|
STDMETHOD(GetService)(REFGUID guidService, REFIID riid, LPVOID *ppvObject);
|
|
|
|
// IMFVideoPresenter methods
|
|
STDMETHOD(ProcessMessage)(MFVP_MESSAGE_TYPE eMessage, ULONG_PTR ulParam);
|
|
STDMETHOD(GetCurrentMediaType)(IMFVideoMediaType** ppMediaType);
|
|
|
|
// IMFClockStateSink methods
|
|
STDMETHOD(OnClockStart)(MFTIME hnsSystemTime, LONGLONG llClockStartOffset);
|
|
STDMETHOD(OnClockStop)(MFTIME hnsSystemTime);
|
|
STDMETHOD(OnClockPause)(MFTIME hnsSystemTime);
|
|
STDMETHOD(OnClockRestart)(MFTIME hnsSystemTime);
|
|
STDMETHOD(OnClockSetRate)(MFTIME hnsSystemTime, float flRate);
|
|
|
|
// IMFRateSupport methods
|
|
STDMETHOD(GetSlowestRate)(MFRATE_DIRECTION eDirection, BOOL bThin, float *pflRate);
|
|
STDMETHOD(GetFastestRate)(MFRATE_DIRECTION eDirection, BOOL bThin, float *pflRate);
|
|
STDMETHOD(IsRateSupported)(BOOL bThin, float flRate, float *pflNearestSupportedRate);
|
|
|
|
// IMFVideoDeviceID methods
|
|
STDMETHOD(GetDeviceID)(IID* pDeviceID);
|
|
|
|
// IMFTopologyServiceLookupClient methods
|
|
STDMETHOD(InitServicePointers)(IMFTopologyServiceLookup *pLookup);
|
|
STDMETHOD(ReleaseServicePointers)();
|
|
|
|
// IMFVideoDisplayControl methods
|
|
STDMETHOD(GetNativeVideoSize)(SIZE* pszVideo, SIZE* pszARVideo) { return E_NOTIMPL; }
|
|
STDMETHOD(GetIdealVideoSize)(SIZE* pszMin, SIZE* pszMax) { return E_NOTIMPL; }
|
|
STDMETHOD(SetVideoPosition)(const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest);
|
|
STDMETHOD(GetVideoPosition)(MFVideoNormalizedRect* pnrcSource, LPRECT prcDest);
|
|
STDMETHOD(SetAspectRatioMode)(DWORD dwAspectRatioMode) { return E_NOTIMPL; }
|
|
STDMETHOD(GetAspectRatioMode)(DWORD* pdwAspectRatioMode) { return E_NOTIMPL; }
|
|
STDMETHOD(SetVideoWindow)(HWND hwndVideo);
|
|
STDMETHOD(GetVideoWindow)(HWND* phwndVideo);
|
|
STDMETHOD(RepaintVideo)();
|
|
STDMETHOD(GetCurrentImage)(BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp) { return E_NOTIMPL; }
|
|
STDMETHOD(SetBorderColor)(COLORREF Clr) { return E_NOTIMPL; }
|
|
STDMETHOD(GetBorderColor)(COLORREF* pClr) { return E_NOTIMPL; }
|
|
STDMETHOD(SetRenderingPrefs)(DWORD dwRenderFlags) { return E_NOTIMPL; }
|
|
STDMETHOD(GetRenderingPrefs)(DWORD* pdwRenderFlags) { return E_NOTIMPL; }
|
|
STDMETHOD(SetFullscreen)(BOOL bFullscreen) { return E_NOTIMPL; }
|
|
STDMETHOD(GetFullscreen)(BOOL* pbFullscreen) { return E_NOTIMPL; }
|
|
|
|
protected:
|
|
EVRCustomPresenter(HRESULT& hr);
|
|
virtual ~EVRCustomPresenter();
|
|
|
|
// CheckShutdown:
|
|
// Returns MF_E_SHUTDOWN if the presenter is shutdown.
|
|
// Call this at the start of any methods that should fail after shutdown.
|
|
inline HRESULT CheckShutdown() const
|
|
{
|
|
if (m_RenderState == RENDER_STATE_SHUTDOWN)
|
|
{
|
|
return MF_E_SHUTDOWN;
|
|
}
|
|
else
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// IsActive: The "active" state is started or paused.
|
|
inline BOOL IsActive() const
|
|
{
|
|
return ((m_RenderState == RENDER_STATE_STARTED) || (m_RenderState == RENDER_STATE_PAUSED));
|
|
}
|
|
|
|
// IsScrubbing: Scrubbing occurs when the frame rate is 0.
|
|
inline BOOL IsScrubbing() const { return m_fRate == 0.0f; }
|
|
|
|
// NotifyEvent: Send an event to the EVR through its IMediaEventSink interface.
|
|
void NotifyEvent(long EventCode, LONG_PTR Param1, LONG_PTR Param2)
|
|
{
|
|
if (m_pMediaEventSink)
|
|
{
|
|
m_pMediaEventSink->Notify(EventCode, Param1, Param2);
|
|
}
|
|
}
|
|
|
|
float GetMaxRate(BOOL bThin);
|
|
|
|
// Mixer operations
|
|
HRESULT ConfigureMixer(IMFTransform *pMixer);
|
|
|
|
// Formats
|
|
HRESULT CreateOptimalVideoType(IMFMediaType* pProposed, IMFMediaType **ppOptimal);
|
|
HRESULT CalculateOutputRectangle(IMFMediaType *pProposed, RECT *prcOutput);
|
|
HRESULT SetMediaType(IMFMediaType *pMediaType);
|
|
HRESULT IsMediaTypeSupported(IMFMediaType *pMediaType);
|
|
|
|
// Message handlers
|
|
HRESULT Flush();
|
|
HRESULT RenegotiateMediaType();
|
|
HRESULT ProcessInputNotify();
|
|
HRESULT BeginStreaming();
|
|
HRESULT EndStreaming();
|
|
HRESULT CheckEndOfStream();
|
|
|
|
// Managing samples
|
|
void ProcessOutputLoop();
|
|
HRESULT ProcessOutput();
|
|
HRESULT DeliverSample(IMFSample *pSample, BOOL bRepaint);
|
|
HRESULT TrackSample(IMFSample *pSample);
|
|
void ReleaseResources();
|
|
|
|
// Frame-stepping
|
|
HRESULT PrepareFrameStep(DWORD cSteps);
|
|
HRESULT StartFrameStep();
|
|
HRESULT DeliverFrameStepSample(IMFSample *pSample);
|
|
HRESULT CompleteFrameStep(IMFSample *pSample);
|
|
HRESULT CancelFrameStep();
|
|
|
|
// Callbacks
|
|
|
|
// Callback when a video sample is released.
|
|
HRESULT OnSampleFree(IMFAsyncResult *pResult);
|
|
AsyncCallback<EVRCustomPresenter> m_SampleFreeCB;
|
|
|
|
protected:
|
|
|
|
// FrameStep: Holds information related to frame-stepping.
|
|
// Note: The purpose of this structure is simply to organize the data in one variable.
|
|
struct FrameStep
|
|
{
|
|
FrameStep() : state(FRAMESTEP_NONE), steps(0), pSampleNoRef(NULL)
|
|
{
|
|
}
|
|
|
|
FRAMESTEP_STATE state; // Current frame-step state.
|
|
VideoSampleList samples; // List of pending samples for frame-stepping.
|
|
DWORD steps; // Number of steps left.
|
|
DWORD_PTR pSampleNoRef; // Identifies the frame-step sample.
|
|
};
|
|
|
|
|
|
protected:
|
|
|
|
RENDER_STATE m_RenderState; // Rendering state.
|
|
FrameStep m_FrameStep; // Frame-stepping information.
|
|
|
|
CritSec m_ObjectLock; // Serializes our public methods.
|
|
|
|
// Samples and scheduling
|
|
Scheduler m_scheduler; // Manages scheduling of samples.
|
|
SamplePool m_SamplePool; // Pool of allocated samples.
|
|
DWORD m_TokenCounter; // Counter. Incremented whenever we create new samples.
|
|
|
|
// Rendering state
|
|
BOOL m_bSampleNotify; // Did the mixer signal it has an input sample?
|
|
BOOL m_bRepaint; // Do we need to repaint the last sample?
|
|
BOOL m_bPrerolled; // Have we presented at least one sample?
|
|
BOOL m_bEndStreaming; // Did we reach the end of the stream (EOS)?
|
|
|
|
MFVideoNormalizedRect m_nrcSource; // Source rectangle.
|
|
float m_fRate; // Playback rate.
|
|
|
|
// Deletable objects.
|
|
D3DPresentEngine *m_pD3DPresentEngine; // Rendering engine. (Never null if the constructor succeeds.)
|
|
|
|
// COM interfaces.
|
|
IMFClock *m_pClock; // The EVR's clock.
|
|
IMFTransform *m_pMixer; // The mixer.
|
|
IMediaEventSink *m_pMediaEventSink; // The EVR's event-sink interface.
|
|
IMFMediaType *m_pMediaType; // Output media type
|
|
};
|
|
|