summaryrefslogtreecommitdiff
path: root/modules/v4l2
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-09-07 21:45:40 +0200
committerAlfred E. Heggestad <aeh@db.org>2014-09-07 21:45:40 +0200
commit9c380fe44ab9bda22891ec8b14c9f34025303b30 (patch)
tree900f6eabeb136218f0e773e5167aabc38e9c08c9 /modules/v4l2
parent3de906aba4bd37ccd93f11c4a2afe981538ace7f (diff)
v4l2: remove support for read, only use MMAP
- also minor cleanups
Diffstat (limited to 'modules/v4l2')
-rw-r--r--modules/v4l2/v4l2.c258
1 files changed, 67 insertions, 191 deletions
diff --git a/modules/v4l2/v4l2.c b/modules/v4l2/v4l2.c
index 3a27770..0f794e2 100644
--- a/modules/v4l2/v4l2.c
+++ b/modules/v4l2/v4l2.c
@@ -36,11 +36,6 @@
#endif
-enum io_method {
- IO_METHOD_READ = 0,
- IO_METHOD_MMAP
-};
-
struct buffer {
void *start;
size_t length;
@@ -52,14 +47,12 @@ struct vidsrc_st {
int fd;
pthread_t thread;
bool run;
- struct vidsz sz, app_sz;
+ struct vidsz sz;
u_int32_t pixfmt;
- struct mbuf *mb;
- vidsrc_frame_h *frameh;
- void *arg;
- enum io_method io;
struct buffer *buffers;
unsigned int n_buffers;
+ vidsrc_frame_h *frameh;
+ void *arg;
};
@@ -69,18 +62,19 @@ static struct vidsrc *vidsrc;
static enum vidfmt match_fmt(u_int32_t fmt)
{
switch (fmt) {
- case V4L2_PIX_FMT_YUV420: return VID_FMT_YUV420P;
- case V4L2_PIX_FMT_YUYV: return VID_FMT_YUYV422;
- case V4L2_PIX_FMT_UYVY: return VID_FMT_UYVY422;
- case V4L2_PIX_FMT_RGB32: return VID_FMT_RGB32;
- case V4L2_PIX_FMT_RGB565: return VID_FMT_RGB565;
- case V4L2_PIX_FMT_RGB555: return VID_FMT_RGB555;
- default: return VID_FMT_N;
+
+ case V4L2_PIX_FMT_YUV420: return VID_FMT_YUV420P;
+ case V4L2_PIX_FMT_YUYV: return VID_FMT_YUYV422;
+ case V4L2_PIX_FMT_UYVY: return VID_FMT_UYVY422;
+ case V4L2_PIX_FMT_RGB32: return VID_FMT_RGB32;
+ case V4L2_PIX_FMT_RGB565: return VID_FMT_RGB565;
+ case V4L2_PIX_FMT_RGB555: return VID_FMT_RGB555;
+ default: return VID_FMT_N;
}
}
-static void get_video_input(struct vidsrc_st *st)
+static void print_video_input(struct vidsrc_st *st)
{
struct v4l2_input input;
@@ -98,7 +92,7 @@ static void get_video_input(struct vidsrc_st *st)
return;
}
- info("v4l2: Current input: %s\n", input.name);
+ info("v4l2: Current input: \"%s\"\n", input.name);
}
@@ -115,21 +109,6 @@ static int xioctl(int fd, unsigned long int request, void *arg)
}
-static int init_read(struct vidsrc_st *st, unsigned int buffer_size)
-{
- st->buffers = calloc(1, sizeof (*st->buffers));
- if (!st->buffers)
- return ENOMEM;
-
- st->buffers[0].length = buffer_size;
- st->buffers[0].start = malloc(buffer_size);
- if (!st->buffers[0].start)
- return ENOMEM;
-
- return 0;
-}
-
-
static int init_mmap(struct vidsrc_st *st, const char *dev_name)
{
struct v4l2_requestbuffers req;
@@ -156,7 +135,7 @@ static int init_mmap(struct vidsrc_st *st, const char *dev_name)
return ENOMEM;
}
- st->buffers = calloc(req.count, sizeof(*st->buffers));
+ st->buffers = mem_zalloc(req.count * sizeof(*st->buffers), NULL);
if (!st->buffers)
return ENOMEM;
@@ -192,7 +171,8 @@ static int init_mmap(struct vidsrc_st *st, const char *dev_name)
}
-static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name)
+static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name,
+ int width, int height)
{
struct v4l2_capability cap;
struct v4l2_format fmt;
@@ -217,22 +197,10 @@ static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name)
return ENODEV;
}
- switch (st->io) {
-
- case IO_METHOD_READ:
- if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
- warning("%s does not support read i/o\n", dev_name);
- return ENOSYS;
- }
- break;
-
- case IO_METHOD_MMAP:
- if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
- warning("v4l2: %s does not support streaming i/o\n",
- dev_name);
- return ENOSYS;
- }
- break;
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ warning("v4l2: %s does not support streaming i/o\n",
+ dev_name);
+ return ENOSYS;
}
/* Negotiate video format */
@@ -261,8 +229,8 @@ static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name)
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = st->app_sz.w;
- fmt.fmt.pix.height = st->app_sz.h;
+ fmt.fmt.pix.width = width;
+ fmt.fmt.pix.height = height;
fmt.fmt.pix.pixelformat = st->pixfmt;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
@@ -284,27 +252,7 @@ static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name)
st->sz.w = fmt.fmt.pix.width;
st->sz.h = fmt.fmt.pix.height;
- if (!vidsz_cmp(&st->sz, &st->app_sz)) {
- info("v4l2: scaling %u x %u ---> %u x %u\n",
- st->sz.w, st->sz.h, st->app_sz.w, st->app_sz.h);
- }
-
- switch (st->io) {
-
- case IO_METHOD_READ:
- err = init_read(st, fmt.fmt.pix.sizeimage);
- break;
-
- case IO_METHOD_MMAP:
- err = init_mmap(st, dev_name);
- break;
-
- default:
- warning("v4l2: unknown io: %d\n", st->io);
- err = EINVAL;
- break;
- }
-
+ err = init_mmap(st, dev_name);
if (err)
return err;
@@ -331,19 +279,9 @@ static void stop_capturing(struct vidsrc_st *st)
if (st->fd < 0)
return;
- switch (st->io) {
-
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
-
- case IO_METHOD_MMAP:
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(st->fd, VIDIOC_STREAMOFF, &type))
- warning("v4l2: VIDIOC_STREAMOFF\n");
- break;
- }
+ xioctl(st->fd, VIDIOC_STREAMOFF, &type);
}
@@ -351,57 +289,38 @@ static void uninit_device(struct vidsrc_st *st)
{
unsigned int i;
- switch (st->io) {
-
- case IO_METHOD_READ:
- if (st->buffers)
- free(st->buffers[0].start);
- break;
-
- case IO_METHOD_MMAP:
- for (i=0; i<st->n_buffers; ++i)
- v4l2_munmap(st->buffers[i].start,
- st->buffers[i].length);
- break;
+ for (i=0; i<st->n_buffers; ++i) {
+ v4l2_munmap(st->buffers[i].start, st->buffers[i].length);
}
- free(st->buffers);
+ st->buffers = mem_deref(st->buffers);
+ st->n_buffers = 0;
}
-static int start_capturing(struct vidsrc_st *st, int fd)
+static int start_capturing(struct vidsrc_st *st)
{
unsigned int i;
enum v4l2_buf_type type;
- switch (st->io) {
-
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
-
- case IO_METHOD_MMAP:
- for (i = 0; i < st->n_buffers; ++i) {
- struct v4l2_buffer buf;
-
- memset(&buf, 0, sizeof(buf));
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
+ for (i = 0; i < st->n_buffers; ++i) {
+ struct v4l2_buffer buf;
- if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
- return errno;
- }
+ memset(&buf, 0, sizeof(buf));
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
- if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
+ if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf))
return errno;
-
- break;
}
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (-1 == xioctl (st->fd, VIDIOC_STREAMON, &type))
+ return errno;
+
return 0;
}
@@ -419,67 +338,38 @@ static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf)
static int read_frame(struct vidsrc_st *st)
{
struct v4l2_buffer buf;
- ssize_t n;
-
- switch (st->io) {
- case IO_METHOD_READ:
- n = v4l2_read(st->fd, st->mb->buf, st->mb->size);
- if (-1 == n) {
- switch (errno) {
+ memset(&buf, 0, sizeof(buf));
- case EAGAIN:
- return 0;
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
- case EIO:
- /* Could ignore EIO, see spec. */
+ if (-1 == xioctl (st->fd, VIDIOC_DQBUF, &buf)) {
+ switch (errno) {
- /* fall through */
+ case EAGAIN:
+ return 0;
- default:
- warning("v4l2: read error: %m\n", errno);
- BREAKPOINT;
- return errno;
- }
- }
-
- call_frame_handler(st, st->mb->buf);
- break;
-
- case IO_METHOD_MMAP:
- memset(&buf, 0, sizeof(buf));
+ case EIO:
+ /* Could ignore EIO, see spec. */
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
+ /* fall through */
- if (-1 == xioctl (st->fd, VIDIOC_DQBUF, &buf)) {
- switch (errno) {
-
- case EAGAIN:
- return 0;
-
- case EIO:
- /* Could ignore EIO, see spec. */
-
- /* fall through */
-
- default:
- warning("v4l2: VIDIOC_DQBUF: %m\n", errno);
- return errno;
- }
+ default:
+ warning("v4l2: VIDIOC_DQBUF: %m\n", errno);
+ return errno;
}
+ }
- if (buf.index >= st->n_buffers) {
- warning("v4l2: index >= n_buffers\n");
- }
+ if (buf.index >= st->n_buffers) {
+ warning("v4l2: index >= n_buffers\n");
+ }
- call_frame_handler(st, st->buffers[buf.index].start);
+ call_frame_handler(st, st->buffers[buf.index].start);
- if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf)) {
- warning("v4l2: VIDIOC_QBUF\n");
- return errno;
- }
- break;
+ if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf)) {
+ warning("v4l2: VIDIOC_QBUF\n");
+ return errno;
}
return 0;
@@ -488,9 +378,6 @@ static int read_frame(struct vidsrc_st *st)
static int vd_open(struct vidsrc_st *st, const char *device)
{
- /* NOTE: with kernel 2.6.26 it takes ~2 seconds to open
- * the video device.
- */
st->fd = v4l2_open(device, O_RDWR);
if (st->fd < 0) {
warning("v4l2: open %s: %m\n", device, errno);
@@ -516,7 +403,6 @@ static void destructor(void *arg)
if (st->fd >= 0)
v4l2_close(st->fd);
- mem_deref(st->mb);
mem_deref(st->vs);
}
@@ -563,32 +449,22 @@ static int alloc(struct vidsrc_st **stp, struct vidsrc *vs,
st->vs = mem_ref(vs);
st->fd = -1;
- st->io = IO_METHOD_MMAP;
-
- st->app_sz = *size;
+ st->sz = *size;
st->frameh = frameh;
st->arg = arg;
-
st->pixfmt = 0;
err = vd_open(st, dev);
if (err)
goto out;
- /* Try Video4Linux 2 first .. */
- err = v4l2_init_device(st, dev);
+ err = v4l2_init_device(st, dev, size->w, size->h);
if (err)
goto out;
- get_video_input(st);
-
- st->mb = mbuf_alloc(st->app_sz.w * st->app_sz.h * 3 / 2);
- if (!st->mb) {
- err = ENOMEM;
- goto out;
- }
+ print_video_input(st);
- err = start_capturing(st, st->fd);
+ err = start_capturing(st);
if (err)
goto out;