This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/v4l-utils.git tree:

Subject: libv4l2: Lazily allocate convert_mmap_buf
Author:  Gregor Jasny <[email protected]>
Date:    Sat Jul 26 21:36:16 2014 +0200

>From Hans de Goede:

Originally this was not possible, which is why I went with the fixed buffer
(IIRC). But later on we started dis-allowing changing various parameters
with buffers mapped, because allowing that was just a bad idea.

In order to allow dynamic allocation of convert_mmap_buf, we need to make
sure that:

a) It is not used whenever dest_fmt changes, since it is used
to store destination fmt data and should always be at least
dest_fmt.fmt.pix.sizeimage bytes. I've just checked and all
places which change dest_fmt first call v4l2_check_buffer_change_ok()
which ensures that convert_mmap_buf is not used, frees it and marks
it as MAP_FAILED.

b) It is not allocated before dest_fmt gets set. It is allocated in
2 places:

1) On DQBUF, which only can be done after a stream-on, at which point
dest_fmt must be set.

2) on v4l2_mmap, which requires the caller having done a QUERYBUF,
and thus a REQBUFS, so dest_fmt must be set at this point.

So long story short, yes doing dynamic alloc should work fine. I
suggest introducing a v4l2_ensure_convert_mmap_buf function for
this which checks if convert_mmap_buf == MAP_FAILED and when it
is allocs a buffer of dest_fmt.fmt.pix.sizeimage bytes rounded
up to a multiple PAGE_SIZE. If convert_mmap_buf != MAP_FAILED
and thus the buffer is already allocated it should simply
return success.

Signed-off-by: Gregor Jasny <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>

 lib/libv4l2/libv4l2-priv.h |    3 +-
 lib/libv4l2/libv4l2.c      |  102 ++++++++++++++++++++++++++++---------------
 2 files changed, 68 insertions(+), 37 deletions(-)

---

http://git.linuxtv.org/v4l-utils.git?a=commitdiff;h=10213c975afdfcc90aa7de39e66c40cd7e8a57f7

diff --git a/lib/libv4l2/libv4l2-priv.h b/lib/libv4l2/libv4l2-priv.h
index ff4c8d2..fdd5ff0 100644
--- a/lib/libv4l2/libv4l2-priv.h
+++ b/lib/libv4l2/libv4l2-priv.h
@@ -31,7 +31,6 @@
    be adjusted! */
 #define V4L2_MAX_NO_FRAMES 32
 #define V4L2_DEFAULT_NREADBUFFERS 4
-#define V4L2_FRAME_BUF_SIZE (4096 * 4096)
 #define V4L2_IGNORE_FIRST_FRAME_ERRORS 3
 #define V4L2_DEFAULT_FPS 30
 
@@ -88,6 +87,8 @@ struct v4l2_dev_info {
        int first_frame;
        struct v4lconvert_data *convert;
        unsigned char *convert_mmap_buf;
+       size_t convert_mmap_buf_size;
+       size_t convert_mmap_frame_size;
        /* Frame bookkeeping is only done when in read or mmap-conversion mode 
*/
        unsigned char *frame_pointers[V4L2_MAX_NO_FRAMES];
        int frame_sizes[V4L2_MAX_NO_FRAMES];
diff --git a/lib/libv4l2/libv4l2.c b/lib/libv4l2/libv4l2.c
index 8291ebe..afac406 100644
--- a/lib/libv4l2/libv4l2.c
+++ b/lib/libv4l2/libv4l2.c
@@ -94,6 +94,48 @@ static struct v4l2_dev_info devices[V4L2_MAX_DEVICES] = {
 };
 static int devices_used;
 
+static int v4l2_ensure_convert_mmap_buf(int index)
+{
+       long page_size;
+
+       if (devices[index].convert_mmap_buf != MAP_FAILED) {
+               return 0;
+       }
+
+       page_size = sysconf(_SC_PAGESIZE);
+       if (page_size < 0) {
+               int saved_err = errno;
+               V4L2_LOG_ERR("unable to retrieve page size\n");
+               errno = saved_err;
+               return -1;
+       }
+
+       /* round up to full page size */
+       devices[index].convert_mmap_frame_size =
+               (((devices[index].dest_fmt.fmt.pix.sizeimage + page_size - 1) /
+               page_size) * page_size);
+
+       devices[index].convert_mmap_buf_size =
+               devices[index].convert_mmap_frame_size * 
devices[index].no_frames;
+
+       devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL,
+                       devices[index].convert_mmap_buf_size,
+                       PROT_READ | PROT_WRITE,
+                       MAP_ANONYMOUS | MAP_PRIVATE,
+                       -1, 0);
+
+       if (devices[index].convert_mmap_buf == MAP_FAILED) {
+               devices[index].convert_mmap_frame_size = 0;
+               devices[index].convert_mmap_buf_size = 0;
+
+               int saved_err = errno;
+               V4L2_LOG_ERR("allocating conversion buffer\n");
+               errno = saved_err;
+               return -1;
+       }
+
+       return 0;
+}
 
 static int v4l2_request_read_buffers(int index)
 {
@@ -317,7 +359,8 @@ static int v4l2_dequeue_and_convert(int index, struct 
v4l2_buffer *buf,
                                &devices[index].src_fmt, 
&devices[index].dest_fmt,
                                devices[index].frame_pointers[buf->index],
                                buf->bytesused, dest ? dest : 
(devices[index].convert_mmap_buf +
-                                       buf->index * V4L2_FRAME_BUF_SIZE), 
dest_size);
+                                       buf->index * 
devices[index].convert_mmap_frame_size),
+                               dest_size);
 
                if (devices[index].first_frame) {
                        /* Always treat convert errors as EAGAIN during the 
first few frames, as
@@ -526,7 +569,7 @@ static void v4l2_set_conversion_buf_params(int index, 
struct v4l2_buffer *buf)
                buf->index = 0;
 
        buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index;
-       buf->length = V4L2_FRAME_BUF_SIZE;
+       buf->length = devices[index].convert_mmap_frame_size;
        if (devices[index].frame_map_count[buf->index])
                buf->flags |= V4L2_BUF_FLAG_MAPPED;
        else
@@ -735,6 +778,8 @@ no_capture:
        devices[index].nreadbuffers = V4L2_DEFAULT_NREADBUFFERS;
        devices[index].convert = convert;
        devices[index].convert_mmap_buf = MAP_FAILED;
+       devices[index].convert_mmap_buf_size = 0;
+       devices[index].convert_mmap_frame_size = 0;
        for (i = 0; i < V4L2_MAX_NO_FRAMES; i++) {
                devices[index].frame_pointers[i] = MAP_FAILED;
                devices[index].frame_map_count[i] = 0;
@@ -808,9 +853,11 @@ int v4l2_close(int fd)
                                V4L2_LOG_WARN("v4l2 mmap buffers still mapped 
on close()\n");
                } else {
                        SYS_MUNMAP(devices[index].convert_mmap_buf,
-                                       devices[index].no_frames * 
V4L2_FRAME_BUF_SIZE);
+                                       devices[index].convert_mmap_buf_size);
                }
                devices[index].convert_mmap_buf = MAP_FAILED;
+               devices[index].convert_mmap_buf_size = 0;
+               devices[index].convert_mmap_frame_size = 0;
        }
        v4lconvert_destroy(devices[index].convert);
        free(devices[index].readbuf);
@@ -864,8 +911,10 @@ static int v4l2_check_buffer_change_ok(int index)
           v4l2_unrequest_read_buffers may change the no_frames, so free the
           convert mmap buffer */
        SYS_MUNMAP(devices[index].convert_mmap_buf,
-                       devices[index].no_frames * V4L2_FRAME_BUF_SIZE);
+                       devices[index].convert_mmap_buf_size);
        devices[index].convert_mmap_buf = MAP_FAILED;
+       devices[index].convert_mmap_buf_size = 0;
+       devices[index].convert_mmap_frame_size = 0;
 
        if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) {
                V4L2_LOG("deactivating read-stream for settings change\n");
@@ -1334,23 +1383,12 @@ no_capture_request:
                /* An application can do a DQBUF before mmap-ing in the buffer,
                   but we need the buffer _now_ to write our converted data
                   to it! */
-               if (devices[index].convert_mmap_buf == MAP_FAILED) {
-                       devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL,
-                               (size_t)(devices[index].no_frames * 
V4L2_FRAME_BUF_SIZE),
-                               PROT_READ | PROT_WRITE,
-                               MAP_ANONYMOUS | MAP_PRIVATE,
-                               -1, 0);
-                       if (devices[index].convert_mmap_buf == MAP_FAILED) {
-                               saved_err = errno;
-                               V4L2_LOG_ERR("allocating conversion buffer\n");
-                               errno = saved_err;
-                               result = -1;
-                               break;
-                       }
-               }
+               result = v4l2_ensure_convert_mmap_buf(index);
+               if (result)
+                       break;
 
                result = v4l2_dequeue_and_convert(index, buf, 0,
-                                                 V4L2_FRAME_BUF_SIZE);
+                               devices[index].convert_mmap_frame_size);
                if (result >= 0) {
                        buf->bytesused = result;
                        result = 0;
@@ -1575,7 +1613,7 @@ void *v4l2_mmap(void *start, size_t length, int prot, int 
flags, int fd,
        if (index == -1 ||
                        /* Check if the mmap data matches our answer to 
QUERY_BUF. If it doesn't,
                           let the kernel handle it (to allow for mmap-based 
non capture use) */
-                       start || length != V4L2_FRAME_BUF_SIZE ||
+                       start || length != 
devices[index].convert_mmap_frame_size ||
                        ((unsigned int)offset & ~0xFFu) != 
V4L2_MMAP_OFFSET_MAGIC) {
                if (index != -1)
                        V4L2_LOG("Passing mmap(%p, %d, ..., %x, through to the 
driver\n",
@@ -1600,26 +1638,16 @@ void *v4l2_mmap(void *start, size_t length, int prot, 
int flags, int fd,
                goto leave;
        }
 
-       if (devices[index].convert_mmap_buf == MAP_FAILED) {
-               devices[index].convert_mmap_buf = (void *)SYS_MMAP(NULL,
-                       (size_t)(devices[index].no_frames * 
V4L2_FRAME_BUF_SIZE),
-                       PROT_READ | PROT_WRITE,
-                       MAP_ANONYMOUS | MAP_PRIVATE,
-                       -1, 0);
-               if (devices[index].convert_mmap_buf == MAP_FAILED) {
-                       int saved_err = errno;
-
-                       V4L2_LOG_ERR("allocating conversion buffer\n");
-                       errno = saved_err;
-                       result = MAP_FAILED;
-                       goto leave;
-               }
+       if (v4l2_ensure_convert_mmap_buf(index)) {
+               errno = EINVAL;
+               result = MAP_FAILED;
+               goto leave;
        }
 
        devices[index].frame_map_count[buffer_index]++;
 
        result = devices[index].convert_mmap_buf +
-               buffer_index * V4L2_FRAME_BUF_SIZE;
+               buffer_index * devices[index].convert_mmap_frame_size;
 
        V4L2_LOG("Fake (conversion) mmap buf %u, seen by app at: %p\n",
                        buffer_index, result);
@@ -1637,10 +1665,11 @@ int v4l2_munmap(void *_start, size_t length)
        unsigned char *start = _start;
 
        /* Is this memory ours? */
-       if (start != MAP_FAILED && length == V4L2_FRAME_BUF_SIZE) {
+       if (start != MAP_FAILED) {
                for (index = 0; index < devices_used; index++)
                        if (devices[index].fd != -1 &&
                                        devices[index].convert_mmap_buf != 
MAP_FAILED &&
+                                       length == 
devices[index].convert_mmap_frame_size &&
                                        start >= 
devices[index].convert_mmap_buf &&
                                        (start - 
devices[index].convert_mmap_buf) % length == 0)
                                break;
@@ -1654,6 +1683,7 @@ int v4l2_munmap(void *_start, size_t length)
 
                        /* Re-do our checks now that we have the lock, things 
may have changed */
                        if (devices[index].convert_mmap_buf != MAP_FAILED &&
+                                       length == 
devices[index].convert_mmap_frame_size &&
                                        start >= 
devices[index].convert_mmap_buf &&
                                        (start - 
devices[index].convert_mmap_buf) % length == 0 &&
                                        buffer_index < 
devices[index].no_frames) {

_______________________________________________
linuxtv-commits mailing list
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to