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
83 const IKsPropertySetVtbl
* KSP_VT
;
87 IUnknown
* WINAPI
QCAP_createVFWCaptureFilter(IUnknown
*pUnkOuter
, HRESULT
*phr
)
89 VfwCapture
*pVfwCapture
;
92 TRACE("%p - %p\n", pUnkOuter
, phr
);
94 *phr
= CLASS_E_NOAGGREGATION
;
99 pVfwCapture
= CoTaskMemAlloc( sizeof(VfwCapture
) );
104 pVfwCapture
->lpVtbl
= &VfwCapture_Vtbl
;
105 pVfwCapture
->IAMStreamConfig_vtbl
= &IAMStreamConfig_VTable
;
106 pVfwCapture
->IAMVideoProcAmp_vtbl
= &IAMVideoProcAmp_VTable
;
107 pVfwCapture
->IPersistPropertyBag_vtbl
= &IPersistPropertyBag_VTable
;
108 pVfwCapture
->refCount
= 1;
109 pVfwCapture
->filterInfo
.achName
[0] = '\0';
110 pVfwCapture
->filterInfo
.pGraph
= NULL
;
111 pVfwCapture
->state
= State_Stopped
;
112 pVfwCapture
->init
= FALSE
;
113 InitializeCriticalSection(&pVfwCapture
->csFilter
);
114 pVfwCapture
->csFilter
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": VfwCapture.csFilter");
115 hr
= VfwPin_Construct((IBaseFilter
*)&pVfwCapture
->lpVtbl
,
116 &pVfwCapture
->csFilter
, &pVfwCapture
->pOutputPin
);
119 CoTaskMemFree(pVfwCapture
);
122 TRACE("-- created at %p\n", pVfwCapture
);
124 ObjectRefCount(TRUE
);
126 return (IUnknown
*)pVfwCapture
;
129 static HRESULT WINAPI
VfwCapture_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
131 VfwCapture
*This
= (VfwCapture
*)iface
;
132 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppv
);
135 if (IsEqualIID(riid
, &IID_IUnknown
) ||
136 IsEqualIID(riid
, &IID_IPersist
) ||
137 IsEqualIID(riid
, &IID_IMediaFilter
) ||
138 IsEqualIID(riid
, &IID_IBaseFilter
))
142 else if (IsEqualIID(riid
, &IID_IAMStreamConfig
))
143 *ppv
= &(This
->IAMStreamConfig_vtbl
);
144 else if (IsEqualIID(riid
, &IID_IAMVideoProcAmp
))
145 *ppv
= &(This
->IAMVideoProcAmp_vtbl
);
146 else if (IsEqualIID(riid
, &IID_IPersistPropertyBag
))
147 *ppv
= &(This
->IPersistPropertyBag_vtbl
);
149 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
150 !IsEqualIID(riid
, &IID_IPersist
) &&
151 !IsEqualIID(riid
, &IID_IPersistPropertyBag
) &&
154 FIXME("Capture system not initialised when looking for %s, "
155 "trying it on primary device now\n", debugstr_guid(riid
));
156 This
->driver_info
= qcap_driver_init( This
->pOutputPin
, 0 );
157 if (!This
->driver_info
)
159 ERR("VfwCapture initialisation failed\n");
167 TRACE("Returning %s interface\n", debugstr_guid(riid
));
168 IUnknown_AddRef((IUnknown
*)(*ppv
));
172 FIXME("No interface for %s!\n", debugstr_guid(riid
));
173 return E_NOINTERFACE
;
176 static ULONG WINAPI
VfwCapture_AddRef(IBaseFilter
* iface
)
178 VfwCapture
*This
= (VfwCapture
*)iface
;
179 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
181 TRACE("%p->() New refcount: %d\n", This
, refCount
);
186 static ULONG WINAPI
VfwCapture_Release(IBaseFilter
* iface
)
188 VfwCapture
*This
= (VfwCapture
*)iface
;
189 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
191 TRACE("%p->() New refcount: %d\n", This
, refCount
);
197 TRACE("destroying everything\n");
200 if (This
->state
!= State_Stopped
)
201 qcap_driver_stop(This
->driver_info
, &This
->state
);
202 qcap_driver_destroy(This
->driver_info
);
204 pin
= (IPinImpl
*) This
->pOutputPin
;
205 if (pin
->pConnectedTo
!= NULL
)
207 IPin_Disconnect(pin
->pConnectedTo
);
208 IPin_Disconnect(This
->pOutputPin
);
210 IPin_Release(This
->pOutputPin
);
211 This
->csFilter
.DebugInfo
->Spare
[0] = 0;
212 DeleteCriticalSection(&This
->csFilter
);
215 ObjectRefCount(FALSE
);
220 /** IPersist methods **/
222 static HRESULT WINAPI
VfwCapture_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
224 TRACE("(%p)\n", pClsid
);
225 *pClsid
= CLSID_VfwCapture
;
229 /** IMediaFilter methods **/
231 static HRESULT WINAPI
VfwCapture_Stop(IBaseFilter
* iface
)
233 VfwCapture
*This
= (VfwCapture
*)iface
;
236 return qcap_driver_stop(This
->driver_info
, &This
->state
);
239 static HRESULT WINAPI
VfwCapture_Pause(IBaseFilter
* iface
)
241 VfwCapture
*This
= (VfwCapture
*)iface
;
244 return qcap_driver_pause(This
->driver_info
, &This
->state
);
247 static HRESULT WINAPI
VfwCapture_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
249 VfwCapture
*This
= (VfwCapture
*)iface
;
250 TRACE("(%x%08x)\n", (ULONG
)(tStart
>> 32), (ULONG
)tStart
);
251 return qcap_driver_run(This
->driver_info
, &This
->state
);
254 static HRESULT WINAPI
255 VfwCapture_GetState( IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
,
256 FILTER_STATE
*pState
)
258 VfwCapture
*This
= (VfwCapture
*)iface
;
260 TRACE("(%u, %p)\n", dwMilliSecsTimeout
, pState
);
262 *pState
= This
->state
;
266 static HRESULT WINAPI
267 VfwCapture_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
269 TRACE("(%p)\n", pClock
);
274 static HRESULT WINAPI
275 VfwCapture_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
277 TRACE("(%p)\n", ppClock
);
282 /** IBaseFilter methods **/
284 static HRESULT WINAPI
285 VfwCapture_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
288 VfwCapture
*This
= (VfwCapture
*)iface
;
290 TRACE("(%p)\n", ppEnum
);
293 epd
.ppPins
= &This
->pOutputPin
;
294 return IEnumPinsImpl_Construct(&epd
, ppEnum
);
297 static HRESULT WINAPI
VfwCapture_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
299 FIXME("(%s, %p) - stub\n", debugstr_w(Id
), ppPin
);
303 static HRESULT WINAPI
VfwCapture_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
305 VfwCapture
*This
= (VfwCapture
*)iface
;
307 TRACE("(%p)\n", pInfo
);
309 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
310 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
313 IFilterGraph_AddRef(pInfo
->pGraph
);
317 static HRESULT WINAPI
318 VfwCapture_JoinFilterGraph( IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
320 VfwCapture
*This
= (VfwCapture
*)iface
;
322 TRACE("(%p, %s)\n", pGraph
, debugstr_w(pName
));
325 lstrcpyW(This
->filterInfo
.achName
, pName
);
327 *This
->filterInfo
.achName
= 0;
328 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
333 static HRESULT WINAPI
334 VfwCapture_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
336 FIXME("(%p) - stub\n", pVendorInfo
);
340 static const IBaseFilterVtbl VfwCapture_Vtbl
=
342 VfwCapture_QueryInterface
,
345 VfwCapture_GetClassID
,
350 VfwCapture_SetSyncSource
,
351 VfwCapture_GetSyncSource
,
354 VfwCapture_QueryFilterInfo
,
355 VfwCapture_JoinFilterGraph
,
356 VfwCapture_QueryVendorInfo
359 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
360 static HRESULT WINAPI
361 AMStreamConfig_QueryInterface( IAMStreamConfig
* iface
, REFIID riid
, LPVOID
* ppv
)
363 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
365 TRACE("%p --> %s\n", This
, debugstr_guid(riid
));
367 if (IsEqualIID(riid
, &IID_IUnknown
) ||
368 IsEqualIID(riid
, &IID_IAMStreamConfig
))
370 IAMStreamConfig_AddRef(iface
);
375 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
376 return E_NOINTERFACE
;
379 static ULONG WINAPI
AMStreamConfig_AddRef( IAMStreamConfig
* iface
)
381 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
383 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
384 return IUnknown_AddRef((IUnknown
*)This
);
387 static ULONG WINAPI
AMStreamConfig_Release( IAMStreamConfig
* iface
)
389 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
391 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
392 return IUnknown_Release((IUnknown
*)This
);
395 static HRESULT WINAPI
396 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
399 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
402 TRACE("(%p): %p->%p\n", iface
, pmt
, pmt
->pbFormat
);
404 if (This
->state
!= State_Stopped
)
406 TRACE("Returning not stopped error\n");
407 return VFW_E_NOT_STOPPED
;
410 dump_AM_MEDIA_TYPE(pmt
);
412 pin
= (IPinImpl
*)This
->pOutputPin
;
413 if (pin
->pConnectedTo
!= NULL
)
415 hr
= IPin_QueryAccept(pin
->pConnectedTo
, pmt
);
416 TRACE("Would accept: %d\n", hr
);
418 return VFW_E_INVALIDMEDIATYPE
;
421 hr
= qcap_driver_set_format(This
->driver_info
, pmt
);
422 if (SUCCEEDED(hr
) && This
->filterInfo
.pGraph
&& pin
->pConnectedTo
)
424 hr
= IFilterGraph_Reconnect(This
->filterInfo
.pGraph
, This
->pOutputPin
);
426 TRACE("Reconnection completed, with new media format..\n");
428 TRACE("Returning: %d\n", hr
);
432 static HRESULT WINAPI
433 AMStreamConfig_GetFormat( IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**pmt
)
435 ICOM_THIS_MULTI(VfwCapture
, IAMStreamConfig_vtbl
, iface
);
437 TRACE("%p -> (%p)\n", iface
, pmt
);
438 return qcap_driver_get_format(This
->driver_info
, pmt
);
441 static HRESULT WINAPI
442 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig
*iface
, int *piCount
,
445 FIXME("%p: %p %p - stub, intentional\n", iface
, piCount
, piSize
);
446 return E_NOTIMPL
; /* Not implemented for this interface */
449 static HRESULT WINAPI
450 AMStreamConfig_GetStreamCaps( IAMStreamConfig
*iface
, int iIndex
,
451 AM_MEDIA_TYPE
**pmt
, BYTE
*pSCC
)
453 FIXME("%p: %d %p %p - stub, intentional\n", iface
, iIndex
, pmt
, pSCC
);
454 return E_NOTIMPL
; /* Not implemented for this interface */
457 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
459 AMStreamConfig_QueryInterface
,
460 AMStreamConfig_AddRef
,
461 AMStreamConfig_Release
,
462 AMStreamConfig_SetFormat
,
463 AMStreamConfig_GetFormat
,
464 AMStreamConfig_GetNumberOfCapabilities
,
465 AMStreamConfig_GetStreamCaps
468 static HRESULT WINAPI
469 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp
* iface
, REFIID riid
,
472 if (IsEqualIID(riid
, &IID_IUnknown
) ||
473 IsEqualIID(riid
, &IID_IAMVideoProcAmp
))
476 IAMVideoProcAmp_AddRef( iface
);
480 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
481 return E_NOINTERFACE
;
484 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
486 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
488 return IUnknown_AddRef((IUnknown
*)This
);
491 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
493 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
495 return IUnknown_Release((IUnknown
*)This
);
498 static HRESULT WINAPI
499 AMVideoProcAmp_GetRange( IAMVideoProcAmp
* iface
, long Property
, long *pMin
,
500 long *pMax
, long *pSteppingDelta
, long *pDefault
, long *pCapsFlags
)
502 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
504 return qcap_driver_get_prop_range( This
->driver_info
, Property
, pMin
, pMax
,
505 pSteppingDelta
, pDefault
, pCapsFlags
);
508 static HRESULT WINAPI
509 AMVideoProcAmp_Set( IAMVideoProcAmp
* iface
, long Property
, long lValue
,
512 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
514 return qcap_driver_set_prop(This
->driver_info
, Property
, lValue
, Flags
);
517 static HRESULT WINAPI
518 AMVideoProcAmp_Get( IAMVideoProcAmp
* iface
, long Property
, long *lValue
,
521 ICOM_THIS_MULTI(VfwCapture
, IAMVideoProcAmp_vtbl
, iface
);
523 return qcap_driver_get_prop(This
->driver_info
, Property
, lValue
, Flags
);
526 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
528 AMVideoProcAmp_QueryInterface
,
529 AMVideoProcAmp_AddRef
,
530 AMVideoProcAmp_Release
,
531 AMVideoProcAmp_GetRange
,
536 static HRESULT WINAPI
537 PPB_QueryInterface( IPersistPropertyBag
* iface
, REFIID riid
, LPVOID
* ppv
)
539 if (IsEqualIID(riid
, &IID_IUnknown
) ||
540 IsEqualIID(riid
, &IID_IPersist
) ||
541 IsEqualIID(riid
, &IID_IPersistPropertyBag
))
543 IPersistPropertyBag_AddRef(iface
);
547 if (IsEqualIID(riid
, &IID_IBaseFilter
))
549 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
550 IPersistPropertyBag_AddRef(iface
);
555 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
556 return E_NOINTERFACE
;
559 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
561 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
563 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
565 return IUnknown_AddRef((IUnknown
*)This
);
568 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
570 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
572 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface
, This
);
574 return IUnknown_Release((IUnknown
*)This
);
577 static HRESULT WINAPI
578 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
580 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
582 FIXME("%p - stub\n", This
);
587 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
589 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
591 FIXME("%p - stub\n", This
);
596 static HRESULT WINAPI
597 PPB_Load( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
598 IErrorLog
*pErrorLog
)
600 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
603 const OLECHAR VFWIndex
[] = {'V','F','W','I','n','d','e','x',0};
605 TRACE("%p/%p-> (%p, %p)\n", iface
, This
, pPropBag
, pErrorLog
);
608 hr
= IPropertyBag_Read(pPropBag
, (LPCOLESTR
)VFWIndex
, &var
, pErrorLog
);
614 This
->driver_info
= qcap_driver_init( This
->pOutputPin
,
615 var
.__VARIANT_NAME_1
.__VARIANT_NAME_2
.__VARIANT_NAME_3
.ulVal
);
616 if (This
->driver_info
)
618 pin
= (VfwPinImpl
*)This
->pOutputPin
;
619 pin
->driver_info
= This
->driver_info
;
630 static HRESULT WINAPI
631 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
632 BOOL fClearDirty
, BOOL fSaveAllProperties
)
634 ICOM_THIS_MULTI(VfwCapture
, IPersistPropertyBag_vtbl
, iface
);
635 FIXME("%p - stub\n", This
);
639 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
650 /* IKsPropertySet interface */
651 static HRESULT WINAPI
652 KSP_QueryInterface( IKsPropertySet
* iface
, REFIID riid
, LPVOID
* ppv
)
654 if (IsEqualIID(riid
, &IID_IUnknown
) ||
655 IsEqualIID(riid
, &IID_IKsPropertySet
))
657 *ppv
= (LPVOID
)iface
;
658 IKsPropertySet_AddRef( iface
);
662 FIXME("No interface for iid %s\n", debugstr_guid(riid
));
663 return E_NOINTERFACE
;
666 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
668 ICOM_THIS_MULTI(VfwPinImpl
, KSP_VT
, iface
);
670 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface
, This
);
672 return IUnknown_AddRef((IUnknown
*)This
);
675 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
677 ICOM_THIS_MULTI(VfwPinImpl
, KSP_VT
, iface
);
679 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface
, This
);
681 return IUnknown_Release((IUnknown
*)This
);
684 static HRESULT WINAPI
685 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
686 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
689 FIXME("%p: stub\n", iface
);
693 static HRESULT WINAPI
694 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
695 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
696 DWORD cbPropData
, DWORD
*pcbReturned
)
702 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
703 return E_PROP_SET_UNSUPPORTED
;
704 if (pPropData
== NULL
&& pcbReturned
== NULL
)
707 *pcbReturned
= sizeof(GUID
);
708 if (pPropData
== NULL
)
710 if (cbPropData
< sizeof(GUID
))
713 *pGuid
= PIN_CATEGORY_PREVIEW
;
714 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
718 static HRESULT WINAPI
719 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
720 DWORD dwPropID
, DWORD
*pTypeSupport
)
722 FIXME("%p: stub\n", iface
);
726 static const IKsPropertySetVtbl KSP_VTable
=
737 VfwPin_Construct( IBaseFilter
* pBaseFilter
, LPCRITICAL_SECTION pCritSec
,
740 static const WCHAR wszOutputPinName
[] = { 'O','u','t','p','u','t',0 };
741 ALLOCATOR_PROPERTIES ap
;
742 VfwPinImpl
* pPinImpl
;
746 pPinImpl
= CoTaskMemAlloc( sizeof(*pPinImpl
) );
748 return E_OUTOFMEMORY
;
750 /* What we put here doesn't matter, the
751 driver function should override it then commit */
753 ap
.cbBuffer
= 230400;
757 piOutput
.dir
= PINDIR_OUTPUT
;
758 piOutput
.pFilter
= pBaseFilter
;
759 lstrcpyW(piOutput
.achName
, wszOutputPinName
);
760 ObjectRefCount(TRUE
);
762 hr
= OutputPin_Init(&piOutput
, &ap
, pBaseFilter
, NULL
, pCritSec
, &pPinImpl
->pin
);
765 pPinImpl
->KSP_VT
= &KSP_VTable
;
766 pPinImpl
->pin
.pin
.lpVtbl
= &VfwPin_Vtbl
;
767 *ppPin
= (IPin
*)(&pPinImpl
->pin
.pin
.lpVtbl
);
773 static HRESULT WINAPI
VfwPin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
775 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
777 TRACE("%s %p\n", debugstr_guid(riid
), ppv
);
780 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPin
))
782 else if (IsEqualIID(riid
, &IID_IKsPropertySet
))
783 *ppv
= (LPVOID
)&(This
->KSP_VT
);
787 IUnknown_AddRef((IUnknown
*)(*ppv
));
791 FIXME("No interface for %s!\n", debugstr_guid(riid
));
792 return E_NOINTERFACE
;
795 static ULONG WINAPI
VfwPin_AddRef(IPin
* iface
)
797 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
798 ULONG refCount
= InterlockedIncrement(&This
->pin
.pin
.refCount
);
800 TRACE("() -> new refcount: %u\n", refCount
);
806 VfwPin_Release(IPin
* iface
)
808 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
809 ULONG refCount
= InterlockedDecrement(&This
->pin
.pin
.refCount
);
811 TRACE("() -> new refcount: %u\n", refCount
);
816 ObjectRefCount(FALSE
);
821 static HRESULT WINAPI
822 VfwPin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
824 ENUMMEDIADETAILS emd
;
828 VfwPinImpl
*This
= (VfwPinImpl
*)iface
;
830 hr
= qcap_driver_get_format(This
->driver_info
, &pmt
);
831 emd
.pMediaTypes
= pmt
;
833 hr
= IEnumMediaTypesImpl_Construct(&emd
, ppEnum
);
834 TRACE("%p -- %x\n", This
, hr
);
835 DeleteMediaType(pmt
);
839 static HRESULT WINAPI
840 VfwPin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
842 TRACE("(%p)->(%p, %p)\n", iface
, apPin
, cPin
);
846 static HRESULT WINAPI
VfwPin_EndOfStream(IPin
* iface
)
852 static HRESULT WINAPI
VfwPin_BeginFlush(IPin
* iface
)
854 TRACE("(%p)->()\n", iface
);
858 static HRESULT WINAPI
VfwPin_EndFlush(IPin
* iface
)
860 TRACE("(%p)->()\n", iface
);
864 static HRESULT WINAPI
865 VfwPin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
,
866 REFERENCE_TIME tStop
, double dRate
)
868 TRACE("(%p)->(%s, %s, %e)\n", iface
, wine_dbgstr_longlong(tStart
),
869 wine_dbgstr_longlong(tStop
), dRate
);
873 static const IPinVtbl VfwPin_Vtbl
=
875 VfwPin_QueryInterface
,
879 OutputPin_ReceiveConnection
,
880 OutputPin_Disconnect
,
881 IPinImpl_ConnectedTo
,
882 IPinImpl_ConnectionMediaType
,
883 IPinImpl_QueryPinInfo
,
884 IPinImpl_QueryDirection
,
886 IPinImpl_QueryAccept
,
887 VfwPin_EnumMediaTypes
,
888 VfwPin_QueryInternalConnections
,