24 #include <core/exception.h>
25 #include <core/exceptions/software.h>
26 #include <fvcams/v4l2.h>
27 #include <fvutils/system/camargp.h>
28 #include <linux/version.h>
29 #include <logging/liblogger.h>
30 #include <sys/ioctl.h>
51 # define v4l2_fd_open(fd, flags) (fd)
52 # define v4l2_close ::close
54 # define v4l2_ioctl ioctl
55 # define v4l2_read read
56 # define v4l2_mmap mmap
57 # define v4l2_munmap munmap
60 namespace firevision {
85 _opened = _started =
false;
86 _nao_hacks = _switch_u_v =
false;
87 _width = _height = _bytes_per_line = _fps = _buffers_length = 0;
91 _brightness.set = _contrast.set = _saturation.set = _hue.set = _red_balance.set =
92 _blue_balance.set = _exposure.set = _gain.set = _lens_x.set = _lens_y.set =
false;
93 _awb = _agc = _h_flip = _v_flip = NOT_SET;
94 _exposure_auto_priority = NOT_SET;
95 _exposure_auto.set =
false;
96 _white_balance_temperature.set =
false;
97 _exposure_absolute.set =
false;
98 _white_balance_temperature.set =
false;
99 _sharpness.set =
false;
101 memset(_format, 0, 5);
102 _frame_buffers = NULL;
103 _capture_time = NULL;
105 _data =
new V4L2CameraData();
143 _opened = _started =
false;
145 _width = _height = _bytes_per_line = _buffers_length = 0;
146 _current_buffer = -1;
147 _frame_buffers = NULL;
148 _capture_time = NULL;
151 _data =
new V4L2CameraData();
153 if (cap->
has(
"device"))
158 if (cap->
has(
"nao")) {
162 if (cap->
has(
"read_method")) {
163 string rm = cap->
get(
"read_method");
164 if (rm.compare(
"READ") == 0)
166 else if (rm.compare(
"MMAP") == 0)
168 else if (rm.compare(
"UPTR") == 0)
171 throw Exception(
"V4L2Cam: Invalid read method");
176 if (cap->
has(
"format")) {
177 string fmt = cap->
get(
"format");
178 if (fmt.length() != 4)
179 throw Exception(
"V4L2Cam: Invalid format fourcc");
180 strncpy(_format, fmt.c_str(), 4);
183 memset(_format, 0, 5);
186 if (cap->
has(
"standard")) {
187 _standard = strdup(cap->
get(
"standard").c_str());
190 if (cap->
has(
"input")) {
191 _input = strdup(cap->
get(
"input").c_str());
194 if (cap->
has(
"size")) {
195 string size = cap->
get(
"size");
196 string::size_type pos;
197 if ((pos =
size.find(
'x')) == string::npos)
198 throw Exception(
"V4L2Cam: invalid image size string");
199 if (pos == (
size.length() - 1))
200 throw Exception(
"V4L2Cam: invalid image size string");
202 unsigned int mult = 1;
203 for (string::size_type i = pos - 1; i != string::npos; --i) {
204 _width += (
size.at(i) -
'0') * mult;
209 for (string::size_type i =
size.length() - 1; i > pos; --i) {
210 _height += (
size.at(i) -
'0') * mult;
215 if (cap->
has(
"switch_u_v")) {
216 _switch_u_v = (cap->
get(
"switch_u_v").compare(
"true") == 0);
221 if (cap->
has(
"fps")) {
222 if ((_fps = atoi(cap->
get(
"fps").c_str())) == 0)
223 throw Exception(
"V4L2Cam: invalid fps string");
228 if (cap->
has(
"awb")) {
229 _awb = (cap->
get(
"awb").compare(
"true") == 0 ? TRUE : FALSE);
234 if (cap->
has(
"agc")) {
235 _agc = (cap->
get(
"agc").compare(
"true") == 0 ? TRUE : FALSE);
240 if (cap->
has(
"h_flip")) {
241 _h_flip = (cap->
get(
"h_flip").compare(
"true") == 0 ? TRUE : FALSE);
246 if (cap->
has(
"v_flip")) {
247 _v_flip = (cap->
get(
"v_flip").compare(
"true") == 0 ? TRUE : FALSE);
252 if (cap->
has(
"brightness")) {
253 _brightness.set =
true;
254 _brightness.value = atoi(cap->
get(
"brightness").c_str());
256 _brightness.set =
false;
259 if (cap->
has(
"contrast")) {
260 _contrast.set =
true;
261 _contrast.value = atoi(cap->
get(
"contrast").c_str());
263 _contrast.set =
false;
266 if (cap->
has(
"saturation")) {
267 _saturation.set =
true;
268 _saturation.value = atoi(cap->
get(
"saturation").c_str());
270 _saturation.set =
false;
273 if (cap->
has(
"hue")) {
275 _hue.value = atoi(cap->
get(
"hue").c_str());
280 if (cap->
has(
"red_balance")) {
281 _red_balance.set =
true;
282 _red_balance.value = atoi(cap->
get(
"red_balance").c_str());
284 _red_balance.set =
false;
287 if (cap->
has(
"blue_balance")) {
288 _blue_balance.set =
true;
289 _blue_balance.value = atoi(cap->
get(
"blue_balance").c_str());
291 _blue_balance.set =
false;
294 if (cap->
has(
"exposure")) {
295 _exposure.set =
true;
296 _exposure.value = atoi(cap->
get(
"exposure").c_str());
298 _exposure.set =
false;
301 if (cap->
has(
"gain")) {
303 _gain.value = atoi(cap->
get(
"gain").c_str());
308 if (cap->
has(
"lens_x")) {
310 _lens_x.value = atoi(cap->
get(
"lens_x").c_str());
315 if (cap->
has(
"lens_y")) {
317 _lens_y.value = atoi(cap->
get(
"lens_y").c_str());
322 if (cap->
has(
"exposure_auto_priority")) {
323 _exposure_auto_priority =
324 (cap->
get(
"exposure_auto_priority").compare(
"true") == 0 ? TRUE : FALSE);
326 _exposure_auto_priority = NOT_SET;
329 if (cap->
has(
"exposure_auto")) {
330 _exposure_auto.set =
true;
331 _exposure_auto.value = atoi(cap->
get(
"exposure_auto").c_str());
333 _exposure_auto.set =
false;
336 if (cap->
has(
"exposure_absolute")) {
337 _exposure_absolute.set =
true;
338 _exposure_absolute.value = atoi(cap->
get(
"exposure_absolute").c_str());
340 _exposure_absolute.set =
false;
343 if (cap->
has(
"white_balance_temperature")) {
344 _white_balance_temperature.set =
true;
345 _white_balance_temperature.value = atoi(cap->
get(
"white_balance_temperature").c_str());
347 _white_balance_temperature.set =
false;
350 if (cap->
has(
"sharpness")) {
351 _sharpness.set =
true;
352 _sharpness.value = atoi(cap->
get(
"sharpness").c_str());
354 _sharpness.set =
false;
368 _nao_hacks = _switch_u_v =
false;
369 _width = _height = _bytes_per_line = _buffers_length = _fps = 0;
370 _current_buffer = -1;
371 _brightness.set = _contrast.set = _saturation.set = _hue.set = _red_balance.set =
372 _blue_balance.set = _exposure.set = _gain.set = _lens_x.set = _lens_y.set =
false;
373 _awb = _agc = _h_flip = _v_flip = NOT_SET;
374 _exposure_auto_priority = NOT_SET;
375 _white_balance_temperature.set =
false;
376 _exposure_auto.set =
false;
377 _exposure_absolute.set =
false;
378 _sharpness.set =
false;
380 memset(_format, 0, 5);
381 _frame_buffers = NULL;
382 _capture_time = NULL;
386 _data =
new V4L2CameraData();
391 if (v4l2_ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps)) {
393 throw Exception(
"V4L2Cam: Could not get capabilities - probably not a v4l2 device");
424 int libv4l2_fd = v4l2_fd_open(_dev, 0);
425 if (libv4l2_fd != -1)
434 throw Exception(
"V4L2Cam: Could not open device");
439 if (v4l2_ioctl(_dev, VIDIOC_QUERYCAP, &_data->caps)) {
441 throw Exception(
"V4L2Cam: Could not get capabilities - probably not a v4l2 device");
453 V4L2Camera::post_open()
457 select_read_method();
473 V4L2Camera::select_read_method()
476 if (!(_data->caps.capabilities
477 & (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING))) {
479 _read_method = (_read_method == READ ? MMAP : READ);
480 if (!(_data->caps.capabilities
481 & (_read_method == READ ? V4L2_CAP_READWRITE : V4L2_CAP_STREAMING))) {
483 throw Exception(
"V4L2Cam: Neither read() nor streaming IO supported");
487 if (_read_method != READ) {
488 v4l2_requestbuffers buf;
491 if (_read_method == MMAP) {
492 _buffers_length = MMAP_NUM_BUFFERS;
493 buf.count = _buffers_length;
494 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
495 buf.memory = V4L2_MEMORY_MMAP;
496 }
else if (_read_method == UPTR) {
499 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
500 buf.memory = V4L2_MEMORY_USERPTR;
503 if (v4l2_ioctl(_dev, VIDIOC_REQBUFS, &buf)) {
505 throw Exception(
"V4L2Cam: REQBUFS query failed");
508 if (_read_method == MMAP) {
509 if (buf.count < _buffers_length) {
511 throw Exception(
"V4L2Cam: Not enough memory for the buffers");
519 switch (_read_method) {
520 case READ: LibLogger::log_debug(
"V4L2Cam",
"Using read() method");
break;
522 case MMAP: LibLogger::log_debug(
"V4L2Cam",
"Using memory mapping method");
break;
525 LibLogger::log_debug(
"V4L2Cam",
"Using user pointer method");
527 throw Exception(
"V4L2Cam: user pointer method not supported yet");
534 V4L2Camera::select_standard()
542 memset(&std, 0,
sizeof(std));
543 for (std.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMSTD, &std) == 0; std.index++) {
544 if (strcmp(_standard, (
const char *)std.name) == 0) {
551 throw Exception(
"Requested standard %s is not supported by the device", _standard);
554 v4l2_std_id current_std_id;
555 if (v4l2_ioctl(_dev, VIDIOC_G_STD, ¤t_std_id) != 0) {
556 throw Exception(
"Failed to read current standard");
558 if (std.id != current_std_id) {
560 v4l2_std_id set_std_id = std.id;
561 if (v4l2_ioctl(_dev, VIDIOC_S_STD, &set_std_id) != 0) {
562 throw Exception(errno,
"Failed to set standard %s", _standard);
569 V4L2Camera::select_input()
577 memset(&inp, 0,
sizeof(inp));
578 for (inp.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMINPUT, &inp) == 0; inp.index++) {
579 if (strcmp(_input, (
const char *)inp.name) == 0) {
586 throw Exception(
"Requested input %s is not supported by the device", _input);
590 if (v4l2_ioctl(_dev, VIDIOC_G_INPUT, ¤t_inp_ind) != 0) {
591 throw Exception(
"Failed to read current input index");
593 if ((
int)inp.index != current_inp_ind) {
595 int set_inp_ind = inp.index;
596 if (v4l2_ioctl(_dev, VIDIOC_S_INPUT, &set_inp_ind) != 0) {
597 throw Exception(errno,
"Failed to set input %s", _input);
611 V4L2Camera::select_format()
613 bool preferred_found =
false;
614 v4l2_fmtdesc format_desc;
616 char fourcc[5] =
" ";
619 if (strcmp(_format,
"") == 0) {
621 strcpy(_format,
"YU12");
625 if (strcmp(_format,
"")) {
627 memset(&format_desc, 0,
sizeof(format_desc));
628 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
629 for (format_desc.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0;
630 format_desc.index++) {
631 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
632 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
633 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
634 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
636 if (strcmp(_format, fourcc) == 0) {
637 preferred_found =
true;
643 if (!preferred_found) {
646 memset(&format_desc, 0,
sizeof(format_desc));
647 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
648 format_desc.index = 0;
649 if (v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc)) {
651 throw Exception(
"V4L2Cam: No image format found");
654 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
655 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
656 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
657 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
663 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
664 if (v4l2_ioctl(_dev, VIDIOC_G_FMT, &
format)) {
666 throw Exception(
"V4L2Cam: Format query failed");
671 format.fmt.pix.pixelformat = v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
672 format.fmt.pix.field = V4L2_FIELD_ANY;
674 format.fmt.pix.width = _width;
676 format.fmt.pix.height = _height;
678 int s_fmt_rv = v4l2_ioctl(_dev, VIDIOC_S_FMT, &
format);
679 if (s_fmt_rv != 0 && errno != EBUSY && _nao_hacks) {
684 LibLogger::log_warn(
"V4L2Cam",
685 "Format setting failed (driver sucks) - %d: %s",
688 LibLogger::log_info(
"V4L2Cam",
"Trying workaround");
691 if (v4l2_ioctl(_dev, VIDIOC_G_STD, &std)) {
693 throw Exception(
"V4L2Cam: Standard query (workaround) failed");
696 if ((_width == 320) && (_height == 240)) {
703 if (v4l2_ioctl(_dev, VIDIOC_S_STD, &std)) {
705 throw Exception(
"V4L2Cam: Standard setting (workaround) failed");
708 format.fmt.pix.width = _width;
709 format.fmt.pix.height = _height;
710 format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
711 format.fmt.pix.field = V4L2_FIELD_ANY;
713 if (v4l2_ioctl(_dev, VIDIOC_S_FMT, &
format)) {
715 throw Exception(
"V4L2Cam: Format setting (workaround) failed");
723 _format[0] =
static_cast<char>(
format.fmt.pix.pixelformat & 0xFF);
724 _format[1] =
static_cast<char>((
format.fmt.pix.pixelformat >> 8) & 0xFF);
725 _format[2] =
static_cast<char>((
format.fmt.pix.pixelformat >> 16) & 0xFF);
726 _format[3] =
static_cast<char>((
format.fmt.pix.pixelformat >> 24) & 0xFF);
728 if (!_nao_hacks || !_switch_u_v) {
729 if (strcmp(_format,
"RGB3") == 0)
731 else if (strcmp(_format,
"Y41P") == 0)
732 _colorspace = YUV411_PACKED;
733 else if (strcmp(_format,
"411P") == 0)
734 _colorspace = YUV411_PLANAR;
735 else if (strcmp(_format,
"YUYV") == 0)
737 else if (strcmp(_format,
"BGR3") == 0)
739 else if (strcmp(_format,
"UYVY") == 0)
740 _colorspace = YUV422_PACKED;
741 else if (strcmp(_format,
"422P") == 0)
742 _colorspace = YUV422_PLANAR;
743 else if (strcmp(_format,
"GREY") == 0)
745 else if (strcmp(_format,
"RGB4") == 0)
746 _colorspace = RGB_WITH_ALPHA;
747 else if (strcmp(_format,
"BGR4") == 0)
748 _colorspace = BGR_WITH_ALPHA;
749 else if (strcmp(_format,
"BA81") == 0)
750 _colorspace = BAYER_MOSAIC_BGGR;
751 else if (strcmp(_format,
"Y16 ") == 0)
752 _colorspace = MONO16;
753 else if (strcmp(_format,
"YU12") == 0)
754 _colorspace = YUV420_PLANAR;
756 _colorspace = CS_UNKNOWN;
760 _width =
format.fmt.pix.width;
761 _height =
format.fmt.pix.height;
764 _bytes_per_line =
format.fmt.pix.bytesperline;
767 if (_bytes_per_line == 0) {
768 LibLogger::log_warn(
"V4L2Cam",
"bytesperline is 0 (driver sucks)");
769 _bytes_per_line = colorspace_buffer_size(_colorspace, _width, _height) / _height;
772 LibLogger::log_debug(
773 "V4L2Cam",
"w%d h%d bpl%d cs%d fmt%s", _width, _height, _bytes_per_line, _colorspace, _format);
780 V4L2Camera::set_fps()
782 v4l2_streamparm param;
783 param.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
784 if (v4l2_ioctl(_dev, VIDIOC_G_PARM, ¶m)) {
786 throw Exception(
"V4L2Cam: Streaming parameter query failed");
789 if (!(param.parm.capture.capability & V4L2_CAP_TIMEPERFRAME)) {
790 LibLogger::log_warn(
"V4L2Cam",
"FPS change not supported");
794 param.parm.capture.timeperframe.numerator = 1;
795 param.parm.capture.timeperframe.denominator = _fps;
796 if (v4l2_ioctl(_dev, VIDIOC_S_PARM, ¶m)) {
798 throw Exception(
"V4L2Cam: Streaming parameter setting failed");
800 LibLogger::log_debug(
"V4L2Cam",
802 param.parm.capture.timeperframe.numerator,
803 param.parm.capture.timeperframe.denominator);
811 V4L2Camera::set_controls()
813 if (_exposure_auto_priority != NOT_SET)
815 if (_exposure_auto.set)
823 if (_h_flip != NOT_SET)
825 if (_v_flip != NOT_SET)
836 if (_red_balance.set)
838 if (_blue_balance.set)
849 if (_exposure_absolute.set)
851 if (_white_balance_temperature.set)
866 v4l2_queryctrl queryctrl;
867 v4l2_control control;
869 memset(&queryctrl, 0,
sizeof(queryctrl));
872 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl)) {
873 if (errno == EINVAL) {
874 LibLogger::log_error(
"V4L2Cam",
"Control %s not supported", ctrl);
879 throw Exception(
"V4L2Cam: %s Control query failed", ctrl);
881 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
882 LibLogger::log_error(
"V4L2Cam",
"Control %s disabled", ctrl);
886 memset(&control, 0,
sizeof(control));
888 control.value = value;
890 if (v4l2_ioctl(_dev, VIDIOC_S_CTRL, &control)) {
892 throw Exception(
"V4L2Cam: %s Control setting failed", ctrl);
905 v4l2_queryctrl queryctrl;
906 v4l2_control control;
908 memset(&queryctrl, 0,
sizeof(queryctrl));
911 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl)) {
912 if (errno == EINVAL) {
913 LibLogger::log_error(
"V4L2Cam",
"Control %s not supported", ctrl);
918 throw Exception(
"V4L2Cam: %s Control query failed", ctrl);
920 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
921 LibLogger::log_error(
"V4L2Cam",
"Control %s disabled", ctrl);
925 memset(&control, 0,
sizeof(control));
928 if (v4l2_ioctl(_dev, VIDIOC_G_CTRL, &control)) {
930 throw Exception(
"V4L2Cam: %s Control value reading failed", ctrl);
933 return control.value;
946 V4L2Camera::create_buffer()
948 _frame_buffers =
new FrameBuffer[_buffers_length];
950 switch (_read_method) {
952 _frame_buffers[0].size = _bytes_per_line * _height;
953 _frame_buffers[0].buffer =
static_cast<unsigned char *
>(malloc(_frame_buffers[0].
size));
954 if (_frame_buffers[0].
buffer == NULL) {
956 throw Exception(
"V4L2Cam: Out of memory");
962 for (
unsigned int i = 0; i < _buffers_length; ++i) {
967 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
968 buffer.memory = V4L2_MEMORY_MMAP;
971 if (v4l2_ioctl(_dev, VIDIOC_QUERYBUF, &
buffer)) {
973 throw Exception(
"V4L2Cam: Buffer query failed");
976 _frame_buffers[i].size =
buffer.length;
977 _frame_buffers[i].buffer =
static_cast<unsigned char *
>(
978 v4l2_mmap(NULL,
buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, _dev,
buffer.m.offset));
979 if (_frame_buffers[i].
buffer == MAP_FAILED) {
981 throw Exception(
"V4L2Cam: Memory mapping failed");
998 V4L2Camera::reset_cropping()
1000 v4l2_cropcap cropcap;
1003 memset(&cropcap, 0,
sizeof(cropcap));
1004 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1006 if (v4l2_ioctl(_dev, VIDIOC_CROPCAP, &cropcap)) {
1007 if (errno == ENOTTY) {
1011 LibLogger::log_warn(
"V4L2Cam",
1012 "cropcap query failed (driver sucks) - %d: %s",
1017 memset(&crop, 0,
sizeof(crop));
1018 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019 crop.c = cropcap.defrect;
1022 if (v4l2_ioctl(_dev, VIDIOC_S_CROP, &crop) && errno != EINVAL) {
1023 LibLogger::log_warn(
"V4L2Cam",
1024 "cropping query failed (driver sucks) - %d: %s",
1038 if (_frame_buffers) {
1039 switch (_read_method) {
1041 free(_frame_buffers[0].
buffer);
1046 for (
unsigned int i = 0; i < _buffers_length; ++i) {
1047 v4l2_munmap(_frame_buffers[i].
buffer, _frame_buffers[i].
size);
1056 delete[] _frame_buffers;
1057 _frame_buffers = NULL;
1058 _current_buffer = -1;
1067 if (_capture_time) {
1068 delete _capture_time;
1077 throw Exception(
"VL42Cam: Camera not opened");
1082 switch (_read_method) {
1089 for (
unsigned int i = 0; i < _buffers_length; ++i) {
1092 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1093 buffer.memory = V4L2_MEMORY_MMAP;
1096 if (v4l2_ioctl(_dev, VIDIOC_QBUF, &
buffer)) {
1098 throw Exception(
"V4L2Cam: Enqueuing buffer failed");
1103 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1104 if (v4l2_ioctl(_dev, VIDIOC_STREAMON, &type)) {
1106 throw Exception(
"V4L2Cam: Starting stream failed");
1128 switch (_read_method) {
1136 int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1137 if (v4l2_ioctl(_dev, VIDIOC_STREAMOFF, &type)) {
1138 throw Exception(
"V4L2Cam: Stopping stream failed");
1144 _current_buffer = -1;
1167 switch (_read_method) {
1169 _current_buffer = 0;
1171 _frame_buffers[_current_buffer].
buffer,
1172 _frame_buffers[_current_buffer].
size)
1174 LibLogger::log_warn(
"V4L2Cam",
"read() failed with code %d: %s", errno, strerror(errno));
1178 if (_capture_time) {
1179 _capture_time->
stamp();
1191 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1192 buffer.memory = V4L2_MEMORY_MMAP;
1194 if (v4l2_ioctl(_dev, VIDIOC_DQBUF, &
buffer)) {
1196 throw Exception(
"V4L2Cam: Dequeuing buffer failed");
1199 _current_buffer =
buffer.index;
1201 if (_capture_time) {
1220 return (_current_buffer == -1 ? NULL : _frame_buffers[_current_buffer].
buffer);
1228 return (_opened && (_current_buffer != -1) ? _frame_buffers[_current_buffer].
size : 0);
1239 switch (_read_method) {
1248 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1249 buffer.memory = V4L2_MEMORY_MMAP;
1250 buffer.index = _current_buffer;
1253 if (v4l2_ioctl(_dev, VIDIOC_QBUF, &
buffer)) {
1254 int errno_save = errno;
1256 throw Exception(errno_save,
"V4L2Cam: Enqueuing buffer failed");
1266 _current_buffer = -1;
1299 return _capture_time;
1319 return get_one_control(
"exposure_auto_priority", V4L2_CID_EXPOSURE_AUTO_PRIORITY);
1329 LibLogger::log_debug(
"V4L2Cam",
1330 (enabled ?
"enabling exposure_auto_priority"
1331 :
"disabling exposure_auto_priority"));
1332 set_one_control(
"AGC", V4L2_CID_EXPOSURE_AUTO_PRIORITY, (enabled ? 1 : 0));
1342 return get_one_control(
"white_balance_temperature", V4L2_CID_WHITE_BALANCE_TEMPERATURE);
1352 LibLogger::log_debug(
"V4L2Cam",
1353 "setting white_balance_temperature to %d",
1356 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
1367 return get_one_control(
"exposure_absolute", V4L2_CID_EXPOSURE_ABSOLUTE);
1377 LibLogger::log_debug(
"V4L2Cam",
"setting exposure_absolute to %d",
exposure_absolute);
1398 LibLogger::log_debug(
"V4L2Cam",
"setting sharpness to %d",
sharpness);
1411 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling AGC" :
"disabling AGC"));
1424 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling AWB" :
"disabling AWB"));
1425 set_one_control(
"AWB", V4L2_CID_AUTO_WHITE_BALANCE, (enabled ? 1 : 0));
1437 LibLogger::log_debug(
"V4L2Cam",
"setting exposure_auto to %d",
exposure_auto);
1450 LibLogger::log_debug(
"V4L2Cam",
"Setting red balance to %d",
red_balance);
1463 LibLogger::log_debug(
"V4L2Cam",
"Setting blue balance to %d",
blue_balance);
1500 LibLogger::log_debug(
"V4L2Cam",
"Setting brighness to %d",
brightness);
1513 LibLogger::log_debug(
"V4L2Cam",
"Setting contrast to %d",
contrast);
1526 LibLogger::log_debug(
"V4L2Cam",
"Setting saturation to %d",
saturation);
1539 LibLogger::log_debug(
"V4L2Cam",
"Setting hue to %d",
hue);
1552 LibLogger::log_debug(
"V4L2Cam",
"Setting exposure to %d",
exposure);
1565 LibLogger::log_debug(
"V4L2Cam",
"Setting gain to %u",
gain);
1578 strncpy(_format,
format, 4);
1618 LibLogger::log_debug(
"V4L2Cam",
1619 (enabled ?
"enabling horizontal flip" :
"disabling horizontal flip"));
1626 LibLogger::log_debug(
"V4L2Cam", (enabled ?
"enabling vertical flip" :
"disabling vertical flip"));
1641 V4L2Camera::set_fps(
unsigned int fps)
1662 LibLogger::log_debug(
"V4L2Cam",
"Setting horizontal lens correction to %d", x_corr);
1669 LibLogger::log_debug(
"V4L2Cam",
"Setting vertical lens correction to %d", y_corr);
1677 cout <<
"==========================================================================" << endl
1678 <<
_device_name <<
" (" << _data->caps.card <<
") - " << _data->caps.bus_info << endl
1679 <<
"Driver: " << _data->caps.driver <<
" (ver " << ((_data->caps.version >> 16) & 0xFF)
1680 <<
"." << ((_data->caps.version >> 8) & 0xFF) <<
"." << (_data->caps.version & 0xFF) <<
")"
1682 <<
"--------------------------------------------------------------------------" << endl;
1685 cout <<
"Capabilities:" << endl;
1686 if (_data->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)
1687 cout <<
" + Video capture interface supported" << endl;
1688 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OUTPUT)
1689 cout <<
" + Video output interface supported" << endl;
1690 if (_data->caps.capabilities & V4L2_CAP_VIDEO_OVERLAY)
1691 cout <<
" + Video overlay interface supported" << endl;
1692 if (_data->caps.capabilities & V4L2_CAP_VBI_CAPTURE)
1693 cout <<
" + Raw VBI capture interface supported" << endl;
1694 if (_data->caps.capabilities & V4L2_CAP_VBI_OUTPUT)
1695 cout <<
" + Raw VBI output interface supported" << endl;
1696 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE)
1697 cout <<
" + Sliced VBI capture interface supported" << endl;
1698 if (_data->caps.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
1699 cout <<
" + Sliced VBI output interface supported" << endl;
1700 if (_data->caps.capabilities & V4L2_CAP_RDS_CAPTURE)
1701 cout <<
" + RDS_CAPTURE set" << endl;
1705 if (_data->caps.capabilities & V4L2_CAP_TUNER)
1706 cout <<
" + Has some sort of tuner" << endl;
1707 if (_data->caps.capabilities & V4L2_CAP_AUDIO)
1708 cout <<
" + Has audio inputs or outputs" << endl;
1709 if (_data->caps.capabilities & V4L2_CAP_RADIO)
1710 cout <<
" + Has a radio receiver" << endl;
1711 if (_data->caps.capabilities & V4L2_CAP_READWRITE)
1712 cout <<
" + read() and write() IO supported" << endl;
1713 if (_data->caps.capabilities & V4L2_CAP_ASYNCIO)
1714 cout <<
" + asynchronous IO supported" << endl;
1715 if (_data->caps.capabilities & V4L2_CAP_STREAMING)
1716 cout <<
" + streaming IO supported" << endl;
1717 if (_data->caps.capabilities & V4L2_CAP_TIMEPERFRAME)
1718 cout <<
" + timeperframe field is supported" << endl;
1722 cout <<
"Inputs:" << endl;
1724 memset(&input, 0,
sizeof(input));
1726 for (input.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMINPUT, &input) == 0; input.index++) {
1727 cout <<
"Input " << input.index <<
": " << input.name << endl;
1729 cout <<
" |- Type: ";
1730 switch (input.type) {
1731 case V4L2_INPUT_TYPE_TUNER: cout <<
"Tuner";
break;
1733 case V4L2_INPUT_TYPE_CAMERA: cout <<
"Camera";
break;
1735 default: cout <<
"Unknown";
1739 cout <<
" |- Supported standards:";
1740 if (input.std == 0) {
1741 cout <<
" Unknown" << endl;
1745 v4l2_standard standard;
1746 memset(&standard, 0,
sizeof(standard));
1749 for (standard.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++) {
1750 if (standard.id & input.std)
1751 cout <<
" + " << standard.name << endl;
1755 if (input.index == 0)
1756 cout <<
"None" << endl;
1760 cout <<
"Outputs:" << endl;
1762 memset(&output, 0,
sizeof(output));
1764 for (output.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMOUTPUT, &output) == 0; output.index++) {
1765 cout <<
" + Output " << output.index <<
": " << output.name << endl;
1767 cout <<
" |- Type: ";
1768 switch (output.type) {
1769 case V4L2_OUTPUT_TYPE_MODULATOR: cout <<
"TV Modulator";
break;
1771 case V4L2_OUTPUT_TYPE_ANALOG: cout <<
"Analog output";
break;
1773 default: cout <<
"Unknown";
1777 cout <<
" |- Supported standards:";
1778 if (output.std == 0) {
1779 cout <<
" Unknown" << endl;
1783 v4l2_standard standard;
1784 memset(&standard, 0,
sizeof(standard));
1787 for (standard.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUMSTD, &standard) == 0; standard.index++) {
1788 if (standard.id & output.std)
1789 cout <<
" + " << standard.name << endl;
1793 if (output.index == 0)
1794 cout <<
"None" << endl;
1798 cout <<
"Formats:" << endl;
1799 v4l2_fmtdesc format_desc;
1800 memset(&format_desc, 0,
sizeof(format_desc));
1801 format_desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1803 char fourcc[5] =
" ";
1804 for (format_desc.index = 0; v4l2_ioctl(_dev, VIDIOC_ENUM_FMT, &format_desc) == 0;
1805 format_desc.index++) {
1806 fourcc[0] =
static_cast<char>(format_desc.pixelformat & 0xFF);
1807 fourcc[1] =
static_cast<char>((format_desc.pixelformat >> 8) & 0xFF);
1808 fourcc[2] =
static_cast<char>((format_desc.pixelformat >> 16) & 0xFF);
1809 fourcc[3] =
static_cast<char>((format_desc.pixelformat >> 24) & 0xFF);
1811 colorspace_t cs = CS_UNKNOWN;
1812 if (strcmp(fourcc,
"RGB3") == 0)
1814 else if (strcmp(fourcc,
"Y41P") == 0)
1816 else if (strcmp(fourcc,
"411P") == 0)
1818 else if (strcmp(fourcc,
"YUYV") == 0)
1820 else if (strcmp(fourcc,
"BGR3") == 0)
1822 else if (strcmp(fourcc,
"UYVY") == 0)
1824 else if (strcmp(fourcc,
"422P") == 0)
1826 else if (strcmp(fourcc,
"GREY") == 0)
1828 else if (strcmp(fourcc,
"RGB4") == 0)
1829 cs = RGB_WITH_ALPHA;
1830 else if (strcmp(fourcc,
"BGR4") == 0)
1831 cs = BGR_WITH_ALPHA;
1832 else if (strcmp(fourcc,
"BA81") == 0)
1833 cs = BAYER_MOSAIC_BGGR;
1834 else if (strcmp(fourcc,
"Y16 ") == 0)
1837 cout <<
" + Format " << format_desc.index <<
": " << fourcc <<
" (" << format_desc.description
1839 if (format_desc.flags & V4L2_FMT_FLAG_COMPRESSED)
1840 cout <<
" [Compressed]";
1841 cout << endl <<
" |- Colorspace: " << colorspace_to_string(cs) << endl;
1848 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1849 if (v4l2_ioctl(_dev, VIDIOC_G_FMT, &
format))
1850 throw Exception(
"V4L2Cam: Format query failed");
1851 fourcc[0] =
static_cast<char>(
format.fmt.pix.pixelformat & 0xFF);
1852 fourcc[1] =
static_cast<char>((
format.fmt.pix.pixelformat >> 8) & 0xFF);
1853 fourcc[2] =
static_cast<char>((
format.fmt.pix.pixelformat >> 16) & 0xFF);
1854 fourcc[3] =
static_cast<char>((
format.fmt.pix.pixelformat >> 24) & 0xFF);
1856 cout <<
" Current Format:" << endl
1857 <<
" " <<
format.fmt.pix.width <<
"x" <<
format.fmt.pix.height <<
" (" << fourcc <<
")"
1859 <<
" " <<
format.fmt.pix.bytesperline <<
" bytes per line" << endl
1860 <<
" Total size: " <<
format.fmt.pix.sizeimage << endl;
1863 cout <<
"Controls:" << endl;
1864 v4l2_queryctrl queryctrl;
1865 v4l2_querymenu querymenu;
1867 memset(&queryctrl, 0,
sizeof(queryctrl));
1869 for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++) {
1870 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl)) {
1871 if (errno == EINVAL)
1874 cout <<
"Control query failed" << endl;
1877 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
1880 cout <<
" + " << queryctrl.name <<
" [" << (queryctrl.id - V4L2_CID_BASE) <<
"] (";
1881 switch (queryctrl.type) {
1882 case V4L2_CTRL_TYPE_INTEGER:
1883 cout <<
"int [" << queryctrl.minimum <<
"-" << queryctrl.maximum <<
" /" << queryctrl.step
1884 <<
" def " << queryctrl.default_value <<
"]";
1887 case V4L2_CTRL_TYPE_MENU: cout <<
"menu [def " << queryctrl.default_value <<
"]";
break;
1889 case V4L2_CTRL_TYPE_BOOLEAN: cout <<
"bool [def " << queryctrl.default_value <<
"]";
break;
1891 case V4L2_CTRL_TYPE_BUTTON: cout <<
"button";
break;
1893 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1894 case V4L2_CTRL_TYPE_INTEGER64: cout <<
"int64";
break;
1896 case V4L2_CTRL_TYPE_CTRL_CLASS: cout <<
"ctrl_class";
break;
1898 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1899 case V4L2_CTRL_TYPE_STRING: cout <<
"string";
break;
1901 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 41)
1902 case V4L2_CTRL_TYPE_BITMASK: cout <<
"bitmask";
break;
1905 cout <<
")" << endl;
1907 if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
1908 cout <<
" |- Menu items:" << endl;
1910 memset(&querymenu, 0,
sizeof(querymenu));
1911 querymenu.id = queryctrl.id;
1913 for (querymenu.index = queryctrl.minimum;
1914 querymenu.index <=
static_cast<unsigned long int>(queryctrl.maximum);
1915 querymenu.index++) {
1916 if (v4l2_ioctl(_dev, VIDIOC_QUERYMENU, &querymenu)) {
1917 cout <<
"Getting menu items failed" << endl;
1920 cout <<
" | + " << querymenu.name << endl;
1924 if (queryctrl.id == V4L2_CID_BASE)
1925 cout <<
"None" << endl;
1929 cout <<
"Private Controls:" << endl;
1930 for (queryctrl.id = V4L2_CID_PRIVATE_BASE;; queryctrl.id++) {
1931 if (v4l2_ioctl(_dev, VIDIOC_QUERYCTRL, &queryctrl)) {
1932 if (errno == EINVAL)
1935 cout <<
"Private Control query failed" << endl;
1939 if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
1942 cout <<
" + " << queryctrl.name <<
" [" << (queryctrl.id - V4L2_CID_PRIVATE_BASE) <<
"] (";
1943 switch (queryctrl.type) {
1944 case V4L2_CTRL_TYPE_INTEGER:
1945 cout <<
"int [" << queryctrl.minimum <<
"-" << queryctrl.maximum <<
" /" << queryctrl.step
1946 <<
" def " << queryctrl.default_value <<
"]";
1949 case V4L2_CTRL_TYPE_MENU: cout <<
"menu [def " << queryctrl.default_value <<
"]";
break;
1951 case V4L2_CTRL_TYPE_BOOLEAN: cout <<
"bool [def " << queryctrl.default_value <<
"]";
break;
1953 case V4L2_CTRL_TYPE_BUTTON: cout <<
"button";
break;
1955 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1956 case V4L2_CTRL_TYPE_INTEGER64: cout <<
"int64";
break;
1958 case V4L2_CTRL_TYPE_CTRL_CLASS: cout <<
"ctrl_class";
break;
1960 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1961 case V4L2_CTRL_TYPE_STRING: cout <<
"string";
break;
1963 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 41)
1964 case V4L2_CTRL_TYPE_BITMASK: cout <<
"bitmask";
break;
1967 cout <<
")" << endl;
1969 if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
1970 cout <<
" |- Menu items:" << endl;
1972 memset(&querymenu, 0,
sizeof(querymenu));
1973 querymenu.id = queryctrl.id;
1975 for (querymenu.index = queryctrl.minimum;
1976 querymenu.index <=
static_cast<unsigned long int>(queryctrl.maximum);
1977 querymenu.index++) {
1978 if (v4l2_ioctl(_dev, VIDIOC_QUERYMENU, &querymenu)) {
1979 cout <<
"Getting menu items failed" << endl;
1982 cout <<
" | + " << querymenu.name << endl;
1986 if (queryctrl.id == V4L2_CID_PRIVATE_BASE)
1987 cout <<
"None" << endl;
1989 cout <<
"==========================================================================" << endl;
Base class for exceptions in Fawkes.
Expected parameter is missing.
Called method has not been implemented.
A class for handling time.
Time & stamp()
Set this time to the current time.
void set_time(const timeval *tv)
Sets the time.
bool has(std::string s) const
Check if an parameter was given.
std::string get(std::string s) const
Get the value of the given parameter.
virtual void size(unsigned int &width, unsigned int &height)
Get the current image size.
virtual void set_fps(unsigned int fps)
Set the number of frames per second the camera tries to deliver.
virtual void close()
Close camera.
virtual void set_exposure_absolute(unsigned int exposure_absolute)
set absolute exposure time (1/s)
virtual void stop()
Stop image transfer from the camera.
virtual unsigned int exposure_absolute()
Get absolute exposure time.
virtual void set_one_control(const char *ctrl, unsigned int id, int value)
Set one Camera control value.
virtual void set_contrast(unsigned int contrast)
Set new contrast.
virtual unsigned int pixel_width()
Width of image in pixels.
virtual int red_balance()
Get current red balance.
virtual unsigned int pixel_height()
Height of image in pixels.
virtual void set_exposure(unsigned int exposure)
Set new exposure.
virtual bool exposure_auto_priority()
Get exposure_auto_priority V4L2 control.
virtual void set_gain(unsigned int gain)
Set new gain.
virtual void set_red_balance(int red_balance)
Set red balance.
virtual unsigned int buffer_size()
Size of buffer.
virtual unsigned int contrast()
Get current contrast.
virtual ~V4L2Camera()
Destructor.
virtual void set_blue_balance(int blue_balance)
Set blue balance.
virtual void dispose_buffer()
Dispose current buffer.
virtual void set_image_number(unsigned int n)
Set image number to retrieve.
virtual void capture()
Capture an image.
virtual void set_size(unsigned int width, unsigned int height)
Set the image size the camera should use.
virtual void set_hue(int hue)
Set new hue.
virtual const char * format()
Get the image format the camera currently uses.
virtual unsigned int brightness()
Get current brightness.
char * _device_name
Device name.
virtual unsigned int exposure()
Get current exposure.
virtual void set_white_balance_temperature(unsigned int white_balance_temperature)
Set white balance.
virtual bool horiz_mirror()
Return whether the camera image is horizontally mirrored.
virtual colorspace_t colorspace()
Colorspace of returned image.
virtual bool ready()
Camera is ready for taking pictures.
virtual void set_brightness(unsigned int brightness)
Set new brightness.
virtual unsigned int lens_y_corr()
Get current lens y correction.
virtual unsigned int fps()
Get the number of frames per second that have been requested from the camera.
virtual void flush()
Flush image queue.
virtual unsigned char * buffer()
Get access to current image buffer.
virtual void start()
Start image transfer from the camera.
virtual void set_lens_x_corr(unsigned int x_corr)
Set lens x correction.
virtual unsigned int height()
Get the current height of the image.
virtual void set_u_balance(int u_balance)
Set u balance.
virtual unsigned int gain()
Get current gain.
virtual void print_info()
Print out camera information.
virtual void set_auto_white_balance(bool enabled)
Enable/disable auto white balance.
virtual fawkes::Time * capture_time()
Get the Time of the last successfully captured image.
virtual void set_exposure_auto(unsigned int exposure_auto)
Enable/disable auto exposure.
virtual void set_v_balance(int v_balance)
Set v balance.
virtual bool auto_gain()
Return whether auto gain is enabled.
virtual void set_format(const char *format)
Set the image format the camera should use.
virtual unsigned int exposure_auto()
Return whether auto exposure is enabled.
virtual void set_exposure_auto_priority(bool enabled)
Set exposure_auto_priority V4L2 control.
virtual unsigned int width()
Get the current width of the image.
virtual unsigned int lens_x_corr()
Get current lens x correction.
virtual void set_saturation(unsigned int saturation)
Set new saturation.
virtual unsigned int saturation()
Get current saturation.
virtual unsigned int sharpness()
Get sharpness value.
V4L2Camera(const char *device_name="/dev/video0")
Constructor.
virtual int v_balance()
Get current v balance.
virtual bool auto_white_balance()
Return whether auto white balance is enabled.
virtual int blue_balance()
Get current blue balance.
virtual void set_vert_mirror(bool enabled)
Set whether the camera should mirror images vertically.
virtual void open()
Open the camera.
virtual int get_one_control(const char *ctrl, unsigned int id)
Get one Camera control value.
virtual void set_sharpness(unsigned int sharpness)
Set sharpness.
virtual int u_balance()
Get current u balance.
virtual bool vert_mirror()
Return whether the camera image is vertically mirrored.
virtual unsigned int white_balance_temperature()
Get absolute white balance setting.
virtual void set_horiz_mirror(bool enabled)
Set whether the camera should mirror images horizontally.
virtual void set_auto_gain(bool enabled)
Enable/disable auto gain.
virtual void set_lens_y_corr(unsigned int y_corr)
Set lens y correction.
virtual int hue()
Get current hue.