if (m_querycap.capabilities & V4L2_CAP_STREAMING) {
v4l2_requestbuffers reqbuf;
- if (reqbufs_user_cap(reqbuf))
+ if (reqbufs_user_cap(reqbuf, 1))
m_capMethods->addItem("User pointer I/O", QVariant(methodUser));
- if (reqbufs_mmap_cap(reqbuf))
+ if (reqbufs_mmap_cap(reqbuf, 1))
m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap));
}
if (m_querycap.capabilities & V4L2_CAP_READWRITE) {
case methodMmap:
if (!dqbuf_mmap_cap(buf)) {
error("dqbuf");
+ m_capStartAct->setChecked(false);
return;
}
case methodUser:
if (!dqbuf_user_cap(buf)) {
error("dqbuf");
+ m_capStartAct->setChecked(false);
return;
}
m_capture->setImage(*m_capImage);
}
-void ApplicationWindow::startCapture(unsigned buffer_size)
+bool ApplicationWindow::startCapture(unsigned buffer_size)
{
unsigned int i;
v4l2_requestbuffers req;
switch (m_capMethod) {
case methodRead:
/* Nothing to do. */
- return;
+ return true;
case methodMmap:
if (!reqbufs_mmap_cap(req, 3)) {
buf.memory = V4L2_MEMORY_MMAP;
buf.index = m_nbuffers;
- if (-1 == ioctl(VIDIOC_QUERYBUF, &buf))
+ if (-1 == ioctl(VIDIOC_QUERYBUF, &buf)) {
perror("VIDIOC_QUERYBUF");
+ goto error;
+ }
m_buffers[m_nbuffers].length = buf.length;
m_buffers[m_nbuffers].start = mmap(buf.length, buf.m.offset);
- if (MAP_FAILED == m_buffers[m_nbuffers].start)
+ if (MAP_FAILED == m_buffers[m_nbuffers].start) {
perror("mmap");
+ goto error;
+ }
}
- for (i = 0; i < m_nbuffers; ++i)
- qbuf_mmap_cap(i);
- if (!streamon_cap())
+ for (i = 0; i < m_nbuffers; ++i) {
+ if (!qbuf_mmap_cap(i)) {
+ perror("VIDIOC_QBUF");
+ goto error;
+ }
+ }
+ if (!streamon_cap()) {
perror("VIDIOC_STREAMON");
- return;
+ goto error;
+ }
+ return true;
case methodUser:
- if (!reqbufs_user_cap(req)) {
+ if (!reqbufs_user_cap(req, 4)) {
error("Cannot capture");
break;
}
+ if (req.count < 4) {
+ error("Too few buffers");
+ reqbufs_user_cap(req);
+ break;
+ }
+
m_buffers = (buffer *)calloc(4, sizeof(*m_buffers));
if (!m_buffers) {
if (!m_buffers[m_nbuffers].start) {
error("Out of memory");
- break;
+ goto error;
}
}
for (i = 0; i < m_nbuffers; ++i)
- qbuf_user_cap(m_buffers[i].start, m_buffers[i].length);
- if (!streamon_cap())
+ if (!qbuf_user_cap(i, m_buffers[i].start, m_buffers[i].length)) {
+ perror("VIDIOC_QBUF");
+ goto error;
+ }
+ if (!streamon_cap()) {
perror("VIDIOC_STREAMON");
- return;
+ goto error;
+ }
+ return true;
}
+error:
m_capStartAct->setChecked(false);
+ return false;
}
void ApplicationWindow::stopCapture()
m_capImage->fill(0);
m_capture->setImage(*m_capImage, true);
m_capture->show();
- startCapture(m_capSrcFormat.fmt.pix.sizeimage);
- m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs);
- connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capFrame()));
+ if (startCapture(m_capSrcFormat.fmt.pix.sizeimage)) {
+ m_capNotifier = new QSocketNotifier(fd(), QSocketNotifier::Read, m_tabs);
+ connect(m_capNotifier, SIGNAL(activated(int)), this, SLOT(capFrame()));
+ }
}
void ApplicationWindow::closeDevice()
private:
CaptureWin *m_capture;
- void startCapture(unsigned buffer_size);
+ bool startCapture(unsigned buffer_size);
void stopCapture();
void startOutput(unsigned buffer_size);
void stopOutput();
return ioctl(VIDIOC_ENUM_FRAMEINTERVALS, &frm) >= 0;
}
-bool v4l2::reqbufs_user_cap(v4l2_requestbuffers &reqbuf)
+bool v4l2::reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count)
{
memset(&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_USERPTR;
+ reqbuf.count = count;
return ioctl(VIDIOC_REQBUFS, &reqbuf) >= 0;
}
bool v4l2::dqbuf_mmap_cap(v4l2_buffer &buf)
{
memset(&buf, 0, sizeof(buf));
-
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
return ioctl(VIDIOC_DQBUF, &buf) >= 0;
bool v4l2::dqbuf_user_cap(v4l2_buffer &buf)
{
memset(&buf, 0, sizeof(buf));
-
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
return ioctl(VIDIOC_DQBUF, &buf) >= 0;
{
v4l2_buffer buf;
+ memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = index;
return qbuf(buf);
}
-bool v4l2::qbuf_user_cap(void *ptr, int length)
+bool v4l2::qbuf_user_cap(int index, void *ptr, int length)
{
v4l2_buffer buf;
+ memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_USERPTR;
buf.m.userptr = (unsigned long)ptr;
buf.length = length;
+ buf.index = index;
return qbuf(buf);
}
bool v4l2::dqbuf_mmap_out(v4l2_buffer &buf)
{
memset(&buf, 0, sizeof(buf));
-
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_MMAP;
return ioctl("dqbuf", VIDIOC_DQBUF, &buf);
bool v4l2::dqbuf_user_out(v4l2_buffer &buf)
{
memset(&buf, 0, sizeof(buf));
-
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_USERPTR;
return ioctl(VIDIOC_DQBUF, &buf) >= 0;
bool enum_frameintervals(v4l2_frmivalenum &frm, __u32 init_pixfmt = 0, __u32 w = 0, __u32 h = 0, int index = 0);
bool reqbufs_mmap_cap(v4l2_requestbuffers &reqbuf, int count = 0);
- bool reqbufs_user_cap(v4l2_requestbuffers &reqbuf);
+ bool reqbufs_user_cap(v4l2_requestbuffers &reqbuf, int count = 0);
bool dqbuf_mmap_cap(v4l2_buffer &buf);
bool dqbuf_user_cap(v4l2_buffer &buf);
bool qbuf(v4l2_buffer &buf);
bool qbuf_mmap_cap(int index);
- bool qbuf_user_cap(void *ptr, int length);
+ bool qbuf_user_cap(int index, void *ptr, int length);
bool streamon_cap();
bool streamoff_cap();