qcap: Convert the Unix library to the __wine_unix_call interface.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-11-02 18:38:11 +01:00
parent 626f85f5f6
commit 62e2d7a99b
4 changed files with 255 additions and 110 deletions

View file

@ -1,4 +1,5 @@
MODULE = qcap.dll MODULE = qcap.dll
UNIXLIB = qcap.so
IMPORTS = strmbase strmiids uuid ole32 oleaut32 IMPORTS = strmbase strmiids uuid ole32 oleaut32
DELAYIMPORTS = msvfw32 DELAYIMPORTS = msvfw32

View file

@ -25,6 +25,8 @@
#define NONAMELESSSTRUCT #define NONAMELESSSTRUCT
#define NONAMELESSUNION #define NONAMELESSUNION
#include "dshow.h" #include "dshow.h"
#include "winternl.h"
#include "wine/unixlib.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/strmbase.h" #include "wine/strmbase.h"
@ -38,25 +40,108 @@ HRESULT file_writer_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
HRESULT smart_tee_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; HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
struct video_capture_funcs struct video_capture_device;
struct create_params
{ {
struct video_capture_device *(CDECL *create)(USHORT index); unsigned int index;
void (CDECL *destroy)(struct video_capture_device *device); struct video_capture_device **device;
HRESULT (CDECL *check_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt); };
HRESULT (CDECL *set_format)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt);
void (CDECL *get_format)(struct video_capture_device *device, AM_MEDIA_TYPE *mt, VIDEOINFOHEADER *format); struct destroy_params
HRESULT (CDECL *get_media_type)(struct video_capture_device *device, {
unsigned int index, AM_MEDIA_TYPE *mt, VIDEOINFOHEADER *format); struct video_capture_device *device;
void (CDECL *get_caps)(struct video_capture_device *device, LONG index, AM_MEDIA_TYPE *mt, };
VIDEOINFOHEADER *format, VIDEO_STREAM_CONFIG_CAPS *caps);
LONG (CDECL *get_caps_count)(struct video_capture_device *device); struct check_format_params
HRESULT (CDECL *get_prop_range)(struct video_capture_device *device, VideoProcAmpProperty property, {
LONG *min, LONG *max, LONG *step, LONG *default_value, LONG *flags); struct video_capture_device *device;
HRESULT (CDECL *get_prop)(struct video_capture_device *device, const AM_MEDIA_TYPE *mt;
VideoProcAmpProperty property, LONG *value, LONG *flags); };
HRESULT (CDECL *set_prop)(struct video_capture_device *device,
VideoProcAmpProperty property, LONG value, LONG flags); struct set_format_params
BOOL (CDECL *read_frame)(struct video_capture_device *device, BYTE *data); {
struct video_capture_device *device;
const AM_MEDIA_TYPE *mt;
};
struct get_format_params
{
struct video_capture_device *device;
AM_MEDIA_TYPE *mt;
VIDEOINFOHEADER *format;
};
struct get_media_type_params
{
struct video_capture_device *device;
unsigned int index;
AM_MEDIA_TYPE *mt;
VIDEOINFOHEADER *format;
};
struct get_caps_params
{
struct video_capture_device *device;
unsigned int index;
AM_MEDIA_TYPE *mt;
VIDEOINFOHEADER *format;
VIDEO_STREAM_CONFIG_CAPS *caps;
};
struct get_caps_count_params
{
struct video_capture_device *device;
int *count;
};
struct get_prop_range_params
{
struct video_capture_device *device;
VideoProcAmpProperty property;
LONG *min;
LONG *max;
LONG *step;
LONG *default_value;
LONG *flags;
};
struct get_prop_params
{
struct video_capture_device *device;
VideoProcAmpProperty property;
LONG *value;
LONG *flags;
};
struct set_prop_params
{
struct video_capture_device *device;
VideoProcAmpProperty property;
LONG value;
LONG flags;
};
struct read_frame_params
{
struct video_capture_device *device;
void *data;
};
enum unix_funcs
{
unix_create,
unix_destroy,
unix_check_format,
unix_set_format,
unix_get_format,
unix_get_media_type,
unix_get_caps,
unix_get_caps_count,
unix_get_prop_range,
unix_get_prop,
unix_set_prop,
unix_read_frame,
}; };
#endif #endif

View file

@ -26,11 +26,12 @@
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD /* work around ioctl breakage on Android */ #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD /* work around ioctl breakage on Android */
#include "config.h" #include "config.h"
#include "wine/port.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <dlfcn.h>
#ifdef HAVE_SYS_IOCTL_H #ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h> #include <sys/ioctl.h>
#endif #endif
@ -118,7 +119,7 @@ static int xioctl(int fd, int request, void * arg)
return r; return r;
} }
static void CDECL v4l_device_destroy(struct video_capture_device *device) static void device_destroy(struct video_capture_device *device)
{ {
if (device->fd != -1) if (device->fd != -1)
video_close(device->fd); video_close(device->fd);
@ -148,17 +149,20 @@ static const struct caps *find_caps(struct video_capture_device *device, const A
return NULL; return NULL;
} }
static HRESULT CDECL v4l_device_check_format(struct video_capture_device *device, const AM_MEDIA_TYPE *mt) static NTSTATUS v4l_device_check_format( void *args )
{ {
TRACE("device %p, mt %p.\n", device, mt); struct check_format_params *params = args;
struct video_capture_device *device = params->device;
if (!mt) TRACE("device %p, mt %p.\n", device, params->mt);
if (!params->mt)
return E_POINTER; return E_POINTER;
if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)) if (!IsEqualGUID(&params->mt->majortype, &MEDIATYPE_Video))
return E_FAIL; return E_FAIL;
if (find_caps(device, mt)) if (find_caps(device, params->mt))
return S_OK; return S_OK;
return E_FAIL; return E_FAIL;
@ -202,11 +206,13 @@ static HRESULT set_caps(struct video_capture_device *device, const struct caps *
return S_OK; return S_OK;
} }
static HRESULT CDECL v4l_device_set_format(struct video_capture_device *device, const AM_MEDIA_TYPE *mt) static NTSTATUS v4l_device_set_format( void *args )
{ {
struct set_format_params *params = args;
struct video_capture_device *device = params->device;
const struct caps *caps; const struct caps *caps;
caps = find_caps(device, mt); caps = find_caps(device, params->mt);
if (!caps) if (!caps)
return E_FAIL; return E_FAIL;
@ -216,29 +222,34 @@ static HRESULT CDECL v4l_device_set_format(struct video_capture_device *device,
return set_caps(device, caps); return set_caps(device, caps);
} }
static void CDECL v4l_device_get_format(struct video_capture_device *device, AM_MEDIA_TYPE *mt, VIDEOINFOHEADER *format) static NTSTATUS v4l_device_get_format( void *args )
{ {
*mt = device->current_caps->media_type; struct get_format_params *params = args;
*format = device->current_caps->video_info; struct video_capture_device *device = params->device;
*params->mt = device->current_caps->media_type;
*params->format = device->current_caps->video_info;
return S_OK;
} }
static HRESULT CDECL v4l_device_get_media_type(struct video_capture_device *device, static NTSTATUS v4l_device_get_media_type( void *args )
unsigned int index, AM_MEDIA_TYPE *mt, VIDEOINFOHEADER *format)
{ {
struct get_media_type_params *params = args;
struct video_capture_device *device = params->device;
unsigned int caps_count = (device->current_caps) ? 1 : device->caps_count; unsigned int caps_count = (device->current_caps) ? 1 : device->caps_count;
if (index >= caps_count) if (params->index >= caps_count)
return VFW_S_NO_MORE_ITEMS; return VFW_S_NO_MORE_ITEMS;
if (device->current_caps) if (device->current_caps)
{ {
*mt = device->current_caps->media_type; *params->mt = device->current_caps->media_type;
*format = device->current_caps->video_info; *params->format = device->current_caps->video_info;
} }
else else
{ {
*mt = device->caps[index].media_type; *params->mt = device->caps[params->index].media_type;
*format = device->caps[index].video_info; *params->format = device->caps[params->index].video_info;
} }
return S_OK; return S_OK;
} }
@ -261,12 +272,13 @@ static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property)
} }
} }
static HRESULT CDECL v4l_device_get_prop_range(struct video_capture_device *device, VideoProcAmpProperty property, static NTSTATUS v4l_device_get_prop_range( void *args )
LONG *min, LONG *max, LONG *step, LONG *default_value, LONG *flags)
{ {
struct get_prop_range_params *params = args;
struct video_capture_device *device = params->device;
struct v4l2_queryctrl ctrl; struct v4l2_queryctrl ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); ctrl.id = v4l2_cid_from_qcap_property(params->property);
if (xioctl(device->fd, VIDIOC_QUERYCTRL, &ctrl) == -1) if (xioctl(device->fd, VIDIOC_QUERYCTRL, &ctrl) == -1)
{ {
@ -274,20 +286,21 @@ static HRESULT CDECL v4l_device_get_prop_range(struct video_capture_device *devi
return E_PROP_ID_UNSUPPORTED; return E_PROP_ID_UNSUPPORTED;
} }
*min = ctrl.minimum; *params->min = ctrl.minimum;
*max = ctrl.maximum; *params->max = ctrl.maximum;
*step = ctrl.step; *params->step = ctrl.step;
*default_value = ctrl.default_value; *params->default_value = ctrl.default_value;
*flags = VideoProcAmp_Flags_Manual; *params->flags = VideoProcAmp_Flags_Manual;
return S_OK; return S_OK;
} }
static HRESULT CDECL v4l_device_get_prop(struct video_capture_device *device, static NTSTATUS v4l_device_get_prop( void *args )
VideoProcAmpProperty property, LONG *value, LONG *flags)
{ {
struct get_prop_params *params = args;
struct video_capture_device *device = params->device;
struct v4l2_control ctrl; struct v4l2_control ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); ctrl.id = v4l2_cid_from_qcap_property(params->property);
if (xioctl(device->fd, VIDIOC_G_CTRL, &ctrl) == -1) if (xioctl(device->fd, VIDIOC_G_CTRL, &ctrl) == -1)
{ {
@ -295,19 +308,20 @@ static HRESULT CDECL v4l_device_get_prop(struct video_capture_device *device,
return E_FAIL; return E_FAIL;
} }
*value = ctrl.value; *params->value = ctrl.value;
*flags = VideoProcAmp_Flags_Manual; *params->flags = VideoProcAmp_Flags_Manual;
return S_OK; return S_OK;
} }
static HRESULT CDECL v4l_device_set_prop(struct video_capture_device *device, static NTSTATUS v4l_device_set_prop( void *args )
VideoProcAmpProperty property, LONG value, LONG flags)
{ {
struct set_prop_params *params = args;
struct video_capture_device *device = params->device;
struct v4l2_control ctrl; struct v4l2_control ctrl;
ctrl.id = v4l2_cid_from_qcap_property(property); ctrl.id = v4l2_cid_from_qcap_property(params->property);
ctrl.value = value; ctrl.value = params->value;
if (xioctl(device->fd, VIDIOC_S_CTRL, &ctrl) == -1) if (xioctl(device->fd, VIDIOC_S_CTRL, &ctrl) == -1)
{ {
@ -337,8 +351,11 @@ static void reverse_image(struct video_capture_device *device, LPBYTE output, co
} }
} }
static BOOL CDECL v4l_device_read_frame(struct video_capture_device *device, BYTE *data) static NTSTATUS v4l_device_read_frame( void *args )
{ {
struct read_frame_params *params = args;
struct video_capture_device *device = params->device;
while (video_read(device->fd, device->image_data, device->image_size) < 0) while (video_read(device->fd, device->image_data, device->image_size) < 0)
{ {
if (errno != EAGAIN) if (errno != EAGAIN)
@ -348,7 +365,7 @@ static BOOL CDECL v4l_device_read_frame(struct video_capture_device *device, BYT
} }
} }
reverse_image(device, data, device->image_data); reverse_image(device, params->data, device->image_data);
return TRUE; return TRUE;
} }
@ -388,21 +405,29 @@ static void fill_caps(__u32 pixelformat, __u32 width, __u32 height,
caps->pixelformat = pixelformat; caps->pixelformat = pixelformat;
} }
static void CDECL v4l_device_get_caps(struct video_capture_device *device, LONG index, static NTSTATUS v4l_device_get_caps( void *args )
AM_MEDIA_TYPE *type, VIDEOINFOHEADER *format, VIDEO_STREAM_CONFIG_CAPS *vscc)
{ {
*vscc = device->caps[index].config; struct get_caps_params *params = args;
*type = device->caps[index].media_type; struct video_capture_device *device = params->device;
*format = device->caps[index].video_info;
*params->caps = device->caps[params->index].config;
*params->mt = device->caps[params->index].media_type;
*params->format = device->caps[params->index].video_info;
return S_OK;
} }
static LONG CDECL v4l_device_get_caps_count(struct video_capture_device *device) static NTSTATUS v4l_device_get_caps_count( void *args )
{ {
return device->caps_count; struct get_caps_count_params *params = args;
struct video_capture_device *device = params->device;
*params->count = device->caps_count;
return S_OK;
} }
static struct video_capture_device * CDECL v4l_device_create(USHORT index) static NTSTATUS v4l_device_create( void *args )
{ {
struct create_params *params = args;
struct v4l2_frmsizeenum frmsize = {0}; struct v4l2_frmsizeenum frmsize = {0};
struct video_capture_device *device; struct video_capture_device *device;
struct v4l2_capability caps = {{0}}; struct v4l2_capability caps = {{0}};
@ -415,9 +440,9 @@ static struct video_capture_device * CDECL v4l_device_create(USHORT index)
have_libv4l2 = video_init(); have_libv4l2 = video_init();
if (!(device = calloc(1, sizeof(*device)))) if (!(device = calloc(1, sizeof(*device))))
return NULL; return E_OUTOFMEMORY;
sprintf(path, "/dev/video%i", index); sprintf(path, "/dev/video%i", params->index);
TRACE("Opening device %s.\n", path); TRACE("Opening device %s.\n", path);
#ifdef O_CLOEXEC #ifdef O_CLOEXEC
if ((fd = video_open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC)) == -1 && errno == EINVAL) if ((fd = video_open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC)) == -1 && errno == EINVAL)
@ -542,35 +567,36 @@ static struct video_capture_device * CDECL v4l_device_create(USHORT index)
device->current_caps->video_info.bmiHeader.biWidth, device->current_caps->video_info.bmiHeader.biWidth,
device->current_caps->video_info.bmiHeader.biHeight); device->current_caps->video_info.bmiHeader.biHeight);
return device; *params->device = device;
return S_OK;
error: error:
v4l_device_destroy(device); device_destroy(device);
return NULL; return E_FAIL;
} }
const struct video_capture_funcs v4l_funcs = static NTSTATUS v4l_device_destroy( void *args )
{ {
.create = v4l_device_create, struct destroy_params *params = args;
.destroy = v4l_device_destroy,
.check_format = v4l_device_check_format, device_destroy( params->device );
.set_format = v4l_device_set_format, return S_OK;
.get_format = v4l_device_get_format, }
.get_media_type = v4l_device_get_media_type,
.get_caps = v4l_device_get_caps, unixlib_entry_t __wine_unix_call_funcs[] =
.get_caps_count = v4l_device_get_caps_count, {
.get_prop_range = v4l_device_get_prop_range, v4l_device_create,
.get_prop = v4l_device_get_prop, v4l_device_destroy,
.set_prop = v4l_device_set_prop, v4l_device_check_format,
.read_frame = v4l_device_read_frame, v4l_device_set_format,
v4l_device_get_format,
v4l_device_get_media_type,
v4l_device_get_caps,
v4l_device_get_caps_count,
v4l_device_get_prop_range,
v4l_device_get_prop,
v4l_device_set_prop,
v4l_device_read_frame,
}; };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
{
if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
*(const struct video_capture_funcs **)ptr_out = &v4l_funcs;
return STATUS_SUCCESS;
}
#endif /* HAVE_LINUX_VIDEODEV2_H */ #endif /* HAVE_LINUX_VIDEODEV2_H */

View file

@ -23,7 +23,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz); WINE_DEFAULT_DEBUG_CHANNEL(quartz);
static const struct video_capture_funcs *capture_funcs; static unixlib_handle_t v4l_handle;
#define V4L_CALL( func, params ) __wine_unix_call( v4l_handle, unix_ ## func, params )
struct vfw_capture struct vfw_capture
{ {
@ -95,7 +97,10 @@ static void vfw_capture_destroy(struct strmbase_filter *iface)
struct vfw_capture *filter = impl_from_strmbase_filter(iface); struct vfw_capture *filter = impl_from_strmbase_filter(iface);
if (filter->init) if (filter->init)
capture_funcs->destroy(filter->device); {
struct destroy_params params = { filter->device };
V4L_CALL( destroy, &params );
}
if (filter->source.pin.peer) if (filter->source.pin.peer)
{ {
@ -139,6 +144,7 @@ static DWORD WINAPI stream_thread(void *arg)
{ {
struct vfw_capture *filter = arg; struct vfw_capture *filter = arg;
const unsigned int image_size = get_image_size(filter); const unsigned int image_size = get_image_size(filter);
struct read_frame_params params;
for (;;) for (;;)
{ {
@ -168,7 +174,9 @@ static DWORD WINAPI stream_thread(void *arg)
IMediaSample_SetActualDataLength(sample, image_size); IMediaSample_SetActualDataLength(sample, image_size);
IMediaSample_GetPointer(sample, &data); IMediaSample_GetPointer(sample, &data);
if (!capture_funcs->read_frame(filter->device, data)) params.device = filter->device;
params.data = data;
if (!V4L_CALL( read_frame, &params ))
{ {
IMediaSample_Release(sample); IMediaSample_Release(sample);
break; break;
@ -284,6 +292,7 @@ static HRESULT WINAPI
AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt) AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
{ {
struct vfw_capture *This = impl_from_IAMStreamConfig(iface); struct vfw_capture *This = impl_from_IAMStreamConfig(iface);
struct set_format_params params;
HRESULT hr; HRESULT hr;
TRACE("filter %p, mt %p.\n", This, pmt); TRACE("filter %p, mt %p.\n", This, pmt);
@ -312,7 +321,9 @@ AMStreamConfig_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *pmt)
return VFW_E_INVALIDMEDIATYPE; return VFW_E_INVALIDMEDIATYPE;
} }
hr = capture_funcs->set_format(This->device, pmt); params.device = This->device;
params.mt = pmt;
hr = V4L_CALL( set_format, &params );
if (SUCCEEDED(hr) && This->filter.graph && This->source.pin.peer) if (SUCCEEDED(hr) && This->filter.graph && This->source.pin.peer)
{ {
hr = IFilterGraph_Reconnect(This->filter.graph, &This->source.pin.IPin_iface); hr = IFilterGraph_Reconnect(This->filter.graph, &This->source.pin.IPin_iface);
@ -344,7 +355,8 @@ static HRESULT WINAPI AMStreamConfig_GetFormat(IAMStreamConfig *iface, AM_MEDIA_
{ {
if ((format = CoTaskMemAlloc(sizeof(VIDEOINFOHEADER)))) if ((format = CoTaskMemAlloc(sizeof(VIDEOINFOHEADER))))
{ {
capture_funcs->get_format(filter->device, *mt, format); struct get_format_params params = { filter->device, *mt, format };
V4L_CALL( get_format, &params );
(*mt)->cbFormat = sizeof(VIDEOINFOHEADER); (*mt)->cbFormat = sizeof(VIDEOINFOHEADER);
(*mt)->pbFormat = (BYTE *)format; (*mt)->pbFormat = (BYTE *)format;
hr = S_OK; hr = S_OK;
@ -368,13 +380,14 @@ static HRESULT WINAPI AMStreamConfig_GetNumberOfCapabilities(IAMStreamConfig *if
int *count, int *size) int *count, int *size)
{ {
struct vfw_capture *filter = impl_from_IAMStreamConfig(iface); struct vfw_capture *filter = impl_from_IAMStreamConfig(iface);
struct get_caps_count_params params = { filter->device, count };
TRACE("filter %p, count %p, size %p.\n", filter, count, size); TRACE("filter %p, count %p, size %p.\n", filter, count, size);
if (!count || !size) if (!count || !size)
return E_POINTER; return E_POINTER;
*count = capture_funcs->get_caps_count(filter->device); V4L_CALL( get_caps_count, &params );
*size = sizeof(VIDEO_STREAM_CONFIG_CAPS); *size = sizeof(VIDEO_STREAM_CONFIG_CAPS);
return S_OK; return S_OK;
@ -386,10 +399,14 @@ static HRESULT WINAPI AMStreamConfig_GetStreamCaps(IAMStreamConfig *iface,
struct vfw_capture *filter = impl_from_IAMStreamConfig(iface); struct vfw_capture *filter = impl_from_IAMStreamConfig(iface);
VIDEOINFOHEADER *format; VIDEOINFOHEADER *format;
AM_MEDIA_TYPE *mt; AM_MEDIA_TYPE *mt;
int count;
struct get_caps_count_params count_params = { filter->device, &count };
struct get_caps_params caps_params;
TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter, index, pmt, vscc); TRACE("filter %p, index %d, pmt %p, vscc %p.\n", filter, index, pmt, vscc);
if (index > capture_funcs->get_caps_count(filter->device)) V4L_CALL( get_caps_count, &count_params );
if (index > count)
return S_FALSE; return S_FALSE;
if (!(mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)))) if (!(mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))))
@ -401,7 +418,12 @@ static HRESULT WINAPI AMStreamConfig_GetStreamCaps(IAMStreamConfig *iface,
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
capture_funcs->get_caps(filter->device, index, mt, format, (VIDEO_STREAM_CONFIG_CAPS *)vscc); caps_params.device = filter->device;
caps_params.index = index;
caps_params.mt = mt;
caps_params.format = format;
caps_params.caps = (VIDEO_STREAM_CONFIG_CAPS *)vscc;
V4L_CALL( get_caps, &caps_params );
mt->cbFormat = sizeof(VIDEOINFOHEADER); mt->cbFormat = sizeof(VIDEOINFOHEADER);
mt->pbFormat = (BYTE *)format; mt->pbFormat = (BYTE *)format;
*pmt = mt; *pmt = mt;
@ -441,32 +463,34 @@ static HRESULT WINAPI AMVideoProcAmp_GetRange(IAMVideoProcAmp *iface, LONG prope
LONG *min, LONG *max, LONG *step, LONG *default_value, LONG *flags) LONG *min, LONG *max, LONG *step, LONG *default_value, LONG *flags)
{ {
struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface); struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface);
struct get_prop_range_params params = { filter->device, property, min, max, step, default_value, flags };
TRACE("filter %p, property %#x, min %p, max %p, step %p, default_value %p, flags %p.\n", 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); filter, property, min, max, step, default_value, flags);
return capture_funcs->get_prop_range(filter->device, property, min, return V4L_CALL( get_prop_range, &params );
max, step, default_value, flags);
} }
static HRESULT WINAPI AMVideoProcAmp_Set(IAMVideoProcAmp *iface, LONG property, static HRESULT WINAPI AMVideoProcAmp_Set(IAMVideoProcAmp *iface, LONG property,
LONG value, LONG flags) LONG value, LONG flags)
{ {
struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface); struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface);
struct set_prop_params params = { filter->device, property, value, flags };
TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter, property, value, flags); TRACE("filter %p, property %#x, value %d, flags %#x.\n", filter, property, value, flags);
return capture_funcs->set_prop(filter->device, property, value, flags); return V4L_CALL( set_prop, &params );
} }
static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp *iface, LONG property, static HRESULT WINAPI AMVideoProcAmp_Get(IAMVideoProcAmp *iface, LONG property,
LONG *value, LONG *flags) LONG *value, LONG *flags)
{ {
struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface); struct vfw_capture *filter = impl_from_IAMVideoProcAmp(iface);
struct get_prop_params params = { filter->device, property, value, flags };
TRACE("filter %p, property %#x, value %p, flags %p.\n", filter, property, value, flags); TRACE("filter %p, property %#x, value %p, flags %p.\n", filter, property, value, flags);
return capture_funcs->get_prop(filter->device, property, value, flags); return V4L_CALL( get_prop, &params );
} }
static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable = static const IAMVideoProcAmpVtbl IAMVideoProcAmp_VTable =
@ -519,6 +543,7 @@ static HRESULT WINAPI PPB_InitNew(IPersistPropertyBag * iface)
static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *bag, IErrorLog *error_log) static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *bag, IErrorLog *error_log)
{ {
struct vfw_capture *filter = impl_from_IPersistPropertyBag(iface); struct vfw_capture *filter = impl_from_IPersistPropertyBag(iface);
struct create_params params;
HRESULT hr; HRESULT hr;
VARIANT var; VARIANT var;
@ -528,11 +553,12 @@ static HRESULT WINAPI PPB_Load(IPersistPropertyBag *iface, IPropertyBag *bag, IE
if (FAILED(hr = IPropertyBag_Read(bag, L"VFWIndex", &var, error_log))) if (FAILED(hr = IPropertyBag_Read(bag, L"VFWIndex", &var, error_log)))
return hr; return hr;
if (!(filter->device = capture_funcs->create(V_I4(&var)))) params.index = V_I4(&var);
return E_FAIL; params.device = &filter->device;
hr = V4L_CALL( create, &params );
filter->init = TRUE; if (SUCCEEDED(hr)) filter->init = TRUE;
return S_OK; return hr;
} }
static HRESULT WINAPI static HRESULT WINAPI
@ -639,20 +665,26 @@ 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) static HRESULT source_query_accept(struct strmbase_pin *pin, const AM_MEDIA_TYPE *mt)
{ {
struct vfw_capture *filter = impl_from_strmbase_pin(pin); struct vfw_capture *filter = impl_from_strmbase_pin(pin);
return capture_funcs->check_format(filter->device, mt); struct check_format_params params = { filter->device, mt };
return V4L_CALL( check_format, &params );
} }
static HRESULT source_get_media_type(struct strmbase_pin *pin, static HRESULT source_get_media_type(struct strmbase_pin *pin,
unsigned int index, AM_MEDIA_TYPE *mt) unsigned int index, AM_MEDIA_TYPE *mt)
{ {
struct vfw_capture *filter = impl_from_strmbase_pin(pin); struct vfw_capture *filter = impl_from_strmbase_pin(pin);
struct get_media_type_params params;
VIDEOINFOHEADER *format; VIDEOINFOHEADER *format;
HRESULT hr; HRESULT hr;
if (!(format = CoTaskMemAlloc(sizeof(*format)))) if (!(format = CoTaskMemAlloc(sizeof(*format))))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if ((hr = capture_funcs->get_media_type(filter->device, index, mt, format)) != S_OK) params.device = filter->device;
params.index = index;
params.mt = mt;
params.format = format;
if ((hr = V4L_CALL( get_media_type, &params )) != S_OK)
{ {
CoTaskMemFree(format); CoTaskMemFree(format);
return hr; return hr;
@ -826,7 +858,8 @@ static const IAMVideoControlVtbl IAMVideoControl_VTable =
static BOOL WINAPI load_capture_funcs(INIT_ONCE *once, void *param, void **context) static BOOL WINAPI load_capture_funcs(INIT_ONCE *once, void *param, void **context)
{ {
__wine_init_unix_lib(qcap_instance, DLL_PROCESS_ATTACH, NULL, &capture_funcs); NtQueryVirtualMemory( GetCurrentProcess(), qcap_instance, MemoryWineUnixFuncs,
&v4l_handle, sizeof(v4l_handle), NULL );
return TRUE; return TRUE;
} }
@ -836,7 +869,7 @@ HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out)
{ {
struct vfw_capture *object; struct vfw_capture *object;
if (!InitOnceExecuteOnce(&init_once, load_capture_funcs, NULL, NULL) || !capture_funcs) if (!InitOnceExecuteOnce(&init_once, load_capture_funcs, NULL, NULL) || !v4l_handle)
return E_FAIL; return E_FAIL;
if (!(object = calloc(1, sizeof(*object)))) if (!(object = calloc(1, sizeof(*object))))