From 96eb602808db2c09e4fea2d36a5360f9fbf71c42 Mon Sep 17 00:00:00 2001 From: josh Date: Fri, 7 Aug 2009 23:06:58 +0000 Subject: [PATCH] requesting and memory-mapping a buffer git-svn-id: svn://anubis/misc/WebcamTracker@121 bd8a9e45-a331-0410-811e-c64571078777 --- WebcamTracker.cc | 94 +++++++++++++++++++++++++++++++++++++----------- WebcamTracker.h | 2 ++ 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/WebcamTracker.cc b/WebcamTracker.cc index 3ba7ada..3bf1b7b 100644 --- a/WebcamTracker.cc +++ b/WebcamTracker.cc @@ -5,6 +5,9 @@ #include /* exit() */ #include /* ioctl() */ #include +#include +#include /* mmap() */ +#include #include #include "WebcamTracker.h" using namespace std; @@ -23,26 +26,61 @@ WebcamTracker::WebcamTracker(const char * device) m_open = true; struct v4l2_capability cap; - ioctl(m_fd, VIDIOC_QUERYCAP, &cap); -#define check_cap(x) do { \ - if (cap.capabilities & (x)) \ - cout << " cap: " << #x << endl; \ - } while (0) - check_cap(V4L2_CAP_VIDEO_CAPTURE); - check_cap(V4L2_CAP_VIDEO_OUTPUT); - check_cap(V4L2_CAP_VIDEO_OVERLAY); - check_cap(V4L2_CAP_VBI_CAPTURE); - check_cap(V4L2_CAP_VBI_OUTPUT); - check_cap(V4L2_CAP_SLICED_VBI_CAPTURE); - check_cap(V4L2_CAP_SLICED_VBI_OUTPUT); - check_cap(V4L2_CAP_RDS_CAPTURE); - check_cap(V4L2_CAP_VIDEO_OUTPUT_OVERLAY); - check_cap(V4L2_CAP_TUNER); - check_cap(V4L2_CAP_AUDIO); - check_cap(V4L2_CAP_RADIO); - check_cap(V4L2_CAP_READWRITE); - check_cap(V4L2_CAP_ASYNCIO); - check_cap(V4L2_CAP_STREAMING); + int ret = ioctl(m_fd, VIDIOC_QUERYCAP, &cap); + if (ret != 0) + { + cerr << "VIDIOC_QUERYCAP ioctl failed: " << ret << endl; + } + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + { + 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; + } } else { @@ -54,6 +92,22 @@ 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) + { + cerr << "~WebcamTracker(): VIDIOC_REQBUFS ioctl failed: " + << ret << endl; + if (errno == EBUSY) + cerr << "EBUSY" << endl; + if (errno == EINVAL) + cerr << "EINVAL" << endl; + } close(m_fd); } } diff --git a/WebcamTracker.h b/WebcamTracker.h index 3f04398..d7c5ad3 100644 --- a/WebcamTracker.h +++ b/WebcamTracker.h @@ -14,6 +14,8 @@ class WebcamTracker ~WebcamTracker(); protected: + void * m_vidbuf; + int m_vidbuflen; bool m_open; int m_fd; };