changed to a more OO style interface; dequeueBuffer() still blocks indefinitely
git-svn-id: svn://anubis/misc/WebcamTracker@124 bd8a9e45-a331-0410-811e-c64571078777
This commit is contained in:
parent
5a72b568b9
commit
3f048de88d
328
WebcamTracker.cc
328
WebcamTracker.cc
@ -14,164 +14,226 @@ using namespace std;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
WebcamTracker("/dev/video0");
|
||||
WebcamTracker wt;
|
||||
wt.open("/dev/video0");
|
||||
wt.start();
|
||||
}
|
||||
|
||||
WebcamTracker::WebcamTracker(const char * device)
|
||||
WebcamTracker::WebcamTracker()
|
||||
{
|
||||
m_open = false;
|
||||
m_fd = open(device, O_RDWR);
|
||||
m_buffers = NULL;
|
||||
m_lengths = NULL;
|
||||
}
|
||||
|
||||
bool WebcamTracker::open(const char * device)
|
||||
{
|
||||
m_fd = ::open(device, O_RDWR);
|
||||
if (m_fd >= 0)
|
||||
{
|
||||
m_open = true;
|
||||
|
||||
struct v4l2_capability cap;
|
||||
int ret = ioctl(m_fd, VIDIOC_QUERYCAP, &cap);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QUERYCAP ioctl failed: " << ret << endl;
|
||||
perror("VIDIOC_QUERYCAP");
|
||||
}
|
||||
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
|
||||
else
|
||||
{
|
||||
cerr << "Warning: V4L2_CAP_VIDEO_CAPTURE not supported!" << endl;
|
||||
if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)
|
||||
{
|
||||
m_open = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Warning: V4L2_CAP_VIDEO_CAPTURE not supported!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
v4l2_requestbuffers reqbuf;
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
reqbuf.count = 1;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_REQBUFS ioctl failed: returned " << ret
|
||||
<< ", errno " << errno;
|
||||
if (errno == EBUSY)
|
||||
cerr << " (EBUSY)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
struct v4l2_buffer buf;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.index = 0;
|
||||
ret = ioctl(m_fd, VIDIOC_QUERYBUF, &buf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QUERYBUF ioctl failed: returned " << ret
|
||||
<< ", errno: " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
m_vidbuflen = buf.length;
|
||||
m_vidbuf = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
m_fd, buf.m.offset);
|
||||
if (m_vidbuf == MAP_FAILED)
|
||||
{
|
||||
cerr << "mmap() failed: errno " << errno;
|
||||
if (errno == EBADF)
|
||||
cerr << " (EBADF)";
|
||||
if (errno == EACCES)
|
||||
cerr << " (EACCES)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
v4l2_buffer qbuf;
|
||||
qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
qbuf.memory = V4L2_MEMORY_MMAP;
|
||||
qbuf.index = 0;
|
||||
ret = ioctl(m_fd, VIDIOC_QBUF, &qbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QBUF failed! errno = " << errno;
|
||||
if (errno == EAGAIN)
|
||||
cerr << " (EAGAIN)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
if (errno == EIO)
|
||||
cerr << " (EIO)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
ret = ioctl(m_fd, VIDIOC_STREAMON, &type);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_STREAMON ioctl failed! errno = " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
struct v4l2_buffer querybuf;
|
||||
querybuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
querybuf.index = 0;
|
||||
ret = ioctl(m_fd, VIDIOC_QUERYBUF, &querybuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QUERYBUF ioctl failed: returned " << ret
|
||||
<< ", errno: " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
if (querybuf.flags & V4L2_BUF_FLAG_DONE)
|
||||
{
|
||||
cout << "buf done" << endl;
|
||||
}
|
||||
|
||||
v4l2_buffer dqbuf;
|
||||
dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
dqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
ret = ioctl(m_fd, VIDIOC_DQBUF, &dqbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_DQBUF failed! errno = " << errno;
|
||||
if (errno == EAGAIN)
|
||||
cerr << " (EAGAIN)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
if (errno == EIO)
|
||||
cerr << " (EIO)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Could not open device '" << device << "'" << endl;
|
||||
}
|
||||
return m_open;
|
||||
}
|
||||
|
||||
void WebcamTracker::start()
|
||||
{
|
||||
requestBuffers(20);
|
||||
for (int i = 0; i < m_numbufs; i++)
|
||||
{
|
||||
mapBuffer(i);
|
||||
queueBuffer(i);
|
||||
}
|
||||
beginStreaming();
|
||||
v4l2_buffer buf;
|
||||
dequeueBuffer(&buf);
|
||||
endStreaming();
|
||||
}
|
||||
|
||||
void WebcamTracker::requestBuffers(int num)
|
||||
{
|
||||
m_numbufs = 0;
|
||||
v4l2_requestbuffers reqbuf;
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
reqbuf.count = num;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
int ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_REQBUFS ioctl failed: returned " << ret
|
||||
<< ", errno " << errno;
|
||||
if (errno == EBUSY)
|
||||
cerr << " (EBUSY)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_numbufs = reqbuf.count;
|
||||
cout << "Got " << m_numbufs << " buffers" << endl;
|
||||
m_buffers = new void *[m_numbufs];
|
||||
m_lengths = new int[m_numbufs];
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::mapBuffer(int i)
|
||||
{
|
||||
struct v4l2_buffer buf;
|
||||
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
buf.index = i;
|
||||
int ret = ioctl(m_fd, VIDIOC_QUERYBUF, &buf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QUERYBUF ioctl failed: returned " << ret
|
||||
<< ", errno: " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
m_buffers[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, m_fd, buf.m.offset);
|
||||
m_lengths[i] = buf.length;
|
||||
if (m_buffers[i] == MAP_FAILED)
|
||||
{
|
||||
cerr << "mmap() failed: errno " << errno;
|
||||
if (errno == EBADF)
|
||||
cerr << " (EBADF)";
|
||||
if (errno == EACCES)
|
||||
cerr << " (EACCES)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::queueBuffer(int i)
|
||||
{
|
||||
v4l2_buffer qbuf;
|
||||
qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
qbuf.memory = V4L2_MEMORY_MMAP;
|
||||
qbuf.index = i;
|
||||
int ret = ioctl(m_fd, VIDIOC_QBUF, &qbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_QBUF failed! errno = " << errno;
|
||||
if (errno == EAGAIN)
|
||||
cerr << " (EAGAIN)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
if (errno == EIO)
|
||||
cerr << " (EIO)";
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::beginStreaming()
|
||||
{
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
int ret = ioctl(m_fd, VIDIOC_STREAMON, &type);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_STREAMON ioctl failed! errno = " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::endStreaming()
|
||||
{
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
int ret = ioctl(m_fd, VIDIOC_STREAMOFF, &type);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_STREAMOFF ioctl failed! errno = " << errno;
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::dequeueBuffer(v4l2_buffer * dqbuf)
|
||||
{
|
||||
dqbuf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
dqbuf->memory = V4L2_MEMORY_MMAP;
|
||||
int ret = ioctl(m_fd, VIDIOC_DQBUF, dqbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "VIDIOC_DQBUF failed! errno = " << errno;
|
||||
if (errno == EAGAIN)
|
||||
cerr << " (EAGAIN)";
|
||||
if (errno == EINVAL)
|
||||
cerr << " (EINVAL)";
|
||||
if (errno == ENOMEM)
|
||||
cerr << " (ENOMEM)";
|
||||
if (errno == EIO)
|
||||
cerr << " (EIO)";
|
||||
cerr << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WebcamTracker::unmapBuffer(int i)
|
||||
{
|
||||
munmap(m_buffers[i], m_lengths[i]);
|
||||
}
|
||||
|
||||
void WebcamTracker::freeBuffers()
|
||||
{
|
||||
v4l2_requestbuffers reqbuf;
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
reqbuf.count = 0;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
int ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
|
||||
if (ret != 0)
|
||||
{
|
||||
cerr << "~WebcamTracker(): VIDIOC_REQBUFS ioctl failed: "
|
||||
<< ret << endl;
|
||||
if (errno == EBUSY)
|
||||
cerr << "EBUSY" << endl;
|
||||
if (errno == EINVAL)
|
||||
cerr << "EINVAL" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
WebcamTracker::~WebcamTracker()
|
||||
{
|
||||
if (m_open)
|
||||
{
|
||||
munmap(m_vidbuf, m_vidbuflen);
|
||||
|
||||
v4l2_requestbuffers reqbuf;
|
||||
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
reqbuf.count = 0;
|
||||
reqbuf.memory = V4L2_MEMORY_MMAP;
|
||||
int ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
|
||||
if (ret != 0)
|
||||
if (m_buffers)
|
||||
{
|
||||
cerr << "~WebcamTracker(): VIDIOC_REQBUFS ioctl failed: "
|
||||
<< ret << endl;
|
||||
if (errno == EBUSY)
|
||||
cerr << "EBUSY" << endl;
|
||||
if (errno == EINVAL)
|
||||
cerr << "EINVAL" << endl;
|
||||
for (int i = 0; i < m_numbufs; i++)
|
||||
{
|
||||
unmapBuffer(i);
|
||||
}
|
||||
delete m_buffers;
|
||||
delete m_lengths;
|
||||
freeBuffers();
|
||||
}
|
||||
close(m_fd);
|
||||
}
|
||||
|
@ -6,16 +6,29 @@
|
||||
#include <sys/ioctl.h> /* ioctl() */
|
||||
#include <libv4lconvert.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
class WebcamTracker
|
||||
{
|
||||
public:
|
||||
WebcamTracker(const char * device);
|
||||
WebcamTracker();
|
||||
~WebcamTracker();
|
||||
bool open(const char * device);
|
||||
void start();
|
||||
|
||||
protected:
|
||||
void * m_vidbuf;
|
||||
int m_vidbuflen;
|
||||
void requestBuffers(int num);
|
||||
void mapBuffer(int i);
|
||||
void queueBuffer(int i);
|
||||
void beginStreaming();
|
||||
void endStreaming();
|
||||
void dequeueBuffer(v4l2_buffer * dqbuf);
|
||||
void unmapBuffer(int i);
|
||||
void freeBuffers();
|
||||
|
||||
bool m_open;
|
||||
int m_fd;
|
||||
int m_numbufs;
|
||||
void ** m_buffers;
|
||||
int * m_lengths;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user