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;
char * _device_name
Device name.
virtual fawkes::Time * capture_time()
Get the Time of the last successfully captured image.
virtual void set_lens_y_corr(unsigned int y_corr)
Set lens y correction.
virtual void set_brightness(unsigned int brightness)
Set new brightness.
virtual void close()
Close camera.
virtual void stop()
Stop image transfer from the camera.
virtual unsigned int lens_y_corr()
Get current lens y correction.
virtual void print_info()
Print out camera information.
virtual bool auto_gain()
Return whether auto gain is enabled.
Called method has not been implemented.
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 void set_fps(unsigned int fps)
Set the number of frames per second the camera tries to deliver.
virtual const char * format()
Get the image format the camera currently uses.
virtual void set_horiz_mirror(bool enabled)
Set whether the camera should mirror images horizontally.
virtual void set_auto_white_balance(bool enabled)
Enable/disable auto white balance.
A class for handling time.
virtual unsigned int white_balance_temperature()
Get absolute white balance setting.
virtual void set_hue(int hue)
Set new hue.
virtual colorspace_t colorspace()
Colorspace of returned image.
virtual void set_format(const char *format)
Set the image format the camera should use.
virtual int v_balance()
Get current v balance.
virtual void set_auto_gain(bool enabled)
Enable/disable auto gain.
virtual int u_balance()
Get current u balance.
virtual unsigned int brightness()
Get current brightness.
virtual void set_size(unsigned int width, unsigned int height)
Set the image size the camera should use.
virtual unsigned int buffer_size()
Size of buffer.
virtual unsigned int exposure_absolute()
Get absolute exposure time.
virtual void set_lens_x_corr(unsigned int x_corr)
Set lens x correction.
virtual int red_balance()
Get current red balance.
bool has(std::string s) const
Check if an parameter was given.
virtual unsigned int exposure_auto()
Return whether auto exposure is enabled.
V4L2Camera(const char *device_name="/dev/video0")
Constructor.
virtual unsigned int contrast()
Get current contrast.
virtual bool exposure_auto_priority()
Get exposure_auto_priority V4L2 control.
Base class for exceptions in Fawkes.
virtual unsigned int pixel_width()
Width of image in pixels.
virtual unsigned char * buffer()
Get access to current image buffer.
virtual void set_contrast(unsigned int contrast)
Set new contrast.
virtual bool ready()
Camera is ready for taking pictures.
virtual unsigned int fps()
Get the number of frames per second that have been requested from the camera.
virtual ~V4L2Camera()
Destructor.
virtual unsigned int height()
Get the current height of the image.
virtual unsigned int exposure()
Get current exposure.
virtual bool vert_mirror()
Return whether the camera image is vertically mirrored.
virtual void set_one_control(const char *ctrl, unsigned int id, int value)
Set one Camera control value.
virtual void set_exposure_auto(unsigned int exposure_auto)
Enable/disable auto exposure.
virtual int get_one_control(const char *ctrl, unsigned int id)
Get one Camera control value.
virtual void set_exposure(unsigned int exposure)
Set new exposure.
virtual void size(unsigned int &width, unsigned int &height)
Get the current image size.
virtual void set_saturation(unsigned int saturation)
Set new saturation.
virtual void set_vert_mirror(bool enabled)
Set whether the camera should mirror images vertically.
virtual void set_exposure_auto_priority(bool enabled)
Set exposure_auto_priority V4L2 control.
virtual void set_blue_balance(int blue_balance)
Set blue balance.
void set_time(const timeval *tv)
Sets the time.
virtual void open()
Open the camera.
virtual void set_red_balance(int red_balance)
Set red balance.
virtual void capture()
Capture an image.
virtual unsigned int width()
Get the current width of the image.
virtual void dispose_buffer()
Dispose current buffer.
virtual int hue()
Get current hue.
virtual unsigned int gain()
Get current gain.
Time & stamp()
Set this time to the current time.
virtual void set_gain(unsigned int gain)
Set new gain.
virtual int blue_balance()
Get current blue balance.
virtual void set_u_balance(int u_balance)
Set u balance.
virtual unsigned int sharpness()
Get sharpness value.
virtual bool auto_white_balance()
Return whether auto white balance is enabled.
virtual unsigned int saturation()
Get current saturation.
virtual void set_exposure_absolute(unsigned int exposure_absolute)
set absolute exposure time (1/s)
virtual void start()
Start image transfer from the camera.
virtual void flush()
Flush image queue.
virtual void set_image_number(unsigned int n)
Set image number to retrieve.
std::string get(std::string s) const
Get the value of the given parameter.
Expected parameter is missing.
virtual void set_v_balance(int v_balance)
Set v balance.
virtual void set_sharpness(unsigned int sharpness)
Set sharpness.
virtual unsigned int pixel_height()
Height of image in pixels.
virtual unsigned int lens_x_corr()
Get current lens x correction.