AJA NTV2 SDK  18.0.0.2717
NTV2 SDK 18.0.0.2717
transfrm.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // File: Transfrm.cpp
3 //
4 // Desc: DirectShow base classes - implements class for simple transform
5 // filters such as video decompressors.
6 //
7 // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
9 
10 
11 #include <streams.h>
12 #include <measure.h>
13 
14 
15 // =================================================================
16 // Implements the CTransformFilter class
17 // =================================================================
18 
20  __inout_opt LPUNKNOWN pUnk,
21  REFCLSID clsid) :
22  CBaseFilter(pName,pUnk,&m_csFilter, clsid),
23  m_pInput(NULL),
24  m_pOutput(NULL),
25  m_bEOSDelivered(FALSE),
26  m_bQualityChanged(FALSE),
27  m_bSampleSkipped(FALSE)
28 {
29 #ifdef PERF
30  RegisterPerfId();
31 #endif // PERF
32 }
33 
34 #ifdef UNICODE
36  __inout_opt LPUNKNOWN pUnk,
37  REFCLSID clsid) :
38  CBaseFilter(pName,pUnk,&m_csFilter, clsid),
39  m_pInput(NULL),
40  m_pOutput(NULL),
41  m_bEOSDelivered(FALSE),
42  m_bQualityChanged(FALSE),
43  m_bSampleSkipped(FALSE)
44 {
45 #ifdef PERF
46  RegisterPerfId();
47 #endif // PERF
48 }
49 #endif
50 
51 // destructor
52 
54 {
55  // Delete the pins
56 
57  delete m_pInput;
58  delete m_pOutput;
59 }
60 
61 
62 // Transform place holder - should never be called
63 HRESULT CTransformFilter::Transform(IMediaSample * pIn, IMediaSample *pOut)
64 {
65  UNREFERENCED_PARAMETER(pIn);
66  UNREFERENCED_PARAMETER(pOut);
67  DbgBreak("CTransformFilter::Transform() should never be called");
68  return E_UNEXPECTED;
69 }
70 
71 
72 // return the number of pins we provide
73 
75 {
76  return 2;
77 }
78 
79 
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
84 
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.
88 
89 CBasePin *
91 {
92  HRESULT hr = S_OK;
93 
94  // Create an input pin if necessary
95 
96  if (m_pInput == NULL) {
97 
98  m_pInput = new CTransformInputPin(NAME("Transform input pin"),
99  this, // Owner filter
100  &hr, // Result code
101  L"XForm In"); // Pin name
102 
103 
104  // Can't fail
105  ASSERT(SUCCEEDED(hr));
106  if (m_pInput == NULL) {
107  return NULL;
108  }
110  new CTransformOutputPin(NAME("Transform output pin"),
111  this, // Owner filter
112  &hr, // Result code
113  L"XForm Out"); // Pin name
114 
115 
116  // Can't fail
117  ASSERT(SUCCEEDED(hr));
118  if (m_pOutput == NULL) {
119  delete m_pInput;
120  m_pInput = NULL;
121  }
122  }
123 
124  // Return the appropriate pin
125 
126  if (n == 0) {
127  return m_pInput;
128  } else
129  if (n == 1) {
130  return m_pOutput;
131  } else {
132  return NULL;
133  }
134 }
135 
136 
137 //
138 // FindPin
139 //
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.
142 
143 STDMETHODIMP CTransformFilter::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
144 {
145  CheckPointer(ppPin,E_POINTER);
146  ValidateReadWritePtr(ppPin,sizeof(IPin *));
147 
148  if (0==lstrcmpW(Id,L"In")) {
149  *ppPin = GetPin(0);
150  } else if (0==lstrcmpW(Id,L"Out")) {
151  *ppPin = GetPin(1);
152  } else {
153  *ppPin = NULL;
154  return VFW_E_NOT_FOUND;
155  }
156 
157  HRESULT hr = NOERROR;
158  // AddRef() returned pointer - but GetPin could fail if memory is low.
159  if (*ppPin) {
160  (*ppPin)->AddRef();
161  } else {
162  hr = E_OUTOFMEMORY; // probably. There's no pin anyway.
163  }
164  return hr;
165 }
166 
167 
168 // override these two functions if you want to inform something
169 // about entry to or exit from streaming state.
170 
171 HRESULT
173 {
174  return NOERROR;
175 }
176 
177 
178 HRESULT
180 {
181  return NOERROR;
182 }
183 
184 
185 // override this to grab extra interfaces on connection
186 
187 HRESULT
188 CTransformFilter::CheckConnect(PIN_DIRECTION dir, IPin *pPin)
189 {
190  UNREFERENCED_PARAMETER(dir);
191  UNREFERENCED_PARAMETER(pPin);
192  return NOERROR;
193 }
194 
195 
196 // place holder to allow derived classes to release any extra interfaces
197 
198 HRESULT
200 {
201  UNREFERENCED_PARAMETER(dir);
202  return NOERROR;
203 }
204 
205 
206 // Let derived classes know about connection completion
207 
208 HRESULT
209 CTransformFilter::CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin)
210 {
211  UNREFERENCED_PARAMETER(direction);
212  UNREFERENCED_PARAMETER(pReceivePin);
213  return NOERROR;
214 }
215 
216 
217 // override this to know when the media type is really set
218 
219 HRESULT
220 CTransformFilter::SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt)
221 {
222  UNREFERENCED_PARAMETER(direction);
223  UNREFERENCED_PARAMETER(pmt);
224  return NOERROR;
225 }
226 
227 
228 // Set up our output sample
229 HRESULT
230 CTransformFilter::InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample)
231 {
232  IMediaSample *pOutSample;
233 
234  // default - times are the same
235 
236  AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();
237  DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0;
238 
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;
245  }
246 
248  HRESULT hr = m_pOutput->m_pAllocator->GetBuffer(
249  &pOutSample
250  , pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ?
251  &pProps->tStart : NULL
252  , pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ?
253  &pProps->tStop : NULL
254  , dwFlags
255  );
256  *ppOutSample = pOutSample;
257  if (FAILED(hr)) {
258  return hr;
259  }
260 
261  ASSERT(pOutSample);
262  IMediaSample2 *pOutSample2;
263  if (SUCCEEDED(pOutSample->QueryInterface(IID_IMediaSample2,
264  (void **)&pOutSample2))) {
265  /* Modify it */
266  AM_SAMPLE2_PROPERTIES OutProps;
267  EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(
268  FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps)
269  ));
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),
279  (PBYTE)&OutProps
280  );
281  if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
282  m_bSampleSkipped = FALSE;
283  }
284  pOutSample2->Release();
285  } else {
286  if (pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) {
287  pOutSample->SetTime(&pProps->tStart,
288  &pProps->tStop);
289  }
290  if (pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) {
291  pOutSample->SetSyncPoint(TRUE);
292  }
293  if (pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) {
294  pOutSample->SetDiscontinuity(TRUE);
295  m_bSampleSkipped = FALSE;
296  }
297  // Copy the media times
298 
299  LONGLONG MediaStart, MediaEnd;
300  if (pSample->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) {
301  pOutSample->SetMediaTime(&MediaStart,&MediaEnd);
302  }
303  }
304  return S_OK;
305 }
306 
307 // override this to customize the transform process
308 
309 HRESULT
310 CTransformFilter::Receive(IMediaSample *pSample)
311 {
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);
316  }
317  HRESULT hr;
318  ASSERT(pSample);
319  IMediaSample * pOutSample;
320 
321  // If no output to deliver to then no point sending us data
322 
323  ASSERT (m_pOutput != NULL) ;
324 
325  // Set up the output sample
326  hr = InitializeOutputSample(pSample, &pOutSample);
327 
328  if (FAILED(hr)) {
329  return hr;
330  }
331 
332  // Start timing the transform (if PERF is defined)
333  MSR_START(m_idTransform);
334 
335  // have the derived class transform the data
336 
337  hr = Transform(pSample, pOutSample);
338 
339  // Stop the clock and log it (if PERF is defined)
340  MSR_STOP(m_idTransform);
341 
342  if (FAILED(hr)) {
343  DbgLog((LOG_TRACE,1,TEXT("Error from transform")));
344  } else {
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.)
348  if (hr == NOERROR) {
349  hr = m_pOutput->m_pInputPin->Receive(pOutSample);
350  m_bSampleSkipped = FALSE; // last thing no longer dropped
351  } else {
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
355  // be sent.
356  if (S_FALSE == hr) {
357 
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;
366  }
367  return NOERROR;
368  }
369  }
370  }
371 
372  // release the output buffer. If the connected pin still needs it,
373  // it will have addrefed it itself.
374  pOutSample->Release();
375 
376  return hr;
377 }
378 
379 
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"
384 {
385  UNREFERENCED_PARAMETER(q);
386  return S_FALSE;
387 }
388 
389 
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
394 HRESULT
396 {
397  HRESULT hr = NOERROR;
398  if (m_pOutput != NULL) {
400  }
401 
402  return hr;
403 }
404 
405 
406 // enter flush state. Receives already blocked
407 // must override this if you have queued data or a worker thread
408 HRESULT
410 {
411  HRESULT hr = NOERROR;
412  if (m_pOutput != NULL) {
413  // block receives -- done by caller (CBaseInputPin::BeginFlush)
414 
415  // discard queued data -- we have no queued data
416 
417  // free anyone blocked on receive - not possible in this filter
418 
419  // call downstream
421  }
422  return hr;
423 }
424 
425 
426 // leave flush state. must override this if you have queued data
427 // or a worker thread
428 HRESULT
430 {
431  // sync with pushing thread -- we have no worker thread
432 
433  // ensure no more data to go downstream -- we have no queued data
434 
435  // call EndFlush on downstream pins
436  ASSERT (m_pOutput != NULL);
437  return m_pOutput->DeliverEndFlush();
438 
439  // caller (the input pin's method) will unblock Receives
440 }
441 
442 
443 // override these so that the derived filter can catch them
444 
445 STDMETHODIMP
447 {
448  CAutoLock lck1(&m_csFilter);
449  if (m_State == State_Stopped) {
450  return NOERROR;
451  }
452 
453  // Succeed the Stop if we are not completely connected
454 
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;
460  return NOERROR;
461  }
462 
463  ASSERT(m_pInput);
464  ASSERT(m_pOutput);
465 
466  // decommit the input pin before locking or we can deadlock
467  m_pInput->Inactive();
468 
469  // synchronize with Receive calls
470 
471  CAutoLock lck2(&m_csReceive);
472  m_pOutput->Inactive();
473 
474  // allow a class derived from CTransformFilter
475  // to know about starting and stopping streaming
476 
477  HRESULT hr = StopStreaming();
478  if (SUCCEEDED(hr)) {
479  // complete the state transition
480  m_State = State_Stopped;
481  m_bEOSDelivered = FALSE;
482  }
483  return hr;
484 }
485 
486 
487 STDMETHODIMP
489 {
490  CAutoLock lck(&m_csFilter);
491  HRESULT hr = NOERROR;
492 
493  if (m_State == State_Paused) {
494  // (This space left deliberately blank)
495  }
496 
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.
501 
502  else if (m_pInput == NULL || m_pInput->IsConnected() == FALSE) {
503  if (m_pOutput && m_bEOSDelivered == FALSE) {
505  m_bEOSDelivered = TRUE;
506  }
507  m_State = State_Paused;
508  }
509 
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
512 
513  else if (m_pOutput->IsConnected() == FALSE) {
514  m_State = State_Paused;
515  }
516 
517  else {
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();
523  }
524  if (SUCCEEDED(hr)) {
526  }
527  }
528 
529  m_bSampleSkipped = FALSE;
530  m_bQualityChanged = FALSE;
531  return hr;
532 }
533 
534 HRESULT
536  REFERENCE_TIME tStart,
537  REFERENCE_TIME tStop,
538  double dRate)
539 {
540  if (m_pOutput != NULL) {
541  return m_pOutput->DeliverNewSegment(tStart, tStop, dRate);
542  }
543  return S_OK;
544 }
545 
546 // Check streaming status
547 HRESULT
549 {
552  return VFW_E_NOT_CONNECTED;
553  } else {
554  // Shouldn't be able to get any data if we're not connected!
555  ASSERT(IsConnected());
556 
557  // we're flushing
558  if (m_bFlushing) {
559  return S_FALSE;
560  }
561  // Don't process stuff in Stopped state
562  if (IsStopped()) {
563  return VFW_E_WRONG_STATE;
564  }
565  if (m_bRunTimeError) {
566  return VFW_E_RUNTIME_ERROR;
567  }
568  return S_OK;
569  }
570 }
571 
572 
573 // =================================================================
574 // Implements the CTransformInputPin class
575 // =================================================================
576 
577 
578 // constructor
579 
581  __in_opt LPCTSTR pObjectName,
582  __inout CTransformFilter *pTransformFilter,
583  __inout HRESULT * phr,
584  __in_opt LPCWSTR pName)
585  : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
586 {
587  DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
588  m_pTransformFilter = pTransformFilter;
589 }
590 
591 #ifdef UNICODE
593  __in_opt LPCSTR pObjectName,
594  __inout CTransformFilter *pTransformFilter,
595  __inout HRESULT * phr,
596  __in_opt LPCWSTR pName)
597  : CBaseInputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pName)
598 {
599  DbgLog((LOG_TRACE,2,TEXT("CTransformInputPin::CTransformInputPin")));
600  m_pTransformFilter = pTransformFilter;
601 }
602 #endif
603 
604 // provides derived filter a chance to grab extra interfaces
605 
606 HRESULT
608 {
609  HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin);
610  if (FAILED(hr)) {
611  return hr;
612  }
613  return CBaseInputPin::CheckConnect(pPin);
614 }
615 
616 
617 // provides derived filter a chance to release it's extra interfaces
618 
619 HRESULT
621 {
622  // Can't disconnect unless stopped
623  ASSERT(IsStopped());
624  m_pTransformFilter->BreakConnect(PINDIR_INPUT);
626 }
627 
628 
629 // Let derived class know when the input pin is connected
630 
631 HRESULT
633 {
634  HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);
635  if (FAILED(hr)) {
636  return hr;
637  }
638  return CBaseInputPin::CompleteConnect(pReceivePin);
639 }
640 
641 
642 // check that we can support a given media type
643 
644 HRESULT
646 {
647  // Check the input type
648 
649  HRESULT hr = m_pTransformFilter->CheckInputType(pmt);
650  if (S_OK != hr) {
651  return hr;
652  }
653 
654  // if the output pin is still connected, then we have
655  // to check the transform not just the input format
656 
657  if ((m_pTransformFilter->m_pOutput != NULL) &&
660  pmt,
662  } else {
663  return hr;
664  }
665 }
666 
667 
668 // set the media type for this connection
669 
670 HRESULT
672 {
673  // Set the base class media type (should always succeed)
674  HRESULT hr = CBasePin::SetMediaType(mtIn);
675  if (FAILED(hr)) {
676  return hr;
677  }
678 
679  // check the transform can be done (should always succeed)
680  ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn)));
681 
682  return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn);
683 }
684 
685 
686 // =================================================================
687 // Implements IMemInputPin interface
688 // =================================================================
689 
690 
691 // provide EndOfStream that passes straight downstream
692 // (there is no queued data)
693 STDMETHODIMP
695 {
697  HRESULT hr = CheckStreaming();
698  if (S_OK == hr) {
700  }
701  return hr;
702 }
703 
704 
705 // enter flushing state. Call default handler to block Receives, then
706 // pass to overridable method in filter
707 STDMETHODIMP
709 {
711  // Are we actually doing anything?
713  if (!IsConnected() ||
715  return VFW_E_NOT_CONNECTED;
716  }
717  HRESULT hr = CBaseInputPin::BeginFlush();
718  if (FAILED(hr)) {
719  return hr;
720  }
721 
722  return m_pTransformFilter->BeginFlush();
723 }
724 
725 
726 // leave flushing state.
727 // Pass to overridable method in filter, then call base class
728 // to unblock receives (finally)
729 STDMETHODIMP
731 {
733  // Are we actually doing anything?
735  if (!IsConnected() ||
737  return VFW_E_NOT_CONNECTED;
738  }
739 
740  HRESULT hr = m_pTransformFilter->EndFlush();
741  if (FAILED(hr)) {
742  return hr;
743  }
744 
745  return CBaseInputPin::EndFlush();
746 }
747 
748 
749 // here's the next block of data from the stream.
750 // AddRef it yourself if you need to hold it beyond the end
751 // of this call.
752 
753 HRESULT
754 CTransformInputPin::Receive(IMediaSample * pSample)
755 {
756  HRESULT hr;
758  ASSERT(pSample);
759 
760  // check all is well with the base class
761  hr = CBaseInputPin::Receive(pSample);
762  if (S_OK == hr) {
763  hr = m_pTransformFilter->Receive(pSample);
764  }
765  return hr;
766 }
767 
768 
769 
770 
771 // override to pass downstream
772 STDMETHODIMP
774  REFERENCE_TIME tStart,
775  REFERENCE_TIME tStop,
776  double dRate)
777 {
778  // Save the values in the pin
779  CBasePin::NewSegment(tStart, tStop, dRate);
780  return m_pTransformFilter->NewSegment(tStart, tStop, dRate);
781 }
782 
783 
784 
785 
786 // =================================================================
787 // Implements the CTransformOutputPin class
788 // =================================================================
789 
790 
791 // constructor
792 
794  __in_opt LPCTSTR pObjectName,
795  __inout CTransformFilter *pTransformFilter,
796  __inout HRESULT * phr,
797  __in_opt LPCWSTR pPinName)
798  : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
799  m_pPosition(NULL)
800 {
801  DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
802  m_pTransformFilter = pTransformFilter;
803 
804 }
805 
806 #ifdef UNICODE
808  __in_opt LPCSTR pObjectName,
809  __inout CTransformFilter *pTransformFilter,
810  __inout HRESULT * phr,
811  __in_opt LPCWSTR pPinName)
812  : CBaseOutputPin(pObjectName, pTransformFilter, &pTransformFilter->m_csFilter, phr, pPinName),
813  m_pPosition(NULL)
814 {
815  DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::CTransformOutputPin")));
816  m_pTransformFilter = pTransformFilter;
817 
818 }
819 #endif
820 
821 // destructor
822 
824 {
825  DbgLog((LOG_TRACE,2,TEXT("CTransformOutputPin::~CTransformOutputPin")));
826 
827  if (m_pPosition) m_pPosition->Release();
828 }
829 
830 
831 // overriden to expose IMediaPosition and IMediaSeeking control interfaces
832 
833 STDMETHODIMP
835 {
836  CheckPointer(ppv,E_POINTER);
837  ValidateReadWritePtr(ppv,sizeof(PVOID));
838  *ppv = NULL;
839 
840  if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {
841 
842  // we should have an input pin by now
843 
845 
846  if (m_pPosition == NULL) {
847 
848  HRESULT hr = CreatePosPassThru(
849  GetOwner(),
850  FALSE,
851  (IPin *)m_pTransformFilter->m_pInput,
852  &m_pPosition);
853  if (FAILED(hr)) {
854  return hr;
855  }
856  }
857  return m_pPosition->QueryInterface(riid, ppv);
858  } else {
860  }
861 }
862 
863 
864 // provides derived filter a chance to grab extra interfaces
865 
866 HRESULT
868 {
869  // we should have an input connection first
870 
872  if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
873  return E_UNEXPECTED;
874  }
875 
876  HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin);
877  if (FAILED(hr)) {
878  return hr;
879  }
880  return CBaseOutputPin::CheckConnect(pPin);
881 }
882 
883 
884 // provides derived filter a chance to release it's extra interfaces
885 
886 HRESULT
888 {
889  // Can't disconnect unless stopped
890  ASSERT(IsStopped());
891  m_pTransformFilter->BreakConnect(PINDIR_OUTPUT);
893 }
894 
895 
896 // Let derived class know when the output pin is connected
897 
898 HRESULT
900 {
901  HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);
902  if (FAILED(hr)) {
903  return hr;
904  }
905  return CBaseOutputPin::CompleteConnect(pReceivePin);
906 }
907 
908 
909 // check a given transform - must have selected input type first
910 
911 HRESULT
913 {
914  // must have selected input first
916  if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {
917  return E_INVALIDARG;
918  }
919 
922  pmtOut);
923 }
924 
925 
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
928 
929 HRESULT
931 {
932  HRESULT hr = NOERROR;
934 
936 
937  // Set the base class media type (should always succeed)
938  hr = CBasePin::SetMediaType(pmtOut);
939  if (FAILED(hr)) {
940  return hr;
941  }
942 
943 #ifdef DEBUG
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.")));
949  }
950 #endif
951 
952  return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut);
953 }
954 
955 
956 // pass the buffer size decision through to the main transform class
957 
958 HRESULT
960  IMemAllocator * pAllocator,
961  __inout ALLOCATOR_PROPERTIES* pProp)
962 {
963  return m_pTransformFilter->DecideBufferSize(pAllocator, pProp);
964 }
965 
966 
967 
968 // return a specific media type indexed by iPosition
969 
970 HRESULT
972  int iPosition,
973  __inout CMediaType *pMediaType)
974 {
976 
977  // We don't have any media types if our input is not connected
978 
980  return m_pTransformFilter->GetMediaType(iPosition,pMediaType);
981  } else {
982  return VFW_S_NO_MORE_ITEMS;
983  }
984 }
985 
986 
987 // Override this if you can do something constructive to act on the
988 // quality message. Consider passing it upstream as well
989 
990 // Pass the quality mesage on upstream.
991 
992 STDMETHODIMP
993 CTransformOutputPin::Notify(IBaseFilter * pSender, Quality q)
994 {
995  UNREFERENCED_PARAMETER(pSender);
996  ValidateReadPtr(pSender,sizeof(IBaseFilter));
997 
998  // First see if we want to handle this ourselves
999  HRESULT hr = m_pTransformFilter->AlterQuality(q);
1000  if (hr!=S_FALSE) {
1001  return hr; // either S_OK or a failure
1002  }
1003 
1004  // S_FALSE means we pass the message on.
1005  // Find the quality sink for our input pin and send it there
1006 
1008 
1010 
1011 } // Notify
1012 
1013 
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)
CTransformFilter::EndOfStream
virtual HRESULT EndOfStream(void)
Definition: transfrm.cpp:395
CBaseInputPin::PassNotify
HRESULT PassNotify(Quality &q)
Definition: amfilter.cpp:3214
CBasePin::NonDelegatingQueryInterface
DECLARE_IUNKNOWN STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
Definition: amfilter.cpp:1610
CTransformFilter::m_pOutput
CTransformOutputPin * m_pOutput
Definition: transfrm.h:299
CTransformFilter::FindPin
STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
Definition: transfrm.cpp:143
CTransformFilter::CTransformFilter
CTransformFilter(__in_opt LPCTSTR, __inout_opt LPUNKNOWN, REFCLSID clsid)
Definition: transfrm.cpp:19
CTransformFilter::m_bEOSDelivered
BOOL m_bEOSDelivered
Definition: transfrm.h:275
CUnknown::GetOwner
LPUNKNOWN GetOwner() const
Definition: combase.h:224
CBaseFilter::NotifyEvent
HRESULT NotifyEvent(long EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2)
Definition: amfilter.cpp:811
CTransformOutputPin
Definition: transfrm.h:108
ValidateReadPtr
#define ValidateReadPtr(p, cb)
Definition: wxdebug.h:239
CTransformFilter::m_csFilter
CCritSec m_csFilter
Definition: transfrm.h:281
CTransformInputPin::NewSegment
STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
Definition: transfrm.cpp:773
CBasePin
Definition: amfilter.h:330
CTransformFilter::Receive
virtual HRESULT Receive(IMediaSample *pSample)
Definition: transfrm.cpp:310
streams.h
NULL
#define NULL
Definition: ntv2caption608types.h:19
CTransformFilter::m_pInput
CTransformInputPin * m_pInput
Definition: transfrm.h:298
MSR_STOP
#define MSR_STOP(a)
Definition: measure.h:138
CTransformFilter::CheckTransform
virtual HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) PURE
CTransformOutputPin::CurrentMediaType
CMediaType & CurrentMediaType()
Definition: transfrm.h:170
CTransformOutputPin::m_pPosition
IUnknown * m_pPosition
Definition: transfrm.h:118
CTransformOutputPin::CTransformOutputPin
CTransformOutputPin(__in_opt LPCTSTR pObjectName, __inout CTransformFilter *pTransformFilter, __inout HRESULT *phr, __in_opt LPCWSTR pName)
Definition: transfrm.cpp:793
LOG_TRACE
@ LOG_TRACE
Definition: wxdebug.h:45
DbgBreak
#define DbgBreak(_x_)
Definition: wxdebug.h:201
NAME
#define NAME(_x_)
Definition: wxdebug.h:179
CBaseOutputPin::DeliverNewSegment
virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
Definition: amfilter.cpp:2784
CTransformInputPin::Receive
STDMETHODIMP Receive(IMediaSample *pSample)
Definition: transfrm.cpp:754
CTransformFilter::~CTransformFilter
~CTransformFilter()
Definition: transfrm.cpp:53
CBasePin::SetMediaType
virtual HRESULT SetMediaType(const CMediaType *)
Definition: amfilter.cpp:1991
CTransformOutputPin::GetMediaType
HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType)
Definition: transfrm.cpp:971
CBaseFilter::Pause
STDMETHODIMP Pause()
Definition: amfilter.cpp:555
CBaseOutputPin::Inactive
HRESULT Inactive(void)
Definition: amfilter.cpp:2729
CAutoLock
Definition: wxutil.h:83
CTransformFilter::CheckConnect
virtual HRESULT CheckConnect(PIN_DIRECTION dir, IPin *pPin)
Definition: transfrm.cpp:188
CBaseOutputPin::m_pInputPin
IMemInputPin * m_pInputPin
Definition: amfilter.h:718
CBaseInputPin::SampleProps
AM_SAMPLE2_PROPERTIES * SampleProps()
Definition: amfilter.h:938
CTransformFilter::BeginFlush
virtual HRESULT BeginFlush(void)
Definition: transfrm.cpp:409
CBasePin::IsConnected
BOOL IsConnected(void)
Definition: amfilter.h:499
CTransformInputPin::BreakConnect
HRESULT BreakConnect()
Definition: transfrm.cpp:620
CTransformInputPin::EndOfStream
STDMETHODIMP EndOfStream(void)
Definition: transfrm.cpp:694
CMediaType::IsValid
BOOL IsValid() const
Definition: mtype.cpp:130
CMediaType
Definition: mtype.h:18
CBaseOutputPin::CheckConnect
HRESULT CheckConnect(IPin *pPin)
Definition: amfilter.cpp:2506
n
unsigned int n
Definition: pstream.cpp:148
CTransformFilter::m_csReceive
CCritSec m_csReceive
Definition: transfrm.h:292
CTransformFilter::GetPin
virtual CBasePin * GetPin(int n)
Definition: transfrm.cpp:90
ValidateReadWritePtr
#define ValidateReadWritePtr(p, cb)
Definition: wxdebug.h:241
CTransformInputPin::CTransformInputPin
CTransformInputPin(__in_opt LPCTSTR pObjectName, __inout CTransformFilter *pTransformFilter, __inout HRESULT *phr, __in_opt LPCWSTR pName)
Definition: transfrm.cpp:580
CTransformOutputPin::CompleteConnect
HRESULT CompleteConnect(IPin *pReceivePin)
Definition: transfrm.cpp:899
CBaseInputPin::Inactive
virtual HRESULT Inactive(void)
Definition: amfilter.cpp:3166
CTransformOutputPin::BreakConnect
HRESULT BreakConnect()
Definition: transfrm.cpp:887
CTransformInputPin::EndFlush
STDMETHODIMP EndFlush(void)
Definition: transfrm.cpp:730
CTransformFilter::GetPinCount
virtual int GetPinCount()
Definition: transfrm.cpp:74
CTransformFilter::BreakConnect
virtual HRESULT BreakConnect(PIN_DIRECTION dir)
Definition: transfrm.cpp:199
MSR_START
#define MSR_START(a)
Definition: measure.h:137
CTransformFilter::CTransformInputPin
friend class CTransformInputPin
Definition: transfrm.h:296
LOG_ERROR
@ LOG_ERROR
Definition: wxdebug.h:48
CTransformFilter::StopStreaming
virtual HRESULT StopStreaming()
Definition: transfrm.cpp:179
CTransformInputPin::BeginFlush
STDMETHODIMP BeginFlush(void)
Definition: transfrm.cpp:708
CTransformOutputPin::~CTransformOutputPin
~CTransformOutputPin()
Definition: transfrm.cpp:823
pName
CHAR * pName
Definition: amvideo.cpp:26
DbgLog
#define DbgLog(_x_)
Definition: wxdebug.h:183
CTransformInputPin::CheckConnect
HRESULT CheckConnect(IPin *pPin)
Definition: transfrm.cpp:607
riid
__in REFIID riid
Definition: dllentry.cpp:192
CTransformFilter::Pause
STDMETHODIMP Pause()
Definition: transfrm.cpp:488
CTransformOutputPin::DecideBufferSize
HRESULT DecideBufferSize(IMemAllocator *pAlloc, __inout ALLOCATOR_PROPERTIES *pProp)
Definition: transfrm.cpp:959
PVOID
void * PVOID
Definition: ajatypes.h:339
CTransformFilter::Stop
STDMETHODIMP Stop()
Definition: transfrm.cpp:446
CTransformOutputPin::NonDelegatingQueryInterface
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
Definition: transfrm.cpp:834
CTransformFilter::m_bQualityChanged
BOOL m_bQualityChanged
Definition: transfrm.h:277
CBaseOutputPin::CompleteConnect
virtual HRESULT CompleteConnect(IPin *pReceivePin)
Definition: amfilter.cpp:2488
CBaseFilter::m_State
FILTER_STATE m_State
Definition: amfilter.h:156
CBaseOutputPin
Definition: amfilter.h:712
CBaseOutputPin::DeliverEndOfStream
virtual HRESULT DeliverEndOfStream(void)
Definition: amfilter.cpp:2702
CTransformInputPin::CompleteConnect
HRESULT CompleteConnect(IPin *pReceivePin)
Definition: transfrm.cpp:632
CBaseOutputPin::m_pAllocator
IMemAllocator * m_pAllocator
Definition: amfilter.h:717
CTransformFilter::Transform
virtual HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut)
Definition: transfrm.cpp:63
CTransformFilter::CompleteConnect
virtual HRESULT CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
Definition: transfrm.cpp:209
EXECUTE_ASSERT
#define EXECUTE_ASSERT(_x_)
Definition: wxdebug.h:207
CBasePin::CheckConnect
virtual HRESULT CheckConnect(IPin *)
Definition: amfilter.cpp:2007
CTransformFilter::AlterQuality
virtual HRESULT AlterQuality(Quality q)
Definition: transfrm.cpp:383
CBasePin::CompleteConnect
virtual HRESULT CompleteConnect(IPin *pReceivePin)
Definition: amfilter.cpp:1979
CTransformFilter::DecideBufferSize
virtual HRESULT DecideBufferSize(IMemAllocator *pAllocator, __inout ALLOCATOR_PROPERTIES *pprop) PURE
CBaseInputPin::m_bFlushing
BYTE m_bFlushing
Definition: amfilter.h:834
CTransformInputPin::CurrentMediaType
CMediaType & CurrentMediaType()
Definition: transfrm.h:100
CTransformFilter::InitializeOutputSample
HRESULT InitializeOutputSample(IMediaSample *pSample, __deref_out IMediaSample **ppOutSample)
Definition: transfrm.cpp:230
CBasePin::m_bRunTimeError
bool m_bRunTimeError
Definition: amfilter.h:339
CBasePin::IsStopped
BOOL IsStopped()
Definition: amfilter.h:504
CBaseFilter
Definition: amfilter.h:148
CTransformFilter::EndFlush
virtual HRESULT EndFlush(void)
Definition: transfrm.cpp:429
CBaseInputPin::EndFlush
STDMETHODIMP EndFlush(void)
Definition: amfilter.cpp:3129
CreatePosPassThru
STDAPI CreatePosPassThru(__in_opt LPUNKNOWN pAgg, BOOL bRenderer, IPin *pPin, __deref_out IUnknown **ppPassThru)
Definition: amfilter.cpp:52
CTransformOutputPin::SetMediaType
HRESULT SetMediaType(const CMediaType *pmt)
Definition: transfrm.cpp:930
CTransformFilter::SetMediaType
virtual HRESULT SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
Definition: transfrm.cpp:220
CBaseOutputPin::DeliverBeginFlush
virtual HRESULT DeliverBeginFlush(void)
Definition: amfilter.cpp:2763
CTransformFilter::StartStreaming
virtual HRESULT StartStreaming()
Definition: transfrm.cpp:172
CTransformOutputPin::Notify
STDMETHODIMP Notify(IBaseFilter *pSender, Quality q)
Definition: transfrm.cpp:993
CTransformFilter::CheckInputType
virtual HRESULT CheckInputType(const CMediaType *mtIn) PURE
CTransformInputPin::CheckMediaType
HRESULT CheckMediaType(const CMediaType *mtIn)
Definition: transfrm.cpp:645
CTransformFilter::m_bSampleSkipped
BOOL m_bSampleSkipped
Definition: transfrm.h:276
CBaseOutputPin::DeliverEndFlush
virtual HRESULT DeliverEndFlush(void)
Definition: amfilter.cpp:2774
CTransformOutputPin::m_pTransformFilter
CTransformFilter * m_pTransformFilter
Definition: transfrm.h:113
CTransformOutputPin::CheckMediaType
HRESULT CheckMediaType(const CMediaType *mtOut)
Definition: transfrm.cpp:912
CBaseInputPin
Definition: amfilter.h:819
CTransformFilter::CTransformOutputPin
friend class CTransformOutputPin
Definition: transfrm.h:297
CBaseInputPin::BeginFlush
STDMETHODIMP BeginFlush(void)
Definition: amfilter.cpp:3105
CTransformInputPin::SetMediaType
HRESULT SetMediaType(const CMediaType *mt)
Definition: transfrm.cpp:671
CBasePin::NewSegment
STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
Definition: amfilter.cpp:2437
CTransformInputPin::m_pTransformFilter
CTransformFilter * m_pTransformFilter
Definition: transfrm.h:38
CheckPointer
#define CheckPointer(p, ret)
Definition: wxdebug.h:225
CTransformFilter::GetMediaType
virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType) PURE
CTransformFilter::NewSegment
virtual HRESULT NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
Definition: transfrm.cpp:535
CBaseInputPin::BreakConnect
HRESULT BreakConnect()
Definition: amfilter.cpp:2921
CTransformOutputPin::CheckConnect
HRESULT CheckConnect(IPin *pPin)
Definition: transfrm.cpp:867
ASSERT
#define ASSERT(_x_)
Definition: wxdebug.h:205
CBaseInputPin::Receive
STDMETHODIMP Receive(IMediaSample *pSample)
Definition: amfilter.cpp:2952
hr
__out HRESULT & hr
Definition: pstream.cpp:145
CTransformFilter
Definition: transfrm.h:174
CTransformInputPin::CheckStreaming
virtual HRESULT CheckStreaming()
Definition: transfrm.cpp:548
measure.h
CBaseOutputPin::BreakConnect
HRESULT BreakConnect()
Definition: amfilter.cpp:2525