You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
4.6 KiB
125 lines
4.6 KiB
From a8ed8c04c119e5a323a2c79fcd0d28b4d29fc28a Mon Sep 17 00:00:00 2001
|
|
From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
|
Date: Thu, 23 Apr 2015 22:56:09 -0300
|
|
Subject: [PATCH] v4l2: use REQBUFS properly
|
|
|
|
There are two issues on this driver with regards to buffer
|
|
request:
|
|
|
|
1) it is not calling VIDIOC_REQBUFS for USERPTR;
|
|
|
|
2) It is calling VIDIOC_REQBUFS at probe, to check the max
|
|
number of supported buffers, but it doesn't deallocate
|
|
the buffers at the end of the probe function.
|
|
|
|
Fix those issues. Also, improve the error/warning messages
|
|
associated with possible problems.
|
|
|
|
This is based on the issues detected by the patch proposed
|
|
to fix this bug:
|
|
https://bugs.archlinux.org/task/44091
|
|
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
|
|
|
diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c
|
|
index aabd16643ddc..f6662d3707f9 100644
|
|
--- a/zbar/video/v4l2.c
|
|
+++ b/zbar/video/v4l2.c
|
|
@@ -201,21 +201,6 @@ static int v4l2_cleanup (zbar_video_t *vdo)
|
|
|
|
static int v4l2_mmap_buffers (zbar_video_t *vdo)
|
|
{
|
|
- struct v4l2_requestbuffers rb;
|
|
- memset(&rb, 0, sizeof(rb));
|
|
- rb.count = vdo->num_images;
|
|
- rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
- rb.memory = V4L2_MEMORY_MMAP;
|
|
- if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
|
|
- return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
|
|
- "requesting video frame buffers (VIDIOC_REQBUFS)"));
|
|
- zprintf(1, "mapping %u buffers (of %d requested)\n",
|
|
- rb.count, vdo->num_images);
|
|
- if(!rb.count)
|
|
- return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
|
|
- "driver returned 0 buffers"));
|
|
- if(vdo->num_images > rb.count)
|
|
- vdo->num_images = rb.count;
|
|
|
|
struct v4l2_buffer vbuf;
|
|
memset(&vbuf, 0, sizeof(vbuf));
|
|
@@ -313,8 +298,32 @@ static int v4l2_set_format (zbar_video_t *vdo,
|
|
static int v4l2_init (zbar_video_t *vdo,
|
|
uint32_t fmt)
|
|
{
|
|
+ struct v4l2_requestbuffers rb;
|
|
if(v4l2_set_format(vdo, fmt))
|
|
return(-1);
|
|
+
|
|
+ memset(&rb, 0, sizeof(rb));
|
|
+ rb.count = vdo->num_images;
|
|
+ rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
+ if(vdo->iomode == VIDEO_MMAP)
|
|
+ rb.memory = V4L2_MEMORY_MMAP;
|
|
+ else
|
|
+ rb.memory = V4L2_MEMORY_USERPTR;
|
|
+
|
|
+ if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
|
|
+ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
|
|
+ "requesting video frame buffers (VIDIOC_REQBUFS)"));
|
|
+
|
|
+ if(!rb.count)
|
|
+ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
|
|
+ "driver returned 0 buffers"));
|
|
+
|
|
+ if(vdo->num_images > rb.count)
|
|
+ vdo->num_images = rb.count;
|
|
+
|
|
+ zprintf(1, "using %u buffers (of %d requested)\n",
|
|
+ rb.count, vdo->num_images);
|
|
+
|
|
if(vdo->iomode == VIDEO_MMAP)
|
|
return(v4l2_mmap_buffers(vdo));
|
|
return(0);
|
|
@@ -324,7 +333,7 @@ static int v4l2_probe_iomode (zbar_video_t *vdo)
|
|
{
|
|
struct v4l2_requestbuffers rb;
|
|
memset(&rb, 0, sizeof(rb));
|
|
- rb.count = vdo->num_images; /* FIXME workaround broken drivers */
|
|
+ rb.count = vdo->num_images;
|
|
rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
|
if(vdo->iomode == VIDEO_MMAP)
|
|
rb.memory = V4L2_MEMORY_MMAP;
|
|
@@ -340,14 +349,31 @@ static int v4l2_probe_iomode (zbar_video_t *vdo)
|
|
return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
|
|
"querying streaming mode (VIDIOC_REQBUFS)"));
|
|
#ifdef HAVE_SYS_MMAN_H
|
|
+ err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
|
|
+ "USERPTR failed. Falling back to mmap");
|
|
vdo->iomode = VIDEO_MMAP;
|
|
+#else
|
|
+ return err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
|
|
+ "Userptr not supported, and zbar was compiled without mmap support"));
|
|
#endif
|
|
}
|
|
else {
|
|
if(!vdo->iomode)
|
|
- vdo->iomode = VIDEO_USERPTR;
|
|
+ rb.memory = V4L2_MEMORY_USERPTR;
|
|
+ /* Update the num_images with the max supported by the driver */
|
|
if(rb.count)
|
|
vdo->num_images = rb.count;
|
|
+ else
|
|
+ err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
|
|
+ "Something is wrong: number of buffers returned by REQBUF is zero!");
|
|
+
|
|
+ /* requesting 0 buffers
|
|
+ * This cleans up the buffers allocated previously on probe
|
|
+ */
|
|
+ rb.count = 0;
|
|
+ if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
|
|
+ err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
|
|
+ "releasing video frame buffers (VIDIOC_REQBUFS)");
|
|
}
|
|
return(0);
|
|
}
|