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/opencv/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 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.
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 synchronize 2 Logitech C310 USB webcams to within 16 ms of one another
164 12th patch: March 9, 2018, Taylor Lanclos <tlanclos@live.com>
165 added support for CV_CAP_PROP_BUFFERSIZE
171 /*M///////////////////////////////////////////////////////////////////////////////////////
173 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
175 // By downloading, copying, installing or using the software you agree to this license.
176 // If you do not agree to this license, do not download, install,
177 // copy or use the software.
180 // Intel License Agreement
181 // For Open Source Computer Vision Library
183 // Copyright (C) 2000, Intel Corporation, all rights reserved.
184 // Third party copyrights are property of their respective owners.
186 // Redistribution and use in source and binary forms, with or without modification,
187 // are permitted provided that the following conditions are met:
189 // * Redistribution's of source code must retain the above copyright notice,
190 // this list of conditions and the following disclaimer.
192 // * Redistribution's in binary form must reproduce the above copyright notice,
193 // this list of conditions and the following disclaimer in the documentation
194 // and/or other materials provided with the distribution.
196 // * The name of Intel Corporation may not be used to endorse or promote products
197 // derived from this software without specific prior written permission.
199 // This software is provided by the copyright holders and contributors "as is" and
200 // any express or implied warranties, including, but not limited to, the implied
201 // warranties of merchantability and fitness for a particular purpose are disclaimed.
202 // In no event shall the Intel Corporation or contributors be liable for any direct,
203 // indirect, incidental, special, exemplary, or consequential damages
204 // (including, but not limited to, procurement of substitute goods or services;
205 // loss of use, data, or profits; or business interruption) however caused
206 // and on any theory of liability, whether in contract, strict liability,
207 // or tort (including negligence or otherwise) arising in any way out of
208 // the use of this software, even if advised of the possibility of such damage.
212 #include "precomp.hpp"
214 #if !defined _WIN32 && (defined HAVE_CAMV4L2 || defined HAVE_VIDEOIO)
220 #include <sys/ioctl.h>
221 #include <sys/types.h>
222 #include <sys/mman.h>
227 #include <sys/stat.h>
228 #include <sys/ioctl.h>
231 #include <asm/types.h> /* for videodev2.h */
232 #include <linux/videodev2.h>
236 // NetBSD compatibility layer with V4L2
237 #include <sys/videoio.h>
240 /* Defaults - If your board can do better, set it here. Set for the most common type inputs. */
241 #define DEFAULT_V4L_WIDTH 640
242 #define DEFAULT_V4L_HEIGHT 480
243 #define DEFAULT_V4L_FPS 30
245 #define CHANNEL_NUMBER 1
246 #define MAX_CAMERAS 8
249 // default and maximum number of V4L buffers, not including last, 'special' buffer
250 #define MAX_V4L_BUFFERS 10
251 #define DEFAULT_V4L_BUFFERS 4
253 // if enabled, then bad JPEG warnings become errors and cause NULL returned instead of image
254 #define V4L_ABORT_BADJPEG
256 #define MAX_DEVICE_DRIVER_NAME 80
260 /* Device Capture Objects */
268 struct CvCaptureCAM_V4L CV_FINAL : public CvCapture
280 int width_set, height_set;
284 bool frame_allocated;
288 buffer buffers[MAX_V4L_BUFFERS + 1];
293 v4l2_cropcap cropcap;
294 v4l2_requestbuffers req;
296 v4l2_queryctrl queryctrl;
300 /* V4L2 control variables */
301 Range focus, brightness, contrast, saturation, hue, gain, exposure;
303 bool open(int _index);
304 bool open(const char* deviceName);
306 virtual double getProperty(int) const CV_OVERRIDE;
307 virtual bool setProperty(int, double) CV_OVERRIDE;
308 virtual bool grabFrame() CV_OVERRIDE;
309 virtual IplImage* retrieveFrame(int) CV_OVERRIDE;
311 Range getRange(int property_id) const {
312 switch (property_id) {
313 case CV_CAP_PROP_BRIGHTNESS:
315 case CV_CAP_PROP_CONTRAST:
317 case CV_CAP_PROP_SATURATION:
319 case CV_CAP_PROP_HUE:
321 case CV_CAP_PROP_GAIN:
323 case CV_CAP_PROP_EXPOSURE:
325 case CV_CAP_PROP_FOCUS:
327 case CV_CAP_PROP_AUTOFOCUS:
329 case CV_CAP_PROP_AUTO_EXPOSURE:
332 return Range(0, 255);
336 virtual ~CvCaptureCAM_V4L();
339 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture );
341 static bool icvGrabFrameCAM_V4L( CvCaptureCAM_V4L* capture );
342 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int );
344 static double icvGetPropertyCAM_V4L( const CvCaptureCAM_V4L* capture, int property_id );
345 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture, int property_id, double value );
347 /*********************** Implementations ***************************************/
349 CvCaptureCAM_V4L::~CvCaptureCAM_V4L() {
350 icvCloseCAM_V4L(this);
353 static bool try_palette_v4l2(CvCaptureCAM_V4L* capture)
355 capture->form = v4l2_format();
356 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
357 capture->form.fmt.pix.pixelformat = capture->palette;
358 capture->form.fmt.pix.field = V4L2_FIELD_ANY;
359 capture->form.fmt.pix.width = capture->width;
360 capture->form.fmt.pix.height = capture->height;
362 if (-1 == ioctl (capture->deviceHandle, VIDIOC_S_FMT, &capture->form))
365 return capture->palette == capture->form.fmt.pix.pixelformat;
368 static int try_init_v4l2(CvCaptureCAM_V4L* capture, const char *deviceName)
370 // Test device for V4L2 compatibility
372 // -1 then unable to open device
373 // 0 then detected nothing
374 // 1 then V4L2 device
378 /* Open and test V4L2 device */
379 capture->deviceHandle = open (deviceName, O_RDWR /* required */ | O_NONBLOCK, 0);
380 if (-1 == capture->deviceHandle)
383 fprintf(stderr, "(DEBUG) try_init_v4l2 open \"%s\": %s\n", deviceName, strerror(errno));
385 icvCloseCAM_V4L(capture);
389 capture->cap = v4l2_capability();
390 if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYCAP, &capture->cap))
393 fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_QUERYCAP \"%s\": %s\n", deviceName, strerror(errno));
395 icvCloseCAM_V4L(capture);
399 /* Query channels number */
400 if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_INPUT, &deviceIndex))
403 fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_G_INPUT \"%s\": %s\n", deviceName, strerror(errno));
405 icvCloseCAM_V4L(capture);
409 /* Query information about current input */
410 capture->inp = v4l2_input();
411 capture->inp.index = deviceIndex;
412 if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
415 fprintf(stderr, "(DEBUG) try_init_v4l2 VIDIOC_ENUMINPUT \"%s\": %s\n", deviceName, strerror(errno));
417 icvCloseCAM_V4L(capture);
425 static int autosetup_capture_mode_v4l2(CvCaptureCAM_V4L* capture) {
426 //in case palette is already set and works, no need to setup.
427 if(capture->palette != 0 and try_palette_v4l2(capture)){
430 __u32 try_order[] = {
434 V4L2_PIX_FMT_YUV411P,
439 V4L2_PIX_FMT_SN9C10X,
447 for (size_t i = 0; i < sizeof(try_order) / sizeof(__u32); i++) {
448 capture->palette = try_order[i];
449 if (try_palette_v4l2(capture)) {
455 "VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV\n");
456 icvCloseCAM_V4L(capture);
460 static void v4l2_control_range(CvCaptureCAM_V4L* cap, __u32 id)
462 cap->queryctrl= v4l2_queryctrl();
463 cap->queryctrl.id = id;
465 if(0 != ioctl(cap->deviceHandle, VIDIOC_QUERYCTRL, &cap->queryctrl))
468 perror ("VIDIOC_QUERYCTRL");
472 if (cap->queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
475 Range range(cap->queryctrl.minimum, cap->queryctrl.maximum);
477 switch(cap->queryctrl.id) {
478 case V4L2_CID_BRIGHTNESS:
479 cap->brightness = range;
481 case V4L2_CID_CONTRAST:
482 cap->contrast = range;
484 case V4L2_CID_SATURATION:
485 cap->saturation = range;
493 case V4L2_CID_EXPOSURE_ABSOLUTE:
494 cap->exposure = range;
496 case V4L2_CID_FOCUS_ABSOLUTE:
502 static void v4l2_scan_controls(CvCaptureCAM_V4L* capture)
507 for (ctrl_id = V4L2_CID_BASE; ctrl_id < V4L2_CID_LASTP1; ctrl_id++)
509 v4l2_control_range(capture, ctrl_id);
512 for (ctrl_id = V4L2_CID_PRIVATE_BASE;;ctrl_id++)
514 v4l2_control_range(capture, ctrl_id);
520 v4l2_control_range(capture, V4L2_CID_FOCUS_ABSOLUTE);
523 static int v4l2_set_fps(CvCaptureCAM_V4L* capture) {
524 v4l2_streamparm setfps = v4l2_streamparm();
525 setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
526 setfps.parm.capture.timeperframe.numerator = 1;
527 setfps.parm.capture.timeperframe.denominator = capture->fps;
528 return ioctl (capture->deviceHandle, VIDIOC_S_PARM, &setfps);
531 static int v4l2_num_channels(__u32 palette) {
533 case V4L2_PIX_FMT_YVU420:
534 case V4L2_PIX_FMT_MJPEG:
535 case V4L2_PIX_FMT_JPEG:
536 case V4L2_PIX_FMT_Y16:
538 case V4L2_PIX_FMT_YUYV:
539 case V4L2_PIX_FMT_UYVY:
541 case V4L2_PIX_FMT_BGR24:
542 case V4L2_PIX_FMT_RGB24:
549 static void v4l2_create_frame(CvCaptureCAM_V4L *capture) {
550 CvSize size(capture->form.fmt.pix.width, capture->form.fmt.pix.height);
552 int depth = IPL_DEPTH_8U;
554 if (!capture->convert_rgb) {
555 channels = v4l2_num_channels(capture->palette);
557 switch(capture->palette) {
558 case V4L2_PIX_FMT_MJPEG:
559 case V4L2_PIX_FMT_JPEG:
560 size = CvSize(capture->buffers[capture->bufferIndex].length, 1);
562 case V4L2_PIX_FMT_YVU420:
563 size.height = size.height * 3 / 2; // "1.5" channels
565 case V4L2_PIX_FMT_Y16:
566 if(!capture->convert_rgb){
567 depth = IPL_DEPTH_16U;
573 /* Set up Image data */
574 cvInitImageHeader(&capture->frame, size, depth, channels);
576 /* Allocate space for pixelformat we convert to.
577 * If we do not convert frame is just points to the buffer
579 if(capture->convert_rgb) {
580 capture->frame.imageData = (char*)cvAlloc(capture->frame.imageSize);
583 capture->frame_allocated = capture->convert_rgb;
586 static int _capture_V4L2 (CvCaptureCAM_V4L *capture)
588 const char* deviceName = capture->deviceName.c_str();
589 if (try_init_v4l2(capture, deviceName) != 1) {
590 /* init of the v4l2 device is not OK */
594 /* V4L2 control variables are zero (memset above) */
596 /* Scan V4L2 controls */
597 v4l2_scan_controls(capture);
599 if ((capture->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
601 fprintf( stderr, "VIDEOIO ERROR: V4L2: device %s is unable to capture video memory.\n",deviceName);
602 icvCloseCAM_V4L(capture);
606 /* The following code sets the CHANNEL_NUMBER of the video input. Some video sources
607 have sub "Channel Numbers". For a typical V4L TV capture card, this is usually 1.
608 I myself am using a simple NTSC video input capture card that uses the value of 1.
609 If you are not in North America or have a different video standard, you WILL have to change
610 the following settings and recompile/reinstall. This set of settings is based on
611 the most commonly encountered input video source types (like my bttv card) */
613 if(capture->inp.index > 0) {
614 capture->inp = v4l2_input();
615 capture->inp.index = CHANNEL_NUMBER;
616 /* Set only channel number to CHANNEL_NUMBER */
617 /* V4L2 have a status field from selected video mode */
618 if (-1 == ioctl (capture->deviceHandle, VIDIOC_ENUMINPUT, &capture->inp))
620 fprintf (stderr, "VIDEOIO ERROR: V4L2: Aren't able to set channel number\n");
621 icvCloseCAM_V4L (capture);
626 /* Find Window info */
627 capture->form = v4l2_format();
628 capture->form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
630 if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &capture->form)) {
631 fprintf( stderr, "VIDEOIO ERROR: V4L2: Could not obtain specifics of capture window.\n\n");
632 icvCloseCAM_V4L(capture);
636 if (autosetup_capture_mode_v4l2(capture) == -1)
639 /* try to set framerate */
640 v4l2_set_fps(capture);
644 /* Buggy driver paranoia. */
645 min = capture->form.fmt.pix.width * 2;
647 if (capture->form.fmt.pix.bytesperline < min)
648 capture->form.fmt.pix.bytesperline = min;
650 min = capture->form.fmt.pix.bytesperline * capture->form.fmt.pix.height;
652 if (capture->form.fmt.pix.sizeimage < min)
653 capture->form.fmt.pix.sizeimage = min;
655 capture->req = v4l2_requestbuffers();
657 unsigned int buffer_number = capture->bufferSize;
661 capture->req.count = buffer_number;
662 capture->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
663 capture->req.memory = V4L2_MEMORY_MMAP;
665 if (-1 == ioctl (capture->deviceHandle, VIDIOC_REQBUFS, &capture->req))
669 fprintf (stderr, "%s does not support memory mapping\n", deviceName);
671 perror ("VIDIOC_REQBUFS");
673 /* free capture, and returns an error code */
674 icvCloseCAM_V4L (capture);
678 if (capture->req.count < buffer_number)
680 if (buffer_number == 1)
682 fprintf (stderr, "Insufficient buffer memory on %s\n", deviceName);
684 /* free capture, and returns an error code */
685 icvCloseCAM_V4L (capture);
689 fprintf (stderr, "Insufficient buffer memory on %s -- decreaseing buffers\n", deviceName);
695 for (unsigned int n_buffers = 0; n_buffers < capture->req.count; ++n_buffers)
697 v4l2_buffer buf = v4l2_buffer();
698 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
699 buf.memory = V4L2_MEMORY_MMAP;
700 buf.index = n_buffers;
702 if (-1 == ioctl (capture->deviceHandle, VIDIOC_QUERYBUF, &buf)) {
703 perror ("VIDIOC_QUERYBUF");
705 /* free capture, and returns an error code */
706 icvCloseCAM_V4L (capture);
710 capture->buffers[n_buffers].length = buf.length;
711 capture->buffers[n_buffers].start =
712 mmap (NULL /* start anywhere */,
714 PROT_READ | PROT_WRITE /* required */,
715 MAP_SHARED /* recommended */,
716 capture->deviceHandle, buf.m.offset);
718 if (MAP_FAILED == capture->buffers[n_buffers].start) {
721 /* free capture, and returns an error code */
722 icvCloseCAM_V4L (capture);
726 if (n_buffers == 0) {
727 capture->buffers[MAX_V4L_BUFFERS].start = malloc( buf.length );
728 capture->buffers[MAX_V4L_BUFFERS].length = buf.length;
732 v4l2_create_frame(capture);
734 // reinitialize buffers
735 capture->FirstCapture = 1;
738 }; /* End _capture_V4L2 */
741 * some properties can not be changed while the device is in streaming mode.
742 * this method closes and re-opens the device to re-start the stream.
743 * this also causes buffers to be reallocated if the frame size was changed.
745 static bool v4l2_reset( CvCaptureCAM_V4L* capture) {
746 String deviceName = capture->deviceName;
747 icvCloseCAM_V4L(capture);
748 capture->deviceName = deviceName;
749 return _capture_V4L2(capture) == 1;
752 bool CvCaptureCAM_V4L::open(int _index)
755 /* Select camera, or rather, V4L video source */
756 if (_index < 0) // Asking for the first device available
758 for (int autoindex = 0; autoindex < MAX_CAMERAS; ++autoindex)
760 name = cv::format("/dev/video%d", autoindex);
761 /* Test using an open to see if this new device name really does exists. */
762 int h = ::open(name.c_str(), O_RDONLY);
772 fprintf(stderr, "VIDEOIO ERROR: V4L: can't find camera device\n");
779 name = cv::format("/dev/video%d", _index);
782 /* Print the CameraNumber at the end of the string with a width of one character */
783 bool res = open(name.c_str());
786 fprintf(stderr, "VIDEOIO ERROR: V4L: can't open camera by index %d\n", _index);
791 bool CvCaptureCAM_V4L::open(const char* _deviceName)
794 fprintf(stderr, "(DEBUG) V4L: opening %s\n", _deviceName);
797 width = DEFAULT_V4L_WIDTH;
798 height = DEFAULT_V4L_HEIGHT;
799 width_set = height_set = 0;
800 bufferSize = DEFAULT_V4L_BUFFERS;
801 fps = DEFAULT_V4L_FPS;
803 deviceName = _deviceName;
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 capture->returnFrame = false;
833 perror ("VIDIOC_DQBUF");
838 assert(buf.index < capture->req.count);
840 memcpy(capture->buffers[MAX_V4L_BUFFERS].start,
841 capture->buffers[buf.index].start,
842 capture->buffers[MAX_V4L_BUFFERS].length );
843 capture->bufferIndex = MAX_V4L_BUFFERS;
844 //printf("got data in buff %d, len=%d, flags=0x%X, seq=%d, used=%d)\n",
845 // buf.index, buf.length, buf.flags, buf.sequence, buf.bytesused);
847 //set timestamp in capture struct to be timestamp of most recent frame
848 capture->timestamp = buf.timestamp;
850 if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf))
851 perror ("VIDIOC_QBUF");
856 static int mainloop_v4l2(CvCaptureCAM_V4L* capture) {
861 while (count-- > 0) {
868 FD_SET (capture->deviceHandle, &fds);
874 r = select (capture->deviceHandle+1, &fds, NULL, NULL, &tv);
884 fprintf (stderr, "select timeout\n");
886 /* end the infinite loop */
890 int returnCode = read_frame_v4l2 (capture);
900 static bool icvGrabFrameCAM_V4L(CvCaptureCAM_V4L* capture) {
901 if (capture->FirstCapture) {
902 /* Some general initialization must take place the first time through */
904 /* This is just a technicality, but all buffers must be filled up before any
905 staggered SYNC is applied. SO, filler up. (see V4L HowTo) */
909 for (capture->bufferIndex = 0;
910 capture->bufferIndex < ((int)capture->req.count);
911 ++capture->bufferIndex)
914 v4l2_buffer buf = v4l2_buffer();
916 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
917 buf.memory = V4L2_MEMORY_MMAP;
918 buf.index = (unsigned long)capture->bufferIndex;
920 if (-1 == ioctl (capture->deviceHandle, VIDIOC_QBUF, &buf)) {
921 perror ("VIDIOC_QBUF");
926 /* enable the streaming */
927 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
928 if (-1 == ioctl (capture->deviceHandle, VIDIOC_STREAMON,
930 /* error enabling the stream */
931 perror ("VIDIOC_STREAMON");
936 #if defined(V4L_ABORT_BADJPEG)
937 // skip first frame. it is often bad -- this is unnotied in traditional apps,
938 // but could be fatal if bad jpeg is enabled
939 if(mainloop_v4l2(capture) != 1)
943 /* preparation is ok */
944 capture->FirstCapture = 0;
947 if(mainloop_v4l2(capture) != 1) return false;
953 * Turn a YUV4:2:0 block into an RGB block
955 * Video4Linux seems to use the blue, green, red channel
956 * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
958 * Color space conversion coefficients taken from the excellent
959 * http://www.inforamp.net/~poynton/ColorFAQ.html
960 * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
961 * Y values are given for all 4 pixels, but the U (Pb)
962 * and V (Pr) are assumed constant over the 2x2 block.
964 * To avoid floating point arithmetic, the color conversion
965 * coefficients are scaled into 16.16 fixed-point integers.
966 * They were determined as follows:
968 * double brightness = 1.0; (0->black; 1->full scale)
969 * double saturation = 1.0; (0->greyscale; 1->full color)
970 * double fixScale = brightness * 256 * 256;
971 * int rvScale = (int)(1.402 * saturation * fixScale);
972 * int guScale = (int)(-0.344136 * saturation * fixScale);
973 * int gvScale = (int)(-0.714136 * saturation * fixScale);
974 * int buScale = (int)(1.772 * saturation * fixScale);
975 * int yScale = (int)(fixScale);
978 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
979 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
982 move_411_block(int yTL, int yTR, int yBL, int yBR, int u, int v,
983 int /*rowPixels*/, unsigned char * rgb)
985 const int rvScale = 91881;
986 const int guScale = -22553;
987 const int gvScale = -46801;
988 const int buScale = 116129;
989 const int yScale = 65536;
992 g = guScale * u + gvScale * v;
1001 yTL *= yScale; yTR *= yScale;
1002 yBL *= yScale; yBR *= yScale;
1004 /* Write out top two first pixels */
1005 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
1006 rgb[2] = LIMIT(r+yTL);
1008 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
1009 rgb[5] = LIMIT(r+yTR);
1011 /* Write out top two last pixels */
1013 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
1014 rgb[2] = LIMIT(r+yBL);
1016 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
1017 rgb[5] = LIMIT(r+yBR);
1020 /* Converts from planar YUV420P to RGB24. */
1022 yuv420p_to_rgb24(int width, int height, uchar* src, uchar* dst)
1024 cvtColor(Mat(height * 3 / 2, width, CV_8U, src), Mat(height, width, CV_8UC3, dst),
1025 COLOR_YUV2BGR_YV12);
1028 // Consider a YUV411P image of 8x2 pixels.
1030 // A plane of Y values as before.
1032 // A plane of U values 1 2
1035 // A plane of V values 1 2
1038 // The U1/V1 samples correspond to the ABCD pixels.
1039 // U2/V2 samples correspond to the EFGH pixels.
1041 /* Converts from planar YUV411P to RGB24. */
1042 /* [FD] untested... */
1044 yuv411p_to_rgb24(int width, int height,
1045 unsigned char *pIn0, unsigned char *pOut0)
1047 const int numpix = width * height;
1048 const int bytes = 24 >> 3;
1049 int i, j, y00, y01, y10, y11, u, v;
1050 unsigned char *pY = pIn0;
1051 unsigned char *pU = pY + numpix;
1052 unsigned char *pV = pU + numpix / 4;
1053 unsigned char *pOut = pOut0;
1055 for (j = 0; j <= height; j++) {
1056 for (i = 0; i <= width - 4; i += 4) {
1064 move_411_block(y00, y01, y10, y11, u, v,
1074 /* convert from 4:2:2 YUYV interlaced to RGB24 */
1076 yuyv_to_rgb24(int width, int height, unsigned char* src, unsigned char* dst) {
1077 cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst),
1078 COLOR_YUV2BGR_YUYV);
1082 uyvy_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1084 cvtColor(Mat(height, width, CV_8UC2, src), Mat(height, width, CV_8UC3, dst),
1085 COLOR_YUV2BGR_UYVY);
1089 y16_to_rgb24 (int width, int height, unsigned char* src, unsigned char* dst)
1092 Mat(height, width, CV_16UC1, src).convertTo(gray8, CV_8U, 0.00390625);
1093 cvtColor(gray8,Mat(height, width, CV_8UC3, dst),COLOR_GRAY2BGR);
1098 /* convert from mjpeg to rgb24 */
1100 mjpeg_to_rgb24(int width, int height, unsigned char* src, int length, IplImage* dst) {
1101 Mat temp = cvarrToMat(dst);
1102 imdecode(Mat(1, length, CV_8U, src), IMREAD_COLOR, &temp);
1103 return temp.data && temp.cols == width && temp.rows == height;
1109 * BAYER2RGB24 ROUTINE TAKEN FROM:
1111 * Sonix SN9C10x based webcam basic I/F routines
1112 * Takafumi Mizuno <taka-qce@ls-a.jp>
1115 static void bayer2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1118 unsigned char *rawpt, *scanpt;
1123 size = WIDTH*HEIGHT;
1125 for ( i = 0; i < size; i++ ) {
1126 if ( (i/WIDTH) % 2 == 0 ) {
1127 if ( (i % 2) == 0 ) {
1129 if ( (i > WIDTH) && ((i % WIDTH) > 0) ) {
1130 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1131 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
1132 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1133 *(rawpt+WIDTH)+*(rawpt-WIDTH))/4; /* G */
1134 *scanpt++ = *rawpt; /* B */
1136 /* first line or left column */
1137 *scanpt++ = *(rawpt+WIDTH+1); /* R */
1138 *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; /* G */
1139 *scanpt++ = *rawpt; /* B */
1143 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) {
1144 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* R */
1145 *scanpt++ = *rawpt; /* G */
1146 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1148 /* first line or right column */
1149 *scanpt++ = *(rawpt+WIDTH); /* R */
1150 *scanpt++ = *rawpt; /* G */
1151 *scanpt++ = *(rawpt-1); /* B */
1155 if ( (i % 2) == 0 ) {
1157 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) {
1158 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
1159 *scanpt++ = *rawpt; /* G */
1160 *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; /* B */
1162 /* bottom line or left column */
1163 *scanpt++ = *(rawpt+1); /* R */
1164 *scanpt++ = *rawpt; /* G */
1165 *scanpt++ = *(rawpt-WIDTH); /* B */
1169 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) {
1170 *scanpt++ = *rawpt; /* R */
1171 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+
1172 *(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1173 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+
1174 *(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* B */
1176 /* bottom line or right column */
1177 *scanpt++ = *rawpt; /* R */
1178 *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */
1179 *scanpt++ = *(rawpt-WIDTH-1); /* B */
1189 // for some reason, red and blue needs to be swapped
1190 // at least for 046d:092f Logitech, Inc. QuickCam Express Plus to work
1191 //see: http://www.siliconimaging.com/RGB%20Bayer.htm
1192 //and 4.6 at http://tldp.org/HOWTO/html_single/libdc1394-HOWTO/
1193 static void sgbrg2rgb24(long int WIDTH, long int HEIGHT, unsigned char *src, unsigned char *dst)
1196 unsigned char *rawpt, *scanpt;
1201 size = WIDTH*HEIGHT;
1203 for ( i = 0; i < size; i++ )
1205 if ( (i/WIDTH) % 2 == 0 ) //even row
1207 if ( (i % 2) == 0 ) //even pixel
1209 if ( (i > WIDTH) && ((i % WIDTH) > 0) )
1211 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* R */
1212 *scanpt++ = *(rawpt); /* G */
1213 *scanpt++ = (*(rawpt-WIDTH) + *(rawpt+WIDTH))/2; /* B */
1216 /* first line or left column */
1218 *scanpt++ = *(rawpt+1); /* R */
1219 *scanpt++ = *(rawpt); /* G */
1220 *scanpt++ = *(rawpt+WIDTH); /* B */
1224 if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) )
1226 *scanpt++ = *(rawpt); /* R */
1227 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1228 *scanpt++ = (*(rawpt-WIDTH-1) + *(rawpt-WIDTH+1) + *(rawpt+WIDTH-1) + *(rawpt+WIDTH+1))/4; /* B */
1231 /* first line or right column */
1233 *scanpt++ = *(rawpt); /* R */
1234 *scanpt++ = (*(rawpt-1)+*(rawpt+WIDTH))/2; /* G */
1235 *scanpt++ = *(rawpt+WIDTH-1); /* B */
1240 if ( (i % 2) == 0 ) //even pixel
1242 if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) )
1244 *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; /* R */
1245 *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; /* G */
1246 *scanpt++ = *(rawpt); /* B */
1249 /* bottom line or left column */
1251 *scanpt++ = *(rawpt-WIDTH+1); /* R */
1252 *scanpt++ = (*(rawpt+1)+*(rawpt-WIDTH))/2; /* G */
1253 *scanpt++ = *(rawpt); /* B */
1257 if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) )
1259 *scanpt++ = (*(rawpt-WIDTH)+*(rawpt+WIDTH))/2; /* R */
1260 *scanpt++ = *(rawpt); /* G */
1261 *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; /* B */
1264 /* bottom line or right column */
1266 *scanpt++ = (*(rawpt-WIDTH)); /* R */
1267 *scanpt++ = *(rawpt); /* G */
1268 *scanpt++ = (*(rawpt-1)); /* B */
1277 rgb24_to_rgb24 (int width, int height, unsigned char *src, unsigned char *dst)
1279 cvtColor(Mat(height, width, CV_8UC3, src), Mat(height, width, CV_8UC3, dst), COLOR_RGB2BGR);
1282 #define CLAMP(x) ((x)<0?0:((x)>255)?255:(x))
1292 static code_table_t table[256];
1293 static int init_done = 0;
1297 sonix_decompress_init
1298 =====================
1299 pre-calculates a locally stored table for efficient huffman-decoding.
1301 Each entry at index x in the table represents the codeword
1302 present at the MSB of byte x.
1305 static void sonix_decompress_init(void)
1308 int is_abs, val, len;
1310 for (i = 0; i < 256; i++) {
1314 if ((i & 0x80) == 0) {
1319 else if ((i & 0xE0) == 0x80) {
1324 else if ((i & 0xE0) == 0xA0) {
1329 else if ((i & 0xF0) == 0xD0) {
1334 else if ((i & 0xF0) == 0xF0) {
1339 else if ((i & 0xF8) == 0xC8) {
1344 else if ((i & 0xFC) == 0xC0) {
1349 else if ((i & 0xFC) == 0xC4) {
1350 /* code 110001xx: unknown */
1354 else if ((i & 0xF0) == 0xE0) {
1357 val = (i & 0x0F) << 4;
1360 table[i].is_abs = is_abs;
1372 decompresses an image encoded by a SN9C101 camera controller chip.
1376 inp pointer to compressed frame (with header already stripped)
1377 OUT outp pointer to decompressed frame
1379 Returns 0 if the operation was successful.
1380 Returns <0 if operation failed.
1383 static int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp)
1389 unsigned char *addr;
1392 /* do sonix_decompress_init first! */
1397 for (row = 0; row < height; row++) {
1403 /* first two pixels in first two rows are stored as raw 8-bit */
1405 addr = inp + (bitpos >> 3);
1406 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1410 addr = inp + (bitpos >> 3);
1411 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1418 while (col < width) {
1419 /* get bitcode from bitstream */
1420 addr = inp + (bitpos >> 3);
1421 code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));
1423 /* update bit position */
1424 bitpos += table[code].len;
1426 /* calculate pixel value */
1427 val = table[code].val;
1428 if (!table[code].is_abs) {
1429 /* value is relative to top and left pixel */
1431 /* left column: relative to top pixel */
1432 val += outp[-2*width];
1435 /* top row: relative to left pixel */
1439 /* main area: average of left pixel and top pixel */
1440 val += (outp[-2] + outp[-2*width]) / 2;
1445 *outp++ = CLAMP(val);
1453 static IplImage* icvRetrieveFrameCAM_V4L( CvCaptureCAM_V4L* capture, int) {
1454 /* Now get what has already been captured as a IplImage return */
1455 // we need memory iff convert_rgb is true
1456 bool recreate_frame = capture->frame_allocated != capture->convert_rgb;
1458 if (!capture->convert_rgb) {
1459 // for mjpeg streams the size might change in between, so we have to change the header
1460 recreate_frame += capture->frame.imageSize != (int)capture->buffers[capture->bufferIndex].length;
1463 if(recreate_frame) {
1464 // printf("realloc %d %zu\n", capture->frame.imageSize, capture->buffers[capture->bufferIndex].length);
1465 if(capture->frame_allocated)
1466 cvFree(&capture->frame.imageData);
1467 v4l2_create_frame(capture);
1470 if(!capture->convert_rgb) {
1471 capture->frame.imageData = (char*)capture->buffers[capture->bufferIndex].start;
1472 return &capture->frame;
1475 switch (capture->palette)
1477 case V4L2_PIX_FMT_BGR24:
1478 memcpy((char *)capture->frame.imageData,
1479 (char *)capture->buffers[capture->bufferIndex].start,
1480 capture->frame.imageSize);
1483 case V4L2_PIX_FMT_YVU420:
1484 yuv420p_to_rgb24(capture->form.fmt.pix.width,
1485 capture->form.fmt.pix.height,
1486 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
1487 (unsigned char*)capture->frame.imageData);
1490 case V4L2_PIX_FMT_YUV411P:
1491 yuv411p_to_rgb24(capture->form.fmt.pix.width,
1492 capture->form.fmt.pix.height,
1493 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
1494 (unsigned char*)capture->frame.imageData);
1497 case V4L2_PIX_FMT_MJPEG:
1498 case V4L2_PIX_FMT_JPEG:
1499 if (!mjpeg_to_rgb24(capture->form.fmt.pix.width,
1500 capture->form.fmt.pix.height,
1501 (unsigned char*)(capture->buffers[capture->bufferIndex]
1503 capture->buffers[capture->bufferIndex].length,
1509 case V4L2_PIX_FMT_YUYV:
1510 yuyv_to_rgb24(capture->form.fmt.pix.width,
1511 capture->form.fmt.pix.height,
1512 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
1513 (unsigned char*)capture->frame.imageData);
1515 case V4L2_PIX_FMT_UYVY:
1516 uyvy_to_rgb24(capture->form.fmt.pix.width,
1517 capture->form.fmt.pix.height,
1518 (unsigned char*)(capture->buffers[capture->bufferIndex].start),
1519 (unsigned char*)capture->frame.imageData);
1521 case V4L2_PIX_FMT_SBGGR8:
1522 bayer2rgb24(capture->form.fmt.pix.width,
1523 capture->form.fmt.pix.height,
1524 (unsigned char*)capture->buffers[capture->bufferIndex].start,
1525 (unsigned char*)capture->frame.imageData);
1528 case V4L2_PIX_FMT_SN9C10X:
1529 sonix_decompress_init();
1530 sonix_decompress(capture->form.fmt.pix.width,
1531 capture->form.fmt.pix.height,
1532 (unsigned char*)capture->buffers[capture->bufferIndex].start,
1533 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start);
1535 bayer2rgb24(capture->form.fmt.pix.width,
1536 capture->form.fmt.pix.height,
1537 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
1538 (unsigned char*)capture->frame.imageData);
1541 case V4L2_PIX_FMT_SGBRG8:
1542 sgbrg2rgb24(capture->form.fmt.pix.width,
1543 capture->form.fmt.pix.height,
1544 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
1545 (unsigned char*)capture->frame.imageData);
1547 case V4L2_PIX_FMT_RGB24:
1548 rgb24_to_rgb24(capture->form.fmt.pix.width,
1549 capture->form.fmt.pix.height,
1550 (unsigned char*)capture->buffers[(capture->bufferIndex+1) % capture->req.count].start,
1551 (unsigned char*)capture->frame.imageData);
1553 case V4L2_PIX_FMT_Y16:
1554 if(capture->convert_rgb){
1555 y16_to_rgb24(capture->form.fmt.pix.width,
1556 capture->form.fmt.pix.height,
1557 (unsigned char*)capture->buffers[capture->bufferIndex].start,
1558 (unsigned char*)capture->frame.imageData);
1560 memcpy((char *)capture->frame.imageData,
1561 (char *)capture->buffers[capture->bufferIndex].start,
1562 capture->frame.imageSize);
1567 if (capture->returnFrame)
1568 return(&capture->frame);
1573 static inline __u32 capPropertyToV4L2(int prop) {
1575 case CV_CAP_PROP_BRIGHTNESS:
1576 return V4L2_CID_BRIGHTNESS;
1577 case CV_CAP_PROP_CONTRAST:
1578 return V4L2_CID_CONTRAST;
1579 case CV_CAP_PROP_SATURATION:
1580 return V4L2_CID_SATURATION;
1581 case CV_CAP_PROP_HUE:
1582 return V4L2_CID_HUE;
1583 case CV_CAP_PROP_GAIN:
1584 return V4L2_CID_GAIN;
1585 case CV_CAP_PROP_AUTO_EXPOSURE:
1586 return V4L2_CID_EXPOSURE_AUTO;
1587 case CV_CAP_PROP_EXPOSURE:
1588 return V4L2_CID_EXPOSURE_ABSOLUTE;
1589 case CV_CAP_PROP_AUTOFOCUS:
1590 return V4L2_CID_FOCUS_AUTO;
1591 case CV_CAP_PROP_FOCUS:
1592 return V4L2_CID_FOCUS_ABSOLUTE;
1598 static double icvGetPropertyCAM_V4L (const CvCaptureCAM_V4L* capture,
1602 memset(&form, 0, sizeof(v4l2_format));
1603 form.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1604 if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_FMT, &form)) {
1605 /* display an error message, and return an error code */
1606 perror ("VIDIOC_G_FMT");
1610 switch (property_id) {
1611 case CV_CAP_PROP_FRAME_WIDTH:
1612 return form.fmt.pix.width;
1613 case CV_CAP_PROP_FRAME_HEIGHT:
1614 return form.fmt.pix.height;
1615 case CV_CAP_PROP_FOURCC:
1616 case CV_CAP_PROP_MODE:
1617 return capture->palette;
1618 case CV_CAP_PROP_FORMAT:
1619 return CV_MAKETYPE(IPL2CV_DEPTH(capture->frame.depth), capture->frame.nChannels);
1620 case CV_CAP_PROP_CONVERT_RGB:
1621 return capture->convert_rgb;
1622 case CV_CAP_PROP_BUFFERSIZE:
1623 return capture->bufferSize;
1626 if(property_id == CV_CAP_PROP_FPS) {
1627 v4l2_streamparm sp = v4l2_streamparm();
1628 sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1629 if (ioctl(capture->deviceHandle, VIDIOC_G_PARM, &sp) < 0){
1630 fprintf(stderr, "VIDEOIO ERROR: V4L: Unable to get camera FPS\n");
1634 return sp.parm.capture.timeperframe.denominator / (double)sp.parm.capture.timeperframe.numerator;
1637 /* initialize the control structure */
1639 if(property_id == CV_CAP_PROP_POS_MSEC) {
1640 if (capture->FirstCapture) {
1643 return 1000 * capture->timestamp.tv_sec + ((double) capture->timestamp.tv_usec) / 1000;
1647 __u32 v4l2id = capPropertyToV4L2(property_id);
1649 if(v4l2id == __u32(-1)) {
1651 "VIDEOIO ERROR: V4L2: getting property #%d is not supported\n",
1656 v4l2_control control = {v4l2id, 0};
1658 if (-1 == ioctl (capture->deviceHandle, VIDIOC_G_CTRL,
1661 fprintf( stderr, "VIDEOIO ERROR: V4L2: ");
1662 switch (property_id) {
1663 case CV_CAP_PROP_BRIGHTNESS:
1664 fprintf (stderr, "Brightness");
1666 case CV_CAP_PROP_CONTRAST:
1667 fprintf (stderr, "Contrast");
1669 case CV_CAP_PROP_SATURATION:
1670 fprintf (stderr, "Saturation");
1672 case CV_CAP_PROP_HUE:
1673 fprintf (stderr, "Hue");
1675 case CV_CAP_PROP_GAIN:
1676 fprintf (stderr, "Gain");
1678 case CV_CAP_PROP_AUTO_EXPOSURE:
1679 fprintf (stderr, "Auto Exposure");
1681 case CV_CAP_PROP_EXPOSURE:
1682 fprintf (stderr, "Exposure");
1684 case CV_CAP_PROP_AUTOFOCUS:
1685 fprintf (stderr, "Autofocus");
1687 case CV_CAP_PROP_FOCUS:
1688 fprintf (stderr, "Focus");
1691 fprintf (stderr, " is not supported by your device\n");
1696 /* get the min/max values */
1697 Range range = capture->getRange(property_id);
1699 /* all was OK, so convert to 0.0 - 1.0 range, and return the value */
1700 return ((double)control.value - range.start) / range.size();
1705 static bool icvSetControl (CvCaptureCAM_V4L* capture,
1706 int property_id, double value) {
1708 /* limitation of the input value */
1711 } else if (value > 1.0) {
1715 /* initialisations */
1716 __u32 v4l2id = capPropertyToV4L2(property_id);
1718 if(v4l2id == __u32(-1)) {
1720 "VIDEOIO ERROR: V4L2: setting property #%d is not supported\n",
1725 /* get the min/max values */
1726 Range range = capture->getRange(property_id);
1728 /* scale the value we want to set */
1729 value = value * range.size() + range.start;
1731 /* set which control we want to set */
1732 v4l2_control control = {v4l2id, int(value)};
1734 /* The driver may clamp the value or return ERANGE, ignored here */
1735 if (-1 == ioctl(capture->deviceHandle, VIDIOC_S_CTRL, &control) && errno != ERANGE) {
1736 perror ("VIDIOC_S_CTRL");
1740 if(control.id == V4L2_CID_EXPOSURE_AUTO && control.value == V4L2_EXPOSURE_MANUAL) {
1741 // update the control range for expose after disabling autoexposure
1742 // as it is not read correctly at startup
1743 // TODO check this again as it might be fixed with Linux 4.5
1744 v4l2_control_range(capture, V4L2_CID_EXPOSURE_ABSOLUTE);
1751 static int icvSetPropertyCAM_V4L( CvCaptureCAM_V4L* capture,
1752 int property_id, double value ){
1753 bool retval = false;
1756 /* two subsequent calls setting WIDTH and HEIGHT will change
1759 switch (property_id) {
1760 case CV_CAP_PROP_FRAME_WIDTH:
1762 int& width = capture->width_set;
1763 int& height = capture->height_set;
1764 width = cvRound(value);
1765 retval = width != 0;
1766 if(width !=0 && height != 0) {
1767 capture->width = width;
1768 capture->height = height;
1769 retval = v4l2_reset(capture);
1774 case CV_CAP_PROP_FRAME_HEIGHT:
1776 int& width = capture->width_set;
1777 int& height = capture->height_set;
1778 height = cvRound(value);
1779 retval = height != 0;
1780 if(width !=0 && height != 0) {
1781 capture->width = width;
1782 capture->height = height;
1783 retval = v4l2_reset(capture);
1788 case CV_CAP_PROP_FPS:
1789 capture->fps = value;
1790 retval = v4l2_reset(capture);
1792 case CV_CAP_PROP_CONVERT_RGB:
1793 // returns "0" for formats we do not know how to map to IplImage
1794 possible = v4l2_num_channels(capture->palette);
1795 capture->convert_rgb = bool(value) && possible;
1796 retval = possible || !bool(value);
1798 case CV_CAP_PROP_FOURCC:
1800 __u32 old_palette = capture->palette;
1801 __u32 new_palette = static_cast<__u32>(value);
1802 capture->palette = new_palette;
1803 if (v4l2_reset(capture)) {
1806 capture->palette = old_palette;
1807 v4l2_reset(capture);
1812 case CV_CAP_PROP_BUFFERSIZE:
1813 if ((int)value > MAX_V4L_BUFFERS || (int)value < 1) {
1814 fprintf(stderr, "V4L: Bad buffer size %d, buffer size must be from 1 to %d\n", (int)value, MAX_V4L_BUFFERS);
1817 capture->bufferSize = (int)value;
1818 if (capture->bufferIndex > capture->bufferSize) {
1819 capture->bufferIndex = 0;
1821 retval = v4l2_reset(capture);
1825 retval = icvSetControl(capture, property_id, value);
1829 /* return the the status */
1833 static void icvCloseCAM_V4L( CvCaptureCAM_V4L* capture ){
1834 /* Deallocate space - Hopefully, no leaks */
1836 if (!capture->deviceName.empty())
1838 if (capture->deviceHandle != -1)
1840 capture->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1841 if (-1 == ioctl(capture->deviceHandle, VIDIOC_STREAMOFF, &capture->type)) {
1842 perror ("Unable to stop the stream");
1845 for (unsigned int n_buffers = 0; n_buffers < MAX_V4L_BUFFERS; ++n_buffers)
1847 if (capture->buffers[n_buffers].start) {
1848 if (-1 == munmap (capture->buffers[n_buffers].start, capture->buffers[n_buffers].length)) {
1851 capture->buffers[n_buffers].start = 0;
1856 if (capture->buffers[MAX_V4L_BUFFERS].start)
1858 free(capture->buffers[MAX_V4L_BUFFERS].start);
1859 capture->buffers[MAX_V4L_BUFFERS].start = 0;
1863 if (capture->deviceHandle != -1)
1864 close(capture->deviceHandle);
1866 if (capture->frame_allocated && capture->frame.imageData)
1867 cvFree(&capture->frame.imageData);
1869 capture->deviceName.clear(); // flag that the capture is closed
1873 bool CvCaptureCAM_V4L::grabFrame()
1875 return icvGrabFrameCAM_V4L( this );
1878 IplImage* CvCaptureCAM_V4L::retrieveFrame(int)
1880 return icvRetrieveFrameCAM_V4L( this, 0 );
1883 double CvCaptureCAM_V4L::getProperty( int propId ) const
1885 return icvGetPropertyCAM_V4L( this, propId );
1888 bool CvCaptureCAM_V4L::setProperty( int propId, double value )
1890 return icvSetPropertyCAM_V4L( this, propId, value );
1893 } // end namespace cv
1895 CvCapture* cvCreateCameraCapture_V4L( int index )
1897 cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
1899 if(capture->open(index))
1906 CvCapture* cvCreateCameraCapture_V4L( const char * deviceName )
1908 cv::CvCaptureCAM_V4L* capture = new cv::CvCaptureCAM_V4L();
1910 if(capture->open( deviceName ))