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"
23 WINE_DEFAULT_DEBUG_CHANNEL(qcap
);
25 static const struct video_capture_funcs
*capture_funcs
;
29 struct strmbase_filter filter
;
30 IAMStreamConfig IAMStreamConfig_iface
;
31 IAMVideoControl IAMVideoControl_iface
;
32 IAMVideoProcAmp IAMVideoProcAmp_iface
;
33 IAMFilterMiscFlags IAMFilterMiscFlags_iface
;
34 IPersistPropertyBag IPersistPropertyBag_iface
;
37 struct strmbase_source source
;
38 IKsPropertySet IKsPropertySet_iface
;
40 struct video_capture_device
*device
;
42 /* FIXME: It would be nice to avoid duplicating this variable with strmbase.
43 * However, synchronization is tricky; we need access to be protected by a
46 CONDITION_VARIABLE state_cv
;
47 CRITICAL_SECTION state_cs
;
52 static inline struct vfw_capture
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
54 return CONTAINING_RECORD(iface
, struct vfw_capture
, filter
);
57 static inline struct vfw_capture
*impl_from_IAMStreamConfig(IAMStreamConfig
*iface
)
59 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMStreamConfig_iface
);
62 static inline struct vfw_capture
*impl_from_IAMVideoControl(IAMVideoControl
*iface
)
64 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMVideoControl_iface
);
67 static inline struct vfw_capture
*impl_from_IAMVideoProcAmp(IAMVideoProcAmp
*iface
)
69 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMVideoProcAmp_iface
);
72 static inline struct vfw_capture
*impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags
*iface
)
74 return CONTAINING_RECORD(iface
, struct vfw_capture
, IAMFilterMiscFlags_iface
);
77 static inline struct vfw_capture
*impl_from_IPersistPropertyBag(IPersistPropertyBag
*iface
)
79 return CONTAINING_RECORD(iface
, struct vfw_capture
, IPersistPropertyBag_iface
);
82 static struct strmbase_pin
*vfw_capture_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
84 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
89 return &filter
->source
.pin
;
92 static void vfw_capture_destroy(struct strmbase_filter
*iface
)
94 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
98 if (filter
->filter
.state
!= State_Stopped
)
99 capture_funcs
->cleanup_stream(filter
->device
);
100 capture_funcs
->destroy(filter
->device
);
103 if (filter
->source
.pin
.peer
)
105 IPin_Disconnect(filter
->source
.pin
.peer
);
106 IPin_Disconnect(&filter
->source
.pin
.IPin_iface
);
108 filter
->state_cs
.DebugInfo
->Spare
[0] = 0;
109 DeleteCriticalSection(&filter
->state_cs
);
110 strmbase_source_cleanup(&filter
->source
);
111 strmbase_filter_cleanup(&filter
->filter
);
112 CoTaskMemFree(filter
);
113 ObjectRefCount(FALSE
);
116 static HRESULT
vfw_capture_query_interface(struct strmbase_filter
*iface
, REFIID iid
, void **out
)
118 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
120 if (IsEqualGUID(iid
, &IID_IPersistPropertyBag
))
121 *out
= &filter
->IPersistPropertyBag_iface
;
122 else if (IsEqualGUID(iid
, &IID_IAMVideoControl
))
123 *out
= &filter
->IAMVideoControl_iface
;
124 else if (IsEqualGUID(iid
, &IID_IAMVideoProcAmp
))
125 *out
= &filter
->IAMVideoProcAmp_iface
;
126 else if (IsEqualGUID(iid
, &IID_IAMFilterMiscFlags
))
127 *out
= &filter
->IAMFilterMiscFlags_iface
;
129 return E_NOINTERFACE
;
131 IUnknown_AddRef((IUnknown
*)*out
);
135 static DWORD WINAPI
stream_thread(void *arg
)
137 struct vfw_capture
*filter
= arg
;
138 const VIDEOINFOHEADER
*format
= (const VIDEOINFOHEADER
*)filter
->source
.pin
.mt
.pbFormat
;
139 const unsigned int image_size
= format
->bmiHeader
.biWidth
140 * format
->bmiHeader
.biHeight
* format
->bmiHeader
.biBitCount
/ 8;
144 IMediaSample
*sample
;
148 EnterCriticalSection(&filter
->state_cs
);
150 while (filter
->state
== State_Paused
)
151 SleepConditionVariableCS(&filter
->state_cv
, &filter
->state_cs
, INFINITE
);
153 if (filter
->state
== State_Stopped
)
155 LeaveCriticalSection(&filter
->state_cs
);
159 LeaveCriticalSection(&filter
->state_cs
);
161 if (FAILED(hr
= BaseOutputPinImpl_GetDeliveryBuffer(&filter
->source
, &sample
, NULL
, NULL
, 0)))
163 ERR("Failed to get sample, hr %#x.\n", hr
);
167 IMediaSample_SetActualDataLength(sample
, image_size
);
168 IMediaSample_GetPointer(sample
, &data
);
170 if (!capture_funcs
->read_frame(filter
->device
, data
))
172 IMediaSample_Release(sample
);
176 hr
= IMemInputPin_Receive(filter
->source
.pMemInputPin
, sample
);
177 IMediaSample_Release(sample
);
180 ERR("IMemInputPin::Receive() returned %#x.\n", hr
);
188 static HRESULT
vfw_capture_init_stream(struct strmbase_filter
*iface
)
190 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
192 capture_funcs
->init_stream(filter
->device
);
194 EnterCriticalSection(&filter
->state_cs
);
195 filter
->state
= State_Paused
;
196 LeaveCriticalSection(&filter
->state_cs
);
198 filter
->thread
= CreateThread(NULL
, 0, stream_thread
, filter
, 0, NULL
);
203 static HRESULT
vfw_capture_start_stream(struct strmbase_filter
*iface
, REFERENCE_TIME time
)
205 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
207 EnterCriticalSection(&filter
->state_cs
);
208 filter
->state
= State_Running
;
209 LeaveCriticalSection(&filter
->state_cs
);
210 WakeConditionVariable(&filter
->state_cv
);
214 static HRESULT
vfw_capture_stop_stream(struct strmbase_filter
*iface
)
216 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
218 EnterCriticalSection(&filter
->state_cs
);
219 filter
->state
= State_Paused
;
220 LeaveCriticalSection(&filter
->state_cs
);
224 static HRESULT
vfw_capture_cleanup_stream(struct strmbase_filter
*iface
)
226 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
228 EnterCriticalSection(&filter
->state_cs
);
229 filter
->state
= State_Stopped
;
230 LeaveCriticalSection(&filter
->state_cs
);
231 WakeConditionVariable(&filter
->state_cv
);
233 WaitForSingleObject(filter
->thread
, INFINITE
);
234 CloseHandle(filter
->thread
);
235 filter
->thread
= NULL
;
237 capture_funcs
->cleanup_stream(filter
->device
);
241 static HRESULT
vfw_capture_wait_state(struct strmbase_filter
*iface
, DWORD timeout
)
243 return iface
->state
== State_Paused
? VFW_S_CANT_CUE
: S_OK
;
246 static const struct strmbase_filter_ops filter_ops
=
248 .filter_get_pin
= vfw_capture_get_pin
,
249 .filter_destroy
= vfw_capture_destroy
,
250 .filter_query_interface
= vfw_capture_query_interface
,
251 .filter_init_stream
= vfw_capture_init_stream
,
252 .filter_start_stream
= vfw_capture_start_stream
,
253 .filter_stop_stream
= vfw_capture_stop_stream
,
254 .filter_cleanup_stream
= vfw_capture_cleanup_stream
,
255 .filter_wait_state
= vfw_capture_wait_state
,
258 static HRESULT WINAPI
AMStreamConfig_QueryInterface(IAMStreamConfig
*iface
, REFIID iid
, void **out
)
260 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
261 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
264 static ULONG WINAPI
AMStreamConfig_AddRef(IAMStreamConfig
*iface
)
266 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
267 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
270 static ULONG WINAPI
AMStreamConfig_Release(IAMStreamConfig
*iface
)
272 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
273 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
276 static HRESULT WINAPI
277 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
279 struct vfw_capture
*This
= impl_from_IAMStreamConfig(iface
);
282 TRACE("filter %p, mt %p.\n", This
, pmt
);
283 strmbase_dump_media_type(pmt
);
285 if (This
->filter
.state
!= State_Stopped
)
287 TRACE("Returning not stopped error\n");
288 return VFW_E_NOT_STOPPED
;
293 TRACE("pmt is NULL\n");
297 if (!IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
300 if (This
->source
.pin
.peer
)
302 hr
= IPin_QueryAccept(This
->source
.pin
.peer
, pmt
);
303 TRACE("Would accept: %d\n", hr
);
305 return VFW_E_INVALIDMEDIATYPE
;
308 hr
= capture_funcs
->set_format(This
->device
, pmt
);
309 if (SUCCEEDED(hr
) && This
->filter
.graph
&& This
->source
.pin
.peer
)
311 hr
= IFilterGraph_Reconnect(This
->filter
.graph
, &This
->source
.pin
.IPin_iface
);
313 TRACE("Reconnection completed, with new media format..\n");
315 TRACE("Returning: %d\n", hr
);
319 static HRESULT WINAPI
AMStreamConfig_GetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**mt
)
321 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
324 TRACE("filter %p, mt %p.\n", filter
, mt
);
326 if (!(*mt
= CoTaskMemAlloc(sizeof(**mt
))))
327 return E_OUTOFMEMORY
;
329 if (SUCCEEDED(hr
= capture_funcs
->get_format(filter
->device
, *mt
)))
330 strmbase_dump_media_type(*mt
);
334 static HRESULT WINAPI
AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig
*iface
,
335 int *count
, int *size
)
337 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
339 TRACE("filter %p, count %p, size %p.\n", filter
, count
, size
);
344 *count
= capture_funcs
->get_caps_count(filter
->device
);
345 *size
= sizeof(VIDEO_STREAM_CONFIG_CAPS
);
350 static HRESULT WINAPI
AMStreamConfig_GetStreamCaps(IAMStreamConfig
*iface
,
351 int index
, AM_MEDIA_TYPE
**pmt
, BYTE
*vscc
)
353 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
355 TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter
, index
, pmt
, vscc
);
357 return capture_funcs
->get_caps(filter
->device
, index
, pmt
, (VIDEO_STREAM_CONFIG_CAPS
*)vscc
);
360 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
362 AMStreamConfig_QueryInterface
,
363 AMStreamConfig_AddRef
,
364 AMStreamConfig_Release
,
365 AMStreamConfig_SetFormat
,
366 AMStreamConfig_GetFormat
,
367 AMStreamConfig_GetNumberOfCapabilities
,
368 AMStreamConfig_GetStreamCaps
371 static HRESULT WINAPI
AMVideoProcAmp_QueryInterface(IAMVideoProcAmp
*iface
, REFIID iid
, void **out
)
373 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
374 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
377 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
379 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
380 return IUnknown_AddRef(filter
->filter
.outer_unk
);
383 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
385 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
386 return IUnknown_Release(filter
->filter
.outer_unk
);
389 static HRESULT WINAPI
AMVideoProcAmp_GetRange(IAMVideoProcAmp
*iface
, LONG property
,
390 LONG
*min
, LONG
*max
, LONG
*step
, LONG
*default_value
, LONG
*flags
)
392 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
394 TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n",
395 filter
, property
, min
, max
, step
, default_value
, flags
);
397 return capture_funcs
->get_prop_range(filter
->device
, property
, min
,
398 max
, step
, default_value
, flags
);
401 static HRESULT WINAPI
AMVideoProcAmp_Set(IAMVideoProcAmp
*iface
, LONG property
,
402 LONG value
, LONG flags
)
404 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
406 TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter
, property
, value
, flags
);
408 return capture_funcs
->set_prop(filter
->device
, property
, value
, flags
);
411 static HRESULT WINAPI
AMVideoProcAmp_Get(IAMVideoProcAmp
*iface
, LONG property
,
412 LONG
*value
, LONG
*flags
)
414 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
416 TRACE("filter %p, property %#x, value %p, flags %p.\n", filter
, property
, value
, flags
);
418 return capture_funcs
->get_prop(filter
->device
, property
, value
, flags
);
421 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
423 AMVideoProcAmp_QueryInterface
,
424 AMVideoProcAmp_AddRef
,
425 AMVideoProcAmp_Release
,
426 AMVideoProcAmp_GetRange
,
431 static HRESULT WINAPI
PPB_QueryInterface(IPersistPropertyBag
*iface
, REFIID iid
, void **out
)
433 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
434 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
437 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
439 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
440 return IUnknown_AddRef(filter
->filter
.outer_unk
);
443 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
445 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
446 return IUnknown_Release(filter
->filter
.outer_unk
);
449 static HRESULT WINAPI
450 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
452 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
454 FIXME("%p - stub\n", This
);
459 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
461 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
463 FIXME("%p - stub\n", This
);
468 static HRESULT WINAPI
PPB_Load(IPersistPropertyBag
*iface
, IPropertyBag
*bag
, IErrorLog
*error_log
)
470 static const OLECHAR VFWIndex
[] = {'V','F','W','I','n','d','e','x',0};
471 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
475 TRACE("filter %p, bag %p, error_log %p.\n", filter
, bag
, error_log
);
478 if (FAILED(hr
= IPropertyBag_Read(bag
, VFWIndex
, &var
, error_log
)))
481 if (!(filter
->device
= capture_funcs
->create(&filter
->source
, V_I4(&var
))))
488 static HRESULT WINAPI
489 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
490 BOOL fClearDirty
, BOOL fSaveAllProperties
)
492 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
493 FIXME("%p - stub\n", This
);
497 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
508 /* IKsPropertySet interface */
509 static inline struct vfw_capture
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
511 return CONTAINING_RECORD(iface
, struct vfw_capture
, IKsPropertySet_iface
);
514 static HRESULT WINAPI
KSP_QueryInterface(IKsPropertySet
*iface
, REFIID iid
, void **out
)
516 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
517 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
520 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
522 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
523 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
526 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
528 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
529 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
532 static HRESULT WINAPI
533 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
534 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
537 FIXME("%p: stub\n", iface
);
541 static HRESULT WINAPI
542 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
543 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
544 DWORD cbPropData
, DWORD
*pcbReturned
)
550 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
551 return E_PROP_SET_UNSUPPORTED
;
552 if (pPropData
== NULL
&& pcbReturned
== NULL
)
555 *pcbReturned
= sizeof(GUID
);
556 if (pPropData
== NULL
)
558 if (cbPropData
< sizeof(GUID
))
561 *pGuid
= PIN_CATEGORY_CAPTURE
;
562 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
566 static HRESULT WINAPI
567 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
568 DWORD dwPropID
, DWORD
*pTypeSupport
)
570 FIXME("%p: stub\n", iface
);
574 static const IKsPropertySetVtbl IKsPropertySet_VTable
=
584 static inline struct vfw_capture
*impl_from_strmbase_pin(struct strmbase_pin
*pin
)
586 return CONTAINING_RECORD(pin
, struct vfw_capture
, source
.pin
);
589 static HRESULT
source_query_accept(struct strmbase_pin
*pin
, const AM_MEDIA_TYPE
*mt
)
591 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
592 return capture_funcs
->check_format(filter
->device
, mt
);
595 static HRESULT
source_get_media_type(struct strmbase_pin
*pin
,
596 unsigned int index
, AM_MEDIA_TYPE
*mt
)
598 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
599 return capture_funcs
->get_media_type(filter
->device
, index
, mt
);
602 static HRESULT
source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
604 struct vfw_capture
*filter
= impl_from_strmbase_pin(iface
);
606 if (IsEqualGUID(iid
, &IID_IKsPropertySet
))
607 *out
= &filter
->IKsPropertySet_iface
;
608 else if (IsEqualGUID(iid
, &IID_IAMStreamConfig
))
609 *out
= &filter
->IAMStreamConfig_iface
;
611 return E_NOINTERFACE
;
613 IUnknown_AddRef((IUnknown
*)*out
);
617 static HRESULT WINAPI
VfwPin_DecideBufferSize(struct strmbase_source
*iface
,
618 IMemAllocator
*pAlloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
620 ALLOCATOR_PROPERTIES actual
;
622 /* What we put here doesn't matter, the
623 driver function should override it then commit */
624 if (!ppropInputRequest
->cBuffers
)
625 ppropInputRequest
->cBuffers
= 3;
626 if (!ppropInputRequest
->cbBuffer
)
627 ppropInputRequest
->cbBuffer
= 230400;
628 if (!ppropInputRequest
->cbAlign
)
629 ppropInputRequest
->cbAlign
= 1;
631 return IMemAllocator_SetProperties(pAlloc
, ppropInputRequest
, &actual
);
634 static const struct strmbase_source_ops source_ops
=
636 .base
.pin_query_accept
= source_query_accept
,
637 .base
.pin_get_media_type
= source_get_media_type
,
638 .base
.pin_query_interface
= source_query_interface
,
639 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
640 .pfnDecideBufferSize
= VfwPin_DecideBufferSize
,
641 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
644 static HRESULT WINAPI
misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
)
646 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
647 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
650 static ULONG WINAPI
misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
652 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
653 return IUnknown_AddRef(filter
->filter
.outer_unk
);
656 static ULONG WINAPI
misc_flags_Release(IAMFilterMiscFlags
*iface
)
658 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
659 return IUnknown_Release(filter
->filter
.outer_unk
);
662 static ULONG WINAPI
misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
664 return AM_FILTER_MISC_FLAGS_IS_SOURCE
;
667 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_VTable
=
669 misc_flags_QueryInterface
,
672 misc_flags_GetMiscFlags
675 static HRESULT WINAPI
video_control_QueryInterface(IAMVideoControl
*iface
, REFIID riid
, void **ppv
)
677 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
678 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
681 static ULONG WINAPI
video_control_AddRef(IAMVideoControl
*iface
)
683 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
684 return IUnknown_AddRef(filter
->filter
.outer_unk
);
687 static ULONG WINAPI
video_control_Release(IAMVideoControl
*iface
)
689 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
690 return IUnknown_Release(filter
->filter
.outer_unk
);
693 static HRESULT WINAPI
video_control_GetCaps(IAMVideoControl
*iface
, IPin
*pin
, LONG
*flags
)
695 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
697 FIXME("filter %p, pin %p, flags %p: stub.\n", filter
, pin
, flags
);
702 static HRESULT WINAPI
video_control_SetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG mode
)
704 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
706 FIXME("filter %p, pin %p, mode %d: stub.\n", filter
, pin
, mode
);
711 static HRESULT WINAPI
video_control_GetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG
*mode
)
713 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
715 FIXME("filter %p, pin %p, mode %p: stub.\n", filter
, pin
, mode
);
720 static HRESULT WINAPI
video_control_GetCurrentActualFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
721 LONGLONG
*frame_rate
)
723 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
725 FIXME("filter %p, pin %p, frame rate %p: stub.\n", filter
, pin
, frame_rate
);
730 static HRESULT WINAPI
video_control_GetMaxAvailableFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
731 LONG index
, SIZE dimensions
, LONGLONG
*frame_rate
)
733 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
735 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), frame rate %p: stub.\n",
736 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, frame_rate
);
741 static HRESULT WINAPI
video_control_GetFrameRateList(IAMVideoControl
*iface
, IPin
*pin
, LONG index
,
742 SIZE dimensions
, LONG
*list_size
, LONGLONG
**frame_rate
)
744 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
746 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), list size %p, frame rate: %p: stub.\n",
747 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, list_size
, frame_rate
);
752 static const IAMVideoControlVtbl IAMVideoControl_VTable
=
754 video_control_QueryInterface
,
755 video_control_AddRef
,
756 video_control_Release
,
757 video_control_GetCaps
,
758 video_control_SetMode
,
759 video_control_GetMode
,
760 video_control_GetCurrentActualFrameRate
,
761 video_control_GetMaxAvailableFrameRate
,
762 video_control_GetFrameRateList
765 static BOOL WINAPI
load_capture_funcs(INIT_ONCE
*once
, void *param
, void **context
)
767 capture_funcs
= &v4l_funcs
;
771 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
773 HRESULT
vfw_capture_create(IUnknown
*outer
, IUnknown
**out
)
775 static const WCHAR source_name
[] = {'O','u','t','p','u','t',0};
776 struct vfw_capture
*object
;
778 if (!InitOnceExecuteOnce(&init_once
, load_capture_funcs
, NULL
, NULL
))
781 if (!(object
= CoTaskMemAlloc(sizeof(*object
))))
782 return E_OUTOFMEMORY
;
784 strmbase_filter_init(&object
->filter
, outer
, &CLSID_VfwCapture
, &filter_ops
);
786 object
->IAMStreamConfig_iface
.lpVtbl
= &IAMStreamConfig_VTable
;
787 object
->IAMVideoControl_iface
.lpVtbl
= &IAMVideoControl_VTable
;
788 object
->IAMVideoProcAmp_iface
.lpVtbl
= &IAMVideoProcAmp_VTable
;
789 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_VTable
;
790 object
->IPersistPropertyBag_iface
.lpVtbl
= &IPersistPropertyBag_VTable
;
791 object
->init
= FALSE
;
793 strmbase_source_init(&object
->source
, &object
->filter
, source_name
, &source_ops
);
795 object
->IKsPropertySet_iface
.lpVtbl
= &IKsPropertySet_VTable
;
797 object
->state
= State_Stopped
;
798 InitializeConditionVariable(&object
->state_cv
);
799 InitializeCriticalSection(&object
->state_cs
);
800 object
->state_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": vfw_capture.state_cs");
802 TRACE("Created VFW capture filter %p.\n", object
);
803 ObjectRefCount(TRUE
);
804 *out
= &object
->filter
.IUnknown_inner
;