d3dx9_30: Add stub for D3DXCpuOptimizations.
[wine.git] / dlls / qcap / vfwcapture.c
blob2551534569683cd4d8eaf82642cb610f54e14d61
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 IAMStreamConfig IAMStreamConfig_iface;
64 IAMVideoProcAmp IAMVideoProcAmp_iface;
65 IPersistPropertyBag IPersistPropertyBag_iface;
67 BOOL init;
68 Capture *driver_info;
70 IPin * pOutputPin;
71 } VfwCapture;
73 static inline VfwCapture *impl_from_IAMStreamConfig(IAMStreamConfig *iface)
75 return CONTAINING_RECORD(iface, VfwCapture, IAMStreamConfig_iface);
78 static inline VfwCapture *impl_from_IAMVideoProcAmp(IAMVideoProcAmp *iface)
80 return CONTAINING_RECORD(iface, VfwCapture, IAMVideoProcAmp_iface);
83 static inline VfwCapture *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface)
85 return CONTAINING_RECORD(iface, VfwCapture, IPersistPropertyBag_iface);
88 /* VfwPin implementation */
89 typedef struct VfwPinImpl
91 BaseOutputPin pin;
92 Capture *driver_info;
93 VfwCapture *parent;
94 const IKsPropertySetVtbl * KSP_VT;
95 } VfwPinImpl;
97 static IPin* WINAPI VfwCapture_GetPin(BaseFilter *iface, int pos)
99 VfwCapture *This = (VfwCapture *)iface;
101 if (pos >= 1 || pos < 0)
102 return NULL;
104 IPin_AddRef(This->pOutputPin);
105 return This->pOutputPin;
108 static LONG WINAPI VfwCapture_GetPinCount(BaseFilter *iface)
110 return 1;
113 static const BaseFilterFuncTable BaseFuncTable = {
114 VfwCapture_GetPin,
115 VfwCapture_GetPinCount
118 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
120 VfwCapture *pVfwCapture;
121 HRESULT hr;
123 TRACE("%p - %p\n", pUnkOuter, phr);
125 *phr = CLASS_E_NOAGGREGATION;
126 if (pUnkOuter)
127 return NULL;
128 *phr = E_OUTOFMEMORY;
130 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
132 if (!pVfwCapture)
133 return NULL;
135 BaseFilter_Init(&pVfwCapture->filter, &VfwCapture_Vtbl, &CLSID_VfwCapture, (DWORD_PTR)(__FILE__ ": VfwCapture.csFilter"), &BaseFuncTable);
137 pVfwCapture->IAMStreamConfig_iface.lpVtbl = &IAMStreamConfig_VTable;
138 pVfwCapture->IAMVideoProcAmp_iface.lpVtbl = &IAMVideoProcAmp_VTable;
139 pVfwCapture->IPersistPropertyBag_iface.lpVtbl = &IPersistPropertyBag_VTable;
140 pVfwCapture->init = FALSE;
142 hr = VfwPin_Construct(&pVfwCapture->filter.IBaseFilter_iface,
143 &pVfwCapture->filter.csFilter, &pVfwCapture->pOutputPin);
144 if (FAILED(hr))
146 CoTaskMemFree(pVfwCapture);
147 return NULL;
149 TRACE("-- created at %p\n", pVfwCapture);
151 ObjectRefCount(TRUE);
152 *phr = S_OK;
153 return (IUnknown *)pVfwCapture;
156 static HRESULT WINAPI VfwCapture_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
158 VfwCapture *This = (VfwCapture *)iface;
159 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
160 *ppv = NULL;
162 if (IsEqualIID(riid, &IID_IUnknown) ||
163 IsEqualIID(riid, &IID_IPersist) ||
164 IsEqualIID(riid, &IID_IMediaFilter) ||
165 IsEqualIID(riid, &IID_IBaseFilter))
167 *ppv = This;
169 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
170 *ppv = &This->IAMStreamConfig_iface;
171 else if (IsEqualIID(riid, &IID_IAMVideoProcAmp))
172 *ppv = &This->IAMVideoProcAmp_iface;
173 else if (IsEqualIID(riid, &IID_IPersistPropertyBag))
174 *ppv = &This->IPersistPropertyBag_iface;
176 if (!IsEqualIID(riid, &IID_IUnknown) &&
177 !IsEqualIID(riid, &IID_IPersist) &&
178 !IsEqualIID(riid, &IID_IPersistPropertyBag) &&
179 !This->init)
181 FIXME("Capture system not initialised when looking for %s, "
182 "trying it on primary device now\n", debugstr_guid(riid));
183 This->driver_info = qcap_driver_init( This->pOutputPin, 0 );
184 if (!This->driver_info)
186 ERR("VfwCapture initialisation failed\n");
187 return E_UNEXPECTED;
189 This->init = TRUE;
192 if (*ppv)
194 TRACE("Returning %s interface\n", debugstr_guid(riid));
195 IUnknown_AddRef((IUnknown *)(*ppv));
196 return S_OK;
199 FIXME("No interface for %s!\n", debugstr_guid(riid));
200 return E_NOINTERFACE;
203 static ULONG WINAPI VfwCapture_Release(IBaseFilter * iface)
205 VfwCapture *This = (VfwCapture *)iface;
206 ULONG refCount = InterlockedDecrement(&This->filter.refCount);
208 TRACE("%p->() New refcount: %d\n", This, refCount);
210 if (!refCount)
212 BasePin *pin;
214 TRACE("destroying everything\n");
215 if (This->init)
217 if (This->filter.state != State_Stopped)
218 qcap_driver_stop(This->driver_info, &This->filter.state);
219 qcap_driver_destroy(This->driver_info);
221 pin = (BasePin*) This->pOutputPin;
222 if (pin->pConnectedTo != NULL)
224 IPin_Disconnect(pin->pConnectedTo);
225 IPin_Disconnect(This->pOutputPin);
227 IPin_Release(This->pOutputPin);
228 BaseFilter_Destroy(&This->filter);
229 CoTaskMemFree(This);
230 ObjectRefCount(FALSE);
232 return refCount;
235 /** IMediaFilter methods **/
237 static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
239 VfwCapture *This = (VfwCapture *)iface;
241 TRACE("()\n");
242 return qcap_driver_stop(This->driver_info, &This->filter.state);
245 static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
247 VfwCapture *This = (VfwCapture *)iface;
249 TRACE("()\n");
250 return qcap_driver_pause(This->driver_info, &This->filter.state);
253 static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
255 VfwCapture *This = (VfwCapture *)iface;
256 TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
257 return qcap_driver_run(This->driver_info, &This->filter.state);
260 /** IBaseFilter methods **/
261 static HRESULT WINAPI VfwCapture_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
263 FIXME("(%s, %p) - stub\n", debugstr_w(Id), ppPin);
264 return E_NOTIMPL;
267 static const IBaseFilterVtbl VfwCapture_Vtbl =
269 VfwCapture_QueryInterface,
270 BaseFilterImpl_AddRef,
271 VfwCapture_Release,
272 BaseFilterImpl_GetClassID,
273 VfwCapture_Stop,
274 VfwCapture_Pause,
275 VfwCapture_Run,
276 BaseFilterImpl_GetState,
277 BaseFilterImpl_SetSyncSource,
278 BaseFilterImpl_GetSyncSource,
279 BaseFilterImpl_EnumPins,
280 VfwCapture_FindPin,
281 BaseFilterImpl_QueryFilterInfo,
282 BaseFilterImpl_JoinFilterGraph,
283 BaseFilterImpl_QueryVendorInfo
286 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
287 static HRESULT WINAPI
288 AMStreamConfig_QueryInterface( IAMStreamConfig * iface, REFIID riid, LPVOID * ppv )
290 VfwCapture *This = impl_from_IAMStreamConfig(iface);
292 TRACE("%p --> %s\n", This, debugstr_guid(riid));
294 if (IsEqualIID(riid, &IID_IUnknown) ||
295 IsEqualIID(riid, &IID_IAMStreamConfig))
297 IAMStreamConfig_AddRef(iface);
298 *ppv = iface;
299 return S_OK;
302 FIXME("No interface for iid %s\n", debugstr_guid(riid));
303 return E_NOINTERFACE;
306 static ULONG WINAPI AMStreamConfig_AddRef( IAMStreamConfig * iface )
308 VfwCapture *This = impl_from_IAMStreamConfig(iface);
310 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
311 return IUnknown_AddRef((IUnknown *)This);
314 static ULONG WINAPI AMStreamConfig_Release( IAMStreamConfig * iface )
316 VfwCapture *This = impl_from_IAMStreamConfig(iface);
318 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
319 return IUnknown_Release((IUnknown *)This);
322 static HRESULT WINAPI
323 AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
325 HRESULT hr;
326 VfwCapture *This = impl_from_IAMStreamConfig(iface);
327 BasePin *pin;
329 TRACE("(%p): %p->%p\n", iface, pmt, pmt ? pmt->pbFormat : NULL);
331 if (This->filter.state != State_Stopped)
333 TRACE("Returning not stopped error\n");
334 return VFW_E_NOT_STOPPED;
337 if (!pmt)
339 TRACE("pmt is NULL\n");
340 return E_POINTER;
343 dump_AM_MEDIA_TYPE(pmt);
345 pin = (BasePin *)This->pOutputPin;
346 if (pin->pConnectedTo != NULL)
348 hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
349 TRACE("Would accept: %d\n", hr);
350 if (hr == S_FALSE)
351 return VFW_E_INVALIDMEDIATYPE;
354 hr = qcap_driver_set_format(This->driver_info, pmt);
355 if (SUCCEEDED(hr) && This->filter.filterInfo.pGraph && pin->pConnectedTo )
357 hr = IFilterGraph_Reconnect(This->filter.filterInfo.pGraph, This->pOutputPin);
358 if (SUCCEEDED(hr))
359 TRACE("Reconnection completed, with new media format..\n");
361 TRACE("Returning: %d\n", hr);
362 return hr;
365 static HRESULT WINAPI
366 AMStreamConfig_GetFormat( IAMStreamConfig *iface, AM_MEDIA_TYPE **pmt )
368 VfwCapture *This = impl_from_IAMStreamConfig(iface);
370 TRACE("%p -> (%p)\n", iface, pmt);
371 return qcap_driver_get_format(This->driver_info, pmt);
374 static HRESULT WINAPI
375 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig *iface, int *piCount,
376 int *piSize )
378 FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
379 return E_NOTIMPL; /* Not implemented for this interface */
382 static HRESULT WINAPI
383 AMStreamConfig_GetStreamCaps( IAMStreamConfig *iface, int iIndex,
384 AM_MEDIA_TYPE **pmt, BYTE *pSCC )
386 FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
387 return E_NOTIMPL; /* Not implemented for this interface */
390 static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
392 AMStreamConfig_QueryInterface,
393 AMStreamConfig_AddRef,
394 AMStreamConfig_Release,
395 AMStreamConfig_SetFormat,
396 AMStreamConfig_GetFormat,
397 AMStreamConfig_GetNumberOfCapabilities,
398 AMStreamConfig_GetStreamCaps
401 static HRESULT WINAPI
402 AMVideoProcAmp_QueryInterface( IAMVideoProcAmp * iface, REFIID riid,
403 LPVOID * ppv )
405 if (IsEqualIID(riid, &IID_IUnknown) ||
406 IsEqualIID(riid, &IID_IAMVideoProcAmp))
408 *ppv = iface;
409 IAMVideoProcAmp_AddRef( iface );
410 return S_OK;
413 FIXME("No interface for iid %s\n", debugstr_guid(riid));
414 return E_NOINTERFACE;
417 static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
419 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
421 return IUnknown_AddRef((IUnknown *)This);
424 static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
426 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
428 return IUnknown_Release((IUnknown *)This);
431 static HRESULT WINAPI
432 AMVideoProcAmp_GetRange( IAMVideoProcAmp * iface, LONG Property, LONG *pMin,
433 LONG *pMax, LONG *pSteppingDelta, LONG *pDefault, LONG *pCapsFlags )
435 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
437 return qcap_driver_get_prop_range( This->driver_info, Property, pMin, pMax,
438 pSteppingDelta, pDefault, pCapsFlags );
441 static HRESULT WINAPI
442 AMVideoProcAmp_Set( IAMVideoProcAmp * iface, LONG Property, LONG lValue,
443 LONG Flags )
445 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
447 return qcap_driver_set_prop(This->driver_info, Property, lValue, Flags);
450 static HRESULT WINAPI
451 AMVideoProcAmp_Get( IAMVideoProcAmp * iface, LONG Property, LONG *lValue,
452 LONG *Flags )
454 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
456 return qcap_driver_get_prop(This->driver_info, Property, lValue, Flags);
459 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
461 AMVideoProcAmp_QueryInterface,
462 AMVideoProcAmp_AddRef,
463 AMVideoProcAmp_Release,
464 AMVideoProcAmp_GetRange,
465 AMVideoProcAmp_Set,
466 AMVideoProcAmp_Get,
469 static HRESULT WINAPI
470 PPB_QueryInterface( IPersistPropertyBag * iface, REFIID riid, LPVOID * ppv )
472 if (IsEqualIID(riid, &IID_IUnknown) ||
473 IsEqualIID(riid, &IID_IPersist) ||
474 IsEqualIID(riid, &IID_IPersistPropertyBag))
476 IPersistPropertyBag_AddRef(iface);
477 *ppv = iface;
478 return S_OK;
480 if (IsEqualIID(riid, &IID_IBaseFilter))
482 /* FIXME: native devenum asks for IBaseFilter, should we return it? */
483 IPersistPropertyBag_AddRef(iface);
484 *ppv = iface;
485 return S_OK;
488 FIXME("No interface for iid %s\n", debugstr_guid(riid));
489 return E_NOINTERFACE;
492 static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
494 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
496 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
498 return IUnknown_AddRef((IUnknown *)This);
501 static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
503 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
505 TRACE("%p --> Forwarding to VfwCapture (%p)\n", iface, This);
507 return IUnknown_Release((IUnknown *)This);
510 static HRESULT WINAPI
511 PPB_GetClassID( IPersistPropertyBag * iface, CLSID * pClassID )
513 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
515 FIXME("%p - stub\n", This);
517 return E_NOTIMPL;
520 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
522 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
524 FIXME("%p - stub\n", This);
526 return E_NOTIMPL;
529 static HRESULT WINAPI
530 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
531 IErrorLog *pErrorLog )
533 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
534 HRESULT hr;
535 VARIANT var;
536 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
538 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
540 V_VT(&var) = VT_I4;
541 hr = IPropertyBag_Read(pPropBag, VFWIndex, &var, pErrorLog);
543 if (SUCCEEDED(hr))
545 VfwPinImpl *pin;
547 This->driver_info = qcap_driver_init( This->pOutputPin,
548 var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal );
549 if (This->driver_info)
551 pin = (VfwPinImpl *)This->pOutputPin;
552 pin->driver_info = This->driver_info;
553 pin->parent = This;
554 This->init = TRUE;
555 hr = S_OK;
557 else
558 hr = E_FAIL;
561 return hr;
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);
570 return E_NOTIMPL;
573 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
575 PPB_QueryInterface,
576 PPB_AddRef,
577 PPB_Release,
578 PPB_GetClassID,
579 PPB_InitNew,
580 PPB_Load,
581 PPB_Save
584 /* IKsPropertySet interface */
585 static HRESULT WINAPI
586 KSP_QueryInterface( IKsPropertySet * iface, REFIID riid, LPVOID * ppv )
588 if (IsEqualIID(riid, &IID_IUnknown) ||
589 IsEqualIID(riid, &IID_IKsPropertySet))
591 *ppv = iface;
592 IKsPropertySet_AddRef( iface );
593 return S_OK;
596 FIXME("No interface for iid %s\n", debugstr_guid(riid));
597 return E_NOINTERFACE;
600 static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
602 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
604 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
606 return IUnknown_AddRef((IUnknown *)This);
609 static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
611 ICOM_THIS_MULTI(VfwPinImpl, KSP_VT, iface);
613 TRACE("%p --> Forwarding to VfwPin (%p)\n", iface, This);
615 return IUnknown_Release((IUnknown *)This);
618 static HRESULT WINAPI
619 KSP_Set( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
620 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
621 DWORD cbPropData )
623 FIXME("%p: stub\n", iface);
624 return E_NOTIMPL;
627 static HRESULT WINAPI
628 KSP_Get( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
629 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
630 DWORD cbPropData, DWORD *pcbReturned )
632 LPGUID pGuid;
634 TRACE("()\n");
636 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
637 return E_PROP_SET_UNSUPPORTED;
638 if (pPropData == NULL && pcbReturned == NULL)
639 return E_POINTER;
640 if (pcbReturned)
641 *pcbReturned = sizeof(GUID);
642 if (pPropData == NULL)
643 return S_OK;
644 if (cbPropData < sizeof(GUID))
645 return E_UNEXPECTED;
646 pGuid = pPropData;
647 *pGuid = PIN_CATEGORY_PREVIEW;
648 FIXME("() Not adding a pin with PIN_CATEGORY_CAPTURE\n");
649 return S_OK;
652 static HRESULT WINAPI
653 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
654 DWORD dwPropID, DWORD *pTypeSupport )
656 FIXME("%p: stub\n", iface);
657 return E_NOTIMPL;
660 static const IKsPropertySetVtbl KSP_VTable =
662 KSP_QueryInterface,
663 KSP_AddRef,
664 KSP_Release,
665 KSP_Set,
666 KSP_Get,
667 KSP_QuerySupported
670 static HRESULT WINAPI VfwPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
672 VfwPinImpl *This = (VfwPinImpl *)iface;
673 AM_MEDIA_TYPE *vfw_pmt;
674 HRESULT hr;
676 if (iPosition < 0)
677 return E_INVALIDARG;
678 if (iPosition > 0)
679 return VFW_S_NO_MORE_ITEMS;
681 hr = qcap_driver_get_format(This->driver_info, &vfw_pmt);
682 if (SUCCEEDED(hr)) {
683 CopyMediaType(pmt, vfw_pmt);
684 DeleteMediaType(vfw_pmt);
686 return hr;
689 static LONG WINAPI VfwPin_GetMediaTypeVersion(BasePin *iface)
691 return 1;
694 static HRESULT WINAPI VfwPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
696 ALLOCATOR_PROPERTIES actual;
698 /* What we put here doesn't matter, the
699 driver function should override it then commit */
700 if (!ppropInputRequest->cBuffers)
701 ppropInputRequest->cBuffers = 3;
702 if (!ppropInputRequest->cbBuffer)
703 ppropInputRequest->cbBuffer = 230400;
704 if (!ppropInputRequest->cbAlign)
705 ppropInputRequest->cbAlign = 1;
707 return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
710 static const BaseOutputPinFuncTable output_BaseOutputFuncTable = {
712 NULL,
713 BaseOutputPinImpl_AttemptConnection,
714 VfwPin_GetMediaTypeVersion,
715 VfwPin_GetMediaType
717 VfwPin_DecideBufferSize,
718 BaseOutputPinImpl_DecideAllocator,
719 BaseOutputPinImpl_BreakConnect
722 static HRESULT
723 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
724 IPin ** ppPin )
726 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
727 PIN_INFO piOutput;
728 HRESULT hr;
730 *ppPin = NULL;
732 piOutput.dir = PINDIR_OUTPUT;
733 piOutput.pFilter = pBaseFilter;
734 lstrcpyW(piOutput.achName, wszOutputPinName);
736 hr = BaseOutputPin_Construct(&VfwPin_Vtbl, sizeof(VfwPinImpl), &piOutput, &output_BaseOutputFuncTable, pCritSec, ppPin);
738 if (SUCCEEDED(hr))
740 VfwPinImpl *pPinImpl = (VfwPinImpl*)*ppPin;
741 pPinImpl->KSP_VT = &KSP_VTable;
742 ObjectRefCount(TRUE);
745 return hr;
748 static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
750 VfwPinImpl *This = (VfwPinImpl *)iface;
752 TRACE("%s %p\n", debugstr_guid(riid), ppv);
754 *ppv = NULL;
755 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
756 *ppv = This;
757 else if (IsEqualIID(riid, &IID_IKsPropertySet))
758 *ppv = &(This->KSP_VT);
759 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
760 return IUnknown_QueryInterface((IUnknown *)This->parent, riid, ppv);
762 if (*ppv)
764 IUnknown_AddRef((IUnknown *)(*ppv));
765 return S_OK;
768 FIXME("No interface for %s!\n", debugstr_guid(riid));
769 return E_NOINTERFACE;
772 static ULONG WINAPI
773 VfwPin_Release(IPin * iface)
775 VfwPinImpl *This = (VfwPinImpl *)iface;
776 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
778 TRACE("() -> new refcount: %u\n", refCount);
780 if (!refCount)
782 BaseOutputPin_Destroy(&This->pin);
783 ObjectRefCount(FALSE);
785 return refCount;
788 static HRESULT WINAPI
789 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
791 AM_MEDIA_TYPE *pmt;
792 HRESULT hr;
794 VfwPinImpl *This = (VfwPinImpl *)iface;
795 hr = qcap_driver_get_format(This->driver_info, &pmt);
796 if (SUCCEEDED(hr)) {
797 hr = BasePinImpl_EnumMediaTypes(iface, ppEnum);
798 DeleteMediaType(pmt);
800 TRACE("%p -- %x\n", This, hr);
801 return hr;
804 static HRESULT WINAPI
805 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
807 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
808 return E_NOTIMPL;
811 static const IPinVtbl VfwPin_Vtbl =
813 VfwPin_QueryInterface,
814 BasePinImpl_AddRef,
815 VfwPin_Release,
816 BaseOutputPinImpl_Connect,
817 BaseOutputPinImpl_ReceiveConnection,
818 BaseOutputPinImpl_Disconnect,
819 BasePinImpl_ConnectedTo,
820 BasePinImpl_ConnectionMediaType,
821 BasePinImpl_QueryPinInfo,
822 BasePinImpl_QueryDirection,
823 BasePinImpl_QueryId,
824 BasePinImpl_QueryAccept,
825 VfwPin_EnumMediaTypes,
826 VfwPin_QueryInternalConnections,
827 BaseOutputPinImpl_EndOfStream,
828 BaseOutputPinImpl_BeginFlush,
829 BaseOutputPinImpl_EndFlush,
830 BasePinImpl_NewSegment