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 #include "qcap_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(quartz
);
26 static const struct video_capture_funcs
*capture_funcs
;
30 struct strmbase_filter filter
;
31 IAMStreamConfig IAMStreamConfig_iface
;
32 IAMVideoControl IAMVideoControl_iface
;
33 IAMVideoProcAmp IAMVideoProcAmp_iface
;
34 IAMFilterMiscFlags IAMFilterMiscFlags_iface
;
35 IPersistPropertyBag IPersistPropertyBag_iface
;
38 struct strmbase_source source
;
39 IKsPropertySet IKsPropertySet_iface
;
41 struct video_capture_device
*device
;
43 /* FIXME: It would be nice to avoid duplicating this variable with strmbase.
44 * However, synchronization is tricky; we need access to be protected by a
47 CONDITION_VARIABLE state_cv
;
48 CRITICAL_SECTION state_cs
;
53 static inline struct vfw_capture
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
55 return CONTAINING_RECORD(iface
, struct vfw_capture
, filter
);
58 static inline struct vfw_capture
*impl_from_IAMStreamConfig(IAMStreamConfig
*iface
)
60 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMStreamConfig_iface
);
63 static inline struct vfw_capture
*impl_from_IAMVideoControl(IAMVideoControl
*iface
)
65 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMVideoControl_iface
);
68 static inline struct vfw_capture
*impl_from_IAMVideoProcAmp(IAMVideoProcAmp
*iface
)
70 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMVideoProcAmp_iface
);
73 static inline struct vfw_capture
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
75 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMFilterMiscFlags_iface
);
78 static inline struct vfw_capture
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
80 return CONTAINING_RECORD(iface
, struct vfw_capture
, IPersistPropertyBag_iface
);
83 static struct strmbase_pin
*vfw_capture_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
85 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
90 return &filter
->source
.pin
;
93 static void vfw_capture_destroy(struct strmbase_filter
*iface
)
95 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
98 capture_funcs
->destroy(filter
->device
);
100 if (filter
->source
.pin
.peer
)
102 IPin_Disconnect(filter
->source
.pin
.peer
);
103 IPin_Disconnect(&filter
->source
.pin
.IPin_iface
);
105 filter
->state_cs
.DebugInfo
->Spare
[0] = 0;
106 DeleteCriticalSection(&filter
->state_cs
);
107 strmbase_source_cleanup(&filter
->source
);
108 strmbase_filter_cleanup(&filter
->filter
);
112 static HRESULT
vfw_capture_query_interface(struct strmbase_filter
*iface
, REFIID iid
, void **out
)
114 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
116 if (IsEqualGUID(iid
, &IID_IPersistPropertyBag
))
117 *out
= &filter
->IPersistPropertyBag_iface
;
118 else if (IsEqualGUID(iid
, &IID_IAMVideoControl
))
119 *out
= &filter
->IAMVideoControl_iface
;
120 else if (IsEqualGUID(iid
, &IID_IAMVideoProcAmp
))
121 *out
= &filter
->IAMVideoProcAmp_iface
;
122 else if (IsEqualGUID(iid
, &IID_IAMFilterMiscFlags
))
123 *out
= &filter
->IAMFilterMiscFlags_iface
;
125 return E_NOINTERFACE
;
127 IUnknown_AddRef((IUnknown
*)*out
);
131 static unsigned int get_image_size(struct vfw_capture
*filter
)
133 const VIDEOINFOHEADER
*format
= (const VIDEOINFOHEADER
*)filter
->source
.pin
.mt
.pbFormat
;
135 return format
->bmiHeader
.biWidth
* format
->bmiHeader
.biHeight
* format
->bmiHeader
.biBitCount
/ 8;
138 static DWORD WINAPI
stream_thread(void *arg
)
140 struct vfw_capture
*filter
= arg
;
141 const unsigned int image_size
= get_image_size(filter
);
145 IMediaSample
*sample
;
149 EnterCriticalSection(&filter
->state_cs
);
151 while (filter
->state
== State_Paused
)
152 SleepConditionVariableCS(&filter
->state_cv
, &filter
->state_cs
, INFINITE
);
154 if (filter
->state
== State_Stopped
)
156 LeaveCriticalSection(&filter
->state_cs
);
160 LeaveCriticalSection(&filter
->state_cs
);
162 if (FAILED(hr
= BaseOutputPinImpl_GetDeliveryBuffer(&filter
->source
, &sample
, NULL
, NULL
, 0)))
164 ERR("Failed to get sample, hr %#x.\n", hr
);
168 IMediaSample_SetActualDataLength(sample
, image_size
);
169 IMediaSample_GetPointer(sample
, &data
);
171 if (!capture_funcs
->read_frame(filter
->device
, data
))
173 IMediaSample_Release(sample
);
177 hr
= IMemInputPin_Receive(filter
->source
.pMemInputPin
, sample
);
178 IMediaSample_Release(sample
);
181 ERR("IMemInputPin::Receive() returned %#x.\n", hr
);
189 static HRESULT
vfw_capture_init_stream(struct strmbase_filter
*iface
)
191 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
194 if (FAILED(hr
= IMemAllocator_Commit(filter
->source
.pAllocator
)))
195 ERR("Failed to commit allocator, hr %#x.\n", hr
);
197 EnterCriticalSection(&filter
->state_cs
);
198 filter
->state
= State_Paused
;
199 LeaveCriticalSection(&filter
->state_cs
);
201 filter
->thread
= CreateThread(NULL
, 0, stream_thread
, filter
, 0, NULL
);
206 static HRESULT
vfw_capture_start_stream(struct strmbase_filter
*iface
, REFERENCE_TIME time
)
208 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
210 EnterCriticalSection(&filter
->state_cs
);
211 filter
->state
= State_Running
;
212 LeaveCriticalSection(&filter
->state_cs
);
213 WakeConditionVariable(&filter
->state_cv
);
217 static HRESULT
vfw_capture_stop_stream(struct strmbase_filter
*iface
)
219 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
221 EnterCriticalSection(&filter
->state_cs
);
222 filter
->state
= State_Paused
;
223 LeaveCriticalSection(&filter
->state_cs
);
227 static HRESULT
vfw_capture_cleanup_stream(struct strmbase_filter
*iface
)
229 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
232 EnterCriticalSection(&filter
->state_cs
);
233 filter
->state
= State_Stopped
;
234 LeaveCriticalSection(&filter
->state_cs
);
235 WakeConditionVariable(&filter
->state_cv
);
237 WaitForSingleObject(filter
->thread
, INFINITE
);
238 CloseHandle(filter
->thread
);
239 filter
->thread
= NULL
;
241 hr
= IMemAllocator_Decommit(filter
->source
.pAllocator
);
242 if (hr
!= S_OK
&& hr
!= VFW_E_NOT_COMMITTED
)
243 ERR("Failed to decommit allocator, hr %#x.\n", hr
);
248 static HRESULT
vfw_capture_wait_state(struct strmbase_filter
*iface
, DWORD timeout
)
250 return iface
->state
== State_Paused
? VFW_S_CANT_CUE
: S_OK
;
253 static const struct strmbase_filter_ops filter_ops
=
255 .filter_get_pin
= vfw_capture_get_pin
,
256 .filter_destroy
= vfw_capture_destroy
,
257 .filter_query_interface
= vfw_capture_query_interface
,
258 .filter_init_stream
= vfw_capture_init_stream
,
259 .filter_start_stream
= vfw_capture_start_stream
,
260 .filter_stop_stream
= vfw_capture_stop_stream
,
261 .filter_cleanup_stream
= vfw_capture_cleanup_stream
,
262 .filter_wait_state
= vfw_capture_wait_state
,
265 static HRESULT WINAPI
AMStreamConfig_QueryInterface(IAMStreamConfig
*iface
, REFIID iid
, void **out
)
267 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
268 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
271 static ULONG WINAPI
AMStreamConfig_AddRef(IAMStreamConfig
*iface
)
273 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
274 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
277 static ULONG WINAPI
AMStreamConfig_Release(IAMStreamConfig
*iface
)
279 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
280 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
283 static HRESULT WINAPI
284 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
286 struct vfw_capture
*This
= impl_from_IAMStreamConfig(iface
);
289 TRACE("filter %p, mt %p.\n", This
, pmt
);
290 strmbase_dump_media_type(pmt
);
292 if (This
->filter
.state
!= State_Stopped
)
294 TRACE("Returning not stopped error\n");
295 return VFW_E_NOT_STOPPED
;
300 TRACE("pmt is NULL\n");
304 if (!IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
307 if (This
->source
.pin
.peer
)
309 hr
= IPin_QueryAccept(This
->source
.pin
.peer
, pmt
);
310 TRACE("Would accept: %d\n", hr
);
312 return VFW_E_INVALIDMEDIATYPE
;
315 hr
= capture_funcs
->set_format(This
->device
, pmt
);
316 if (SUCCEEDED(hr
) && This
->filter
.graph
&& This
->source
.pin
.peer
)
318 hr
= IFilterGraph_Reconnect(This
->filter
.graph
, &This
->source
.pin
.IPin_iface
);
320 TRACE("Reconnection completed, with new media format..\n");
322 TRACE("Returning: %d\n", hr
);
326 static HRESULT WINAPI
AMStreamConfig_GetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**mt
)
328 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
329 VIDEOINFOHEADER
*format
;
332 TRACE("filter %p, mt %p.\n", filter
, mt
);
334 if (!(*mt
= CoTaskMemAlloc(sizeof(**mt
))))
335 return E_OUTOFMEMORY
;
337 EnterCriticalSection(&filter
->filter
.filter_cs
);
339 if (filter
->source
.pin
.peer
)
341 hr
= CopyMediaType(*mt
, &filter
->source
.pin
.mt
);
345 if ((format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
347 capture_funcs
->get_format(filter
->device
, *mt
, format
);
348 (*mt
)->cbFormat
= sizeof(VIDEOINFOHEADER
);
349 (*mt
)->pbFormat
= (BYTE
*)format
;
358 LeaveCriticalSection(&filter
->filter
.filter_cs
);
361 strmbase_dump_media_type(*mt
);
367 static HRESULT WINAPI
AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig
*iface
,
368 int *count
, int *size
)
370 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
372 TRACE("filter %p, count %p, size %p.\n", filter
, count
, size
);
377 *count
= capture_funcs
->get_caps_count(filter
->device
);
378 *size
= sizeof(VIDEO_STREAM_CONFIG_CAPS
);
383 static HRESULT WINAPI
AMStreamConfig_GetStreamCaps(IAMStreamConfig
*iface
,
384 int index
, AM_MEDIA_TYPE
**pmt
, BYTE
*vscc
)
386 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
387 VIDEOINFOHEADER
*format
;
390 TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter
, index
, pmt
, vscc
);
392 if (index
> capture_funcs
->get_caps_count(filter
->device
))
395 if (!(mt
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
))))
396 return E_OUTOFMEMORY
;
398 if (!(format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
401 return E_OUTOFMEMORY
;
404 capture_funcs
->get_caps(filter
->device
, index
, mt
, format
, (VIDEO_STREAM_CONFIG_CAPS
*)vscc
);
405 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
406 mt
->pbFormat
= (BYTE
*)format
;
411 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
413 AMStreamConfig_QueryInterface
,
414 AMStreamConfig_AddRef
,
415 AMStreamConfig_Release
,
416 AMStreamConfig_SetFormat
,
417 AMStreamConfig_GetFormat
,
418 AMStreamConfig_GetNumberOfCapabilities
,
419 AMStreamConfig_GetStreamCaps
422 static HRESULT WINAPI
AMVideoProcAmp_QueryInterface(IAMVideoProcAmp
*iface
, REFIID iid
, void **out
)
424 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
425 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
428 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
430 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
431 return IUnknown_AddRef(filter
->filter
.outer_unk
);
434 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
436 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
437 return IUnknown_Release(filter
->filter
.outer_unk
);
440 static HRESULT WINAPI
AMVideoProcAmp_GetRange(IAMVideoProcAmp
*iface
, LONG property
,
441 LONG
*min
, LONG
*max
, LONG
*step
, LONG
*default_value
, LONG
*flags
)
443 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
445 TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n",
446 filter
, property
, min
, max
, step
, default_value
, flags
);
448 return capture_funcs
->get_prop_range(filter
->device
, property
, min
,
449 max
, step
, default_value
, flags
);
452 static HRESULT WINAPI
AMVideoProcAmp_Set(IAMVideoProcAmp
*iface
, LONG property
,
453 LONG value
, LONG flags
)
455 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
457 TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter
, property
, value
, flags
);
459 return capture_funcs
->set_prop(filter
->device
, property
, value
, flags
);
462 static HRESULT WINAPI
AMVideoProcAmp_Get(IAMVideoProcAmp
*iface
, LONG property
,
463 LONG
*value
, LONG
*flags
)
465 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
467 TRACE("filter %p, property %#x, value %p, flags %p.\n", filter
, property
, value
, flags
);
469 return capture_funcs
->get_prop(filter
->device
, property
, value
, flags
);
472 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
474 AMVideoProcAmp_QueryInterface
,
475 AMVideoProcAmp_AddRef
,
476 AMVideoProcAmp_Release
,
477 AMVideoProcAmp_GetRange
,
482 static HRESULT WINAPI
PPB_QueryInterface(IPersistPropertyBag
*iface
, REFIID iid
, void **out
)
484 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
485 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
488 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
490 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
491 return IUnknown_AddRef(filter
->filter
.outer_unk
);
494 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
496 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
497 return IUnknown_Release(filter
->filter
.outer_unk
);
500 static HRESULT WINAPI
501 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
503 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
505 FIXME("%p - stub\n", This
);
510 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
512 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
514 FIXME("%p - stub\n", This
);
519 static HRESULT WINAPI
PPB_Load(IPersistPropertyBag
*iface
, IPropertyBag
*bag
, IErrorLog
*error_log
)
521 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
525 TRACE("filter %p, bag %p, error_log %p.\n", filter
, bag
, error_log
);
528 if (FAILED(hr
= IPropertyBag_Read(bag
, L
"VFWIndex", &var
, error_log
)))
531 if (!(filter
->device
= capture_funcs
->create(V_I4(&var
))))
538 static HRESULT WINAPI
539 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
540 BOOL fClearDirty
, BOOL fSaveAllProperties
)
542 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
543 FIXME("%p - stub\n", This
);
547 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
558 /* IKsPropertySet interface */
559 static inline struct vfw_capture
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
561 return CONTAINING_RECORD(iface
, struct vfw_capture
, IKsPropertySet_iface
);
564 static HRESULT WINAPI
KSP_QueryInterface(IKsPropertySet
*iface
, REFIID iid
, void **out
)
566 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
567 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
570 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
572 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
573 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
576 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
578 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
579 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
582 static HRESULT WINAPI
583 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
584 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
587 FIXME("%p: stub\n", iface
);
591 static HRESULT WINAPI
592 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
593 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
594 DWORD cbPropData
, DWORD
*pcbReturned
)
600 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
601 return E_PROP_SET_UNSUPPORTED
;
602 if (pPropData
== NULL
&& pcbReturned
== NULL
)
605 *pcbReturned
= sizeof(GUID
);
606 if (pPropData
== NULL
)
608 if (cbPropData
< sizeof(GUID
))
611 *pGuid
= PIN_CATEGORY_CAPTURE
;
612 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
616 static HRESULT WINAPI
617 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
618 DWORD dwPropID
, DWORD
*pTypeSupport
)
620 FIXME("%p: stub\n", iface
);
624 static const IKsPropertySetVtbl IKsPropertySet_VTable
=
634 static inline struct vfw_capture
*impl_from_strmbase_pin(struct strmbase_pin
*pin
)
636 return CONTAINING_RECORD(pin
, struct vfw_capture
, source
.pin
);
639 static HRESULT
source_query_accept(struct strmbase_pin
*pin
, const AM_MEDIA_TYPE
*mt
)
641 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
642 return capture_funcs
->check_format(filter
->device
, mt
);
645 static HRESULT
source_get_media_type(struct strmbase_pin
*pin
,
646 unsigned int index
, AM_MEDIA_TYPE
*mt
)
648 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
649 VIDEOINFOHEADER
*format
;
652 if (!(format
= CoTaskMemAlloc(sizeof(*format
))))
653 return E_OUTOFMEMORY
;
655 if ((hr
= capture_funcs
->get_media_type(filter
->device
, index
, mt
, format
)) != S_OK
)
657 CoTaskMemFree(format
);
660 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
661 mt
->pbFormat
= (BYTE
*)format
;
665 static HRESULT
source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
667 struct vfw_capture
*filter
= impl_from_strmbase_pin(iface
);
669 if (IsEqualGUID(iid
, &IID_IKsPropertySet
))
670 *out
= &filter
->IKsPropertySet_iface
;
671 else if (IsEqualGUID(iid
, &IID_IAMStreamConfig
))
672 *out
= &filter
->IAMStreamConfig_iface
;
674 return E_NOINTERFACE
;
676 IUnknown_AddRef((IUnknown
*)*out
);
680 static HRESULT WINAPI
VfwPin_DecideBufferSize(struct strmbase_source
*iface
,
681 IMemAllocator
*allocator
, ALLOCATOR_PROPERTIES
*req_props
)
683 struct vfw_capture
*filter
= impl_from_strmbase_pin(&iface
->pin
);
684 ALLOCATOR_PROPERTIES ret_props
;
686 if (!req_props
->cBuffers
)
687 req_props
->cBuffers
= 3;
688 if (!req_props
->cbBuffer
)
689 req_props
->cbBuffer
= get_image_size(filter
);
690 if (!req_props
->cbAlign
)
691 req_props
->cbAlign
= 1;
693 return IMemAllocator_SetProperties(allocator
, req_props
, &ret_props
);
696 static const struct strmbase_source_ops source_ops
=
698 .base
.pin_query_accept
= source_query_accept
,
699 .base
.pin_get_media_type
= source_get_media_type
,
700 .base
.pin_query_interface
= source_query_interface
,
701 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
702 .pfnDecideBufferSize
= VfwPin_DecideBufferSize
,
703 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
706 static HRESULT WINAPI
misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
)
708 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
709 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
712 static ULONG WINAPI
misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
714 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
715 return IUnknown_AddRef(filter
->filter
.outer_unk
);
718 static ULONG WINAPI
misc_flags_Release(IAMFilterMiscFlags
*iface
)
720 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
721 return IUnknown_Release(filter
->filter
.outer_unk
);
724 static ULONG WINAPI
misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
726 return AM_FILTER_MISC_FLAGS_IS_SOURCE
;
729 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_VTable
=
731 misc_flags_QueryInterface
,
734 misc_flags_GetMiscFlags
737 static HRESULT WINAPI
video_control_QueryInterface(IAMVideoControl
*iface
, REFIID riid
, void **ppv
)
739 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
740 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
743 static ULONG WINAPI
video_control_AddRef(IAMVideoControl
*iface
)
745 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
746 return IUnknown_AddRef(filter
->filter
.outer_unk
);
749 static ULONG WINAPI
video_control_Release(IAMVideoControl
*iface
)
751 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
752 return IUnknown_Release(filter
->filter
.outer_unk
);
755 static HRESULT WINAPI
video_control_GetCaps(IAMVideoControl
*iface
, IPin
*pin
, LONG
*flags
)
757 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
759 FIXME("filter %p, pin %p, flags %p: stub.\n", filter
, pin
, flags
);
764 static HRESULT WINAPI
video_control_SetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG mode
)
766 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
768 FIXME("filter %p, pin %p, mode %d: stub.\n", filter
, pin
, mode
);
773 static HRESULT WINAPI
video_control_GetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG
*mode
)
775 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
777 FIXME("filter %p, pin %p, mode %p: stub.\n", filter
, pin
, mode
);
782 static HRESULT WINAPI
video_control_GetCurrentActualFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
783 LONGLONG
*frame_rate
)
785 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
787 FIXME("filter %p, pin %p, frame rate %p: stub.\n", filter
, pin
, frame_rate
);
792 static HRESULT WINAPI
video_control_GetMaxAvailableFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
793 LONG index
, SIZE dimensions
, LONGLONG
*frame_rate
)
795 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
797 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), frame rate %p: stub.\n",
798 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, frame_rate
);
803 static HRESULT WINAPI
video_control_GetFrameRateList(IAMVideoControl
*iface
, IPin
*pin
, LONG index
,
804 SIZE dimensions
, LONG
*list_size
, LONGLONG
**frame_rate
)
806 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
808 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), list size %p, frame rate: %p: stub.\n",
809 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, list_size
, frame_rate
);
814 static const IAMVideoControlVtbl IAMVideoControl_VTable
=
816 video_control_QueryInterface
,
817 video_control_AddRef
,
818 video_control_Release
,
819 video_control_GetCaps
,
820 video_control_SetMode
,
821 video_control_GetMode
,
822 video_control_GetCurrentActualFrameRate
,
823 video_control_GetMaxAvailableFrameRate
,
824 video_control_GetFrameRateList
827 static BOOL WINAPI
load_capture_funcs(INIT_ONCE
*once
, void *param
, void **context
)
829 __wine_init_unix_lib(qcap_instance
, DLL_PROCESS_ATTACH
, NULL
, &capture_funcs
);
833 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
835 HRESULT
vfw_capture_create(IUnknown
*outer
, IUnknown
**out
)
837 struct vfw_capture
*object
;
839 if (!InitOnceExecuteOnce(&init_once
, load_capture_funcs
, NULL
, NULL
) || !capture_funcs
)
842 if (!(object
= calloc(1, sizeof(*object
))))
843 return E_OUTOFMEMORY
;
845 strmbase_filter_init(&object
->filter
, outer
, &CLSID_VfwCapture
, &filter_ops
);
847 object
->IAMStreamConfig_iface
.lpVtbl
= &IAMStreamConfig_VTable
;
848 object
->IAMVideoControl_iface
.lpVtbl
= &IAMVideoControl_VTable
;
849 object
->IAMVideoProcAmp_iface
.lpVtbl
= &IAMVideoProcAmp_VTable
;
850 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_VTable
;
851 object
->IPersistPropertyBag_iface
.lpVtbl
= &IPersistPropertyBag_VTable
;
853 strmbase_source_init(&object
->source
, &object
->filter
, L
"Output", &source_ops
);
855 object
->IKsPropertySet_iface
.lpVtbl
= &IKsPropertySet_VTable
;
857 object
->state
= State_Stopped
;
858 InitializeConditionVariable(&object
->state_cv
);
859 InitializeCriticalSection(&object
->state_cs
);
860 object
->state_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": vfw_capture.state_cs");
862 TRACE("Created VFW capture filter %p.\n", object
);
863 *out
= &object
->filter
.IUnknown_inner
;