cap_libv4l.cpp

blair a, 2014-02-16 10:36 pm

Download (57.2 kB)

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