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