Re: [PATCH] media: v4l2-mem2mem: Apply DST_QUEUE_OFF_BASE on MMAP buffers across ioctls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Dec 9, 2021 at 8:06 PM Hans Verkuil <hverkuil-cisco@xxxxxxxxx> wrote:
>
> On 09/12/2021 07:29, Chen-Yu Tsai wrote:
> > DST_QUEUE_OFF_BASE is applied to offset/mem_offset on MMAP capture buffers
> > only for the VIDIOC_QUERYBUF ioctl, while the userspace fields (including
> > offset/mem_offset) are filled in for VIDIOC_{QUERY,PREPARE,Q,DQ}BUF
> > ioctls. This leads to differences in the values presented to userspace.
> > If userspace attempts to mmap the capture buffer directly using values
> > from DQBUF, it will fail.
> >
> > Move the code that applies the magic offset into a helper, and call
> > that helper from all four ioctl entry points.
> >
> > Fixes: 7f98639def42 ("V4L/DVB: add memory-to-memory device helper framework for videobuf")
> > Fixes: 908a0d7c588e ("[media] v4l: mem2mem: port to videobuf2")
> > Signed-off-by: Chen-Yu Tsai <wenst@xxxxxxxxxxxx>
> > ---
> > This was tested on RK3399 with
> >
> >     gst-launch-1.0 videotestsrc num-buffers=2 ! v4l2jpegenc ! fakesink
> >
> > and verifying the values using the V4L2 debug messages:
> >
> >     video2: VIDIOC_QUERYBUF: 00:00:00.000000 index=0, type=vid-cap-mplane, request_fd=0, flags=0x00004000, field=any, sequence=0, memory=mmap
> >     plane 0: bytesused=0, data_offset=0x00000000, offset/userptr=0x40000000, length=2097152
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >     video2: VIDIOC_QUERYBUF: 00:00:00.000000 index=0, type=vid-out-mplane, request_fd=0, flags=0x00004000, field=any, sequence=0, memory=mmap
> >     plane 0: bytesused=0, data_offset=0x00000000, offset/userptr=0x0, length=153600
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >
> >     video2: VIDIOC_QBUF: 00:00:00.000000 index=0, type=vid-cap-mplane, request_fd=0, flags=0x00004003, field=any, sequence=0, memory=mmap
> >     plane 0: bytesused=2097152, data_offset=0x00000000, offset/userptr=0x40000000, length=2097152
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >     video2: VIDIOC_QBUF: 00:00:00.000000 index=0, type=vid-out-mplane, request_fd=0, flags=0x00004003, field=none, sequence=0, memory=mmap
> >     plane 0: bytesused=153600, data_offset=0x00000000, offset/userptr=0x0, length=153600
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >
> >     video2: VIDIOC_DQBUF: 00:00:00.000000 index=0, type=vid-cap-mplane, request_fd=0, flags=0x00004001, field=none, sequence=0, memory=mmap
> >     plane 0: bytesused=6324, data_offset=0x00000000, offset/userptr=0x40000000, length=2097152
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >     video2: VIDIOC_DQBUF: 00:00:00.000000 index=0, type=vid-out-mplane, request_fd=0, flags=0x00004001, field=none, sequence=0, memory=mmap
> >     plane 0: bytesused=153600, data_offset=0x00000000, offset/userptr=0x0, length=153600
> >     timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
> >
> > Gstreamer doesn't do PREPAREBUF calls, so that path was not verified.
> > However the code changes are exactly the same, so I'm quite confident
> > about them.
> >
> > ---
> >  drivers/media/v4l2-core/v4l2-mem2mem.c | 46 ++++++++++++++++++++------
> >  1 file changed, 35 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
> > index e2654b422334..b47f25297c43 100644
> > --- a/drivers/media/v4l2-core/v4l2-mem2mem.c
> > +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
> > @@ -585,19 +585,14 @@ int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> >  }
> >  EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
> >
> > -int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> > -                   struct v4l2_buffer *buf)
> > +static void v4l2_m2m_adjust_mem_offset(struct vb2_queue *vq,
> > +                                    struct v4l2_buffer *buf)
> >  {
> > -     struct vb2_queue *vq;
> > -     int ret = 0;
> > -     unsigned int i;
> > -
> > -     vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
> > -     ret = vb2_querybuf(vq, buf);
> > -
> >       /* Adjust MMAP memory offsets for the CAPTURE queue */
> >       if (buf->memory == V4L2_MEMORY_MMAP && V4L2_TYPE_IS_CAPTURE(vq->type)) {
> >               if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
> > +                     unsigned int i;
> > +
> >                       for (i = 0; i < buf->length; ++i)
> >                               buf->m.planes[i].m.mem_offset
> >                                       += DST_QUEUE_OFF_BASE;
> > @@ -605,6 +600,19 @@ int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> >                       buf->m.offset += DST_QUEUE_OFF_BASE;
> >               }
> >       }
> > +}
> > +
> > +int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> > +                   struct v4l2_buffer *buf)
> > +{
> > +     struct vb2_queue *vq;
> > +     int ret = 0;
> > +
> > +     vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
> > +     ret = vb2_querybuf(vq, buf);
> > +
> > +     /* Adjust MMAP memory offsets for the CAPTURE queue */
> > +     v4l2_m2m_adjust_mem_offset(vq, buf);
> >
> >       return ret;
> >  }
> > @@ -760,6 +768,10 @@ int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> >       }
> >
> >       ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
> > +
> > +     /* Adjust MMAP memory offsets for the CAPTURE queue */
> > +     v4l2_m2m_adjust_mem_offset(vq, buf);
> > +
> >       if (ret)
> >               return ret;
> >
> > @@ -784,9 +796,15 @@ int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> >                  struct v4l2_buffer *buf)
> >  {
> >       struct vb2_queue *vq;
> > +     int ret;
> >
> >       vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
> > -     return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
> > +     ret = vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
> > +
> > +     /* Adjust MMAP memory offsets for the CAPTURE queue */
> > +     v4l2_m2m_adjust_mem_offset(vq, buf);
> > +
> > +     return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
> >
> > @@ -795,9 +813,15 @@ int v4l2_m2m_prepare_buf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
> >  {
> >       struct video_device *vdev = video_devdata(file);
> >       struct vb2_queue *vq;
> > +     int ret;
> >
> >       vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
> > -     return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
> > +     ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
> > +
> > +     /* Adjust MMAP memory offsets for the CAPTURE queue */
> > +     v4l2_m2m_adjust_mem_offset(vq, buf);
> > +
> > +     return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
> >
> >
>
> For all these functions you should only call v4l2_m2m_adjust_mem_offset() if !ret.
> If the vb2_* function returned an error, then the offset fields aren't filled in,
> so it makes no sense to update them. And besides, the struct isn't copied back to
> userspace anyway on error.

Got it. That makes more sense than the original code.

ChenYu



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux