~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/modules/videoio/src/cap_v4l.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This is the contributed code:
 
2
 
 
3
File:             cvcap_v4l.cpp
 
4
Current Location: ../opencv-0.9.6/otherlibs/videoio
 
5
 
 
6
Original Version: 2003-03-12  Magnus Lundin lundin@mlu.mine.nu
 
7
Original Comments:
 
8
 
 
9
ML:This set of files adds support for firevre and usb cameras.
 
10
First it tries to install a firewire camera,
 
11
if that fails it tries a v4l/USB camera
 
12
It has been tested with the motempl sample program
 
13
 
 
14
First Patch:  August 24, 2004 Travis Wood   TravisOCV@tkwood.com
 
15
For Release:  OpenCV-Linux Beta4  opencv-0.9.6
 
16
Tested On:    LMLBT44 with 8 video inputs
 
17
Problems?     Post your questions at answers.opencv.org,
 
18
              Report bugs at code.opencv.org,
 
19
              Submit your fixes at https://github.com/Itseez/opencv/
 
20
Patched Comments:
 
21
 
 
22
TW: The cv cam utils that came with the initial release of OpenCV for LINUX Beta4
 
23
were not working.  I have rewritten them so they work for me. At the same time, trying
 
24
to keep the original code as ML wrote it as unchanged as possible.  No one likes to debug
 
25
someone elses code, so I resisted changes as much as possible.  I have tried to keep the
 
26
same "ideas" where applicable, that is, where I could figure out what the previous author
 
27
intended. Some areas I just could not help myself and had to "spiffy-it-up" my way.
 
28
 
 
29
These drivers should work with other V4L frame capture cards other then my bttv
 
30
driven frame capture card.
 
31
 
 
32
Re Written driver for standard V4L mode. Tested using LMLBT44 video capture card.
 
33
Standard bttv drivers are on the LMLBT44 with up to 8 Inputs.
 
34
 
 
35
This utility was written with the help of the document:
 
36
http://pages.cpsc.ucalgary.ca/~sayles/VFL_HowTo
 
37
as a general guide for interfacing into the V4l standard.
 
38
 
 
39
Made the index value passed for icvOpenCAM_V4L(index) be the number of the
 
40
video device source in the /dev tree. The -1 uses original /dev/video.
 
41
 
 
42
Index  Device
 
43
  0    /dev/video0
 
44
  1    /dev/video1
 
45
  2    /dev/video2
 
46
  3    /dev/video3
 
47
  ...
 
48
  7    /dev/video7
 
49
with
 
50
  -1   /dev/video
 
51
 
 
52
TW: You can select any video source, but this package was limited from the start to only
 
53
ONE camera opened at any ONE time.
 
54
This is an original program limitation.
 
55
If you are interested, I will make my version available to other OpenCV users.  The big
 
56
difference in mine is you may pass the camera number as part of the cv argument, but this
 
57
convention is non standard for current OpenCV calls and the camera number is not currently
 
58
passed into the called routine.
 
59
 
 
60
Second Patch:   August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
 
61
For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
 
62
 
 
63
FS: this patch fix not sequential index of device (unplugged device), and real numCameras.
 
64
    for -1 index (icvOpenCAM_V4L) i dont use /dev/video but real device available, because
 
65
    if /dev/video is a link to /dev/video0 and i unplugged device on /dev/video0, /dev/video
 
66
    is a bad link. I search the first available device with indexList.
 
67
 
 
68
Third Patch:   December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
 
69
For Release:  OpenCV-Linux Beta4 Opencv-0.9.6
 
70
 
 
71
[FD] I modified the following:
 
72
 - handle YUV420P, YUV420, and YUV411P palettes (for many webcams) without using floating-point
 
73
 - cvGrabFrame should not wait for the end of the first frame, and should return quickly
 
74
   (see videoio doc)
 
75
 - cvRetrieveFrame should in turn wait for the end of frame capture, and should not
 
76
   trigger the capture of the next frame (the user choses when to do it using GrabFrame)
 
77
   To get the old behavior, re-call cvRetrieveFrame just after cvGrabFrame.
 
78
 - having global bufferIndex and FirstCapture variables makes the code non-reentrant
 
79
 (e.g. when using several cameras), put these in the CvCapture struct.
 
80
 - according to V4L HowTo, incrementing the buffer index must be done before VIDIOCMCAPTURE.
 
81
 - the VID_TYPE_SCALES stuff from V4L HowTo is wrong: image size can be changed
 
82
   even if the hardware does not support scaling (e.g. webcams can have several
 
83
   resolutions available). Just don't try to set the size at 640x480 if the hardware supports
 
84
   scaling: open with the default (probably best) image size, and let the user scale it
 
85
   using SetProperty.
 
86
 - image size can be changed by two subsequent calls to SetProperty (for width and height)
 
87
 - bug fix: if the image size changes, realloc the new image only when it is grabbed
 
88
 - issue errors only when necessary, fix error message formatting.
 
89
 
 
90
Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
 
91
For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
 
92
 
 
93
I modified the following:
 
94
  - Additional Video4Linux2 support :)
 
95
  - Use mmap functions (v4l2)
 
96
  - New methods are internal:
 
97
    try_palette_v4l2 -> rewrite try_palette for v4l2
 
98
    mainloop_v4l2, read_image_v4l2 -> this methods are moved from official v4l2 capture.c example
 
99
    try_init_v4l -> device v4l initialisation
 
100
    try_init_v4l2 -> device v4l2 initialisation
 
101
    autosetup_capture_mode_v4l -> autodetect capture modes for v4l
 
102
    autosetup_capture_mode_v4l2 -> autodetect capture modes for v4l2
 
103
  - Modifications are according with Video4Linux old codes
 
104
  - Video4Linux handling is automatically if it does not recognize a Video4Linux2 device
 
105
  - Tested successfully with Logitech Quickcam Express (V4L), Creative Vista (V4L) and Genius VideoCam Notebook (V4L2)
 
106
  - Correct source lines with compiler warning messages
 
107
  - Information message from v4l/v4l2 detection
 
108
 
 
109
Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
 
110
For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
 
111
 
 
112
I modified the following:
 
113
  - SN9C10x chip based webcams support
 
114
  - New methods are internal:
 
115
    bayer2rgb24, sonix_decompress -> decoder routines for SN9C10x decoding from Takafumi Mizuno <taka-qce@ls-a.jp> with his pleasure :)
 
116
  - Tested successfully with Genius VideoCam Notebook (V4L2)
 
117
 
 
118
Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
 
119
For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
 
120
 
 
121
I added the following:
 
122
  - Add capture control support (hue, saturation, brightness, contrast, gain)
 
123
  - Get and change V4L capture controls (hue, saturation, brightness, contrast)
 
124
  - New method is internal:
 
125
    icvSetControl -> set capture controls
 
126
  - Tested successfully with Creative Vista (V4L)
 
127
 
 
128
Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
 
129
For Release:  OpenCV-Linux Beta5 OpenCV-0.9.7
 
130
 
 
131
I added the following:
 
132
  - Detect, get and change V4L2 capture controls (hue, saturation, brightness, contrast, gain)
 
133
  - New methods are internal:
 
134
    v4l2_scan_controls_enumerate_menu, v4l2_scan_controls -> detect capture control intervals
 
135
  - Tested successfully with Genius VideoCam Notebook (V4L2)
 
136
 
 
137
8th patch: Jan 5, 2006, Olivier.Bornet@idiap.ch
 
138
Add support of V4L2_PIX_FMT_YUYV and V4L2_PIX_FMT_MJPEG.
 
139
With this patch, new webcams of Logitech, like QuickCam Fusion works.
 
140
Note: For use these webcams, look at the UVC driver at
 
141
http://linux-uvc.berlios.de/
 
142
 
 
143
9th patch: Mar 4, 2006, Olivier.Bornet@idiap.ch
 
144
- try V4L2 before V4L, because some devices are V4L2 by default,
 
145
  but they try to implement the V4L compatibility layer.
 
146
  So, I think this is better to support V4L2 before V4L.
 
147
- better separation between V4L2 and V4L initialization. (this was needed to support
 
148
  some drivers working, but not fully with V4L2. (so, we do not know when we
 
149
  need to switch from V4L2 to V4L.
 
150
 
 
151
10th patch: July 02, 2008, Mikhail Afanasyev fopencv@theamk.com
 
152
Fix reliability problems with high-resolution UVC cameras on linux
 
153
the symptoms were damaged image and 'Corrupt JPEG data: premature end of data segment' on stderr
 
154
- V4L_ABORT_BADJPEG detects JPEG warnings and turns them into errors, so bad images
 
155
  could be filtered out
 
156
- USE_TEMP_BUFFER fixes the main problem (improper buffer management) and
 
157
  prevents bad images in the first place
 
158
 
 
159
11th patch: April 2, 2013, Forrest Reiling forrest.reiling@gmail.com
 
160
Added v4l2 support for getting capture property CV_CAP_PROP_POS_MSEC.
 
161
Returns the millisecond timestamp of the last frame grabbed or 0 if no frames have been grabbed
 
162
Used to successfully synchonize 2 Logitech C310 USB webcams to within 16 ms of one another
 
163
 
 
164
 
 
165
make & enjoy!
 
166
 
 
167
*/
 
168
 
 
169
/*M///////////////////////////////////////////////////////////////////////////////////////
 
170
//
 
171
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 
172
//
 
173
//  By downloading, copying, installing or using the software you agree to this license.
 
174
//  If you do not agree to this license, do not download, install,
 
175
//  copy or use the software.
 
176
//
 
177
//
 
178
//                        Intel License Agreement
 
179
//                For Open Source Computer Vision Library
 
180
//
 
181
// Copyright (C) 2000, Intel Corporation, all rights reserved.
 
182
// Third party copyrights are property of their respective owners.
 
183
//
 
184
// Redistribution and use in source and binary forms, with or without modification,
 
185
// are permitted provided that the following conditions are met:
 
186
//
 
187
//   * Redistribution's of source code must retain the above copyright notice,
 
188
//     this list of conditions and the following disclaimer.
 
189
//
 
190
//   * Redistribution's in binary form must reproduce the above copyright notice,
 
191
//     this list of conditions and the following disclaimer in the documentation
 
192
//     and/or other materials provided with the distribution.
 
193
//
 
194
//   * The name of Intel Corporation may not be used to endorse or promote products
 
195
//     derived from this software without specific prior written permission.
 
196
//
 
197
// This software is provided by the copyright holders and contributors "as is" and
 
198
// any express or implied warranties, including, but not limited to, the implied
 
199
// warranties of merchantability and fitness for a particular purpose are disclaimed.
 
200
// In no event shall the Intel Corporation or contributors be liable for any direct,
 
201
// indirect, incidental, special, exemplary, or consequential damages
 
202
// (including, but not limited to, procurement of substitute goods or services;
 
203
// loss of use, data, or profits; or business interruption) however caused
 
204
// and on any theory of liability, whether in contract, strict liability,
 
205
// or tort (including negligence or otherwise) arising in any way out of
 
206
// the use of this software, even if advised of the possibility of such damage.
 
207
//
 
208
//M*/
 
209
 
 
210
#include "precomp.hpp"
 
211
 
 
212
#if !defined WIN32 && (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO)
 
213
 
 
214
#include <stdio.h>
 
215
#include <unistd.h>
 
216
#include <fcntl.h>
 
217
#include <errno.h>
 
218
#include <sys/ioctl.h>
 
219
#include <sys/types.h>
 
220
#include <sys/mman.h>
 
221
 
 
222
#include <string.h>
 
223
#include <stdlib.h>
 
224
#include <assert.h>
 
225
#include <sys/stat.h>
 
226
#include <sys/ioctl.h>
 
227
 
 
228
#ifdef HAVE_CAMV4L2
 
229
#include <asm/types.h>          /* for videodev2.h */
 
230
#include <linux/videodev2.h>
 
231
#endif
 
232
 
 
233
#ifdef HAVE_VIDEOIO
 
234
// NetBSD compability layer with V4L2
 
235
#include <sys/videoio.h>
 
236
#endif
 
237
 
 
238
/* Defaults - If your board can do better, set it here.  Set for the most common type inputs. */
 
239
#define DEFAULT_V4L_WIDTH  640
 
240
#define DEFAULT_V4L_HEIGHT 480
 
241
#define DEFAULT_V4L_FPS 30
 
242
 
 
243
#define CHANNEL_NUMBER 1
 
244
#define MAX_CAMERAS 8
 
245
 
 
246
 
 
247
// default and maximum number of V4L buffers, not including last, 'special' buffer
 
248
#define MAX_V4L_BUFFERS 10
 
249
#define DEFAULT_V4L_BUFFERS 4
 
250
 
 
251
// if enabled, then bad JPEG warnings become errors and cause NULL returned instead of image
 
252
#define V4L_ABORT_BADJPEG
 
253
 
 
254
#define MAX_DEVICE_DRIVER_NAME 80
 
255
 
 
256
namespace cv {
 
257
 
 
258
/* Device Capture Objects */
 
259
/* V4L2 structure */
 
260
struct buffer
 
261
{
 
262
  void *  start;
 
263
  size_t  length;
 
264
};
 
265
 
 
266
static unsigned int n_buffers = 0;
 
267
 
 
268
struct CvCaptureCAM_V4L : public CvCapture
 
269
{
 
270
    int deviceHandle;
 
271
    int bufferIndex;
 
272
    int FirstCapture;
 
273
 
 
274
    char *memoryMap;
 
275
    IplImage frame;
 
276
 
 
277
   __u32 palette;
 
278
   int index;
 
279
   int width, height;
 
280
   __u32 fps;
 
281
   bool convert_rgb;
 
282
   bool frame_allocated;
 
283
 
 
284
   /* V4L2 variables */
 
285
   buffer buffers[MAX_V4L_BUFFERS + 1];
 
286
   v4l2_capability cap;
 
287
   v4l2_input inp;
 
288
   v4l2_format form;
 
289
   v4l2_crop crop;
 
290
   v4l2_cropcap cropcap;
 
291
   v4l2_requestbuffers req;
 
292
   v4l2_buf_type type;
 
293
   v4l2_queryctrl queryctrl;
 
294
 
 
295
   timeval timestamp;
 
296
 
 
297
   /* V4L2 control variables */
 
298
   Range focus, brightness, contrast, saturation, hue, gain, exposure;
 
299
 
 
300
   bool open(int _index);
 
301
 
 
302
   virtual double getProperty(int) const;
 
303
   virtual bool setProperty(int, double);
 
304
   virtual bool grabFrame();
 
305
   virtual IplImage* retrieveFrame(int);
 
306
 
 
307
   Range getRange(int property_id) const {
 
308
       switch (property_id) {
 
309
       case CV_CAP_PROP_BRIGHTNESS:
 
310
           return brightness;
 
311
       case CV_CAP_PROP_CONTRAST:
 
312
           return contrast;
 
313
       case CV_CAP_PROP_SATURATION:
 
314
           return saturation;
 
315
       case CV_CAP_PROP_HUE:
 
316
           return hue;
 
317
       case CV_CAP_PROP_GAIN:
 
318
           return gain;
 
319
       case CV_CAP_PROP_EXPOSURE:
 
320
           return exposure;
 
321
       case CV_CAP_PROP_FOCUS:
 
322
           return focus;
 
323
       case CV_CAP_PROP_AUTOFOCUS:
 
324
           return Range(0, 1);
 
325
       default:
 
326
           return Range(0, 255);
 
327
       }
 
328
   }
 
329
 
 
330
   virtual ~CvCaptureCAM_V4L();
 
331
};
 
332
 
 
333
static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
 
334
 
 
335
static bool icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
 
336
static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
 
337
 
 
338
static double icvGetPropertyCAM_V4L( const CvCaptureCAM_V4L* capture, int property_id );
 
339
static int    icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
 
340
 
 
341
/***********************   Implementations  ***************************************/
 
342
 
 
343
static int numCameras = 0;
 
344
static int indexList = 0;
 
345
 
 
346
CvCaptureCAM_V4L::~CvCaptureCAM_V4L() {
 
347
    icvCloseCAM_V4L(this);
 
348
}
 
349
 
 
350
/* Simple test program: Find number of Video Sources available.
 
351
   Start from 0 and go to MAX_CAMERAS while checking for the device with that name.
 
352
   If it fails on the first attempt of /dev/video0, then check if /dev/video is valid.
 
353
   Returns the global numCameras with the correct value (we hope) */
 
354
 
 
355
static void icvInitCapture_V4L() {
 
356
   int deviceHandle;
 
357
   int CameraNumber;
 
358
   char deviceName[MAX_DEVICE_DRIVER_NAME];
 
359
 
 
360
   CameraNumber = 0;
 
361
   while(CameraNumber < MAX_CAMERAS) {
 
362
      /* Print the CameraNumber at the end of the string with a width of one character */
 
363
      sprintf(deviceName, "/dev/video%1d", CameraNumber);
 
364
      /* Test using an open to see if this new device name really does exists. */
 
365
      deviceHandle = open(deviceName, O_RDONLY);
 
366
      if (deviceHandle != -1) {
 
367
         /* This device does indeed exist - add it to the total so far */
 
368
    // add indexList
 
369
    indexList|=(1 << CameraNumber);
 
370
        numCameras++;
 
371
    }
 
372
    if (deviceHandle != -1)
 
373
      close(deviceHandle);
 
374
      /* Set up to test the next /dev/video source in line */
 
375
      CameraNumber++;
 
376
   } /* End while */
 
377
 
 
378
}; /* End icvInitCapture_V4L */
 
379
 
 
380
static bool try_palette_v4l2(CvCaptureCAM_V4L* capture)
 
381
{
 
382
  capture->form = v4l2_format();
 
383
  capture->form.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
384
  capture->form.fmt.pix.pixelformat = capture->palette;
 
385
  capture->form.fmt.pix.field       = V4L2_FIELD_ANY;
 
386
  capture->form.fmt.pix.width       = capture->width;
 
387
  capture->form.fmt.pix.height      = capture->height;
 
388
 
 
389
  if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
 
390
      return false;
 
391
 
 
392
  return capture->palette == capture->form.fmt.pix.pixelformat;
 
393
}
 
394
 
 
395
static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
 
396
{
 
397
  // Test device for V4L2 compability
 
398
  // Return value:
 
399
  // -1 then unable to open device
 
400
  //  0 then detected nothing
 
401
  //  1 then V4L2 device
 
402
 
 
403
  int deviceIndex;
 
404
 
 
405
  /* Open and test V4L2 device */
 
406
  capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
 
407
  if (-1 == capture->deviceHandle)
 
408
  {
 
409
#ifndef NDEBUG
 
410
    fprintf(stderr, "(DEBUG) try_init_v4l2 open \"%s\": %s\n", deviceName, strerror(errno));
 
411
#endif
 
412
    icvCloseCAM_V4L(capture);
 
413
    return -1;
 
414
  }
 
415
 
 
416
  capture->cap = v4l2_capability();
 
417
  if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
 
418
  {
 
419
#ifndef NDEBUG
 
420
    fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_QUERYCAP \"%s\": %s\n", deviceName, strerror(errno));
 
421
#endif
 
422
    icvCloseCAM_V4L(capture);
 
423
    return 0;
 
424
  }
 
425
 
 
426
  /* Query channels number */
 
427
  if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_INPUT, &deviceIndex))
 
428
  {
 
429
#ifndef NDEBUG
 
430
    fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_G_INPUT \"%s\": %s\n", deviceName, strerror(errno));
 
431
#endif
 
432
    icvCloseCAM_V4L(capture);
 
433
    return 0;
 
434
  }
 
435
 
 
436
  /* Query information about current input */
 
437
  capture->inp = v4l2_input();
 
438
  capture->inp.index = deviceIndex;
 
439
  if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
 
440
  {
 
441
#ifndef NDEBUG
 
442
    fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_ENUMINPUT \"%s\": %s\n", deviceName, strerror(errno));
 
443
#endif
 
444
    icvCloseCAM_V4L(capture);
 
445
    return 0;
 
446
  }
 
447
 
 
448
  return 1;
 
449
 
 
450
}
 
451
 
 
452
static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) {
 
453
    __u32 try_order[] = {
 
454
            V4L2_PIX_FMT_BGR24,
 
455
            V4L2_PIX_FMT_YVU420,
 
456
            V4L2_PIX_FMT_YUV411P,
 
457
#ifdef HAVE_JPEG
 
458
            V4L2_PIX_FMT_MJPEG,
 
459
            V4L2_PIX_FMT_JPEG,
 
460
#endif
 
461
            V4L2_PIX_FMT_YUYV,
 
462
            V4L2_PIX_FMT_UYVY,
 
463
            V4L2_PIX_FMT_SN9C10X,
 
464
            V4L2_PIX_FMT_SBGGR8,
 
465
            V4L2_PIX_FMT_SGBRG8,
 
466
            V4L2_PIX_FMT_RGB24
 
467
    };
 
468
 
 
469
    for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) {
 
470
        capture->palette = try_order[i];
 
471
        if (try_palette_v4l2(capture)) {
 
472
            return 0;
 
473
        }
 
474
    }
 
475
 
 
476
    fprintf(stderr,
 
477
            "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
 
478
    icvCloseCAM_V4L(capture);
 
479
    return -1;
 
480
}
 
481
 
 
482
static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id)
 
483
{
 
484
    cap->queryctrl= v4l2_queryctrl();
 
485
    cap->queryctrl.id = id;
 
486
 
 
487
    if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl))
 
488
    {
 
489
        if (errno != EINVAL)
 
490
            perror ("VIDIOC_QUERYCTRL");
 
491
        return;
 
492
    }
 
493
 
 
494
    if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
 
495
        return;
 
496
 
 
497
    Range range(cap->queryctrl.minimum, cap->queryctrl.maximum);
 
498
 
 
499
    switch(cap->queryctrl.id) {
 
500
    case V4L2_CID_BRIGHTNESS:
 
501
        cap->brightness = range;
 
502
        break;
 
503
    case V4L2_CID_CONTRAST:
 
504
        cap->contrast = range;
 
505
        break;
 
506
    case V4L2_CID_SATURATION:
 
507
        cap->saturation = range;
 
508
        break;
 
509
    case V4L2_CID_HUE:
 
510
        cap->hue = range;
 
511
        break;
 
512
    case V4L2_CID_GAIN:
 
513
        cap->gain = range;
 
514
        break;
 
515
    case V4L2_CID_EXPOSURE:
 
516
        cap->exposure = range;
 
517
        break;
 
518
    case V4L2_CID_FOCUS_ABSOLUTE:
 
519
        cap->focus = range;
 
520
        break;
 
521
    }
 
522
}
 
523
 
 
524
static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
 
525
{
 
526
 
 
527
  __u32 ctrl_id;
 
528
 
 
529
  for (ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++)
 
530
  {
 
531
      v4l2_control_range(capture, ctrl_id);
 
532
  }
 
533
 
 
534
  for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
 
535
  {
 
536
      v4l2_control_range(capture, ctrl_id);
 
537
 
 
538
      if (errno == EINVAL)
 
539
        break;
 
540
  }
 
541
 
 
542
  v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE);
 
543
}
 
544
 
 
545
static int v4l2_set_fps(CvCaptureCAM_V4L* capture) {
 
546
    v4l2_streamparm setfps = v4l2_streamparm();
 
547
    setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
548
    setfps.parm.capture.timeperframe.numerator = 1;
 
549
    setfps.parm.capture.timeperframe.denominator = capture->fps;
 
550
    return ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
 
551
}
 
552
 
 
553
static int v4l2_num_channels(__u32 palette) {
 
554
    switch(palette) {
 
555
    case V4L2_PIX_FMT_YVU420:
 
556
    case V4L2_PIX_FMT_MJPEG:
 
557
    case V4L2_PIX_FMT_JPEG:
 
558
        return 1;
 
559
    case V4L2_PIX_FMT_YUYV:
 
560
    case V4L2_PIX_FMT_UYVY:
 
561
        return 2;
 
562
    case V4L2_PIX_FMT_BGR24:
 
563
    case V4L2_PIX_FMT_RGB24:
 
564
        return 3;
 
565
    default:
 
566
        return 0;
 
567
    }
 
568
}
 
569
 
 
570
static void v4l2_create_frame(CvCaptureCAM_V4L *capture) {
 
571
    CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height);
 
572
    int channels = 3;
 
573
 
 
574
    if (!capture->convert_rgb) {
 
575
        channels = v4l2_num_channels(capture->palette);
 
576
 
 
577
        switch(capture->palette) {
 
578
        case V4L2_PIX_FMT_MJPEG:
 
579
        case V4L2_PIX_FMT_JPEG:
 
580
            size = CvSize(capture->buffers[capture->bufferIndex].length, 1);
 
581
            break;
 
582
        case V4L2_PIX_FMT_YVU420:
 
583
            size.height = size.height * 3 / 2; // "1.5" channels
 
584
            break;
 
585
        }
 
586
    }
 
587
 
 
588
    /* Set up Image data */
 
589
    cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels);
 
590
 
 
591
    /* Allocate space for pixelformat we convert to.
 
592
     * If we do not convert frame is just points to the buffer
 
593
     */
 
594
    if(capture->convert_rgb) {
 
595
        capture->frame.imageData = (char*)cvAlloc(capture->frame.imageSize);
 
596
    }
 
597
 
 
598
    capture->frame_allocated = capture->convert_rgb;
 
599
}
 
600
 
 
601
static int _capture_V4L2 (CvCaptureCAM_V4L *capture)
 
602
{
 
603
   char deviceName[MAX_DEVICE_DRIVER_NAME];
 
604
   /* Print the CameraNumber at the end of the string with a width of one character */
 
605
   sprintf(deviceName, "/dev/video%1d", capture->index);
 
606
 
 
607
   if (try_init_v4l2(capture, deviceName) != 1) {
 
608
       /* init of the v4l2 device is not OK */
 
609
       return -1;
 
610
   }
 
611
 
 
612
   /* V4L2 control variables are zero (memset above) */
 
613
 
 
614
   /* Scan V4L2 controls */
 
615
   v4l2_scan_controls(capture);
 
616
 
 
617
   if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
 
618
      /* Nope. */
 
619
      fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
 
620
      icvCloseCAM_V4L(capture);
 
621
      return -1;
 
622
   }
 
623
 
 
624
   /* The following code sets the CHANNEL_NUMBER of the video input.  Some video sources
 
625
   have sub "Channel Numbers".  For a typical V4L TV capture card, this is usually 1.
 
626
   I myself am using a simple NTSC video input capture card that uses the value of 1.
 
627
   If you are not in North America or have a different video standard, you WILL have to change
 
628
   the following settings and recompile/reinstall.  This set of settings is based on
 
629
   the most commonly encountered input video source types (like my bttv card) */
 
630
 
 
631
   if(capture->inp.index > 0) {
 
632
       capture->inp = v4l2_input();
 
633
       capture->inp.index = CHANNEL_NUMBER;
 
634
       /* Set only channel number to CHANNEL_NUMBER */
 
635
       /* V4L2 have a status field from selected video mode */
 
636
       if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
 
637
       {
 
638
         fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
 
639
         icvCloseCAM_V4L (capture);
 
640
         return -1;
 
641
       }
 
642
   } /* End if */
 
643
 
 
644
   /* Find Window info */
 
645
   capture->form = v4l2_format();
 
646
   capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
647
 
 
648
   if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
 
649
       fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
 
650
       icvCloseCAM_V4L(capture);
 
651
       return -1;
 
652
   }
 
653
 
 
654
   if (autosetup_capture_mode_v4l2(capture) == -1)
 
655
       return -1;
 
656
 
 
657
   /* try to set framerate */
 
658
   v4l2_set_fps(capture);
 
659
 
 
660
   unsigned int min;
 
661
 
 
662
   /* Buggy driver paranoia. */
 
663
   min = capture->form.fmt.pix.width * 2;
 
664
 
 
665
   if (capture->form.fmt.pix.bytesperline < min)
 
666
       capture->form.fmt.pix.bytesperline = min;
 
667
 
 
668
   min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
 
669
 
 
670
   if (capture->form.fmt.pix.sizeimage < min)
 
671
       capture->form.fmt.pix.sizeimage = min;
 
672
 
 
673
   capture->req = v4l2_requestbuffers();
 
674
 
 
675
   unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
 
676
 
 
677
   try_again:
 
678
 
 
679
   capture->req.count = buffer_number;
 
680
   capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
681
   capture->req.memory = V4L2_MEMORY_MMAP;
 
682
 
 
683
   if (-1 == ioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
 
684
   {
 
685
       if (EINVAL == errno)
 
686
       {
 
687
         fprintf (stderr, "%s does not support memory mapping\n", deviceName);
 
688
       } else {
 
689
         perror ("VIDIOC_REQBUFS");
 
690
       }
 
691
       /* free capture, and returns an error code */
 
692
       icvCloseCAM_V4L (capture);
 
693
       return -1;
 
694
   }
 
695
 
 
696
   if (capture->req.count < buffer_number)
 
697
   {
 
698
       if (buffer_number == 1)
 
699
       {
 
700
           fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
 
701
 
 
702
           /* free capture, and returns an error code */
 
703
           icvCloseCAM_V4L (capture);
 
704
           return -1;
 
705
       } else {
 
706
         buffer_number--;
 
707
     fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
 
708
 
 
709
     goto try_again;
 
710
       }
 
711
   }
 
712
 
 
713
   for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
 
714
   {
 
715
       v4l2_buffer buf = v4l2_buffer();
 
716
       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
717
       buf.memory = V4L2_MEMORY_MMAP;
 
718
       buf.index = n_buffers;
 
719
 
 
720
       if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
 
721
           perror ("VIDIOC_QUERYBUF");
 
722
 
 
723
           /* free capture, and returns an error code */
 
724
           icvCloseCAM_V4L (capture);
 
725
           return -1;
 
726
       }
 
727
 
 
728
       capture->buffers[n_buffers].length = buf.length;
 
729
       capture->buffers[n_buffers].start =
 
730
         mmap (NULL /* start anywhere */,
 
731
               buf.length,
 
732
               PROT_READ | PROT_WRITE /* required */,
 
733
               MAP_SHARED /* recommended */,
 
734
               capture->deviceHandle, buf.m.offset);
 
735
 
 
736
       if (MAP_FAILED == capture->buffers[n_buffers].start) {
 
737
           perror ("mmap");
 
738
 
 
739
           /* free capture, and returns an error code */
 
740
           icvCloseCAM_V4L (capture);
 
741
           return -1;
 
742
       }
 
743
 
 
744
       if (n_buffers == 0) {
 
745
     capture->buffers[MAX_V4L_BUFFERS].start = malloc( buf.length );
 
746
     capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
 
747
       }
 
748
   }
 
749
 
 
750
   v4l2_create_frame(capture);
 
751
 
 
752
   // reinitialize buffers
 
753
   capture->FirstCapture = 1;
 
754
 
 
755
   return 1;
 
756
}; /* End _capture_V4L2 */
 
757
 
 
758
/**
 
759
 * some properties can not be changed while the device is in streaming mode.
 
760
 * this method closes and re-opens the device to re-start the stream.
 
761
 * this also causes buffers to be reallocated if the frame size was changed.
 
762
 */
 
763
static bool v4l2_reset( CvCaptureCAM_V4L* capture) {
 
764
    int index = capture->index;
 
765
    icvCloseCAM_V4L(capture);
 
766
    capture->index = index;
 
767
    return _capture_V4L2(capture) == 1;
 
768
}
 
769
 
 
770
bool CvCaptureCAM_V4L::open(int _index)
 
771
{
 
772
   int autoindex = 0;
 
773
 
 
774
   index = -1; // set the capture to closed state
 
775
 
 
776
   if (!numCameras)
 
777
      icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
 
778
   if (!numCameras)
 
779
     return false; /* Are there any /dev/video input sources? */
 
780
 
 
781
   //search index in indexList
 
782
   if ( (_index>-1) && ! ((1 << _index) & indexList) )
 
783
   {
 
784
     fprintf( stderr, "VIDEOIO ERROR: V4L: index %d is not correct!\n",_index);
 
785
     return false; /* Did someone ask for not correct video source number? */
 
786
   }
 
787
 
 
788
   /* Select camera, or rather, V4L video source */
 
789
   if (_index<0) { // Asking for the first device available
 
790
     for (; autoindex<MAX_CAMERAS;autoindex++)
 
791
    if (indexList & (1<<autoindex))
 
792
        break;
 
793
     if (autoindex==MAX_CAMERAS)
 
794
    return false;
 
795
     _index=autoindex;
 
796
     autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
 
797
   }
 
798
 
 
799
   index = _index;
 
800
   FirstCapture = 1;
 
801
   width = DEFAULT_V4L_WIDTH;
 
802
   height = DEFAULT_V4L_HEIGHT;
 
803
   fps = DEFAULT_V4L_FPS;
 
804
   convert_rgb = true;
 
805
 
 
806
   return _capture_V4L2(this) == 1;
 
807
}
 
808
 
 
809
static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
 
810
    v4l2_buffer buf = v4l2_buffer();
 
811
 
 
812
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
813
    buf.memory = V4L2_MEMORY_MMAP;
 
814
 
 
815
    if (-1 == ioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
 
816
        switch (errno) {
 
817
        case EAGAIN:
 
818
            return 0;
 
819
 
 
820
        case EIO:
 
821
        if (!(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)))
 
822
        {
 
823
          if (ioctl(capture->deviceHandle, VIDIOC_QBUF, &buf) == -1)
 
824
          {
 
825
            return 0;
 
826
          }
 
827
        }
 
828
        return 0;
 
829
 
 
830
        default:
 
831
            /* display the error and stop processing */
 
832
            perror ("VIDIOC_DQBUF");
 
833
            return 1;
 
834
        }
 
835
   }
 
836
 
 
837
   assert(buf.index < capture->req.count);
 
838
 
 
839
   memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
 
840
      capture->buffers[buf.index].start,
 
841
      capture->buffers[MAX_V4L_BUFFERS].length );
 
842
   capture->bufferIndex = MAX_V4L_BUFFERS;
 
843
   //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
 
844
   //     buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
 
845
 
 
846
   if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
 
847
       perror ("VIDIOC_QBUF");
 
848
 
 
849
   //set timestamp in capture struct to be timestamp of most recent frame
 
850
   capture->timestamp = buf.timestamp;
 
851
 
 
852
   return 1;
 
853
}
 
854
 
 
855
static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
 
856
    unsigned int count;
 
857
 
 
858
    count = 1;
 
859
 
 
860
    while (count-- > 0) {
 
861
        for (;;) {
 
862
            fd_set fds;
 
863
            struct timeval tv;
 
864
            int r;
 
865
 
 
866
            FD_ZERO (&fds);
 
867
            FD_SET (capture->deviceHandle, &fds);
 
868
 
 
869
            /* Timeout. */
 
870
            tv.tv_sec = 10;
 
871
            tv.tv_usec = 0;
 
872
 
 
873
            r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
 
874
 
 
875
            if (-1 == r) {
 
876
                if (EINTR == errno)
 
877
                    continue;
 
878
 
 
879
                perror ("select");
 
880
            }
 
881
 
 
882
            if (0 == r) {
 
883
                fprintf (stderr, "select timeout\n");
 
884
 
 
885
                /* end the infinite loop */
 
886
                break;
 
887
            }
 
888
 
 
889
            if (read_frame_v4l2 (capture))
 
890
                break;
 
891
        }
 
892
    }
 
893
}
 
894
 
 
895
static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
 
896
   if (capture->FirstCapture) {
 
897
      /* Some general initialization must take place the first time through */
 
898
 
 
899
      /* This is just a technicality, but all buffers must be filled up before any
 
900
         staggered SYNC is applied.  SO, filler up. (see V4L HowTo) */
 
901
 
 
902
      {
 
903
 
 
904
        for (capture->bufferIndex = 0;
 
905
             capture->bufferIndex < ((int)capture->req.count);
 
906
             ++capture->bufferIndex)
 
907
        {
 
908
 
 
909
          v4l2_buffer buf = v4l2_buffer();
 
910
 
 
911
          buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
912
          buf.memory      = V4L2_MEMORY_MMAP;
 
913
          buf.index       = (unsigned long)capture->bufferIndex;
 
914
 
 
915
          if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
 
916
              perror ("VIDIOC_QBUF");
 
917
              return false;
 
918
          }
 
919
        }
 
920
 
 
921
        /* enable the streaming */
 
922
        capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
923
        if (-1 == ioctl (capture->deviceHandle, VIDIOC_STREAMON,
 
924
                          &capture->type)) {
 
925
            /* error enabling the stream */
 
926
            perror ("VIDIOC_STREAMON");
 
927
            return false;
 
928
        }
 
929
      }
 
930
 
 
931
#if defined(V4L_ABORT_BADJPEG)
 
932
        // skip first frame. it is often bad -- this is unnotied in traditional apps,
 
933
        //  but could be fatal if bad jpeg is enabled
 
934
        mainloop_v4l2(capture);
 
935
#endif
 
936
 
 
937
      /* preparation is ok */
 
938
      capture->FirstCapture = 0;
 
939
   }
 
940
 
 
941
   mainloop_v4l2(capture);
 
942
 
 
943
   return true;
 
944
}
 
945
 
 
946
/*
 
947
 * Turn a YUV4:2:0 block into an RGB block
 
948
 *
 
949
 * Video4Linux seems to use the blue, green, red channel
 
950
 * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
 
951
 *
 
952
 * Color space conversion coefficients taken from the excellent
 
953
 * http://www.inforamp.net/~poynton/ColorFAQ.html
 
954
 * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
 
955
 * Y values are given for all 4 pixels, but the U (Pb)
 
956
 * and V (Pr) are assumed constant over the 2x2 block.
 
957
 *
 
958
 * To avoid floating point arithmetic, the color conversion
 
959
 * coefficients are scaled into 16.16 fixed-point integers.
 
960
 * They were determined as follows:
 
961
 *
 
962
 *  double brightness = 1.0;  (0->black; 1->full scale)
 
963
 *  double saturation = 1.0;  (0->greyscale; 1->full color)
 
964
 *  double fixScale = brightness * 256 * 256;
 
965
 *  int rvScale = (int)(1.402 * saturation * fixScale);
 
966
 *  int guScale = (int)(-0.344136 * saturation * fixScale);
 
967
 *  int gvScale = (int)(-0.714136 * saturation * fixScale);
 
968
 *  int buScale = (int)(1.772 * saturation * fixScale);
 
969
 *  int yScale = (int)(fixScale);
 
970
 */
 
971
 
 
972
/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
 
973
#define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
 
974
 
 
975
static inline void
 
976
move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
 
977
               int /*rowPixels*/, unsigned char * rgb)
 
978
{
 
979
    const int rvScale = 91881;
 
980
    const int guScale = -22553;
 
981
    const int gvScale = -46801;
 
982
    const int buScale = 116129;
 
983
    const int yScale  = 65536;
 
984
    int r, g, b;
 
985
 
 
986
    g = guScale * u + gvScale * v;
 
987
//  if (force_rgb) {
 
988
//      r = buScale * u;
 
989
//      b = rvScale * v;
 
990
//  } else {
 
991
        r = rvScale * v;
 
992
        b = buScale * u;
 
993
//  }
 
994
 
 
995
    yTL *= yScale; yTR *= yScale;
 
996
    yBL *= yScale; yBR *= yScale;
 
997
 
 
998
    /* Write out top two first pixels */
 
999
    rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
 
1000
    rgb[2] = LIMIT(r+yTL);
 
1001
 
 
1002
    rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
 
1003
    rgb[5] = LIMIT(r+yTR);
 
1004
 
 
1005
    /* Write out top two last pixels */
 
1006
    rgb += 6;
 
1007
    rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
 
1008
    rgb[2] = LIMIT(r+yBL);
 
1009
 
 
1010
    rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
 
1011
    rgb[5] = LIMIT(r+yBR);
 
1012
}
 
1013
 
 
1014
/* Converts from planar YUV420P to RGB24. */
 
1015
static inline void
 
1016
yuv420p_to_rgb24(int width, int height, uchar* src, uchar* dst)
 
1017
{
 
1018
    cvtColor(Mat(height * 3 / 2, width, CV_8U, src), Mat(height, width, CV_8UC3, dst),
 
1019
             COLOR_YUV2BGR_YV12);
 
1020
}
 
1021
 
 
1022
// Consider a YUV411P image of 8x2 pixels.
 
1023
//
 
1024
// A plane of Y values as before.
 
1025
//
 
1026
// A plane of U values    1       2
 
1027
//                        3       4
 
1028
//
 
1029
// A plane of V values    1       2
 
1030
//                        3       4
 
1031
//
 
1032
// The U1/V1 samples correspond to the ABCD pixels.
 
1033
//     U2/V2 samples correspond to the EFGH pixels.
 
1034
//
 
1035
/* Converts from planar YUV411P to RGB24. */
 
1036
/* [FD] untested... */
 
1037
static void
 
1038
yuv411p_to_rgb24(int width, int height,
 
1039
           unsigned char *pIn0, unsigned char *pOut0)
 
1040
{
 
1041
    const int numpix = width * height;
 
1042
    const int bytes = 24 >> 3;
 
1043
    int i, j, y00, y01, y10, y11, u, v;
 
1044
    unsigned char *pY = pIn0;
 
1045
    unsigned char *pU = pY + numpix;
 
1046
    unsigned char *pV = pU + numpix / 4;
 
1047
    unsigned char *pOut = pOut0;
 
1048
 
 
1049
    for (j = 0; j <= height; j++) {
 
1050
        for (i = 0; i <= width - 4; i += 4) {
 
1051
            y00 = *pY;
 
1052
            y01 = *(pY + 1);
 
1053
            y10 = *(pY + 2);
 
1054
            y11 = *(pY + 3);
 
1055
            u = (*pU++) - 128;
 
1056
            v = (*pV++) - 128;
 
1057
 
 
1058
            move_411_block(y00, y01, y10, y11, u, v,
 
1059
                       width, pOut);
 
1060
 
 
1061
            pY += 4;
 
1062
            pOut += 4 * bytes;
 
1063
 
 
1064
        }
 
1065
    }
 
1066
}
 
1067
 
 
1068
/* convert from 4:2:2 YUYV interlaced to RGB24 */
 
1069
static void
 
1070
yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) {
 
1071
    cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst),
 
1072
             COLOR_YUV2BGR_YUYV);
 
1073
}
 
1074
 
 
1075
static inline void
 
1076
uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
 
1077
{
 
1078
    cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst),
 
1079
             COLOR_YUV2BGR_UYVY);
 
1080
}
 
1081
#ifdef HAVE_JPEG
 
1082
 
 
1083
/* convert from mjpeg to rgb24 */
 
1084
static bool
 
1085
mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* dst) {
 
1086
    Mat temp = cvarrToMat(dst);
 
1087
    imdecode(Mat(1, length, CV_8U, src), IMREAD_COLOR, &temp);
 
1088
    return temp.data && temp.cols == width && temp.rows == height;
 
1089
}
 
1090
 
 
1091
#endif
 
1092
 
 
1093
/*
 
1094
 * BAYER2RGB24 ROUTINE TAKEN FROM:
 
1095
 *
 
1096
 * Sonix SN9C10x based webcam basic I/F routines
 
1097
 * Takafumi Mizuno <taka-qce@ls-a.jp>
 
1098
 *
 
1099
 */
 
1100
static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
 
1101
{
 
1102
    long int i;
 
1103
    unsigned char *rawpt, *scanpt;
 
1104
    long int size;
 
1105
 
 
1106
    rawpt = src;
 
1107
    scanpt = dst;
 
1108
    size = WIDTH*HEIGHT;
 
1109
 
 
1110
    for ( i = 0; i < size; i++ ) {
 
1111
  if ( (i/WIDTH) % 2 == 0 ) {
 
1112
      if ( (i % 2) == 0 ) {
 
1113
    /* B */
 
1114
    if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
 
1115
        *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
 
1116
         *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;  /* R */
 
1117
        *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
 
1118
         *(rawpt+WIDTH)+*(rawpt-WIDTH))/4;      /* G */
 
1119
        *scanpt++ = *rawpt;                                     /* B */
 
1120
    } else {
 
1121
        /* first line or left column */
 
1122
        *scanpt++ = *(rawpt+WIDTH+1);           /* R */
 
1123
        *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2;      /* G */
 
1124
        *scanpt++ = *rawpt;                             /* B */
 
1125
    }
 
1126
      } else {
 
1127
    /* (B)G */
 
1128
    if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
 
1129
        *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;  /* R */
 
1130
        *scanpt++ = *rawpt;                                     /* G */
 
1131
        *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;          /* B */
 
1132
    } else {
 
1133
        /* first line or right column */
 
1134
        *scanpt++ = *(rawpt+WIDTH);     /* R */
 
1135
        *scanpt++ = *rawpt;             /* G */
 
1136
        *scanpt++ = *(rawpt-1); /* B */
 
1137
    }
 
1138
      }
 
1139
  } else {
 
1140
      if ( (i % 2) == 0 ) {
 
1141
    /* G(R) */
 
1142
    if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
 
1143
        *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;          /* R */
 
1144
        *scanpt++ = *rawpt;                                     /* G */
 
1145
        *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2;  /* B */
 
1146
    } else {
 
1147
        /* bottom line or left column */
 
1148
        *scanpt++ = *(rawpt+1);         /* R */
 
1149
        *scanpt++ = *rawpt;                     /* G */
 
1150
        *scanpt++ = *(rawpt-WIDTH);             /* B */
 
1151
    }
 
1152
      } else {
 
1153
    /* R */
 
1154
    if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
 
1155
        *scanpt++ = *rawpt;                                     /* R */
 
1156
        *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
 
1157
         *(rawpt-WIDTH)+*(rawpt+WIDTH))/4;      /* G */
 
1158
        *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
 
1159
         *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;  /* B */
 
1160
    } else {
 
1161
        /* bottom line or right column */
 
1162
        *scanpt++ = *rawpt;                             /* R */
 
1163
        *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2;      /* G */
 
1164
        *scanpt++ = *(rawpt-WIDTH-1);           /* B */
 
1165
    }
 
1166
      }
 
1167
  }
 
1168
  rawpt++;
 
1169
    }
 
1170
 
 
1171
}
 
1172
 
 
1173
// SGBRG to RGB24
 
1174
// for some reason, red and blue needs to be swapped
 
1175
// at least for  046d:092f Logitech, Inc. QuickCam Express Plus to work
 
1176
//see: http://www.siliconimaging.com/RGB%20Bayer.htm
 
1177
//and 4.6 at http://tldp.org/HOWTO/html_single/libdc1394-HOWTO/
 
1178
static void sgbrg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
 
1179
{
 
1180
    long int i;
 
1181
    unsigned char *rawpt, *scanpt;
 
1182
    long int size;
 
1183
 
 
1184
    rawpt = src;
 
1185
    scanpt = dst;
 
1186
    size = WIDTH*HEIGHT;
 
1187
 
 
1188
    for ( i = 0; i < size; i++ )
 
1189
    {
 
1190
        if ( (i/WIDTH) % 2 == 0 ) //even row
 
1191
        {
 
1192
            if ( (i % 2) == 0 ) //even pixel
 
1193
            {
 
1194
                if ( (i > WIDTH) && ((i % WIDTH) > 0) )
 
1195
                {
 
1196
                    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2;       /* R */
 
1197
                    *scanpt++ = *(rawpt);                        /* G */
 
1198
                    *scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2;      /* B */
 
1199
                } else
 
1200
                {
 
1201
                  /* first line or left column */
 
1202
 
 
1203
                  *scanpt++ = *(rawpt+1);           /* R */
 
1204
                  *scanpt++ = *(rawpt);             /* G */
 
1205
                  *scanpt++ =  *(rawpt+WIDTH);      /* B */
 
1206
                }
 
1207
            } else //odd pixel
 
1208
            {
 
1209
                if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
 
1210
                {
 
1211
                    *scanpt++ = *(rawpt);       /* R */
 
1212
                    *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
 
1213
                    *scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) + *(rawpt+WIDTH-1) + *(rawpt+WIDTH+1))/4;      /* B */
 
1214
                } else
 
1215
                {
 
1216
                    /* first line or right column */
 
1217
 
 
1218
                    *scanpt++ = *(rawpt);       /* R */
 
1219
                    *scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
 
1220
                    *scanpt++ = *(rawpt+WIDTH-1);      /* B */
 
1221
                }
 
1222
            }
 
1223
        } else
 
1224
        { //odd row
 
1225
            if ( (i % 2) == 0 ) //even pixel
 
1226
            {
 
1227
                if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
 
1228
                {
 
1229
                    *scanpt++ =  (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4;          /* R */
 
1230
                    *scanpt++ =  (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4;      /* G */
 
1231
                    *scanpt++ =  *(rawpt); /* B */
 
1232
                } else
 
1233
                {
 
1234
                    /* bottom line or left column */
 
1235
 
 
1236
                    *scanpt++ =  *(rawpt-WIDTH+1);          /* R */
 
1237
                    *scanpt++ =  (*(rawpt+1)+*(rawpt-WIDTH))/2;      /* G */
 
1238
                    *scanpt++ =  *(rawpt); /* B */
 
1239
                }
 
1240
            } else
 
1241
            { //odd pixel
 
1242
                if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
 
1243
                {
 
1244
                    *scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2;  /* R */
 
1245
                    *scanpt++ = *(rawpt);      /* G */
 
1246
                    *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
 
1247
                } else
 
1248
                {
 
1249
                    /* bottom line or right column */
 
1250
 
 
1251
                    *scanpt++ = (*(rawpt-WIDTH));  /* R */
 
1252
                    *scanpt++ = *(rawpt);      /* G */
 
1253
                    *scanpt++ = (*(rawpt-1)); /* B */
 
1254
                }
 
1255
            }
 
1256
        }
 
1257
        rawpt++;
 
1258
    }
 
1259
}
 
1260
 
 
1261
static inline void
 
1262
rgb24_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
 
1263
{
 
1264
    cvtColor(Mat(height, width, CV_8UC3, src), Mat(height, width, CV_8UC3, dst), COLOR_RGB2BGR);
 
1265
}
 
1266
 
 
1267
#define CLAMP(x)        ((x)<0?0:((x)>255)?255:(x))
 
1268
 
 
1269
typedef struct {
 
1270
  int is_abs;
 
1271
  int len;
 
1272
  int val;
 
1273
} code_table_t;
 
1274
 
 
1275
 
 
1276
/* local storage */
 
1277
static code_table_t table[256];
 
1278
static int init_done = 0;
 
1279
 
 
1280
 
 
1281
/*
 
1282
  sonix_decompress_init
 
1283
  =====================
 
1284
    pre-calculates a locally stored table for efficient huffman-decoding.
 
1285
 
 
1286
  Each entry at index x in the table represents the codeword
 
1287
  present at the MSB of byte x.
 
1288
 
 
1289
*/
 
1290
static void sonix_decompress_init(void)
 
1291
{
 
1292
  int i;
 
1293
  int is_abs, val, len;
 
1294
 
 
1295
  for (i = 0; i < 256; i++) {
 
1296
    is_abs = 0;
 
1297
    val = 0;
 
1298
    len = 0;
 
1299
    if ((i & 0x80) == 0) {
 
1300
      /* code 0 */
 
1301
      val = 0;
 
1302
      len = 1;
 
1303
    }
 
1304
    else if ((i & 0xE0) == 0x80) {
 
1305
      /* code 100 */
 
1306
      val = +4;
 
1307
      len = 3;
 
1308
    }
 
1309
    else if ((i & 0xE0) == 0xA0) {
 
1310
      /* code 101 */
 
1311
      val = -4;
 
1312
      len = 3;
 
1313
    }
 
1314
    else if ((i & 0xF0) == 0xD0) {
 
1315
      /* code 1101 */
 
1316
      val = +11;
 
1317
      len = 4;
 
1318
    }
 
1319
    else if ((i & 0xF0) == 0xF0) {
 
1320
      /* code 1111 */
 
1321
      val = -11;
 
1322
      len = 4;
 
1323
    }
 
1324
    else if ((i & 0xF8) == 0xC8) {
 
1325
      /* code 11001 */
 
1326
      val = +20;
 
1327
      len = 5;
 
1328
    }
 
1329
    else if ((i & 0xFC) == 0xC0) {
 
1330
      /* code 110000 */
 
1331
      val = -20;
 
1332
      len = 6;
 
1333
    }
 
1334
    else if ((i & 0xFC) == 0xC4) {
 
1335
      /* code 110001xx: unknown */
 
1336
      val = 0;
 
1337
      len = 8;
 
1338
    }
 
1339
    else if ((i & 0xF0) == 0xE0) {
 
1340
      /* code 1110xxxx */
 
1341
      is_abs = 1;
 
1342
      val = (i & 0x0F) << 4;
 
1343
      len = 8;
 
1344
    }
 
1345
    table[i].is_abs = is_abs;
 
1346
    table[i].val = val;
 
1347
    table[i].len = len;
 
1348
  }
 
1349
 
 
1350
  init_done = 1;
 
1351
}
 
1352
 
 
1353
 
 
1354
/*
 
1355
  sonix_decompress
 
1356
  ================
 
1357
    decompresses an image encoded by a SN9C101 camera controller chip.
 
1358
 
 
1359
  IN    width
 
1360
    height
 
1361
    inp         pointer to compressed frame (with header already stripped)
 
1362
  OUT   outp    pointer to decompressed frame
 
1363
 
 
1364
  Returns 0 if the operation was successful.
 
1365
  Returns <0 if operation failed.
 
1366
 
 
1367
*/
 
1368
static int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
 
1369
{
 
1370
  int row, col;
 
1371
  int val;
 
1372
  int bitpos;
 
1373
  unsigned char code;
 
1374
  unsigned char *addr;
 
1375
 
 
1376
  if (!init_done) {
 
1377
    /* do sonix_decompress_init first! */
 
1378
    return -1;
 
1379
  }
 
1380
 
 
1381
  bitpos = 0;
 
1382
  for (row = 0; row < height; row++) {
 
1383
 
 
1384
    col = 0;
 
1385
 
 
1386
 
 
1387
 
 
1388
    /* first two pixels in first two rows are stored as raw 8-bit */
 
1389
    if (row < 2) {
 
1390
      addr = inp + (bitpos >> 3);
 
1391
      code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
 
1392
      bitpos += 8;
 
1393
      *outp++ = code;
 
1394
 
 
1395
      addr = inp + (bitpos >> 3);
 
1396
      code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
 
1397
      bitpos += 8;
 
1398
      *outp++ = code;
 
1399
 
 
1400
      col += 2;
 
1401
    }
 
1402
 
 
1403
    while (col < width) {
 
1404
      /* get bitcode from bitstream */
 
1405
      addr = inp + (bitpos >> 3);
 
1406
      code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
 
1407
 
 
1408
      /* update bit position */
 
1409
      bitpos += table[code].len;
 
1410
 
 
1411
      /* calculate pixel value */
 
1412
      val = table[code].val;
 
1413
      if (!table[code].is_abs) {
 
1414
        /* value is relative to top and left pixel */
 
1415
        if (col < 2) {
 
1416
          /* left column: relative to top pixel */
 
1417
          val += outp[-2*width];
 
1418
        }
 
1419
        else if (row < 2) {
 
1420
          /* top row: relative to left pixel */
 
1421
          val += outp[-2];
 
1422
        }
 
1423
        else {
 
1424
          /* main area: average of left pixel and top pixel */
 
1425
          val += (outp[-2] + outp[-2*width]) / 2;
 
1426
        }
 
1427
      }
 
1428
 
 
1429
      /* store pixel */
 
1430
      *outp++ = CLAMP(val);
 
1431
      col++;
 
1432
    }
 
1433
  }
 
1434
 
 
1435
  return 0;
 
1436
}
 
1437
 
 
1438
static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
 
1439
    /* Now get what has already been captured as a IplImage return */
 
1440
    // we need memory iff convert_rgb is true
 
1441
    bool recreate_frame = capture->frame_allocated != capture->convert_rgb;
 
1442
 
 
1443
    if (!capture->convert_rgb) {
 
1444
        // for mjpeg streams the size might change in between, so we have to change the header
 
1445
        recreate_frame += capture->frame.imageSize != (int)capture->buffers[capture->bufferIndex].length;
 
1446
    }
 
1447
 
 
1448
    if(recreate_frame) {
 
1449
        // printf("realloc %d %zu\n", capture->frame.imageSize, capture->buffers[capture->bufferIndex].length);
 
1450
        if(capture->frame_allocated)
 
1451
            cvFree(&capture->frame.imageData);
 
1452
        v4l2_create_frame(capture);
 
1453
    }
 
1454
 
 
1455
    if(!capture->convert_rgb) {
 
1456
        capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start;
 
1457
        return &capture->frame;
 
1458
    }
 
1459
 
 
1460
    switch (capture->palette)
 
1461
    {
 
1462
    case V4L2_PIX_FMT_BGR24:
 
1463
        memcpy((char *)capture->frame.imageData,
 
1464
               (char *)capture->buffers[capture->bufferIndex].start,
 
1465
               capture->frame.imageSize);
 
1466
        break;
 
1467
 
 
1468
    case V4L2_PIX_FMT_YVU420:
 
1469
        yuv420p_to_rgb24(capture->form.fmt.pix.width,
 
1470
                 capture->form.fmt.pix.height,
 
1471
                 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
 
1472
                 (unsigned char*)capture->frame.imageData);
 
1473
        break;
 
1474
 
 
1475
    case V4L2_PIX_FMT_YUV411P:
 
1476
        yuv411p_to_rgb24(capture->form.fmt.pix.width,
 
1477
                 capture->form.fmt.pix.height,
 
1478
                 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
 
1479
                 (unsigned char*)capture->frame.imageData);
 
1480
        break;
 
1481
#ifdef HAVE_JPEG
 
1482
    case V4L2_PIX_FMT_MJPEG:
 
1483
    case V4L2_PIX_FMT_JPEG:
 
1484
        if (!mjpeg_to_rgb24(capture->form.fmt.pix.width,
 
1485
                    capture->form.fmt.pix.height,
 
1486
                    (unsigned char*)(capture->buffers[capture->bufferIndex]
 
1487
                             .start),
 
1488
                    capture->buffers[capture->bufferIndex].length,
 
1489
                    &capture->frame))
 
1490
          return 0;
 
1491
        break;
 
1492
#endif
 
1493
 
 
1494
    case V4L2_PIX_FMT_YUYV:
 
1495
        yuyv_to_rgb24(capture->form.fmt.pix.width,
 
1496
                  capture->form.fmt.pix.height,
 
1497
                  (unsigned char*)(capture->buffers[capture->bufferIndex].start),
 
1498
                  (unsigned char*)capture->frame.imageData);
 
1499
        break;
 
1500
    case V4L2_PIX_FMT_UYVY:
 
1501
        uyvy_to_rgb24(capture->form.fmt.pix.width,
 
1502
                  capture->form.fmt.pix.height,
 
1503
                  (unsigned char*)(capture->buffers[capture->bufferIndex].start),
 
1504
                  (unsigned char*)capture->frame.imageData);
 
1505
        break;
 
1506
    case V4L2_PIX_FMT_SBGGR8:
 
1507
        bayer2rgb24(capture->form.fmt.pix.width,
 
1508
                capture->form.fmt.pix.height,
 
1509
                (unsigned char*)capture->buffers[capture->bufferIndex].start,
 
1510
                (unsigned char*)capture->frame.imageData);
 
1511
        break;
 
1512
 
 
1513
    case V4L2_PIX_FMT_SN9C10X:
 
1514
        sonix_decompress_init();
 
1515
        sonix_decompress(capture->form.fmt.pix.width,
 
1516
                 capture->form.fmt.pix.height,
 
1517
                 (unsigned char*)capture->buffers[capture->bufferIndex].start,
 
1518
                 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start);
 
1519
 
 
1520
        bayer2rgb24(capture->form.fmt.pix.width,
 
1521
                capture->form.fmt.pix.height,
 
1522
                (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
 
1523
                (unsigned char*)capture->frame.imageData);
 
1524
        break;
 
1525
 
 
1526
    case V4L2_PIX_FMT_SGBRG8:
 
1527
        sgbrg2rgb24(capture->form.fmt.pix.width,
 
1528
                capture->form.fmt.pix.height,
 
1529
                (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
 
1530
                (unsigned char*)capture->frame.imageData);
 
1531
        break;
 
1532
    case V4L2_PIX_FMT_RGB24:
 
1533
        rgb24_to_rgb24(capture->form.fmt.pix.width,
 
1534
                capture->form.fmt.pix.height,
 
1535
                (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
 
1536
                (unsigned char*)capture->frame.imageData);
 
1537
        break;
 
1538
    }
 
1539
 
 
1540
    return(&capture->frame);
 
1541
}
 
1542
 
 
1543
static inline __u32 capPropertyToV4L2(int prop) {
 
1544
    switch (prop) {
 
1545
    case CV_CAP_PROP_BRIGHTNESS:
 
1546
        return V4L2_CID_BRIGHTNESS;
 
1547
    case CV_CAP_PROP_CONTRAST:
 
1548
        return V4L2_CID_CONTRAST;
 
1549
    case CV_CAP_PROP_SATURATION:
 
1550
        return V4L2_CID_SATURATION;
 
1551
    case CV_CAP_PROP_HUE:
 
1552
        return V4L2_CID_HUE;
 
1553
    case CV_CAP_PROP_GAIN:
 
1554
        return V4L2_CID_GAIN;
 
1555
    case CV_CAP_PROP_EXPOSURE:
 
1556
        return V4L2_CID_EXPOSURE;
 
1557
    case CV_CAP_PROP_AUTOFOCUS:
 
1558
        return V4L2_CID_FOCUS_AUTO;
 
1559
    case CV_CAP_PROP_FOCUS:
 
1560
        return V4L2_CID_FOCUS_ABSOLUTE;
 
1561
    default:
 
1562
        return -1;
 
1563
    }
 
1564
}
 
1565
 
 
1566
static double icvGetPropertyCAM_V4L (const CvCaptureCAM_V4L* capture,
 
1567
                                     int property_id ) {
 
1568
  {
 
1569
      v4l2_format form;
 
1570
      form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1571
      if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &form)) {
 
1572
          /* display an error message, and return an error code */
 
1573
          perror ("VIDIOC_G_FMT");
 
1574
          return -1;
 
1575
      }
 
1576
 
 
1577
      switch (property_id) {
 
1578
      case CV_CAP_PROP_FRAME_WIDTH:
 
1579
          return form.fmt.pix.width;
 
1580
      case CV_CAP_PROP_FRAME_HEIGHT:
 
1581
          return form.fmt.pix.height;
 
1582
      case CV_CAP_PROP_FOURCC:
 
1583
      case CV_CAP_PROP_MODE:
 
1584
          return capture->palette;
 
1585
      case CV_CAP_PROP_FORMAT:
 
1586
          return CV_MAKETYPE(CV_8U, capture->frame.nChannels);
 
1587
      case CV_CAP_PROP_CONVERT_RGB:
 
1588
          return capture->convert_rgb;
 
1589
      }
 
1590
 
 
1591
      if(property_id == CV_CAP_PROP_FPS) {
 
1592
          v4l2_streamparm sp = v4l2_streamparm();
 
1593
          sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1594
          if (ioctl(capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){
 
1595
              fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n");
 
1596
              return -1;
 
1597
          }
 
1598
 
 
1599
          return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator;
 
1600
      }
 
1601
 
 
1602
      /* initialize the control structure */
 
1603
 
 
1604
      if(property_id == CV_CAP_PROP_POS_MSEC) {
 
1605
          if (capture->FirstCapture) {
 
1606
            return 0;
 
1607
          } else {
 
1608
            return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
 
1609
          }
 
1610
      }
 
1611
 
 
1612
      __u32 v4l2id = capPropertyToV4L2(property_id);
 
1613
 
 
1614
      if(v4l2id == __u32(-1)) {
 
1615
          fprintf(stderr,
 
1616
                  "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n",
 
1617
                  property_id);
 
1618
          return -1;
 
1619
      }
 
1620
 
 
1621
      v4l2_control control = {v4l2id, 0};
 
1622
 
 
1623
      if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL,
 
1624
                        &control)) {
 
1625
 
 
1626
          fprintf( stderr, "VIDEOIO ERROR: V4L2: ");
 
1627
          switch (property_id) {
 
1628
          case CV_CAP_PROP_BRIGHTNESS:
 
1629
              fprintf (stderr, "Brightness");
 
1630
              break;
 
1631
          case CV_CAP_PROP_CONTRAST:
 
1632
              fprintf (stderr, "Contrast");
 
1633
              break;
 
1634
          case CV_CAP_PROP_SATURATION:
 
1635
              fprintf (stderr, "Saturation");
 
1636
              break;
 
1637
          case CV_CAP_PROP_HUE:
 
1638
              fprintf (stderr, "Hue");
 
1639
              break;
 
1640
          case CV_CAP_PROP_GAIN:
 
1641
              fprintf (stderr, "Gain");
 
1642
              break;
 
1643
          case CV_CAP_PROP_EXPOSURE:
 
1644
              fprintf (stderr, "Exposure");
 
1645
              break;
 
1646
          case CV_CAP_PROP_AUTOFOCUS:
 
1647
              fprintf (stderr, "Autofocus");
 
1648
              break;
 
1649
          case CV_CAP_PROP_FOCUS:
 
1650
              fprintf (stderr, "Focus");
 
1651
              break;
 
1652
          }
 
1653
          fprintf (stderr, " is not supported by your device\n");
 
1654
 
 
1655
          return -1;
 
1656
      }
 
1657
 
 
1658
      /* get the min/max values */
 
1659
      Range range = capture->getRange(property_id);
 
1660
 
 
1661
      /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
 
1662
      return ((double)control.value - range.start) / range.size();
 
1663
 
 
1664
  }
 
1665
};
 
1666
 
 
1667
static bool icvSetControl (CvCaptureCAM_V4L* capture,
 
1668
                          int property_id, double value) {
 
1669
 
 
1670
  /* limitation of the input value */
 
1671
  if (value < 0.0) {
 
1672
    value = 0.0;
 
1673
  } else if (value > 1.0) {
 
1674
    value = 1.0;
 
1675
  }
 
1676
 
 
1677
    /* initialisations */
 
1678
    __u32 v4l2id = capPropertyToV4L2(property_id);
 
1679
 
 
1680
    if(v4l2id == __u32(-1)) {
 
1681
        fprintf(stderr,
 
1682
                "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n",
 
1683
                property_id);
 
1684
        return -1;
 
1685
    }
 
1686
 
 
1687
    /* get the min/max values */
 
1688
    Range range = capture->getRange(property_id);
 
1689
 
 
1690
    /* scale the value we want to set */
 
1691
    value = value * range.size() + range.start;
 
1692
 
 
1693
    /* set which control we want to set */
 
1694
    v4l2_control control = {v4l2id, int(value)};
 
1695
 
 
1696
    /* The driver may clamp the value or return ERANGE, ignored here */
 
1697
    if (-1 == ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &control) && errno != ERANGE) {
 
1698
        perror ("VIDIOC_S_CTRL");
 
1699
        return false;
 
1700
    }
 
1701
 
 
1702
    /* all was OK */
 
1703
    return true;
 
1704
}
 
1705
 
 
1706
static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
 
1707
                                  int property_id, double value ){
 
1708
    static int width = 0, height = 0;
 
1709
    bool retval = false;
 
1710
    bool possible;
 
1711
 
 
1712
    /* two subsequent calls setting WIDTH and HEIGHT will change
 
1713
       the video size */
 
1714
 
 
1715
    switch (property_id) {
 
1716
    case CV_CAP_PROP_FRAME_WIDTH:
 
1717
        width = cvRound(value);
 
1718
        if(width !=0 && height != 0) {
 
1719
            capture->width = width;
 
1720
            capture->height = height;
 
1721
            retval = v4l2_reset(capture);
 
1722
            width = height = 0;
 
1723
        }
 
1724
        break;
 
1725
    case CV_CAP_PROP_FRAME_HEIGHT:
 
1726
        height = cvRound(value);
 
1727
        if(width !=0 && height != 0) {
 
1728
            capture->width = width;
 
1729
            capture->height = height;
 
1730
            retval = v4l2_reset(capture);
 
1731
            width = height = 0;
 
1732
        }
 
1733
        break;
 
1734
    case CV_CAP_PROP_FPS:
 
1735
        capture->fps = value;
 
1736
        retval = v4l2_reset(capture);
 
1737
        break;
 
1738
    case CV_CAP_PROP_CONVERT_RGB:
 
1739
        // returns "0" for formats we do not know how to map to IplImage
 
1740
        possible = v4l2_num_channels(capture->palette);
 
1741
        capture->convert_rgb = bool(value) && possible;
 
1742
        retval = possible || !bool(value);
 
1743
        break;
 
1744
    default:
 
1745
        retval = icvSetControl(capture, property_id, value);
 
1746
        break;
 
1747
    }
 
1748
 
 
1749
    /* return the the status */
 
1750
    return retval;
 
1751
}
 
1752
 
 
1753
static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
 
1754
   /* Deallocate space - Hopefully, no leaks */
 
1755
 
 
1756
   if (capture->index > -1)
 
1757
   {
 
1758
       if (capture->deviceHandle != -1)
 
1759
       {
 
1760
           capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
1761
           if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) {
 
1762
               perror ("Unable to stop the stream");
 
1763
       }
 
1764
 
 
1765
       for (unsigned int n_buffers_ = 0; n_buffers_ < capture->req.count; ++n_buffers_)
 
1766
       {
 
1767
           if (-1 == munmap (capture->buffers[n_buffers_].start, capture->buffers[n_buffers_].length)) {
 
1768
               perror ("munmap");
 
1769
           }
 
1770
       }
 
1771
 
 
1772
       if (capture->buffers[MAX_V4L_BUFFERS].start)
 
1773
       {
 
1774
           free(capture->buffers[MAX_V4L_BUFFERS].start);
 
1775
           capture->buffers[MAX_V4L_BUFFERS].start = 0;
 
1776
       }
 
1777
     }
 
1778
 
 
1779
     if (capture->deviceHandle != -1)
 
1780
       close(capture->deviceHandle);
 
1781
 
 
1782
     if (capture->frame.imageData)
 
1783
         cvFree(&capture->frame.imageData);
 
1784
 
 
1785
     capture->index = -1; // flag that the capture is closed
 
1786
   }
 
1787
};
 
1788
 
 
1789
bool CvCaptureCAM_V4L::grabFrame()
 
1790
{
 
1791
    return icvGrabFrameCAM_V4L( this );
 
1792
}
 
1793
 
 
1794
IplImage* CvCaptureCAM_V4L::retrieveFrame(int)
 
1795
{
 
1796
    return icvRetrieveFrameCAM_V4L( this, 0 );
 
1797
}
 
1798
 
 
1799
double CvCaptureCAM_V4L::getProperty( int propId ) const
 
1800
{
 
1801
    return icvGetPropertyCAM_V4L( this, propId );
 
1802
}
 
1803
 
 
1804
bool CvCaptureCAM_V4L::setProperty( int propId, double value )
 
1805
{
 
1806
    return icvSetPropertyCAM_V4L( this, propId, value );
 
1807
}
 
1808
 
 
1809
} // end namespace cv
 
1810
 
 
1811
CvCapture* cvCreateCameraCapture_V4L( int index )
 
1812
{
 
1813
    cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
 
1814
 
 
1815
    if(capture->open(index))
 
1816
        return capture;
 
1817
 
 
1818
    delete capture;
 
1819
    return NULL;
 
1820
}
 
1821
 
 
1822
#endif