[PATCH 2/4] qcap: Move the video capture device creation function to the function table.

Zebediah Figura z.figura12 at gmail.com
Tue Nov 24 20:11:15 CST 2020


Signed-off-by: Zebediah Figura <z.figura12 at 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;
 
-- 
2.29.2




More information about the wine-devel mailing list