Release 1.3.7.
[wine/gsoc-2012-control.git] / dlls / qcap / vfwcapture.c
blob387a05e46f0fe2437744a6cde93e7cb41f7f20e5
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 "capture.h"
39 #include "uuids.h"
40 #include "vfwmsgs.h"
41 #include "amvideo.h"
42 #include "strmif.h"
43 #include "ddraw.h"
44 #include "ocidl.h"
45 #include "oleauto.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
49 #define ICOM_THIS_MULTI(impl,field,iface) \
50 impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
52 static const IBaseFilterVtbl VfwCapture_Vtbl;
53 static const IAMStreamConfigVtbl IAMStreamConfig_VTable;
54 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable;
55 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable;
56 static const IPinVtbl VfwPin_Vtbl;
58 static HRESULT VfwPin_Construct( IBaseFilter *, LPCRITICAL_SECTION, IPin ** );
60 typedef struct VfwCapture
62 BaseFilter filter;
63 const IAMStreamConfigVtbl * IAMStreamConfig_vtbl;
64 const IAMVideoProcAmpVtbl * IAMVideoProcAmp_vtbl;
65 const IPersistPropertyBagVtbl * IPersistPropertyBag_vtbl;
67 BOOL init;
68 Capture *driver_info;
70 IPin * pOutputPin;
71 } VfwCapture;
73 /* VfwPin implementation */
74 typedef struct VfwPinImpl
76 BaseOutputPin pin;
77 Capture *driver_info;
78 VfwCapture *parent;
79 const IKsPropertySetVtbl * KSP_VT;
80 } VfwPinImpl;
82 static IPin* WINAPI VfwCapture_GetPin(BaseFilter *iface, int pos)
84 VfwCapture *This = (VfwCapture *)iface;
86 if (pos >= 1 || pos < 0)
87 return NULL;
89 IPin_AddRef(This->pOutputPin);
90 return This->pOutputPin;
93 static LONG WINAPI VfwCapture_GetPinCount(BaseFilter *iface)
95 return 1;
98 static const BaseFilterFuncTable BaseFuncTable = {
99 VfwCapture_GetPin,
100 VfwCapture_GetPinCount
103 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
105 VfwCapture *pVfwCapture;
106 HRESULT hr;
108 TRACE("%p - %p\n", pUnkOuter, phr);
110 *phr = CLASS_E_NOAGGREGATION;
111 if (pUnkOuter)
112 return NULL;
113 *phr = E_OUTOFMEMORY;
115 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
117 if (!pVfwCapture)
118 return NULL;
120 BaseFilter_Init(&pVfwCapture->filter, &VfwCapture_Vtbl, &CLSID_VfwCapture, (DWORD_PTR)(__FILE__ ": VfwCapture.csFilter"), &BaseFuncTable);
122 pVfwCapture->IAMStreamConfig_vtbl = &IAMStreamConfig_VTable;
123 pVfwCapture->IAMVideoProcAmp_vtbl = &IAMVideoProcAmp_VTable;
124 pVfwCapture->IPersistPropertyBag_vtbl = &IPersistPropertyBag_VTable;
125 pVfwCapture->init = FALSE;
127 hr = VfwPin_Construct((IBaseFilter *)&pVfwCapture->filter.lpVtbl,
128 &pVfwCapture->filter.csFilter, &pVfwCapture->pOutputPin);
129 if (FAILED(hr))
131 CoTaskMemFree(pVfwCapture);
132 return NULL;
134 TRACE("-- created at %p\n", pVfwCapture);
136 ObjectRefCount(TRUE);
137 *phr = S_OK;
138 return (IUnknown *)pVfwCapture;
141 static HRESULT WINAPI VfwCapture_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
143 VfwCapture *This = (VfwCapture *)iface;
144 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
145 *ppv = NULL;
147 if (IsEqualIID(riid, &IID_IUnknown) ||
148 IsEqualIID(riid, &IID_IPersist) ||
149 IsEqualIID(riid, &IID_IMediaFilter) ||
150 IsEqualIID(riid, &IID_IBaseFilter))
152 *ppv = This;
154 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
155 *ppv = &(This->IAMStreamConfig_vtbl);
156 else if (IsEqualIID(riid, &IID_IAMVideoProcAmp))
157 *ppv = &(This->IAMVideoProcAmp_vtbl);
158 else if (IsEqualIID(riid, &IID_IPersistPropertyBag))
159 *ppv = &(This->IPersistPropertyBag_vtbl);
161 if (!IsEqualIID(riid, &IID_IUnknown) &&
162 !IsEqualIID(riid, &IID_IPersist) &&
163 !IsEqualIID(riid, &IID_IPersistPropertyBag) &&
164 !This->init)
166 FIXME("Capture system not initialised when looking for %s, "
167 "trying it on primary device now\n", debugstr_guid(riid));
168 This->driver_info = qcap_driver_init( This->pOutputPin, 0 );
169 if (!This->driver_info)
171 ERR("VfwCapture initialisation failed\n");
172 return E_UNEXPECTED;
174 This->init = TRUE;
177 if (*ppv)
179 TRACE("Returning %s interface\n", debugstr_guid(riid));
180 IUnknown_AddRef((IUnknown *)(*ppv));
181 return S_OK;
184 FIXME("No interface for %s!\n", debugstr_guid(riid));
185 return E_NOINTERFACE;
188 static ULONG WINAPI VfwCapture_Release(IBaseFilter * iface)
190 VfwCapture *This = (VfwCapture *)iface;
191 ULONG refCount = BaseFilterImpl_Release(iface);
193 TRACE("%p->() New refcount: %d\n", This, refCount);
195 if (!refCount)
197 BasePin *pin;
199 TRACE("destroying everything\n");
200 if (This->init)
202 if (This->filter.state != State_Stopped)
203 qcap_driver_stop(This->driver_info, &This->filter.state);
204 qcap_driver_destroy(This->driver_info);
206 pin = (BasePin*) This->pOutputPin;
207 if (pin->pConnectedTo != NULL)
209 IPin_Disconnect(pin->pConnectedTo);
210 IPin_Disconnect(This->pOutputPin);
212 IPin_Release(This->pOutputPin);
213 CoTaskMemFree(This);
214 ObjectRefCount(FALSE);
216 return refCount;
219 /** IMediaFilter methods **/
221 static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
223 VfwCapture *This = (VfwCapture *)iface;
225 TRACE("()\n");
226 return qcap_driver_stop(This->driver_info, &This->filter.state);
229 static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
231 VfwCapture *This = (VfwCapture *)iface;
233 TRACE("()\n");
234 return qcap_driver_pause(This->driver_info, &This->filter.state);
237 static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
239 VfwCapture *This = (VfwCapture *)iface;
240 TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
241 return qcap_driver_run(This->driver_info, &This->filter.state);
244 /** IBaseFilter methods **/
245 static HRESULT WINAPI VfwCapture_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
247 FIXME("(%s, %p) - stub\n", debugstr_w(Id), ppPin);
248 return E_NOTIMPL;
251 static const IBaseFilterVtbl VfwCapture_Vtbl =
253 VfwCapture_QueryInterface,
254 BaseFilterImpl_AddRef,
255 VfwCapture_Release,
256 BaseFilterImpl_GetClassID,
257 VfwCapture_Stop,
258 VfwCapture_Pause,
259 VfwCapture_Run,
260 BaseFilterImpl_GetState,
261 BaseFilterImpl_SetSyncSource,
262 BaseFilterImpl_GetSyncSource,
263 BaseFilterImpl_EnumPins,
264 VfwCapture_FindPin,
265 BaseFilterImpl_QueryFilterInfo,
266 BaseFilterImpl_JoinFilterGraph,
267 BaseFilterImpl_QueryVendorInfo
270 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
271 static HRESULT WINAPI
272 AMStreamConfig_QueryInterface( IAMStreamConfig * iface, REFIID riid, LPVOID * ppv )
274 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
276 TRACE("%p --> %s\n", This, debugstr_guid(riid));
278 if (IsEqualIID(riid, &IID_IUnknown) ||
279 IsEqualIID(riid, &IID_IAMStreamConfig))
281 IAMStreamConfig_AddRef(iface);
282 *ppv = iface;
283 return S_OK;
286 FIXME("No interface for iid %s\n", debugstr_guid(riid));
287 return E_NOINTERFACE;
290 static ULONG WINAPI AMStreamConfig_AddRef( IAMStreamConfig * iface )
292 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
294 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
295 return IUnknown_AddRef((IUnknown *)This);
298 static ULONG WINAPI AMStreamConfig_Release( IAMStreamConfig * iface )
300 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
302 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
303 return IUnknown_Release((IUnknown *)This);
306 static HRESULT WINAPI
307 AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
309 HRESULT hr;
310 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
311 BasePin *pin;
313 TRACE("(%p): %p->%p\n", iface, pmt, pmt ? pmt->pbFormat : NULL);
315 if (This->filter.state != State_Stopped)
317 TRACE("Returning not stopped error\n");
318 return VFW_E_NOT_STOPPED;
321 if (!pmt)
323 TRACE("pmt is NULL\n");
324 return E_POINTER;
327 dump_AM_MEDIA_TYPE(pmt);
329 pin = (BasePin *)This->pOutputPin;
330 if (pin->pConnectedTo != NULL)
332 hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
333 TRACE("Would accept: %d\n", hr);
334 if (hr == S_FALSE)
335 return VFW_E_INVALIDMEDIATYPE;
338 hr = qcap_driver_set_format(This->driver_info, pmt);
339 if (SUCCEEDED(hr) && This->filter.filterInfo.pGraph && pin->pConnectedTo )
341 hr = IFilterGraph_Reconnect(This->filter.filterInfo.pGraph, This->pOutputPin);
342 if (SUCCEEDED(hr))
343 TRACE("Reconnection completed, with new media format..\n");
345 TRACE("Returning: %d\n", hr);
346 return hr;
349 static HRESULT WINAPI
350 AMStreamConfig_GetFormat( IAMStreamConfig *iface, AM_MEDIA_TYPE **pmt )
352 ICOM_THIS_MULTI(VfwCapture, IAMStreamConfig_vtbl, iface);
354 TRACE("%p -> (%p)\n", iface, pmt);
355 return qcap_driver_get_format(This->driver_info, pmt);
358 static HRESULT WINAPI
359 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig *iface, int *piCount,
360 int *piSize )
362 FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
363 return E_NOTIMPL; /* Not implemented for this interface */
366 static HRESULT WINAPI
367 AMStreamConfig_GetStreamCaps( IAMStreamConfig *iface, int iIndex,
368 AM_MEDIA_TYPE **pmt, BYTE *pSCC )
370 FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
371 return E_NOTIMPL; /* Not implemented for this interface */
374 static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
376 AMStreamConfig_QueryInterface,
377 AMStreamConfig_AddRef,
378 AMStreamConfig_Release,
379 AMStreamConfig_SetFormat,
380 AMStreamConfig_GetFormat,
381 AMStreamConfig_GetNumberOfCapabilities,
382 AMStreamConfig_GetStreamCaps
385 static HRESULT WINAPI
386 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp * iface, REFIID riid,
387 LPVOID * ppv )
389 if (IsEqualIID(riid, &IID_IUnknown) ||
390 IsEqualIID(riid, &IID_IAMVideoProcAmp))
392 *ppv = iface;
393 IAMVideoProcAmp_AddRef( iface );
394 return S_OK;
397 FIXME("No interface for iid %s\n", debugstr_guid(riid));
398 return E_NOINTERFACE;
401 static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
403 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
405 return IUnknown_AddRef((IUnknown *)This);
408 static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
410 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
412 return IUnknown_Release((IUnknown *)This);
415 static HRESULT WINAPI
416 AMVideoProcAmp_GetRange( IAMVideoProcAmp * iface, LONG Property, LONG *pMin,
417 LONG *pMax, LONG *pSteppingDelta, LONG *pDefault, LONG *pCapsFlags )
419 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
421 return qcap_driver_get_prop_range( This->driver_info, Property, pMin, pMax,
422 pSteppingDelta, pDefault, pCapsFlags );
425 static HRESULT WINAPI
426 AMVideoProcAmp_Set( IAMVideoProcAmp * iface, LONG Property, LONG lValue,
427 LONG Flags )
429 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
431 return qcap_driver_set_prop(This->driver_info, Property, lValue, Flags);
434 static HRESULT WINAPI
435 AMVideoProcAmp_Get( IAMVideoProcAmp * iface, LONG Property, LONG *lValue,
436 LONG *Flags )
438 ICOM_THIS_MULTI(VfwCapture, IAMVideoProcAmp_vtbl, iface);
440 return qcap_driver_get_prop(This->driver_info, Property, lValue, Flags);
443 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
445 AMVideoProcAmp_QueryInterface,
446 AMVideoProcAmp_AddRef,
447 AMVideoProcAmp_Release,
448 AMVideoProcAmp_GetRange,
449 AMVideoProcAmp_Set,
450 AMVideoProcAmp_Get,
453 static HRESULT WINAPI
454 PPB_QueryInterface( IPersistPropertyBag * iface, REFIID riid, LPVOID * ppv )
456 if (IsEqualIID(riid, &IID_IUnknown) ||
457 IsEqualIID(riid, &IID_IPersist) ||
458 IsEqualIID(riid, &IID_IPersistPropertyBag))
460 IPersistPropertyBag_AddRef(iface);
461 *ppv = iface;
462 return S_OK;
464 if (IsEqualIID(riid, &IID_IBaseFilter))
466 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
467 IPersistPropertyBag_AddRef(iface);
468 *ppv = iface;
469 return S_OK;
472 FIXME("No interface for iid %s\n", debugstr_guid(riid));
473 return E_NOINTERFACE;
476 static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
478 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
480 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
482 return IUnknown_AddRef((IUnknown *)This);
485 static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
487 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
489 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
491 return IUnknown_Release((IUnknown *)This);
494 static HRESULT WINAPI
495 PPB_GetClassID( IPersistPropertyBag * iface, CLSID * pClassID )
497 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
499 FIXME("%p - stub\n", This);
501 return E_NOTIMPL;
504 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
506 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
508 FIXME("%p - stub\n", This);
510 return E_NOTIMPL;
513 static HRESULT WINAPI
514 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
515 IErrorLog *pErrorLog )
517 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
518 HRESULT hr;
519 VARIANT var;
520 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
522 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
524 V_VT(&var) = VT_I4;
525 hr = IPropertyBag_Read(pPropBag, VFWIndex, &var, pErrorLog);
527 if (SUCCEEDED(hr))
529 VfwPinImpl *pin;
531 This->driver_info = qcap_driver_init( This->pOutputPin,
532 var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal );
533 if (This->driver_info)
535 pin = (VfwPinImpl *)This->pOutputPin;
536 pin->driver_info = This->driver_info;
537 pin->parent = This;
538 This->init = TRUE;
539 hr = S_OK;
541 else
542 hr = E_FAIL;
545 return hr;
548 static HRESULT WINAPI
549 PPB_Save( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
550 BOOL fClearDirty, BOOL fSaveAllProperties )
552 ICOM_THIS_MULTI(VfwCapture, IPersistPropertyBag_vtbl, iface);
553 FIXME("%p - stub\n", This);
554 return E_NOTIMPL;
557 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
559 PPB_QueryInterface,
560 PPB_AddRef,
561 PPB_Release,
562 PPB_GetClassID,
563 PPB_InitNew,
564 PPB_Load,
565 PPB_Save
568 /* IKsPropertySet interface */
569 static HRESULT WINAPI
570 KSP_QueryInterface( IKsPropertySet * iface, REFIID riid, LPVOID * ppv )
572 if (IsEqualIID(riid, &IID_IUnknown) ||
573 IsEqualIID(riid, &IID_IKsPropertySet))
575 *ppv = iface;
576 IKsPropertySet_AddRef( iface );
577 return S_OK;
580 FIXME("No interface for iid %s\n", debugstr_guid(riid));
581 return E_NOINTERFACE;
584 static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
586 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
588 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
590 return IUnknown_AddRef((IUnknown *)This);
593 static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
595 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
597 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
599 return IUnknown_Release((IUnknown *)This);
602 static HRESULT WINAPI
603 KSP_Set( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
604 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
605 DWORD cbPropData )
607 FIXME("%p: stub\n", iface);
608 return E_NOTIMPL;
611 static HRESULT WINAPI
612 KSP_Get( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
613 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
614 DWORD cbPropData, DWORD *pcbReturned )
616 LPGUID pGuid;
618 TRACE("()\n");
620 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
621 return E_PROP_SET_UNSUPPORTED;
622 if (pPropData == NULL && pcbReturned == NULL)
623 return E_POINTER;
624 if (pcbReturned)
625 *pcbReturned = sizeof(GUID);
626 if (pPropData == NULL)
627 return S_OK;
628 if (cbPropData < sizeof(GUID))
629 return E_UNEXPECTED;
630 pGuid = pPropData;
631 *pGuid = PIN_CATEGORY_PREVIEW;
632 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
633 return S_OK;
636 static HRESULT WINAPI
637 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
638 DWORD dwPropID, DWORD *pTypeSupport )
640 FIXME("%p: stub\n", iface);
641 return E_NOTIMPL;
644 static const IKsPropertySetVtbl KSP_VTable =
646 KSP_QueryInterface,
647 KSP_AddRef,
648 KSP_Release,
649 KSP_Set,
650 KSP_Get,
651 KSP_QuerySupported
654 static HRESULT WINAPI VfwPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
656 VfwPinImpl *This = (VfwPinImpl *)iface;
657 AM_MEDIA_TYPE *vfw_pmt;
658 HRESULT hr;
660 if (iPosition < 0)
661 return E_INVALIDARG;
662 if (iPosition > 0)
663 return VFW_S_NO_MORE_ITEMS;
665 hr = qcap_driver_get_format(This->driver_info, &vfw_pmt);
666 CopyMediaType(pmt, vfw_pmt);
667 DeleteMediaType(vfw_pmt);
669 return hr;
672 LONG WINAPI VfwPin_GetMediaTypeVersion(BasePin *iface)
674 return 1;
677 static HRESULT WINAPI VfwPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
679 ALLOCATOR_PROPERTIES actual;
681 /* What we put here doesn't matter, the
682 driver function should override it then commit */
683 if (!ppropInputRequest->cBuffers)
684 ppropInputRequest->cBuffers = 3;
685 if (!ppropInputRequest->cbBuffer)
686 ppropInputRequest->cbBuffer = 230400;
687 if (!ppropInputRequest->cbAlign)
688 ppropInputRequest->cbAlign = 1;
690 return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
693 static const BasePinFuncTable output_BaseFuncTable = {
694 NULL,
695 BaseOutputPinImpl_AttemptConnection,
696 VfwPin_GetMediaTypeVersion,
697 VfwPin_GetMediaType
700 static const BaseOutputPinFuncTable output_BaseOutputFuncTable = {
701 VfwPin_DecideBufferSize,
702 BaseOutputPinImpl_DecideAllocator,
703 BaseOutputPinImpl_BreakConnect
706 static HRESULT
707 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
708 IPin ** ppPin )
710 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
711 PIN_INFO piOutput;
712 HRESULT hr;
714 ppPin = NULL;
716 piOutput.dir = PINDIR_OUTPUT;
717 piOutput.pFilter = pBaseFilter;
718 lstrcpyW(piOutput.achName, wszOutputPinName);
719 ObjectRefCount(TRUE);
721 hr = BaseOutputPin_Construct(&VfwPin_Vtbl, sizeof(VfwPinImpl), &piOutput, &output_BaseFuncTable, &output_BaseOutputFuncTable, pCritSec, ppPin);
723 if (SUCCEEDED(hr))
725 VfwPinImpl *pPinImpl = (VfwPinImpl*)*ppPin;
726 pPinImpl->KSP_VT = &KSP_VTable;
729 return hr;
732 static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
734 VfwPinImpl *This = (VfwPinImpl *)iface;
736 TRACE("%s %p\n", debugstr_guid(riid), ppv);
738 *ppv = NULL;
739 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
740 *ppv = This;
741 else if (IsEqualIID(riid, &IID_IKsPropertySet))
742 *ppv = &(This->KSP_VT);
743 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
744 return IUnknown_QueryInterface((IUnknown *)This->parent, riid, ppv);
746 if (*ppv)
748 IUnknown_AddRef((IUnknown *)(*ppv));
749 return S_OK;
752 FIXME("No interface for %s!\n", debugstr_guid(riid));
753 return E_NOINTERFACE;
756 static ULONG WINAPI
757 VfwPin_Release(IPin * iface)
759 VfwPinImpl *This = (VfwPinImpl *)iface;
760 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
762 TRACE("() -> new refcount: %u\n", refCount);
764 if (!refCount)
766 CoTaskMemFree(This);
767 ObjectRefCount(FALSE);
769 return refCount;
772 static HRESULT WINAPI
773 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
775 AM_MEDIA_TYPE *pmt;
776 HRESULT hr;
778 VfwPinImpl *This = (VfwPinImpl *)iface;
779 hr = qcap_driver_get_format(This->driver_info, &pmt);
780 if (SUCCEEDED(hr))
781 hr = BasePinImpl_EnumMediaTypes(iface, ppEnum);
782 TRACE("%p -- %x\n", This, hr);
783 DeleteMediaType(pmt);
785 return hr;
788 static HRESULT WINAPI
789 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
791 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
792 return E_NOTIMPL;
795 static const IPinVtbl VfwPin_Vtbl =
797 VfwPin_QueryInterface,
798 BasePinImpl_AddRef,
799 VfwPin_Release,
800 BaseOutputPinImpl_Connect,
801 BaseOutputPinImpl_ReceiveConnection,
802 BaseOutputPinImpl_Disconnect,
803 BasePinImpl_ConnectedTo,
804 BasePinImpl_ConnectionMediaType,
805 BasePinImpl_QueryPinInfo,
806 BasePinImpl_QueryDirection,
807 BasePinImpl_QueryId,
808 BasePinImpl_QueryAccept,
809 VfwPin_EnumMediaTypes,
810 VfwPin_QueryInternalConnections,
811 BaseOutputPinImpl_EndOfStream,
812 BaseOutputPinImpl_BeginFlush,
813 BaseOutputPinImpl_EndFlush,
814 BasePinImpl_NewSegment