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
33 #include "qcap_main.h"
34 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
47 static const IBaseFilterVtbl VfwCapture_Vtbl
;
48 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
;
49 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
;
50 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
;
51 static const IPinVtbl VfwPin_Vtbl
;
53 static HRESULT
VfwPin_Construct( IBaseFilter
*, LPCRITICAL_SECTION
, IPin
** );
55 typedef struct VfwCapture
57 IUnknown IUnknown_inner
;
59 IAMStreamConfig IAMStreamConfig_iface
;
60 IAMVideoProcAmp IAMVideoProcAmp_iface
;
61 IPersistPropertyBag IPersistPropertyBag_iface
;
69 static inline VfwCapture
*impl_from_IUnknown(IUnknown
*iface
)
71 return CONTAINING_RECORD(iface
, VfwCapture
, IUnknown_inner
);
74 static inline VfwCapture
*impl_from_BaseFilter(BaseFilter
*iface
)
76 return CONTAINING_RECORD(iface
, VfwCapture
, filter
);
79 static inline VfwCapture
*impl_from_IBaseFilter(IBaseFilter
*iface
)
81 return CONTAINING_RECORD(iface
, VfwCapture
, filter
.IBaseFilter_iface
);
84 static inline VfwCapture
*impl_from_IAMStreamConfig(IAMStreamConfig
*iface
)
86 return CONTAINING_RECORD(iface
, VfwCapture
, IAMStreamConfig_iface
);
89 static inline VfwCapture
*impl_from_IAMVideoProcAmp(IAMVideoProcAmp
*iface
)
91 return CONTAINING_RECORD(iface
, VfwCapture
, IAMVideoProcAmp_iface
);
94 static inline VfwCapture
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
96 return CONTAINING_RECORD(iface
, VfwCapture
, IPersistPropertyBag_iface
);
99 /* VfwPin implementation */
100 typedef struct VfwPinImpl
103 IKsPropertySet IKsPropertySet_iface
;
108 /* VfwCapture inner IUnknown */
109 static HRESULT WINAPI
unknown_inner_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ret_iface
)
111 VfwCapture
*This
= impl_from_IUnknown(iface
);
113 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ret_iface
);
117 if (IsEqualIID(riid
, &IID_IUnknown
))
118 *ret_iface
= &This
->IUnknown_inner
;
119 else if (IsEqualIID(riid
, &IID_IPersist
) || IsEqualIID(riid
, &IID_IMediaFilter
) ||
120 IsEqualIID(riid
, &IID_IBaseFilter
))
121 *ret_iface
= &This
->filter
.IBaseFilter_iface
;
122 else if (IsEqualIID(riid
, &IID_IPersistPropertyBag
))
123 *ret_iface
= &This
->IPersistPropertyBag_iface
;
124 else if (IsEqualIID(riid
, &IID_IAMFilterMiscFlags
))
125 FIXME("IAMFilterMiscFlags not supported yet!\n");
126 else if (IsEqualIID(riid
, &IID_ISpecifyPropertyPages
))
127 FIXME("ISpecifyPropertyPages not supported yet!\n");
128 else if (IsEqualIID(riid
, &IID_IAMVfwCaptureDialogs
))
129 FIXME("IAMVfwCaptureDialogs not supported yet!\n");
130 else if (IsEqualIID(riid
, &IID_IAMStreamConfig
))
131 *ret_iface
= &This
->IAMStreamConfig_iface
;
132 else if (IsEqualIID(riid
, &IID_IAMVideoProcAmp
))
133 *ret_iface
= &This
->IAMVideoProcAmp_iface
;
135 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ret_iface
);
138 return E_NOINTERFACE
;
140 IUnknown_AddRef((IUnknown
*)*ret_iface
);
144 static ULONG WINAPI
unknown_inner_AddRef(IUnknown
*iface
)
146 VfwCapture
*This
= impl_from_IUnknown(iface
);
147 ULONG ref
= BaseFilterImpl_AddRef(&This
->filter
.IBaseFilter_iface
);
149 TRACE("(%p) ref=%d\n", This
, ref
);
154 static ULONG WINAPI
unknown_inner_Release(IUnknown
*iface
)
156 VfwCapture
*This
= impl_from_IUnknown(iface
);
157 ULONG ref
= InterlockedDecrement(&This
->filter
.refCount
);
159 TRACE("(%p) ref=%d\n", This
, ref
);
165 TRACE("destroying everything\n");
168 if (This
->filter
.state
!= State_Stopped
)
169 qcap_driver_stop(This
->driver_info
, &This
->filter
.state
);
170 qcap_driver_destroy(This
->driver_info
);
172 IPin_ConnectedTo(This
->pOutputPin
, &conn
);
175 IPin_Disconnect(conn
);
176 IPin_Disconnect(This
->pOutputPin
);
179 IPin_Release(This
->pOutputPin
);
180 BaseFilter_Destroy(&This
->filter
);
182 ObjectRefCount(FALSE
);
188 static const IUnknownVtbl unknown_inner_vtbl
=
190 unknown_inner_QueryInterface
,
191 unknown_inner_AddRef
,
192 unknown_inner_Release
,
195 static IPin
* WINAPI
VfwCapture_GetPin(BaseFilter
*iface
, int pos
)
197 VfwCapture
*This
= impl_from_BaseFilter(iface
);
199 if (pos
>= 1 || pos
< 0)
202 IPin_AddRef(This
->pOutputPin
);
203 return This
->pOutputPin
;
206 static LONG WINAPI
VfwCapture_GetPinCount(BaseFilter
*iface
)
211 static const BaseFilterFuncTable BaseFuncTable
= {
213 VfwCapture_GetPinCount
216 IUnknown
* WINAPI
QCAP_createVFWCaptureFilter(IUnknown
*pUnkOuter
, HRESULT
*phr
)
218 VfwCapture
*pVfwCapture
;
221 TRACE("%p - %p\n", pUnkOuter
, phr
);
223 *phr
= E_OUTOFMEMORY
;
224 pVfwCapture
= CoTaskMemAlloc( sizeof(VfwCapture
) );
228 BaseFilter_Init(&pVfwCapture
->filter
, &VfwCapture_Vtbl
, &CLSID_VfwCapture
, (DWORD_PTR
)(__FILE__
": VfwCapture.csFilter"), &BaseFuncTable
);
230 pVfwCapture
->IUnknown_inner
.lpVtbl
= &unknown_inner_vtbl
;
231 pVfwCapture
->IAMStreamConfig_iface
.lpVtbl
= &IAMStreamConfig_VTable
;
232 pVfwCapture
->IAMVideoProcAmp_iface
.lpVtbl
= &IAMVideoProcAmp_VTable
;
233 pVfwCapture
->IPersistPropertyBag_iface
.lpVtbl
= &IPersistPropertyBag_VTable
;
234 pVfwCapture
->init
= FALSE
;
237 pVfwCapture
->outer_unk
= pUnkOuter
;
239 pVfwCapture
->outer_unk
= &pVfwCapture
->IUnknown_inner
;
241 hr
= VfwPin_Construct(&pVfwCapture
->filter
.IBaseFilter_iface
,
242 &pVfwCapture
->filter
.csFilter
, &pVfwCapture
->pOutputPin
);
245 CoTaskMemFree(pVfwCapture
);
248 TRACE("-- created at %p\n", pVfwCapture
);
250 ObjectRefCount(TRUE
);
252 return &pVfwCapture
->IUnknown_inner
;
255 static HRESULT WINAPI
VfwCapture_QueryInterface(IBaseFilter
*iface
, REFIID riid
, void **ret_iface
)
257 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
259 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ret_iface
);
262 static ULONG WINAPI
VfwCapture_AddRef(IBaseFilter
*iface
)
264 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
266 return IUnknown_AddRef(This
->outer_unk
);
269 static ULONG WINAPI
VfwCapture_Release(IBaseFilter
* iface
)
271 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
273 return IUnknown_Release(This
->outer_unk
);
276 /** IMediaFilter methods **/
278 static HRESULT WINAPI
VfwCapture_Stop(IBaseFilter
* iface
)
280 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
283 return qcap_driver_stop(This
->driver_info
, &This
->filter
.state
);
286 static HRESULT WINAPI
VfwCapture_Pause(IBaseFilter
* iface
)
288 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
291 return qcap_driver_pause(This
->driver_info
, &This
->filter
.state
);
294 static HRESULT WINAPI
VfwCapture_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
296 VfwCapture
*This
= impl_from_IBaseFilter(iface
);
297 TRACE("(%x%08x)\n", (ULONG
)(tStart
>> 32), (ULONG
)tStart
);
298 return qcap_driver_run(This
->driver_info
, &This
->filter
.state
);
301 /** IBaseFilter methods **/
302 static HRESULT WINAPI
VfwCapture_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
304 FIXME("(%s, %p) - stub\n", debugstr_w(Id
), ppPin
);
308 static const IBaseFilterVtbl VfwCapture_Vtbl
=
310 VfwCapture_QueryInterface
,
313 BaseFilterImpl_GetClassID
,
317 BaseFilterImpl_GetState
,
318 BaseFilterImpl_SetSyncSource
,
319 BaseFilterImpl_GetSyncSource
,
320 BaseFilterImpl_EnumPins
,
322 BaseFilterImpl_QueryFilterInfo
,
323 BaseFilterImpl_JoinFilterGraph
,
324 BaseFilterImpl_QueryVendorInfo
327 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
328 static HRESULT WINAPI
AMStreamConfig_QueryInterface(IAMStreamConfig
*iface
, REFIID riid
,
331 VfwCapture
*This
= impl_from_IAMStreamConfig(iface
);
333 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ret_iface
);
336 static ULONG WINAPI
AMStreamConfig_AddRef( IAMStreamConfig
* iface
)
338 VfwCapture
*This
= impl_from_IAMStreamConfig(iface
);
340 return IUnknown_AddRef(This
->outer_unk
);
343 static ULONG WINAPI
AMStreamConfig_Release( IAMStreamConfig
* iface
)
345 VfwCapture
*This
= impl_from_IAMStreamConfig(iface
);
347 return IUnknown_Release(This
->outer_unk
);
350 static HRESULT WINAPI
351 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
354 VfwCapture
*This
= impl_from_IAMStreamConfig(iface
);
357 TRACE("(%p): %p->%p\n", iface
, pmt
, pmt
? pmt
->pbFormat
: NULL
);
359 if (This
->filter
.state
!= State_Stopped
)
361 TRACE("Returning not stopped error\n");
362 return VFW_E_NOT_STOPPED
;
367 TRACE("pmt is NULL\n");
371 dump_AM_MEDIA_TYPE(pmt
);
373 pin
= (BasePin
*)This
->pOutputPin
;
374 if (pin
->pConnectedTo
!= NULL
)
376 hr
= IPin_QueryAccept(pin
->pConnectedTo
, pmt
);
377 TRACE("Would accept: %d\n", hr
);
379 return VFW_E_INVALIDMEDIATYPE
;
382 hr
= qcap_driver_set_format(This
->driver_info
, pmt
);
383 if (SUCCEEDED(hr
) && This
->filter
.filterInfo
.pGraph
&& pin
->pConnectedTo
)
385 hr
= IFilterGraph_Reconnect(This
->filter
.filterInfo
.pGraph
, This
->pOutputPin
);
387 TRACE("Reconnection completed, with new media format..\n");
389 TRACE("Returning: %d\n", hr
);
393 static HRESULT WINAPI
394 AMStreamConfig_GetFormat( IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**pmt
)
396 VfwCapture
*This
= impl_from_IAMStreamConfig(iface
);
398 TRACE("%p -> (%p)\n", iface
, pmt
);
399 return qcap_driver_get_format(This
->driver_info
, pmt
);
402 static HRESULT WINAPI
403 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig
*iface
, int *piCount
,
406 FIXME("%p: %p %p - stub, intentional\n", iface
, piCount
, piSize
);
408 return E_NOTIMPL
; /* Not implemented for this interface */
411 static HRESULT WINAPI
412 AMStreamConfig_GetStreamCaps( IAMStreamConfig
*iface
, int iIndex
,
413 AM_MEDIA_TYPE
**pmt
, BYTE
*pSCC
)
415 FIXME("%p: %d %p %p - stub, intentional\n", iface
, iIndex
, pmt
, pSCC
);
416 return E_NOTIMPL
; /* Not implemented for this interface */
419 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
421 AMStreamConfig_QueryInterface
,
422 AMStreamConfig_AddRef
,
423 AMStreamConfig_Release
,
424 AMStreamConfig_SetFormat
,
425 AMStreamConfig_GetFormat
,
426 AMStreamConfig_GetNumberOfCapabilities
,
427 AMStreamConfig_GetStreamCaps
430 static HRESULT WINAPI
AMVideoProcAmp_QueryInterface(IAMVideoProcAmp
*iface
, REFIID riid
,
433 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
435 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ret_iface
);
438 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
440 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
442 return IUnknown_AddRef(This
->outer_unk
);
445 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
447 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
449 return IUnknown_Release(This
->outer_unk
);
452 static HRESULT WINAPI
453 AMVideoProcAmp_GetRange( IAMVideoProcAmp
* iface
, LONG Property
, LONG
*pMin
,
454 LONG
*pMax
, LONG
*pSteppingDelta
, LONG
*pDefault
, LONG
*pCapsFlags
)
456 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
458 return qcap_driver_get_prop_range( This
->driver_info
, Property
, pMin
, pMax
,
459 pSteppingDelta
, pDefault
, pCapsFlags
);
462 static HRESULT WINAPI
463 AMVideoProcAmp_Set( IAMVideoProcAmp
* iface
, LONG Property
, LONG lValue
,
466 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
468 return qcap_driver_set_prop(This
->driver_info
, Property
, lValue
, Flags
);
471 static HRESULT WINAPI
472 AMVideoProcAmp_Get( IAMVideoProcAmp
* iface
, LONG Property
, LONG
*lValue
,
475 VfwCapture
*This
= impl_from_IAMVideoProcAmp(iface
);
477 return qcap_driver_get_prop(This
->driver_info
, Property
, lValue
, Flags
);
480 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
482 AMVideoProcAmp_QueryInterface
,
483 AMVideoProcAmp_AddRef
,
484 AMVideoProcAmp_Release
,
485 AMVideoProcAmp_GetRange
,
490 static HRESULT WINAPI
PPB_QueryInterface(IPersistPropertyBag
*iface
, REFIID riid
, void **ret_iface
)
492 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
494 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ret_iface
);
497 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
499 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
501 return IUnknown_AddRef(This
->outer_unk
);
504 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
506 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
508 return IUnknown_Release(This
->outer_unk
);
511 static HRESULT WINAPI
512 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
514 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
516 FIXME("%p - stub\n", This
);
521 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
523 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
525 FIXME("%p - stub\n", This
);
530 static HRESULT WINAPI
531 PPB_Load( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
532 IErrorLog
*pErrorLog
)
534 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
537 const OLECHAR VFWIndex
[] = {'V','F','W','I','n','d','e','x',0};
539 TRACE("%p/%p-> (%p, %p)\n", iface
, This
, pPropBag
, pErrorLog
);
542 hr
= IPropertyBag_Read(pPropBag
, VFWIndex
, &var
, pErrorLog
);
548 This
->driver_info
= qcap_driver_init( This
->pOutputPin
,
549 var
.__VARIANT_NAME_1
.__VARIANT_NAME_2
.__VARIANT_NAME_3
.ulVal
);
550 if (This
->driver_info
)
552 pin
= (VfwPinImpl
*)This
->pOutputPin
;
564 static HRESULT WINAPI
565 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
566 BOOL fClearDirty
, BOOL fSaveAllProperties
)
568 VfwCapture
*This
= impl_from_IPersistPropertyBag(iface
);
569 FIXME("%p - stub\n", This
);
573 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
584 /* IKsPropertySet interface */
585 static inline VfwPinImpl
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
587 return CONTAINING_RECORD(iface
, VfwPinImpl
, IKsPropertySet_iface
);
590 static HRESULT WINAPI
KSP_QueryInterface(IKsPropertySet
* iface
, REFIID riid
, void **ret_iface
)
592 VfwPinImpl
*This
= impl_from_IKsPropertySet(iface
);
594 return IPin_QueryInterface(&This
->pin
.pin
.IPin_iface
, riid
, ret_iface
);
597 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
599 VfwPinImpl
*This
= impl_from_IKsPropertySet(iface
);
601 return IPin_AddRef(&This
->pin
.pin
.IPin_iface
);
604 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
606 VfwPinImpl
*This
= impl_from_IKsPropertySet(iface
);
608 return IPin_Release(&This
->pin
.pin
.IPin_iface
);
611 static HRESULT WINAPI
612 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
613 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
616 FIXME("%p: stub\n", iface
);
620 static HRESULT WINAPI
621 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
622 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
623 DWORD cbPropData
, DWORD
*pcbReturned
)
629 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
630 return E_PROP_SET_UNSUPPORTED
;
631 if (pPropData
== NULL
&& pcbReturned
== NULL
)
634 *pcbReturned
= sizeof(GUID
);
635 if (pPropData
== NULL
)
637 if (cbPropData
< sizeof(GUID
))
640 *pGuid
= PIN_CATEGORY_CAPTURE
;
641 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
645 static HRESULT WINAPI
646 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
647 DWORD dwPropID
, DWORD
*pTypeSupport
)
649 FIXME("%p: stub\n", iface
);
653 static const IKsPropertySetVtbl IKsPropertySet_VTable
=
663 static inline VfwPinImpl
*impl_from_BasePin(BasePin
*pin
)
665 return CONTAINING_RECORD(pin
, VfwPinImpl
, pin
.pin
);
668 static HRESULT WINAPI
VfwPin_GetMediaType(BasePin
*pin
, int iPosition
, AM_MEDIA_TYPE
*pmt
)
670 VfwPinImpl
*This
= impl_from_BasePin(pin
);
671 AM_MEDIA_TYPE
*vfw_pmt
;
677 return VFW_S_NO_MORE_ITEMS
;
679 hr
= qcap_driver_get_format(This
->parent
->driver_info
, &vfw_pmt
);
681 CopyMediaType(pmt
, vfw_pmt
);
682 DeleteMediaType(vfw_pmt
);
687 static LONG WINAPI
VfwPin_GetMediaTypeVersion(BasePin
*iface
)
692 static HRESULT WINAPI
VfwPin_DecideBufferSize(BaseOutputPin
*iface
, IMemAllocator
*pAlloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
694 ALLOCATOR_PROPERTIES actual
;
696 /* What we put here doesn't matter, the
697 driver function should override it then commit */
698 if (!ppropInputRequest
->cBuffers
)
699 ppropInputRequest
->cBuffers
= 3;
700 if (!ppropInputRequest
->cbBuffer
)
701 ppropInputRequest
->cbBuffer
= 230400;
702 if (!ppropInputRequest
->cbAlign
)
703 ppropInputRequest
->cbAlign
= 1;
705 return IMemAllocator_SetProperties(pAlloc
, ppropInputRequest
, &actual
);
708 static const BaseOutputPinFuncTable output_BaseOutputFuncTable
= {
711 BaseOutputPinImpl_AttemptConnection
,
712 VfwPin_GetMediaTypeVersion
,
715 VfwPin_DecideBufferSize
,
716 BaseOutputPinImpl_DecideAllocator
,
717 BaseOutputPinImpl_BreakConnect
721 VfwPin_Construct( IBaseFilter
* pBaseFilter
, LPCRITICAL_SECTION pCritSec
,
724 static const WCHAR wszOutputPinName
[] = { 'O','u','t','p','u','t',0 };
730 piOutput
.dir
= PINDIR_OUTPUT
;
731 piOutput
.pFilter
= pBaseFilter
;
732 lstrcpyW(piOutput
.achName
, wszOutputPinName
);
734 hr
= BaseOutputPin_Construct(&VfwPin_Vtbl
, sizeof(VfwPinImpl
), &piOutput
, &output_BaseOutputFuncTable
, pCritSec
, ppPin
);
738 VfwPinImpl
*pPinImpl
= (VfwPinImpl
*)*ppPin
;
739 pPinImpl
->IKsPropertySet_iface
.lpVtbl
= &IKsPropertySet_VTable
;
740 ObjectRefCount(TRUE
);
746 static inline VfwPinImpl
*impl_from_IPin(IPin
*iface
)
748 return CONTAINING_RECORD(iface
, VfwPinImpl
, pin
.pin
.IPin_iface
);
751 static HRESULT WINAPI
VfwPin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
753 VfwPinImpl
*This
= impl_from_IPin(iface
);
755 TRACE("%s %p\n", debugstr_guid(riid
), ppv
);
758 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
760 else if (IsEqualIID(riid
, &IID_IKsPropertySet
))
761 *ppv
= &This
->IKsPropertySet_iface
;
762 else if (IsEqualIID(riid
, &IID_IAMStreamConfig
))
763 return IUnknown_QueryInterface((IUnknown
*)This
->parent
, riid
, ppv
);
767 IUnknown_AddRef((IUnknown
*)(*ppv
));
771 FIXME("No interface for %s!\n", debugstr_guid(riid
));
772 return E_NOINTERFACE
;
776 VfwPin_Release(IPin
* iface
)
778 VfwPinImpl
*This
= impl_from_IPin(iface
);
779 ULONG refCount
= InterlockedDecrement(&This
->pin
.pin
.refCount
);
781 TRACE("() -> new refcount: %u\n", refCount
);
785 BaseOutputPin_Destroy(&This
->pin
);
786 ObjectRefCount(FALSE
);
791 static HRESULT WINAPI
792 VfwPin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
794 VfwPinImpl
*This
= impl_from_IPin(iface
);
798 hr
= qcap_driver_get_format(This
->parent
->driver_info
, &pmt
);
800 hr
= BasePinImpl_EnumMediaTypes(iface
, ppEnum
);
801 DeleteMediaType(pmt
);
803 TRACE("%p -- %x\n", This
, hr
);
807 static HRESULT WINAPI
808 VfwPin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
810 TRACE("(%p)->(%p, %p)\n", iface
, apPin
, cPin
);
814 static const IPinVtbl VfwPin_Vtbl
=
816 VfwPin_QueryInterface
,
819 BaseOutputPinImpl_Connect
,
820 BaseOutputPinImpl_ReceiveConnection
,
821 BaseOutputPinImpl_Disconnect
,
822 BasePinImpl_ConnectedTo
,
823 BasePinImpl_ConnectionMediaType
,
824 BasePinImpl_QueryPinInfo
,
825 BasePinImpl_QueryDirection
,
827 BasePinImpl_QueryAccept
,
828 VfwPin_EnumMediaTypes
,
829 VfwPin_QueryInternalConnections
,
830 BaseOutputPinImpl_EndOfStream
,
831 BaseOutputPinImpl_BeginFlush
,
832 BaseOutputPinImpl_EndFlush
,
833 BasePinImpl_NewSegment