2 * Implements IPin and IMemInputPin. (internal)
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
34 #include "quartz_private.h"
39 /***************************************************************************
46 CPinBaseImpl_fnQueryInterface(IPin* iface,REFIID riid,void** ppobj)
48 ICOM_THIS(CPinBaseImpl,iface);
50 TRACE("(%p)->()\n",This);
52 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
56 CPinBaseImpl_fnAddRef(IPin* iface)
58 ICOM_THIS(CPinBaseImpl,iface);
60 TRACE("(%p)->()\n",This);
62 return IUnknown_AddRef(This->punkControl);
66 CPinBaseImpl_fnRelease(IPin* iface)
68 ICOM_THIS(CPinBaseImpl,iface);
70 TRACE("(%p)->()\n",This);
72 return IUnknown_Release(This->punkControl);
76 CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
78 ICOM_THIS(CPinBaseImpl,iface);
79 HRESULT hr = E_NOTIMPL;
83 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
87 TRACE("Connect() should not be sent to input pins\n");
93 TRACE("try to connect to %p\n",pPin);
95 EnterCriticalSection( This->pcsPin );
97 if ( This->pPinConnectedTo != NULL )
99 hr = VFW_E_ALREADY_CONNECTED;
103 /* return fail if running */
104 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
105 if ( hr != S_OK || fs != State_Stopped )
107 TRACE("not stopped\n");
108 hr = VFW_E_NOT_STOPPED;
112 if ( This->pHandlers->pOnPreConnect != NULL )
114 hr = This->pHandlers->pOnPreConnect(This,pPin);
117 TRACE("OnPreconnect() failed hr = %08lx\n",hr);
124 hr = IPin_QueryAccept(iface,pmt);
127 hr = IPin_ReceiveConnection(pPin,iface,pmt);
133 for ( i = 0; i < This->cAcceptTypes; i++ )
135 pmt = &This->pmtAcceptTypes[i];
136 hr = IPin_QueryAccept(iface,pmt);
139 hr = IPin_ReceiveConnection(pPin,iface,pmt);
140 TRACE("ReceiveConnection - %08lx\n",hr);
148 hr = VFW_E_TYPE_NOT_ACCEPTED;
153 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
154 if ( This->pmtConn == NULL )
157 IPin_Disconnect(pPin);
161 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
162 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
165 TRACE("no IMemInputPin\n");
166 IPin_Disconnect(pPin);
170 if ( This->pHandlers->pOnPostConnect != NULL )
172 hr = This->pHandlers->pOnPostConnect(This,pPin);
175 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
176 IPin_Disconnect(pPin);
186 IPin_Disconnect(iface);
188 LeaveCriticalSection( This->pcsPin );
190 TRACE("return %08lx\n",hr);
195 static HRESULT WINAPI
196 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
198 ICOM_THIS(CPinBaseImpl,iface);
199 HRESULT hr = E_NOTIMPL;
202 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
206 TRACE("ReceiveConnection() should not be sent to output pins\n");
209 if ( pPin == NULL || pmt == NULL )
212 EnterCriticalSection( This->pcsPin );
214 if ( This->pPinConnectedTo != NULL )
216 hr = VFW_E_ALREADY_CONNECTED;
220 /* return fail if running */
221 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
222 if ( hr != S_OK || fs != State_Stopped )
224 TRACE("not stopped\n");
225 hr = VFW_E_NOT_STOPPED;
229 if ( This->pHandlers->pOnPreConnect != NULL )
231 hr = This->pHandlers->pOnPreConnect(This,pPin);
234 TRACE("OnPreConnect() failed hr = %08lx\n",hr);
239 hr = IPin_QueryAccept(iface,pmt);
243 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
244 if ( This->pmtConn == NULL )
250 if ( This->pHandlers->pOnPostConnect != NULL )
252 hr = This->pHandlers->pOnPostConnect(This,pPin);
255 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
261 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
265 IPin_Disconnect(iface);
266 LeaveCriticalSection( This->pcsPin );
271 static HRESULT WINAPI
272 CPinBaseImpl_fnDisconnect(IPin* iface)
274 ICOM_THIS(CPinBaseImpl,iface);
275 HRESULT hr = NOERROR;
278 TRACE("(%p)->()\n",This);
280 EnterCriticalSection( This->pcsPin );
282 /* return fail if running */
283 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
284 if ( hr != S_OK || fs != State_Stopped )
286 TRACE("not stopped\n");
287 hr = VFW_E_NOT_STOPPED;
291 if ( This->pHandlers->pOnDisconnect != NULL )
292 hr = This->pHandlers->pOnDisconnect(This);
294 if ( This->pmtConn != NULL )
296 QUARTZ_MediaType_Destroy( This->pmtConn );
297 This->pmtConn = NULL;
299 if ( This->pMemInputPinConnectedTo != NULL )
301 IMemInputPin_Release(This->pMemInputPinConnectedTo);
302 This->pMemInputPinConnectedTo = NULL;
304 if ( This->pPinConnectedTo != NULL )
306 /* FIXME - cleanup */
308 IPin_Release(This->pPinConnectedTo);
309 This->pPinConnectedTo = NULL;
314 hr = S_FALSE; /* FIXME - is this correct??? */
318 LeaveCriticalSection( This->pcsPin );
323 static HRESULT WINAPI
324 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
326 ICOM_THIS(CPinBaseImpl,iface);
327 HRESULT hr = VFW_E_NOT_CONNECTED;
329 TRACE("(%p)->(%p)\n",This,ppPin);
334 EnterCriticalSection( This->pcsPin );
336 *ppPin = This->pPinConnectedTo;
337 if ( This->pPinConnectedTo != NULL )
339 IPin_AddRef(This->pPinConnectedTo);
343 LeaveCriticalSection( This->pcsPin );
348 static HRESULT WINAPI
349 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
351 ICOM_THIS(CPinBaseImpl,iface);
354 TRACE("(%p)->(%p)\n",This,pmt);
359 EnterCriticalSection( This->pcsPin );
361 if ( This->pmtConn != NULL )
363 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
367 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
368 pmt->bFixedSizeSamples = TRUE;
369 pmt->lSampleSize = 1;
370 hr = VFW_E_NOT_CONNECTED;
373 LeaveCriticalSection( This->pcsPin );
378 static HRESULT WINAPI
379 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
381 ICOM_THIS(CPinBaseImpl,iface);
383 TRACE("(%p)->(%p)\n",This,pinfo);
388 EnterCriticalSection( This->pcsPin );
390 ZeroMemory( pinfo, sizeof(PIN_INFO) );
391 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
392 if ( pinfo->pFilter != NULL )
393 IBaseFilter_AddRef( pinfo->pFilter );
394 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
395 if ( This->cbIdLen <= sizeof(pinfo->achName) )
396 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
399 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
400 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
403 LeaveCriticalSection( This->pcsPin );
408 static HRESULT WINAPI
409 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
411 ICOM_THIS(CPinBaseImpl,iface);
413 TRACE("(%p)->(%p)\n",This,pdir);
418 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
423 static HRESULT WINAPI
424 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
426 ICOM_THIS(CPinBaseImpl,iface);
428 TRACE("(%p)->(%p)\n",This,lpwszId);
430 if ( lpwszId == NULL )
433 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
434 if ( *lpwszId == NULL )
435 return E_OUTOFMEMORY;
436 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
441 static HRESULT WINAPI
442 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
444 ICOM_THIS(CPinBaseImpl,iface);
447 TRACE("(%p)->(%p)\n",This,pmt);
453 EnterCriticalSection( This->pcsPin );
454 if ( This->pHandlers->pCheckMediaType != NULL )
455 hr = This->pHandlers->pCheckMediaType(This,pmt);
456 LeaveCriticalSection( This->pcsPin );
461 static HRESULT WINAPI
462 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
464 ICOM_THIS(CPinBaseImpl,iface);
467 TRACE("(%p)->(%p)\n",This,ppenum);
469 if ( ppenum == NULL )
474 EnterCriticalSection( This->pcsPin );
475 if ( This->cAcceptTypes > 0 )
476 hr = QUARTZ_CreateEnumMediaTypes(
477 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
478 LeaveCriticalSection( This->pcsPin );
483 static HRESULT WINAPI
484 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
486 ICOM_THIS(CPinBaseImpl,iface);
488 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
490 /* E_NOTIMPL means 'no internal connections'. */
494 static HRESULT WINAPI
495 CPinBaseImpl_fnEndOfStream(IPin* iface)
497 ICOM_THIS(CPinBaseImpl,iface);
498 HRESULT hr = E_NOTIMPL;
500 TRACE("(%p)->()\n",This);
505 EnterCriticalSection( This->pcsPinReceive );
506 if ( This->pHandlers->pEndOfStream != NULL )
507 hr = This->pHandlers->pEndOfStream(This);
508 LeaveCriticalSection( This->pcsPinReceive );
513 static HRESULT WINAPI
514 CPinBaseImpl_fnBeginFlush(IPin* iface)
516 ICOM_THIS(CPinBaseImpl,iface);
517 HRESULT hr = E_NOTIMPL;
519 TRACE("(%p)->()\n",This);
524 EnterCriticalSection( This->pcsPin );
525 if ( This->pHandlers->pBeginFlush != NULL )
526 hr = This->pHandlers->pBeginFlush(This);
527 LeaveCriticalSection( This->pcsPin );
529 EnterCriticalSection( This->pcsPinReceive );
530 LeaveCriticalSection( This->pcsPinReceive );
535 static HRESULT WINAPI
536 CPinBaseImpl_fnEndFlush(IPin* iface)
538 ICOM_THIS(CPinBaseImpl,iface);
539 HRESULT hr = E_NOTIMPL;
541 TRACE("(%p)->()\n",This);
546 EnterCriticalSection( This->pcsPin );
547 if ( This->pHandlers->pEndFlush != NULL )
548 hr = This->pHandlers->pEndFlush(This);
549 LeaveCriticalSection( This->pcsPin );
554 static HRESULT WINAPI
555 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
557 ICOM_THIS(CPinBaseImpl,iface);
558 HRESULT hr = E_NOTIMPL;
560 TRACE("(%p)->()\n",This);
565 EnterCriticalSection( This->pcsPin );
566 if ( This->pHandlers->pNewSegment != NULL )
567 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
568 LeaveCriticalSection( This->pcsPin );
576 static ICOM_VTABLE(IPin) ipin =
578 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
579 /* IUnknown fields */
580 CPinBaseImpl_fnQueryInterface,
581 CPinBaseImpl_fnAddRef,
582 CPinBaseImpl_fnRelease,
584 CPinBaseImpl_fnConnect,
585 CPinBaseImpl_fnReceiveConnection,
586 CPinBaseImpl_fnDisconnect,
587 CPinBaseImpl_fnConnectedTo,
588 CPinBaseImpl_fnConnectionMediaType,
589 CPinBaseImpl_fnQueryPinInfo,
590 CPinBaseImpl_fnQueryDirection,
591 CPinBaseImpl_fnQueryId,
592 CPinBaseImpl_fnQueryAccept,
593 CPinBaseImpl_fnEnumMediaTypes,
594 CPinBaseImpl_fnQueryInternalConnections,
595 CPinBaseImpl_fnEndOfStream,
596 CPinBaseImpl_fnBeginFlush,
597 CPinBaseImpl_fnEndFlush,
598 CPinBaseImpl_fnNewSegment,
602 HRESULT CPinBaseImpl_InitIPin(
603 CPinBaseImpl* This, IUnknown* punkControl,
604 CRITICAL_SECTION* pcsPin,
605 CRITICAL_SECTION* pcsPinReceive,
606 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
608 const CBasePinHandlers* pHandlers )
610 HRESULT hr = NOERROR;
612 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
614 if ( punkControl == NULL )
616 ERR( "punkControl must not be NULL\n" );
620 ICOM_VTBL(This) = &ipin;
621 This->punkControl = punkControl;
622 This->pHandlers = pHandlers;
623 This->cbIdLen = sizeof(WCHAR)*(lstrlenW(pwszId)+1);
625 This->bOutput = bOutput;
626 This->pmtAcceptTypes = NULL;
627 This->cAcceptTypes = 0;
628 This->pcsPin = pcsPin;
629 This->pcsPinReceive = pcsPinReceive;
630 This->pFilter = pFilter;
631 This->pPinConnectedTo = NULL;
632 This->pMemInputPinConnectedTo = NULL;
633 This->pmtConn = NULL;
634 This->pAsyncOut = NULL;
636 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
637 if ( This->pwszId == NULL )
642 memcpy( This->pwszId, pwszId, This->cbIdLen );
647 CPinBaseImpl_UninitIPin( This );
651 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
653 TRACE("(%p)\n",This);
655 IPin_Disconnect( (IPin*)(This) );
657 if ( This->pwszId != NULL )
659 QUARTZ_FreeMem( This->pwszId );
665 /***************************************************************************
667 * CMemInputPinBaseImpl
672 static HRESULT WINAPI
673 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
675 ICOM_THIS(CMemInputPinBaseImpl,iface);
677 TRACE("(%p)->()\n",This);
679 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
683 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
685 ICOM_THIS(CMemInputPinBaseImpl,iface);
687 TRACE("(%p)->()\n",This);
689 return IUnknown_AddRef(This->punkControl);
693 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
695 ICOM_THIS(CMemInputPinBaseImpl,iface);
697 TRACE("(%p)->()\n",This);
699 return IUnknown_Release(This->punkControl);
703 static HRESULT WINAPI
704 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
706 ICOM_THIS(CMemInputPinBaseImpl,iface);
707 HRESULT hr = NOERROR;
710 TRACE("(%p)->()\n",This);
712 if ( ppAllocator == NULL )
715 EnterCriticalSection( This->pPin->pcsPin );
717 if ( This->pAllocator == NULL )
719 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
722 hr = IUnknown_QueryInterface(punk,
723 &IID_IMemAllocator,(void**)&This->pAllocator);
724 IUnknown_Release(punk);
730 *ppAllocator = This->pAllocator;
731 IMemAllocator_AddRef(This->pAllocator);
734 LeaveCriticalSection( This->pPin->pcsPin );
739 static HRESULT WINAPI
740 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
742 ICOM_THIS(CMemInputPinBaseImpl,iface);
744 TRACE("(%p)->()\n",This);
746 if ( pAllocator == NULL )
749 EnterCriticalSection( This->pPin->pcsPin );
751 if ( This->pAllocator != NULL )
753 IMemAllocator_Release(This->pAllocator);
754 This->pAllocator = NULL;
756 This->pAllocator = pAllocator;
757 IMemAllocator_AddRef(This->pAllocator);
759 This->bReadonly = bReadonly;
761 LeaveCriticalSection( This->pPin->pcsPin );
766 static HRESULT WINAPI
767 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
769 ICOM_THIS(CMemInputPinBaseImpl,iface);
771 TRACE("(%p)->(%p)\n",This,pProp);
776 /* E_MOTIMPL means 'no requirements' */
780 static HRESULT WINAPI
781 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
783 ICOM_THIS(CMemInputPinBaseImpl,iface);
784 HRESULT hr = E_NOTIMPL;
786 TRACE("(%p)->(%p)\n",This,pSample);
788 EnterCriticalSection( This->pPin->pcsPinReceive );
789 if ( This->pPin->pHandlers->pReceive != NULL )
790 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
791 LeaveCriticalSection( This->pPin->pcsPinReceive );
796 static HRESULT WINAPI
797 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
799 ICOM_THIS(CMemInputPinBaseImpl,iface);
803 TRACE("(%p)->()\n",This);
805 if ( ppSample == NULL || pnSampleProcessed == NULL )
809 for ( n = 0; n < nSample; n++ )
811 hr = IMemInputPin_Receive(iface,ppSample[n]);
816 *pnSampleProcessed = n;
820 static HRESULT WINAPI
821 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
823 ICOM_THIS(CMemInputPinBaseImpl,iface);
824 HRESULT hr = E_NOTIMPL;
826 TRACE("(%p)->()\n",This);
828 EnterCriticalSection( This->pPin->pcsPin );
829 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
830 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
831 LeaveCriticalSection( This->pPin->pcsPin );
837 static ICOM_VTABLE(IMemInputPin) imeminputpin =
839 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
840 /* IUnknown fields */
841 CMemInputPinBaseImpl_fnQueryInterface,
842 CMemInputPinBaseImpl_fnAddRef,
843 CMemInputPinBaseImpl_fnRelease,
844 /* IMemInputPin fields */
845 CMemInputPinBaseImpl_fnGetAllocator,
846 CMemInputPinBaseImpl_fnNotifyAllocator,
847 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
848 CMemInputPinBaseImpl_fnReceive,
849 CMemInputPinBaseImpl_fnReceiveMultiple,
850 CMemInputPinBaseImpl_fnReceiveCanBlock,
853 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
854 CMemInputPinBaseImpl* This, IUnknown* punkControl,
857 TRACE("(%p,%p)\n",This,punkControl);
859 if ( punkControl == NULL )
861 ERR( "punkControl must not be NULL\n" );
865 ICOM_VTBL(This) = &imeminputpin;
866 This->punkControl = punkControl;
868 This->pAllocator = NULL;
869 This->bReadonly = FALSE;
874 void CMemInputPinBaseImpl_UninitIMemInputPin(
875 CMemInputPinBaseImpl* This )
877 TRACE("(%p)\n",This);
879 if ( This->pAllocator != NULL )
881 IMemAllocator_Release(This->pAllocator);
882 This->pAllocator = NULL;
886 /***************************************************************************
888 * CQualityControlPassThruImpl
892 static HRESULT WINAPI
893 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
895 ICOM_THIS(CQualityControlPassThruImpl,iface);
897 TRACE("(%p)->()\n",This);
899 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
903 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
905 ICOM_THIS(CQualityControlPassThruImpl,iface);
907 TRACE("(%p)->()\n",This);
909 return IUnknown_AddRef(This->punkControl);
913 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
915 ICOM_THIS(CQualityControlPassThruImpl,iface);
917 TRACE("(%p)->()\n",This);
919 return IUnknown_Release(This->punkControl);
923 static HRESULT WINAPI
924 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
926 ICOM_THIS(CQualityControlPassThruImpl,iface);
927 HRESULT hr = S_FALSE;
929 TRACE("(%p)->()\n",This);
931 if ( This->pControl != NULL )
932 return IQualityControl_Notify( This->pControl, pFilter, q );
934 EnterCriticalSection( This->pPin->pcsPin );
935 if ( This->pPin->pHandlers->pQualityNotify != NULL )
936 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
937 LeaveCriticalSection( This->pPin->pcsPin );
942 static HRESULT WINAPI
943 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
945 ICOM_THIS(CQualityControlPassThruImpl,iface);
947 TRACE("(%p)->()\n",This);
949 This->pControl = pControl; /* AddRef() must not be called */
954 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
956 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
957 /* IUnknown fields */
958 CQualityControlPassThruImpl_fnQueryInterface,
959 CQualityControlPassThruImpl_fnAddRef,
960 CQualityControlPassThruImpl_fnRelease,
961 /* IQualityControl fields */
962 CQualityControlPassThruImpl_fnNotify,
963 CQualityControlPassThruImpl_fnSetSink,
966 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
967 CQualityControlPassThruImpl* This, IUnknown* punkControl,
970 TRACE("(%p,%p)\n",This,punkControl);
972 if ( punkControl == NULL )
974 ERR( "punkControl must not be NULL\n" );
978 ICOM_VTBL(This) = &iqualitycontrol;
979 This->punkControl = punkControl;
985 void CQualityControlPassThruImpl_UninitIQualityControl(
986 CQualityControlPassThruImpl* This )
990 /***************************************************************************
992 * helper methods for output pins.
996 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
998 if ( This->pHandlers->pReceive == NULL )
1001 return This->pHandlers->pReceive( This, pSample );
1004 HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This )
1006 if ( This->pHandlers->pReceiveCanBlock == NULL )
1009 return This->pHandlers->pReceiveCanBlock( This );
1012 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
1014 if ( This->pHandlers->pEndOfStream == NULL )
1017 return This->pHandlers->pEndOfStream( This );
1020 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
1022 if ( This->pHandlers->pBeginFlush == NULL )
1025 return This->pHandlers->pBeginFlush( This );
1028 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
1030 if ( This->pHandlers->pEndFlush == NULL )
1033 return This->pHandlers->pEndFlush( This );
1036 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1038 if ( This->pHandlers->pNewSegment == NULL )
1041 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
1046 /***************************************************************************
1048 * handlers for output pins.
1052 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1054 if ( pImpl->pMemInputPinConnectedTo == NULL )
1057 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
1060 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1062 if ( pImpl->pMemInputPinConnectedTo == NULL )
1065 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1068 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1070 if ( pImpl->pPinConnectedTo == NULL )
1073 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1076 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1078 if ( pImpl->pPinConnectedTo == NULL )
1081 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1084 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1086 if ( pImpl->pPinConnectedTo == NULL )
1089 return IPin_EndFlush(pImpl->pPinConnectedTo);
1092 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1094 if ( pImpl->pPinConnectedTo == NULL )
1097 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1100 /***************************************************************************
1102 * handlers for output pins (async).
1106 typedef struct OutputPinTask OutputPinTask;
1108 enum OutputPinTaskType
1112 OutTask_EndOfStream,
1118 struct OutputPinTask
1120 OutputPinTask* pNext;
1121 enum OutputPinTaskType tasktype;
1122 IMediaSample* pSample;
1123 REFERENCE_TIME rtStart;
1124 REFERENCE_TIME rtStop;
1128 struct OutputPinAsyncImpl
1130 HANDLE m_hTaskThread;
1131 HANDLE m_hTaskEvent;
1132 IPin* m_pPin; /* connected pin */
1133 IMemInputPin* m_pMemInputPin; /* connected pin */
1134 CRITICAL_SECTION m_csTasks;
1135 OutputPinTask* m_pFirst;
1136 OutputPinTask* m_pLast;
1137 OutputPinTask* m_pTaskExitThread;
1140 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1142 OutputPinTask* pTask;
1144 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1145 pTask->pNext = NULL;
1146 pTask->tasktype = tasktype;
1147 pTask->pSample = NULL;
1152 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1154 if ( pTask->pSample != NULL )
1155 IMediaSample_Release( pTask->pSample );
1156 QUARTZ_FreeMem( pTask );
1159 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1161 EnterCriticalSection( &This->m_csTasks );
1165 pTask->pNext = This->m_pFirst;
1166 This->m_pFirst = pTask;
1167 if ( This->m_pLast == NULL )
1168 This->m_pLast = pTask;
1172 if ( This->m_pLast != NULL )
1173 This->m_pLast->pNext = pTask;
1175 This->m_pFirst = pTask;
1176 This->m_pLast = pTask;
1179 LeaveCriticalSection( &This->m_csTasks );
1181 SetEvent( This->m_hTaskEvent );
1184 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1186 OutputPinTask* pTask;
1188 EnterCriticalSection( &This->m_csTasks );
1189 pTask = This->m_pFirst;
1190 if ( pTask != NULL )
1192 This->m_pFirst = pTask->pNext;
1193 if ( This->m_pFirst == NULL )
1194 This->m_pLast = NULL;
1196 SetEvent( This->m_hTaskEvent );
1199 LeaveCriticalSection( &This->m_csTasks );
1204 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1206 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1207 OutputPinTask* pTask;
1209 BOOL bInFlush = FALSE;
1214 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1215 ResetEvent( This->m_hTaskEvent );
1217 pTask = OutputPinAsync_GetNextTask( This );
1218 if ( pTask == NULL )
1222 switch ( pTask->tasktype )
1224 case OutTask_ExitThread:
1227 case OutTask_Receive:
1229 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1231 case OutTask_EndOfStream:
1232 hr = IPin_EndOfStream( This->m_pPin );
1234 case OutTask_BeginFlush:
1236 hr = IPin_BeginFlush( This->m_pPin );
1238 case OutTask_EndFlush:
1240 hr = IPin_EndFlush( This->m_pPin );
1242 case OutTask_NewSegment:
1243 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1246 ERR( "unexpected task type %d.\n", pTask->tasktype );
1251 OutputPinAsync_FreeTask( pTask );
1255 ERR( "hresult %08lx\n", hr );
1263 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1268 FIXME("(%p)\n",pImpl);
1270 if ( pImpl->pMemInputPinConnectedTo == NULL )
1273 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1274 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1275 if ( pImpl->pAsyncOut == NULL )
1276 return E_OUTOFMEMORY;
1278 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1279 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1280 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1281 pImpl->pAsyncOut->m_pFirst = NULL;
1282 pImpl->pAsyncOut->m_pLast = NULL;
1283 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1284 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1285 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1287 pImpl->pAsyncOut->m_hTaskEvent =
1288 CreateEventA( NULL, TRUE, FALSE, NULL );
1289 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1295 pImpl->pAsyncOut->m_pTaskExitThread =
1296 OutputPinAsync_AllocTask( OutTask_ExitThread );
1297 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1303 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1304 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1306 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1314 OutputPinAsync_OnInactive( pImpl );
1318 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1320 OutputPinTask* pTask;
1322 FIXME("(%p)\n",pImpl);
1324 if ( pImpl->pAsyncOut == NULL )
1327 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1329 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1330 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1333 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1335 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1336 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1338 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1339 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1341 /* release all tasks. */
1344 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1345 if ( pTask == NULL )
1347 OutputPinAsync_FreeTask( pTask );
1350 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1352 QUARTZ_FreeMem( pImpl->pAsyncOut );
1353 pImpl->pAsyncOut = NULL;
1358 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1360 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1361 OutputPinTask* pTask;
1363 TRACE("(%p,%p)\n",pImpl,pSample);
1368 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1369 if ( pTask == NULL )
1370 return E_OUTOFMEMORY;
1371 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1372 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1377 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1382 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1384 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1385 OutputPinTask* pTask;
1387 TRACE("(%p)\n",pImpl);
1392 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1393 if ( pTask == NULL )
1394 return E_OUTOFMEMORY;
1395 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1400 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1402 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1403 OutputPinTask* pTask;
1405 TRACE("(%p)\n",pImpl);
1410 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1411 if ( pTask == NULL )
1412 return E_OUTOFMEMORY;
1413 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1418 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1420 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1421 OutputPinTask* pTask;
1423 TRACE("(%p)\n",pImpl);
1428 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1429 if ( pTask == NULL )
1430 return E_OUTOFMEMORY;
1431 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1436 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1438 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1439 OutputPinTask* pTask;
1441 TRACE("(%p)\n",pImpl);
1446 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1447 if ( pTask == NULL )
1448 return E_OUTOFMEMORY;
1449 pTask->rtStart = rtStart;
1450 pTask->rtStop = rtStop;
1452 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );