stash
[wine/wine64.git] / dlls / qcap / vfwcapture.c
blobcfb9487c787de17d3b44dad383700ce8cc2a7aef
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
23 #define COBJMACROS
25 #include "config.h"
26 #include <stdarg.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wtypes.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "dshow.h"
35 #include "qcap_main.h"
36 #include "wine/debug.h"
38 #include "pin.h"
39 #include "capture.h"
40 #include "uuids.h"
41 #include "vfwmsgs.h"
42 #include "amvideo.h"
43 #include "strmif.h"
44 #include "ddraw.h"
45 #include "ocidl.h"
46 #include "oleauto.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;
68 BOOL init;
69 Capture *driver_info;
70 LONG refCount;
71 FILTER_INFO filterInfo;
72 FILTER_STATE state;
73 CRITICAL_SECTION csFilter;
75 IPin * pOutputPin;
76 } VfwCapture;
78 /* VfwPin implementation */
79 typedef struct VfwPinImpl
81 OutputPin pin;
82 Capture *driver_info;
83 VfwCapture *parent;
84 const IKsPropertySetVtbl * KSP_VT;
85 } VfwPinImpl;
88 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
90 VfwCapture *pVfwCapture;
91 HRESULT hr;
93 TRACE("%p - %p\n", pUnkOuter, phr);
95 *phr = CLASS_E_NOAGGREGATION;
96 if (pUnkOuter)
97 return NULL;
98 *phr = E_OUTOFMEMORY;
100 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
102 if (!pVfwCapture)
103 return NULL;
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);
118 if (FAILED(hr))
120 CoTaskMemFree(pVfwCapture);
121 return NULL;
123 TRACE("-- created at %p\n", pVfwCapture);
125 ObjectRefCount(TRUE);
126 *phr = S_OK;
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);
134 *ppv = NULL;
136 if (IsEqualIID(riid, &IID_IUnknown) ||
137 IsEqualIID(riid, &IID_IPersist) ||
138 IsEqualIID(riid, &IID_IMediaFilter) ||
139 IsEqualIID(riid, &IID_IBaseFilter))
141 *ppv = This;
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) &&
153 !This->init)
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");
161 return E_UNEXPECTED;
163 This->init = TRUE;
166 if (*ppv)
168 TRACE("Returning %s interface\n", debugstr_guid(riid));
169 IUnknown_AddRef((IUnknown *)(*ppv));
170 return S_OK;
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);
184 return 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);
194 if (!refCount)
196 IPinImpl *pin;
198 TRACE("destroying everything\n");
199 if (This->init)
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);
214 This->lpVtbl = NULL;
215 CoTaskMemFree(This);
216 ObjectRefCount(FALSE);
218 return refCount;
221 /** IPersist methods **/
223 static HRESULT WINAPI VfwCapture_GetClassID(IBaseFilter * iface, CLSID * pClsid)
225 TRACE("(%p)\n", pClsid);
226 *pClsid = CLSID_VfwCapture;
227 return S_OK;
230 /** IMediaFilter methods **/
232 static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
234 VfwCapture *This = (VfwCapture *)iface;
236 TRACE("()\n");
237 return qcap_driver_stop(This->driver_info, &This->state);
240 static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
242 VfwCapture *This = (VfwCapture *)iface;
244 TRACE("()\n");
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;
264 return S_OK;
267 static HRESULT WINAPI
268 VfwCapture_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
270 TRACE("(%p)\n", pClock);
272 return S_OK;
275 static HRESULT WINAPI
276 VfwCapture_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
278 TRACE("(%p)\n", ppClock);
280 return S_OK;
283 /** IBaseFilter methods **/
285 static HRESULT WINAPI
286 VfwCapture_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
288 ENUMPINDETAILS epd;
289 VfwCapture *This = (VfwCapture *)iface;
291 TRACE("(%p)\n", ppEnum);
293 epd.cPins = 1;
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);
301 return E_NOTIMPL;
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;
313 if (pInfo->pGraph)
314 IFilterGraph_AddRef(pInfo->pGraph);
315 return S_OK;
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));
325 if (pName)
326 lstrcpyW(This->filterInfo.achName, pName);
327 else
328 *This->filterInfo.achName = 0;
329 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
331 return S_OK;
334 static HRESULT WINAPI
335 VfwCapture_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
337 FIXME("(%p) - stub\n", pVendorInfo);
338 return E_NOTIMPL;
341 static const IBaseFilterVtbl VfwCapture_Vtbl =
343 VfwCapture_QueryInterface,
344 VfwCapture_AddRef,
345 VfwCapture_Release,
346 VfwCapture_GetClassID,
347 VfwCapture_Stop,
348 VfwCapture_Pause,
349 VfwCapture_Run,
350 VfwCapture_GetState,
351 VfwCapture_SetSyncSource,
352 VfwCapture_GetSyncSource,
353 VfwCapture_EnumPins,
354 VfwCapture_FindPin,
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);
372 *ppv = iface;
373 return S_OK;
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)
399 HRESULT hr;
400 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
401 IPinImpl *pin;
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;
411 if (!pmt)
413 TRACE("pmt is NULL\n");
414 return E_POINTER;
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);
424 if (hr == S_FALSE)
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);
432 if (SUCCEEDED(hr))
433 TRACE("Reconnection completed, with new media format..\n");
435 TRACE("Returning: %d\n", hr);
436 return 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,
450 int *piSize )
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,
477 LPVOID * ppv )
479 if (IsEqualIID(riid, &IID_IUnknown) ||
480 IsEqualIID(riid, &IID_IAMVideoProcAmp))
482 *ppv = iface;
483 IAMVideoProcAmp_AddRef( iface );
484 return S_OK;
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,
517 long Flags )
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,
526 long *Flags )
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,
539 AMVideoProcAmp_Set,
540 AMVideoProcAmp_Get,
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);
551 *ppv = iface;
552 return S_OK;
554 if (IsEqualIID(riid, &IID_IBaseFilter))
556 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
557 IPersistPropertyBag_AddRef(iface);
558 *ppv = iface;
559 return S_OK;
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);
591 return E_NOTIMPL;
594 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
596 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
598 FIXME("%p - stub\n", This);
600 return E_NOTIMPL;
603 static HRESULT WINAPI
604 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
605 IErrorLog *pErrorLog )
607 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
608 HRESULT hr;
609 VARIANT var;
610 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
612 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
614 V_VT(&var) = VT_I4;
615 hr = IPropertyBag_Read(pPropBag, (LPCOLESTR)VFWIndex, &var, pErrorLog);
617 if (SUCCEEDED(hr))
619 VfwPinImpl *pin;
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;
627 pin->parent = This;
628 This->init = TRUE;
629 hr = S_OK;
631 else
632 hr = E_FAIL;
635 return hr;
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);
644 return E_NOTIMPL;
647 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
649 PPB_QueryInterface,
650 PPB_AddRef,
651 PPB_Release,
652 PPB_GetClassID,
653 PPB_InitNew,
654 PPB_Load,
655 PPB_Save
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))
665 *ppv = (LPVOID)iface;
666 IKsPropertySet_AddRef( iface );
667 return S_OK;
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,
695 DWORD cbPropData )
697 FIXME("%p: stub\n", iface);
698 return E_NOTIMPL;
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 )
706 LPGUID pGuid;
708 TRACE("()\n");
710 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
711 return E_PROP_SET_UNSUPPORTED;
712 if (pPropData == NULL && pcbReturned == NULL)
713 return E_POINTER;
714 if (pcbReturned)
715 *pcbReturned = sizeof(GUID);
716 if (pPropData == NULL)
717 return S_OK;
718 if (cbPropData < sizeof(GUID))
719 return E_UNEXPECTED;
720 pGuid = pPropData;
721 *pGuid = PIN_CATEGORY_PREVIEW;
722 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
723 return S_OK;
726 static HRESULT WINAPI
727 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
728 DWORD dwPropID, DWORD *pTypeSupport )
730 FIXME("%p: stub\n", iface);
731 return E_NOTIMPL;
734 static const IKsPropertySetVtbl KSP_VTable =
736 KSP_QueryInterface,
737 KSP_AddRef,
738 KSP_Release,
739 KSP_Set,
740 KSP_Get,
741 KSP_QuerySupported
744 static HRESULT
745 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
746 IPin ** ppPin )
748 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
749 ALLOCATOR_PROPERTIES ap;
750 VfwPinImpl * pPinImpl;
751 PIN_INFO piOutput;
752 HRESULT hr;
754 pPinImpl = CoTaskMemAlloc( sizeof(*pPinImpl) );
755 if (!pPinImpl)
756 return E_OUTOFMEMORY;
758 /* What we put here doesn't matter, the
759 driver function should override it then commit */
760 ap.cBuffers = 3;
761 ap.cbBuffer = 230400;
762 ap.cbAlign = 1;
763 ap.cbPrefix = 0;
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);
771 if (SUCCEEDED(hr))
773 pPinImpl->KSP_VT = &KSP_VTable;
774 pPinImpl->pin.pin.lpVtbl = &VfwPin_Vtbl;
775 *ppPin = (IPin *)(&pPinImpl->pin.pin.lpVtbl);
776 return S_OK;
779 CoTaskMemFree(pPinImpl);
780 return E_FAIL;
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);
789 *ppv = NULL;
790 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
791 *ppv = (LPVOID)This;
792 else if (IsEqualIID(riid, &IID_IKsPropertySet))
793 *ppv = (LPVOID)&(This->KSP_VT);
794 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
795 return IUnknown_QueryInterface((IUnknown *)This->parent, riid, ppv);
797 if (*ppv)
799 IUnknown_AddRef((IUnknown *)(*ppv));
800 return S_OK;
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);
814 return refCount;
817 static ULONG WINAPI
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);
825 if (!refCount)
827 CoTaskMemFree(This);
828 ObjectRefCount(FALSE);
830 return refCount;
833 static HRESULT WINAPI
834 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
836 ENUMMEDIADETAILS emd;
837 AM_MEDIA_TYPE *pmt;
838 HRESULT hr;
840 VfwPinImpl *This = (VfwPinImpl *)iface;
841 emd.cMediaTypes = 1;
842 hr = qcap_driver_get_format(This->driver_info, &pmt);
843 emd.pMediaTypes = pmt;
844 if (SUCCEEDED(hr))
845 hr = IEnumMediaTypesImpl_Construct(&emd, ppEnum);
846 TRACE("%p -- %x\n", This, hr);
847 DeleteMediaType(pmt);
848 return hr;
851 static HRESULT WINAPI
852 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
854 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
855 return E_NOTIMPL;
858 static HRESULT WINAPI VfwPin_EndOfStream(IPin * iface)
860 TRACE("()\n");
861 return E_UNEXPECTED;
864 static HRESULT WINAPI VfwPin_BeginFlush(IPin * iface)
866 TRACE("(%p)->()\n", iface);
867 return E_UNEXPECTED;
870 static HRESULT WINAPI VfwPin_EndFlush(IPin * iface)
872 TRACE("(%p)->()\n", iface);
873 return E_UNEXPECTED;
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);
882 return E_UNEXPECTED;
885 static const IPinVtbl VfwPin_Vtbl =
887 VfwPin_QueryInterface,
888 VfwPin_AddRef,
889 VfwPin_Release,
890 OutputPin_Connect,
891 OutputPin_ReceiveConnection,
892 OutputPin_Disconnect,
893 IPinImpl_ConnectedTo,
894 IPinImpl_ConnectionMediaType,
895 IPinImpl_QueryPinInfo,
896 IPinImpl_QueryDirection,
897 IPinImpl_QueryId,
898 IPinImpl_QueryAccept,
899 VfwPin_EnumMediaTypes,
900 VfwPin_QueryInternalConnections,
901 VfwPin_EndOfStream,
902 VfwPin_BeginFlush,
903 VfwPin_EndFlush,
904 VfwPin_NewSegment