requesting and memory-mapping a buffer

git-svn-id: svn://anubis/misc/WebcamTracker@121 bd8a9e45-a331-0410-811e-c64571078777
This commit is contained in:
josh 2009-08-07 23:06:58 +00:00
parent ca070c2d8c
commit 96eb602808
2 changed files with 76 additions and 20 deletions

View File

@ -5,6 +5,9 @@
#include <stdlib.h> /* exit() */ #include <stdlib.h> /* exit() */
#include <sys/ioctl.h> /* ioctl() */ #include <sys/ioctl.h> /* ioctl() */
#include <libv4lconvert.h> #include <libv4lconvert.h>
#include <unistd.h>
#include <sys/mman.h> /* mmap() */
#include <errno.h>
#include <iostream> #include <iostream>
#include "WebcamTracker.h" #include "WebcamTracker.h"
using namespace std; using namespace std;
@ -23,26 +26,61 @@ WebcamTracker::WebcamTracker(const char * device)
m_open = true; m_open = true;
struct v4l2_capability cap; struct v4l2_capability cap;
ioctl(m_fd, VIDIOC_QUERYCAP, &cap); int ret = ioctl(m_fd, VIDIOC_QUERYCAP, &cap);
#define check_cap(x) do { \ if (ret != 0)
if (cap.capabilities & (x)) \ {
cout << " cap: " << #x << endl; \ cerr << "VIDIOC_QUERYCAP ioctl failed: " << ret << endl;
} while (0) }
check_cap(V4L2_CAP_VIDEO_CAPTURE); if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
check_cap(V4L2_CAP_VIDEO_OUTPUT); {
check_cap(V4L2_CAP_VIDEO_OVERLAY); cerr << "Warning: V4L2_CAP_VIDEO_CAPTURE not supported!" << endl;
check_cap(V4L2_CAP_VBI_CAPTURE); }
check_cap(V4L2_CAP_VBI_OUTPUT);
check_cap(V4L2_CAP_SLICED_VBI_CAPTURE); v4l2_requestbuffers reqbuf;
check_cap(V4L2_CAP_SLICED_VBI_OUTPUT); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
check_cap(V4L2_CAP_RDS_CAPTURE); reqbuf.count = 1;
check_cap(V4L2_CAP_VIDEO_OUTPUT_OVERLAY); reqbuf.memory = V4L2_MEMORY_MMAP;
check_cap(V4L2_CAP_TUNER); ret = ioctl(m_fd, VIDIOC_REQBUFS, &reqbuf);
check_cap(V4L2_CAP_AUDIO); if (ret != 0)
check_cap(V4L2_CAP_RADIO); {
check_cap(V4L2_CAP_READWRITE); cerr << "VIDIOC_REQBUFS ioctl failed: returned " << ret
check_cap(V4L2_CAP_ASYNCIO); << ", errno " << errno;
check_cap(V4L2_CAP_STREAMING); 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;
}
} }
else else
{ {
@ -54,6 +92,22 @@ WebcamTracker::~WebcamTracker()
{ {
if (m_open) 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)
{
cerr << "~WebcamTracker(): VIDIOC_REQBUFS ioctl failed: "
<< ret << endl;
if (errno == EBUSY)
cerr << "EBUSY" << endl;
if (errno == EINVAL)
cerr << "EINVAL" << endl;
}
close(m_fd); close(m_fd);
} }
} }

View File

@ -14,6 +14,8 @@ class WebcamTracker
~WebcamTracker(); ~WebcamTracker();
protected: protected:
void * m_vidbuf;
int m_vidbuflen;
bool m_open; bool m_open;
int m_fd; int m_fd;
}; };