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...