26#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
43#ifdef HAVE_ASM_TYPES_H
46#ifdef HAVE_LINUX_VIDEODEV2_H
47#include <linux/videodev2.h>
52#define WIN32_NO_STATUS
57#ifdef HAVE_LINUX_VIDEODEV2_H
67static BOOL video_init(
void)
70 static void *video_lib;
74 if (!(video_lib = dlopen(SONAME_LIBV4L2,
RTLD_NOW)))
76 video_open = dlsym(video_lib,
"v4l2_open");
77 video_close = dlsym(video_lib,
"v4l2_close");
78 video_ioctl = dlsym(video_lib,
"v4l2_ioctl");
79 video_read = dlsym(video_lib,
"v4l2_read");
92 VIDEO_STREAM_CONFIG_CAPS
config;
95struct video_capture_device
97 const struct caps *current_caps;
100 struct v4l2_format device_format;
125static void device_destroy(
struct video_capture_device *
device)
135static const struct caps *find_caps(
struct video_capture_device *
device,
const AM_MEDIA_TYPE *mt)
147 if (
IsEqualGUID(&mt->formattype, &caps->media_type.formattype)
171static HRESULT set_caps(
struct video_capture_device *
device,
const struct caps *caps,
BOOL try)
173 struct v4l2_format
format = {0};
177 width = caps->video_info.bmiHeader.biWidth;
178 height = caps->video_info.bmiHeader.biHeight;
183 ERR(
"Failed to allocate memory.\n");
187 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
188 format.fmt.pix.pixelformat = caps->pixelformat;
191 if (xioctl(
device->fd,
try ? VIDIOC_TRY_FMT : VIDIOC_S_FMT, &
format) == -1
192 ||
format.fmt.pix.pixelformat != caps->pixelformat
203 device->current_caps = caps;
205 device->image_pitch =
width * caps->video_info.bmiHeader.biBitCount / 8;
207 device->image_data = image_data;
215 const struct caps *caps;
221 if (
device->current_caps == caps)
241 unsigned int caps_count = (
device->current_caps) ? 1 :
device->caps_count;
263 case VideoProcAmp_Brightness:
264 return V4L2_CID_BRIGHTNESS;
266 return V4L2_CID_CONTRAST;
270 return V4L2_CID_SATURATION;
281 struct v4l2_queryctrl
ctrl;
283 ctrl.id = v4l2_cid_from_qcap_property(
params->property);
285 if (xioctl(
device->fd, VIDIOC_QUERYCTRL, &
ctrl) == -1)
303 struct v4l2_control
ctrl;
305 ctrl.id = v4l2_cid_from_qcap_property(
params->property);
307 if (xioctl(
device->fd, VIDIOC_G_CTRL, &
ctrl) == -1)
323 struct v4l2_control
ctrl;
325 ctrl.id = v4l2_cid_from_qcap_property(
params->property);
328 if (xioctl(
device->fd, VIDIOC_S_CTRL, &
ctrl) == -1)
339 int inoffset, outoffset, pitch;
343 outoffset =
device->image_size;
344 pitch =
device->image_pitch;
346 while (outoffset > 0)
350 for (
x = 0;
x < pitch;
x++)
351 output[outoffset +
x] =
input[inoffset +
x];
375 __u32 max_fps,
__u32 min_fps,
struct caps *caps)
379 memset(caps, 0,
sizeof(*caps));
381 caps->video_info.bmiHeader.biSize =
sizeof(caps->video_info.bmiHeader);
382 caps->video_info.bmiHeader.biWidth =
width;
383 caps->video_info.bmiHeader.biHeight =
height;
384 caps->video_info.bmiHeader.biPlanes = 1;
385 caps->video_info.bmiHeader.biBitCount =
depth;
386 caps->video_info.bmiHeader.biCompression =
BI_RGB;
388 caps->media_type.majortype = MEDIATYPE_Video;
389 caps->media_type.subtype = MEDIASUBTYPE_RGB24;
390 caps->media_type.bFixedSizeSamples =
TRUE;
391 caps->media_type.bTemporalCompression =
FALSE;
393 caps->media_type.formattype = FORMAT_VideoInfo;
394 caps->media_type.pUnk =
NULL;
398 caps->config.MaxFrameInterval = 10000000 / max_fps;
399 caps->config.MinFrameInterval = 10000000 / min_fps;
400 caps->config.MaxOutputSize.cx =
width;
401 caps->config.MaxOutputSize.cy =
height;
402 caps->config.MinOutputSize.cx =
width;
403 caps->config.MinOutputSize.cy =
height;
404 caps->config.guid = FORMAT_VideoInfo;
433 struct v4l2_frmsizeenum frmsize = {0};
434 struct video_capture_device *
device;
435 struct v4l2_capability caps = {{0}};
436 struct v4l2_format
format = {0};
442 have_libv4l2 = video_init();
461 if (xioctl(
fd, VIDIOC_QUERYCAP, &caps) == -1)
467#ifdef V4L2_CAP_DEVICE_CAPS
468 if (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
469 caps.capabilities = caps.device_caps;
472 if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))
474 WARN(
"Device does not support single-planar video capture.\n");
478 if (!(caps.capabilities & V4L2_CAP_READWRITE))
480 WARN(
"Device does not support read().\n");
483 ERR_(winediag)(
"Reading from %s requires libv4l2, but it could not be loaded.\n",
path);
485 ERR_(winediag)(
"Reading from %s requires libv4l2, but Wine was compiled without libv4l2 support.\n",
path);
490 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
491 if (xioctl(
fd, VIDIOC_G_FMT, &
format) == -1)
497 format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
498 if (xioctl(
fd, VIDIOC_TRY_FMT, &
format) == -1
499 ||
format.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24)
501 ERR(
"This device doesn't support V4L2_PIX_FMT_BGR24 format.\n");
505 frmsize.pixel_format = V4L2_PIX_FMT_BGR24;
506 while (xioctl(
fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) != -1)
508 struct v4l2_frmivalenum frmival = {0};
509 __u32 max_fps = 30, min_fps = 30;
510 struct caps *new_caps;
512 frmival.pixel_format =
format.fmt.pix.pixelformat;
513 if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
515 frmival.
width = frmsize.discrete.width;
516 frmival.height = frmsize.discrete.height;
518 else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)
520 frmival.width = frmsize.stepwise.max_width;
521 frmival.height = frmsize.stepwise.min_height;
525 FIXME(
"Unhandled frame size type: %d.\n", frmsize.type);
529 if (xioctl(
fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) != -1)
531 if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE)
533 max_fps = frmival.discrete.denominator / frmival.discrete.numerator;
536 else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE
537 || frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)
539 min_fps = frmival.stepwise.max.denominator / frmival.stepwise.max.numerator;
540 max_fps = frmival.stepwise.min.denominator / frmival.stepwise.min.numerator;
550 fill_caps(
format.fmt.pix.pixelformat, frmsize.discrete.
width, frmsize.discrete.height,
564 ERR_(winediag)(
"You may need libv4l2 to use this device.\n");
568 TRACE(
"Format: %d bpp - %dx%d.\n",
device->current_caps->video_info.bmiHeader.biBitCount,
569 (
int)
device->current_caps->video_info.bmiHeader.biWidth,
570 (
int)
device->current_caps->video_info.bmiHeader.biHeight);
587 if (xioctl(
device->fd, VIDIOC_S_FMT, &
device->device_format) == -1)
609 v4l_device_check_format,
610 v4l_device_set_format,
611 v4l_device_get_format,
612 v4l_device_get_media_type,
614 v4l_device_get_caps_count,
615 v4l_device_get_prop_range,
618 v4l_device_read_frame,
627struct am_media_type32
631 BOOL bFixedSizeSamples;
632 BOOL bTemporalCompression;
642 mt->majortype = mt32->majortype;
643 mt->subtype = mt32->subtype;
644 mt->bFixedSizeSamples = mt32->bFixedSizeSamples;
645 mt->bTemporalCompression = mt32->bTemporalCompression;
646 mt->lSampleSize = mt32->lSampleSize;
647 mt->formattype = mt32->formattype;
649 mt->cbFormat = mt32->cbFormat;
654static void put_media_type(
const AM_MEDIA_TYPE *mt,
struct am_media_type32 *mt32 )
656 mt32->majortype = mt->majortype;
657 mt32->subtype = mt->subtype;
658 mt32->bFixedSizeSamples = mt->bFixedSizeSamples;
659 mt32->bTemporalCompression = mt->bTemporalCompression;
660 mt32->lSampleSize = mt->lSampleSize;
661 mt32->formattype = mt->formattype;
670 }
const *params32 =
args;
678 return v4l_device_create( &
params );
681static NTSTATUS wow64_v4l_device_check_format(
void *
args )
687 }
const *params32 =
args;
696 return v4l_device_check_format( &
params );
699static NTSTATUS wow64_v4l_device_set_format(
void *
args )
705 }
const *params32 =
args;
714 return v4l_device_set_format( &
params );
717static NTSTATUS wow64_v4l_device_get_format(
void *
args )
724 }
const *params32 =
args;
739static NTSTATUS wow64_v4l_device_get_media_type(
void *
args )
747 }
const *params32 =
args;
772 }
const *params32 =
args;
789static NTSTATUS wow64_v4l_device_get_caps_count(
void *
args )
795 }
const *params32 =
args;
803 return v4l_device_get_caps_count( &
params );
806static NTSTATUS wow64_v4l_device_get_prop_range(
void *
args )
817 }
const *params32 =
args;
830 return v4l_device_get_prop_range( &
params );
841 }
const *params32 =
args;
851 return v4l_device_get_prop( &
params );
854static NTSTATUS wow64_v4l_device_read_frame(
void *
args )
860 }
const *params32 =
args;
868 return v4l_device_read_frame( &
params );
871const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
873 wow64_v4l_device_create,
876 wow64_v4l_device_check_format,
877 wow64_v4l_device_set_format,
878 wow64_v4l_device_get_format,
879 wow64_v4l_device_get_media_type,
880 wow64_v4l_device_get_caps,
881 wow64_v4l_device_get_caps_count,
882 wow64_v4l_device_get_prop_range,
883 wow64_v4l_device_get_prop,
885 wow64_v4l_device_read_frame,
enum VideoProcAmp_Contrast
enum VideoProcAmp_Saturation
@ VideoProcAmp_Flags_Manual
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
const unixlib_entry_t __wine_unix_call_funcs[]
BOOL get_media_type(const WCHAR *filename, GUID *majortype, GUID *subtype, GUID *source_clsid)
#define WINE_DECLARE_DEBUG_CHANNEL(x)
char *CDECL strerror(int err)
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
struct tagVIDEOINFOHEADER VIDEOINFOHEADER
GLint GLint GLsizei GLsizei GLsizei depth
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei count
GLint GLint GLsizei GLsizei height
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble r
GLint GLint GLsizei width
GLenum const GLfloat * params
GLenum GLenum GLenum input
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
static HANDLE get_device(USHORT page, USHORT usages[], UINT usage_count, DWORD access)
#define IsEqualGUID(rguid1, rguid2)
UINT64 video_capture_device_t
video_capture_device_t * device
video_capture_device_t device
video_capture_device_t device
video_capture_device_t device
VideoProcAmpProperty property
video_capture_device_t device
video_capture_device_t device
#define E_PROP_ID_UNSUPPORTED
#define VFW_E_TYPE_NOT_ACCEPTED
#define VFW_S_NO_MORE_ITEMS
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
#define ERROR_NO_SYSTEM_RESOURCES