1 /* This is the contributed code:
4 Current Location: ../opencv-0.9.6/otherlibs/highgui
6 Original Version: 2003-03-12 Magnus Lundin lundin@mlu.mine.nu
9 ML:This set of files adds support for firevre and usb cameras.
10 First it tries to install a firewire camera,
11 if that fails it tries a v4l/USB camera
12 It has been tested with the motempl sample program
14 First Patch: August 24, 2004 Travis Wood TravisOCV@tkwood.com
15 For Release: OpenCV-Linux Beta4 opencv-0.9.6
16 Tested On: LMLBT44 with 8 video inputs
17 Problems? Post problems/fixes to OpenCV group on groups.yahoo.com
20 TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
21 were not working. I have rewritten them so they work for me. At the same time, trying
22 to keep the original code as ML wrote it as unchanged as possible. No one likes to debug
23 someone elses code, so I resisted changes as much as possible. I have tried to keep the
24 same "ideas" where applicable, that is, where I could figure out what the previous author
25 intended. Some areas I just could not help myself and had to "spiffy-it-up" my way.
27 These drivers should work with other V4L frame capture cards other then my bttv
28 driven frame capture card.
30 Re Written driver for standard V4L mode. Tested using LMLBT44 video capture card.
31 Standard bttv drivers are on the LMLBT44 with up to 8 Inputs.
33 This utility was written with the help of the document:
34 http://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo
35 as a general guide for interfacing into the V4l standard.
37 Made the index value passed for icvOpenCAM_V4L(index) be the number of the
38 video device source in the /dev tree. The -1 uses original /dev/video.
50 TW: You can select any video source, but this package was limited from the start to only
51 ONE camera opened at any ONE time.
52 This is an original program limitation.
53 If you are interested, I will make my version available to other OpenCV users. The big
54 difference in mine is you may pass the camera number as part of the cv argument, but this
55 convention is non standard for current OpenCV calls and the camera number is not currently
56 passed into the called routine.
58 Second Patch: August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
59 For Release: OpenCV-Linux Beta4 Opencv-0.9.6
61 FS: this patch fix not sequential index of device (unplugged device), and real numCameras.
62 for -1 index (icvOpenCAM_V4L) i dont use /dev/video but real device available, because
63 if /dev/video is a link to /dev/video0 and i unplugged device on /dev/video0, /dev/video
64 is a bad link. I search the first available device with indexList.
66 Third Patch: December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
67 For Release: OpenCV-Linux Beta4 Opencv-0.9.6
69 [FD] I modified the following:
70 - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point
71 - cvGrabFrame should not wait for the end of the first frame, and should return quickly
73 - cvRetrieveFrame should in turn wait for the end of frame capture, and should not
74 trigger the capture of the next frame (the user choses when to do it using GrabFrame)
75 To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame.
76 - having global bufferIndex and FirstCapture variables makes the code non-reentrant
77 (e.g. when using several cameras), put these in the CvCapture struct.
78 - according to V4L HowTo, incrementing the buffer index must be done before VIDIOCMCAPTURE.
79 - the VID_TYPE_SCALES stuff from V4L HowTo is wrong: image size can be changed
80 even if the hardware does not support scaling (e.g. webcams can have several
81 resolutions available). Just don't try to set the size at 640x480 if the hardware supports
82 scaling: open with the default (probably best) image size, and let the user scale it
84 - image size can be changed by two subsequent calls to SetProperty (for width and height)
85 - bug fix: if the image size changes, realloc the new image only when it is grabbed
86 - issue errors only when necessary, fix error message formatting.
88 Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
89 For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
91 I modified the following:
92 - Additional Video4Linux2 support :)
93 - Use mmap functions (v4l2)
94 - New methods are internal:
95 try_palette_v4l2 -> rewrite try_palette for v4l2
96 mainloop_v4l2, read_image_v4l2 -> this methods are moved from official v4l2 capture.c example
97 try_init_v4l -> device v4l initialisation
98 try_init_v4l2 -> device v4l2 initialisation
99 autosetup_capture_mode_v4l -> autodetect capture modes for v4l
100 autosetup_capture_mode_v4l2 -> autodetect capture modes for v4l2
101 - Modifications are according with Video4Linux old codes
102 - Video4Linux handling is automatically if it does not recognize a Video4Linux2 device
103 - Tested succesful with Logitech Quickcam Express (V4L), Creative Vista (V4L) and Genius VideoCam Notebook (V4L2)
104 - Correct source lines with compiler warning messages
105 - Information message from v4l/v4l2 detection
107 Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
108 For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
110 I modified the following:
111 - SN9C10x chip based webcams support
112 - New methods are internal:
113 bayer2rgb24, sonix_decompress -> decoder routines for SN9C10x decoding from Takafumi Mizuno <taka-qce@ls-a.jp> with his pleasure :)
114 - Tested succesful with Genius VideoCam Notebook (V4L2)
116 Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
117 For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
119 I added the following:
120 - Add capture control support (hue, saturation, brightness, contrast, gain)
121 - Get and change V4L capture controls (hue, saturation, brightness, contrast)
122 - New method is internal:
123 icvSetControl -> set capture controls
124 - Tested succesful with Creative Vista (V4L)
126 Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
127 For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
129 I added the following:
130 - Detect, get and change V4L2 capture controls (hue, saturation, brightness, contrast, gain)
131 - New methods are internal:
132 v4l2_scan_controls_enumerate_menu, v4l2_scan_controls -> detect capture control intervals
133 - Tested succesful with Genius VideoCam Notebook (V4L2)
135 8th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch
136 Add support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG.
137 With this patch, new webcams of Logitech, like QuickCam Fusion works.
138 Note: For use these webcams, look at the UVC driver at
139 http://linux-uvc.berlios.de/
141 9th patch: Mar 4, 2006, Olivier.Bornet@idiap.ch
142 - try V4L2 before V4L, because some devices are V4L2 by default,
143 but they try to implement the V4L compatibility layer.
144 So, I think this is better to support V4L2 before V4L.
145 - better separation between V4L2 and V4L initialization. (this was needed to support
146 some drivers working, but not fully with V4L2. (so, we do not know when we
147 need to switch from V4L2 to V4L.
149 10th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com
150 Fix reliability problems with high-resolution UVC cameras on linux
151 the symptoms were damaged image and 'Corrupt JPEG data: premature end of data segment' on stderr
152 - V4L_ABORT_BADJPEG detects JPEG warnings and turns them into errors, so bad images
153 could be filtered out
154 - USE_TEMP_BUFFER fixes the main problem (improper buffer management) and
155 prevents bad images in the first place
162 /*M///////////////////////////////////////////////////////////////////////////////////////
164 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
166 // By downloading, copying, installing or using the software you agree to this license.
167 // If you do not agree to this license, do not download, install,
168 // copy or use the software.
171 // Intel License Agreement
172 // For Open Source Computer Vision Library
174 // Copyright (C) 2000, Intel Corporation, all rights reserved.
175 // Third party copyrights are property of their respective owners.
177 // Redistribution and use in source and binary forms, with or without modification,
178 // are permitted provided that the following conditions are met:
180 // * Redistribution's of source code must retain the above copyright notice,
181 // this list of conditions and the following disclaimer.
183 // * Redistribution's in binary form must reproduce the above copyright notice,
184 // this list of conditions and the following disclaimer in the documentation
185 // and/or other materials provided with the distribution.
187 // * The name of Intel Corporation may not be used to endorse or promote products
188 // derived from this software without specific prior written permission.
190 // This software is provided by the copyright holders and contributors "as is" and
191 // any express or implied warranties, including, but not limited to, the implied
192 // warranties of merchantability and fitness for a particular purpose are disclaimed.
193 // In no event shall the Intel Corporation or contributors be liable for any direct,
194 // indirect, incidental, special, exemplary, or consequential damages
195 // (including, but not limited to, procurement of substitute goods or services;
196 // loss of use, data, or profits; or business interruption) however caused
197 // and on any theory of liability, whether in contract, strict liability,
198 // or tort (including negligence or otherwise) arising in any way out of
199 // the use of this software, even if advised of the possibility of such damage.
203 #include "_highgui.h"
205 #if !defined WIN32 && defined HAVE_CAMV4L && defined HAVE_CAMV4L2
207 #define CLEAR(x) memset (&(x), 0, sizeof (x))
213 #include <sys/types.h>
214 #include <sys/mman.h>
217 #include <asm/types.h> /* for videodev2.h */
219 #include <sys/stat.h>
220 #include <sys/ioctl.h>
222 #include <linux/videodev.h>
223 #include <linux/videodev2.h>
228 /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */
229 #define DEFAULT_V4L_WIDTH 640
230 #define DEFAULT_V4L_HEIGHT 480
232 #define CHANNEL_NUMBER 1
233 #define MAX_CAMERAS 8
236 // default and maximum number of V4L buffers, not including last, 'special' buffer
237 #define MAX_V4L_BUFFERS 10
238 #define DEFAULT_V4L_BUFFERS 4
240 // if enabled, copies data from the buffer. this uses a bit more memory,
241 // but much more reliable for some UVC cameras
242 #define USE_TEMP_BUFFER
244 #define MAX_DEVICE_DRIVER_NAME 80
246 /* Device Capture Objects */
253 static unsigned int n_buffers = 0;
255 typedef struct CvCaptureCAM_V4L
260 struct video_capability capability;
261 struct video_window captureWindow;
262 struct video_picture imageProperties;
263 struct video_mbuf memoryBuffer;
264 struct video_mmap *mmaps;
269 buffer buffers[MAX_V4L_BUFFERS + 1];
270 struct v4l2_capability cap;
271 struct v4l2_input inp;
272 struct v4l2_format form;
273 struct v4l2_crop crop;
274 struct v4l2_cropcap cropcap;
275 struct v4l2_requestbuffers req;
276 struct v4l2_jpegcompression compr;
277 struct v4l2_control control;
278 enum v4l2_buf_type type;
279 struct v4l2_queryctrl queryctrl;
280 struct v4l2_querymenu querymenu;
282 /* V4L2 control variables */
283 int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max;
284 int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max;
285 int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max;
286 int v4l2_hue, v4l2_hue_min, v4l2_hue_max;
287 int v4l2_gain, v4l2_gain_min, v4l2_gain_max;
288 int v4l2_exposure, v4l2_exposure_min, v4l2_exposure_max;
294 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
296 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
297 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
299 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
300 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
302 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
304 /*********************** Implementations ***************************************/
306 static int numCameras = 0;
307 static int indexList = 0;
309 // IOCTL handling for V4L2
310 static int xioctl( int fd, int request, void *arg)
316 do r = v4l2_ioctl (fd, request, arg);
317 while (-1 == r && EINTR == errno);
324 /* Simple test program: Find number of Video Sources available.
325 Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
326 If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
327 Returns the global numCameras with the correct value (we hope) */
329 static void icvInitCapture_V4L() {
332 char deviceName[MAX_DEVICE_DRIVER_NAME];
335 while(CameraNumber < MAX_CAMERAS) {
336 /* Print the CameraNumber at the end of the string with a width of one character */
337 sprintf(deviceName, "/dev/video%1d", CameraNumber);
338 /* Test using an open to see if this new device name really does exists. */
339 deviceHandle = open(deviceName, O_RDONLY);
340 if (deviceHandle != -1) {
341 /* This device does indeed exist - add it to the total so far */
343 indexList|=(1 << CameraNumber);
346 if (deviceHandle != -1)
348 /* Set up to test the next /dev/video source in line */
352 }; /* End icvInitCapture_V4L */
355 static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
358 // if detect = -1 then unable to open device
359 // if detect = 0 then detected nothing
360 // if detect = 1 then V4L device
364 // Test device for V4L compability
366 /* Test using an open to see if this new device name really does exists. */
367 /* No matter what the name - it still must be opened! */
368 capture->deviceHandle = v4l1_open(deviceName, O_RDWR);
371 if (capture->deviceHandle == 0)
375 icvCloseCAM_V4L(capture);
380 /* Query the newly opened device for its capabilities */
381 if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
385 icvCloseCAM_V4L(capture);
398 static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
401 // if detect = -1 then unable to open device
402 // if detect = 0 then detected nothing
403 // if detect = 1 then V4L2 device
407 // Test device for V4L2 compability
409 /* Open and test V4L2 device */
410 capture->deviceHandle = v4l2_open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
414 if (capture->deviceHandle == 0)
418 icvCloseCAM_V4L(capture);
423 CLEAR (capture->cap);
424 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
428 icvCloseCAM_V4L(capture);
432 CLEAR (capture->capability);
433 capture->capability.type = capture->cap.capabilities;
435 /* Query channels number */
436 if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
448 static void v4l2_scan_controls_enumerate_menu(CvCaptureCAM_V4L* capture)
450 // printf (" Menu items:\n");
451 CLEAR (capture->querymenu);
452 capture->querymenu.id = capture->queryctrl.id;
453 for (capture->querymenu.index = capture->queryctrl.minimum;
454 (int)capture->querymenu.index <= capture->queryctrl.maximum;
455 capture->querymenu.index++)
457 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYMENU,
458 &capture->querymenu))
460 // printf (" %s\n", capture->querymenu.name);
462 perror ("VIDIOC_QUERYMENU");
467 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
472 for (ctrl_id = V4L2_CID_BASE;
473 ctrl_id < V4L2_CID_LASTP1;
477 /* set the id we will query now */
478 CLEAR (capture->queryctrl);
479 capture->queryctrl.id = ctrl_id;
481 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
482 &capture->queryctrl))
485 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
488 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
490 capture->v4l2_brightness = 1;
491 capture->v4l2_brightness_min = capture->queryctrl.minimum;
492 capture->v4l2_brightness_max = capture->queryctrl.maximum;
495 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
497 capture->v4l2_contrast = 1;
498 capture->v4l2_contrast_min = capture->queryctrl.minimum;
499 capture->v4l2_contrast_max = capture->queryctrl.maximum;
502 if (capture->queryctrl.id == V4L2_CID_SATURATION)
504 capture->v4l2_saturation = 1;
505 capture->v4l2_saturation_min = capture->queryctrl.minimum;
506 capture->v4l2_saturation_max = capture->queryctrl.maximum;
509 if (capture->queryctrl.id == V4L2_CID_HUE)
511 capture->v4l2_hue = 1;
512 capture->v4l2_hue_min = capture->queryctrl.minimum;
513 capture->v4l2_hue_max = capture->queryctrl.maximum;
516 if (capture->queryctrl.id == V4L2_CID_GAIN)
518 capture->v4l2_gain = 1;
519 capture->v4l2_gain_min = capture->queryctrl.minimum;
520 capture->v4l2_gain_max = capture->queryctrl.maximum;
523 if (capture->queryctrl.id == V4L2_CID_EXPOSURE)
525 capture->v4l2_exposure = 1;
526 capture->v4l2_exposure_min = capture->queryctrl.minimum;
527 capture->v4l2_exposure_max = capture->queryctrl.maximum;
530 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
531 v4l2_scan_controls_enumerate_menu(capture);
538 perror ("VIDIOC_QUERYCTRL");
544 for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
547 /* set the id we will query now */
548 CLEAR (capture->queryctrl);
549 capture->queryctrl.id = ctrl_id;
551 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
552 &capture->queryctrl))
555 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
558 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
560 capture->v4l2_brightness = 1;
561 capture->v4l2_brightness_min = capture->queryctrl.minimum;
562 capture->v4l2_brightness_max = capture->queryctrl.maximum;
565 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
567 capture->v4l2_contrast = 1;
568 capture->v4l2_contrast_min = capture->queryctrl.minimum;
569 capture->v4l2_contrast_max = capture->queryctrl.maximum;
572 if (capture->queryctrl.id == V4L2_CID_SATURATION)
574 capture->v4l2_saturation = 1;
575 capture->v4l2_saturation_min = capture->queryctrl.minimum;
576 capture->v4l2_saturation_max = capture->queryctrl.maximum;
579 if (capture->queryctrl.id == V4L2_CID_HUE)
581 capture->v4l2_hue = 1;
582 capture->v4l2_hue_min = capture->queryctrl.minimum;
583 capture->v4l2_hue_max = capture->queryctrl.maximum;
586 if (capture->queryctrl.id == V4L2_CID_GAIN)
588 capture->v4l2_gain = 1;
589 capture->v4l2_gain_min = capture->queryctrl.minimum;
590 capture->v4l2_gain_max = capture->queryctrl.maximum;
593 if (capture->queryctrl.id == V4L2_CID_EXPOSURE)
595 capture->v4l2_exposure = 1;
596 capture->v4l2_exposure_min = capture->queryctrl.minimum;
597 capture->v4l2_exposure_max = capture->queryctrl.maximum;
600 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
601 v4l2_scan_controls_enumerate_menu(capture);
608 perror ("VIDIOC_QUERYCTRL");
616 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
620 detect_v4l2 = try_init_v4l2(capture, deviceName);
622 if (detect_v4l2 != 1) {
623 /* init of the v4l2 device is not OK */
627 /* starting from here, we assume we are in V4L2 mode */
628 capture->is_v4l2_device = 1;
630 /* Init V4L2 control variables */
631 capture->v4l2_brightness = 0;
632 capture->v4l2_contrast = 0;
633 capture->v4l2_saturation = 0;
634 capture->v4l2_hue = 0;
635 capture->v4l2_gain = 0;
636 capture->v4l2_exposure = 0;
638 capture->v4l2_brightness_min = 0;
639 capture->v4l2_contrast_min = 0;
640 capture->v4l2_saturation_min = 0;
641 capture->v4l2_hue_min = 0;
642 capture->v4l2_gain_min = 0;
643 capture->v4l2_exposure_min = 0;
645 capture->v4l2_brightness_max = 0;
646 capture->v4l2_contrast_max = 0;
647 capture->v4l2_saturation_max = 0;
648 capture->v4l2_hue_max = 0;
649 capture->v4l2_gain_max = 0;
650 capture->v4l2_exposure_max = 0;
652 /* Scan V4L2 controls */
653 v4l2_scan_controls(capture);
655 if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
657 fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
658 icvCloseCAM_V4L(capture);
662 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
663 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
664 I myself am using a simple NTSC video input capture card that uses the value of 1.
665 If you are not in North America or have a different video standard, you WILL have to change
666 the following settings and recompile/reinstall. This set of settings is based on
667 the most commonly encountered input video source types (like my bttv card) */
669 if(capture->inp.index > 0) {
670 CLEAR (capture->inp);
671 capture->inp.index = CHANNEL_NUMBER;
672 /* Set only channel number to CHANNEL_NUMBER */
673 /* V4L2 have a status field from selected video mode */
674 if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
676 fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n");
677 icvCloseCAM_V4L (capture);
682 /* Find Window info */
683 CLEAR (capture->form);
684 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
686 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
687 fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
688 icvCloseCAM_V4L(capture);
692 /* libv4l will convert from any format to V4L2_PIX_FMT_BGR24 */
693 CLEAR (capture->form);
694 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
695 capture->form.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
696 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
697 capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
698 capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
700 if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
701 fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl S_FMT\n\n");
705 if (V4L2_PIX_FMT_BGR24 != capture->form.fmt.pix.pixelformat) {
706 fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n\n");
710 icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
714 /* Buggy driver paranoia. */
715 min = capture->form.fmt.pix.width * 2;
717 if (capture->form.fmt.pix.bytesperline < min)
718 capture->form.fmt.pix.bytesperline = min;
720 min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
722 if (capture->form.fmt.pix.sizeimage < min)
723 capture->form.fmt.pix.sizeimage = min;
725 CLEAR (capture->req);
727 unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
731 capture->req.count = buffer_number;
732 capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
733 capture->req.memory = V4L2_MEMORY_MMAP;
735 if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
739 fprintf (stderr, "%s does not support memory mapping\n", deviceName);
741 perror ("VIDIOC_REQBUFS");
743 /* free capture, and returns an error code */
744 icvCloseCAM_V4L (capture);
748 if (capture->req.count < buffer_number)
750 if (buffer_number == 1)
752 fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
754 /* free capture, and returns an error code */
755 icvCloseCAM_V4L (capture);
759 fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
765 for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
767 struct v4l2_buffer buf;
771 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
772 buf.memory = V4L2_MEMORY_MMAP;
773 buf.index = n_buffers;
775 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
776 perror ("VIDIOC_QUERYBUF");
778 /* free capture, and returns an error code */
779 icvCloseCAM_V4L (capture);
783 capture->buffers[n_buffers].length = buf.length;
784 capture->buffers[n_buffers].start =
785 mmap (NULL /* start anywhere */,
787 PROT_READ | PROT_WRITE /* required */,
788 MAP_SHARED /* recommended */,
789 capture->deviceHandle, buf.m.offset);
791 if (MAP_FAILED == capture->buffers[n_buffers].start) {
794 /* free capture, and returns an error code */
795 icvCloseCAM_V4L (capture);
799 #ifdef USE_TEMP_BUFFER
800 if (n_buffers == 0) {
801 capture->buffers[MAX_V4L_BUFFERS].start = malloc( buf.length );
802 capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
807 /* Set up Image data */
808 cvInitImageHeader( &capture->frame,
809 cvSize( capture->captureWindow.width,
810 capture->captureWindow.height ),
811 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
812 /* Allocate space for RGBA data */
813 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
816 }; /* End _capture_V4L2 */
819 static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
823 detect_v4l = try_init_v4l(capture, deviceName);
825 if ((detect_v4l == -1)
828 fprintf (stderr, "HIGHGUI ERROR: V4L"
829 ": device %s: Unable to open for READ ONLY\n", deviceName);
834 if ((detect_v4l <= 0)
837 fprintf (stderr, "HIGHGUI ERROR: V4L"
838 ": device %s: Unable to query number of channels\n", deviceName);
844 if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
846 fprintf( stderr, "HIGHGUI ERROR: V4L: "
847 "device %s is unable to capture video memory.\n",deviceName);
848 icvCloseCAM_V4L(capture);
855 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
856 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
857 I myself am using a simple NTSC video input capture card that uses the value of 1.
858 If you are not in North America or have a different video standard, you WILL have to change
859 the following settings and recompile/reinstall. This set of settings is based on
860 the most commonly encountered input video source types (like my bttv card) */
864 if(capture->capability.channels>0) {
866 struct video_channel selectedChannel;
868 selectedChannel.channel=CHANNEL_NUMBER;
869 if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
870 /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
871 // selectedChannel.norm = VIDEO_MODE_NTSC;
872 if (v4l1_ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
873 /* Could not set selected channel - Oh well */
874 //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
883 if(v4l1_ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
884 fprintf( stderr, "HIGHGUI ERROR: V4L: "
885 "Could not obtain specifics of capture window.\n\n");
886 icvCloseCAM_V4L(capture);
893 if(v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
894 fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
895 icvCloseCAM_V4L(capture);
899 capture->imageProperties.palette = VIDEO_PALETTE_RGB24;
900 capture->imageProperties.depth = 24;
901 if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) {
902 fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n");
903 icvCloseCAM_V4L(capture);
906 if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
907 fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n");
908 icvCloseCAM_V4L(capture);
911 if (capture->imageProperties.palette != VIDEO_PALETTE_RGB24) {
912 fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n\n");
913 icvCloseCAM_V4L(capture);
921 v4l1_ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
922 capture->memoryMap = (char *)v4l1_mmap(0,
923 capture->memoryBuffer.size,
924 PROT_READ | PROT_WRITE,
926 capture->deviceHandle,
928 if (capture->memoryMap == MAP_FAILED) {
929 fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
930 icvCloseCAM_V4L(capture);
933 /* Set up video_mmap structure pointing to this memory mapped area so each image may be
934 retrieved from an index value */
935 capture->mmaps = (struct video_mmap *)
936 (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
937 if (!capture->mmaps) {
938 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not memory map video frames.\n");
939 icvCloseCAM_V4L(capture);
945 /* Set up Image data */
946 cvInitImageHeader( &capture->frame,
947 cvSize( capture->captureWindow.width,
948 capture->captureWindow.height ),
949 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
950 /* Allocate space for RGBA data */
951 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
954 }; /* End _capture_V4L */
956 static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
958 static int autoindex;
961 char deviceName[MAX_DEVICE_DRIVER_NAME];
964 icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
966 return NULL; /* Are there any /dev/video input sources? */
968 //search index in indexList
969 if ( (index>-1) && ! ((1 << index) & indexList) )
971 fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index);
972 return NULL; /* Did someone ask for not correct video source number? */
974 /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
975 the handles for V4L processing */
976 CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
978 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
981 /* Select camera, or rather, V4L video source */
982 if (index<0) { // Asking for the first device available
983 for (; autoindex<MAX_CAMERAS;autoindex++)
984 if (indexList & (1<<autoindex))
986 if (autoindex==MAX_CAMERAS)
989 autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
991 /* Print the CameraNumber at the end of the string with a width of one character */
992 sprintf(deviceName, "/dev/video%1d", index);
994 /* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */
995 memset(capture,0,sizeof(CvCaptureCAM_V4L));
996 /* Present the routines needed for V4L funtionality. They are inserted as part of
997 the standard set of cv calls promoting transparency. "Vector Table" insertion. */
998 capture->FirstCapture = 1;
1001 if (_capture_V4L2 (capture, deviceName) == -1) {
1002 icvCloseCAM_V4L(capture);
1003 capture->is_v4l2_device = 0;
1004 if (_capture_V4L (capture, deviceName) == -1) {
1005 icvCloseCAM_V4L(capture);
1009 capture->is_v4l2_device = 1;
1013 }; /* End icvOpenCAM_V4L */
1017 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1018 struct v4l2_buffer buf;
1022 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1023 buf.memory = V4L2_MEMORY_MMAP;
1025 if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1031 /* Could ignore EIO, see spec. */
1036 /* display the error and stop processing */
1037 perror ("VIDIOC_DQBUF");
1042 assert(buf.index < capture->req.count);
1044 #ifdef USE_TEMP_BUFFER
1045 memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
1046 capture->buffers[buf.index].start,
1047 capture->buffers[MAX_V4L_BUFFERS].length );
1048 capture->bufferIndex = MAX_V4L_BUFFERS;
1049 //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
1050 // buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
1052 capture->bufferIndex = buf.index;
1055 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1056 perror ("VIDIOC_QBUF");
1061 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1066 while (count-- > 0) {
1073 FD_SET (capture->deviceHandle, &fds);
1079 r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1089 fprintf (stderr, "select timeout\n");
1091 /* end the infinite loop */
1095 if (read_frame_v4l2 (capture))
1101 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1103 if (capture->FirstCapture) {
1104 /* Some general initialization must take place the first time through */
1106 /* This is just a technicality, but all buffers must be filled up before any
1107 staggered SYNC is applied. SO, filler up. (see V4L HowTo) */
1109 if (capture->is_v4l2_device == 1)
1112 for (capture->bufferIndex = 0;
1113 capture->bufferIndex < ((int)capture->req.count);
1114 ++capture->bufferIndex)
1117 struct v4l2_buffer buf;
1121 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1122 buf.memory = V4L2_MEMORY_MMAP;
1123 buf.index = (unsigned long)capture->bufferIndex;
1125 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1126 perror ("VIDIOC_QBUF");
1131 /* enable the streaming */
1132 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1133 if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
1135 /* error enabling the stream */
1136 perror ("VIDIOC_STREAMON");
1142 for (capture->bufferIndex = 0;
1143 capture->bufferIndex < (capture->memoryBuffer.frames-1);
1144 ++capture->bufferIndex) {
1146 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1147 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1148 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1149 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1151 if (v4l1_ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1152 fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1160 /* preparation is ok */
1161 capture->FirstCapture = 0;
1164 if (capture->is_v4l2_device == 1)
1167 mainloop_v4l2(capture);
1172 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1173 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1174 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1175 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1177 if (v4l1_ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1178 &capture->mmaps[capture->bufferIndex]) == -1) {
1179 /* capture is on the way, so just exit */
1183 ++capture->bufferIndex;
1184 if (capture->bufferIndex == capture->memoryBuffer.frames) {
1185 capture->bufferIndex = 0;
1193 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
1195 if (capture->is_v4l2_device == 0)
1198 /* [FD] this really belongs here */
1199 if (v4l1_ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
1200 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
1205 /* Now get what has already been captured as a IplImage return */
1207 /* First, reallocate imageData if the frame size changed */
1209 if (capture->is_v4l2_device == 1)
1212 if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
1213 || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
1214 cvFree(&capture->frame.imageData);
1215 cvInitImageHeader( &capture->frame,
1216 cvSize( capture->form.fmt.pix.width,
1217 capture->form.fmt.pix.height ),
1218 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1219 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1225 if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
1226 || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
1227 cvFree(&capture->frame.imageData);
1228 cvInitImageHeader( &capture->frame,
1229 cvSize( capture->captureWindow.width,
1230 capture->captureWindow.height ),
1231 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1232 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1237 if (capture->is_v4l2_device == 1)
1240 memcpy((char *)capture->frame.imageData,
1241 (char *)capture->buffers[capture->bufferIndex].start,
1242 capture->frame.imageSize);
1245 #endif /* HAVE_CAMV4L2 */
1248 switch(capture->imageProperties.palette) {
1249 case VIDEO_PALETTE_RGB24:
1250 memcpy((char *)capture->frame.imageData,
1251 (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
1252 capture->frame.imageSize);
1256 "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n",
1257 capture->imageProperties.palette);
1264 return(&capture->frame);
1267 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
1270 if (capture->is_v4l2_device == 1)
1273 /* default value for min and max */
1277 CLEAR (capture->form);
1278 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1279 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
1280 /* display an error message, and return an error code */
1281 perror ("VIDIOC_G_FMT");
1285 switch (property_id) {
1286 case CV_CAP_PROP_FRAME_WIDTH:
1287 return capture->form.fmt.pix.width;
1288 case CV_CAP_PROP_FRAME_HEIGHT:
1289 return capture->form.fmt.pix.height;
1292 /* initialize the control structure */
1294 switch (property_id) {
1295 case CV_CAP_PROP_BRIGHTNESS:
1296 capture->control.id = V4L2_CID_BRIGHTNESS;
1298 case CV_CAP_PROP_CONTRAST:
1299 capture->control.id = V4L2_CID_CONTRAST;
1301 case CV_CAP_PROP_SATURATION:
1302 capture->control.id = V4L2_CID_SATURATION;
1304 case CV_CAP_PROP_HUE:
1305 capture->control.id = V4L2_CID_HUE;
1307 case CV_CAP_PROP_GAIN:
1308 capture->control.id = V4L2_CID_GAIN;
1310 case CV_CAP_PROP_EXPOSURE:
1311 capture->control.id = V4L2_CID_EXPOSURE;
1315 "HIGHGUI ERROR: V4L2: getting property #%d is not supported\n",
1320 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_CTRL,
1321 &capture->control)) {
1323 fprintf( stderr, "HIGHGUI ERROR: V4L2: ");
1324 switch (property_id) {
1325 case CV_CAP_PROP_BRIGHTNESS:
1326 fprintf (stderr, "Brightness");
1328 case CV_CAP_PROP_CONTRAST:
1329 fprintf (stderr, "Contrast");
1331 case CV_CAP_PROP_SATURATION:
1332 fprintf (stderr, "Saturation");
1334 case CV_CAP_PROP_HUE:
1335 fprintf (stderr, "Hue");
1337 case CV_CAP_PROP_GAIN:
1338 fprintf (stderr, "Gain");
1340 case CV_CAP_PROP_EXPOSURE:
1341 fprintf (stderr, "Exposure");
1344 fprintf (stderr, " is not supported by your device\n");
1349 /* get the min/max values */
1350 switch (property_id) {
1352 case CV_CAP_PROP_BRIGHTNESS:
1353 v4l2_min = capture->v4l2_brightness_min;
1354 v4l2_max = capture->v4l2_brightness_max;
1356 case CV_CAP_PROP_CONTRAST:
1357 v4l2_min = capture->v4l2_contrast_min;
1358 v4l2_max = capture->v4l2_contrast_max;
1360 case CV_CAP_PROP_SATURATION:
1361 v4l2_min = capture->v4l2_saturation_min;
1362 v4l2_max = capture->v4l2_saturation_max;
1364 case CV_CAP_PROP_HUE:
1365 v4l2_min = capture->v4l2_hue_min;
1366 v4l2_max = capture->v4l2_hue_max;
1368 case CV_CAP_PROP_GAIN:
1369 v4l2_min = capture->v4l2_gain_min;
1370 v4l2_max = capture->v4l2_gain_max;
1372 case CV_CAP_PROP_EXPOSURE:
1373 v4l2_min = capture->v4l2_exposure_min;
1374 v4l2_max = capture->v4l2_exposure_max;
1378 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1379 return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min);
1386 if (v4l1_ioctl (capture->deviceHandle,
1387 VIDIOCGWIN, &capture->captureWindow) < 0) {
1389 "HIGHGUI ERROR: V4L: "
1390 "Unable to determine size of incoming image\n");
1391 icvCloseCAM_V4L(capture);
1395 switch (property_id) {
1396 case CV_CAP_PROP_FRAME_WIDTH:
1397 retval = capture->captureWindow.width;
1399 case CV_CAP_PROP_FRAME_HEIGHT:
1400 retval = capture->captureWindow.height;
1402 case CV_CAP_PROP_BRIGHTNESS:
1403 retval = capture->imageProperties.brightness;
1405 case CV_CAP_PROP_CONTRAST:
1406 retval = capture->imageProperties.contrast;
1408 case CV_CAP_PROP_SATURATION:
1409 retval = capture->imageProperties.colour;
1411 case CV_CAP_PROP_HUE:
1412 retval = capture->imageProperties.hue;
1414 case CV_CAP_PROP_GAIN:
1416 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
1419 case CV_CAP_PROP_EXPOSURE:
1421 "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
1426 "HIGHGUI ERROR: V4L: getting property #%d is not supported\n",
1431 /* there was a problem */
1435 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1436 return float (retval) / 0xFFFF;
1442 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
1444 if (capture->is_v4l2_device == 1)
1447 CLEAR (capture->crop);
1448 capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1449 capture->crop.c.left = 0;
1450 capture->crop.c.top = 0;
1451 capture->crop.c.height = h*24;
1452 capture->crop.c.width = w*24;
1454 /* set the crop area, but don't exit if the device don't support croping */
1455 xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
1457 CLEAR (capture->form);
1458 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1460 /* read the current setting, mainly to retreive the pixelformat information */
1461 xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
1463 /* set the values we want to change */
1464 capture->form.fmt.pix.width = w;
1465 capture->form.fmt.pix.height = h;
1466 capture->form.fmt.win.chromakey = 0;
1467 capture->form.fmt.win.field = V4L2_FIELD_ANY;
1468 capture->form.fmt.win.clips = 0;
1469 capture->form.fmt.win.clipcount = 0;
1470 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
1472 /* ask the device to change the size
1473 * don't test if the set of the size is ok, because some device
1474 * don't allow changing the size, and we will get the real size
1476 xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
1478 /* try to set framerate to 30 fps */
1479 struct v4l2_streamparm setfps;
1480 memset (&setfps, 0, sizeof(struct v4l2_streamparm));
1481 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1482 setfps.parm.capture.timeperframe.numerator = 1;
1483 setfps.parm.capture.timeperframe.denominator = 30;
1484 xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
1486 /* we need to re-initialize some things, like buffers, because the size has
1488 capture->FirstCapture = 1;
1490 /* Get window info again, to get the real value */
1491 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
1493 fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
1495 icvCloseCAM_V4L(capture);
1505 if (capture==0) return 0;
1506 if (w>capture->capability.maxwidth) {
1507 w=capture->capability.maxwidth;
1509 if (h>capture->capability.maxheight) {
1510 h=capture->capability.maxheight;
1513 capture->captureWindow.width=w;
1514 capture->captureWindow.height=h;
1516 if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
1517 icvCloseCAM_V4L(capture);
1521 if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
1522 icvCloseCAM_V4L(capture);
1526 capture->FirstCapture = 1;
1534 static int icvSetControl (CvCaptureCAM_V4L* capture,
1535 int property_id, double value) {
1537 /* limitation of the input value */
1540 } else if (value > 1.0) {
1544 if (capture->is_v4l2_device == 1)
1547 /* default value for min and max */
1551 /* initialisations */
1552 CLEAR (capture->control);
1554 /* set which control we want to set */
1555 switch (property_id) {
1557 case CV_CAP_PROP_BRIGHTNESS:
1558 capture->control.id = V4L2_CID_BRIGHTNESS;
1560 case CV_CAP_PROP_CONTRAST:
1561 capture->control.id = V4L2_CID_CONTRAST;
1563 case CV_CAP_PROP_SATURATION:
1564 capture->control.id = V4L2_CID_SATURATION;
1566 case CV_CAP_PROP_HUE:
1567 capture->control.id = V4L2_CID_HUE;
1569 case CV_CAP_PROP_GAIN:
1570 capture->control.id = V4L2_CID_GAIN;
1572 case CV_CAP_PROP_EXPOSURE:
1573 capture->control.id = V4L2_CID_EXPOSURE;
1577 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
1582 /* get the min and max values */
1583 if (-1 == xioctl (capture->deviceHandle,
1584 VIDIOC_G_CTRL, &capture->control)) {
1585 // perror ("VIDIOC_G_CTRL for getting min/max values");
1589 /* get the min/max values */
1590 switch (property_id) {
1592 case CV_CAP_PROP_BRIGHTNESS:
1593 v4l2_min = capture->v4l2_brightness_min;
1594 v4l2_max = capture->v4l2_brightness_max;
1596 case CV_CAP_PROP_CONTRAST:
1597 v4l2_min = capture->v4l2_contrast_min;
1598 v4l2_max = capture->v4l2_contrast_max;
1600 case CV_CAP_PROP_SATURATION:
1601 v4l2_min = capture->v4l2_saturation_min;
1602 v4l2_max = capture->v4l2_saturation_max;
1604 case CV_CAP_PROP_HUE:
1605 v4l2_min = capture->v4l2_hue_min;
1606 v4l2_max = capture->v4l2_hue_max;
1608 case CV_CAP_PROP_GAIN:
1609 v4l2_min = capture->v4l2_gain_min;
1610 v4l2_max = capture->v4l2_gain_max;
1612 case CV_CAP_PROP_EXPOSURE:
1613 v4l2_min = capture->v4l2_exposure_min;
1614 v4l2_max = capture->v4l2_exposure_max;
1618 /* initialisations */
1619 CLEAR (capture->control);
1621 /* set which control we want to set */
1622 switch (property_id) {
1624 case CV_CAP_PROP_BRIGHTNESS:
1625 capture->control.id = V4L2_CID_BRIGHTNESS;
1627 case CV_CAP_PROP_CONTRAST:
1628 capture->control.id = V4L2_CID_CONTRAST;
1630 case CV_CAP_PROP_SATURATION:
1631 capture->control.id = V4L2_CID_SATURATION;
1633 case CV_CAP_PROP_HUE:
1634 capture->control.id = V4L2_CID_HUE;
1636 case CV_CAP_PROP_GAIN:
1637 capture->control.id = V4L2_CID_GAIN;
1639 case CV_CAP_PROP_EXPOSURE:
1640 capture->control.id = V4L2_CID_EXPOSURE;
1644 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
1649 /* set the value we want to set to the scaled the value */
1650 capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min);
1652 /* The driver may clamp the value or return ERANGE, ignored here */
1653 if (-1 == xioctl (capture->deviceHandle,
1654 VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) {
1655 perror ("VIDIOC_S_CTRL");
1663 /* scale the value to the wanted integer one */
1664 v4l_value = (int)(0xFFFF * value);
1666 switch (property_id) {
1667 case CV_CAP_PROP_BRIGHTNESS:
1668 capture->imageProperties.brightness = v4l_value;
1670 case CV_CAP_PROP_CONTRAST:
1671 capture->imageProperties.contrast = v4l_value;
1673 case CV_CAP_PROP_SATURATION:
1674 capture->imageProperties.colour = v4l_value;
1676 case CV_CAP_PROP_HUE:
1677 capture->imageProperties.hue = v4l_value;
1679 case CV_CAP_PROP_GAIN:
1681 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
1683 case CV_CAP_PROP_EXPOSURE:
1685 "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
1689 "HIGHGUI ERROR: V4L: property #%d is not supported\n",
1695 if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties)
1699 "HIGHGUI ERROR: V4L: Unable to set video informations\n");
1700 icvCloseCAM_V4L(capture);
1710 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
1711 int property_id, double value ){
1712 static int width = 0, height = 0;
1715 /* initialization */
1718 /* two subsequent calls setting WIDTH and HEIGHT will change
1720 /* the first one will return an error, though. */
1722 switch (property_id) {
1723 case CV_CAP_PROP_FRAME_WIDTH:
1724 width = cvRound(value);
1725 if(width !=0 && height != 0) {
1726 retval = icvSetVideoSize( capture, width, height);
1730 case CV_CAP_PROP_FRAME_HEIGHT:
1731 height = cvRound(value);
1732 if(width !=0 && height != 0) {
1733 retval = icvSetVideoSize( capture, width, height);
1737 case CV_CAP_PROP_BRIGHTNESS:
1738 case CV_CAP_PROP_CONTRAST:
1739 case CV_CAP_PROP_SATURATION:
1740 case CV_CAP_PROP_HUE:
1741 case CV_CAP_PROP_GAIN:
1742 case CV_CAP_PROP_EXPOSURE:
1743 retval = icvSetControl(capture, property_id, value);
1747 "HIGHGUI ERROR: V4L: setting property #%d is not supported\n",
1751 /* return the the status */
1755 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
1756 /* Deallocate space - Hopefully, no leaks */
1761 if (capture->is_v4l2_device == 0)
1765 free(capture->mmaps);
1766 if (capture->memoryMap)
1767 v4l1_munmap(capture->memoryMap, capture->memoryBuffer.size);
1768 if (capture->deviceHandle != -1)
1769 v4l1_close(capture->deviceHandle);
1772 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1773 if (xioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type) < 0) {
1774 perror ("Unable to stop the stream.");
1777 for (unsigned int n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
1779 if (-1 == v4l2_munmap (capture->buffers[n_buffers].start, capture->buffers[n_buffers].length)) {
1784 if (capture->deviceHandle != -1)
1785 v4l2_close(capture->deviceHandle);
1788 if (capture->frame.imageData)
1789 cvFree(&capture->frame.imageData);
1790 //cvFree((void **)capture);
1795 class CvCaptureCAM_V4L_CPP : CvCapture
1798 CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
1799 virtual ~CvCaptureCAM_V4L_CPP() { close(); }
1801 virtual bool open( int index );
1802 virtual void close();
1804 virtual double getProperty(int);
1805 virtual bool setProperty(int, double);
1806 virtual bool grabFrame();
1807 virtual IplImage* retrieveFrame(int);
1810 CvCaptureCAM_V4L* captureV4L;
1813 bool CvCaptureCAM_V4L_CPP::open( int index )
1816 captureV4L = icvCaptureFromCAM_V4L(index);
1817 return captureV4L != 0;
1820 void CvCaptureCAM_V4L_CPP::close()
1824 icvCloseCAM_V4L( captureV4L );
1825 cvFree( &captureV4L );
1829 bool CvCaptureCAM_V4L_CPP::grabFrame()
1831 return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
1834 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
1836 return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
1839 double CvCaptureCAM_V4L_CPP::getProperty( int propId )
1841 return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
1844 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
1846 return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
1849 CvCapture* cvCreateCameraCapture_V4L( int index )
1851 CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
1853 if( capture->open( index ))
1854 return (CvCapture*)capture;