shell32/autocomplete: Remove the property after replacing the callback instead of...
[wine.git] / dlls / qcap / vfwcapture.c
blobca804fe095248c35e20544feb533f4a82c56f750
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 COBJMACROS
23 #include "config.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wtypes.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "dshow.h"
33 #include "qcap_main.h"
34 #include "wine/debug.h"
36 #include "capture.h"
37 #include "uuids.h"
38 #include "vfwmsgs.h"
39 #include "amvideo.h"
40 #include "strmif.h"
41 #include "ddraw.h"
42 #include "ocidl.h"
43 #include "oleauto.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;
58 BaseFilter filter;
59 IAMStreamConfig IAMStreamConfig_iface;
60 IAMVideoProcAmp IAMVideoProcAmp_iface;
61 IPersistPropertyBag IPersistPropertyBag_iface;
62 IUnknown *outer_unk;
63 BOOL init;
64 Capture *driver_info;
66 IPin * pOutputPin;
67 } VfwCapture;
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
102 BaseOutputPin pin;
103 IKsPropertySet IKsPropertySet_iface;
104 VfwCapture *parent;
105 } VfwPinImpl;
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);
115 *ret_iface = NULL;
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;
134 else
135 WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ret_iface);
137 if (!*ret_iface)
138 return E_NOINTERFACE;
140 IUnknown_AddRef((IUnknown*)*ret_iface);
141 return S_OK;
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);
151 return 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);
161 if (!ref)
163 IPin *conn = NULL;
165 TRACE("destroying everything\n");
166 if (This->init)
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);
173 if (conn)
175 IPin_Disconnect(conn);
176 IPin_Disconnect(This->pOutputPin);
177 IPin_Release(conn);
179 IPin_Release(This->pOutputPin);
180 BaseFilter_Destroy(&This->filter);
181 CoTaskMemFree(This);
182 ObjectRefCount(FALSE);
185 return ref;
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)
200 return NULL;
202 IPin_AddRef(This->pOutputPin);
203 return This->pOutputPin;
206 static LONG WINAPI VfwCapture_GetPinCount(BaseFilter *iface)
208 return 1;
211 static const BaseFilterFuncTable BaseFuncTable = {
212 VfwCapture_GetPin,
213 VfwCapture_GetPinCount
216 IUnknown * WINAPI QCAP_createVFWCaptureFilter(IUnknown *pUnkOuter, HRESULT *phr)
218 VfwCapture *pVfwCapture;
219 HRESULT hr;
221 TRACE("%p - %p\n", pUnkOuter, phr);
223 *phr = E_OUTOFMEMORY;
224 pVfwCapture = CoTaskMemAlloc( sizeof(VfwCapture) );
225 if (!pVfwCapture)
226 return NULL;
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;
236 if (pUnkOuter)
237 pVfwCapture->outer_unk = pUnkOuter;
238 else
239 pVfwCapture->outer_unk = &pVfwCapture->IUnknown_inner;
241 hr = VfwPin_Construct(&pVfwCapture->filter.IBaseFilter_iface,
242 &pVfwCapture->filter.csFilter, &pVfwCapture->pOutputPin);
243 if (FAILED(hr))
245 CoTaskMemFree(pVfwCapture);
246 return NULL;
248 TRACE("-- created at %p\n", pVfwCapture);
250 ObjectRefCount(TRUE);
251 *phr = S_OK;
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);
282 TRACE("()\n");
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);
290 TRACE("()\n");
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("(%s)\n", wine_dbgstr_longlong(tStart));
298 return qcap_driver_run(This->driver_info, &This->filter.state);
301 static const IBaseFilterVtbl VfwCapture_Vtbl =
303 VfwCapture_QueryInterface,
304 VfwCapture_AddRef,
305 VfwCapture_Release,
306 BaseFilterImpl_GetClassID,
307 VfwCapture_Stop,
308 VfwCapture_Pause,
309 VfwCapture_Run,
310 BaseFilterImpl_GetState,
311 BaseFilterImpl_SetSyncSource,
312 BaseFilterImpl_GetSyncSource,
313 BaseFilterImpl_EnumPins,
314 BaseFilterImpl_FindPin,
315 BaseFilterImpl_QueryFilterInfo,
316 BaseFilterImpl_JoinFilterGraph,
317 BaseFilterImpl_QueryVendorInfo
320 /* AMStreamConfig interface, we only need to implement {G,S}etFormat */
321 static HRESULT WINAPI AMStreamConfig_QueryInterface(IAMStreamConfig *iface, REFIID riid,
322 void **ret_iface)
324 VfwCapture *This = impl_from_IAMStreamConfig(iface);
326 return IUnknown_QueryInterface(This->outer_unk, riid, ret_iface);
329 static ULONG WINAPI AMStreamConfig_AddRef( IAMStreamConfig * iface )
331 VfwCapture *This = impl_from_IAMStreamConfig(iface);
333 return IUnknown_AddRef(This->outer_unk);
336 static ULONG WINAPI AMStreamConfig_Release( IAMStreamConfig * iface )
338 VfwCapture *This = impl_from_IAMStreamConfig(iface);
340 return IUnknown_Release(This->outer_unk);
343 static HRESULT WINAPI
344 AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
346 HRESULT hr;
347 VfwCapture *This = impl_from_IAMStreamConfig(iface);
348 BasePin *pin;
350 TRACE("(%p): %p->%p\n", iface, pmt, pmt ? pmt->pbFormat : NULL);
352 if (This->filter.state != State_Stopped)
354 TRACE("Returning not stopped error\n");
355 return VFW_E_NOT_STOPPED;
358 if (!pmt)
360 TRACE("pmt is NULL\n");
361 return E_POINTER;
364 dump_AM_MEDIA_TYPE(pmt);
366 pin = (BasePin *)This->pOutputPin;
367 if (pin->pConnectedTo != NULL)
369 hr = IPin_QueryAccept(pin->pConnectedTo, pmt);
370 TRACE("Would accept: %d\n", hr);
371 if (hr == S_FALSE)
372 return VFW_E_INVALIDMEDIATYPE;
375 hr = qcap_driver_set_format(This->driver_info, pmt);
376 if (SUCCEEDED(hr) && This->filter.filterInfo.pGraph && pin->pConnectedTo )
378 hr = IFilterGraph_Reconnect(This->filter.filterInfo.pGraph, This->pOutputPin);
379 if (SUCCEEDED(hr))
380 TRACE("Reconnection completed, with new media format..\n");
382 TRACE("Returning: %d\n", hr);
383 return hr;
386 static HRESULT WINAPI
387 AMStreamConfig_GetFormat( IAMStreamConfig *iface, AM_MEDIA_TYPE **pmt )
389 VfwCapture *This = impl_from_IAMStreamConfig(iface);
391 TRACE("%p -> (%p)\n", iface, pmt);
392 return qcap_driver_get_format(This->driver_info, pmt);
395 static HRESULT WINAPI
396 AMStreamConfig_GetNumberOfCapabilities( IAMStreamConfig *iface, int *piCount,
397 int *piSize )
399 FIXME("%p: %p %p - stub, intentional\n", iface, piCount, piSize);
400 *piCount = 0;
401 return E_NOTIMPL; /* Not implemented for this interface */
404 static HRESULT WINAPI
405 AMStreamConfig_GetStreamCaps( IAMStreamConfig *iface, int iIndex,
406 AM_MEDIA_TYPE **pmt, BYTE *pSCC )
408 FIXME("%p: %d %p %p - stub, intentional\n", iface, iIndex, pmt, pSCC);
409 return E_NOTIMPL; /* Not implemented for this interface */
412 static const IAMStreamConfigVtbl IAMStreamConfig_VTable =
414 AMStreamConfig_QueryInterface,
415 AMStreamConfig_AddRef,
416 AMStreamConfig_Release,
417 AMStreamConfig_SetFormat,
418 AMStreamConfig_GetFormat,
419 AMStreamConfig_GetNumberOfCapabilities,
420 AMStreamConfig_GetStreamCaps
423 static HRESULT WINAPI AMVideoProcAmp_QueryInterface(IAMVideoProcAmp *iface, REFIID riid,
424 void **ret_iface)
426 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
428 return IUnknown_QueryInterface(This->outer_unk, riid, ret_iface);
431 static ULONG WINAPI AMVideoProcAmp_AddRef(IAMVideoProcAmp * iface)
433 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
435 return IUnknown_AddRef(This->outer_unk);
438 static ULONG WINAPI AMVideoProcAmp_Release(IAMVideoProcAmp * iface)
440 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
442 return IUnknown_Release(This->outer_unk);
445 static HRESULT WINAPI
446 AMVideoProcAmp_GetRange( IAMVideoProcAmp * iface, LONG Property, LONG *pMin,
447 LONG *pMax, LONG *pSteppingDelta, LONG *pDefault, LONG *pCapsFlags )
449 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
451 return qcap_driver_get_prop_range( This->driver_info, Property, pMin, pMax,
452 pSteppingDelta, pDefault, pCapsFlags );
455 static HRESULT WINAPI
456 AMVideoProcAmp_Set( IAMVideoProcAmp * iface, LONG Property, LONG lValue,
457 LONG Flags )
459 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
461 return qcap_driver_set_prop(This->driver_info, Property, lValue, Flags);
464 static HRESULT WINAPI
465 AMVideoProcAmp_Get( IAMVideoProcAmp * iface, LONG Property, LONG *lValue,
466 LONG *Flags )
468 VfwCapture *This = impl_from_IAMVideoProcAmp(iface);
470 return qcap_driver_get_prop(This->driver_info, Property, lValue, Flags);
473 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
475 AMVideoProcAmp_QueryInterface,
476 AMVideoProcAmp_AddRef,
477 AMVideoProcAmp_Release,
478 AMVideoProcAmp_GetRange,
479 AMVideoProcAmp_Set,
480 AMVideoProcAmp_Get,
483 static HRESULT WINAPI PPB_QueryInterface(IPersistPropertyBag *iface, REFIID riid, void **ret_iface)
485 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
487 return IUnknown_QueryInterface(This->outer_unk, riid, ret_iface);
490 static ULONG WINAPI PPB_AddRef(IPersistPropertyBag * iface)
492 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
494 return IUnknown_AddRef(This->outer_unk);
497 static ULONG WINAPI PPB_Release(IPersistPropertyBag * iface)
499 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
501 return IUnknown_Release(This->outer_unk);
504 static HRESULT WINAPI
505 PPB_GetClassID( IPersistPropertyBag * iface, CLSID * pClassID )
507 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
509 FIXME("%p - stub\n", This);
511 return E_NOTIMPL;
514 static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
516 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
518 FIXME("%p - stub\n", This);
520 return E_NOTIMPL;
523 static HRESULT WINAPI
524 PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
525 IErrorLog *pErrorLog )
527 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
528 HRESULT hr;
529 VARIANT var;
530 const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0};
532 TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog);
534 V_VT(&var) = VT_I4;
535 hr = IPropertyBag_Read(pPropBag, VFWIndex, &var, pErrorLog);
537 if (SUCCEEDED(hr))
539 VfwPinImpl *pin;
541 This->driver_info = qcap_driver_init( This->pOutputPin,
542 var.__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.ulVal );
543 if (This->driver_info)
545 pin = (VfwPinImpl *)This->pOutputPin;
546 pin->parent = This;
547 This->init = TRUE;
548 hr = S_OK;
550 else
551 hr = E_FAIL;
554 return hr;
557 static HRESULT WINAPI
558 PPB_Save( IPersistPropertyBag * iface, IPropertyBag *pPropBag,
559 BOOL fClearDirty, BOOL fSaveAllProperties )
561 VfwCapture *This = impl_from_IPersistPropertyBag(iface);
562 FIXME("%p - stub\n", This);
563 return E_NOTIMPL;
566 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable =
568 PPB_QueryInterface,
569 PPB_AddRef,
570 PPB_Release,
571 PPB_GetClassID,
572 PPB_InitNew,
573 PPB_Load,
574 PPB_Save
577 /* IKsPropertySet interface */
578 static inline VfwPinImpl *impl_from_IKsPropertySet(IKsPropertySet *iface)
580 return CONTAINING_RECORD(iface, VfwPinImpl, IKsPropertySet_iface);
583 static HRESULT WINAPI KSP_QueryInterface(IKsPropertySet * iface, REFIID riid, void **ret_iface)
585 VfwPinImpl *This = impl_from_IKsPropertySet(iface);
587 return IPin_QueryInterface(&This->pin.pin.IPin_iface, riid, ret_iface);
590 static ULONG WINAPI KSP_AddRef(IKsPropertySet * iface)
592 VfwPinImpl *This = impl_from_IKsPropertySet(iface);
594 return IPin_AddRef(&This->pin.pin.IPin_iface);
597 static ULONG WINAPI KSP_Release(IKsPropertySet * iface)
599 VfwPinImpl *This = impl_from_IKsPropertySet(iface);
601 return IPin_Release(&This->pin.pin.IPin_iface);
604 static HRESULT WINAPI
605 KSP_Set( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
606 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
607 DWORD cbPropData )
609 FIXME("%p: stub\n", iface);
610 return E_NOTIMPL;
613 static HRESULT WINAPI
614 KSP_Get( IKsPropertySet * iface, REFGUID guidPropSet, DWORD dwPropID,
615 LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData,
616 DWORD cbPropData, DWORD *pcbReturned )
618 LPGUID pGuid;
620 TRACE("()\n");
622 if (!IsEqualIID(guidPropSet, &AMPROPSETID_Pin))
623 return E_PROP_SET_UNSUPPORTED;
624 if (pPropData == NULL && pcbReturned == NULL)
625 return E_POINTER;
626 if (pcbReturned)
627 *pcbReturned = sizeof(GUID);
628 if (pPropData == NULL)
629 return S_OK;
630 if (cbPropData < sizeof(GUID))
631 return E_UNEXPECTED;
632 pGuid = pPropData;
633 *pGuid = PIN_CATEGORY_CAPTURE;
634 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
635 return S_OK;
638 static HRESULT WINAPI
639 KSP_QuerySupported( IKsPropertySet * iface, REFGUID guidPropSet,
640 DWORD dwPropID, DWORD *pTypeSupport )
642 FIXME("%p: stub\n", iface);
643 return E_NOTIMPL;
646 static const IKsPropertySetVtbl IKsPropertySet_VTable =
648 KSP_QueryInterface,
649 KSP_AddRef,
650 KSP_Release,
651 KSP_Set,
652 KSP_Get,
653 KSP_QuerySupported
656 static inline VfwPinImpl *impl_from_BasePin(BasePin *pin)
658 return CONTAINING_RECORD(pin, VfwPinImpl, pin.pin);
661 static HRESULT WINAPI VfwPin_CheckMediaType(BasePin *pin, const AM_MEDIA_TYPE *amt)
663 FIXME("(%p) stub\n", pin);
664 return E_NOTIMPL;
667 static HRESULT WINAPI VfwPin_GetMediaType(BasePin *pin, int iPosition, AM_MEDIA_TYPE *pmt)
669 VfwPinImpl *This = impl_from_BasePin(pin);
670 AM_MEDIA_TYPE *vfw_pmt;
671 HRESULT hr;
673 if (iPosition < 0)
674 return E_INVALIDARG;
675 if (iPosition > 0)
676 return VFW_S_NO_MORE_ITEMS;
678 hr = qcap_driver_get_format(This->parent->driver_info, &vfw_pmt);
679 if (SUCCEEDED(hr)) {
680 CopyMediaType(pmt, vfw_pmt);
681 DeleteMediaType(vfw_pmt);
683 return hr;
686 static LONG WINAPI VfwPin_GetMediaTypeVersion(BasePin *iface)
688 return 1;
691 static HRESULT WINAPI VfwPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
693 ALLOCATOR_PROPERTIES actual;
695 /* What we put here doesn't matter, the
696 driver function should override it then commit */
697 if (!ppropInputRequest->cBuffers)
698 ppropInputRequest->cBuffers = 3;
699 if (!ppropInputRequest->cbBuffer)
700 ppropInputRequest->cbBuffer = 230400;
701 if (!ppropInputRequest->cbAlign)
702 ppropInputRequest->cbAlign = 1;
704 return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
707 static const BaseOutputPinFuncTable output_BaseOutputFuncTable = {
709 VfwPin_CheckMediaType,
710 BaseOutputPinImpl_AttemptConnection,
711 VfwPin_GetMediaTypeVersion,
712 VfwPin_GetMediaType
714 VfwPin_DecideBufferSize,
715 BaseOutputPinImpl_DecideAllocator,
716 BaseOutputPinImpl_BreakConnect
719 static HRESULT
720 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
721 IPin ** ppPin )
723 static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
724 PIN_INFO piOutput;
725 HRESULT hr;
727 *ppPin = NULL;
729 piOutput.dir = PINDIR_OUTPUT;
730 piOutput.pFilter = pBaseFilter;
731 lstrcpyW(piOutput.achName, wszOutputPinName);
733 hr = BaseOutputPin_Construct(&VfwPin_Vtbl, sizeof(VfwPinImpl), &piOutput, &output_BaseOutputFuncTable, pCritSec, ppPin);
735 if (SUCCEEDED(hr))
737 VfwPinImpl *pPinImpl = (VfwPinImpl*)*ppPin;
738 pPinImpl->IKsPropertySet_iface.lpVtbl = &IKsPropertySet_VTable;
739 ObjectRefCount(TRUE);
742 return hr;
745 static inline VfwPinImpl *impl_from_IPin(IPin *iface)
747 return CONTAINING_RECORD(iface, VfwPinImpl, pin.pin.IPin_iface);
750 static HRESULT WINAPI VfwPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
752 VfwPinImpl *This = impl_from_IPin(iface);
754 TRACE("%s %p\n", debugstr_guid(riid), ppv);
756 *ppv = NULL;
757 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPin))
758 *ppv = This;
759 else if (IsEqualIID(riid, &IID_IKsPropertySet))
760 *ppv = &This->IKsPropertySet_iface;
761 else if (IsEqualIID(riid, &IID_IAMStreamConfig))
762 return IUnknown_QueryInterface((IUnknown *)This->parent, riid, ppv);
764 if (*ppv)
766 IUnknown_AddRef((IUnknown *)(*ppv));
767 return S_OK;
770 FIXME("No interface for %s!\n", debugstr_guid(riid));
771 return E_NOINTERFACE;
774 static ULONG WINAPI
775 VfwPin_Release(IPin * iface)
777 VfwPinImpl *This = impl_from_IPin(iface);
778 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
780 TRACE("() -> new refcount: %u\n", refCount);
782 if (!refCount)
784 BaseOutputPin_Destroy(&This->pin);
785 ObjectRefCount(FALSE);
787 return refCount;
790 static HRESULT WINAPI
791 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
793 VfwPinImpl *This = impl_from_IPin(iface);
794 AM_MEDIA_TYPE *pmt;
795 HRESULT hr;
797 hr = qcap_driver_get_format(This->parent->driver_info, &pmt);
798 if (SUCCEEDED(hr)) {
799 hr = BasePinImpl_EnumMediaTypes(iface, ppEnum);
800 DeleteMediaType(pmt);
802 TRACE("%p -- %x\n", This, hr);
803 return hr;
806 static HRESULT WINAPI
807 VfwPin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
809 TRACE("(%p)->(%p, %p)\n", iface, apPin, cPin);
810 return E_NOTIMPL;
813 static const IPinVtbl VfwPin_Vtbl =
815 VfwPin_QueryInterface,
816 BasePinImpl_AddRef,
817 VfwPin_Release,
818 BaseOutputPinImpl_Connect,
819 BaseOutputPinImpl_ReceiveConnection,
820 BaseOutputPinImpl_Disconnect,
821 BasePinImpl_ConnectedTo,
822 BasePinImpl_ConnectionMediaType,
823 BasePinImpl_QueryPinInfo,
824 BasePinImpl_QueryDirection,
825 BasePinImpl_QueryId,
826 BasePinImpl_QueryAccept,
827 VfwPin_EnumMediaTypes,
828 VfwPin_QueryInternalConnections,
829 BaseOutputPinImpl_EndOfStream,
830 BaseOutputPinImpl_BeginFlush,
831 BaseOutputPinImpl_EndFlush,
832 BasePinImpl_NewSegment