1
/* This is the contributed code:
4
Current Location: ../opencv-0.9.6/otherlibs/videoio
6
Original Version: 2003-03-12 Magnus Lundin lundin@mlu.mine.nu
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
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/
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.
29
These drivers should work with other V4L frame capture cards other then my bttv
30
driven frame capture card.
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.
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.
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.
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.
60
Second Patch: August 28, 2004 Sfuncia Fabio fiblan@yahoo.it
61
For Release: OpenCV-Linux Beta4 Opencv-0.9.6
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.
68
Third Patch: December 9, 2004 Frederic Devernay Frederic.Devernay@inria.fr
69
For Release: OpenCV-Linux Beta4 Opencv-0.9.6
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
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
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.
90
Fourth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
91
For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
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
109
Fifth Patch: Sept 7, 2005 Csaba Kertesz sign@freemail.hu
110
For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
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)
118
Sixth Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
119
For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
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)
128
Seventh Patch: Sept 10, 2005 Csaba Kertesz sign@freemail.hu
129
For Release: OpenCV-Linux Beta5 OpenCV-0.9.7
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)
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/
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.
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
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
169
/*M///////////////////////////////////////////////////////////////////////////////////////
171
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
178
// Intel License Agreement
179
// For Open Source Computer Vision Library
181
// Copyright (C) 2000, Intel Corporation, all rights reserved.
182
// Third party copyrights are property of their respective owners.
184
// Redistribution and use in source and binary forms, with or without modification,
185
// are permitted provided that the following conditions are met:
187
// * Redistribution's of source code must retain the above copyright notice,
188
// this list of conditions and the following disclaimer.
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.
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.
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.
210
#include "precomp.hpp"
212
#if !defined WIN32 && (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO)
218
#include <sys/ioctl.h>
219
#include <sys/types.h>
220
#include <sys/mman.h>
225
#include <sys/stat.h>
226
#include <sys/ioctl.h>
229
#include <asm/types.h> /* for videodev2.h */
230
#include <linux/videodev2.h>
234
// NetBSD compability layer with V4L2
235
#include <sys/videoio.h>
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
243
#define CHANNEL_NUMBER 1
244
#define MAX_CAMERAS 8
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
251
// if enabled, then bad JPEG warnings become errors and cause NULL returned instead of image
252
#define V4L_ABORT_BADJPEG
254
#define MAX_DEVICE_DRIVER_NAME 80
258
/* Device Capture Objects */
266
static unsigned int n_buffers = 0;
268
struct CvCaptureCAM_V4L : public CvCapture
282
bool frame_allocated;
285
buffer buffers[MAX_V4L_BUFFERS + 1];
290
v4l2_cropcap cropcap;
291
v4l2_requestbuffers req;
293
v4l2_queryctrl queryctrl;
297
/* V4L2 control variables */
298
Range focus, brightness, contrast, saturation, hue, gain, exposure;
300
bool open(int _index);
302
virtual double getProperty(int) const;
303
virtual bool setProperty(int, double);
304
virtual bool grabFrame();
305
virtual IplImage* retrieveFrame(int);
307
Range getRange(int property_id) const {
308
switch (property_id) {
309
case CV_CAP_PROP_BRIGHTNESS:
311
case CV_CAP_PROP_CONTRAST:
313
case CV_CAP_PROP_SATURATION:
315
case CV_CAP_PROP_HUE:
317
case CV_CAP_PROP_GAIN:
319
case CV_CAP_PROP_EXPOSURE:
321
case CV_CAP_PROP_FOCUS:
323
case CV_CAP_PROP_AUTOFOCUS:
326
return Range(0, 255);
330
virtual ~CvCaptureCAM_V4L();
333
static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
335
static bool icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
336
static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
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 );
341
/*********************** Implementations ***************************************/
343
static int numCameras = 0;
344
static int indexList = 0;
346
CvCaptureCAM_V4L::~CvCaptureCAM_V4L() {
347
icvCloseCAM_V4L(this);
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) */
355
static void icvInitCapture_V4L() {
358
char deviceName[MAX_DEVICE_DRIVER_NAME];
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 */
369
indexList|=(1 << CameraNumber);
372
if (deviceHandle != -1)
374
/* Set up to test the next /dev/video source in line */
378
}; /* End icvInitCapture_V4L */
380
static bool try_palette_v4l2(CvCaptureCAM_V4L* capture)
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;
389
if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
392
return capture->palette == capture->form.fmt.pix.pixelformat;
395
static int try_init_v4l2(CvCaptureCAM_V4L* capture, char *deviceName)
397
// Test device for V4L2 compability
399
// -1 then unable to open device
400
// 0 then detected nothing
401
// 1 then V4L2 device
405
/* Open and test V4L2 device */
406
capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
407
if (-1 == capture->deviceHandle)
410
fprintf(stderr, "(DEBUG) try_init_v4l2 open \"%s\": %s\n", deviceName, strerror(errno));
412
icvCloseCAM_V4L(capture);
416
capture->cap = v4l2_capability();
417
if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
420
fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_QUERYCAP \"%s\": %s\n", deviceName, strerror(errno));
422
icvCloseCAM_V4L(capture);
426
/* Query channels number */
427
if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_INPUT, &deviceIndex))
430
fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_G_INPUT \"%s\": %s\n", deviceName, strerror(errno));
432
icvCloseCAM_V4L(capture);
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))
442
fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_ENUMINPUT \"%s\": %s\n", deviceName, strerror(errno));
444
icvCloseCAM_V4L(capture);
452
static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) {
453
__u32 try_order[] = {
456
V4L2_PIX_FMT_YUV411P,
463
V4L2_PIX_FMT_SN9C10X,
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)) {
477
"VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
478
icvCloseCAM_V4L(capture);
482
static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id)
484
cap->queryctrl= v4l2_queryctrl();
485
cap->queryctrl.id = id;
487
if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl))
490
perror ("VIDIOC_QUERYCTRL");
494
if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
497
Range range(cap->queryctrl.minimum, cap->queryctrl.maximum);
499
switch(cap->queryctrl.id) {
500
case V4L2_CID_BRIGHTNESS:
501
cap->brightness = range;
503
case V4L2_CID_CONTRAST:
504
cap->contrast = range;
506
case V4L2_CID_SATURATION:
507
cap->saturation = range;
515
case V4L2_CID_EXPOSURE:
516
cap->exposure = range;
518
case V4L2_CID_FOCUS_ABSOLUTE:
524
static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
529
for (ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++)
531
v4l2_control_range(capture, ctrl_id);
534
for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
536
v4l2_control_range(capture, ctrl_id);
542
v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE);
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);
553
static int v4l2_num_channels(__u32 palette) {
555
case V4L2_PIX_FMT_YVU420:
556
case V4L2_PIX_FMT_MJPEG:
557
case V4L2_PIX_FMT_JPEG:
559
case V4L2_PIX_FMT_YUYV:
560
case V4L2_PIX_FMT_UYVY:
562
case V4L2_PIX_FMT_BGR24:
563
case V4L2_PIX_FMT_RGB24:
570
static void v4l2_create_frame(CvCaptureCAM_V4L *capture) {
571
CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height);
574
if (!capture->convert_rgb) {
575
channels = v4l2_num_channels(capture->palette);
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);
582
case V4L2_PIX_FMT_YVU420:
583
size.height = size.height * 3 / 2; // "1.5" channels
588
/* Set up Image data */
589
cvInitImageHeader(&capture->frame, size, IPL_DEPTH_8U, channels);
591
/* Allocate space for pixelformat we convert to.
592
* If we do not convert frame is just points to the buffer
594
if(capture->convert_rgb) {
595
capture->frame.imageData = (char*)cvAlloc(capture->frame.imageSize);
598
capture->frame_allocated = capture->convert_rgb;
601
static int _capture_V4L2 (CvCaptureCAM_V4L *capture)
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);
607
if (try_init_v4l2(capture, deviceName) != 1) {
608
/* init of the v4l2 device is not OK */
612
/* V4L2 control variables are zero (memset above) */
614
/* Scan V4L2 controls */
615
v4l2_scan_controls(capture);
617
if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
619
fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
620
icvCloseCAM_V4L(capture);
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) */
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))
638
fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
639
icvCloseCAM_V4L (capture);
644
/* Find Window info */
645
capture->form = v4l2_format();
646
capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
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);
654
if (autosetup_capture_mode_v4l2(capture) == -1)
657
/* try to set framerate */
658
v4l2_set_fps(capture);
662
/* Buggy driver paranoia. */
663
min = capture->form.fmt.pix.width * 2;
665
if (capture->form.fmt.pix.bytesperline < min)
666
capture->form.fmt.pix.bytesperline = min;
668
min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
670
if (capture->form.fmt.pix.sizeimage < min)
671
capture->form.fmt.pix.sizeimage = min;
673
capture->req = v4l2_requestbuffers();
675
unsigned int buffer_number = DEFAULT_V4L_BUFFERS;
679
capture->req.count = buffer_number;
680
capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
681
capture->req.memory = V4L2_MEMORY_MMAP;
683
if (-1 == ioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
687
fprintf (stderr, "%s does not support memory mapping\n", deviceName);
689
perror ("VIDIOC_REQBUFS");
691
/* free capture, and returns an error code */
692
icvCloseCAM_V4L (capture);
696
if (capture->req.count < buffer_number)
698
if (buffer_number == 1)
700
fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
702
/* free capture, and returns an error code */
703
icvCloseCAM_V4L (capture);
707
fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
713
for (n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
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;
720
if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
721
perror ("VIDIOC_QUERYBUF");
723
/* free capture, and returns an error code */
724
icvCloseCAM_V4L (capture);
728
capture->buffers[n_buffers].length = buf.length;
729
capture->buffers[n_buffers].start =
730
mmap (NULL /* start anywhere */,
732
PROT_READ | PROT_WRITE /* required */,
733
MAP_SHARED /* recommended */,
734
capture->deviceHandle, buf.m.offset);
736
if (MAP_FAILED == capture->buffers[n_buffers].start) {
739
/* free capture, and returns an error code */
740
icvCloseCAM_V4L (capture);
744
if (n_buffers == 0) {
745
capture->buffers[MAX_V4L_BUFFERS].start = malloc( buf.length );
746
capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
750
v4l2_create_frame(capture);
752
// reinitialize buffers
753
capture->FirstCapture = 1;
756
}; /* End _capture_V4L2 */
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.
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;
770
bool CvCaptureCAM_V4L::open(int _index)
774
index = -1; // set the capture to closed state
777
icvInitCapture_V4L(); /* Havent called icvInitCapture yet - do it now! */
779
return false; /* Are there any /dev/video input sources? */
781
//search index in indexList
782
if ( (_index>-1) && ! ((1 << _index) & indexList) )
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? */
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))
793
if (autoindex==MAX_CAMERAS)
796
autoindex++;// i can recall icvOpenCAM_V4l with index=-1 for next camera
801
width = DEFAULT_V4L_WIDTH;
802
height = DEFAULT_V4L_HEIGHT;
803
fps = DEFAULT_V4L_FPS;
806
return _capture_V4L2(this) == 1;
809
static int read_frame_v4l2(CvCaptureCAM_V4L* capture) {
810
v4l2_buffer buf = v4l2_buffer();
812
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
813
buf.memory = V4L2_MEMORY_MMAP;
815
if (-1 == ioctl (capture->deviceHandle, VIDIOC_DQBUF, &buf)) {
821
if (!(buf.flags & (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)))
823
if (ioctl(capture->deviceHandle, VIDIOC_QBUF, &buf) == -1)
831
/* display the error and stop processing */
832
perror ("VIDIOC_DQBUF");
837
assert(buf.index < capture->req.count);
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);
846
if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
847
perror ("VIDIOC_QBUF");
849
//set timestamp in capture struct to be timestamp of most recent frame
850
capture->timestamp = buf.timestamp;
855
static void mainloop_v4l2(CvCaptureCAM_V4L* capture) {
860
while (count-- > 0) {
867
FD_SET (capture->deviceHandle, &fds);
873
r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
883
fprintf (stderr, "select timeout\n");
885
/* end the infinite loop */
889
if (read_frame_v4l2 (capture))
895
static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
896
if (capture->FirstCapture) {
897
/* Some general initialization must take place the first time through */
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) */
904
for (capture->bufferIndex = 0;
905
capture->bufferIndex < ((int)capture->req.count);
906
++capture->bufferIndex)
909
v4l2_buffer buf = v4l2_buffer();
911
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
912
buf.memory = V4L2_MEMORY_MMAP;
913
buf.index = (unsigned long)capture->bufferIndex;
915
if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
916
perror ("VIDIOC_QBUF");
921
/* enable the streaming */
922
capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
923
if (-1 == ioctl (capture->deviceHandle, VIDIOC_STREAMON,
925
/* error enabling the stream */
926
perror ("VIDIOC_STREAMON");
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);
937
/* preparation is ok */
938
capture->FirstCapture = 0;
941
mainloop_v4l2(capture);
947
* Turn a YUV4:2:0 block into an RGB block
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.
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.
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:
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);
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)))
976
move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
977
int /*rowPixels*/, unsigned char * rgb)
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;
986
g = guScale * u + gvScale * v;
995
yTL *= yScale; yTR *= yScale;
996
yBL *= yScale; yBR *= yScale;
998
/* Write out top two first pixels */
999
rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1000
rgb[2] = LIMIT(r+yTL);
1002
rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1003
rgb[5] = LIMIT(r+yTR);
1005
/* Write out top two last pixels */
1007
rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1008
rgb[2] = LIMIT(r+yBL);
1010
rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1011
rgb[5] = LIMIT(r+yBR);
1014
/* Converts from planar YUV420P to RGB24. */
1016
yuv420p_to_rgb24(int width, int height, uchar* src, uchar* dst)
1018
cvtColor(Mat(height * 3 / 2, width, CV_8U, src), Mat(height, width, CV_8UC3, dst),
1019
COLOR_YUV2BGR_YV12);
1022
// Consider a YUV411P image of 8x2 pixels.
1024
// A plane of Y values as before.
1026
// A plane of U values 1 2
1029
// A plane of V values 1 2
1032
// The U1/V1 samples correspond to the ABCD pixels.
1033
// U2/V2 samples correspond to the EFGH pixels.
1035
/* Converts from planar YUV411P to RGB24. */
1036
/* [FD] untested... */
1038
yuv411p_to_rgb24(int width, int height,
1039
unsigned char *pIn0, unsigned char *pOut0)
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;
1049
for (j = 0; j <= height; j++) {
1050
for (i = 0; i <= width - 4; i += 4) {
1058
move_411_block(y00, y01, y10, y11, u, v,
1068
/* convert from 4:2:2 YUYV interlaced to RGB24 */
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);
1076
uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1078
cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst),
1079
COLOR_YUV2BGR_UYVY);
1083
/* convert from mjpeg to rgb24 */
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;
1094
* BAYER2RGB24 ROUTINE TAKEN FROM:
1096
* Sonix SN9C10x based webcam basic I/F routines
1097
* Takafumi Mizuno <taka-qce@ls-a.jp>
1100
static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1103
unsigned char *rawpt, *scanpt;
1108
size = WIDTH*HEIGHT;
1110
for ( i = 0; i < size; i++ ) {
1111
if ( (i/WIDTH) % 2 == 0 ) {
1112
if ( (i % 2) == 0 ) {
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 */
1121
/* first line or left column */
1122
*scanpt++ = *(rawpt+WIDTH+1); /* R */
1123
*scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
1124
*scanpt++ = *rawpt; /* B */
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 */
1133
/* first line or right column */
1134
*scanpt++ = *(rawpt+WIDTH); /* R */
1135
*scanpt++ = *rawpt; /* G */
1136
*scanpt++ = *(rawpt-1); /* B */
1140
if ( (i % 2) == 0 ) {
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 */
1147
/* bottom line or left column */
1148
*scanpt++ = *(rawpt+1); /* R */
1149
*scanpt++ = *rawpt; /* G */
1150
*scanpt++ = *(rawpt-WIDTH); /* B */
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 */
1161
/* bottom line or right column */
1162
*scanpt++ = *rawpt; /* R */
1163
*scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
1164
*scanpt++ = *(rawpt-WIDTH-1); /* B */
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)
1181
unsigned char *rawpt, *scanpt;
1186
size = WIDTH*HEIGHT;
1188
for ( i = 0; i < size; i++ )
1190
if ( (i/WIDTH) % 2 == 0 ) //even row
1192
if ( (i % 2) == 0 ) //even pixel
1194
if ( (i > WIDTH) && ((i % WIDTH) > 0) )
1196
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
1197
*scanpt++ = *(rawpt); /* G */
1198
*scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2; /* B */
1201
/* first line or left column */
1203
*scanpt++ = *(rawpt+1); /* R */
1204
*scanpt++ = *(rawpt); /* G */
1205
*scanpt++ = *(rawpt+WIDTH); /* B */
1209
if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
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 */
1216
/* first line or right column */
1218
*scanpt++ = *(rawpt); /* R */
1219
*scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
1220
*scanpt++ = *(rawpt+WIDTH-1); /* B */
1225
if ( (i % 2) == 0 ) //even pixel
1227
if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
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 */
1234
/* bottom line or left column */
1236
*scanpt++ = *(rawpt-WIDTH+1); /* R */
1237
*scanpt++ = (*(rawpt+1)+*(rawpt-WIDTH))/2; /* G */
1238
*scanpt++ = *(rawpt); /* B */
1242
if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
1244
*scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2; /* R */
1245
*scanpt++ = *(rawpt); /* G */
1246
*scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1249
/* bottom line or right column */
1251
*scanpt++ = (*(rawpt-WIDTH)); /* R */
1252
*scanpt++ = *(rawpt); /* G */
1253
*scanpt++ = (*(rawpt-1)); /* B */
1262
rgb24_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1264
cvtColor(Mat(height, width, CV_8UC3, src), Mat(height, width, CV_8UC3, dst), COLOR_RGB2BGR);
1267
#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
1277
static code_table_t table[256];
1278
static int init_done = 0;
1282
sonix_decompress_init
1283
=====================
1284
pre-calculates a locally stored table for efficient huffman-decoding.
1286
Each entry at index x in the table represents the codeword
1287
present at the MSB of byte x.
1290
static void sonix_decompress_init(void)
1293
int is_abs, val, len;
1295
for (i = 0; i < 256; i++) {
1299
if ((i & 0x80) == 0) {
1304
else if ((i & 0xE0) == 0x80) {
1309
else if ((i & 0xE0) == 0xA0) {
1314
else if ((i & 0xF0) == 0xD0) {
1319
else if ((i & 0xF0) == 0xF0) {
1324
else if ((i & 0xF8) == 0xC8) {
1329
else if ((i & 0xFC) == 0xC0) {
1334
else if ((i & 0xFC) == 0xC4) {
1335
/* code 110001xx: unknown */
1339
else if ((i & 0xF0) == 0xE0) {
1342
val = (i & 0x0F) << 4;
1345
table[i].is_abs = is_abs;
1357
decompresses an image encoded by a SN9C101 camera controller chip.
1361
inp pointer to compressed frame (with header already stripped)
1362
OUT outp pointer to decompressed frame
1364
Returns 0 if the operation was successful.
1365
Returns <0 if operation failed.
1368
static int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
1374
unsigned char *addr;
1377
/* do sonix_decompress_init first! */
1382
for (row = 0; row < height; row++) {
1388
/* first two pixels in first two rows are stored as raw 8-bit */
1390
addr = inp + (bitpos >> 3);
1391
code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1395
addr = inp + (bitpos >> 3);
1396
code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
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)));
1408
/* update bit position */
1409
bitpos += table[code].len;
1411
/* calculate pixel value */
1412
val = table[code].val;
1413
if (!table[code].is_abs) {
1414
/* value is relative to top and left pixel */
1416
/* left column: relative to top pixel */
1417
val += outp[-2*width];
1420
/* top row: relative to left pixel */
1424
/* main area: average of left pixel and top pixel */
1425
val += (outp[-2] + outp[-2*width]) / 2;
1430
*outp++ = CLAMP(val);
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;
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;
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);
1455
if(!capture->convert_rgb) {
1456
capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start;
1457
return &capture->frame;
1460
switch (capture->palette)
1462
case V4L2_PIX_FMT_BGR24:
1463
memcpy((char *)capture->frame.imageData,
1464
(char *)capture->buffers[capture->bufferIndex].start,
1465
capture->frame.imageSize);
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);
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);
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]
1488
capture->buffers[capture->bufferIndex].length,
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);
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);
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);
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);
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);
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);
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);
1540
return(&capture->frame);
1543
static inline __u32 capPropertyToV4L2(int 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;
1566
static double icvGetPropertyCAM_V4L (const CvCaptureCAM_V4L* capture,
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");
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;
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");
1599
return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator;
1602
/* initialize the control structure */
1604
if(property_id == CV_CAP_PROP_POS_MSEC) {
1605
if (capture->FirstCapture) {
1608
return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
1612
__u32 v4l2id = capPropertyToV4L2(property_id);
1614
if(v4l2id == __u32(-1)) {
1616
"VIDEOIO ERROR: V4L2: getting property #%d is not supported\n",
1621
v4l2_control control = {v4l2id, 0};
1623
if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL,
1626
fprintf( stderr, "VIDEOIO ERROR: V4L2: ");
1627
switch (property_id) {
1628
case CV_CAP_PROP_BRIGHTNESS:
1629
fprintf (stderr, "Brightness");
1631
case CV_CAP_PROP_CONTRAST:
1632
fprintf (stderr, "Contrast");
1634
case CV_CAP_PROP_SATURATION:
1635
fprintf (stderr, "Saturation");
1637
case CV_CAP_PROP_HUE:
1638
fprintf (stderr, "Hue");
1640
case CV_CAP_PROP_GAIN:
1641
fprintf (stderr, "Gain");
1643
case CV_CAP_PROP_EXPOSURE:
1644
fprintf (stderr, "Exposure");
1646
case CV_CAP_PROP_AUTOFOCUS:
1647
fprintf (stderr, "Autofocus");
1649
case CV_CAP_PROP_FOCUS:
1650
fprintf (stderr, "Focus");
1653
fprintf (stderr, " is not supported by your device\n");
1658
/* get the min/max values */
1659
Range range = capture->getRange(property_id);
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();
1667
static bool icvSetControl (CvCaptureCAM_V4L* capture,
1668
int property_id, double value) {
1670
/* limitation of the input value */
1673
} else if (value > 1.0) {
1677
/* initialisations */
1678
__u32 v4l2id = capPropertyToV4L2(property_id);
1680
if(v4l2id == __u32(-1)) {
1682
"VIDEOIO ERROR: V4L2: setting property #%d is not supported\n",
1687
/* get the min/max values */
1688
Range range = capture->getRange(property_id);
1690
/* scale the value we want to set */
1691
value = value * range.size() + range.start;
1693
/* set which control we want to set */
1694
v4l2_control control = {v4l2id, int(value)};
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");
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;
1712
/* two subsequent calls setting WIDTH and HEIGHT will change
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);
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);
1734
case CV_CAP_PROP_FPS:
1735
capture->fps = value;
1736
retval = v4l2_reset(capture);
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);
1745
retval = icvSetControl(capture, property_id, value);
1749
/* return the the status */
1753
static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
1754
/* Deallocate space - Hopefully, no leaks */
1756
if (capture->index > -1)
1758
if (capture->deviceHandle != -1)
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");
1765
for (unsigned int n_buffers_ = 0; n_buffers_ < capture->req.count; ++n_buffers_)
1767
if (-1 == munmap (capture->buffers[n_buffers_].start, capture->buffers[n_buffers_].length)) {
1772
if (capture->buffers[MAX_V4L_BUFFERS].start)
1774
free(capture->buffers[MAX_V4L_BUFFERS].start);
1775
capture->buffers[MAX_V4L_BUFFERS].start = 0;
1779
if (capture->deviceHandle != -1)
1780
close(capture->deviceHandle);
1782
if (capture->frame.imageData)
1783
cvFree(&capture->frame.imageData);
1785
capture->index = -1; // flag that the capture is closed
1789
bool CvCaptureCAM_V4L::grabFrame()
1791
return icvGrabFrameCAM_V4L( this );
1794
IplImage* CvCaptureCAM_V4L::retrieveFrame(int)
1796
return icvRetrieveFrameCAM_V4L( this, 0 );
1799
double CvCaptureCAM_V4L::getProperty( int propId ) const
1801
return icvGetPropertyCAM_V4L( this, propId );
1804
bool CvCaptureCAM_V4L::setProperty( int propId, double value )
1806
return icvSetPropertyCAM_V4L( this, propId, value );
1809
} // end namespace cv
1811
CvCapture* cvCreateCameraCapture_V4L( int index )
1813
cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
1815
if(capture->open(index))