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