mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-01 07:37:02 +00:00
qcap: Convert the Unix library to the __wine_unix_call interface.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
626f85f5f6
commit
62e2d7a99b
4 changed files with 255 additions and 110 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
170
dlls/qcap/v4l.c
170
dlls/qcap/v4l.c
|
@ -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(¶ms->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 */
|
||||||
|
|
|
@ -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, ¶ms );
|
||||||
|
}
|
||||||
|
|
||||||
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, ¶ms ))
|
||||||
{
|
{
|
||||||
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, ¶ms );
|
||||||
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, ¶ms );
|
||||||
(*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, ¶ms );
|
||||||
*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, ¶ms );
|
||||||
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, ¶ms );
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ¶ms );
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ¶ms );
|
||||||
|
|
||||||
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, ¶ms );
|
||||||
}
|
}
|
||||||
|
|
||||||
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, ¶ms )) != 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))))
|
||||||
|
|
Loading…
Reference in a new issue