24#define FDLDEBUG(msg) LDEBUG('[' << itsFd << ':' << itsName << "] " << msg) 
   25#define FDLINFO(msg) LINFO('[' << itsFd << ':' << itsName << "] " << msg) 
   26#define FDLERROR(msg) LERROR('[' << itsFd << ':' << itsName << "] " << msg) 
   27#define FDLFATAL(msg) LFATAL('[' << itsFd << ':' << itsName << "] " << msg) 
   31    itsFd(fd), itsName(name), itsType(type), itsNqueued(0)
 
   34  struct v4l2_requestbuffers req = { };
 
   37  req.memory = V4L2_MEMORY_MMAP;
 
   38  XIOCTL(fd, VIDIOC_REQBUFS, &req);
 
   39  FDLDEBUG(
"Reqbufs for " << num << 
" buffers returned " << req.count << 
" buffers");
 
   42  for (
unsigned int i = 0; i < req.count; ++i)
 
   44    struct v4l2_buffer buf = { };
 
   45    struct v4l2_plane plane = { };
 
   47    buf.memory = V4L2_MEMORY_MMAP;
 
   50    if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
   54      buf.m.planes = &plane;
 
   56      try { 
XIOCTL(fd, VIDIOC_QUERYBUF, &buf); } 
catch (...) { 
FDLFATAL(
"Failed to request buffers"); }
 
   57      if (buf.length != 1) 
LFATAL(
"Only one V4L2 plane is supported for now, i.e., only packed video formats.");
 
   62      try { 
XIOCTL(fd, VIDIOC_QUERYBUF, &buf); } 
catch (...) { 
FDLFATAL(
"Failed to request buffers"); }
 
   69    struct v4l2_exportbuffer ex_buf = { };
 
   76    try { 
XIOCTL(fd, VIDIOC_EXPBUF, &ex_buf); } 
catch (...) { 
FDLDEBUG(
"Could not get dma_buf fd for buffer " << i); }
 
   80    if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
   81      itsBuffers.push_back(std::make_shared<jevois::VideoBuf>(fd, buf.m.planes[0].length,
 
   82                                                              buf.m.planes[0].m.mem_offset, dmafd));
 
   84      itsBuffers.push_back(std::make_shared<jevois::VideoBuf>(fd, buf.length, buf.m.offset, dmafd));
 
   86    FDLDEBUG(
"Added mmap'd buffer " << i << 
" of size " << buf.length);
 
 
   93  if (itsNqueued) 
FDLDEBUG(itsNqueued << 
" buffers are still queued...");
 
   96  for (
auto & b : itsBuffers)
 
   98    if (b.use_count() > 1) 
FDLDEBUG(
"Ref count non zero when attempting to free VideoBuf");
 
  106  struct v4l2_requestbuffers req = { };
 
  109  req.memory = V4L2_MEMORY_MMAP;
 
  111  catch (...) { 
FDLDEBUG(
"Error trying to free V4L2 buffers -- IGNORED"); }
 
 
  117  return itsBuffers.size();
 
 
  129  if (index >= itsBuffers.size()) 
FDLFATAL(
"Index " << index << 
" out of range [0.." << itsBuffers.size() << 
']');
 
  131  return itsBuffers[index];
 
 
  137  if (itsType == V4L2_BUF_TYPE_VIDEO_OUTPUT) 
FDLFATAL(
"Cannot enqueue output buffers by index");
 
  138  if (itsNqueued == itsBuffers.size())
 
  139    throw std::runtime_error(
'[' + std::to_string(itsFd) + 
':' + itsName + 
"] All buffers have already been queued");
 
  141  struct v4l2_buffer buf = { };
 
  143  buf.memory = V4L2_MEMORY_MMAP;
 
  146  if (itsType == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
  148    struct v4l2_plane plane = { };
 
  150    buf.m.planes = &plane;
 
 
  161  if (itsNqueued == itsBuffers.size())
 
  162    throw std::runtime_error(
'[' + std::to_string(itsFd) + 
':' + itsName + 
"] All buffers have already been queued");
 
 
  172  for (
unsigned int i = 0; i < itsBuffers.size(); ++i) qbuf(i);
 
 
  178  for (
unsigned int i = 0; i < itsBuffers.size(); ++i)
 
  179    if (i != index) 
try { qbuf(i); } 
catch (...) { }
 
 
  185  if (itsNqueued == 0) 
FDLFATAL(
"No buffer is currently queued");
 
  187  memset(&buf, 0, 
sizeof(
struct v4l2_buffer));
 
  189  buf.memory = V4L2_MEMORY_MMAP;
 
  191  if (itsType == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 
  193    struct v4l2_plane plane = { };
 
  195    buf.m.planes = &plane;
 
 
  210  struct v4l2_buffer buf;
 
  214  while (itsNqueued && retry-- >= 0)
 
  216    try { dqbuf(buf); } 
catch (...) { std::this_thread::sleep_for(std::chrono::milliseconds(5)); }
 
 
std::shared_ptr< VideoBuf > get(size_t const index) const
Get one buffer, by index [0 .. size()[.
void dqbufall()
Dequeue all buffers, typically used when stopping a stream, not that this may take some time.
void qbufall()
Queue all buffers, typically used when starting streaming on capture devices.
size_t nqueued() const
Get the number of buffers queued, this is always in [0 .. size()[.
size_t size() const
Get the number of buffers allocated.
void qbufallbutone(size_t const index)
Queue all buffers that are not already queued except one specified.
void qbuf(size_t const index)
Queue one buffer to V4L2, by index [0 .. size()[.
~VideoBuffers()
Free the MMAP'd memory area.
VideoBuffers(char const *name, int const fd, v4l2_buf_type type, size_t const num=4)
Construct and allocate MMAP'd video buffers.
void dqbuf(struct v4l2_buffer &buf)
Dequeue the next captured/displayed buffer, blocks until one is available.
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
#define XIOCTL_QUIET_ONCE(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error throw quietly.
#define XIOCTL_QUIET(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error throw quietly.
#define XIOCTL(dev, req, mem)
Helper macro to execute an ioctl, ignore interruptions, and, if error, issue a fatal message and thro...