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(qcap
);
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
);
110 ObjectRefCount(FALSE
);
113 static HRESULT
vfw_capture_query_interface(struct strmbase_filter
*iface
, REFIID iid
, void **out
)
115 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
117 if (IsEqualGUID(iid
, &IID_IPersistPropertyBag
))
118 *out
= &filter
->IPersistPropertyBag_iface
;
119 else if (IsEqualGUID(iid
, &IID_IAMVideoControl
))
120 *out
= &filter
->IAMVideoControl_iface
;
121 else if (IsEqualGUID(iid
, &IID_IAMVideoProcAmp
))
122 *out
= &filter
->IAMVideoProcAmp_iface
;
123 else if (IsEqualGUID(iid
, &IID_IAMFilterMiscFlags
))
124 *out
= &filter
->IAMFilterMiscFlags_iface
;
126 return E_NOINTERFACE
;
128 IUnknown_AddRef((IUnknown
*)*out
);
132 static unsigned int get_image_size(struct vfw_capture
*filter
)
134 const VIDEOINFOHEADER
*format
= (const VIDEOINFOHEADER
*)filter
->source
.pin
.mt
.pbFormat
;
136 return format
->bmiHeader
.biWidth
* format
->bmiHeader
.biHeight
* format
->bmiHeader
.biBitCount
/ 8;
139 static DWORD WINAPI
stream_thread(void *arg
)
141 struct vfw_capture
*filter
= arg
;
142 const unsigned int image_size
= get_image_size(filter
);
146 IMediaSample
*sample
;
150 EnterCriticalSection(&filter
->state_cs
);
152 while (filter
->state
== State_Paused
)
153 SleepConditionVariableCS(&filter
->state_cv
, &filter
->state_cs
, INFINITE
);
155 if (filter
->state
== State_Stopped
)
157 LeaveCriticalSection(&filter
->state_cs
);
161 LeaveCriticalSection(&filter
->state_cs
);
163 if (FAILED(hr
= BaseOutputPinImpl_GetDeliveryBuffer(&filter
->source
, &sample
, NULL
, NULL
, 0)))
165 ERR("Failed to get sample, hr %#x.\n", hr
);
169 IMediaSample_SetActualDataLength(sample
, image_size
);
170 IMediaSample_GetPointer(sample
, &data
);
172 if (!capture_funcs
->read_frame(filter
->device
, data
))
174 IMediaSample_Release(sample
);
178 hr
= IMemInputPin_Receive(filter
->source
.pMemInputPin
, sample
);
179 IMediaSample_Release(sample
);
182 ERR("IMemInputPin::Receive() returned %#x.\n", hr
);
190 static HRESULT
vfw_capture_init_stream(struct strmbase_filter
*iface
)
192 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
193 ALLOCATOR_PROPERTIES req_props
, ret_props
;
196 req_props
.cBuffers
= 3;
197 req_props
.cbBuffer
= get_image_size(filter
);
198 req_props
.cbAlign
= 1;
199 req_props
.cbPrefix
= 0;
200 if (FAILED(hr
= IMemAllocator_SetProperties(filter
->source
.pAllocator
, &req_props
, &ret_props
))
201 && hr
!= VFW_E_ALREADY_COMMITTED
)
202 ERR("Failed to set allocator properties (buffer size %u), hr %#x.\n", req_props
.cbBuffer
, hr
);
204 if (FAILED(hr
= IMemAllocator_Commit(filter
->source
.pAllocator
)))
205 ERR("Failed to commit allocator, hr %#x.\n", hr
);
207 EnterCriticalSection(&filter
->state_cs
);
208 filter
->state
= State_Paused
;
209 LeaveCriticalSection(&filter
->state_cs
);
211 filter
->thread
= CreateThread(NULL
, 0, stream_thread
, filter
, 0, NULL
);
216 static HRESULT
vfw_capture_start_stream(struct strmbase_filter
*iface
, REFERENCE_TIME time
)
218 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
220 EnterCriticalSection(&filter
->state_cs
);
221 filter
->state
= State_Running
;
222 LeaveCriticalSection(&filter
->state_cs
);
223 WakeConditionVariable(&filter
->state_cv
);
227 static HRESULT
vfw_capture_stop_stream(struct strmbase_filter
*iface
)
229 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
231 EnterCriticalSection(&filter
->state_cs
);
232 filter
->state
= State_Paused
;
233 LeaveCriticalSection(&filter
->state_cs
);
237 static HRESULT
vfw_capture_cleanup_stream(struct strmbase_filter
*iface
)
239 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
242 EnterCriticalSection(&filter
->state_cs
);
243 filter
->state
= State_Stopped
;
244 LeaveCriticalSection(&filter
->state_cs
);
245 WakeConditionVariable(&filter
->state_cv
);
247 WaitForSingleObject(filter
->thread
, INFINITE
);
248 CloseHandle(filter
->thread
);
249 filter
->thread
= NULL
;
251 hr
= IMemAllocator_Decommit(filter
->source
.pAllocator
);
252 if (hr
!= S_OK
&& hr
!= VFW_E_NOT_COMMITTED
)
253 ERR("Failed to decommit allocator, hr %#x.\n", hr
);
258 static HRESULT
vfw_capture_wait_state(struct strmbase_filter
*iface
, DWORD timeout
)
260 return iface
->state
== State_Paused
? VFW_S_CANT_CUE
: S_OK
;
263 static const struct strmbase_filter_ops filter_ops
=
265 .filter_get_pin
= vfw_capture_get_pin
,
266 .filter_destroy
= vfw_capture_destroy
,
267 .filter_query_interface
= vfw_capture_query_interface
,
268 .filter_init_stream
= vfw_capture_init_stream
,
269 .filter_start_stream
= vfw_capture_start_stream
,
270 .filter_stop_stream
= vfw_capture_stop_stream
,
271 .filter_cleanup_stream
= vfw_capture_cleanup_stream
,
272 .filter_wait_state
= vfw_capture_wait_state
,
275 static HRESULT WINAPI
AMStreamConfig_QueryInterface(IAMStreamConfig
*iface
, REFIID iid
, void **out
)
277 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
278 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
281 static ULONG WINAPI
AMStreamConfig_AddRef(IAMStreamConfig
*iface
)
283 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
284 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
287 static ULONG WINAPI
AMStreamConfig_Release(IAMStreamConfig
*iface
)
289 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
290 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
293 static HRESULT WINAPI
294 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
296 struct vfw_capture
*This
= impl_from_IAMStreamConfig(iface
);
299 TRACE("filter %p, mt %p.\n", This
, pmt
);
300 strmbase_dump_media_type(pmt
);
302 if (This
->filter
.state
!= State_Stopped
)
304 TRACE("Returning not stopped error\n");
305 return VFW_E_NOT_STOPPED
;
310 TRACE("pmt is NULL\n");
314 if (!IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
317 if (This
->source
.pin
.peer
)
319 hr
= IPin_QueryAccept(This
->source
.pin
.peer
, pmt
);
320 TRACE("Would accept: %d\n", hr
);
322 return VFW_E_INVALIDMEDIATYPE
;
325 hr
= capture_funcs
->set_format(This
->device
, pmt
);
326 if (SUCCEEDED(hr
) && This
->filter
.graph
&& This
->source
.pin
.peer
)
328 hr
= IFilterGraph_Reconnect(This
->filter
.graph
, &This
->source
.pin
.IPin_iface
);
330 TRACE("Reconnection completed, with new media format..\n");
332 TRACE("Returning: %d\n", hr
);
336 static HRESULT WINAPI
AMStreamConfig_GetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**mt
)
338 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
339 VIDEOINFOHEADER
*format
;
342 TRACE("filter %p, mt %p.\n", filter
, mt
);
344 if (!(*mt
= CoTaskMemAlloc(sizeof(**mt
))))
345 return E_OUTOFMEMORY
;
347 EnterCriticalSection(&filter
->filter
.filter_cs
);
349 if (filter
->source
.pin
.peer
)
351 hr
= CopyMediaType(*mt
, &filter
->source
.pin
.mt
);
355 if ((format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
357 capture_funcs
->get_format(filter
->device
, *mt
, format
);
358 (*mt
)->cbFormat
= sizeof(VIDEOINFOHEADER
);
359 (*mt
)->pbFormat
= (BYTE
*)format
;
368 LeaveCriticalSection(&filter
->filter
.filter_cs
);
371 strmbase_dump_media_type(*mt
);
377 static HRESULT WINAPI
AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig
*iface
,
378 int *count
, int *size
)
380 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
382 TRACE("filter %p, count %p, size %p.\n", filter
, count
, size
);
387 *count
= capture_funcs
->get_caps_count(filter
->device
);
388 *size
= sizeof(VIDEO_STREAM_CONFIG_CAPS
);
393 static HRESULT WINAPI
AMStreamConfig_GetStreamCaps(IAMStreamConfig
*iface
,
394 int index
, AM_MEDIA_TYPE
**pmt
, BYTE
*vscc
)
396 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
397 VIDEOINFOHEADER
*format
;
400 TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter
, index
, pmt
, vscc
);
402 if (index
> capture_funcs
->get_caps_count(filter
->device
))
405 if (!(mt
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
))))
406 return E_OUTOFMEMORY
;
408 if (!(format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
411 return E_OUTOFMEMORY
;
414 capture_funcs
->get_caps(filter
->device
, index
, mt
, format
, (VIDEO_STREAM_CONFIG_CAPS
*)vscc
);
415 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
416 mt
->pbFormat
= (BYTE
*)format
;
421 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
423 AMStreamConfig_QueryInterface
,
424 AMStreamConfig_AddRef
,
425 AMStreamConfig_Release
,
426 AMStreamConfig_SetFormat
,
427 AMStreamConfig_GetFormat
,
428 AMStreamConfig_GetNumberOfCapabilities
,
429 AMStreamConfig_GetStreamCaps
432 static HRESULT WINAPI
AMVideoProcAmp_QueryInterface(IAMVideoProcAmp
*iface
, REFIID iid
, void **out
)
434 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
435 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
438 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
440 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
441 return IUnknown_AddRef(filter
->filter
.outer_unk
);
444 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
446 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
447 return IUnknown_Release(filter
->filter
.outer_unk
);
450 static HRESULT WINAPI
AMVideoProcAmp_GetRange(IAMVideoProcAmp
*iface
, LONG property
,
451 LONG
*min
, LONG
*max
, LONG
*step
, LONG
*default_value
, LONG
*flags
)
453 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
455 TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n",
456 filter
, property
, min
, max
, step
, default_value
, flags
);
458 return capture_funcs
->get_prop_range(filter
->device
, property
, min
,
459 max
, step
, default_value
, flags
);
462 static HRESULT WINAPI
AMVideoProcAmp_Set(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 %d, flags %#x.\n", filter
, property
, value
, flags
);
469 return capture_funcs
->set_prop(filter
->device
, property
, value
, flags
);
472 static HRESULT WINAPI
AMVideoProcAmp_Get(IAMVideoProcAmp
*iface
, LONG property
,
473 LONG
*value
, LONG
*flags
)
475 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
477 TRACE("filter %p, property %#x, value %p, flags %p.\n", filter
, property
, value
, flags
);
479 return capture_funcs
->get_prop(filter
->device
, property
, value
, flags
);
482 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
484 AMVideoProcAmp_QueryInterface
,
485 AMVideoProcAmp_AddRef
,
486 AMVideoProcAmp_Release
,
487 AMVideoProcAmp_GetRange
,
492 static HRESULT WINAPI
PPB_QueryInterface(IPersistPropertyBag
*iface
, REFIID iid
, void **out
)
494 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
495 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
498 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
500 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
501 return IUnknown_AddRef(filter
->filter
.outer_unk
);
504 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
506 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
507 return IUnknown_Release(filter
->filter
.outer_unk
);
510 static HRESULT WINAPI
511 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
513 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
515 FIXME("%p - stub\n", This
);
520 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
522 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
524 FIXME("%p - stub\n", This
);
529 static HRESULT WINAPI
PPB_Load(IPersistPropertyBag
*iface
, IPropertyBag
*bag
, IErrorLog
*error_log
)
531 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
535 TRACE("filter %p, bag %p, error_log %p.\n", filter
, bag
, error_log
);
538 if (FAILED(hr
= IPropertyBag_Read(bag
, L
"VFWIndex", &var
, error_log
)))
541 if (!(filter
->device
= capture_funcs
->create(V_I4(&var
))))
548 static HRESULT WINAPI
549 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
550 BOOL fClearDirty
, BOOL fSaveAllProperties
)
552 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
553 FIXME("%p - stub\n", This
);
557 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
568 /* IKsPropertySet interface */
569 static inline struct vfw_capture
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
571 return CONTAINING_RECORD(iface
, struct vfw_capture
, IKsPropertySet_iface
);
574 static HRESULT WINAPI
KSP_QueryInterface(IKsPropertySet
*iface
, REFIID iid
, void **out
)
576 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
577 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
580 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
582 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
583 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
586 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
588 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
589 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
592 static HRESULT WINAPI
593 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
594 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
597 FIXME("%p: stub\n", iface
);
601 static HRESULT WINAPI
602 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
603 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
604 DWORD cbPropData
, DWORD
*pcbReturned
)
610 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
611 return E_PROP_SET_UNSUPPORTED
;
612 if (pPropData
== NULL
&& pcbReturned
== NULL
)
615 *pcbReturned
= sizeof(GUID
);
616 if (pPropData
== NULL
)
618 if (cbPropData
< sizeof(GUID
))
621 *pGuid
= PIN_CATEGORY_CAPTURE
;
622 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
626 static HRESULT WINAPI
627 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
628 DWORD dwPropID
, DWORD
*pTypeSupport
)
630 FIXME("%p: stub\n", iface
);
634 static const IKsPropertySetVtbl IKsPropertySet_VTable
=
644 static inline struct vfw_capture
*impl_from_strmbase_pin(struct strmbase_pin
*pin
)
646 return CONTAINING_RECORD(pin
, struct vfw_capture
, source
.pin
);
649 static HRESULT
source_query_accept(struct strmbase_pin
*pin
, const AM_MEDIA_TYPE
*mt
)
651 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
652 return capture_funcs
->check_format(filter
->device
, mt
);
655 static HRESULT
source_get_media_type(struct strmbase_pin
*pin
,
656 unsigned int index
, AM_MEDIA_TYPE
*mt
)
658 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
659 VIDEOINFOHEADER
*format
;
662 if (!(format
= CoTaskMemAlloc(sizeof(*format
))))
663 return E_OUTOFMEMORY
;
665 if ((hr
= capture_funcs
->get_media_type(filter
->device
, index
, mt
, format
)) != S_OK
)
667 CoTaskMemFree(format
);
670 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
671 mt
->pbFormat
= (BYTE
*)format
;
675 static HRESULT
source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
677 struct vfw_capture
*filter
= impl_from_strmbase_pin(iface
);
679 if (IsEqualGUID(iid
, &IID_IKsPropertySet
))
680 *out
= &filter
->IKsPropertySet_iface
;
681 else if (IsEqualGUID(iid
, &IID_IAMStreamConfig
))
682 *out
= &filter
->IAMStreamConfig_iface
;
684 return E_NOINTERFACE
;
686 IUnknown_AddRef((IUnknown
*)*out
);
690 static HRESULT WINAPI
VfwPin_DecideBufferSize(struct strmbase_source
*iface
,
691 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 struct strmbase_source_ops source_ops
=
709 .base
.pin_query_accept
= source_query_accept
,
710 .base
.pin_get_media_type
= source_get_media_type
,
711 .base
.pin_query_interface
= source_query_interface
,
712 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
713 .pfnDecideBufferSize
= VfwPin_DecideBufferSize
,
714 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
717 static HRESULT WINAPI
misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
)
719 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
720 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
723 static ULONG WINAPI
misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
725 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
726 return IUnknown_AddRef(filter
->filter
.outer_unk
);
729 static ULONG WINAPI
misc_flags_Release(IAMFilterMiscFlags
*iface
)
731 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
732 return IUnknown_Release(filter
->filter
.outer_unk
);
735 static ULONG WINAPI
misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
737 return AM_FILTER_MISC_FLAGS_IS_SOURCE
;
740 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_VTable
=
742 misc_flags_QueryInterface
,
745 misc_flags_GetMiscFlags
748 static HRESULT WINAPI
video_control_QueryInterface(IAMVideoControl
*iface
, REFIID riid
, void **ppv
)
750 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
751 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
754 static ULONG WINAPI
video_control_AddRef(IAMVideoControl
*iface
)
756 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
757 return IUnknown_AddRef(filter
->filter
.outer_unk
);
760 static ULONG WINAPI
video_control_Release(IAMVideoControl
*iface
)
762 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
763 return IUnknown_Release(filter
->filter
.outer_unk
);
766 static HRESULT WINAPI
video_control_GetCaps(IAMVideoControl
*iface
, IPin
*pin
, LONG
*flags
)
768 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
770 FIXME("filter %p, pin %p, flags %p: stub.\n", filter
, pin
, flags
);
775 static HRESULT WINAPI
video_control_SetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG mode
)
777 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
779 FIXME("filter %p, pin %p, mode %d: stub.\n", filter
, pin
, mode
);
784 static HRESULT WINAPI
video_control_GetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG
*mode
)
786 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
788 FIXME("filter %p, pin %p, mode %p: stub.\n", filter
, pin
, mode
);
793 static HRESULT WINAPI
video_control_GetCurrentActualFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
794 LONGLONG
*frame_rate
)
796 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
798 FIXME("filter %p, pin %p, frame rate %p: stub.\n", filter
, pin
, frame_rate
);
803 static HRESULT WINAPI
video_control_GetMaxAvailableFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
804 LONG index
, SIZE dimensions
, LONGLONG
*frame_rate
)
806 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
808 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), frame rate %p: stub.\n",
809 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, frame_rate
);
814 static HRESULT WINAPI
video_control_GetFrameRateList(IAMVideoControl
*iface
, IPin
*pin
, LONG index
,
815 SIZE dimensions
, LONG
*list_size
, LONGLONG
**frame_rate
)
817 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
819 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), list size %p, frame rate: %p: stub.\n",
820 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, list_size
, frame_rate
);
825 static const IAMVideoControlVtbl IAMVideoControl_VTable
=
827 video_control_QueryInterface
,
828 video_control_AddRef
,
829 video_control_Release
,
830 video_control_GetCaps
,
831 video_control_SetMode
,
832 video_control_GetMode
,
833 video_control_GetCurrentActualFrameRate
,
834 video_control_GetMaxAvailableFrameRate
,
835 video_control_GetFrameRateList
838 static BOOL WINAPI
load_capture_funcs(INIT_ONCE
*once
, void *param
, void **context
)
840 __wine_init_unix_lib(qcap_instance
, DLL_PROCESS_ATTACH
, NULL
, &capture_funcs
);
844 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
846 HRESULT
vfw_capture_create(IUnknown
*outer
, IUnknown
**out
)
848 struct vfw_capture
*object
;
850 if (!InitOnceExecuteOnce(&init_once
, load_capture_funcs
, NULL
, NULL
) || !capture_funcs
)
853 if (!(object
= calloc(1, sizeof(*object
))))
854 return E_OUTOFMEMORY
;
856 strmbase_filter_init(&object
->filter
, outer
, &CLSID_VfwCapture
, &filter_ops
);
858 object
->IAMStreamConfig_iface
.lpVtbl
= &IAMStreamConfig_VTable
;
859 object
->IAMVideoControl_iface
.lpVtbl
= &IAMVideoControl_VTable
;
860 object
->IAMVideoProcAmp_iface
.lpVtbl
= &IAMVideoProcAmp_VTable
;
861 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_VTable
;
862 object
->IPersistPropertyBag_iface
.lpVtbl
= &IPersistPropertyBag_VTable
;
864 strmbase_source_init(&object
->source
, &object
->filter
, L
"Output", &source_ops
);
866 object
->IKsPropertySet_iface
.lpVtbl
= &IKsPropertySet_VTable
;
868 object
->state
= State_Stopped
;
869 InitializeConditionVariable(&object
->state_cv
);
870 InitializeCriticalSection(&object
->state_cs
);
871 object
->state_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": vfw_capture.state_cs");
873 TRACE("Created VFW capture filter %p.\n", object
);
874 ObjectRefCount(TRUE
);
875 *out
= &object
->filter
.IUnknown_inner
;