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