2 /***************************************************************************
3 * v4l2.cpp - Video4Linux 2 camera access
5 * Created: Sat Jul 5 20:40:20 2008
6 * Copyright 2008 Tobias Kellner
8 ****************************************************************************/
10 /* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24 #include <cams/v4l2.h>
26 #include <core/exception.h>
27 #include <core/exceptions/software.h>
28 #include <utils/logging/liblogger.h>
29 #include <fvutils/system/camargp.h>
32 #include <sys/ioctl.h>
38 #include <linux/version.h>
43 using fawkes::Exception;
44 using fawkes::MissingParameterException;
45 using fawkes::NotImplementedException;
46 using fawkes::LibLogger;
52 v4l2_capability caps; //< Device capabilites
58 /** @class V4L2Camera <cams/v4l2.h>
59 * Video4Linux 2 camera access implementation.
62 * @todo Standards queries (VIDIOC_ENUMSTD)
63 * @todo v4l2_pix_format.field
64 * @author Tobias Kellner
69 * @param device_name device file name (e.g. /dev/video0)
71 V4L2Camera::V4L2Camera(const char *device_name)
73 _opened = _started = false;
74 _nao_hacks = _switch_u_v = false;
75 _width = _height = _bytes_per_line = _fps = _buffers_length = 0;
77 _brightness.set = _contrast.set = _saturation.set = _hue.set =
78 _red_balance.set = _blue_balance.set = _exposure.set = _gain.set =
79 _lens_x.set = _lens_y.set = false;
80 _aec = _awb = _agc = _h_flip = _v_flip = NOT_SET;
82 memset(_format, 0, 5);
83 _frame_buffers = NULL;
85 _device_name = strdup(device_name);
86 _data = new V4L2CameraData();
91 * Initialize camera with parameters from camera argument parser.
92 * Supported arguments:
94 * - device=DEV, device file, for example /dev/video0 (required)
96 * - read_method=METHOD, preferred read method
98 * MMAP: memory mapping
100 * - format=FOURCC, preferred format
101 * - size=WIDTHxHEIGHT, preferred image size
102 * - switch_u_v=true/false, switch U and V channels
103 * - fps=FPS, frames per second
104 * - aec=true/false, Auto Exposition enabled [warning: only valid on nao]
105 * - awb=true/false, Auto White Balance enabled
106 * - agc=true/false, Auto Gain enabled
107 * - h_flip=true/false, Horizontal mirror
108 * - v_flip=true/false, Vertical mirror
109 * - brightness=BRIGHT, Brightness [0-255] (def. 128)
110 * - contrast=CONTR, Contrast [0-127] (def. 64)
111 * - saturation=SAT, Saturation [0-256] (def. 128)
112 * - hue=HUE, Hue [-180-180] (def. 0)
113 * - red_balance=RB, Red Balance [0-255] (def. 128)
114 * - blue_balance=BB, Blue Balance [0-255] (def. 128)
115 * - exposure=EXP, Exposure [0-65535] (def. 60)
116 * - gain=GAIN, Gain [0-255] (def. 0)
117 * - lens_x=CORR, Lens Correction X [0-255] (def. 0)
118 * - lens_y=CORR, Lens Correction Y [0-255] (def. 0)
119 * @param cap camera argument parser
121 V4L2Camera::V4L2Camera(const CameraArgumentParser *cap)
123 _opened = _started = false;
125 _width = _height = _bytes_per_line = _buffers_length = 0;
126 _current_buffer = -1;
127 _frame_buffers = NULL;
128 _capture_time = NULL;
129 _data = new V4L2CameraData();
131 if (cap->has("device")) _device_name = strdup(cap->get("device").c_str());
132 else throw MissingParameterException("V4L2Cam: Missing device");
135 if (cap->has("read_method"))
137 string rm = cap->get("read_method");
138 if (rm.compare("READ") == 0) _read_method = READ;
139 else if (rm.compare("MMAP") == 0) _read_method = MMAP;
140 else if (rm.compare("UPTR") == 0) _read_method = UPTR;
141 else throw Exception("V4L2Cam: Invalid read method");
149 if (cap->has("format"))
151 string fmt = cap->get("format");
152 if (fmt.length() != 4) throw Exception("V4L2Cam: Invalid format fourcc");
153 strncpy(_format, fmt.c_str(), 4);
158 memset(_format, 0, 5);
162 if (cap->has("size"))
164 string size = cap->get("size");
165 string::size_type pos;
166 if ((pos = size.find('x')) == string::npos) throw Exception("V4L2Cam: invalid image size string");
167 if ((pos == (size.length() - 1))) throw Exception("V4L2Cam: invalid image size string");
169 unsigned int mult = 1;
170 for (string::size_type i = pos - 1; i != string::npos; --i)
172 _width += (size.at(i) - '0') * mult;
177 for (string::size_type i = size.length() - 1; i > pos; --i)
179 _height += (size.at(i) - '0') * mult;
185 if (cap->has("switch_u_v"))
187 _switch_u_v = (cap->get("switch_u_v").compare("true") == 0);
197 if ((_fps = atoi(cap->get("fps").c_str())) == 0) throw Exception("V4L2Cam: invalid fps string");
207 _aec = (cap->get("aec").compare("true") == 0 ? TRUE : FALSE);
217 _awb = (cap->get("awb").compare("true") == 0 ? TRUE : FALSE);
227 _agc = (cap->get("agc").compare("true") == 0 ? TRUE : FALSE);
235 if (cap->has("h_flip"))
237 _h_flip = (cap->get("h_flip").compare("true") == 0 ? TRUE : FALSE);
245 if (cap->has("v_flip"))
247 _v_flip = (cap->get("v_flip").compare("true") == 0 ? TRUE : FALSE);
255 if (cap->has("brightness"))
257 _brightness.set = true;
258 _brightness.value = atoi(cap->get("brightness").c_str());
262 _brightness.set = false;
266 if (cap->has("contrast"))
268 _contrast.set = true;
269 _contrast.value = atoi(cap->get("contrast").c_str());
273 _contrast.set = false;
277 if (cap->has("saturation"))
279 _saturation.set = true;
280 _saturation.value = atoi(cap->get("saturation").c_str());
284 _saturation.set = false;
291 _hue.value = atoi(cap->get("hue").c_str());
299 if (cap->has("red_balance"))
301 _red_balance.set = true;
302 _red_balance.value = atoi(cap->get("red_balance").c_str());
306 _red_balance.set = false;
310 if (cap->has("blue_balance"))
312 _blue_balance.set = true;
313 _blue_balance.value = atoi(cap->get("blue_balance").c_str());
317 _blue_balance.set = false;
321 if (cap->has("exposure"))
323 _exposure.set = true;
324 _exposure.value = atoi(cap->get("exposure").c_str());
328 _exposure.set = false;
332 if (cap->has("gain"))
335 _gain.value = atoi(cap->get("gain").c_str());
343 if (cap->has("lens_x"))
346 _lens_x.value = atoi(cap->get("lens_x").c_str());
354 if (cap->has("lens_y"))
357 _lens_y.value = atoi(cap->get("lens_y").c_str());
366 /** Protected Constructor.
367 * Gets called from V4LCamera, when the device has already been opened
368 * and determined to be a V4L2 device.
369 * @param device_name device file name (e.g. /dev/video0)
370 * @param dev file descriptor of the opened device
372 V4L2Camera::V4L2Camera(const char *device_name, int dev)
376 _nao_hacks = _switch_u_v = false;
377 _width = _height = _bytes_per_line = _buffers_length = _fps = 0;
378 _current_buffer = -1;
379 _brightness.set = _contrast.set = _saturation.set = _hue.set =
380 _red_balance.set = _blue_balance.set = _exposure.set = _gain.set =
381 _lens_x.set = _lens_y.set = false;
382 _aec = _awb = _agc = _h_flip = _v_flip = NOT_SET;
384 memset(_format, 0, 5);
385 _frame_buffers = NULL;
386 _capture_time = NULL;
387 _device_name = strdup(device_name);
388 _data = new V4L2CameraData();
392 // getting capabilities
393 if (ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps))
396 throw Exception("V4L2Cam: Could not get capabilities - probably not a v4l2 device");
403 V4L2Camera::~V4L2Camera()
405 if (_started) stop();
406 if (_opened) close();
415 if (_started) stop();
418 _dev = ::open(_device_name, O_RDWR);
419 if (_dev < 0) throw Exception("V4L2Cam: Could not open device");
423 // getting capabilities
424 if (ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps))
427 throw Exception("V4L2Cam: Could not get capabilities - probably not a v4l2 device");
434 * Post-open() operations.
435 * Precondition: _dev (file desc) and _data->caps (capabilities) are set.
436 * @param dev file descriptor of the opened device
439 V4L2Camera::post_open()
441 //LibLogger::log_debug("V4L2Cam", "select_read_method()");
442 select_read_method();
444 //LibLogger::log_debug("V4L2Cam", "select_format()");
449 //LibLogger::log_debug("V4L2Cam", "set_fps()");
453 //LibLogger::log_debug("V4L2Cam", "set_controls()");
456 //LibLogger::log_debug("V4L2Cam", "create_buffer()");
459 //LibLogger::log_debug("V4L2Cam", "reset_cropping()");
465 * Find suitable reading method.
466 * The one set in _read_method is preferred.
468 * - _read_method and _buffers_length are set
471 V4L2Camera::select_read_method()
473 /* try preferred method */
474 if (!(_data->caps.capabilities &
475 (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING)))
477 /* preferred read method not supported - try next */
478 _read_method = (_read_method == READ ? MMAP : READ);
479 if (!(_data->caps.capabilities &
480 (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING)))
483 throw Exception("V4L2Cam: Neither read() nor streaming IO supported");
487 if (_read_method != READ)
489 v4l2_requestbuffers buf;
491 /* Streaming IO - Try 1st method, and if that fails 2nd */
492 for (int i = 0; i < 2; ++i)
494 if (_read_method == MMAP)
496 _buffers_length = MMAP_NUM_BUFFERS;
497 buf.count = _buffers_length;
498 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
499 buf.memory = V4L2_MEMORY_MMAP;
505 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
506 buf.memory = V4L2_MEMORY_USERPTR;
509 if (ioctl(_dev, VIDIOC_REQBUFS, &buf))
514 throw Exception("V4L2Cam: REQBUFS query failed");
521 throw Exception("V4L2Cam: Neither memory mapped nor user pointer IO supported");
524 /* try other method */
525 _read_method = (_read_method == MMAP ? UPTR : MMAP);
529 /* Method supported */
530 if ((_read_method == MMAP) && (buf.count < _buffers_length))
533 throw Exception("V4L2Cam: Not enough memory for the buffers");
544 switch (_read_method)
547 LibLogger::log_debug("V4L2Cam", "Using read() method");
551 LibLogger::log_debug("V4L2Cam", "Using memory mapping method");
555 LibLogger::log_debug("V4L2Cam", "Using user pointer method");
557 throw Exception("V4L2Cam: user pointer method not supported yet");
563 * Find suitable image format.
564 * The one set in _format (if any) is preferred.
566 * - _format is set (and selected)
567 * - _colorspace is set accordingly
568 * - _width, _height, and _bytes_per_line are set
571 V4L2Camera::select_format()
573 bool preferred_found = false;
574 v4l2_fmtdesc format_desc;
576 char fourcc[5] = " ";
578 if (strcmp(_format, ""))
580 /* Try to select preferred format */
581 memset(&format_desc, 0, sizeof(format_desc));
582 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
583 for (format_desc.index = 0; ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0; format_desc.index++)
585 fourcc[0] = static_cast<char>(format_desc.pixelformat & 0xFF);
586 fourcc[1] = static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
587 fourcc[2] = static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
588 fourcc[3] = static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
590 if (strcmp(_format, fourcc) == 0)
592 preferred_found = true;
598 if (!preferred_found)
600 /* Preferred format not found (or none selected)
601 -> just take first available format */
602 memset(&format_desc, 0, sizeof(format_desc));
603 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
604 format_desc.index = 0;
605 if (ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc))
608 throw Exception("V4L2Cam: No image format found");
611 fourcc[0] = static_cast<char>(format_desc.pixelformat & 0xFF);
612 fourcc[1] = static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
613 fourcc[2] = static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
614 fourcc[3] = static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
617 /* Now set this format */
619 memset(&format, 0, sizeof(format));
620 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
621 if (ioctl(_dev, VIDIOC_G_FMT, &format))
624 throw Exception("V4L2Cam: Format query failed");
627 //LibLogger::log_debug("V4L2Cam", "setting %dx%d (%s) - type %d", _width, _height, fourcc, format.type);
629 format.fmt.pix.pixelformat = v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
630 format.fmt.pix.field = V4L2_FIELD_ANY;
632 format.fmt.pix.width = _width;
634 format.fmt.pix.height = _height;
636 if (ioctl(_dev, VIDIOC_S_FMT, &format))
638 //throw Exception(errno, "Failed to set video format");
641 /* According to nao cam driver source code, G/S_STD isn't supported */
642 // Nao workaround (Hack alert)
643 LibLogger::log_warn("V4L2Cam", "Format setting failed (driver sucks) - %d: %s", errno, strerror(errno));
644 LibLogger::log_info("V4L2Cam", "Trying workaround");
648 if (ioctl(_dev, VIDIOC_G_STD, &std))
651 throw Exception("V4L2Cam: Standard query (workaround) failed");
654 if ((_width == 320) && (_height == 240))
656 std = 0x04000000UL; // QVGA
660 std = 0x08000000UL; // VGA
664 if (ioctl(_dev, VIDIOC_S_STD, &std))
667 throw Exception("V4L2Cam: Standard setting (workaround) failed");
670 format.fmt.pix.width = _width;
671 format.fmt.pix.height = _height;
672 format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
673 format.fmt.pix.field = V4L2_FIELD_ANY;
675 if (ioctl(_dev, VIDIOC_S_FMT, &format))
678 throw Exception("V4L2Cam: Format setting (workaround) failed");
681 if (_switch_u_v) _colorspace = YVY2;
684 /* ...and store final values */
685 _format[0] = static_cast<char>(format.fmt.pix.pixelformat & 0xFF);
686 _format[1] = static_cast<char>((format.fmt.pix.pixelformat >> 8) & 0xFF);
687 _format[2] = static_cast<char>((format.fmt.pix.pixelformat >> 16) & 0xFF);
688 _format[3] = static_cast<char>((format.fmt.pix.pixelformat >> 24) & 0xFF);
690 if (!_nao_hacks || !_switch_u_v)
692 if (strcmp(_format, "RGB3") == 0) _colorspace = RGB;
693 else if (strcmp(_format, "Y41P") == 0) _colorspace = YUV411_PACKED; //different byte ordering
694 else if (strcmp(_format, "411P") == 0) _colorspace = YUV411_PLANAR;
695 else if (strcmp(_format, "YUYV") == 0) _colorspace = YUY2;
696 else if (strcmp(_format, "BGR3") == 0) _colorspace = BGR;
697 else if (strcmp(_format, "UYVY") == 0) _colorspace = YUV422_PACKED;
698 else if (strcmp(_format, "422P") == 0) _colorspace = YUV422_PLANAR;
699 else if (strcmp(_format, "GREY") == 0) _colorspace = GRAY8;
700 else if (strcmp(_format, "RGB4") == 0) _colorspace = RGB_WITH_ALPHA;
701 else if (strcmp(_format, "BGR4") == 0) _colorspace = BGR_WITH_ALPHA;
702 else if (strcmp(_format, "BA81") == 0) _colorspace = BAYER_MOSAIC_BGGR;
703 else if (strcmp(_format, "Y16 ") == 0) _colorspace = MONO16;
704 else _colorspace = CS_UNKNOWN;
709 _width = format.fmt.pix.width;
710 _height = format.fmt.pix.height;
713 _bytes_per_line = format.fmt.pix.bytesperline;
715 /* Hack for bad drivers */
716 if (_bytes_per_line == 0)
718 LibLogger::log_warn("V4L2Cam", "bytesperline is 0 (driver sucks)");
719 _bytes_per_line = colorspace_buffer_size(_colorspace, _width, _height) / _height;
722 LibLogger::log_debug("V4L2Cam", "w%d h%d bpl%d cs%d fmt%s", _width, _height, _bytes_per_line, _colorspace, _format);
726 * Set desired FPS count.
729 V4L2Camera::set_fps()
731 if (!(_data->caps.capabilities & V4L2_CAP_TIMEPERFRAME) && !_nao_hacks)
733 LibLogger::log_warn("V4L2Cam", "FPS change not supported");
737 v4l2_streamparm param;
738 param.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
739 if (ioctl(_dev, VIDIOC_G_PARM, ¶m))
742 throw Exception("V4L2Cam: Streaming parameter query failed");
745 param.parm.capture.timeperframe.numerator = 1;
746 param.parm.capture.timeperframe.denominator = _fps;
747 param.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
748 if (ioctl(_dev, VIDIOC_S_PARM, ¶m))
751 //throw Exception("V4L2Cam: Streaming parameter setting failed");
752 LibLogger::log_warn("V4L2Cam", "Streaming parameter setting failed - %d: %2", errno, strerror(errno));
756 LibLogger::log_debug("V4L2Cam", "FPS set - %d/%d",
757 param.parm.capture.timeperframe.numerator,
758 param.parm.capture.timeperframe.denominator);
763 * Set Camera controls.
766 V4L2Camera::set_controls()
770 LibLogger::log_debug("V4L2Cam", (_aec == TRUE ? "enabling AEC" : "disabling AEC"));
771 if (!_nao_hacks) LibLogger::log_warn("V4L2Cam", "AEC toggling will only work on Nao");
773 set_one_control("AEC", V4L2_CID_AUDIO_MUTE, //<- this is why it will only work on Naos ;)
774 (_aec == TRUE ? 1 : 0));
779 LibLogger::log_debug("V4L2Cam", (_awb == TRUE ? "enabling AWB" : "disabling AWB"));
780 set_one_control("AWB", V4L2_CID_AUTO_WHITE_BALANCE, (_awb == TRUE ? 1 : 0));
785 LibLogger::log_debug("V4L2Cam", (_agc == TRUE ? "enabling AGC" : "disabling AGC"));
786 set_one_control("AGC", V4L2_CID_AUTOGAIN, (_agc == TRUE ? 1 : 0));
789 if (_h_flip != NOT_SET)
791 LibLogger::log_debug("V4L2Cam", (_h_flip == TRUE ? "enabling horizontal flip" : "disabling horizontal flip"));
792 set_one_control("hflip", V4L2_CID_HFLIP, (_h_flip == TRUE ? 1 : 0));
795 if (_v_flip != NOT_SET)
797 LibLogger::log_debug("V4L2Cam", (_v_flip == TRUE ? "enabling vertical flip" : "disabling vertical flip"));
798 set_one_control("vhflip", V4L2_CID_VFLIP, (_v_flip == TRUE ? 1 : 0));
803 LibLogger::log_debug("V4L2Cam", "Setting brighness to %d", _brightness.value);
804 set_one_control("brightness", V4L2_CID_BRIGHTNESS, _brightness.value);
809 LibLogger::log_debug("V4L2Cam", "Setting contrast to %d", _contrast.value);
810 set_one_control("contrast", V4L2_CID_CONTRAST, _contrast.value);
815 LibLogger::log_debug("V4L2Cam", "Setting saturation to %d", _saturation.value);
816 set_one_control("saturation", V4L2_CID_SATURATION, _saturation.value);
821 LibLogger::log_debug("V4L2Cam", "Setting hue to %d", _hue.value);
822 set_one_control("hue", V4L2_CID_HUE, _hue.value);
825 if (_red_balance.set)
827 LibLogger::log_debug("V4L2Cam", "Setting red balance to %d", _red_balance.value);
828 set_one_control("red balance", V4L2_CID_RED_BALANCE, _red_balance.value);
831 if (_blue_balance.set)
833 LibLogger::log_debug("V4L2Cam", "Setting blue balance to %d", _blue_balance.value);
834 set_one_control("blue balance", V4L2_CID_BLUE_BALANCE, _blue_balance.value);
839 LibLogger::log_debug("V4L2Cam", "Setting exposure to %d", _exposure.value);
840 set_one_control("exposure", V4L2_CID_EXPOSURE, _exposure.value);
845 LibLogger::log_debug("V4L2Cam", "Setting gain to %d", _gain.value);
846 set_one_control("gain", V4L2_CID_GAIN, _gain.value);
851 LibLogger::log_debug("V4L2Cam", "Setting horizontal lens correction to %d", _lens_x.value);
852 set_one_control("lens x", V4L2_CID_HCENTER/*_DEPRECATED*/, _lens_x.value);
857 LibLogger::log_debug("V4L2Cam", "Setting vertical lens correction to %d", _lens_y.value);
858 set_one_control("lens y", V4L2_CID_VCENTER/*_DEPRECATED*/, _lens_y.value);
863 * Set one Camera control value.
864 * @param ctrl name of the value
865 * @param id ID of the value
866 * @param value value to set
869 V4L2Camera::set_one_control(const char *ctrl, unsigned int id, int value)
871 v4l2_queryctrl queryctrl;
872 v4l2_control control;
874 memset(&queryctrl, 0, sizeof(queryctrl));
877 if (ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
881 LibLogger::log_error("V4L2Cam", "Control %s not supported", ctrl);
886 throw Exception("V4L2Cam: %s Control query failed", ctrl);
888 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
890 LibLogger::log_error("V4L2Cam", "Control %s disabled", ctrl);
894 memset(&control, 0, sizeof(control));
896 control.value = value;
898 if (ioctl(_dev, VIDIOC_S_CTRL, &control))
901 throw Exception("V4L2Cam: %s Control setting failed", ctrl);
906 * Get one Camera control value.
907 * @param ctrl name of the value
908 * @param id ID of the value
909 * @return current value
912 V4L2Camera::get_one_control(const char *ctrl, unsigned int id)
914 v4l2_queryctrl queryctrl;
915 v4l2_control control;
917 memset(&queryctrl, 0, sizeof(queryctrl));
920 if (ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
924 LibLogger::log_error("V4L2Cam", "Control %s not supported", ctrl);
929 throw Exception("V4L2Cam: %s Control query failed", ctrl);
931 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
933 LibLogger::log_error("V4L2Cam", "Control %s disabled", ctrl);
937 memset(&control, 0, sizeof(control));
940 if (ioctl(_dev, VIDIOC_G_CTRL, &control))
943 throw Exception("V4L2Cam: %s Control value reading failed", ctrl);
946 return control.value;
950 * Create a buffer for image transfer.
952 * - _read_method is set
953 * - _height and _bytes_per_line are set
954 * - _buffers_length is set
956 * - _frame_buffers is set up
959 V4L2Camera::create_buffer()
961 _frame_buffers = new FrameBuffer[_buffers_length];
963 switch (_read_method)
967 _frame_buffers[0].size = _bytes_per_line * _height;
968 _frame_buffers[0].buffer = static_cast<unsigned char *>(malloc(_frame_buffers[0].size));
969 if (_frame_buffers[0].buffer == NULL)
972 throw Exception("V4L2Cam: Out of memory");
979 for (unsigned int i = 0; i < _buffers_length; ++i)
981 /* Query status of buffer */
984 memset(&buffer, 0, sizeof (buffer));
985 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
986 buffer.memory = V4L2_MEMORY_MMAP;
989 if (ioctl(_dev, VIDIOC_QUERYBUF, &buffer))
992 throw Exception("V4L2Cam: Buffer query failed");
995 _frame_buffers[i].size = buffer.length;
996 _frame_buffers[i].buffer = static_cast<unsigned char *>(
997 mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, _dev, buffer.m.offset)
999 if (_frame_buffers[i].buffer == MAP_FAILED)
1002 throw Exception("V4L2Cam: Memory mapping failed");
1010 /* not supported yet */
1016 * Reset cropping parameters.
1019 V4L2Camera::reset_cropping()
1021 v4l2_cropcap cropcap;
1024 memset(&cropcap, 0, sizeof(cropcap));
1025 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1027 if (ioctl(_dev, VIDIOC_CROPCAP, &cropcap))
1029 LibLogger::log_warn("V4L2Cam", "cropcap query failed (driver sucks) - %d: %s", errno, strerror(errno));
1032 memset(&crop, 0, sizeof(crop));
1033 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1034 crop.c = cropcap.defrect;
1036 /* Ignore if cropping is not supported (EINVAL). */
1037 if (ioctl(_dev, VIDIOC_S_CROP, &crop) && errno != EINVAL)
1039 LibLogger::log_warn("V4L2Cam", "cropping query failed (driver sucks) - %d: %s", errno, strerror(errno));
1046 //LibLogger::log_debug("V4L2Cam", "close()");
1048 if (_started) stop();
1059 switch (_read_method)
1063 free(_frame_buffers[0].buffer);
1069 for (unsigned int i = 0; i < _buffers_length; ++i)
1071 munmap(_frame_buffers[i].buffer, _frame_buffers[i].size);
1077 /* not supported yet */
1080 delete[] _frame_buffers;
1081 _frame_buffers = NULL;
1082 _current_buffer = -1;
1087 delete _capture_time;
1095 //LibLogger::log_info("V4L2Cam", "start()");
1097 if (!_opened) throw Exception("VL42Cam: Camera not opened");
1099 if (_started) stop();
1101 switch (_read_method)
1104 /* nothing to do here */
1109 /* enqueue buffers */
1110 for (unsigned int i = 0; i < _buffers_length; ++i)
1113 memset(&buffer, 0, sizeof(buffer));
1114 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1115 buffer.memory = V4L2_MEMORY_MMAP;
1118 if (ioctl(_dev, VIDIOC_QBUF, &buffer))
1121 throw Exception("V4L2Cam: Enqueuing buffer failed");
1125 /* start streaming */
1126 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1127 if (ioctl(_dev, VIDIOC_STREAMON, &type))
1130 throw Exception("V4L2Cam: Starting stream failed");
1136 /* not supported yet */
1140 //LibLogger::log_debug("V4L2Cam", "start() complete");
1147 //LibLogger::log_debug("V4L2Cam", "stop()");
1149 if (!_started) return;
1151 switch(_read_method)
1154 /* nothing to do here */
1157 case MMAP: /* fall through */
1160 /* stop streaming */
1161 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1162 if (ioctl(_dev, VIDIOC_STREAMOFF, &type))
1165 throw Exception("V4L2Cam: Stopping stream failed");
1171 _current_buffer = -1;
1178 //LibLogger::log_debug("V4L2Cam", "ready()");
1186 //LibLogger::log_debug("V4L2Cam", "flush()");
1191 V4L2Camera::capture()
1193 //LibLogger::log_debug("V4L2Cam", "capture()");
1195 if (!_started) return;
1197 switch (_read_method)
1201 _current_buffer = 0;
1202 //LibLogger::log_debug("V4L2Cam", "calling read()");
1203 if (read(_dev, _frame_buffers[_current_buffer].buffer, _frame_buffers[_current_buffer].size) == -1)
1205 //TODO: errno handling
1206 LibLogger::log_warn("V4L2Cam", "read() failed with code %d: %s", errno, strerror(errno));
1208 //LibLogger::log_debug("V4L2Cam", "returned from read()");
1210 //No timestamping support here - just take current system time
1213 _capture_time->stamp();
1217 _capture_time = new fawkes::Time();
1225 /* dequeue buffer */
1227 memset(&buffer, 0, sizeof(buffer));
1228 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1229 buffer.memory = V4L2_MEMORY_MMAP;
1231 if (ioctl(_dev, VIDIOC_DQBUF, &buffer))
1233 //TODO: errno handling -> EAGAIN, ...?
1235 throw Exception("V4L2Cam: Dequeuing buffer failed");
1238 _current_buffer = buffer.index;
1242 _capture_time->set_time(&buffer.timestamp);
1246 _capture_time = new fawkes::Time(&buffer.timestamp);
1252 /* not supported yet */
1258 V4L2Camera::buffer()
1260 //LibLogger::log_debug("V4L2Cam", "buffer()");
1262 return (_current_buffer == -1 ? NULL : _frame_buffers[_current_buffer].buffer);
1266 V4L2Camera::buffer_size()
1268 //LibLogger::log_debug("V4L2Cam", "buffer_size()");
1270 return (_opened && (_current_buffer != -1) ? _frame_buffers[_current_buffer].size : 0);
1274 V4L2Camera::dispose_buffer()
1276 //LibLogger::log_debug("V4L2Cam", "dispose_buffer()");
1278 if (!_opened) return;
1280 switch(_read_method)
1283 /* nothing to do here */
1288 /* enqueue next buffer */
1290 memset(&buffer, 0, sizeof(buffer));
1291 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1292 buffer.memory = V4L2_MEMORY_MMAP;
1293 buffer.index = _current_buffer;
1294 if (ioctl(_dev, VIDIOC_QBUF, &buffer))
1297 throw Exception("V4L2Cam: Enqueuing buffer failed");
1303 /* not supported yet */
1307 _current_buffer = -1;
1311 V4L2Camera::pixel_width()
1313 //LibLogger::log_debug("V4L2Cam", "pixel_width()");
1319 V4L2Camera::pixel_height()
1321 //LibLogger::log_debug("V4L2Cam", "pixel_height()");
1327 V4L2Camera::colorspace()
1329 //LibLogger::log_debug("V4L2Cam", "colorspace()");
1338 V4L2Camera::capture_time()
1340 return _capture_time;
1344 V4L2Camera::set_image_number(unsigned int n)
1346 //LibLogger::log_debug("V4L2Cam", "set_image_number(%d)", n);
1352 /* --- CameraControls --- */
1355 V4L2Camera::auto_gain()
1357 return get_one_control("AGC", V4L2_CID_AUTOGAIN);
1361 V4L2Camera::set_auto_gain(bool enabled)
1363 LibLogger::log_debug("V4L2Cam", (enabled ? "enabling AGC" : "disabling AGC"));
1364 set_one_control("AGC", V4L2_CID_AUTOGAIN, (enabled ? 1 : 0));
1368 V4L2Camera::auto_white_balance()
1370 return get_one_control("AWB", V4L2_CID_AUTO_WHITE_BALANCE);
1374 V4L2Camera::set_auto_white_balance(bool enabled)
1376 LibLogger::log_debug("V4L2Cam", (enabled ? "enabling AWB" : "disabling AWB"));
1377 set_one_control("AWB", V4L2_CID_AUTO_WHITE_BALANCE, (enabled ? 1 : 0));
1381 V4L2Camera::auto_exposure()
1383 if (!_nao_hacks) LibLogger::log_warn("V4L2Cam", "AEC will only work on Nao");
1384 return get_one_control("AEC", V4L2_CID_AUDIO_MUTE);
1388 V4L2Camera::set_auto_exposure(bool enabled)
1390 LibLogger::log_debug("V4L2Cam", (enabled ? "enabling AEC" : "disabling AEC"));
1391 if (!_nao_hacks) LibLogger::log_warn("V4L2Cam", "AEC toggling will only work on Nao");
1393 set_one_control("AEC", V4L2_CID_AUDIO_MUTE, //<- this is why it will only work on Naos ;)
1398 V4L2Camera::red_balance()
1400 return get_one_control("red balance", V4L2_CID_RED_BALANCE);
1404 V4L2Camera::set_red_balance(int red_balance)
1406 LibLogger::log_debug("V4L2Cam", "Setting red balance to %d", red_balance);
1407 set_one_control("red balance", V4L2_CID_RED_BALANCE, red_balance);
1411 V4L2Camera::blue_balance()
1413 return get_one_control("blue balance", V4L2_CID_BLUE_BALANCE);
1417 V4L2Camera::set_blue_balance(int blue_balance)
1419 LibLogger::log_debug("V4L2Cam", "Setting blue balance to %d", blue_balance);
1420 set_one_control("blue balance", V4L2_CID_BLUE_BALANCE, blue_balance);
1424 V4L2Camera::u_balance()
1426 throw NotImplementedException("No such method in the V4L2 standard");
1430 V4L2Camera::set_u_balance(int u_balance)
1432 throw NotImplementedException("No such method in the V4L2 standard");
1436 V4L2Camera::v_balance()
1438 throw NotImplementedException("No such method in the V4L2 standard");
1442 V4L2Camera::set_v_balance(int v_balance)
1444 throw NotImplementedException("No such method in the V4L2 standard");
1448 V4L2Camera::brightness()
1450 return get_one_control("brightness", V4L2_CID_BRIGHTNESS);
1454 V4L2Camera::set_brightness(unsigned int brightness)
1456 LibLogger::log_debug("V4L2Cam", "Setting brighness to %d", brightness);
1457 set_one_control("brightness", V4L2_CID_BRIGHTNESS, brightness);
1461 V4L2Camera::contrast()
1463 return get_one_control("contrast", V4L2_CID_CONTRAST);
1467 V4L2Camera::set_contrast(unsigned int contrast)
1469 LibLogger::log_debug("V4L2Cam", "Setting contrast to %d", contrast);
1470 set_one_control("contrast", V4L2_CID_CONTRAST, contrast);
1474 V4L2Camera::saturation()
1476 return get_one_control("saturation", V4L2_CID_SATURATION);
1480 V4L2Camera::set_saturation(unsigned int saturation)
1482 LibLogger::log_debug("V4L2Cam", "Setting saturation to %d", saturation);
1483 set_one_control("saturation", V4L2_CID_SATURATION, saturation);
1489 return get_one_control("hue", V4L2_CID_HUE);
1493 V4L2Camera::set_hue(int hue)
1495 LibLogger::log_debug("V4L2Cam", "Setting hue to %d", hue);
1496 set_one_control("hue", V4L2_CID_HUE, hue);
1500 V4L2Camera::exposure()
1502 return get_one_control("exposure", V4L2_CID_EXPOSURE);
1506 V4L2Camera::set_exposure(unsigned int exposure)
1508 LibLogger::log_debug("V4L2Cam", "Setting exposure to %d", exposure);
1509 set_one_control("exposure", V4L2_CID_EXPOSURE, exposure);
1515 return get_one_control("gain", V4L2_CID_GAIN);
1519 V4L2Camera::set_gain(unsigned int gain)
1521 LibLogger::log_debug("V4L2Cam", "Setting gain to %u", gain);
1522 set_one_control("gain", V4L2_CID_GAIN, gain);
1527 V4L2Camera::format()
1533 V4L2Camera::set_format(const char *format)
1535 strncpy(_format, format, 4);
1543 return pixel_width();
1547 V4L2Camera::height()
1549 return pixel_height();
1553 V4L2Camera::set_size(unsigned int width,
1554 unsigned int height)
1562 V4L2Camera::horiz_mirror()
1564 return (get_one_control("hflip", V4L2_CID_HFLIP) != 0);
1568 V4L2Camera::vert_mirror()
1570 return (get_one_control("vflip", V4L2_CID_VFLIP) != 0);
1574 V4L2Camera::set_horiz_mirror(bool enabled)
1576 LibLogger::log_debug("V4L2Cam", (enabled ? "enabling horizontal flip" : "disabling horizontal flip"));
1577 set_one_control("hflip", V4L2_CID_HFLIP, (enabled ? 1 : 0));
1581 V4L2Camera::set_vert_mirror(bool enabled)
1583 LibLogger::log_debug("V4L2Cam", (enabled ? "enabling vertical flip" : "disabling vertical flip"));
1584 set_one_control("vflip", V4L2_CID_VFLIP, (enabled ? 1 : 0));
1587 /** Get the number of frames per second that have been requested from the camera.
1588 * A return value of 0 means that fps haven't been set yet through the camera.
1589 * @return the currently requested fps or 0 if not set yet
1598 V4L2Camera::set_fps(unsigned int fps)
1605 V4L2Camera::lens_x_corr()
1607 return get_one_control("lens x", V4L2_CID_HCENTER/*_DEPRECATED*/);
1611 V4L2Camera::lens_y_corr()
1613 return get_one_control("lens y", V4L2_CID_VCENTER/*_DEPRECATED*/);
1617 V4L2Camera::set_lens_x_corr(unsigned int x_corr)
1619 LibLogger::log_debug("V4L2Cam", "Setting horizontal lens correction to %d", x_corr);
1620 set_one_control("lens x", V4L2_CID_HCENTER/*_DEPRECATED*/, x_corr);
1624 V4L2Camera::set_lens_y_corr(unsigned int y_corr)
1626 LibLogger::log_debug("V4L2Cam", "Setting vertical lens correction to %d", y_corr);
1627 set_one_control("lens x", V4L2_CID_VCENTER/*_DEPRECATED*/, y_corr);
1632 V4L2Camera::print_info()
1634 /* General capabilities */
1636 "=========================================================================="
1637 << endl << _device_name << " (" << _data->caps.card << ") - " << _data->caps.bus_info
1638 << endl << "Driver: " << _data->caps.driver << " (ver " <<
1639 ((_data->caps.version >> 16) & 0xFF) << "." <<
1640 ((_data->caps.version >> 8) & 0xFF) << "." <<
1641 (_data->caps.version & 0xFF) << ")" << endl <<
1642 "--------------------------------------------------------------------------"
1645 /* General capabilities */
1646 cout << "Capabilities:" << endl;
1647 if (_data->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)
1648 cout << " + Video capture interface supported" << endl;
1649 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OUTPUT)
1650 cout << " + Video output interface supported" << endl;
1651 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OVERLAY)
1652 cout << " + Video overlay interface supported" << endl;
1653 if (_data->caps.capabilities & V4L2_CAP_VBI_CAPTURE)
1654 cout << " + Raw VBI capture interface supported" << endl;
1655 if (_data->caps.capabilities & V4L2_CAP_VBI_OUTPUT)
1656 cout << " + Raw VBI output interface supported" << endl;
1657 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE)
1658 cout << " + Sliced VBI capture interface supported" << endl;
1659 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
1660 cout << " + Sliced VBI output interface supported" << endl;
1661 if (_data->caps.capabilities & V4L2_CAP_RDS_CAPTURE)
1662 cout << " + RDS_CAPTURE set" << endl;
1663 /* Not included in Nao's version
1664 if (caps.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
1665 cout << " + Video output overlay interface supported" << endl; */
1666 if (_data->caps.capabilities & V4L2_CAP_TUNER)
1667 cout << " + Has some sort of tuner" << endl;
1668 if (_data->caps.capabilities & V4L2_CAP_AUDIO)
1669 cout << " + Has audio inputs or outputs" << endl;
1670 if (_data->caps.capabilities & V4L2_CAP_RADIO)
1671 cout << " + Has a radio receiver" << endl;
1672 if (_data->caps.capabilities & V4L2_CAP_READWRITE)
1673 cout << " + read() and write() IO supported" << endl;
1674 if (_data->caps.capabilities & V4L2_CAP_ASYNCIO)
1675 cout << " + asynchronous IO supported" << endl;
1676 if (_data->caps.capabilities & V4L2_CAP_STREAMING)
1677 cout << " + streaming IO supported" << endl;
1678 if (_data->caps.capabilities & V4L2_CAP_TIMEPERFRAME)
1679 cout << " + timeperframe field is supported" << endl;
1683 cout << "Inputs:" << endl;
1685 memset(&input, 0, sizeof(input));
1687 for (input.index = 0; ioctl(_dev, VIDIOC_ENUMINPUT, &input) == 0; input.index++)
1689 cout << "Input " << input.index << ": " << input.name << endl;
1691 cout << " |- Type: ";
1694 case V4L2_INPUT_TYPE_TUNER:
1698 case V4L2_INPUT_TYPE_CAMERA:
1707 cout << " |- Supported standards:";
1710 cout << " Unknown" << endl;
1716 v4l2_standard standard;
1717 memset (&standard, 0, sizeof(standard));
1720 for (standard.index = 0; ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++)
1722 if (standard.id & input.std) cout << " + " << standard.name << endl;
1726 if (input.index == 0) cout << "None" << endl;
1730 cout << "Outputs:" << endl;
1732 memset (&output, 0, sizeof(output));
1734 for (output.index = 0; ioctl(_dev, VIDIOC_ENUMOUTPUT, &output) == 0; output.index++)
1736 cout << " + Output " << output.index << ": " << output.name << endl;
1738 cout << " |- Type: ";
1739 switch (output.type)
1741 case V4L2_OUTPUT_TYPE_MODULATOR:
1742 cout << "TV Modulator";
1745 case V4L2_OUTPUT_TYPE_ANALOG:
1746 cout << "Analog output";
1754 cout << " |- Supported standards:";
1755 if (output.std == 0)
1757 cout << " Unknown" << endl;
1763 v4l2_standard standard;
1764 memset (&standard, 0, sizeof (standard));
1767 for (standard.index = 0; ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++)
1769 if (standard.id & output.std) cout << " + " << standard.name << endl;
1773 if (output.index == 0) cout << "None" << endl;
1776 /* Supported formats */
1777 cout << "Formats:" << endl;
1778 v4l2_fmtdesc format_desc;
1779 memset(&format_desc, 0, sizeof(format_desc));
1780 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1782 char fourcc[5] = " ";
1783 for (format_desc.index = 0; ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0; format_desc.index++)
1785 fourcc[0] = static_cast<char>(format_desc.pixelformat & 0xFF);
1786 fourcc[1] = static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
1787 fourcc[2] = static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
1788 fourcc[3] = static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
1790 colorspace_t cs = CS_UNKNOWN;
1791 if (strcmp(fourcc, "RGB3") == 0) cs = RGB;
1792 else if (strcmp(fourcc, "Y41P") == 0) cs = YUV411_PACKED; //different byte ordering
1793 else if (strcmp(fourcc, "411P") == 0) cs = YUV411_PLANAR;
1794 else if (strcmp(fourcc, "YUYV") == 0) cs = YUY2;
1795 else if (strcmp(fourcc, "BGR3") == 0) cs = BGR;
1796 else if (strcmp(fourcc, "UYVY") == 0) cs = YUV422_PACKED;
1797 else if (strcmp(fourcc, "422P") == 0) cs = YUV422_PLANAR;
1798 else if (strcmp(fourcc, "GREY") == 0) cs = GRAY8;
1799 else if (strcmp(fourcc, "RGB4") == 0) cs = RGB_WITH_ALPHA;
1800 else if (strcmp(fourcc, "BGR4") == 0) cs = BGR_WITH_ALPHA;
1801 else if (strcmp(fourcc, "BA81") == 0) cs = BAYER_MOSAIC_BGGR;
1802 else if (strcmp(fourcc, "Y16 ") == 0) cs = MONO16;
1804 cout << " + Format " << format_desc.index << ": " << fourcc <<
1805 " (" << format_desc.description << ")";
1806 if (format_desc.flags & V4L2_FMT_FLAG_COMPRESSED) cout << " [Compressed]";
1807 cout << endl << " |- Colorspace: " << colorspace_to_string(cs) << endl;
1811 /* Current Format */
1813 memset(&format, 0, sizeof(format));
1814 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1815 if (ioctl(_dev, VIDIOC_G_FMT, &format)) throw Exception("V4L2Cam: Format query failed");
1816 fourcc[0] = static_cast<char>(format.fmt.pix.pixelformat & 0xFF);
1817 fourcc[1] = static_cast<char>((format.fmt.pix.pixelformat >> 8) & 0xFF);
1818 fourcc[2] = static_cast<char>((format.fmt.pix.pixelformat >> 16) & 0xFF);
1819 fourcc[3] = static_cast<char>((format.fmt.pix.pixelformat >> 24) & 0xFF);
1821 cout << " Current Format:" << endl <<
1822 " " << format.fmt.pix.width << "x" << format.fmt.pix.height <<
1823 " (" << fourcc << ")" << endl <<
1824 " " << format.fmt.pix.bytesperline << " bytes per line" << endl <<
1825 " Total size: " << format.fmt.pix.sizeimage << endl;
1827 /* Supported Controls */
1828 cout << "Controls:" << endl;
1829 v4l2_queryctrl queryctrl;
1830 v4l2_querymenu querymenu;
1832 memset(&queryctrl, 0, sizeof(queryctrl));
1834 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1;
1837 if (ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
1839 if (errno == EINVAL) continue;
1841 cout << "Control query failed" << endl;
1844 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue;
1846 cout << " + " << queryctrl.name << " [" <<
1847 (queryctrl.id - V4L2_CID_BASE) << "] (";
1848 switch (queryctrl.type)
1850 case V4L2_CTRL_TYPE_INTEGER:
1851 cout << "int [" << queryctrl.minimum << "-" << queryctrl.maximum <<
1852 " /" << queryctrl.step << " def " << queryctrl.default_value <<
1856 case V4L2_CTRL_TYPE_MENU:
1857 cout << "menu [def " << queryctrl.default_value << "]";
1860 case V4L2_CTRL_TYPE_BOOLEAN:
1861 cout << "bool [def " << queryctrl.default_value << "]";
1864 case V4L2_CTRL_TYPE_BUTTON:
1868 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1869 case V4L2_CTRL_TYPE_INTEGER64:
1873 case V4L2_CTRL_TYPE_CTRL_CLASS:
1874 cout << "ctrl_class";
1877 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1878 case V4L2_CTRL_TYPE_STRING:
1883 cout << ")" << endl;
1885 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
1887 cout << " |- Menu items:" << endl;
1889 memset(&querymenu, 0, sizeof(querymenu));
1890 querymenu.id = queryctrl.id;
1892 for (querymenu.index = queryctrl.minimum;
1893 querymenu.index <= static_cast<unsigned long int>(queryctrl.maximum);
1896 if (ioctl(_dev, VIDIOC_QUERYMENU, &querymenu))
1898 cout << "Getting menu items failed" << endl;
1901 cout << " | + " << querymenu.name << endl;
1905 if (queryctrl.id == V4L2_CID_BASE) cout << "None" << endl;
1908 /* Supported Private Controls */
1909 cout << "Private Controls:" << endl;
1910 for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
1912 if (ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
1914 if (errno == EINVAL) break;
1916 cout << "Private Control query failed" << endl;
1920 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue;
1922 cout << " + " << queryctrl.name << " [" <<
1923 (queryctrl.id - V4L2_CID_PRIVATE_BASE) << "] (";
1924 switch (queryctrl.type)
1926 case V4L2_CTRL_TYPE_INTEGER:
1927 cout << "int [" << queryctrl.minimum << "-" << queryctrl.maximum <<
1928 " /" << queryctrl.step << " def " << queryctrl.default_value <<
1932 case V4L2_CTRL_TYPE_MENU:
1933 cout << "menu [def " << queryctrl.default_value << "]";
1936 case V4L2_CTRL_TYPE_BOOLEAN:
1937 cout << "bool [def " << queryctrl.default_value << "]";
1940 case V4L2_CTRL_TYPE_BUTTON:
1944 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1945 case V4L2_CTRL_TYPE_INTEGER64:
1949 case V4L2_CTRL_TYPE_CTRL_CLASS:
1950 cout << "ctrl_class";
1953 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1954 case V4L2_CTRL_TYPE_STRING:
1959 cout << ")" << endl;
1961 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
1963 cout << " |- Menu items:" << endl;
1965 memset(&querymenu, 0, sizeof(querymenu));
1966 querymenu.id = queryctrl.id;
1968 for (querymenu.index = queryctrl.minimum;
1969 querymenu.index <= static_cast<unsigned long int>(queryctrl.maximum);
1972 if (ioctl(_dev, VIDIOC_QUERYMENU, &querymenu))
1974 cout << "Getting menu items failed" << endl;
1977 cout << " | + " << querymenu.name << endl;
1981 if (queryctrl.id == V4L2_CID_PRIVATE_BASE) cout << "None" << endl;
1984 "=========================================================================="