1 //------------------------------------------------------------------------------
4 // Desc: DirectShow base classes - implements class for simple transform
5 // filters such as video decompressors.
7 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
15 // =================================================================
16 // Implements the CTransformFilter class
17 // =================================================================
19 CTransformFilter::CTransformFilter(TCHAR
*pName
,
22 CBaseFilter(pName
,pUnk
,&m_csFilter
, clsid
),
25 m_bEOSDelivered(FALSE
),
26 m_bQualityChanged(FALSE
),
27 m_bSampleSkipped(FALSE
)
35 CTransformFilter::CTransformFilter(char *pName
,
38 CBaseFilter(pName
,pUnk
,&m_csFilter
, clsid
),
41 m_bEOSDelivered(FALSE
),
42 m_bQualityChanged(FALSE
),
43 m_bSampleSkipped(FALSE
)
53 CTransformFilter::~CTransformFilter()
62 // Transform place holder - should never be called
63 HRESULT
CTransformFilter::Transform(IMediaSample
* pIn
, IMediaSample
*pOut
)
65 UNREFERENCED_PARAMETER(pIn
);
66 UNREFERENCED_PARAMETER(pOut
);
67 DbgBreak("CTransformFilter::Transform() should never be called");
72 // return the number of pins we provide
74 int CTransformFilter::GetPinCount()
80 // return a non-addrefed CBasePin * for the user to addref if he holds onto it
81 // for longer than his pointer to us. We create the pins dynamically when they
82 // are asked for rather than in the constructor. This is because we want to
83 // give the derived class an oppportunity to return different pin objects
85 // We return the objects as and when they are needed. If either of these fails
86 // then we return NULL, the assumption being that the caller will realise the
87 // whole deal is off and destroy us - which in turn will delete everything.
90 CTransformFilter::GetPin(int n
)
94 // Create an input pin if necessary
96 if (m_pInput
== NULL
) {
98 m_pInput
= new CTransformInputPin(NAME("Transform input pin"),
101 L
"XForm In"); // Pin name
105 ASSERT(SUCCEEDED(hr
));
106 if (m_pInput
== NULL
) {
109 m_pOutput
= (CTransformOutputPin
*)
110 new CTransformOutputPin(NAME("Transform output pin"),
111 this, // Owner filter
113 L
"XForm Out"); // Pin name
117 ASSERT(SUCCEEDED(hr
));
118 if (m_pOutput
== NULL
) {
124 // Return the appropriate pin
140 // If Id is In or Out then return the IPin* for that pin
141 // creating the pin if need be. Otherwise return NULL with an error.
143 STDMETHODIMP
CTransformFilter::FindPin(LPCWSTR Id
, IPin
**ppPin
)
145 CheckPointer(ppPin
,E_POINTER
);
146 ValidateReadWritePtr(ppPin
,sizeof(IPin
*));
148 if (0==lstrcmpW(Id
,L
"In")) {
150 } else if (0==lstrcmpW(Id
,L
"Out")) {
154 return VFW_E_NOT_FOUND
;
157 HRESULT hr
= NOERROR
;
158 // AddRef() returned pointer - but GetPin could fail if memory is low.
162 hr
= E_OUTOFMEMORY
; // probably. There's no pin anyway.
168 // override these two functions if you want to inform something
169 // about entry to or exit from streaming state.
172 CTransformFilter::StartStreaming()
179 CTransformFilter::StopStreaming()
185 // override this to grab extra interfaces on connection
188 CTransformFilter::CheckConnect(PIN_DIRECTION dir
,IPin
*pPin
)
190 UNREFERENCED_PARAMETER(dir
);
191 UNREFERENCED_PARAMETER(pPin
);
196 // place holder to allow derived classes to release any extra interfaces
199 CTransformFilter::BreakConnect(PIN_DIRECTION dir
)
201 UNREFERENCED_PARAMETER(dir
);
206 // Let derived classes know about connection completion
209 CTransformFilter::CompleteConnect(PIN_DIRECTION direction
,IPin
*pReceivePin
)
211 UNREFERENCED_PARAMETER(direction
);
212 UNREFERENCED_PARAMETER(pReceivePin
);
217 // override this to know when the media type is really set
220 CTransformFilter::SetMediaType(PIN_DIRECTION direction
,const CMediaType
*pmt
)
222 UNREFERENCED_PARAMETER(direction
);
223 UNREFERENCED_PARAMETER(pmt
);
228 // Set up our output sample
230 CTransformFilter::InitializeOutputSample(IMediaSample
*pSample
, IMediaSample
**ppOutSample
)
232 IMediaSample
*pOutSample
;
234 // default - times are the same
236 AM_SAMPLE2_PROPERTIES
* const pProps
= m_pInput
->SampleProps();
237 DWORD dwFlags
= m_bSampleSkipped
? AM_GBF_PREVFRAMESKIPPED
: 0;
239 // This will prevent the image renderer from switching us to DirectDraw
240 // when we can't do it without skipping frames because we're not on a
241 // keyframe. If it really has to switch us, it still will, but then we
242 // will have to wait for the next keyframe
243 if (!(pProps
->dwSampleFlags
& AM_SAMPLE_SPLICEPOINT
)) {
244 dwFlags
|= AM_GBF_NOTASYNCPOINT
;
247 ASSERT(m_pOutput
->m_pAllocator
!= NULL
);
248 HRESULT hr
= m_pOutput
->m_pAllocator
->GetBuffer(
250 , pProps
->dwSampleFlags
& AM_SAMPLE_TIMEVALID
?
251 &pProps
->tStart
: NULL
252 , pProps
->dwSampleFlags
& AM_SAMPLE_STOPVALID
?
253 &pProps
->tStop
: NULL
256 *ppOutSample
= pOutSample
;
262 IMediaSample2
*pOutSample2
;
263 if (SUCCEEDED(pOutSample
->QueryInterface(IID_IMediaSample2
,
264 (void **)&pOutSample2
))) {
266 AM_SAMPLE2_PROPERTIES OutProps
;
267 EXECUTE_ASSERT(SUCCEEDED(pOutSample2
->GetProperties(
268 FIELD_OFFSET(AM_SAMPLE2_PROPERTIES
, tStart
), (PBYTE
)&OutProps
)
270 OutProps
.dwTypeSpecificFlags
= pProps
->dwTypeSpecificFlags
;
271 OutProps
.dwSampleFlags
=
272 (OutProps
.dwSampleFlags
& AM_SAMPLE_TYPECHANGED
) |
273 (pProps
->dwSampleFlags
& ~AM_SAMPLE_TYPECHANGED
);
274 OutProps
.tStart
= pProps
->tStart
;
275 OutProps
.tStop
= pProps
->tStop
;
276 OutProps
.cbData
= FIELD_OFFSET(AM_SAMPLE2_PROPERTIES
, dwStreamId
);
277 hr
= pOutSample2
->SetProperties(
278 FIELD_OFFSET(AM_SAMPLE2_PROPERTIES
, dwStreamId
),
281 if (pProps
->dwSampleFlags
& AM_SAMPLE_DATADISCONTINUITY
) {
282 m_bSampleSkipped
= FALSE
;
284 pOutSample2
->Release();
286 if (pProps
->dwSampleFlags
& AM_SAMPLE_TIMEVALID
) {
287 pOutSample
->SetTime(&pProps
->tStart
,
290 if (pProps
->dwSampleFlags
& AM_SAMPLE_SPLICEPOINT
) {
291 pOutSample
->SetSyncPoint(TRUE
);
293 if (pProps
->dwSampleFlags
& AM_SAMPLE_DATADISCONTINUITY
) {
294 pOutSample
->SetDiscontinuity(TRUE
);
295 m_bSampleSkipped
= FALSE
;
297 // Copy the media times
299 LONGLONG MediaStart
, MediaEnd
;
300 if (pSample
->GetMediaTime(&MediaStart
,&MediaEnd
) == NOERROR
) {
301 pOutSample
->SetMediaTime(&MediaStart
,&MediaEnd
);
307 // override this to customize the transform process
310 CTransformFilter::Receive(IMediaSample
*pSample
)
312 /* Check for other streams and pass them on */
313 AM_SAMPLE2_PROPERTIES
* const pProps
= m_pInput
->SampleProps();
314 if (pProps
->dwStreamId
!= AM_STREAM_MEDIA
) {
315 return m_pOutput
->m_pInputPin
->Receive(pSample
);
319 IMediaSample
* pOutSample
;
321 // If no output to deliver to then no point sending us data
323 ASSERT (m_pOutput
!= NULL
) ;
325 // Set up the output sample
326 hr
= InitializeOutputSample(pSample
, &pOutSample
);
332 // Start timing the transform (if PERF is defined)
333 MSR_START(m_idTransform
);
335 // have the derived class transform the data
337 hr
= Transform(pSample
, pOutSample
);
339 // Stop the clock and log it (if PERF is defined)
340 MSR_STOP(m_idTransform
);
343 DbgLog((LOG_TRACE
,1,TEXT("Error from transform")));
345 // the Transform() function can return S_FALSE to indicate that the
346 // sample should not be delivered; we only deliver the sample if it's
347 // really S_OK (same as NOERROR, of course.)
349 hr
= m_pOutput
->m_pInputPin
->Receive(pOutSample
);
350 m_bSampleSkipped
= FALSE
; // last thing no longer dropped
352 // S_FALSE returned from Transform is a PRIVATE agreement
353 // We should return NOERROR from Receive() in this cause because returning S_FALSE
354 // from Receive() means that this is the end of the stream and no more data should
358 // Release the sample before calling notify to avoid
359 // deadlocks if the sample holds a lock on the system
360 // such as DirectDraw buffers do
361 pOutSample
->Release();
362 m_bSampleSkipped
= TRUE
;
363 if (!m_bQualityChanged
) {
364 NotifyEvent(EC_QUALITY_CHANGE
,0,0);
365 m_bQualityChanged
= TRUE
;
372 // release the output buffer. If the connected pin still needs it,
373 // it will have addrefed it itself.
374 pOutSample
->Release();
380 // Return S_FALSE to mean "pass the note on upstream"
381 // Return NOERROR (Same as S_OK)
382 // to mean "I've done something about it, don't pass it on"
383 HRESULT
CTransformFilter::AlterQuality(Quality q
)
385 UNREFERENCED_PARAMETER(q
);
390 // EndOfStream received. Default behaviour is to deliver straight
391 // downstream, since we have no queued data. If you overrode Receive
392 // and have queue data, then you need to handle this and deliver EOS after
393 // all queued data is sent
395 CTransformFilter::EndOfStream(void)
397 HRESULT hr
= NOERROR
;
398 if (m_pOutput
!= NULL
) {
399 hr
= m_pOutput
->DeliverEndOfStream();
406 // enter flush state. Receives already blocked
407 // must override this if you have queued data or a worker thread
409 CTransformFilter::BeginFlush(void)
411 HRESULT hr
= NOERROR
;
412 if (m_pOutput
!= NULL
) {
413 // block receives -- done by caller (CBaseInputPin::BeginFlush)
415 // discard queued data -- we have no queued data
417 // free anyone blocked on receive - not possible in this filter
420 hr
= m_pOutput
->DeliverBeginFlush();
426 // leave flush state. must override this if you have queued data
427 // or a worker thread
429 CTransformFilter::EndFlush(void)
431 // sync with pushing thread -- we have no worker thread
433 // ensure no more data to go downstream -- we have no queued data
435 // call EndFlush on downstream pins
436 ASSERT (m_pOutput
!= NULL
);
437 return m_pOutput
->DeliverEndFlush();
439 // caller (the input pin's method) will unblock Receives
443 // override these so that the derived filter can catch them
446 CTransformFilter::Stop()
448 CAutoLock
lck1(&m_csFilter
);
449 if (m_State
== State_Stopped
) {
453 // Succeed the Stop if we are not completely connected
455 ASSERT(m_pInput
== NULL
|| m_pOutput
!= NULL
);
456 if (m_pInput
== NULL
|| m_pInput
->IsConnected() == FALSE
||
457 m_pOutput
->IsConnected() == FALSE
) {
458 m_State
= State_Stopped
;
459 m_bEOSDelivered
= FALSE
;
466 // decommit the input pin before locking or we can deadlock
467 m_pInput
->Inactive();
469 // synchronize with Receive calls
471 CAutoLock
lck2(&m_csReceive
);
472 m_pOutput
->Inactive();
474 // allow a class derived from CTransformFilter
475 // to know about starting and stopping streaming
477 HRESULT hr
= StopStreaming();
479 // complete the state transition
480 m_State
= State_Stopped
;
481 m_bEOSDelivered
= FALSE
;
488 CTransformFilter::Pause()
490 CAutoLock
lck(&m_csFilter
);
491 HRESULT hr
= NOERROR
;
493 if (m_State
== State_Paused
) {
494 // (This space left deliberately blank)
497 // If we have no input pin or it isn't yet connected then when we are
498 // asked to pause we deliver an end of stream to the downstream filter.
499 // This makes sure that it doesn't sit there forever waiting for
500 // samples which we cannot ever deliver without an input connection.
502 else if (m_pInput
== NULL
|| m_pInput
->IsConnected() == FALSE
) {
503 if (m_pOutput
&& m_bEOSDelivered
== FALSE
) {
504 m_pOutput
->DeliverEndOfStream();
505 m_bEOSDelivered
= TRUE
;
507 m_State
= State_Paused
;
510 // We may have an input connection but no output connection
511 // However, if we have an input pin we do have an output pin
513 else if (m_pOutput
->IsConnected() == FALSE
) {
514 m_State
= State_Paused
;
518 if (m_State
== State_Stopped
) {
519 // allow a class derived from CTransformFilter
520 // to know about starting and stopping streaming
521 CAutoLock
lck2(&m_csReceive
);
522 hr
= StartStreaming();
525 hr
= CBaseFilter::Pause();
529 m_bSampleSkipped
= FALSE
;
530 m_bQualityChanged
= FALSE
;
535 CTransformFilter::NewSegment(
536 REFERENCE_TIME tStart
,
537 REFERENCE_TIME tStop
,
540 if (m_pOutput
!= NULL
) {
541 return m_pOutput
->DeliverNewSegment(tStart
, tStop
, dRate
);
546 // Check streaming status
548 CTransformInputPin::CheckStreaming()
550 ASSERT(m_pTransformFilter
->m_pOutput
!= NULL
);
551 if (!m_pTransformFilter
->m_pOutput
->IsConnected()) {
552 return VFW_E_NOT_CONNECTED
;
554 // Shouldn't be able to get any data if we're not connected!
555 ASSERT(IsConnected());
561 // Don't process stuff in Stopped state
563 return VFW_E_WRONG_STATE
;
565 if (m_bRunTimeError
) {
566 return VFW_E_RUNTIME_ERROR
;
573 // =================================================================
574 // Implements the CTransformInputPin class
575 // =================================================================
580 CTransformInputPin::CTransformInputPin(
582 CTransformFilter
*pTransformFilter
,
585 : CBaseInputPin(pObjectName
, pTransformFilter
, &pTransformFilter
->m_csFilter
, phr
, pName
)
587 DbgLog((LOG_TRACE
,2,TEXT("CTransformInputPin::CTransformInputPin")));
588 m_pTransformFilter
= pTransformFilter
;
592 CTransformInputPin::CTransformInputPin(
594 CTransformFilter
*pTransformFilter
,
597 : CBaseInputPin(pObjectName
, pTransformFilter
, &pTransformFilter
->m_csFilter
, phr
, pName
)
599 DbgLog((LOG_TRACE
,2,TEXT("CTransformInputPin::CTransformInputPin")));
600 m_pTransformFilter
= pTransformFilter
;
604 // provides derived filter a chance to grab extra interfaces
607 CTransformInputPin::CheckConnect(IPin
*pPin
)
609 HRESULT hr
= m_pTransformFilter
->CheckConnect(PINDIR_INPUT
,pPin
);
613 return CBaseInputPin::CheckConnect(pPin
);
617 // provides derived filter a chance to release it's extra interfaces
620 CTransformInputPin::BreakConnect()
622 // Can't disconnect unless stopped
624 m_pTransformFilter
->BreakConnect(PINDIR_INPUT
);
625 return CBaseInputPin::BreakConnect();
629 // Let derived class know when the input pin is connected
632 CTransformInputPin::CompleteConnect(IPin
*pReceivePin
)
634 HRESULT hr
= m_pTransformFilter
->CompleteConnect(PINDIR_INPUT
,pReceivePin
);
638 return CBaseInputPin::CompleteConnect(pReceivePin
);
642 // check that we can support a given media type
645 CTransformInputPin::CheckMediaType(const CMediaType
* pmt
)
647 // Check the input type
649 HRESULT hr
= m_pTransformFilter
->CheckInputType(pmt
);
654 // if the output pin is still connected, then we have
655 // to check the transform not just the input format
657 if ((m_pTransformFilter
->m_pOutput
!= NULL
) &&
658 (m_pTransformFilter
->m_pOutput
->IsConnected())) {
659 return m_pTransformFilter
->CheckTransform(
661 &m_pTransformFilter
->m_pOutput
->CurrentMediaType());
668 // set the media type for this connection
671 CTransformInputPin::SetMediaType(const CMediaType
* mtIn
)
673 // Set the base class media type (should always succeed)
674 HRESULT hr
= CBasePin::SetMediaType(mtIn
);
679 // check the transform can be done (should always succeed)
680 ASSERT(SUCCEEDED(m_pTransformFilter
->CheckInputType(mtIn
)));
682 return m_pTransformFilter
->SetMediaType(PINDIR_INPUT
,mtIn
);
686 // =================================================================
687 // Implements IMemInputPin interface
688 // =================================================================
691 // provide EndOfStream that passes straight downstream
692 // (there is no queued data)
694 CTransformInputPin::EndOfStream(void)
696 CAutoLock
lck(&m_pTransformFilter
->m_csReceive
);
697 HRESULT hr
= CheckStreaming();
699 hr
= m_pTransformFilter
->EndOfStream();
705 // enter flushing state. Call default handler to block Receives, then
706 // pass to overridable method in filter
708 CTransformInputPin::BeginFlush(void)
710 CAutoLock
lck(&m_pTransformFilter
->m_csFilter
);
711 // Are we actually doing anything?
712 ASSERT(m_pTransformFilter
->m_pOutput
!= NULL
);
713 if (!IsConnected() ||
714 !m_pTransformFilter
->m_pOutput
->IsConnected()) {
715 return VFW_E_NOT_CONNECTED
;
717 HRESULT hr
= CBaseInputPin::BeginFlush();
722 return m_pTransformFilter
->BeginFlush();
726 // leave flushing state.
727 // Pass to overridable method in filter, then call base class
728 // to unblock receives (finally)
730 CTransformInputPin::EndFlush(void)
732 CAutoLock
lck(&m_pTransformFilter
->m_csFilter
);
733 // Are we actually doing anything?
734 ASSERT(m_pTransformFilter
->m_pOutput
!= NULL
);
735 if (!IsConnected() ||
736 !m_pTransformFilter
->m_pOutput
->IsConnected()) {
737 return VFW_E_NOT_CONNECTED
;
740 HRESULT hr
= m_pTransformFilter
->EndFlush();
745 return CBaseInputPin::EndFlush();
749 // here's the next block of data from the stream.
750 // AddRef it yourself if you need to hold it beyond the end
754 CTransformInputPin::Receive(IMediaSample
* pSample
)
757 CAutoLock
lck(&m_pTransformFilter
->m_csReceive
);
760 // check all is well with the base class
761 hr
= CBaseInputPin::Receive(pSample
);
763 hr
= m_pTransformFilter
->Receive(pSample
);
771 // override to pass downstream
773 CTransformInputPin::NewSegment(
774 REFERENCE_TIME tStart
,
775 REFERENCE_TIME tStop
,
778 // Save the values in the pin
779 CBasePin::NewSegment(tStart
, tStop
, dRate
);
780 return m_pTransformFilter
->NewSegment(tStart
, tStop
, dRate
);
786 // =================================================================
787 // Implements the CTransformOutputPin class
788 // =================================================================
793 CTransformOutputPin::CTransformOutputPin(
795 CTransformFilter
*pTransformFilter
,
798 : CBaseOutputPin(pObjectName
, pTransformFilter
, &pTransformFilter
->m_csFilter
, phr
, pPinName
),
801 DbgLog((LOG_TRACE
,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
802 m_pTransformFilter
= pTransformFilter
;
807 CTransformOutputPin::CTransformOutputPin(
809 CTransformFilter
*pTransformFilter
,
812 : CBaseOutputPin(pObjectName
, pTransformFilter
, &pTransformFilter
->m_csFilter
, phr
, pPinName
),
815 DbgLog((LOG_TRACE
,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
816 m_pTransformFilter
= pTransformFilter
;
823 CTransformOutputPin::~CTransformOutputPin()
825 DbgLog((LOG_TRACE
,2,TEXT("CTransformOutputPin::~CTransformOutputPin")));
827 if (m_pPosition
) m_pPosition
->Release();
831 // overriden to expose IMediaPosition and IMediaSeeking control interfaces
834 CTransformOutputPin::NonDelegatingQueryInterface(REFIID riid
, void **ppv
)
836 CheckPointer(ppv
,E_POINTER
);
837 ValidateReadWritePtr(ppv
,sizeof(PVOID
));
840 if (riid
== IID_IMediaPosition
|| riid
== IID_IMediaSeeking
) {
842 // we should have an input pin by now
844 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
846 if (m_pPosition
== NULL
) {
848 HRESULT hr
= CreatePosPassThru(
851 (IPin
*)m_pTransformFilter
->m_pInput
,
857 return m_pPosition
->QueryInterface(riid
, ppv
);
859 return CBaseOutputPin::NonDelegatingQueryInterface(riid
, ppv
);
864 // provides derived filter a chance to grab extra interfaces
867 CTransformOutputPin::CheckConnect(IPin
*pPin
)
869 // we should have an input connection first
871 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
872 if ((m_pTransformFilter
->m_pInput
->IsConnected() == FALSE
)) {
876 HRESULT hr
= m_pTransformFilter
->CheckConnect(PINDIR_OUTPUT
,pPin
);
880 return CBaseOutputPin::CheckConnect(pPin
);
884 // provides derived filter a chance to release it's extra interfaces
887 CTransformOutputPin::BreakConnect()
889 // Can't disconnect unless stopped
891 m_pTransformFilter
->BreakConnect(PINDIR_OUTPUT
);
892 return CBaseOutputPin::BreakConnect();
896 // Let derived class know when the output pin is connected
899 CTransformOutputPin::CompleteConnect(IPin
*pReceivePin
)
901 HRESULT hr
= m_pTransformFilter
->CompleteConnect(PINDIR_OUTPUT
,pReceivePin
);
905 return CBaseOutputPin::CompleteConnect(pReceivePin
);
909 // check a given transform - must have selected input type first
912 CTransformOutputPin::CheckMediaType(const CMediaType
* pmtOut
)
914 // must have selected input first
915 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
916 if ((m_pTransformFilter
->m_pInput
->IsConnected() == FALSE
)) {
920 return m_pTransformFilter
->CheckTransform(
921 &m_pTransformFilter
->m_pInput
->CurrentMediaType(),
926 // called after we have agreed a media type to actually set it in which case
927 // we run the CheckTransform function to get the output format type again
930 CTransformOutputPin::SetMediaType(const CMediaType
* pmtOut
)
932 HRESULT hr
= NOERROR
;
933 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
935 ASSERT(m_pTransformFilter
->m_pInput
->CurrentMediaType().IsValid());
937 // Set the base class media type (should always succeed)
938 hr
= CBasePin::SetMediaType(pmtOut
);
944 if (FAILED(m_pTransformFilter
->CheckTransform(&m_pTransformFilter
->
945 m_pInput
->CurrentMediaType(),pmtOut
))) {
946 DbgLog((LOG_ERROR
,0,TEXT("*** This filter is accepting an output media type")));
947 DbgLog((LOG_ERROR
,0,TEXT(" that it can't currently transform to. I hope")));
948 DbgLog((LOG_ERROR
,0,TEXT(" it's smart enough to reconnect its input.")));
952 return m_pTransformFilter
->SetMediaType(PINDIR_OUTPUT
,pmtOut
);
956 // pass the buffer size decision through to the main transform class
959 CTransformOutputPin::DecideBufferSize(
960 IMemAllocator
* pAllocator
,
961 ALLOCATOR_PROPERTIES
* pProp
)
963 return m_pTransformFilter
->DecideBufferSize(pAllocator
, pProp
);
968 // return a specific media type indexed by iPosition
971 CTransformOutputPin::GetMediaType(
973 CMediaType
*pMediaType
)
975 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
977 // We don't have any media types if our input is not connected
979 if (m_pTransformFilter
->m_pInput
->IsConnected()) {
980 return m_pTransformFilter
->GetMediaType(iPosition
,pMediaType
);
982 return VFW_S_NO_MORE_ITEMS
;
987 // Override this if you can do something constructive to act on the
988 // quality message. Consider passing it upstream as well
990 // Pass the quality mesage on upstream.
993 CTransformOutputPin::Notify(IBaseFilter
* pSender
, Quality q
)
995 UNREFERENCED_PARAMETER(pSender
);
996 ValidateReadPtr(pSender
,sizeof(IBaseFilter
));
998 // First see if we want to handle this ourselves
999 HRESULT hr
= m_pTransformFilter
->AlterQuality(q
);
1001 return hr
; // either S_OK or a failure
1004 // S_FALSE means we pass the message on.
1005 // Find the quality sink for our input pin and send it there
1007 ASSERT(m_pTransformFilter
->m_pInput
!= NULL
);
1009 return m_pTransformFilter
->m_pInput
->PassNotify(q
);
1014 // the following removes a very large number of level 4 warnings from the microsoft
1015 // compiler output, which are not useful at all in this case.
1016 #pragma warning(disable:4514)