YARP
Yet Another Robot Platform
V4L_camera.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 
20 #include "V4L_camera.h"
21 #include "list.h"
22 #include "USBcameraLogComponent.h"
23 
24 #include <yarp/os/LogStream.h>
25 #include <yarp/os/Time.h>
26 #include <yarp/os/Value.h>
27 
28 #include <cstdio>
29 #include <ctime>
30 #include <opencv2/core/core.hpp>
31 #include <opencv2/imgproc/imgproc.hpp>
32 # if CV_MAJOR_VERSION >= 3
33 # include <opencv2/core/core_c.h>
34 # endif // CV_MAJOR_VERSION
35 
36 using namespace yarp::os;
37 using namespace yarp::dev;
38 
39 
40 static double getEpochTimeShift()
41 {
42  struct timeval epochtime;
43  struct timespec vsTime;
44 
45  gettimeofday(&epochtime, nullptr);
46  clock_gettime(CLOCK_MONOTONIC, &vsTime);
47 
48  double uptime = vsTime.tv_sec + vsTime.tv_nsec / 1000000000.0;
49  double epoch = epochtime.tv_sec + epochtime.tv_usec / 1000000.0;
50  return epoch - uptime;
51 }
52 
53 
54 double V4L_camera::checkDouble(yarp::os::Searchable& config, const char* key)
55 {
56  if (config.check(key)) {
57  return config.find(key).asFloat64();
58  }
59 
60  return -1.0;
61 }
62 
63 #define NOT_PRESENT -1
64 int V4L_camera::convertYARP_to_V4L(int feature)
65 {
66  switch (feature) {
68  return V4L2_CID_BRIGHTNESS;
69  case YARP_FEATURE_SHUTTER: // this maps also on exposure
71  return V4L2_CID_EXPOSURE;
73  return V4L2_CID_SHARPNESS;
74  case YARP_FEATURE_HUE:
75  return V4L2_CID_HUE;
77  return V4L2_CID_SATURATION;
78  case YARP_FEATURE_GAMMA:
79  return V4L2_CID_GAMMA;
80  case YARP_FEATURE_GAIN:
81  return V4L2_CID_GAIN;
82  case YARP_FEATURE_IRIS:
83  return V4L2_CID_IRIS_ABSOLUTE;
84 
85  // case YARP_FEATURE_WHITE_BALANCE: -> this has to e mapped on the couple V4L2_CID_BLUE_BALANCE && V4L2_CID_RED_BALANCE
86 
88  // not yet implemented //
90  // case YARP_FEATURE_FOCUS: return DC1394_FEATURE_FOCUS;
91  // case YARP_FEATURE_TEMPERATURE: return DC1394_FEATURE_TEMPERATURE;
92  // case YARP_FEATURE_TRIGGER: return DC1394_FEATURE_TRIGGER;
93  // case YARP_FEATURE_TRIGGER_DELAY: return DC1394_FEATURE_TRIGGER_DELAY;
94  // case YARP_FEATURE_FRAME_RATE: return DC1394_FEATURE_FRAME_RATE;
95  // case YARP_FEATURE_ZOOM: return DC1394_FEATURE_ZOOM;
96  // case YARP_FEATURE_PAN: return DC1394_FEATURE_PAN;
97  // case YARP_FEATURE_TILT: return DC1394_FEATURE_TILT;
98  }
99  return NOT_PRESENT;
100 }
101 
103  PeriodicThread(1.0 / DEFAULT_FRAMERATE), doCropping(false), toEpochOffset(getEpochTimeShift())
104 {
105  verbose = false;
106  param.fps = DEFAULT_FRAMERATE;
107  param.io = IO_METHOD_MMAP;
108  param.deviceId = "/dev/video0";
109  param.fd = -1;
110  param.n_buffers = 0;
111  param.buffers = nullptr;
112  param.camModel = STANDARD_UVC;
113  param.dual = false;
114 
115  param.addictionalResize = false;
116  param.resizeOffset_x = 0;
117  param.resizeOffset_y = 0;
118  param.resizeWidth = 0;
119  param.resizeHeight = 0;
120 
121  _v4lconvert_data = YARP_NULLPTR;
122  myCounter = 0;
123  timeTot = 0;
124 
125  param.user_width = DEFAULT_WIDTH;
126  param.user_height = DEFAULT_HEIGHT;
127  param.raw_image = YARP_NULLPTR;
128  param.raw_image_size = 0;
129  param.read_image = YARP_NULLPTR;
130 
131  param.src_image = YARP_NULLPTR;
132  param.src_image_size = 0;
133 
134  param.dst_image_rgb = YARP_NULLPTR;
135  param.dst_image_size_rgb = 0;
136 
137  use_exposure_absolute = false;
138  camMap["default"] = STANDARD_UVC;
139  camMap["leopard_python"] = LEOPARD_PYTHON;
140 
141  configFx = false;
142  configFy = false;
143  configPPx = false;
144  configPPy = false;
145  configRet = false;
146  configDistM = false;
147  configIntrins = false;
148  configured = false;
149 
150  // leopard debugging
151  pixel_fmt_leo = V4L2_PIX_FMT_SGRBG8;
152  bit_shift = 2; // after firmware update, the shift has to be 2 instead of 4
153  bit_bayer = 8;
154 }
155 
157 {
158  return timeStamp;
159 }
160 
161 int V4L_camera::convertV4L_to_YARP_format(int format)
162 {
163  switch (format) {
164  case V4L2_PIX_FMT_GREY:
165  return VOCAB_PIXEL_MONO;
166  case V4L2_PIX_FMT_Y16:
167  return VOCAB_PIXEL_MONO16;
168  case V4L2_PIX_FMT_RGB24:
169  return VOCAB_PIXEL_RGB;
170 // case V4L2_PIX_FMT_ABGR32 : return VOCAB_PIXEL_BGRA; //unsupported by linux travis configuration
171  case V4L2_PIX_FMT_BGR24:
172  return VOCAB_PIXEL_BGR;
173  case V4L2_PIX_FMT_SGRBG8:
175  case V4L2_PIX_FMT_SBGGR8:
177  case V4L2_PIX_FMT_SBGGR16:
179  case V4L2_PIX_FMT_SGBRG8:
181  case V4L2_PIX_FMT_SRGGB8:
183  case V4L2_PIX_FMT_YUV420:
184  return VOCAB_PIXEL_YUV_420;
185  case V4L2_PIX_FMT_YUV444:
186  return VOCAB_PIXEL_YUV_444;
187  case V4L2_PIX_FMT_YYUV:
188  return VOCAB_PIXEL_YUV_422;
189  case V4L2_PIX_FMT_YUV411P:
190  return VOCAB_PIXEL_YUV_411;
191  }
192  return NOT_PRESENT;
193 }
194 
195 void V4L_camera::populateConfigurations()
196 {
197  struct v4l2_fmtdesc fmt;
198  struct v4l2_frmsizeenum frmsize;
199  struct v4l2_frmivalenum frmival;
200 
201  fmt.index = 0;
202  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
203 
204  while (ioctl(param.fd, VIDIOC_ENUM_FMT, &fmt) >= 0) {
205  memset(&frmsize, 0, sizeof(v4l2_frmsizeenum));
206  frmsize.pixel_format = fmt.pixelformat;
207  frmsize.index = 0;
208  frmsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
209  while (xioctl(param.fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) >= 0) {
210  if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
211  memset(&frmival, 0, sizeof(v4l2_frmivalenum));
212  frmival.index = 0;
213  frmival.pixel_format = fmt.pixelformat;
214  frmival.width = frmsize.discrete.width;
215  frmival.height = frmsize.discrete.height;
216  frmsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
217  while (xioctl(param.fd, VIDIOC_ENUM_FRAMEINTERVALS, &frmival) >= 0) {
218  CameraConfig c;
219  c.pixelCoding = (YarpVocabPixelTypesEnum)convertV4L_to_YARP_format(frmival.pixel_format);
220  c.width = frmival.width;
221  c.height = frmival.height;
222  c.framerate = (1.0 * frmival.discrete.denominator) / frmival.discrete.numerator;
223  param.configurations.push_back(c);
224  frmival.index++;
225  }
226  }
227  frmsize.index++;
228  }
229  fmt.index++;
230  }
231 }
232 
237 {
238  struct stat st;
239  yCTrace(USBCAMERA) << "input params are " << config.toString();
240 
241 
242  if (!fromConfig(config)) {
243  return false;
244  }
245 
246  // stat file
247  if (-1 == stat(param.deviceId.c_str(), &st)) {
248  yCError(USBCAMERA, "Cannot identify '%s': %d, %s", param.deviceId.c_str(), errno, strerror(errno));
249  return false;
250  }
251 
252  // check if it is a device
253  if (!S_ISCHR(st.st_mode)) {
254  yCError(USBCAMERA, "%s is no device", param.deviceId.c_str());
255  return false;
256  }
257 
258  // open device
259  param.fd = v4l2_open(param.deviceId.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0);
260 
261  // check if opening was successfull
262  if (-1 == param.fd) {
263  yCError(USBCAMERA, "Cannot open '%s': %d, %s", param.deviceId.c_str(), errno, strerror(errno));
264  return false;
265  }
266 
267  // if previous instance crashed, maybe will help (?)
268  captureStop();
269  deviceUninit();
270  v4l2_close(param.fd);
271 
273  // re-open device
274  param.fd = v4l2_open(param.deviceId.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0);
275 
276  // check if opening was successfull
277  if (-1 == param.fd) {
278  yCError(USBCAMERA, "Cannot open '%s': %d, %s", param.deviceId.c_str(), errno, strerror(errno));
279  return false;
280  }
281 
282 
283  // Initting video device
284  deviceInit();
285  if (verbose) {
286  enumerate_controls();
287  }
288  if (!check_V4L2_control(V4L2_CID_EXPOSURE)) {
289  use_exposure_absolute = check_V4L2_control(V4L2_CID_EXPOSURE_ABSOLUTE);
290  }
291  captureStart();
293  start();
294 
295  populateConfigurations();
296 
297  // Configure the device settings from input file
298  setFeature(YARP_FEATURE_GAIN, checkDouble(config, "gain"));
299  setFeature(YARP_FEATURE_EXPOSURE, checkDouble(config, "exposure"));
300  setFeature(YARP_FEATURE_BRIGHTNESS, checkDouble(config, "brightness"));
301  setFeature(YARP_FEATURE_SHARPNESS, checkDouble(config, "sharpness"));
302  yarp::os::Bottle& white_balance = config.findGroup("white_balance");
303  if (!white_balance.isNull()) {
304  setFeature(YARP_FEATURE_WHITE_BALANCE, white_balance.get(2).asFloat64(), white_balance.get(1).asFloat64());
305  }
306  setFeature(YARP_FEATURE_HUE, checkDouble(config, "hue"));
307  setFeature(YARP_FEATURE_SATURATION, checkDouble(config, "saturation"));
308  setFeature(YARP_FEATURE_GAMMA, checkDouble(config, "gamma"));
309  setFeature(YARP_FEATURE_SHUTTER, checkDouble(config, "shutter"));
310  setFeature(YARP_FEATURE_IRIS, checkDouble(config, "iris"));
311 
312  return true;
313 }
314 
316 {
317  return height();
318 }
319 
321 {
322  return width();
323 }
324 
326 {
327  configurations = param.configurations;
328  return true;
329 }
330 bool V4L_camera::getRgbResolution(int& width, int& height)
331 {
332  width = param.user_width;
333  height = param.user_height;
334  return true;
335 }
336 
337 bool V4L_camera::setRgbResolution(int width, int height)
338 {
339  mutex.wait();
340  captureStop();
341  deviceUninit();
342  param.user_width = width;
343  param.user_height = height;
344  bool res = deviceInit();
345  captureStart();
346  mutex.post();
347  return res;
348 }
349 
350 bool V4L_camera::getRgbFOV(double& horizontalFov, double& verticalFov)
351 {
352  horizontalFov = param.horizontalFov;
353  verticalFov = param.verticalFov;
354  return configFx && configFy;
355 }
356 
357 bool V4L_camera::setRgbFOV(double horizontalFov, double verticalFov)
358 {
359  yCError(USBCAMERA) << "cannot set fov";
360  return false;
361 }
362 
364 {
365  intrinsic = param.intrinsic;
366  return configIntrins;
367 }
368 
369 bool V4L_camera::getRgbMirroring(bool& mirror)
370 {
371 
372  mirror = (ioctl(param.fd, V4L2_CID_HFLIP) != 0);
373  return true;
374 }
375 
377 {
378  int ret = ioctl(param.fd, V4L2_CID_HFLIP, &mirror);
379  if (ret < 0) {
380  yCError(USBCAMERA) << "V4L2_CID_HFLIP - Unable to mirror image-" << strerror(errno);
381  return false;
382  }
383  return true;
384 }
385 
386 bool V4L_camera::fromConfig(yarp::os::Searchable& config)
387 {
388  if (config.check("verbose")) {
389  verbose = true;
390  }
391 
392  if (!config.check("width")) {
393  yCDebug(USBCAMERA) << "width parameter not found, using default value of " << DEFAULT_WIDTH;
394  param.user_width = DEFAULT_WIDTH;
395  } else {
396  param.user_width = config.find("width").asInt32();
397  }
398 
399  if (!config.check("height")) {
400  yCDebug(USBCAMERA) << "height parameter not found, using default value of " << DEFAULT_HEIGHT;
401  param.user_height = DEFAULT_HEIGHT;
402  } else {
403  param.user_height = config.find("height").asInt32();
404  }
405 
406  if (!config.check("framerate")) {
407  yCDebug(USBCAMERA) << "framerate parameter not found, using default value of " << DEFAULT_FRAMERATE;
408  param.fps = DEFAULT_FRAMERATE;
409  } else {
410  param.fps = config.find("framerate").asInt32();
411  }
412 
413  if (!config.check("d")) {
414  yCError(USBCAMERA) << "No camera identifier was specified! (e.g. '--d /dev/video0' on Linux OS)";
415  return false;
416  }
417 
418  param.deviceId = config.find("d").asString();
419  param.flip = config.check("flip", Value("false")).asBool();
420 
421  if (!config.check("camModel")) {
422  yCInfo(USBCAMERA) << "No 'camModel' was specified, working with 'standard' uvc";
423  param.camModel = STANDARD_UVC;
424  } else {
425  std::map<std::string, supported_cams>::iterator it = camMap.find(config.find("camModel").asString());
426  if (it != camMap.end()) {
427  param.camModel = it->second;
428  yCDebug(USBCAMERA) << "cam model name : " << config.find("camModel").asString() << " -- number : " << it->second;
429  } else {
430  yCError(USBCAMERA) << "Unknown camera model <" << config.find("camModel").asString() << ">";
431  yCInfo(USBCAMERA) << "Supported models are: ";
432  for (it = camMap.begin(); it != camMap.end(); it++) {
433  yCInfo(USBCAMERA, " <%s>", it->first.c_str());
434  }
435  return false;
436  }
437  }
438 
439  // Check for addictional leopard parameter for debugging purpose
440  if (param.camModel == LEOPARD_PYTHON) {
441  yCDebug(USBCAMERA) << "-------------------------------\nusbCamera: Using leopard camera!!";
442  bit_shift = config.check("shift", Value(bit_shift), "right shift of <n> bits").asInt32();
443  bit_bayer = config.check("bit_bayer", Value(bit_bayer), "uses <n> bits bayer conversion").asInt32();
444  switch (bit_bayer) {
445  case 8:
446  pixel_fmt_leo = V4L2_PIX_FMT_SGRBG8;
447  break;
448 
449  case 10:
450  pixel_fmt_leo = V4L2_PIX_FMT_SGRBG10;
451  break;
452 
453  case 12:
454  pixel_fmt_leo = V4L2_PIX_FMT_SGRBG12;
455  break;
456 
457  default:
458  yCError(USBCAMERA) << "bayer conversion with " << bit_bayer << "not supported";
459  return false;
460  }
461 
462  yCDebug(USBCAMERA) << "--------------------------------";
463  yCDebug(USBCAMERA) << bit_shift << "bits of right shift applied to raw data";
464  yCDebug(USBCAMERA) << "Bits used for de-bayer " << bit_bayer;
465  }
466 
467  //crop is used to pass from 16:9 to 4:3
468  if (config.check("crop")) {
469  doCropping = true;
470  yCInfo(USBCAMERA, "Cropping enabled.");
471  } else {
472  doCropping = false;
473  }
474 
475  Value isDual = config.check("dual", Value(0), "Is this a dual camera? Two cameras merged into a single frame");
476 
477  if (config.find("dual").asBool()) {
478  param.dual = true;
479  yCInfo(USBCAMERA, "Using dual input camera.");
480  } else {
481  param.dual = false;
482  }
483 
484  int type = 0;
485  if (!config.check("pixelType")) {
486  yCError(USBCAMERA) << "No 'pixelType' was specified!";
487  return false;
488  }
489  {
490  type = config.find("pixelType").asInt32();
491  }
492 
493  switch (type) {
494  case VOCAB_PIXEL_MONO:
495  // Pixel type raw is the native one from the camera
496  param.pixelType = convertV4L_to_YARP_format(param.src_fmt.fmt.pix.pixelformat);
497  break;
498 
499  case VOCAB_PIXEL_RGB:
500  // is variable param.pixelType really required??
501  param.pixelType = V4L2_PIX_FMT_RGB24;
502  break;
503 
504  default:
505  yCError(USBCAMERA, "no valid pixel format found!! This should not happen!!");
506  return false;
507  break;
508  }
509  Value* retM;
510  retM = Value::makeList("1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0");
511  configFx = config.check("horizontalFov");
512  configFy = config.check("verticalFov");
513  configPPx = config.check("principalPointX");
514  configPPy = config.check("principalPointY");
515  configRet = config.check("retificationMatrix");
516  configDistM = config.check("distortionModel");
517  Bottle bt;
518  bt = config.findGroup("cameraDistortionModelGroup");
519  if (!bt.isNull()) {
520  if (bt.find("name").isNull() || bt.find("k1").isNull()
521  || bt.find("k2").isNull() || bt.find("k3").isNull()
522  || bt.find("t1").isNull() || bt.find("t2").isNull()) {
523  yCError(USBCAMERA) << "group cameraDistortionModelGroup incomplete, "
524  "fields k1, k2, k3, t1, t2, name are required when using cameraDistortionModelGroup";
525  configIntrins = false;
526  return false;
527  }
528  {
529  configIntrins = true;
530  }
531  } else {
532  configIntrins = false;
533  }
534  param.horizontalFov = config.check("horizontalFov", Value(0.0), "desired horizontal fov of test image").asFloat64();
535  param.verticalFov = config.check("verticalFov", Value(0.0), "desired vertical fov of test image").asFloat64();
536  if (config.check("mirror")) {
537  if (!setRgbMirroring(config.check("mirror",
538  Value(0),
539  "mirroring disabled by default")
540  .asBool())) {
541  yCError(USBCAMERA, "cannot set mirroring option");
542  return false;
543  }
544  }
545 
546  param.intrinsic.put("focalLengthX", config.check("focalLengthX", Value(0.0), "Horizontal component of the focal lenght").asFloat64());
547  param.intrinsic.put("focalLengthY", config.check("focalLengthY", Value(0.0), "Vertical component of the focal lenght").asFloat64());
548  param.intrinsic.put("principalPointX", config.check("principalPointX", Value(0.0), "X coordinate of the principal point").asFloat64());
549  param.intrinsic.put("principalPointY", config.check("principalPointY", Value(0.0), "Y coordinate of the principal point").asFloat64());
550  param.intrinsic.put("retificationMatrix", config.check("retificationMatrix", *retM, "Matrix that describes the lens' distortion"));
551  param.intrinsic.put("distortionModel", config.check("distortionModel", Value(""), "Reference to group of parameters describing the distortion model of the camera").asString());
552  if (bt.isNull()) {
553  param.intrinsic.put("name", "");
554  param.intrinsic.put("k1", 0.0);
555  param.intrinsic.put("k2", 0.0);
556  param.intrinsic.put("k3", 0.0);
557  param.intrinsic.put("t1", 0.0);
558  param.intrinsic.put("t2", 0.0);
559  } else {
560  param.intrinsic.put("name", bt.check("name", Value(""), "Name of the distortion model").asString());
561  param.intrinsic.put("k1", bt.check("k1", Value(0.0), "Radial distortion coefficient of the lens").asFloat64());
562  param.intrinsic.put("k2", bt.check("k2", Value(0.0), "Radial distortion coefficient of the lens").asFloat64());
563  param.intrinsic.put("k3", bt.check("k3", Value(0.0), "Radial distortion coefficient of the lens").asFloat64());
564  param.intrinsic.put("t1", bt.check("t1", Value(0.0), "Tangential distortion of the lens").asFloat64());
565  param.intrinsic.put("t2", bt.check("t2", Value(0.0), "Tangential distortion of the lens").asFloat64());
566  }
567  delete retM;
568 
569  yCDebug(USBCAMERA) << "using following device " << param.deviceId << "with the configuration: " << param.user_width << "x" << param.user_height << "; camModel is " << param.camModel;
570  return true;
571 }
572 
573 int V4L_camera::getfd()
574 {
575  return param.fd;
576 }
577 
578 bool V4L_camera::threadInit()
579 {
581 
582  timeStart = timeNow = timeElapsed = yarp::os::Time::now();
583  frameCounter = 0;
584  return true;
585 }
586 
587 void V4L_camera::run()
588 {
589  if (full_FrameRead()) {
590  frameCounter++;
591  } else {
592  yCError(USBCAMERA) << "Failed acquiring new frame";
593  }
594 
595  timeNow = yarp::os::Time::now();
596  if ((timeElapsed = timeNow - timeStart) > 1.0f) {
597  yCInfo(USBCAMERA, "frames acquired %d in %f sec", frameCounter, timeElapsed);
598  frameCounter = 0;
599  timeStart = timeNow;
600  }
601 }
602 
603 void V4L_camera::threadRelease()
604 {
606 }
607 
608 
612 bool V4L_camera::deviceInit()
613 {
614  struct v4l2_capability cap;
615  struct v4l2_cropcap cropcap;
616  struct v4l2_crop crop;
617  struct v4l2_streamparm frameint;
618  configured = false;
619 
620  if (-1 == xioctl(param.fd, VIDIOC_QUERYCAP, &cap)) {
621  if (EINVAL == errno) {
622  yCError(USBCAMERA, "%s is no V4L2 device", param.deviceId.c_str());
623  }
624  return false;
625  }
626 
627  if (verbose) {
628  list_cap_v4l2(param.fd);
629  }
630 
631  if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
632  yCError(USBCAMERA, "%s is no video capture device", param.deviceId.c_str());
633  return false;
634  }
635 
636  yCInfo(USBCAMERA, "%s is good V4L2_CAP_VIDEO_CAPTURE", param.deviceId.c_str());
637 
638  switch (param.io) {
639  case IO_METHOD_READ:
640  if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
641  yCError(USBCAMERA, "%s does not support read i/o", param.deviceId.c_str());
642  return false;
643  }
644  break;
645 
646  case IO_METHOD_MMAP:
647  case IO_METHOD_USERPTR:
648  if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
649  yCError(USBCAMERA, "%s does not support streaming i/o", param.deviceId.c_str());
650  return false;
651  }
652  break;
653 
654  default:
655  yCError(USBCAMERA, "Unknown io method for device %s", param.deviceId.c_str());
656  return false;
657  break;
658  }
659 
660  CLEAR(cropcap);
661  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
662 
663  if (0 == xioctl(param.fd, VIDIOC_CROPCAP, &cropcap)) {
664  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
665  crop.c = cropcap.defrect; /* reset to default */
666 
667  /* Reset cropping to default if possible.
668  * Don't care about errors
669  */
670  xioctl(param.fd, VIDIOC_S_CROP, &crop);
671  }
672 
673  CLEAR(param.src_fmt);
674  CLEAR(param.dst_fmt);
675 
676  _v4lconvert_data = v4lconvert_create(param.fd);
677  if (_v4lconvert_data == nullptr) {
678  yCError(USBCAMERA) << "Failed to initialize v4lconvert. Conversion to required format may not work";
679  }
680 
681  /*
682  * dst_fmt is the image format the user require.
683  * With try_format, V4l does an handshake with the camera and the best match from
684  * the available formats provided by the camera is selected.
685  * src_fmt will contain the source format, i.e. the configuration to be sent to the
686  * camera to optimize the conversion which will be done afterwards.
687  *
688  * VERY IMPORTANT NOTE:
689  *
690  * In case no match is found for the user input provided in dst_fmt, than dst_fmt
691  * itself may be changed to provide the best conversion possible similar to user
692  * input. In particular, pixel format conversion together with rescaling may not
693  * be possible to achieve. In this case only pixel format conversion will be done
694  * and we need to take care of the rescaling.
695  */
696 
697  param.dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
698  param.dst_fmt.fmt.pix.width = param.user_width;
699  param.dst_fmt.fmt.pix.height = param.user_height;
700  param.dst_fmt.fmt.pix.field = V4L2_FIELD_NONE;
701  param.dst_fmt.fmt.pix.pixelformat = param.pixelType;
702 
703  if (v4lconvert_try_format(_v4lconvert_data, &(param.dst_fmt), &(param.src_fmt)) != 0) {
704  yCError(USBCAMERA, "v4lconvert_try_format -> Error is: %s", v4lconvert_get_error_message(_v4lconvert_data));
705  return false;
706  }
707 
708  // Check if dst_fmt has been changed by the v4lconvert_try_format
709  if (param.dst_fmt.fmt.pix.width != param.user_width ||
710  param.dst_fmt.fmt.pix.height != param.user_height ||
711  param.dst_fmt.fmt.pix.pixelformat != param.pixelType) {
712  yCWarning(USBCAMERA) << "Conversion from HW supported configuration into user requested format will require addictional step.\n"
713  << "Performance issue may arise.";
714 
715  param.addictionalResize = true;
716 
717  // Compute offsets for cropping image in case the source image and the one
718  // required by the user have different form factors, i.e 16/9 vs 4/3
719  double inputFF = (double)param.dst_fmt.fmt.pix.width / (double)param.dst_fmt.fmt.pix.height;
720  double outputFF = (double)param.user_width / (double)param.user_height;
721 
722  if (outputFF < inputFF) {
723  // Use all vertical pixels, crop lateral pixels to get the central portion of the image
724  param.resizeOffset_y = 0;
725  param.resizeHeight = param.dst_fmt.fmt.pix.height;
726 
727  if (!param.dual) {
728  param.resizeOffset_x = (param.dst_fmt.fmt.pix.width - (param.dst_fmt.fmt.pix.height * outputFF)) / 2;
729  param.resizeWidth = param.dst_fmt.fmt.pix.width - param.resizeOffset_x * 2;
730  } else {
731  param.resizeOffset_x = (param.dst_fmt.fmt.pix.width - (param.dst_fmt.fmt.pix.height * outputFF)) / 4; // "/4" is "/2" 2 times because there are 2 images
732  param.resizeWidth = param.dst_fmt.fmt.pix.width / 2 - param.resizeOffset_x * 2;
733  }
734  } else {
735  // Use all horizontal pixels, crop top/bottom pixels to get the central portion of the image
736  param.resizeOffset_x = 0;
737 
738  if (!param.dual) {
739  param.resizeWidth = param.dst_fmt.fmt.pix.width;
740  param.resizeOffset_y = (param.dst_fmt.fmt.pix.height - (param.dst_fmt.fmt.pix.width / outputFF)) / 2;
741  param.resizeHeight = param.dst_fmt.fmt.pix.height - param.resizeOffset_y * 2;
742  } else {
743  param.resizeWidth = param.dst_fmt.fmt.pix.width / 2;
744  param.resizeOffset_y = (param.dst_fmt.fmt.pix.height - (param.dst_fmt.fmt.pix.width / outputFF)) / 2;
745  param.resizeHeight = param.dst_fmt.fmt.pix.height - param.resizeOffset_y * 2;
746  }
747  }
748  } else {
749  param.addictionalResize = false;
750  param.resizeOffset_x = 0;
751  param.resizeWidth = param.user_width / 2;
752  param.resizeOffset_y = 0;
753  param.resizeHeight = param.user_height;
754  }
755 
756  if (-1 == xioctl(param.fd, VIDIOC_S_FMT, &param.src_fmt)) {
757  yCError(USBCAMERA) << "xioctl error VIDIOC_S_FMT" << strerror(errno);
758  return false;
759  }
760 
761  /* If the user has set the fps to -1, don't try to set the frame interval */
762  if (param.fps != -1) {
763  CLEAR(frameint);
764 
765  /* Attempt to set the frame interval. */
766  frameint.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
767  frameint.parm.capture.timeperframe.numerator = 1;
768  frameint.parm.capture.timeperframe.denominator = param.fps;
769  if (-1 == xioctl(param.fd, VIDIOC_S_PARM, &frameint)) {
770  yCError(USBCAMERA, "Unable to set frame interval.");
771  }
772  }
773 
774  param.src_image_size = param.src_fmt.fmt.pix.sizeimage;
775  param.src_image = new unsigned char[param.src_image_size];
776 
777  param.dst_image_size_rgb = param.dst_fmt.fmt.pix.width * param.dst_fmt.fmt.pix.height * 3;
778  param.dst_image_rgb = new unsigned char[param.dst_image_size_rgb];
779 
780  // raw image is for non-standard type only, for example leopard_python
781  if (param.camModel == LEOPARD_PYTHON) {
782  /* This camera sends bayer 10bit over 2bytes for each piece of information,
783  * therefore the total size of the image is 2 times the number of pixels.
784  */
785  param.raw_image_size = param.src_fmt.fmt.pix.width * param.src_fmt.fmt.pix.height * 2;
786  param.raw_image = new unsigned char[param.raw_image_size];
787  param.read_image = param.raw_image; // store the image read in the raw_image buffer
788  } else // This buffer should not be used for STANDARD_UVC cameras
789  {
790  param.read_image = param.src_image; // store the image read in the src_image buffer
791  param.raw_image_size = 0;
792  param.raw_image = YARP_NULLPTR;
793  }
794 
795  switch (param.io) {
796  case IO_METHOD_READ:
797  readInit(param.src_fmt.fmt.pix.sizeimage);
798  break;
799 
800  case IO_METHOD_MMAP:
801  mmapInit();
802  break;
803 
804  case IO_METHOD_USERPTR:
805  userptrInit(param.src_fmt.fmt.pix.sizeimage);
806  break;
807  }
808 
809  if (verbose) {
811  }
812  configured = true;
813 
814  return true;
815 }
816 
817 bool V4L_camera::deviceUninit()
818 {
819  unsigned int i;
820  bool ret = true;
821  configured = false;
822 
823  switch (param.io) {
824  case IO_METHOD_READ:
825  free(param.buffers[0].start);
826  break;
827 
828  case IO_METHOD_MMAP:
829  for (i = 0; i < param.n_buffers; ++i) {
830  if (-1 == v4l2_munmap(param.buffers[i].start, param.buffers[i].length)) {
831  ret = false;
832  }
833  }
834 
835  CLEAR(param.req);
836  // memset(param.req, 0, sizeof(struct v4l2_requestbuffers));
837  param.req.count = 0;
838  param.req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
839  param.req.memory = V4L2_MEMORY_MMAP;
840  if (xioctl(param.fd, VIDIOC_REQBUFS, &param.req) < 0) {
841  yCError(USBCAMERA, "VIDIOC_REQBUFS - Failed to delete buffers: %s (errno %d)", strerror(errno), errno);
842  return false;
843  }
844 
845  break;
846 
847  case IO_METHOD_USERPTR:
848  for (i = 0; i < param.n_buffers; ++i) {
849  free(param.buffers[i].start);
850  }
851  break;
852  }
853 
854  if (param.buffers != nullptr) {
855  free(param.buffers);
856  }
857 
858  if (param.raw_image != YARP_NULLPTR) {
859  delete[] param.raw_image;
860  param.raw_image = YARP_NULLPTR;
861  }
862 
863  if (param.src_image != YARP_NULLPTR) {
864  delete[] param.src_image;
865  param.src_image = YARP_NULLPTR;
866  }
867 
868  if (param.dst_image_rgb != YARP_NULLPTR) {
869  delete[] param.dst_image_rgb;
870  param.dst_image_rgb = YARP_NULLPTR;
871  }
872 
873  if (_v4lconvert_data != YARP_NULLPTR) {
874  v4lconvert_destroy(_v4lconvert_data);
875  _v4lconvert_data = YARP_NULLPTR;
876  }
877 
878  return ret;
879 }
880 
885 {
887 
888  stop(); // stop yarp thread acquiring images
889 
890  if (param.fd != -1) {
891  captureStop();
892  deviceUninit();
893 
894  if (-1 == v4l2_close(param.fd)) {
895  yCError(USBCAMERA) << "Error closing V4l2 device";
896  }
897  return false;
898  }
899  param.fd = -1;
900  return true;
901 }
902 
903 
904 // IFrameGrabberRgb Interface 777
905 bool V4L_camera::getRgbBuffer(unsigned char* buffer)
906 {
907  bool res = false;
908  mutex.wait();
909  if (configured) {
910  imagePreProcess();
911  imageProcess();
912 
913  if (!param.addictionalResize) {
914  memcpy(buffer, param.dst_image_rgb, param.dst_image_size_rgb);
915  } else {
916  memcpy(buffer, param.outMat.data, param.outMat.total() * 3);
917  }
918  mutex.post();
919  res = true;
920  } else {
921  yCError(USBCAMERA) << "unable to get the buffer, device uninitialized";
922  mutex.post();
923  res = false;
924  }
925  return res;
926 }
927 
928 // IFrameGrabber Interface
929 bool V4L_camera::getRawBuffer(unsigned char* buffer)
930 {
931  bool res = false;
932  mutex.wait();
933  if (configured) {
934  imagePreProcess();
935  memcpy(buffer, param.src_image, param.src_image_size);
936  res = true;
937  } else {
938  yCError(USBCAMERA) << "unable to get the buffer, device uninitialized";
939  res = false;
940  }
941  mutex.post();
942  return res;
943 }
944 
946 {
947  return param.src_image_size;
948 }
949 
955 {
956  /*
957  * return user setting because at the end of the day, this is what
958  * the image must look like
959  */
960  return param.user_height;
961 }
962 
967 int V4L_camera::width() const
968 {
969  /*
970  * return user setting because at the end of the day, this is what
971  * the image must look like
972  */
973  return param.user_width;
974 }
975 
984 int V4L_camera::xioctl(int fd, int request, void* argp)
985 {
986  int r;
987 
988  do {
989  r = v4l2_ioctl(fd, request, argp);
990  } while (-1 == r && EINTR == errno);
991 
992  return r;
993 }
994 
995 
997 
998 
999 struct v4l2_queryctrl queryctrl;
1000 struct v4l2_querymenu querymenu;
1001 
1002 void V4L_camera::enumerate_menu()
1003 {
1004  yCInfo(USBCAMERA, "Menu items:");
1005 
1006  memset(&querymenu, 0, sizeof(querymenu));
1007  querymenu.id = queryctrl.id;
1008 
1009  for (querymenu.index = (__u32)queryctrl.minimum; querymenu.index <= (__u32)queryctrl.maximum; querymenu.index++) {
1010  if (0 == ioctl(param.fd, VIDIOC_QUERYMENU, &querymenu)) {
1011  yCInfo(USBCAMERA, " %s", querymenu.name);
1012  } else {
1013  yCError(USBCAMERA, "VIDIOC_QUERYMENU: %d, %s", errno, strerror(errno));
1014  return;
1015  }
1016  }
1017 }
1018 
1019 
1020 bool V4L_camera::enumerate_controls()
1021 {
1022  memset(&queryctrl, 0, sizeof(queryctrl));
1023 
1024  for (queryctrl.id = V4L2_CID_BASE; queryctrl.id < V4L2_CID_LASTP1; queryctrl.id++) {
1025  if (0 == ioctl(param.fd, VIDIOC_QUERYCTRL, &queryctrl)) {
1026  if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1027  continue;
1028  }
1029 
1030  yCInfo(USBCAMERA, "Control %s (id %d)", queryctrl.name, queryctrl.id);
1031 
1032  if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
1033  enumerate_menu();
1034  }
1035  } else {
1036  if (errno == EINVAL) {
1037  continue;
1038  }
1039 
1040  yCError(USBCAMERA, "VIDIOC_QUERYCTRL: %d, %s", errno, strerror(errno));
1041  return false;
1042  }
1043  }
1044 
1045  for (queryctrl.id = V4L2_CID_PRIVATE_BASE;; queryctrl.id++) {
1046  if (0 == ioctl(param.fd, VIDIOC_QUERYCTRL, &queryctrl)) {
1047  if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1048  continue;
1049  }
1050 
1051  yCInfo(USBCAMERA, "Control %s", queryctrl.name);
1052 
1053  if (queryctrl.type == V4L2_CTRL_TYPE_MENU) {
1054  enumerate_menu();
1055  }
1056  } else {
1057  if (errno == EINVAL) {
1058  break;
1059  }
1060 
1061  yCError(USBCAMERA, "VIDIOC_QUERYCTRL: %d, %s", errno, strerror(errno));
1062  return false;
1063  }
1064  }
1065  return true;
1066 }
1067 
1071 bool V4L_camera::full_FrameRead()
1072 {
1073  bool got_it = false;
1074  void* image_ret = nullptr;
1075  unsigned int count;
1076  unsigned int numberOfTimeouts;
1077 
1078  fd_set fds;
1079  struct timeval tv;
1080  int r;
1081 
1082  numberOfTimeouts = 0;
1083  count = 10; //trials
1084 
1085 
1086  for (unsigned int i = 0; i < count; i++) {
1087  FD_ZERO(&fds);
1088  FD_SET(param.fd, &fds);
1089 
1090  /* Timeout. */
1091  tv.tv_sec = 1;
1092  tv.tv_usec = 0;
1093 
1094  r = select(param.fd + 1, &fds, nullptr, nullptr, &tv);
1095 
1096  if (r < 0) {
1097  if (EINTR == errno) {
1098  continue;
1099  }
1100 
1101  return image_ret != nullptr;
1102  }
1103  if (0 == r) {
1104  numberOfTimeouts++;
1105  {
1106  yCWarning(USBCAMERA, "timeout while reading image [%d/%d]", numberOfTimeouts, count);
1107  got_it = false;
1108  }
1109  } else if ((r > 0) && (FD_ISSET(param.fd, &fds))) {
1110  if (frameRead()) {
1111  //yCTrace(USBCAMERA, "got an image");
1112  got_it = true;
1113  break;
1114  }
1115  yCWarning(USBCAMERA, "trial %d failed", i);
1116 
1117  } else {
1118  yCWarning(USBCAMERA, "select woke up for something else");
1119  }
1120 
1121  /* EAGAIN - continue select loop. */
1122  }
1123  return got_it;
1124 }
1125 
1129 bool V4L_camera::frameRead()
1130 {
1131  unsigned int i;
1132  struct v4l2_buffer buf;
1133  mutex.wait();
1134 
1135  switch (param.io) {
1136  case IO_METHOD_READ:
1137  if (-1 == v4l2_read(param.fd, param.buffers[0].start, param.buffers[0].length)) {
1138  mutex.post();
1139  return false;
1140  }
1141 
1142  timeStamp.update(toEpochOffset + buf.timestamp.tv_sec + buf.timestamp.tv_usec / 1000000.0);
1143  // imageProcess(param.buffers[0].start);
1144  break;
1145 
1146 
1147  case IO_METHOD_MMAP:
1148  CLEAR(buf);
1149 
1150  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1151  buf.memory = V4L2_MEMORY_MMAP;
1152 
1153  if (-1 == xioctl(param.fd, VIDIOC_DQBUF, &buf)) {
1154  yCError(USBCAMERA, "usbCamera VIDIOC_DQBUF");
1155  mutex.post();
1156  return false;
1157  }
1158 
1159  if (!(buf.index < param.n_buffers)) {
1160  mutex.post();
1161  return false;
1162  }
1163 
1164  memcpy(param.read_image, param.buffers[buf.index].start, param.buffers[0].length);
1165  // imageProcess(param.raw_image);
1166  timeStamp.update(toEpochOffset + buf.timestamp.tv_sec + buf.timestamp.tv_usec / 1000000.0);
1167 
1168  if (-1 == xioctl(param.fd, VIDIOC_QBUF, &buf)) {
1169  yCError(USBCAMERA, "VIDIOC_QBUF");
1170  mutex.post();
1171  return false;
1172  }
1173 
1174  break;
1175 
1176  case IO_METHOD_USERPTR:
1177  CLEAR(buf);
1178 
1179  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1180  buf.memory = V4L2_MEMORY_USERPTR;
1181 
1182  if (-1 == xioctl(param.fd, VIDIOC_DQBUF, &buf)) {
1183  yCError(USBCAMERA, "VIDIOC_DQBUF");
1184  mutex.post();
1185  return false;
1186  }
1187 
1188  for (i = 0; i < param.n_buffers; ++i) {
1189  if (buf.m.userptr == (unsigned long)param.buffers[i].start && buf.length == param.buffers[i].length) {
1190  break;
1191  }
1192  }
1193 
1194  if (!(i < param.n_buffers)) {
1195  mutex.post();
1196  return false;
1197  }
1198 
1199  memcpy(param.read_image, param.buffers[buf.index].start, param.buffers[0].length);
1200  timeStamp.update(toEpochOffset + buf.timestamp.tv_sec + buf.timestamp.tv_usec / 1000000.0);
1201 
1202 
1203  if (-1 == xioctl(param.fd, VIDIOC_QBUF, &buf)) {
1204  yCError(USBCAMERA, "VIDIOC_QBUF");
1205  }
1206  break;
1207 
1208  default:
1209  yCError(USBCAMERA, "frameRead no read method configured");
1210  }
1211  mutex.post();
1212  return true;
1213 }
1214 
1215 /*
1216  * This function is intended to perform custom code to adapt
1217  * non standard pixel types to a standard one, in order to
1218  * use standard conversion libraries afterward.
1219  */
1220 void V4L_camera::imagePreProcess()
1221 {
1222  switch (param.camModel) {
1223  case LEOPARD_PYTHON:
1224  {
1225  // Here we are resizing the byte information from 10 to 8 bits.
1226  // Width and Height are not modified by this operation.
1227  const uint _pixelNum = param.src_fmt.fmt.pix.width * param.src_fmt.fmt.pix.height;
1228 
1229  uint16_t* raw_p = (uint16_t*)param.raw_image;
1230  for (uint i = 0; i < _pixelNum; i++) {
1231  param.src_image[i] = (unsigned char)(raw_p[i] >> bit_shift);
1232  }
1233 
1234  // Set the correct pixel type fot the v4l_convert to work on.
1235  param.src_fmt.fmt.pix.bytesperline = param.src_fmt.fmt.pix.width;
1236  param.src_fmt.fmt.pix.pixelformat = pixel_fmt_leo;
1237  break;
1238  }
1239  case STANDARD_UVC:
1240  default:
1241  // Nothing to do here
1242  break;
1243  }
1244 }
1245 
1249 void V4L_camera::imageProcess()
1250 {
1251  static bool initted = false;
1252  static int err = 0;
1253 
1254  timeStart = yarp::os::Time::now();
1255 
1256  // imagePreProcess() should already be called before entering here!!
1257  // src_fmt and dst_fmt must be alredy fixed up if needed!!
1258 
1259  // Convert from src type to RGB
1260  if (v4lconvert_convert((v4lconvert_data*)_v4lconvert_data,
1261  &param.src_fmt,
1262  &param.dst_fmt,
1263  param.src_image,
1264  param.src_image_size,
1265  param.dst_image_rgb,
1266  param.dst_image_size_rgb)
1267  < 0) {
1268  if ((err % 20) == 0) {
1269  yCError(USBCAMERA, "error converting \n\t Error message is: %s", v4lconvert_get_error_message(_v4lconvert_data));
1270  err = 0;
1271  }
1272  err++;
1273  return;
1274  }
1275 
1276  if (param.addictionalResize) {
1277  if (!param.dual) {
1278  cv::Mat img(cv::Size(param.dst_fmt.fmt.pix.width, param.dst_fmt.fmt.pix.height), CV_8UC3, param.dst_image_rgb);
1279  cv::Rect crop(param.resizeOffset_x, param.resizeOffset_y, param.resizeWidth, param.resizeHeight);
1280  cv::resize(img(crop), param.outMat, cvSize(param.user_width, param.user_height), 0, 0, cv::INTER_CUBIC);
1281  } else {
1282  // Load whole image in a cv::Mat
1283  cv::Mat img(cv::Size(param.dst_fmt.fmt.pix.width, param.dst_fmt.fmt.pix.height), CV_8UC3, param.dst_image_rgb);
1284  cv::Mat img_right;
1285  cv::Rect crop(param.resizeOffset_x, param.resizeOffset_y, param.resizeWidth, param.resizeHeight);
1286 
1287  cv::resize(img(crop), param.outMat, cvSize(param.user_width / 2, param.user_height), 0, 0, cv::INTER_CUBIC);
1288  cv::Rect crop2(param.resizeWidth + param.resizeOffset_x * 2, param.resizeOffset_y, param.resizeWidth, param.resizeHeight);
1289  cv::resize(img(crop2), img_right, cvSize(param.user_width / 2, param.user_height), 0, 0, cv::INTER_CUBIC);
1290  cv::hconcat(param.outMat, img_right, param.outMat);
1291  }
1292  if (param.flip) {
1293  cv::flip(param.outMat, param.outMat, 1);
1294  }
1295  } else {
1296  if (param.flip) {
1297  cv::Mat img(cv::Size(param.dst_fmt.fmt.pix.width, param.dst_fmt.fmt.pix.height), CV_8UC3, param.dst_image_rgb);
1298  param.outMat = img;
1299  cv::flip(param.outMat, param.outMat, 1);
1300  }
1301  }
1302 
1303  timeElapsed = yarp::os::Time::now() - timeStart;
1304  myCounter++;
1305  timeTot += timeElapsed;
1306 
1307  if ((myCounter % 60) == 0) {
1308  if (!initted) {
1309  timeTot = 0;
1310  myCounter = 0;
1311  initted = true;
1312  }
1313  }
1314 }
1315 
1319 void V4L_camera::captureStop()
1320 {
1321  int ret = 0;
1322  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1323  switch (param.io) {
1324  case IO_METHOD_READ:
1325  //do nothing
1326  break;
1327 
1328  case IO_METHOD_MMAP:
1329  default:
1330  ret = xioctl(param.fd, VIDIOC_STREAMOFF, &type);
1331  if (ret < 0) {
1332  if (errno != 9) { /* errno = 9 means the capture was allready stoped*/
1333  yCError(USBCAMERA, "VIDIOC_STREAMOFF - Unable to stop capture: %d, %s", errno, strerror(errno));
1334  }
1335  }
1336  break;
1337  }
1338 }
1339 
1343 void V4L_camera::captureStart()
1344 {
1345  unsigned int i;
1346  enum v4l2_buf_type type;
1347 
1348  switch (param.io) {
1349  case IO_METHOD_READ:
1350  /* Nothing to do. */
1351  break;
1352 
1353  case IO_METHOD_MMAP:
1354  for (i = 0; i < param.n_buffers; ++i) {
1355  struct v4l2_buffer buf;
1356  CLEAR(buf);
1357 
1358  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1359  buf.memory = V4L2_MEMORY_MMAP;
1360  buf.index = i;
1361 
1362  if (-1 == xioctl(param.fd, VIDIOC_QBUF, &buf)) {
1363  yCError(USBCAMERA, "VIDIOC_QBUF");
1364  }
1365  }
1366 
1367  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1368 
1369  if (-1 == xioctl(param.fd, VIDIOC_STREAMON, &type)) {
1370  yCError(USBCAMERA, "VIDIOC_STREAMON");
1371  }
1372 
1373  break;
1374 
1375  case IO_METHOD_USERPTR:
1376  for (i = 0; i < param.n_buffers; ++i) {
1377  struct v4l2_buffer buf;
1378 
1379  CLEAR(buf);
1380 
1381  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1382  buf.memory = V4L2_MEMORY_USERPTR;
1383  buf.index = i;
1384  buf.m.userptr = (unsigned long)param.buffers[i].start;
1385  buf.length = param.buffers[i].length;
1386 
1387  if (-1 == xioctl(param.fd, VIDIOC_QBUF, &buf)) {
1388  yCError(USBCAMERA, "VIDIOC_QBUF");
1389  }
1390  }
1391 
1392  type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1393 
1394  if (-1 == xioctl(param.fd, VIDIOC_STREAMON, &type)) {
1395  yCError(USBCAMERA, "VIDIOC_STREAMON");
1396  }
1397 
1398  break;
1399  }
1400 }
1401 
1402 
1403 bool V4L_camera::readInit(unsigned int buffer_size)
1404 {
1405  param.buffers = (struct buffer*)calloc(1, sizeof(*(param.buffers)));
1406 
1407  if (param.buffers == nullptr) {
1408  yCError(USBCAMERA, "cannot allocate buffer, out of memory");
1409  return false;
1410  }
1411 
1412  param.buffers[0].length = buffer_size;
1413  param.buffers[0].start = malloc(buffer_size);
1414 
1415  if (param.buffers[0].start == nullptr) {
1416  yCError(USBCAMERA, "cannot allocate buffer, out of memory");
1417  return false;
1418  }
1419  return true;
1420 }
1421 
1422 bool V4L_camera::mmapInit()
1423 {
1424  CLEAR(param.req);
1425 
1427  param.req.count = param.n_buffers;
1428  param.req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1429  param.req.memory = V4L2_MEMORY_MMAP;
1430 
1431  if (-1 == xioctl(param.fd, VIDIOC_REQBUFS, &param.req)) {
1432  if (EINVAL == errno) {
1433  yCError(USBCAMERA, "%s does not support memory mapping", param.deviceId.c_str());
1434  return false;
1435  }
1436  yCError(USBCAMERA, "Error on device %s requesting memory mapping (VIDIOC_REQBUFS)", param.deviceId.c_str());
1437  return false;
1438  }
1439 
1440  if (param.req.count < 1) {
1441  yCError(USBCAMERA, "Insufficient buffer memory on %s", param.deviceId.c_str());
1442  return false;
1443  }
1444 
1445  if (param.req.count == 1) {
1446  yCError(USBCAMERA, "Only 1 buffer was available, you may encounter performance issue acquiring images from device %s", param.deviceId.c_str());
1447  }
1448 
1449  param.buffers = (struct buffer*)calloc(param.req.count, sizeof(*(param.buffers)));
1450 
1451  if (param.buffers == nullptr) {
1452  yCError(USBCAMERA, "Out of memory");
1453  return false;
1454  }
1455 
1456  struct v4l2_buffer buf;
1457 
1458  for (param.n_buffers = 0; param.n_buffers < param.req.count; param.n_buffers++) {
1459  CLEAR(buf);
1460 
1461  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1462  buf.memory = V4L2_MEMORY_MMAP;
1463  buf.index = param.n_buffers;
1464 
1465  if (-1 == xioctl(param.fd, VIDIOC_QUERYBUF, &buf)) {
1466  yCError(USBCAMERA, "VIDIOC_QUERYBUF");
1467  }
1468 
1469  param.buffers[param.n_buffers].length = buf.length;
1470  param.buffers[param.n_buffers].start = v4l2_mmap(nullptr, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, param.fd, buf.m.offset);
1471 
1472  if (MAP_FAILED == param.buffers[param.n_buffers].start) {
1473  yCError(USBCAMERA, "mmap");
1474  }
1475  }
1476  return true;
1477 }
1478 
1479 bool V4L_camera::userptrInit(unsigned int buffer_size)
1480 {
1481  unsigned int page_size;
1482 
1483  page_size = getpagesize();
1484  buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
1485 
1486  CLEAR(param.req);
1487 
1488  param.req.count = VIDIOC_REQBUFS_COUNT;
1489  param.req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1490  param.req.memory = V4L2_MEMORY_USERPTR;
1491 
1492  if (-1 == xioctl(param.fd, VIDIOC_REQBUFS, &param.req)) {
1493  if (EINVAL == errno) {
1494  yCError(USBCAMERA, "%s does not support user pointer i/o", param.deviceId.c_str());
1495  return false;
1496  }
1497  yCError(USBCAMERA, "Error requesting VIDIOC_REQBUFS for device %s", param.deviceId.c_str());
1498  return false;
1499  }
1500 
1501  param.buffers = (struct buffer*)calloc(4, sizeof(*(param.buffers)));
1502 
1503  if (param.buffers == nullptr) {
1504  yCError(USBCAMERA, "cannot allocate buffer, out of memory");
1505  return false;
1506  }
1507 
1508  for (param.n_buffers = 0; param.n_buffers < 4; ++param.n_buffers) {
1509  param.buffers[param.n_buffers].length = buffer_size;
1510  param.buffers[param.n_buffers].start = memalign(/* boundary */ page_size, buffer_size);
1511 
1512  if (param.buffers[param.n_buffers].start == nullptr) {
1513  yCError(USBCAMERA, "cannot allocate buffer, out of memory");
1514  return false;
1515  }
1516  }
1517  return true;
1518 }
1519 
1520 bool V4L_camera::set_V4L2_control(uint32_t id, double value, bool verbatim)
1521 {
1522  if (value < 0) {
1523  return false;
1524  }
1525 
1526  struct v4l2_queryctrl queryctrl;
1527  struct v4l2_control control;
1528 
1529  memset(&queryctrl, 0, sizeof(queryctrl));
1530  queryctrl.id = id;
1531 
1532  if (-1 == ioctl(param.fd, VIDIOC_QUERYCTRL, &queryctrl)) {
1533  if (errno != EINVAL) {
1534  yCError(USBCAMERA, "VIDIOC_QUERYCTRL: %d, %s", errno, strerror(errno));
1535  } else {
1536  yCError(USBCAMERA, "Cannot set control <%s> (id 0x%0X) is not supported", queryctrl.name, queryctrl.id);
1537  }
1538  return false;
1539  }
1540 
1541  if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1542  yCError(USBCAMERA, "Control %s is disabled", queryctrl.name);
1543  return false;
1544  }
1545  memset(&control, 0, sizeof(control));
1546  control.id = id;
1547  if (verbatim) {
1548  control.value = value;
1549  } else {
1550  if (param.camModel == LEOPARD_PYTHON) {
1551  if ((V4L2_CID_EXPOSURE == id) || (V4L2_CID_EXPOSURE_ABSOLUTE == id) || (V4L2_CID_EXPOSURE_AUTO == id)) {
1552  queryctrl.maximum = 8000;
1553  queryctrl.minimum = 0;
1554  }
1555  }
1556  control.value = (int32_t)(value * (queryctrl.maximum - queryctrl.minimum) + queryctrl.minimum);
1557  }
1558  if (-1 == ioctl(param.fd, VIDIOC_S_CTRL, &control)) {
1559  yCError(USBCAMERA, "VIDIOC_S_CTRL: %d, %s", errno, strerror(errno));
1560  if (errno == ERANGE) {
1561  yCError(USBCAMERA, "Normalized input value %f ( equivalent to raw value of %d) was out of range for control %s: Min and Max are: %d - %d", value, control.value, queryctrl.name, queryctrl.minimum, queryctrl.maximum);
1562  }
1563  return false;
1564  }
1565  if (verbose) {
1566  yCInfo(USBCAMERA, "set control %s to %d done!", queryctrl.name, control.value);
1567  }
1568 
1569  return true;
1570 }
1571 
1572 bool V4L_camera::check_V4L2_control(uint32_t id)
1573 {
1574  // yCTrace(USBCAMERA);
1575  struct v4l2_queryctrl queryctrl;
1576  struct v4l2_control control;
1577 
1578  memset(&control, 0, sizeof(control));
1579  memset(&queryctrl, 0, sizeof(queryctrl));
1580 
1581  control.id = id;
1582  queryctrl.id = id;
1583 
1584  if (-1 == ioctl(param.fd, VIDIOC_QUERYCTRL, &queryctrl)) {
1585  if (errno != EINVAL) {
1586  yCError(USBCAMERA, "VIDIOC_QUERYCTRL: %d, %s", errno, strerror(errno));
1587  }
1588  return false;
1589  }
1590  return true;
1591 }
1592 
1593 double V4L_camera::get_V4L2_control(uint32_t id, bool verbatim)
1594 {
1595  struct v4l2_queryctrl queryctrl;
1596  struct v4l2_control control;
1597 
1598  memset(&control, 0, sizeof(control));
1599  memset(&queryctrl, 0, sizeof(queryctrl));
1600 
1601  control.id = id;
1602  queryctrl.id = id;
1603 
1604  if (-1 == ioctl(param.fd, VIDIOC_QUERYCTRL, &queryctrl)) {
1605  if (errno != EINVAL) {
1606  yCError(USBCAMERA, "VIDIOC_QUERYCTRL: %d, %s", errno, strerror(errno));
1607  }
1608 
1609  return -1.0;
1610  }
1611 
1612  if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
1613  yCError(USBCAMERA, "Control %s is disabled", queryctrl.name);
1614  } else {
1615  if (-1 == ioctl(param.fd, VIDIOC_G_CTRL, &control)) {
1616  yCError(USBCAMERA, "VIDIOC_G_CTRL: %d, %s", errno, strerror(errno));
1617  return -1.0;
1618  }
1619  }
1620  if (verbatim) {
1621  return control.value;
1622  }
1623 
1624  if (param.camModel == LEOPARD_PYTHON) {
1625  if ((V4L2_CID_EXPOSURE == id) || (V4L2_CID_EXPOSURE_ABSOLUTE == id) || (V4L2_CID_EXPOSURE_AUTO == id)) {
1626  queryctrl.maximum = 8000;
1627  queryctrl.minimum = 0;
1628  }
1629  }
1630  return (double)(control.value - queryctrl.minimum) / (queryctrl.maximum - queryctrl.minimum);
1631 }
1632 
1634 {
1635  camera->busType = BUS_USB;
1636  camera->deviceDescription = "USB3 camera";
1637  return true;
1638 }
1639 
1640 bool V4L_camera::hasFeature(int feature, bool* _hasFeature)
1641 {
1642  bool tmpMan(false);
1643  bool tmpAuto(false);
1644  bool tmpOnce(false);
1645 
1646  switch (feature) {
1648  tmpMan = check_V4L2_control(V4L2_CID_RED_BALANCE) && check_V4L2_control(V4L2_CID_BLUE_BALANCE);
1649  tmpOnce = check_V4L2_control(V4L2_CID_DO_WHITE_BALANCE);
1650  tmpAuto = check_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE);
1651  break;
1652 
1653  case YARP_FEATURE_EXPOSURE:
1654  tmpMan = check_V4L2_control(V4L2_CID_EXPOSURE) || check_V4L2_control(V4L2_CID_EXPOSURE_ABSOLUTE);
1655  tmpAuto = check_V4L2_control(V4L2_CID_EXPOSURE_AUTO);
1656  break;
1657 
1658  default:
1659  tmpMan = check_V4L2_control(convertYARP_to_V4L(feature));
1660  break;
1661  }
1662 
1663  *_hasFeature = tmpMan || tmpOnce || tmpAuto;
1664  return true;
1665 }
1666 
1667 bool V4L_camera::setFeature(int feature, double value)
1668 {
1669  bool ret = false;
1670  switch (feature) {
1671  case YARP_FEATURE_EXPOSURE:
1672  if (use_exposure_absolute) {
1673  ret = set_V4L2_control(V4L2_CID_EXPOSURE_ABSOLUTE, value);
1674  } else {
1675  ret = set_V4L2_control(V4L2_CID_EXPOSURE, value);
1676  }
1677  break;
1678 
1679  default:
1680  ret = set_V4L2_control(convertYARP_to_V4L(feature), value);
1681  break;
1682  }
1683  return ret;
1684 }
1685 
1686 bool V4L_camera::getFeature(int feature, double* value)
1687 {
1688  double tmp = 0.0;
1689  switch (feature) {
1690  case YARP_FEATURE_EXPOSURE:
1691  if (use_exposure_absolute) {
1692  tmp = get_V4L2_control(V4L2_CID_EXPOSURE_ABSOLUTE);
1693  } else {
1694  tmp = get_V4L2_control(V4L2_CID_EXPOSURE);
1695  }
1696  break;
1697 
1698  default:
1699  tmp = get_V4L2_control(convertYARP_to_V4L(feature));
1700  break;
1701  }
1702 
1703  if (tmp == -1) {
1704  return false;
1705  }
1706 
1707  *value = tmp;
1708  return true;
1709 }
1710 
1711 bool V4L_camera::setFeature(int feature, double value1, double value2)
1712 {
1713  if (feature == YARP_FEATURE_WHITE_BALANCE) {
1714  bool ret = true;
1715  ret &= set_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE, false);
1716  ret &= set_V4L2_control(V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_WHITE_BALANCE_MANUAL);
1717  ret &= set_V4L2_control(V4L2_CID_RED_BALANCE, value1);
1718  ret &= set_V4L2_control(V4L2_CID_BLUE_BALANCE, value2);
1719  return ret;
1720  }
1721  return false;
1722 }
1723 
1724 bool V4L_camera::getFeature(int feature, double* value1, double* value2)
1725 {
1726  if (feature == YARP_FEATURE_WHITE_BALANCE) {
1727  *value1 = get_V4L2_control(V4L2_CID_RED_BALANCE);
1728  *value2 = get_V4L2_control(V4L2_CID_BLUE_BALANCE);
1729  return !((*value1 == -1) || (*value2 == -1));
1730  }
1731  return false;
1732 }
1733 
1734 bool V4L_camera::hasOnOff(int feature, bool* _hasOnOff)
1735 {
1736  bool _hasAuto;
1737  // I can't find any meaning of setting a feature to off on V4l ... what it is supposed to do????
1738  switch (feature) {
1739  // The following do have a way to set them auto/manual
1741  case YARP_FEATURE_EXPOSURE:
1742  if (hasAuto(feature, &_hasAuto)) {
1743  *_hasOnOff = true;
1744  } else {
1745  *_hasOnOff = false;
1746  }
1747  break;
1748 
1749  // try it out
1750  default:
1751  hasAuto(feature, &_hasAuto);
1752  if (_hasAuto) {
1753  *_hasOnOff = true;
1754  } else {
1755  *_hasOnOff = false;
1756  }
1757  break;
1758  }
1759  return true;
1760 }
1761 
1762 bool V4L_camera::setActive(int feature, bool onoff)
1763 {
1764  // I can't find any meaning of setting a feature to off on V4l ... what it is supposed to do????
1765  bool tmp;
1766  switch (feature) {
1768  tmp = set_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE, onoff);
1769  if (tmp) {
1770  isActive_vector[feature] = onoff;
1771  }
1772  break;
1773 
1774  case YARP_FEATURE_EXPOSURE:
1775  if (onoff) {
1776  set_V4L2_control(V4L2_LOCK_EXPOSURE, false);
1777 
1778  hasAuto(feature, &tmp);
1779  if (tmp) {
1780  tmp = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_AUTO);
1781  } else {
1782  tmp = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
1783  }
1784 
1785  if (tmp) {
1786  isActive_vector[feature] = onoff;
1787  }
1788  } else {
1789  bool man = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL);
1790  if (!man) {
1791  man = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_SHUTTER_PRIORITY, true);
1792  if (!man) {
1793  yCError(USBCAMERA) << "Cannot set manual exposure";
1794  }
1795  }
1796  set_V4L2_control(V4L2_LOCK_EXPOSURE, true);
1797  isActive_vector[feature] = onoff;
1798  }
1799  break;
1800 
1801  default: // what to do in each case?
1802  if (onoff) {
1803  isActive_vector[feature] = true;
1804  return true;
1805  }
1806  isActive_vector[feature] = false;
1807  return false;
1808  }
1809  return true;
1810 }
1811 
1812 bool V4L_camera::getActive(int feature, bool* _isActive)
1813 {
1814  switch (feature) {
1816  {
1817  double tmp = get_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE);
1818  if (tmp == 1) {
1819  *_isActive = true;
1820  } else {
1821  *_isActive = false;
1822  }
1823  break;
1824  }
1825 
1826  case YARP_FEATURE_EXPOSURE:
1827  {
1828  bool _hasMan(false);
1829  bool _hasMan2(false);
1830  hasFeature(V4L2_CID_EXPOSURE, &_hasMan) || hasFeature(V4L2_CID_EXPOSURE_ABSOLUTE, &_hasMan2); // check manual version (normal and asbolute)
1831  double _hasAuto = get_V4L2_control(V4L2_CID_EXPOSURE_AUTO, true); // check auto version
1832 
1833  *_isActive = (_hasAuto == V4L2_EXPOSURE_AUTO) || _hasMan || _hasMan2;
1834  break;
1835  }
1836 
1837  default:
1838  *_isActive = true;
1839  break;
1840  }
1841 
1842  return true;
1843 }
1844 
1845 bool V4L_camera::hasAuto(int feature, bool* _hasAuto)
1846 {
1847  switch (feature) {
1849  *_hasAuto = check_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE);
1850  break;
1851 
1853  *_hasAuto = check_V4L2_control(V4L2_CID_AUTOBRIGHTNESS);
1854  break;
1855 
1856  case YARP_FEATURE_GAIN:
1857  *_hasAuto = check_V4L2_control(V4L2_CID_AUTOGAIN);
1858  break;
1859 
1860  case YARP_FEATURE_EXPOSURE:
1861  *_hasAuto = check_V4L2_control(V4L2_CID_EXPOSURE_AUTO);
1862  break;
1863 
1864  case YARP_FEATURE_HUE:
1865  *_hasAuto = check_V4L2_control(V4L2_CID_HUE_AUTO);
1866  break;
1867 
1868  default:
1869  *_hasAuto = false;
1870  break;
1871  }
1872  return true;
1873 }
1874 
1875 bool V4L_camera::hasManual(int feature, bool* _hasManual)
1876 {
1877  if (feature == YARP_FEATURE_WHITE_BALANCE) {
1878  *_hasManual = check_V4L2_control(V4L2_CID_RED_BALANCE) && check_V4L2_control(V4L2_CID_BLUE_BALANCE);
1879  return true;
1880  }
1881 
1882  if (feature == YARP_FEATURE_EXPOSURE) {
1883  *_hasManual = check_V4L2_control(V4L2_CID_EXPOSURE) || check_V4L2_control(V4L2_CID_EXPOSURE_ABSOLUTE);
1884  return true;
1885  }
1886  return hasFeature(feature, _hasManual);
1887 }
1888 
1889 bool V4L_camera::hasOnePush(int feature, bool* _hasOnePush)
1890 {
1891  // I'm not able to map a 'onePush' request on V4L api
1892  switch (feature) {
1894  *_hasOnePush = check_V4L2_control(V4L2_CID_DO_WHITE_BALANCE);
1895  return true;
1896 
1897  default:
1898  *_hasOnePush = false;
1899  break;
1900  }
1901  return true;
1902 }
1903 
1904 bool V4L_camera::setMode(int feature, FeatureMode mode)
1905 {
1906  bool ret = false;
1907  switch (feature) {
1909  if (mode == MODE_AUTO) {
1910  ret = set_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE, true);
1911  } else {
1912  ret = set_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE, false);
1913  }
1914  break;
1915 
1916  case YARP_FEATURE_EXPOSURE:
1917  bool _tmpAuto;
1918  hasAuto(V4L2_CID_EXPOSURE_AUTO, &_tmpAuto);
1919 
1920  if (_tmpAuto) {
1921  if (mode == MODE_AUTO) {
1922  ret = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, true);
1923  } else {
1924  ret = set_V4L2_control(V4L2_CID_EXPOSURE_AUTO, false);
1925  }
1926  } else {
1927  ret = mode != MODE_AUTO;
1928  }
1929  break;
1930 
1931  case YARP_FEATURE_GAIN:
1932  if (mode == MODE_AUTO) {
1933  yCInfo(USBCAMERA) << "GAIN: set mode auto";
1934  ret = set_V4L2_control(V4L2_CID_AUTOGAIN, true);
1935  } else {
1936  yCInfo(USBCAMERA) << "GAIN: set mode manual";
1937  ret = set_V4L2_control(V4L2_CID_AUTOGAIN, false);
1938  }
1939  break;
1940 
1942  {
1943  bool _tmpAuto;
1944  hasAuto(YARP_FEATURE_BRIGHTNESS, &_tmpAuto);
1945 
1946  if (_tmpAuto) {
1947  if (mode == MODE_AUTO) {
1948  ret = set_V4L2_control(V4L2_CID_AUTOBRIGHTNESS, true);
1949  } else {
1950  ret = set_V4L2_control(V4L2_CID_AUTOBRIGHTNESS, false);
1951  }
1952  } else {
1953  ret = mode != MODE_AUTO;
1954  }
1955  break;
1956  }
1957 
1958  case YARP_FEATURE_HUE:
1959  if (mode == MODE_AUTO) {
1960  ret = set_V4L2_control(V4L2_CID_HUE_AUTO, true);
1961  } else {
1962  ret = set_V4L2_control(V4L2_CID_HUE_AUTO, false);
1963  }
1964  break;
1965 
1966  default:
1967  yCError(USBCAMERA) << "Feature " << feature << " does not support auto mode";
1968  break;
1969  }
1970  return ret;
1971 }
1972 
1973 bool V4L_camera::getMode(int feature, FeatureMode* mode)
1974 {
1975  bool _tmpAuto;
1976  switch (feature) {
1978  {
1979  double ret = get_V4L2_control(V4L2_CID_AUTO_WHITE_BALANCE);
1980  *mode = toFeatureMode(ret != 0.0);
1981  break;
1982  }
1983 
1984  case YARP_FEATURE_EXPOSURE:
1985  {
1986  double ret = get_V4L2_control(V4L2_CID_EXPOSURE_AUTO);
1987  if (ret == -1.0) {
1988  *mode = MODE_MANUAL;
1989  break;
1990  }
1991 
1992  if (ret == V4L2_EXPOSURE_MANUAL) {
1993  *mode = MODE_MANUAL;
1994  } else {
1995  *mode = MODE_AUTO;
1996  }
1997  break;
1998  }
1999 
2001  hasAuto(YARP_FEATURE_BRIGHTNESS, &_tmpAuto);
2002  *mode = toFeatureMode(_tmpAuto);
2003  if (!_tmpAuto) {
2004  *mode = MODE_MANUAL;
2005  } else {
2006  double ret = get_V4L2_control(V4L2_CID_AUTOBRIGHTNESS);
2007  *mode = toFeatureMode(ret != 0.0);
2008  }
2009  break;
2010 
2011  case YARP_FEATURE_GAIN:
2012  hasAuto(YARP_FEATURE_GAIN, &_tmpAuto);
2013  *mode = toFeatureMode(_tmpAuto);
2014  if (!_tmpAuto) {
2015  *mode = MODE_MANUAL;
2016  } else {
2017  double ret = get_V4L2_control(V4L2_CID_AUTOGAIN);
2018  *mode = toFeatureMode(ret != 0.0);
2019  }
2020  break;
2021 
2022  case YARP_FEATURE_HUE:
2023  hasAuto(YARP_FEATURE_HUE, &_tmpAuto);
2024  *mode = toFeatureMode(_tmpAuto);
2025  if (!_tmpAuto) {
2026  *mode = MODE_MANUAL;
2027  } else {
2028  double ret = get_V4L2_control(V4L2_CID_HUE_AUTO);
2029  *mode = toFeatureMode(ret != 0.0);
2030  }
2031  break;
2032 
2033  default:
2034  *mode = MODE_MANUAL;
2035  break;
2036  }
2037  return true;
2038 }
2039 
2040 bool V4L_camera::setOnePush(int feature)
2041 {
2042  // I'm not able to map a 'onePush' request on each V4L api
2043  if (feature == YARP_FEATURE_WHITE_BALANCE) {
2044  return set_V4L2_control(V4L2_CID_DO_WHITE_BALANCE, true);
2045  }
2046  return false;
2047 }
@ YARP_FEATURE_SHARPNESS
@ YARP_FEATURE_BRIGHTNESS
@ YARP_FEATURE_HUE
@ YARP_FEATURE_WHITE_BALANCE
@ YARP_FEATURE_GAMMA
@ YARP_FEATURE_EXPOSURE
@ YARP_FEATURE_IRIS
@ YARP_FEATURE_SATURATION
@ YARP_FEATURE_SHUTTER
@ YARP_FEATURE_GAIN
bool ret
#define CLEAR
Definition: Log.cpp:198
const yarp::os::LogComponent & USBCAMERA()
struct v4l2_queryctrl queryctrl
Definition: V4L_camera.cpp:999
static double getEpochTimeShift()
Definition: V4L_camera.cpp:40
struct v4l2_querymenu querymenu
#define NOT_PRESENT
Definition: V4L_camera.cpp:63
#define DEFAULT_HEIGHT
Definition: V4L_camera.h:56
#define DEFAULT_FRAMERATE
Definition: V4L_camera.h:57
#define VIDIOC_REQBUFS_COUNT
Definition: V4L_camera.h:58
#define DEFAULT_WIDTH
Definition: V4L_camera.h:55
@ STANDARD_UVC
Definition: V4L_camera.h:69
@ LEOPARD_PYTHON
Definition: V4L_camera.h:70
@ IO_METHOD_MMAP
Definition: V4L_camera.h:63
@ IO_METHOD_READ
Definition: V4L_camera.h:62
@ IO_METHOD_USERPTR
Definition: V4L_camera.h:64
bool getMode(int feature, FeatureMode *mode) override
Get the current mode for the feature.
bool getRgbMirroring(bool &mirror) override
Get the mirroring setting of the sensor.
Definition: V4L_camera.cpp:369
bool setRgbMirroring(bool mirror) override
Set the mirroring setting of the sensor.
Definition: V4L_camera.cpp:376
int getRgbWidth() override
Return the width of each frame.
Definition: V4L_camera.cpp:320
bool setMode(int feature, FeatureMode mode) override
Set the requested mode for the feature.
yarp::os::Stamp getLastInputStamp() override
Return the time stamp relative to the last acquisition.
Definition: V4L_camera.cpp:156
bool setRgbFOV(double horizontalFov, double verticalFov) override
Set the field of view (FOV) of the rgb camera.
Definition: V4L_camera.cpp:357
bool setRgbResolution(int width, int height) override
Set the resolution of the rgb image from the camera.
Definition: V4L_camera.cpp:337
bool hasOnePush(int feature, bool *_hasOnePush) override
Check if the requested feature has the 'onePush' mode.
bool close() override
close device
Definition: V4L_camera.cpp:884
bool hasFeature(int feature, bool *hasFeature) override
Check if camera has the requested feature (saturation, brightness ...
bool getRgbIntrinsicParam(yarp::os::Property &intrinsic) override
Get the intrinsic parameters of the rgb camera.
Definition: V4L_camera.cpp:363
bool hasOnOff(int feature, bool *_hasOnOff) override
Check if the camera has the ability to turn on/off the requested feature.
bool setActive(int feature, bool onoff) override
Set the requested feature on or off.
bool getCameraDescription(CameraDescriptor *camera) override
Get a basic description of the camera hw.
int getRgbHeight() override
Return the height of each frame.
Definition: V4L_camera.cpp:315
bool getRgbFOV(double &horizontalFov, double &verticalFov) override
Get the field of view (FOV) of the rgb camera.
Definition: V4L_camera.cpp:350
bool hasAuto(int feature, bool *_hasAuto) override
Check if the requested feature has the 'auto' mode.
int width() const override
Return the width of each frame.
Definition: V4L_camera.cpp:967
bool getFeature(int feature, double *value) override
Get the current value for the requested feature.
bool setOnePush(int feature) override
Set the requested feature to a value (saturation, brightness ...
bool setFeature(int feature, double value) override
Set the requested feature to a value (saturation, brightness ...
bool getActive(int feature, bool *_isActive) override
Get the current status of the feature, on or off.
bool getRgbResolution(int &width, int &height) override
Get the resolution of the rgb image from the camera.
Definition: V4L_camera.cpp:330
bool getRgbBuffer(unsigned char *buffer) override
Get a rgb buffer from the frame grabber, if required demosaicking/color reconstruction is applied.
Definition: V4L_camera.cpp:905
int height() const override
Return the height of each frame.
Definition: V4L_camera.cpp:954
int getRawBufferSize() override
Get the size of the card's internal buffer, the user should use this method to allocate the storage t...
Definition: V4L_camera.cpp:945
bool getRawBuffer(unsigned char *buffer) override
Get the raw buffer from the frame grabber.
Definition: V4L_camera.cpp:929
bool getRgbSupportedConfigurations(yarp::sig::VectorOf< yarp::dev::CameraConfig > &configurations) override
Get the possible configurations of the camera.
Definition: V4L_camera.cpp:325
bool open(yarp::os::Searchable &config) override
open device
Definition: V4L_camera.cpp:236
bool hasManual(int feature, bool *_hasManual) override
Check if the requested feature has the 'manual' mode.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:73
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:249
bool check(const std::string &key) const override
Check if there exists a property of the given name.
Definition: Bottle.cpp:280
bool isNull() const override
Checks if the object is invalid.
Definition: Bottle.cpp:373
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
Definition: Bottle.cpp:290
An abstraction for a periodic thread.
bool start()
Call this to start the thread.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
A class for storing options and configuration information.
Definition: Property.h:37
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:998
A base class for nested structures that can be searched.
Definition: Searchable.h:69
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
virtual Bottle & findGroup(const std::string &key) const =0
Gets a list corresponding to a given keyword.
void wait()
Decrement the counter, even if we must wait to do that.
Definition: Semaphore.cpp:99
void post()
Increment the counter.
Definition: Semaphore.cpp:114
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:25
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:113
A single value (typically within a Bottle).
Definition: Value.h:47
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:225
virtual bool asBool() const
Get boolean value.
Definition: Value.cpp:189
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition: Value.cpp:207
bool isNull() const override
Checks if the object is invalid.
Definition: Value.cpp:383
virtual std::string asString() const
Get string value.
Definition: Value.cpp:237
Provides:
Definition: Vector.h:122
void push_back(const T &elem)
Push a new element in the vector: size is changed.
Definition: Vector.h:282
#define YARP_NULLPTR
Expands to either the standard nullptr or to 0 elsewhere.
Definition: compiler.h:2935
#define yCInfo(component,...)
Definition: LogComponent.h:135
#define yCError(component,...)
Definition: LogComponent.h:157
#define yCTrace(component,...)
Definition: LogComponent.h:88
#define yCWarning(component,...)
Definition: LogComponent.h:146
#define yCDebug(component,...)
Definition: LogComponent.h:112
YarpVocabPixelTypesEnum
Definition: Image.h:46
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR16
Definition: Image.h:65
@ VOCAB_PIXEL_YUV_420
Definition: Image.h:70
@ VOCAB_PIXEL_MONO16
Definition: Image.h:49
@ VOCAB_PIXEL_ENCODING_BAYER_BGGR8
Definition: Image.h:64
@ VOCAB_PIXEL_YUV_444
Definition: Image.h:71
@ VOCAB_PIXEL_BGR
Definition: Image.h:55
@ VOCAB_PIXEL_ENCODING_BAYER_RGGB8
Definition: Image.h:68
@ VOCAB_PIXEL_ENCODING_BAYER_GRBG8
Definition: Image.h:62
@ VOCAB_PIXEL_YUV_422
Definition: Image.h:72
@ VOCAB_PIXEL_ENCODING_BAYER_GBRG8
Definition: Image.h:66
@ VOCAB_PIXEL_MONO
Definition: Image.h:48
@ VOCAB_PIXEL_YUV_411
Definition: Image.h:73
@ VOCAB_PIXEL_RGB
Definition: Image.h:50
void list_cap_v4l2(int fd)
Definition: list.cpp:291
void query_current_image_fmt_v4l2(int fd)
Definition: list.cpp:57
An interface for the device drivers.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:124
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:114
An interface to the operating system, including Port based communication.
int stat(const char *path)
Portable wrapper for the stat() function.
Definition: Os.cpp:88
std::string deviceId
Definition: V4L_camera.h:84
struct v4l2_format dst_fmt
Definition: V4L_camera.h:130
unsigned char * read_image
Definition: V4L_camera.h:109
unsigned int n_buffers
Definition: V4L_camera.h:127
yarp::sig::VectorOf< yarp::dev::CameraConfig > configurations
Definition: V4L_camera.h:124
size_t pixelType
Definition: V4L_camera.h:132
struct buffer * buffers
Definition: V4L_camera.h:128
__u32 user_height
Definition: V4L_camera.h:91
struct v4l2_format src_fmt
Definition: V4L_camera.h:129
unsigned char * raw_image
Definition: V4L_camera.h:104
io_method io
Definition: V4L_camera.h:98
unsigned char * dst_image_rgb
Definition: V4L_camera.h:118
int resizeOffset_x
Definition: V4L_camera.h:87
int resizeHeight
Definition: V4L_camera.h:88
yarp::os::Property intrinsic
Definition: V4L_camera.h:95
int resizeWidth
Definition: V4L_camera.h:88
int resizeOffset_y
Definition: V4L_camera.h:87
struct v4l2_requestbuffers req
Definition: V4L_camera.h:131
__u32 user_width
Definition: V4L_camera.h:90
double horizontalFov
Definition: V4L_camera.h:93
unsigned char * src_image
Definition: V4L_camera.h:113
bool addictionalResize
Definition: V4L_camera.h:86
cv::Mat outMat
Definition: V4L_camera.h:122
supported_cams camModel
Definition: V4L_camera.h:133
double verticalFov
Definition: V4L_camera.h:94
unsigned int dst_image_size_rgb
Definition: V4L_camera.h:119
unsigned int src_image_size
Definition: V4L_camera.h:114
unsigned int raw_image_size
Definition: V4L_camera.h:105
size_t length
Definition: V4L_camera.h:77
void * start
Definition: V4L_camera.h:76
Struct describing a possible camera configuration.
Definition: IVisualParams.h:33
YarpVocabPixelTypesEnum pixelCoding
Definition: IVisualParams.h:37