JeVois  1.0
JeVois Smart Embedded Machine Vision Toolkit
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),
58  itsDoneIdx(itsInvalidIdx), itsRunning(false)
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  JEVOIS_TIMED_LOCK(itsMtx);
117 
118  // Get current format:
119  itsFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
120  XIOCTL(itsFd, VIDIOC_G_FMT, &itsFormat);
121 
122  // Set desired format:
123  itsFormat.fmt.pix.width = m.cw;
124  itsFormat.fmt.pix.height = m.ch;
125  itsFormat.fmt.pix.pixelformat = m.cfmt;
126  itsFormat.fmt.pix.field = V4L2_FIELD_NONE;
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 
219  // Wait for event from the gadget kernel driver and process them:
220  while (itsRunning.load())
221  try
222  {
223  // Requeue any done buffer. To avoid having to use a double lock on itsOutputMtx (for itsDoneIdx) and itsMtx (for
224  // itsBuffers->qbuf()), we just copy itsDoneIdx into a local variable here, and invalidate it, with itsOutputMtx
225  // locked, then we will do the qbuf() later, if needed, while itsMtx is locked:
226  size_t doneidx;
227  {
228  std::lock_guard<std::mutex> _(itsOutputMtx);
229  doneidx = itsDoneIdx;
230  itsDoneIdx = itsInvalidIdx;
231  }
232 
233  std::unique_lock<std::timed_mutex> lck(itsMtx);
234 
235  // Do the actual qbuf of any done buffer:
236  if (doneidx != itsInvalidIdx) itsBuffers->qbuf(doneidx);
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.buf = itsBuffers->get(buf.index);
269  img.bufindex = buf.index;
270 
271  // Unlock itsMtx:
272  lck.unlock();
273 
274  // We want to never block waiting for people to consume our grabbed frames here, hence we just overwrite our
275  // output image here, it just always contains the latest grabbed image:
276  {
277  std::lock_guard<std::mutex> _(itsOutputMtx);
278  itsOutputImage = img;
279  }
280  LDEBUG("Captured image " << img.bufindex << " ready for processing");
281 
282  // Let anyone trying to get() our image know it's here:
283  itsOutputCondVar.notify_all();
284 
285  // This is also a good time to sleep a bit since it will take a while for the next frame to arrive, this
286  // should allow people who had been trying to get a lock on itsMtx to get it now:
287  std::this_thread::sleep_for(std::chrono::milliseconds(5));
288  }
289  }
290  } catch (...) { jevois::warnAndIgnoreException(); }
291 
292  // Switch out of running state in case we did interrupt the loop here by a break statement:
293  itsRunning.store(false);
294 }
295 
296 // ##############################################################################################################
298 {
299  JEVOIS_TRACE(2);
300 
301  LDEBUG("Turning on camera stream");
302 
303  JEVOIS_TIMED_LOCK(itsMtx);
304 
305  if (itsStreaming.load() || itsBuffers) { LERROR("Stream is already on -- IGNORED"); return; }
306 
307  itsStreaming.store(false); // just in case user forgot to call abortStream()
308 
309  // If number of buffers is zero, adjust it depending on frame size:
310  unsigned int nbuf = itsNbufs;
311  if (nbuf == 0)
312  {
313  unsigned int framesize = jevois::v4l2ImageSize(itsFormat.fmt.pix.pixelformat, itsFormat.fmt.pix.width,
314  itsFormat.fmt.pix.height);
315 
316  // Aim for about 4 mbyte when using small images:
317  nbuf = (4U * 1024U * 1024U) / framesize;
318  }
319 
320  // Force number of buffers to a sane value:
321  if (nbuf < 3) nbuf = 3; else if (nbuf > 63) nbuf = 63;
322 
323  // Allocate the buffers for our current video format:
324  itsBuffers = new jevois::VideoBuffers("camera", itsFd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nbuf);
325  LINFO(itsBuffers->size() << " buffers of " << itsBuffers->get(0)->length() << " bytes allocated");
326 
327  // Enqueue all our buffers:
328  itsBuffers->qbufall();
329  LDEBUG("All buffers queued to camera driver");
330 
331  // Start streaming at the device level:
332  int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
333  XIOCTL(itsFd, VIDIOC_STREAMON, &type);
334  LDEBUG("Device stream on");
335 
336  itsStreaming.store(true);
337  LDEBUG("Streaming is on");
338 }
339 
340 // ##############################################################################################################
342 {
343  JEVOIS_TRACE(2);
344 
345  // Set its Streaming to false here while unlocked, which will introduce some sleeping in our run() thread, thereby
346  // helping us acquire our needed double lock:
347  itsStreaming.store(false);
348 
349  // Unblock any get() that is waiting on itsOutputCondVar, it will then throw now that streaming is off:
350  itsOutputCondVar.notify_all();
351 }
352 
353 // ##############################################################################################################
355 {
356  JEVOIS_TRACE(2);
357 
358  // Note: we allow for several streamOff() without complaining, this happens, e.g., when destroying a Camera that is
359  // not currently streaming.
360 
361  LDEBUG("Turning off camera stream");
362 
363  // Abort stream in case it was not already done, which will introduce some sleeping in our run() thread, thereby
364  // helping us acquire our needed double lock:
365  abortStream();
366 
367  // We need a double lock here so that we can both turn off the stream and nuke our output image and done idx:
368  std::unique_lock<std::timed_mutex> lk1(itsMtx, std::defer_lock);
369  std::unique_lock<std::mutex> lk2(itsOutputMtx, std::defer_lock);
370  std::lock(lk1, lk2);
371 
372  // Invalidate our output image:
373  itsOutputImage.invalidate();
374 
375  // User may have called done() but our run() thread has not yet gotten to requeueing this image, if so requeue it here
376  // as it seems to keep the driver happier:
377  if (itsDoneIdx != itsInvalidIdx && itsBuffers) itsBuffers->qbuf(itsDoneIdx);
378  itsDoneIdx = itsInvalidIdx;
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  {
421  std::lock_guard<std::mutex> _(itsOutputMtx);
422  if (itsDoneIdx != itsInvalidIdx) LFATAL("Previous done() image not yet recycled by driver");
423  itsDoneIdx = img.bufindex;
424  }
425 
426  LDEBUG("Image " << img.bufindex << " freed by processing");
427 }
428 
429 // ##############################################################################################################
430 void jevois::Camera::queryControl(struct v4l2_queryctrl & qc) const
431 {
432  XIOCTL_QUIET(itsFd, VIDIOC_QUERYCTRL, &qc);
433 }
434 
435 // ##############################################################################################################
436 void jevois::Camera::queryMenu(struct v4l2_querymenu & qm) const
437 {
438  XIOCTL_QUIET(itsFd, VIDIOC_QUERYMENU, &qm);
439 }
440 
441 // ##############################################################################################################
442 void jevois::Camera::getControl(struct v4l2_control & ctrl) const
443 {
444 #ifdef JEVOIS_PLATFORM
445  XIOCTL(itsFd, 0xc00c561b /* should be VIDIOC_G_CTRL, bug in kernel headers? */, &ctrl);
446 #else
447  XIOCTL(itsFd, VIDIOC_G_CTRL, &ctrl);
448 #endif
449 }
450 
451 // ##############################################################################################################
452 void jevois::Camera::setControl(struct v4l2_control const & ctrl)
453 {
454 #ifdef JEVOIS_PLATFORM
455  XIOCTL(itsFd, 0xc00c561c /* should be VIDIOC_S_CTRL, bug in kernel headers? */, &ctrl);
456 #else
457  XIOCTL(itsFd, VIDIOC_S_CTRL, &ctrl);
458 #endif
459 }
460 
461 // ##############################################################################################################
462 void jevois::Camera::writeRegister(unsigned char reg, unsigned char val)
463 {
464  unsigned char data[2] = { reg, val };
465 
466  LINFO("Writing 0x" << std::hex << val << " to 0x" << reg);
467  XIOCTL(itsFd, _IOW('V', 192, short), data);
468 }
469 
470 // ##############################################################################################################
471 unsigned char jevois::Camera::readRegister(unsigned char reg)
472 {
473  unsigned char data[2] = { reg, 0 };
474 
475  XIOCTL(itsFd, _IOWR('V', 193, short), data);
476  LINFO("Register 0x" << std::hex << reg << " has value 0x" << data[1]);
477  return data[1];
478 }
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level. ...
Definition: Log.H:148
std::string warnAndIgnoreException()
Convenience function to catch an exception, issue some LERROR (depending on type), and ignore it.
Definition: Log.C:200
~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:430
void writeRegister(unsigned char reg, unsigned char val) override
Write a value to one of the camera's registers.
Definition: Camera.C:462
unsigned int height
Image height in pixels.
Definition: RawImage.H:140
static struct v4l2_fract fpsToV4l2(float fps)
Convert from fps to V4L2 interval.
Definition: VideoMapping.C:79
void streamOff() override
Stop streaming.
Definition: Camera.C:354
unsigned char readRegister(unsigned char reg) override
Read a value from one of the camera's registers.
Definition: Camera.C:471
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:141
#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:142
#define JEVOIS_TIMED_LOCK(mtx)
Helper macro to create a timed_lock_guard object.
Definition: Log.H:292
void streamOn() override
Start streaming.
Definition: Camera.C:297
void invalidate()
Invalidate the image by zero'ing out the pointer to pixel buffer and the dims and format...
Definition: RawImage.C:39
void abortStream() override
Abort streaming.
Definition: Camera.C:341
#define JEVOIS_TRACE(level)
Trace object.
Definition: Log.H:260
#define PLFATAL(msg)
Like LDEBUG but appends errno and strerror(errno), to be used when some system call fails...
Definition: Log.H:214
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:452
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:186
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:436
#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:32
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:205
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:61
unsigned int cfmt
camera pixel format
Definition: VideoMapping.H:48
unsigned int cw
camera width
Definition: VideoMapping.H:49
void getControl(struct v4l2_control &ctrl) const
Get a control's current value, throw if unsupported by hardware.
Definition: Camera.C:442
#define PLERROR(msg)
Like LERROR but appends errno and strerror(errno), to be used when some system call fails...
Definition: Log.H:194
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition: Log.H:169
size_t bufindex
The index of the data buffer in the kernel driver.
Definition: RawImage.H:143
unsigned int width
Image width in pixels.
Definition: RawImage.H:139
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