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.
153 /*M///////////////////////////////////////////////////////////////////////////////////////
155 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
157 // By downloading, copying, installing or using the software you agree to this license.
158 // If you do not agree to this license, do not download, install,
159 // copy or use the software.
162 // Intel License Agreement
163 // For Open Source Computer Vision Library
165 // Copyright (C) 2000, Intel Corporation, all rights reserved.
166 // Third party copyrights are property of their respective owners.
168 // Redistribution and use in source and binary forms, with or without modification,
169 // are permitted provided that the following conditions are met:
171 // * Redistribution's of source code must retain the above copyright notice,
172 // this list of conditions and the following disclaimer.
174 // * Redistribution's in binary form must reproduce the above copyright notice,
175 // this list of conditions and the following disclaimer in the documentation
176 // and/or other materials provided with the distribution.
178 // * The name of Intel Corporation may not be used to endorse or promote products
179 // derived from this software without specific prior written permission.
181 // This software is provided by the copyright holders and contributors "as is" and
182 // any express or implied warranties, including, but not limited to, the implied
183 // warranties of merchantability and fitness for a particular purpose are disclaimed.
184 // In no event shall the Intel Corporation or contributors be liable for any direct,
185 // indirect, incidental, special, exemplary, or consequential damages
186 // (including, but not limited to, procurement of substitute goods or services;
187 // loss of use, data, or profits; or business interruption) however caused
188 // and on any theory of liability, whether in contract, strict liability,
189 // or tort (including negligence or otherwise) arising in any way out of
190 // the use of this software, even if advised of the possibility of such damage.
194 #include "_highgui.h"
196 #if !defined WIN32 && defined HAVE_CAMV4L
198 #define CLEAR(x) memset (&(x), 0, sizeof (x))
204 #include <sys/ioctl.h>
205 #include <sys/types.h>
206 #include <sys/mman.h>
208 #include <linux/videodev.h>
212 #include <asm/types.h> /* for videodev2.h */
214 #include <sys/stat.h>
215 #include <sys/ioctl.h>
218 #include <linux/videodev2.h>
221 /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */
222 #define DEFAULT_V4L_WIDTH 640
223 #define DEFAULT_V4L_HEIGHT 480
225 #define CHANNEL_NUMBER 1
226 #define MAX_CAMERAS 8
228 #define MAX_DEVICE_DRIVER_NAME 80
230 /* Device Capture Objects */
241 static unsigned int n_buffers = 0;
243 /* Additional V4L2 pixelformats support for Sonix SN9C10x base webcams */
244 #ifndef V4L2_PIX_FMT_SBGGR8
245 #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
247 #ifndef V4L2_PIX_FMT_SN9C10X
248 #define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x cmpr. */
251 #endif /* HAVE_CAMV4L2 */
253 int PALETTE_BGR24 = 0,
262 typedef struct CvCaptureCAM_V4L
267 struct video_capability capability;
268 struct video_window captureWindow;
269 struct video_picture imageProperties;
270 struct video_mbuf memoryBuffer;
271 struct video_mmap *mmaps;
279 struct v4l2_capability cap;
280 struct v4l2_input inp;
281 struct v4l2_format form;
282 struct v4l2_crop crop;
283 struct v4l2_cropcap cropcap;
284 struct v4l2_requestbuffers req;
285 struct v4l2_jpegcompression compr;
286 struct v4l2_control control;
287 enum v4l2_buf_type type;
288 struct v4l2_queryctrl queryctrl;
289 struct v4l2_querymenu querymenu;
291 /* V4L2 control variables */
292 int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max;
293 int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max;
294 int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max;
295 int v4l2_hue, v4l2_hue_min, v4l2_hue_max;
296 int v4l2_gain, v4l2_gain_min, v4l2_gain_max;
298 #endif /* HAVE_CAMV4L2 */
305 int V4L2_SUPPORT = 0;
307 #endif /* HAVE_CAMV4L2 */
309 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
311 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
312 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture );
314 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
315 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
317 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
319 /*********************** Implementations ***************************************/
321 static int numCameras = 0;
322 static int indexList = 0;
326 // IOCTL handling for V4L2
327 static int xioctl( int fd, int request, void *arg)
333 do r = ioctl (fd, request, arg);
334 while (-1 == r && EINTR == errno);
340 #endif /* HAVE_CAMV4L2 */
342 /* Simple test program: Find number of Video Sources available.
343 Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
344 If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
345 Returns the global numCameras with the correct value (we hope) */
347 static void icvInitCapture_V4L() {
350 char deviceName[MAX_DEVICE_DRIVER_NAME];
353 while(CameraNumber < MAX_CAMERAS) {
354 /* Print the CameraNumber at the end of the string with a width of one character */
355 sprintf(deviceName, "/dev/video%1d", CameraNumber);
356 /* Test using an open to see if this new device name really does exists. */
357 deviceHandle = open(deviceName, O_RDONLY);
358 if (deviceHandle != -1) {
359 /* This device does indeed exist - add it to the total so far */
361 indexList|=(1 << CameraNumber);
365 /* Set up to test the next /dev/video source in line */
369 }; /* End icvInitCapture_V4L */
373 struct video_picture *cam_pic,
377 cam_pic->palette = pal;
378 cam_pic->depth = depth;
379 if (ioctl(fd, VIDIOCSPICT, cam_pic) < 0)
381 if (ioctl(fd, VIDIOCGPICT, cam_pic) < 0)
383 if (cam_pic->palette == pal)
390 static int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace)
392 CLEAR (capture->form);
394 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
395 capture->form.fmt.pix.pixelformat = colorspace;
396 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
397 capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
398 capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
400 if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
404 if (colorspace != capture->form.fmt.pix.pixelformat)
410 #endif /* HAVE_CAMV4L2 */
412 static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
415 // if detect = -1 then unable to open device
416 // if detect = 0 then detected nothing
417 // if detect = 1 then V4L device
421 // Test device for V4L compability
423 /* Test using an open to see if this new device name really does exists. */
424 /* No matter what the name - it still must be opened! */
425 capture->deviceHandle = open(deviceName, O_RDWR);
428 if (capture->deviceHandle == 0)
432 icvCloseCAM_V4L(capture);
437 /* Query the newly opened device for its capabilities */
438 if (ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
442 icvCloseCAM_V4L(capture);
456 static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
459 // if detect = -1 then unable to open device
460 // if detect = 0 then detected nothing
461 // if detect = 1 then V4L2 device
465 // Test device for V4L2 compability
467 /* Open and test V4L2 device */
468 capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
472 if (capture->deviceHandle == 0)
476 icvCloseCAM_V4L(capture);
481 CLEAR (capture->cap);
482 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
486 icvCloseCAM_V4L(capture);
490 CLEAR (capture->capability);
491 capture->capability.type = capture->cap.capabilities;
493 /* Query channels number */
494 if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
505 static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture)
507 if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0)
512 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0)
517 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0)
525 /* support for MJPEG is only available with libjpeg and gcc,
526 because it's use libjepg and fmemopen()
528 if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0)
536 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0)
540 else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0)
545 if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0)
547 CLEAR (capture->compr);
548 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_JPEGCOMP, &capture->compr)) {
549 perror ("VIDIOC_G_JPEGCOMP");
553 capture->compr.quality = 0;
555 if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_JPEGCOMP, &capture->compr)) {
556 perror ("VIDIOC_S_JPEGCOMP");
562 if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0)
568 fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
569 icvCloseCAM_V4L(capture);
577 #endif /* HAVE_CAMV4L2 */
579 static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture)
582 if(ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
583 fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
584 icvCloseCAM_V4L(capture);
588 /* Yet MORE things that might have to be changes with your frame capture card */
589 /* This sets the scale to the center of a 2^16 number */
590 if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_RGB24, 24)) {
591 //printf("negotiated palette RGB24\n");
593 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420P, 16)) {
594 //printf("negotiated palette YUV420P\n");
596 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420, 16)) {
597 //printf("negotiated palette YUV420\n");
599 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV411P, 16)) {
600 //printf("negotiated palette YUV420P\n");
603 fprintf(stderr, "HIGHGUI ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n");
604 icvCloseCAM_V4L(capture);
614 static void v4l2_scan_controls_enumerate_menu(CvCaptureCAM_V4L* capture)
616 // printf (" Menu items:\n");
617 CLEAR (capture->querymenu);
618 capture->querymenu.id = capture->queryctrl.id;
619 for (capture->querymenu.index = capture->queryctrl.minimum;
620 (int)capture->querymenu.index <= capture->queryctrl.maximum;
621 capture->querymenu.index++)
623 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYMENU,
624 &capture->querymenu))
626 // printf (" %s\n", capture->querymenu.name);
628 perror ("VIDIOC_QUERYMENU");
633 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
638 for (ctrl_id = V4L2_CID_BASE;
639 ctrl_id < V4L2_CID_LASTP1;
643 /* set the id we will query now */
644 CLEAR (capture->queryctrl);
645 capture->queryctrl.id = ctrl_id;
647 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
648 &capture->queryctrl))
651 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
654 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
656 capture->v4l2_brightness = 1;
657 capture->v4l2_brightness_min = capture->queryctrl.minimum;
658 capture->v4l2_brightness_max = capture->queryctrl.maximum;
661 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
663 capture->v4l2_contrast = 1;
664 capture->v4l2_contrast_min = capture->queryctrl.minimum;
665 capture->v4l2_contrast_max = capture->queryctrl.maximum;
668 if (capture->queryctrl.id == V4L2_CID_SATURATION)
670 capture->v4l2_saturation = 1;
671 capture->v4l2_saturation_min = capture->queryctrl.minimum;
672 capture->v4l2_saturation_max = capture->queryctrl.maximum;
675 if (capture->queryctrl.id == V4L2_CID_HUE)
677 capture->v4l2_hue = 1;
678 capture->v4l2_hue_min = capture->queryctrl.minimum;
679 capture->v4l2_hue_max = capture->queryctrl.maximum;
682 if (capture->queryctrl.id == V4L2_CID_GAIN)
684 capture->v4l2_gain = 1;
685 capture->v4l2_gain_min = capture->queryctrl.minimum;
686 capture->v4l2_gain_max = capture->queryctrl.maximum;
689 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
690 v4l2_scan_controls_enumerate_menu(capture);
697 perror ("VIDIOC_QUERYCTRL");
703 for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
706 /* set the id we will query now */
707 CLEAR (capture->queryctrl);
708 capture->queryctrl.id = ctrl_id;
710 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
711 &capture->queryctrl))
714 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
717 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
719 capture->v4l2_brightness = 1;
720 capture->v4l2_brightness_min = capture->queryctrl.minimum;
721 capture->v4l2_brightness_max = capture->queryctrl.maximum;
724 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
726 capture->v4l2_contrast = 1;
727 capture->v4l2_contrast_min = capture->queryctrl.minimum;
728 capture->v4l2_contrast_max = capture->queryctrl.maximum;
731 if (capture->queryctrl.id == V4L2_CID_SATURATION)
733 capture->v4l2_saturation = 1;
734 capture->v4l2_saturation_min = capture->queryctrl.minimum;
735 capture->v4l2_saturation_max = capture->queryctrl.maximum;
738 if (capture->queryctrl.id == V4L2_CID_HUE)
740 capture->v4l2_hue = 1;
741 capture->v4l2_hue_min = capture->queryctrl.minimum;
742 capture->v4l2_hue_max = capture->queryctrl.maximum;
745 if (capture->queryctrl.id == V4L2_CID_GAIN)
747 capture->v4l2_gain = 1;
748 capture->v4l2_gain_min = capture->queryctrl.minimum;
749 capture->v4l2_gain_max = capture->queryctrl.maximum;
752 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
753 v4l2_scan_controls_enumerate_menu(capture);
760 perror ("VIDIOC_QUERYCTRL");
768 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
772 detect_v4l2 = try_init_v4l2(capture, deviceName);
774 if (detect_v4l2 != 1) {
775 /* init of the v4l2 device is not OK */
779 /* starting from here, we assume we are in V4L2 mode */
782 /* Init V4L2 control variables */
783 capture->v4l2_brightness = 0;
784 capture->v4l2_contrast = 0;
785 capture->v4l2_saturation = 0;
786 capture->v4l2_hue = 0;
787 capture->v4l2_gain = 0;
789 capture->v4l2_brightness_min = 0;
790 capture->v4l2_contrast_min = 0;
791 capture->v4l2_saturation_min = 0;
792 capture->v4l2_hue_min = 0;
793 capture->v4l2_gain_min = 0;
795 capture->v4l2_brightness_max = 0;
796 capture->v4l2_contrast_max = 0;
797 capture->v4l2_saturation_max = 0;
798 capture->v4l2_hue_max = 0;
799 capture->v4l2_gain_max = 0;
801 /* Scan V4L2 controls */
802 v4l2_scan_controls(capture);
804 if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
806 fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
807 icvCloseCAM_V4L(capture);
811 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
812 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
813 I myself am using a simple NTSC video input capture card that uses the value of 1.
814 If you are not in North America or have a different video standard, you WILL have to change
815 the following settings and recompile/reinstall. This set of settings is based on
816 the most commonly encountered input video source types (like my bttv card) */
818 if(capture->inp.index > 0) {
819 CLEAR (capture->inp);
820 capture->inp.index = CHANNEL_NUMBER;
821 /* Set only channel number to CHANNEL_NUMBER */
822 /* V4L2 have a status field from selected video mode */
823 if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
825 fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n");
826 icvCloseCAM_V4L (capture);
831 /* Find Window info */
832 CLEAR (capture->form);
833 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
835 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
836 fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
837 icvCloseCAM_V4L(capture);
841 if (V4L2_SUPPORT == 0)
845 if (autosetup_capture_mode_v4l2(capture) == -1)
848 icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
852 /* Buggy driver paranoia. */
853 min = capture->form.fmt.pix.width * 2;
855 if (capture->form.fmt.pix.bytesperline < min)
856 capture->form.fmt.pix.bytesperline = min;
858 min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
860 if (capture->form.fmt.pix.sizeimage < min)
861 capture->form.fmt.pix.sizeimage = min;
863 CLEAR (capture->req);
865 unsigned int buffer_number = 4;
869 capture->req.count = buffer_number;
870 capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
871 capture->req.memory = V4L2_MEMORY_MMAP;
873 if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
877 fprintf (stderr, "%s does not support memory mapping\n", deviceName);
879 perror ("VIDIOC_REQBUFS");
881 /* free capture, and returns an error code */
882 icvCloseCAM_V4L (capture);
886 if (capture->req.count < buffer_number)
888 if (buffer_number == 1)
890 fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
892 /* free capture, and returns an error code */
893 icvCloseCAM_V4L (capture);
902 for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
904 struct v4l2_buffer buf;
908 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
909 buf.memory = V4L2_MEMORY_MMAP;
910 buf.index = n_buffers;
912 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
913 perror ("VIDIOC_QUERYBUF");
915 /* free capture, and returns an error code */
916 icvCloseCAM_V4L (capture);
920 capture->buffers[n_buffers].length = buf.length;
921 capture->buffers[n_buffers].start =
922 mmap (NULL /* start anywhere */,
924 PROT_READ | PROT_WRITE /* required */,
925 MAP_SHARED /* recommended */,
926 capture->deviceHandle, buf.m.offset);
928 if (MAP_FAILED == capture->buffers[n_buffers].start) {
931 /* free capture, and returns an error code */
932 icvCloseCAM_V4L (capture);
937 /* Set up Image data */
938 cvInitImageHeader( &capture->frame,
939 cvSize( capture->captureWindow.width,
940 capture->captureWindow.height ),
941 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
942 /* Allocate space for RGBA data */
943 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
946 }; /* End _capture_V4L2 */
948 #endif /* HAVE_CAMV4L2 */
950 static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
954 detect_v4l = try_init_v4l(capture, deviceName);
956 if ((detect_v4l == -1)
959 fprintf (stderr, "HIGHGUI ERROR: V4L"
960 ": device %s: Unable to open for READ ONLY\n", deviceName);
965 if ((detect_v4l <= 0)
968 fprintf (stderr, "HIGHGUI ERROR: V4L"
969 ": device %s: Unable to query number of channels\n", deviceName);
975 if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
977 fprintf( stderr, "HIGHGUI ERROR: V4L: "
978 "device %s is unable to capture video memory.\n",deviceName);
979 icvCloseCAM_V4L(capture);
986 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
987 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
988 I myself am using a simple NTSC video input capture card that uses the value of 1.
989 If you are not in North America or have a different video standard, you WILL have to change
990 the following settings and recompile/reinstall. This set of settings is based on
991 the most commonly encountered input video source types (like my bttv card) */
995 if(capture->capability.channels>0) {
997 struct video_channel selectedChannel;
999 selectedChannel.channel=CHANNEL_NUMBER;
1000 if (ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
1001 /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
1002 // selectedChannel.norm = VIDEO_MODE_NTSC;
1003 if (ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
1004 /* Could not set selected channel - Oh well */
1005 //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
1014 if(ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
1015 fprintf( stderr, "HIGHGUI ERROR: V4L: "
1016 "Could not obtain specifics of capture window.\n\n");
1017 icvCloseCAM_V4L(capture);
1025 if (autosetup_capture_mode_v4l(capture) == -1)
1032 ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
1033 capture->memoryMap = (char *)mmap(0,
1034 capture->memoryBuffer.size,
1035 PROT_READ | PROT_WRITE,
1037 capture->deviceHandle,
1039 if (capture->memoryMap == MAP_FAILED) {
1040 fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
1041 icvCloseCAM_V4L(capture);
1044 /* Set up video_mmap structure pointing to this memory mapped area so each image may be
1045 retrieved from an index value */
1046 capture->mmaps = (struct video_mmap *)
1047 (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
1048 if (!capture->mmaps) {
1049 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not memory map video frames.\n");
1050 icvCloseCAM_V4L(capture);
1056 /* Set up Image data */
1057 cvInitImageHeader( &capture->frame,
1058 cvSize( capture->captureWindow.width,
1059 capture->captureWindow.height ),
1060 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1061 /* Allocate space for RGBA data */
1062 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1065 }; /* End _capture_V4L */
1067 static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
1069 static int autoindex=0;
1071 char deviceName[MAX_DEVICE_DRIVER_NAME];
1075 icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
1077 return NULL; /* Are there any /dev/video input sources? */
1079 //search index in indexList
1080 if ( (index>-1) && ! ((1 << index) & indexList) )
1082 fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index);
1083 return NULL; /* Did someone ask for not correct video source number? */
1085 /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
1086 the handles for V4L processing */
1087 CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
1089 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
1092 /* Select camera, or rather, V4L video source */
1093 if (index<0) { // Asking for the first device available
1094 for (; autoindex<MAX_CAMERAS;autoindex++)
1095 if (indexList & (1<<autoindex))
1097 if (autoindex==MAX_CAMERAS)
1100 autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
1102 /* Print the CameraNumber at the end of the string with a width of one character */
1103 sprintf(deviceName, "/dev/video%1d", index);
1105 /* w/o memset some parts arent initialized - AKA: Fill it with zeros so it is clean */
1106 memset(capture,0,sizeof(CvCaptureCAM_V4L));
1107 /* Present the routines needed for V4L funtionality. They are inserted as part of
1108 the standard set of cv calls promoting transparency. "Vector Table" insertion. */
1109 capture->FirstCapture = 1;
1112 if (_capture_V4L2 (capture, deviceName) == -1) {
1113 icvCloseCAM_V4L(capture);
1115 #endif /* HAVE_CAMV4L2 */
1116 if (_capture_V4L (capture, deviceName) == -1) {
1117 icvCloseCAM_V4L(capture);
1124 #endif /* HAVE_CAMV4L2 */
1127 }; /* End icvOpenCAM_V4L */
1131 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1132 struct v4l2_buffer buf;
1136 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1137 buf.memory = V4L2_MEMORY_MMAP;
1139 if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1145 /* Could ignore EIO, see spec. */
1150 /* display the error and stop processing */
1151 perror ("VIDIOC_DQBUF");
1156 assert(buf.index < capture->req.count);
1158 capture->bufferIndex = buf.index;
1160 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1161 perror ("VIDIOC_QBUF");
1166 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1171 while (count-- > 0) {
1178 FD_SET (capture->deviceHandle, &fds);
1184 r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1194 fprintf (stderr, "select timeout\n");
1196 /* end the infinite loop */
1200 if (read_frame_v4l2 (capture))
1206 #endif /* HAVE_CAMV4L2 */
1208 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1210 if (capture->FirstCapture) {
1211 /* Some general initialization must take place the first time through */
1213 /* This is just a technicality, but all buffers must be filled up before any
1214 staggered SYNC is applied. SO, filler up. (see V4L HowTo) */
1218 if (V4L2_SUPPORT == 1)
1221 for (capture->bufferIndex = 0;
1222 capture->bufferIndex < ((int)capture->req.count);
1223 ++capture->bufferIndex)
1226 struct v4l2_buffer buf;
1230 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1231 buf.memory = V4L2_MEMORY_MMAP;
1232 buf.index = (unsigned long)capture->bufferIndex;
1234 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1235 perror ("VIDIOC_QBUF");
1240 /* enable the streaming */
1241 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1242 if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
1244 /* error enabling the stream */
1245 perror ("VIDIOC_STREAMON");
1249 #endif /* HAVE_CAMV4L2 */
1252 for (capture->bufferIndex = 0;
1253 capture->bufferIndex < (capture->memoryBuffer.frames-1);
1254 ++capture->bufferIndex) {
1256 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1257 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1258 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1259 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1261 if (ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1262 fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1269 /* preparation is ok */
1270 capture->FirstCapture = 0;
1275 if (V4L2_SUPPORT == 1)
1278 mainloop_v4l2(capture);
1281 #endif /* HAVE_CAMV4L2 */
1284 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1285 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1286 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1287 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1289 if (ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1290 &capture->mmaps[capture->bufferIndex]) == -1) {
1291 /* capture is on the way, so just exit */
1295 ++capture->bufferIndex;
1296 if (capture->bufferIndex == capture->memoryBuffer.frames) {
1297 capture->bufferIndex = 0;
1306 * Turn a YUV4:2:0 block into an RGB block
1308 * Video4Linux seems to use the blue, green, red channel
1309 * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
1311 * Color space conversion coefficients taken from the excellent
1312 * http://www.inforamp.net/~poynton/ColorFAQ.html
1313 * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
1314 * Y values are given for all 4 pixels, but the U (Pb)
1315 * and V (Pr) are assumed constant over the 2x2 block.
1317 * To avoid floating point arithmetic, the color conversion
1318 * coefficients are scaled into 16.16 fixed-point integers.
1319 * They were determined as follows:
1321 * double brightness = 1.0; (0->black; 1->full scale)
1322 * double saturation = 1.0; (0->greyscale; 1->full color)
1323 * double fixScale = brightness * 256 * 256;
1324 * int rvScale = (int)(1.402 * saturation * fixScale);
1325 * int guScale = (int)(-0.344136 * saturation * fixScale);
1326 * int gvScale = (int)(-0.714136 * saturation * fixScale);
1327 * int buScale = (int)(1.772 * saturation * fixScale);
1328 * int yScale = (int)(fixScale);
1331 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
1332 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
1335 move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1336 int rowPixels, unsigned char * rgb)
1338 const int rvScale = 91881;
1339 const int guScale = -22553;
1340 const int gvScale = -46801;
1341 const int buScale = 116129;
1342 const int yScale = 65536;
1345 g = guScale * u + gvScale * v;
1354 yTL *= yScale; yTR *= yScale;
1355 yBL *= yScale; yBR *= yScale;
1357 /* Write out top two pixels */
1358 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1359 rgb[2] = LIMIT(r+yTL);
1361 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1362 rgb[5] = LIMIT(r+yTR);
1364 /* Skip down to next line to write out bottom two pixels */
1365 rgb += 3 * rowPixels;
1366 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1367 rgb[2] = LIMIT(r+yBL);
1369 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1370 rgb[5] = LIMIT(r+yBR);
1374 move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1375 int rowPixels, unsigned char * rgb)
1377 const int rvScale = 91881;
1378 const int guScale = -22553;
1379 const int gvScale = -46801;
1380 const int buScale = 116129;
1381 const int yScale = 65536;
1384 g = guScale * u + gvScale * v;
1393 yTL *= yScale; yTR *= yScale;
1394 yBL *= yScale; yBR *= yScale;
1396 /* Write out top two first pixels */
1397 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1398 rgb[2] = LIMIT(r+yTL);
1400 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1401 rgb[5] = LIMIT(r+yTR);
1403 /* Write out top two last pixels */
1405 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1406 rgb[2] = LIMIT(r+yBL);
1408 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1409 rgb[5] = LIMIT(r+yBR);
1412 // Consider a YUV420P image of 8x2 pixels.
1414 // A plane of Y values A B C D E F G H
1417 // A plane of U values 1 2 3 4
1418 // A plane of V values 1 2 3 4 ....
1420 // The U1/V1 samples correspond to the ABIJ pixels.
1421 // U2/V2 samples correspond to the CDKL pixels.
1423 /* Converts from planar YUV420P to RGB24. */
1425 yuv420p_to_rgb24(int width, int height,
1426 unsigned char *pIn0, unsigned char *pOut0)
1428 const int numpix = width * height;
1429 const int bytes = 24 >> 3;
1430 int i, j, y00, y01, y10, y11, u, v;
1431 unsigned char *pY = pIn0;
1432 unsigned char *pU = pY + numpix;
1433 unsigned char *pV = pU + numpix / 4;
1434 unsigned char *pOut = pOut0;
1436 for (j = 0; j <= height - 2; j += 2) {
1437 for (i = 0; i <= width - 2; i += 2) {
1440 y10 = *(pY + width);
1441 y11 = *(pY + width + 1);
1445 move_420_block(y00, y01, y10, y11, u, v,
1453 pOut += width * bytes;
1457 // Consider a YUV420 image of 6x2 pixels.
1462 // The U1/V1 samples correspond to the ABIJ pixels.
1463 // U2/V2 samples correspond to the CDKL pixels.
1465 /* Converts from interlaced YUV420 to RGB24. */
1466 /* [FD] untested... */
1468 yuv420_to_rgb24(int width, int height,
1469 unsigned char *pIn0, unsigned char *pOut0)
1471 const int bytes = 24 >> 3;
1472 int i, j, y00, y01, y10, y11, u, v;
1473 unsigned char *pY = pIn0;
1474 unsigned char *pU = pY + 4;
1475 unsigned char *pV = pU + width;
1476 unsigned char *pOut = pOut0;
1478 for (j = 0; j <= height - 2; j += 2) {
1479 for (i = 0; i <= width - 4; i += 4) {
1482 y10 = *(pY + width);
1483 y11 = *(pY + width + 1);
1487 move_420_block(y00, y01, y10, y11, u, v,
1495 y10 = *(pY + width);
1496 y11 = *(pY + width + 1);
1500 move_420_block(y00, y01, y10, y11, u, v,
1508 pOut += width * bytes;
1512 // Consider a YUV411P image of 8x2 pixels.
1514 // A plane of Y values as before.
1516 // A plane of U values 1 2
1519 // A plane of V values 1 2
1522 // The U1/V1 samples correspond to the ABCD pixels.
1523 // U2/V2 samples correspond to the EFGH pixels.
1525 /* Converts from planar YUV411P to RGB24. */
1526 /* [FD] untested... */
1528 yuv411p_to_rgb24(int width, int height,
1529 unsigned char *pIn0, unsigned char *pOut0)
1531 const int numpix = width * height;
1532 const int bytes = 24 >> 3;
1533 int i, j, y00, y01, y10, y11, u, v;
1534 unsigned char *pY = pIn0;
1535 unsigned char *pU = pY + numpix;
1536 unsigned char *pV = pU + numpix / 4;
1537 unsigned char *pOut = pOut0;
1539 for (j = 0; j <= height; j++) {
1540 for (i = 0; i <= width - 4; i += 4) {
1548 move_411_block(y00, y01, y10, y11, u, v,
1558 /* convert from 4:2:2 YUYV interlaced to RGB24 */
1559 /* based on ccvt_yuyv_bgr32() from camstream */
1561 if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
1563 yuyv_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1568 int r, g, b, cr, cg, cb, y1, y2;
1577 cb = ((*s - 128) * 454) >> 8;
1578 cg = (*s++ - 128) * 88;
1580 cr = ((*s - 128) * 359) >> 8;
1581 cg = (cg + (*s++ - 128) * 183) >> 8;
1609 uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1614 int r, g, b, cr, cg, cb, y1, y2;
1622 cb = ((*s - 128) * 454) >> 8;
1623 cg = (*s++ - 128) * 88;
1625 cr = ((*s - 128) * 359) >> 8;
1626 cg = (cg + (*s++ - 128) * 183) >> 8;
1656 /* support for MJPEG is only available with libjpeg and gcc,
1657 because it's use libjepg and fmemopen()
1660 /* include headers to be able to use libjpeg and GrFmtJpegReader */
1663 #include "jpeglib.h"
1666 /* define a new class for using fmemopen() instead of fopen() */
1667 class MyMJpegReader : public GrFmtJpegReader {
1669 MyMJpegReader (unsigned char *src, size_t src_size);
1672 unsigned char *my_src;
1676 /////////////////////// Error processing /////////////////////
1678 typedef struct GrFmtJpegErrorMgr
1680 struct jpeg_error_mgr pub; /* "parent" structure */
1681 jmp_buf setjmp_buffer; /* jump label */
1687 error_exit( j_common_ptr cinfo )
1689 GrFmtJpegErrorMgr* err_mgr = (GrFmtJpegErrorMgr*)(cinfo->err);
1691 /* Return control to the setjmp point */
1692 longjmp( err_mgr->setjmp_buffer, 1 );
1695 /////////////////////// MyMJpegReader ///////////////////
1697 /* constructor just call the parent constructor, but without real filename */
1698 MyMJpegReader::MyMJpegReader (unsigned char *src, size_t src_size)
1699 : GrFmtJpegReader ("/dev/null") {
1700 /* memorize the given src memory area, with it's size */
1702 my_src_size = src_size;
1706 MyMJpegReader::ReadHeader is almost like GrFmtJpegReader::ReadHeader,
1707 just use fmemopen() instead of fopen()
1709 bool MyMJpegReader::ReadHeader () {
1710 bool result = false;
1713 jpeg_decompress_struct* cinfo = new jpeg_decompress_struct;
1714 GrFmtJpegErrorMgr* jerr = new GrFmtJpegErrorMgr;
1716 cinfo->err = jpeg_std_error(&jerr->pub);
1717 jerr->pub.error_exit = error_exit;
1722 if( setjmp( jerr->setjmp_buffer ) == 0 )
1724 jpeg_create_decompress( cinfo );
1726 m_f = fmemopen( my_src, my_src_size, "rb" );
1729 jpeg_stdio_src( cinfo, m_f );
1730 jpeg_read_header( cinfo, TRUE );
1732 m_width = cinfo->image_width;
1733 m_height = cinfo->image_height;
1734 m_iscolor = cinfo->num_components > 1;
1746 /* convert from mjpeg to rgb24 */
1748 mjpeg_to_rgb24 (int width, int height,
1749 unsigned char *src, int length,
1752 /* use a MyMJpegReader reader for doing the conversion */
1753 MyMJpegReader* reader = 0;
1754 reader = new MyMJpegReader (src, length);
1755 reader->ReadHeader ();
1756 reader->ReadData (dst, width * 3, 1 );
1765 * BAYER2RGB24 ROUTINE TAKEN FROM:
1767 * Sonix SN9C10x based webcam basic I/F routines
1768 * Takafumi Mizuno <taka-qce@ls-a.jp>
1772 void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1775 unsigned char *rawpt, *scanpt;
1780 size = WIDTH*HEIGHT;
1782 for ( i = 0; i < size; i++ ) {
1783 if ( (i/WIDTH) % 2 == 0 ) {
1784 if ( (i % 2) == 0 ) {
1786 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
1787 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1788 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
1789 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1790 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
1791 *scanpt++ = *rawpt; /* B */
1793 /* first line or left column */
1794 *scanpt++ = *(rawpt+WIDTH+1); /* R */
1795 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
1796 *scanpt++ = *rawpt; /* B */
1800 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
1801 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
1802 *scanpt++ = *rawpt; /* G */
1803 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1805 /* first line or right column */
1806 *scanpt++ = *(rawpt+WIDTH); /* R */
1807 *scanpt++ = *rawpt; /* G */
1808 *scanpt++ = *(rawpt-1); /* B */
1812 if ( (i % 2) == 0 ) {
1814 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
1815 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
1816 *scanpt++ = *rawpt; /* G */
1817 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
1819 /* bottom line or left column */
1820 *scanpt++ = *(rawpt+1); /* R */
1821 *scanpt++ = *rawpt; /* G */
1822 *scanpt++ = *(rawpt-WIDTH); /* B */
1826 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
1827 *scanpt++ = *rawpt; /* R */
1828 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1829 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1830 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1831 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
1833 /* bottom line or right column */
1834 *scanpt++ = *rawpt; /* R */
1835 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
1836 *scanpt++ = *(rawpt-WIDTH-1); /* B */
1846 #define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
1856 static code_table_t table[256];
1857 static int init_done = 0;
1861 sonix_decompress_init
1862 =====================
1863 pre-calculates a locally stored table for efficient huffman-decoding.
1865 Each entry at index x in the table represents the codeword
1866 present at the MSB of byte x.
1869 void sonix_decompress_init(void)
1872 int is_abs, val, len;
1874 for (i = 0; i < 256; i++) {
1878 if ((i & 0x80) == 0) {
1883 else if ((i & 0xE0) == 0x80) {
1888 else if ((i & 0xE0) == 0xA0) {
1893 else if ((i & 0xF0) == 0xD0) {
1898 else if ((i & 0xF0) == 0xF0) {
1903 else if ((i & 0xF8) == 0xC8) {
1908 else if ((i & 0xFC) == 0xC0) {
1913 else if ((i & 0xFC) == 0xC4) {
1914 /* code 110001xx: unknown */
1918 else if ((i & 0xF0) == 0xE0) {
1921 val = (i & 0x0F) << 4;
1924 table[i].is_abs = is_abs;
1936 decompresses an image encoded by a SN9C101 camera controller chip.
1940 inp pointer to compressed frame (with header already stripped)
1941 OUT outp pointer to decompressed frame
1943 Returns 0 if the operation was successful.
1944 Returns <0 if operation failed.
1947 int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
1953 unsigned char *addr;
1956 /* do sonix_decompress_init first! */
1961 for (row = 0; row < height; row++) {
1967 /* first two pixels in first two rows are stored as raw 8-bit */
1969 addr = inp + (bitpos >> 3);
1970 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1974 addr = inp + (bitpos >> 3);
1975 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1982 while (col < width) {
1983 /* get bitcode from bitstream */
1984 addr = inp + (bitpos >> 3);
1985 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1987 /* update bit position */
1988 bitpos += table[code].len;
1990 /* calculate pixel value */
1991 val = table[code].val;
1992 if (!table[code].is_abs) {
1993 /* value is relative to top and left pixel */
1995 /* left column: relative to top pixel */
1996 val += outp[-2*width];
1999 /* top row: relative to left pixel */
2003 /* main area: average of left pixel and top pixel */
2004 val += (outp[-2] + outp[-2*width]) / 2;
2009 *outp++ = CLAMP(val);
2018 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture) {
2021 if (V4L2_SUPPORT == 0)
2022 #endif /* HAVE_CAMV4L2 */
2025 /* [FD] this really belongs here */
2026 if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
2027 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
2032 /* Now get what has already been captured as a IplImage return */
2034 /* First, reallocate imageData if the frame size changed */
2038 if (V4L2_SUPPORT == 1)
2041 if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
2042 || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
2043 cvFree(&capture->frame.imageData);
2044 cvInitImageHeader( &capture->frame,
2045 cvSize( capture->form.fmt.pix.width,
2046 capture->form.fmt.pix.height ),
2047 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2048 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2052 #endif /* HAVE_CAMV4L2 */
2055 if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
2056 || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
2057 cvFree(&capture->frame.imageData);
2058 cvInitImageHeader( &capture->frame,
2059 cvSize( capture->captureWindow.width,
2060 capture->captureWindow.height ),
2061 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2062 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2069 if (V4L2_SUPPORT == 1)
2072 if (PALETTE_BGR24 == 1)
2073 memcpy((char *)capture->frame.imageData,
2074 (char *)capture->buffers[capture->bufferIndex].start,
2075 capture->frame.imageSize);
2077 if (PALETTE_YVU420 == 1)
2078 yuv420p_to_rgb24(capture->form.fmt.pix.width,
2079 capture->form.fmt.pix.height,
2080 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2081 (unsigned char*)capture->frame.imageData);
2083 if (PALETTE_YUV411P == 1)
2084 yuv411p_to_rgb24(capture->form.fmt.pix.width,
2085 capture->form.fmt.pix.height,
2086 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2087 (unsigned char*)capture->frame.imageData);
2091 /* support for MJPEG is only available with libjpeg and gcc,
2092 because it's use libjepg and fmemopen()
2094 if (PALETTE_MJPEG == 1)
2095 mjpeg_to_rgb24(capture->form.fmt.pix.width,
2096 capture->form.fmt.pix.height,
2097 (unsigned char*)(capture->buffers[capture->bufferIndex]
2099 capture->buffers[capture->bufferIndex].length,
2100 (unsigned char*)capture->frame.imageData);
2104 if (PALETTE_YUYV == 1)
2105 yuyv_to_rgb24(capture->form.fmt.pix.width,
2106 capture->form.fmt.pix.height,
2107 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2108 (unsigned char*)capture->frame.imageData);
2110 if (PALETTE_UYVY == 1)
2111 uyvy_to_rgb24(capture->form.fmt.pix.width,
2112 capture->form.fmt.pix.height,
2113 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2114 (unsigned char*)capture->frame.imageData);
2116 if (PALETTE_SBGGR8 == 1)
2118 bayer2rgb24(capture->form.fmt.pix.width,
2119 capture->form.fmt.pix.height,
2120 (unsigned char*)capture->buffers[capture->bufferIndex].start,
2121 (unsigned char*)capture->frame.imageData);
2124 if (PALETTE_SN9C10X == 1)
2126 sonix_decompress_init();
2128 sonix_decompress(capture->form.fmt.pix.width,
2129 capture->form.fmt.pix.height,
2130 (unsigned char*)capture->buffers[capture->bufferIndex].start,
2131 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start);
2133 bayer2rgb24(capture->form.fmt.pix.width,
2134 capture->form.fmt.pix.height,
2135 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
2136 (unsigned char*)capture->frame.imageData);
2140 #endif /* HAVE_CAMV4L2 */
2143 switch(capture->imageProperties.palette) {
2144 case VIDEO_PALETTE_RGB24:
2145 memcpy((char *)capture->frame.imageData,
2146 (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2147 capture->frame.imageSize);
2149 case VIDEO_PALETTE_YUV420P:
2150 yuv420p_to_rgb24(capture->captureWindow.width,
2151 capture->captureWindow.height,
2152 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2153 (unsigned char*)capture->frame.imageData);
2155 case VIDEO_PALETTE_YUV420:
2156 yuv420_to_rgb24(capture->captureWindow.width,
2157 capture->captureWindow.height,
2158 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2159 (unsigned char*)capture->frame.imageData);
2161 case VIDEO_PALETTE_YUV411P:
2162 yuv411p_to_rgb24(capture->captureWindow.width,
2163 capture->captureWindow.height,
2164 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2165 (unsigned char*)capture->frame.imageData);
2169 "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n",
2170 capture->imageProperties.palette);
2177 return(&capture->frame);
2180 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
2185 if (V4L2_SUPPORT == 1)
2188 /* default value for min and max */
2192 CLEAR (capture->form);
2193 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2194 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
2195 /* display an error message, and return an error code */
2196 perror ("VIDIOC_G_FMT");
2200 switch (property_id) {
2201 case CV_CAP_PROP_FRAME_WIDTH:
2202 return capture->form.fmt.pix.width;
2203 case CV_CAP_PROP_FRAME_HEIGHT:
2204 return capture->form.fmt.pix.height;
2207 /* initialize the control structure */
2209 switch (property_id) {
2210 case CV_CAP_PROP_BRIGHTNESS:
2211 capture->control.id = V4L2_CID_BRIGHTNESS;
2213 case CV_CAP_PROP_CONTRAST:
2214 capture->control.id = V4L2_CID_CONTRAST;
2216 case CV_CAP_PROP_SATURATION:
2217 capture->control.id = V4L2_CID_SATURATION;
2219 case CV_CAP_PROP_HUE:
2220 capture->control.id = V4L2_CID_HUE;
2222 case CV_CAP_PROP_GAIN:
2223 capture->control.id = V4L2_CID_GAIN;
2227 "HIGHGUI ERROR: V4L2: getting property #%d is not supported\n",
2232 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_CTRL,
2233 &capture->control)) {
2235 fprintf( stderr, "HIGHGUI ERROR: V4L2: ");
2236 switch (property_id) {
2237 case CV_CAP_PROP_BRIGHTNESS:
2238 fprintf (stderr, "Brightness");
2240 case CV_CAP_PROP_CONTRAST:
2241 fprintf (stderr, "Contrast");
2243 case CV_CAP_PROP_SATURATION:
2244 fprintf (stderr, "Saturation");
2246 case CV_CAP_PROP_HUE:
2247 fprintf (stderr, "Hue");
2249 case CV_CAP_PROP_GAIN:
2250 fprintf (stderr, "Gain");
2253 fprintf (stderr, " is not supported by your device\n");
2258 /* get the min/max values */
2259 switch (property_id) {
2261 case CV_CAP_PROP_BRIGHTNESS:
2262 v4l2_min = capture->v4l2_brightness_min;
2263 v4l2_max = capture->v4l2_brightness_max;
2265 case CV_CAP_PROP_CONTRAST:
2266 v4l2_min = capture->v4l2_contrast_min;
2267 v4l2_max = capture->v4l2_contrast_max;
2269 case CV_CAP_PROP_SATURATION:
2270 v4l2_min = capture->v4l2_saturation_min;
2271 v4l2_max = capture->v4l2_saturation_max;
2273 case CV_CAP_PROP_HUE:
2274 v4l2_min = capture->v4l2_hue_min;
2275 v4l2_max = capture->v4l2_hue_max;
2277 case CV_CAP_PROP_GAIN:
2278 v4l2_min = capture->v4l2_gain_min;
2279 v4l2_max = capture->v4l2_gain_max;
2283 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2284 return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min);
2287 #endif /* HAVE_CAMV4L2 */
2292 if (ioctl (capture->deviceHandle,
2293 VIDIOCGWIN, &capture->captureWindow) < 0) {
2295 "HIGHGUI ERROR: V4L: "
2296 "Unable to determine size of incoming image\n");
2297 icvCloseCAM_V4L(capture);
2301 switch (property_id) {
2302 case CV_CAP_PROP_FRAME_WIDTH:
2303 retval = capture->captureWindow.width;
2305 case CV_CAP_PROP_FRAME_HEIGHT:
2306 retval = capture->captureWindow.height;
2308 case CV_CAP_PROP_BRIGHTNESS:
2309 retval = capture->imageProperties.brightness;
2311 case CV_CAP_PROP_CONTRAST:
2312 retval = capture->imageProperties.contrast;
2314 case CV_CAP_PROP_SATURATION:
2315 retval = capture->imageProperties.colour;
2317 case CV_CAP_PROP_HUE:
2318 retval = capture->imageProperties.hue;
2320 case CV_CAP_PROP_GAIN:
2322 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
2327 "HIGHGUI ERROR: V4L: getting property #%d is not supported\n",
2332 /* there was a problem */
2336 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2337 return float (retval) / 0xFFFF;
2343 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
2347 if (V4L2_SUPPORT == 1)
2350 CLEAR (capture->crop);
2351 capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2352 capture->crop.c.left = 0;
2353 capture->crop.c.top = 0;
2354 capture->crop.c.height = h*24;
2355 capture->crop.c.width = w*24;
2357 /* set the crop area, but don't exit if the device don't support croping */
2358 xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
2360 CLEAR (capture->form);
2361 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2363 /* read the current setting, mainly to retreive the pixelformat information */
2364 xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
2366 /* set the values we want to change */
2367 capture->form.fmt.pix.width = w;
2368 capture->form.fmt.pix.height = h;
2369 capture->form.fmt.win.chromakey = 0;
2370 capture->form.fmt.win.field = V4L2_FIELD_ANY;
2371 capture->form.fmt.win.clips = 0;
2372 capture->form.fmt.win.clipcount = 0;
2373 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
2375 /* ask the device to change the size
2376 * don't test if the set of the size is ok, because some device
2377 * don't allow changing the size, and we will get the real size
2379 xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
2381 /* try to set framerate to 30 fps */
2382 struct v4l2_streamparm setfps;
2383 memset (&setfps, 0, sizeof(struct v4l2_streamparm));
2384 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2385 setfps.parm.capture.timeperframe.numerator = 1;
2386 setfps.parm.capture.timeperframe.denominator = 30;
2387 xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
2389 /* we need to re-initialize some things, like buffers, because the size has
2391 capture->FirstCapture = 1;
2393 /* Get window info again, to get the real value */
2394 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
2396 fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
2398 icvCloseCAM_V4L(capture);
2406 #endif /* HAVE_CAMV4L2 */
2409 if (capture==0) return 0;
2410 if (w>capture->capability.maxwidth) {
2411 w=capture->capability.maxwidth;
2413 if (h>capture->capability.maxheight) {
2414 h=capture->capability.maxheight;
2417 capture->captureWindow.width=w;
2418 capture->captureWindow.height=h;
2420 if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
2421 icvCloseCAM_V4L(capture);
2425 if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
2426 icvCloseCAM_V4L(capture);
2430 capture->FirstCapture = 1;
2438 static int icvSetControl (CvCaptureCAM_V4L* capture,
2439 int property_id, double value) {
2441 /* limitation of the input value */
2444 } else if (value > 1.0) {
2450 if (V4L2_SUPPORT == 1)
2453 /* default value for min and max */
2457 /* initialisations */
2458 CLEAR (capture->control);
2460 /* set which control we want to set */
2461 switch (property_id) {
2463 case CV_CAP_PROP_BRIGHTNESS:
2464 capture->control.id = V4L2_CID_BRIGHTNESS;
2466 case CV_CAP_PROP_CONTRAST:
2467 capture->control.id = V4L2_CID_CONTRAST;
2469 case CV_CAP_PROP_SATURATION:
2470 capture->control.id = V4L2_CID_SATURATION;
2472 case CV_CAP_PROP_HUE:
2473 capture->control.id = V4L2_CID_HUE;
2475 case CV_CAP_PROP_GAIN:
2476 capture->control.id = V4L2_CID_GAIN;
2480 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
2485 /* get the min and max values */
2486 if (-1 == xioctl (capture->deviceHandle,
2487 VIDIOC_G_CTRL, &capture->control)) {
2488 // perror ("VIDIOC_G_CTRL for getting min/max values");
2492 /* get the min/max values */
2493 switch (property_id) {
2495 case CV_CAP_PROP_BRIGHTNESS:
2496 v4l2_min = capture->v4l2_brightness_min;
2497 v4l2_max = capture->v4l2_brightness_max;
2499 case CV_CAP_PROP_CONTRAST:
2500 v4l2_min = capture->v4l2_contrast_min;
2501 v4l2_max = capture->v4l2_contrast_max;
2503 case CV_CAP_PROP_SATURATION:
2504 v4l2_min = capture->v4l2_saturation_min;
2505 v4l2_max = capture->v4l2_saturation_max;
2507 case CV_CAP_PROP_HUE:
2508 v4l2_min = capture->v4l2_hue_min;
2509 v4l2_max = capture->v4l2_hue_max;
2511 case CV_CAP_PROP_GAIN:
2512 v4l2_min = capture->v4l2_gain_min;
2513 v4l2_max = capture->v4l2_gain_max;
2517 /* initialisations */
2518 CLEAR (capture->control);
2520 /* set which control we want to set */
2521 switch (property_id) {
2523 case CV_CAP_PROP_BRIGHTNESS:
2524 capture->control.id = V4L2_CID_BRIGHTNESS;
2526 case CV_CAP_PROP_CONTRAST:
2527 capture->control.id = V4L2_CID_CONTRAST;
2529 case CV_CAP_PROP_SATURATION:
2530 capture->control.id = V4L2_CID_SATURATION;
2532 case CV_CAP_PROP_HUE:
2533 capture->control.id = V4L2_CID_HUE;
2535 case CV_CAP_PROP_GAIN:
2536 capture->control.id = V4L2_CID_GAIN;
2540 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
2545 /* set the value we want to set to the scaled the value */
2546 capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min);
2548 /* The driver may clamp the value or return ERANGE, ignored here */
2549 if (-1 == xioctl (capture->deviceHandle,
2550 VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) {
2551 perror ("VIDIOC_S_CTRL");
2555 #endif /* HAVE_CAMV4L2 */
2560 /* scale the value to the wanted integer one */
2561 v4l_value = (int)(0xFFFF * value);
2563 switch (property_id) {
2564 case CV_CAP_PROP_BRIGHTNESS:
2565 capture->imageProperties.brightness = v4l_value;
2567 case CV_CAP_PROP_CONTRAST:
2568 capture->imageProperties.contrast = v4l_value;
2570 case CV_CAP_PROP_SATURATION:
2571 capture->imageProperties.colour = v4l_value;
2573 case CV_CAP_PROP_HUE:
2574 capture->imageProperties.hue = v4l_value;
2576 case CV_CAP_PROP_GAIN:
2578 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
2582 "HIGHGUI ERROR: V4L: property #%d is not supported\n",
2587 if (ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties)
2591 "HIGHGUI ERROR: V4L: Unable to set video informations\n");
2592 icvCloseCAM_V4L(capture);
2602 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
2603 int property_id, double value ){
2604 static int width = 0, height = 0;
2607 /* initialization */
2610 /* two subsequent calls setting WIDTH and HEIGHT will change
2612 /* the first one will return an error, though. */
2614 switch (property_id) {
2615 case CV_CAP_PROP_FRAME_WIDTH:
2616 width = cvRound(value);
2617 if(width !=0 && height != 0) {
2618 retval = icvSetVideoSize( capture, width, height);
2622 case CV_CAP_PROP_FRAME_HEIGHT:
2623 height = cvRound(value);
2624 if(width !=0 && height != 0) {
2625 retval = icvSetVideoSize( capture, width, height);
2629 case CV_CAP_PROP_BRIGHTNESS:
2630 case CV_CAP_PROP_CONTRAST:
2631 case CV_CAP_PROP_SATURATION:
2632 case CV_CAP_PROP_HUE:
2633 case CV_CAP_PROP_GAIN:
2634 retval = icvSetControl(capture, property_id, value);
2638 "HIGHGUI ERROR: V4L: setting property #%d is not supported\n",
2642 /* return the the status */
2646 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
2647 /* Deallocate space - Hopefully, no leaks */
2653 if (V4L2_SUPPORT == 0)
2654 #endif /* HAVE_CAMV4L2 */
2658 free(capture->mmaps);
2659 if (capture->memoryMap)
2660 munmap(capture->memoryMap, capture->memoryBuffer.size);
2666 for (unsigned int n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
2668 if (-1 == munmap (capture->buffers[n_buffers].start, capture->buffers[n_buffers].length)) {
2674 #endif /* HAVE_CAMV4L2 */
2676 if (capture->deviceHandle > 0) close(capture->deviceHandle);
2678 if (capture->frame.imageData) cvFree(&capture->frame.imageData);
2679 //cvFree((void **)capture);
2684 class CvCaptureCAM_V4L_CPP : CvCapture
2687 CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
2688 virtual ~CvCaptureCAM_V4L_CPP() { close(); }
2690 virtual bool open( int index );
2691 virtual void close();
2693 virtual double getProperty(int);
2694 virtual bool setProperty(int, double);
2695 virtual bool grabFrame();
2696 virtual IplImage* retrieveFrame();
2699 CvCaptureCAM_V4L* captureV4L;
2702 bool CvCaptureCAM_V4L_CPP::open( int index )
2705 captureV4L = icvCaptureFromCAM_V4L(index);
2706 return captureV4L != 0;
2709 void CvCaptureCAM_V4L_CPP::close()
2713 icvCloseCAM_V4L( captureV4L );
2714 cvFree( &captureV4L );
2718 bool CvCaptureCAM_V4L_CPP::grabFrame()
2720 return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
2723 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame()
2725 return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L ) : 0;
2728 double CvCaptureCAM_V4L_CPP::getProperty( int propId )
2730 return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
2733 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
2735 return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
2738 CvCapture* cvCreateCameraCapture_V4L( int index )
2740 CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
2742 if( capture->open( index ))
2743 return (CvCapture*)capture;