2 * Implements IPin and IMemInputPin. (internal)
4 * hidenori@a2.ctktv.ne.jp
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz);
20 #include "quartz_private.h"
25 /***************************************************************************
32 CPinBaseImpl_fnQueryInterface(IPin* iface,REFIID riid,void** ppobj)
34 ICOM_THIS(CPinBaseImpl,iface);
36 TRACE("(%p)->()\n",This);
38 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
42 CPinBaseImpl_fnAddRef(IPin* iface)
44 ICOM_THIS(CPinBaseImpl,iface);
46 TRACE("(%p)->()\n",This);
48 return IUnknown_AddRef(This->punkControl);
52 CPinBaseImpl_fnRelease(IPin* iface)
54 ICOM_THIS(CPinBaseImpl,iface);
56 TRACE("(%p)->()\n",This);
58 return IUnknown_Release(This->punkControl);
62 CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
64 ICOM_THIS(CPinBaseImpl,iface);
65 HRESULT hr = E_NOTIMPL;
69 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
73 TRACE("Connect() should not be sent to input pins\n");
79 TRACE("try to connect to %p\n",pPin);
81 EnterCriticalSection( This->pcsPin );
83 if ( This->pPinConnectedTo != NULL )
85 hr = VFW_E_ALREADY_CONNECTED;
89 /* return fail if running */
90 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
91 if ( hr != S_OK || fs != State_Stopped )
93 TRACE("not stopped\n");
94 hr = VFW_E_NOT_STOPPED;
98 if ( This->pHandlers->pOnPreConnect != NULL )
100 hr = This->pHandlers->pOnPreConnect(This,pPin);
103 TRACE("OnPreconnect() failed hr = %08lx\n",hr);
110 hr = IPin_QueryAccept(iface,pmt);
113 hr = IPin_ReceiveConnection(pPin,iface,pmt);
119 for ( i = 0; i < This->cAcceptTypes; i++ )
121 pmt = &This->pmtAcceptTypes[i];
122 hr = IPin_QueryAccept(iface,pmt);
125 hr = IPin_ReceiveConnection(pPin,iface,pmt);
126 TRACE("ReceiveConnection - %08lx\n",hr);
134 hr = VFW_E_TYPE_NOT_ACCEPTED;
139 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
140 if ( This->pmtConn == NULL )
143 IPin_Disconnect(pPin);
147 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
148 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
151 TRACE("no IMemInputPin\n");
152 IPin_Disconnect(pPin);
156 if ( This->pHandlers->pOnPostConnect != NULL )
158 hr = This->pHandlers->pOnPostConnect(This,pPin);
161 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
162 IPin_Disconnect(pPin);
172 IPin_Disconnect(iface);
174 LeaveCriticalSection( This->pcsPin );
176 TRACE("return %08lx\n",hr);
181 static HRESULT WINAPI
182 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
184 ICOM_THIS(CPinBaseImpl,iface);
185 HRESULT hr = E_NOTIMPL;
188 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
192 TRACE("ReceiveConnection() should not be sent to output pins\n");
195 if ( pPin == NULL || pmt == NULL )
198 EnterCriticalSection( This->pcsPin );
200 if ( This->pPinConnectedTo != NULL )
202 hr = VFW_E_ALREADY_CONNECTED;
206 /* return fail if running */
207 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
208 if ( hr != S_OK || fs != State_Stopped )
210 TRACE("not stopped\n");
211 hr = VFW_E_NOT_STOPPED;
215 if ( This->pHandlers->pOnPreConnect != NULL )
217 hr = This->pHandlers->pOnPreConnect(This,pPin);
220 TRACE("OnPreConnect() failed hr = %08lx\n",hr);
225 hr = IPin_QueryAccept(iface,pmt);
229 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
230 if ( This->pmtConn == NULL )
236 if ( This->pHandlers->pOnPostConnect != NULL )
238 hr = This->pHandlers->pOnPostConnect(This,pPin);
241 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
247 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
251 IPin_Disconnect(iface);
252 LeaveCriticalSection( This->pcsPin );
257 static HRESULT WINAPI
258 CPinBaseImpl_fnDisconnect(IPin* iface)
260 ICOM_THIS(CPinBaseImpl,iface);
261 HRESULT hr = NOERROR;
264 TRACE("(%p)->()\n",This);
266 EnterCriticalSection( This->pcsPin );
268 /* return fail if running */
269 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
270 if ( hr != S_OK || fs != State_Stopped )
272 TRACE("not stopped\n");
273 hr = VFW_E_NOT_STOPPED;
277 if ( This->pHandlers->pOnDisconnect != NULL )
278 hr = This->pHandlers->pOnDisconnect(This);
280 if ( This->pmtConn != NULL )
282 QUARTZ_MediaType_Destroy( This->pmtConn );
283 This->pmtConn = NULL;
285 if ( This->pMemInputPinConnectedTo != NULL )
287 IMemInputPin_Release(This->pMemInputPinConnectedTo);
288 This->pMemInputPinConnectedTo = NULL;
290 if ( This->pPinConnectedTo != NULL )
292 /* FIXME - cleanup */
294 IPin_Release(This->pPinConnectedTo);
295 This->pPinConnectedTo = NULL;
300 hr = S_FALSE; /* FIXME - is this correct??? */
304 LeaveCriticalSection( This->pcsPin );
309 static HRESULT WINAPI
310 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
312 ICOM_THIS(CPinBaseImpl,iface);
313 HRESULT hr = VFW_E_NOT_CONNECTED;
315 TRACE("(%p)->(%p)\n",This,ppPin);
320 EnterCriticalSection( This->pcsPin );
322 *ppPin = This->pPinConnectedTo;
323 if ( This->pPinConnectedTo != NULL )
325 IPin_AddRef(This->pPinConnectedTo);
329 LeaveCriticalSection( This->pcsPin );
334 static HRESULT WINAPI
335 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
337 ICOM_THIS(CPinBaseImpl,iface);
340 TRACE("(%p)->(%p)\n",This,pmt);
345 EnterCriticalSection( This->pcsPin );
347 if ( This->pmtConn != NULL )
349 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
353 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
354 pmt->bFixedSizeSamples = TRUE;
355 pmt->lSampleSize = 1;
356 hr = VFW_E_NOT_CONNECTED;
359 LeaveCriticalSection( This->pcsPin );
364 static HRESULT WINAPI
365 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
367 ICOM_THIS(CPinBaseImpl,iface);
369 TRACE("(%p)->(%p)\n",This,pinfo);
374 EnterCriticalSection( This->pcsPin );
376 ZeroMemory( pinfo, sizeof(PIN_INFO) );
377 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
378 if ( pinfo->pFilter != NULL )
379 IBaseFilter_AddRef( pinfo->pFilter );
380 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
381 if ( This->cbIdLen <= sizeof(pinfo->achName) )
382 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
385 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
386 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
389 LeaveCriticalSection( This->pcsPin );
394 static HRESULT WINAPI
395 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
397 ICOM_THIS(CPinBaseImpl,iface);
399 TRACE("(%p)->(%p)\n",This,pdir);
404 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
409 static HRESULT WINAPI
410 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
412 ICOM_THIS(CPinBaseImpl,iface);
414 TRACE("(%p)->(%p)\n",This,lpwszId);
416 if ( lpwszId == NULL )
419 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
420 if ( *lpwszId == NULL )
421 return E_OUTOFMEMORY;
422 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
427 static HRESULT WINAPI
428 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
430 ICOM_THIS(CPinBaseImpl,iface);
433 TRACE("(%p)->(%p)\n",This,pmt);
439 EnterCriticalSection( This->pcsPin );
440 if ( This->pHandlers->pCheckMediaType != NULL )
441 hr = This->pHandlers->pCheckMediaType(This,pmt);
442 LeaveCriticalSection( This->pcsPin );
447 static HRESULT WINAPI
448 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
450 ICOM_THIS(CPinBaseImpl,iface);
453 TRACE("(%p)->(%p)\n",This,ppenum);
455 if ( ppenum == NULL )
460 EnterCriticalSection( This->pcsPin );
461 if ( This->cAcceptTypes > 0 )
462 hr = QUARTZ_CreateEnumMediaTypes(
463 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
464 LeaveCriticalSection( This->pcsPin );
469 static HRESULT WINAPI
470 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
472 ICOM_THIS(CPinBaseImpl,iface);
474 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
476 /* E_NOTIMPL means 'no internal connections'. */
480 static HRESULT WINAPI
481 CPinBaseImpl_fnEndOfStream(IPin* iface)
483 ICOM_THIS(CPinBaseImpl,iface);
484 HRESULT hr = E_NOTIMPL;
486 TRACE("(%p)->()\n",This);
491 EnterCriticalSection( This->pcsPinReceive );
492 if ( This->pHandlers->pEndOfStream != NULL )
493 hr = This->pHandlers->pEndOfStream(This);
494 LeaveCriticalSection( This->pcsPinReceive );
499 static HRESULT WINAPI
500 CPinBaseImpl_fnBeginFlush(IPin* iface)
502 ICOM_THIS(CPinBaseImpl,iface);
503 HRESULT hr = E_NOTIMPL;
505 TRACE("(%p)->()\n",This);
510 EnterCriticalSection( This->pcsPin );
511 if ( This->pHandlers->pBeginFlush != NULL )
512 hr = This->pHandlers->pBeginFlush(This);
513 LeaveCriticalSection( This->pcsPin );
515 EnterCriticalSection( This->pcsPinReceive );
516 LeaveCriticalSection( This->pcsPinReceive );
521 static HRESULT WINAPI
522 CPinBaseImpl_fnEndFlush(IPin* iface)
524 ICOM_THIS(CPinBaseImpl,iface);
525 HRESULT hr = E_NOTIMPL;
527 TRACE("(%p)->()\n",This);
532 EnterCriticalSection( This->pcsPin );
533 if ( This->pHandlers->pEndFlush != NULL )
534 hr = This->pHandlers->pEndFlush(This);
535 LeaveCriticalSection( This->pcsPin );
540 static HRESULT WINAPI
541 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
543 ICOM_THIS(CPinBaseImpl,iface);
544 HRESULT hr = E_NOTIMPL;
546 TRACE("(%p)->()\n",This);
551 EnterCriticalSection( This->pcsPin );
552 if ( This->pHandlers->pNewSegment != NULL )
553 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
554 LeaveCriticalSection( This->pcsPin );
562 static ICOM_VTABLE(IPin) ipin =
564 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
565 /* IUnknown fields */
566 CPinBaseImpl_fnQueryInterface,
567 CPinBaseImpl_fnAddRef,
568 CPinBaseImpl_fnRelease,
570 CPinBaseImpl_fnConnect,
571 CPinBaseImpl_fnReceiveConnection,
572 CPinBaseImpl_fnDisconnect,
573 CPinBaseImpl_fnConnectedTo,
574 CPinBaseImpl_fnConnectionMediaType,
575 CPinBaseImpl_fnQueryPinInfo,
576 CPinBaseImpl_fnQueryDirection,
577 CPinBaseImpl_fnQueryId,
578 CPinBaseImpl_fnQueryAccept,
579 CPinBaseImpl_fnEnumMediaTypes,
580 CPinBaseImpl_fnQueryInternalConnections,
581 CPinBaseImpl_fnEndOfStream,
582 CPinBaseImpl_fnBeginFlush,
583 CPinBaseImpl_fnEndFlush,
584 CPinBaseImpl_fnNewSegment,
588 HRESULT CPinBaseImpl_InitIPin(
589 CPinBaseImpl* This, IUnknown* punkControl,
590 CRITICAL_SECTION* pcsPin,
591 CRITICAL_SECTION* pcsPinReceive,
592 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
594 const CBasePinHandlers* pHandlers )
596 HRESULT hr = NOERROR;
598 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
600 if ( punkControl == NULL )
602 ERR( "punkControl must not be NULL\n" );
606 ICOM_VTBL(This) = &ipin;
607 This->punkControl = punkControl;
608 This->pHandlers = pHandlers;
609 This->cbIdLen = sizeof(WCHAR)*(lstrlenW(pwszId)+1);
611 This->bOutput = bOutput;
612 This->pmtAcceptTypes = NULL;
613 This->cAcceptTypes = 0;
614 This->pcsPin = pcsPin;
615 This->pcsPinReceive = pcsPinReceive;
616 This->pFilter = pFilter;
617 This->pPinConnectedTo = NULL;
618 This->pMemInputPinConnectedTo = NULL;
619 This->pmtConn = NULL;
620 This->pAsyncOut = NULL;
622 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
623 if ( This->pwszId == NULL )
628 memcpy( This->pwszId, pwszId, This->cbIdLen );
633 CPinBaseImpl_UninitIPin( This );
637 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
639 TRACE("(%p)\n",This);
641 IPin_Disconnect( (IPin*)(This) );
643 if ( This->pwszId != NULL )
645 QUARTZ_FreeMem( This->pwszId );
651 /***************************************************************************
653 * CMemInputPinBaseImpl
658 static HRESULT WINAPI
659 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
661 ICOM_THIS(CMemInputPinBaseImpl,iface);
663 TRACE("(%p)->()\n",This);
665 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
669 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
671 ICOM_THIS(CMemInputPinBaseImpl,iface);
673 TRACE("(%p)->()\n",This);
675 return IUnknown_AddRef(This->punkControl);
679 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
681 ICOM_THIS(CMemInputPinBaseImpl,iface);
683 TRACE("(%p)->()\n",This);
685 return IUnknown_Release(This->punkControl);
689 static HRESULT WINAPI
690 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
692 ICOM_THIS(CMemInputPinBaseImpl,iface);
693 HRESULT hr = NOERROR;
696 TRACE("(%p)->()\n",This);
698 if ( ppAllocator == NULL )
701 EnterCriticalSection( This->pPin->pcsPin );
703 if ( This->pAllocator == NULL )
705 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
708 hr = IUnknown_QueryInterface(punk,
709 &IID_IMemAllocator,(void**)&This->pAllocator);
710 IUnknown_Release(punk);
716 *ppAllocator = This->pAllocator;
717 IMemAllocator_AddRef(This->pAllocator);
720 LeaveCriticalSection( This->pPin->pcsPin );
725 static HRESULT WINAPI
726 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
728 ICOM_THIS(CMemInputPinBaseImpl,iface);
730 TRACE("(%p)->()\n",This);
732 if ( pAllocator == NULL )
735 EnterCriticalSection( This->pPin->pcsPin );
737 if ( This->pAllocator != NULL )
739 IMemAllocator_Release(This->pAllocator);
740 This->pAllocator = NULL;
742 This->pAllocator = pAllocator;
743 IMemAllocator_AddRef(This->pAllocator);
745 This->bReadonly = bReadonly;
747 LeaveCriticalSection( This->pPin->pcsPin );
752 static HRESULT WINAPI
753 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
755 ICOM_THIS(CMemInputPinBaseImpl,iface);
757 TRACE("(%p)->(%p)\n",This,pProp);
762 /* E_MOTIMPL means 'no requirements' */
766 static HRESULT WINAPI
767 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
769 ICOM_THIS(CMemInputPinBaseImpl,iface);
770 HRESULT hr = E_NOTIMPL;
772 TRACE("(%p)->(%p)\n",This,pSample);
774 EnterCriticalSection( This->pPin->pcsPinReceive );
775 if ( This->pPin->pHandlers->pReceive != NULL )
776 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
777 LeaveCriticalSection( This->pPin->pcsPinReceive );
782 static HRESULT WINAPI
783 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
785 ICOM_THIS(CMemInputPinBaseImpl,iface);
789 TRACE("(%p)->()\n",This);
791 if ( ppSample == NULL || pnSampleProcessed == NULL )
795 for ( n = 0; n < nSample; n++ )
797 hr = IMemInputPin_Receive(iface,ppSample[n]);
802 *pnSampleProcessed = n;
806 static HRESULT WINAPI
807 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
809 ICOM_THIS(CMemInputPinBaseImpl,iface);
810 HRESULT hr = E_NOTIMPL;
812 TRACE("(%p)->()\n",This);
814 EnterCriticalSection( This->pPin->pcsPin );
815 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
816 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
817 LeaveCriticalSection( This->pPin->pcsPin );
823 static ICOM_VTABLE(IMemInputPin) imeminputpin =
825 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
826 /* IUnknown fields */
827 CMemInputPinBaseImpl_fnQueryInterface,
828 CMemInputPinBaseImpl_fnAddRef,
829 CMemInputPinBaseImpl_fnRelease,
830 /* IMemInputPin fields */
831 CMemInputPinBaseImpl_fnGetAllocator,
832 CMemInputPinBaseImpl_fnNotifyAllocator,
833 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
834 CMemInputPinBaseImpl_fnReceive,
835 CMemInputPinBaseImpl_fnReceiveMultiple,
836 CMemInputPinBaseImpl_fnReceiveCanBlock,
839 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
840 CMemInputPinBaseImpl* This, IUnknown* punkControl,
843 TRACE("(%p,%p)\n",This,punkControl);
845 if ( punkControl == NULL )
847 ERR( "punkControl must not be NULL\n" );
851 ICOM_VTBL(This) = &imeminputpin;
852 This->punkControl = punkControl;
854 This->pAllocator = NULL;
855 This->bReadonly = FALSE;
860 void CMemInputPinBaseImpl_UninitIMemInputPin(
861 CMemInputPinBaseImpl* This )
863 TRACE("(%p)\n",This);
865 if ( This->pAllocator != NULL )
867 IMemAllocator_Release(This->pAllocator);
868 This->pAllocator = NULL;
872 /***************************************************************************
874 * CQualityControlPassThruImpl
878 static HRESULT WINAPI
879 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
881 ICOM_THIS(CQualityControlPassThruImpl,iface);
883 TRACE("(%p)->()\n",This);
885 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
889 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
891 ICOM_THIS(CQualityControlPassThruImpl,iface);
893 TRACE("(%p)->()\n",This);
895 return IUnknown_AddRef(This->punkControl);
899 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
901 ICOM_THIS(CQualityControlPassThruImpl,iface);
903 TRACE("(%p)->()\n",This);
905 return IUnknown_Release(This->punkControl);
909 static HRESULT WINAPI
910 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
912 ICOM_THIS(CQualityControlPassThruImpl,iface);
913 HRESULT hr = S_FALSE;
915 TRACE("(%p)->()\n",This);
917 if ( This->pControl != NULL )
918 return IQualityControl_Notify( This->pControl, pFilter, q );
920 EnterCriticalSection( This->pPin->pcsPin );
921 if ( This->pPin->pHandlers->pQualityNotify != NULL )
922 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
923 LeaveCriticalSection( This->pPin->pcsPin );
928 static HRESULT WINAPI
929 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
931 ICOM_THIS(CQualityControlPassThruImpl,iface);
933 TRACE("(%p)->()\n",This);
935 This->pControl = pControl; /* AddRef() must not be called */
940 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
942 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
943 /* IUnknown fields */
944 CQualityControlPassThruImpl_fnQueryInterface,
945 CQualityControlPassThruImpl_fnAddRef,
946 CQualityControlPassThruImpl_fnRelease,
947 /* IQualityControl fields */
948 CQualityControlPassThruImpl_fnNotify,
949 CQualityControlPassThruImpl_fnSetSink,
952 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
953 CQualityControlPassThruImpl* This, IUnknown* punkControl,
956 TRACE("(%p,%p)\n",This,punkControl);
958 if ( punkControl == NULL )
960 ERR( "punkControl must not be NULL\n" );
964 ICOM_VTBL(This) = &iqualitycontrol;
965 This->punkControl = punkControl;
971 void CQualityControlPassThruImpl_UninitIQualityControl(
972 CQualityControlPassThruImpl* This )
976 /***************************************************************************
978 * helper methods for output pins.
982 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
984 if ( This->pHandlers->pReceive == NULL )
987 return This->pHandlers->pReceive( This, pSample );
990 HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This )
992 if ( This->pHandlers->pReceiveCanBlock == NULL )
995 return This->pHandlers->pReceiveCanBlock( This );
998 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
1000 if ( This->pHandlers->pEndOfStream == NULL )
1003 return This->pHandlers->pEndOfStream( This );
1006 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
1008 if ( This->pHandlers->pBeginFlush == NULL )
1011 return This->pHandlers->pBeginFlush( This );
1014 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
1016 if ( This->pHandlers->pEndFlush == NULL )
1019 return This->pHandlers->pEndFlush( This );
1022 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1024 if ( This->pHandlers->pNewSegment == NULL )
1027 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
1032 /***************************************************************************
1034 * handlers for output pins.
1038 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1040 if ( pImpl->pMemInputPinConnectedTo == NULL )
1043 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
1046 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1048 if ( pImpl->pMemInputPinConnectedTo == NULL )
1051 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1054 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1056 if ( pImpl->pPinConnectedTo == NULL )
1059 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1062 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1064 if ( pImpl->pPinConnectedTo == NULL )
1067 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1070 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1072 if ( pImpl->pPinConnectedTo == NULL )
1075 return IPin_EndFlush(pImpl->pPinConnectedTo);
1078 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1080 if ( pImpl->pPinConnectedTo == NULL )
1083 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1086 /***************************************************************************
1088 * handlers for output pins (async).
1092 typedef struct OutputPinTask OutputPinTask;
1094 enum OutputPinTaskType
1098 OutTask_EndOfStream,
1104 struct OutputPinTask
1106 OutputPinTask* pNext;
1107 enum OutputPinTaskType tasktype;
1108 IMediaSample* pSample;
1109 REFERENCE_TIME rtStart;
1110 REFERENCE_TIME rtStop;
1114 struct OutputPinAsyncImpl
1116 HANDLE m_hTaskThread;
1117 HANDLE m_hTaskEvent;
1118 IPin* m_pPin; /* connected pin */
1119 IMemInputPin* m_pMemInputPin; /* connected pin */
1120 CRITICAL_SECTION m_csTasks;
1121 OutputPinTask* m_pFirst;
1122 OutputPinTask* m_pLast;
1123 OutputPinTask* m_pTaskExitThread;
1126 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1128 OutputPinTask* pTask;
1130 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1131 pTask->pNext = NULL;
1132 pTask->tasktype = tasktype;
1133 pTask->pSample = NULL;
1138 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1140 if ( pTask->pSample != NULL )
1141 IMediaSample_Release( pTask->pSample );
1142 QUARTZ_FreeMem( pTask );
1145 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1147 EnterCriticalSection( &This->m_csTasks );
1151 pTask->pNext = This->m_pFirst;
1152 This->m_pFirst = pTask;
1153 if ( This->m_pLast == NULL )
1154 This->m_pLast = pTask;
1158 if ( This->m_pLast != NULL )
1159 This->m_pLast->pNext = pTask;
1161 This->m_pFirst = pTask;
1162 This->m_pLast = pTask;
1165 LeaveCriticalSection( &This->m_csTasks );
1167 SetEvent( This->m_hTaskEvent );
1170 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1172 OutputPinTask* pTask;
1174 EnterCriticalSection( &This->m_csTasks );
1175 pTask = This->m_pFirst;
1176 if ( pTask != NULL )
1178 This->m_pFirst = pTask->pNext;
1179 if ( This->m_pFirst == NULL )
1180 This->m_pLast = NULL;
1182 SetEvent( This->m_hTaskEvent );
1185 LeaveCriticalSection( &This->m_csTasks );
1190 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1192 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1193 OutputPinTask* pTask;
1195 BOOL bInFlush = FALSE;
1200 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1201 ResetEvent( This->m_hTaskEvent );
1203 pTask = OutputPinAsync_GetNextTask( This );
1204 if ( pTask == NULL )
1208 switch ( pTask->tasktype )
1210 case OutTask_ExitThread:
1213 case OutTask_Receive:
1215 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1217 case OutTask_EndOfStream:
1218 hr = IPin_EndOfStream( This->m_pPin );
1220 case OutTask_BeginFlush:
1222 hr = IPin_BeginFlush( This->m_pPin );
1224 case OutTask_EndFlush:
1226 hr = IPin_EndFlush( This->m_pPin );
1228 case OutTask_NewSegment:
1229 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1232 ERR( "unexpected task type %d.\n", pTask->tasktype );
1237 OutputPinAsync_FreeTask( pTask );
1241 ERR( "hresult %08lx\n", hr );
1249 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1254 FIXME("(%p)\n",pImpl);
1256 if ( pImpl->pMemInputPinConnectedTo == NULL )
1259 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1260 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1261 if ( pImpl->pAsyncOut == NULL )
1262 return E_OUTOFMEMORY;
1264 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1265 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1266 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1267 pImpl->pAsyncOut->m_pFirst = NULL;
1268 pImpl->pAsyncOut->m_pLast = NULL;
1269 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1270 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1271 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1273 pImpl->pAsyncOut->m_hTaskEvent =
1274 CreateEventA( NULL, TRUE, FALSE, NULL );
1275 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1281 pImpl->pAsyncOut->m_pTaskExitThread =
1282 OutputPinAsync_AllocTask( OutTask_ExitThread );
1283 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1289 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1290 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1292 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1300 OutputPinAsync_OnInactive( pImpl );
1304 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1306 OutputPinTask* pTask;
1308 FIXME("(%p)\n",pImpl);
1310 if ( pImpl->pAsyncOut == NULL )
1313 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1315 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1316 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1319 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1321 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1322 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1324 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1325 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1327 /* release all tasks. */
1330 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1331 if ( pTask == NULL )
1333 OutputPinAsync_FreeTask( pTask );
1336 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1338 QUARTZ_FreeMem( pImpl->pAsyncOut );
1339 pImpl->pAsyncOut = NULL;
1344 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1346 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1347 OutputPinTask* pTask;
1349 TRACE("(%p,%p)\n",pImpl,pSample);
1354 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1355 if ( pTask == NULL )
1356 return E_OUTOFMEMORY;
1357 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1358 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1363 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1368 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1370 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1371 OutputPinTask* pTask;
1373 TRACE("(%p)\n",pImpl);
1378 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1379 if ( pTask == NULL )
1380 return E_OUTOFMEMORY;
1381 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1386 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1388 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1389 OutputPinTask* pTask;
1391 TRACE("(%p)\n",pImpl);
1396 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1397 if ( pTask == NULL )
1398 return E_OUTOFMEMORY;
1399 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1404 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1406 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1407 OutputPinTask* pTask;
1409 TRACE("(%p)\n",pImpl);
1414 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1415 if ( pTask == NULL )
1416 return E_OUTOFMEMORY;
1417 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1422 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1424 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1425 OutputPinTask* pTask;
1427 TRACE("(%p)\n",pImpl);
1432 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1433 if ( pTask == NULL )
1434 return E_OUTOFMEMORY;
1435 pTask->rtStart = rtStart;
1436 pTask->rtStop = rtStop;
1438 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );