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: Apr 13, 2010, Filipe Almeida filipe.almeida (at) ist.utl.pt
    160 - Tries to setup all properties first through v4l2_ioctl call.
    161 - Allows setting up all Video4Linux properties through cvSetCaptureProperty instead of only CV_CAP_PROP_BRIGHTNESS, CV_CAP_PROP_CONTRAST, CV_CAP_PROP_SATURATION, CV_CAP_PROP_HUE, CV_CAP_PROP_GAIN and CV_CAP_PROP_EXPOSURE.
    162 
    163 12th patch: Apr 16, 2010, Filipe Almeida filipe.almeida (at) ist.utl.pt
    164 - CvCaptureCAM_V4L structure cleanup (no longer needs <PROPERTY>_{min,max,} variables)
    165 - Introduction of v4l2_ctrl_range - minimum and maximum allowed values for v4l controls
    166 - Allows setting up all Video4Linux properties through cvSetCaptureProperty using input values between 0.0 and 1.0
    167 - Gets v4l properties first through v4l2_ioctl call (ignores capture->is_v4l2_device)
    168 - cvGetCaptureProperty adjusted to support the changes
    169 - Returns device properties to initial values after device closes
    170 
    171 13th patch: Apr 27, 2010, Filipe Almeida filipe.almeida (at) ist.utl.pt
    172 - Solved problem mmaping the device using uvcvideo driver (use o v4l2_mmap instead of mmap)
    173 make & enjoy!
    174 
    175 14th patch: May 10, 2010, Filipe Almeida filipe.almeida (at) ist.utl.pt
    176 - Bug #142: Solved/Workaround "setting frame width and height does not work"
    177   There was a problem setting up the size when the input is a v4l2 device
    178   The workaround closes the camera and reopens it with the new definition
    179   Planning for future rewrite of this whole library (July/August 2010)
    180 
    181 15th patch: May 12, 2010, Filipe Almeida filipe.almeida (at) ist.utl.pt
    182 - Broken compile of library (include "_videoio.h")
    183 
    184 16th patch: Dec 16, 2014, Joseph Howse josephhowse (at) nummist.com
    185 - Allow getting/setting CV_CAP_PROP_MODE. These values are supported:
    186     - CV_CAP_MODE_BGR  : BGR24 (default)
    187     - CV_CAP_MODE_RGB  : RGB24
    188     - CV_CAP_MODE_GRAY : Y8, extracted from YUV420
    189 - Tested successfully on these cameras:
    190     - PlayStation 3 Eye
    191     - Logitech C920
    192     - Odroid USB-CAM 720P
    193 
    194 17th patch: May 9, 2015, Matt Sandler
    195  added supported for CV_CAP_PROP_POS_MSEC, CV_CAP_PROP_POS_FRAMES, CV_CAP_PROP_FPS
    196 
    197 */
    198 
    199 /*M///////////////////////////////////////////////////////////////////////////////////////
    200 //
    201 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
    202 //
    203 //  By downloading, copying, installing or using the software you agree to this license.
    204 //  If you do not agree to this license, do not download, install,
    205 //  copy or use the software.
    206 //
    207 //
    208 //                        Intel License Agreement
    209 //                For Open Source Computer Vision Library
    210 //
    211 // Copyright (C) 2000, Intel Corporation, all rights reserved.
    212 // Third party copyrights are property of their respective owners.
    213 //
    214 // Redistribution and use in source and binary forms, with or without modification,
    215 // are permitted provided that the following conditions are met:
    216 //
    217 //   * Redistribution's of source code must retain the above copyright notice,
    218 //     this list of conditions and the following disclaimer.
    219 //
    220 //   * Redistribution's in binary form must reproduce the above copyright notice,
    221 //     this list of conditions and the following disclaimer in the documentation
    222 //     and/or other materials provided with the distribution.
    223 //
    224 //   * The name of Intel Corporation may not be used to endorse or promote products
    225 //     derived from this software without specific prior written permission.
    226 //
    227 // This software is provided by the copyright holders and contributors "as is" and
    228 // any express or implied warranties, including, but not limited to, the implied
    229 // warranties of merchantability and fitness for a particular purpose are disclaimed.
    230 // In no event shall the Intel Corporation or contributors be liable for any direct,
    231 // indirect, incidental, special, exemplary, or consequential damages
    232 // (including, but not limited to, procurement of substitute goods or services;
    233 // loss of use, data, or profits; or business interruption) however caused
    234 // and on any theory of liability, whether in contract, strict liability,
    235 // or tort (including negligence or otherwise) arising in any way out of
    236 // the use of this software, even if advised of the possibility of such damage.
    237 //
    238 //M*/
    239 
    240 #include "precomp.hpp"
    241 
    242 #if !defined WIN32 && defined HAVE_LIBV4L
    243 
    244 #define CLEAR(x) memset (&(x), 0, sizeof (x))
    245 
    246 #include <stdio.h>
    247 #include <unistd.h>
    248 #include <fcntl.h>
    249 #include <errno.h>
    250 #include <sys/types.h>
    251 #include <sys/mman.h>
    252 #include <string.h>
    253 #include <stdlib.h>
    254 #include <asm/types.h>          /* for videodev2.h */
    255 #include <assert.h>
    256 #include <sys/stat.h>
    257 #include <sys/ioctl.h>
    258 
    259 #ifdef HAVE_CAMV4L
    260 #include <linux/videodev.h>
    261 #endif
    262 #ifdef HAVE_CAMV4L2
    263 #include <linux/videodev2.h>
    264 #endif
    265 
    266 #include <libv4l1.h>
    267 #include <libv4l2.h>
    268 
    269 /* Defaults - If your board can do better, set it here.  Set for the most common type inputs. */
    270 #define DEFAULT_V4L_WIDTH  640
    271 #define DEFAULT_V4L_HEIGHT 480
    272 
    273 #define CHANNEL_NUMBER 1
    274 #define MAX_CAMERAS 8
    275 
    276 
    277 // default and maximum number of V4L buffers, not including last, 'special' buffer
    278 #define MAX_V4L_BUFFERS 10
    279 #define DEFAULT_V4L_BUFFERS 4
    280 
    281 // if enabled, copies data from the buffer. this uses a bit more memory,
    282 //  but much more reliable for some UVC cameras
    283 #define USE_TEMP_BUFFER
    284 
    285 #define MAX_DEVICE_DRIVER_NAME 80
    286 
    287 /* Device Capture Objects */
    288 /* V4L2 structure */
    289 struct buffer
    290 {
    291   void *  start;
    292   size_t  length;
    293 };
    294 static unsigned int n_buffers = 0;
    295 
    296 /* TODO: Dilemas: */
    297 /* TODO: Consider drop the use of this data structure and perform ioctl to obtain needed values */
    298 /* TODO: Consider at program exit return controls to the initial values - See v4l2_free_ranges function */
    299 /* TODO: Consider at program exit reset the device to default values - See v4l2_free_ranges function */
    300 typedef struct v4l2_ctrl_range {
    301   __u32 ctrl_id;
    302   __s32 initial_value;
    303   __s32 current_value;
    304   __s32 minimum;
    305   __s32 maximum;
    306   __s32 default_value;
    307 } v4l2_ctrl_range;
    308 
    309 typedef struct CvCaptureCAM_V4L
    310 {
    311     char* deviceName;
    312     int deviceHandle;
    313     int bufferIndex;
    314     int FirstCapture;
    315 
    316     int width; int height;
    317     int mode;
    318 
    319     struct video_capability capability;
    320     struct video_window     captureWindow;
    321     struct video_picture    imageProperties;
    322     struct video_mbuf       memoryBuffer;
    323     struct video_mmap       *mmaps;
    324     char *memoryMap;
    325     IplImage frame;
    326 
    327    /* V4L2 variables */
    328    buffer buffers[MAX_V4L_BUFFERS + 1];
    329    struct v4l2_capability cap;
    330    struct v4l2_input inp;
    331    struct v4l2_format form;
    332    struct v4l2_crop crop;
    333    struct v4l2_cropcap cropcap;
    334    struct v4l2_requestbuffers req;
    335    struct v4l2_jpegcompression compr;
    336    struct v4l2_control control;
    337    enum v4l2_buf_type type;
    338    struct v4l2_queryctrl queryctrl;
    339 
    340    struct timeval timestamp;
    341 
    342    /** value set the buffer of V4L*/
    343    int sequence;
    344 
    345    /* V4L2 control variables */
    346    v4l2_ctrl_range** v4l2_ctrl_ranges;
    347    int v4l2_ctrl_count;
    348 
    349    int is_v4l2_device;
    350 }
    351 CvCaptureCAM_V4L;
    352 
    353 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
    354 
    355 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
    356 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
    357 CvCapture* cvCreateCameraCapture_V4L( int index );
    358 
    359 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
    360 static int    icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
    361 
    362 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
    363 
    364 /***********************   Implementations  ***************************************/
    365 
    366 static int numCameras = 0;
    367 static int indexList = 0;
    368 
    369 // IOCTL handling for V4L2
    370 #ifdef HAVE_IOCTL_ULONG
    371 static int xioctl( int fd, unsigned long request, void *arg)
    372 #else
    373 static int xioctl( int fd, int request, void *arg)
    374 #endif
    375 {
    376 
    377   int r;
    378 
    379 
    380   do r = v4l2_ioctl (fd, request, arg);
    381   while (-1 == r && EINTR == errno);
    382 
    383   return r;
    384 
    385 }
    386 
    387 
    388 /* Simple test program: Find number of Video Sources available.
    389    Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
    390    If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
    391    Returns the global numCameras with the correct value (we hope) */
    392 
    393 static void icvInitCapture_V4L() {
    394    int deviceHandle;
    395    int CameraNumber;
    396    char deviceName[MAX_DEVICE_DRIVER_NAME];
    397 
    398    CameraNumber = 0;
    399    while(CameraNumber < MAX_CAMERAS) {
    400       /* Print the CameraNumber at the end of the string with a width of one character */
    401       sprintf(deviceName, "/dev/video%1d", CameraNumber);
    402       /* Test using an open to see if this new device name really does exists. */
    403       deviceHandle = open(deviceName, O_RDONLY);
    404       if (deviceHandle != -1) {
    405          /* This device does indeed exist - add it to the total so far */
    406     // add indexList
    407     indexList|=(1 << CameraNumber);
    408         numCameras++;
    409     }
    410     if (deviceHandle != -1)
    411       close(deviceHandle);
    412       /* Set up to test the next /dev/video source in line */
    413       CameraNumber++;
    414    } /* End while */
    415 
    416 }; /* End icvInitCapture_V4L */
    417 
    418 
    419 static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
    420 
    421 {
    422 
    423   // if detect = -1 then unable to open device
    424   // if detect = 0 then detected nothing
    425   // if detect = 1 then V4L device
    426   int detect = 0;
    427 
    428 
    429   // Test device for V4L compability
    430 
    431   /* Test using an open to see if this new device name really does exists. */
    432   /* No matter what the name - it still must be opened! */
    433   capture->deviceHandle = v4l1_open(deviceName, O_RDWR);
    434 
    435 
    436   if (capture->deviceHandle == 0)
    437   {
    438     detect = -1;
    439 
    440     icvCloseCAM_V4L(capture);
    441   }
    442 
    443   if (detect == 0)
    444   {
    445     /* Query the newly opened device for its capabilities */
    446     if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
    447     {
    448       detect = 0;
    449 
    450       icvCloseCAM_V4L(capture);
    451     }
    452       else
    453     {
    454       detect = 1;
    455     }
    456   }
    457 
    458   return detect;
    459 
    460 }
    461 
    462 
    463 static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
    464 {
    465 
    466   // if detect = -1 then unable to open device
    467   // if detect = 0 then detected nothing
    468   // if detect = 1 then V4L2 device
    469   int detect = 0;
    470 
    471 
    472   // Test device for V4L2 compability
    473 
    474   /* Open and test V4L2 device */
    475   capture->deviceHandle = v4l2_open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
    476 
    477 
    478 
    479   if (capture->deviceHandle == 0)
    480   {
    481     detect = -1;
    482 
    483     icvCloseCAM_V4L(capture);
    484   }
    485 
    486   if (detect == 0)
    487   {
    488     CLEAR (capture->cap);
    489     if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
    490     {
    491       detect = 0;
    492 
    493       icvCloseCAM_V4L(capture);
    494     }
    495       else
    496     {
    497       CLEAR (capture->capability);
    498       capture->capability.type = capture->cap.capabilities;
    499 
    500       /* Query channels number */
    501       if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
    502       {
    503         detect = 1;
    504       }
    505     }
    506   }
    507 
    508   return detect;
    509 
    510 }
    511 
    512 
    513 static void v4l2_free_ranges(CvCaptureCAM_V4L* capture) {
    514   int i;
    515   if (capture->v4l2_ctrl_ranges != NULL) {
    516     for (i = 0; i < capture->v4l2_ctrl_count; i++) {
    517       /* Return device to initial values: */
    518       /* double value = (capture->v4l2_ctrl_ranges[i]->initial_value == 0)?0.0:((float)capture->v4l2_ctrl_ranges[i]->initial_value - capture->v4l2_ctrl_ranges[i]->minimum) / (capture->v4l2_ctrl_ranges[i]->maximum - capture->v4l2_ctrl_ranges[i]->minimum); */
    519       /* Return device to default values: */
    520       /* double value = (capture->v4l2_ctrl_ranges[i]->default_value == 0)?0.0:((float)capture->v4l2_ctrl_ranges[i]->default_value - capture->v4l2_ctrl_ranges[i]->minimum + 1) / (capture->v4l2_ctrl_ranges[i]->maximum - capture->v4l2_ctrl_ranges[i]->minimum); */
    521 
    522       /* icvSetPropertyCAM_V4L(capture, capture->v4l2_ctrl_ranges[i]->ctrl_id, value); */
    523       free(capture->v4l2_ctrl_ranges[i]);
    524     }
    525   }
    526   free(capture->v4l2_ctrl_ranges);
    527   capture->v4l2_ctrl_count  = 0;
    528   capture->v4l2_ctrl_ranges = NULL;
    529 }
    530 
    531 static void v4l2_add_ctrl_range(CvCaptureCAM_V4L* capture, v4l2_control* ctrl) {
    532   v4l2_ctrl_range* range    = (v4l2_ctrl_range*)malloc(sizeof(v4l2_ctrl_range));
    533   range->ctrl_id            = ctrl->id;
    534   range->initial_value      = ctrl->value;
    535   range->current_value      = ctrl->value;
    536   range->minimum            = capture->queryctrl.minimum;
    537   range->maximum            = capture->queryctrl.maximum;
    538   range->default_value      = capture->queryctrl.default_value;
    539   capture->v4l2_ctrl_ranges[capture->v4l2_ctrl_count] = range;
    540   capture->v4l2_ctrl_count += 1;
    541   capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)realloc((v4l2_ctrl_range**)capture->v4l2_ctrl_ranges, (capture->v4l2_ctrl_count + 1) * sizeof(v4l2_ctrl_range*));
    542 }
    543 
    544 static int v4l2_get_ctrl_default(CvCaptureCAM_V4L* capture, __u32 id) {
    545   int i;
    546   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
    547     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
    548       return capture->v4l2_ctrl_ranges[i]->default_value;
    549     }
    550   }
    551   return -1;
    552 }
    553 
    554 static int v4l2_get_ctrl_min(CvCaptureCAM_V4L* capture, __u32 id) {
    555   int i;
    556   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
    557     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
    558       return capture->v4l2_ctrl_ranges[i]->minimum;
    559     }
    560   }
    561   return -1;
    562 }
    563 
    564 static int v4l2_get_ctrl_max(CvCaptureCAM_V4L* capture, __u32 id) {
    565   int i;
    566   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
    567     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
    568       return capture->v4l2_ctrl_ranges[i]->maximum;
    569     }
    570   }
    571   return -1;
    572 }
    573 
    574 
    575 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) {
    576 
    577   __u32 ctrl_id;
    578   struct v4l2_control c;
    579   if (capture->v4l2_ctrl_ranges != NULL) {
    580     v4l2_free_ranges(capture);
    581   }
    582   capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)malloc(sizeof(v4l2_ctrl_range*));
    583 #ifdef V4L2_CTRL_FLAG_NEXT_CTRL
    584   /* Try the extended control API first */
    585   capture->queryctrl.id      = V4L2_CTRL_FLAG_NEXT_CTRL;
    586   if(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl)) {
    587     do {
    588       c.id = capture->queryctrl.id;
    589       capture->queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
    590       if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
    591         continue;
    592       }
    593       if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
    594          capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
    595          capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
    596         continue;
    597       }
    598       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
    599         v4l2_add_ctrl_range(capture, &c);
    600       }
    601 
    602     } while(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl));
    603   } else
    604 #endif
    605   {
    606     /* Check all the standard controls */
    607     for(ctrl_id=V4L2_CID_BASE; ctrl_id<V4L2_CID_LASTP1; ctrl_id++) {
    608       capture->queryctrl.id = ctrl_id;
    609       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
    610         if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
    611           continue;
    612         }
    613         if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
    614            capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
    615            capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
    616           continue;
    617         }
    618         c.id = ctrl_id;
    619 
    620         if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
    621           v4l2_add_ctrl_range(capture, &c);
    622         }
    623       }
    624     }
    625 
    626     /* Check any custom controls */
    627     for(ctrl_id=V4L2_CID_PRIVATE_BASE; ; ctrl_id++) {
    628       capture->queryctrl.id = ctrl_id;
    629       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
    630         if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
    631           continue;
    632         }
    633 
    634 
    635         if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
    636            capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
    637            capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
    638            continue;
    639         }
    640 
    641         c.id = ctrl_id;
    642 
    643         if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
    644           v4l2_add_ctrl_range(capture, &c);
    645         }
    646       } else {
    647         break;
    648       }
    649     }
    650   }
    651 }
    652 
    653 static inline int channels_for_mode(int mode)
    654 {
    655     switch(mode) {
    656     case CV_CAP_MODE_GRAY:
    657         return 1;
    658     case CV_CAP_MODE_YUYV:
    659         return 2;
    660     default:
    661         return 3;
    662     }
    663 }
    664 
    665 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
    666 {
    667    int detect_v4l2 = 0;
    668 
    669    capture->deviceName = strdup(deviceName);
    670 
    671    detect_v4l2 = try_init_v4l2(capture, deviceName);
    672 
    673    if (detect_v4l2 != 1) {
    674        /* init of the v4l2 device is not OK */
    675        return -1;
    676    }
    677 
    678    /* starting from here, we assume we are in V4L2 mode */
    679    capture->is_v4l2_device = 1;
    680 
    681    capture->v4l2_ctrl_ranges = NULL;
    682    capture->v4l2_ctrl_count = 0;
    683 
    684    /* Scan V4L2 controls */
    685    v4l2_scan_controls(capture);
    686 
    687    if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
    688       /* Nope. */
    689       fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
    690       icvCloseCAM_V4L(capture);
    691       return -1;
    692    }
    693 
    694    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
    695    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
    696    I myself am using a simple NTSC video input capture card that uses the value of 1.
    697    If you are not in North America or have a different video standard, you WILL have to change
    698    the following settings and recompile/reinstall.  This set of settings is based on
    699    the most commonly encountered input video source types (like my bttv card) */
    700 
    701    if(capture->inp.index > 0) {
    702        CLEAR (capture->inp);
    703        capture->inp.index = CHANNEL_NUMBER;
    704        /* Set only channel number to CHANNEL_NUMBER */
    705        /* V4L2 have a status field from selected video mode */
    706        if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
    707        {
    708          fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
    709          icvCloseCAM_V4L (capture);
    710          return -1;
    711        }
    712    } /* End if */
    713 
    714    /* Find Window info */
    715    CLEAR (capture->form);
    716    capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    717 
    718    if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
    719        fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
    720        icvCloseCAM_V4L(capture);
    721        return -1;
    722    }
    723 
    724   /* libv4l will convert from any format to V4L2_PIX_FMT_BGR24,
    725      V4L2_PIX_FMT_RGV24, or V4L2_PIX_FMT_YUV420 */
    726   unsigned int requestedPixelFormat;
    727   switch (capture->mode) {
    728   case CV_CAP_MODE_RGB:
    729     requestedPixelFormat = V4L2_PIX_FMT_RGB24;
    730     break;
    731   case CV_CAP_MODE_GRAY:
    732     requestedPixelFormat = V4L2_PIX_FMT_YUV420;
    733     break;
    734   case CV_CAP_MODE_YUYV:
    735     requestedPixelFormat = V4L2_PIX_FMT_YUYV;
    736     break;
    737   default:
    738     requestedPixelFormat = V4L2_PIX_FMT_BGR24;
    739     break;
    740   }
    741   CLEAR (capture->form);
    742   capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    743   capture->form.fmt.pix.pixelformat = requestedPixelFormat;
    744   capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
    745   capture->form.fmt.pix.width       = capture->width;
    746   capture->form.fmt.pix.height      = capture->height;
    747 
    748   if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
    749       fprintf(stderr, "VIDEOIO ERROR: libv4l unable to ioctl S_FMT\n");
    750       return -1;
    751   }
    752 
    753   if (requestedPixelFormat != capture->form.fmt.pix.pixelformat) {
    754       fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n");
    755       return -1;
    756   }
    757 
    758    /* icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); */
    759 
    760    unsigned int min;
    761 
    762    /* Buggy driver paranoia. */
    763    min = capture->form.fmt.pix.width * 2;
    764 
    765    if (capture->form.fmt.pix.bytesperline < min)
    766        capture->form.fmt.pix.bytesperline = min;
    767 
    768    min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
    769 
    770    if (capture->form.fmt.pix.sizeimage < min)
    771        capture->form.fmt.pix.sizeimage = min;
    772 
    773    CLEAR (capture->req);
    774 
    775    unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
    776 
    777    try_again:
    778 
    779    capture->req.count = buffer_number;
    780    capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    781    capture->req.memory = V4L2_MEMORY_MMAP;
    782 
    783    if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
    784    {
    785        if (EINVAL == errno)
    786        {
    787          fprintf (stderr, "%s does not support memory mapping\n", deviceName);
    788        } else {
    789          perror ("VIDIOC_REQBUFS");
    790        }
    791        /* free capture, and returns an error code */
    792        icvCloseCAM_V4L (capture);
    793        return -1;
    794    }
    795 
    796    if (capture->req.count < buffer_number)
    797    {
    798        if (buffer_number == 1)
    799        {
    800            fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
    801 
    802            /* free capture, and returns an error code */
    803            icvCloseCAM_V4L (capture);
    804            return -1;
    805        } else {
    806          buffer_number--;
    807    fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
    808 
    809    goto try_again;
    810        }
    811    }
    812 
    813    for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
    814    {
    815        struct v4l2_buffer buf;
    816 
    817        CLEAR (buf);
    818 
    819        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    820        buf.memory = V4L2_MEMORY_MMAP;
    821        buf.index = n_buffers;
    822 
    823        if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
    824            perror ("VIDIOC_QUERYBUF");
    825 
    826            /* free capture, and returns an error code */
    827            icvCloseCAM_V4L (capture);
    828            return -1;
    829        }
    830 
    831        capture->buffers[n_buffers].length = buf.length;
    832        capture->buffers[n_buffers].start =
    833          v4l2_mmap (NULL /* start anywhere */,
    834                     buf.length,
    835                     PROT_READ | PROT_WRITE /* required */,
    836                     MAP_SHARED /* recommended */,
    837                     capture->deviceHandle, buf.m.offset);
    838 
    839        if (MAP_FAILED == capture->buffers[n_buffers].start) {
    840            perror ("mmap");
    841 
    842            /* free capture, and returns an error code */
    843            icvCloseCAM_V4L (capture);
    844            return -1;
    845        }
    846 
    847 #ifdef USE_TEMP_BUFFER
    848        if (n_buffers == 0) {
    849            if (capture->buffers[MAX_V4L_BUFFERS].start) {
    850                free(capture->buffers[MAX_V4L_BUFFERS].start);
    851                capture->buffers[MAX_V4L_BUFFERS].start = NULL;
    852        }
    853 
    854            capture->buffers[MAX_V4L_BUFFERS].start = malloc(buf.length);
    855            capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
    856        };
    857 #endif
    858    }
    859 
    860    /* Set up Image data */
    861    cvInitImageHeader( &capture->frame,
    862                       cvSize( capture->captureWindow.width,
    863                               capture->captureWindow.height ),
    864                       IPL_DEPTH_8U, channels_for_mode(capture->mode),
    865                       IPL_ORIGIN_TL, 4 );
    866    /* Allocate space for RGBA data */
    867    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
    868 
    869    return 1;
    870 }; /* End _capture_V4L2 */
    871 
    872 
    873 static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
    874 {
    875    int detect_v4l = 0;
    876 
    877    detect_v4l = try_init_v4l(capture, deviceName);
    878 
    879    if (detect_v4l == -1)
    880    {
    881      fprintf (stderr, "VIDEOIO ERROR: V4L"
    882               ": device %s: Unable to open for READ ONLY\n", deviceName);
    883 
    884      return -1;
    885    }
    886 
    887    if (detect_v4l <= 0)
    888    {
    889      fprintf (stderr, "VIDEOIO ERROR: V4L"
    890               ": device %s: Unable to query number of channels\n", deviceName);
    891 
    892      return -1;
    893    }
    894 
    895    {
    896      if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
    897        /* Nope. */
    898        fprintf( stderr, "VIDEOIO ERROR: V4L: "
    899                 "device %s is unable to capture video memory.\n",deviceName);
    900        icvCloseCAM_V4L(capture);
    901        return -1;
    902      }
    903 
    904    }
    905 
    906 
    907    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
    908    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
    909    I myself am using a simple NTSC video input capture card that uses the value of 1.
    910    If you are not in North America or have a different video standard, you WILL have to change
    911    the following settings and recompile/reinstall.  This set of settings is based on
    912    the most commonly encountered input video source types (like my bttv card) */
    913 
    914    {
    915 
    916      if(capture->capability.channels>0) {
    917 
    918        struct video_channel selectedChannel;
    919 
    920        selectedChannel.channel=CHANNEL_NUMBER;
    921        if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
    922           /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
    923 //           selectedChannel.norm = VIDEO_MODE_NTSC;
    924           if (v4l1_ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
    925              /* Could not set selected channel - Oh well */
    926              //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
    927           } /* End if */
    928        } /* End if */
    929      } /* End if */
    930 
    931    }
    932 
    933    {
    934 
    935      if(v4l1_ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
    936        fprintf( stderr, "VIDEOIO ERROR: V4L: "
    937                 "Could not obtain specifics of capture window.\n\n");
    938        icvCloseCAM_V4L(capture);
    939        return -1;
    940      }
    941 
    942    }
    943 
    944    {
    945       if(v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
    946          fprintf( stderr, "VIDEOIO ERROR: V4L: Unable to determine size of incoming image\n");
    947          icvCloseCAM_V4L(capture);
    948          return -1;
    949       }
    950 
    951       int requestedVideoPalette;
    952       int depth;
    953       switch (capture->mode) {
    954       case CV_CAP_MODE_GRAY:
    955         requestedVideoPalette = VIDEO_PALETTE_YUV420;
    956         depth = 8;
    957         break;
    958       case CV_CAP_MODE_YUYV:
    959         requestedVideoPalette = VIDEO_PALETTE_YUYV;
    960         depth = 16;
    961         break;
    962       default:
    963         requestedVideoPalette = VIDEO_PALETTE_RGB24;
    964         depth = 24;
    965         break;
    966       }
    967       capture->imageProperties.depth = depth;
    968       capture->imageProperties.palette = requestedVideoPalette;
    969       if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) {
    970         fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n");
    971         icvCloseCAM_V4L(capture);
    972         return -1;
    973       }
    974       if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
    975         fprintf( stderr, "VIDEOIO ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n");
    976         icvCloseCAM_V4L(capture);
    977         return -1;
    978       }
    979       if (capture->imageProperties.palette != requestedVideoPalette) {
    980         fprintf( stderr, "VIDEOIO ERROR: libv4l unable convert to requested pixfmt\n\n");
    981         icvCloseCAM_V4L(capture);
    982         return -1;
    983       }
    984 
    985    }
    986 
    987    {
    988 
    989      v4l1_ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
    990      capture->memoryMap  = (char *)v4l1_mmap(0,
    991                                    capture->memoryBuffer.size,
    992                                    PROT_READ | PROT_WRITE,
    993                                    MAP_SHARED,
    994                                    capture->deviceHandle,
    995                                    0);
    996      if (capture->memoryMap == MAP_FAILED) {
    997         fprintf( stderr, "VIDEOIO ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
    998         icvCloseCAM_V4L(capture);
    999         return -1;
   1000      }
   1001 
   1002      /* Set up video_mmap structure pointing to this memory mapped area so each image may be
   1003         retrieved from an index value */
   1004      capture->mmaps = (struct video_mmap *)
   1005                  (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
   1006      if (!capture->mmaps) {
   1007         fprintf( stderr, "VIDEOIO ERROR: V4L: Could not memory map video frames.\n");
   1008         icvCloseCAM_V4L(capture);
   1009         return -1;
   1010      }
   1011 
   1012    }
   1013 
   1014    /* Set up Image data */
   1015    cvInitImageHeader( &capture->frame,
   1016                       cvSize( capture->captureWindow.width,
   1017                               capture->captureWindow.height ),
   1018                       IPL_DEPTH_8U, channels_for_mode(capture->mode),
   1019                       IPL_ORIGIN_TL, 4 );
   1020    /* Allocate space for RGBA data */
   1021    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
   1022 
   1023    return 1;
   1024 }; /* End _capture_V4L */
   1025 
   1026 static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
   1027 {
   1028    static int autoindex;
   1029    autoindex = 0;
   1030 
   1031    char deviceName[MAX_DEVICE_DRIVER_NAME];
   1032 
   1033    if (!numCameras)
   1034       icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
   1035    if (!numCameras)
   1036      return NULL; /* Are there any /dev/video input sources? */
   1037 
   1038    //search index in indexList
   1039    if ( (index>-1) && ! ((1 << index) & indexList) )
   1040    {
   1041      fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",index);
   1042      return NULL; /* Did someone ask for not correct video source number? */
   1043    }
   1044    /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
   1045       the handles for V4L processing */
   1046    CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
   1047    if (!capture) {
   1048       fprintf( stderr, "VIDEOIO ERROR: V4L: Could not allocate memory for capture process.\n");
   1049       return NULL;
   1050    }
   1051 
   1052 #ifdef USE_TEMP_BUFFER
   1053    capture->buffers[MAX_V4L_BUFFERS].start = NULL;
   1054 #endif
   1055 
   1056    /* Select camera, or rather, V4L video source */
   1057    if (index<0) { // Asking for the first device available
   1058      for (; autoindex<MAX_CAMERAS;autoindex++)
   1059     if (indexList & (1<<autoindex))
   1060         break;
   1061      if (autoindex==MAX_CAMERAS)
   1062     return NULL;
   1063      index=autoindex;
   1064      autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
   1065    }
   1066    /* Print the CameraNumber at the end of the string with a width of one character */
   1067    sprintf(deviceName, "/dev/video%1d", index);
   1068 
   1069    /* w/o memset some parts  arent initialized - AKA: Fill it with zeros so it is clean */
   1070    memset(capture,0,sizeof(CvCaptureCAM_V4L));
   1071    /* Present the routines needed for V4L funtionality.  They are inserted as part of
   1072       the standard set of cv calls promoting transparency.  "Vector Table" insertion. */
   1073    capture->FirstCapture = 1;
   1074 
   1075    /* set the default size */
   1076    capture->width  = DEFAULT_V4L_WIDTH;
   1077    capture->height = DEFAULT_V4L_HEIGHT;
   1078 
   1079    if (_capture_V4L2 (capture, deviceName) == -1) {
   1080        icvCloseCAM_V4L(capture);
   1081        capture->is_v4l2_device = 0;
   1082        if (_capture_V4L (capture, deviceName) == -1) {
   1083            icvCloseCAM_V4L(capture);
   1084            return NULL;
   1085        }
   1086    } else {
   1087        capture->is_v4l2_device = 1;
   1088    }
   1089 
   1090    return capture;
   1091 }; /* End icvOpenCAM_V4L */
   1092 
   1093 #ifdef HAVE_CAMV4L2
   1094 
   1095 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
   1096     struct v4l2_buffer buf;
   1097 
   1098     CLEAR (buf);
   1099 
   1100     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1101     buf.memory = V4L2_MEMORY_MMAP;
   1102 
   1103     if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
   1104         switch (errno) {
   1105         case EAGAIN:
   1106             return 0;
   1107 
   1108         case EIO:
   1109             /* Could ignore EIO, see spec. */
   1110 
   1111             /* fall through */
   1112 
   1113         default:
   1114             /* display the error and stop processing */
   1115             perror ("VIDIOC_DQBUF");
   1116             return 1;
   1117         }
   1118    }
   1119 
   1120    assert(buf.index < capture->req.count);
   1121 
   1122 #ifdef USE_TEMP_BUFFER
   1123    memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
   1124     capture->buffers[buf.index].start,
   1125     capture->buffers[MAX_V4L_BUFFERS].length );
   1126    capture->bufferIndex = MAX_V4L_BUFFERS;
   1127    //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
   1128    //   buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
   1129 #else
   1130    capture->bufferIndex = buf.index;
   1131 #endif
   1132 
   1133    if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
   1134        perror ("VIDIOC_QBUF");
   1135 
   1136    //set timestamp in capture struct to be timestamp of most recent frame
   1137    /** where timestamps refer to the instant the field or frame was received by the driver, not the capture time*/
   1138    capture->timestamp = buf.timestamp;   //printf( "timestamp update done \n");
   1139    capture->sequence = buf.sequence;
   1140 
   1141    return 1;
   1142 }
   1143 
   1144 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
   1145     unsigned int count;
   1146 
   1147     count = 1;
   1148 
   1149     while (count-- > 0) {
   1150         for (;;) {
   1151             fd_set fds;
   1152             struct timeval tv;
   1153             int r;
   1154 
   1155             FD_ZERO (&fds);
   1156             FD_SET (capture->deviceHandle, &fds);
   1157 
   1158             /* Timeout. */
   1159             tv.tv_sec = 10;
   1160             tv.tv_usec = 0;
   1161 
   1162             r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
   1163 
   1164             if (-1 == r) {
   1165                 if (EINTR == errno)
   1166                     continue;
   1167 
   1168                 perror ("select");
   1169             }
   1170 
   1171             if (0 == r) {
   1172                 fprintf (stderr, "select timeout\n");
   1173 
   1174                 /* end the infinite loop */
   1175                 break;
   1176             }
   1177 
   1178             if (read_frame_v4l2 (capture))
   1179                 break;
   1180         }
   1181     }
   1182 }
   1183 
   1184 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
   1185 
   1186    if (capture->FirstCapture) {
   1187       /* Some general initialization must take place the first time through */
   1188 
   1189       /* This is just a technicality, but all buffers must be filled up before any
   1190          staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
   1191 
   1192       if (capture->is_v4l2_device == 1)
   1193       {
   1194 
   1195         for (capture->bufferIndex = 0;
   1196              capture->bufferIndex < ((int)capture->req.count);
   1197              ++capture->bufferIndex)
   1198         {
   1199 
   1200           struct v4l2_buffer buf;
   1201 
   1202           CLEAR (buf);
   1203 
   1204           buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1205           buf.memory      = V4L2_MEMORY_MMAP;
   1206           buf.index       = (unsigned long)capture->bufferIndex;
   1207 
   1208           if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
   1209               perror ("VIDIOC_QBUF");
   1210               return 0;
   1211           }
   1212         }
   1213 
   1214         /* enable the streaming */
   1215         capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1216         if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
   1217                           &capture->type)) {
   1218             /* error enabling the stream */
   1219             perror ("VIDIOC_STREAMON");
   1220             return 0;
   1221         }
   1222       } else
   1223       {
   1224 
   1225         for (capture->bufferIndex = 0;
   1226          capture->bufferIndex < (capture->memoryBuffer.frames-1);
   1227          ++capture->bufferIndex) {
   1228 
   1229           capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
   1230           capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
   1231           capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
   1232           capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
   1233 
   1234           if (v4l1_ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
   1235             fprintf( stderr, "VIDEOIO ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
   1236             return 0;
   1237           }
   1238         }
   1239 
   1240       }
   1241 
   1242       /* preparation is ok */
   1243       capture->FirstCapture = 0;
   1244    }
   1245 
   1246    if (capture->is_v4l2_device == 1)
   1247    {
   1248 
   1249      mainloop_v4l2(capture);
   1250 
   1251    } else
   1252    {
   1253 
   1254    capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
   1255    capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
   1256    capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
   1257    capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
   1258 
   1259    if (v4l1_ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
   1260            &capture->mmaps[capture->bufferIndex]) == -1) {
   1261       /* capture is on the way, so just exit */
   1262       return 1;
   1263    }
   1264 
   1265      ++capture->bufferIndex;
   1266      if (capture->bufferIndex == capture->memoryBuffer.frames) {
   1267         capture->bufferIndex = 0;
   1268      }
   1269 
   1270    }
   1271 
   1272    return(1);
   1273 }
   1274 
   1275 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
   1276 
   1277   if (capture->is_v4l2_device == 0)
   1278   {
   1279 
   1280     /* [FD] this really belongs here */
   1281     if (v4l1_ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
   1282       fprintf( stderr, "VIDEOIO ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
   1283     }
   1284 
   1285   }
   1286 
   1287    /* Now get what has already been captured as a IplImage return */
   1288 
   1289    /* First, reallocate imageData if the frame size changed */
   1290 
   1291   if (capture->is_v4l2_device == 1)
   1292   {
   1293 
   1294     if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
   1295        || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
   1296         cvFree(&capture->frame.imageData);
   1297         cvInitImageHeader( &capture->frame,
   1298                            cvSize( capture->form.fmt.pix.width,
   1299                                    capture->form.fmt.pix.height ),
   1300                            IPL_DEPTH_8U, channels_for_mode(capture->mode),
   1301                            IPL_ORIGIN_TL, 4 );
   1302        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
   1303     }
   1304 
   1305   } else
   1306   {
   1307 
   1308     if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
   1309       || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
   1310        cvFree(&capture->frame.imageData);
   1311        cvInitImageHeader( &capture->frame,
   1312                           cvSize( capture->captureWindow.width,
   1313                                   capture->captureWindow.height ),
   1314                           IPL_DEPTH_8U, channels_for_mode(capture->mode),
   1315                           IPL_ORIGIN_TL, 4 );
   1316        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
   1317     }
   1318 
   1319   }
   1320 
   1321   if (capture->is_v4l2_device == 1)
   1322   {
   1323 
   1324     if(capture->buffers[capture->bufferIndex].start){
   1325       memcpy((char *)capture->frame.imageData,
   1326          (char *)capture->buffers[capture->bufferIndex].start,
   1327          capture->frame.imageSize);
   1328     }
   1329 
   1330   } else
   1331 #endif /* HAVE_CAMV4L2 */
   1332   {
   1333 
   1334     switch(capture->imageProperties.palette) {
   1335       case VIDEO_PALETTE_RGB24:
   1336       case VIDEO_PALETTE_YUV420:
   1337       case VIDEO_PALETTE_YUYV:
   1338         memcpy((char *)capture->frame.imageData,
   1339            (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
   1340            capture->frame.imageSize);
   1341         break;
   1342       default:
   1343         fprintf( stderr,
   1344                  "VIDEOIO ERROR: V4L: Cannot convert from palette %d to mode %d\n",
   1345                  capture->imageProperties.palette,
   1346                  capture->mode);
   1347         return 0;
   1348     }
   1349 
   1350   }
   1351 
   1352    return(&capture->frame);
   1353 }
   1354 
   1355 /* TODO: review this adaptation */
   1356 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
   1357                                      int property_id ) {
   1358   char name[32];
   1359   int is_v4l2_device = 0;
   1360       /* initialize the control structure */
   1361   switch (property_id) {
   1362     case CV_CAP_PROP_FRAME_WIDTH:
   1363     case CV_CAP_PROP_FRAME_HEIGHT:
   1364       CLEAR (capture->form);
   1365       capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1366       if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
   1367           /* display an error message, and return an error code */
   1368           perror ("VIDIOC_G_FMT");
   1369         if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
   1370           fprintf (stderr, " ERROR: V4L: Unable to determine size of incoming image\n");
   1371           icvCloseCAM_V4L(capture);
   1372           return -1;
   1373         } else {
   1374           int retval = (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->captureWindow.width:capture->captureWindow.height;
   1375           return retval / 0xFFFF;
   1376         }
   1377       }
   1378       return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
   1379 
   1380     case CV_CAP_PROP_POS_MSEC:
   1381         if (capture->FirstCapture) {
   1382             return 0;
   1383         } else {
   1384             //would be maximally numerically stable to cast to convert as bits, but would also be counterintuitive to decode
   1385             return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
   1386         }
   1387         break;
   1388 
   1389     case CV_CAP_PROP_POS_FRAMES:
   1390         return capture->sequence;
   1391         break;
   1392 
   1393     case CV_CAP_PROP_FPS: {
   1394         struct v4l2_streamparm sp;
   1395         memset (&sp, 0, sizeof(struct v4l2_streamparm));
   1396         sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1397         if (xioctl (capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){
   1398             fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n");
   1399             return (double) -1;
   1400         }
   1401 
   1402         // this is the captureable, not per say what you'll get..
   1403         double framesPerSec = sp.parm.capture.timeperframe.denominator / (double)  sp.parm.capture.timeperframe.numerator ;
   1404         return framesPerSec;
   1405     }
   1406     break;
   1407 
   1408 
   1409     case CV_CAP_PROP_MODE:
   1410       return capture->mode;
   1411       break;
   1412     case CV_CAP_PROP_BRIGHTNESS:
   1413       sprintf(name, "Brightness");
   1414       capture->control.id = V4L2_CID_BRIGHTNESS;
   1415       break;
   1416     case CV_CAP_PROP_CONTRAST:
   1417       sprintf(name, "Contrast");
   1418       capture->control.id = V4L2_CID_CONTRAST;
   1419       break;
   1420     case CV_CAP_PROP_SATURATION:
   1421       sprintf(name, "Saturation");
   1422       capture->control.id = V4L2_CID_SATURATION;
   1423       break;
   1424     case CV_CAP_PROP_HUE:
   1425       sprintf(name, "Hue");
   1426       capture->control.id = V4L2_CID_HUE;
   1427       break;
   1428     case CV_CAP_PROP_GAIN:
   1429       sprintf(name, "Gain");
   1430       capture->control.id = V4L2_CID_GAIN;
   1431       break;
   1432     case CV_CAP_PROP_EXPOSURE:
   1433       sprintf(name, "Exposure");
   1434       capture->control.id = V4L2_CID_EXPOSURE;
   1435       break;
   1436     default:
   1437       sprintf(name, "<unknown property string>");
   1438       capture->control.id = property_id;
   1439   }
   1440 
   1441   if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
   1442     /* all went well */
   1443     is_v4l2_device = 1;
   1444   } else {
   1445     fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
   1446   }
   1447 
   1448   if (is_v4l2_device == 1) {
   1449       /* get the min/max values */
   1450       int v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
   1451       int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
   1452 
   1453       if ((v4l2_min == -1) && (v4l2_max == -1)) {
   1454         fprintf(stderr, "VIDEOIO ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id);
   1455         return -1;
   1456       }
   1457 
   1458       /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
   1459       return ((float)capture->control.value - v4l2_min) / (v4l2_max - v4l2_min);
   1460 
   1461   } else {
   1462     /* TODO: review this section */
   1463     int retval = -1;
   1464 
   1465     switch (property_id) {
   1466       case CV_CAP_PROP_BRIGHTNESS:
   1467         retval = capture->imageProperties.brightness;
   1468         break;
   1469       case CV_CAP_PROP_CONTRAST:
   1470         retval = capture->imageProperties.contrast;
   1471         break;
   1472       case CV_CAP_PROP_SATURATION:
   1473         retval = capture->imageProperties.colour;
   1474         break;
   1475       case CV_CAP_PROP_HUE:
   1476         retval = capture->imageProperties.hue;
   1477         break;
   1478       case CV_CAP_PROP_GAIN:
   1479         fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
   1480         return -1;
   1481         break;
   1482       case CV_CAP_PROP_EXPOSURE:
   1483         fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
   1484         return -1;
   1485         break;
   1486     }
   1487 
   1488     if (retval == -1) {
   1489       /* there was a problem */
   1490       return -1;
   1491     }
   1492     /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
   1493     return float (retval) / 0xFFFF;
   1494   }
   1495 }
   1496 
   1497 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
   1498 
   1499   if (capture->is_v4l2_device == 1)
   1500   {
   1501     char deviceName[MAX_DEVICE_DRIVER_NAME];
   1502     sprintf(deviceName, "%s", capture->deviceName);
   1503     icvCloseCAM_V4L(capture);
   1504     _capture_V4L2(capture, deviceName);
   1505 
   1506     int cropHeight;
   1507     int cropWidth;
   1508     switch (capture->mode) {
   1509     case CV_CAP_MODE_GRAY:
   1510       cropHeight = h*8;
   1511       cropWidth = w*8;
   1512       break;
   1513     case CV_CAP_MODE_YUYV:
   1514       cropHeight = h*16;
   1515       cropWidth = w*16;
   1516       break;
   1517     default:
   1518       cropHeight = h*24;
   1519       cropWidth = w*24;
   1520       break;
   1521     }
   1522     CLEAR (capture->crop);
   1523     capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1524     capture->crop.c.left       = 0;
   1525     capture->crop.c.top        = 0;
   1526     capture->crop.c.height     = cropHeight;
   1527     capture->crop.c.width      = cropWidth;
   1528 
   1529     /* set the crop area, but don't exit if the device don't support croping */
   1530     xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
   1531 
   1532     CLEAR (capture->form);
   1533     capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1534 
   1535     /* read the current setting, mainly to retreive the pixelformat information */
   1536     xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
   1537 
   1538     /* set the values we want to change */
   1539     capture->form.fmt.pix.width = w;
   1540     capture->form.fmt.pix.height = h;
   1541     capture->form.fmt.win.chromakey = 0;
   1542     capture->form.fmt.win.field = V4L2_FIELD_ANY;
   1543     capture->form.fmt.win.clips = 0;
   1544     capture->form.fmt.win.clipcount = 0;
   1545     capture->form.fmt.pix.field = V4L2_FIELD_ANY;
   1546 
   1547     /* ask the device to change the size
   1548      * don't test if the set of the size is ok, because some device
   1549      * don't allow changing the size, and we will get the real size
   1550      * later */
   1551     xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
   1552 
   1553     /* try to set framerate to 30 fps */
   1554 
   1555     struct v4l2_streamparm setfps;
   1556     memset (&setfps, 0, sizeof(struct v4l2_streamparm));
   1557 
   1558     setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1559     setfps.parm.capture.timeperframe.numerator = 1;
   1560     setfps.parm.capture.timeperframe.denominator = 30;
   1561 
   1562     xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
   1563 
   1564 
   1565     /* we need to re-initialize some things, like buffers, because the size has
   1566      * changed */
   1567     capture->FirstCapture = 1;
   1568 
   1569     /* Get window info again, to get the real value */
   1570     if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
   1571     {
   1572       fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
   1573 
   1574       icvCloseCAM_V4L(capture);
   1575 
   1576       return 0;
   1577     }
   1578 
   1579     return 0;
   1580 
   1581   } else
   1582   {
   1583 
   1584     if (capture==0) return 0;
   1585      if (w>capture->capability.maxwidth) {
   1586        w=capture->capability.maxwidth;
   1587      }
   1588      if (h>capture->capability.maxheight) {
   1589        h=capture->capability.maxheight;
   1590      }
   1591 
   1592      capture->captureWindow.width=w;
   1593      capture->captureWindow.height=h;
   1594 
   1595      if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
   1596        icvCloseCAM_V4L(capture);
   1597        return 0;
   1598      }
   1599 
   1600      if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
   1601        icvCloseCAM_V4L(capture);
   1602        return 0;
   1603      }
   1604 
   1605      capture->FirstCapture = 1;
   1606 
   1607   }
   1608 
   1609   return 0;
   1610 
   1611 }
   1612 
   1613 static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) {
   1614   struct v4l2_control c;
   1615   __s32 ctrl_value;
   1616   char name[32];
   1617   int is_v4l2  = 1;
   1618   int v4l2_min = 0;
   1619   int v4l2_max = 255;
   1620   if (capture->v4l2_ctrl_ranges == NULL) {
   1621     v4l2_scan_controls(capture);
   1622   }
   1623 
   1624   CLEAR (capture->control);
   1625   CLEAR (capture->queryctrl);
   1626 
   1627   /* get current values */
   1628   switch (property_id) {
   1629     case CV_CAP_PROP_BRIGHTNESS:
   1630       sprintf(name, "Brightness");
   1631       capture->control.id = V4L2_CID_BRIGHTNESS;
   1632       break;
   1633     case CV_CAP_PROP_CONTRAST:
   1634       sprintf(name, "Contrast");
   1635       capture->control.id = V4L2_CID_CONTRAST;
   1636       break;
   1637     case CV_CAP_PROP_SATURATION:
   1638       sprintf(name, "Saturation");
   1639       capture->control.id = V4L2_CID_SATURATION;
   1640       break;
   1641     case CV_CAP_PROP_HUE:
   1642       sprintf(name, "Hue");
   1643       capture->control.id = V4L2_CID_HUE;
   1644       break;
   1645     case CV_CAP_PROP_GAIN:
   1646       sprintf(name, "Gain");
   1647       capture->control.id = V4L2_CID_GAIN;
   1648       break;
   1649     case CV_CAP_PROP_EXPOSURE:
   1650       sprintf(name, "Exposure");
   1651       capture->control.id = V4L2_CID_EXPOSURE;
   1652       break;
   1653     default:
   1654       sprintf(name, "<unknown property string>");
   1655       capture->control.id = property_id;
   1656   }
   1657 
   1658   v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
   1659   v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
   1660 
   1661   if ((v4l2_min == -1) && (v4l2_max == -1)) {
   1662     fprintf(stderr, "VIDEOIO ERROR: V4L: Property %s(%u) not supported by device\n", name, property_id);
   1663     return -1;
   1664   }
   1665 
   1666   if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
   1667     /* all went well */
   1668   } else {
   1669     fprintf(stderr, "VIDEOIO ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
   1670   }
   1671 
   1672   if (v4l2_max != 0) {
   1673     double val = value;
   1674     if (value < 0.0) {
   1675       val = 0.0;
   1676     } else if (value > 1.0) {
   1677       val = 1.0;
   1678     }
   1679     ctrl_value = val * (double)(v4l2_max - v4l2_min) + v4l2_min;
   1680   } else {
   1681     ctrl_value = v4l2_get_ctrl_default(capture, capture->control.id) * (double)(v4l2_max - v4l2_min) + v4l2_min;
   1682   }
   1683 
   1684   /* try and set value as if it was a v4l2 device */
   1685   c.id    = capture->control.id;
   1686   c.value = ctrl_value;
   1687   if (v4l2_ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &c) != 0) {
   1688     /* The driver may clamp the value or return ERANGE, ignored here */
   1689     if (errno != ERANGE) {
   1690       fprintf(stderr, "VIDEOIO ERROR: V4L2: Failed to set control \"%d\": %s (value %d)\n", c.id, strerror(errno), c.value);
   1691       is_v4l2 = 0;
   1692     } else {
   1693       return 0;
   1694     }
   1695   } else {
   1696     return 0;
   1697   }
   1698 
   1699   if (is_v4l2 == 0) { /* use v4l1_ioctl */
   1700     fprintf(stderr, "VIDEOIO WARNING: Setting property %u through v4l2 failed. Trying with v4l1.\n", c.id);
   1701     int v4l_value;
   1702     /* scale the value to the wanted integer one */
   1703     v4l_value = (int)(0xFFFF * value);
   1704 
   1705     switch (property_id) {
   1706       case CV_CAP_PROP_BRIGHTNESS:
   1707         capture->imageProperties.brightness = v4l_value;
   1708         break;
   1709       case CV_CAP_PROP_CONTRAST:
   1710         capture->imageProperties.contrast = v4l_value;
   1711         break;
   1712       case CV_CAP_PROP_SATURATION:
   1713         capture->imageProperties.colour = v4l_value;
   1714         break;
   1715       case CV_CAP_PROP_HUE:
   1716         capture->imageProperties.hue = v4l_value;
   1717         break;
   1718       case CV_CAP_PROP_GAIN:
   1719           fprintf(stderr, "VIDEOIO ERROR: V4L: Gain control in V4L is not supported\n");
   1720         return -1;
   1721     case CV_CAP_PROP_EXPOSURE:
   1722         fprintf(stderr, "VIDEOIO ERROR: V4L: Exposure control in V4L is not supported\n");
   1723         return -1;
   1724     default:
   1725         fprintf(stderr, "VIDEOIO ERROR: V4L: property #%d is not supported\n", property_id);
   1726         return -1;
   1727     }
   1728 
   1729     if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0){
   1730       fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set video informations\n");
   1731       icvCloseCAM_V4L(capture);
   1732       return -1;
   1733     }
   1734   }
   1735 
   1736   /* all was OK */
   1737   return 0;
   1738 }
   1739 
   1740 static int icvSetPropertyCAM_V4L(CvCaptureCAM_V4L* capture, int property_id, double value){
   1741     static int width = 0, height = 0;
   1742     int retval;
   1743 
   1744     /* initialization */
   1745     retval = 0;
   1746 
   1747     /* two subsequent calls setting WIDTH and HEIGHT will change
   1748        the video size */
   1749     /* the first one will return an error, though. */
   1750 
   1751     switch (property_id) {
   1752     case CV_CAP_PROP_FRAME_WIDTH:
   1753         width = cvRound(value);
   1754         capture->width = width;
   1755         if(width !=0 && height != 0) {
   1756             retval = icvSetVideoSize( capture, width, height);
   1757             width = height = 0;
   1758         }
   1759         break;
   1760     case CV_CAP_PROP_FRAME_HEIGHT:
   1761         height = cvRound(value);
   1762         capture->height = height;
   1763         if(width !=0 && height != 0) {
   1764             retval = icvSetVideoSize( capture, width, height);
   1765             width = height = 0;
   1766         }
   1767         break;
   1768     case CV_CAP_PROP_MODE:
   1769         int mode;
   1770         mode = cvRound(value);
   1771         if (capture->mode != mode) {
   1772             switch (mode) {
   1773             case CV_CAP_MODE_BGR:
   1774             case CV_CAP_MODE_RGB:
   1775             case CV_CAP_MODE_GRAY:
   1776             case CV_CAP_MODE_YUYV:
   1777                 capture->mode = mode;
   1778                 /* recreate the capture buffer for the same output resolution
   1779                    but a different pixel format */
   1780                 retval = icvSetVideoSize(capture, capture->width, capture->height);
   1781                 break;
   1782             default:
   1783                 fprintf(stderr, "VIDEOIO ERROR: V4L/V4L2: Unsupported mode: %d\n", mode);
   1784                 retval=0;
   1785                 break;
   1786             }
   1787         }
   1788         break;
   1789     case CV_CAP_PROP_FPS:
   1790         struct v4l2_streamparm setfps;
   1791         memset (&setfps, 0, sizeof(struct v4l2_streamparm));
   1792         setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1793         setfps.parm.capture.timeperframe.numerator = 1;
   1794         setfps.parm.capture.timeperframe.denominator = value;
   1795         if (xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps) < 0){
   1796             fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to set camera FPS\n");
   1797             retval=0;
   1798         }
   1799         break;
   1800     default:
   1801         retval = icvSetControl(capture, property_id, value);
   1802     }
   1803 
   1804     /* return the the status */
   1805     return retval;
   1806 }
   1807 
   1808 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
   1809    /* Deallocate space - Hopefully, no leaks */
   1810    if (capture) {
   1811      v4l2_free_ranges(capture);
   1812      if (capture->is_v4l2_device == 0) {
   1813        if (capture->mmaps) {
   1814          free(capture->mmaps);
   1815        }
   1816        if (capture->memoryMap) {
   1817          v4l1_munmap(capture->memoryMap, capture->memoryBuffer.size);
   1818        }
   1819        if (capture->deviceHandle != -1) {
   1820          v4l1_close(capture->deviceHandle);
   1821        }
   1822      } else {
   1823        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   1824        if (xioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type) < 0) {
   1825          perror ("Unable to stop the stream.");
   1826        }
   1827        for (unsigned int n_buffers2 = 0; n_buffers2 < capture->req.count; ++n_buffers2) {
   1828          if (-1 == v4l2_munmap (capture->buffers[n_buffers2].start, capture->buffers[n_buffers2].length)) {
   1829            perror ("munmap");
   1830          }
   1831        }
   1832 
   1833        if (capture->deviceHandle != -1) {
   1834          v4l2_close(capture->deviceHandle);
   1835        }
   1836      }
   1837 
   1838      if (capture->frame.imageData)
   1839        cvFree(&capture->frame.imageData);
   1840 
   1841 #ifdef USE_TEMP_BUFFER
   1842      if (capture->buffers[MAX_V4L_BUFFERS].start) {
   1843        free(capture->buffers[MAX_V4L_BUFFERS].start);
   1844        capture->buffers[MAX_V4L_BUFFERS].start = NULL;
   1845      }
   1846 #endif
   1847 
   1848      free(capture->deviceName);
   1849      capture->deviceName = NULL;
   1850      //v4l2_free_ranges(capture);
   1851      //cvFree((void **)capture);
   1852    }
   1853 };
   1854 
   1855 
   1856 class CvCaptureCAM_V4L_CPP : CvCapture
   1857 {
   1858 public:
   1859     CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
   1860     virtual ~CvCaptureCAM_V4L_CPP() { close(); }
   1861 
   1862     virtual bool open( int index );
   1863     virtual void close();
   1864 
   1865     virtual double getProperty(int) const;
   1866     virtual bool setProperty(int, double);
   1867     virtual bool grabFrame();
   1868     virtual IplImage* retrieveFrame(int);
   1869 protected:
   1870 
   1871     CvCaptureCAM_V4L* captureV4L;
   1872 };
   1873 
   1874 bool CvCaptureCAM_V4L_CPP::open( int index )
   1875 {
   1876     close();
   1877     captureV4L = icvCaptureFromCAM_V4L(index);
   1878     return captureV4L != 0;
   1879 }
   1880 
   1881 void CvCaptureCAM_V4L_CPP::close()
   1882 {
   1883     if( captureV4L )
   1884     {
   1885         icvCloseCAM_V4L( captureV4L );
   1886         cvFree( &captureV4L );
   1887     }
   1888 }
   1889 
   1890 bool CvCaptureCAM_V4L_CPP::grabFrame()
   1891 {
   1892     return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
   1893 }
   1894 
   1895 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
   1896 {
   1897     return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
   1898 }
   1899 
   1900 double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const
   1901 {
   1902     return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
   1903 }
   1904 
   1905 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
   1906 {
   1907     return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
   1908 }
   1909 
   1910 CvCapture* cvCreateCameraCapture_V4L( int index )
   1911 {
   1912     CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
   1913 
   1914     if( capture->open( index ))
   1915         return (CvCapture*)capture;
   1916 
   1917     delete capture;
   1918     return 0;
   1919 }
   1920 
   1921 #endif
   1922