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