1/* This is the contributed code: 2 3File: cvcap_v4l.cpp 4Current Location: ../opencv-0.9.6/otherlibs/videoio 5 6Original Version: 2003-03-12 Magnus Lundin lundin@mlu.mine.nu 7Original Comments: 8 9ML:This set of files adds support for firevre and usb cameras. 10First it tries to install a firewire camera, 11if that fails it tries a v4l/USB camera 12It has been tested with the motempl sample program 13 14First Patch: August 24, 2004 Travis Wood TravisOCV@tkwood.com 15For Release: OpenCV-Linux Beta4 opencv-0.9.6 16Tested On: LMLBT44 with 8 video inputs 17Problems? Post your questions at answers.opencv.org, 18 Report bugs at code.opencv.org, 19 Submit your fixes at https://github.com/Itseez/opencv/ 20Patched Comments: 21 22TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4 23were not working. I have rewritten them so they work for me. At the same time, trying 24to keep the original code as ML wrote it as unchanged as possible. No one likes to debug 25someone elses code, so I resisted changes as much as possible. I have tried to keep the 26same "ideas" where applicable, that is, where I could figure out what the previous author 27intended. Some areas I just could not help myself and had to "spiffy-it-up" my way. 28 29These drivers should work with other V4L frame capture cards other then my bttv 30driven frame capture card. 31 32Re Written driver for standard V4L mode. Tested using LMLBT44 video capture card. 33Standard bttv drivers are on the LMLBT44 with up to 8 Inputs. 34 35This utility was written with the help of the document: 36http://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo 37as a general guide for interfacing into the V4l standard. 38 39Made the index value passed for icvOpenCAM_V4L(index) be the number of the 40video device source in the /dev tree. The -1 uses original /dev/video. 41 42Index Device 43 0 /dev/video0 44 1 /dev/video1 45 2 /dev/video2 46 3 /dev/video3 47 ... 48 7 /dev/video7 49with 50 -1 /dev/video 51 52TW: You can select any video source, but this package was limited from the start to only 53ONE camera opened at any ONE time. 54This is an original program limitation. 55If you are interested, I will make my version available to other OpenCV users. The big 56difference in mine is you may pass the camera number as part of the cv argument, but this 57convention is non standard for current OpenCV calls and the camera number is not currently 58passed into the called routine. 59 60Second Patch: August 28, 2004 Sfuncia Fabio fiblan@yahoo.it 61For Release: OpenCV-Linux Beta4 Opencv-0.9.6 62 63FS: 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 68Third Patch: December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr 69For 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 90Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu 91For Release: OpenCV-Linux Beta5 OpenCV-0.9.7 92 93I 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 109Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu 110For Release: OpenCV-Linux Beta5 OpenCV-0.9.7 111 112I 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 118Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu 119For Release: OpenCV-Linux Beta5 OpenCV-0.9.7 120 121I 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 128Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu 129For Release: OpenCV-Linux Beta5 OpenCV-0.9.7 130 131I 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 1378th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch 138Add support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG. 139With this patch, new webcams of Logitech, like QuickCam Fusion works. 140Note: For use these webcams, look at the UVC driver at 141http://linux-uvc.berlios.de/ 142 1439th 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 15110th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com 152Fix reliability problems with high-resolution UVC cameras on linux 153the 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 15911th 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 16312th 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 17113th 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) 173make & enjoy! 174 17514th 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 18115th patch: May 12, 2010, Filipe Almeida filipe.almeida@ist.utl.pt 182- Broken compile of library (include "_videoio.h") 183 18416th 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 19417th 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 */ 289struct buffer 290{ 291 void * start; 292 size_t length; 293}; 294static 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 */ 300typedef 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 309typedef 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} 351CvCaptureCAM_V4L; 352 353static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ); 354 355static int icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture ); 356static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int ); 357CvCapture* cvCreateCameraCapture_V4L( int index ); 358 359static double icvGetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id ); 360static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value ); 361 362static int icvSetVideoSize( CvCaptureCAM_V4L* capture, int w, int h); 363 364/*********************** Implementations ***************************************/ 365 366static int numCameras = 0; 367static int indexList = 0; 368 369// IOCTL handling for V4L2 370#ifdef HAVE_IOCTL_ULONG 371static int xioctl( int fd, unsigned long request, void *arg) 372#else 373static 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 393static 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 419static 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 463static 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 513static 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 531static 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 544static 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 554static 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 564static 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 575static 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 653static 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 665static 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 873static 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 1026static 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 1095static 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 1144static 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 1184static 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 1275static 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 */ 1356static 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 1497static 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 1613static 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 1740static 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 1808static 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 1856class CvCaptureCAM_V4L_CPP : CvCapture 1857{ 1858public: 1859 CvCaptureCAM_V4L_CPP() { captureV4L = 0; } 1860 virtual ~CvCaptureCAM_V4L_CPP() { close(); } 1861 1862 virtual bool open( int index ); 1863 virtual void close(); 1864 1865 virtual double getProperty(int) const; 1866 virtual bool setProperty(int, double); 1867 virtual bool grabFrame(); 1868 virtual IplImage* retrieveFrame(int); 1869protected: 1870 1871 CvCaptureCAM_V4L* captureV4L; 1872}; 1873 1874bool CvCaptureCAM_V4L_CPP::open( int index ) 1875{ 1876 close(); 1877 captureV4L = icvCaptureFromCAM_V4L(index); 1878 return captureV4L != 0; 1879} 1880 1881void CvCaptureCAM_V4L_CPP::close() 1882{ 1883 if( captureV4L ) 1884 { 1885 icvCloseCAM_V4L( captureV4L ); 1886 cvFree( &captureV4L ); 1887 } 1888} 1889 1890bool CvCaptureCAM_V4L_CPP::grabFrame() 1891{ 1892 return captureV4L ? icvGrabFrameCAM_V4L( captureV4L ) != 0 : false; 1893} 1894 1895IplImage* CvCaptureCAM_V4L_CPP::retrieveFrame(int) 1896{ 1897 return captureV4L ? icvRetrieveFrameCAM_V4L( captureV4L, 0 ) : 0; 1898} 1899 1900double CvCaptureCAM_V4L_CPP::getProperty( int propId ) const 1901{ 1902 return captureV4L ? icvGetPropertyCAM_V4L( captureV4L, propId ) : 0.0; 1903} 1904 1905bool CvCaptureCAM_V4L_CPP::setProperty( int propId, double value ) 1906{ 1907 return captureV4L ? icvSetPropertyCAM_V4L( captureV4L, propId, value ) != 0 : false; 1908} 1909 1910CvCapture* 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