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
)))
202 ERR("Failed to set allocator properties (buffer size %u), hr %#x.\n", req_props
.cbBuffer
, hr
);
206 if (FAILED(hr
= IMemAllocator_Commit(filter
->source
.pAllocator
)))
207 ERR("Failed to commit allocator, hr %#x.\n", hr
);
209 EnterCriticalSection(&filter
->state_cs
);
210 filter
->state
= State_Paused
;
211 LeaveCriticalSection(&filter
->state_cs
);
213 filter
->thread
= CreateThread(NULL
, 0, stream_thread
, filter
, 0, NULL
);
218 static HRESULT
vfw_capture_start_stream(struct strmbase_filter
*iface
, REFERENCE_TIME time
)
220 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
222 EnterCriticalSection(&filter
->state_cs
);
223 filter
->state
= State_Running
;
224 LeaveCriticalSection(&filter
->state_cs
);
225 WakeConditionVariable(&filter
->state_cv
);
229 static HRESULT
vfw_capture_stop_stream(struct strmbase_filter
*iface
)
231 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
233 EnterCriticalSection(&filter
->state_cs
);
234 filter
->state
= State_Paused
;
235 LeaveCriticalSection(&filter
->state_cs
);
239 static HRESULT
vfw_capture_cleanup_stream(struct strmbase_filter
*iface
)
241 struct vfw_capture
*filter
= impl_from_strmbase_filter(iface
);
244 EnterCriticalSection(&filter
->state_cs
);
245 filter
->state
= State_Stopped
;
246 LeaveCriticalSection(&filter
->state_cs
);
247 WakeConditionVariable(&filter
->state_cv
);
249 WaitForSingleObject(filter
->thread
, INFINITE
);
250 CloseHandle(filter
->thread
);
251 filter
->thread
= NULL
;
253 hr
= IMemAllocator_Decommit(filter
->source
.pAllocator
);
254 if (hr
!= S_OK
&& hr
!= VFW_E_NOT_COMMITTED
)
255 ERR("Failed to decommit allocator, hr %#x.\n", hr
);
260 static HRESULT
vfw_capture_wait_state(struct strmbase_filter
*iface
, DWORD timeout
)
262 return iface
->state
== State_Paused
? VFW_S_CANT_CUE
: S_OK
;
265 static const struct strmbase_filter_ops filter_ops
=
267 .filter_get_pin
= vfw_capture_get_pin
,
268 .filter_destroy
= vfw_capture_destroy
,
269 .filter_query_interface
= vfw_capture_query_interface
,
270 .filter_init_stream
= vfw_capture_init_stream
,
271 .filter_start_stream
= vfw_capture_start_stream
,
272 .filter_stop_stream
= vfw_capture_stop_stream
,
273 .filter_cleanup_stream
= vfw_capture_cleanup_stream
,
274 .filter_wait_state
= vfw_capture_wait_state
,
277 static HRESULT WINAPI
AMStreamConfig_QueryInterface(IAMStreamConfig
*iface
, REFIID iid
, void **out
)
279 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
280 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
283 static ULONG WINAPI
AMStreamConfig_AddRef(IAMStreamConfig
*iface
)
285 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
286 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
289 static ULONG WINAPI
AMStreamConfig_Release(IAMStreamConfig
*iface
)
291 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
292 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
295 static HRESULT WINAPI
296 AMStreamConfig_SetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
*pmt
)
298 struct vfw_capture
*This
= impl_from_IAMStreamConfig(iface
);
301 TRACE("filter %p, mt %p.\n", This
, pmt
);
302 strmbase_dump_media_type(pmt
);
304 if (This
->filter
.state
!= State_Stopped
)
306 TRACE("Returning not stopped error\n");
307 return VFW_E_NOT_STOPPED
;
312 TRACE("pmt is NULL\n");
316 if (!IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
))
319 if (This
->source
.pin
.peer
)
321 hr
= IPin_QueryAccept(This
->source
.pin
.peer
, pmt
);
322 TRACE("Would accept: %d\n", hr
);
324 return VFW_E_INVALIDMEDIATYPE
;
327 hr
= capture_funcs
->set_format(This
->device
, pmt
);
328 if (SUCCEEDED(hr
) && This
->filter
.graph
&& This
->source
.pin
.peer
)
330 hr
= IFilterGraph_Reconnect(This
->filter
.graph
, &This
->source
.pin
.IPin_iface
);
332 TRACE("Reconnection completed, with new media format..\n");
334 TRACE("Returning: %d\n", hr
);
338 static HRESULT WINAPI
AMStreamConfig_GetFormat(IAMStreamConfig
*iface
, AM_MEDIA_TYPE
**mt
)
340 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
341 VIDEOINFOHEADER
*format
;
344 TRACE("filter %p, mt %p.\n", filter
, mt
);
346 if (!(*mt
= CoTaskMemAlloc(sizeof(**mt
))))
347 return E_OUTOFMEMORY
;
349 EnterCriticalSection(&filter
->filter
.filter_cs
);
351 if (filter
->source
.pin
.peer
)
353 hr
= CopyMediaType(*mt
, &filter
->source
.pin
.mt
);
357 if ((format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
359 capture_funcs
->get_format(filter
->device
, *mt
, format
);
360 (*mt
)->cbFormat
= sizeof(VIDEOINFOHEADER
);
361 (*mt
)->pbFormat
= (BYTE
*)format
;
370 LeaveCriticalSection(&filter
->filter
.filter_cs
);
373 strmbase_dump_media_type(*mt
);
379 static HRESULT WINAPI
AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig
*iface
,
380 int *count
, int *size
)
382 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
384 TRACE("filter %p, count %p, size %p.\n", filter
, count
, size
);
389 *count
= capture_funcs
->get_caps_count(filter
->device
);
390 *size
= sizeof(VIDEO_STREAM_CONFIG_CAPS
);
395 static HRESULT WINAPI
AMStreamConfig_GetStreamCaps(IAMStreamConfig
*iface
,
396 int index
, AM_MEDIA_TYPE
**pmt
, BYTE
*vscc
)
398 struct vfw_capture
*filter
= impl_from_IAMStreamConfig(iface
);
399 VIDEOINFOHEADER
*format
;
402 TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter
, index
, pmt
, vscc
);
404 if (index
> capture_funcs
->get_caps_count(filter
->device
))
407 if (!(mt
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
))))
408 return E_OUTOFMEMORY
;
410 if (!(format
= CoTaskMemAlloc(sizeof(VIDEOINFOHEADER
))))
413 return E_OUTOFMEMORY
;
416 capture_funcs
->get_caps(filter
->device
, index
, mt
, format
, (VIDEO_STREAM_CONFIG_CAPS
*)vscc
);
417 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
418 mt
->pbFormat
= (BYTE
*)format
;
423 static const IAMStreamConfigVtbl IAMStreamConfig_VTable
=
425 AMStreamConfig_QueryInterface
,
426 AMStreamConfig_AddRef
,
427 AMStreamConfig_Release
,
428 AMStreamConfig_SetFormat
,
429 AMStreamConfig_GetFormat
,
430 AMStreamConfig_GetNumberOfCapabilities
,
431 AMStreamConfig_GetStreamCaps
434 static HRESULT WINAPI
AMVideoProcAmp_QueryInterface(IAMVideoProcAmp
*iface
, REFIID iid
, void **out
)
436 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
437 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
440 static ULONG WINAPI
AMVideoProcAmp_AddRef(IAMVideoProcAmp
* iface
)
442 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
443 return IUnknown_AddRef(filter
->filter
.outer_unk
);
446 static ULONG WINAPI
AMVideoProcAmp_Release(IAMVideoProcAmp
* iface
)
448 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
449 return IUnknown_Release(filter
->filter
.outer_unk
);
452 static HRESULT WINAPI
AMVideoProcAmp_GetRange(IAMVideoProcAmp
*iface
, LONG property
,
453 LONG
*min
, LONG
*max
, LONG
*step
, LONG
*default_value
, LONG
*flags
)
455 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
457 TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n",
458 filter
, property
, min
, max
, step
, default_value
, flags
);
460 return capture_funcs
->get_prop_range(filter
->device
, property
, min
,
461 max
, step
, default_value
, flags
);
464 static HRESULT WINAPI
AMVideoProcAmp_Set(IAMVideoProcAmp
*iface
, LONG property
,
465 LONG value
, LONG flags
)
467 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
469 TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter
, property
, value
, flags
);
471 return capture_funcs
->set_prop(filter
->device
, property
, value
, flags
);
474 static HRESULT WINAPI
AMVideoProcAmp_Get(IAMVideoProcAmp
*iface
, LONG property
,
475 LONG
*value
, LONG
*flags
)
477 struct vfw_capture
*filter
= impl_from_IAMVideoProcAmp(iface
);
479 TRACE("filter %p, property %#x, value %p, flags %p.\n", filter
, property
, value
, flags
);
481 return capture_funcs
->get_prop(filter
->device
, property
, value
, flags
);
484 static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable
=
486 AMVideoProcAmp_QueryInterface
,
487 AMVideoProcAmp_AddRef
,
488 AMVideoProcAmp_Release
,
489 AMVideoProcAmp_GetRange
,
494 static HRESULT WINAPI
PPB_QueryInterface(IPersistPropertyBag
*iface
, REFIID iid
, void **out
)
496 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
497 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, iid
, out
);
500 static ULONG WINAPI
PPB_AddRef(IPersistPropertyBag
* iface
)
502 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
503 return IUnknown_AddRef(filter
->filter
.outer_unk
);
506 static ULONG WINAPI
PPB_Release(IPersistPropertyBag
* iface
)
508 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
509 return IUnknown_Release(filter
->filter
.outer_unk
);
512 static HRESULT WINAPI
513 PPB_GetClassID( IPersistPropertyBag
* iface
, CLSID
* pClassID
)
515 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
517 FIXME("%p - stub\n", This
);
522 static HRESULT WINAPI
PPB_InitNew(IPersistPropertyBag
* iface
)
524 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
526 FIXME("%p - stub\n", This
);
531 static HRESULT WINAPI
PPB_Load(IPersistPropertyBag
*iface
, IPropertyBag
*bag
, IErrorLog
*error_log
)
533 struct vfw_capture
*filter
= impl_from_IPersistPropertyBag(iface
);
537 TRACE("filter %p, bag %p, error_log %p.\n", filter
, bag
, error_log
);
540 if (FAILED(hr
= IPropertyBag_Read(bag
, L
"VFWIndex", &var
, error_log
)))
543 if (!(filter
->device
= capture_funcs
->create(V_I4(&var
))))
550 static HRESULT WINAPI
551 PPB_Save( IPersistPropertyBag
* iface
, IPropertyBag
*pPropBag
,
552 BOOL fClearDirty
, BOOL fSaveAllProperties
)
554 struct vfw_capture
*This
= impl_from_IPersistPropertyBag(iface
);
555 FIXME("%p - stub\n", This
);
559 static const IPersistPropertyBagVtbl IPersistPropertyBag_VTable
=
570 /* IKsPropertySet interface */
571 static inline struct vfw_capture
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
573 return CONTAINING_RECORD(iface
, struct vfw_capture
, IKsPropertySet_iface
);
576 static HRESULT WINAPI
KSP_QueryInterface(IKsPropertySet
*iface
, REFIID iid
, void **out
)
578 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
579 return IPin_QueryInterface(&filter
->source
.pin
.IPin_iface
, iid
, out
);
582 static ULONG WINAPI
KSP_AddRef(IKsPropertySet
* iface
)
584 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
585 return IPin_AddRef(&filter
->source
.pin
.IPin_iface
);
588 static ULONG WINAPI
KSP_Release(IKsPropertySet
* iface
)
590 struct vfw_capture
*filter
= impl_from_IKsPropertySet(iface
);
591 return IPin_Release(&filter
->source
.pin
.IPin_iface
);
594 static HRESULT WINAPI
595 KSP_Set( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
596 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
599 FIXME("%p: stub\n", iface
);
603 static HRESULT WINAPI
604 KSP_Get( IKsPropertySet
* iface
, REFGUID guidPropSet
, DWORD dwPropID
,
605 LPVOID pInstanceData
, DWORD cbInstanceData
, LPVOID pPropData
,
606 DWORD cbPropData
, DWORD
*pcbReturned
)
612 if (!IsEqualIID(guidPropSet
, &ROPSETID_Pin
))
613 return E_PROP_SET_UNSUPPORTED
;
614 if (pPropData
== NULL
&& pcbReturned
== NULL
)
617 *pcbReturned
= sizeof(GUID
);
618 if (pPropData
== NULL
)
620 if (cbPropData
< sizeof(GUID
))
623 *pGuid
= PIN_CATEGORY_CAPTURE
;
624 FIXME("() Not adding a pin with PIN_CATEGORY_PREVIEW\n");
628 static HRESULT WINAPI
629 KSP_QuerySupported( IKsPropertySet
* iface
, REFGUID guidPropSet
,
630 DWORD dwPropID
, DWORD
*pTypeSupport
)
632 FIXME("%p: stub\n", iface
);
636 static const IKsPropertySetVtbl IKsPropertySet_VTable
=
646 static inline struct vfw_capture
*impl_from_strmbase_pin(struct strmbase_pin
*pin
)
648 return CONTAINING_RECORD(pin
, struct vfw_capture
, source
.pin
);
651 static HRESULT
source_query_accept(struct strmbase_pin
*pin
, const AM_MEDIA_TYPE
*mt
)
653 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
654 return capture_funcs
->check_format(filter
->device
, mt
);
657 static HRESULT
source_get_media_type(struct strmbase_pin
*pin
,
658 unsigned int index
, AM_MEDIA_TYPE
*mt
)
660 struct vfw_capture
*filter
= impl_from_strmbase_pin(pin
);
661 VIDEOINFOHEADER
*format
;
664 if (!(format
= CoTaskMemAlloc(sizeof(*format
))))
665 return E_OUTOFMEMORY
;
667 if ((hr
= capture_funcs
->get_media_type(filter
->device
, index
, mt
, format
)) != S_OK
)
669 CoTaskMemFree(format
);
672 mt
->cbFormat
= sizeof(VIDEOINFOHEADER
);
673 mt
->pbFormat
= (BYTE
*)format
;
677 static HRESULT
source_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
679 struct vfw_capture
*filter
= impl_from_strmbase_pin(iface
);
681 if (IsEqualGUID(iid
, &IID_IKsPropertySet
))
682 *out
= &filter
->IKsPropertySet_iface
;
683 else if (IsEqualGUID(iid
, &IID_IAMStreamConfig
))
684 *out
= &filter
->IAMStreamConfig_iface
;
686 return E_NOINTERFACE
;
688 IUnknown_AddRef((IUnknown
*)*out
);
692 static HRESULT WINAPI
VfwPin_DecideBufferSize(struct strmbase_source
*iface
,
693 IMemAllocator
*pAlloc
, ALLOCATOR_PROPERTIES
*ppropInputRequest
)
695 ALLOCATOR_PROPERTIES actual
;
697 /* What we put here doesn't matter, the
698 driver function should override it then commit */
699 if (!ppropInputRequest
->cBuffers
)
700 ppropInputRequest
->cBuffers
= 3;
701 if (!ppropInputRequest
->cbBuffer
)
702 ppropInputRequest
->cbBuffer
= 230400;
703 if (!ppropInputRequest
->cbAlign
)
704 ppropInputRequest
->cbAlign
= 1;
706 return IMemAllocator_SetProperties(pAlloc
, ppropInputRequest
, &actual
);
709 static const struct strmbase_source_ops source_ops
=
711 .base
.pin_query_accept
= source_query_accept
,
712 .base
.pin_get_media_type
= source_get_media_type
,
713 .base
.pin_query_interface
= source_query_interface
,
714 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
715 .pfnDecideBufferSize
= VfwPin_DecideBufferSize
,
716 .pfnDecideAllocator
= BaseOutputPinImpl_DecideAllocator
,
719 static HRESULT WINAPI
misc_flags_QueryInterface(IAMFilterMiscFlags
*iface
, REFIID riid
, void **ppv
)
721 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
722 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
725 static ULONG WINAPI
misc_flags_AddRef(IAMFilterMiscFlags
*iface
)
727 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
728 return IUnknown_AddRef(filter
->filter
.outer_unk
);
731 static ULONG WINAPI
misc_flags_Release(IAMFilterMiscFlags
*iface
)
733 struct vfw_capture
*filter
= impl_from_IAMFilterMiscFlags(iface
);
734 return IUnknown_Release(filter
->filter
.outer_unk
);
737 static ULONG WINAPI
misc_flags_GetMiscFlags(IAMFilterMiscFlags
*iface
)
739 return AM_FILTER_MISC_FLAGS_IS_SOURCE
;
742 static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_VTable
=
744 misc_flags_QueryInterface
,
747 misc_flags_GetMiscFlags
750 static HRESULT WINAPI
video_control_QueryInterface(IAMVideoControl
*iface
, REFIID riid
, void **ppv
)
752 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
753 return IUnknown_QueryInterface(filter
->filter
.outer_unk
, riid
, ppv
);
756 static ULONG WINAPI
video_control_AddRef(IAMVideoControl
*iface
)
758 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
759 return IUnknown_AddRef(filter
->filter
.outer_unk
);
762 static ULONG WINAPI
video_control_Release(IAMVideoControl
*iface
)
764 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
765 return IUnknown_Release(filter
->filter
.outer_unk
);
768 static HRESULT WINAPI
video_control_GetCaps(IAMVideoControl
*iface
, IPin
*pin
, LONG
*flags
)
770 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
772 FIXME("filter %p, pin %p, flags %p: stub.\n", filter
, pin
, flags
);
777 static HRESULT WINAPI
video_control_SetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG mode
)
779 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
781 FIXME("filter %p, pin %p, mode %d: stub.\n", filter
, pin
, mode
);
786 static HRESULT WINAPI
video_control_GetMode(IAMVideoControl
*iface
, IPin
*pin
, LONG
*mode
)
788 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
790 FIXME("filter %p, pin %p, mode %p: stub.\n", filter
, pin
, mode
);
795 static HRESULT WINAPI
video_control_GetCurrentActualFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
796 LONGLONG
*frame_rate
)
798 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
800 FIXME("filter %p, pin %p, frame rate %p: stub.\n", filter
, pin
, frame_rate
);
805 static HRESULT WINAPI
video_control_GetMaxAvailableFrameRate(IAMVideoControl
*iface
, IPin
*pin
,
806 LONG index
, SIZE dimensions
, LONGLONG
*frame_rate
)
808 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
810 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), frame rate %p: stub.\n",
811 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, frame_rate
);
816 static HRESULT WINAPI
video_control_GetFrameRateList(IAMVideoControl
*iface
, IPin
*pin
, LONG index
,
817 SIZE dimensions
, LONG
*list_size
, LONGLONG
**frame_rate
)
819 struct vfw_capture
*filter
= impl_from_IAMVideoControl(iface
);
821 FIXME("filter %p, pin %p, index %d, dimensions (%dx%d), list size %p, frame rate: %p: stub.\n",
822 filter
, pin
, index
, dimensions
.cx
, dimensions
.cy
, list_size
, frame_rate
);
827 static const IAMVideoControlVtbl IAMVideoControl_VTable
=
829 video_control_QueryInterface
,
830 video_control_AddRef
,
831 video_control_Release
,
832 video_control_GetCaps
,
833 video_control_SetMode
,
834 video_control_GetMode
,
835 video_control_GetCurrentActualFrameRate
,
836 video_control_GetMaxAvailableFrameRate
,
837 video_control_GetFrameRateList
840 static BOOL WINAPI
load_capture_funcs(INIT_ONCE
*once
, void *param
, void **context
)
842 __wine_init_unix_lib(qcap_instance
, DLL_PROCESS_ATTACH
, NULL
, &capture_funcs
);
846 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
848 HRESULT
vfw_capture_create(IUnknown
*outer
, IUnknown
**out
)
850 struct vfw_capture
*object
;
852 if (!InitOnceExecuteOnce(&init_once
, load_capture_funcs
, NULL
, NULL
) || !capture_funcs
)
855 if (!(object
= calloc(1, sizeof(*object
))))
856 return E_OUTOFMEMORY
;
858 strmbase_filter_init(&object
->filter
, outer
, &CLSID_VfwCapture
, &filter_ops
);
860 object
->IAMStreamConfig_iface
.lpVtbl
= &IAMStreamConfig_VTable
;
861 object
->IAMVideoControl_iface
.lpVtbl
= &IAMVideoControl_VTable
;
862 object
->IAMVideoProcAmp_iface
.lpVtbl
= &IAMVideoProcAmp_VTable
;
863 object
->IAMFilterMiscFlags_iface
.lpVtbl
= &IAMFilterMiscFlags_VTable
;
864 object
->IPersistPropertyBag_iface
.lpVtbl
= &IPersistPropertyBag_VTable
;
866 strmbase_source_init(&object
->source
, &object
->filter
, L
"Output", &source_ops
);
868 object
->IKsPropertySet_iface
.lpVtbl
= &IKsPropertySet_VTable
;
870 object
->state
= State_Stopped
;
871 InitializeConditionVariable(&object
->state_cv
);
872 InitializeCriticalSection(&object
->state_cs
);
873 object
->state_cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": vfw_capture.state_cs");
875 TRACE("Created VFW capture filter %p.\n", object
);
876 ObjectRefCount(TRUE
);
877 *out
= &object
->filter
.IUnknown_inner
;