25 #include <fvcams/v4l2.h>
27 #include <core/exception.h>
28 #include <core/exceptions/software.h>
29 #include <logging/liblogger.h>
30 #include <fvutils/system/camargp.h>
33 #include <sys/ioctl.h>
39 #include <linux/version.h>
53 # define v4l2_fd_open(fd, flags) (fd)
54 # define v4l2_close ::close
56 # define v4l2_ioctl ioctl
57 # define v4l2_read read
58 # define v4l2_mmap mmap
59 # define v4l2_munmap munmap
62 namespace firevision {
90 V4L2Camera::V4L2Camera(
const char *device_name)
92 _opened = _started =
false;
93 _nao_hacks = _switch_u_v =
false;
94 _width = _height = _bytes_per_line = _fps = _buffers_length = 0;
96 _brightness.set = _contrast.set = _saturation.set = _hue.set =
97 _red_balance.set = _blue_balance.set = _exposure.set = _gain.set =
98 _lens_x.set = _lens_y.set =
false;
99 _aec = _awb = _agc = _h_flip = _v_flip = NOT_SET;
101 memset(_format, 0, 5);
102 _frame_buffers = NULL;
103 _capture_time = NULL;
104 _device_name = strdup(device_name);
105 _data =
new V4L2CameraData();
142 _opened = _started =
false;
144 _width = _height = _bytes_per_line = _buffers_length = 0;
145 _current_buffer = -1;
146 _frame_buffers = NULL;
147 _capture_time = NULL;
148 _data =
new V4L2CameraData();
150 if (cap->
has(
"device")) _device_name = strdup(cap->
get(
"device").c_str());
154 if (cap->
has(
"read_method"))
156 string rm = cap->
get(
"read_method");
157 if (rm.compare(
"READ") == 0) _read_method = READ;
158 else if (rm.compare(
"MMAP") == 0) _read_method = MMAP;
159 else if (rm.compare(
"UPTR") == 0) _read_method = UPTR;
160 else throw Exception(
"V4L2Cam: Invalid read method");
168 if (cap->
has(
"format"))
170 string fmt = cap->
get(
"format");
171 if (fmt.length() != 4)
throw Exception(
"V4L2Cam: Invalid format fourcc");
172 strncpy(_format, fmt.c_str(), 4);
177 memset(_format, 0, 5);
181 if (cap->
has(
"size"))
183 string size = cap->
get(
"size");
184 string::size_type pos;
185 if ((pos = size.find(
'x')) == string::npos)
throw Exception(
"V4L2Cam: invalid image size string");
186 if ((pos == (size.length() - 1)))
throw Exception(
"V4L2Cam: invalid image size string");
188 unsigned int mult = 1;
189 for (string::size_type i = pos - 1; i != string::npos; --i)
191 _width += (size.at(i) -
'0') * mult;
196 for (string::size_type i = size.length() - 1; i > pos; --i)
198 _height += (size.at(i) -
'0') * mult;
204 if (cap->
has(
"switch_u_v"))
206 _switch_u_v = (cap->
get(
"switch_u_v").compare(
"true") == 0);
216 if ((_fps = atoi(cap->
get(
"fps").c_str())) == 0)
throw Exception(
"V4L2Cam: invalid fps string");
226 _aec = (cap->
get(
"aec").compare(
"true") == 0 ? TRUE : FALSE);
236 _awb = (cap->
get(
"awb").compare(
"true") == 0 ? TRUE : FALSE);
246 _agc = (cap->
get(
"agc").compare(
"true") == 0 ? TRUE : FALSE);
254 if (cap->
has(
"h_flip"))
256 _h_flip = (cap->
get(
"h_flip").compare(
"true") == 0 ? TRUE : FALSE);
264 if (cap->
has(
"v_flip"))
266 _v_flip = (cap->
get(
"v_flip").compare(
"true") == 0 ? TRUE : FALSE);
274 if (cap->
has(
"brightness"))
276 _brightness.set =
true;
277 _brightness.value = atoi(cap->
get(
"brightness").c_str());
281 _brightness.set =
false;
285 if (cap->
has(
"contrast"))
287 _contrast.set =
true;
288 _contrast.value = atoi(cap->
get(
"contrast").c_str());
292 _contrast.set =
false;
296 if (cap->
has(
"saturation"))
298 _saturation.set =
true;
299 _saturation.value = atoi(cap->
get(
"saturation").c_str());
303 _saturation.set =
false;
310 _hue.value = atoi(cap->
get(
"hue").c_str());
318 if (cap->
has(
"red_balance"))
320 _red_balance.set =
true;
321 _red_balance.value = atoi(cap->
get(
"red_balance").c_str());
325 _red_balance.set =
false;
329 if (cap->
has(
"blue_balance"))
331 _blue_balance.set =
true;
332 _blue_balance.value = atoi(cap->
get(
"blue_balance").c_str());
336 _blue_balance.set =
false;
340 if (cap->
has(
"exposure"))
342 _exposure.set =
true;
343 _exposure.value = atoi(cap->
get(
"exposure").c_str());
347 _exposure.set =
false;
351 if (cap->
has(
"gain"))
354 _gain.value = atoi(cap->
get(
"gain").c_str());
362 if (cap->
has(
"lens_x"))
365 _lens_x.value = atoi(cap->
get(
"lens_x").c_str());
373 if (cap->
has(
"lens_y"))
376 _lens_y.value = atoi(cap->
get(
"lens_y").c_str());
391 V4L2Camera::V4L2Camera(
const char *device_name,
int dev)
395 _nao_hacks = _switch_u_v =
false;
396 _width = _height = _bytes_per_line = _buffers_length = _fps = 0;
397 _current_buffer = -1;
398 _brightness.set = _contrast.set = _saturation.set = _hue.set =
399 _red_balance.set = _blue_balance.set = _exposure.set = _gain.set =
400 _lens_x.set = _lens_y.set =
false;
401 _aec = _awb = _agc = _h_flip = _v_flip = NOT_SET;
403 memset(_format, 0, 5);
404 _frame_buffers = NULL;
405 _capture_time = NULL;
406 _device_name = strdup(device_name);
407 _data =
new V4L2CameraData();
412 if (v4l2_ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps))
415 throw Exception(
"V4L2Cam: Could not get capabilities - probably not a v4l2 device");
422 V4L2Camera::~V4L2Camera()
424 if (_started) stop();
425 if (_opened) close();
434 if (_started) stop();
437 _dev = ::open(_device_name, O_RDWR);
438 int libv4l2_fd = v4l2_fd_open(_dev, 0);
439 if (libv4l2_fd != -1) _dev = libv4l2_fd;
446 if (_dev < 0)
throw Exception(
"V4L2Cam: Could not open device");
451 if (v4l2_ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps))
454 throw Exception(
"V4L2Cam: Could not get capabilities - probably not a v4l2 device");
466 V4L2Camera::post_open()
469 select_read_method();
498 V4L2Camera::select_read_method()
501 if (!(_data->caps.capabilities &
502 (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING)))
505 _read_method = (_read_method == READ ? MMAP : READ);
506 if (!(_data->caps.capabilities &
507 (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING)))
510 throw Exception(
"V4L2Cam: Neither read() nor streaming IO supported");
514 if (_read_method != READ)
516 v4l2_requestbuffers buf;
519 for (
int i = 0; i < 2; ++i)
521 if (_read_method == MMAP)
523 _buffers_length = MMAP_NUM_BUFFERS;
524 buf.count = _buffers_length;
525 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
526 buf.memory = V4L2_MEMORY_MMAP;
532 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
533 buf.memory = V4L2_MEMORY_USERPTR;
536 if (v4l2_ioctl(_dev, VIDIOC_REQBUFS, &buf))
541 throw Exception(
"V4L2Cam: REQBUFS query failed");
548 throw Exception(
"V4L2Cam: Neither memory mapped nor user pointer IO supported");
552 _read_method = (_read_method == MMAP ? UPTR : MMAP);
557 if ((_read_method == MMAP) && (buf.count < _buffers_length))
560 throw Exception(
"V4L2Cam: Not enough memory for the buffers");
571 switch (_read_method)
574 LibLogger::log_debug(
"V4L2Cam",
"Using read() method");
578 LibLogger::log_debug(
"V4L2Cam",
"Using memory mapping method");
582 LibLogger::log_debug(
"V4L2Cam",
"Using user pointer method");
584 throw Exception(
"V4L2Cam: user pointer method not supported yet");
598 V4L2Camera::select_format()
600 bool preferred_found =
false;
601 v4l2_fmtdesc format_desc;
603 char fourcc[5] =
" ";
605 if (strcmp(_format,
""))
608 memset(&format_desc, 0,
sizeof(format_desc));
609 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
610 for (format_desc.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0; format_desc.index++)
612 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
613 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
614 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
615 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
617 if (strcmp(_format, fourcc) == 0)
619 preferred_found =
true;
625 if (!preferred_found)
629 memset(&format_desc, 0,
sizeof(format_desc));
630 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
631 format_desc.index = 0;
632 if (v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc))
635 throw Exception(
"V4L2Cam: No image format found");
638 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
639 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
640 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
641 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
646 memset(&format, 0,
sizeof(format));
647 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
648 if (v4l2_ioctl(_dev, VIDIOC_G_FMT, &format))
651 throw Exception(
"V4L2Cam: Format query failed");
656 format.fmt.pix.pixelformat = v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
657 format.fmt.pix.field = V4L2_FIELD_ANY;
659 format.fmt.pix.width = _width;
661 format.fmt.pix.height = _height;
663 if (v4l2_ioctl(_dev, VIDIOC_S_FMT, &format))
669 LibLogger::log_warn(
"V4L2Cam",
"Format setting failed (driver sucks) - %d: %s", errno, strerror(errno));
670 LibLogger::log_info(
"V4L2Cam",
"Trying workaround");
674 if (v4l2_ioctl(_dev, VIDIOC_G_STD, &std))
677 throw Exception(
"V4L2Cam: Standard query (workaround) failed");
680 if ((_width == 320) && (_height == 240))
690 if (v4l2_ioctl(_dev, VIDIOC_S_STD, &std))
693 throw Exception(
"V4L2Cam: Standard setting (workaround) failed");
696 format.fmt.pix.width = _width;
697 format.fmt.pix.height = _height;
698 format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
699 format.fmt.pix.field = V4L2_FIELD_ANY;
701 if (v4l2_ioctl(_dev, VIDIOC_S_FMT, &format))
704 throw Exception(
"V4L2Cam: Format setting (workaround) failed");
707 if (_switch_u_v) _colorspace = YVY2;
711 _format[0] =
static_cast<char>(format.fmt.pix.pixelformat & 0xFF);
712 _format[1] =
static_cast<char>((format.fmt.pix.pixelformat >> 8) & 0xFF);
713 _format[2] =
static_cast<char>((format.fmt.pix.pixelformat >> 16) & 0xFF);
714 _format[3] =
static_cast<char>((format.fmt.pix.pixelformat >> 24) & 0xFF);
716 if (!_nao_hacks || !_switch_u_v)
718 if (strcmp(_format,
"RGB3") == 0) _colorspace = RGB;
719 else if (strcmp(_format,
"Y41P") == 0) _colorspace = YUV411_PACKED;
720 else if (strcmp(_format,
"411P") == 0) _colorspace = YUV411_PLANAR;
721 else if (strcmp(_format,
"YUYV") == 0) _colorspace = YUY2;
722 else if (strcmp(_format,
"BGR3") == 0) _colorspace = BGR;
723 else if (strcmp(_format,
"UYVY") == 0) _colorspace = YUV422_PACKED;
724 else if (strcmp(_format,
"422P") == 0) _colorspace = YUV422_PLANAR;
725 else if (strcmp(_format,
"GREY") == 0) _colorspace = GRAY8;
726 else if (strcmp(_format,
"RGB4") == 0) _colorspace = RGB_WITH_ALPHA;
727 else if (strcmp(_format,
"BGR4") == 0) _colorspace = BGR_WITH_ALPHA;
728 else if (strcmp(_format,
"BA81") == 0) _colorspace = BAYER_MOSAIC_BGGR;
729 else if (strcmp(_format,
"Y16 ") == 0) _colorspace = MONO16;
730 else _colorspace = CS_UNKNOWN;
735 _width = format.fmt.pix.width;
736 _height = format.fmt.pix.height;
739 _bytes_per_line = format.fmt.pix.bytesperline;
742 if (_bytes_per_line == 0)
744 LibLogger::log_warn(
"V4L2Cam",
"bytesperline is 0 (driver sucks)");
745 _bytes_per_line = colorspace_buffer_size(_colorspace, _width, _height) / _height;
748 LibLogger::log_debug(
"V4L2Cam",
"w%d h%d bpl%d cs%d fmt%s", _width, _height, _bytes_per_line, _colorspace, _format);
755 V4L2Camera::set_fps()
757 v4l2_streamparm param;
758 param.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
759 if (v4l2_ioctl(_dev, VIDIOC_G_PARM, ¶m))
762 throw Exception(
"V4L2Cam: Streaming parameter query failed");
765 if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
767 LibLogger::log_warn(
"V4L2Cam",
"FPS change not supported");
771 param.parm.capture.timeperframe.numerator = 1;
772 param.parm.capture.timeperframe.denominator = _fps;
773 if (v4l2_ioctl(_dev, VIDIOC_S_PARM, ¶m))
776 throw Exception(
"V4L2Cam: Streaming parameter setting failed");
780 LibLogger::log_debug(
"V4L2Cam",
"FPS set - %d/%d",
781 param.parm.capture.timeperframe.numerator,
782 param.parm.capture.timeperframe.denominator);
790 V4L2Camera::set_controls()
792 if (_aec != NOT_SET) set_auto_exposure(_aec == TRUE);
793 if (_awb != NOT_SET) set_auto_white_balance(_awb == TRUE);
794 if (_agc != NOT_SET) set_auto_gain(_agc == TRUE);
796 if (_h_flip != NOT_SET) set_horiz_mirror(_h_flip == TRUE);
797 if (_v_flip != NOT_SET) set_vert_mirror(_v_flip == TRUE);
799 if (_brightness.set) set_brightness(_brightness.value);
800 if (_contrast.set) set_contrast(_contrast.value);
801 if (_saturation.set) set_saturation(_saturation.value);
802 if (_hue.set) set_hue(_hue.value);
803 if (_red_balance.set) set_red_balance(_red_balance.value);
804 if (_blue_balance.set) set_blue_balance(_blue_balance.value);
805 if (_exposure.set) set_exposure(_exposure.value);
806 if (_gain.set) set_gain(_gain.value);
807 if (_lens_x.set) set_lens_x_corr(_lens_x.value);
808 if (_lens_y.set) set_lens_y_corr(_lens_y.value);
818 V4L2Camera::set_one_control(
const char *ctrl,
unsigned int id,
int value)
820 v4l2_queryctrl queryctrl;
821 v4l2_control control;
823 memset(&queryctrl, 0,
sizeof(queryctrl));
826 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
830 LibLogger::log_error(
"V4L2Cam",
"Control %s not supported", ctrl);
835 throw Exception(
"V4L2Cam: %s Control query failed", ctrl);
837 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
839 LibLogger::log_error(
"V4L2Cam",
"Control %s disabled", ctrl);
843 memset(&control, 0,
sizeof(control));
845 control.value = value;
847 if (v4l2_ioctl(_dev, VIDIOC_S_CTRL, &control))
850 throw Exception(
"V4L2Cam: %s Control setting failed", ctrl);
861 V4L2Camera::get_one_control(
const char *ctrl,
unsigned int id)
863 v4l2_queryctrl queryctrl;
864 v4l2_control control;
866 memset(&queryctrl, 0,
sizeof(queryctrl));
869 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
873 LibLogger::log_error(
"V4L2Cam",
"Control %s not supported", ctrl);
878 throw Exception(
"V4L2Cam: %s Control query failed", ctrl);
880 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
882 LibLogger::log_error(
"V4L2Cam",
"Control %s disabled", ctrl);
886 memset(&control, 0,
sizeof(control));
889 if (v4l2_ioctl(_dev, VIDIOC_G_CTRL, &control))
892 throw Exception(
"V4L2Cam: %s Control value reading failed", ctrl);
895 return control.value;
908 V4L2Camera::create_buffer()
910 _frame_buffers =
new FrameBuffer[_buffers_length];
912 switch (_read_method)
916 _frame_buffers[0].size = _bytes_per_line * _height;
917 _frame_buffers[0].buffer =
static_cast<unsigned char *
>(malloc(_frame_buffers[0].size));
918 if (_frame_buffers[0].buffer == NULL)
921 throw Exception(
"V4L2Cam: Out of memory");
928 for (
unsigned int i = 0; i < _buffers_length; ++i)
933 memset(&buffer, 0,
sizeof (buffer));
934 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
935 buffer.memory = V4L2_MEMORY_MMAP;
938 if (v4l2_ioctl(_dev, VIDIOC_QUERYBUF, &buffer))
941 throw Exception(
"V4L2Cam: Buffer query failed");
944 _frame_buffers[i].size = buffer.length;
945 _frame_buffers[i].buffer =
static_cast<unsigned char *
>(
946 v4l2_mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, _dev, buffer.m.offset)
948 if (_frame_buffers[i].buffer == MAP_FAILED)
951 throw Exception(
"V4L2Cam: Memory mapping failed");
968 V4L2Camera::reset_cropping()
970 v4l2_cropcap cropcap;
973 memset(&cropcap, 0,
sizeof(cropcap));
974 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
976 if (v4l2_ioctl(_dev, VIDIOC_CROPCAP, &cropcap))
978 LibLogger::log_warn(
"V4L2Cam",
"cropcap query failed (driver sucks) - %d: %s", errno, strerror(errno));
981 memset(&crop, 0,
sizeof(crop));
982 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
983 crop.c = cropcap.defrect;
986 if (v4l2_ioctl(_dev, VIDIOC_S_CROP, &crop) && errno != EINVAL)
988 LibLogger::log_warn(
"V4L2Cam",
"cropping query failed (driver sucks) - %d: %s", errno, strerror(errno));
997 if (_started) stop();
1001 switch (_read_method)
1005 free(_frame_buffers[0].buffer);
1011 for (
unsigned int i = 0; i < _buffers_length; ++i)
1013 v4l2_munmap(_frame_buffers[i].buffer, _frame_buffers[i].size);
1022 delete[] _frame_buffers;
1023 _frame_buffers = NULL;
1024 _current_buffer = -1;
1036 delete _capture_time;
1046 if (!_opened)
throw Exception(
"VL42Cam: Camera not opened");
1048 if (_started) stop();
1050 switch (_read_method)
1059 for (
unsigned int i = 0; i < _buffers_length; ++i)
1062 memset(&buffer, 0,
sizeof(buffer));
1063 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1064 buffer.memory = V4L2_MEMORY_MMAP;
1067 if (v4l2_ioctl(_dev, VIDIOC_QBUF, &buffer))
1070 throw Exception(
"V4L2Cam: Enqueuing buffer failed");
1075 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1076 if (v4l2_ioctl(_dev, VIDIOC_STREAMON, &type))
1079 throw Exception(
"V4L2Cam: Starting stream failed");
1098 if (!_started)
return;
1100 switch (_read_method)
1110 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1111 if (v4l2_ioctl(_dev, VIDIOC_STREAMOFF, &type))
1114 throw Exception(
"V4L2Cam: Stopping stream failed");
1120 _current_buffer = -1;
1140 V4L2Camera::capture()
1144 if (!_started)
return;
1146 switch (_read_method)
1150 _current_buffer = 0;
1152 if (v4l2_read(_dev, _frame_buffers[_current_buffer].buffer, _frame_buffers[_current_buffer].size) == -1)
1155 LibLogger::log_warn(
"V4L2Cam",
"read() failed with code %d: %s", errno, strerror(errno));
1162 _capture_time->stamp();
1176 memset(&buffer, 0,
sizeof(buffer));
1177 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1178 buffer.memory = V4L2_MEMORY_MMAP;
1180 if (v4l2_ioctl(_dev, VIDIOC_DQBUF, &buffer))
1184 throw Exception(
"V4L2Cam: Dequeuing buffer failed");
1187 _current_buffer = buffer.index;
1191 _capture_time->set_time(&buffer.timestamp);
1207 V4L2Camera::buffer()
1211 return (_current_buffer == -1 ? NULL : _frame_buffers[_current_buffer].buffer);
1215 V4L2Camera::buffer_size()
1219 return (_opened && (_current_buffer != -1) ? _frame_buffers[_current_buffer].size : 0);
1223 V4L2Camera::dispose_buffer()
1227 if (!_opened)
return;
1229 switch (_read_method)
1239 memset(&buffer, 0,
sizeof(buffer));
1240 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1241 buffer.memory = V4L2_MEMORY_MMAP;
1242 buffer.index = _current_buffer;
1245 if (v4l2_ioctl(_dev, VIDIOC_QBUF, &buffer))
1247 int errno_save = errno;
1249 throw Exception(errno_save,
"V4L2Cam: Enqueuing buffer failed");
1259 _current_buffer = -1;
1263 V4L2Camera::pixel_width()
1271 V4L2Camera::pixel_height()
1279 V4L2Camera::colorspace()
1290 V4L2Camera::capture_time()
1292 return _capture_time;
1296 V4L2Camera::set_image_number(
unsigned int n)
1307 V4L2Camera::auto_gain()
1309 return get_one_control(
"AGC", V4L2_CID_AUTOGAIN);
1313 V4L2Camera::set_auto_gain(
bool enabled)
1315 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling AGC" :
"disabling AGC"));
1316 set_one_control(
"AGC", V4L2_CID_AUTOGAIN, (enabled ? 1 : 0));
1320 V4L2Camera::auto_white_balance()
1322 return get_one_control(
"AWB", V4L2_CID_AUTO_WHITE_BALANCE);
1326 V4L2Camera::set_auto_white_balance(
bool enabled)
1328 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling AWB" :
"disabling AWB"));
1329 set_one_control(
"AWB", V4L2_CID_AUTO_WHITE_BALANCE, (enabled ? 1 : 0));
1333 V4L2Camera::auto_exposure()
1339 V4L2Camera::set_auto_exposure(
bool enabled)
1345 V4L2Camera::red_balance()
1347 return get_one_control(
"red balance", V4L2_CID_RED_BALANCE);
1351 V4L2Camera::set_red_balance(
int red_balance)
1353 LibLogger::log_debug(
"V4L2Cam",
"Setting red balance to %d", red_balance);
1354 set_one_control(
"red balance", V4L2_CID_RED_BALANCE, red_balance);
1358 V4L2Camera::blue_balance()
1360 return get_one_control(
"blue balance", V4L2_CID_BLUE_BALANCE);
1364 V4L2Camera::set_blue_balance(
int blue_balance)
1366 LibLogger::log_debug(
"V4L2Cam",
"Setting blue balance to %d", blue_balance);
1367 set_one_control(
"blue balance", V4L2_CID_BLUE_BALANCE, blue_balance);
1371 V4L2Camera::u_balance()
1377 V4L2Camera::set_u_balance(
int u_balance)
1383 V4L2Camera::v_balance()
1389 V4L2Camera::set_v_balance(
int v_balance)
1395 V4L2Camera::brightness()
1397 return get_one_control(
"brightness", V4L2_CID_BRIGHTNESS);
1401 V4L2Camera::set_brightness(
unsigned int brightness)
1403 LibLogger::log_debug(
"V4L2Cam",
"Setting brighness to %d", brightness);
1404 set_one_control(
"brightness", V4L2_CID_BRIGHTNESS, brightness);
1408 V4L2Camera::contrast()
1410 return get_one_control(
"contrast", V4L2_CID_CONTRAST);
1414 V4L2Camera::set_contrast(
unsigned int contrast)
1416 LibLogger::log_debug(
"V4L2Cam",
"Setting contrast to %d", contrast);
1417 set_one_control(
"contrast", V4L2_CID_CONTRAST, contrast);
1421 V4L2Camera::saturation()
1423 return get_one_control(
"saturation", V4L2_CID_SATURATION);
1427 V4L2Camera::set_saturation(
unsigned int saturation)
1429 LibLogger::log_debug(
"V4L2Cam",
"Setting saturation to %d", saturation);
1430 set_one_control(
"saturation", V4L2_CID_SATURATION, saturation);
1436 return get_one_control(
"hue", V4L2_CID_HUE);
1440 V4L2Camera::set_hue(
int hue)
1442 LibLogger::log_debug(
"V4L2Cam",
"Setting hue to %d", hue);
1443 set_one_control(
"hue", V4L2_CID_HUE, hue);
1447 V4L2Camera::exposure()
1449 return get_one_control(
"exposure", V4L2_CID_EXPOSURE);
1453 V4L2Camera::set_exposure(
unsigned int exposure)
1455 LibLogger::log_debug(
"V4L2Cam",
"Setting exposure to %d", exposure);
1456 set_one_control(
"exposure", V4L2_CID_EXPOSURE, exposure);
1462 return get_one_control(
"gain", V4L2_CID_GAIN);
1466 V4L2Camera::set_gain(
unsigned int gain)
1468 LibLogger::log_debug(
"V4L2Cam",
"Setting gain to %u", gain);
1469 set_one_control(
"gain", V4L2_CID_GAIN, gain);
1474 V4L2Camera::format()
1480 V4L2Camera::set_format(
const char *format)
1482 strncpy(_format, format, 4);
1490 return pixel_width();
1494 V4L2Camera::height()
1496 return pixel_height();
1500 V4L2Camera::set_size(
unsigned int width,
1501 unsigned int height)
1509 V4L2Camera::horiz_mirror()
1511 return (get_one_control(
"hflip", V4L2_CID_HFLIP) != 0);
1515 V4L2Camera::vert_mirror()
1517 return (get_one_control(
"vflip", V4L2_CID_VFLIP) != 0);
1521 V4L2Camera::set_horiz_mirror(
bool enabled)
1523 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling horizontal flip" :
"disabling horizontal flip"));
1524 set_one_control(
"hflip", V4L2_CID_HFLIP, (enabled ? 1 : 0));
1528 V4L2Camera::set_vert_mirror(
bool enabled)
1530 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling vertical flip" :
"disabling vertical flip"));
1531 set_one_control(
"vflip", V4L2_CID_VFLIP, (enabled ? 1 : 0));
1545 V4L2Camera::set_fps(
unsigned int fps)
1552 V4L2Camera::lens_x_corr()
1554 return get_one_control(
"lens x", V4L2_CID_HCENTER);
1558 V4L2Camera::lens_y_corr()
1560 return get_one_control(
"lens y", V4L2_CID_VCENTER);
1564 V4L2Camera::set_lens_x_corr(
unsigned int x_corr)
1566 LibLogger::log_debug(
"V4L2Cam",
"Setting horizontal lens correction to %d", x_corr);
1567 set_one_control(
"lens x", V4L2_CID_HCENTER, x_corr);
1571 V4L2Camera::set_lens_y_corr(
unsigned int y_corr)
1573 LibLogger::log_debug(
"V4L2Cam",
"Setting vertical lens correction to %d", y_corr);
1574 set_one_control(
"lens x", V4L2_CID_VCENTER, y_corr);
1579 V4L2Camera::print_info()
1583 "=========================================================================="
1584 << endl << _device_name <<
" (" << _data->caps.card <<
") - " << _data->caps.bus_info
1585 << endl <<
"Driver: " << _data->caps.driver <<
" (ver " <<
1586 ((_data->caps.version >> 16) & 0xFF) <<
"." <<
1587 ((_data->caps.version >> 8) & 0xFF) <<
"." <<
1588 (_data->caps.version & 0xFF) <<
")" << endl <<
1589 "--------------------------------------------------------------------------"
1593 cout <<
"Capabilities:" << endl;
1594 if (_data->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)
1595 cout <<
" + Video capture interface supported" << endl;
1596 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OUTPUT)
1597 cout <<
" + Video output interface supported" << endl;
1598 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OVERLAY)
1599 cout <<
" + Video overlay interface supported" << endl;
1600 if (_data->caps.capabilities & V4L2_CAP_VBI_CAPTURE)
1601 cout <<
" + Raw VBI capture interface supported" << endl;
1602 if (_data->caps.capabilities & V4L2_CAP_VBI_OUTPUT)
1603 cout <<
" + Raw VBI output interface supported" << endl;
1604 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE)
1605 cout <<
" + Sliced VBI capture interface supported" << endl;
1606 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
1607 cout <<
" + Sliced VBI output interface supported" << endl;
1608 if (_data->caps.capabilities & V4L2_CAP_RDS_CAPTURE)
1609 cout <<
" + RDS_CAPTURE set" << endl;
1613 if (_data->caps.capabilities & V4L2_CAP_TUNER)
1614 cout <<
" + Has some sort of tuner" << endl;
1615 if (_data->caps.capabilities & V4L2_CAP_AUDIO)
1616 cout <<
" + Has audio inputs or outputs" << endl;
1617 if (_data->caps.capabilities & V4L2_CAP_RADIO)
1618 cout <<
" + Has a radio receiver" << endl;
1619 if (_data->caps.capabilities & V4L2_CAP_READWRITE)
1620 cout <<
" + read() and write() IO supported" << endl;
1621 if (_data->caps.capabilities & V4L2_CAP_ASYNCIO)
1622 cout <<
" + asynchronous IO supported" << endl;
1623 if (_data->caps.capabilities & V4L2_CAP_STREAMING)
1624 cout <<
" + streaming IO supported" << endl;
1625 if (_data->caps.capabilities & V4L2_CAP_TIMEPERFRAME)
1626 cout <<
" + timeperframe field is supported" << endl;
1630 cout <<
"Inputs:" << endl;
1632 memset(&input, 0,
sizeof(input));
1634 for (input.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMINPUT, &input) == 0; input.index++)
1636 cout <<
"Input " << input.index <<
": " << input.name << endl;
1638 cout <<
" |- Type: ";
1641 case V4L2_INPUT_TYPE_TUNER:
1645 case V4L2_INPUT_TYPE_CAMERA:
1654 cout <<
" |- Supported standards:";
1657 cout <<
" Unknown" << endl;
1663 v4l2_standard standard;
1664 memset (&standard, 0,
sizeof(standard));
1667 for (standard.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++)
1669 if (standard.id & input.std) cout <<
" + " << standard.name << endl;
1673 if (input.index == 0) cout <<
"None" << endl;
1677 cout <<
"Outputs:" << endl;
1679 memset (&output, 0,
sizeof(output));
1681 for (output.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMOUTPUT, &output) == 0; output.index++)
1683 cout <<
" + Output " << output.index <<
": " << output.name << endl;
1685 cout <<
" |- Type: ";
1686 switch (output.type)
1688 case V4L2_OUTPUT_TYPE_MODULATOR:
1689 cout <<
"TV Modulator";
1692 case V4L2_OUTPUT_TYPE_ANALOG:
1693 cout <<
"Analog output";
1701 cout <<
" |- Supported standards:";
1702 if (output.std == 0)
1704 cout <<
" Unknown" << endl;
1710 v4l2_standard standard;
1711 memset (&standard, 0,
sizeof (standard));
1714 for (standard.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++)
1716 if (standard.id & output.std) cout <<
" + " << standard.name << endl;
1720 if (output.index == 0) cout <<
"None" << endl;
1724 cout <<
"Formats:" << endl;
1725 v4l2_fmtdesc format_desc;
1726 memset(&format_desc, 0,
sizeof(format_desc));
1727 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1729 char fourcc[5] =
" ";
1730 for (format_desc.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0; format_desc.index++)
1732 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
1733 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
1734 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
1735 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
1737 colorspace_t cs = CS_UNKNOWN;
1738 if (strcmp(fourcc,
"RGB3") == 0) cs = RGB;
1739 else if (strcmp(fourcc,
"Y41P") == 0) cs = YUV411_PACKED;
1740 else if (strcmp(fourcc,
"411P") == 0) cs = YUV411_PLANAR;
1741 else if (strcmp(fourcc,
"YUYV") == 0) cs = YUY2;
1742 else if (strcmp(fourcc,
"BGR3") == 0) cs = BGR;
1743 else if (strcmp(fourcc,
"UYVY") == 0) cs = YUV422_PACKED;
1744 else if (strcmp(fourcc,
"422P") == 0) cs = YUV422_PLANAR;
1745 else if (strcmp(fourcc,
"GREY") == 0) cs = GRAY8;
1746 else if (strcmp(fourcc,
"RGB4") == 0) cs = RGB_WITH_ALPHA;
1747 else if (strcmp(fourcc,
"BGR4") == 0) cs = BGR_WITH_ALPHA;
1748 else if (strcmp(fourcc,
"BA81") == 0) cs = BAYER_MOSAIC_BGGR;
1749 else if (strcmp(fourcc,
"Y16 ") == 0) cs = MONO16;
1751 cout <<
" + Format " << format_desc.index <<
": " << fourcc <<
1752 " (" << format_desc.description <<
")";
1753 if (format_desc.flags & V4L2_FMT_FLAG_COMPRESSED) cout <<
" [Compressed]";
1754 cout << endl <<
" |- Colorspace: " << colorspace_to_string(cs) << endl;
1760 memset(&format, 0,
sizeof(format));
1761 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1762 if (v4l2_ioctl(_dev, VIDIOC_G_FMT, &format))
throw Exception(
"V4L2Cam: Format query failed");
1763 fourcc[0] =
static_cast<char>(format.fmt.pix.pixelformat & 0xFF);
1764 fourcc[1] =
static_cast<char>((format.fmt.pix.pixelformat >> 8) & 0xFF);
1765 fourcc[2] =
static_cast<char>((format.fmt.pix.pixelformat >> 16) & 0xFF);
1766 fourcc[3] =
static_cast<char>((format.fmt.pix.pixelformat >> 24) & 0xFF);
1768 cout <<
" Current Format:" << endl <<
1769 " " << format.fmt.pix.width <<
"x" << format.fmt.pix.height <<
1770 " (" << fourcc <<
")" << endl <<
1771 " " << format.fmt.pix.bytesperline <<
" bytes per line" << endl <<
1772 " Total size: " << format.fmt.pix.sizeimage << endl;
1775 cout <<
"Controls:" << endl;
1776 v4l2_queryctrl queryctrl;
1777 v4l2_querymenu querymenu;
1779 memset(&queryctrl, 0,
sizeof(queryctrl));
1781 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1;
1784 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
1786 if (errno == EINVAL)
continue;
1788 cout <<
"Control query failed" << endl;
1791 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
continue;
1793 cout <<
" + " << queryctrl.name <<
" [" <<
1794 (queryctrl.id - V4L2_CID_BASE) <<
"] (";
1795 switch (queryctrl.type)
1797 case V4L2_CTRL_TYPE_INTEGER:
1798 cout <<
"int [" << queryctrl.minimum <<
"-" << queryctrl.maximum <<
1799 " /" << queryctrl.step <<
" def " << queryctrl.default_value <<
1803 case V4L2_CTRL_TYPE_MENU:
1804 cout <<
"menu [def " << queryctrl.default_value <<
"]";
1807 case V4L2_CTRL_TYPE_BOOLEAN:
1808 cout <<
"bool [def " << queryctrl.default_value <<
"]";
1811 case V4L2_CTRL_TYPE_BUTTON:
1815 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1816 case V4L2_CTRL_TYPE_INTEGER64:
1820 case V4L2_CTRL_TYPE_CTRL_CLASS:
1821 cout <<
"ctrl_class";
1824 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1825 case V4L2_CTRL_TYPE_STRING:
1829 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)
1830 case V4L2_CTRL_TYPE_BITMASK:
1835 cout <<
")" << endl;
1837 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
1839 cout <<
" |- Menu items:" << endl;
1841 memset(&querymenu, 0,
sizeof(querymenu));
1842 querymenu.id = queryctrl.id;
1844 for (querymenu.index = queryctrl.minimum;
1845 querymenu.index <= static_cast<unsigned long int>(queryctrl.maximum);
1848 if (v4l2_ioctl(_dev, VIDIOC_QUERYMENU, &querymenu))
1850 cout <<
"Getting menu items failed" << endl;
1853 cout <<
" | + " << querymenu.name << endl;
1857 if (queryctrl.id == V4L2_CID_BASE) cout <<
"None" << endl;
1861 cout <<
"Private Controls:" << endl;
1862 for (queryctrl.id = V4L2_CID_PRIVATE_BASE; ; queryctrl.id++)
1864 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl))
1866 if (errno == EINVAL)
break;
1868 cout <<
"Private Control query failed" << endl;
1872 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
continue;
1874 cout <<
" + " << queryctrl.name <<
" [" <<
1875 (queryctrl.id - V4L2_CID_PRIVATE_BASE) <<
"] (";
1876 switch (queryctrl.type)
1878 case V4L2_CTRL_TYPE_INTEGER:
1879 cout <<
"int [" << queryctrl.minimum <<
"-" << queryctrl.maximum <<
1880 " /" << queryctrl.step <<
" def " << queryctrl.default_value <<
1884 case V4L2_CTRL_TYPE_MENU:
1885 cout <<
"menu [def " << queryctrl.default_value <<
"]";
1888 case V4L2_CTRL_TYPE_BOOLEAN:
1889 cout <<
"bool [def " << queryctrl.default_value <<
"]";
1892 case V4L2_CTRL_TYPE_BUTTON:
1896 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
1897 case V4L2_CTRL_TYPE_INTEGER64:
1901 case V4L2_CTRL_TYPE_CTRL_CLASS:
1902 cout <<
"ctrl_class";
1905 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
1906 case V4L2_CTRL_TYPE_STRING:
1910 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)
1911 case V4L2_CTRL_TYPE_BITMASK:
1916 cout <<
")" << endl;
1918 if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
1920 cout <<
" |- Menu items:" << endl;
1922 memset(&querymenu, 0,
sizeof(querymenu));
1923 querymenu.id = queryctrl.id;
1925 for (querymenu.index = queryctrl.minimum;
1926 querymenu.index <= static_cast<unsigned long int>(queryctrl.maximum);
1929 if (v4l2_ioctl(_dev, VIDIOC_QUERYMENU, &querymenu))
1931 cout <<
"Getting menu items failed" << endl;
1934 cout <<
" | + " << querymenu.name << endl;
1938 if (queryctrl.id == V4L2_CID_PRIVATE_BASE) cout <<
"None" << endl;
1941 "=========================================================================="