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
264 CvCaptureVTable* vtable;
268 struct video_capability capability;
269 struct video_window captureWindow;
270 struct video_picture imageProperties;
271 struct video_mbuf memoryBuffer;
272 struct video_mmap *mmaps;
280 struct v4l2_capability cap;
281 struct v4l2_input inp;
282 struct v4l2_format form;
283 struct v4l2_crop crop;
284 struct v4l2_cropcap cropcap;
285 struct v4l2_requestbuffers req;
286 struct v4l2_jpegcompression compr;
287 struct v4l2_control control;
288 enum v4l2_buf_type type;
289 struct v4l2_queryctrl queryctrl;
290 struct v4l2_querymenu querymenu;
292 /* V4L2 control variables */
293 int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max;
294 int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max;
295 int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max;
296 int v4l2_hue, v4l2_hue_min, v4l2_hue_max;
297 int v4l2_gain, v4l2_gain_min, v4l2_gain_max;
299 #endif /* HAVE_CAMV4L2 */
306 int V4L2_SUPPORT = 0;
308 #endif /* HAVE_CAMV4L2 */
310 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
312 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
313 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture );
315 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
316 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
318 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
320 /*********************** Implementations ***************************************/
322 static int numCameras = 0;
323 static int indexList = 0;
324 CvCaptureVTable captureCAM_V4L_vtable =
327 (CvCaptureCloseFunc)icvCloseCAM_V4L,
328 (CvCaptureGrabFrameFunc)icvGrabFrameCAM_V4L,
329 (CvCaptureRetrieveFrameFunc)icvRetrieveFrameCAM_V4L,
330 (CvCaptureGetPropertyFunc)icvGetPropertyCAM_V4L,
331 (CvCaptureSetPropertyFunc)icvSetPropertyCAM_V4L,
332 (CvCaptureGetDescriptionFunc)0
337 // IOCTL handling for V4L2
338 static int xioctl( int fd, int request, void *arg)
344 do r = ioctl (fd, request, arg);
345 while (-1 == r && EINTR == errno);
351 #endif /* HAVE_CAMV4L2 */
353 /* Simple test program: Find number of Video Sources available.
354 Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
355 If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
356 Returns the global numCameras with the correct value (we hope) */
358 void icvInitCapture_V4L() {
361 char deviceName[MAX_DEVICE_DRIVER_NAME];
364 while(CameraNumber < MAX_CAMERAS) {
365 /* Print the CameraNumber at the end of the string with a width of one character */
366 sprintf(deviceName, "/dev/video%1d", CameraNumber);
367 /* Test using an open to see if this new device name really does exists. */
368 deviceHandle = open(deviceName, O_RDONLY);
369 if (deviceHandle != -1) {
370 /* This device does indeed exist - add it to the total so far */
372 indexList|=(1 << CameraNumber);
376 /* Set up to test the next /dev/video source in line */
380 }; /* End icvInitCapture_V4L */
384 struct video_picture *cam_pic,
388 cam_pic->palette = pal;
389 cam_pic->depth = depth;
390 if (ioctl(fd, VIDIOCSPICT, cam_pic) < 0)
392 if (ioctl(fd, VIDIOCGPICT, cam_pic) < 0)
394 if (cam_pic->palette == pal)
401 int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace)
403 CLEAR (capture->form);
405 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
406 capture->form.fmt.pix.pixelformat = colorspace;
407 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
408 capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
409 capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
411 if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
415 if (colorspace != capture->form.fmt.pix.pixelformat)
421 #endif /* HAVE_CAMV4L2 */
423 int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
426 // if detect = -1 then unable to open device
427 // if detect = 0 then detected nothing
428 // if detect = 1 then V4L device
432 // Test device for V4L compability
434 /* Test using an open to see if this new device name really does exists. */
435 /* No matter what the name - it still must be opened! */
436 capture->deviceHandle = open(deviceName, O_RDWR);
439 if (capture->deviceHandle == 0)
443 icvCloseCAM_V4L(capture);
448 /* Query the newly opened device for its capabilities */
449 if (ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
453 icvCloseCAM_V4L(capture);
467 int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
470 // if detect = -1 then unable to open device
471 // if detect = 0 then detected nothing
472 // if detect = 1 then V4L2 device
476 // Test device for V4L2 compability
478 /* Open and test V4L2 device */
479 capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
483 if (capture->deviceHandle == 0)
487 icvCloseCAM_V4L(capture);
492 CLEAR (capture->cap);
493 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
497 icvCloseCAM_V4L(capture);
501 CLEAR (capture->capability);
502 capture->capability.type = capture->cap.capabilities;
504 /* Query channels number */
505 if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
516 int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture)
518 if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0)
523 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0)
528 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0)
536 /* support for MJPEG is only available with libjpeg and gcc,
537 because it's use libjepg and fmemopen()
539 if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0)
547 if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0)
551 else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0)
556 if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0)
558 CLEAR (capture->compr);
559 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_JPEGCOMP, &capture->compr)) {
560 perror ("VIDIOC_G_JPEGCOMP");
564 capture->compr.quality = 0;
566 if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_JPEGCOMP, &capture->compr)) {
567 perror ("VIDIOC_S_JPEGCOMP");
573 if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0)
579 fprintf(stderr, "HIGHGUI ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
580 icvCloseCAM_V4L(capture);
588 #endif /* HAVE_CAMV4L2 */
590 int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture)
593 if(ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
594 fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
595 icvCloseCAM_V4L(capture);
599 /* Yet MORE things that might have to be changes with your frame capture card */
600 /* This sets the scale to the center of a 2^16 number */
601 if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_RGB24, 24)) {
602 //printf("negotiated palette RGB24\n");
604 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420P, 16)) {
605 //printf("negotiated palette YUV420P\n");
607 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420, 16)) {
608 //printf("negotiated palette YUV420\n");
610 else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV411P, 16)) {
611 //printf("negotiated palette YUV420P\n");
614 fprintf(stderr, "HIGHGUI ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n");
615 icvCloseCAM_V4L(capture);
625 void v4l2_scan_controls_enumerate_menu(CvCaptureCAM_V4L* capture)
627 // printf (" Menu items:\n");
628 CLEAR (capture->querymenu);
629 capture->querymenu.id = capture->queryctrl.id;
630 for (capture->querymenu.index = capture->queryctrl.minimum;
631 (int)capture->querymenu.index <= capture->queryctrl.maximum;
632 capture->querymenu.index++)
634 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYMENU,
635 &capture->querymenu))
637 // printf (" %s\n", capture->querymenu.name);
639 perror ("VIDIOC_QUERYMENU");
644 void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
649 for (ctrl_id = V4L2_CID_BASE;
650 ctrl_id < V4L2_CID_LASTP1;
654 /* set the id we will query now */
655 CLEAR (capture->queryctrl);
656 capture->queryctrl.id = ctrl_id;
658 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
659 &capture->queryctrl))
662 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
665 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
667 capture->v4l2_brightness = 1;
668 capture->v4l2_brightness_min = capture->queryctrl.minimum;
669 capture->v4l2_brightness_max = capture->queryctrl.maximum;
672 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
674 capture->v4l2_contrast = 1;
675 capture->v4l2_contrast_min = capture->queryctrl.minimum;
676 capture->v4l2_contrast_max = capture->queryctrl.maximum;
679 if (capture->queryctrl.id == V4L2_CID_SATURATION)
681 capture->v4l2_saturation = 1;
682 capture->v4l2_saturation_min = capture->queryctrl.minimum;
683 capture->v4l2_saturation_max = capture->queryctrl.maximum;
686 if (capture->queryctrl.id == V4L2_CID_HUE)
688 capture->v4l2_hue = 1;
689 capture->v4l2_hue_min = capture->queryctrl.minimum;
690 capture->v4l2_hue_max = capture->queryctrl.maximum;
693 if (capture->queryctrl.id == V4L2_CID_GAIN)
695 capture->v4l2_gain = 1;
696 capture->v4l2_gain_min = capture->queryctrl.minimum;
697 capture->v4l2_gain_max = capture->queryctrl.maximum;
700 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
701 v4l2_scan_controls_enumerate_menu(capture);
708 perror ("VIDIOC_QUERYCTRL");
714 for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
717 /* set the id we will query now */
718 CLEAR (capture->queryctrl);
719 capture->queryctrl.id = ctrl_id;
721 if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
722 &capture->queryctrl))
725 if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
728 if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
730 capture->v4l2_brightness = 1;
731 capture->v4l2_brightness_min = capture->queryctrl.minimum;
732 capture->v4l2_brightness_max = capture->queryctrl.maximum;
735 if (capture->queryctrl.id == V4L2_CID_CONTRAST)
737 capture->v4l2_contrast = 1;
738 capture->v4l2_contrast_min = capture->queryctrl.minimum;
739 capture->v4l2_contrast_max = capture->queryctrl.maximum;
742 if (capture->queryctrl.id == V4L2_CID_SATURATION)
744 capture->v4l2_saturation = 1;
745 capture->v4l2_saturation_min = capture->queryctrl.minimum;
746 capture->v4l2_saturation_max = capture->queryctrl.maximum;
749 if (capture->queryctrl.id == V4L2_CID_HUE)
751 capture->v4l2_hue = 1;
752 capture->v4l2_hue_min = capture->queryctrl.minimum;
753 capture->v4l2_hue_max = capture->queryctrl.maximum;
756 if (capture->queryctrl.id == V4L2_CID_GAIN)
758 capture->v4l2_gain = 1;
759 capture->v4l2_gain_min = capture->queryctrl.minimum;
760 capture->v4l2_gain_max = capture->queryctrl.maximum;
763 if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU)
764 v4l2_scan_controls_enumerate_menu(capture);
771 perror ("VIDIOC_QUERYCTRL");
779 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
783 detect_v4l2 = try_init_v4l2(capture, deviceName);
785 if (detect_v4l2 != 1) {
786 /* init of the v4l2 device is not OK */
790 /* starting from here, we assume we are in V4L2 mode */
793 /* Init V4L2 control variables */
794 capture->v4l2_brightness = 0;
795 capture->v4l2_contrast = 0;
796 capture->v4l2_saturation = 0;
797 capture->v4l2_hue = 0;
798 capture->v4l2_gain = 0;
800 capture->v4l2_brightness_min = 0;
801 capture->v4l2_contrast_min = 0;
802 capture->v4l2_saturation_min = 0;
803 capture->v4l2_hue_min = 0;
804 capture->v4l2_gain_min = 0;
806 capture->v4l2_brightness_max = 0;
807 capture->v4l2_contrast_max = 0;
808 capture->v4l2_saturation_max = 0;
809 capture->v4l2_hue_max = 0;
810 capture->v4l2_gain_max = 0;
812 /* Scan V4L2 controls */
813 v4l2_scan_controls(capture);
815 if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
817 fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
818 icvCloseCAM_V4L(capture);
822 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
823 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
824 I myself am using a simple NTSC video input capture card that uses the value of 1.
825 If you are not in North America or have a different video standard, you WILL have to change
826 the following settings and recompile/reinstall. This set of settings is based on
827 the most commonly encountered input video source types (like my bttv card) */
829 if(capture->inp.index > 0) {
830 CLEAR (capture->inp);
831 capture->inp.index = CHANNEL_NUMBER;
832 /* Set only channel number to CHANNEL_NUMBER */
833 /* V4L2 have a status field from selected video mode */
834 if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
836 fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n");
837 icvCloseCAM_V4L (capture);
842 /* Find Window info */
843 CLEAR (capture->form);
844 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
846 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
847 fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
848 icvCloseCAM_V4L(capture);
852 if (V4L2_SUPPORT == 0)
856 if (autosetup_capture_mode_v4l2(capture) == -1)
859 icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
863 /* Buggy driver paranoia. */
864 min = capture->form.fmt.pix.width * 2;
866 if (capture->form.fmt.pix.bytesperline < min)
867 capture->form.fmt.pix.bytesperline = min;
869 min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
871 if (capture->form.fmt.pix.sizeimage < min)
872 capture->form.fmt.pix.sizeimage = min;
874 CLEAR (capture->req);
876 capture->req.count = 4;
877 capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
878 capture->req.memory = V4L2_MEMORY_MMAP;
880 if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
884 fprintf (stderr, "%s does not support memory mapping\n", deviceName);
886 perror ("VIDIOC_REQBUFS");
888 /* free capture, and returns an error code */
889 icvCloseCAM_V4L (capture);
893 if (capture->req.count < 4)
895 fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
897 /* free capture, and returns an error code */
898 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 CvCapture * cvCaptureFromCAM_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->vtable = &captureCAM_V4L_vtable;
1110 capture->FirstCapture = 1;
1113 if (_capture_V4L2 (capture, deviceName) == -1) {
1114 icvCloseCAM_V4L(capture);
1116 #endif /* HAVE_CAMV4L2 */
1117 if (_capture_V4L (capture, deviceName) == -1) {
1118 icvCloseCAM_V4L(capture);
1125 #endif /* HAVE_CAMV4L2 */
1127 return (CvCapture *)capture;
1128 }; /* End icvOpenCAM_V4L */
1132 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1133 struct v4l2_buffer buf;
1137 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1138 buf.memory = V4L2_MEMORY_MMAP;
1140 if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1146 /* Could ignore EIO, see spec. */
1151 /* display the error and stop processing */
1152 perror ("VIDIOC_DQBUF");
1157 assert(buf.index < capture->req.count);
1159 capture->bufferIndex = buf.index;
1161 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1162 perror ("VIDIOC_QBUF");
1167 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1172 while (count-- > 0) {
1179 FD_SET (capture->deviceHandle, &fds);
1185 r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1195 fprintf (stderr, "select timeout\n");
1197 /* end the infinite loop */
1201 if (read_frame_v4l2 (capture))
1207 #endif /* HAVE_CAMV4L2 */
1209 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1211 if (capture->FirstCapture) {
1212 /* Some general initialization must take place the first time through */
1214 /* This is just a technicality, but all buffers must be filled up before any
1215 staggered SYNC is applied. SO, filler up. (see V4L HowTo) */
1219 if (V4L2_SUPPORT == 1)
1222 for (capture->bufferIndex = 0;
1223 capture->bufferIndex < ((int)capture->req.count);
1224 ++capture->bufferIndex)
1227 struct v4l2_buffer buf;
1231 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1232 buf.memory = V4L2_MEMORY_MMAP;
1233 buf.index = (unsigned long)capture->bufferIndex;
1235 if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1236 perror ("VIDIOC_QBUF");
1241 /* enable the streaming */
1242 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1243 if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
1245 /* error enabling the stream */
1246 perror ("VIDIOC_STREAMON");
1250 #endif /* HAVE_CAMV4L2 */
1253 for (capture->bufferIndex = 0;
1254 capture->bufferIndex < (capture->memoryBuffer.frames-1);
1255 ++capture->bufferIndex) {
1257 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1258 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1259 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1260 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1262 if (ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1263 fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1270 /* preparation is ok */
1271 capture->FirstCapture = 0;
1276 if (V4L2_SUPPORT == 1)
1279 mainloop_v4l2(capture);
1282 #endif /* HAVE_CAMV4L2 */
1285 capture->mmaps[capture->bufferIndex].frame = capture->bufferIndex;
1286 capture->mmaps[capture->bufferIndex].width = capture->captureWindow.width;
1287 capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1288 capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1290 if (ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1291 &capture->mmaps[capture->bufferIndex]) == -1) {
1292 /* capture is on the way, so just exit */
1296 ++capture->bufferIndex;
1297 if (capture->bufferIndex == capture->memoryBuffer.frames) {
1298 capture->bufferIndex = 0;
1307 * Turn a YUV4:2:0 block into an RGB block
1309 * Video4Linux seems to use the blue, green, red channel
1310 * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
1312 * Color space conversion coefficients taken from the excellent
1313 * http://www.inforamp.net/~poynton/ColorFAQ.html
1314 * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
1315 * Y values are given for all 4 pixels, but the U (Pb)
1316 * and V (Pr) are assumed constant over the 2x2 block.
1318 * To avoid floating point arithmetic, the color conversion
1319 * coefficients are scaled into 16.16 fixed-point integers.
1320 * They were determined as follows:
1322 * double brightness = 1.0; (0->black; 1->full scale)
1323 * double saturation = 1.0; (0->greyscale; 1->full color)
1324 * double fixScale = brightness * 256 * 256;
1325 * int rvScale = (int)(1.402 * saturation * fixScale);
1326 * int guScale = (int)(-0.344136 * saturation * fixScale);
1327 * int gvScale = (int)(-0.714136 * saturation * fixScale);
1328 * int buScale = (int)(1.772 * saturation * fixScale);
1329 * int yScale = (int)(fixScale);
1332 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
1333 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
1336 move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1337 int rowPixels, unsigned char * rgb)
1339 const int rvScale = 91881;
1340 const int guScale = -22553;
1341 const int gvScale = -46801;
1342 const int buScale = 116129;
1343 const int yScale = 65536;
1346 g = guScale * u + gvScale * v;
1355 yTL *= yScale; yTR *= yScale;
1356 yBL *= yScale; yBR *= yScale;
1358 /* Write out top two pixels */
1359 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1360 rgb[2] = LIMIT(r+yTL);
1362 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1363 rgb[5] = LIMIT(r+yTR);
1365 /* Skip down to next line to write out bottom two pixels */
1366 rgb += 3 * rowPixels;
1367 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1368 rgb[2] = LIMIT(r+yBL);
1370 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1371 rgb[5] = LIMIT(r+yBR);
1375 move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1376 int rowPixels, unsigned char * rgb)
1378 const int rvScale = 91881;
1379 const int guScale = -22553;
1380 const int gvScale = -46801;
1381 const int buScale = 116129;
1382 const int yScale = 65536;
1385 g = guScale * u + gvScale * v;
1394 yTL *= yScale; yTR *= yScale;
1395 yBL *= yScale; yBR *= yScale;
1397 /* Write out top two first pixels */
1398 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1399 rgb[2] = LIMIT(r+yTL);
1401 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1402 rgb[5] = LIMIT(r+yTR);
1404 /* Write out top two last pixels */
1406 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1407 rgb[2] = LIMIT(r+yBL);
1409 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1410 rgb[5] = LIMIT(r+yBR);
1413 // Consider a YUV420P image of 8x2 pixels.
1415 // A plane of Y values A B C D E F G H
1418 // A plane of U values 1 2 3 4
1419 // A plane of V values 1 2 3 4 ....
1421 // The U1/V1 samples correspond to the ABIJ pixels.
1422 // U2/V2 samples correspond to the CDKL pixels.
1424 /* Converts from planar YUV420P to RGB24. */
1426 yuv420p_to_rgb24(int width, int height,
1427 unsigned char *pIn0, unsigned char *pOut0)
1429 const int numpix = width * height;
1430 const int bytes = 24 >> 3;
1431 int i, j, y00, y01, y10, y11, u, v;
1432 unsigned char *pY = pIn0;
1433 unsigned char *pU = pY + numpix;
1434 unsigned char *pV = pU + numpix / 4;
1435 unsigned char *pOut = pOut0;
1437 for (j = 0; j <= height - 2; j += 2) {
1438 for (i = 0; i <= width - 2; i += 2) {
1441 y10 = *(pY + width);
1442 y11 = *(pY + width + 1);
1446 move_420_block(y00, y01, y10, y11, u, v,
1454 pOut += width * bytes;
1458 // Consider a YUV420 image of 6x2 pixels.
1463 // The U1/V1 samples correspond to the ABIJ pixels.
1464 // U2/V2 samples correspond to the CDKL pixels.
1466 /* Converts from interlaced YUV420 to RGB24. */
1467 /* [FD] untested... */
1469 yuv420_to_rgb24(int width, int height,
1470 unsigned char *pIn0, unsigned char *pOut0)
1472 const int bytes = 24 >> 3;
1473 int i, j, y00, y01, y10, y11, u, v;
1474 unsigned char *pY = pIn0;
1475 unsigned char *pU = pY + 4;
1476 unsigned char *pV = pU + width;
1477 unsigned char *pOut = pOut0;
1479 for (j = 0; j <= height - 2; j += 2) {
1480 for (i = 0; i <= width - 4; i += 4) {
1483 y10 = *(pY + width);
1484 y11 = *(pY + width + 1);
1488 move_420_block(y00, y01, y10, y11, u, v,
1496 y10 = *(pY + width);
1497 y11 = *(pY + width + 1);
1501 move_420_block(y00, y01, y10, y11, u, v,
1509 pOut += width * bytes;
1513 // Consider a YUV411P image of 8x2 pixels.
1515 // A plane of Y values as before.
1517 // A plane of U values 1 2
1520 // A plane of V values 1 2
1523 // The U1/V1 samples correspond to the ABCD pixels.
1524 // U2/V2 samples correspond to the EFGH pixels.
1526 /* Converts from planar YUV411P to RGB24. */
1527 /* [FD] untested... */
1529 yuv411p_to_rgb24(int width, int height,
1530 unsigned char *pIn0, unsigned char *pOut0)
1532 const int numpix = width * height;
1533 const int bytes = 24 >> 3;
1534 int i, j, y00, y01, y10, y11, u, v;
1535 unsigned char *pY = pIn0;
1536 unsigned char *pU = pY + numpix;
1537 unsigned char *pV = pU + numpix / 4;
1538 unsigned char *pOut = pOut0;
1540 for (j = 0; j <= height; j++) {
1541 for (i = 0; i <= width - 4; i += 4) {
1549 move_411_block(y00, y01, y10, y11, u, v,
1559 /* convert from 4:2:2 YUYV interlaced to RGB24 */
1560 /* based on ccvt_yuyv_bgr32() from camstream */
1562 if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
1564 yuyv_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1569 int r, g, b, cr, cg, cb, y1, y2;
1578 cb = ((*s - 128) * 454) >> 8;
1579 cg = (*s++ - 128) * 88;
1581 cr = ((*s - 128) * 359) >> 8;
1582 cg = (cg + (*s++ - 128) * 183) >> 8;
1610 uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1615 int r, g, b, cr, cg, cb, y1, y2;
1623 cb = ((*s - 128) * 454) >> 8;
1624 cg = (*s++ - 128) * 88;
1626 cr = ((*s - 128) * 359) >> 8;
1627 cg = (cg + (*s++ - 128) * 183) >> 8;
1657 /* support for MJPEG is only available with libjpeg and gcc,
1658 because it's use libjepg and fmemopen()
1661 /* include headers to be able to use libjpeg and GrFmtJpegReader */
1664 #include "jpeglib.h"
1667 /* define a new class for using fmemopen() instead of fopen() */
1668 class MyMJpegReader : public GrFmtJpegReader {
1670 MyMJpegReader (unsigned char *src, size_t src_size);
1673 unsigned char *my_src;
1677 /////////////////////// Error processing /////////////////////
1679 typedef struct GrFmtJpegErrorMgr
1681 struct jpeg_error_mgr pub; /* "parent" structure */
1682 jmp_buf setjmp_buffer; /* jump label */
1688 error_exit( j_common_ptr cinfo )
1690 GrFmtJpegErrorMgr* err_mgr = (GrFmtJpegErrorMgr*)(cinfo->err);
1692 /* Return control to the setjmp point */
1693 longjmp( err_mgr->setjmp_buffer, 1 );
1696 /////////////////////// MyMJpegReader ///////////////////
1698 /* constructor just call the parent constructor, but without real filename */
1699 MyMJpegReader::MyMJpegReader (unsigned char *src, size_t src_size)
1700 : GrFmtJpegReader ("/dev/null") {
1701 /* memorize the given src memory area, with it's size */
1703 my_src_size = src_size;
1707 MyMJpegReader::ReadHeader is almost like GrFmtJpegReader::ReadHeader,
1708 just use fmemopen() instead of fopen()
1710 bool MyMJpegReader::ReadHeader () {
1711 bool result = false;
1714 jpeg_decompress_struct* cinfo = new jpeg_decompress_struct;
1715 GrFmtJpegErrorMgr* jerr = new GrFmtJpegErrorMgr;
1717 cinfo->err = jpeg_std_error(&jerr->pub);
1718 jerr->pub.error_exit = error_exit;
1723 if( setjmp( jerr->setjmp_buffer ) == 0 )
1725 jpeg_create_decompress( cinfo );
1727 m_f = fmemopen( my_src, my_src_size, "rb" );
1730 jpeg_stdio_src( cinfo, m_f );
1731 jpeg_read_header( cinfo, TRUE );
1733 m_width = cinfo->image_width;
1734 m_height = cinfo->image_height;
1735 m_iscolor = cinfo->num_components > 1;
1747 /* convert from mjpeg to rgb24 */
1749 mjpeg_to_rgb24 (int width, int height,
1750 unsigned char *src, int length,
1753 /* use a MyMJpegReader reader for doing the conversion */
1754 MyMJpegReader* reader = 0;
1755 reader = new MyMJpegReader (src, length);
1756 reader->ReadHeader ();
1757 reader->ReadData (dst, width * 3, 1 );
1766 * BAYER2RGB24 ROUTINE TAKEN FROM:
1768 * Sonix SN9C10x based webcam basic I/F routines
1769 * Takafumi Mizuno <taka-qce@ls-a.jp>
1773 void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1776 unsigned char *rawpt, *scanpt;
1781 size = WIDTH*HEIGHT;
1783 for ( i = 0; i < size; i++ ) {
1784 if ( (i/WIDTH) % 2 == 0 ) {
1785 if ( (i % 2) == 0 ) {
1787 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
1788 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1789 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
1790 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1791 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
1792 *scanpt++ = *rawpt; /* B */
1794 /* first line or left column */
1795 *scanpt++ = *(rawpt+WIDTH+1); /* R */
1796 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
1797 *scanpt++ = *rawpt; /* B */
1801 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
1802 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
1803 *scanpt++ = *rawpt; /* G */
1804 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1806 /* first line or right column */
1807 *scanpt++ = *(rawpt+WIDTH); /* R */
1808 *scanpt++ = *rawpt; /* G */
1809 *scanpt++ = *(rawpt-1); /* B */
1813 if ( (i % 2) == 0 ) {
1815 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
1816 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
1817 *scanpt++ = *rawpt; /* G */
1818 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
1820 /* bottom line or left column */
1821 *scanpt++ = *(rawpt+1); /* R */
1822 *scanpt++ = *rawpt; /* G */
1823 *scanpt++ = *(rawpt-WIDTH); /* B */
1827 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
1828 *scanpt++ = *rawpt; /* R */
1829 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1830 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1831 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1832 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
1834 /* bottom line or right column */
1835 *scanpt++ = *rawpt; /* R */
1836 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
1837 *scanpt++ = *(rawpt-WIDTH-1); /* B */
1847 #define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
1857 static code_table_t table[256];
1858 static int init_done = 0;
1862 sonix_decompress_init
1863 =====================
1864 pre-calculates a locally stored table for efficient huffman-decoding.
1866 Each entry at index x in the table represents the codeword
1867 present at the MSB of byte x.
1870 void sonix_decompress_init(void)
1873 int is_abs, val, len;
1875 for (i = 0; i < 256; i++) {
1879 if ((i & 0x80) == 0) {
1884 else if ((i & 0xE0) == 0x80) {
1889 else if ((i & 0xE0) == 0xA0) {
1894 else if ((i & 0xF0) == 0xD0) {
1899 else if ((i & 0xF0) == 0xF0) {
1904 else if ((i & 0xF8) == 0xC8) {
1909 else if ((i & 0xFC) == 0xC0) {
1914 else if ((i & 0xFC) == 0xC4) {
1915 /* code 110001xx: unknown */
1919 else if ((i & 0xF0) == 0xE0) {
1922 val = (i & 0x0F) << 4;
1925 table[i].is_abs = is_abs;
1937 decompresses an image encoded by a SN9C101 camera controller chip.
1941 inp pointer to compressed frame (with header already stripped)
1942 OUT outp pointer to decompressed frame
1944 Returns 0 if the operation was successful.
1945 Returns <0 if operation failed.
1948 int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
1954 unsigned char *addr;
1957 /* do sonix_decompress_init first! */
1962 for (row = 0; row < height; row++) {
1968 /* first two pixels in first two rows are stored as raw 8-bit */
1970 addr = inp + (bitpos >> 3);
1971 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1975 addr = inp + (bitpos >> 3);
1976 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1983 while (col < width) {
1984 /* get bitcode from bitstream */
1985 addr = inp + (bitpos >> 3);
1986 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1988 /* update bit position */
1989 bitpos += table[code].len;
1991 /* calculate pixel value */
1992 val = table[code].val;
1993 if (!table[code].is_abs) {
1994 /* value is relative to top and left pixel */
1996 /* left column: relative to top pixel */
1997 val += outp[-2*width];
2000 /* top row: relative to left pixel */
2004 /* main area: average of left pixel and top pixel */
2005 val += (outp[-2] + outp[-2*width]) / 2;
2010 *outp++ = CLAMP(val);
2019 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture) {
2022 if (V4L2_SUPPORT == 0)
2023 #endif /* HAVE_CAMV4L2 */
2026 /* [FD] this really belongs here */
2027 if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex]) == -1) {
2028 fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
2033 /* Now get what has already been captured as a IplImage return */
2035 /* First, reallocate imageData if the frame sized changed */
2039 if (V4L2_SUPPORT == 1)
2042 if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
2043 || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
2044 cvFree(&capture->frame.imageData);
2045 cvInitImageHeader( &capture->frame,
2046 cvSize( capture->form.fmt.pix.width,
2047 capture->form.fmt.pix.height ),
2048 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2049 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2053 #endif /* HAVE_CAMV4L2 */
2056 if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
2057 || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
2058 cvFree(&capture->frame.imageData);
2059 cvInitImageHeader( &capture->frame,
2060 cvSize( capture->captureWindow.width,
2061 capture->captureWindow.height ),
2062 IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2063 capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2070 if (V4L2_SUPPORT == 1)
2073 if (PALETTE_BGR24 == 1)
2074 memcpy((char *)capture->frame.imageData,
2075 (char *)capture->buffers[capture->bufferIndex].start,
2076 capture->frame.imageSize);
2078 if (PALETTE_YVU420 == 1)
2079 yuv420p_to_rgb24(capture->form.fmt.pix.width,
2080 capture->form.fmt.pix.height,
2081 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2082 (unsigned char*)capture->frame.imageData);
2084 if (PALETTE_YUV411P == 1)
2085 yuv411p_to_rgb24(capture->form.fmt.pix.width,
2086 capture->form.fmt.pix.height,
2087 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2088 (unsigned char*)capture->frame.imageData);
2092 /* support for MJPEG is only available with libjpeg and gcc,
2093 because it's use libjepg and fmemopen()
2095 if (PALETTE_MJPEG == 1)
2096 mjpeg_to_rgb24(capture->form.fmt.pix.width,
2097 capture->form.fmt.pix.height,
2098 (unsigned char*)(capture->buffers[capture->bufferIndex]
2100 capture->buffers[capture->bufferIndex].length,
2101 (unsigned char*)capture->frame.imageData);
2105 if (PALETTE_YUYV == 1)
2106 yuyv_to_rgb24(capture->form.fmt.pix.width,
2107 capture->form.fmt.pix.height,
2108 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2109 (unsigned char*)capture->frame.imageData);
2111 if (PALETTE_UYVY == 1)
2112 uyvy_to_rgb24(capture->form.fmt.pix.width,
2113 capture->form.fmt.pix.height,
2114 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2115 (unsigned char*)capture->frame.imageData);
2117 if (PALETTE_SBGGR8 == 1)
2119 bayer2rgb24(capture->form.fmt.pix.width,
2120 capture->form.fmt.pix.height,
2121 (unsigned char*)capture->buffers[capture->bufferIndex].start,
2122 (unsigned char*)capture->frame.imageData);
2125 if (PALETTE_SN9C10X == 1)
2127 sonix_decompress_init();
2129 sonix_decompress(capture->form.fmt.pix.width,
2130 capture->form.fmt.pix.height,
2131 (unsigned char*)capture->buffers[capture->bufferIndex].start,
2132 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start);
2134 bayer2rgb24(capture->form.fmt.pix.width,
2135 capture->form.fmt.pix.height,
2136 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
2137 (unsigned char*)capture->frame.imageData);
2141 #endif /* HAVE_CAMV4L2 */
2144 switch(capture->imageProperties.palette) {
2145 case VIDEO_PALETTE_RGB24:
2146 memcpy((char *)capture->frame.imageData,
2147 (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2148 capture->frame.imageSize);
2150 case VIDEO_PALETTE_YUV420P:
2151 yuv420p_to_rgb24(capture->captureWindow.width,
2152 capture->captureWindow.height,
2153 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2154 (unsigned char*)capture->frame.imageData);
2156 case VIDEO_PALETTE_YUV420:
2157 yuv420_to_rgb24(capture->captureWindow.width,
2158 capture->captureWindow.height,
2159 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2160 (unsigned char*)capture->frame.imageData);
2162 case VIDEO_PALETTE_YUV411P:
2163 yuv411p_to_rgb24(capture->captureWindow.width,
2164 capture->captureWindow.height,
2165 (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2166 (unsigned char*)capture->frame.imageData);
2170 "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n",
2171 capture->imageProperties.palette);
2178 return(&capture->frame);
2181 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
2186 if (V4L2_SUPPORT == 1)
2189 /* default value for min and max */
2193 CLEAR (capture->form);
2194 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2195 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
2196 /* display an error message, and return an error code */
2197 perror ("VIDIOC_G_FMT");
2201 switch (property_id) {
2202 case CV_CAP_PROP_FRAME_WIDTH:
2203 return capture->form.fmt.pix.width;
2204 case CV_CAP_PROP_FRAME_HEIGHT:
2205 return capture->form.fmt.pix.height;
2208 /* initialize the control structure */
2210 switch (property_id) {
2211 case CV_CAP_PROP_BRIGHTNESS:
2212 capture->control.id = V4L2_CID_BRIGHTNESS;
2214 case CV_CAP_PROP_CONTRAST:
2215 capture->control.id = V4L2_CID_CONTRAST;
2217 case CV_CAP_PROP_SATURATION:
2218 capture->control.id = V4L2_CID_SATURATION;
2220 case CV_CAP_PROP_HUE:
2221 capture->control.id = V4L2_CID_HUE;
2223 case CV_CAP_PROP_GAIN:
2224 capture->control.id = V4L2_CID_GAIN;
2228 "HIGHGUI ERROR: V4L2: getting property #%d is not supported\n",
2233 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_CTRL,
2234 &capture->control)) {
2236 fprintf( stderr, "HIGHGUI ERROR: V4L2: ");
2237 switch (property_id) {
2238 case CV_CAP_PROP_BRIGHTNESS:
2239 fprintf (stderr, "Brightness");
2241 case CV_CAP_PROP_CONTRAST:
2242 fprintf (stderr, "Contrast");
2244 case CV_CAP_PROP_SATURATION:
2245 fprintf (stderr, "Saturation");
2247 case CV_CAP_PROP_HUE:
2248 fprintf (stderr, "Hue");
2250 case CV_CAP_PROP_GAIN:
2251 fprintf (stderr, "Gain");
2254 fprintf (stderr, " is not supported by your device\n");
2259 /* get the min/max values */
2260 switch (property_id) {
2262 case CV_CAP_PROP_BRIGHTNESS:
2263 v4l2_min = capture->v4l2_brightness_min;
2264 v4l2_max = capture->v4l2_brightness_max;
2266 case CV_CAP_PROP_CONTRAST:
2267 v4l2_min = capture->v4l2_contrast_min;
2268 v4l2_max = capture->v4l2_contrast_max;
2270 case CV_CAP_PROP_SATURATION:
2271 v4l2_min = capture->v4l2_saturation_min;
2272 v4l2_max = capture->v4l2_saturation_max;
2274 case CV_CAP_PROP_HUE:
2275 v4l2_min = capture->v4l2_hue_min;
2276 v4l2_max = capture->v4l2_hue_max;
2278 case CV_CAP_PROP_GAIN:
2279 v4l2_min = capture->v4l2_gain_min;
2280 v4l2_max = capture->v4l2_gain_max;
2284 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2285 return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min);
2288 #endif /* HAVE_CAMV4L2 */
2293 if (ioctl (capture->deviceHandle,
2294 VIDIOCGWIN, &capture->captureWindow) < 0) {
2296 "HIGHGUI ERROR: V4L: "
2297 "Unable to determine size of incoming image\n");
2298 icvCloseCAM_V4L(capture);
2302 switch (property_id) {
2303 case CV_CAP_PROP_FRAME_WIDTH:
2304 retval = capture->captureWindow.width;
2306 case CV_CAP_PROP_FRAME_HEIGHT:
2307 retval = capture->captureWindow.height;
2309 case CV_CAP_PROP_BRIGHTNESS:
2310 retval = capture->imageProperties.brightness;
2312 case CV_CAP_PROP_CONTRAST:
2313 retval = capture->imageProperties.contrast;
2315 case CV_CAP_PROP_SATURATION:
2316 retval = capture->imageProperties.colour;
2318 case CV_CAP_PROP_HUE:
2319 retval = capture->imageProperties.hue;
2321 case CV_CAP_PROP_GAIN:
2323 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
2328 "HIGHGUI ERROR: V4L: getting property #%d is not supported\n",
2333 /* there was a problem */
2337 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2338 return float (retval) / 0xFFFF;
2344 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
2348 if (V4L2_SUPPORT == 1)
2351 CLEAR (capture->crop);
2352 capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2353 capture->crop.c.left = 0;
2354 capture->crop.c.top = 0;
2355 capture->crop.c.height = h*24;
2356 capture->crop.c.width = w*24;
2358 /* set the crop area, but don't exit if the device don't support croping */
2359 xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
2361 CLEAR (capture->form);
2362 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2364 /* read the current setting, mainly to retreive the pixelformat information */
2365 xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
2367 /* set the values we want to change */
2368 capture->form.fmt.pix.width = w;
2369 capture->form.fmt.pix.height = h;
2370 capture->form.fmt.win.chromakey = 0;
2371 capture->form.fmt.win.field = V4L2_FIELD_ANY;
2372 capture->form.fmt.win.clips = 0;
2373 capture->form.fmt.win.clipcount = 0;
2374 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
2376 /* ask the device to change the size
2377 * don't test if the set of the size is ok, because some device
2378 * don't allow changing the size, and we will get the real size
2380 xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
2382 /* try to set framerate to 30 fps */
2383 struct v4l2_streamparm setfps;
2384 memset (&setfps, 0, sizeof(struct v4l2_streamparm));
2385 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2386 setfps.parm.capture.timeperframe.numerator = 1;
2387 setfps.parm.capture.timeperframe.denominator = 30;
2388 xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
2390 /* we need to re-initialize some things, like buffers, because the size has
2392 capture->FirstCapture = 1;
2394 /* Get window info again, to get the real value */
2395 if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
2397 fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
2399 icvCloseCAM_V4L(capture);
2407 #endif /* HAVE_CAMV4L2 */
2410 if (capture==0) return 0;
2411 if (w>capture->capability.maxwidth) {
2412 w=capture->capability.maxwidth;
2414 if (h>capture->capability.maxheight) {
2415 h=capture->capability.maxheight;
2418 capture->captureWindow.width=w;
2419 capture->captureWindow.height=h;
2421 if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
2422 icvCloseCAM_V4L(capture);
2426 if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
2427 icvCloseCAM_V4L(capture);
2431 capture->FirstCapture = 1;
2439 static int icvSetControl (CvCaptureCAM_V4L* capture,
2440 int property_id, double value) {
2442 /* limitation of the input value */
2445 } else if (value > 1.0) {
2451 if (V4L2_SUPPORT == 1)
2454 /* default value for min and max */
2458 /* initialisations */
2459 CLEAR (capture->control);
2461 /* set which control we want to set */
2462 switch (property_id) {
2464 case CV_CAP_PROP_BRIGHTNESS:
2465 capture->control.id = V4L2_CID_BRIGHTNESS;
2467 case CV_CAP_PROP_CONTRAST:
2468 capture->control.id = V4L2_CID_CONTRAST;
2470 case CV_CAP_PROP_SATURATION:
2471 capture->control.id = V4L2_CID_SATURATION;
2473 case CV_CAP_PROP_HUE:
2474 capture->control.id = V4L2_CID_HUE;
2476 case CV_CAP_PROP_GAIN:
2477 capture->control.id = V4L2_CID_GAIN;
2481 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
2486 /* get the min and max values */
2487 if (-1 == xioctl (capture->deviceHandle,
2488 VIDIOC_G_CTRL, &capture->control)) {
2489 // perror ("VIDIOC_G_CTRL for getting min/max values");
2493 /* get the min/max values */
2494 switch (property_id) {
2496 case CV_CAP_PROP_BRIGHTNESS:
2497 v4l2_min = capture->v4l2_brightness_min;
2498 v4l2_max = capture->v4l2_brightness_max;
2500 case CV_CAP_PROP_CONTRAST:
2501 v4l2_min = capture->v4l2_contrast_min;
2502 v4l2_max = capture->v4l2_contrast_max;
2504 case CV_CAP_PROP_SATURATION:
2505 v4l2_min = capture->v4l2_saturation_min;
2506 v4l2_max = capture->v4l2_saturation_max;
2508 case CV_CAP_PROP_HUE:
2509 v4l2_min = capture->v4l2_hue_min;
2510 v4l2_max = capture->v4l2_hue_max;
2512 case CV_CAP_PROP_GAIN:
2513 v4l2_min = capture->v4l2_gain_min;
2514 v4l2_max = capture->v4l2_gain_max;
2518 /* initialisations */
2519 CLEAR (capture->control);
2521 /* set which control we want to set */
2522 switch (property_id) {
2524 case CV_CAP_PROP_BRIGHTNESS:
2525 capture->control.id = V4L2_CID_BRIGHTNESS;
2527 case CV_CAP_PROP_CONTRAST:
2528 capture->control.id = V4L2_CID_CONTRAST;
2530 case CV_CAP_PROP_SATURATION:
2531 capture->control.id = V4L2_CID_SATURATION;
2533 case CV_CAP_PROP_HUE:
2534 capture->control.id = V4L2_CID_HUE;
2536 case CV_CAP_PROP_GAIN:
2537 capture->control.id = V4L2_CID_GAIN;
2541 "HIGHGUI ERROR: V4L2: setting property #%d is not supported\n",
2546 /* set the value we want to set to the scaled the value */
2547 capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min);
2549 /* The driver may clamp the value or return ERANGE, ignored here */
2550 if (-1 == xioctl (capture->deviceHandle,
2551 VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) {
2552 perror ("VIDIOC_S_CTRL");
2556 #endif /* HAVE_CAMV4L2 */
2561 /* scale the value to the wanted integer one */
2562 v4l_value = (int)(0xFFFF * value);
2564 switch (property_id) {
2565 case CV_CAP_PROP_BRIGHTNESS:
2566 capture->imageProperties.brightness = v4l_value;
2568 case CV_CAP_PROP_CONTRAST:
2569 capture->imageProperties.contrast = v4l_value;
2571 case CV_CAP_PROP_SATURATION:
2572 capture->imageProperties.colour = v4l_value;
2574 case CV_CAP_PROP_HUE:
2575 capture->imageProperties.hue = v4l_value;
2577 case CV_CAP_PROP_GAIN:
2579 "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
2583 "HIGHGUI ERROR: V4L: property #%d is not supported\n",
2588 if (ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties)
2592 "HIGHGUI ERROR: V4L: Unable to set video informations\n");
2593 icvCloseCAM_V4L(capture);
2603 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
2604 int property_id, double value ){
2605 static int width = 0, height = 0;
2608 /* initialization */
2611 /* two subsequent calls setting WIDTH and HEIGHT will change
2613 /* the first one will return an error, though. */
2615 switch (property_id) {
2616 case CV_CAP_PROP_FRAME_WIDTH:
2617 width = cvRound(value);
2618 if(width !=0 && height != 0) {
2619 retval = icvSetVideoSize( capture, width, height);
2623 case CV_CAP_PROP_FRAME_HEIGHT:
2624 height = cvRound(value);
2625 if(width !=0 && height != 0) {
2626 retval = icvSetVideoSize( capture, width, height);
2630 case CV_CAP_PROP_BRIGHTNESS:
2631 case CV_CAP_PROP_CONTRAST:
2632 case CV_CAP_PROP_SATURATION:
2633 case CV_CAP_PROP_HUE:
2634 case CV_CAP_PROP_GAIN:
2635 retval = icvSetControl(capture, property_id, value);
2639 "HIGHGUI ERROR: V4L: setting property #%d is not supported\n",
2643 /* return the the status */
2647 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
2648 /* Deallocate space - Hopefully, no leaks */
2654 if (V4L2_SUPPORT == 0)
2655 #endif /* HAVE_CAMV4L2 */
2659 free(capture->mmaps);
2660 if (capture->memoryMap)
2661 munmap(capture->memoryMap, capture->memoryBuffer.size);
2667 for (unsigned int n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
2669 if (-1 == munmap (capture->buffers[n_buffers].start, capture->buffers[n_buffers].length)) {
2675 #endif /* HAVE_CAMV4L2 */
2677 if (capture->deviceHandle > 0) close(capture->deviceHandle);
2679 if (capture->frame.imageData) cvFree(&capture->frame.imageData);
2680 //cvFree((void **)capture);