1 /* This is the contributed code:
2 
3 File:             cvcap_v4l.cpp
4 Current Location: ../opencv-0.9.6/otherlibs/videoio
5 
6 Original Version: 2003-03-12  Magnus Lundin lundin@mlu.mine.nu
7 Original Comments:
8 
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
13 
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 your questions at answers.opencv.org,
18               Report bugs at code.opencv.org,
19               Submit your fixes at https://github.com/Itseez/opencv/
20 Patched Comments:
21 
22 TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
23 were not working.  I have rewritten them so they work for me. At the same time, trying
24 to keep the original code as ML wrote it as unchanged as possible.  No one likes to debug
25 someone elses code, so I resisted changes as much as possible.  I have tried to keep the
26 same "ideas" where applicable, that is, where I could figure out what the previous author
27 intended. Some areas I just could not help myself and had to "spiffy-it-up" my way.
28 
29 These drivers should work with other V4L frame capture cards other then my bttv
30 driven frame capture card.
31 
32 Re Written driver for standard V4L mode. Tested using LMLBT44 video capture card.
33 Standard bttv drivers are on the LMLBT44 with up to 8 Inputs.
34 
35 This utility was written with the help of the document:
36 http://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo
37 as a general guide for interfacing into the V4l standard.
38 
39 Made the index value passed for icvOpenCAM_V4L(index) be the number of the
40 video device source in the /dev tree. The -1 uses original /dev/video.
41 
42 Index  Device
43   0    /dev/video0
44   1    /dev/video1
45   2    /dev/video2
46   3    /dev/video3
47   ...
48   7    /dev/video7
49 with
50   -1   /dev/video
51 
52 TW: You can select any video source, but this package was limited from the start to only
53 ONE camera opened at any ONE time.
54 This is an original program limitation.
55 If you are interested, I will make my version available to other OpenCV users.  The big
56 difference in mine is you may pass the camera number as part of the cv argument, but this
57 convention is non standard for current OpenCV calls and the camera number is not currently
58 passed into the called routine.
59 
60 Second Patch:   August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
61 For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
62 
63 FS: this patch fix not sequential index of device (unplugged device), and real numCameras.
64     for -1 index (icvOpenCAM_V4L) i dont use /dev/video but real device available, because
65     if /dev/video is a link to /dev/video0 and i unplugged device on /dev/video0, /dev/video
66     is a bad link. I search the first available device with indexList.
67 
68 Third Patch:   December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
69 For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
70 
71 [FD] I modified the following:
72  - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point
73  - cvGrabFrame should not wait for the end of the first frame, and should return quickly
74    (see videoio doc)
75  - cvRetrieveFrame should in turn wait for the end of frame capture, and should not
76    trigger the capture of the next frame (the user choses when to do it using GrabFrame)
77    To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame.
78  - having global bufferIndex and FirstCapture variables makes the code non-reentrant
79  (e.g. when using several cameras), put these in the CvCapture struct.
80  - according to V4L HowTo, incrementing the buffer index must be done before VIDIOCMCAPTURE.
81  - the VID_TYPE_SCALES stuff from V4L HowTo is wrong: image size can be changed
82    even if the hardware does not support scaling (e.g. webcams can have several
83    resolutions available). Just don't try to set the size at 640x480 if the hardware supports
84    scaling: open with the default (probably best) image size, and let the user scale it
85    using SetProperty.
86  - image size can be changed by two subsequent calls to SetProperty (for width and height)
87  - bug fix: if the image size changes, realloc the new image only when it is grabbed
88  - issue errors only when necessary, fix error message formatting.
89 
90 Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
91 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
92 
93 I modified the following:
94   - Additional Video4Linux2 support :)
95   - Use mmap functions (v4l2)
96   - New methods are internal:
97     try_palette_v4l2 -> rewrite try_palette for v4l2
98     mainloop_v4l2, read_image_v4l2 -> this methods are moved from official v4l2 capture.c example
99     try_init_v4l -> device v4l initialisation
100     try_init_v4l2 -> device v4l2 initialisation
101     autosetup_capture_mode_v4l -> autodetect capture modes for v4l
102     autosetup_capture_mode_v4l2 -> autodetect capture modes for v4l2
103   - Modifications are according with Video4Linux old codes
104   - Video4Linux handling is automatically if it does not recognize a Video4Linux2 device
105   - Tested successfully with Logitech Quickcam Express (V4L), Creative Vista (V4L) and Genius VideoCam Notebook (V4L2)
106   - Correct source lines with compiler warning messages
107   - Information message from v4l/v4l2 detection
108 
109 Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
110 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
111 
112 I modified the following:
113   - SN9C10x chip based webcams support
114   - New methods are internal:
115     bayer2rgb24, sonix_decompress -> decoder routines for SN9C10x decoding from Takafumi Mizuno <taka-qce@ls-a.jp> with his pleasure :)
116   - Tested successfully with Genius VideoCam Notebook (V4L2)
117 
118 Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
119 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
120 
121 I added the following:
122   - Add capture control support (hue, saturation, brightness, contrast, gain)
123   - Get and change V4L capture controls (hue, saturation, brightness, contrast)
124   - New method is internal:
125     icvSetControl -> set capture controls
126   - Tested successfully with Creative Vista (V4L)
127 
128 Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
129 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
130 
131 I added the following:
132   - Detect, get and change V4L2 capture controls (hue, saturation, brightness, contrast, gain)
133   - New methods are internal:
134     v4l2_scan_controls_enumerate_menu, v4l2_scan_controls -> detect capture control intervals
135   - Tested successfully with Genius VideoCam Notebook (V4L2)
136 
137 8th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch
138 Add support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG.
139 With this patch, new webcams of Logitech, like QuickCam Fusion works.
140 Note: For use these webcams, look at the UVC driver at
141 http://linux-uvc.berlios.de/
142 
143 9th patch: Mar 4, 2006, Olivier.Bornet@idiap.ch
144 - try V4L2 before V4L, because some devices are V4L2 by default,
145   but they try to implement the V4L compatibility layer.
146   So, I think this is better to support V4L2 before V4L.
147 - better separation between V4L2 and V4L initialization. (this was needed to support
148   some drivers working, but not fully with V4L2. (so, we do not know when we
149   need to switch from V4L2 to V4L.
150 
151 10th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com
152 Fix reliability problems with high-resolution UVC cameras on linux
153 the symptoms were damaged image and 'Corrupt JPEG data: premature end of data segment' on stderr
154 - V4L_ABORT_BADJPEG detects JPEG warnings and turns them into errors, so bad images
155   could be filtered out
156 - USE_TEMP_BUFFER fixes the main problem (improper buffer management) and
157   prevents bad images in the first place
158 
159 11th patch: April 2, 2013, Forrest Reiling forrest.reiling@gmail.com
160 Added v4l2 support for getting capture property CV_CAP_PROP_POS_MSEC.
161 Returns the millisecond timestamp of the last frame grabbed or 0 if no frames have been grabbed
162 Used to successfully synchonize 2 Logitech C310 USB webcams to within 16 ms of one another
163 
164 
165 make & enjoy!
166 
167 */
168 
169 /*M///////////////////////////////////////////////////////////////////////////////////////
170 //
171 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
172 //
173 //  By downloading, copying, installing or using the software you agree to this license.
174 //  If you do not agree to this license, do not download, install,
175 //  copy or use the software.
176 //
177 //
178 //                        Intel License Agreement
179 //                For Open Source Computer Vision Library
180 //
181 // Copyright (C) 2000, Intel Corporation, all rights reserved.
182 // Third party copyrights are property of their respective owners.
183 //
184 // Redistribution and use in source and binary forms, with or without modification,
185 // are permitted provided that the following conditions are met:
186 //
187 //   * Redistribution's of source code must retain the above copyright notice,
188 //     this list of conditions and the following disclaimer.
189 //
190 //   * Redistribution's in binary form must reproduce the above copyright notice,
191 //     this list of conditions and the following disclaimer in the documentation
192 //     and/or other materials provided with the distribution.
193 //
194 //   * The name of Intel Corporation may not be used to endorse or promote products
195 //     derived from this software without specific prior written permission.
196 //
197 // This software is provided by the copyright holders and contributors "as is" and
198 // any express or implied warranties, including, but not limited to, the implied
199 // warranties of merchantability and fitness for a particular purpose are disclaimed.
200 // In no event shall the Intel Corporation or contributors be liable for any direct,
201 // indirect, incidental, special, exemplary, or consequential damages
202 // (including, but not limited to, procurement of substitute goods or services;
203 // loss of use, data, or profits; or business interruption) however caused
204 // and on any theory of liability, whether in contract, strict liability,
205 // or tort (including negligence or otherwise) arising in any way out of
206 // the use of this software, even if advised of the possibility of such damage.
207 //
208 //M*/
209 
210 #include "precomp.hpp"
211 
212 #if !defined WIN32 && (defined HAVE_CAMV4L || defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO)
213 
214 #define CLEAR(x) memset (&(x), 0, sizeof (x))
215 
216 #include <stdio.h>
217 #include <unistd.h>
218 #include <fcntl.h>
219 #include <errno.h>
220 #include <sys/ioctl.h>
221 #include <sys/types.h>
222 #include <sys/mman.h>
223 
224 #ifdef HAVE_CAMV4L
225 #include <linux/videodev.h>
226 #endif
227 
228 #include <string.h>
229 #include <stdlib.h>
230 #include <assert.h>
231 #include <sys/stat.h>
232 #include <sys/ioctl.h>
233 
234 #ifdef HAVE_CAMV4L2
235 #include <asm/types.h>          /* for videodev2.h */
236 #include <linux/videodev2.h>
237 #endif
238 
239 #ifdef HAVE_VIDEOIO
240 #include <sys/videoio.h>
241 #define HAVE_CAMV4L2
242 #endif
243 
244 /* Defaults - If your board can do better, set it here.  Set for the most common type inputs. */
245 #define DEFAULT_V4L_WIDTH  640
246 #define DEFAULT_V4L_HEIGHT 480
247 
248 #define CHANNEL_NUMBER 1
249 #define MAX_CAMERAS 8
250 
251 
252 // default and maximum number of V4L buffers, not including last, 'special' buffer
253 #define MAX_V4L_BUFFERS 10
254 #define DEFAULT_V4L_BUFFERS 4
255 
256 // if enabled, then bad JPEG warnings become errors and cause NULL returned instead of image
257 #define V4L_ABORT_BADJPEG
258 
259 #define MAX_DEVICE_DRIVER_NAME 80
260 
261 /* Device Capture Objects */
262 
263 #ifdef HAVE_CAMV4L2
264 
265 /* V4L2 structure */
266 struct buffer
267 {
268   void *  start;
269   size_t  length;
270 };
271 
272 static unsigned int n_buffers = 0;
273 
274 /* Additional V4L2 pixelformats support for Sonix SN9C10x base webcams */
275 #ifndef V4L2_PIX_FMT_SBGGR8
276 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */
277 #endif
278 #ifndef V4L2_PIX_FMT_SN9C10X
279 #define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S','9','1','0') /* SN9C10x cmpr. */
280 #endif
281 
282 #ifndef V4L2_PIX_FMT_SGBRG
283 #define V4L2_PIX_FMT_SGBRG v4l2_fourcc('G','B','R','G') /* bayer GBRG   GBGB.. RGRG.. */
284 #endif
285 
286 #endif  /* HAVE_CAMV4L2 */
287 
288 enum PALETTE_TYPE {
289   PALETTE_BGR24 = 1,
290   PALETTE_YVU420,
291   PALETTE_YUV411P,
292   PALETTE_YUYV,
293   PALETTE_UYVY,
294   PALETTE_SBGGR8,
295   PALETTE_SN9C10X,
296   PALETTE_MJPEG,
297   PALETTE_SGBRG,
298   PALETTE_RGB24
299 };
300 
301 typedef struct CvCaptureCAM_V4L
302 {
303     int deviceHandle;
304     int bufferIndex;
305     int FirstCapture;
306 #ifdef HAVE_CAMV4L
307     struct video_capability capability;
308     struct video_window     captureWindow;
309     struct video_picture    imageProperties;
310     struct video_mbuf       memoryBuffer;
311     struct video_mmap       *mmaps;
312 #endif /* HAVE_CAMV4L */
313     char *memoryMap;
314     IplImage frame;
315 
316 #ifdef HAVE_CAMV4L2
317    enum PALETTE_TYPE palette;
318    /* V4L2 variables */
319    buffer buffers[MAX_V4L_BUFFERS + 1];
320    struct v4l2_capability cap;
321    struct v4l2_input inp;
322    struct v4l2_format form;
323    struct v4l2_crop crop;
324    struct v4l2_cropcap cropcap;
325    struct v4l2_requestbuffers req;
326    struct v4l2_control control;
327    enum v4l2_buf_type type;
328    struct v4l2_queryctrl queryctrl;
329 
330    struct timeval timestamp;
331 
332    /* V4L2 control variables */
333    int v4l2_brightness, v4l2_brightness_min, v4l2_brightness_max;
334    int v4l2_contrast, v4l2_contrast_min, v4l2_contrast_max;
335    int v4l2_saturation, v4l2_saturation_min, v4l2_saturation_max;
336    int v4l2_hue, v4l2_hue_min, v4l2_hue_max;
337    int v4l2_gain, v4l2_gain_min, v4l2_gain_max;
338    int v4l2_exposure, v4l2_exposure_min, v4l2_exposure_max;
339 
340 #endif /* HAVE_CAMV4L2 */
341 
342 }
343 CvCaptureCAM_V4L;
344 
345 #ifdef HAVE_CAMV4L2
346 
347 int V4L2_SUPPORT = 0;
348 
349 #endif /* HAVE_CAMV4L2 */
350 
351 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
352 
353 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
354 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
355 
356 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
357 static int    icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
358 
359 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
360 
361 /***********************   Implementations  ***************************************/
362 
363 static int numCameras = 0;
364 static int indexList = 0;
365 
366 /* Simple test program: Find number of Video Sources available.
367    Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
368    If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
369    Returns the global numCameras with the correct value (we hope) */
370 
icvInitCapture_V4L()371 static void icvInitCapture_V4L() {
372    int deviceHandle;
373    int CameraNumber;
374    char deviceName[MAX_DEVICE_DRIVER_NAME];
375 
376    CameraNumber = 0;
377    while(CameraNumber < MAX_CAMERAS) {
378       /* Print the CameraNumber at the end of the string with a width of one character */
379       sprintf(deviceName, "/dev/video%1d", CameraNumber);
380       /* Test using an open to see if this new device name really does exists. */
381       deviceHandle = open(deviceName, O_RDONLY);
382       if (deviceHandle != -1) {
383          /* This device does indeed exist - add it to the total so far */
384     // add indexList
385     indexList|=(1 << CameraNumber);
386         numCameras++;
387     }
388     if (deviceHandle != -1)
389       close(deviceHandle);
390       /* Set up to test the next /dev/video source in line */
391       CameraNumber++;
392    } /* End while */
393 
394 }; /* End icvInitCapture_V4L */
395 
396 #ifdef HAVE_CAMV4L
397 
398 static int
try_palette(int fd,struct video_picture * cam_pic,int pal,int depth)399 try_palette(int fd,
400             struct video_picture *cam_pic,
401             int pal,
402             int depth)
403 {
404   cam_pic->palette = pal;
405   cam_pic->depth = depth;
406   if (ioctl(fd, VIDIOCSPICT, cam_pic) < 0)
407     return 0;
408   if (ioctl(fd, VIDIOCGPICT, cam_pic) < 0)
409     return 0;
410   if (cam_pic->palette == pal)
411     return 1;
412   return 0;
413 }
414 
415 #endif /* HAVE_CAMV4L */
416 
417 #ifdef HAVE_CAMV4L2
418 
try_palette_v4l2(CvCaptureCAM_V4L * capture,unsigned long colorspace)419 static int try_palette_v4l2(CvCaptureCAM_V4L* capture, unsigned long colorspace)
420 {
421   CLEAR (capture->form);
422 
423   capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
424   capture->form.fmt.pix.pixelformat = colorspace;
425   capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
426   capture->form.fmt.pix.width = DEFAULT_V4L_WIDTH;
427   capture->form.fmt.pix.height = DEFAULT_V4L_HEIGHT;
428 
429   if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
430       return -1;
431 
432 
433   if (colorspace != capture->form.fmt.pix.pixelformat)
434     return -1;
435   else
436     return 0;
437 }
438 
439 #endif /* HAVE_CAMV4L2 */
440 
441 #ifdef HAVE_CAMV4L
442 
try_init_v4l(CvCaptureCAM_V4L * capture,char * deviceName)443 static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
444 {
445 
446   // if detect = -1 then unable to open device
447   // if detect = 0 then detected nothing
448   // if detect = 1 then V4L device
449   int detect = 0;
450 
451 
452   // Test device for V4L compability
453 
454   /* Test using an open to see if this new device name really does exists. */
455   /* No matter what the name - it still must be opened! */
456   capture->deviceHandle = open(deviceName, O_RDWR);
457 
458   if (capture->deviceHandle == 0)
459   {
460     detect = -1;
461 
462     icvCloseCAM_V4L(capture);
463   }
464 
465   if (detect == 0)
466   {
467     /* Query the newly opened device for its capabilities */
468     if (ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
469     {
470       detect = 0;
471       icvCloseCAM_V4L(capture);
472     }
473       else
474     {
475       detect = 1;
476     }
477   }
478 
479   return detect;
480 
481 }
482 
483 #endif /* HAVE_CAMV4L */
484 
485 #ifdef HAVE_CAMV4L2
486 
try_init_v4l2(CvCaptureCAM_V4L * capture,char * deviceName)487 static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
488 {
489   // Test device for V4L2 compability
490   // Return value:
491   // -1 then unable to open device
492   //  0 then detected nothing
493   //  1 then V4L2 device
494 
495   int deviceIndex;
496 
497   /* Open and test V4L2 device */
498   capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
499   if (-1 == capture->deviceHandle)
500   {
501 #ifndef NDEBUG
502     fprintf(stderr, "(DEBUG) try_init_v4l2 open \"%s\": %s\n", deviceName, strerror(errno));
503 #endif
504     icvCloseCAM_V4L(capture);
505     return -1;
506   }
507 
508   CLEAR (capture->cap);
509   if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
510   {
511 #ifndef NDEBUG
512     fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_QUERYCAP \"%s\": %s\n", deviceName, strerror(errno));
513 #endif
514     icvCloseCAM_V4L(capture);
515     return 0;
516   }
517 
518   /* Query channels number */
519   if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_INPUT, &deviceIndex))
520   {
521 #ifndef NDEBUG
522     fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_G_INPUT \"%s\": %s\n", deviceName, strerror(errno));
523 #endif
524     icvCloseCAM_V4L(capture);
525     return 0;
526   }
527 
528   /* Query information about current input */
529   CLEAR (capture->inp);
530   capture->inp.index = deviceIndex;
531   if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
532   {
533 #ifndef NDEBUG
534     fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_ENUMINPUT \"%s\": %s\n", deviceName, strerror(errno));
535 #endif
536     icvCloseCAM_V4L(capture);
537     return 0;
538   }
539 
540   return 1;
541 
542 }
543 
autosetup_capture_mode_v4l2(CvCaptureCAM_V4L * capture)544 static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture)
545 {
546   if (try_palette_v4l2(capture, V4L2_PIX_FMT_BGR24) == 0)
547   {
548     capture->palette = PALETTE_BGR24;
549   }
550   else
551   if (try_palette_v4l2(capture, V4L2_PIX_FMT_YVU420) == 0)
552   {
553     capture->palette = PALETTE_YVU420;
554   }
555   else
556   if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUV411P) == 0)
557   {
558     capture->palette = PALETTE_YUV411P;
559   }
560   else
561 
562 #ifdef HAVE_JPEG
563   if (try_palette_v4l2(capture, V4L2_PIX_FMT_MJPEG) == 0 ||
564       try_palette_v4l2(capture, V4L2_PIX_FMT_JPEG) == 0)
565   {
566     capture->palette = PALETTE_MJPEG;
567   }
568   else
569 #endif
570 
571   if (try_palette_v4l2(capture, V4L2_PIX_FMT_YUYV) == 0)
572   {
573     capture->palette = PALETTE_YUYV;
574   }
575   else if (try_palette_v4l2(capture, V4L2_PIX_FMT_UYVY) == 0)
576   {
577     capture->palette = PALETTE_UYVY;
578   }
579   else
580   if (try_palette_v4l2(capture, V4L2_PIX_FMT_SN9C10X) == 0)
581   {
582     capture->palette = PALETTE_SN9C10X;
583   } else
584   if (try_palette_v4l2(capture, V4L2_PIX_FMT_SBGGR8) == 0)
585   {
586     capture->palette = PALETTE_SBGGR8;
587   } else
588   if (try_palette_v4l2(capture, V4L2_PIX_FMT_SGBRG) == 0)
589   {
590     capture->palette = PALETTE_SGBRG;
591   }
592   else if (try_palette_v4l2(capture, V4L2_PIX_FMT_RGB24) == 0)
593   {
594     capture->palette = PALETTE_RGB24;
595   }
596       else
597   {
598     fprintf(stderr, "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
599     icvCloseCAM_V4L(capture);
600     return -1;
601   }
602 
603   return 0;
604 
605 }
606 
607 #endif /* HAVE_CAMV4L2 */
608 
609 #ifdef HAVE_CAMV4L
610 
autosetup_capture_mode_v4l(CvCaptureCAM_V4L * capture)611 static int autosetup_capture_mode_v4l(CvCaptureCAM_V4L* capture)
612 {
613 
614   if(ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
615      fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n");
616      icvCloseCAM_V4L(capture);
617      return -1;
618   }
619 
620   /* Yet MORE things that might have to be changes with your frame capture card */
621   /* This sets the scale to the center of a 2^16 number */
622   if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_RGB24, 24)) {
623       //printf("negotiated palette RGB24\n");
624   }
625   else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420P, 16)) {
626       //printf("negotiated palette YUV420P\n");
627   }
628   else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV420, 16)) {
629       //printf("negotiated palette YUV420\n");
630   }
631   else if (try_palette(capture->deviceHandle, &capture->imageProperties, VIDEO_PALETTE_YUV411P, 16)) {
632       //printf("negotiated palette YUV420P\n");
633   }
634   else {
635     fprintf(stderr, "VIDEOIO ERROR: V4L: Pixel format of incoming image is unsupported by OpenCV\n");
636     icvCloseCAM_V4L(capture);
637     return -1;
638   }
639 
640   return 0;
641 
642 }
643 
644 #endif /* HAVE_CAMV4L */
645 
646 #ifdef HAVE_CAMV4L2
647 
648 
v4l2_scan_controls(CvCaptureCAM_V4L * capture)649 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
650 {
651 
652   __u32 ctrl_id;
653 
654   for (ctrl_id = V4L2_CID_BASE;
655        ctrl_id < V4L2_CID_LASTP1;
656        ctrl_id++)
657   {
658 
659     /* set the id we will query now */
660     CLEAR (capture->queryctrl);
661     capture->queryctrl.id = ctrl_id;
662 
663     if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
664                      &capture->queryctrl))
665     {
666 
667       if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
668         continue;
669 
670       if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
671       {
672         capture->v4l2_brightness = 1;
673         capture->v4l2_brightness_min = capture->queryctrl.minimum;
674         capture->v4l2_brightness_max = capture->queryctrl.maximum;
675       }
676 
677       if (capture->queryctrl.id == V4L2_CID_CONTRAST)
678       {
679         capture->v4l2_contrast = 1;
680         capture->v4l2_contrast_min = capture->queryctrl.minimum;
681         capture->v4l2_contrast_max = capture->queryctrl.maximum;
682       }
683 
684       if (capture->queryctrl.id == V4L2_CID_SATURATION)
685       {
686         capture->v4l2_saturation = 1;
687         capture->v4l2_saturation_min = capture->queryctrl.minimum;
688         capture->v4l2_saturation_max = capture->queryctrl.maximum;
689       }
690 
691       if (capture->queryctrl.id == V4L2_CID_HUE)
692       {
693         capture->v4l2_hue = 1;
694         capture->v4l2_hue_min = capture->queryctrl.minimum;
695         capture->v4l2_hue_max = capture->queryctrl.maximum;
696       }
697 
698       if (capture->queryctrl.id == V4L2_CID_GAIN)
699       {
700         capture->v4l2_gain = 1;
701         capture->v4l2_gain_min = capture->queryctrl.minimum;
702         capture->v4l2_gain_max = capture->queryctrl.maximum;
703       }
704 
705       if (capture->queryctrl.id == V4L2_CID_EXPOSURE)
706       {
707         capture->v4l2_exposure = 1;
708         capture->v4l2_exposure_min = capture->queryctrl.minimum;
709         capture->v4l2_exposure_max = capture->queryctrl.maximum;
710       }
711 
712 
713     } else {
714 
715       if (errno == EINVAL)
716         continue;
717 
718       perror ("VIDIOC_QUERYCTRL");
719 
720     }
721 
722   }
723 
724   for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
725   {
726 
727     /* set the id we will query now */
728     CLEAR (capture->queryctrl);
729     capture->queryctrl.id = ctrl_id;
730 
731     if (0 == ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL,
732                      &capture->queryctrl))
733     {
734 
735       if (capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
736         continue;
737 
738       if (capture->queryctrl.id == V4L2_CID_BRIGHTNESS)
739       {
740         capture->v4l2_brightness = 1;
741         capture->v4l2_brightness_min = capture->queryctrl.minimum;
742         capture->v4l2_brightness_max = capture->queryctrl.maximum;
743       }
744 
745       if (capture->queryctrl.id == V4L2_CID_CONTRAST)
746       {
747         capture->v4l2_contrast = 1;
748         capture->v4l2_contrast_min = capture->queryctrl.minimum;
749         capture->v4l2_contrast_max = capture->queryctrl.maximum;
750       }
751 
752       if (capture->queryctrl.id == V4L2_CID_SATURATION)
753       {
754         capture->v4l2_saturation = 1;
755         capture->v4l2_saturation_min = capture->queryctrl.minimum;
756         capture->v4l2_saturation_max = capture->queryctrl.maximum;
757       }
758 
759       if (capture->queryctrl.id == V4L2_CID_HUE)
760       {
761         capture->v4l2_hue = 1;
762         capture->v4l2_hue_min = capture->queryctrl.minimum;
763         capture->v4l2_hue_max = capture->queryctrl.maximum;
764       }
765 
766       if (capture->queryctrl.id == V4L2_CID_GAIN)
767       {
768         capture->v4l2_gain = 1;
769         capture->v4l2_gain_min = capture->queryctrl.minimum;
770         capture->v4l2_gain_max = capture->queryctrl.maximum;
771       }
772 
773       if (capture->queryctrl.id == V4L2_CID_EXPOSURE)
774       {
775         capture->v4l2_exposure = 1;
776         capture->v4l2_exposure_min = capture->queryctrl.minimum;
777         capture->v4l2_exposure_max = capture->queryctrl.maximum;
778       }
779 
780     } else {
781 
782       if (errno == EINVAL)
783         break;
784 
785       perror ("VIDIOC_QUERYCTRL");
786 
787     }
788 
789   }
790 
791 }
792 
_capture_V4L2(CvCaptureCAM_V4L * capture,char * deviceName)793 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
794 {
795    int detect_v4l2 = 0;
796 
797    detect_v4l2 = try_init_v4l2(capture, deviceName);
798 
799    if (detect_v4l2 != 1) {
800        /* init of the v4l2 device is not OK */
801        return -1;
802    }
803 
804    /* starting from here, we assume we are in V4L2 mode */
805    V4L2_SUPPORT = 1;
806 
807    /* Init V4L2 control variables */
808    capture->v4l2_brightness = 0;
809    capture->v4l2_contrast = 0;
810    capture->v4l2_saturation = 0;
811    capture->v4l2_hue = 0;
812    capture->v4l2_gain = 0;
813    capture->v4l2_exposure = 0;
814 
815    capture->v4l2_brightness_min = 0;
816    capture->v4l2_contrast_min = 0;
817    capture->v4l2_saturation_min = 0;
818    capture->v4l2_hue_min = 0;
819    capture->v4l2_gain_min = 0;
820    capture->v4l2_exposure_min = 0;
821 
822    capture->v4l2_brightness_max = 0;
823    capture->v4l2_contrast_max = 0;
824    capture->v4l2_saturation_max = 0;
825    capture->v4l2_hue_max = 0;
826    capture->v4l2_gain_max = 0;
827    capture->v4l2_exposure_max = 0;
828 
829    capture->timestamp.tv_sec = 0;
830    capture->timestamp.tv_usec = 0;
831 
832    /* Scan V4L2 controls */
833    v4l2_scan_controls(capture);
834 
835    if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
836       /* Nope. */
837       fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
838       icvCloseCAM_V4L(capture);
839       return -1;
840    }
841 
842    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
843    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
844    I myself am using a simple NTSC video input capture card that uses the value of 1.
845    If you are not in North America or have a different video standard, you WILL have to change
846    the following settings and recompile/reinstall.  This set of settings is based on
847    the most commonly encountered input video source types (like my bttv card) */
848 
849    if(capture->inp.index > 0) {
850        CLEAR (capture->inp);
851        capture->inp.index = CHANNEL_NUMBER;
852        /* Set only channel number to CHANNEL_NUMBER */
853        /* V4L2 have a status field from selected video mode */
854        if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
855        {
856          fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
857          icvCloseCAM_V4L (capture);
858          return -1;
859        }
860    } /* End if */
861 
862    /* Find Window info */
863    CLEAR (capture->form);
864    capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
865 
866    if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
867        fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
868        icvCloseCAM_V4L(capture);
869        return -1;
870    }
871 
872    if (V4L2_SUPPORT == 0)
873    {
874    }
875 
876    if (autosetup_capture_mode_v4l2(capture) == -1)
877        return -1;
878 
879    icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT);
880 
881    unsigned int min;
882 
883    /* Buggy driver paranoia. */
884    min = capture->form.fmt.pix.width * 2;
885 
886    if (capture->form.fmt.pix.bytesperline < min)
887        capture->form.fmt.pix.bytesperline = min;
888 
889    min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
890 
891    if (capture->form.fmt.pix.sizeimage < min)
892        capture->form.fmt.pix.sizeimage = min;
893 
894    CLEAR (capture->req);
895 
896    unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
897 
898    try_again:
899 
900    capture->req.count = buffer_number;
901    capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
902    capture->req.memory = V4L2_MEMORY_MMAP;
903 
904    if (-1 == ioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
905    {
906        if (EINVAL == errno)
907        {
908          fprintf (stderr, "%s does not support memory mapping\n", deviceName);
909        } else {
910          perror ("VIDIOC_REQBUFS");
911        }
912        /* free capture, and returns an error code */
913        icvCloseCAM_V4L (capture);
914        return -1;
915    }
916 
917    if (capture->req.count < buffer_number)
918    {
919        if (buffer_number == 1)
920        {
921            fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
922 
923            /* free capture, and returns an error code */
924            icvCloseCAM_V4L (capture);
925            return -1;
926        } else {
927          buffer_number--;
928      fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
929 
930      goto try_again;
931        }
932    }
933 
934    for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
935    {
936        struct v4l2_buffer buf;
937 
938        CLEAR (buf);
939 
940        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
941        buf.memory = V4L2_MEMORY_MMAP;
942        buf.index = n_buffers;
943 
944        if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
945            perror ("VIDIOC_QUERYBUF");
946 
947            /* free capture, and returns an error code */
948            icvCloseCAM_V4L (capture);
949            return -1;
950        }
951 
952        capture->buffers[n_buffers].length = buf.length;
953        capture->buffers[n_buffers].start =
954          mmap (NULL /* start anywhere */,
955                buf.length,
956                PROT_READ | PROT_WRITE /* required */,
957                MAP_SHARED /* recommended */,
958                capture->deviceHandle, buf.m.offset);
959 
960        if (MAP_FAILED == capture->buffers[n_buffers].start) {
961            perror ("mmap");
962 
963            /* free capture, and returns an error code */
964            icvCloseCAM_V4L (capture);
965            return -1;
966        }
967 
968        if (n_buffers == 0) {
969      capture->buffers[MAX_V4L_BUFFERS].start = malloc( buf.length );
970      capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
971        }
972    }
973 
974    /* Set up Image data */
975    cvInitImageHeader( &capture->frame,
976                       cvSize( capture->form.fmt.pix.width,
977                               capture->form.fmt.pix.height ),
978                       IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
979    /* Allocate space for RGBA data */
980    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
981 
982    return 1;
983 }; /* End _capture_V4L2 */
984 
985 #endif /* HAVE_CAMV4L2 */
986 
987 #ifdef HAVE_CAMV4L
988 
_capture_V4L(CvCaptureCAM_V4L * capture,char * deviceName)989 static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
990 {
991    int detect_v4l = 0;
992 
993    detect_v4l = try_init_v4l(capture, deviceName);
994 
995    if ((detect_v4l == -1)
996        )
997    {
998      fprintf (stderr, "VIDEOIO ERROR: V4L"
999               ": device %s: Unable to open for READ ONLY\n", deviceName);
1000 
1001      return -1;
1002    }
1003 
1004    if ((detect_v4l <= 0)
1005        )
1006    {
1007      fprintf (stderr, "VIDEOIO ERROR: V4L"
1008               ": device %s: Unable to query number of channels\n", deviceName);
1009 
1010      return -1;
1011    }
1012 
1013    {
1014      if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
1015        /* Nope. */
1016        fprintf( stderr, "VIDEOIO ERROR: V4L: "
1017                 "device %s is unable to capture video memory.\n",deviceName);
1018        icvCloseCAM_V4L(capture);
1019        return -1;
1020      }
1021 
1022    }
1023 
1024 
1025    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
1026    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
1027    I myself am using a simple NTSC video input capture card that uses the value of 1.
1028    If you are not in North America or have a different video standard, you WILL have to change
1029    the following settings and recompile/reinstall.  This set of settings is based on
1030    the most commonly encountered input video source types (like my bttv card) */
1031 
1032    {
1033 
1034      if(capture->capability.channels>0) {
1035 
1036        struct video_channel selectedChannel;
1037        memset(&selectedChannel, 0, sizeof(selectedChannel));
1038 
1039        selectedChannel.channel=CHANNEL_NUMBER;
1040        if (ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
1041           /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
1042 //           selectedChannel.norm = VIDEO_MODE_NTSC;
1043           if (ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
1044              /* Could not set selected channel - Oh well */
1045              //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
1046           } /* End if */
1047        } /* End if */
1048      } /* End if */
1049 
1050    }
1051 
1052    {
1053 
1054      if(ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
1055        fprintf( stderr, "VIDEOIO ERROR: V4L: "
1056                 "Could not obtain specifics of capture window.\n\n");
1057        icvCloseCAM_V4L(capture);
1058        return -1;
1059      }
1060 
1061    }
1062 
1063    {
1064 
1065      if (autosetup_capture_mode_v4l(capture) == -1)
1066        return -1;
1067 
1068    }
1069 
1070    {
1071 
1072      ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
1073      capture->memoryMap  = (char *)mmap(0,
1074                                    capture->memoryBuffer.size,
1075                                    PROT_READ | PROT_WRITE,
1076                                    MAP_SHARED,
1077                                    capture->deviceHandle,
1078                                    0);
1079      if (capture->memoryMap == MAP_FAILED) {
1080         fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
1081         icvCloseCAM_V4L(capture);
1082      }
1083 
1084      /* Set up video_mmap structure pointing to this memory mapped area so each image may be
1085         retrieved from an index value */
1086      capture->mmaps = (struct video_mmap *)
1087                  (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
1088      if (!capture->mmaps) {
1089         fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n");
1090         icvCloseCAM_V4L(capture);
1091         return -1;
1092      }
1093 
1094    }
1095 
1096    /* Set up Image data */
1097    cvInitImageHeader( &capture->frame,
1098                       cvSize( capture->captureWindow.width,
1099                               capture->captureWindow.height ),
1100                       IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1101    /* Allocate space for RGBA data */
1102    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1103 
1104    return 1;
1105 }; /* End _capture_V4L */
1106 
1107 #endif /* HAVE_CAMV4L */
1108 
icvCaptureFromCAM_V4L(int index)1109 static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
1110 {
1111    static int autoindex;
1112    autoindex = 0;
1113 
1114    char deviceName[MAX_DEVICE_DRIVER_NAME];
1115 
1116    if (!numCameras)
1117       icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
1118    if (!numCameras)
1119      return NULL; /* Are there any /dev/video input sources? */
1120 
1121    //search index in indexList
1122    if ( (index>-1) && ! ((1 << index) & indexList) )
1123    {
1124      fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index);
1125      return NULL; /* Did someone ask for not correct video source number? */
1126    }
1127    /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
1128       the handles for V4L processing */
1129    CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
1130    if (!capture) {
1131       fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n");
1132       return NULL;
1133    }
1134    /* Select camera, or rather, V4L video source */
1135    if (index<0) { // Asking for the first device available
1136      for (; autoindex<MAX_CAMERAS;autoindex++)
1137     if (indexList & (1<<autoindex))
1138         break;
1139      if (autoindex==MAX_CAMERAS)
1140     return NULL;
1141      index=autoindex;
1142      autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
1143    }
1144    /* Print the CameraNumber at the end of the string with a width of one character */
1145    sprintf(deviceName, "/dev/video%1d", index);
1146 
1147    /* w/o memset some parts  arent initialized - AKA: Fill it with zeros so it is clean */
1148    memset(capture,0,sizeof(CvCaptureCAM_V4L));
1149    /* Present the routines needed for V4L funtionality.  They are inserted as part of
1150       the standard set of cv calls promoting transparency.  "Vector Table" insertion. */
1151    capture->FirstCapture = 1;
1152 
1153 #ifdef HAVE_CAMV4L2
1154    if (_capture_V4L2 (capture, deviceName) == -1) {
1155        icvCloseCAM_V4L(capture);
1156        V4L2_SUPPORT = 0;
1157 #endif  /* HAVE_CAMV4L2 */
1158 #ifdef HAVE_CAMV4L
1159        if (_capture_V4L (capture, deviceName) == -1) {
1160            icvCloseCAM_V4L(capture);
1161            return NULL;
1162        }
1163 #endif  /* HAVE_CAMV4L */
1164 #ifdef HAVE_CAMV4L2
1165    } else {
1166        V4L2_SUPPORT = 1;
1167    }
1168 #endif  /* HAVE_CAMV4L2 */
1169 
1170    return capture;
1171 }; /* End icvOpenCAM_V4L */
1172 
1173 #ifdef HAVE_CAMV4L2
1174 
read_frame_v4l2(CvCaptureCAM_V4L * capture)1175 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1176     struct v4l2_buffer buf;
1177 
1178     CLEAR (buf);
1179 
1180     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1181     buf.memory = V4L2_MEMORY_MMAP;
1182 
1183     if (-1 == ioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1184         switch (errno) {
1185         case EAGAIN:
1186             return 0;
1187 
1188         case EIO:
1189         if (!(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)))
1190         {
1191           if (ioctl(capture->deviceHandle, VIDIOC_QBUF, &buf) == -1)
1192           {
1193             return 0;
1194           }
1195         }
1196         return 0;
1197 
1198         default:
1199             /* display the error and stop processing */
1200             perror ("VIDIOC_DQBUF");
1201             return 1;
1202         }
1203    }
1204 
1205    assert(buf.index < capture->req.count);
1206 
1207    memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
1208       capture->buffers[buf.index].start,
1209       capture->buffers[MAX_V4L_BUFFERS].length );
1210    capture->bufferIndex = MAX_V4L_BUFFERS;
1211    //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
1212    //	  buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
1213 
1214    if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1215        perror ("VIDIOC_QBUF");
1216 
1217    //set timestamp in capture struct to be timestamp of most recent frame
1218    capture->timestamp = buf.timestamp;
1219 
1220    return 1;
1221 }
1222 
mainloop_v4l2(CvCaptureCAM_V4L * capture)1223 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1224     unsigned int count;
1225 
1226     count = 1;
1227 
1228     while (count-- > 0) {
1229         for (;;) {
1230             fd_set fds;
1231             struct timeval tv;
1232             int r;
1233 
1234             FD_ZERO (&fds);
1235             FD_SET (capture->deviceHandle, &fds);
1236 
1237             /* Timeout. */
1238             tv.tv_sec = 10;
1239             tv.tv_usec = 0;
1240 
1241             r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1242 
1243             if (-1 == r) {
1244                 if (EINTR == errno)
1245                     continue;
1246 
1247                 perror ("select");
1248             }
1249 
1250             if (0 == r) {
1251                 fprintf (stderr, "select timeout\n");
1252 
1253                 /* end the infinite loop */
1254                 break;
1255             }
1256 
1257             if (read_frame_v4l2 (capture))
1258                 break;
1259         }
1260     }
1261 }
1262 
1263 #endif /* HAVE_CAMV4L2 */
1264 
icvGrabFrameCAM_V4L(CvCaptureCAM_V4L * capture)1265 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1266 
1267    if (capture->FirstCapture) {
1268       /* Some general initialization must take place the first time through */
1269 
1270       /* This is just a technicality, but all buffers must be filled up before any
1271          staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
1272 
1273 #ifdef HAVE_CAMV4L2
1274 
1275 #ifdef HAVE_CAMV4L
1276       if (V4L2_SUPPORT == 1)
1277 #endif
1278       {
1279 
1280         for (capture->bufferIndex = 0;
1281              capture->bufferIndex < ((int)capture->req.count);
1282              ++capture->bufferIndex)
1283         {
1284 
1285           struct v4l2_buffer buf;
1286 
1287           CLEAR (buf);
1288 
1289           buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1290           buf.memory      = V4L2_MEMORY_MMAP;
1291           buf.index       = (unsigned long)capture->bufferIndex;
1292 
1293           if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1294               perror ("VIDIOC_QBUF");
1295               return 0;
1296           }
1297         }
1298 
1299         /* enable the streaming */
1300         capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1301         if (-1 == ioctl (capture->deviceHandle, VIDIOC_STREAMON,
1302                           &capture->type)) {
1303             /* error enabling the stream */
1304             perror ("VIDIOC_STREAMON");
1305             return 0;
1306         }
1307       }
1308 #endif /* HAVE_CAMV4L2 */
1309 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
1310       else
1311 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
1312 #ifdef HAVE_CAMV4L
1313       {
1314 
1315         for (capture->bufferIndex = 0;
1316          capture->bufferIndex < (capture->memoryBuffer.frames-1);
1317          ++capture->bufferIndex) {
1318 
1319           capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1320           capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1321           capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1322           capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1323 
1324           if (ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1325             fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1326             return 0;
1327           }
1328         }
1329 
1330       }
1331 #endif /* HAVE_CAMV4L */
1332 
1333 #if defined(V4L_ABORT_BADJPEG) && defined(HAVE_CAMV4L2)
1334      if (V4L2_SUPPORT == 1)
1335      {
1336         // skip first frame. it is often bad -- this is unnotied in traditional apps,
1337         //  but could be fatal if bad jpeg is enabled
1338         mainloop_v4l2(capture);
1339      }
1340 #endif
1341 
1342       /* preparation is ok */
1343       capture->FirstCapture = 0;
1344    }
1345 
1346 #ifdef HAVE_CAMV4L2
1347 
1348    if (V4L2_SUPPORT == 1)
1349    {
1350 
1351      mainloop_v4l2(capture);
1352 
1353    }
1354 #endif /* HAVE_CAMV4L2 */
1355 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
1356      else
1357 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
1358 #ifdef HAVE_CAMV4L
1359    {
1360 
1361      capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1362      capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1363      capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1364      capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1365 
1366      if (ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1367         &capture->mmaps[capture->bufferIndex]) == -1) {
1368      /* capture is on the way, so just exit */
1369      return 1;
1370      }
1371 
1372      ++capture->bufferIndex;
1373      if (capture->bufferIndex == capture->memoryBuffer.frames) {
1374         capture->bufferIndex = 0;
1375      }
1376 
1377    }
1378 #endif /* HAVE_CAMV4L */
1379 
1380    return(1);
1381 }
1382 
1383 /*
1384  * Turn a YUV4:2:0 block into an RGB block
1385  *
1386  * Video4Linux seems to use the blue, green, red channel
1387  * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
1388  *
1389  * Color space conversion coefficients taken from the excellent
1390  * http://www.inforamp.net/~poynton/ColorFAQ.html
1391  * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
1392  * Y values are given for all 4 pixels, but the U (Pb)
1393  * and V (Pr) are assumed constant over the 2x2 block.
1394  *
1395  * To avoid floating point arithmetic, the color conversion
1396  * coefficients are scaled into 16.16 fixed-point integers.
1397  * They were determined as follows:
1398  *
1399  *  double brightness = 1.0;  (0->black; 1->full scale)
1400  *  double saturation = 1.0;  (0->greyscale; 1->full color)
1401  *  double fixScale = brightness * 256 * 256;
1402  *  int rvScale = (int)(1.402 * saturation * fixScale);
1403  *  int guScale = (int)(-0.344136 * saturation * fixScale);
1404  *  int gvScale = (int)(-0.714136 * saturation * fixScale);
1405  *  int buScale = (int)(1.772 * saturation * fixScale);
1406  *  int yScale = (int)(fixScale);
1407  */
1408 
1409 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
1410 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
1411 
1412 static inline void
move_420_block(int yTL,int yTR,int yBL,int yBR,int u,int v,int rowPixels,unsigned char * rgb)1413 move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1414                int rowPixels, unsigned char * rgb)
1415 {
1416     const int rvScale = 91881;
1417     const int guScale = -22553;
1418     const int gvScale = -46801;
1419     const int buScale = 116129;
1420     const int yScale  = 65536;
1421     int r, g, b;
1422 
1423     g = guScale * u + gvScale * v;
1424 //  if (force_rgb) {
1425 //      r = buScale * u;
1426 //      b = rvScale * v;
1427 //  } else {
1428         r = rvScale * v;
1429         b = buScale * u;
1430 //  }
1431 
1432     yTL *= yScale; yTR *= yScale;
1433     yBL *= yScale; yBR *= yScale;
1434 
1435     /* Write out top two pixels */
1436     rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1437     rgb[2] = LIMIT(r+yTL);
1438 
1439     rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1440     rgb[5] = LIMIT(r+yTR);
1441 
1442     /* Skip down to next line to write out bottom two pixels */
1443     rgb += 3 * rowPixels;
1444     rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1445     rgb[2] = LIMIT(r+yBL);
1446 
1447     rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1448     rgb[5] = LIMIT(r+yBR);
1449 }
1450 
1451 static inline void
move_411_block(int yTL,int yTR,int yBL,int yBR,int u,int v,int,unsigned char * rgb)1452 move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
1453                int /*rowPixels*/, unsigned char * rgb)
1454 {
1455     const int rvScale = 91881;
1456     const int guScale = -22553;
1457     const int gvScale = -46801;
1458     const int buScale = 116129;
1459     const int yScale  = 65536;
1460     int r, g, b;
1461 
1462     g = guScale * u + gvScale * v;
1463 //  if (force_rgb) {
1464 //      r = buScale * u;
1465 //      b = rvScale * v;
1466 //  } else {
1467         r = rvScale * v;
1468         b = buScale * u;
1469 //  }
1470 
1471     yTL *= yScale; yTR *= yScale;
1472     yBL *= yScale; yBR *= yScale;
1473 
1474     /* Write out top two first pixels */
1475     rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1476     rgb[2] = LIMIT(r+yTL);
1477 
1478     rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1479     rgb[5] = LIMIT(r+yTR);
1480 
1481     /* Write out top two last pixels */
1482     rgb += 6;
1483     rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1484     rgb[2] = LIMIT(r+yBL);
1485 
1486     rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1487     rgb[5] = LIMIT(r+yBR);
1488 }
1489 
1490 // Consider a YUV420P image of 8x2 pixels.
1491 //
1492 // A plane of Y values    A B C D E F G H
1493 //                        I J K L M N O P
1494 //
1495 // A plane of U values    1   2   3   4
1496 // A plane of V values    1   2   3   4 ....
1497 //
1498 // The U1/V1 samples correspond to the ABIJ pixels.
1499 //     U2/V2 samples correspond to the CDKL pixels.
1500 //
1501 /* Converts from planar YUV420P to RGB24. */
1502 static void
yuv420p_to_rgb24(int width,int height,unsigned char * pIn0,unsigned char * pOut0)1503 yuv420p_to_rgb24(int width, int height,
1504            unsigned char *pIn0, unsigned char *pOut0)
1505 {
1506     const int numpix = width * height;
1507     const int bytes = 24 >> 3;
1508     int i, j, y00, y01, y10, y11, u, v;
1509     unsigned char *pY = pIn0;
1510     unsigned char *pU = pY + numpix;
1511     unsigned char *pV = pU + numpix / 4;
1512     unsigned char *pOut = pOut0;
1513 
1514     for (j = 0; j <= height - 2; j += 2) {
1515         for (i = 0; i <= width - 2; i += 2) {
1516             y00 = *pY;
1517             y01 = *(pY + 1);
1518             y10 = *(pY + width);
1519             y11 = *(pY + width + 1);
1520             u = (*pU++) - 128;
1521             v = (*pV++) - 128;
1522 
1523             move_420_block(y00, y01, y10, y11, u, v,
1524                        width, pOut);
1525 
1526             pY += 2;
1527             pOut += 2 * bytes;
1528 
1529         }
1530         pY += width;
1531         pOut += width * bytes;
1532     }
1533 }
1534 
1535 // Consider a YUV420 image of 6x2 pixels.
1536 //
1537 // A B C D U1 U2
1538 // I J K L V1 V2
1539 //
1540 // The U1/V1 samples correspond to the ABIJ pixels.
1541 //     U2/V2 samples correspond to the CDKL pixels.
1542 //
1543 /* Converts from interlaced YUV420 to RGB24. */
1544 /* [FD] untested... */
1545 #ifdef HAVE_CAMV4L
1546 static void
yuv420_to_rgb24(int width,int height,unsigned char * pIn0,unsigned char * pOut0)1547 yuv420_to_rgb24(int width, int height,
1548         unsigned char *pIn0, unsigned char *pOut0)
1549 {
1550     const int bytes = 24 >> 3;
1551     int i, j, y00, y01, y10, y11, u, v;
1552     unsigned char *pY = pIn0;
1553     unsigned char *pU = pY + 4;
1554     unsigned char *pV = pU + width;
1555     unsigned char *pOut = pOut0;
1556 
1557     for (j = 0; j <= height - 2; j += 2) {
1558         for (i = 0; i <= width - 4; i += 4) {
1559             y00 = *pY;
1560             y01 = *(pY + 1);
1561             y10 = *(pY + width);
1562             y11 = *(pY + width + 1);
1563             u = (*pU++) - 128;
1564             v = (*pV++) - 128;
1565 
1566             move_420_block(y00, y01, y10, y11, u, v,
1567                        width, pOut);
1568 
1569             pY += 2;
1570             pOut += 2 * bytes;
1571 
1572             y00 = *pY;
1573             y01 = *(pY + 1);
1574             y10 = *(pY + width);
1575             y11 = *(pY + width + 1);
1576             u = (*pU++) - 128;
1577             v = (*pV++) - 128;
1578 
1579             move_420_block(y00, y01, y10, y11, u, v,
1580                        width, pOut);
1581 
1582             pY += 4; // skip UV
1583             pOut += 2 * bytes;
1584 
1585         }
1586         pY += width;
1587         pOut += width * bytes;
1588     }
1589 }
1590 #endif //HAVE_CAMV4L
1591 
1592 // Consider a YUV411P image of 8x2 pixels.
1593 //
1594 // A plane of Y values as before.
1595 //
1596 // A plane of U values    1       2
1597 //                        3       4
1598 //
1599 // A plane of V values    1       2
1600 //                        3       4
1601 //
1602 // The U1/V1 samples correspond to the ABCD pixels.
1603 //     U2/V2 samples correspond to the EFGH pixels.
1604 //
1605 /* Converts from planar YUV411P to RGB24. */
1606 /* [FD] untested... */
1607 static void
yuv411p_to_rgb24(int width,int height,unsigned char * pIn0,unsigned char * pOut0)1608 yuv411p_to_rgb24(int width, int height,
1609            unsigned char *pIn0, unsigned char *pOut0)
1610 {
1611     const int numpix = width * height;
1612     const int bytes = 24 >> 3;
1613     int i, j, y00, y01, y10, y11, u, v;
1614     unsigned char *pY = pIn0;
1615     unsigned char *pU = pY + numpix;
1616     unsigned char *pV = pU + numpix / 4;
1617     unsigned char *pOut = pOut0;
1618 
1619     for (j = 0; j <= height; j++) {
1620         for (i = 0; i <= width - 4; i += 4) {
1621             y00 = *pY;
1622             y01 = *(pY + 1);
1623             y10 = *(pY + 2);
1624             y11 = *(pY + 3);
1625             u = (*pU++) - 128;
1626             v = (*pV++) - 128;
1627 
1628             move_411_block(y00, y01, y10, y11, u, v,
1629                        width, pOut);
1630 
1631             pY += 4;
1632             pOut += 4 * bytes;
1633 
1634         }
1635     }
1636 }
1637 
1638 /* convert from 4:2:2 YUYV interlaced to RGB24 */
1639 /* based on ccvt_yuyv_bgr32() from camstream */
1640 #define SAT(c) \
1641         if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
1642 
1643 #ifdef HAVE_CAMV4L2
1644 static void
yuyv_to_rgb24(int width,int height,unsigned char * src,unsigned char * dst)1645 yuyv_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1646 {
1647    unsigned char *s;
1648    unsigned char *d;
1649    int l, c;
1650    int r, g, b, cr, cg, cb, y1, y2;
1651 
1652    l = height;
1653    s = src;
1654    d = dst;
1655    while (l--) {
1656       c = width >> 1;
1657       while (c--) {
1658          y1 = *s++;
1659          cb = ((*s - 128) * 454) >> 8;
1660          cg = (*s++ - 128) * 88;
1661          y2 = *s++;
1662          cr = ((*s - 128) * 359) >> 8;
1663          cg = (cg + (*s++ - 128) * 183) >> 8;
1664 
1665          r = y1 + cr;
1666          b = y1 + cb;
1667          g = y1 - cg;
1668          SAT(r);
1669          SAT(g);
1670          SAT(b);
1671 
1672      *d++ = b;
1673      *d++ = g;
1674      *d++ = r;
1675 
1676          r = y2 + cr;
1677          b = y2 + cb;
1678          g = y2 - cg;
1679          SAT(r);
1680          SAT(g);
1681          SAT(b);
1682 
1683      *d++ = b;
1684      *d++ = g;
1685      *d++ = r;
1686       }
1687    }
1688 }
1689 
1690 static void
uyvy_to_rgb24(int width,int height,unsigned char * src,unsigned char * dst)1691 uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1692 {
1693    unsigned char *s;
1694    unsigned char *d;
1695    int l, c;
1696    int r, g, b, cr, cg, cb, y1, y2;
1697 
1698    l = height;
1699    s = src;
1700    d = dst;
1701    while (l--) {
1702       c = width >> 1;
1703       while (c--) {
1704          cb = ((*s - 128) * 454) >> 8;
1705          cg = (*s++ - 128) * 88;
1706          y1 = *s++;
1707          cr = ((*s - 128) * 359) >> 8;
1708          cg = (cg + (*s++ - 128) * 183) >> 8;
1709          y2 = *s++;
1710 
1711          r = y1 + cr;
1712          b = y1 + cb;
1713          g = y1 - cg;
1714          SAT(r);
1715          SAT(g);
1716          SAT(b);
1717 
1718      *d++ = b;
1719      *d++ = g;
1720      *d++ = r;
1721 
1722          r = y2 + cr;
1723          b = y2 + cb;
1724          g = y2 - cg;
1725          SAT(r);
1726          SAT(g);
1727          SAT(b);
1728 
1729      *d++ = b;
1730      *d++ = g;
1731      *d++ = r;
1732       }
1733    }
1734 }
1735 #endif //HAVE_CAMV4L2
1736 
1737 #ifdef HAVE_JPEG
1738 
1739 /* convert from mjpeg to rgb24 */
1740 static bool
mjpeg_to_rgb24(int width,int height,unsigned char * src,int length,unsigned char * dst)1741 mjpeg_to_rgb24 (int width, int height,
1742         unsigned char *src, int length,
1743         unsigned char *dst)
1744 {
1745   cv::Mat temp=cv::imdecode(cv::Mat(std::vector<uchar>(src, src + length)), 1);
1746   if( !temp.data || temp.cols != width || temp.rows != height )
1747     return false;
1748   memcpy(dst, temp.data, width*height*3);
1749   return true;
1750 }
1751 
1752 #endif
1753 
1754 /*
1755  * BAYER2RGB24 ROUTINE TAKEN FROM:
1756  *
1757  * Sonix SN9C10x based webcam basic I/F routines
1758  * Takafumi Mizuno <taka-qce@ls-a.jp>
1759  *
1760  */
1761 
1762 #ifdef HAVE_CAMV4L2
bayer2rgb24(long int WIDTH,long int HEIGHT,unsigned char * src,unsigned char * dst)1763 static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1764 {
1765     long int i;
1766     unsigned char *rawpt, *scanpt;
1767     long int size;
1768 
1769     rawpt = src;
1770     scanpt = dst;
1771     size = WIDTH*HEIGHT;
1772 
1773     for ( i = 0; i < size; i++ ) {
1774   if ( (i/WIDTH) % 2 == 0 ) {
1775       if ( (i % 2) == 0 ) {
1776     /* B */
1777     if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
1778         *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1779          *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;  /* R */
1780         *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1781          *(rawpt+WIDTH)+*(rawpt-WIDTH))/4;      /* G */
1782         *scanpt++ = *rawpt;                                     /* B */
1783     } else {
1784         /* first line or left column */
1785         *scanpt++ = *(rawpt+WIDTH+1);           /* R */
1786         *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2;      /* G */
1787         *scanpt++ = *rawpt;                             /* B */
1788     }
1789       } else {
1790     /* (B)G */
1791     if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
1792         *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;  /* R */
1793         *scanpt++ = *rawpt;                                     /* G */
1794         *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;          /* B */
1795     } else {
1796         /* first line or right column */
1797         *scanpt++ = *(rawpt+WIDTH);     /* R */
1798         *scanpt++ = *rawpt;             /* G */
1799         *scanpt++ = *(rawpt-1); /* B */
1800     }
1801       }
1802   } else {
1803       if ( (i % 2) == 0 ) {
1804     /* G(R) */
1805     if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
1806         *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;          /* R */
1807         *scanpt++ = *rawpt;                                     /* G */
1808         *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;  /* B */
1809     } else {
1810         /* bottom line or left column */
1811         *scanpt++ = *(rawpt+1);         /* R */
1812         *scanpt++ = *rawpt;                     /* G */
1813         *scanpt++ = *(rawpt-WIDTH);             /* B */
1814     }
1815       } else {
1816     /* R */
1817     if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
1818         *scanpt++ = *rawpt;                                     /* R */
1819         *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1820          *(rawpt-WIDTH)+*(rawpt+WIDTH))/4;      /* G */
1821         *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1822          *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;  /* B */
1823     } else {
1824         /* bottom line or right column */
1825         *scanpt++ = *rawpt;                             /* R */
1826         *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2;      /* G */
1827         *scanpt++ = *(rawpt-WIDTH-1);           /* B */
1828     }
1829       }
1830   }
1831   rawpt++;
1832     }
1833 
1834 }
1835 
1836 // SGBRG to RGB24
1837 // for some reason, red and blue needs to be swapped
1838 // at least for  046d:092f Logitech, Inc. QuickCam Express Plus to work
1839 //see: http://www.siliconimaging.com/RGB%20Bayer.htm
1840 //and 4.6 at http://tldp.org/HOWTO/html_single/libdc1394-HOWTO/
sgbrg2rgb24(long int WIDTH,long int HEIGHT,unsigned char * src,unsigned char * dst)1841 static void sgbrg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1842 {
1843     long int i;
1844     unsigned char *rawpt, *scanpt;
1845     long int size;
1846 
1847     rawpt = src;
1848     scanpt = dst;
1849     size = WIDTH*HEIGHT;
1850 
1851     for ( i = 0; i < size; i++ )
1852     {
1853         if ( (i/WIDTH) % 2 == 0 ) //even row
1854         {
1855             if ( (i % 2) == 0 ) //even pixel
1856             {
1857                 if ( (i > WIDTH) && ((i % WIDTH) > 0) )
1858                 {
1859                     *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;       /* R */
1860                     *scanpt++ = *(rawpt);                        /* G */
1861                     *scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2;      /* B */
1862                 } else
1863                 {
1864                   /* first line or left column */
1865 
1866                   *scanpt++ = *(rawpt+1);           /* R */
1867                   *scanpt++ = *(rawpt);             /* G */
1868                   *scanpt++ =  *(rawpt+WIDTH);      /* B */
1869                 }
1870             } else //odd pixel
1871             {
1872                 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
1873                 {
1874                     *scanpt++ = *(rawpt);       /* R */
1875                     *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1876                     *scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) + *(rawpt+WIDTH-1) + *(rawpt+WIDTH+1))/4;      /* B */
1877                 } else
1878                 {
1879                     /* first line or right column */
1880 
1881                     *scanpt++ = *(rawpt);       /* R */
1882                     *scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
1883                     *scanpt++ = *(rawpt+WIDTH-1);      /* B */
1884                 }
1885             }
1886         } else
1887         { //odd row
1888             if ( (i % 2) == 0 ) //even pixel
1889             {
1890                 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
1891                 {
1892                     *scanpt++ =  (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;          /* R */
1893                     *scanpt++ =  (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4;      /* G */
1894                     *scanpt++ =  *(rawpt); /* B */
1895                 } else
1896                 {
1897                     /* bottom line or left column */
1898 
1899                     *scanpt++ =  *(rawpt-WIDTH+1);          /* R */
1900                     *scanpt++ =  (*(rawpt+1)+*(rawpt-WIDTH))/2;      /* G */
1901                     *scanpt++ =  *(rawpt); /* B */
1902                 }
1903             } else
1904             { //odd pixel
1905                 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
1906                 {
1907                     *scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2;  /* R */
1908                     *scanpt++ = *(rawpt);      /* G */
1909                     *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1910                 } else
1911                 {
1912                     /* bottom line or right column */
1913 
1914                     *scanpt++ = (*(rawpt-WIDTH));  /* R */
1915                     *scanpt++ = *(rawpt);      /* G */
1916                     *scanpt++ = (*(rawpt-1)); /* B */
1917                 }
1918             }
1919         }
1920         rawpt++;
1921     }
1922 }
1923 
1924 static void
rgb24_to_rgb24(int width,int height,unsigned char * src,unsigned char * dst)1925 rgb24_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1926 {
1927   const int size = width * height;
1928   for(int i = 0; i < size; ++i, src += 3, dst += 3)
1929   {
1930     *(dst + 0) = *(src + 2);
1931     *(dst + 1) = *(src + 1);
1932     *(dst + 2) = *(src + 0);
1933   }
1934 }
1935 
1936 #define CLAMP(x)        ((x)<0?0:((x)>255)?255:(x))
1937 
1938 typedef struct {
1939   int is_abs;
1940   int len;
1941   int val;
1942 } code_table_t;
1943 
1944 
1945 /* local storage */
1946 static code_table_t table[256];
1947 static int init_done = 0;
1948 
1949 
1950 /*
1951   sonix_decompress_init
1952   =====================
1953     pre-calculates a locally stored table for efficient huffman-decoding.
1954 
1955   Each entry at index x in the table represents the codeword
1956   present at the MSB of byte x.
1957 
1958 */
sonix_decompress_init(void)1959 static void sonix_decompress_init(void)
1960 {
1961   int i;
1962   int is_abs, val, len;
1963 
1964   for (i = 0; i < 256; i++) {
1965     is_abs = 0;
1966     val = 0;
1967     len = 0;
1968     if ((i & 0x80) == 0) {
1969       /* code 0 */
1970       val = 0;
1971       len = 1;
1972     }
1973     else if ((i & 0xE0) == 0x80) {
1974       /* code 100 */
1975       val = +4;
1976       len = 3;
1977     }
1978     else if ((i & 0xE0) == 0xA0) {
1979       /* code 101 */
1980       val = -4;
1981       len = 3;
1982     }
1983     else if ((i & 0xF0) == 0xD0) {
1984       /* code 1101 */
1985       val = +11;
1986       len = 4;
1987     }
1988     else if ((i & 0xF0) == 0xF0) {
1989       /* code 1111 */
1990       val = -11;
1991       len = 4;
1992     }
1993     else if ((i & 0xF8) == 0xC8) {
1994       /* code 11001 */
1995       val = +20;
1996       len = 5;
1997     }
1998     else if ((i & 0xFC) == 0xC0) {
1999       /* code 110000 */
2000       val = -20;
2001       len = 6;
2002     }
2003     else if ((i & 0xFC) == 0xC4) {
2004       /* code 110001xx: unknown */
2005       val = 0;
2006       len = 8;
2007     }
2008     else if ((i & 0xF0) == 0xE0) {
2009       /* code 1110xxxx */
2010       is_abs = 1;
2011       val = (i & 0x0F) << 4;
2012       len = 8;
2013     }
2014     table[i].is_abs = is_abs;
2015     table[i].val = val;
2016     table[i].len = len;
2017   }
2018 
2019   init_done = 1;
2020 }
2021 
2022 
2023 /*
2024   sonix_decompress
2025   ================
2026     decompresses an image encoded by a SN9C101 camera controller chip.
2027 
2028   IN    width
2029     height
2030     inp         pointer to compressed frame (with header already stripped)
2031   OUT   outp    pointer to decompressed frame
2032 
2033   Returns 0 if the operation was successful.
2034   Returns <0 if operation failed.
2035 
2036 */
sonix_decompress(int width,int height,unsigned char * inp,unsigned char * outp)2037 static int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
2038 {
2039   int row, col;
2040   int val;
2041   int bitpos;
2042   unsigned char code;
2043   unsigned char *addr;
2044 
2045   if (!init_done) {
2046     /* do sonix_decompress_init first! */
2047     return -1;
2048   }
2049 
2050   bitpos = 0;
2051   for (row = 0; row < height; row++) {
2052 
2053     col = 0;
2054 
2055 
2056 
2057     /* first two pixels in first two rows are stored as raw 8-bit */
2058     if (row < 2) {
2059       addr = inp + (bitpos >> 3);
2060       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
2061       bitpos += 8;
2062       *outp++ = code;
2063 
2064       addr = inp + (bitpos >> 3);
2065       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
2066       bitpos += 8;
2067       *outp++ = code;
2068 
2069       col += 2;
2070     }
2071 
2072     while (col < width) {
2073       /* get bitcode from bitstream */
2074       addr = inp + (bitpos >> 3);
2075       code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
2076 
2077       /* update bit position */
2078       bitpos += table[code].len;
2079 
2080       /* calculate pixel value */
2081       val = table[code].val;
2082       if (!table[code].is_abs) {
2083         /* value is relative to top and left pixel */
2084         if (col < 2) {
2085           /* left column: relative to top pixel */
2086           val += outp[-2*width];
2087         }
2088         else if (row < 2) {
2089           /* top row: relative to left pixel */
2090           val += outp[-2];
2091         }
2092         else {
2093           /* main area: average of left pixel and top pixel */
2094           val += (outp[-2] + outp[-2*width]) / 2;
2095         }
2096       }
2097 
2098       /* store pixel */
2099       *outp++ = CLAMP(val);
2100       col++;
2101     }
2102   }
2103 
2104   return 0;
2105 }
2106 #endif //HAVE_CAMV4L2
2107 
icvRetrieveFrameCAM_V4L(CvCaptureCAM_V4L * capture,int)2108 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
2109 
2110 #ifdef HAVE_CAMV4L2
2111   if (V4L2_SUPPORT == 0)
2112 #endif /* HAVE_CAMV4L2 */
2113 #ifdef HAVE_CAMV4L
2114   {
2115 
2116     /* [FD] this really belongs here */
2117     if (ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
2118       fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
2119     }
2120 
2121   }
2122 #endif /* HAVE_CAMV4L */
2123 
2124    /* Now get what has already been captured as a IplImage return */
2125 
2126    /* First, reallocate imageData if the frame size changed */
2127 
2128 #ifdef HAVE_CAMV4L2
2129 
2130   if (V4L2_SUPPORT == 1)
2131   {
2132 
2133     if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
2134        || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
2135         cvFree(&capture->frame.imageData);
2136         cvInitImageHeader( &capture->frame,
2137               cvSize( capture->form.fmt.pix.width,
2138                   capture->form.fmt.pix.height ),
2139               IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2140        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2141     }
2142 
2143   }
2144 #endif /* HAVE_CAMV4L2 */
2145 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2146     else
2147 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2148 #ifdef HAVE_CAMV4L
2149   {
2150 
2151     if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
2152       || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
2153        cvFree(&capture->frame.imageData);
2154        cvInitImageHeader( &capture->frame,
2155               cvSize( capture->captureWindow.width,
2156                   capture->captureWindow.height ),
2157               IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
2158        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
2159     }
2160 
2161   }
2162 #endif /* HAVE_CAMV4L */
2163 
2164 #ifdef HAVE_CAMV4L2
2165 
2166   if (V4L2_SUPPORT == 1)
2167   {
2168     switch (capture->palette)
2169     {
2170     case PALETTE_BGR24:
2171         memcpy((char *)capture->frame.imageData,
2172                (char *)capture->buffers[capture->bufferIndex].start,
2173                capture->frame.imageSize);
2174         break;
2175 
2176     case PALETTE_YVU420:
2177         yuv420p_to_rgb24(capture->form.fmt.pix.width,
2178                  capture->form.fmt.pix.height,
2179                  (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2180                  (unsigned char*)capture->frame.imageData);
2181         break;
2182 
2183     case PALETTE_YUV411P:
2184         yuv411p_to_rgb24(capture->form.fmt.pix.width,
2185                  capture->form.fmt.pix.height,
2186                  (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2187                  (unsigned char*)capture->frame.imageData);
2188         break;
2189 #ifdef HAVE_JPEG
2190     case PALETTE_MJPEG:
2191         if (!mjpeg_to_rgb24(capture->form.fmt.pix.width,
2192                     capture->form.fmt.pix.height,
2193                     (unsigned char*)(capture->buffers[capture->bufferIndex]
2194                              .start),
2195                     capture->buffers[capture->bufferIndex].length,
2196                     (unsigned char*)capture->frame.imageData))
2197           return 0;
2198         break;
2199 #endif
2200 
2201     case PALETTE_YUYV:
2202         yuyv_to_rgb24(capture->form.fmt.pix.width,
2203                   capture->form.fmt.pix.height,
2204                   (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2205                   (unsigned char*)capture->frame.imageData);
2206         break;
2207     case PALETTE_UYVY:
2208         uyvy_to_rgb24(capture->form.fmt.pix.width,
2209                   capture->form.fmt.pix.height,
2210                   (unsigned char*)(capture->buffers[capture->bufferIndex].start),
2211                   (unsigned char*)capture->frame.imageData);
2212         break;
2213     case PALETTE_SBGGR8:
2214         bayer2rgb24(capture->form.fmt.pix.width,
2215                 capture->form.fmt.pix.height,
2216                 (unsigned char*)capture->buffers[capture->bufferIndex].start,
2217                 (unsigned char*)capture->frame.imageData);
2218         break;
2219 
2220     case PALETTE_SN9C10X:
2221         sonix_decompress_init();
2222         sonix_decompress(capture->form.fmt.pix.width,
2223                  capture->form.fmt.pix.height,
2224                  (unsigned char*)capture->buffers[capture->bufferIndex].start,
2225                  (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start);
2226 
2227         bayer2rgb24(capture->form.fmt.pix.width,
2228                 capture->form.fmt.pix.height,
2229                 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
2230                 (unsigned char*)capture->frame.imageData);
2231         break;
2232 
2233     case PALETTE_SGBRG:
2234         sgbrg2rgb24(capture->form.fmt.pix.width,
2235                 capture->form.fmt.pix.height,
2236                 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
2237                 (unsigned char*)capture->frame.imageData);
2238         break;
2239     case PALETTE_RGB24:
2240         rgb24_to_rgb24(capture->form.fmt.pix.width,
2241                 capture->form.fmt.pix.height,
2242                 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
2243                 (unsigned char*)capture->frame.imageData);
2244         break;
2245     }
2246   }
2247 #endif /* HAVE_CAMV4L2 */
2248 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2249     else
2250 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2251 #ifdef HAVE_CAMV4L
2252   {
2253 
2254     switch(capture->imageProperties.palette)
2255     {
2256     case VIDEO_PALETTE_RGB24:
2257         memcpy((char *)capture->frame.imageData,
2258            (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2259            capture->frame.imageSize);
2260         break;
2261     case VIDEO_PALETTE_YUV420P:
2262         yuv420p_to_rgb24(capture->captureWindow.width,
2263              capture->captureWindow.height,
2264              (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2265              (unsigned char*)capture->frame.imageData);
2266         break;
2267     case VIDEO_PALETTE_YUV420:
2268         yuv420_to_rgb24(capture->captureWindow.width,
2269           capture->captureWindow.height,
2270           (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2271           (unsigned char*)capture->frame.imageData);
2272         break;
2273     case VIDEO_PALETTE_YUV411P:
2274         yuv411p_to_rgb24(capture->captureWindow.width,
2275           capture->captureWindow.height,
2276           (unsigned char*)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
2277           (unsigned char*)capture->frame.imageData);
2278         break;
2279     default:
2280         fprintf( stderr,
2281                  "VIDEOIO ERROR: V4L: Cannot convert from palette %d to RGB\n",
2282                  capture->imageProperties.palette);
2283 
2284         return 0;
2285     }
2286 
2287   }
2288 #endif /* HAVE_CAMV4L */
2289 
2290    return(&capture->frame);
2291 }
2292 
icvGetPropertyCAM_V4L(CvCaptureCAM_V4L * capture,int property_id)2293 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
2294                                      int property_id ) {
2295 
2296 #ifdef HAVE_CAMV4L2
2297 
2298 #ifdef HAVE_CAMV4L
2299   if (V4L2_SUPPORT == 1)
2300 #endif
2301   {
2302 
2303       /* default value for min and max */
2304       int v4l2_min = 0;
2305       int v4l2_max = 255;
2306 
2307       CLEAR (capture->form);
2308       capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2309       if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
2310           /* display an error message, and return an error code */
2311           perror ("VIDIOC_G_FMT");
2312           return -1;
2313       }
2314 
2315       switch (property_id) {
2316       case CV_CAP_PROP_FRAME_WIDTH:
2317           return capture->form.fmt.pix.width;
2318       case CV_CAP_PROP_FRAME_HEIGHT:
2319           return capture->form.fmt.pix.height;
2320       }
2321 
2322       /* initialize the control structure */
2323 
2324       switch (property_id) {
2325       case CV_CAP_PROP_POS_MSEC:
2326           if (capture->FirstCapture) {
2327             return 0;
2328           } else {
2329             return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
2330           }
2331           break;
2332       case CV_CAP_PROP_BRIGHTNESS:
2333           capture->control.id = V4L2_CID_BRIGHTNESS;
2334           break;
2335       case CV_CAP_PROP_CONTRAST:
2336           capture->control.id = V4L2_CID_CONTRAST;
2337           break;
2338       case CV_CAP_PROP_SATURATION:
2339           capture->control.id = V4L2_CID_SATURATION;
2340           break;
2341       case CV_CAP_PROP_HUE:
2342           capture->control.id = V4L2_CID_HUE;
2343           break;
2344       case CV_CAP_PROP_GAIN:
2345           capture->control.id = V4L2_CID_GAIN;
2346           break;
2347       case CV_CAP_PROP_EXPOSURE:
2348           capture->control.id = V4L2_CID_EXPOSURE;
2349           break;
2350       default:
2351         fprintf(stderr,
2352                 "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n",
2353                 property_id);
2354         return -1;
2355       }
2356 
2357       if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL,
2358                         &capture->control)) {
2359 
2360           fprintf( stderr, "VIDEOIO ERROR: V4L2: ");
2361           switch (property_id) {
2362           case CV_CAP_PROP_BRIGHTNESS:
2363               fprintf (stderr, "Brightness");
2364               break;
2365           case CV_CAP_PROP_CONTRAST:
2366               fprintf (stderr, "Contrast");
2367               break;
2368           case CV_CAP_PROP_SATURATION:
2369               fprintf (stderr, "Saturation");
2370               break;
2371           case CV_CAP_PROP_HUE:
2372               fprintf (stderr, "Hue");
2373               break;
2374           case CV_CAP_PROP_GAIN:
2375               fprintf (stderr, "Gain");
2376               break;
2377           case CV_CAP_PROP_EXPOSURE:
2378               fprintf (stderr, "Exposure");
2379               break;
2380           }
2381           fprintf (stderr, " is not supported by your device\n");
2382 
2383           return -1;
2384       }
2385 
2386       /* get the min/max values */
2387       switch (property_id) {
2388 
2389       case CV_CAP_PROP_BRIGHTNESS:
2390           v4l2_min = capture->v4l2_brightness_min;
2391           v4l2_max = capture->v4l2_brightness_max;
2392           break;
2393       case CV_CAP_PROP_CONTRAST:
2394           v4l2_min = capture->v4l2_contrast_min;
2395           v4l2_max = capture->v4l2_contrast_max;
2396           break;
2397       case CV_CAP_PROP_SATURATION:
2398           v4l2_min = capture->v4l2_saturation_min;
2399           v4l2_max = capture->v4l2_saturation_max;
2400           break;
2401       case CV_CAP_PROP_HUE:
2402           v4l2_min = capture->v4l2_hue_min;
2403           v4l2_max = capture->v4l2_hue_max;
2404           break;
2405       case CV_CAP_PROP_GAIN:
2406           v4l2_min = capture->v4l2_gain_min;
2407           v4l2_max = capture->v4l2_gain_max;
2408           break;
2409       case CV_CAP_PROP_EXPOSURE:
2410           v4l2_min = capture->v4l2_exposure_min;
2411           v4l2_max = capture->v4l2_exposure_max;
2412           break;
2413       }
2414 
2415       /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2416       return ((float)capture->control.value - v4l2_min + 1) / (v4l2_max - v4l2_min);
2417 
2418   }
2419 #endif /* HAVE_CAMV4L2 */
2420 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2421     else
2422 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2423 #ifdef HAVE_CAMV4L
2424   {
2425 
2426     int retval = -1;
2427 
2428     if (ioctl (capture->deviceHandle,
2429                VIDIOCGWIN, &capture->captureWindow) < 0) {
2430         fprintf (stderr,
2431                  "VIDEOIO ERROR: V4L: "
2432                  "Unable to determine size of incoming image\n");
2433         icvCloseCAM_V4L(capture);
2434         return -1;
2435     }
2436 
2437     switch (property_id) {
2438     case CV_CAP_PROP_FRAME_WIDTH:
2439         retval = capture->captureWindow.width;
2440         break;
2441     case CV_CAP_PROP_FRAME_HEIGHT:
2442         retval = capture->captureWindow.height;
2443         break;
2444     case CV_CAP_PROP_BRIGHTNESS:
2445         retval = capture->imageProperties.brightness;
2446         break;
2447     case CV_CAP_PROP_CONTRAST:
2448         retval = capture->imageProperties.contrast;
2449         break;
2450     case CV_CAP_PROP_SATURATION:
2451         retval = capture->imageProperties.colour;
2452         break;
2453     case CV_CAP_PROP_HUE:
2454         retval = capture->imageProperties.hue;
2455         break;
2456     case CV_CAP_PROP_GAIN:
2457         fprintf(stderr,
2458                 "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
2459         return -1;
2460         break;
2461     case CV_CAP_PROP_EXPOSURE:
2462         fprintf(stderr,
2463                 "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
2464         return -1;
2465         break;
2466     default:
2467         fprintf(stderr,
2468                 "VIDEOIO ERROR: V4L: getting property #%d is not supported\n",
2469                 property_id);
2470     }
2471 
2472     if (retval == -1) {
2473         /* there was a problem */
2474         return -1;
2475     }
2476 
2477     /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
2478     return float (retval) / 0xFFFF;
2479 
2480   }
2481 #endif /* HAVE_CAMV4L */
2482 
2483 };
2484 
icvSetVideoSize(CvCaptureCAM_V4L * capture,int w,int h)2485 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
2486 
2487 #ifdef HAVE_CAMV4L2
2488 
2489   if (V4L2_SUPPORT == 1)
2490   {
2491 
2492     CLEAR (capture->cropcap);
2493     capture->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2494 
2495     if (ioctl (capture->deviceHandle, VIDIOC_CROPCAP, &capture->cropcap) < 0) {
2496         fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_CROPCAP\n");
2497     } else {
2498 
2499         CLEAR (capture->crop);
2500         capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2501         capture->crop.c= capture->cropcap.defrect;
2502 
2503         /* set the crop area, but don't exit if the device don't support croping */
2504         if (ioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop) < 0) {
2505             fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: VIDIOC_S_CROP\n");
2506         }
2507     }
2508 
2509     CLEAR (capture->form);
2510     capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2511 
2512     /* read the current setting, mainly to retreive the pixelformat information */
2513     ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
2514 
2515     /* set the values we want to change */
2516     capture->form.fmt.pix.width = w;
2517     capture->form.fmt.pix.height = h;
2518     capture->form.fmt.win.chromakey = 0;
2519     capture->form.fmt.win.field = V4L2_FIELD_ANY;
2520     capture->form.fmt.win.clips = 0;
2521     capture->form.fmt.win.clipcount = 0;
2522     capture->form.fmt.pix.field = V4L2_FIELD_ANY;
2523 
2524     /* ask the device to change the size
2525      * don't test if the set of the size is ok, because some device
2526      * don't allow changing the size, and we will get the real size
2527      * later */
2528     ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
2529 
2530     /* try to set framerate to 30 fps */
2531     struct v4l2_streamparm setfps;
2532     memset (&setfps, 0, sizeof(struct v4l2_streamparm));
2533     setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2534     setfps.parm.capture.timeperframe.numerator = 1;
2535     setfps.parm.capture.timeperframe.denominator = 30;
2536     ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
2537 
2538     /* we need to re-initialize some things, like buffers, because the size has
2539      * changed */
2540     capture->FirstCapture = 1;
2541 
2542     /* Get window info again, to get the real value */
2543     if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
2544     {
2545       fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
2546 
2547       icvCloseCAM_V4L(capture);
2548 
2549       return 0;
2550     }
2551 
2552     return 0;
2553 
2554   }
2555 #endif /* HAVE_CAMV4L2 */
2556 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2557     else
2558 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2559 #ifdef HAVE_CAMV4L
2560   {
2561 
2562     if (capture==0) return 0;
2563      if (w>capture->capability.maxwidth) {
2564        w=capture->capability.maxwidth;
2565      }
2566      if (h>capture->capability.maxheight) {
2567        h=capture->capability.maxheight;
2568      }
2569 
2570      capture->captureWindow.width=w;
2571      capture->captureWindow.height=h;
2572 
2573      if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
2574        icvCloseCAM_V4L(capture);
2575        return 0;
2576      }
2577 
2578      if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
2579        icvCloseCAM_V4L(capture);
2580        return 0;
2581      }
2582 
2583      capture->FirstCapture = 1;
2584 
2585   }
2586 #endif /* HAVE_CAMV4L */
2587 
2588   return 0;
2589 
2590 }
2591 
icvSetControl(CvCaptureCAM_V4L * capture,int property_id,double value)2592 static int icvSetControl (CvCaptureCAM_V4L* capture,
2593                           int property_id, double value) {
2594 
2595   /* limitation of the input value */
2596   if (value < 0.0) {
2597     value = 0.0;
2598   } else if (value > 1.0) {
2599     value = 1.0;
2600   }
2601 
2602 #ifdef HAVE_CAMV4L2
2603 
2604   if (V4L2_SUPPORT == 1)
2605   {
2606 
2607     /* default value for min and max */
2608     int v4l2_min = 0;
2609     int v4l2_max = 255;
2610 
2611     /* initialisations */
2612     CLEAR (capture->control);
2613 
2614     /* set which control we want to set */
2615     switch (property_id) {
2616 
2617     case CV_CAP_PROP_BRIGHTNESS:
2618         capture->control.id = V4L2_CID_BRIGHTNESS;
2619         break;
2620     case CV_CAP_PROP_CONTRAST:
2621         capture->control.id = V4L2_CID_CONTRAST;
2622         break;
2623     case CV_CAP_PROP_SATURATION:
2624         capture->control.id = V4L2_CID_SATURATION;
2625         break;
2626     case CV_CAP_PROP_HUE:
2627         capture->control.id = V4L2_CID_HUE;
2628         break;
2629     case CV_CAP_PROP_GAIN:
2630         capture->control.id = V4L2_CID_GAIN;
2631         break;
2632     case CV_CAP_PROP_EXPOSURE:
2633         capture->control.id = V4L2_CID_EXPOSURE;
2634         break;
2635     default:
2636         fprintf(stderr,
2637                 "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n",
2638                 property_id);
2639         return -1;
2640     }
2641 
2642     /* get the min and max values */
2643     if (-1 == ioctl (capture->deviceHandle,
2644                       VIDIOC_G_CTRL, &capture->control)) {
2645 //          perror ("VIDIOC_G_CTRL for getting min/max values");
2646           return -1;
2647     }
2648 
2649     /* get the min/max values */
2650     switch (property_id) {
2651 
2652     case CV_CAP_PROP_BRIGHTNESS:
2653         v4l2_min = capture->v4l2_brightness_min;
2654         v4l2_max = capture->v4l2_brightness_max;
2655         break;
2656     case CV_CAP_PROP_CONTRAST:
2657         v4l2_min = capture->v4l2_contrast_min;
2658         v4l2_max = capture->v4l2_contrast_max;
2659         break;
2660     case CV_CAP_PROP_SATURATION:
2661         v4l2_min = capture->v4l2_saturation_min;
2662         v4l2_max = capture->v4l2_saturation_max;
2663         break;
2664     case CV_CAP_PROP_HUE:
2665         v4l2_min = capture->v4l2_hue_min;
2666         v4l2_max = capture->v4l2_hue_max;
2667         break;
2668     case CV_CAP_PROP_GAIN:
2669         v4l2_min = capture->v4l2_gain_min;
2670         v4l2_max = capture->v4l2_gain_max;
2671         break;
2672     case CV_CAP_PROP_EXPOSURE:
2673         v4l2_min = capture->v4l2_exposure_min;
2674         v4l2_max = capture->v4l2_exposure_max;
2675         break;
2676     }
2677 
2678     /* initialisations */
2679     CLEAR (capture->control);
2680 
2681     /* set which control we want to set */
2682     switch (property_id) {
2683 
2684     case CV_CAP_PROP_BRIGHTNESS:
2685         capture->control.id = V4L2_CID_BRIGHTNESS;
2686         break;
2687     case CV_CAP_PROP_CONTRAST:
2688         capture->control.id = V4L2_CID_CONTRAST;
2689         break;
2690     case CV_CAP_PROP_SATURATION:
2691         capture->control.id = V4L2_CID_SATURATION;
2692         break;
2693     case CV_CAP_PROP_HUE:
2694         capture->control.id = V4L2_CID_HUE;
2695         break;
2696     case CV_CAP_PROP_GAIN:
2697         capture->control.id = V4L2_CID_GAIN;
2698         break;
2699     case CV_CAP_PROP_EXPOSURE:
2700         capture->control.id = V4L2_CID_EXPOSURE;
2701         break;
2702     default:
2703         fprintf(stderr,
2704                 "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n",
2705                 property_id);
2706         return -1;
2707     }
2708 
2709     /* set the value we want to set to the scaled the value */
2710     capture->control.value = (int)(value * (v4l2_max - v4l2_min) + v4l2_min);
2711 
2712     /* The driver may clamp the value or return ERANGE, ignored here */
2713     if (-1 == ioctl (capture->deviceHandle,
2714                       VIDIOC_S_CTRL, &capture->control) && errno != ERANGE) {
2715         perror ("VIDIOC_S_CTRL");
2716         return -1;
2717     }
2718   }
2719 #endif /* HAVE_CAMV4L2 */
2720 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2721     else
2722 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2723 #ifdef HAVE_CAMV4L
2724   {
2725 
2726     int v4l_value;
2727 
2728     /* scale the value to the wanted integer one */
2729     v4l_value = (int)(0xFFFF * value);
2730 
2731     switch (property_id) {
2732     case CV_CAP_PROP_BRIGHTNESS:
2733       capture->imageProperties.brightness = v4l_value;
2734       break;
2735     case CV_CAP_PROP_CONTRAST:
2736       capture->imageProperties.contrast = v4l_value;
2737       break;
2738     case CV_CAP_PROP_SATURATION:
2739       capture->imageProperties.colour = v4l_value;
2740       break;
2741     case CV_CAP_PROP_HUE:
2742       capture->imageProperties.hue = v4l_value;
2743       break;
2744     case CV_CAP_PROP_GAIN:
2745         fprintf(stderr,
2746                 "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
2747         return -1;
2748     case CV_CAP_PROP_EXPOSURE:
2749         fprintf(stderr,
2750                 "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
2751         return -1;
2752     default:
2753         fprintf(stderr,
2754                 "VIDEOIO ERROR: V4L: property #%d is not supported\n",
2755                 property_id);
2756         return -1;
2757     }
2758 
2759     if (ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties)
2760         < 0)
2761     {
2762        fprintf(stderr,
2763                "VIDEOIO ERROR: V4L: Unable to set video informations\n");
2764        icvCloseCAM_V4L(capture);
2765        return -1;
2766     }
2767   }
2768 #endif /* HAVE_CAMV4L */
2769 
2770   /* all was OK */
2771   return 0;
2772 
2773 }
2774 
icvSetPropertyCAM_V4L(CvCaptureCAM_V4L * capture,int property_id,double value)2775 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
2776                                   int property_id, double value ){
2777     static int width = 0, height = 0;
2778     int retval;
2779 
2780     /* initialization */
2781     retval = 0;
2782 
2783     /* two subsequent calls setting WIDTH and HEIGHT will change
2784        the video size */
2785     /* the first one will return an error, though. */
2786 
2787     switch (property_id) {
2788     case CV_CAP_PROP_FRAME_WIDTH:
2789         width = cvRound(value);
2790         if(width !=0 && height != 0) {
2791             retval = icvSetVideoSize( capture, width, height);
2792             width = height = 0;
2793         }
2794         break;
2795     case CV_CAP_PROP_FRAME_HEIGHT:
2796         height = cvRound(value);
2797         if(width !=0 && height != 0) {
2798             retval = icvSetVideoSize( capture, width, height);
2799             width = height = 0;
2800         }
2801         break;
2802     case CV_CAP_PROP_BRIGHTNESS:
2803     case CV_CAP_PROP_CONTRAST:
2804     case CV_CAP_PROP_SATURATION:
2805     case CV_CAP_PROP_HUE:
2806     case CV_CAP_PROP_GAIN:
2807     case CV_CAP_PROP_EXPOSURE:
2808         retval = icvSetControl(capture, property_id, value);
2809         break;
2810     default:
2811         fprintf(stderr,
2812                 "VIDEOIO ERROR: V4L: setting property #%d is not supported\n",
2813                 property_id);
2814     }
2815 
2816     /* return the the status */
2817     return retval;
2818 }
2819 
icvCloseCAM_V4L(CvCaptureCAM_V4L * capture)2820 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
2821    /* Deallocate space - Hopefully, no leaks */
2822 
2823    if (capture)
2824    {
2825 
2826 #ifdef HAVE_CAMV4L2
2827      if (V4L2_SUPPORT == 0)
2828 #endif /* HAVE_CAMV4L2 */
2829 #ifdef HAVE_CAMV4L
2830      {
2831 
2832        if (capture->mmaps)
2833          free(capture->mmaps);
2834        if (capture->memoryMap)
2835          munmap(capture->memoryMap, capture->memoryBuffer.size);
2836 
2837      }
2838 #endif /* HAVE_CAMV4L */
2839 #if defined(HAVE_CAMV4L) && defined(HAVE_CAMV4L2)
2840      else
2841 #endif /* HAVE_CAMV4L && HAVE_CAMV4L2 */
2842 #ifdef HAVE_CAMV4L2
2843        {
2844        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2845        if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) {
2846            perror ("Unable to stop the stream.");
2847        }
2848 
2849        for (unsigned int n_buffers_ = 0; n_buffers_ < capture->req.count; ++n_buffers_)
2850        {
2851            if (-1 == munmap (capture->buffers[n_buffers_].start, capture->buffers[n_buffers_].length)) {
2852                perror ("munmap");
2853            }
2854        }
2855 
2856        if (capture->buffers[MAX_V4L_BUFFERS].start)
2857        {
2858            free(capture->buffers[MAX_V4L_BUFFERS].start);
2859            capture->buffers[MAX_V4L_BUFFERS].start = 0;
2860        }
2861      }
2862 #endif /* HAVE_CAMV4L2 */
2863 
2864      if (capture->deviceHandle != -1)
2865        close(capture->deviceHandle);
2866 
2867      if (capture->frame.imageData) cvFree(&capture->frame.imageData);
2868       //cvFree((void **)capture);
2869    }
2870 };
2871 
2872 
2873 class CvCaptureCAM_V4L_CPP : CvCapture
2874 {
2875 public:
CvCaptureCAM_V4L_CPP()2876     CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
~CvCaptureCAM_V4L_CPP()2877     virtual ~CvCaptureCAM_V4L_CPP() { close(); }
2878 
2879     virtual bool open( int index );
2880     virtual void close();
2881 
2882     virtual double getProperty(int) const;
2883     virtual bool setProperty(int, double);
2884     virtual bool grabFrame();
2885     virtual IplImage* retrieveFrame(int);
2886 protected:
2887 
2888     CvCaptureCAM_V4L* captureV4L;
2889 };
2890 
open(int index)2891 bool CvCaptureCAM_V4L_CPP::open( int index )
2892 {
2893     close();
2894     captureV4L = icvCaptureFromCAM_V4L(index);
2895     return captureV4L != 0;
2896 }
2897 
close()2898 void CvCaptureCAM_V4L_CPP::close()
2899 {
2900     if( captureV4L )
2901     {
2902         icvCloseCAM_V4L( captureV4L );
2903         cvFree( &captureV4L );
2904     }
2905 }
2906 
grabFrame()2907 bool CvCaptureCAM_V4L_CPP::grabFrame()
2908 {
2909     return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
2910 }
2911 
retrieveFrame(int)2912 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
2913 {
2914     return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
2915 }
2916 
getProperty(int propId) const2917 double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const
2918 {
2919     return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
2920 }
2921 
setProperty(int propId,double value)2922 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
2923 {
2924     return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
2925 }
2926 
cvCreateCameraCapture_V4L(int index)2927 CvCapture* cvCreateCameraCapture_V4L( int index )
2928 {
2929     CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
2930 
2931     if( capture->open( index ))
2932         return (CvCapture*)capture;
2933 
2934     delete capture;
2935     return 0;
2936 }
2937 
2938 #endif
2939