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