JeVois  1.10
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Camera.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 #include <jevois/Core/Camera.H>
19 #include <jevois/Debug/Log.H>
20 #include <jevois/Util/Utils.H>
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 
29 namespace
30 {
31  //! Temporary fix for bug in sunxi-vfe kernel camera driver which returns MBUS format instead or V4L2
32  unsigned int v4l2sunxiFix(unsigned int fcc)
33  {
34  switch (fcc)
35  {
36  case 0x2008: // Handle bug in our sunxi camera driver
37  case V4L2_PIX_FMT_YUYV: return V4L2_PIX_FMT_YUYV;
38 
39  case V4L2_PIX_FMT_GREY: return V4L2_PIX_FMT_GREY;
40 
41  case 0x3001: // Handle bug in our sunxi camera driver
42  case V4L2_PIX_FMT_SRGGB8: return V4L2_PIX_FMT_SRGGB8;
43 
44  case 0x1008: // Handle bug in our sunxi camera driver
45  case V4L2_PIX_FMT_RGB565: return V4L2_PIX_FMT_RGB565;
46 
47  case V4L2_PIX_FMT_MJPEG: return V4L2_PIX_FMT_MJPEG;
48 
49  case V4L2_PIX_FMT_BGR24: return V4L2_PIX_FMT_BGR24;
50 
51  default: LFATAL("Unsupported pixel format " << jevois::fccstr(fcc));
52  }
53  }
54 }
55 
56 // ##############################################################################################################
57 jevois::Camera::Camera(std::string const & devname, unsigned int const nbufs) :
58  jevois::VideoInput(devname, nbufs), itsFd(-1), itsBuffers(nullptr), itsFormat(), itsStreaming(false), itsFps(0.0F)
59 {
60  JEVOIS_TRACE(1);
61 
62  JEVOIS_TIMED_LOCK(itsMtx);
63 
64  // Get our run() thread going and wait until it is cranking, it will flip itsRunning to true as it starts:
65  itsRunFuture = std::async(std::launch::async, &jevois::Camera::run, this);
66  while (itsRunning.load() == false) std::this_thread::sleep_for(std::chrono::milliseconds(5));
67 
68  // Open the device:
69  itsFd = open(devname.c_str(), O_RDWR | O_NONBLOCK, 0);
70  if (itsFd == -1) PLFATAL("Camera device open failed on " << devname);
71 
72  // See what kinds of inputs we have and select the first one that is a camera:
73  int camidx = -1;
74  struct v4l2_input inp = { };
75  while (true)
76  {
77  try { XIOCTL_QUIET(itsFd, VIDIOC_ENUMINPUT, &inp); } catch (...) { break; }
78  if (inp.type == V4L2_INPUT_TYPE_CAMERA)
79  {
80  if (camidx == -1) camidx = inp.index;
81  LDEBUG("Input " << inp.index << " [" << inp.name << "] is a camera sensor");
82  } else LDEBUG("Input " << inp.index << " [" << inp.name << "] is a NOT camera sensor");
83  ++inp.index;
84  }
85 
86  if (camidx == -1) LFATAL("No valid camera input found on device " << devname);
87 
88  // Select the camera input, this seems to be required by VFE for the camera to power on:
89  XIOCTL(itsFd, VIDIOC_S_INPUT, &camidx);
90 
91  // Find out what camera can do:
92  struct v4l2_capability cap = { };
93  XIOCTL(itsFd, VIDIOC_QUERYCAP, &cap);
94 
95  LINFO('[' << itsFd << "] V4L2 camera " << devname << " card " << cap.card << " bus " << cap.bus_info);
96  if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) LFATAL(devname << " is not a video capture device");
97  if ((cap.capabilities & V4L2_CAP_STREAMING) == 0) LFATAL(devname << " does not support streaming");
98 
99  // List the supported formats:
100  struct v4l2_fmtdesc fmtdesc = { };
101  fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
102  while (true)
103  {
104  try { XIOCTL_QUIET(itsFd, VIDIOC_ENUM_FMT, &fmtdesc); } catch (...) { break; }
105  LDEBUG("Format " << fmtdesc.index << " is [" << fmtdesc.description << "] fcc " << std::showbase <<
106  std::hex << fmtdesc.pixelformat << " [" << jevois::fccstr(fmtdesc.pixelformat) << ']');
107  ++fmtdesc.index;
108  }
109 }
110 
111 // ##############################################################################################################
113 {
114  JEVOIS_TRACE(2);
115 
116  // We may be streaming, eg, if we were running a mapping with no USB out and then the user starts a video grabber. So
117  // make sure we stream off first:
118  if (itsStreaming.load()) streamOff();
119 
120  JEVOIS_TIMED_LOCK(itsMtx);
121 
122  // Get current format:
123  itsFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124  XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
125 
126  // Set desired format:
127  itsFormat.fmt.pix.width = m.cw;
128  itsFormat.fmt.pix.height = m.ch;
129  itsFormat.fmt.pix.pixelformat = m.cfmt;
130  itsFormat.fmt.pix.field = V4L2_FIELD_NONE;
131  itsFps = m.cfps;
132 
133  LDEBUG("Requesting video format " << itsFormat.fmt.pix.width << 'x' << itsFormat.fmt.pix.height << ' ' <<
134  jevois::fccstr(itsFormat.fmt.pix.pixelformat));
135  try
136  {
137  XIOCTL(itsFd, VIDIOC_S_FMT, &itsFormat);
138  }
139  catch (...)
140  {
141  // Oops, maybe this sensor only supports raw bayer:
142  itsFormat.fmt.pix.pixelformat = V4L2_PIX_FMT_SRGGB8;
143  XIOCTL(itsFd, VIDIOC_S_FMT, &itsFormat);
144  }
145 
146  // Get the format back as the driver may have adjusted some sizes, etc:
147  XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
148 
149  // The driver returns a different format code, may be the mbus code instead of the v4l2 fcc...
150  itsFormat.fmt.pix.pixelformat = v4l2sunxiFix(itsFormat.fmt.pix.pixelformat);
151 
152  LINFO("Camera set video format to " << itsFormat.fmt.pix.width << 'x' << itsFormat.fmt.pix.height << ' ' <<
153  jevois::fccstr(itsFormat.fmt.pix.pixelformat));
154 
155  // Because modules may rely on the exact format that they request, throw if the camera modified it:
156  if (itsFormat.fmt.pix.width != m.cw ||
157  itsFormat.fmt.pix.height != m.ch ||
158  (itsFormat.fmt.pix.pixelformat != m.cfmt &&
159  (m.cfmt != V4L2_PIX_FMT_YUYV || itsFormat.fmt.pix.pixelformat != V4L2_PIX_FMT_SRGGB8)))
160  LFATAL("Camera did not accept the requested video format as specified");
161 
162  // Allocate a RawImage for conversion from Bayer to YUYV if needed:
163  if (m.cfmt == V4L2_PIX_FMT_YUYV && itsFormat.fmt.pix.pixelformat == V4L2_PIX_FMT_SRGGB8)
164  {
165  // We will grab raw Bayer and store that into itsOutputImage, finally converting to YUYV in get():
166  itsConvertedOutputImage.width = itsFormat.fmt.pix.width;
167  itsConvertedOutputImage.height = itsFormat.fmt.pix.height;
168  itsConvertedOutputImage.fmt = V4L2_PIX_FMT_YUYV;
169  itsConvertedOutputImage.fps = itsFps;
170  itsConvertedOutputImage.buf = std::make_shared<jevois::VideoBuf>(-1, itsConvertedOutputImage.bytesize(), 0);
171  }
172  else
173  itsConvertedOutputImage.invalidate();
174 
175  // Reset cropping parameters. NOTE: just open()'ing the device does not reset it, according to the unix toolchain
176  // philosophy. Hence, although here we do not provide support for cropping, we still need to ensure that it is
177  // properly reset. Note that some cameras do not support this so here we swallow that exception:
178  try
179  {
180  struct v4l2_cropcap cropcap = { };
181  cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
182  XIOCTL_QUIET(itsFd, VIDIOC_CROPCAP, &cropcap);
183 
184  struct v4l2_crop crop = { };
185  crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect;
186  XIOCTL_QUIET(itsFd, VIDIOC_S_CROP, &crop);
187 
188  LDEBUG("Set cropping rectangle to " << cropcap.defrect.width << 'x' << cropcap.defrect.height << " @ ("
189  << cropcap.defrect.left << ", " << cropcap.defrect.top << ')');
190  }
191  catch (...) { LDEBUG("Querying/setting crop rectangle not supported"); }
192 
193  // Set frame rate:
194  try
195  {
196  struct v4l2_streamparm parms = { };
197  parms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
198  parms.parm.capture.timeperframe = jevois::VideoMapping::fpsToV4l2(m.cfps);
199  parms.parm.capture.capturemode = 2; // V4L2_MODE_VIDEO not defined in our headers? its value is 2.
200  XIOCTL(itsFd, VIDIOC_S_PARM, &parms);
201 
202  LDEBUG("Set framerate to " << m.cfps << " fps");
203  }
204  catch (...) { LERROR("Setting frame rate to " << m.cfps << " fps failed -- IGNORED"); }
205 }
206 
207 // ##############################################################################################################
209 {
210  JEVOIS_TRACE(1);
211 
212  // Turn off streaming if it was on:
213  try { streamOff(); } catch (...) { jevois::warnAndIgnoreException(); }
214 
215  // Block until the run() thread completes:
216  itsRunning.store(false);
217  if (itsRunFuture.valid()) try { itsRunFuture.get(); } catch (...) { jevois::warnAndIgnoreException(); }
218 
219  if (itsBuffers) delete itsBuffers;
220 
221  if (close(itsFd) == -1) PLERROR("Error closing V4L2 camera");
222 }
223 
224 // ##############################################################################################################
225 void jevois::Camera::run()
226 {
227  JEVOIS_TRACE(1);
228 
229  fd_set rfds; // For new images captured
230  fd_set efds; // For errors
231  struct timeval tv;
232 
233  // Switch to running state:
234  itsRunning.store(true);
235 
236  // We may have to wait until the device is opened:
237  while (itsFd == -1) std::this_thread::sleep_for(std::chrono::milliseconds(1));
238 
239  LDEBUG("run() thread ready");
240 
241  // NOTE: The flow is a little complex here, the goal is to minimize latency between a frame being captured and us
242  // dequeueing it from the driver and making it available to get(). To achieve low latency, we thus need to be polling
243  // the driver most of the time, and we need to prevent other threads from doing various ioctls while we are polling,
244  // as the SUNXI-VFE driver does not like that. Thus, there is high contention on itsMtx which we lock most of the
245  // time. For this reason we do a bit of sleeping with itsMtx unlocked at places where we know it will not increase our
246  // captured image delivery latency.
247  std::vector<size_t> doneidx;
248 
249  // Wait for event from the gadget kernel driver and process them:
250  while (itsRunning.load())
251  try
252  {
253  // Requeue any done buffer. To avoid having to use a double lock on itsOutputMtx (for itsDoneIdx) and itsMtx (for
254  // itsBuffers->qbuf()), we just swap itsDoneIdx into a local variable here, and invalidate it, with itsOutputMtx
255  // locked, then we will do the qbuf() later, if needed, while itsMtx is locked:
256  {
257  std::lock_guard<std::mutex> _(itsOutputMtx);
258  if (itsDoneIdx.empty() == false) itsDoneIdx.swap(doneidx);
259  }
260 
261  std::unique_lock<std::timed_mutex> lck(itsMtx);
262 
263  // Do the actual qbuf of any done buffer, ignoring any exception:
264  for (size_t idx : doneidx) try { itsBuffers->qbuf(idx); } catch (...) { jevois::warnAndIgnoreException(); }
265  doneidx.clear();
266 
267  // SUNXI-VFE does not like to be polled when not streaming; if indeed we are not streaming, unlock and then sleep
268  // a bit to avoid too much contention on itsMtx:
269  if (itsStreaming.load() == false)
270  {
271  lck.unlock();
272  std::this_thread::sleep_for(std::chrono::milliseconds(5));
273  continue;
274  }
275 
276  // Poll the device to wait for any new captured video frame:
277  FD_ZERO(&rfds); FD_ZERO(&efds); FD_SET(itsFd, &rfds); FD_SET(itsFd, &efds);
278  tv.tv_sec = 0; tv.tv_usec = 5000;
279 
280  int ret = select(itsFd + 1, &rfds, nullptr, &efds, &tv);
281  if (ret == -1) { PLERROR("Select error"); if (errno == EINTR) continue; else break; }
282  else if (ret > 0) // NOTE: ret == 0 would mean timeout
283  {
284  if (FD_ISSET(itsFd, &efds)) LFATAL("Camera device error");
285 
286  if (FD_ISSET(itsFd, &rfds))
287  {
288  // A new frame has been captured. Dequeue a buffer from the camera driver:
289  struct v4l2_buffer buf;
290  itsBuffers->dqbuf(buf);
291 
292  // Create a RawImage from that buffer:
293  jevois::RawImage img;
294  img.width = itsFormat.fmt.pix.width;
295  img.height = itsFormat.fmt.pix.height;
296  img.fmt = itsFormat.fmt.pix.pixelformat;
297  img.fps = itsFps;
298  img.buf = itsBuffers->get(buf.index);
299  img.bufindex = buf.index;
300 
301  // Unlock itsMtx:
302  lck.unlock();
303 
304  // We want to never block waiting for people to consume our grabbed frames here, hence we just overwrite our
305  // output image here, it just always contains the latest grabbed image:
306  {
307  std::lock_guard<std::mutex> _(itsOutputMtx);
308  itsOutputImage = img;
309  }
310  LDEBUG("Captured image " << img.bufindex << " ready for processing");
311 
312  // Let anyone trying to get() our image know it's here:
313  itsOutputCondVar.notify_all();
314 
315  // This is also a good time to sleep a bit since it will take a while for the next frame to arrive, this
316  // should allow people who had been trying to get a lock on itsMtx to get it now:
317  std::this_thread::sleep_for(std::chrono::milliseconds(5));
318  }
319  }
320  } catch (...) { jevois::warnAndIgnoreException(); }
321 
322  // Switch out of running state in case we did interrupt the loop here by a break statement:
323  itsRunning.store(false);
324 }
325 
326 // ##############################################################################################################
328 {
329  JEVOIS_TRACE(2);
330 
331  LDEBUG("Turning on camera stream");
332 
333  JEVOIS_TIMED_LOCK(itsMtx);
334 
335  if (itsStreaming.load() || itsBuffers) { LERROR("Stream is already on -- IGNORED"); return; }
336 
337  itsStreaming.store(false); // just in case user forgot to call abortStream()
338 
339  // If number of buffers is zero, adjust it depending on frame size:
340  unsigned int nbuf = itsNbufs;
341  if (nbuf == 0)
342  {
343  unsigned int framesize = jevois::v4l2ImageSize(itsFormat.fmt.pix.pixelformat, itsFormat.fmt.pix.width,
344  itsFormat.fmt.pix.height);
345 
346  // Aim for about 4 mbyte when using small images, and no more than 5 buffers in any case:
347  nbuf = (4U * 1024U * 1024U) / framesize;
348  if (nbuf > 5) nbuf = 5;
349  }
350 
351  // Force number of buffers to a sane value:
352  if (nbuf < 3) nbuf = 3; else if (nbuf > 63) nbuf = 63;
353 
354  // Allocate the buffers for our current video format:
355  itsBuffers = new jevois::VideoBuffers("camera", itsFd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nbuf);
356  LINFO(itsBuffers->size() << " buffers of " << itsBuffers->get(0)->length() << " bytes allocated");
357 
358  // Enqueue all our buffers:
359  itsBuffers->qbufall();
360  LDEBUG("All buffers queued to camera driver");
361 
362  // Start streaming at the device level:
363  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
364  XIOCTL(itsFd, VIDIOC_STREAMON, &type);
365  LDEBUG("Device stream on");
366 
367  itsStreaming.store(true);
368  LDEBUG("Streaming is on");
369 }
370 
371 // ##############################################################################################################
373 {
374  JEVOIS_TRACE(2);
375 
376  // Set its Streaming to false here while unlocked, which will introduce some sleeping in our run() thread, thereby
377  // helping us acquire our needed double lock:
378  itsStreaming.store(false);
379 
380  // Unblock any get() that is waiting on itsOutputCondVar, it will then throw now that streaming is off:
381  itsOutputCondVar.notify_all();
382 }
383 
384 // ##############################################################################################################
386 {
387  JEVOIS_TRACE(2);
388 
389  // Note: we allow for several streamOff() without complaining, this happens, e.g., when destroying a Camera that is
390  // not currently streaming.
391 
392  LDEBUG("Turning off camera stream");
393 
394  // Abort stream in case it was not already done, which will introduce some sleeping in our run() thread, thereby
395  // helping us acquire our needed double lock:
396  abortStream();
397 
398  // We need a double lock here so that we can both turn off the stream and nuke our output image and done idx:
399  std::unique_lock<std::timed_mutex> lk1(itsMtx, std::defer_lock);
400  std::unique_lock<std::mutex> lk2(itsOutputMtx, std::defer_lock);
401  std::lock(lk1, lk2);
402 
403  // Invalidate our output image:
404  itsOutputImage.invalidate();
405 
406  // User may have called done() but our run() thread has not yet gotten to requeueing this image, if so requeue it here
407  // as it seems to keep the driver happier:
408  if (itsBuffers)
409  for (size_t idx : itsDoneIdx) try { itsBuffers->qbuf(idx); } catch (...) { jevois::warnAndIgnoreException(); }
410  itsDoneIdx.clear();
411 
412  // Stop streaming at the device level:
413  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
414  try { XIOCTL_QUIET(itsFd, VIDIOC_STREAMOFF, &type); } catch (...) { }
415 
416  // Nuke all the buffers:
417  if (itsBuffers) { delete itsBuffers; itsBuffers = nullptr; }
418 
419  // Unblock any get() that is waiting on itsOutputCondVar, it will then throw now that streaming is off:
420  lk2.unlock();
421  itsOutputCondVar.notify_all();
422 
423  LDEBUG("Camera stream is off");
424 }
425 
426 // ##############################################################################################################
428 {
429  JEVOIS_TRACE(4);
430 
431  if (itsConvertedOutputImage.valid())
432  {
433  // We need to convert from Bayer to YUYV:
434  std::unique_lock<std::mutex> ulck(itsOutputMtx);
435  itsOutputCondVar.wait(ulck, [&]() { return itsOutputImage.valid() || itsStreaming.load() == false; });
436  if (itsStreaming.load() == false) { LDEBUG("Not streaming"); throw std::runtime_error("Camera not streaming"); }
437  jevois::rawimage::convertBayerToYUYV(itsOutputImage, itsConvertedOutputImage);
438  img = itsConvertedOutputImage;
439  img.bufindex = itsOutputImage.bufindex;
440  itsOutputImage.invalidate();
441  }
442  else
443  {
444  // Regular get() with no conversion:
445  std::unique_lock<std::mutex> ulck(itsOutputMtx);
446  itsOutputCondVar.wait(ulck, [&]() { return itsOutputImage.valid() || itsStreaming.load() == false; });
447  if (itsStreaming.load() == false) { LDEBUG("Not streaming"); throw std::runtime_error("Camera not streaming"); }
448  img = itsOutputImage;
449  itsOutputImage.invalidate();
450  }
451 
452  LDEBUG("Camera image " << img.bufindex << " handed over to processing");
453 }
454 
455 // ##############################################################################################################
457 {
458  JEVOIS_TRACE(4);
459 
460  if (itsStreaming.load() == false)
461  { LDEBUG("Not streaming"); throw std::runtime_error("Camera done() rejected while not streaming"); }
462 
463  // To avoid blocking for a long time here, we do not try to lock itsMtx and to qbuf() the buffer right now, instead we
464  // just make a note that this buffer is available and it will be requeued by our run() thread:
465  std::lock_guard<std::mutex> _(itsOutputMtx);
466  itsDoneIdx.push_back(img.bufindex);
467 
468  LDEBUG("Image " << img.bufindex << " freed by processing");
469 }
470 
471 // ##############################################################################################################
472 void jevois::Camera::queryControl(struct v4l2_queryctrl & qc) const
473 {
474  XIOCTL_QUIET(itsFd, VIDIOC_QUERYCTRL, &qc);
475 }
476 
477 // ##############################################################################################################
478 void jevois::Camera::queryMenu(struct v4l2_querymenu & qm) const
479 {
480  XIOCTL_QUIET(itsFd, VIDIOC_QUERYMENU, &qm);
481 }
482 
483 // ##############################################################################################################
484 void jevois::Camera::getControl(struct v4l2_control & ctrl) const
485 {
486 #ifdef JEVOIS_PLATFORM
487  XIOCTL(itsFd, 0xc00c561b /* should be VIDIOC_G_CTRL, bug in kernel headers? */, &ctrl);
488 #else
489  XIOCTL(itsFd, VIDIOC_G_CTRL, &ctrl);
490 #endif
491 }
492 
493 // ##############################################################################################################
494 void jevois::Camera::setControl(struct v4l2_control const & ctrl)
495 {
496 #ifdef JEVOIS_PLATFORM
497  XIOCTL(itsFd, 0xc00c561c /* should be VIDIOC_S_CTRL, bug in kernel headers? */, &ctrl);
498 #else
499  XIOCTL(itsFd, VIDIOC_S_CTRL, &ctrl);
500 #endif
501 }
502 
503 // ##############################################################################################################
504 void jevois::Camera::writeRegister(unsigned short reg, unsigned short val)
505 {
506  unsigned short data[2] = { reg, val };
507 
508  LDEBUG("Writing 0x" << std::hex << val << " to 0x" << reg);
509  XIOCTL(itsFd, _IOW('V', 192, int), data);
510 }
511 
512 // ##############################################################################################################
513 unsigned short jevois::Camera::readRegister(unsigned short reg)
514 {
515  unsigned short data[2] = { reg, 0 };
516 
517  XIOCTL(itsFd, _IOWR('V', 193, int), data);
518  LDEBUG("Register 0x" << std::hex << reg << " has value 0x" << data[1]);
519  return data[1];
520 }
521 
522 // ##############################################################################################################
523 void jevois::Camera::writeIMUregister(unsigned short reg, unsigned short val)
524 {
525  unsigned short data[2] = { reg, val };
526 
527  LDEBUG("Writing 0x" << std::hex << val << " to 0x" << reg);
528  XIOCTL(itsFd, _IOW('V', 194, int), data);
529 }
530 
531 // ##############################################################################################################
532 unsigned short jevois::Camera::readIMUregister(unsigned short reg)
533 {
534  unsigned short data[2] = { reg, 0 };
535 
536  XIOCTL(itsFd, _IOWR('V', 195, int), data);
537  LDEBUG("Register 0x" << std::hex << reg << " has value 0x" << data[1]);
538  return data[1];
539 }
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level. ...
Definition: Log.H:155
std::string warnAndIgnoreException()
Convenience function to catch an exception, issue some LERROR (depending on type), and ignore it.
Definition: Log.C:211
~Camera()
Close the device and free all resources.
Definition: Camera.C:208
void queryControl(struct v4l2_queryctrl &qc) const override
Get information about a control, throw if unsupported by hardware.
Definition: Camera.C:472
void dqbuf(struct v4l2_buffer &buf)
Dequeue the next captured/displayed buffer, blocks until one is available.
Definition: VideoBuffers.C:133
unsigned int height
Image height in pixels.
Definition: RawImage.H:146
static struct v4l2_fract fpsToV4l2(float fps)
Convert from fps to V4L2 interval.
Definition: VideoMapping.C:65
void getControl(struct v4l2_control &ctrl) const
Get a control&#39;s current value, throw if unsupported by hardware.
Definition: Camera.C:484
void streamOff() override
Stop streaming.
Definition: Camera.C:385
void setFormat(VideoMapping const &m) override
Set the video format and frame rate.
Definition: Camera.C:112
unsigned int fmt
Pixel format as a V4L2_PIX_FMT_XXX.
Definition: RawImage.H:147
#define XIOCTL_QUIET(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error throw quietly.
std::shared_ptr< VideoBuf > buf
The pixel data buffer.
Definition: RawImage.H:149
#define JEVOIS_TIMED_LOCK(mtx)
Helper macro to create a timed_lock_guard object.
Definition: Log.H:299
void streamOn() override
Start streaming.
Definition: Camera.C:327
void invalidate()
Invalidate the image by zero&#39;ing out the pointer to pixel buffer and the dims and format...
Definition: RawImage.C:42
void abortStream() override
Abort streaming.
Definition: Camera.C:372
unsigned int const itsNbufs
Our number of buffers.
Definition: VideoInput.H:107
#define JEVOIS_TRACE(level)
Trace object.
Definition: Log.H:267
#define PLFATAL(msg)
Like LDEBUG but appends errno and strerror(errno), to be used when some system call fails...
Definition: Log.H:221
void setControl(struct v4l2_control const &ctrl) override
Set a control, throw if control not supported or the hardware rejects the value.
Definition: Camera.C:494
void done(RawImage &img) override
Indicate that user processing is done with an image previously obtained via get() ...
Definition: Camera.C:456
unsigned short readIMUregister(unsigned short reg) override
Read a value from one of the camera&#39;s IMU registers.
Definition: Camera.C:532
bool valid() const
Check whether the image has a valid pixel buffer.
Definition: RawImage.C:46
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level. ...
Definition: Log.H:193
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
unsigned int ch
camera height
Definition: VideoMapping.H:52
Collection of buffers for V4L2 video frames (Camera or Gadget) with hooks to the MMAP&#39;d areas...
Definition: VideoBuffers.H:41
unsigned short readRegister(unsigned short reg) override
Read a value from one of the camera&#39;s registers.
Definition: Camera.C:513
size_t size() const
Get the number of buffers allocated.
Definition: VideoBuffers.C:80
Camera(std::string const &devname, unsigned int const nbufs=0)
Construct and open the device.
Definition: Camera.C:57
Simple struct to hold video mapping definitions for the processing Engine.
Definition: VideoMapping.H:43
void queryMenu(struct v4l2_querymenu &qm) const override
Get the available menu entry names for a menu-type control, throw if unsupported by hardware...
Definition: Camera.C:478
#define XIOCTL(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error, issue a fatal message and thro...
std::shared_ptr< VideoBuf > get(size_t const index) const
Get one buffer, by index [0 .. size()[.
Definition: VideoBuffers.C:92
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
Definition: Utils.C:39
Base class for video input, which will get derived into Camera and MovieInput.
Definition: VideoInput.H:31
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:212
unsigned int v4l2ImageSize(unsigned int fcc, unsigned int width, unsigned int height)
Return the image size in bytes for a given V4L2_PIX_FMT_..., width, height.
Definition: Utils.C:108
void qbuf(size_t const index)
Queue one buffer to V4L2, by index [0 .. size()[.
Definition: VideoBuffers.C:100
unsigned int cfmt
camera pixel format
Definition: VideoMapping.H:50
unsigned int cw
camera width
Definition: VideoMapping.H:51
float fps
Programmed frames/s as given by current video mapping, may not be actual.
Definition: RawImage.H:148
unsigned int bytesize() const
Helper function to get the total number of bytes in the RawImage, i.e., width * height * bytesperpix(...
Definition: RawImage.C:38
void writeIMUregister(unsigned short reg, unsigned short val) override
Write a value to one of the camera&#39;s IMU registers.
Definition: Camera.C:523
void qbufall()
Queue all buffers, typically used when starting streaming on capture devices.
Definition: VideoBuffers.C:127
#define PLERROR(msg)
Like LERROR but appends errno and strerror(errno), to be used when some system call fails...
Definition: Log.H:201
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:176
size_t bufindex
The index of the data buffer in the kernel driver.
Definition: RawImage.H:150
unsigned int width
Image width in pixels.
Definition: RawImage.H:145
float cfps
camera frame rate in frames/sec
Definition: VideoMapping.H:53
void writeRegister(unsigned short reg, unsigned short val) override
Write a value to one of the camera&#39;s registers.
Definition: Camera.C:504
void get(RawImage &img) override
Get the next captured buffer.
Definition: Camera.C:427
void convertBayerToYUYV(RawImage const &src, RawImage &dst)
Convert from Bayer to YUYV, only used internally by Camera class.
Definition: RawImageOps.C:1576