Home | History | Annotate | Download | only in src
      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 (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 (at) ls-a.jp> with his pleasure :)
    116   - Tested successfully with Genius VideoCam Notebook (V4L2)
    117 
    118 Sixth Patch: Sept 10, 2005 Csaba Kertesz sign (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 (at) 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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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
   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
   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
   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
   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
   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
   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
   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
   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 (at) ls-a.jp>
   1759  *
   1760  */
   1761 
   1762 #ifdef HAVE_CAMV4L2
   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/
   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
   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 */
   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 */
   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 
   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 
   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 
   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 
   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 
   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 
   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:
   2876     CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
   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 
   2891 bool CvCaptureCAM_V4L_CPP::open( int index )
   2892 {
   2893     close();
   2894     captureV4L = icvCaptureFromCAM_V4L(index);
   2895     return captureV4L != 0;
   2896 }
   2897 
   2898 void CvCaptureCAM_V4L_CPP::close()
   2899 {
   2900     if( captureV4L )
   2901     {
   2902         icvCloseCAM_V4L( captureV4L );
   2903         cvFree( &captureV4L );
   2904     }
   2905 }
   2906 
   2907 bool CvCaptureCAM_V4L_CPP::grabFrame()
   2908 {
   2909     return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
   2910 }
   2911 
   2912 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
   2913 {
   2914     return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
   2915 }
   2916 
   2917 double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const
   2918 {
   2919     return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
   2920 }
   2921 
   2922 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
   2923 {
   2924     return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
   2925 }
   2926 
   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