DirectShow Learning (6) CTRANSFROMFILTER and the source code analysis of the associated PIN class

xiaoxiao2021-03-06  24

DirectShow Learning (6): CTRANSFROMFILTER and the source code resolution of the associated PIN class

1. The CTransformInputPin class is derived from CBaseInputpin.

a) member variables CTransformfilter * m_ptransformfilter;

b) IPin interface function: STDMETHODIMP QueryId (LPWSTR * Id) {return AMGetWideString (L "In", Id);} // provide EndOfStream that passes straight downstreamSTDMETHODIMP EndOfStream (void); {CAutoLock lck (& ​​m_pTransformFilter-> m_csReceive); HRESULT hr = CheckStreaming (); if (S_OK == hr) {hr = m_pTransformFilter-> EndOfStream ();} return hr;} // passes it to CTransformFilter :: BeginFlushSTDMETHODIMP BeginFlush (void); {CAutoLock lck (& ​​m_pTransformFilter-> m_csFilter); if (IsConnected (!) || m_pTransformFilter-> m_pOutput-> IsConnected ()) {return VFW_E_NOT_CONNECTED;}! HRESULT hr = CBaseInputPin :: BeginFlush (); return m_pTransformFilter-> BeginFlush ();} // passes it to CTransformFilter :: EndFlushSTDMETHODIMP EndFlush (void); {CAutoLock lck (& ​​m_pTransformFilter-> m_csFilter); (!! IsConnected () || m_pTransformFilter-> m_pOutput-> IsConnected ()) if {return VFW_E_NOT_CONNECTED;} HRESULT hr = m_pTransformFilter-> Endflush (); return cbaseinputpin :: endflush );} STDMETHODIMP NewSegment (REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); {// Save the values ​​in the pin CBasePin :: NewSegment (tStart, tStop, dRate); return m_pTransformFilter-> NewSegment (tStart, tStop, dRate); }

c) IMemInputPin interface function // here's the next block of data from the stream.// AddRef it yourself if you need to hold it beyond the end // of this call.STDMETHODIMP Receive (IMediaSample * pSample); {CAutoLock lck ( & m_pTransformFilter-> m_csReceive); // check all is well with the base class hr = CBaseInputPin :: Receive (pSample); if (S_OK == hr) {hr = m_pTransformFilter-> Receive (pSample);} return hr;}

d) inherited from CBasePin and CBaseInputPin function: HRESULT CheckConnect (IPin * pPin); {HRESULT hr = m_pTransformFilter-> CheckConnect (PINDIR_INPUT, pPin); return CBaseInputPin :: CheckConnect (pPin);} HRESULT BreakConnect (); {m_pTransformFilter- > BreakConnect (PINDIR_INPUT); return CBaseInputPin :: BreakConnect ();} HRESULT CompleteConnect (IPin * pReceivePin); {HRESULT hr = m_pTransformFilter-> CompleteConnect (PINDIR_INPUT, pReceivePin); return CBaseInputPin :: CompleteConnect (pReceivePin);} HRESULT CheckMediaType ( const CMediaType * mtIn); {HRESULT hr = m_pTransformFilter-> CheckInputType (pmt); // if the output pin is still connected, then we have // ​​to check the transform not just the input format if ((m_pTransformFilter-> m_pOutput! = NULL) && (m_pTransformFilter-> m_pOutput-> IsConnected ())) {return m_pTransformFilter-> CheckTransform (pmt, & m_pTransformFilter-> m_pOutput-> CurrentMediaType ());} else {return hr;}} // set the connec tion media typeHRESULT SetMediaType (const CMediaType * mt); {// Set the base class media type (should always succeed) HRESULT hr = CBasePin :: SetMediaType (mtIn); // check the transform can be done (should always succeed) ASSERT (SUCCEEDED (m_pTransformFilter-> CheckInputType (mtIn))); return m_pTransformFilter-> SetMediaType (PINDIR_INPUT, mtIn);} // Check if it's OK to process samplesvirtual HRESULT CheckStreaming (); {// the CheckStreaming CBaseInputPin similar function, but Increase the Output PIN of the TRANSFORM FILTER to connect} 2. CTRANSFORMOUTPUTPIN class is derived from CBASEOUTPUTPIN.

a) member variables: CTransformFilter * m_pTransformFilter; // implement IMediaPosition by passing upstreamIUnknown * m_pPosition; b) NonDelegatingQueryInterface function STDMETHODIMP NonDelegatingQueryInterface (REFIID riid, void ** ppv) {if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {/ / we should have an input pin by now if (m_pPosition == NULL) {HRESULT hr = CreatePosPassThru (GetOwner (), FALSE, (IPin *) m_pTransformFilter-> m_pInput, & m_pPosition); return m_pPosition-> QueryInterface (riid, ppv) ;} else {return CBaseOutputPin :: NonDelegatingQueryInterface (riid, ppv);}} STDAPI CreatePosPassThru (LPUNKNOWN pAgg, BOOL bRenderer, IPin * pPin, IUnknown ** ppPassThru) {HRESULT hr = CoCreateInstance (CLSID_SeekingPassThru, pAgg, CLSCTX_INPROC_SERVER, IID_IUnknown, ( void **) & punkseek; IzeekingPassthru * PPASSTHRU; hr = punkseek-> queryinterface (IID_ID_ISEEKINGPASSTHRU); hr = ppassthru-> init (Brenderer, PPIN PPASSTHRU-> Release (); * PPPASSTHRU = PUNKSeek;}

c) IPIN interface functions stdmethodimp queryid (lpwstr * id) {Return AMGETWIDESTRING (L "out", ID);}

d) IQualityControl interface function STDMETHODIMP Notify (IBaseFilter * pSender, Quality q); ​​{// First see if we want to handle this ourselves HRESULT hr = m_pTransformFilter-> AlterQuality (q);! if (hr = S_FALSE) {return hr ; // Either s_ok or a failure} return m_ptransformfilter-> m_pinput-> Passnotify (q);

e) inherited from CBasePin and CBaseInputPin function: HRESULT CheckConnect (IPin * pPin); {if ((m_pTransformFilter-> m_pInput-> IsConnected () == FALSE)) {return E_UNEXPECTED;} HRESULT hr = m_pTransformFilter-> CheckConnect (PINDIR_OUTPUT , pPin); return CBaseOutputPin :: CheckConnect (pPin);} HRESULT BreakConnect (); {m_pTransformFilter-> BreakConnect (PINDIR_OUTPUT); return CBaseOutputPin :: BreakConnect ();} HRESULT CompleteConnect (IPin * pReceivePin); {HRESULT hr = m_pTransformFilter -> CompleteConnect (PINDIR_OUTPUT, pReceivePin); return CBaseOutputPin :: CompleteConnect (pReceivePin);} // check that we can support this output typeHRESULT CheckMediaType (const CMediaType * mtOut); {if ((m_pTransformFilter-> m_pInput-> IsConnected () == FALSE)) {return E_INVALIDARG;} return m_pTransformFilter-> CheckTransform (& m_pTransformFilter-> m_pInput-> CurrentMediaType (), pmtOut);} // set the connection media type, called after we have agreed a media type to // actually Set IT IT ITWA run the CheckTransform function to get the // output format type againHRESULT SetMediaType (const CMediaType * pmt); {hr = CBasePin :: SetMediaType (pmtOut); return m_pTransformFilter-> SetMediaType (PINDIR_OUTPUT, pmtOut);} // called from CBaseOutputPin during connection to ask for // the count and size of buffers we need.HRESULT DecideBufferSize (IMemAllocator * pAlloc, ALLOCATOR_PROPERTIES * pProp); {return m_pTransformFilter-> DecideBufferSize (pAllocator, pProp);} // returns the preferred formats for a pinHRESULT getMediaType (int iposition, cmediatype * pmediatype); {if (m_ptransformfilter-> m_pinput->

ISconnected ()) {return m_ptransformfilter-> getMediatype (iposition, pmediatype);} else {returnvfw_s_no_more_items;}} 3. CTransformFilter class is derived from CBASEFILTER

a) a member variable BOOL m_bEOSDelivered; // have we sent EndOfStreamBOOL m_bSampleSkipped; // Did we just skip a frameBOOL m_bQualityChanged; // Have we degraded // critical section protecting filter state.CCritSec m_csFilter;? // critical section stopping state changes ( ie Stop) while we're // processing a sample This critical section is held when processing // events that occur on the receive thread -. receive () and EndOfStream () .// If you want to hold both m_csReceive and m_csFilter then GRAB / / M_CSFILTER FIRST - LIKE CTRANSFORMFILTER :: Stop () does.ccritsec m_csreceive; // THESE HOLD Our Input and output pinsctransformInputpin * m_pinput; cTransformoutputPin * m_poutput;

b) The new virtual functions: // Transform, must overridevirtual HRESULT Transform (IMediaSample * pIn, IMediaSample * pOut); // check if you can support mtIn, must overridevirtual HRESULT CheckInputType (const CMediaType * mtIn) PURE; // check if you can support the transform from this input to this output, must overridevirtual HRESULT CheckTransform (const CMediaType * mtIn, const CMediaType * mtOut) PURE; // call the SetProperties function with appropriate arguments, must overridevirtual HRESULT DecideBufferSize (IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES * pprop) PURE; // override to suggest OUTPUT pin media types, must overridevirtual HRESULT getMediaType (int iPosition, CMediaType * pMediaType) PURE; // you can also override these if you want to know about streamingvirtual HRESULT startStreaming (); {return Norror; Virtual HRESULT StopStreaming (); {Return noError;} // override if you can do anything constructive with Quality NotificationsVirtual HRESULT ALTERQUALES (Quality Q); { // Return S_false to Mean "Pass the note on upstream" // Return noerror (Same as s_ok) // to mean "I'VE DONE SOMETHING ABOUT IT IT, DON 'T PASS IT" Return S_FALSE;} // Override this to know when the media type is actually setvirtual HRESULT SetMediaType (PIN_DIRECTION direction, const CMediaType * pmt); {return NOERROR;} // chance to grab extra interfaces on connectionvirtual HRESULT CheckConnect (PIN_DIRECTION dir, IPin * pPin); {return NOERROR; } virtual HRESULT BreakConnect (PIN_DIRECTION dir); {return NOERROR;} virtual HRESULT CompleteConnect (PIN_DIRECTION direction, IPin * pReceivePin); {return NOERROR;} // chance to customize the transform processvirtual HRESULT Receive (IMediaSample * pSample);

{/ * Check for other streams and pass them on * / AM_SAMPLE2_PROPERTIES * const pProps = m_pInput-> SampleProps (); if (pProps-> dwStreamId = AM_STREAM_MEDIA!) {Return m_pOutput-> m_pInputPin-> Receive (pSample);} IMediaSample * pOutSample; // Set up the output sample hr = InitializeOutputSample (pSample, & pOutSample); // have the derived class transform the data hr = Transform (pSample, pOutSample); // the Transform () function can return S_FALSE to indicate that The // Sample Should Not Be Delivered; We Only Deliver The Sample If It's // Really S_OK (Same as Noerror, of Course) IF (HR == noError) {hr = m_poutput-> m_pinputpin-> receive (poutsample); m_bSampleSkipped = FALSE; // last thing no longer dropped} else {// S_FALSE returned from Transform is a PRIVATE agreement // We should return NOERROR from Receive () in this cause because // returning S_FALSE from Receive () means that this is The end of // the stream and no more data should be sent. If (S_FALSE == hr) {// Release the sample before calling notify to avoid // deadlocks if the sample holds a lock on the system // such as DirectDraw buffers do pOutSample -> Release (); m_bSampleSkipped = TRUE; if (m_bQualityChanged!) {NotifyEvent (EC_QUALITY_CHANGE, 0,0); m_bQualityChanged = TRUE;} return NOERROR;}} pOutSample-> Release ();} // if you override Receive, You May NEED TO OVERRIDE THESE THEE TOOVIRTUAL HRESULT Endofstream (Void); {hr = m_poutput->

DeliverEndOfStream ();} virtual HRESULT BeginFlush (void); {hr = m_pOutput-> DeliverBeginFlush ();} virtual HRESULT EndFlush (void); {return m_pOutput-> DeliverEndFlush ();} virtual HRESULT NewSegment (REFERENCE_TIME tStart, REFERENCE_TIME tStop, Double Drate; {Return M_Poutput-> DeliverneWSegment (TStart, Tstop, Drate);

c) the succession CBaseFilter function: virtual int GetPinCount (); {return 2;} virtual CBasePin * GetPin (int n); {// Create an input pin if necessary if (m_pInput == NULL) {m_pInput = new CTransformInputPin (NAME ("Transform Input Pin"), this, // o oer filter & hr, // Result code L "xform in"); // pin name m_poutput = (ctransformoutputpin *) New CTransformoutputpin (Name ("Transform Output Pin"), THIS , // RESULT CODE L "XForm out"); // pin name} // Return the appropriate Pin if (n == 0) {return m_pinput;} else if (n == 1) { Return m_poutput;} else {return null;}}}} stdmethodimp Findpin (LPCWSTR ID, IPIN ** PPPIN); {IF (0 == LSTRCMPW (ID, L "i n ")) {* pppin = getpin (0);} else if (0 == lstrcmpw (id, l")) {* pppin = getpin (1);} if (* pppin) {(* PPPIN) -> AddRef ();}} STDMETHODIMP Stop (); {CAutoLock lck1 (& m_csFilter); if (m_State == State_Stopped) {return NOERROR;} if (m_pInput == NULL || m_pInput-> IsConnected () == FALSE | | M_poutput-> iSconnected () == false) {m_state = state_stopped; m_beosdelivered = false; return noerror;} // decommit the inputlock m_pinput-> inactive ();

// synchronize with Receive calls CAutoLock lck2 (& m_csReceive); m_pOutput-> Inactive (); // allow a class derived from CTransformFilter // to know about starting and stopping streaming HRESULT hr = StopStreaming (); if (SUCCEEDED (hr)) {// complete the state transition m_State = State_Stopped; m_bEOSDelivered = FALSE;}} STDMETHODIMP Pause (); {CAutoLock lck (& ​​m_csFilter); if (m_State == State_Paused) {} ​​else if (m_pInput == NULL || m_pInput-> IsConnected () == FALSE) {if (m_pOutput && m_bEOSDelivered == FALSE) {m_pOutput-> DeliverEndOfStream (); m_bEOSDelivered = TRUE;} m_State = State_Paused;} else if (m_pOutput-> IsConnected () == FALSE) {m_State = State_Paused;} else {if (m_State == State_Stopped) {CAutoLock lck2 (& m_csReceive); hr = startStreaming ();} if (SUCCEEDED (hr)) {hr = CBaseFilter :: Pause ();}} m_bSampleSkipped = FALSE; m_bqualitychanged = FALSE;

d) Other functions // Standard setup for output sampleHRESULT InitializeOutputSample (IMediaSample * pSample, IMediaSample ** ppOutSample); {IMediaSample * pOutSample; AM_SAMPLE2_PROPERTIES * const pProps = m_pInput-> SampleProps (); DWORD dwFlags = m_bSampleSkipped AM_GBF_PREVFRAMESKIPPED:? 0; if (! (pProps-> dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {dwFlags | = AM_GBF_NOTASYNCPOINT;} HRESULT hr = m_pOutput-> m_pAllocator-> GetBuffer (& pOutSample, pProps-> dwSampleFlags & AM_SAMPLE_TIMEVALID & pProps-> tStart:? NULL, pProps-> dwSampleFlags & AM_SAMPLE_STOPVALID? & PPROPS-> TSTOP: NULL, DWFLAGS); * ppoutsample = poutsample; // If IMEDISAMPLE2 interface is supported, call the interface to set the properties, otherwise call iMediasample to set} Previous: Learn (5) CSource class and its Source code analysis of a concrete implementation example

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

New Post(0)