DirectShow Learning (8): Source Code Analysis of CBASERENDER Class and Class PIN

xiaoxiao2021-03-06  44

DirectShow Learning (8): Source Code Analysis of CBASERENDER Class and Class PIN 1. CrenderRinputPin class [renbase.h / renbase.cpp] derived from CBaseInputpin.

a) member variable: CBASERENDERER * m_PRENDERER;

b) IPin inherited interfaces and functions HRESULT BreakConnect (); {HRESULT hr = m_pRenderer-> BreakConnect (); return CBaseInputPin :: BreakConnect ();} HRESULT CompleteConnect (IPin * pReceivePin); {HRESULT hr = m_pRenderer-> CompleteConnect ( pReceivePin); return CBaseInputPin :: CompleteConnect (pReceivePin);} HRESULT SetMediaType (const CMediaType * pmt); {HRESULT hr = CBaseInputPin :: SetMediaType (pmt); return m_pRenderer-> SetMediaType (pmt);} HRESULT CheckMediaType (const CMediaType * pmt); {return m_pRenderer-> CheckMediaType (pmt);} HRESULT Active (); {return m_pRenderer-> Active ();} HRESULT Inactive (); {ASSERT (CritCheckIn (& m_pRenderer-> m_InterfaceLock)); m_bRunTimeError = FALSE; return m_pRenderer-> Inactive ();} STDMETHODIMP QueryId (LPWSTR * Id); {* Id = (LPWSTR) CoTaskMemAlloc (8); lstrcpyW (* Id, L "In");} STDMETHODIMP EndOfStream (); {CAutoLock cRendererLock ( & m_prenderer-> m_interfacelock); Cautolock CsampleLock (& ​​M_Prenderer-> m_rendrerlock); HRESULT HR = Checkstreaming (); hr = m_prendere r-> EndOfStream (); hr = CBaseInputPin :: EndOfStream ();} STDMETHODIMP BeginFlush (); {HRESULT hr = m_pRenderer-> EndFlush (); hr = CBaseInputPin :: EndFlush ();} STDMETHODIMP EndFlush (); {CAutoLock cRendererLock (& ​​m_pRenderer-> m_InterfaceLock); CAutoLock cSampleLock (& ​​m_pRenderer-> m_RendererLock); CBaseInputPin :: BeginFlush (); m_pRenderer-> BeginFlush (); return m_pRenderer-> ResetEndOfStream ();} STDMETHODIMP Receive (IMediaSample * pMediaSample); {HRESULT HR = m_prenderer-> received (psample); failed (hr)) {assert (critcheckout); Cautolock CrenderLock (&)

m_pRenderer-> m_InterfaceLock);!! if (! IsStopped () && IsFlushing () && m_pRenderer-> m_bAbort && m_bRunTimeError) {m_pRenderer-> NotifyEvent (EC_ERRORABORT, hr, 0);! CAutoLock alRendererLock (& ​​m_pRenderer-> m_RendererLock); if (m_pRenderer-> isStreaming () && m_pRenderer-> IsEndOfStreamDelivered ()!) {m_pRenderer-> NotifyEndOfStream ();} m_bRunTimeError = TRUE;.}}} 2 CBaseRender class [renbase.h / renbase.cpp] derived from CBaseFilter.

a) Member variable crendrepospassthru * m_pposition; // media seeking pass by Object class CrenderposposPassthru derived from CPSPASSTHRU, the latter inherited from interface iMediaseEKing and class cmediaposition. The class cmediaposition implements interface IMEDIAPSION.

See the specific implementation ctlutil.hCAMEvent m_RenderEvent; // Used to signal timer eventsCAMEvent m_ThreadSignal; // Signalled to release worker threadCAMEvent m_evComplete; // Signalled when state completeBOOL m_bAbort; // Stop us from rendering more dataBOOL m_bStreaming; // Are we currently streamingDWORD_PTR m_dwAdvise; // Timer advise cookieIMediaSample * m_pMediaSample; // Current image media sampleBOOL m_bEOS; // Any more samples in the streamBOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETECRendererInputPin * m_pInputPin; // Our renderer input pin objectCCritSec m_InterfaceLock; // Critical section for interfacesCCritSec m_RendererLock; // Controls access to internalsIQualityControl * m_pQSink; // QualityControl sinkBOOL m_bRepaintStatus; // Can we signal an EC_REPAINT // Avoid some deadlocks by tracking filter dur ing stopvolatile BOOL m_bInReceive; // Inside Receive between PrepareReceive // ​​And actually processing the sampleREFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETEUINT m_EndOfStreamTimer; // Used to signal end of streamCCritSec m_ObjectCreationLock; // This lock protects the creation and // of M_pposition and m_pinputpin. It Ensures That Two Threads Cannot Create // Either Object Simultaneously The constructor is initialized to each member,

m_evComplete (TRUE), m_bAbort (FALSE), m_pPosition (NULL), m_ThreadSignal (TRUE), m_bStreaming (FALSE), m_bEOS (FALSE), m_bEOSDelivered (FALSE), m_pMediaSample (NULL), m_dwAdvise (0), m_pQSink (NULL), m_pinputpin (null), m_brepaintstatus (true), m_signaltime (0), m_binreceive (false), m_endofstreamtimer (0); in the destructive function calls StopStreaming and Clearpendingsample; and delete m_pposition and m_pinputpin.

b) newly added virtual functions // Overriden to say what interfaces we support and wherevirtual HRESULT GetMediaPositionInterface (REFIID riid, void ** ppv); {CAutoLock cObjectCreationLock (& ​​m_ObjectCreationLock); if (m_pPosition) {return m_pPosition-> NonDelegatingQueryInterface (riid, ppv);} m_pPosition = new CRendererPosPassThru (NAME ( "Renderer CPosPassThru"), CBaseFilter :: GetOwner (), (HRESULT *) & hr, GetPin (0)); return GetMediaPositionInterface (riid, ppv);} virtual HRESULT SourceThreadCanWait (BOOL bCanWait); {if (bCanWait == TRUE) m_ThreadSignal.Reset (); else m_ThreadSignal.Set ();} virtual HRESULT WaitForRenderTime (); {HANDLE WaitObjects [] = {m_ThreadSignal, m_RenderEvent}; OnWaitStart (); while (Result == WAIT_TIMEOUT) {Result = WaitForMultipleObjects (2, WaitObjects, FALSE, RENDER_TIMEOUT);} OnWaitEnd (); if (Result == WAIT_OBJECT_0) {return VFW_E_STATE_CHANGED;} SignalTimerFired ();} virtual HRESULT CompleteStateChange (FILTER_STATE oldState); { IF (m_pinputpin-> iSconnected () == false) {ready (); return s_ok;} if (isendofStream () == true) {ready (); returnes s_ok;} if (Havecurrentsample () == True) {IF (oldState = State_Stopped!) {Ready (); return S_OK;}} NotReady ();} virtual void OnReceiveFirstSample (IMediaSample * pMediaSample) {}; virtual void OnRenderStart (IMediaSample * pMediaSample) {} virtual void OnRenderEnd (IMediaSample * pMediaSample) {} virtual HRESULT OnStartStreaming () {return NOERROR;}; virtual HRESULT OnStopStreaming () {return NOERROR;}; virtual void OnWaitStart () {}; virtual void OnWaitEnd () {}; virtual void PrepareRender () {};

// Quality management implementation for scheduling renderingvirtual BOOL ScheduleSample (IMediaSample * pMediaSample); {REFERENCE_TIME StartSample, EndSample; if (pMediaSample == NULL) {return FALSE;} HRESULT hr = GetSampleTimes (pMediaSample, & StartSample, & EndSample); if (FAILED ( hr)) {return FALSE;} if (hr == S_OK) {EXECUTE_ASSERT (SetEvent ((HANDLE) m_RenderEvent)); return TRUE;} ASSERT (WAIT_TIMEOUT == WaitForSingleObject ((HANDLE) m_RenderEvent, 0)); hr = m_pClock -> AdviseTime ((REFERENCE_TIME) m_tStart, // Start run time StartSample, // Stream time (hEVENT) (HANDLE) m_RenderEvent, // Render notification & m_dwAdvise); // Advise cookie if (SUCCEEDED (hr)) {return TRUE; } Return False;} Virtual HRESULT GETSAMPLETIMES (IMEDISAMPLE * PMEDISAMPLE, REFERENCE_TIME * PSTARTTIME, REFERENCE_TIME * PENDTIME); { if (SUCCEEDED (pMediaSample-> GetTime (pStartTime, pEndTime))) {if (* pEndTime <* pStartTime) {return VFW_E_START_TIME_AFTER_END;}} else {return S_OK;} if (m_pClock == NULL) {return S_OK;} return ShouldDrawSampleNow (pMediaSample, pStartTime, pEndTime);} virtual HRESULT ShouldDrawSampleNow (IMediaSample * pMediaSample, REFERENCE_TIME * ptrStart, REFERENCE_TIME * ptrEnd); {return S_FALSE;} virtual HRESULT SendEndOfStream (); {ASSERT (CritCheckIn (& m_RendererLock)); if (m_bEOS = = False || m_beosdelivered || m_endofstreamtimer) {return noerror;} = f (m_pclock ==

NULL) {return NotifyEndOfStream ();} REFERENCE_TIME Signal = m_tStart m_SignalTime; REFERENCE_TIME CurrentTime; m_pClock-> GetTime (& CurrentTime); LONG Delay = LONG ((Signal - CurrentTime) / 10000); if (Delay Unadvise (m_dwAdvise); SignalTimerFired ();} m_RenderEvent.Reset (); return (dwAdvise S_OK:? S_FALSE);} virtual HRESULT ClearPendingSample (); {CAutoLock cRendererLock (& ​​m_RendererLock); if (m_pMediaSample) {m_pMediaSample-> Release (); m_pmediasample = null;}} Virtual HRESULT PrepareReceive; {Cautolock CinterFaceLock (& ​​M_INTERFACELOCK); M_BINRECEIVE = true; hResult HR =

m_pInputPin-> CBaseInputPin :: Receive (pMediaSample); if (hr = NOERROR!) {m_bInReceive = FALSE; return E_FAIL;} if (m_pInputPin-> SampleProps () -> pMediaType) {hr = m_pInputPin-> SetMediaType ((CMediaType * ) m_pInputPin-> SampleProps () -> pMediaType); if (FAILED (hr)) {m_bInReceive = FALSE; return hr;}} CAutoLock cSampleLock (& ​​m_RendererLock); if (m_pMediaSample || m_bEOS || m_bAbort) {Ready (); m_bInReceive = FALSE; return E_UNEXPECTED;} if (m_pPosition) m_pPosition-> RegisterMediaTime (pMediaSample); if ((m_bStreaming == TRUE) && (ScheduleSample (pMediaSample) == FALSE)) {ASSERT (WAIT_TIMEOUT == WaitForSingleObject ((HANDLE) m_RenderEvent, 0)); ASSERT (CancelNotification () == S_FALSE); m_bInReceive = FALSE; return VFW_E_SAMPLE_REJECTED;} m_SignalTime = m_pInputPin-> SampleProps () -> tStop; m_pMediaSample = pMediaSample; m_pMediaSample-> AddRef (); if (m_bStreaming == false) {se tRepaintStatus (TRUE);}} virtual BOOL HaveCurrentSample (); {// Checks if there is a sample waiting at the renderer CAutoLock cRendererLock (& ​​m_RendererLock); return (m_pMediaSample == NULL FALSE:? TRUE);} virtual IMediaSample * GetCurrentSample ( ); {CAutoLock cRendererLock (& ​​m_RendererLock); if (m_pMediaSample) {m_pMediaSample-> AddRef ();} return m_pMediaSample;} virtual HRESULT Render (IMediaSample * pMediaSample); {if (pMediaSample == NULL) {return S_FALSE;} if ( M_BStreaming == false) {Return S_false;} Onrenderstart (Pmediasample); Dorendersample (Pmediasample);

OnRenderend (PmediaMple);} Virtual HRESULT Dorendersample (IMEDIAMPLE * PMEDISAMPLE) PURE

c) IBaseFilter interface function and inherit function virtual int GetPinCount (); {1} virtual CBasePin * GetPin (int n); {CAutoLock cObjectCreationLock (& ​​m_ObjectCreationLock); if (m_pInputPin == NULL) {m_pInputPin = new CRendererInputPin (this, & hr, L "In");} return m_pInputPin;} STDMETHODIMP Stop (); {CAutoLock cRendererLock (& ​​m_InterfaceLock); if (m_State == State_Stopped) {return NOERROR;} if (m_pInputPin-> IsConnected () == FALSE) {m_State = State_Stopped; return NOERROR;} CBaseFilter :: Stop (); if (m_pInputPin-> Allocator ()) {m_pInputPin-> Allocator () -> decommit ();} SetRepaintStatus (TRUE); StopStreaming (); SourceThreadCanWait (FALSE); ResetEndOfStream (); CancelNotification (); Ready (); WaitForReceiveToComplete (); m_bAbort = FALSE;} STDMETHODIMP Pause (); {CAutoLock cRendererLock (& ​​m_InterfaceLock); FILTER_STATE oldState = m_State; if (m_State == State_Paused) {return CompleteStateChange (State_Paused }} If (m_pinputpin-> isconnected () == false) {M_State = State_Paused; return CompleteStateChange (State_Paused);} HRESULT hr = CBaseFilter :: Pause (); SetRepaintStatus (TRUE); StopStreaming (); SourceThreadCanWait (TRUE); CancelNotification (); ResetEndOfStreamTimer (); if (m_pInputPin-> Allocator ()) {m_pInputPin-> Allocator () -> Commit ();} if (oldState == State_Stopped) {m_bAbort = FALSE; ClearPendingSample ();} return CompleteStateChange (oldState);} STDMETHODIMP Run (REFERENCE_TIME StartTime); {CAutoLock CrenderRerlock; filter_state = m_state; if (m_pinputpin->

IsConnected () == FALSE) {NotifyEvent (EC_COMPLETE, S_OK, (LONG_PTR) (IBaseFilter *) this); m_State = State_Running; return NOERROR;} Ready (); HRESULT hr = CBaseFilter :: Run (StartTime); SourceThreadCanWait (TRUE ); SetRepaintStatus (FALSE); if (m_pInputPin-> Allocator ()) {m_pInputPin-> Allocator () -> Commit ();} if (oldState == State_Stopped) {m_bAbort = FALSE; ClearPendingSample ();} return startStreaming ( );} STDMETHODIMP GetState (DWORD dwMSecs, FILTER_STATE * State); {checkPointer (State, E_POINTER); if (WaitDispatchingMessages (m_evComplete, dwMSecs) == WAIT_TIMEOUT) {* State = m_State; return VFW_S_STATE_INTERMEDIATE;} * State = m_State;} STDMETHODIMP FINDPIN (LPCWSTR ID, IPIN ** PPPIN); {IF (0 == LSTRCMPW (ID, L "in")) {* pppin = getpin (0); (* PPPIN) -> addRef ();}} Virtual HRESULT ACTIVE (); {RETURN NOERROR;} Virtual HRESULT INACTIVE (); {if (m_pposition) {m_pposition-> resetmediatime ();} clearpendingsample ();} Virtual HRESULT STA rtStreaming (); {CAutoLock cRendererLock (& ​​m_RendererLock); if (m_bStreaming == TRUE) {return NOERROR;} m_bStreaming = TRUE; timeBeginPeriod (1); OnStartStreaming (); ASSERT (WAIT_TIMEOUT == WaitForSingleObject ((HANDLE) m_RenderEvent, 0) ); ASSERT (CancelNotification () == S_FALSE); if (m_pMediaSample == NULL) {return SendEndOfStream ();} if (ScheduleSample (m_pMediaSample!)) m_RenderEvent.Set ();} virtual HRESULT StopStreaming (); {CAutoLock cRendererLock (& m_rendrerlock); m_beosdelivered = false; if (m_bstreaming == true) {m_bstreaming = false; onstopstreaming ();

timeEndPeriod (1);}} virtual HRESULT BeginFlush (); {if (m_State == State_Paused) {NotReady ();} SourceThreadCanWait (FALSE); CancelNotification (); ClearPendingSample (); WaitForReceiveToComplete ();} virtual HRESULT EndFlush () ; {if (m_pPosition) m_pPosition-> ResetMediaTime (); SourceThreadCanWait (TRUE);} virtual HRESULT BreakConnect (); {if (m_pQSink) {m_pQSink-> Release (); m_pQSink = NULL;} if (m_pInputPin-> IsConnected ( ) == FALSE) {return S_FALSE;} if (m_State = State_Stopped && m_pInputPin-> CanReconnectWhenActive ()) {return VFW_E_NOT_STOPPED;}!! SetRepaintStatus (FALSE); ResetEndOfStream (); ClearPendingSample (); m_bAbort = FALSE; if (State_Running == m_State) {StopStreaming ();}} virtual HRESULT SetMediaType (const CMediaType * pmt); {return NOERROR;} virtual HRESULT CompleteConnect (IPin * pReceivePin); {ASSERT (CritCheckIn (& m_InterfaceLock)); m_bAbort = FALSE; if ( State_running == getRealState ()) {HRESULT HR = StartStreaming (); SetRepaintStatus (FALSE);} else {SetRepaintStatus (TRUE);}} virtual HRESULT Receive (IMediaSample * pMediaSample); {HRESULT hr = PrepareReceive (pSample); if (m_State == State_Paused) {PrepareRender (); m_bInReceive = FALSE; { // We must hold both these locks CAutoLock cRendererLock (& ​​m_InterfaceLock); if (m_State == State_Stopped) return NOERROR; m_bInReceive = TRUE; CAutoLock cSampleLock (& ​​m_RendererLock); OnReceiveFirstSample (pSample);} Ready ();} hr = WaitForRenderTime () ;

if (FAILED (hr)) {m_bInReceive = FALSE; return NOERROR;} PrepareRender (); m_bInReceive = FALSE; CAutoLock cRendererLock (& ​​m_InterfaceLock); if (m_State == State_Stopped) return NOERROR; CAutoLock cSampleLock (& ​​m_RendererLock); Render (m_pMediaSample) Clearpendingsample (); sendndofstream (); cancelNotification ();} Virtual HResult Checkmediatype (const cmediatype *)

d) Other functions BOOL IsEndOfStream () {return m_bEOS;}; BOOL IsEndOfStreamDelivered () {return m_bEOSDelivered;}; BOOL IsStreaming () {return m_bStreaming;}; void SetAbortSignal (BOOL bAbort) {m_bAbort = bAbort;}; CAMEvent * GetRenderEvent () {return & m_RenderEvent;}; // Permit access to the transition statevoid Ready () {m_evComplete.Set ();}; void NotReady () {m_evComplete.Reset ();}; BOOL CheckReady () {return m_evComplete.Check ();}; FILTER_STATE GetRealState () {return m_State;}; void SendRepaint (); {CAutoLock cSampleLock (& ​​m_RendererLock); if (m_bAbort == FALSE) {if (m_pInputPin-> IsConnected () == TRUE) {if ( m_pinputpin-> isflushing () == false) {if (isendofstream () == false) {if (m_brepaintstatus == true) {ipin * ppin = (ipIN *) m_pinputpin; notifyevent (EC_REPAINT, (long_ptr) PPIN, 0) SetRepaintStatus (false);}}}}}}}} void sendnotifywindow (ipin * ppin, hwnd hwnd); { IMediaEventSink * pSink; HRESULT hr = pPin-> QueryInterface (IID_IMediaEventSink, (void **) & pSink); if (SUCCEEDED (hr)) {pSink-> Notify (EC_NOTIFY_WINDOW, LONG_PTR (hwnd), 0); pSink-> Release ( );} NotifyEvent (EC_NOTIFY_WINDOW, LONG_PTR (hwnd), 0);} BOOL OnDisplayChange (); {CAutoLock cSampleLock (& ​​m_RendererLock); if (m_pInputPin-> IsConnected () == FALSE) {return FALSE;} IPin * pPin = ( IPin *) m_pInputPin; m_pInputPin-> AddRef (); NotifyEvent (EC_DISPLAY_CHANGED, (LONG_PTR) pPin, 0); SetAbortSignal (TRUE); ClearPendingSample (); m_pInputPin-> Release ();} void SetRepaintStatus (BOOL bRepaint);

{CAutoLock cSampleLock (& ​​m_RendererLock); m_bRepaintStatus = bRepaint;} void TimerCallback (); {CAutoLock cRendererLock (& ​​m_RendererLock); if (m_EndOfStreamTimer) {m_EndOfStreamTimer = 0; SendEndOfStream ();}} void ResetEndOfStreamTimer (); {ASSERT (CritCheckOut (& m_RendererLock )); if (m_EndOfStreamTimer) {timeKillEvent (m_EndOfStreamTimer); m_EndOfStreamTimer = 0;}} HRESULT NotifyEndOfStream (); {CAutoLock cRendererLock (& ​​m_RendererLock); if (m_bStreaming == FALSE) {return NOERROR;} m_EndOfStreamTimer = 0; if (m_pPosition ) m_pPosition-> EOS (); m_bEOSDelivered = TRUE; return NotifyEvent (EC_COMPLETE, S_OK, (LONG_PTR) (IBaseFilter *) this);} void SignalTimerFired (); {m_dwAdvise = 0;} void WaitForReceiveToComplete (); {for (; ;) {if (m_bInReceive) {break;!} MSG msg; // Receive all interthread sendmessages PeekMessage (& msg, NULL, WM_NULL, WM_NULL, PM_NOREMOVE); Sleep (1);} if (HIWORD (GetQueueStatus (QS _POSTMESSAGE)) & QS_POSTMESSAGE) {PostThreadMessage (GetCurrentThreadId (), WM_NULL, 0, 0);}} STDMETHODIMP NonDelegatingQueryInterface (REFIID riid, void ** ppv) {if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {return GetMediaPositionInterface (riid, ppv);} else {return cbasefilter :: NondelegatingQueryinterface (riid, ppv);}}

e) friend function friend void CALLBACK EndOfStreamTimer (UINT uID, // Timer identifier UINT uMsg, // Not currently used DWORD_PTR dwUser, // User information DWORD_PTR dw1, // Windows reserved DWORD_PTR dw2); // Is also reserved {CBaseRenderer * prenderuere = (CBASERENDER *) dwuser; prenderuere-> TimerCallback ();} Previous article:

(7) Source code analysis of CTRANSINPLACEFILTER and associated PIN classes

转载请注明原文地址:https://www.9cbs.com/read-53642.html

New Post(0)