upstream: [media] vb2: if bytesused is 0, then fill with output buffer length
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 7 Apr 2014 11:57:48 +0000 (08:57 -0300)
committerChanho Park <chanho61.park@samsung.com>
Tue, 18 Nov 2014 02:56:09 +0000 (11:56 +0900)
The application should really always fill in bytesused for output
buffers, unfortunately the vb2 framework never checked for that.

So for single planar formats replace a bytesused of 0 by the length
of the buffer, and for multiplanar format do the same if bytesused is
0 for ALL planes.

This seems to be what the user really intended if v4l2_buffer was
just memset to 0.

I'm afraid that just checking for this and returning an error would
break too many applications. Quite a few drivers never check for bytesused
at all and just use the buffer length instead.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Acked-by: Pawel Osciak <pawel@osciak.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
drivers/media/v4l2-core/videobuf2-core.c

index e50b040..4c43aaa 100644 (file)
@@ -1111,15 +1111,30 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
        if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
                /* Fill in driver-provided information for OUTPUT types */
                if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+                       bool bytesused_is_used;
+
+                       /* Check if bytesused == 0 for all planes */
+                       for (plane = 0; plane < vb->num_planes; ++plane)
+                               if (b->m.planes[plane].bytesused)
+                                       break;
+                       bytesused_is_used = plane < vb->num_planes;
+
                        /*
                         * Will have to go up to b->length when API starts
                         * accepting variable number of planes.
+                        *
+                        * If bytesused_is_used is false, then fall back to the
+                        * full buffer size. In that case userspace clearly
+                        * never bothered to set it and it's a safe assumption
+                        * that they really meant to use the full plane sizes.
                         */
                        for (plane = 0; plane < vb->num_planes; ++plane) {
-                               v4l2_planes[plane].bytesused =
-                                       b->m.planes[plane].bytesused;
-                               v4l2_planes[plane].data_offset =
-                                       b->m.planes[plane].data_offset;
+                               struct v4l2_plane *pdst = &v4l2_planes[plane];
+                               struct v4l2_plane *psrc = &b->m.planes[plane];
+
+                               pdst->bytesused = bytesused_is_used ?
+                                       psrc->bytesused : psrc->length;
+                               pdst->data_offset = psrc->data_offset;
                        }
                }
 
@@ -1145,9 +1160,15 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
                 * so fill in relevant v4l2_buffer struct fields instead.
                 * In videobuf we use our internal V4l2_planes struct for
                 * single-planar buffers as well, for simplicity.
+                *
+                * If bytesused == 0, then fall back to the full buffer size
+                * as that's a sensible default.
                 */
                if (V4L2_TYPE_IS_OUTPUT(b->type))
-                       v4l2_planes[0].bytesused = b->bytesused;
+                       v4l2_planes[0].bytesused =
+                               b->bytesused ? b->bytesused : b->length;
+               else
+                       v4l2_planes[0].bytesused = 0;
 
                if (b->memory == V4L2_MEMORY_USERPTR) {
                        v4l2_planes[0].m.userptr = b->m.userptr;