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