CLAHE Python bindings
[profile/ivi/opencv.git] / modules / highgui / src / cap_libv4l.cpp
1 /* This is the contributed code:
2
3 File:             cvcap_v4l.cpp
4 Current Location: ../opencv-0.9.6/otherlibs/highgui
5
6 Original Version: 2003-03-12  Magnus Lundin lundin@mlu.mine.nu
7 Original Comments:
8
9 ML:This set of files adds support for firevre and usb cameras.
10 First it tries to install a firewire camera,
11 if that fails it tries a v4l/USB camera
12 It has been tested with the motempl sample program
13
14 First Patch:  August 24, 2004 Travis Wood   TravisOCV@tkwood.com
15 For Release:  OpenCV-Linux Beta4  opencv-0.9.6
16 Tested On:    LMLBT44 with 8 video inputs
17 Problems?     Post problems/fixes to OpenCV group on groups.yahoo.com
18 Patched Comments:
19
20 TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
21 were not working.  I have rewritten them so they work for me. At the same time, trying
22 to keep the original code as ML wrote it as unchanged as possible.  No one likes to debug
23 someone elses code, so I resisted changes as much as possible.  I have tried to keep the
24 same "ideas" where applicable, that is, where I could figure out what the previous author
25 intended. Some areas I just could not help myself and had to "spiffy-it-up" my way.
26
27 These drivers should work with other V4L frame capture cards other then my bttv
28 driven frame capture card.
29
30 Re Written driver for standard V4L mode. Tested using LMLBT44 video capture card.
31 Standard bttv drivers are on the LMLBT44 with up to 8 Inputs.
32
33 This utility was written with the help of the document:
34 http://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo
35 as a general guide for interfacing into the V4l standard.
36
37 Made the index value passed for icvOpenCAM_V4L(index) be the number of the
38 video device source in the /dev tree. The -1 uses original /dev/video.
39
40 Index  Device
41   0    /dev/video0
42   1    /dev/video1
43   2    /dev/video2
44   3    /dev/video3
45   ...
46   7    /dev/video7
47 with
48   -1   /dev/video
49
50 TW: You can select any video source, but this package was limited from the start to only
51 ONE camera opened at any ONE time.
52 This is an original program limitation.
53 If you are interested, I will make my version available to other OpenCV users.  The big
54 difference in mine is you may pass the camera number as part of the cv argument, but this
55 convention is non standard for current OpenCV calls and the camera number is not currently
56 passed into the called routine.
57
58 Second Patch:   August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
59 For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
60
61 FS: this patch fix not sequential index of device (unplugged device), and real numCameras.
62     for -1 index (icvOpenCAM_V4L) i dont use /dev/video but real device available, because
63     if /dev/video is a link to /dev/video0 and i unplugged device on /dev/video0, /dev/video
64     is a bad link. I search the first available device with indexList.
65
66 Third Patch:   December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
67 For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
68
69 [FD] I modified the following:
70  - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point
71  - cvGrabFrame should not wait for the end of the first frame, and should return quickly
72    (see highgui doc)
73  - cvRetrieveFrame should in turn wait for the end of frame capture, and should not
74    trigger the capture of the next frame (the user choses when to do it using GrabFrame)
75    To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame.
76  - having global bufferIndex and FirstCapture variables makes the code non-reentrant
77  (e.g. when using several cameras), put these in the CvCapture struct.
78  - according to V4L HowTo, incrementing the buffer index must be done before VIDIOCMCAPTURE.
79  - the VID_TYPE_SCALES stuff from V4L HowTo is wrong: image size can be changed
80    even if the hardware does not support scaling (e.g. webcams can have several
81    resolutions available). Just don't try to set the size at 640x480 if the hardware supports
82    scaling: open with the default (probably best) image size, and let the user scale it
83    using SetProperty.
84  - image size can be changed by two subsequent calls to SetProperty (for width and height)
85  - bug fix: if the image size changes, realloc the new image only when it is grabbed
86  - issue errors only when necessary, fix error message formatting.
87
88 Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
89 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
90
91 I modified the following:
92   - Additional Video4Linux2 support :)
93   - Use mmap functions (v4l2)
94   - New methods are internal:
95     try_palette_v4l2 -> rewrite try_palette for v4l2
96     mainloop_v4l2, read_image_v4l2 -> this methods are moved from official v4l2 capture.c example
97     try_init_v4l -> device v4l initialisation
98     try_init_v4l2 -> device v4l2 initialisation
99     autosetup_capture_mode_v4l -> autodetect capture modes for v4l
100     autosetup_capture_mode_v4l2 -> autodetect capture modes for v4l2
101   - Modifications are according with Video4Linux old codes
102   - Video4Linux handling is automatically if it does not recognize a Video4Linux2 device
103   - Tested succesful with Logitech Quickcam Express (V4L), Creative Vista (V4L) and Genius VideoCam Notebook (V4L2)
104   - Correct source lines with compiler warning messages
105   - Information message from v4l/v4l2 detection
106
107 Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
108 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
109
110 I modified the following:
111   - SN9C10x chip based webcams support
112   - New methods are internal:
113     bayer2rgb24, sonix_decompress -> decoder routines for SN9C10x decoding from Takafumi Mizuno <taka-qce@ls-a.jp> with his pleasure :)
114   - Tested succesful with Genius VideoCam Notebook (V4L2)
115
116 Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
117 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
118
119 I added the following:
120   - Add capture control support (hue, saturation, brightness, contrast, gain)
121   - Get and change V4L capture controls (hue, saturation, brightness, contrast)
122   - New method is internal:
123     icvSetControl -> set capture controls
124   - Tested succesful with Creative Vista (V4L)
125
126 Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
127 For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
128
129 I added the following:
130   - Detect, get and change V4L2 capture controls (hue, saturation, brightness, contrast, gain)
131   - New methods are internal:
132     v4l2_scan_controls_enumerate_menu, v4l2_scan_controls -> detect capture control intervals
133   - Tested succesful with Genius VideoCam Notebook (V4L2)
134
135 8th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch
136 Add support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG.
137 With this patch, new webcams of Logitech, like QuickCam Fusion works.
138 Note: For use these webcams, look at the UVC driver at
139 http://linux-uvc.berlios.de/
140
141 9th patch: Mar 4, 2006, Olivier.Bornet@idiap.ch
142 - try V4L2 before V4L, because some devices are V4L2 by default,
143   but they try to implement the V4L compatibility layer.
144   So, I think this is better to support V4L2 before V4L.
145 - better separation between V4L2 and V4L initialization. (this was needed to support
146   some drivers working, but not fully with V4L2. (so, we do not know when we
147   need to switch from V4L2 to V4L.
148
149 10th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com
150 Fix reliability problems with high-resolution UVC cameras on linux
151 the symptoms were damaged image and 'Corrupt JPEG data: premature end of data segment' on stderr
152 - V4L_ABORT_BADJPEG detects JPEG warnings and turns them into errors, so bad images
153   could be filtered out
154 - USE_TEMP_BUFFER fixes the main problem (improper buffer management) and
155   prevents bad images in the first place
156
157 11th patch: Apr 13, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
158 - Tries to setup all properties first through v4l2_ioctl call.
159 - Allows seting 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.
160
161 12th patch: Apr 16, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
162 - CvCaptureCAM_V4L structure cleanup (no longer needs <PROPERTY>_{min,max,} variables)
163 - Introduction of v4l2_ctrl_range - minimum and maximum allowed values for v4l controls
164 - Allows seting up all Video4Linux properties through cvSetCaptureProperty using input values between 0.0 and 1.0
165 - Gets v4l properties first through v4l2_ioctl call (ignores capture->is_v4l2_device)
166 - cvGetCaptureProperty adjusted to support the changes
167 - Returns device properties to initial values after device closes
168
169 13th patch: Apr 27, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
170 - Solved problem mmaping the device using uvcvideo driver (use o v4l2_mmap instead of mmap)
171 make & enjoy!
172
173 14th patch: May 10, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
174 - Bug #142: Solved/Workaround "setting frame width and height does not work"
175   There was a problem setting up the size when the input is a v4l2 device
176   The workaround closes the camera and reopens it with the new definition
177   Planning for future rewrite of this whole library (July/August 2010)
178
179 15th patch: May 12, 2010, Filipe Almeida filipe.almeida@ist.utl.pt
180 - Broken compile of library (include "_highgui.h")
181 */
182
183 /*M///////////////////////////////////////////////////////////////////////////////////////
184 //
185 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
186 //
187 //  By downloading, copying, installing or using the software you agree to this license.
188 //  If you do not agree to this license, do not download, install,
189 //  copy or use the software.
190 //
191 //
192 //                        Intel License Agreement
193 //                For Open Source Computer Vision Library
194 //
195 // Copyright (C) 2000, Intel Corporation, all rights reserved.
196 // Third party copyrights are property of their respective owners.
197 //
198 // Redistribution and use in source and binary forms, with or without modification,
199 // are permitted provided that the following conditions are met:
200 //
201 //   * Redistribution's of source code must retain the above copyright notice,
202 //     this list of conditions and the following disclaimer.
203 //
204 //   * Redistribution's in binary form must reproduce the above copyright notice,
205 //     this list of conditions and the following disclaimer in the documentation
206 //     and/or other materials provided with the distribution.
207 //
208 //   * The name of Intel Corporation may not be used to endorse or promote products
209 //     derived from this software without specific prior written permission.
210 //
211 // This software is provided by the copyright holders and contributors "as is" and
212 // any express or implied warranties, including, but not limited to, the implied
213 // warranties of merchantability and fitness for a particular purpose are disclaimed.
214 // In no event shall the Intel Corporation or contributors be liable for any direct,
215 // indirect, incidental, special, exemplary, or consequential damages
216 // (including, but not limited to, procurement of substitute goods or services;
217 // loss of use, data, or profits; or business interruption) however caused
218 // and on any theory of liability, whether in contract, strict liability,
219 // or tort (including negligence or otherwise) arising in any way out of
220 // the use of this software, even if advised of the possibility of such damage.
221 //
222 //M*/
223
224 #include "precomp.hpp"
225
226 #if !defined WIN32 && defined HAVE_LIBV4L
227
228 #define CLEAR(x) memset (&(x), 0, sizeof (x))
229
230 #include <stdio.h>
231 #include <unistd.h>
232 #include <fcntl.h>
233 #include <errno.h>
234 #include <sys/types.h>
235 #include <sys/mman.h>
236 #include <string.h>
237 #include <stdlib.h>
238 #include <asm/types.h>          /* for videodev2.h */
239 #include <assert.h>
240 #include <sys/stat.h>
241 #include <sys/ioctl.h>
242
243 #ifdef HAVE_CAMV4L
244 #include <linux/videodev.h>
245 #endif
246 #ifdef HAVE_CAMV4L2
247 #include <linux/videodev2.h>
248 #endif
249
250 #include <libv4l1.h>
251 #include <libv4l2.h>
252
253 /* Defaults - If your board can do better, set it here.  Set for the most common type inputs. */
254 #define DEFAULT_V4L_WIDTH  640
255 #define DEFAULT_V4L_HEIGHT 480
256
257 #define CHANNEL_NUMBER 1
258 #define MAX_CAMERAS 8
259
260
261 // default and maximum number of V4L buffers, not including last, 'special' buffer
262 #define MAX_V4L_BUFFERS 10
263 #define DEFAULT_V4L_BUFFERS 4
264
265 // if enabled, copies data from the buffer. this uses a bit more memory,
266 //  but much more reliable for some UVC cameras
267 #define USE_TEMP_BUFFER
268
269 #define MAX_DEVICE_DRIVER_NAME 80
270
271 /* Device Capture Objects */
272 /* V4L2 structure */
273 struct buffer
274 {
275   void *  start;
276   size_t  length;
277 };
278 static unsigned int n_buffers = 0;
279
280 /* TODO: Dilemas: */
281 /* TODO: Consider drop the use of this data structure and perform ioctl to obtain needed values */
282 /* TODO: Consider at program exit return controls to the initial values - See v4l2_free_ranges function */
283 /* TODO: Consider at program exit reset the device to default values - See v4l2_free_ranges function */
284 typedef struct v4l2_ctrl_range {
285   __u32 ctrl_id;
286   __s32 initial_value;
287   __s32 current_value;
288   __s32 minimum;
289   __s32 maximum;
290   __s32 default_value;
291 } v4l2_ctrl_range;
292
293 typedef struct CvCaptureCAM_V4L
294 {
295     char* deviceName;
296     int deviceHandle;
297     int bufferIndex;
298     int FirstCapture;
299
300     int width; int height;
301
302     struct video_capability capability;
303     struct video_window     captureWindow;
304     struct video_picture    imageProperties;
305     struct video_mbuf       memoryBuffer;
306     struct video_mmap       *mmaps;
307     char *memoryMap;
308     IplImage frame;
309
310    /* V4L2 variables */
311    buffer buffers[MAX_V4L_BUFFERS + 1];
312    struct v4l2_capability cap;
313    struct v4l2_input inp;
314    struct v4l2_format form;
315    struct v4l2_crop crop;
316    struct v4l2_cropcap cropcap;
317    struct v4l2_requestbuffers req;
318    struct v4l2_jpegcompression compr;
319    struct v4l2_control control;
320    enum v4l2_buf_type type;
321    struct v4l2_queryctrl queryctrl;
322    struct v4l2_querymenu querymenu;
323
324    /* V4L2 control variables */
325    v4l2_ctrl_range** v4l2_ctrl_ranges;
326    int v4l2_ctrl_count;
327
328    int is_v4l2_device;
329 }
330 CvCaptureCAM_V4L;
331
332 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
333
334 static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
335 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
336 CvCapture* cvCreateCameraCapture_V4L( int index );
337
338 static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id );
339 static int    icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
340
341 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h);
342
343 /***********************   Implementations  ***************************************/
344
345 static int numCameras = 0;
346 static int indexList = 0;
347
348 // IOCTL handling for V4L2
349 #ifdef HAVE_IOCTL_ULONG
350 static int xioctl( int fd, unsigned long request, void *arg)
351 #else
352 static int xioctl( int fd, int request, void *arg)
353 #endif
354 {
355
356   int r;
357
358
359   do r = v4l2_ioctl (fd, request, arg);
360   while (-1 == r && EINTR == errno);
361
362   return r;
363
364 }
365
366
367 /* Simple test program: Find number of Video Sources available.
368    Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
369    If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
370    Returns the global numCameras with the correct value (we hope) */
371
372 static void icvInitCapture_V4L() {
373    int deviceHandle;
374    int CameraNumber;
375    char deviceName[MAX_DEVICE_DRIVER_NAME];
376
377    CameraNumber = 0;
378    while(CameraNumber < MAX_CAMERAS) {
379       /* Print the CameraNumber at the end of the string with a width of one character */
380       sprintf(deviceName, "/dev/video%1d", CameraNumber);
381       /* Test using an open to see if this new device name really does exists. */
382       deviceHandle = open(deviceName, O_RDONLY);
383       if (deviceHandle != -1) {
384          /* This device does indeed exist - add it to the total so far */
385     // add indexList
386     indexList|=(1 << CameraNumber);
387         numCameras++;
388     }
389     if (deviceHandle != -1)
390       close(deviceHandle);
391       /* Set up to test the next /dev/video source in line */
392       CameraNumber++;
393    } /* End while */
394
395 }; /* End icvInitCapture_V4L */
396
397
398 static int try_init_v4l(CvCaptureCAM_V4L* capture, char *deviceName)
399
400 {
401
402   // if detect = -1 then unable to open device
403   // if detect = 0 then detected nothing
404   // if detect = 1 then V4L device
405   int detect = 0;
406
407
408   // Test device for V4L compability
409
410   /* Test using an open to see if this new device name really does exists. */
411   /* No matter what the name - it still must be opened! */
412   capture->deviceHandle = v4l1_open(deviceName, O_RDWR);
413
414
415   if (capture->deviceHandle == 0)
416   {
417     detect = -1;
418
419     icvCloseCAM_V4L(capture);
420   }
421
422   if (detect == 0)
423   {
424     /* Query the newly opened device for its capabilities */
425     if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCAP, &capture->capability) < 0)
426     {
427       detect = 0;
428
429       icvCloseCAM_V4L(capture);
430     }
431       else
432     {
433       detect = 1;
434     }
435   }
436
437   return detect;
438
439 }
440
441
442 static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
443 {
444
445   // if detect = -1 then unable to open device
446   // if detect = 0 then detected nothing
447   // if detect = 1 then V4L2 device
448   int detect = 0;
449
450
451   // Test device for V4L2 compability
452
453   /* Open and test V4L2 device */
454   capture->deviceHandle = v4l2_open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
455
456
457
458   if (capture->deviceHandle == 0)
459   {
460     detect = -1;
461
462     icvCloseCAM_V4L(capture);
463   }
464
465   if (detect == 0)
466   {
467     CLEAR (capture->cap);
468     if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
469     {
470       detect = 0;
471
472       icvCloseCAM_V4L(capture);
473     }
474       else
475     {
476       CLEAR (capture->capability);
477       capture->capability.type = capture->cap.capabilities;
478
479       /* Query channels number */
480       if (-1 != xioctl (capture->deviceHandle, VIDIOC_G_INPUT, &capture->capability.channels))
481       {
482         detect = 1;
483       }
484     }
485   }
486
487   return detect;
488
489 }
490
491
492 static void v4l2_scan_controls_enumerate_menu(CvCaptureCAM_V4L* capture)
493 {
494 //  printf (" Menu items:\n");
495   CLEAR (capture->querymenu);
496   capture->querymenu.id = capture->queryctrl.id;
497   for (capture->querymenu.index = capture->queryctrl.minimum;
498        (int)capture->querymenu.index <= capture->queryctrl.maximum;
499        capture->querymenu.index++)
500   {
501     if (0 == xioctl (capture->deviceHandle, VIDIOC_QUERYMENU,
502                      &capture->querymenu))
503     {
504       //printf (" %s\n", capture->querymenu.name);
505     } else {
506         perror ("VIDIOC_QUERYMENU");
507     }
508   }
509 }
510
511 static void v4l2_free_ranges(CvCaptureCAM_V4L* capture) {
512   int i;
513   if (capture->v4l2_ctrl_ranges != NULL) {
514     for (i = 0; i < capture->v4l2_ctrl_count; i++) {
515       /* Return device to initial values: */
516       /* 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); */
517       /* Return device to default values: */
518       /* 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); */
519
520       /* icvSetPropertyCAM_V4L(capture, capture->v4l2_ctrl_ranges[i]->ctrl_id, value); */
521       free(capture->v4l2_ctrl_ranges[i]);
522     }
523   }
524   free(capture->v4l2_ctrl_ranges);
525   capture->v4l2_ctrl_count  = 0;
526   capture->v4l2_ctrl_ranges = NULL;
527 }
528
529 static void v4l2_add_ctrl_range(CvCaptureCAM_V4L* capture, v4l2_control* ctrl) {
530   v4l2_ctrl_range* range    = (v4l2_ctrl_range*)malloc(sizeof(v4l2_ctrl_range));
531   range->ctrl_id            = ctrl->id;
532   range->initial_value      = ctrl->value;
533   range->current_value      = ctrl->value;
534   range->minimum            = capture->queryctrl.minimum;
535   range->maximum            = capture->queryctrl.maximum;
536   range->default_value      = capture->queryctrl.default_value;
537   capture->v4l2_ctrl_ranges[capture->v4l2_ctrl_count] = range;
538   capture->v4l2_ctrl_count += 1;
539   capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)realloc((v4l2_ctrl_range**)capture->v4l2_ctrl_ranges, (capture->v4l2_ctrl_count + 1) * sizeof(v4l2_ctrl_range*));
540 }
541
542 static int v4l2_get_ctrl_default(CvCaptureCAM_V4L* capture, __u32 id) {
543   int i;
544   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
545     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
546       return capture->v4l2_ctrl_ranges[i]->default_value;
547     }
548   }
549   return -1;
550 }
551
552 static int v4l2_get_ctrl_min(CvCaptureCAM_V4L* capture, __u32 id) {
553   int i;
554   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
555     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
556       return capture->v4l2_ctrl_ranges[i]->minimum;
557     }
558   }
559   return -1;
560 }
561
562 static int v4l2_get_ctrl_max(CvCaptureCAM_V4L* capture, __u32 id) {
563   int i;
564   for (i = 0; i < capture->v4l2_ctrl_count; i++) {
565     if (id == capture->v4l2_ctrl_ranges[i]->ctrl_id) {
566       return capture->v4l2_ctrl_ranges[i]->maximum;
567     }
568   }
569   return -1;
570 }
571
572
573 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture) {
574
575   __u32 ctrl_id;
576   struct v4l2_control c;
577   if (capture->v4l2_ctrl_ranges != NULL) {
578     v4l2_free_ranges(capture);
579   }
580   capture->v4l2_ctrl_ranges = (v4l2_ctrl_range**)malloc(sizeof(v4l2_ctrl_range*));
581 #ifdef V4L2_CTRL_FLAG_NEXT_CTRL
582   /* Try the extended control API first */
583   capture->queryctrl.id      = V4L2_CTRL_FLAG_NEXT_CTRL;
584   if(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl)) {
585     do {
586       c.id = capture->queryctrl.id;
587       capture->queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
588       if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
589         continue;
590       }
591       if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU) {
592         v4l2_scan_controls_enumerate_menu(capture);
593       }
594       if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
595          capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
596          capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
597         continue;
598       }
599       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
600         v4l2_add_ctrl_range(capture, &c);
601       }
602
603     } while(0 == v4l2_ioctl (capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl));
604   } else
605 #endif
606   {
607     /* Check all the standard controls */
608     for(ctrl_id=V4L2_CID_BASE; ctrl_id<V4L2_CID_LASTP1; ctrl_id++) {
609       capture->queryctrl.id = ctrl_id;
610       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
611         if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
612           continue;
613         }
614         if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU) {
615           v4l2_scan_controls_enumerate_menu(capture);
616         }
617         if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
618            capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
619            capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
620           continue;
621         }
622         c.id = ctrl_id;
623
624         if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
625           v4l2_add_ctrl_range(capture, &c);
626         }
627       }
628     }
629
630     /* Check any custom controls */
631     for(ctrl_id=V4L2_CID_PRIVATE_BASE; ; ctrl_id++) {
632       capture->queryctrl.id = ctrl_id;
633       if(v4l2_ioctl(capture->deviceHandle, VIDIOC_QUERYCTRL, &capture->queryctrl) == 0) {
634         if(capture->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
635           continue;
636         }
637
638         if (capture->queryctrl.type == V4L2_CTRL_TYPE_MENU) {
639           v4l2_scan_controls_enumerate_menu(capture);
640         }
641
642         if(capture->queryctrl.type != V4L2_CTRL_TYPE_INTEGER &&
643            capture->queryctrl.type != V4L2_CTRL_TYPE_BOOLEAN &&
644            capture->queryctrl.type != V4L2_CTRL_TYPE_MENU) {
645            continue;
646         }
647
648         c.id = ctrl_id;
649
650         if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &c) == 0) {
651           v4l2_add_ctrl_range(capture, &c);
652         }
653       } else {
654         break;
655       }
656     }
657   }
658 }
659
660 static int _capture_V4L2 (CvCaptureCAM_V4L *capture, char *deviceName)
661 {
662    int detect_v4l2 = 0;
663
664    capture->deviceName = strdup(deviceName);
665
666    detect_v4l2 = try_init_v4l2(capture, deviceName);
667
668    if (detect_v4l2 != 1) {
669        /* init of the v4l2 device is not OK */
670        return -1;
671    }
672
673    /* starting from here, we assume we are in V4L2 mode */
674    capture->is_v4l2_device = 1;
675
676    capture->v4l2_ctrl_ranges = NULL;
677    capture->v4l2_ctrl_count = 0;
678
679    /* Scan V4L2 controls */
680    v4l2_scan_controls(capture);
681
682    if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
683       /* Nope. */
684       fprintf( stderr, "HIGHGUI ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
685       icvCloseCAM_V4L(capture);
686       return -1;
687    }
688
689    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
690    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
691    I myself am using a simple NTSC video input capture card that uses the value of 1.
692    If you are not in North America or have a different video standard, you WILL have to change
693    the following settings and recompile/reinstall.  This set of settings is based on
694    the most commonly encountered input video source types (like my bttv card) */
695
696    if(capture->inp.index > 0) {
697        CLEAR (capture->inp);
698        capture->inp.index = CHANNEL_NUMBER;
699        /* Set only channel number to CHANNEL_NUMBER */
700        /* V4L2 have a status field from selected video mode */
701        if (-1 == xioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
702        {
703          fprintf (stderr, "HIGHGUI ERROR: V4L2: Aren't able to set channel number\n");
704          icvCloseCAM_V4L (capture);
705          return -1;
706        }
707    } /* End if */
708
709    /* Find Window info */
710    CLEAR (capture->form);
711    capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
712
713    if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
714        fprintf( stderr, "HIGHGUI ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
715        icvCloseCAM_V4L(capture);
716        return -1;
717    }
718
719   /* libv4l will convert from any format to V4L2_PIX_FMT_BGR24 */
720   CLEAR (capture->form);
721   capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
722   capture->form.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
723   capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
724   capture->form.fmt.pix.width = capture->width;
725   capture->form.fmt.pix.height = capture->height;
726
727   if (-1 == xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form)) {
728       fprintf(stderr, "HIGHGUI ERROR: libv4l unable to ioctl S_FMT\n");
729       return -1;
730   }
731
732   if (V4L2_PIX_FMT_BGR24 != capture->form.fmt.pix.pixelformat) {
733       fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n");
734       return -1;
735   }
736
737    /* icvSetVideoSize(capture, DEFAULT_V4L_WIDTH, DEFAULT_V4L_HEIGHT); */
738
739    unsigned int min;
740
741    /* Buggy driver paranoia. */
742    min = capture->form.fmt.pix.width * 2;
743
744    if (capture->form.fmt.pix.bytesperline < min)
745        capture->form.fmt.pix.bytesperline = min;
746
747    min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
748
749    if (capture->form.fmt.pix.sizeimage < min)
750        capture->form.fmt.pix.sizeimage = min;
751
752    CLEAR (capture->req);
753
754    unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
755
756    try_again:
757
758    capture->req.count = buffer_number;
759    capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
760    capture->req.memory = V4L2_MEMORY_MMAP;
761
762    if (-1 == xioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
763    {
764        if (EINVAL == errno)
765        {
766          fprintf (stderr, "%s does not support memory mapping\n", deviceName);
767        } else {
768          perror ("VIDIOC_REQBUFS");
769        }
770        /* free capture, and returns an error code */
771        icvCloseCAM_V4L (capture);
772        return -1;
773    }
774
775    if (capture->req.count < buffer_number)
776    {
777        if (buffer_number == 1)
778        {
779            fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
780
781            /* free capture, and returns an error code */
782            icvCloseCAM_V4L (capture);
783            return -1;
784        } else {
785          buffer_number--;
786    fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
787
788    goto try_again;
789        }
790    }
791
792    for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
793    {
794        struct v4l2_buffer buf;
795
796        CLEAR (buf);
797
798        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
799        buf.memory = V4L2_MEMORY_MMAP;
800        buf.index = n_buffers;
801
802        if (-1 == xioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
803            perror ("VIDIOC_QUERYBUF");
804
805            /* free capture, and returns an error code */
806            icvCloseCAM_V4L (capture);
807            return -1;
808        }
809
810        capture->buffers[n_buffers].length = buf.length;
811        capture->buffers[n_buffers].start =
812          v4l2_mmap (NULL /* start anywhere */,
813                     buf.length,
814                     PROT_READ | PROT_WRITE /* required */,
815                     MAP_SHARED /* recommended */,
816                     capture->deviceHandle, buf.m.offset);
817
818        if (MAP_FAILED == capture->buffers[n_buffers].start) {
819            perror ("mmap");
820
821            /* free capture, and returns an error code */
822            icvCloseCAM_V4L (capture);
823            return -1;
824        }
825
826 #ifdef USE_TEMP_BUFFER
827        if (n_buffers == 0) {
828            if (capture->buffers[MAX_V4L_BUFFERS].start) {
829                free(capture->buffers[MAX_V4L_BUFFERS].start);
830                capture->buffers[MAX_V4L_BUFFERS].start = NULL;
831        }
832
833            capture->buffers[MAX_V4L_BUFFERS].start = malloc(buf.length);
834            capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
835        };
836 #endif
837    }
838
839    /* Set up Image data */
840    cvInitImageHeader( &capture->frame,
841                       cvSize( capture->captureWindow.width,
842                               capture->captureWindow.height ),
843                       IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
844    /* Allocate space for RGBA data */
845    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
846
847    return 1;
848 }; /* End _capture_V4L2 */
849
850
851 static int _capture_V4L (CvCaptureCAM_V4L *capture, char *deviceName)
852 {
853    int detect_v4l = 0;
854
855    detect_v4l = try_init_v4l(capture, deviceName);
856
857    if ((detect_v4l == -1)
858        )
859    {
860      fprintf (stderr, "HIGHGUI ERROR: V4L"
861               ": device %s: Unable to open for READ ONLY\n", deviceName);
862
863      return -1;
864    }
865
866    if ((detect_v4l <= 0)
867        )
868    {
869      fprintf (stderr, "HIGHGUI ERROR: V4L"
870               ": device %s: Unable to query number of channels\n", deviceName);
871
872      return -1;
873    }
874
875    {
876      if ((capture->capability.type & VID_TYPE_CAPTURE) == 0) {
877        /* Nope. */
878        fprintf( stderr, "HIGHGUI ERROR: V4L: "
879                 "device %s is unable to capture video memory.\n",deviceName);
880        icvCloseCAM_V4L(capture);
881        return -1;
882      }
883
884    }
885
886
887    /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
888    have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
889    I myself am using a simple NTSC video input capture card that uses the value of 1.
890    If you are not in North America or have a different video standard, you WILL have to change
891    the following settings and recompile/reinstall.  This set of settings is based on
892    the most commonly encountered input video source types (like my bttv card) */
893
894    {
895
896      if(capture->capability.channels>0) {
897
898        struct video_channel selectedChannel;
899
900        selectedChannel.channel=CHANNEL_NUMBER;
901        if (v4l1_ioctl(capture->deviceHandle, VIDIOCGCHAN , &selectedChannel) != -1) {
902           /* set the video mode to ( VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM) */
903 //           selectedChannel.norm = VIDEO_MODE_NTSC;
904           if (v4l1_ioctl(capture->deviceHandle, VIDIOCSCHAN , &selectedChannel) == -1) {
905              /* Could not set selected channel - Oh well */
906              //printf("\n%d, %s not NTSC capable.\n",selectedChannel.channel, selectedChannel.name);
907           } /* End if */
908        } /* End if */
909      } /* End if */
910
911    }
912
913    {
914
915      if(v4l1_ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) == -1) {
916        fprintf( stderr, "HIGHGUI ERROR: V4L: "
917                 "Could not obtain specifics of capture window.\n\n");
918        icvCloseCAM_V4L(capture);
919        return -1;
920      }
921
922    }
923
924    {
925       if(v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
926          fprintf( stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
927          icvCloseCAM_V4L(capture);
928          return -1;
929       }
930
931       capture->imageProperties.palette = VIDEO_PALETTE_RGB24;
932       capture->imageProperties.depth = 24;
933       if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0) {
934         fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCSPICT\n\n");
935          icvCloseCAM_V4L(capture);
936         return -1;
937       }
938       if (v4l1_ioctl(capture->deviceHandle, VIDIOCGPICT, &capture->imageProperties) < 0) {
939         fprintf( stderr, "HIGHGUI ERROR: libv4l unable to ioctl VIDIOCGPICT\n\n");
940          icvCloseCAM_V4L(capture);
941         return -1;
942       }
943       if (capture->imageProperties.palette != VIDEO_PALETTE_RGB24) {
944         fprintf( stderr, "HIGHGUI ERROR: libv4l unable convert to requested pixfmt\n\n");
945          icvCloseCAM_V4L(capture);
946         return -1;
947       }
948
949    }
950
951    {
952
953      v4l1_ioctl(capture->deviceHandle, VIDIOCGMBUF, &capture->memoryBuffer);
954      capture->memoryMap  = (char *)v4l1_mmap(0,
955                                    capture->memoryBuffer.size,
956                                    PROT_READ | PROT_WRITE,
957                                    MAP_SHARED,
958                                    capture->deviceHandle,
959                                    0);
960      if (capture->memoryMap == MAP_FAILED) {
961         fprintf( stderr, "HIGHGUI ERROR: V4L: Mapping Memmory from video source error: %s\n", strerror(errno));
962         icvCloseCAM_V4L(capture);
963         return -1;
964      }
965
966      /* Set up video_mmap structure pointing to this memory mapped area so each image may be
967         retrieved from an index value */
968      capture->mmaps = (struct video_mmap *)
969                  (malloc(capture->memoryBuffer.frames * sizeof(struct video_mmap)));
970      if (!capture->mmaps) {
971         fprintf( stderr, "HIGHGUI ERROR: V4L: Could not memory map video frames.\n");
972         icvCloseCAM_V4L(capture);
973         return -1;
974      }
975
976    }
977
978    /* Set up Image data */
979    cvInitImageHeader( &capture->frame,
980                       cvSize( capture->captureWindow.width,
981                               capture->captureWindow.height ),
982                       IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
983    /* Allocate space for RGBA data */
984    capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
985
986    return 1;
987 }; /* End _capture_V4L */
988
989 static CvCaptureCAM_V4L * icvCaptureFromCAM_V4L (int index)
990 {
991    static int autoindex;
992    autoindex = 0;
993
994    char deviceName[MAX_DEVICE_DRIVER_NAME];
995
996    if (!numCameras)
997       icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
998    if (!numCameras)
999      return NULL; /* Are there any /dev/video input sources? */
1000
1001    //search index in indexList
1002    if ( (index>-1) && ! ((1 << index) & indexList) )
1003    {
1004      fprintf( stderr, "HIGHGUI ERROR: V4L: index %d is not correct!\n",index);
1005      return NULL; /* Did someone ask for not correct video source number? */
1006    }
1007    /* Allocate memory for this humongus CvCaptureCAM_V4L structure that contains ALL
1008       the handles for V4L processing */
1009    CvCaptureCAM_V4L * capture = (CvCaptureCAM_V4L*)cvAlloc(sizeof(CvCaptureCAM_V4L));
1010    if (!capture) {
1011       fprintf( stderr, "HIGHGUI ERROR: V4L: Could not allocate memory for capture process.\n");
1012       return NULL;
1013    }
1014
1015 #ifdef USE_TEMP_BUFFER
1016    capture->buffers[MAX_V4L_BUFFERS].start = NULL;
1017 #endif
1018
1019    /* Select camera, or rather, V4L video source */
1020    if (index<0) { // Asking for the first device available
1021      for (; autoindex<MAX_CAMERAS;autoindex++)
1022     if (indexList & (1<<autoindex))
1023         break;
1024      if (autoindex==MAX_CAMERAS)
1025     return NULL;
1026      index=autoindex;
1027      autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
1028    }
1029    /* Print the CameraNumber at the end of the string with a width of one character */
1030    sprintf(deviceName, "/dev/video%1d", index);
1031
1032    /* w/o memset some parts  arent initialized - AKA: Fill it with zeros so it is clean */
1033    memset(capture,0,sizeof(CvCaptureCAM_V4L));
1034    /* Present the routines needed for V4L funtionality.  They are inserted as part of
1035       the standard set of cv calls promoting transparency.  "Vector Table" insertion. */
1036    capture->FirstCapture = 1;
1037
1038    /* set the default size */
1039    capture->width  = DEFAULT_V4L_WIDTH;
1040    capture->height = DEFAULT_V4L_HEIGHT;
1041
1042    if (_capture_V4L2 (capture, deviceName) == -1) {
1043        icvCloseCAM_V4L(capture);
1044        capture->is_v4l2_device = 0;
1045        if (_capture_V4L (capture, deviceName) == -1) {
1046            icvCloseCAM_V4L(capture);
1047            return NULL;
1048        }
1049    } else {
1050        capture->is_v4l2_device = 1;
1051    }
1052
1053    return capture;
1054 }; /* End icvOpenCAM_V4L */
1055
1056 #ifdef HAVE_CAMV4L2
1057
1058 static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
1059     struct v4l2_buffer buf;
1060
1061     CLEAR (buf);
1062
1063     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1064     buf.memory = V4L2_MEMORY_MMAP;
1065
1066     if (-1 == xioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
1067         switch (errno) {
1068         case EAGAIN:
1069             return 0;
1070
1071         case EIO:
1072             /* Could ignore EIO, see spec. */
1073
1074             /* fall through */
1075
1076         default:
1077             /* display the error and stop processing */
1078             perror ("VIDIOC_DQBUF");
1079             return 1;
1080         }
1081    }
1082
1083    assert(buf.index < capture->req.count);
1084
1085 #ifdef USE_TEMP_BUFFER
1086    memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
1087     capture->buffers[buf.index].start,
1088     capture->buffers[MAX_V4L_BUFFERS].length );
1089    capture->bufferIndex = MAX_V4L_BUFFERS;
1090    //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
1091    //   buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
1092 #else
1093    capture->bufferIndex = buf.index;
1094 #endif
1095
1096    if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
1097        perror ("VIDIOC_QBUF");
1098
1099    return 1;
1100 }
1101
1102 static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
1103     unsigned int count;
1104
1105     count = 1;
1106
1107     while (count-- > 0) {
1108         for (;;) {
1109             fd_set fds;
1110             struct timeval tv;
1111             int r;
1112
1113             FD_ZERO (&fds);
1114             FD_SET (capture->deviceHandle, &fds);
1115
1116             /* Timeout. */
1117             tv.tv_sec = 10;
1118             tv.tv_usec = 0;
1119
1120             r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
1121
1122             if (-1 == r) {
1123                 if (EINTR == errno)
1124                     continue;
1125
1126                 perror ("select");
1127             }
1128
1129             if (0 == r) {
1130                 fprintf (stderr, "select timeout\n");
1131
1132                 /* end the infinite loop */
1133                 break;
1134             }
1135
1136             if (read_frame_v4l2 (capture))
1137                 break;
1138         }
1139     }
1140 }
1141
1142 static int icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
1143
1144    if (capture->FirstCapture) {
1145       /* Some general initialization must take place the first time through */
1146
1147       /* This is just a technicality, but all buffers must be filled up before any
1148          staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
1149
1150       if (capture->is_v4l2_device == 1)
1151       {
1152
1153         for (capture->bufferIndex = 0;
1154              capture->bufferIndex < ((int)capture->req.count);
1155              ++capture->bufferIndex)
1156         {
1157
1158           struct v4l2_buffer buf;
1159
1160           CLEAR (buf);
1161
1162           buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1163           buf.memory      = V4L2_MEMORY_MMAP;
1164           buf.index       = (unsigned long)capture->bufferIndex;
1165
1166           if (-1 == xioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
1167               perror ("VIDIOC_QBUF");
1168               return 0;
1169           }
1170         }
1171
1172         /* enable the streaming */
1173         capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1174         if (-1 == xioctl (capture->deviceHandle, VIDIOC_STREAMON,
1175                           &capture->type)) {
1176             /* error enabling the stream */
1177             perror ("VIDIOC_STREAMON");
1178             return 0;
1179         }
1180       } else
1181       {
1182
1183         for (capture->bufferIndex = 0;
1184          capture->bufferIndex < (capture->memoryBuffer.frames-1);
1185          ++capture->bufferIndex) {
1186
1187           capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1188           capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1189           capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1190           capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1191
1192           if (v4l1_ioctl(capture->deviceHandle, VIDIOCMCAPTURE, &capture->mmaps[capture->bufferIndex]) == -1) {
1193             fprintf( stderr, "HIGHGUI ERROR: V4L: Initial Capture Error: Unable to load initial memory buffers.\n");
1194             return 0;
1195           }
1196         }
1197
1198       }
1199
1200       /* preparation is ok */
1201       capture->FirstCapture = 0;
1202    }
1203
1204    if (capture->is_v4l2_device == 1)
1205    {
1206
1207      mainloop_v4l2(capture);
1208
1209    } else
1210    {
1211
1212      capture->mmaps[capture->bufferIndex].frame  = capture->bufferIndex;
1213      capture->mmaps[capture->bufferIndex].width  = capture->captureWindow.width;
1214      capture->mmaps[capture->bufferIndex].height = capture->captureWindow.height;
1215      capture->mmaps[capture->bufferIndex].format = capture->imageProperties.palette;
1216
1217      if (v4l1_ioctl (capture->deviceHandle, VIDIOCMCAPTURE,
1218     &capture->mmaps[capture->bufferIndex]) == -1) {
1219    /* capture is on the way, so just exit */
1220    return 1;
1221      }
1222
1223      ++capture->bufferIndex;
1224      if (capture->bufferIndex == capture->memoryBuffer.frames) {
1225         capture->bufferIndex = 0;
1226      }
1227
1228    }
1229
1230    return(1);
1231 }
1232
1233 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
1234
1235   if (capture->is_v4l2_device == 0)
1236   {
1237
1238     /* [FD] this really belongs here */
1239     if (v4l1_ioctl(capture->deviceHandle, VIDIOCSYNC, &capture->mmaps[capture->bufferIndex].frame) == -1) {
1240       fprintf( stderr, "HIGHGUI ERROR: V4L: Could not SYNC to video stream. %s\n", strerror(errno));
1241     }
1242
1243   }
1244
1245    /* Now get what has already been captured as a IplImage return */
1246
1247    /* First, reallocate imageData if the frame size changed */
1248
1249   if (capture->is_v4l2_device == 1)
1250   {
1251
1252     if(((unsigned long)capture->frame.width != capture->form.fmt.pix.width)
1253        || ((unsigned long)capture->frame.height != capture->form.fmt.pix.height)) {
1254         cvFree(&capture->frame.imageData);
1255         cvInitImageHeader( &capture->frame,
1256               cvSize( capture->form.fmt.pix.width,
1257                   capture->form.fmt.pix.height ),
1258               IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1259        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1260     }
1261
1262   } else
1263   {
1264
1265     if((capture->frame.width != capture->mmaps[capture->bufferIndex].width)
1266       || (capture->frame.height != capture->mmaps[capture->bufferIndex].height)) {
1267        cvFree(&capture->frame.imageData);
1268        cvInitImageHeader( &capture->frame,
1269               cvSize( capture->captureWindow.width,
1270                   capture->captureWindow.height ),
1271               IPL_DEPTH_8U, 3, IPL_ORIGIN_TL, 4 );
1272        capture->frame.imageData = (char *)cvAlloc(capture->frame.imageSize);
1273     }
1274
1275   }
1276
1277   if (capture->is_v4l2_device == 1)
1278   {
1279
1280     if(capture->buffers[capture->bufferIndex].start){
1281       memcpy((char *)capture->frame.imageData,
1282          (char *)capture->buffers[capture->bufferIndex].start,
1283          capture->frame.imageSize);
1284     }
1285
1286   } else
1287 #endif /* HAVE_CAMV4L2 */
1288   {
1289
1290     switch(capture->imageProperties.palette) {
1291       case VIDEO_PALETTE_RGB24:
1292         memcpy((char *)capture->frame.imageData,
1293            (char *)(capture->memoryMap + capture->memoryBuffer.offsets[capture->bufferIndex]),
1294            capture->frame.imageSize);
1295         break;
1296       default:
1297         fprintf( stderr,
1298                  "HIGHGUI ERROR: V4L: Cannot convert from palette %d to RGB\n",
1299                  capture->imageProperties.palette);
1300         return 0;
1301     }
1302
1303   }
1304
1305    return(&capture->frame);
1306 }
1307
1308 /* TODO: review this adaptation */
1309 static double icvGetPropertyCAM_V4L (CvCaptureCAM_V4L* capture,
1310                                      int property_id ) {
1311   char name[32];
1312   int is_v4l2_device = 0;
1313       /* initialize the control structure */
1314   switch (property_id) {
1315     case CV_CAP_PROP_FRAME_WIDTH:
1316     case CV_CAP_PROP_FRAME_HEIGHT:
1317       CLEAR (capture->form);
1318       capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1319       if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
1320           /* display an error message, and return an error code */
1321           perror ("VIDIOC_G_FMT");
1322         if (v4l1_ioctl (capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
1323           fprintf (stderr, "HIGHGUI ERROR: V4L: Unable to determine size of incoming image\n");
1324           icvCloseCAM_V4L(capture);
1325           return -1;
1326         } else {
1327           int retval = (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->captureWindow.width:capture->captureWindow.height;
1328           return retval / 0xFFFF;
1329         }
1330       }
1331       return (property_id == CV_CAP_PROP_FRAME_WIDTH)?capture->form.fmt.pix.width:capture->form.fmt.pix.height;
1332     case CV_CAP_PROP_BRIGHTNESS:
1333       sprintf(name, "Brightness");
1334       capture->control.id = V4L2_CID_BRIGHTNESS;
1335       break;
1336     case CV_CAP_PROP_CONTRAST:
1337       sprintf(name, "Contrast");
1338       capture->control.id = V4L2_CID_CONTRAST;
1339       break;
1340     case CV_CAP_PROP_SATURATION:
1341       sprintf(name, "Saturation");
1342       capture->control.id = V4L2_CID_SATURATION;
1343       break;
1344     case CV_CAP_PROP_HUE:
1345       sprintf(name, "Hue");
1346       capture->control.id = V4L2_CID_HUE;
1347       break;
1348     case CV_CAP_PROP_GAIN:
1349       sprintf(name, "Gain");
1350       capture->control.id = V4L2_CID_GAIN;
1351       break;
1352     case CV_CAP_PROP_EXPOSURE:
1353       sprintf(name, "Exposure");
1354       capture->control.id = V4L2_CID_EXPOSURE;
1355       break;
1356     default:
1357       sprintf(name, "<unknown property string>");
1358       capture->control.id = property_id;
1359   }
1360
1361   if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
1362     /* all went well */
1363     is_v4l2_device = 1;
1364   } else {
1365     fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
1366   }
1367
1368   if (is_v4l2_device == 1) {
1369       /* get the min/max values */
1370       int v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
1371       int v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
1372
1373       if ((v4l2_min == -1) && (v4l2_max == -1)) {
1374         fprintf(stderr, "HIGHGUI ERROR: V4L2: Property %s(%u) not supported by device\n", name, property_id);
1375         return -1;
1376       }
1377
1378       /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1379       return ((float)capture->control.value - v4l2_min) / (v4l2_max - v4l2_min);
1380
1381   } else {
1382     /* TODO: review this section */
1383     int retval = -1;
1384
1385     switch (property_id) {
1386       case CV_CAP_PROP_BRIGHTNESS:
1387         retval = capture->imageProperties.brightness;
1388         break;
1389       case CV_CAP_PROP_CONTRAST:
1390         retval = capture->imageProperties.contrast;
1391         break;
1392       case CV_CAP_PROP_SATURATION:
1393         retval = capture->imageProperties.colour;
1394         break;
1395       case CV_CAP_PROP_HUE:
1396         retval = capture->imageProperties.hue;
1397         break;
1398       case CV_CAP_PROP_GAIN:
1399         fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
1400         return -1;
1401         break;
1402       case CV_CAP_PROP_EXPOSURE:
1403         fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
1404         return -1;
1405         break;
1406     }
1407
1408     if (retval == -1) {
1409       /* there was a problem */
1410       return -1;
1411     }
1412     /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1413     return float (retval) / 0xFFFF;
1414   }
1415 }
1416
1417 static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h) {
1418
1419   if (capture->is_v4l2_device == 1)
1420   {
1421     char deviceName[MAX_DEVICE_DRIVER_NAME];
1422     sprintf(deviceName, "%s", capture->deviceName);
1423     icvCloseCAM_V4L(capture);
1424     _capture_V4L2(capture, deviceName);
1425
1426     CLEAR (capture->crop);
1427     capture->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1428     capture->crop.c.left       = 0;
1429     capture->crop.c.top        = 0;
1430     capture->crop.c.height     = h*24;
1431     capture->crop.c.width      = w*24;
1432
1433     /* set the crop area, but don't exit if the device don't support croping */
1434     xioctl (capture->deviceHandle, VIDIOC_S_CROP, &capture->crop);
1435
1436     CLEAR (capture->form);
1437     capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1438
1439     /* read the current setting, mainly to retreive the pixelformat information */
1440     xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form);
1441
1442     /* set the values we want to change */
1443     capture->form.fmt.pix.width = w;
1444     capture->form.fmt.pix.height = h;
1445     capture->form.fmt.win.chromakey = 0;
1446     capture->form.fmt.win.field = V4L2_FIELD_ANY;
1447     capture->form.fmt.win.clips = 0;
1448     capture->form.fmt.win.clipcount = 0;
1449     capture->form.fmt.pix.field = V4L2_FIELD_ANY;
1450
1451     /* ask the device to change the size
1452      * don't test if the set of the size is ok, because some device
1453      * don't allow changing the size, and we will get the real size
1454      * later */
1455     xioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form);
1456
1457     /* try to set framerate to 30 fps */
1458     struct v4l2_streamparm setfps;
1459     memset (&setfps, 0, sizeof(struct v4l2_streamparm));
1460     setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1461     setfps.parm.capture.timeperframe.numerator = 1;
1462     setfps.parm.capture.timeperframe.denominator = 30;
1463     xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
1464
1465     /* we need to re-initialize some things, like buffers, because the size has
1466      * changed */
1467     capture->FirstCapture = 1;
1468
1469     /* Get window info again, to get the real value */
1470     if (-1 == xioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form))
1471     {
1472       fprintf(stderr, "HIGHGUI ERROR: V4L/V4L2: Could not obtain specifics of capture window.\n\n");
1473
1474       icvCloseCAM_V4L(capture);
1475
1476       return 0;
1477     }
1478
1479     return 0;
1480
1481   } else
1482   {
1483
1484     if (capture==0) return 0;
1485      if (w>capture->capability.maxwidth) {
1486        w=capture->capability.maxwidth;
1487      }
1488      if (h>capture->capability.maxheight) {
1489        h=capture->capability.maxheight;
1490      }
1491
1492      capture->captureWindow.width=w;
1493      capture->captureWindow.height=h;
1494
1495      if (ioctl(capture->deviceHandle, VIDIOCSWIN, &capture->captureWindow) < 0) {
1496        icvCloseCAM_V4L(capture);
1497        return 0;
1498      }
1499
1500      if (ioctl(capture->deviceHandle, VIDIOCGWIN, &capture->captureWindow) < 0) {
1501        icvCloseCAM_V4L(capture);
1502        return 0;
1503      }
1504
1505      capture->FirstCapture = 1;
1506
1507   }
1508
1509   return 0;
1510
1511 }
1512
1513 static int icvSetControl (CvCaptureCAM_V4L* capture, int property_id, double value) {
1514   struct v4l2_control c;
1515   __s32 ctrl_value;
1516   char name[32];
1517   int is_v4l2  = 1;
1518   int v4l2_min = 0;
1519   int v4l2_max = 255;
1520   if (capture->v4l2_ctrl_ranges == NULL) {
1521     v4l2_scan_controls(capture);
1522   }
1523
1524   CLEAR (capture->control);
1525   CLEAR (capture->queryctrl);
1526
1527   /* get current values */
1528   switch (property_id) {
1529     case CV_CAP_PROP_BRIGHTNESS:
1530       sprintf(name, "Brightness");
1531       capture->control.id = V4L2_CID_BRIGHTNESS;
1532       break;
1533     case CV_CAP_PROP_CONTRAST:
1534       sprintf(name, "Contrast");
1535       capture->control.id = V4L2_CID_CONTRAST;
1536       break;
1537     case CV_CAP_PROP_SATURATION:
1538       sprintf(name, "Saturation");
1539       capture->control.id = V4L2_CID_SATURATION;
1540       break;
1541     case CV_CAP_PROP_HUE:
1542       sprintf(name, "Hue");
1543       capture->control.id = V4L2_CID_HUE;
1544       break;
1545     case CV_CAP_PROP_GAIN:
1546       sprintf(name, "Gain");
1547       capture->control.id = V4L2_CID_GAIN;
1548       break;
1549     case CV_CAP_PROP_EXPOSURE:
1550       sprintf(name, "Exposure");
1551       capture->control.id = V4L2_CID_EXPOSURE;
1552       break;
1553     default:
1554       sprintf(name, "<unknown property string>");
1555       capture->control.id = property_id;
1556   }
1557
1558   v4l2_min = v4l2_get_ctrl_min(capture, capture->control.id);
1559   v4l2_max = v4l2_get_ctrl_max(capture, capture->control.id);
1560
1561   if ((v4l2_min == -1) && (v4l2_max == -1)) {
1562     fprintf(stderr, "HIGHGUI ERROR: V4L: Property %s(%u) not supported by device\n", name, property_id);
1563     return -1;
1564   }
1565
1566   if(v4l2_ioctl(capture->deviceHandle, VIDIOC_G_CTRL, &capture->control) == 0) {
1567     /* all went well */
1568   } else {
1569     fprintf(stderr, "HIGHGUI ERROR: V4L2: Unable to get property %s(%u) - %s\n", name, capture->control.id, strerror(errno));
1570   }
1571
1572   if (v4l2_max != 0) {
1573     double val = value;
1574     if (value < 0.0) {
1575       val = 0.0;
1576     } else if (value > 1.0) {
1577       val = 1.0;
1578     }
1579     ctrl_value = val * (double)(v4l2_max - v4l2_min) + v4l2_min;
1580   } else {
1581     ctrl_value = v4l2_get_ctrl_default(capture, capture->control.id) * (double)(v4l2_max - v4l2_min) + v4l2_min;
1582   }
1583
1584   /* try and set value as if it was a v4l2 device */
1585   c.id    = capture->control.id;
1586   c.value = ctrl_value;
1587   if (v4l2_ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &c) != 0) {
1588     /* The driver may clamp the value or return ERANGE, ignored here */
1589     if (errno != ERANGE) {
1590       fprintf(stderr, "HIGHGUI ERROR: V4L2: Failed to set control \"%d\": %s (value %d)\n", c.id, strerror(errno), c.value);
1591       is_v4l2 = 0;
1592     } else {
1593       return 0;
1594     }
1595   } else {
1596     return 0;
1597   }
1598
1599   if (is_v4l2 == 0) { /* use v4l1_ioctl */
1600     fprintf(stderr, "HIGHGUI WARNING: Setting property %u through v4l2 failed. Trying with v4l1.\n", c.id);
1601     int v4l_value;
1602     /* scale the value to the wanted integer one */
1603     v4l_value = (int)(0xFFFF * value);
1604
1605     switch (property_id) {
1606       case CV_CAP_PROP_BRIGHTNESS:
1607         capture->imageProperties.brightness = v4l_value;
1608         break;
1609       case CV_CAP_PROP_CONTRAST:
1610         capture->imageProperties.contrast = v4l_value;
1611         break;
1612       case CV_CAP_PROP_SATURATION:
1613         capture->imageProperties.colour = v4l_value;
1614         break;
1615       case CV_CAP_PROP_HUE:
1616         capture->imageProperties.hue = v4l_value;
1617         break;
1618       case CV_CAP_PROP_GAIN:
1619           fprintf(stderr, "HIGHGUI ERROR: V4L: Gain control in V4L is not supported\n");
1620         return -1;
1621     case CV_CAP_PROP_EXPOSURE:
1622         fprintf(stderr, "HIGHGUI ERROR: V4L: Exposure control in V4L is not supported\n");
1623         return -1;
1624     default:
1625         fprintf(stderr, "HIGHGUI ERROR: V4L: property #%d is not supported\n", property_id);
1626         return -1;
1627     }
1628
1629     if (v4l1_ioctl(capture->deviceHandle, VIDIOCSPICT, &capture->imageProperties) < 0){
1630       fprintf(stderr, "HIGHGUI ERROR: V4L: Unable to set video informations\n");
1631       icvCloseCAM_V4L(capture);
1632       return -1;
1633     }
1634   }
1635
1636   /* all was OK */
1637   return 0;
1638 }
1639
1640 static int icvSetPropertyCAM_V4L(CvCaptureCAM_V4L* capture, int property_id, double value){
1641     static int width = 0, height = 0;
1642     int retval;
1643
1644     /* initialization */
1645     retval = 0;
1646
1647     /* two subsequent calls setting WIDTH and HEIGHT will change
1648        the video size */
1649     /* the first one will return an error, though. */
1650
1651     switch (property_id) {
1652     case CV_CAP_PROP_FRAME_WIDTH:
1653         width = cvRound(value);
1654         capture->width = width;
1655         if(width !=0 && height != 0) {
1656             retval = icvSetVideoSize( capture, width, height);
1657             width = height = 0;
1658         }
1659         break;
1660     case CV_CAP_PROP_FRAME_HEIGHT:
1661         height = cvRound(value);
1662         capture->height = height;
1663         if(width !=0 && height != 0) {
1664             retval = icvSetVideoSize( capture, width, height);
1665             width = height = 0;
1666         }
1667         break;
1668     case CV_CAP_PROP_FPS:
1669         struct v4l2_streamparm setfps;
1670         memset (&setfps, 0, sizeof(struct v4l2_streamparm));
1671         setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1672         setfps.parm.capture.timeperframe.numerator = 1;
1673         setfps.parm.capture.timeperframe.denominator = value;
1674         if (xioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps) < 0){
1675             fprintf(stderr, "HIGHGUI ERROR: V4L: Unable to set camera FPS\n");
1676             retval=0;
1677         }
1678         break;
1679     default:
1680         retval = icvSetControl(capture, property_id, value);
1681     }
1682
1683     /* return the the status */
1684     return retval;
1685 }
1686
1687 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
1688    /* Deallocate space - Hopefully, no leaks */
1689    if (capture) {
1690      v4l2_free_ranges(capture);
1691      if (capture->is_v4l2_device == 0) {
1692        if (capture->mmaps) {
1693          free(capture->mmaps);
1694        }
1695        if (capture->memoryMap) {
1696          v4l1_munmap(capture->memoryMap, capture->memoryBuffer.size);
1697        }
1698        if (capture->deviceHandle != -1) {
1699          v4l1_close(capture->deviceHandle);
1700        }
1701      } else {
1702        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1703        if (xioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type) < 0) {
1704          perror ("Unable to stop the stream.");
1705        }
1706        for (unsigned int n_buffers2 = 0; n_buffers2 < capture->req.count; ++n_buffers2) {
1707          if (-1 == v4l2_munmap (capture->buffers[n_buffers2].start, capture->buffers[n_buffers2].length)) {
1708            perror ("munmap");
1709          }
1710        }
1711
1712        if (capture->deviceHandle != -1) {
1713          v4l2_close(capture->deviceHandle);
1714        }
1715      }
1716
1717      if (capture->frame.imageData)
1718        cvFree(&capture->frame.imageData);
1719
1720 #ifdef USE_TEMP_BUFFER
1721      if (capture->buffers[MAX_V4L_BUFFERS].start) {
1722        free(capture->buffers[MAX_V4L_BUFFERS].start);
1723        capture->buffers[MAX_V4L_BUFFERS].start = NULL;
1724      }
1725 #endif
1726
1727      free(capture->deviceName);
1728      capture->deviceName = NULL;
1729      //v4l2_free_ranges(capture);
1730      //cvFree((void **)capture);
1731    }
1732 };
1733
1734
1735 class CvCaptureCAM_V4L_CPP : CvCapture
1736 {
1737 public:
1738     CvCaptureCAM_V4L_CPP() { captureV4L = 0; }
1739     virtual ~CvCaptureCAM_V4L_CPP() { close(); }
1740
1741     virtual bool open( int index );
1742     virtual void close();
1743
1744     virtual double getProperty(int);
1745     virtual bool setProperty(int, double);
1746     virtual bool grabFrame();
1747     virtual IplImage* retrieveFrame(int);
1748 protected:
1749
1750     CvCaptureCAM_V4L* captureV4L;
1751 };
1752
1753 bool CvCaptureCAM_V4L_CPP::open( int index )
1754 {
1755     close();
1756     captureV4L = icvCaptureFromCAM_V4L(index);
1757     return captureV4L != 0;
1758 }
1759
1760 void CvCaptureCAM_V4L_CPP::close()
1761 {
1762     if( captureV4L )
1763     {
1764         icvCloseCAM_V4L( captureV4L );
1765         cvFree( &captureV4L );
1766     }
1767 }
1768
1769 bool CvCaptureCAM_V4L_CPP::grabFrame()
1770 {
1771     return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false;
1772 }
1773
1774 IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int)
1775 {
1776     return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0;
1777 }
1778
1779 double CvCaptureCAM_V4L_CPP::getProperty( int propId )
1780 {
1781     return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0;
1782 }
1783
1784 bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value )
1785 {
1786     return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false;
1787 }
1788
1789 CvCapture* cvCreateCameraCapture_V4L( int index )
1790 {
1791     CvCaptureCAM_V4L_CPP* capture = new CvCaptureCAM_V4L_CPP;
1792
1793     if( capture->open( index ))
1794         return (CvCapture*)capture;
1795
1796     delete capture;
1797     return 0;
1798 }
1799
1800 #endif