dllhost: Add ISurrogate stub implementation.
[wine.git] / dlls / qcap / v4l.c
blob577cc8293291b7060db21fa353222022ee39d1e5
1 /*
2 * v4l2 backend to the VFW Capture filter
4 * Copyright 2005 Maarten Lankhorst
5 * Copyright 2019 Zebediah Figura
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #if 0
23 #pragma makedep unix
24 #endif
26 #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD /* work around ioctl breakage on Android */
28 #include "config.h"
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <dlfcn.h>
35 #include <sys/ioctl.h>
36 #include <sys/mman.h>
37 #include <errno.h>
38 #include <sys/time.h>
39 #ifdef HAVE_ASM_TYPES_H
40 #include <asm/types.h>
41 #endif
42 #ifdef HAVE_LINUX_VIDEODEV2_H
43 #include <linux/videodev2.h>
44 #endif
45 #include <unistd.h>
47 #include "ntstatus.h"
48 #define WIN32_NO_STATUS
49 #include "initguid.h"
50 #include "qcap_private.h"
51 #include "winternl.h"
53 #ifdef HAVE_LINUX_VIDEODEV2_H
55 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
56 WINE_DECLARE_DEBUG_CHANNEL(winediag);
58 static typeof(open) *video_open = open;
59 static typeof(close) *video_close = close;
60 static typeof(ioctl) *video_ioctl = ioctl;
61 static typeof(read) *video_read = read;
63 static BOOL video_init(void)
65 #ifdef SONAME_LIBV4L2
66 static void *video_lib;
68 if (video_lib)
69 return TRUE;
70 if (!(video_lib = dlopen(SONAME_LIBV4L2, RTLD_NOW)))
71 return FALSE;
72 video_open = dlsym(video_lib, "v4l2_open");
73 video_close = dlsym(video_lib, "v4l2_close");
74 video_ioctl = dlsym(video_lib, "v4l2_ioctl");
75 video_read = dlsym(video_lib, "v4l2_read");
77 return TRUE;
78 #else
79 return FALSE;
80 #endif
83 struct caps
85 __u32 pixelformat;
86 AM_MEDIA_TYPE media_type;
87 VIDEOINFOHEADER video_info;
88 VIDEO_STREAM_CONFIG_CAPS config;
91 struct video_capture_device
93 const struct caps *current_caps;
94 struct caps *caps;
95 LONG caps_count;
97 int image_size, image_pitch;
98 BYTE *image_data;
100 int fd, mmap;
103 static int xioctl(int fd, int request, void * arg)
105 int r;
107 do {
108 r = video_ioctl (fd, request, arg);
109 } while (-1 == r && EINTR == errno);
111 return r;
114 static struct video_capture_device *get_device( video_capture_device_t dev )
116 return (struct video_capture_device *)(ULONG_PTR)dev;
119 static void device_destroy(struct video_capture_device *device)
121 if (device->fd != -1)
122 video_close(device->fd);
123 if (device->caps_count)
124 free(device->caps);
125 free(device->image_data);
126 free(device);
129 static const struct caps *find_caps(struct video_capture_device *device, const AM_MEDIA_TYPE *mt)
131 const VIDEOINFOHEADER *video_info = (VIDEOINFOHEADER *)mt->pbFormat;
132 LONG index;
134 if (mt->cbFormat < sizeof(VIDEOINFOHEADER) || !video_info)
135 return NULL;
137 for (index = 0; index < device->caps_count; index++)
139 struct caps *caps = &device->caps[index];
141 if (IsEqualGUID(&mt->formattype, &caps->media_type.formattype)
142 && video_info->bmiHeader.biWidth == caps->video_info.bmiHeader.biWidth
143 && video_info->bmiHeader.biHeight == caps->video_info.bmiHeader.biHeight)
144 return caps;
146 return NULL;
149 static NTSTATUS v4l_device_check_format( void *args )
151 const struct check_format_params *params = args;
152 struct video_capture_device *device = get_device(params->device);
154 TRACE("device %p, mt %p.\n", device, params->mt);
156 if (!IsEqualGUID(&params->mt->majortype, &MEDIATYPE_Video))
157 return E_FAIL;
159 if (find_caps(device, params->mt))
160 return S_OK;
162 return E_FAIL;
165 static HRESULT set_caps(struct video_capture_device *device, const struct caps *caps)
167 struct v4l2_format format = {0};
168 LONG width, height, image_size;
169 BYTE *image_data;
171 width = caps->video_info.bmiHeader.biWidth;
172 height = caps->video_info.bmiHeader.biHeight;
173 image_size = width * height * caps->video_info.bmiHeader.biBitCount / 8;
175 if (!(image_data = malloc(image_size)))
177 ERR("Failed to allocate memory.\n");
178 return E_OUTOFMEMORY;
181 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
182 format.fmt.pix.pixelformat = caps->pixelformat;
183 format.fmt.pix.width = width;
184 format.fmt.pix.height = height;
185 if (xioctl(device->fd, VIDIOC_S_FMT, &format) == -1
186 || format.fmt.pix.pixelformat != caps->pixelformat
187 || format.fmt.pix.width != width
188 || format.fmt.pix.height != height)
190 ERR("Failed to set pixel format: %s.\n", strerror(errno));
191 free(image_data);
192 return VFW_E_TYPE_NOT_ACCEPTED;
195 device->current_caps = caps;
196 device->image_size = image_size;
197 device->image_pitch = width * caps->video_info.bmiHeader.biBitCount / 8;
198 free(device->image_data);
199 device->image_data = image_data;
200 return S_OK;
203 static NTSTATUS v4l_device_set_format( void *args )
205 const struct set_format_params *params = args;
206 struct video_capture_device *device = get_device(params->device);
207 const struct caps *caps;
209 caps = find_caps(device, params->mt);
210 if (!caps)
211 return E_FAIL;
213 if (device->current_caps == caps)
214 return S_OK;
216 return set_caps(device, caps);
219 static NTSTATUS v4l_device_get_format( void *args )
221 const struct get_format_params *params = args;
222 struct video_capture_device *device = get_device(params->device);
224 *params->mt = device->current_caps->media_type;
225 *params->format = device->current_caps->video_info;
226 return S_OK;
229 static NTSTATUS v4l_device_get_media_type( void *args )
231 const struct get_media_type_params *params = args;
232 struct video_capture_device *device = get_device(params->device);
233 unsigned int caps_count = (device->current_caps) ? 1 : device->caps_count;
235 if (params->index >= caps_count)
236 return VFW_S_NO_MORE_ITEMS;
238 if (device->current_caps)
240 *params->mt = device->current_caps->media_type;
241 *params->format = device->current_caps->video_info;
243 else
245 *params->mt = device->caps[params->index].media_type;
246 *params->format = device->caps[params->index].video_info;
248 return S_OK;
251 static __u32 v4l2_cid_from_qcap_property(VideoProcAmpProperty property)
253 switch (property)
255 case VideoProcAmp_Brightness:
256 return V4L2_CID_BRIGHTNESS;
257 case VideoProcAmp_Contrast:
258 return V4L2_CID_CONTRAST;
259 case VideoProcAmp_Hue:
260 return V4L2_CID_HUE;
261 case VideoProcAmp_Saturation:
262 return V4L2_CID_SATURATION;
263 default:
264 FIXME("Unhandled property %d.\n", property);
265 return 0;
269 static NTSTATUS v4l_device_get_prop_range( void *args )
271 const struct get_prop_range_params *params = args;
272 struct video_capture_device *device = get_device(params->device);
273 struct v4l2_queryctrl ctrl;
275 ctrl.id = v4l2_cid_from_qcap_property(params->property);
277 if (xioctl(device->fd, VIDIOC_QUERYCTRL, &ctrl) == -1)
279 WARN("Failed to query control: %s\n", strerror(errno));
280 return E_PROP_ID_UNSUPPORTED;
283 *params->min = ctrl.minimum;
284 *params->max = ctrl.maximum;
285 *params->step = ctrl.step;
286 *params->default_value = ctrl.default_value;
287 *params->flags = VideoProcAmp_Flags_Manual;
288 return S_OK;
291 static NTSTATUS v4l_device_get_prop( void *args )
293 const struct get_prop_params *params = args;
294 struct video_capture_device *device = get_device(params->device);
295 struct v4l2_control ctrl;
297 ctrl.id = v4l2_cid_from_qcap_property(params->property);
299 if (xioctl(device->fd, VIDIOC_G_CTRL, &ctrl) == -1)
301 WARN("Failed to get property: %s\n", strerror(errno));
302 return E_FAIL;
305 *params->value = ctrl.value;
306 *params->flags = VideoProcAmp_Flags_Manual;
308 return S_OK;
311 static NTSTATUS v4l_device_set_prop( void *args )
313 const struct set_prop_params *params = args;
314 struct video_capture_device *device = get_device(params->device);
315 struct v4l2_control ctrl;
317 ctrl.id = v4l2_cid_from_qcap_property(params->property);
318 ctrl.value = params->value;
320 if (xioctl(device->fd, VIDIOC_S_CTRL, &ctrl) == -1)
322 WARN("Failed to set property: %s\n", strerror(errno));
323 return E_FAIL;
326 return S_OK;
329 static void reverse_image(struct video_capture_device *device, LPBYTE output, const BYTE *input)
331 int inoffset, outoffset, pitch;
333 /* the whole image needs to be reversed,
334 because the dibs are messed up in windows */
335 outoffset = device->image_size;
336 pitch = device->image_pitch;
337 inoffset = 0;
338 while (outoffset > 0)
340 int x;
341 outoffset -= pitch;
342 for (x = 0; x < pitch; x++)
343 output[outoffset + x] = input[inoffset + x];
344 inoffset += pitch;
348 static NTSTATUS v4l_device_read_frame( void *args )
350 const struct read_frame_params *params = args;
351 struct video_capture_device *device = get_device(params->device);
353 while (video_read(device->fd, device->image_data, device->image_size) < 0)
355 if (errno != EAGAIN)
357 ERR("Failed to read frame: %s\n", strerror(errno));
358 return FALSE;
362 reverse_image(device, params->data, device->image_data);
363 return TRUE;
366 static void fill_caps(__u32 pixelformat, __u32 width, __u32 height,
367 __u32 max_fps, __u32 min_fps, struct caps *caps)
369 LONG depth = 24;
371 memset(caps, 0, sizeof(*caps));
372 caps->video_info.dwBitRate = width * height * depth * max_fps;
373 caps->video_info.bmiHeader.biSize = sizeof(caps->video_info.bmiHeader);
374 caps->video_info.bmiHeader.biWidth = width;
375 caps->video_info.bmiHeader.biHeight = height;
376 caps->video_info.bmiHeader.biPlanes = 1;
377 caps->video_info.bmiHeader.biBitCount = depth;
378 caps->video_info.bmiHeader.biCompression = BI_RGB;
379 caps->video_info.bmiHeader.biSizeImage = width * height * depth / 8;
380 caps->media_type.majortype = MEDIATYPE_Video;
381 caps->media_type.subtype = MEDIASUBTYPE_RGB24;
382 caps->media_type.bFixedSizeSamples = TRUE;
383 caps->media_type.bTemporalCompression = FALSE;
384 caps->media_type.lSampleSize = width * height * depth / 8;
385 caps->media_type.formattype = FORMAT_VideoInfo;
386 caps->media_type.pUnk = NULL;
387 caps->media_type.cbFormat = sizeof(VIDEOINFOHEADER);
388 /* We reallocate the caps array, so pbFormat has to be set after all caps
389 * have been enumerated. */
390 caps->config.MaxFrameInterval = 10000000 * max_fps;
391 caps->config.MinFrameInterval = 10000000 * min_fps;
392 caps->config.MaxOutputSize.cx = width;
393 caps->config.MaxOutputSize.cy = height;
394 caps->config.MinOutputSize.cx = width;
395 caps->config.MinOutputSize.cy = height;
396 caps->config.guid = FORMAT_VideoInfo;
397 caps->config.MinBitsPerSecond = width * height * depth * min_fps;
398 caps->config.MaxBitsPerSecond = width * height * depth * max_fps;
399 caps->pixelformat = pixelformat;
402 static NTSTATUS v4l_device_get_caps( void *args )
404 const struct get_caps_params *params = args;
405 struct video_capture_device *device = get_device(params->device);
407 *params->caps = device->caps[params->index].config;
408 *params->mt = device->caps[params->index].media_type;
409 *params->format = device->caps[params->index].video_info;
410 return S_OK;
413 static NTSTATUS v4l_device_get_caps_count( void *args )
415 const struct get_caps_count_params *params = args;
416 struct video_capture_device *device = get_device(params->device);
418 *params->count = device->caps_count;
419 return S_OK;
422 static NTSTATUS v4l_device_create( void *args )
424 const struct create_params *params = args;
425 struct v4l2_frmsizeenum frmsize = {0};
426 struct video_capture_device *device;
427 struct v4l2_capability caps = {{0}};
428 struct v4l2_format format = {0};
429 BOOL have_libv4l2;
430 char path[20];
431 HRESULT hr;
432 int fd, i;
434 have_libv4l2 = video_init();
436 if (!(device = calloc(1, sizeof(*device))))
437 return E_OUTOFMEMORY;
439 sprintf(path, "/dev/video%i", params->index);
440 TRACE("Opening device %s.\n", path);
441 #ifdef O_CLOEXEC
442 if ((fd = video_open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC)) == -1 && errno == EINVAL)
443 #endif
444 fd = video_open(path, O_RDWR | O_NONBLOCK);
445 if (fd == -1)
447 WARN("Failed to open video device: %s\n", strerror(errno));
448 goto error;
450 fcntl(fd, F_SETFD, FD_CLOEXEC); /* in case O_CLOEXEC isn't supported */
451 device->fd = fd;
453 if (xioctl(fd, VIDIOC_QUERYCAP, &caps) == -1)
455 WARN("Failed to query device capabilities: %s\n", strerror(errno));
456 goto error;
459 #ifdef V4L2_CAP_DEVICE_CAPS
460 if (caps.capabilities & V4L2_CAP_DEVICE_CAPS)
461 caps.capabilities = caps.device_caps;
462 #endif
464 if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))
466 WARN("Device does not support single-planar video capture.\n");
467 goto error;
470 if (!(caps.capabilities & V4L2_CAP_READWRITE))
472 WARN("Device does not support read().\n");
473 if (!have_libv4l2)
474 #ifdef SONAME_LIBV4L2
475 ERR_(winediag)("Reading from %s requires libv4l2, but it could not be loaded.\n", path);
476 #else
477 ERR_(winediag)("Reading from %s requires libv4l2, but Wine was compiled without libv4l2 support.\n", path);
478 #endif
479 goto error;
482 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
483 if (xioctl(fd, VIDIOC_G_FMT, &format) == -1)
485 ERR("Failed to get device format: %s\n", strerror(errno));
486 goto error;
489 format.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
490 if (xioctl(fd, VIDIOC_TRY_FMT, &format) == -1
491 || format.fmt.pix.pixelformat != V4L2_PIX_FMT_BGR24)
493 ERR("This device doesn't support V4L2_PIX_FMT_BGR24 format.\n");
494 goto error;
497 frmsize.pixel_format = V4L2_PIX_FMT_BGR24;
498 while (xioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) != -1)
500 struct v4l2_frmivalenum frmival = {0};
501 __u32 max_fps = 30, min_fps = 30;
502 struct caps *new_caps;
504 frmival.pixel_format = format.fmt.pix.pixelformat;
505 if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE)
507 frmival.width = frmsize.discrete.width;
508 frmival.height = frmsize.discrete.height;
510 else if (frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE)
512 frmival.width = frmsize.stepwise.max_width;
513 frmival.height = frmsize.stepwise.min_height;
515 else
517 FIXME("Unhandled frame size type: %d.\n", frmsize.type);
518 continue;
521 if (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) != -1)
523 if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE)
525 max_fps = frmival.discrete.denominator / frmival.discrete.numerator;
526 min_fps = max_fps;
528 else if (frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE
529 || frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)
531 max_fps = frmival.stepwise.max.denominator / frmival.stepwise.max.numerator;
532 min_fps = frmival.stepwise.min.denominator / frmival.stepwise.min.numerator;
535 else
536 ERR("Failed to get fps: %s.\n", strerror(errno));
538 new_caps = realloc(device->caps, (device->caps_count + 1) * sizeof(*device->caps));
539 if (!new_caps)
540 goto error;
541 device->caps = new_caps;
542 fill_caps(format.fmt.pix.pixelformat, frmsize.discrete.width, frmsize.discrete.height,
543 max_fps, min_fps, &device->caps[device->caps_count]);
544 device->caps_count++;
546 frmsize.index++;
549 /* We reallocate the caps array, so we have to delay setting pbFormat. */
550 for (i = 0; i < device->caps_count; ++i)
551 device->caps[i].media_type.pbFormat = (BYTE *)&device->caps[i].video_info;
553 if (FAILED(hr = set_caps(device, &device->caps[0])))
555 if (hr == VFW_E_TYPE_NOT_ACCEPTED && !have_libv4l2)
556 ERR_(winediag)("You may need libv4l2 to use this device.\n");
557 goto error;
560 TRACE("Format: %d bpp - %dx%d.\n", device->current_caps->video_info.bmiHeader.biBitCount,
561 (int)device->current_caps->video_info.bmiHeader.biWidth,
562 (int)device->current_caps->video_info.bmiHeader.biHeight);
564 *params->device = (ULONG_PTR)device;
565 return S_OK;
567 error:
568 device_destroy(device);
569 return E_FAIL;
572 static NTSTATUS v4l_device_destroy( void *args )
574 const struct destroy_params *params = args;
576 device_destroy( get_device(params->device) );
577 return S_OK;
580 const unixlib_entry_t __wine_unix_call_funcs[] =
582 v4l_device_create,
583 v4l_device_destroy,
584 v4l_device_check_format,
585 v4l_device_set_format,
586 v4l_device_get_format,
587 v4l_device_get_media_type,
588 v4l_device_get_caps,
589 v4l_device_get_caps_count,
590 v4l_device_get_prop_range,
591 v4l_device_get_prop,
592 v4l_device_set_prop,
593 v4l_device_read_frame,
596 #ifdef _WIN64
598 typedef ULONG PTR32;
600 struct am_media_type32
602 GUID majortype;
603 GUID subtype;
604 BOOL bFixedSizeSamples;
605 BOOL bTemporalCompression;
606 ULONG lSampleSize;
607 GUID formattype;
608 PTR32 pUnk;
609 ULONG cbFormat;
610 PTR32 pbFormat;
613 static AM_MEDIA_TYPE *get_media_type( const struct am_media_type32 *mt32, AM_MEDIA_TYPE *mt )
615 mt->majortype = mt32->majortype;
616 mt->subtype = mt32->subtype;
617 mt->bFixedSizeSamples = mt32->bFixedSizeSamples;
618 mt->bTemporalCompression = mt32->bTemporalCompression;
619 mt->lSampleSize = mt32->lSampleSize;
620 mt->formattype = mt32->formattype;
621 mt->pUnk = NULL;
622 mt->cbFormat = mt32->cbFormat;
623 mt->pbFormat = ULongToPtr(mt32->pbFormat);
624 return mt;
627 static void put_media_type( const AM_MEDIA_TYPE *mt, struct am_media_type32 *mt32 )
629 mt32->majortype = mt->majortype;
630 mt32->subtype = mt->subtype;
631 mt32->bFixedSizeSamples = mt->bFixedSizeSamples;
632 mt32->bTemporalCompression = mt->bTemporalCompression;
633 mt32->lSampleSize = mt->lSampleSize;
634 mt32->formattype = mt->formattype;
637 static NTSTATUS wow64_v4l_device_create( void *args )
639 struct
641 unsigned int index;
642 PTR32 device;
643 } const *params32 = args;
645 struct create_params params =
647 params32->index,
648 ULongToPtr(params32->device)
651 return v4l_device_create( &params );
654 static NTSTATUS wow64_v4l_device_check_format( void *args )
656 struct
658 video_capture_device_t device;
659 PTR32 mt;
660 } const *params32 = args;
662 AM_MEDIA_TYPE mt;
663 struct check_format_params params =
665 params32->device,
666 get_media_type( ULongToPtr(params32->mt), &mt )
669 return v4l_device_check_format( &params );
672 static NTSTATUS wow64_v4l_device_set_format( void *args )
674 struct
676 video_capture_device_t device;
677 PTR32 mt;
678 } const *params32 = args;
680 AM_MEDIA_TYPE mt;
681 struct set_format_params params =
683 params32->device,
684 get_media_type( ULongToPtr(params32->mt), &mt )
687 return v4l_device_set_format( &params );
690 static NTSTATUS wow64_v4l_device_get_format( void *args )
692 struct
694 video_capture_device_t device;
695 PTR32 mt;
696 PTR32 format;
697 } const *params32 = args;
699 AM_MEDIA_TYPE mt;
700 struct get_format_params params =
702 params32->device,
703 &mt,
704 ULongToPtr(params32->format)
707 NTSTATUS status = v4l_device_get_format( &params );
708 if (!status) put_media_type( &mt, ULongToPtr(params32->mt) );
709 return status;
712 static NTSTATUS wow64_v4l_device_get_media_type( void *args )
714 struct
716 video_capture_device_t device;
717 unsigned int index;
718 PTR32 mt;
719 PTR32 format;
720 } const *params32 = args;
722 AM_MEDIA_TYPE mt;
723 struct get_media_type_params params =
725 params32->device,
726 params32->index,
727 &mt,
728 ULongToPtr(params32->format)
731 NTSTATUS status = v4l_device_get_media_type( &params );
732 if (!status) put_media_type( &mt, ULongToPtr(params32->mt) );
733 return status;
736 static NTSTATUS wow64_v4l_device_get_caps( void *args )
738 struct
740 video_capture_device_t device;
741 unsigned int index;
742 PTR32 mt;
743 PTR32 format;
744 PTR32 caps;
745 } const *params32 = args;
747 AM_MEDIA_TYPE mt;
748 struct get_caps_params params =
750 params32->device,
751 params32->index,
752 &mt,
753 ULongToPtr(params32->format),
754 ULongToPtr(params32->caps)
757 NTSTATUS status = v4l_device_get_caps( &params );
758 if (!status) put_media_type( &mt, ULongToPtr(params32->mt) );
759 return status;
762 static NTSTATUS wow64_v4l_device_get_caps_count( void *args )
764 struct
766 video_capture_device_t device;
767 PTR32 count;
768 } const *params32 = args;
770 struct get_caps_count_params params =
772 params32->device,
773 ULongToPtr(params32->count)
776 return v4l_device_get_caps_count( &params );
779 static NTSTATUS wow64_v4l_device_get_prop_range( void *args )
781 struct
783 video_capture_device_t device;
784 VideoProcAmpProperty property;
785 PTR32 min;
786 PTR32 max;
787 PTR32 step;
788 PTR32 default_value;
789 PTR32 flags;
790 } const *params32 = args;
792 struct get_prop_range_params params =
794 params32->device,
795 params32->property,
796 ULongToPtr(params32->min),
797 ULongToPtr(params32->max),
798 ULongToPtr(params32->step),
799 ULongToPtr(params32->default_value),
800 ULongToPtr(params32->flags)
803 return v4l_device_get_prop_range( &params );
806 static NTSTATUS wow64_v4l_device_get_prop( void *args )
808 struct
810 video_capture_device_t device;
811 VideoProcAmpProperty property;
812 PTR32 value;
813 PTR32 flags;
814 } const *params32 = args;
816 struct get_prop_params params =
818 params32->device,
819 params32->property,
820 ULongToPtr(params32->value),
821 ULongToPtr(params32->flags)
824 return v4l_device_get_prop( &params );
827 static NTSTATUS wow64_v4l_device_read_frame( void *args )
829 struct
831 video_capture_device_t device;
832 PTR32 data;
833 } const *params32 = args;
835 struct read_frame_params params =
837 params32->device,
838 ULongToPtr(params32->data)
841 return v4l_device_read_frame( &params );
844 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
846 wow64_v4l_device_create,
847 v4l_device_destroy,
848 wow64_v4l_device_check_format,
849 wow64_v4l_device_set_format,
850 wow64_v4l_device_get_format,
851 wow64_v4l_device_get_media_type,
852 wow64_v4l_device_get_caps,
853 wow64_v4l_device_get_caps_count,
854 wow64_v4l_device_get_prop_range,
855 wow64_v4l_device_get_prop,
856 v4l_device_set_prop,
857 wow64_v4l_device_read_frame,
860 #endif /* _WIN64 */
862 #endif /* HAVE_LINUX_VIDEODEV2_H */