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