1 /* Video For Windows Steering structure
3 * Copyright 2005 Maarten Lankhorst
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
35 #include "qcap_main.h"
36 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
50 #define ICOM_THIS_MULTI(impl,field,iface) \
51 impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
53 static const IBaseFilterVtbl VfwCapture_Vtbl
;
54 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
;
55 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
;
56 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
;
57 static const IPinVtbl VfwPin_Vtbl
;
59 static HRESULT
VfwPin_Construct( IBaseFilter
*, LPCRITICAL_SECTION
, IPin
** );
61 typedef struct VfwCapture
63 const IBaseFilterVtbl
* lpVtbl
;
64 const IAMStreamConfigVtbl
* IAMStreamConfig_vtbl
;
65 const IAMVideoProcAmpVtbl
* IAMVideoProcAmp_vtbl
;
66 const IPersistPropertyBagVtbl
* IPersistPropertyBag_vtbl
;
71 FILTER_INFO filterInfo
;
73 CRITICAL_SECTION csFilter
;
78 /* VfwPin implementation */
79 typedef struct VfwPinImpl
84 const IKsPropertySetVtbl
* KSP_VT
;
88 IUnknown
* WINAPI
QCAP_createVFWCaptureFilter(IUnknown
*pUnkOuter
, HRESULT
*phr
)
90 VfwCapture
*pVfwCapture
;
93 TRACE("%p - %p\n", pUnkOuter
, phr
);
95 *phr
= CLASS_E_NOAGGREGATION
;
100 pVfwCapture
= CoTaskMemAlloc( sizeof(VfwCapture
) );
105 pVfwCapture
->lpVtbl
= &VfwCapture_Vtbl
;
106 pVfwCapture
->IAMStreamConfig_vtbl
= &IAMStreamConfig_VTable
;
107 pVfwCapture
->IAMVideoProcAmp_vtbl
= &IAMVideoProcAmp_VTable
;
108 pVfwCapture
->IPersistPropertyBag_vtbl
= &IPersistPropertyBag_VTable
;
109 pVfwCapture
->refCount
= 1;
110 pVfwCapture
->filterInfo
.achName
[0] = '\0';
111 pVfwCapture
->filterInfo
.pGraph
= NULL
;
112 pVfwCapture
->state
= State_Stopped
;
113 pVfwCapture
->init
= FALSE
;
114 InitializeCriticalSection(&pVfwCapture
->csFilter
);
115 pVfwCapture
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": VfwCapture.csFilter");
116 hr
= VfwPin_Construct((IBaseFilter
*)&pVfwCapture
->lpVtbl
,
117 &pVfwCapture
->csFilter
, &pVfwCapture
->pOutputPin
);
120 CoTaskMemFree(pVfwCapture
);
123 TRACE("-- created at %p\n", pVfwCapture
);
125 ObjectRefCount(TRUE
);
127 return (IUnknown
*)pVfwCapture
;
130 static HRESULT WINAPI
VfwCapture_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
132 VfwCapture
*This
= (VfwCapture
*)iface
;
133 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
136 if (IsEqualIID(riid
, &IID_IUnknown
) ||
137 IsEqualIID(riid
, &IID_IPersist
) ||
138 IsEqualIID(riid
, &IID_IMediaFilter
) ||
139 IsEqualIID(riid
, &IID_IBaseFilter
))
143 else if (IsEqualIID(riid
, &IID_IAMStreamConfig
))
144 *ppv
= &(This
->IAMStreamConfig_vtbl
);
145 else if (IsEqualIID(riid
, &IID_IAMVideoProcAmp
))
146 *ppv
= &(This
->IAMVideoProcAmp_vtbl
);
147 else if (IsEqualIID(riid
, &IID_IPersistPropertyBag
))
148 *ppv
= &(This
->IPersistPropertyBag_vtbl
);
150 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
151 !IsEqualIID(riid
, &IID_IPersist
) &&
152 !IsEqualIID(riid
, &IID_IPersistPropertyBag
) &&
155 FIXME("Capture system not initialised when looking for %s, "
156 "trying it on primary device now\n", debugstr_guid(riid
));
157 This
->driver_info
= qcap_driver_init( This
->pOutputPin
, 0 );
158 if (!This
->driver_info
)
160 ERR("VfwCapture initialisation failed\n");
168 TRACE("Returning %s interface\n", debugstr_guid(riid
));
169 IUnknown_AddRef((IUnknown
*)(*ppv
));
173 FIXME("No interface for %s!\n", debugstr_guid(riid
));
174 return E_NOINTERFACE
;
177 static ULONG WINAPI
VfwCapture_AddRef(IBaseFilter
* iface
)
179 VfwCapture
*This
= (VfwCapture
*)iface
;
180 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
182 TRACE("%p->() New refcount: %d\n", This
, refCount
);
187 static ULONG WINAPI
VfwCapture_Release(IBaseFilter
* iface
)
189 VfwCapture
*This
= (VfwCapture
*)iface
;
190 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
192 TRACE("%p->() New refcount: %d\n", This
, refCount
);
198 TRACE("destroying everything\n");
201 if (This
->state
!= State_Stopped
)
202 qcap_driver_stop(This
->driver_info
, &This
->state
);
203 qcap_driver_destroy(This
->driver_info
);
205 pin
= (IPinImpl
*) This
->pOutputPin
;
206 if (pin
->pConnectedTo
!= NULL
)
208 IPin_Disconnect(pin
->pConnectedTo
);
209 IPin_Disconnect(This
->pOutputPin
);
211 IPin_Release(This
->pOutputPin
);
212 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
213 DeleteCriticalSection(&This
->csFilter
);
216 ObjectRefCount(FALSE
);
221 /** IPersist methods **/
223 static HRESULT WINAPI
VfwCapture_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
225 TRACE("(%p)\n", pClsid
);
226 *pClsid
= CLSID_VfwCapture
;
230 /** IMediaFilter methods **/
232 static HRESULT WINAPI
VfwCapture_Stop(IBaseFilter
* iface
)
234 VfwCapture
*This
= (VfwCapture
*)iface
;
237 return qcap_driver_stop(This
->driver_info
, &This
->state
);
240 static HRESULT WINAPI
VfwCapture_Pause(IBaseFilter
* iface
)
242 VfwCapture
*This
= (VfwCapture
*)iface
;
245 return qcap_driver_pause(This
->driver_info
, &This
->state
);
248 static HRESULT WINAPI
VfwCapture_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
250 VfwCapture
*This
= (VfwCapture
*)iface
;
251 TRACE("(%x%08x)\n", (ULONG
)(tStart
>> 32), (ULONG
)tStart
);
252 return qcap_driver_run(This
->driver_info
, &This
->state
);
255 static HRESULT WINAPI
256 VfwCapture_GetState( IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
,
257 FILTER_STATE
*pState
)
259 VfwCapture
*This
= (VfwCapture
*)iface
;
261 TRACE("(%u, %p)\n", dwMilliSecsTimeout
, pState
);
263 *pState
= This
->state
;
267 static HRESULT WINAPI
268 VfwCapture_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
270 TRACE("(%p)\n", pClock
);
275 static HRESULT WINAPI
276 VfwCapture_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
278 TRACE("(%p)\n", ppClock
);
283 /** IBaseFilter methods **/
285 static HRESULT WINAPI
286 VfwCapture_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
289 VfwCapture
*This
= (VfwCapture
*)iface
;
291 TRACE("(%p)\n", ppEnum
);
294 epd
.ppPins
= &This
->pOutputPin
;
295 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
298 static HRESULT WINAPI
VfwCapture_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
300 FIXME("(%s, %p) - stub\n", debugstr_w(Id
), ppPin
);
304 static HRESULT WINAPI
VfwCapture_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
306 VfwCapture
*This
= (VfwCapture
*)iface
;
308 TRACE("(%p)\n", pInfo
);
310 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
311 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
314 IFilterGraph_AddRef(pInfo
->pGraph
);
318 static HRESULT WINAPI
319 VfwCapture_JoinFilterGraph( IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
321 VfwCapture
*This
= (VfwCapture
*)iface
;
323 TRACE("(%p, %s)\n", pGraph
, debugstr_w(pName
));
326 lstrcpyW(This
->filterInfo
.achName
, pName
);
328 *This
->filterInfo
.achName
= 0;
329 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
334 static HRESULT WINAPI
335 VfwCapture_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
337 FIXME("(%p) - stub\n", pVendorInfo
);
341 static const IBaseFilterVtbl VfwCapture_Vtbl
=
343 VfwCapture_QueryInterface
,
346 VfwCapture_GetClassID
,
351 VfwCapture_SetSyncSource
,
352 VfwCapture_GetSyncSource
,
355 VfwCapture_QueryFilterInfo
,
356 VfwCapture_JoinFilterGraph
,
357 VfwCapture_QueryVendorInfo
360 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
361 static HRESULT WINAPI
362 AMStreamConfig_QueryInterface( IAMStreamConfig
* iface
, REFIID riid
, LPVOID
* ppv
)
364 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
366 TRACE("%p --> %s\n", This
, debugstr_guid(riid
));
368 if (IsEqualIID(riid
, &IID_IUnknown
) ||
369 IsEqualIID(riid
, &IID_IAMStreamConfig
))
371 IAMStreamConfig_AddRef(iface
);
376 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
377 return E_NOINTERFACE
;
380 static ULONG WINAPI
AMStreamConfig_AddRef( IAMStreamConfig
* iface
)
382 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
384 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
385 return IUnknown_AddRef((IUnknown
*)This
);
388 static ULONG WINAPI
AMStreamConfig_Release( IAMStreamConfig
* iface
)
390 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
392 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
393 return IUnknown_Release((IUnknown
*)This
);
396 static HRESULT WINAPI
397 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
400 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
403 TRACE("(%p): %p->%p\n", iface
, pmt
, pmt
? pmt
->pbFormat
: NULL
);
405 if (This
->state
!= State_Stopped
)
407 TRACE("Returning not stopped error\n");
408 return VFW_E_NOT_STOPPED
;
413 TRACE("pmt is NULL\n");
417 dump_AM_MEDIA_TYPE(pmt
);
419 pin
= (IPinImpl
*)This
->pOutputPin
;
420 if (pin
->pConnectedTo
!= NULL
)
422 hr
= IPin_QueryAccept(pin
->pConnectedTo
, pmt
);
423 TRACE("Would accept: %d\n", hr
);
425 return VFW_E_INVALIDMEDIATYPE
;
428 hr
= qcap_driver_set_format(This
->driver_info
, pmt
);
429 if (SUCCEEDED(hr
) && This
->filterInfo
.pGraph
&& pin
->pConnectedTo
)
431 hr
= IFilterGraph_Reconnect(This
->filterInfo
.pGraph
, This
->pOutputPin
);
433 TRACE("Reconnection completed, with new media format..\n");
435 TRACE("Returning: %d\n", hr
);
439 static HRESULT WINAPI
440 AMStreamConfig_GetFormat( IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**pmt
)
442 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
444 TRACE("%p -> (%p)\n", iface
, pmt
);
445 return qcap_driver_get_format(This
->driver_info
, pmt
);
448 static HRESULT WINAPI
449 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig
*iface
, int *piCount
,
452 FIXME("%p: %p %p - stub, intentional\n", iface
, piCount
, piSize
);
453 return E_NOTIMPL
; /* Not implemented for this interface */
456 static HRESULT WINAPI
457 AMStreamConfig_GetStreamCaps( IAMStreamConfig
*iface
, int iIndex
,
458 AM_MEDIA_TYPE
**pmt
, BYTE
*pSCC
)
460 FIXME("%p: %d %p %p - stub, intentional\n", iface
, iIndex
, pmt
, pSCC
);
461 return E_NOTIMPL
; /* Not implemented for this interface */
464 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
466 AMStreamConfig_QueryInterface
,
467 AMStreamConfig_AddRef
,
468 AMStreamConfig_Release
,
469 AMStreamConfig_SetFormat
,
470 AMStreamConfig_GetFormat
,
471 AMStreamConfig_GetNumberOfCapabilities
,
472 AMStreamConfig_GetStreamCaps
475 static HRESULT WINAPI
476 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp
* iface
, REFIID riid
,
479 if (IsEqualIID(riid
, &IID_IUnknown
) ||
480 IsEqualIID(riid
, &IID_IAMVideoProcAmp
))
483 IAMVideoProcAmp_AddRef( iface
);
487 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
488 return E_NOINTERFACE
;
491 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
493 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
495 return IUnknown_AddRef((IUnknown
*)This
);
498 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
500 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
502 return IUnknown_Release((IUnknown
*)This
);
505 static HRESULT WINAPI
506 AMVideoProcAmp_GetRange( IAMVideoProcAmp
* iface
, LONG Property
, LONG
*pMin
,
507 LONG
*pMax
, LONG
*pSteppingDelta
, LONG
*pDefault
, LONG
*pCapsFlags
)
509 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
511 return qcap_driver_get_prop_range( This
->driver_info
, Property
, pMin
, pMax
,
512 pSteppingDelta
, pDefault
, pCapsFlags
);
515 static HRESULT WINAPI
516 AMVideoProcAmp_Set( IAMVideoProcAmp
* iface
, LONG Property
, LONG lValue
,
519 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
521 return qcap_driver_set_prop(This
->driver_info
, Property
, lValue
, Flags
);
524 static HRESULT WINAPI
525 AMVideoProcAmp_Get( IAMVideoProcAmp
* iface
, LONG Property
, LONG
*lValue
,
528 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
530 return qcap_driver_get_prop(This
->driver_info
, Property
, lValue
, Flags
);
533 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
535 AMVideoProcAmp_QueryInterface
,
536 AMVideoProcAmp_AddRef
,
537 AMVideoProcAmp_Release
,
538 AMVideoProcAmp_GetRange
,
543 static HRESULT WINAPI
544 PPB_QueryInterface( IPersistPropertyBag
* iface
, REFIID riid
, LPVOID
* ppv
)
546 if (IsEqualIID(riid
, &IID_IUnknown
) ||
547 IsEqualIID(riid
, &IID_IPersist
) ||
548 IsEqualIID(riid
, &IID_IPersistPropertyBag
))
550 IPersistPropertyBag_AddRef(iface
);
554 if (IsEqualIID(riid
, &IID_IBaseFilter
))
556 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
557 IPersistPropertyBag_AddRef(iface
);
562 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
563 return E_NOINTERFACE
;
566 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
568 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
570 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
572 return IUnknown_AddRef((IUnknown
*)This
);
575 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
577 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
579 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
581 return IUnknown_Release((IUnknown
*)This
);
584 static HRESULT WINAPI
585 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
587 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
589 FIXME("%p - stub\n", This
);
594 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
596 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
598 FIXME("%p - stub\n", This
);
603 static HRESULT WINAPI
604 PPB_Load( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
605 IErrorLog
*pErrorLog
)
607 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
610 const OLECHAR VFWIndex
[] = {'V','F','W','I','n','d','e','x',0};
612 TRACE("%p/%p-> (%p, %p)\n", iface
, This
, pPropBag
, pErrorLog
);
615 hr
= IPropertyBag_Read(pPropBag
, VFWIndex
, &var
, pErrorLog
);
621 This
->driver_info
= qcap_driver_init( This
->pOutputPin
,
622 var
.__VARIANT_NAME_1
.__VARIANT_NAME_2
.__VARIANT_NAME_3
.ulVal
);
623 if (This
->driver_info
)
625 pin
= (VfwPinImpl
*)This
->pOutputPin
;
626 pin
->driver_info
= This
->driver_info
;
638 static HRESULT WINAPI
639 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
640 BOOL fClearDirty
, BOOL fSaveAllProperties
)
642 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
643 FIXME("%p - stub\n", This
);
647 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
658 /* IKsPropertySet interface */
659 static HRESULT WINAPI
660 KSP_QueryInterface( IKsPropertySet
* iface
, REFIID riid
, LPVOID
* ppv
)
662 if (IsEqualIID(riid
, &IID_IUnknown
) ||
663 IsEqualIID(riid
, &IID_IKsPropertySet
))
666 IKsPropertySet_AddRef( iface
);
670 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
671 return E_NOINTERFACE
;
674 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
676 ICOM_THIS_MULTI(VfwPinImpl
, KSP_VT
, iface
);
678 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface
, This
);
680 return IUnknown_AddRef((IUnknown
*)This
);
683 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
685 ICOM_THIS_MULTI(VfwPinImpl
, KSP_VT
, iface
);
687 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface
, This
);
689 return IUnknown_Release((IUnknown
*)This
);
692 static HRESULT WINAPI
693 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
694 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
697 FIXME("%p: stub\n", iface
);
701 static HRESULT WINAPI
702 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
703 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
704 DWORD cbPropData
, DWORD
*pcbReturned
)
710 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
711 return E_PROP_SET_UNSUPPORTED
;
712 if (pPropData
== NULL
&& pcbReturned
== NULL
)
715 *pcbReturned
= sizeof(GUID
);
716 if (pPropData
== NULL
)
718 if (cbPropData
< sizeof(GUID
))
721 *pGuid
= PIN_CATEGORY_PREVIEW
;
722 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
726 static HRESULT WINAPI
727 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
728 DWORD dwPropID
, DWORD
*pTypeSupport
)
730 FIXME("%p: stub\n", iface
);
734 static const IKsPropertySetVtbl KSP_VTable
=
745 VfwPin_Construct( IBaseFilter
* pBaseFilter
, LPCRITICAL_SECTION pCritSec
,
748 static const WCHAR wszOutputPinName
[] = { 'O','u','t','p','u','t',0 };
749 ALLOCATOR_PROPERTIES ap
;
750 VfwPinImpl
* pPinImpl
;
754 pPinImpl
= CoTaskMemAlloc( sizeof(*pPinImpl
) );
756 return E_OUTOFMEMORY
;
758 /* What we put here doesn't matter, the
759 driver function should override it then commit */
761 ap
.cbBuffer
= 230400;
765 piOutput
.dir
= PINDIR_OUTPUT
;
766 piOutput
.pFilter
= pBaseFilter
;
767 lstrcpyW(piOutput
.achName
, wszOutputPinName
);
768 ObjectRefCount(TRUE
);
770 hr
= OutputPin_Init(&piOutput
, &ap
, pBaseFilter
, NULL
, pCritSec
, &pPinImpl
->pin
);
773 pPinImpl
->KSP_VT
= &KSP_VTable
;
774 pPinImpl
->pin
.pin
.lpVtbl
= &VfwPin_Vtbl
;
775 *ppPin
= (IPin
*)(&pPinImpl
->pin
.pin
.lpVtbl
);
779 CoTaskMemFree(pPinImpl
);
783 static HRESULT WINAPI
VfwPin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
785 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
787 TRACE("%s %p\n", debugstr_guid(riid
), ppv
);
790 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
792 else if (IsEqualIID(riid
, &IID_IKsPropertySet
))
793 *ppv
= &(This
->KSP_VT
);
794 else if (IsEqualIID(riid
, &IID_IAMStreamConfig
))
795 return IUnknown_QueryInterface((IUnknown
*)This
->parent
, riid
, ppv
);
799 IUnknown_AddRef((IUnknown
*)(*ppv
));
803 FIXME("No interface for %s!\n", debugstr_guid(riid
));
804 return E_NOINTERFACE
;
807 static ULONG WINAPI
VfwPin_AddRef(IPin
* iface
)
809 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
810 ULONG refCount
= InterlockedIncrement(&This
->pin
.pin
.refCount
);
812 TRACE("() -> new refcount: %u\n", refCount
);
818 VfwPin_Release(IPin
* iface
)
820 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
821 ULONG refCount
= InterlockedDecrement(&This
->pin
.pin
.refCount
);
823 TRACE("() -> new refcount: %u\n", refCount
);
828 ObjectRefCount(FALSE
);
833 static HRESULT WINAPI
834 VfwPin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
836 ENUMMEDIADETAILS emd
;
840 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
842 hr
= qcap_driver_get_format(This
->driver_info
, &pmt
);
843 emd
.pMediaTypes
= pmt
;
845 hr
= IEnumMediaTypesImpl_Construct(&emd
, ppEnum
);
846 TRACE("%p -- %x\n", This
, hr
);
847 DeleteMediaType(pmt
);
851 static HRESULT WINAPI
852 VfwPin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
854 TRACE("(%p)->(%p, %p)\n", iface
, apPin
, cPin
);
858 static HRESULT WINAPI
VfwPin_EndOfStream(IPin
* iface
)
864 static HRESULT WINAPI
VfwPin_BeginFlush(IPin
* iface
)
866 TRACE("(%p)->()\n", iface
);
870 static HRESULT WINAPI
VfwPin_EndFlush(IPin
* iface
)
872 TRACE("(%p)->()\n", iface
);
876 static HRESULT WINAPI
877 VfwPin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
,
878 REFERENCE_TIME tStop
, double dRate
)
880 TRACE("(%p)->(%s, %s, %e)\n", iface
, wine_dbgstr_longlong(tStart
),
881 wine_dbgstr_longlong(tStop
), dRate
);
885 static const IPinVtbl VfwPin_Vtbl
=
887 VfwPin_QueryInterface
,
891 OutputPin_ReceiveConnection
,
892 OutputPin_Disconnect
,
893 IPinImpl_ConnectedTo
,
894 IPinImpl_ConnectionMediaType
,
895 IPinImpl_QueryPinInfo
,
896 IPinImpl_QueryDirection
,
898 IPinImpl_QueryAccept
,
899 VfwPin_EnumMediaTypes
,
900 VfwPin_QueryInternalConnections
,