Started Implementing Video Renderer.
[wine/multimedia.git] / dlls / quartz / basepin.c
blob1f809b7b3e3ccbcfc37dd336cdb4a1dfccb65d73
1 /*
2 * Implements IPin and IMemInputPin. (internal)
4 * hidenori@a2.ctktv.ne.jp
5 */
7 #include "config.h"
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "winerror.h"
14 #include "wine/obj_base.h"
15 #include "strmif.h"
16 #include "vfwmsgs.h"
17 #include "wine/unicode.h"
19 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(quartz);
22 #include "quartz_private.h"
23 #include "basefilt.h"
24 #include "memalloc.h"
27 /***************************************************************************
29 * CPinBaseImpl
33 static HRESULT WINAPI
34 CPinBaseImpl_fnQueryInterface(IPin* iface,REFIID riid,void** ppobj)
36 ICOM_THIS(CPinBaseImpl,iface);
38 TRACE("(%p)->()\n",This);
40 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
43 static ULONG WINAPI
44 CPinBaseImpl_fnAddRef(IPin* iface)
46 ICOM_THIS(CPinBaseImpl,iface);
48 TRACE("(%p)->()\n",This);
50 return IUnknown_AddRef(This->punkControl);
53 static ULONG WINAPI
54 CPinBaseImpl_fnRelease(IPin* iface)
56 ICOM_THIS(CPinBaseImpl,iface);
58 TRACE("(%p)->()\n",This);
60 return IUnknown_Release(This->punkControl);
63 static HRESULT WINAPI
64 CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
66 ICOM_THIS(CPinBaseImpl,iface);
67 HRESULT hr = E_NOTIMPL;
68 ULONG i;
70 FIXME("(%p)->(%p,%p) stub!\n",This,pPin,pmt);
72 if ( !This->bOutput )
73 return E_UNEXPECTED;
74 if ( pPin == NULL )
75 return E_POINTER;
77 TRACE("try to connect to %p\n",pPin);
79 EnterCriticalSection( This->pcsPin );
81 if ( This->pPinConnectedTo != NULL )
83 hr = VFW_E_ALREADY_CONNECTED;
84 goto err;
87 /* FIXME - return fail if running */
89 if ( This->pHandlers->pOnPreConnect != NULL )
91 hr = This->pHandlers->pOnPreConnect(This,pPin);
92 if ( FAILED(hr) )
93 goto err;
96 if ( pmt != NULL )
98 hr = IPin_QueryAccept(iface,pmt);
99 if ( FAILED(hr) )
100 goto err;
101 hr = IPin_ReceiveConnection(pPin,iface,pmt);
102 if ( FAILED(hr) )
103 goto err;
105 else
107 for ( i = 0; i < This->cAcceptTypes; i++ )
109 pmt = &This->pmtAcceptTypes[i];
110 hr = IPin_QueryAccept(iface,pmt);
111 if ( SUCCEEDED(hr) )
113 hr = IPin_ReceiveConnection(pPin,iface,pmt);
114 if ( SUCCEEDED(hr) )
116 goto connected;
121 hr = VFW_E_TYPE_NOT_ACCEPTED;
122 goto err;
125 connected:;
126 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
127 if ( This->pmtConn == NULL )
129 hr = E_OUTOFMEMORY;
130 IPin_Disconnect(pPin);
131 goto err;
134 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
135 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
136 if ( FAILED(hr) )
138 IPin_Disconnect(pPin);
139 goto err;
142 if ( This->pHandlers->pOnPostConnect != NULL )
144 hr = This->pHandlers->pOnPostConnect(This,pPin);
145 if ( FAILED(hr) )
147 IPin_Disconnect(pPin);
148 goto err;
152 hr = S_OK;
154 err:
155 if ( FAILED(hr) )
157 IPin_Disconnect(iface);
159 LeaveCriticalSection( This->pcsPin );
161 return hr;
164 static HRESULT WINAPI
165 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
167 ICOM_THIS(CPinBaseImpl,iface);
168 HRESULT hr = E_NOTIMPL;
170 FIXME("(%p)->(%p,%p) stub!\n",This,pPin,pmt);
172 if ( This->bOutput )
173 return E_UNEXPECTED;
174 if ( pPin == NULL || pmt == NULL )
175 return E_POINTER;
177 EnterCriticalSection( This->pcsPin );
179 if ( This->pPinConnectedTo != NULL )
181 hr = VFW_E_ALREADY_CONNECTED;
182 goto err;
185 /* FIXME - return fail if running */
187 if ( This->pHandlers->pOnPreConnect != NULL )
189 hr = This->pHandlers->pOnPreConnect(This,pPin);
190 if ( FAILED(hr) )
191 goto err;
194 hr = IPin_QueryAccept(iface,pmt);
195 if ( FAILED(hr) )
196 goto err;
198 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
199 if ( This->pmtConn == NULL )
201 hr = E_OUTOFMEMORY;
202 goto err;
205 if ( This->pHandlers->pOnPostConnect != NULL )
207 hr = This->pHandlers->pOnPostConnect(This,pPin);
208 if ( FAILED(hr) )
209 goto err;
212 hr = S_OK;
213 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
215 err:
216 if ( FAILED(hr) )
217 IPin_Disconnect(iface);
218 LeaveCriticalSection( This->pcsPin );
220 return hr;
223 static HRESULT WINAPI
224 CPinBaseImpl_fnDisconnect(IPin* iface)
226 ICOM_THIS(CPinBaseImpl,iface);
227 HRESULT hr = NOERROR;
229 FIXME("(%p)->() stub!\n",This);
231 EnterCriticalSection( This->pcsPin );
233 /* FIXME - return fail if running */
235 if ( This->pHandlers->pOnDisconnect != NULL )
236 hr = This->pHandlers->pOnDisconnect(This);
238 if ( This->pmtConn != NULL )
240 QUARTZ_MediaType_Destroy( This->pmtConn );
241 This->pmtConn = NULL;
243 if ( This->pMemInputPinConnectedTo != NULL )
245 IMemInputPin_Release(This->pMemInputPinConnectedTo);
246 This->pMemInputPinConnectedTo = NULL;
248 if ( This->pPinConnectedTo != NULL )
250 /* FIXME - cleanup */
252 IPin_Release(This->pPinConnectedTo);
253 This->pPinConnectedTo = NULL;
254 hr = NOERROR;
256 else
258 hr = S_FALSE; /* FIXME - is this correct??? */
261 LeaveCriticalSection( This->pcsPin );
263 return hr;
266 static HRESULT WINAPI
267 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
269 ICOM_THIS(CPinBaseImpl,iface);
270 HRESULT hr = VFW_E_NOT_CONNECTED;
272 TRACE("(%p)->(%p)\n",This,ppPin);
274 if ( ppPin == NULL )
275 return E_POINTER;
277 EnterCriticalSection( This->pcsPin );
279 *ppPin = This->pPinConnectedTo;
280 if ( This->pPinConnectedTo != NULL )
282 IPin_AddRef(This->pPinConnectedTo);
283 hr = NOERROR;
286 LeaveCriticalSection( This->pcsPin );
288 return hr;
291 static HRESULT WINAPI
292 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
294 ICOM_THIS(CPinBaseImpl,iface);
295 HRESULT hr = E_FAIL;
297 TRACE("(%p)->(%p)\n",This,pmt);
299 if ( pmt == NULL )
300 return E_POINTER;
302 EnterCriticalSection( This->pcsPin );
304 if ( This->pmtConn != NULL )
306 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
308 else
310 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
311 pmt->bFixedSizeSamples = TRUE;
312 pmt->lSampleSize = 1;
313 hr = NOERROR;
316 LeaveCriticalSection( This->pcsPin );
318 return hr;
321 static HRESULT WINAPI
322 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
324 ICOM_THIS(CPinBaseImpl,iface);
326 TRACE("(%p)->(%p)\n",This,pinfo);
328 if ( pinfo == NULL )
329 return E_POINTER;
331 EnterCriticalSection( This->pcsPin );
333 ZeroMemory( pinfo, sizeof(PIN_INFO) );
334 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
335 if ( pinfo->pFilter != NULL )
336 IBaseFilter_AddRef( pinfo->pFilter );
337 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
338 if ( This->cbIdLen <= sizeof(pinfo->achName) )
339 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
340 else
342 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
343 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
346 LeaveCriticalSection( This->pcsPin );
348 return NOERROR;
351 static HRESULT WINAPI
352 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
354 ICOM_THIS(CPinBaseImpl,iface);
356 TRACE("(%p)->(%p)\n",This,pdir);
358 if ( pdir == NULL )
359 return E_POINTER;
361 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
363 return NOERROR;
366 static HRESULT WINAPI
367 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
369 ICOM_THIS(CPinBaseImpl,iface);
371 TRACE("(%p)->(%p)\n",This,lpwszId);
373 if ( lpwszId == NULL )
374 return E_POINTER;
376 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
377 if ( *lpwszId == NULL )
378 return E_OUTOFMEMORY;
379 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
381 return NOERROR;
384 static HRESULT WINAPI
385 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
387 ICOM_THIS(CPinBaseImpl,iface);
388 HRESULT hr;
390 TRACE("(%p)->(%p)\n",This,pmt);
392 if ( pmt == NULL )
393 return E_POINTER;
395 hr = NOERROR;
396 EnterCriticalSection( This->pcsPin );
397 if ( This->pHandlers->pCheckMediaType != NULL )
398 hr = This->pHandlers->pCheckMediaType(This,pmt);
399 LeaveCriticalSection( This->pcsPin );
401 return hr;
404 static HRESULT WINAPI
405 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
407 ICOM_THIS(CPinBaseImpl,iface);
408 HRESULT hr;
410 TRACE("(%p)->(%p)\n",This,ppenum);
412 if ( ppenum == NULL )
413 return E_POINTER;
415 hr = E_NOTIMPL;
417 EnterCriticalSection( This->pcsPin );
418 if ( This->cAcceptTypes > 0 )
419 hr = QUARTZ_CreateEnumMediaTypes(
420 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
421 LeaveCriticalSection( This->pcsPin );
423 return hr;
426 static HRESULT WINAPI
427 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
429 ICOM_THIS(CPinBaseImpl,iface);
431 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
433 /* E_NOTIMPL means 'no internal connections'. */
434 return E_NOTIMPL;
437 static HRESULT WINAPI
438 CPinBaseImpl_fnEndOfStream(IPin* iface)
440 ICOM_THIS(CPinBaseImpl,iface);
441 HRESULT hr = E_NOTIMPL;
443 TRACE("(%p)->()\n",This);
445 if ( This->bOutput )
446 return E_UNEXPECTED;
448 EnterCriticalSection( This->pcsPin );
449 if ( This->pHandlers->pEndOfStream != NULL )
450 hr = This->pHandlers->pEndOfStream(This);
451 LeaveCriticalSection( This->pcsPin );
453 return hr;
456 static HRESULT WINAPI
457 CPinBaseImpl_fnBeginFlush(IPin* iface)
459 ICOM_THIS(CPinBaseImpl,iface);
460 HRESULT hr = E_NOTIMPL;
462 TRACE("(%p)->()\n",This);
464 if ( This->bOutput )
465 return E_UNEXPECTED;
467 EnterCriticalSection( This->pcsPin );
468 if ( This->pHandlers->pBeginFlush != NULL )
469 hr = This->pHandlers->pBeginFlush(This);
470 LeaveCriticalSection( This->pcsPin );
472 return hr;
475 static HRESULT WINAPI
476 CPinBaseImpl_fnEndFlush(IPin* iface)
478 ICOM_THIS(CPinBaseImpl,iface);
479 HRESULT hr = E_NOTIMPL;
481 TRACE("(%p)->()\n",This);
483 if ( This->bOutput )
484 return E_UNEXPECTED;
486 EnterCriticalSection( This->pcsPin );
487 if ( This->pHandlers->pEndFlush != NULL )
488 hr = This->pHandlers->pEndFlush(This);
489 LeaveCriticalSection( This->pcsPin );
491 return hr;
494 static HRESULT WINAPI
495 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
497 ICOM_THIS(CPinBaseImpl,iface);
498 HRESULT hr = E_NOTIMPL;
500 TRACE("(%p)->()\n",This);
502 if ( This->bOutput )
503 return E_UNEXPECTED;
505 EnterCriticalSection( This->pcsPin );
506 if ( This->pHandlers->pNewSegment != NULL )
507 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
508 LeaveCriticalSection( This->pcsPin );
510 return hr;
516 static ICOM_VTABLE(IPin) ipin =
518 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
519 /* IUnknown fields */
520 CPinBaseImpl_fnQueryInterface,
521 CPinBaseImpl_fnAddRef,
522 CPinBaseImpl_fnRelease,
523 /* IPin fields */
524 CPinBaseImpl_fnConnect,
525 CPinBaseImpl_fnReceiveConnection,
526 CPinBaseImpl_fnDisconnect,
527 CPinBaseImpl_fnConnectedTo,
528 CPinBaseImpl_fnConnectionMediaType,
529 CPinBaseImpl_fnQueryPinInfo,
530 CPinBaseImpl_fnQueryDirection,
531 CPinBaseImpl_fnQueryId,
532 CPinBaseImpl_fnQueryAccept,
533 CPinBaseImpl_fnEnumMediaTypes,
534 CPinBaseImpl_fnQueryInternalConnections,
535 CPinBaseImpl_fnEndOfStream,
536 CPinBaseImpl_fnBeginFlush,
537 CPinBaseImpl_fnEndFlush,
538 CPinBaseImpl_fnNewSegment,
542 HRESULT CPinBaseImpl_InitIPin(
543 CPinBaseImpl* This, IUnknown* punkControl,
544 CRITICAL_SECTION* pcsPin,
545 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
546 BOOL bOutput,
547 const CBasePinHandlers* pHandlers )
549 HRESULT hr = NOERROR;
551 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
553 if ( punkControl == NULL )
555 ERR( "punkControl must not be NULL\n" );
556 return E_INVALIDARG;
559 ICOM_VTBL(This) = &ipin;
560 This->punkControl = punkControl;
561 This->pHandlers = pHandlers;
562 This->cbIdLen = sizeof(WCHAR)*(strlenW(pwszId)+1);
563 This->pwszId = NULL;
564 This->bOutput = bOutput;
565 This->pmtAcceptTypes = NULL;
566 This->cAcceptTypes = 0;
567 This->pcsPin = pcsPin;
568 This->pFilter = pFilter;
569 This->pPinConnectedTo = NULL;
570 This->pMemInputPinConnectedTo = NULL;
571 This->pmtConn = NULL;
572 This->pAsyncOut = NULL;
574 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
575 if ( This->pwszId == NULL )
577 hr = E_OUTOFMEMORY;
578 goto err;
580 memcpy( This->pwszId, pwszId, This->cbIdLen );
582 return NOERROR;
584 err:;
585 CPinBaseImpl_UninitIPin( This );
586 return hr;
589 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
591 TRACE("(%p)\n",This);
593 IPin_Disconnect( (IPin*)(This) );
595 if ( This->pwszId != NULL )
597 QUARTZ_FreeMem( This->pwszId );
598 This->pwszId = NULL;
603 /***************************************************************************
605 * CMemInputPinBaseImpl
610 static HRESULT WINAPI
611 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
613 ICOM_THIS(CMemInputPinBaseImpl,iface);
615 TRACE("(%p)->()\n",This);
617 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
620 static ULONG WINAPI
621 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
623 ICOM_THIS(CMemInputPinBaseImpl,iface);
625 TRACE("(%p)->()\n",This);
627 return IUnknown_AddRef(This->punkControl);
630 static ULONG WINAPI
631 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
633 ICOM_THIS(CMemInputPinBaseImpl,iface);
635 TRACE("(%p)->()\n",This);
637 return IUnknown_Release(This->punkControl);
641 static HRESULT WINAPI
642 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
644 ICOM_THIS(CMemInputPinBaseImpl,iface);
645 HRESULT hr = NOERROR;
646 IUnknown* punk;
648 TRACE("(%p)->()\n",This);
650 if ( ppAllocator == NULL )
651 return E_POINTER;
653 EnterCriticalSection( This->pPin->pcsPin );
655 if ( This->pAllocator == NULL )
657 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
658 if ( hr == NOERROR )
660 hr = IUnknown_QueryInterface(punk,
661 &IID_IMemAllocator,(void**)&This->pAllocator);
662 IUnknown_Release(punk);
666 if ( hr == NOERROR )
668 *ppAllocator = This->pAllocator;
669 IMemAllocator_AddRef(This->pAllocator);
672 LeaveCriticalSection( This->pPin->pcsPin );
674 return hr;
677 static HRESULT WINAPI
678 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
680 ICOM_THIS(CMemInputPinBaseImpl,iface);
682 TRACE("(%p)->()\n",This);
684 if ( pAllocator == NULL )
685 return E_POINTER;
687 EnterCriticalSection( This->pPin->pcsPin );
689 if ( This->pAllocator != NULL )
691 IMemAllocator_Release(This->pAllocator);
692 This->pAllocator = NULL;
694 This->pAllocator = pAllocator;
695 IMemAllocator_AddRef(This->pAllocator);
697 This->bReadonly = bReadonly;
699 LeaveCriticalSection( This->pPin->pcsPin );
701 return NOERROR;
704 static HRESULT WINAPI
705 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
707 ICOM_THIS(CMemInputPinBaseImpl,iface);
709 TRACE("(%p)->(%p)\n",This,pProp);
711 if ( pProp == NULL )
712 return E_POINTER;
714 /* E_MOTIMPL means 'no requirements' */
715 return E_NOTIMPL;
718 static HRESULT WINAPI
719 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
721 ICOM_THIS(CMemInputPinBaseImpl,iface);
722 HRESULT hr = E_NOTIMPL;
724 TRACE("(%p)->(%p)\n",This,pSample);
726 EnterCriticalSection( This->pPin->pcsPin );
727 if ( This->pPin->pHandlers->pReceive != NULL )
728 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
729 LeaveCriticalSection( This->pPin->pcsPin );
731 return hr;
734 static HRESULT WINAPI
735 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
737 ICOM_THIS(CMemInputPinBaseImpl,iface);
738 long n;
739 HRESULT hr;
741 TRACE("(%p)->()\n",This);
743 if ( ppSample == NULL || pnSampleProcessed == NULL )
744 return E_POINTER;
746 EnterCriticalSection( This->pPin->pcsPin );
748 hr = NOERROR;
749 for ( n = 0; n < nSample; n++ )
751 hr = IMemInputPin_Receive(iface,ppSample[n]);
752 if ( FAILED(hr) )
753 break;
756 LeaveCriticalSection( This->pPin->pcsPin );
758 *pnSampleProcessed = n;
759 return hr;
762 static HRESULT WINAPI
763 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
765 ICOM_THIS(CMemInputPinBaseImpl,iface);
766 HRESULT hr = E_NOTIMPL;
768 TRACE("(%p)->()\n",This);
770 EnterCriticalSection( This->pPin->pcsPin );
771 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
772 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
773 LeaveCriticalSection( This->pPin->pcsPin );
775 return hr;
779 static ICOM_VTABLE(IMemInputPin) imeminputpin =
781 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
782 /* IUnknown fields */
783 CMemInputPinBaseImpl_fnQueryInterface,
784 CMemInputPinBaseImpl_fnAddRef,
785 CMemInputPinBaseImpl_fnRelease,
786 /* IMemInputPin fields */
787 CMemInputPinBaseImpl_fnGetAllocator,
788 CMemInputPinBaseImpl_fnNotifyAllocator,
789 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
790 CMemInputPinBaseImpl_fnReceive,
791 CMemInputPinBaseImpl_fnReceiveMultiple,
792 CMemInputPinBaseImpl_fnReceiveCanBlock,
795 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
796 CMemInputPinBaseImpl* This, IUnknown* punkControl,
797 CPinBaseImpl* pPin )
799 TRACE("(%p,%p)\n",This,punkControl);
801 if ( punkControl == NULL )
803 ERR( "punkControl must not be NULL\n" );
804 return E_INVALIDARG;
807 ICOM_VTBL(This) = &imeminputpin;
808 This->punkControl = punkControl;
809 This->pPin = pPin;
810 This->pAllocator = NULL;
811 This->bReadonly = FALSE;
813 return NOERROR;
816 void CMemInputPinBaseImpl_UninitIMemInputPin(
817 CMemInputPinBaseImpl* This )
819 TRACE("(%p)\n",This);
821 if ( This->pAllocator != NULL )
823 IMemAllocator_Release(This->pAllocator);
824 This->pAllocator = NULL;
828 /***************************************************************************
830 * CQualityControlPassThruImpl
834 static HRESULT WINAPI
835 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
837 ICOM_THIS(CQualityControlPassThruImpl,iface);
839 TRACE("(%p)->()\n",This);
841 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
844 static ULONG WINAPI
845 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
847 ICOM_THIS(CQualityControlPassThruImpl,iface);
849 TRACE("(%p)->()\n",This);
851 return IUnknown_AddRef(This->punkControl);
854 static ULONG WINAPI
855 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
857 ICOM_THIS(CQualityControlPassThruImpl,iface);
859 TRACE("(%p)->()\n",This);
861 return IUnknown_Release(This->punkControl);
865 static HRESULT WINAPI
866 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
868 ICOM_THIS(CQualityControlPassThruImpl,iface);
869 HRESULT hr = S_FALSE;
871 TRACE("(%p)->()\n",This);
873 if ( This->pControl != NULL )
874 return IQualityControl_Notify( This->pControl, pFilter, q );
876 EnterCriticalSection( This->pPin->pcsPin );
877 if ( This->pPin->pHandlers->pQualityNotify != NULL )
878 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
879 LeaveCriticalSection( This->pPin->pcsPin );
881 return hr;
884 static HRESULT WINAPI
885 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
887 ICOM_THIS(CQualityControlPassThruImpl,iface);
889 TRACE("(%p)->()\n",This);
891 This->pControl = pControl; /* AddRef() must not be called */
893 return NOERROR;
896 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
898 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
899 /* IUnknown fields */
900 CQualityControlPassThruImpl_fnQueryInterface,
901 CQualityControlPassThruImpl_fnAddRef,
902 CQualityControlPassThruImpl_fnRelease,
903 /* IQualityControl fields */
904 CQualityControlPassThruImpl_fnNotify,
905 CQualityControlPassThruImpl_fnSetSink,
908 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
909 CQualityControlPassThruImpl* This, IUnknown* punkControl,
910 CPinBaseImpl* pPin )
912 TRACE("(%p,%p)\n",This,punkControl);
914 if ( punkControl == NULL )
916 ERR( "punkControl must not be NULL\n" );
917 return E_INVALIDARG;
920 ICOM_VTBL(This) = &iqualitycontrol;
921 This->punkControl = punkControl;
922 This->pPin = pPin;
924 return NOERROR;
927 void CQualityControlPassThruImpl_UninitIQualityControl(
928 CQualityControlPassThruImpl* This )
932 /***************************************************************************
934 * helper methods for output pins.
938 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
940 if ( This->pHandlers->pReceive == NULL )
941 return E_NOTIMPL;
943 return This->pHandlers->pReceive( This, pSample );
946 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
948 if ( This->pHandlers->pEndOfStream == NULL )
949 return E_NOTIMPL;
951 return This->pHandlers->pEndOfStream( This );
954 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
956 if ( This->pHandlers->pBeginFlush == NULL )
957 return E_NOTIMPL;
959 return This->pHandlers->pBeginFlush( This );
962 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
964 if ( This->pHandlers->pEndFlush == NULL )
965 return E_NOTIMPL;
967 return This->pHandlers->pEndFlush( This );
970 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
972 if ( This->pHandlers->pNewSegment == NULL )
973 return E_NOTIMPL;
975 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
980 /***************************************************************************
982 * handlers for output pins.
986 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
988 if ( pImpl->pMemInputPinConnectedTo == NULL )
989 return E_UNEXPECTED;
991 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
994 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
996 if ( pImpl->pMemInputPinConnectedTo == NULL )
997 return S_FALSE;
999 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1002 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1004 if ( pImpl->pPinConnectedTo == NULL )
1005 return NOERROR;
1007 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1010 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1012 if ( pImpl->pPinConnectedTo == NULL )
1013 return NOERROR;
1015 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1018 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1020 if ( pImpl->pPinConnectedTo == NULL )
1021 return NOERROR;
1023 return IPin_EndFlush(pImpl->pPinConnectedTo);
1026 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1028 if ( pImpl->pPinConnectedTo == NULL )
1029 return NOERROR;
1031 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1034 /***************************************************************************
1036 * handlers for output pins (async).
1040 typedef struct OutputPinTask OutputPinTask;
1042 enum OutputPinTaskType
1044 OutTask_ExitThread,
1045 OutTask_Receive,
1046 OutTask_EndOfStream,
1047 OutTask_BeginFlush,
1048 OutTask_EndFlush,
1049 OutTask_NewSegment,
1052 struct OutputPinTask
1054 OutputPinTask* pNext;
1055 enum OutputPinTaskType tasktype;
1056 IMediaSample* pSample;
1057 REFERENCE_TIME rtStart;
1058 REFERENCE_TIME rtStop;
1059 double rate;
1062 struct OutputPinAsyncImpl
1064 HANDLE m_hTaskThread;
1065 HANDLE m_hTaskEvent;
1066 IPin* m_pPin; /* connected pin */
1067 IMemInputPin* m_pMemInputPin; /* connected pin */
1068 CRITICAL_SECTION m_csTasks;
1069 OutputPinTask* m_pFirst;
1070 OutputPinTask* m_pLast;
1071 OutputPinTask* m_pTaskExitThread;
1074 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1076 OutputPinTask* pTask;
1078 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1079 pTask->pNext = NULL;
1080 pTask->tasktype = tasktype;
1081 pTask->pSample = NULL;
1083 return pTask;
1086 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1088 if ( pTask->pSample != NULL )
1089 IMediaSample_Release( pTask->pSample );
1090 QUARTZ_FreeMem( pTask );
1093 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1095 EnterCriticalSection( &This->m_csTasks );
1097 if ( bFirst )
1099 pTask->pNext = This->m_pFirst;
1100 This->m_pFirst = pTask;
1101 if ( This->m_pLast == NULL )
1102 This->m_pLast = pTask;
1104 else
1106 if ( This->m_pLast != NULL )
1107 This->m_pLast->pNext = pTask;
1108 else
1109 This->m_pFirst = pTask;
1110 This->m_pLast = pTask;
1113 LeaveCriticalSection( &This->m_csTasks );
1115 SetEvent( This->m_hTaskEvent );
1118 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1120 OutputPinTask* pTask;
1122 EnterCriticalSection( &This->m_csTasks );
1123 pTask = This->m_pFirst;
1124 if ( pTask != NULL )
1126 This->m_pFirst = pTask->pNext;
1127 if ( This->m_pFirst == NULL )
1128 This->m_pLast = NULL;
1129 else
1130 SetEvent( This->m_hTaskEvent );
1133 LeaveCriticalSection( &This->m_csTasks );
1135 return pTask;
1138 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1140 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1141 OutputPinTask* pTask;
1142 BOOL bLoop = TRUE;
1143 BOOL bInFlush = FALSE;
1144 HRESULT hr;
1146 while ( bLoop )
1148 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1149 ResetEvent( This->m_hTaskEvent );
1151 pTask = OutputPinAsync_GetNextTask( This );
1152 if ( pTask == NULL )
1153 continue;
1155 hr = S_OK;
1156 switch ( pTask->tasktype )
1158 case OutTask_ExitThread:
1159 bLoop = FALSE;
1160 break;
1161 case OutTask_Receive:
1162 if ( !bInFlush )
1163 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1164 break;
1165 case OutTask_EndOfStream:
1166 hr = IPin_EndOfStream( This->m_pPin );
1167 break;
1168 case OutTask_BeginFlush:
1169 bInFlush = TRUE;
1170 hr = IPin_BeginFlush( This->m_pPin );
1171 break;
1172 case OutTask_EndFlush:
1173 bInFlush = FALSE;
1174 hr = IPin_EndFlush( This->m_pPin );
1175 break;
1176 case OutTask_NewSegment:
1177 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1178 break;
1179 default:
1180 ERR( "unexpected task type %d.\n", pTask->tasktype );
1181 bLoop = FALSE;
1182 break;
1185 OutputPinAsync_FreeTask( pTask );
1187 if ( FAILED(hr) )
1189 ERR( "hresult %08lx\n", hr );
1190 bLoop = FALSE;
1194 return 0;
1197 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1199 HRESULT hr;
1200 DWORD dwThreadId;
1202 FIXME("(%p)\n",pImpl);
1204 if ( pImpl->pMemInputPinConnectedTo == NULL )
1205 return NOERROR;
1207 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1208 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1209 if ( pImpl->pAsyncOut == NULL )
1210 return E_OUTOFMEMORY;
1212 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1213 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1214 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1215 pImpl->pAsyncOut->m_pFirst = NULL;
1216 pImpl->pAsyncOut->m_pLast = NULL;
1217 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1218 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1219 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1221 pImpl->pAsyncOut->m_hTaskEvent =
1222 CreateEventA( NULL, TRUE, FALSE, NULL );
1223 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1225 hr = E_FAIL;
1226 goto err;
1229 pImpl->pAsyncOut->m_pTaskExitThread =
1230 OutputPinAsync_AllocTask( OutTask_ExitThread );
1231 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1233 hr = E_OUTOFMEMORY;
1234 goto err;
1237 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1238 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1239 0, &dwThreadId );
1240 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1242 hr = E_FAIL;
1243 goto err;
1246 return NOERROR;
1247 err:
1248 OutputPinAsync_OnInactive( pImpl );
1249 return hr;
1252 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1254 OutputPinTask* pTask;
1256 FIXME("(%p)\n",pImpl);
1258 if ( pImpl->pAsyncOut == NULL )
1259 return NOERROR;
1261 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1263 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1264 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1267 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1269 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1270 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1272 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1273 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1275 /* release all tasks. */
1276 while ( 1 )
1278 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1279 if ( pTask == NULL )
1280 break;
1281 OutputPinAsync_FreeTask( pTask );
1284 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1286 QUARTZ_FreeMem( pImpl->pAsyncOut );
1287 pImpl->pAsyncOut = NULL;
1289 return NOERROR;
1292 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1294 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1295 OutputPinTask* pTask;
1297 TRACE("(%p,%p)\n",pImpl,pSample);
1299 if ( This == NULL )
1300 return NOERROR;
1302 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1303 if ( pTask == NULL )
1304 return E_OUTOFMEMORY;
1305 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1306 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1308 return NOERROR;
1311 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1313 return S_FALSE;
1316 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1318 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1319 OutputPinTask* pTask;
1321 TRACE("(%p)\n",pImpl);
1323 if ( This == NULL )
1324 return NOERROR;
1326 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1327 if ( pTask == NULL )
1328 return E_OUTOFMEMORY;
1329 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1331 return NOERROR;
1334 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1336 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1337 OutputPinTask* pTask;
1339 TRACE("(%p)\n",pImpl);
1341 if ( This == NULL )
1342 return NOERROR;
1344 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1345 if ( pTask == NULL )
1346 return E_OUTOFMEMORY;
1347 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1349 return NOERROR;
1352 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1354 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1355 OutputPinTask* pTask;
1357 TRACE("(%p)\n",pImpl);
1359 if ( This == NULL )
1360 return NOERROR;
1362 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1363 if ( pTask == NULL )
1364 return E_OUTOFMEMORY;
1365 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1367 return NOERROR;
1370 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1372 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1373 OutputPinTask* pTask;
1375 TRACE("(%p)\n",pImpl);
1377 if ( This == NULL )
1378 return NOERROR;
1380 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1381 if ( pTask == NULL )
1382 return E_OUTOFMEMORY;
1383 pTask->rtStart = rtStart;
1384 pTask->rtStop = rtStop;
1385 pTask->rate = rate;
1386 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1388 return NOERROR;