Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/qcap/qcap_private.h | 10 +--- dlls/qcap/v4l.c | 121 ++++++++++++++++----------------------- dlls/qcap/vfwcapture.c | 69 +++++++++++----------- 3 files changed, 90 insertions(+), 110 deletions(-)
diff --git a/dlls/qcap/qcap_private.h b/dlls/qcap/qcap_private.h index bbbe2ef43ec..9df432f8d05 100644 --- a/dlls/qcap/qcap_private.h +++ b/dlls/qcap/qcap_private.h @@ -40,13 +40,9 @@ HRESULT file_writer_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; HRESULT smart_tee_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN; HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
-struct video_capture_device -{ - const struct video_capture_device_ops *ops; -}; - -struct video_capture_device_ops +struct video_capture_funcs { + struct video_capture_device *(*create)(struct strmbase_source *pin, USHORT index); void (*destroy)(struct video_capture_device *device); HRESULT (*check_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); HRESULT (*set_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); @@ -64,6 +60,6 @@ struct video_capture_device_ops void (*cleanup_stream)(struct video_capture_device *device); };
-struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHORT card); +extern const struct video_capture_funcs v4l_funcs;
#endif diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c index cfae2b1d1ec..a007adce492 100644 --- a/dlls/qcap/v4l.c +++ b/dlls/qcap/v4l.c @@ -88,10 +88,8 @@ struct caps VIDEO_STREAM_CONFIG_CAPS config; };
-struct v4l_device +struct video_capture_device { - struct video_capture_device d; - const struct caps *current_caps; struct caps *caps; LONG caps_count; @@ -108,11 +106,6 @@ struct v4l_device CRITICAL_SECTION state_cs; };
-static inline struct v4l_device *v4l_device(struct video_capture_device *iface) -{ - return CONTAINING_RECORD(iface, struct v4l_device, d); -} - static int xioctl(int fd, int request, void * arg) { int r; @@ -124,10 +117,8 @@ static int xioctl(int fd, int request, void * arg) return r; }
-static void v4l_device_destroy(struct video_capture_device *iface) +static void v4l_device_destroy(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); - device->state_cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&device->state_cs); if (device->fd != -1) @@ -138,7 +129,7 @@ static void v4l_device_destroy(struct video_capture_device *iface) heap_free(device); }
-static const struct caps *find_caps(struct v4l_device *device, const AM_MEDIA_TYPE *mt) +static const struct caps *find_caps(struct video_capture_device *device, const AM_MEDIA_TYPE *mt) { const VIDEOINFOHEADER *video_info = (VIDEOINFOHEADER *)mt->pbFormat; LONG index; @@ -158,10 +149,8 @@ static const struct caps *find_caps(struct v4l_device *device, const AM_MEDIA_TY return NULL; }
-static HRESULT v4l_device_check_format(struct video_capture_device *iface, const AM_MEDIA_TYPE *mt) +static HRESULT v4l_device_check_format(struct video_capture_device *device, const AM_MEDIA_TYPE *mt) { - struct v4l_device *device = v4l_device(iface); - TRACE("device %p, mt %p.\n", device, mt);
if (!mt) @@ -176,7 +165,7 @@ static HRESULT v4l_device_check_format(struct video_capture_device *iface, const return E_FAIL; }
-static HRESULT set_caps(struct v4l_device *device, const struct caps *caps) +static HRESULT set_caps(struct video_capture_device *device, const struct caps *caps) { struct v4l2_format format = {0}; LONG width, height, image_size; @@ -214,9 +203,8 @@ static HRESULT set_caps(struct v4l_device *device, const struct caps *caps) return S_OK; }
-static HRESULT v4l_device_set_format(struct video_capture_device *iface, const AM_MEDIA_TYPE *mt) +static HRESULT v4l_device_set_format(struct video_capture_device *device, const AM_MEDIA_TYPE *mt) { - struct v4l_device *device = v4l_device(iface); const struct caps *caps;
caps = find_caps(device, mt); @@ -229,17 +217,14 @@ static HRESULT v4l_device_set_format(struct video_capture_device *iface, const A return set_caps(device, caps); }
-static HRESULT v4l_device_get_format(struct video_capture_device *iface, AM_MEDIA_TYPE *mt) +static HRESULT v4l_device_get_format(struct video_capture_device *device, AM_MEDIA_TYPE *mt) { - struct v4l_device *device = v4l_device(iface); - return CopyMediaType(mt, &device->current_caps->media_type); }
-static HRESULT v4l_device_get_media_type(struct video_capture_device *iface, +static HRESULT v4l_device_get_media_type(struct video_capture_device *device, unsigned int index, AM_MEDIA_TYPE *mt) { - struct v4l_device *device = v4l_device(iface); unsigned int caps_count = (device->current_caps) ? 1 : device->caps_count;
if (index >= caps_count) @@ -269,10 +254,9 @@ static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property) } }
-static HRESULT v4l_device_get_prop_range(struct video_capture_device *iface, VideoProcAmpProperty property, +static HRESULT v4l_device_get_prop_range(struct video_capture_device *device, VideoProcAmpProperty property, LONG *min, LONG *max, LONG *step, LONG *default_value, LONG *flags) { - struct v4l_device *device = v4l_device(iface); struct v4l2_queryctrl ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); @@ -291,10 +275,9 @@ static HRESULT v4l_device_get_prop_range(struct video_capture_device *iface, Vid return S_OK; }
-static HRESULT v4l_device_get_prop(struct video_capture_device *iface, +static HRESULT v4l_device_get_prop(struct video_capture_device *device, VideoProcAmpProperty property, LONG *value, LONG *flags) { - struct v4l_device *device = v4l_device(iface); struct v4l2_control ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); @@ -311,10 +294,9 @@ static HRESULT v4l_device_get_prop(struct video_capture_device *iface, return S_OK; }
-static HRESULT v4l_device_set_prop(struct video_capture_device *iface, +static HRESULT v4l_device_set_prop(struct video_capture_device *device, VideoProcAmpProperty property, LONG value, LONG flags) { - struct v4l_device *device = v4l_device(iface); struct v4l2_control ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); @@ -329,7 +311,7 @@ static HRESULT v4l_device_set_prop(struct video_capture_device *iface, return S_OK; }
-static void reverse_image(struct v4l_device *device, LPBYTE output, const BYTE *input) +static void reverse_image(struct video_capture_device *device, LPBYTE output, const BYTE *input) { int inoffset, outoffset, pitch;
@@ -350,7 +332,7 @@ static void reverse_image(struct v4l_device *device, LPBYTE output, const BYTE *
static DWORD WINAPI ReadThread(void *arg) { - struct v4l_device *device = arg; + struct video_capture_device *device = arg; HRESULT hr; IMediaSample *pSample = NULL; unsigned char *pTarget; @@ -406,9 +388,8 @@ static DWORD WINAPI ReadThread(void *arg) return 0; }
-static void v4l_device_init_stream(struct video_capture_device *iface) +static void v4l_device_init_stream(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); ALLOCATOR_PROPERTIES req_props, ret_props; HRESULT hr;
@@ -431,25 +412,22 @@ static void v4l_device_init_stream(struct video_capture_device *iface) device->thread = CreateThread(NULL, 0, ReadThread, device, 0, NULL); }
-static void v4l_device_start_stream(struct video_capture_device *iface) +static void v4l_device_start_stream(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); EnterCriticalSection(&device->state_cs); device->state = State_Running; LeaveCriticalSection(&device->state_cs); }
-static void v4l_device_stop_stream(struct video_capture_device *iface) +static void v4l_device_stop_stream(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); EnterCriticalSection(&device->state_cs); device->state = State_Paused; LeaveCriticalSection(&device->state_cs); }
-static void v4l_device_cleanup_stream(struct video_capture_device *iface) +static void v4l_device_cleanup_stream(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); HRESULT hr;
EnterCriticalSection(&device->state_cs); @@ -502,11 +480,9 @@ static void fill_caps(__u32 pixelformat, __u32 width, __u32 height, caps->pixelformat = pixelformat; }
-static HRESULT v4l_device_get_caps(struct video_capture_device *iface, LONG index, +static HRESULT v4l_device_get_caps(struct video_capture_device *device, LONG index, AM_MEDIA_TYPE **type, VIDEO_STREAM_CONFIG_CAPS *vscc) { - struct v4l_device *device = v4l_device(iface); - if (index >= device->caps_count) return S_FALSE;
@@ -519,37 +495,17 @@ static HRESULT v4l_device_get_caps(struct video_capture_device *iface, LONG inde return S_OK; }
-static LONG v4l_device_get_caps_count(struct video_capture_device *iface) +static LONG v4l_device_get_caps_count(struct video_capture_device *device) { - struct v4l_device *device = v4l_device(iface); - return device->caps_count; }
-static const struct video_capture_device_ops v4l_device_ops = -{ - .destroy = v4l_device_destroy, - .check_format = v4l_device_check_format, - .set_format = v4l_device_set_format, - .get_format = v4l_device_get_format, - .get_media_type = v4l_device_get_media_type, - .get_caps = v4l_device_get_caps, - .get_caps_count = v4l_device_get_caps_count, - .get_prop_range = v4l_device_get_prop_range, - .get_prop = v4l_device_get_prop, - .set_prop = v4l_device_set_prop, - .init_stream = v4l_device_init_stream, - .start_stream = v4l_device_start_stream, - .stop_stream = v4l_device_stop_stream, - .cleanup_stream = v4l_device_cleanup_stream, -}; - -struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHORT card) +struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHORT index) { struct v4l2_frmsizeenum frmsize = {0}; + struct video_capture_device *device; struct v4l2_capability caps = {{0}}; struct v4l2_format format = {0}; - struct v4l_device *device; BOOL have_libv4l2; char path[20]; HRESULT hr; @@ -560,7 +516,7 @@ struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHO if (!(device = heap_alloc_zero(sizeof(*device)))) return NULL;
- sprintf(path, "/dev/video%i", card); + sprintf(path, "/dev/video%i", index); TRACE("Opening device %s.\n", path); #ifdef O_CLOEXEC if ((fd = video_open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC)) == -1 && errno == EINVAL) @@ -681,30 +637,53 @@ struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHO goto error; }
- device->d.ops = &v4l_device_ops; device->pin = pin; device->state = State_Stopped; InitializeConditionVariable(&device->state_cv); InitializeCriticalSection(&device->state_cs); - device->state_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": v4l_device.state_cs"); + device->state_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": video_capture_device.state_cs");
TRACE("Format: %d bpp - %dx%d.\n", device->current_caps->video_info.bmiHeader.biBitCount, device->current_caps->video_info.bmiHeader.biWidth, device->current_caps->video_info.bmiHeader.biHeight);
- return &device->d; + return device;
error: - v4l_device_destroy(&device->d); + v4l_device_destroy(device); return NULL; }
+const struct video_capture_funcs v4l_funcs = +{ + .create = v4l_device_create, + .destroy = v4l_device_destroy, + .check_format = v4l_device_check_format, + .set_format = v4l_device_set_format, + .get_format = v4l_device_get_format, + .get_media_type = v4l_device_get_media_type, + .get_caps = v4l_device_get_caps, + .get_caps_count = v4l_device_get_caps_count, + .get_prop_range = v4l_device_get_prop_range, + .get_prop = v4l_device_get_prop, + .set_prop = v4l_device_set_prop, + .init_stream = v4l_device_init_stream, + .start_stream = v4l_device_start_stream, + .stop_stream = v4l_device_stop_stream, + .cleanup_stream = v4l_device_cleanup_stream, +}; + #else
-struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHORT card) +static struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHORT index) { ERR("v4l2 was not present at compilation time.\n"); return NULL; }
+const struct video_capture_funcs v4l_funcs = +{ + .create = v4l_device_create, +}; + #endif /* defined(VIDIOCMCAPTURE) */ diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index a79cce50380..9ff96f13f91 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -22,6 +22,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(qcap);
+static const struct video_capture_funcs *capture_funcs; + struct vfw_capture { struct strmbase_filter filter; @@ -85,8 +87,8 @@ static void vfw_capture_destroy(struct strmbase_filter *iface) if (filter->init) { if (filter->filter.state != State_Stopped) - filter->device->ops->cleanup_stream(filter->device); - filter->device->ops->destroy(filter->device); + capture_funcs->cleanup_stream(filter->device); + capture_funcs->destroy(filter->device); }
if (filter->source.pin.peer) @@ -123,7 +125,7 @@ static HRESULT vfw_capture_init_stream(struct strmbase_filter *iface) { struct vfw_capture *filter = impl_from_strmbase_filter(iface);
- filter->device->ops->init_stream(filter->device); + capture_funcs->init_stream(filter->device); return S_OK; }
@@ -131,7 +133,7 @@ static HRESULT vfw_capture_start_stream(struct strmbase_filter *iface, REFERENCE { struct vfw_capture *filter = impl_from_strmbase_filter(iface);
- filter->device->ops->start_stream(filter->device); + capture_funcs->start_stream(filter->device); return S_OK; }
@@ -139,7 +141,7 @@ static HRESULT vfw_capture_stop_stream(struct strmbase_filter *iface) { struct vfw_capture *filter = impl_from_strmbase_filter(iface);
- filter->device->ops->stop_stream(filter->device); + capture_funcs->stop_stream(filter->device); return S_OK; }
@@ -147,7 +149,7 @@ static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface) { struct vfw_capture *filter = impl_from_strmbase_filter(iface);
- filter->device->ops->cleanup_stream(filter->device); + capture_funcs->cleanup_stream(filter->device); return S_OK; }
@@ -218,7 +220,7 @@ AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt) return VFW_E_INVALIDMEDIATYPE; }
- hr = This->device->ops->set_format(This->device, pmt); + hr = capture_funcs->set_format(This->device, pmt); if (SUCCEEDED(hr) && This->filter.graph && This->source.pin.peer) { hr = IFilterGraph_Reconnect(This->filter.graph, &This->source.pin.IPin_iface); @@ -239,7 +241,7 @@ static HRESULT WINAPI AMStreamConfig_GetFormat(IAMStreamConfig *iface, AM_MEDIA_ if (!(*mt = CoTaskMemAlloc(sizeof(**mt)))) return E_OUTOFMEMORY;
- if (SUCCEEDED(hr = filter->device->ops->get_format(filter->device, *mt))) + if (SUCCEEDED(hr = capture_funcs->get_format(filter->device, *mt))) strmbase_dump_media_type(*mt); return hr; } @@ -254,7 +256,7 @@ static HRESULT WINAPI AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig *if if (!count || !size) return E_POINTER;
- *count = filter->device->ops->get_caps_count(filter->device); + *count = capture_funcs->get_caps_count(filter->device); *size = sizeof(VIDEO_STREAM_CONFIG_CAPS);
return S_OK; @@ -267,7 +269,7 @@ static HRESULT WINAPI AMStreamConfig_GetStreamCaps(IAMStreamConfig *iface,
TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter, index, pmt, vscc);
- return filter->device->ops->get_caps(filter->device, index, pmt, (VIDEO_STREAM_CONFIG_CAPS *)vscc); + return capture_funcs->get_caps(filter->device, index, pmt, (VIDEO_STREAM_CONFIG_CAPS *)vscc); }
static const IAMStreamConfigVtbl IAMStreamConfig_VTable = @@ -307,7 +309,7 @@ static HRESULT WINAPI AMVideoProcAmp_GetRange(IAMVideoProcAmp *iface, LONG prope TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n", filter, property, min, max, step, default_value, flags);
- return filter->device->ops->get_prop_range(filter->device, property, min, + return capture_funcs->get_prop_range(filter->device, property, min, max, step, default_value, flags); }
@@ -318,7 +320,7 @@ static HRESULT WINAPI AMVideoProcAmp_Set(IAMVideoProcAmp *iface, LONG property,
TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter, property, value, flags);
- return filter->device->ops->set_prop(filter->device, property, value, flags); + return capture_funcs->set_prop(filter->device, property, value, flags); }
static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp *iface, LONG property, @@ -328,7 +330,7 @@ static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp *iface, LONG property,
TRACE("filter %p, property %#x, value %p, flags %p.\n", filter, property, value, flags);
- return filter->device->ops->get_prop(filter->device, property, value, flags); + return capture_funcs->get_prop(filter->device, property, value, flags); }
static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable = @@ -378,32 +380,24 @@ static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface) return E_NOTIMPL; }
-static HRESULT WINAPI -PPB_Load( IPersistPropertyBag * iface, IPropertyBag *pPropBag, - IErrorLog *pErrorLog ) +static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *bag, IErrorLog *error_log) { static const OLECHAR VFWIndex[] = {'V','F','W','I','n','d','e','x',0}; - struct vfw_capture *This = impl_from_IPersistPropertyBag(iface); + struct vfw_capture *filter = impl_from_IPersistPropertyBag(iface); HRESULT hr; VARIANT var;
- TRACE("%p/%p-> (%p, %p)\n", iface, This, pPropBag, pErrorLog); + TRACE("filter %p, bag %p, error_log %p.\n", filter, bag, error_log);
V_VT(&var) = VT_I4; - hr = IPropertyBag_Read(pPropBag, VFWIndex, &var, pErrorLog); + if (FAILED(hr = IPropertyBag_Read(bag, VFWIndex, &var, error_log))) + return hr;
- if (SUCCEEDED(hr)) - { - if ((This->device = v4l_device_create(&This->source, V_I4(&var)))) - { - This->init = TRUE; - hr = S_OK; - } - else - hr = E_FAIL; - } + if (!(filter->device = capture_funcs->create(&filter->source, V_I4(&var)))) + return E_FAIL;
- return hr; + filter->init = TRUE; + return S_OK; }
static HRESULT WINAPI @@ -510,14 +504,14 @@ static inline struct vfw_capture *impl_from_strmbase_pin(struct strmbase_pin *pi static HRESULT source_query_accept(struct strmbase_pin *pin, const AM_MEDIA_TYPE *mt) { struct vfw_capture *filter = impl_from_strmbase_pin(pin); - return filter->device->ops->check_format(filter->device, mt); + return capture_funcs->check_format(filter->device, mt); }
static HRESULT source_get_media_type(struct strmbase_pin *pin, unsigned int index, AM_MEDIA_TYPE *mt) { struct vfw_capture *filter = impl_from_strmbase_pin(pin); - return filter->device->ops->get_media_type(filter->device, index, mt); + return capture_funcs->get_media_type(filter->device, index, mt); }
static HRESULT source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) @@ -683,11 +677,22 @@ static const IAMVideoControlVtbl IAMVideoControl_VTable = video_control_GetFrameRateList };
+static BOOL WINAPI load_capture_funcs(INIT_ONCE *once, void *param, void **context) +{ + capture_funcs = &v4l_funcs; + return TRUE; +} + +static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; + HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) { static const WCHAR source_name[] = {'O','u','t','p','u','t',0}; struct vfw_capture *object;
+ if (!InitOnceExecuteOnce(&init_once, load_capture_funcs, NULL, NULL)) + return E_FAIL; + if (!(object = CoTaskMemAlloc(sizeof(*object)))) return E_OUTOFMEMORY;