diff mbox

[1/6,v4] V4L: add two new ioctl()s for multi-size videobuffer management

Message ID Pine.LNX.4.64.1108050908590.26715@axis700.grange (mailing list archive)
State RFC
Headers show

Commit Message

Guennadi Liakhovetski Aug. 5, 2011, 7:47 a.m. UTC
A possibility to preallocate and initialise buffers of different sizes
in V4L2 is required for an efficient implementation of asnapshot mode.
This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
VIDIOC_PREPARE_BUF and defines respective data structures.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---

v4:

1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
   argument, instead of a frame format specification, including 
   documentation update
2. documentation improvements, as suggested by Hans
3. increased reserved fields to 18, as suggested by Sakari

 Documentation/DocBook/media/v4l/io.xml             |   17 ++
 Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
 .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 ++++++++++++++++++++
 .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
 drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
 drivers/media/video/v4l2-ioctl.c                   |   26 +++
 include/linux/videodev2.h                          |   18 +++
 include/media/v4l2-ioctl.h                         |    2 +
 8 files changed, 328 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
 create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml

Comments

Sakari Ailus Aug. 6, 2011, 6:42 p.m. UTC | #1
Guennadi Liakhovetski wrote:
> A possibility to preallocate and initialise buffers of different sizes
> in V4L2 is required for an efficient implementation of asnapshot mode.
> This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> VIDIOC_PREPARE_BUF and defines respective data structures.
> 
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---

Hi Guennadi,

Many thanks for the patchset! I have a few comments below, after reading
through the patch once again.

> 
> v4:
> 
> 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
>    argument, instead of a frame format specification, including 
>    documentation update
> 2. documentation improvements, as suggested by Hans
> 3. increased reserved fields to 18, as suggested by Sakari
> 
>  Documentation/DocBook/media/v4l/io.xml             |   17 ++
>  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 ++++++++++++++++++++
>  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
>  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
>  drivers/media/video/v4l2-ioctl.c                   |   26 +++
>  include/linux/videodev2.h                          |   18 +++
>  include/media/v4l2-ioctl.h                         |    2 +
>  8 files changed, 328 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> 
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 227e7ac..ff03dd2 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -927,6 +927,23 @@ ioctl is called.</entry>
>  Applications set or clear this flag before calling the
>  <constant>VIDIOC_QBUF</constant> ioctl.</entry>
>  	  </row>
> +	  <row>
> +	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
> +	    <entry>0x0400</entry>
> +	    <entry>Caches do not have to be invalidated for this buffer.
> +Typically applications shall use this flag if the data captured in the buffer
> +is not going to be touched by the CPU, instead the buffer will, probably, be
> +passed on to a DMA-capable hardware unit for further processing or output.
> +</entry>
> +	  </row>
> +	  <row>
> +	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
> +	    <entry>0x0800</entry>
> +	    <entry>Caches do not have to be cleaned for this buffer.
> +Typically applications shall use this flag for output buffers if the data
> +in this buffer has not been created by the CPU but by some DMA-capable unit,
> +in which case caches have not been used.</entry>
> +	  </row>
>  	</tbody>
>        </tgroup>
>      </table>
> diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
> index 0d05e87..06bb179 100644
> --- a/Documentation/DocBook/media/v4l/v4l2.xml
> +++ b/Documentation/DocBook/media/v4l/v4l2.xml
> @@ -462,6 +462,7 @@ and discussions on the V4L mailing list.</revremark>
>      &sub-close;
>      &sub-ioctl;
>      <!-- All ioctls go here. -->
> +    &sub-create-bufs;
>      &sub-cropcap;
>      &sub-dbg-g-chip-ident;
>      &sub-dbg-g-register;
> @@ -504,6 +505,7 @@ and discussions on the V4L mailing list.</revremark>
>      &sub-queryctrl;
>      &sub-query-dv-preset;
>      &sub-querystd;
> +    &sub-prepare-buf;
>      &sub-reqbufs;
>      &sub-s-hw-freq-seek;
>      &sub-streamon;
> diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> new file mode 100644
> index 0000000..b37b9a4
> --- /dev/null
> +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> @@ -0,0 +1,161 @@
> +<refentry id="vidioc-create-bufs">
> +  <refmeta>
> +    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
> +    &manvol;
> +  </refmeta>
> +
> +  <refnamediv>
> +    <refname>VIDIOC_CREATE_BUFS</refname>
> +    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
> +  </refnamediv>
> +
> +  <refsynopsisdiv>
> +    <funcsynopsis>
> +      <funcprototype>
> +	<funcdef>int <function>ioctl</function></funcdef>
> +	<paramdef>int <parameter>fd</parameter></paramdef>
> +	<paramdef>int <parameter>request</parameter></paramdef>
> +	<paramdef>struct v4l2_create_buffers *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +  </refsynopsisdiv>
> +
> +  <refsect1>
> +    <title>Arguments</title>
> +
> +    <variablelist>
> +      <varlistentry>
> +	<term><parameter>fd</parameter></term>
> +	<listitem>
> +	  <para>&fd;</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>request</parameter></term>
> +	<listitem>
> +	  <para>VIDIOC_CREATE_BUFS</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>argp</parameter></term>
> +	<listitem>
> +	  <para></para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +  <refsect1>
> +    <title>Description</title>
> +
> +    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
> +mapped</link> or <link linkend="userp">user pointer</link>
> +I/O. It can be used as an alternative or in addition to the
> +<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
> +is required. This ioctl can be called multiple times to create buffers of
> +different sizes.</para>
> +
> +    <para>To allocate device buffers applications initialize relevant
> +fields of the <structname>v4l2_create_buffers</structname> structure.
> +They set the <structfield>type</structfield> field  to the respective stream
> +or buffer type. <structfield>count</structfield> must be set to the number of
> +required buffers. <structfield>memory</structfield> specifies the required I/O
> +method. If <structfield>num_planes</structfield> == 0 or all elements of the
> +<structfield>sizes</structfield> array are 0, then buffers, suitable for the
> +currently configured video format, are allocated, exactly like for the
> +<constant>VIDIOC_REQBUFS</constant> ioctl. If
> +<structfield>num_planes</structfield> > 0 and at least some of the respective
> +<structfield>sizes</structfield> elements are non-zero, this information will be
> +used for buffer-allocation. The <structfield>reserved</structfield> array must
> +be zeroed. When the ioctl is called with a pointer to this structure the driver
> +will attempt to allocate up to the requested number of buffers and store the
> +actual number allocated and the starting index in the
> +<structfield>count</structfield> and the <structfield>index</structfield>
> +fields respectively. On return <structfield>count</structfield> can be smaller
> +than the number requested.</para>
> +    <para>When the I/O method is not supported the ioctl
> +returns an &EINVAL;.</para>
> +
> +    <table pgwide="1" frame="none" id="v4l2-create-buffers">
> +      <title>struct <structname>v4l2_create_buffers</structname></title>
> +      <tgroup cols="3">
> +	&cs-str;
> +	<tbody valign="top">
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>index</structfield></entry>
> +	    <entry>The starting buffer index, returned by the driver.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>count</structfield></entry>
> +	    <entry>The number of buffers requested or granted.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>type</structfield></entry>
> +	    <entry>V4L2 buffer type: one of <constant>V4L2_BUF_TYPE_*</constant>
> +values.</entry>

&v4l2-buf-type;

here?

> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>memory</structfield></entry>
> +	    <entry>Applications set this field to
> +<constant>V4L2_MEMORY_MMAP</constant> or
> +<constant>V4L2_MEMORY_USERPTR</constant>.</entry>

&v4l2-memory;

> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>fourcc</structfield></entry>
> +	    <entry>One of V4L2_PIX_FMT_* FOURCCs of the video data.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>num_planes</structfield></entry>
> +	    <entry>Number of planes or 0 to use the current format.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>size[VIDEO_MAX_PLANES]</structfield></entry>
> +	    <entry>Explicit sizes of buffers, being created.</entry>
> +	  </row>
> +	  <row>
> +	    <entry>__u32</entry>
> +	    <entry><structfield>reserved</structfield>[18]</entry>
> +	    <entry>A place holder for future extensions.</entry>
> +	  </row>
> +	</tbody>
> +      </tgroup>
> +    </table>
> +  </refsect1>
> +
> +  <refsect1>
> +    &return-value;
> +
> +    <variablelist>
> +      <varlistentry>
> +	<term><errorcode>ENOMEM</errorcode></term>
> +	<listitem>
> +	  <para>No memory to allocate buffers for <link linkend="mmap">memory
> +mapped</link> I/O.</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><errorcode>EINVAL</errorcode></term>
> +	<listitem>
> +	  <para>The buffer type (<structfield>type</structfield> field) or the
> +requested I/O method (<structfield>memory</structfield>) is not
> +supported.</para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +</refentry>
> +
> +<!--
> +Local Variables:
> +mode: sgml
> +sgml-parent-document: "v4l2.sgml"
> +indent-tabs-mode: nil
> +End:
> +-->
> diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> new file mode 100644
> index 0000000..509e752
> --- /dev/null
> +++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> @@ -0,0 +1,96 @@
> +<refentry id="vidioc-prepare-buf">
> +  <refmeta>
> +    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
> +    &manvol;
> +  </refmeta>
> +
> +  <refnamediv>
> +    <refname>VIDIOC_PREPARE_BUF</refname>
> +    <refpurpose>Prepare a buffer for I/O</refpurpose>
> +  </refnamediv>
> +
> +  <refsynopsisdiv>
> +    <funcsynopsis>
> +      <funcprototype>
> +	<funcdef>int <function>ioctl</function></funcdef>
> +	<paramdef>int <parameter>fd</parameter></paramdef>
> +	<paramdef>int <parameter>request</parameter></paramdef>
> +	<paramdef>struct v4l2_buffer *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +  </refsynopsisdiv>
> +
> +  <refsect1>
> +    <title>Arguments</title>
> +
> +    <variablelist>
> +      <varlistentry>
> +	<term><parameter>fd</parameter></term>
> +	<listitem>
> +	  <para>&fd;</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>request</parameter></term>
> +	<listitem>
> +	  <para>VIDIOC_PREPARE_BUF</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><parameter>argp</parameter></term>
> +	<listitem>
> +	  <para></para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +  <refsect1>
> +    <title>Description</title>
> +
> +    <para>Applications can optionally call the
> +<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
> +to the driver before actually enqueuing it, using the
> +<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.

s/<constant>VIDIOC_QBUF</constant>/&VIDIOC_QBUF;/

> +Such preparations may include cache invalidation or cleaning. Performing them
> +in advance saves time during the actual I/O. In case such cache operations are
> +not required, the application can use one of
> +<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
> +<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
> +step.</para>
> +
> +    <para>The <structname>v4l2_buffer</structname> structure is

s/<structname>v4l2_buffer</structname>/&v4l2-buffer;/

> +specified in <xref linkend="buffer" />.</para>
> +  </refsect1>
> +
> +  <refsect1>
> +    &return-value;
> +
> +    <variablelist>
> +      <varlistentry>
> +	<term><errorcode>EBUSY</errorcode></term>
> +	<listitem>
> +	  <para>File I/O is in progress.</para>
> +	</listitem>
> +      </varlistentry>
> +      <varlistentry>
> +	<term><errorcode>EINVAL</errorcode></term>
> +	<listitem>
> +	  <para>The buffer <structfield>type</structfield> is not
> +supported, or the <structfield>index</structfield> is out of bounds,
> +or no buffers have been allocated yet, or the
> +<structfield>userptr</structfield> or
> +<structfield>length</structfield> are invalid.</para>
> +	</listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +</refentry>
> +
> +<!--
> +Local Variables:
> +mode: sgml
> +sgml-parent-document: "v4l2.sgml"
> +indent-tabs-mode: nil
> +End:
> +-->
> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> index 61979b7..ee5eec8 100644
> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> @@ -702,6 +702,7 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
>  #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
>  #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
>  #define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
> +#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
>  
>  #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
>  #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
> @@ -751,6 +752,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>  	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
>  	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
>  	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
> +	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
>  	}
>  
>  	switch (cmd) {
> @@ -775,6 +777,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>  		compatible_arg = 0;
>  		break;
>  
> +	case VIDIOC_PREPARE_BUF:
>  	case VIDIOC_QUERYBUF:
>  	case VIDIOC_QBUF:
>  	case VIDIOC_DQBUF:
> @@ -860,6 +863,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>  		err = put_v4l2_format32(&karg.v2f, up);
>  		break;
>  
> +	case VIDIOC_PREPARE_BUF:
>  	case VIDIOC_QUERYBUF:
>  	case VIDIOC_QBUF:
>  	case VIDIOC_DQBUF:
> @@ -959,6 +963,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
>  	case VIDIOC_DQEVENT32:
>  	case VIDIOC_SUBSCRIBE_EVENT:
>  	case VIDIOC_UNSUBSCRIBE_EVENT:
> +	case VIDIOC_CREATE_BUFS:
> +	case VIDIOC_PREPARE_BUF32:
>  		ret = do_video_ioctl(file, cmd, arg);
>  		break;
>  
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 002ce13..3da87c0 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = {
>  	[_IOC_NR(VIDIOC_DQEVENT)]	   = "VIDIOC_DQEVENT",
>  	[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
>  	[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
> +	[_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
> +	[_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
>  };
>  #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>  
> @@ -2216,6 +2218,30 @@ static long __video_do_ioctl(struct file *file,
>  		dbgarg(cmd, "type=0x%8.8x", sub->type);
>  		break;
>  	}
> +	case VIDIOC_CREATE_BUFS:
> +	{
> +		struct v4l2_create_buffers *create = arg;
> +
> +		if (!ops->vidioc_create_bufs)
> +			break;
> +
> +		ret = ops->vidioc_create_bufs(file, fh, create);
> +
> +		dbgarg(cmd, "count=%u @ %u\n", create->count, create->index);
> +		break;
> +	}
> +	case VIDIOC_PREPARE_BUF:
> +	{
> +		struct v4l2_buffer *b = arg;
> +
> +		if (!ops->vidioc_prepare_buf)
> +			break;
> +
> +		ret = ops->vidioc_prepare_buf(file, fh, b);
> +
> +		dbgarg(cmd, "index=%d", b->index);
> +		break;
> +	}
>  	default:
>  	{
>  		bool valid_prio = true;
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index fca24cc..3cd0cb3 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -653,6 +653,9 @@ struct v4l2_buffer {
>  #define V4L2_BUF_FLAG_ERROR	0x0040
>  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
>  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> +/* Cache handling flags */
> +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800

Do we want to have a flag to tell the buffer has been prepared but not
queued yet? I'm not at all certain such a flag would be required; just
asking.

Perhaps the ERROR flag should be reset if it is present.

If the answer to either of the above is yes, the PREPARE_BUF would need
to be WR ioctl.

>  /*
>   *	O V E R L A Y   P R E V I E W
> @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
>  	__u32 revision;    /* chip revision, chip specific */
>  } __attribute__ ((packed));
>  
> +/* VIDIOC_CREATE_BUFS */
> +struct v4l2_create_buffers {
> +	__u32	index;	/* output: buffers index...index + count - 1 have been created */
> +	__u32	count;
> +	__u32	type;
> +	__u32	memory;
> +	__u32	fourcc;
> +	__u32	num_planes;
> +	__u32	sizes[VIDEO_MAX_PLANES];
> +	__u32	reserved[18];
> +};
> +
>  /*
>   *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
>   *
> @@ -2182,6 +2197,9 @@ struct v4l2_dbg_chip_ident {
>  #define	VIDIOC_SUBSCRIBE_EVENT	 _IOW('V', 90, struct v4l2_event_subscription)
>  #define	VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
>  
> +#define VIDIOC_CREATE_BUFS	_IOWR('V', 92, struct v4l2_create_buffers)
> +#define VIDIOC_PREPARE_BUF	 _IOW('V', 93, struct v4l2_buffer)
>  /* Reminder: when adding new ioctls please add support for them to
>     drivers/media/video/v4l2-compat-ioctl32.c as well! */
>  
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index dd9f1e7..4d1c74a 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -122,6 +122,8 @@ struct v4l2_ioctl_ops {
>  	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
>  	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
>  
> +	int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
> +	int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
>  
>  	int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
>  	int (*vidioc_g_fbuf)   (struct file *file, void *fh,

Kind regards,
Pawel Osciak Aug. 6, 2011, 9:51 p.m. UTC | #2
Hi Guennadi,

On Fri, Aug 5, 2011 at 00:47, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> A possibility to preallocate and initialise buffers of different sizes
> in V4L2 is required for an efficient implementation of asnapshot mode.
> This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> VIDIOC_PREPARE_BUF and defines respective data structures.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> v4:
>
> 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its
>   argument, instead of a frame format specification, including
>   documentation update
> 2. documentation improvements, as suggested by Hans
> 3. increased reserved fields to 18, as suggested by Sakari
>
>  Documentation/DocBook/media/v4l/io.xml             |   17 ++
>  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 ++++++++++++++++++++
>  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
>  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
>  drivers/media/video/v4l2-ioctl.c                   |   26 +++
>  include/linux/videodev2.h                          |   18 +++
>  include/media/v4l2-ioctl.h                         |    2 +
>  8 files changed, 328 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
>
> diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
> index 227e7ac..ff03dd2 100644
> --- a/Documentation/DocBook/media/v4l/io.xml
> +++ b/Documentation/DocBook/media/v4l/io.xml
> @@ -927,6 +927,23 @@ ioctl is called.</entry>
>  Applications set or clear this flag before calling the
>  <constant>VIDIOC_QBUF</constant> ioctl.</entry>
>          </row>
> +         <row>
> +           <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
> +           <entry>0x0400</entry>
> +           <entry>Caches do not have to be invalidated for this buffer.
> +Typically applications shall use this flag if the data captured in the buffer
> +is not going to be touched by the CPU, instead the buffer will, probably, be
> +passed on to a DMA-capable hardware unit for further processing or output.
> +</entry>
> +         </row>
> +         <row>
> +           <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
> +           <entry>0x0800</entry>
> +           <entry>Caches do not have to be cleaned for this buffer.
> +Typically applications shall use this flag for output buffers if the data
> +in this buffer has not been created by the CPU but by some DMA-capable unit,
> +in which case caches have not been used.</entry>
> +         </row>
>        </tbody>
>       </tgroup>
>     </table>
> diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
> index 0d05e87..06bb179 100644
> --- a/Documentation/DocBook/media/v4l/v4l2.xml
> +++ b/Documentation/DocBook/media/v4l/v4l2.xml
> @@ -462,6 +462,7 @@ and discussions on the V4L mailing list.</revremark>
>     &sub-close;
>     &sub-ioctl;
>     <!-- All ioctls go here. -->
> +    &sub-create-bufs;
>     &sub-cropcap;
>     &sub-dbg-g-chip-ident;
>     &sub-dbg-g-register;
> @@ -504,6 +505,7 @@ and discussions on the V4L mailing list.</revremark>
>     &sub-queryctrl;
>     &sub-query-dv-preset;
>     &sub-querystd;
> +    &sub-prepare-buf;
>     &sub-reqbufs;
>     &sub-s-hw-freq-seek;
>     &sub-streamon;
> diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> new file mode 100644
> index 0000000..b37b9a4
> --- /dev/null
> +++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> @@ -0,0 +1,161 @@
> +<refentry id="vidioc-create-bufs">
> +  <refmeta>
> +    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
> +    &manvol;
> +  </refmeta>
> +
> +  <refnamediv>
> +    <refname>VIDIOC_CREATE_BUFS</refname>
> +    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
> +  </refnamediv>
> +
> +  <refsynopsisdiv>
> +    <funcsynopsis>
> +      <funcprototype>
> +       <funcdef>int <function>ioctl</function></funcdef>
> +       <paramdef>int <parameter>fd</parameter></paramdef>
> +       <paramdef>int <parameter>request</parameter></paramdef>
> +       <paramdef>struct v4l2_create_buffers *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +  </refsynopsisdiv>
> +
> +  <refsect1>
> +    <title>Arguments</title>
> +
> +    <variablelist>
> +      <varlistentry>
> +       <term><parameter>fd</parameter></term>
> +       <listitem>
> +         <para>&fd;</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><parameter>request</parameter></term>
> +       <listitem>
> +         <para>VIDIOC_CREATE_BUFS</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><parameter>argp</parameter></term>
> +       <listitem>
> +         <para></para>
> +       </listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +  <refsect1>
> +    <title>Description</title>
> +
> +    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
> +mapped</link> or <link linkend="userp">user pointer</link>
> +I/O. It can be used as an alternative or in addition to the
> +<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
> +is required. This ioctl can be called multiple times to create buffers of
> +different sizes.</para>
> +
> +    <para>To allocate device buffers applications initialize relevant
> +fields of the <structname>v4l2_create_buffers</structname> structure.
> +They set the <structfield>type</structfield> field  to the respective stream
> +or buffer type. <structfield>count</structfield> must be set to the number of
> +required buffers. <structfield>memory</structfield> specifies the required I/O
> +method. If <structfield>num_planes</structfield> == 0 or all elements of the
> +<structfield>sizes</structfield> array are 0, then buffers, suitable for the
> +currently configured video format, are allocated, exactly like for the
> +<constant>VIDIOC_REQBUFS</constant> ioctl. If
> +<structfield>num_planes</structfield> > 0 and at least some of the respective
> +<structfield>sizes</structfield> elements are non-zero, this information will be

Instead of "at least some must be filled", I would say it more strongly:
"If num_planes > 0, the elements in range 0 to num_planes-1 have to be
filled with desired plane sizes for each buffer. This information will
then be used instead of current format for buffer allocation." or
something similar.
Unless we want to allow sizes for some planes to be taken from format
and some from sizes[], which I doubt...

> +used for buffer-allocation. The <structfield>reserved</structfield> array must
> +be zeroed. When the ioctl is called with a pointer to this structure the driver
> +will attempt to allocate up to the requested number of buffers and store the
> +actual number allocated and the starting index in the
> +<structfield>count</structfield> and the <structfield>index</structfield>
> +fields respectively. On return <structfield>count</structfield> can be smaller

Needs a comma after "return".

> +than the number requested.</para>
> +    <para>When the I/O method is not supported the ioctl
> +returns an &EINVAL;.</para>
> +
> +    <table pgwide="1" frame="none" id="v4l2-create-buffers">
> +      <title>struct <structname>v4l2_create_buffers</structname></title>
> +      <tgroup cols="3">
> +       &cs-str;
> +       <tbody valign="top">
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>index</structfield></entry>
> +           <entry>The starting buffer index, returned by the driver.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>count</structfield></entry>
> +           <entry>The number of buffers requested or granted.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>type</structfield></entry>
> +           <entry>V4L2 buffer type: one of <constant>V4L2_BUF_TYPE_*</constant>
> +values.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>memory</structfield></entry>
> +           <entry>Applications set this field to
> +<constant>V4L2_MEMORY_MMAP</constant> or
> +<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>fourcc</structfield></entry>
> +           <entry>One of V4L2_PIX_FMT_* FOURCCs of the video data.</entry>
> +         </row>

If sizes is zero, we use the currently configured format, but if this
is filled, this overrides the currently selected format, right? But in
that case, sizes should be specified as well. I think it should be
described explicitly above. So maybe "if fourcc is specified, sizes
has to be filled and those parameters override the currently
configured format; if either fourcc or sizes is not specified, the
currently configured format is used".

> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>num_planes</structfield></entry>
> +           <entry>Number of planes or 0 to use the current format.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>size[VIDEO_MAX_PLANES]</structfield></entry>
> +           <entry>Explicit sizes of buffers, being created.</entry>
> +         </row>
> +         <row>
> +           <entry>__u32</entry>
> +           <entry><structfield>reserved</structfield>[18]</entry>
> +           <entry>A place holder for future extensions.</entry>
> +         </row>
> +       </tbody>
> +      </tgroup>
> +    </table>
> +  </refsect1>
> +
> +  <refsect1>
> +    &return-value;
> +
> +    <variablelist>
> +      <varlistentry>
> +       <term><errorcode>ENOMEM</errorcode></term>
> +       <listitem>
> +         <para>No memory to allocate buffers for <link linkend="mmap">memory
> +mapped</link> I/O.</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><errorcode>EINVAL</errorcode></term>
> +       <listitem>
> +         <para>The buffer type (<structfield>type</structfield> field) or the
> +requested I/O method (<structfield>memory</structfield>) is not
> +supported.</para>

Do we also return this error if the provided fourcc format is not supported?

> +       </listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +</refentry>
> +
> +<!--
> +Local Variables:
> +mode: sgml
> +sgml-parent-document: "v4l2.sgml"
> +indent-tabs-mode: nil
> +End:
> +-->
> diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> new file mode 100644
> index 0000000..509e752
> --- /dev/null
> +++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> @@ -0,0 +1,96 @@
> +<refentry id="vidioc-prepare-buf">
> +  <refmeta>
> +    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
> +    &manvol;
> +  </refmeta>
> +
> +  <refnamediv>
> +    <refname>VIDIOC_PREPARE_BUF</refname>
> +    <refpurpose>Prepare a buffer for I/O</refpurpose>
> +  </refnamediv>
> +
> +  <refsynopsisdiv>
> +    <funcsynopsis>
> +      <funcprototype>
> +       <funcdef>int <function>ioctl</function></funcdef>
> +       <paramdef>int <parameter>fd</parameter></paramdef>
> +       <paramdef>int <parameter>request</parameter></paramdef>
> +       <paramdef>struct v4l2_buffer *<parameter>argp</parameter></paramdef>
> +      </funcprototype>
> +    </funcsynopsis>
> +  </refsynopsisdiv>
> +
> +  <refsect1>
> +    <title>Arguments</title>
> +
> +    <variablelist>
> +      <varlistentry>
> +       <term><parameter>fd</parameter></term>
> +       <listitem>
> +         <para>&fd;</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><parameter>request</parameter></term>
> +       <listitem>
> +         <para>VIDIOC_PREPARE_BUF</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><parameter>argp</parameter></term>
> +       <listitem>
> +         <para></para>
> +       </listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +
> +  <refsect1>
> +    <title>Description</title>
> +
> +    <para>Applications can optionally call the
> +<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
> +to the driver before actually enqueuing it, using the
> +<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
> +Such preparations may include cache invalidation or cleaning. Performing them
> +in advance saves time during the actual I/O. In case such cache operations are
> +not required, the application can use one of
> +<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
> +<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
> +step.</para>
> +
> +    <para>The <structname>v4l2_buffer</structname> structure is
> +specified in <xref linkend="buffer" />.</para>
> +  </refsect1>
> +
> +  <refsect1>
> +    &return-value;
> +
> +    <variablelist>
> +      <varlistentry>
> +       <term><errorcode>EBUSY</errorcode></term>
> +       <listitem>
> +         <para>File I/O is in progress.</para>
> +       </listitem>
> +      </varlistentry>
> +      <varlistentry>
> +       <term><errorcode>EINVAL</errorcode></term>
> +       <listitem>
> +         <para>The buffer <structfield>type</structfield> is not
> +supported, or the <structfield>index</structfield> is out of bounds,
> +or no buffers have been allocated yet, or the
> +<structfield>userptr</structfield> or
> +<structfield>length</structfield> are invalid.</para>
> +       </listitem>
> +      </varlistentry>
> +    </variablelist>
> +  </refsect1>
> +</refentry>
> +
> +<!--
> +Local Variables:
> +mode: sgml
> +sgml-parent-document: "v4l2.sgml"
> +indent-tabs-mode: nil
> +End:
> +-->
> diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
> index 61979b7..ee5eec8 100644
> --- a/drivers/media/video/v4l2-compat-ioctl32.c
> +++ b/drivers/media/video/v4l2-compat-ioctl32.c
> @@ -702,6 +702,7 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
>  #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
>  #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
>  #define        VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
> +#define VIDIOC_PREPARE_BUF32   _IOWR('V', 93, struct v4l2_buffer32)
>
>  #define VIDIOC_OVERLAY32       _IOW ('V', 14, s32)
>  #define VIDIOC_STREAMON32      _IOW ('V', 18, s32)
> @@ -751,6 +752,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>        case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
>        case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
>        case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
> +       case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
>        }
>
>        switch (cmd) {
> @@ -775,6 +777,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>                compatible_arg = 0;
>                break;
>
> +       case VIDIOC_PREPARE_BUF:
>        case VIDIOC_QUERYBUF:
>        case VIDIOC_QBUF:
>        case VIDIOC_DQBUF:
> @@ -860,6 +863,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
>                err = put_v4l2_format32(&karg.v2f, up);
>                break;
>
> +       case VIDIOC_PREPARE_BUF:
>        case VIDIOC_QUERYBUF:
>        case VIDIOC_QBUF:
>        case VIDIOC_DQBUF:
> @@ -959,6 +963,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
>        case VIDIOC_DQEVENT32:
>        case VIDIOC_SUBSCRIBE_EVENT:
>        case VIDIOC_UNSUBSCRIBE_EVENT:
> +       case VIDIOC_CREATE_BUFS:
> +       case VIDIOC_PREPARE_BUF32:
>                ret = do_video_ioctl(file, cmd, arg);
>                break;
>
> diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
> index 002ce13..3da87c0 100644
> --- a/drivers/media/video/v4l2-ioctl.c
> +++ b/drivers/media/video/v4l2-ioctl.c
> @@ -260,6 +260,8 @@ static const char *v4l2_ioctls[] = {
>        [_IOC_NR(VIDIOC_DQEVENT)]          = "VIDIOC_DQEVENT",
>        [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
>        [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
> +       [_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
> +       [_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
>  };
>  #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
>
> @@ -2216,6 +2218,30 @@ static long __video_do_ioctl(struct file *file,
>                dbgarg(cmd, "type=0x%8.8x", sub->type);
>                break;
>        }
> +       case VIDIOC_CREATE_BUFS:
> +       {
> +               struct v4l2_create_buffers *create = arg;
> +
> +               if (!ops->vidioc_create_bufs)
> +                       break;
> +
> +               ret = ops->vidioc_create_bufs(file, fh, create);
> +
> +               dbgarg(cmd, "count=%u @ %u\n", create->count, create->index);
> +               break;
> +       }
> +       case VIDIOC_PREPARE_BUF:
> +       {
> +               struct v4l2_buffer *b = arg;
> +
> +               if (!ops->vidioc_prepare_buf)
> +                       break;
> +
> +               ret = ops->vidioc_prepare_buf(file, fh, b);
> +
> +               dbgarg(cmd, "index=%d", b->index);
> +               break;
> +       }
>        default:
>        {
>                bool valid_prio = true;
> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index fca24cc..3cd0cb3 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -653,6 +653,9 @@ struct v4l2_buffer {
>  #define V4L2_BUF_FLAG_ERROR    0x0040
>  #define V4L2_BUF_FLAG_TIMECODE 0x0100  /* timecode field is valid */
>  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> +/* Cache handling flags */
> +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE      0x0400
> +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN           0x0800
>
>  /*
>  *     O V E R L A Y   P R E V I E W
> @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
>        __u32 revision;    /* chip revision, chip specific */
>  } __attribute__ ((packed));
>
> +/* VIDIOC_CREATE_BUFS */
> +struct v4l2_create_buffers {
> +       __u32   index;  /* output: buffers index...index + count - 1 have been created */
> +       __u32   count;
> +       __u32   type;
> +       __u32   memory;
> +       __u32   fourcc;
> +       __u32   num_planes;
> +       __u32   sizes[VIDEO_MAX_PLANES];
> +       __u32   reserved[18];
> +};
> +
>  /*
>  *     I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
>  *
> @@ -2182,6 +2197,9 @@ struct v4l2_dbg_chip_ident {
>  #define        VIDIOC_SUBSCRIBE_EVENT   _IOW('V', 90, struct v4l2_event_subscription)
>  #define        VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
>
> +#define VIDIOC_CREATE_BUFS     _IOWR('V', 92, struct v4l2_create_buffers)
> +#define VIDIOC_PREPARE_BUF      _IOW('V', 93, struct v4l2_buffer)
> +
>  /* Reminder: when adding new ioctls please add support for them to
>    drivers/media/video/v4l2-compat-ioctl32.c as well! */
>
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index dd9f1e7..4d1c74a 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -122,6 +122,8 @@ struct v4l2_ioctl_ops {
>        int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
>        int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
>
> +       int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
> +       int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
>
>        int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
>        int (*vidioc_g_fbuf)   (struct file *file, void *fh,
> --
> 1.7.2.5
>
>
Hans Verkuil (hansverk) Aug. 8, 2011, 9:16 a.m. UTC | #3
Hi Guennadi!

On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> A possibility to preallocate and initialise buffers of different sizes
> in V4L2 is required for an efficient implementation of asnapshot mode.
> This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> VIDIOC_PREPARE_BUF and defines respective data structures.
> 
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
> 
> v4:
> 
> 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
>    argument, instead of a frame format specification, including 
>    documentation update
> 2. documentation improvements, as suggested by Hans
> 3. increased reserved fields to 18, as suggested by Sakari
> 
>  Documentation/DocBook/media/v4l/io.xml             |   17 ++
>  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
>  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 
++++++++++++++++++++
>  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
>  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
>  drivers/media/video/v4l2-ioctl.c                   |   26 +++
>  include/linux/videodev2.h                          |   18 +++
>  include/media/v4l2-ioctl.h                         |    2 +
>  8 files changed, 328 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
>  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> 

<snip>

> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> index fca24cc..3cd0cb3 100644
> --- a/include/linux/videodev2.h
> +++ b/include/linux/videodev2.h
> @@ -653,6 +653,9 @@ struct v4l2_buffer {
>  #define V4L2_BUF_FLAG_ERROR	0x0040
>  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
>  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> +/* Cache handling flags */
> +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
>  
>  /*
>   *	O V E R L A Y   P R E V I E W
> @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
>  	__u32 revision;    /* chip revision, chip specific */
>  } __attribute__ ((packed));
>  
> +/* VIDIOC_CREATE_BUFS */
> +struct v4l2_create_buffers {
> +	__u32	index;	/* output: buffers index...index + count - 1 have been 
created */
> +	__u32	count;
> +	__u32	type;
> +	__u32	memory;
> +	__u32	fourcc;
> +	__u32	num_planes;
> +	__u32	sizes[VIDEO_MAX_PLANES];
> +	__u32	reserved[18];
> +};

I know you are going to hate me for this, but I've changed my mind: I think
this should use a struct v4l2_format after all.

This change of heart came out of discussions during the V4L2 brainstorm 
meeting last week. The only way to be sure the buffers are allocated optimally 
is if the driver has all the information. The easiest way to do that is by 
passing struct v4l2_format. This is also consistent with REQBUFS since that 
uses the information from the currently selected format (i.e. what you get 
back from VIDIOC_G_FMT).

There can be subtle behaviors such as allocating from different memory back 
based on the fourcc and the size of the image.

One reason why I liked passing sizes directly is that it allows the caller to 
ask for more memory than is strictly necessary.

However, while brainstorming last week the suggestion was made that there is 
no reason why the user can't set the sizeimage field in 
v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec explicitly 
mentions that the sizeimage field is set by the driver, but for the new 
CREATEBUFS ioctl no such limitation has to be placed. The only thing necessary 
is to ensure that sizeimage is not too small (and you probably want some 
sanity check against crazy values as well).

This way the decision on how to allocate memory is the same between REQBUFS 
and CREATEBUFS (i.e. both use v4l2_format information), but there is no need 
for a union as we had in the initial proposal since apps can set the sizeimage 
to something larger than strictly necessary (or just leave it to 0 to get the 
smallest size).

Regards,

	Hans

> +
>  /*
>   *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
>   *
> @@ -2182,6 +2197,9 @@ struct v4l2_dbg_chip_ident {
>  #define	VIDIOC_SUBSCRIBE_EVENT	 _IOW('V', 90, struct 
v4l2_event_subscription)
>  #define	VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct 
v4l2_event_subscription)
>  
> +#define VIDIOC_CREATE_BUFS	_IOWR('V', 92, struct v4l2_create_buffers)
> +#define VIDIOC_PREPARE_BUF	 _IOW('V', 93, struct v4l2_buffer)
> +
>  /* Reminder: when adding new ioctls please add support for them to
>     drivers/media/video/v4l2-compat-ioctl32.c as well! */
>  
> diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
> index dd9f1e7..4d1c74a 100644
> --- a/include/media/v4l2-ioctl.h
> +++ b/include/media/v4l2-ioctl.h
> @@ -122,6 +122,8 @@ struct v4l2_ioctl_ops {
>  	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer 
*b);
>  	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer 
*b);
>  
> +	int (*vidioc_create_bufs)(struct file *file, void *fh, struct 
v4l2_create_buffers *b);
> +	int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer 
*b);
>  
>  	int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
>  	int (*vidioc_g_fbuf)   (struct file *file, void *fh,
> -- 
> 1.7.2.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Aug. 8, 2011, 11:40 a.m. UTC | #4
On Monday 08 August 2011 11:16:41 Hans Verkuil wrote:
> On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > A possibility to preallocate and initialise buffers of different sizes
> > in V4L2 is required for an efficient implementation of asnapshot mode.
> > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > VIDIOC_PREPARE_BUF and defines respective data structures.
> > 
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> > 
> > v4:
> > 
> > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its
> > 
> >    argument, instead of a frame format specification, including
> >    documentation update
> > 
> > 2. documentation improvements, as suggested by Hans
> > 3. increased reserved fields to 18, as suggested by Sakari
> > 
> >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
> 
> ++++++++++++++++++++
> 
> >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
> >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> >  include/linux/videodev2.h                          |   18 +++
> >  include/media/v4l2-ioctl.h                         |    2 +
> >  8 files changed, 328 insertions(+), 0 deletions(-)
> >  create mode 100644
> >  Documentation/DocBook/media/v4l/vidioc-create-bufs.xml create mode
> >  100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> 
> <snip>
> 
> > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > index fca24cc..3cd0cb3 100644
> > --- a/include/linux/videodev2.h
> > +++ b/include/linux/videodev2.h
> > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > 
> >  #define V4L2_BUF_FLAG_ERROR	0x0040
> >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > 
> > +/* Cache handling flags */
> > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > 
> >  /*
> >  
> >   *	O V E R L A Y   P R E V I E W
> > 
> > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > 
> >  	__u32 revision;    /* chip revision, chip specific */
> >  
> >  } __attribute__ ((packed));
> > 
> > +/* VIDIOC_CREATE_BUFS */
> > +struct v4l2_create_buffers {
> > +	__u32	index;	/* output: buffers index...index + count - 1 have been
> 
> created */
> 
> > +	__u32	count;
> > +	__u32	type;
> > +	__u32	memory;
> > +	__u32	fourcc;
> > +	__u32	num_planes;
> > +	__u32	sizes[VIDEO_MAX_PLANES];
> > +	__u32	reserved[18];
> > +};
> 
> I know you are going to hate me for this, but I've changed my mind: I think
> this should use a struct v4l2_format after all.
> 
> This change of heart came out of discussions during the V4L2 brainstorm
> meeting last week. The only way to be sure the buffers are allocated
> optimally is if the driver has all the information. The easiest way to do
> that is by passing struct v4l2_format. This is also consistent with
> REQBUFS since that uses the information from the currently selected format
> (i.e. what you get back from VIDIOC_G_FMT).
> 
> There can be subtle behaviors such as allocating from different memory back
> based on the fourcc and the size of the image.
> 
> One reason why I liked passing sizes directly is that it allows the caller
> to ask for more memory than is strictly necessary.
> 
> However, while brainstorming last week the suggestion was made that there
> is no reason why the user can't set the sizeimage field in
> v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec explicitly
> mentions that the sizeimage field is set by the driver, but for the new
> CREATEBUFS ioctl no such limitation has to be placed. The only thing
> necessary is to ensure that sizeimage is not too small (and you probably
> want some sanity check against crazy values as well).

We need to decide on a policy here. What should be the maximum allowable size 
for MMAP buffers ? How do we restrict the requested image size so that 
application won't be allowed to starve the system by requesting memory for 1GP 
images ?

> This way the decision on how to allocate memory is the same between REQBUFS
> and CREATEBUFS (i.e. both use v4l2_format information), but there is no
> need for a union as we had in the initial proposal since apps can set the
> sizeimage to something larger than strictly necessary (or just leave it to
> 0 to get the smallest size).
Hans Verkuil (hansverk) Aug. 8, 2011, 12:40 p.m. UTC | #5
On Monday, August 08, 2011 13:40:23 Laurent Pinchart wrote:
> On Monday 08 August 2011 11:16:41 Hans Verkuil wrote:
> > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > A possibility to preallocate and initialise buffers of different sizes
> > > in V4L2 is required for an efficient implementation of asnapshot mode.
> > > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > 
> > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > ---
> > > 
> > > v4:
> > > 
> > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in 
its
> > > 
> > >    argument, instead of a frame format specification, including
> > >    documentation update
> > > 
> > > 2. documentation improvements, as suggested by Hans
> > > 3. increased reserved fields to 18, as suggested by Sakari
> > > 
> > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
> > 
> > ++++++++++++++++++++
> > 
> > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
> > >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> > >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > >  include/linux/videodev2.h                          |   18 +++
> > >  include/media/v4l2-ioctl.h                         |    2 +
> > >  8 files changed, 328 insertions(+), 0 deletions(-)
> > >  create mode 100644
> > >  Documentation/DocBook/media/v4l/vidioc-create-bufs.xml create mode
> > >  100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > 
> > <snip>
> > 
> > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > index fca24cc..3cd0cb3 100644
> > > --- a/include/linux/videodev2.h
> > > +++ b/include/linux/videodev2.h
> > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > > 
> > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid 
*/
> > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > 
> > > +/* Cache handling flags */
> > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > > 
> > >  /*
> > >  
> > >   *	O V E R L A Y   P R E V I E W
> > > 
> > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > > 
> > >  	__u32 revision;    /* chip revision, chip specific */
> > >  
> > >  } __attribute__ ((packed));
> > > 
> > > +/* VIDIOC_CREATE_BUFS */
> > > +struct v4l2_create_buffers {
> > > +	__u32	index;	/* output: buffers index...index + count - 1 have 
been
> > 
> > created */
> > 
> > > +	__u32	count;
> > > +	__u32	type;
> > > +	__u32	memory;
> > > +	__u32	fourcc;
> > > +	__u32	num_planes;
> > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > +	__u32	reserved[18];
> > > +};
> > 
> > I know you are going to hate me for this, but I've changed my mind: I 
think
> > this should use a struct v4l2_format after all.
> > 
> > This change of heart came out of discussions during the V4L2 brainstorm
> > meeting last week. The only way to be sure the buffers are allocated
> > optimally is if the driver has all the information. The easiest way to do
> > that is by passing struct v4l2_format. This is also consistent with
> > REQBUFS since that uses the information from the currently selected format
> > (i.e. what you get back from VIDIOC_G_FMT).
> > 
> > There can be subtle behaviors such as allocating from different memory 
back
> > based on the fourcc and the size of the image.
> > 
> > One reason why I liked passing sizes directly is that it allows the caller
> > to ask for more memory than is strictly necessary.
> > 
> > However, while brainstorming last week the suggestion was made that there
> > is no reason why the user can't set the sizeimage field in
> > v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec 
explicitly
> > mentions that the sizeimage field is set by the driver, but for the new
> > CREATEBUFS ioctl no such limitation has to be placed. The only thing
> > necessary is to ensure that sizeimage is not too small (and you probably
> > want some sanity check against crazy values as well).
> 
> We need to decide on a policy here. What should be the maximum allowable 
size 
> for MMAP buffers ? How do we restrict the requested image size so that 
> application won't be allowed to starve the system by requesting memory for 
1GP 
> images ?

Either just a arbitrary cap like 1 GB (mainly to prevent any weird calculation 
problems around the 2 GB (signedness) and 4 GB (wrap-around) boundaries), or 
something like 3 or 4 times the minimum buffer size.

I'm in favor of enforcing a 1 GB cap in vb2 and letting drivers enforce a 
policy of their own if that makes sense for them.

I don't really see a problem with requesting large amounts of memory. What 
constitutes 'large' is not something the kernel knows, that's dependent on the 
use case.

Regards,

	Hans

> 
> > This way the decision on how to allocate memory is the same between 
REQBUFS
> > and CREATEBUFS (i.e. both use v4l2_format information), but there is no
> > need for a union as we had in the initial proposal since apps can set the
> > sizeimage to something larger than strictly necessary (or just leave it to
> > 0 to get the smallest size).
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Aug. 8, 2011, 10:06 p.m. UTC | #6
Hi Hans,

On Monday 08 August 2011 14:40:27 Hans Verkuil wrote:
> On Monday, August 08, 2011 13:40:23 Laurent Pinchart wrote:
> > On Monday 08 August 2011 11:16:41 Hans Verkuil wrote:
> > > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > > A possibility to preallocate and initialise buffers of different
> > > > sizes in V4L2 is required for an efficient implementation of
> > > > asnapshot mode. This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS
> > > > and
> > > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > > 
> > > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > > ---
> > > > 
> > > > v4:
> > > > 
> > > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in
> > > >    its argument, instead of a frame format specification, including
> > > >    documentation update
> > > > 
> > > > 2. documentation improvements, as suggested by Hans
> > > > 3. increased reserved fields to 18, as suggested by Sakari
> > > > 
> > > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
> > > 
> > > ++++++++++++++++++++
> > > 
> > > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96
> > > >  ++++++++++++ drivers/media/video/v4l2-compat-ioctl32.c          |  
> > > >   6 + drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > > >  include/linux/videodev2.h                          |   18 +++
> > > >  include/media/v4l2-ioctl.h                         |    2 + 8 files
> > > >  changed, 328 insertions(+), 0 deletions(-)
> > > >  create mode 100644
> > > >  Documentation/DocBook/media/v4l/vidioc-create-bufs.xml create mode
> > > >  100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > > 
> > > <snip>
> > > 
> > > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > > index fca24cc..3cd0cb3 100644
> > > > --- a/include/linux/videodev2.h
> > > > +++ b/include/linux/videodev2.h
> > > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > > > 
> > > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> > > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > > 
> > > > +/* Cache handling flags */
> > > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > > > 
> > > >  /*
> > > >  
> > > >   *	O V E R L A Y   P R E V I E W
> > > > 
> > > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > > > 
> > > >  	__u32 revision;    /* chip revision, chip specific */
> > > >  
> > > >  } __attribute__ ((packed));
> > > > 
> > > > +/* VIDIOC_CREATE_BUFS */
> > > > +struct v4l2_create_buffers {
> > > > +	__u32	index;	/* output: buffers index...index + count - 1 have been
> > > > created */
> > > >
> > > > +	__u32	count;
> > > > +	__u32	type;
> > > > +	__u32	memory;
> > > > +	__u32	fourcc;
> > > > +	__u32	num_planes;
> > > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > > +	__u32	reserved[18];
> > > > +};
> > > 
> > > I know you are going to hate me for this, but I've changed my mind: I
> > > think this should use a struct v4l2_format after all.
> > > 
> > > This change of heart came out of discussions during the V4L2 brainstorm
> > > meeting last week. The only way to be sure the buffers are allocated
> > > optimally is if the driver has all the information. The easiest way to
> > > do that is by passing struct v4l2_format. This is also consistent with
> > > REQBUFS since that uses the information from the currently selected
> > > format (i.e. what you get back from VIDIOC_G_FMT).
> > > 
> > > There can be subtle behaviors such as allocating from different memory
> > > back based on the fourcc and the size of the image.
> > > 
> > > One reason why I liked passing sizes directly is that it allows the
> > > caller to ask for more memory than is strictly necessary.
> > > 
> > > However, while brainstorming last week the suggestion was made that
> > > there is no reason why the user can't set the sizeimage field in
> > > v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec
> > > explicitly mentions that the sizeimage field is set by the driver, but
> > > for the new CREATEBUFS ioctl no such limitation has to be placed. The
> > > only thing necessary is to ensure that sizeimage is not too small (and
> > > you probably want some sanity check against crazy values as well).
> > 
> > We need to decide on a policy here. What should be the maximum allowable
> > size for MMAP buffers ? How do we restrict the requested image size so
> > that application won't be allowed to starve the system by requesting
> > memory for 1GP images ?
> 
> Either just a arbitrary cap like 1 GB (mainly to prevent any weird
> calculation problems around the 2 GB (signedness) and 4 GB (wrap-around)
> boundaries), or something like 3 or 4 times the minimum buffer size.
> 
> I'm in favor of enforcing a 1 GB cap in vb2 and letting drivers enforce a
> policy of their own if that makes sense for them.

Wouldn't that be a security issue ? Any application with permissions to access 
the video device could DoS the system.

> I don't really see a problem with requesting large amounts of memory. What
> constitutes 'large' is not something the kernel knows, that's dependent on
> the use case.
Sakari Ailus Aug. 8, 2011, 10:46 p.m. UTC | #7
Laurent Pinchart wrote:
> Hi Hans,
>
> On Monday 08 August 2011 14:40:27 Hans Verkuil wrote:
>> On Monday, August 08, 2011 13:40:23 Laurent Pinchart wrote:
>>> On Monday 08 August 2011 11:16:41 Hans Verkuil wrote:
>>>> On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
>>>>> A possibility to preallocate and initialise buffers of different
>>>>> sizes in V4L2 is required for an efficient implementation of
>>>>> asnapshot mode. This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS
>>>>> and
>>>>> VIDIOC_PREPARE_BUF and defines respective data structures.
>>>>>
>>>>> Signed-off-by: Guennadi Liakhovetski<g.liakhovetski@gmx.de>
>>>>> ---
>>>>>
>>>>> v4:
>>>>>
>>>>> 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in
>>>>>     its argument, instead of a frame format specification, including
>>>>>     documentation update
>>>>>
>>>>> 2. documentation improvements, as suggested by Hans
>>>>> 3. increased reserved fields to 18, as suggested by Sakari
>>>>>
>>>>>   Documentation/DocBook/media/v4l/io.xml             |   17 ++
>>>>>   Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
>>>>>   .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
>>>>
>>>> ++++++++++++++++++++
>>>>
>>>>>   .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96
>>>>>   ++++++++++++ drivers/media/video/v4l2-compat-ioctl32.c          |
>>>>>    6 + drivers/media/video/v4l2-ioctl.c                   |   26 +++
>>>>>   include/linux/videodev2.h                          |   18 +++
>>>>>   include/media/v4l2-ioctl.h                         |    2 + 8 files
>>>>>   changed, 328 insertions(+), 0 deletions(-)
>>>>>   create mode 100644
>>>>>   Documentation/DocBook/media/v4l/vidioc-create-bufs.xml create mode
>>>>>   100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
>>>>
>>>> <snip>
>>>>
>>>>> diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
>>>>> index fca24cc..3cd0cb3 100644
>>>>> --- a/include/linux/videodev2.h
>>>>> +++ b/include/linux/videodev2.h
>>>>> @@ -653,6 +653,9 @@ struct v4l2_buffer {
>>>>>
>>>>>   #define V4L2_BUF_FLAG_ERROR	0x0040
>>>>>   #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
>>>>>   #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
>>>>>
>>>>> +/* Cache handling flags */
>>>>> +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
>>>>> +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
>>>>>
>>>>>   /*
>>>>>
>>>>>    *	O V E R L A Y   P R E V I E W
>>>>>
>>>>> @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
>>>>>
>>>>>   	__u32 revision;    /* chip revision, chip specific */
>>>>>
>>>>>   } __attribute__ ((packed));
>>>>>
>>>>> +/* VIDIOC_CREATE_BUFS */
>>>>> +struct v4l2_create_buffers {
>>>>> +	__u32	index;	/* output: buffers index...index + count - 1 have been
>>>>> created */
>>>>>
>>>>> +	__u32	count;
>>>>> +	__u32	type;
>>>>> +	__u32	memory;
>>>>> +	__u32	fourcc;
>>>>> +	__u32	num_planes;
>>>>> +	__u32	sizes[VIDEO_MAX_PLANES];
>>>>> +	__u32	reserved[18];
>>>>> +};
>>>>
>>>> I know you are going to hate me for this, but I've changed my mind: I
>>>> think this should use a struct v4l2_format after all.
>>>>
>>>> This change of heart came out of discussions during the V4L2 brainstorm
>>>> meeting last week. The only way to be sure the buffers are allocated
>>>> optimally is if the driver has all the information. The easiest way to
>>>> do that is by passing struct v4l2_format. This is also consistent with
>>>> REQBUFS since that uses the information from the currently selected
>>>> format (i.e. what you get back from VIDIOC_G_FMT).
>>>>
>>>> There can be subtle behaviors such as allocating from different memory
>>>> back based on the fourcc and the size of the image.
>>>>
>>>> One reason why I liked passing sizes directly is that it allows the
>>>> caller to ask for more memory than is strictly necessary.
>>>>
>>>> However, while brainstorming last week the suggestion was made that
>>>> there is no reason why the user can't set the sizeimage field in
>>>> v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec
>>>> explicitly mentions that the sizeimage field is set by the driver, but
>>>> for the new CREATEBUFS ioctl no such limitation has to be placed. The
>>>> only thing necessary is to ensure that sizeimage is not too small (and
>>>> you probably want some sanity check against crazy values as well).
>>>
>>> We need to decide on a policy here. What should be the maximum allowable
>>> size for MMAP buffers ? How do we restrict the requested image size so
>>> that application won't be allowed to starve the system by requesting
>>> memory for 1GP images ?
>>
>> Either just a arbitrary cap like 1 GB (mainly to prevent any weird
>> calculation problems around the 2 GB (signedness) and 4 GB (wrap-around)
>> boundaries), or something like 3 or 4 times the minimum buffer size.
>>
>> I'm in favor of enforcing a 1 GB cap in vb2 and letting drivers enforce a
>> policy of their own if that makes sense for them.
>
> Wouldn't that be a security issue ? Any application with permissions to access
> the video device could DoS the system.

I wonder if it would make sense to add a new resource limit for this. 
That should make it easy to have a common default while keeping it 
easily changeable.

The limit could apply to multimedia related buffers that typically are 
pinned to memory.

Or perhaps we just use RLIMIT_MEMLOCK; that's what it really is after 
all. The manual page (man getrlimit) isn't very clear whether it's 
supposed to apply to process or user id, though. The defaults would need 
to change; in my system with 3 GiB of memory the default seems to be 64 
kiB...

Cheers,
Hans Verkuil Aug. 9, 2011, 7:26 a.m. UTC | #8
On Tuesday, August 09, 2011 00:06:10 Laurent Pinchart wrote:
> Hi Hans,
> 
> On Monday 08 August 2011 14:40:27 Hans Verkuil wrote:
> > On Monday, August 08, 2011 13:40:23 Laurent Pinchart wrote:
> > > On Monday 08 August 2011 11:16:41 Hans Verkuil wrote:
> > > > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > > > A possibility to preallocate and initialise buffers of different
> > > > > sizes in V4L2 is required for an efficient implementation of
> > > > > asnapshot mode. This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS
> > > > > and
> > > > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > > > 
> > > > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > > > ---
> > > > > 
> > > > > v4:
> > > > > 
> > > > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in
> > > > >    its argument, instead of a frame format specification, including
> > > > >    documentation update
> > > > > 
> > > > > 2. documentation improvements, as suggested by Hans
> > > > > 3. increased reserved fields to 18, as suggested by Sakari
> > > > > 
> > > > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > > > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > > > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
> > > > 
> > > > ++++++++++++++++++++
> > > > 
> > > > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96
> > > > >  ++++++++++++ drivers/media/video/v4l2-compat-ioctl32.c          |  
> > > > >   6 + drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > > > >  include/linux/videodev2.h                          |   18 +++
> > > > >  include/media/v4l2-ioctl.h                         |    2 + 8 files
> > > > >  changed, 328 insertions(+), 0 deletions(-)
> > > > >  create mode 100644
> > > > >  Documentation/DocBook/media/v4l/vidioc-create-bufs.xml create mode
> > > > >  100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > > > 
> > > > <snip>
> > > > 
> > > > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > > > index fca24cc..3cd0cb3 100644
> > > > > --- a/include/linux/videodev2.h
> > > > > +++ b/include/linux/videodev2.h
> > > > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > > > > 
> > > > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > > > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> > > > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > > > 
> > > > > +/* Cache handling flags */
> > > > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > > > > 
> > > > >  /*
> > > > >  
> > > > >   *	O V E R L A Y   P R E V I E W
> > > > > 
> > > > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > > > > 
> > > > >  	__u32 revision;    /* chip revision, chip specific */
> > > > >  
> > > > >  } __attribute__ ((packed));
> > > > > 
> > > > > +/* VIDIOC_CREATE_BUFS */
> > > > > +struct v4l2_create_buffers {
> > > > > +	__u32	index;	/* output: buffers index...index + count - 1 have been
> > > > > created */
> > > > >
> > > > > +	__u32	count;
> > > > > +	__u32	type;
> > > > > +	__u32	memory;
> > > > > +	__u32	fourcc;
> > > > > +	__u32	num_planes;
> > > > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > > > +	__u32	reserved[18];
> > > > > +};
> > > > 
> > > > I know you are going to hate me for this, but I've changed my mind: I
> > > > think this should use a struct v4l2_format after all.
> > > > 
> > > > This change of heart came out of discussions during the V4L2 brainstorm
> > > > meeting last week. The only way to be sure the buffers are allocated
> > > > optimally is if the driver has all the information. The easiest way to
> > > > do that is by passing struct v4l2_format. This is also consistent with
> > > > REQBUFS since that uses the information from the currently selected
> > > > format (i.e. what you get back from VIDIOC_G_FMT).
> > > > 
> > > > There can be subtle behaviors such as allocating from different memory
> > > > back based on the fourcc and the size of the image.
> > > > 
> > > > One reason why I liked passing sizes directly is that it allows the
> > > > caller to ask for more memory than is strictly necessary.
> > > > 
> > > > However, while brainstorming last week the suggestion was made that
> > > > there is no reason why the user can't set the sizeimage field in
> > > > v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec
> > > > explicitly mentions that the sizeimage field is set by the driver, but
> > > > for the new CREATEBUFS ioctl no such limitation has to be placed. The
> > > > only thing necessary is to ensure that sizeimage is not too small (and
> > > > you probably want some sanity check against crazy values as well).
> > > 
> > > We need to decide on a policy here. What should be the maximum allowable
> > > size for MMAP buffers ? How do we restrict the requested image size so
> > > that application won't be allowed to starve the system by requesting
> > > memory for 1GP images ?
> > 
> > Either just a arbitrary cap like 1 GB (mainly to prevent any weird
> > calculation problems around the 2 GB (signedness) and 4 GB (wrap-around)
> > boundaries), or something like 3 or 4 times the minimum buffer size.
> > 
> > I'm in favor of enforcing a 1 GB cap in vb2 and letting drivers enforce a
> > policy of their own if that makes sense for them.
> 
> Wouldn't that be a security issue ? Any application with permissions to access 
> the video device could DoS the system.

How is this any different from an application that tries to use more memory
then there is available? It's an out-of-memory situation, that can happen at
any time. Anyone can make an application that runs out of memory.

Out-of-memory is not a security risk AFAIK.

Note BTW that in practice kmalloc already has a cap (something like 16 or 32
MB, I believe it depends on the kernel .config) and so has CMA (the size of
the CMA memory region(s)). So I do not think we need to do anything special
here.

Regards,

	Hans

> > I don't really see a problem with requesting large amounts of memory. What
> > constitutes 'large' is not something the kernel knows, that's dependent on
> > the use case.
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sakari Ailus Aug. 9, 2011, 11:37 p.m. UTC | #9
On Tue, Aug 09, 2011 at 09:26:30AM +0200, Hans Verkuil wrote:
...
> > Wouldn't that be a security issue ? Any application with permissions to access 
> > the video device could DoS the system.
> 
> How is this any different from an application that tries to use more memory
> then there is available? It's an out-of-memory situation, that can happen at
> any time. Anyone can make an application that runs out of memory.
> 
> Out-of-memory is not a security risk AFAIK.

If you coun availability to security, then it is.

This might not be an issue in embedded systems which have a single user, but
think of the availability of the interface in e.g. a server.

Also, this memory is locked to system physical memory, making it impossible
to page it out to a block device.

> Note BTW that in practice kmalloc already has a cap (something like 16 or 32
> MB, I believe it depends on the kernel .config) and so has CMA (the size of

This is per a single allocation. A user could create any number of them.
Hans Verkuil Aug. 10, 2011, 6:25 a.m. UTC | #10
On Wednesday, August 10, 2011 01:37:27 Sakari Ailus wrote:
> On Tue, Aug 09, 2011 at 09:26:30AM +0200, Hans Verkuil wrote:
> ...
> > > Wouldn't that be a security issue ? Any application with permissions to access 
> > > the video device could DoS the system.
> > 
> > How is this any different from an application that tries to use more memory
> > then there is available? It's an out-of-memory situation, that can happen at
> > any time. Anyone can make an application that runs out of memory.
> > 
> > Out-of-memory is not a security risk AFAIK.
> 
> If you coun availability to security, then it is.
> 
> This might not be an issue in embedded systems which have a single user, but
> think of the availability of the interface in e.g. a server.
> 
> Also, this memory is locked to system physical memory, making it impossible
> to page it out to a block device.

So? Anyone can make a program that allocates and uses a lot of memory causing
an out of memory error. I still don't see how that differs from trying to allocate
these buffers.

If the system has swap space (which I haven't used in years) then it may take
longer before you run out of memory, but the effect is the same.

Out of memory is a normal condition, not a security risk.

The problem I have is that you can't really determine a valid policy here
since that will depend entirely on your use-case and (embedded) device.

Regards,

	Hans

> > Note BTW that in practice kmalloc already has a cap (something like 16 or 32
> > MB, I believe it depends on the kernel .config) and so has CMA (the size of
> 
> This is per a single allocation. A user could create any number of them.

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sakari Ailus Aug. 11, 2011, 11:09 a.m. UTC | #11
On Wed, Aug 10, 2011 at 08:25:24AM +0200, Hans Verkuil wrote:
> On Wednesday, August 10, 2011 01:37:27 Sakari Ailus wrote:
> > On Tue, Aug 09, 2011 at 09:26:30AM +0200, Hans Verkuil wrote:
> > ...
> > > > Wouldn't that be a security issue ? Any application with permissions to access 
> > > > the video device could DoS the system.
> > > 
> > > How is this any different from an application that tries to use more memory
> > > then there is available? It's an out-of-memory situation, that can happen at
> > > any time. Anyone can make an application that runs out of memory.
> > > 
> > > Out-of-memory is not a security risk AFAIK.
> > 
> > If you coun availability to security, then it is.
> > 
> > This might not be an issue in embedded systems which have a single user, but
> > think of the availability of the interface in e.g. a server.
> > 
> > Also, this memory is locked to system physical memory, making it impossible
> > to page it out to a block device.
> 
> So? Anyone can make a program that allocates and uses a lot of memory causing
> an out of memory error. I still don't see how that differs from trying to allocate
> these buffers.

The difference is between physical and virtual memory. Reserving buffers
pinned in physical memory will starve all the other users very efficiently.

> Out of memory is a normal condition, not a security risk.

Administrators of largish servers with thousands of users might disagree. I
have to admit I don't know their usage patterns very well so I have no
demands on the issue. ulimit is being used in those systems as is quota,
that I know.

On the other hand, those systems typically do not contain V4L2 devices
either.

> The problem I have is that you can't really determine a valid policy here
> since that will depend entirely on your use-case and (embedded) device.

This is quite similar case as with the CMA in my opinion. The proposal (by
Arnd, if my memory serves me correctly) was to limit the CMA allocations
under certain percentage of the system memory address space. The limit could
be overriddend e.g. in board code.
Guennadi Liakhovetski Aug. 15, 2011, 11:28 a.m. UTC | #12
Hi Hans

On Mon, 8 Aug 2011, Hans Verkuil wrote:

> Hi Guennadi!
> 
> On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > A possibility to preallocate and initialise buffers of different sizes
> > in V4L2 is required for an efficient implementation of asnapshot mode.
> > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > VIDIOC_PREPARE_BUF and defines respective data structures.
> > 
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> > 
> > v4:
> > 
> > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
> >    argument, instead of a frame format specification, including 
> >    documentation update
> > 2. documentation improvements, as suggested by Hans
> > 3. increased reserved fields to 18, as suggested by Sakari
> > 
> >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 
> ++++++++++++++++++++
> >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
> >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> >  include/linux/videodev2.h                          |   18 +++
> >  include/media/v4l2-ioctl.h                         |    2 +
> >  8 files changed, 328 insertions(+), 0 deletions(-)
> >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > 
> 
> <snip>
> 
> > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > index fca24cc..3cd0cb3 100644
> > --- a/include/linux/videodev2.h
> > +++ b/include/linux/videodev2.h
> > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> >  #define V4L2_BUF_FLAG_ERROR	0x0040
> >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > +/* Cache handling flags */
> > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> >  
> >  /*
> >   *	O V E R L A Y   P R E V I E W
> > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> >  	__u32 revision;    /* chip revision, chip specific */
> >  } __attribute__ ((packed));
> >  
> > +/* VIDIOC_CREATE_BUFS */
> > +struct v4l2_create_buffers {
> > +	__u32	index;	/* output: buffers index...index + count - 1 have been 
> created */
> > +	__u32	count;
> > +	__u32	type;
> > +	__u32	memory;
> > +	__u32	fourcc;
> > +	__u32	num_planes;
> > +	__u32	sizes[VIDEO_MAX_PLANES];
> > +	__u32	reserved[18];
> > +};
> 
> I know you are going to hate me for this,

hm, I'll consider this possibility;-)

> but I've changed my mind: I think
> this should use a struct v4l2_format after all.
> 
> This change of heart came out of discussions during the V4L2 brainstorm 
> meeting last week. The only way to be sure the buffers are allocated optimally 
> is if the driver has all the information. The easiest way to do that is by 
> passing struct v4l2_format. This is also consistent with REQBUFS since that 
> uses the information from the currently selected format (i.e. what you get 
> back from VIDIOC_G_FMT).
> 
> There can be subtle behaviors such as allocating from different memory back 
> based on the fourcc and the size of the image.
> 
> One reason why I liked passing sizes directly is that it allows the caller to 
> ask for more memory than is strictly necessary.
> 
> However, while brainstorming last week the suggestion was made that there is 
> no reason why the user can't set the sizeimage field in 
> v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec explicitly 
> mentions that the sizeimage field is set by the driver, but for the new 
> CREATEBUFS ioctl no such limitation has to be placed. The only thing necessary 
> is to ensure that sizeimage is not too small (and you probably want some 
> sanity check against crazy values as well).

Centrally in videobuf2 or in each driver?

> This way the decision on how to allocate memory is the same between REQBUFS 
> and CREATEBUFS (i.e. both use v4l2_format information), but there is no need 
> for a union as we had in the initial proposal since apps can set the sizeimage 
> to something larger than strictly necessary (or just leave it to 0 to get the 
> smallest size).

There was no union in previous versions of the patch. You mean, we don't 
need the .size member?

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil (hansverk) Aug. 15, 2011, 11:36 a.m. UTC | #13
On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> Hi Hans
> 
> On Mon, 8 Aug 2011, Hans Verkuil wrote:
> 
> > Hi Guennadi!
> > 
> > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > A possibility to preallocate and initialise buffers of different sizes
> > > in V4L2 is required for an efficient implementation of asnapshot mode.
> > > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > 
> > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > ---
> > > 
> > > v4:
> > > 
> > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
> > >    argument, instead of a frame format specification, including 
> > >    documentation update
> > > 2. documentation improvements, as suggested by Hans
> > > 3. increased reserved fields to 18, as suggested by Sakari
> > > 
> > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 
> > ++++++++++++++++++++
> > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
> > >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> > >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > >  include/linux/videodev2.h                          |   18 +++
> > >  include/media/v4l2-ioctl.h                         |    2 +
> > >  8 files changed, 328 insertions(+), 0 deletions(-)
> > >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> > >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > > 
> > 
> > <snip>
> > 
> > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > index fca24cc..3cd0cb3 100644
> > > --- a/include/linux/videodev2.h
> > > +++ b/include/linux/videodev2.h
> > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > +/* Cache handling flags */
> > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > >  
> > >  /*
> > >   *	O V E R L A Y   P R E V I E W
> > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > >  	__u32 revision;    /* chip revision, chip specific */
> > >  } __attribute__ ((packed));
> > >  
> > > +/* VIDIOC_CREATE_BUFS */
> > > +struct v4l2_create_buffers {
> > > +	__u32	index;	/* output: buffers index...index + count - 1 have been 
> > created */
> > > +	__u32	count;
> > > +	__u32	type;
> > > +	__u32	memory;
> > > +	__u32	fourcc;
> > > +	__u32	num_planes;
> > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > +	__u32	reserved[18];
> > > +};
> > 
> > I know you are going to hate me for this,
> 
> hm, I'll consider this possibility;-)
> 
> > but I've changed my mind: I think
> > this should use a struct v4l2_format after all.
> > 
> > This change of heart came out of discussions during the V4L2 brainstorm 
> > meeting last week. The only way to be sure the buffers are allocated optimally 
> > is if the driver has all the information. The easiest way to do that is by 
> > passing struct v4l2_format. This is also consistent with REQBUFS since that 
> > uses the information from the currently selected format (i.e. what you get 
> > back from VIDIOC_G_FMT).
> > 
> > There can be subtle behaviors such as allocating from different memory back 
> > based on the fourcc and the size of the image.
> > 
> > One reason why I liked passing sizes directly is that it allows the caller to 
> > ask for more memory than is strictly necessary.
> > 
> > However, while brainstorming last week the suggestion was made that there is 
> > no reason why the user can't set the sizeimage field in 
> > v4l2_pix_format(_mplane) to something higher. The S/TRY_FMT spec explicitly 
> > mentions that the sizeimage field is set by the driver, but for the new 
> > CREATEBUFS ioctl no such limitation has to be placed. The only thing necessary 
> > is to ensure that sizeimage is not too small (and you probably want some 
> > sanity check against crazy values as well).
> 
> Centrally in videobuf2 or in each driver?

The 'too small' check can only be done in the driver since the driver has to
calculate the size based on the format. The 'is crazy value' check can be done
centrally. But note the discussion on what constitutes 'crazy'.

> > This way the decision on how to allocate memory is the same between REQBUFS 
> > and CREATEBUFS (i.e. both use v4l2_format information), but there is no need 
> > for a union as we had in the initial proposal since apps can set the sizeimage 
> > to something larger than strictly necessary (or just leave it to 0 to get the 
> > smallest size).
> 
> There was no union in previous versions of the patch. You mean, we don't 
> need the .size member?

Sorry, I thought we had a union containing the size and the format. Anyway, we
don't need the .size member if we allow the user to set the sizeimage fields in
the format when calling CREATEBUFS.

Regards,

       Hans

> 
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Aug. 15, 2011, 1:45 p.m. UTC | #14
On Mon, 15 Aug 2011, Hans Verkuil wrote:

> On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > Hi Hans
> > 
> > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> > 
> > > Hi Guennadi!
> > > 
> > > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > > A possibility to preallocate and initialise buffers of different sizes
> > > > in V4L2 is required for an efficient implementation of asnapshot mode.
> > > > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > > 
> > > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > > ---
> > > > 
> > > > v4:
> > > > 
> > > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in its 
> > > >    argument, instead of a frame format specification, including 
> > > >    documentation update
> > > > 2. documentation improvements, as suggested by Hans
> > > > 3. increased reserved fields to 18, as suggested by Sakari
> > > > 
> > > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161 
> > > ++++++++++++++++++++
> > > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96 ++++++++++++
> > > >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> > > >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > > >  include/linux/videodev2.h                          |   18 +++
> > > >  include/media/v4l2-ioctl.h                         |    2 +
> > > >  8 files changed, 328 insertions(+), 0 deletions(-)
> > > >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> > > >  create mode 100644 Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > > > 
> > > 
> > > <snip>
> > > 
> > > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > > index fca24cc..3cd0cb3 100644
> > > > --- a/include/linux/videodev2.h
> > > > +++ b/include/linux/videodev2.h
> > > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
> > > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > > +/* Cache handling flags */
> > > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > > >  
> > > >  /*
> > > >   *	O V E R L A Y   P R E V I E W
> > > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > > >  	__u32 revision;    /* chip revision, chip specific */
> > > >  } __attribute__ ((packed));
> > > >  
> > > > +/* VIDIOC_CREATE_BUFS */
> > > > +struct v4l2_create_buffers {
> > > > +	__u32	index;	/* output: buffers index...index + count - 1 have been 
> > > created */
> > > > +	__u32	count;
> > > > +	__u32	type;
> > > > +	__u32	memory;
> > > > +	__u32	fourcc;
> > > > +	__u32	num_planes;
> > > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > > +	__u32	reserved[18];
> > > > +};
> > > 
> > > I know you are going to hate me for this,
> > 
> > hm, I'll consider this possibility;-)
> > 
> > > but I've changed my mind: I think
> > > this should use a struct v4l2_format after all.

While switching back, I have to change the struct vb2_ops::queue_setup() 
operation to take a struct v4l2_create_buffers pointer. An earlier version 
of this patch just added one more parameter to .queue_setup(), which is 
easier - changes to videobuf2-core.c are smaller, but it is then 
redundant. We could use the create pointer for both input and output. The 
video plane configuration in frame format is the same as what is 
calculated in .queue_setup(), IIUC. So, we could just let the driver fill 
that one in. This would require then the videobuf2-core.c to parse struct 
v4l2_format to decide which union member we need, depending on the buffer 
type. Do we want this or shall drivers duplicate plane sizes in separate 
.queue_setup() parameters?

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Aug. 16, 2011, 1:13 p.m. UTC | #15
On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:

> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> 
> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > > Hi Hans
> > > 
> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:

[snip]

> > > > but I've changed my mind: I think
> > > > this should use a struct v4l2_format after all.
> 
> While switching back, I have to change the struct vb2_ops::queue_setup() 
> operation to take a struct v4l2_create_buffers pointer. An earlier version 
> of this patch just added one more parameter to .queue_setup(), which is 
> easier - changes to videobuf2-core.c are smaller, but it is then 
> redundant. We could use the create pointer for both input and output. The 
> video plane configuration in frame format is the same as what is 
> calculated in .queue_setup(), IIUC. So, we could just let the driver fill 
> that one in. This would require then the videobuf2-core.c to parse struct 
> v4l2_format to decide which union member we need, depending on the buffer 
> type. Do we want this or shall drivers duplicate plane sizes in separate 
> .queue_setup() parameters?

Let me explain my question a bit. The current .queue_setup() method is

	int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
			   unsigned int *num_planes, unsigned int sizes[],
			   void *alloc_ctxs[]);

To support multiple-size buffers we also have to pass a pointer to struct 
v4l2_create_buffers to this function now. We can either do it like this:

	int (*queue_setup)(struct vb2_queue *q,
			   struct v4l2_create_buffers *create,
			   unsigned int *num_buffers,
			   unsigned int *num_planes, unsigned int sizes[],
			   void *alloc_ctxs[]);

and let all drivers fill in respective fields in *create, e.g., either do

	create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
	create->format.fmt.pix_mp.num_planes = ...;

and also duplicate it in method parameters

	*num_planes = create->format.fmt.pix_mp.num_planes;
	sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;

or with

	create->format.fmt.pix.sizeimage = ...;

for single-plane. Alternatively we make the prototype

	int (*queue_setup)(struct vb2_queue *q,
			   struct v4l2_create_buffers *create,
			   unsigned int *num_buffers,
			   void *alloc_ctxs[]);

then drivers only fill in *create, and the videobuf2-core will have to 
check create->format.type to decide, which of create->format.fmt.* is 
relevant and extract plane sizes from there.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pawel Osciak Aug. 16, 2011, 4:14 p.m. UTC | #16
Hi Guennadi,

On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
>
>> On Mon, 15 Aug 2011, Hans Verkuil wrote:
>>
>> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
>> > > Hi Hans
>> > >
>> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
>
> [snip]
>
>> > > > but I've changed my mind: I think
>> > > > this should use a struct v4l2_format after all.
>>
>> While switching back, I have to change the struct vb2_ops::queue_setup()
>> operation to take a struct v4l2_create_buffers pointer. An earlier version
>> of this patch just added one more parameter to .queue_setup(), which is
>> easier - changes to videobuf2-core.c are smaller, but it is then
>> redundant. We could use the create pointer for both input and output. The
>> video plane configuration in frame format is the same as what is
>> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
>> that one in. This would require then the videobuf2-core.c to parse struct
>> v4l2_format to decide which union member we need, depending on the buffer
>> type. Do we want this or shall drivers duplicate plane sizes in separate
>> .queue_setup() parameters?
>
> Let me explain my question a bit. The current .queue_setup() method is
>
>        int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
>                           unsigned int *num_planes, unsigned int sizes[],
>                           void *alloc_ctxs[]);
>
> To support multiple-size buffers we also have to pass a pointer to struct
> v4l2_create_buffers to this function now. We can either do it like this:
>
>        int (*queue_setup)(struct vb2_queue *q,
>                           struct v4l2_create_buffers *create,
>                           unsigned int *num_buffers,
>                           unsigned int *num_planes, unsigned int sizes[],
>                           void *alloc_ctxs[]);
>
> and let all drivers fill in respective fields in *create, e.g., either do
>
>        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
>        create->format.fmt.pix_mp.num_planes = ...;
>
> and also duplicate it in method parameters
>
>        *num_planes = create->format.fmt.pix_mp.num_planes;
>        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
>
> or with
>
>        create->format.fmt.pix.sizeimage = ...;
>
> for single-plane. Alternatively we make the prototype
>
>        int (*queue_setup)(struct vb2_queue *q,
>                           struct v4l2_create_buffers *create,
>                           unsigned int *num_buffers,
>                           void *alloc_ctxs[]);
>
> then drivers only fill in *create, and the videobuf2-core will have to
> check create->format.type to decide, which of create->format.fmt.* is
> relevant and extract plane sizes from there.


Could we try exploring an alternative idea?
The queue_setup callback was added to decouple formats from vb2 (and
add some asynchronousness). But now we are doing the opposite, adding
format awareness to vb2. Does vb2 really need to know about formats? I
really believe it doesn't. It only needs sizes and counts. Also, we
are actually complicating things I think. The proposal, IIUC, would
look like this:

driver_queue_setup(..., create, num_buffers, [num_planes], ...)
{
    if (create != NULL && create->format != NULL) {
        /* use create->fmt to fill sizes */
    } else if (create != NULL) { /* this assumes we have both format or sizes */
        /* use create->sizes to fill sizes */
    } else {
        /* use currently selected format to fill sizes */
    }
}

driver_s_fmt(format)
{
    /* ... */
    driver_fill_format(&create->fmt);
    /* ... */
}

driver_create_bufs(create)
{
    vb2_create_bufs(create);
}

vb2_create_bufs(create)
{
    driver_queue_setup(..., create, ...);
    vb2_fill_format(&create->fmt); /* note different from
driver_fill_format(), but both needed */
}

vb2_reqbufs(reqbufs)
{
   driver_queue_setup(..., NULL, ...);
}

The queue_setup not only becomes unnecessarily complicated, but I'm
starting to question the convenience of it. And we are teaching vb2
how to interpret format structs, even though vb2 only needs sizes, and
even though the driver has to do it anyway and knows better how.

As for the idea to fill fmt in vb2, even if vb2 was to do it in
create_bufs, some code to parse and fill the format fields would need
to be in the driver anyway, because it still has to support s_fmt and
friends. So adding that code to vb2 would duplicate it, and if the
driver wanted to be non-standard in a way it filled the format fields,
we'd not be allowing that.

My suggestion would be to remove queue_setup callback and instead
modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
buffers. I think it should simplify things both for drivers and vb2,
would keep vb2 format-unaware and save us some round trips between vb2
and driver:

driver_create_bufs(...) /* optional */
{
    /* use create->fmt (or sizes) */
    ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs);
    fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
have a common function for that */
    return ret;
}

driver_reqbufs(...)
{
    /* use current format */
    return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs);
}

And the call to both could easily converge into one in vb2, as the
only difference is that vb2_reqbufs would need to free first, if any
allocated buffers were present:

vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
{
    if (buffers_allocated(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs)) {
        free_buffers(...);
    }

    return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs);
}

If the driver didn't want create_bufs, it'd just not implement it.
What do you think?
Guennadi Liakhovetski Aug. 17, 2011, 8:41 a.m. UTC | #17
On Sat, 6 Aug 2011, Sakari Ailus wrote:

> Guennadi Liakhovetski wrote:
> > A possibility to preallocate and initialise buffers of different sizes
> > in V4L2 is required for an efficient implementation of asnapshot mode.
> > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > VIDIOC_PREPARE_BUF and defines respective data structures.
> > 
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> 
> Hi Guennadi,

[snip]

> > +    <para>When the I/O method is not supported the ioctl
> > +returns an &EINVAL;.</para>
> > +
> > +    <table pgwide="1" frame="none" id="v4l2-create-buffers">
> > +      <title>struct <structname>v4l2_create_buffers</structname></title>
> > +      <tgroup cols="3">
> > +	&cs-str;
> > +	<tbody valign="top">
> > +	  <row>
> > +	    <entry>__u32</entry>
> > +	    <entry><structfield>index</structfield></entry>
> > +	    <entry>The starting buffer index, returned by the driver.</entry>
> > +	  </row>
> > +	  <row>
> > +	    <entry>__u32</entry>
> > +	    <entry><structfield>count</structfield></entry>
> > +	    <entry>The number of buffers requested or granted.</entry>
> > +	  </row>
> > +	  <row>
> > +	    <entry>__u32</entry>
> > +	    <entry><structfield>type</structfield></entry>
> > +	    <entry>V4L2 buffer type: one of <constant>V4L2_BUF_TYPE_*</constant>
> > +values.</entry>
> 
> &v4l2-buf-type;
> 
> here?

No idea and I don't care all that much, tbh. I certainly copy-pasted those 
constructs from other documents, and yes, they are inconsistent across 
v4l: some use my version, some yours, others <xref linkend=...>. I'm happy 
with either or none of those. Just tell me _something_, that's 
approapriate.

> 
> > +	  </row>
> > +	  <row>
> > +	    <entry>__u32</entry>
> > +	    <entry><structfield>memory</structfield></entry>
> > +	    <entry>Applications set this field to
> > +<constant>V4L2_MEMORY_MMAP</constant> or
> > +<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
> 
> &v4l2-memory;

[snip]

> > +    <para>Applications can optionally call the
> > +<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
> > +to the driver before actually enqueuing it, using the
> > +<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
> 
> s/<constant>VIDIOC_QBUF</constant>/&VIDIOC_QBUF;/

*shrug*

> > > +Such preparations may include cache invalidation or cleaning. Performing them
> > +in advance saves time during the actual I/O. In case such cache operations are
> > +not required, the application can use one of
> > +<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
> > +<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
> > +step.</para>
> > +
> > +    <para>The <structname>v4l2_buffer</structname> structure is
> 
> s/<structname>v4l2_buffer</structname>/&v4l2-buffer;/

"structname" seems to be more precise, but well...

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Aug. 17, 2011, 9:11 a.m. UTC | #18
On Tue, 16 Aug 2011, Pawel Osciak wrote:

> Hi Guennadi,
> 
> On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
> >
> >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> >>
> >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> >> > > Hi Hans
> >> > >
> >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> >
> > [snip]
> >
> >> > > > but I've changed my mind: I think
> >> > > > this should use a struct v4l2_format after all.
> >>
> >> While switching back, I have to change the struct vb2_ops::queue_setup()
> >> operation to take a struct v4l2_create_buffers pointer. An earlier version
> >> of this patch just added one more parameter to .queue_setup(), which is
> >> easier - changes to videobuf2-core.c are smaller, but it is then
> >> redundant. We could use the create pointer for both input and output. The
> >> video plane configuration in frame format is the same as what is
> >> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
> >> that one in. This would require then the videobuf2-core.c to parse struct
> >> v4l2_format to decide which union member we need, depending on the buffer
> >> type. Do we want this or shall drivers duplicate plane sizes in separate
> >> .queue_setup() parameters?
> >
> > Let me explain my question a bit. The current .queue_setup() method is
> >
> >        int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
> >                           unsigned int *num_planes, unsigned int sizes[],
> >                           void *alloc_ctxs[]);
> >
> > To support multiple-size buffers we also have to pass a pointer to struct
> > v4l2_create_buffers to this function now. We can either do it like this:
> >
> >        int (*queue_setup)(struct vb2_queue *q,
> >                           struct v4l2_create_buffers *create,
> >                           unsigned int *num_buffers,
> >                           unsigned int *num_planes, unsigned int sizes[],
> >                           void *alloc_ctxs[]);
> >
> > and let all drivers fill in respective fields in *create, e.g., either do
> >
> >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
> >        create->format.fmt.pix_mp.num_planes = ...;
> >
> > and also duplicate it in method parameters
> >
> >        *num_planes = create->format.fmt.pix_mp.num_planes;
> >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> >
> > or with
> >
> >        create->format.fmt.pix.sizeimage = ...;
> >
> > for single-plane. Alternatively we make the prototype
> >
> >        int (*queue_setup)(struct vb2_queue *q,
> >                           struct v4l2_create_buffers *create,
> >                           unsigned int *num_buffers,
> >                           void *alloc_ctxs[]);
> >
> > then drivers only fill in *create, and the videobuf2-core will have to
> > check create->format.type to decide, which of create->format.fmt.* is
> > relevant and extract plane sizes from there.
> 
> 
> Could we try exploring an alternative idea?
> The queue_setup callback was added to decouple formats from vb2 (and
> add some asynchronousness). But now we are doing the opposite, adding
> format awareness to vb2. Does vb2 really need to know about formats? I
> really believe it doesn't. It only needs sizes and counts.

This kind of objection was expected:-) However, I think, you're a bit 
exaggerating. VB2 does not have to _fill_ the format. All frame-format 
fields like fourcc code, width, height, colorspace are only input from the 
user. If the user didn't fill them in, they should not be used. The only 
thing, that vb2 will have to learn about formats is to find the location 
of (plane-)buffer sizes in struct v4l2_format, for which it will have to 
interpret the .type value. I.e., we just have to add this:

static int vb2_parse_planes(const struct v4l2_create_buffers *create,
			    unsigned int *num_planes, unsigned int *plane_sizes)
{
	int i;

	switch (create->format.type) {
	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
		*num_planes = 1;
		plane_sizes[0] = create->format.fmt.pix.sizeimage;
		return 0;
	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
		*num_planes = create->format.fmt.pix_mp.num_planes;
		for (i = 0; i < *num_planes; i++)
			plane_sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
		return 0;
	default:
		return -EINVAL;
	}
}

Can you live with this or you still think it's too much format-knowledge 
for vb2? Or am I missing something, why we need more knowledge?

> Also, we
> are actually complicating things I think. The proposal, IIUC, would
> look like this:
> 
> driver_queue_setup(..., create, num_buffers, [num_planes], ...)
> {
>     if (create != NULL && create->format != NULL) {
>         /* use create->fmt to fill sizes */
>     } else if (create != NULL) { /* this assumes we have both format or sizes */
>         /* use create->sizes to fill sizes */
>     } else {
>         /* use currently selected format to fill sizes */
>     }
> }
> 
> driver_s_fmt(format)
> {
>     /* ... */
>     driver_fill_format(&create->fmt);
>     /* ... */
> }
> 
> driver_create_bufs(create)
> {
>     vb2_create_bufs(create);
> }
> 
> vb2_create_bufs(create)
> {
>     driver_queue_setup(..., create, ...);
>     vb2_fill_format(&create->fmt); /* note different from
> driver_fill_format(), but both needed */
> }
> 
> vb2_reqbufs(reqbufs)
> {
>    driver_queue_setup(..., NULL, ...);
> }
> 
> The queue_setup not only becomes unnecessarily complicated, but I'm
> starting to question the convenience of it. And we are teaching vb2
> how to interpret format structs, even though vb2 only needs sizes, and
> even though the driver has to do it anyway and knows better how.
> 
> As for the idea to fill fmt in vb2, even if vb2 was to do it in
> create_bufs, some code to parse and fill the format fields would need
> to be in the driver anyway, because it still has to support s_fmt and
> friends. So adding that code to vb2 would duplicate it, and if the
> driver wanted to be non-standard in a way it filled the format fields,
> we'd not be allowing that.
> 
> My suggestion would be to remove queue_setup callback and instead
> modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
> buffers. I think it should simplify things both for drivers and vb2,
> would keep vb2 format-unaware and save us some round trips between vb2
> and driver:

Right, I see what you mean. Well, this seems doable. Do we want this? It 
does seem to simplify things a bit by removing .queue_setup()... Opinions?

> driver_create_bufs(...) /* optional */
> {
>     /* use create->fmt (or sizes) */
>     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
>     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
> have a common function for that */
>     return ret;
> }
> 
> driver_reqbufs(...)
> {
>     /* use current format */
>     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }
> 
> And the call to both could easily converge into one in vb2, as the
> only difference is that vb2_reqbufs would need to free first, if any
> allocated buffers were present:
> 
> vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> {
>     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs)) {
>         free_buffers(...);
>     }
> 
>     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }
> 
> If the driver didn't want create_bufs, it'd just not implement it.
> What do you think?
> 
> -- 
> Best regards,
> Pawel Osciak

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Aug. 17, 2011, 9:14 a.m. UTC | #19
On Wednesday 17 August 2011 11:11:01 Guennadi Liakhovetski wrote:
> On Tue, 16 Aug 2011, Pawel Osciak wrote:
> > On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski wrote:
> > > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
> > >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> > >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> > > [snip]
> > > 
> > >> > > > but I've changed my mind: I think
> > >> > > > this should use a struct v4l2_format after all.
> > >> 
> > >> While switching back, I have to change the struct
> > >> vb2_ops::queue_setup() operation to take a struct v4l2_create_buffers
> > >> pointer. An earlier version of this patch just added one more
> > >> parameter to .queue_setup(), which is easier - changes to
> > >> videobuf2-core.c are smaller, but it is then redundant. We could use
> > >> the create pointer for both input and output. The video plane
> > >> configuration in frame format is the same as what is calculated in
> > >> .queue_setup(), IIUC. So, we could just let the driver fill that one
> > >> in. This would require then the videobuf2-core.c to parse struct
> > >> v4l2_format to decide which union member we need, depending on the
> > >> buffer type. Do we want this or shall drivers duplicate plane sizes
> > >> in separate .queue_setup() parameters?
> > > 
> > > Let me explain my question a bit. The current .queue_setup() method is
> > > 
> > >        int (*queue_setup)(struct vb2_queue *q, unsigned int
> > >        *num_buffers,
> > >        
> > >                           unsigned int *num_planes, unsigned int
> > >                           sizes[], void *alloc_ctxs[]);
> > > 
> > > To support multiple-size buffers we also have to pass a pointer to
> > > struct
> > > 
> > > v4l2_create_buffers to this function now. We can either do it like this:
> > >        int (*queue_setup)(struct vb2_queue *q,
> > >        
> > >                           struct v4l2_create_buffers *create,
> > >                           unsigned int *num_buffers,
> > >                           unsigned int *num_planes, unsigned int
> > >                           sizes[], void *alloc_ctxs[]);
> > > 
> > > and let all drivers fill in respective fields in *create, e.g., either
> > > do
> > > 
> > >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
> > >        create->format.fmt.pix_mp.num_planes = ...;
> > > 
> > > and also duplicate it in method parameters
> > > 
> > >        *num_planes = create->format.fmt.pix_mp.num_planes;
> > >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> > > 
> > > or with
> > > 
> > >        create->format.fmt.pix.sizeimage = ...;
> > > 
> > > for single-plane. Alternatively we make the prototype
> > > 
> > >        int (*queue_setup)(struct vb2_queue *q,
> > >        
> > >                           struct v4l2_create_buffers *create,
> > >                           unsigned int *num_buffers,
> > >                           void *alloc_ctxs[]);
> > > 
> > > then drivers only fill in *create, and the videobuf2-core will have to
> > > check create->format.type to decide, which of create->format.fmt.* is
> > > relevant and extract plane sizes from there.
> > 
> > Could we try exploring an alternative idea?
> > The queue_setup callback was added to decouple formats from vb2 (and
> > add some asynchronousness). But now we are doing the opposite, adding
> > format awareness to vb2. Does vb2 really need to know about formats? I
> > really believe it doesn't. It only needs sizes and counts.
> 
> This kind of objection was expected:-) However, I think, you're a bit
> exaggerating. VB2 does not have to _fill_ the format. All frame-format
> fields like fourcc code, width, height, colorspace are only input from the
> user. If the user didn't fill them in, they should not be used. The only
> thing, that vb2 will have to learn about formats is to find the location
> of (plane-)buffer sizes in struct v4l2_format, for which it will have to
> interpret the .type value. I.e., we just have to add this:
> 
> static int vb2_parse_planes(const struct v4l2_create_buffers *create,
> 			    unsigned int *num_planes, unsigned int *plane_sizes)
> {
> 	int i;
> 
> 	switch (create->format.type) {
> 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
> 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
> 		*num_planes = 1;
> 		plane_sizes[0] = create->format.fmt.pix.sizeimage;
> 		return 0;
> 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
> 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
> 		*num_planes = create->format.fmt.pix_mp.num_planes;
> 		for (i = 0; i < *num_planes; i++)
> 			plane_sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> 		return 0;
> 	default:
> 		return -EINVAL;
> 	}
> }
> 
> Can you live with this or you still think it's too much format-knowledge
> for vb2? Or am I missing something, why we need more knowledge?
> 
> > Also, we
> > are actually complicating things I think. The proposal, IIUC, would
> > look like this:
> > 
> > driver_queue_setup(..., create, num_buffers, [num_planes], ...)
> > {
> > 
> >     if (create != NULL && create->format != NULL) {
> >     
> >         /* use create->fmt to fill sizes */
> >     
> >     } else if (create != NULL) { /* this assumes we have both format or
> >     sizes */
> >     
> >         /* use create->sizes to fill sizes */
> >     
> >     } else {
> >     
> >         /* use currently selected format to fill sizes */
> >     
> >     }
> > 
> > }
> > 
> > driver_s_fmt(format)
> > {
> > 
> >     /* ... */
> >     driver_fill_format(&create->fmt);
> >     /* ... */
> > 
> > }
> > 
> > driver_create_bufs(create)
> > {
> > 
> >     vb2_create_bufs(create);
> > 
> > }
> > 
> > vb2_create_bufs(create)
> > {
> > 
> >     driver_queue_setup(..., create, ...);
> >     vb2_fill_format(&create->fmt); /* note different from
> > 
> > driver_fill_format(), but both needed */
> > }
> > 
> > vb2_reqbufs(reqbufs)
> > {
> > 
> >    driver_queue_setup(..., NULL, ...);
> > 
> > }
> > 
> > The queue_setup not only becomes unnecessarily complicated, but I'm
> > starting to question the convenience of it. And we are teaching vb2
> > how to interpret format structs, even though vb2 only needs sizes, and
> > even though the driver has to do it anyway and knows better how.
> > 
> > As for the idea to fill fmt in vb2, even if vb2 was to do it in
> > create_bufs, some code to parse and fill the format fields would need
> > to be in the driver anyway, because it still has to support s_fmt and
> > friends. So adding that code to vb2 would duplicate it, and if the
> > driver wanted to be non-standard in a way it filled the format fields,
> > we'd not be allowing that.
> > 
> > My suggestion would be to remove queue_setup callback and instead
> > modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
> > buffers. I think it should simplify things both for drivers and vb2,
> > would keep vb2 format-unaware and save us some round trips between vb2
> > and driver:
> Right, I see what you mean. Well, this seems doable. Do we want this? It
> does seem to simplify things a bit by removing .queue_setup()... Opinions?

I might not have thought about all the possible issues this could bring, but I 
like it.

> > driver_create_bufs(...) /* optional */
> > {
> > 
> >     /* use create->fmt (or sizes) */
> >     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > 
> > plane_sizes, alloc_ctxs);
> > 
> >     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
> > 
> > have a common function for that */
> > 
> >     return ret;
> > 
> > }
> > 
> > driver_reqbufs(...)
> > {
> > 
> >     /* use current format */
> >     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
> > 
> > plane_sizes, alloc_ctxs);
> > }
> > 
> > And the call to both could easily converge into one in vb2, as the
> > only difference is that vb2_reqbufs would need to free first, if any
> > allocated buffers were present:
> > 
> > vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> > {
> > 
> >     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
> > 
> > plane_sizes, alloc_ctxs)) {
> > 
> >         free_buffers(...);
> >     
> >     }
> >     
> >     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > 
> > plane_sizes, alloc_ctxs);
> > }
> > 
> > If the driver didn't want create_bufs, it'd just not implement it.
> > What do you think?
Sakari Ailus Aug. 17, 2011, 12:13 p.m. UTC | #20
On Wed, Aug 17, 2011 at 10:41:51AM +0200, Guennadi Liakhovetski wrote:
> On Sat, 6 Aug 2011, Sakari Ailus wrote:
> 
> > Guennadi Liakhovetski wrote:
> > > A possibility to preallocate and initialise buffers of different sizes
> > > in V4L2 is required for an efficient implementation of asnapshot mode.
> > > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > 
> > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > ---
> > 
> > Hi Guennadi,
> 
> [snip]
> 
> > > +    <para>When the I/O method is not supported the ioctl
> > > +returns an &EINVAL;.</para>
> > > +
> > > +    <table pgwide="1" frame="none" id="v4l2-create-buffers">
> > > +      <title>struct <structname>v4l2_create_buffers</structname></title>
> > > +      <tgroup cols="3">
> > > +	&cs-str;
> > > +	<tbody valign="top">
> > > +	  <row>
> > > +	    <entry>__u32</entry>
> > > +	    <entry><structfield>index</structfield></entry>
> > > +	    <entry>The starting buffer index, returned by the driver.</entry>
> > > +	  </row>
> > > +	  <row>
> > > +	    <entry>__u32</entry>
> > > +	    <entry><structfield>count</structfield></entry>
> > > +	    <entry>The number of buffers requested or granted.</entry>
> > > +	  </row>
> > > +	  <row>
> > > +	    <entry>__u32</entry>
> > > +	    <entry><structfield>type</structfield></entry>
> > > +	    <entry>V4L2 buffer type: one of <constant>V4L2_BUF_TYPE_*</constant>
> > > +values.</entry>
> > 
> > &v4l2-buf-type;
> > 
> > here?
> 
> No idea and I don't care all that much, tbh. I certainly copy-pasted those 
> constructs from other documents, and yes, they are inconsistent across 
> v4l: some use my version, some yours, others <xref linkend=...>. I'm happy 
> with either or none of those. Just tell me _something_, that's 
> approapriate.

Links are being used in other parts of V4L2 documentation. I think
PREPARE_BUF documentation should use them, too, rather than duplicating
parts of definitions.

> > 
> > > +	  </row>
> > > +	  <row>
> > > +	    <entry>__u32</entry>
> > > +	    <entry><structfield>memory</structfield></entry>
> > > +	    <entry>Applications set this field to
> > > +<constant>V4L2_MEMORY_MMAP</constant> or
> > > +<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
> > 
> > &v4l2-memory;
> 
> [snip]
> 
> > > +    <para>Applications can optionally call the
> > > +<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
> > > +to the driver before actually enqueuing it, using the
> > > +<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
> > 
> > s/<constant>VIDIOC_QBUF</constant>/&VIDIOC_QBUF;/
> 
> *shrug*
> 
> > > > +Such preparations may include cache invalidation or cleaning. Performing them
> > > +in advance saves time during the actual I/O. In case such cache operations are
> > > +not required, the application can use one of
> > > +<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
> > > +<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
> > > +step.</para>
> > > +
> > > +    <para>The <structname>v4l2_buffer</structname> structure is
> > 
> > s/<structname>v4l2_buffer</structname>/&v4l2-buffer;/
> 
> "structname" seems to be more precise, but well...

It's precise but precision isn't everything: giving the user a link to the
definition of e.g. v4l2_buffer is more useful than forcing him or her to
look for it elsewhere in the documentation. These are small issues but the
usability of the documentation counts a lot.

Regards,
Marek Szyprowski Aug. 17, 2011, 1:22 p.m. UTC | #21
Hello,

On Monday, August 15, 2011 3:46 PM Guennadi Liakhovetski wrote:
> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> > > > On Friday, August 05, 2011 09:47:13 Guennadi Liakhovetski wrote:
> > > > > A possibility to preallocate and initialise buffers of different sizes
> > > > > in V4L2 is required for an efficient implementation of asnapshot mode.
> > > > > This patch adds two new ioctl()s: VIDIOC_CREATE_BUFS and
> > > > > VIDIOC_PREPARE_BUF and defines respective data structures.
> > > > >
> > > > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > > > ---
> > > > >
> > > > > v4:
> > > > >
> > > > > 1. CREATE_BUFS now takes an array of plane sizes and a fourcc code in
its
> > > > >    argument, instead of a frame format specification, including
> > > > >    documentation update
> > > > > 2. documentation improvements, as suggested by Hans
> > > > > 3. increased reserved fields to 18, as suggested by Sakari
> > > > >
> > > > >  Documentation/DocBook/media/v4l/io.xml             |   17 ++
> > > > >  Documentation/DocBook/media/v4l/v4l2.xml           |    2 +
> > > > >  .../DocBook/media/v4l/vidioc-create-bufs.xml       |  161
> > > > ++++++++++++++++++++
> > > > >  .../DocBook/media/v4l/vidioc-prepare-buf.xml       |   96
++++++++++++
> > > > >  drivers/media/video/v4l2-compat-ioctl32.c          |    6 +
> > > > >  drivers/media/video/v4l2-ioctl.c                   |   26 +++
> > > > >  include/linux/videodev2.h                          |   18 +++
> > > > >  include/media/v4l2-ioctl.h                         |    2 +
> > > > >  8 files changed, 328 insertions(+), 0 deletions(-)
> > > > >  create mode 100644
Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
> > > > >  create mode 100644
Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
> > > > >
> > > >
> > > > <snip>
> > > >
> > > > > diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
> > > > > index fca24cc..3cd0cb3 100644
> > > > > --- a/include/linux/videodev2.h
> > > > > +++ b/include/linux/videodev2.h
> > > > > @@ -653,6 +653,9 @@ struct v4l2_buffer {
> > > > >  #define V4L2_BUF_FLAG_ERROR	0x0040
> > > > >  #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is
valid */
> > > > >  #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
> > > > > +/* Cache handling flags */
> > > > > +#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
> > > > > +#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
> > > > >
> > > > >  /*
> > > > >   *	O V E R L A Y   P R E V I E W
> > > > > @@ -2092,6 +2095,18 @@ struct v4l2_dbg_chip_ident {
> > > > >  	__u32 revision;    /* chip revision, chip specific */
> > > > >  } __attribute__ ((packed));
> > > > >
> > > > > +/* VIDIOC_CREATE_BUFS */
> > > > > +struct v4l2_create_buffers {
> > > > > +	__u32	index;	/* output: buffers index...index + count - 1
have been
> > > > created */
> > > > > +	__u32	count;
> > > > > +	__u32	type;
> > > > > +	__u32	memory;
> > > > > +	__u32	fourcc;
> > > > > +	__u32	num_planes;
> > > > > +	__u32	sizes[VIDEO_MAX_PLANES];
> > > > > +	__u32	reserved[18];
> > > > > +};
> > > >
> > > > I know you are going to hate me for this,
> > >
> > > hm, I'll consider this possibility;-)
> > >
> > > > but I've changed my mind: I think
> > > > this should use a struct v4l2_format after all.
> 
> While switching back, I have to change the struct vb2_ops::queue_setup()
> operation to take a struct v4l2_create_buffers pointer. An earlier version
> of this patch just added one more parameter to .queue_setup(), which is
> easier - changes to videobuf2-core.c are smaller, but it is then
> redundant. We could use the create pointer for both input and output. The
> video plane configuration in frame format is the same as what is
> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
> that one in. This would require then the videobuf2-core.c to parse struct
> v4l2_format to decide which union member we need, depending on the buffer
> type. Do we want this or shall drivers duplicate plane sizes in separate
> .queue_setup() parameters?

IMHO if possible we should have only one callback for the driver. Please 
notice that the driver should be also allowed to increase (or decrease) the
number of buffers for particular format/fourcc.

Best regards
Pawel Osciak Aug. 17, 2011, 2:57 p.m. UTC | #22
On Wed, Aug 17, 2011 at 06:22, Marek Szyprowski
<m.szyprowski@samsung.com> wrote:
> Hello,
>
> On Monday, August 15, 2011 3:46 PM Guennadi Liakhovetski wrote:
>> While switching back, I have to change the struct vb2_ops::queue_setup()
>> operation to take a struct v4l2_create_buffers pointer. An earlier version
>> of this patch just added one more parameter to .queue_setup(), which is
>> easier - changes to videobuf2-core.c are smaller, but it is then
>> redundant. We could use the create pointer for both input and output. The
>> video plane configuration in frame format is the same as what is
>> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
>> that one in. This would require then the videobuf2-core.c to parse struct
>> v4l2_format to decide which union member we need, depending on the buffer
>> type. Do we want this or shall drivers duplicate plane sizes in separate
>> .queue_setup() parameters?
>
> IMHO if possible we should have only one callback for the driver. Please
> notice that the driver should be also allowed to increase (or decrease) the
> number of buffers for particular format/fourcc.
>

Or remove queue_setup altogether (please see my example above). What
do you think Marek?
Pawel Osciak Aug. 17, 2011, 3:29 p.m. UTC | #23
Hi

On Wed, Aug 17, 2011 at 02:11, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Tue, 16 Aug 2011, Pawel Osciak wrote:
>
>> Hi Guennadi,
>>
>> On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>> > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
>> >
>> >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
>> >>
>> >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
>> >> > > Hi Hans
>> >> > >
>> >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
>> >
>> > [snip]
>> >
>> >> > > > but I've changed my mind: I think
>> >> > > > this should use a struct v4l2_format after all.
>> >>
>> >> While switching back, I have to change the struct vb2_ops::queue_setup()
>> >> operation to take a struct v4l2_create_buffers pointer. An earlier version
>> >> of this patch just added one more parameter to .queue_setup(), which is
>> >> easier - changes to videobuf2-core.c are smaller, but it is then
>> >> redundant. We could use the create pointer for both input and output. The
>> >> video plane configuration in frame format is the same as what is
>> >> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
>> >> that one in. This would require then the videobuf2-core.c to parse struct
>> >> v4l2_format to decide which union member we need, depending on the buffer
>> >> type. Do we want this or shall drivers duplicate plane sizes in separate
>> >> .queue_setup() parameters?
>> >
>> > Let me explain my question a bit. The current .queue_setup() method is
>> >
>> >        int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
>> >                           unsigned int *num_planes, unsigned int sizes[],
>> >                           void *alloc_ctxs[]);
>> >
>> > To support multiple-size buffers we also have to pass a pointer to struct
>> > v4l2_create_buffers to this function now. We can either do it like this:
>> >
>> >        int (*queue_setup)(struct vb2_queue *q,
>> >                           struct v4l2_create_buffers *create,
>> >                           unsigned int *num_buffers,
>> >                           unsigned int *num_planes, unsigned int sizes[],
>> >                           void *alloc_ctxs[]);
>> >
>> > and let all drivers fill in respective fields in *create, e.g., either do
>> >
>> >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
>> >        create->format.fmt.pix_mp.num_planes = ...;
>> >
>> > and also duplicate it in method parameters
>> >
>> >        *num_planes = create->format.fmt.pix_mp.num_planes;
>> >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
>> >
>> > or with
>> >
>> >        create->format.fmt.pix.sizeimage = ...;
>> >
>> > for single-plane. Alternatively we make the prototype
>> >
>> >        int (*queue_setup)(struct vb2_queue *q,
>> >                           struct v4l2_create_buffers *create,
>> >                           unsigned int *num_buffers,
>> >                           void *alloc_ctxs[]);
>> >
>> > then drivers only fill in *create, and the videobuf2-core will have to
>> > check create->format.type to decide, which of create->format.fmt.* is
>> > relevant and extract plane sizes from there.
>>
>>
>> Could we try exploring an alternative idea?
>> The queue_setup callback was added to decouple formats from vb2 (and
>> add some asynchronousness). But now we are doing the opposite, adding
>> format awareness to vb2. Does vb2 really need to know about formats? I
>> really believe it doesn't. It only needs sizes and counts.
>
> This kind of objection was expected:-) However, I think, you're a bit
> exaggerating. VB2 does not have to _fill_ the format. All frame-format
> fields like fourcc code, width, height, colorspace are only input from the
> user. If the user didn't fill them in, they should not be used. The only
> thing, that vb2 will have to learn about formats is to find the location
> of (plane-)buffer sizes in struct v4l2_format, for which it will have to
> interpret the .type value. I.e., we just have to add this:
>
> static int vb2_parse_planes(const struct v4l2_create_buffers *create,
>                            unsigned int *num_planes, unsigned int *plane_sizes)
> {
>        int i;
>
>        switch (create->format.type) {
>        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
>        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
>                *num_planes = 1;
>                plane_sizes[0] = create->format.fmt.pix.sizeimage;
>                return 0;
>        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
>        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
>                *num_planes = create->format.fmt.pix_mp.num_planes;
>                for (i = 0; i < *num_planes; i++)
>                        plane_sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
>                return 0;
>        default:
>                return -EINVAL;
>        }
> }
>
> Can you live with this or you still think it's too much format-knowledge
> for vb2? Or am I missing something, why we need more knowledge?
>

True, I exaggerated a bit there. You are right with the above (I was
also thinking of a case when the driver would want to adjust the
format passed to CREATE_BUFS, but that seems to work as well).

But I think my point still stands though: the drivers will have to
parse the format struct themselves for both createbufs and s_fmt and
friends, and know how to fill the sizeimage for both, but in the
createbufs case instead of assigning them in fmt struct, drivers would
be passing them to vb2 "outside" of it, as separate arguments. And the
filling code would have to be in drivers anyway for s_fmt. I'm
definitely for adding more things to vb2 to simplify drivers, but in
this case I'm just not seeing much of a gain :)

Now that I think of it, if we were to make vb2 get the format here,
why not simply pass the format struct to vb2 with sizeimages filled in
and forget about separate sizes arguments? I mean, it would be simpler
for the driver to just fill in fmt struct with numbers of planes and
sizeimages and pass only fmt to vb2 (and make vb2 use those for
allocation), instead of passing fmt unfilled and sizes separately and
make vb2 fill them in.

Either way, I'm still strongly leaning towards removing the
queue_setup callback and not passing format to vb2, for the reasons
I've already stated above.

>> Also, we
>> are actually complicating things I think. The proposal, IIUC, would
>> look like this:
>>
>> driver_queue_setup(..., create, num_buffers, [num_planes], ...)
>> {
>>     if (create != NULL && create->format != NULL) {
>>         /* use create->fmt to fill sizes */
>>     } else if (create != NULL) { /* this assumes we have both format or sizes */
>>         /* use create->sizes to fill sizes */
>>     } else {
>>         /* use currently selected format to fill sizes */
>>     }
>> }
>>
>> driver_s_fmt(format)
>> {
>>     /* ... */
>>     driver_fill_format(&create->fmt);
>>     /* ... */
>> }
>>
>> driver_create_bufs(create)
>> {
>>     vb2_create_bufs(create);
>> }
>>
>> vb2_create_bufs(create)
>> {
>>     driver_queue_setup(..., create, ...);
>>     vb2_fill_format(&create->fmt); /* note different from
>> driver_fill_format(), but both needed */
>> }
>>
>> vb2_reqbufs(reqbufs)
>> {
>>    driver_queue_setup(..., NULL, ...);
>> }
>>
>> The queue_setup not only becomes unnecessarily complicated, but I'm
>> starting to question the convenience of it. And we are teaching vb2
>> how to interpret format structs, even though vb2 only needs sizes, and
>> even though the driver has to do it anyway and knows better how.
>>
>> As for the idea to fill fmt in vb2, even if vb2 was to do it in
>> create_bufs, some code to parse and fill the format fields would need
>> to be in the driver anyway, because it still has to support s_fmt and
>> friends. So adding that code to vb2 would duplicate it, and if the
>> driver wanted to be non-standard in a way it filled the format fields,
>> we'd not be allowing that.
>>
>> My suggestion would be to remove queue_setup callback and instead
>> modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
>> buffers. I think it should simplify things both for drivers and vb2,
>> would keep vb2 format-unaware and save us some round trips between vb2
>> and driver:
>
> Right, I see what you mean. Well, this seems doable. Do we want this? It
> does seem to simplify things a bit by removing .queue_setup()... Opinions?
>

Thanks :) The more I think of queue_setup, the more I think that
although it was giving us that nice callback-based design, it's not
worth keeping if we were to make it more complicated. And it really
isn't such a big difference from directly calling
vb2_reqbufs/vb2_createbufs, which we have to call anyway, and the flow
and parameters are simpler.

>> driver_create_bufs(...) /* optional */
>> {
>>     /* use create->fmt (or sizes) */
>>     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
>> plane_sizes, alloc_ctxs);
>>     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
>> have a common function for that */
>>     return ret;
>> }
>>
>> driver_reqbufs(...)
>> {
>>     /* use current format */
>>     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
>> plane_sizes, alloc_ctxs);
>> }
>>
>> And the call to both could easily converge into one in vb2, as the
>> only difference is that vb2_reqbufs would need to free first, if any
>> allocated buffers were present:
>>
>> vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
>> {
>>     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
>> plane_sizes, alloc_ctxs)) {
>>         free_buffers(...);
>>     }
>>
>>     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
>> plane_sizes, alloc_ctxs);
>> }
>>
>> If the driver didn't want create_bufs, it'd just not implement it.
>> What do you think?
>>
>> --
>> Best regards,
>> Pawel Osciak
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
>
Marek Szyprowski Aug. 18, 2011, 5:49 a.m. UTC | #24
Hello,

On Wednesday, August 17, 2011 4:58 PM Pawel Osciak wrote:

> On Wed, Aug 17, 2011 at 06:22, Marek Szyprowski <m.szyprowski@samsung.com>
> wrote:
> > On Monday, August 15, 2011 3:46 PM Guennadi Liakhovetski wrote:
> >> While switching back, I have to change the struct vb2_ops::queue_setup()
> >> operation to take a struct v4l2_create_buffers pointer. An earlier version
> >> of this patch just added one more parameter to .queue_setup(), which is
> >> easier - changes to videobuf2-core.c are smaller, but it is then
> >> redundant. We could use the create pointer for both input and output. The
> >> video plane configuration in frame format is the same as what is
> >> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
> >> that one in. This would require then the videobuf2-core.c to parse struct
> >> v4l2_format to decide which union member we need, depending on the buffer
> >> type. Do we want this or shall drivers duplicate plane sizes in separate
> >> .queue_setup() parameters?
> >
> > IMHO if possible we should have only one callback for the driver. Please
> > notice that the driver should be also allowed to increase (or decrease) the
> > number of buffers for particular format/fourcc.
> >
> 
> Or remove queue_setup altogether (please see my example above). What
> do you think Marek?

I'm perfectly fine with replacing queue_setup callback with something else.

Best regards
Hans Verkuil (hansverk) Aug. 22, 2011, 10:06 a.m. UTC | #25
Sorry for starting this discussion and then disappearing. I've been very
busy lately, so my apologies for that.

On Tuesday, August 16, 2011 18:14:33 Pawel Osciak wrote:
> Hi Guennadi,
> 
> On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
> >
> >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> >>
> >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> >> > > Hi Hans
> >> > >
> >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> >
> > [snip]
> >
> >> > > > but I've changed my mind: I think
> >> > > > this should use a struct v4l2_format after all.
> >>
> >> While switching back, I have to change the struct vb2_ops::queue_setup()
> >> operation to take a struct v4l2_create_buffers pointer. An earlier 
version
> >> of this patch just added one more parameter to .queue_setup(), which is
> >> easier - changes to videobuf2-core.c are smaller, but it is then
> >> redundant. We could use the create pointer for both input and output. The
> >> video plane configuration in frame format is the same as what is
> >> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
> >> that one in. This would require then the videobuf2-core.c to parse struct
> >> v4l2_format to decide which union member we need, depending on the buffer
> >> type. Do we want this or shall drivers duplicate plane sizes in separate
> >> .queue_setup() parameters?
> >
> > Let me explain my question a bit. The current .queue_setup() method is
> >
> >        int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
> >                           unsigned int *num_planes, unsigned int sizes[],
> >                           void *alloc_ctxs[]);
> >
> > To support multiple-size buffers we also have to pass a pointer to struct
> > v4l2_create_buffers to this function now. We can either do it like this:
> >
> >        int (*queue_setup)(struct vb2_queue *q,
> >                           struct v4l2_create_buffers *create,
> >                           unsigned int *num_buffers,
> >                           unsigned int *num_planes, unsigned int sizes[],
> >                           void *alloc_ctxs[]);
> >
> > and let all drivers fill in respective fields in *create, e.g., either do
> >
> >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
> >        create->format.fmt.pix_mp.num_planes = ...;
> >
> > and also duplicate it in method parameters
> >
> >        *num_planes = create->format.fmt.pix_mp.num_planes;
> >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> >
> > or with
> >
> >        create->format.fmt.pix.sizeimage = ...;
> >
> > for single-plane. Alternatively we make the prototype
> >
> >        int (*queue_setup)(struct vb2_queue *q,
> >                           struct v4l2_create_buffers *create,
> >                           unsigned int *num_buffers,
> >                           void *alloc_ctxs[]);
> >
> > then drivers only fill in *create, and the videobuf2-core will have to
> > check create->format.type to decide, which of create->format.fmt.* is
> > relevant and extract plane sizes from there.
> 
> 
> Could we try exploring an alternative idea?
> The queue_setup callback was added to decouple formats from vb2 (and
> add some asynchronousness). But now we are doing the opposite, adding
> format awareness to vb2. Does vb2 really need to know about formats? I
> really believe it doesn't. It only needs sizes and counts. Also, we
> are actually complicating things I think. The proposal, IIUC, would
> look like this:
> 
> driver_queue_setup(..., create, num_buffers, [num_planes], ...)
> {
>     if (create != NULL && create->format != NULL) {
>         /* use create->fmt to fill sizes */

Right.

>     } else if (create != NULL) { /* this assumes we have both format or 
sizes */
>         /* use create->sizes to fill sizes */

No, create->format should always be set. If the application can fill in the
sizeimage field(s), then there is no need for create->sizes.

>     } else {
>         /* use currently selected format to fill sizes */

Right.

>     }
> }
> 
> driver_s_fmt(format)
> {
>     /* ... */
>     driver_fill_format(&create->fmt);
>     /* ... */
> }

???

> 
> driver_create_bufs(create)
> {
>     vb2_create_bufs(create);
> }
> 
> vb2_create_bufs(create)
> {
>     driver_queue_setup(..., create, ...);
>     vb2_fill_format(&create->fmt); /* note different from
> driver_fill_format(), but both needed */

Huh? Why call vb2_fill_format? vb2 should have no knowledge whatsoever about
formats. The driver needs that information in order to be able to allocate
buffers correctly since that depends on the required format. But vb2 doesn't
need that knowledge.

> }
> 
> vb2_reqbufs(reqbufs)
> {
>    driver_queue_setup(..., NULL, ...);
> }
> 
> The queue_setup not only becomes unnecessarily complicated, but I'm
> starting to question the convenience of it. And we are teaching vb2
> how to interpret format structs, even though vb2 only needs sizes, and
> even though the driver has to do it anyway and knows better how.

No, vb2 just needs to pass the format information from the user to the
driver.

There seems to be some misunderstanding here.

The point of my original suggestion that create_bufs should use v4l2_format
is that the driver needs the format information in order to decide how and
where the buffers have to be allocated. Having the format available is the
only reliable way to do that.

This is already done for REQBUFS since the driver will use the current format
to make these decisions.

One way of simplifying queue_setup is actually to always supply the format.
In the case of REQBUFS the driver might do something like this:

driver_reqbufs(requestbuffers)
{
	struct v4l2_format fmt;
	struct v4l2_create_buffers create;

	vb2_free_bufs(); // reqbufs should free any existing bufs
	if (requestbuffers->count == 0)
		return 0;
	driver_g_fmt(&fmt);	// call the g_fmt ioctl op
	// fill in create
	vb2_create_bufs(create);
}

So vb2 just sees a call requesting to create so many buffers for a particular
format, and it just hands that information over to the driver *without*
parsing it.

And the driver gets the request from vb2 to create X buffers for format F, and
will figure out how to do that and returns the buffer/plane/allocator context
information back to vb2.

Regards,

	Hans

> As for the idea to fill fmt in vb2, even if vb2 was to do it in
> create_bufs, some code to parse and fill the format fields would need
> to be in the driver anyway, because it still has to support s_fmt and
> friends. So adding that code to vb2 would duplicate it, and if the
> driver wanted to be non-standard in a way it filled the format fields,
> we'd not be allowing that.
> 
> My suggestion would be to remove queue_setup callback and instead
> modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
> buffers. I think it should simplify things both for drivers and vb2,
> would keep vb2 format-unaware and save us some round trips between vb2
> and driver:
> 
> driver_create_bufs(...) /* optional */
> {
>     /* use create->fmt (or sizes) */
>     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
>     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
> have a common function for that */
>     return ret;
> }
> 
> driver_reqbufs(...)
> {
>     /* use current format */
>     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }
> 
> And the call to both could easily converge into one in vb2, as the
> only difference is that vb2_reqbufs would need to free first, if any
> allocated buffers were present:
> 
> vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> {
>     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs)) {
>         free_buffers(...);
>     }
> 
>     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }
> 
> If the driver didn't want create_bufs, it'd just not implement it.
> What do you think?
> 
> -- 
> Best regards,
> Pawel Osciak
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Aug. 22, 2011, 10:40 a.m. UTC | #26
Hi Hans

On Mon, 22 Aug 2011, Hans Verkuil wrote:

> Sorry for starting this discussion and then disappearing. I've been very
> busy lately, so my apologies for that.
> 
> On Tuesday, August 16, 2011 18:14:33 Pawel Osciak wrote:
> > Hi Guennadi,
> > 
> > On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
> > <g.liakhovetski@gmx.de> wrote:
> > > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
> > >
> > >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> > >>
> > >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > >> > > Hi Hans
> > >> > >
> > >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> > >
> > > [snip]
> > >
> > >> > > > but I've changed my mind: I think
> > >> > > > this should use a struct v4l2_format after all.
> > >>
> > >> While switching back, I have to change the struct vb2_ops::queue_setup()
> > >> operation to take a struct v4l2_create_buffers pointer. An earlier 
> version
> > >> of this patch just added one more parameter to .queue_setup(), which is
> > >> easier - changes to videobuf2-core.c are smaller, but it is then
> > >> redundant. We could use the create pointer for both input and output. The
> > >> video plane configuration in frame format is the same as what is
> > >> calculated in .queue_setup(), IIUC. So, we could just let the driver fill
> > >> that one in. This would require then the videobuf2-core.c to parse struct
> > >> v4l2_format to decide which union member we need, depending on the buffer
> > >> type. Do we want this or shall drivers duplicate plane sizes in separate
> > >> .queue_setup() parameters?
> > >
> > > Let me explain my question a bit. The current .queue_setup() method is
> > >
> > >        int (*queue_setup)(struct vb2_queue *q, unsigned int *num_buffers,
> > >                           unsigned int *num_planes, unsigned int sizes[],
> > >                           void *alloc_ctxs[]);
> > >
> > > To support multiple-size buffers we also have to pass a pointer to struct
> > > v4l2_create_buffers to this function now. We can either do it like this:
> > >
> > >        int (*queue_setup)(struct vb2_queue *q,
> > >                           struct v4l2_create_buffers *create,
> > >                           unsigned int *num_buffers,
> > >                           unsigned int *num_planes, unsigned int sizes[],
> > >                           void *alloc_ctxs[]);
> > >
> > > and let all drivers fill in respective fields in *create, e.g., either do
> > >
> > >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
> > >        create->format.fmt.pix_mp.num_planes = ...;
> > >
> > > and also duplicate it in method parameters
> > >
> > >        *num_planes = create->format.fmt.pix_mp.num_planes;
> > >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> > >
> > > or with
> > >
> > >        create->format.fmt.pix.sizeimage = ...;
> > >
> > > for single-plane. Alternatively we make the prototype
> > >
> > >        int (*queue_setup)(struct vb2_queue *q,
> > >                           struct v4l2_create_buffers *create,
> > >                           unsigned int *num_buffers,
> > >                           void *alloc_ctxs[]);
> > >
> > > then drivers only fill in *create, and the videobuf2-core will have to
> > > check create->format.type to decide, which of create->format.fmt.* is
> > > relevant and extract plane sizes from there.
> > 
> > 
> > Could we try exploring an alternative idea?
> > The queue_setup callback was added to decouple formats from vb2 (and
> > add some asynchronousness). But now we are doing the opposite, adding
> > format awareness to vb2. Does vb2 really need to know about formats? I
> > really believe it doesn't. It only needs sizes and counts. Also, we
> > are actually complicating things I think. The proposal, IIUC, would
> > look like this:
> > 
> > driver_queue_setup(..., create, num_buffers, [num_planes], ...)
> > {
> >     if (create != NULL && create->format != NULL) {
> >         /* use create->fmt to fill sizes */
> 
> Right.
> 
> >     } else if (create != NULL) { /* this assumes we have both format or 
> sizes */
> >         /* use create->sizes to fill sizes */
> 
> No, create->format should always be set. If the application can fill in the
> sizeimage field(s), then there is no need for create->sizes.
> 
> >     } else {
> >         /* use currently selected format to fill sizes */
> 
> Right.
> 
> >     }
> > }
> > 
> > driver_s_fmt(format)
> > {
> >     /* ... */
> >     driver_fill_format(&create->fmt);
> >     /* ... */
> > }
> 
> ???
> 
> > 
> > driver_create_bufs(create)
> > {
> >     vb2_create_bufs(create);
> > }
> > 
> > vb2_create_bufs(create)
> > {
> >     driver_queue_setup(..., create, ...);
> >     vb2_fill_format(&create->fmt); /* note different from
> > driver_fill_format(), but both needed */
> 
> Huh? Why call vb2_fill_format? vb2 should have no knowledge whatsoever about
> formats. The driver needs that information in order to be able to allocate
> buffers correctly since that depends on the required format. But vb2 doesn't
> need that knowledge.

It would be good if you also could have a look at my reply to this Pawel's 
mail:

http://article.gmane.org/gmane.linux.drivers.video-input-infrastructure/36905

and, specifically, at the vb2_parse_planes() function in it. That's my 
understanding of what would be needed, if we preserve .queue_setup() and 
use your last suggestion to include struct v4l2_format in struct 
v4l2_create_buffers.

However, from your reply I couldn't understand your attitude to removing 
.queue_setup() altogether. Do you see any disadvantages in doing so? Is it 
serving any special role, that we are overseeing?

Thanks
Guennadi

> 
> > }
> > 
> > vb2_reqbufs(reqbufs)
> > {
> >    driver_queue_setup(..., NULL, ...);
> > }
> > 
> > The queue_setup not only becomes unnecessarily complicated, but I'm
> > starting to question the convenience of it. And we are teaching vb2
> > how to interpret format structs, even though vb2 only needs sizes, and
> > even though the driver has to do it anyway and knows better how.
> 
> No, vb2 just needs to pass the format information from the user to the
> driver.
> 
> There seems to be some misunderstanding here.
> 
> The point of my original suggestion that create_bufs should use v4l2_format
> is that the driver needs the format information in order to decide how and
> where the buffers have to be allocated. Having the format available is the
> only reliable way to do that.
> 
> This is already done for REQBUFS since the driver will use the current format
> to make these decisions.
> 
> One way of simplifying queue_setup is actually to always supply the format.
> In the case of REQBUFS the driver might do something like this:
> 
> driver_reqbufs(requestbuffers)
> {
> 	struct v4l2_format fmt;
> 	struct v4l2_create_buffers create;
> 
> 	vb2_free_bufs(); // reqbufs should free any existing bufs
> 	if (requestbuffers->count == 0)
> 		return 0;
> 	driver_g_fmt(&fmt);	// call the g_fmt ioctl op
> 	// fill in create
> 	vb2_create_bufs(create);
> }
> 
> So vb2 just sees a call requesting to create so many buffers for a particular
> format, and it just hands that information over to the driver *without*
> parsing it.
> 
> And the driver gets the request from vb2 to create X buffers for format F, and
> will figure out how to do that and returns the buffer/plane/allocator context
> information back to vb2.
> 
> Regards,
> 
> 	Hans
> 
> > As for the idea to fill fmt in vb2, even if vb2 was to do it in
> > create_bufs, some code to parse and fill the format fields would need
> > to be in the driver anyway, because it still has to support s_fmt and
> > friends. So adding that code to vb2 would duplicate it, and if the
> > driver wanted to be non-standard in a way it filled the format fields,
> > we'd not be allowing that.
> > 
> > My suggestion would be to remove queue_setup callback and instead
> > modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
> > buffers. I think it should simplify things both for drivers and vb2,
> > would keep vb2 format-unaware and save us some round trips between vb2
> > and driver:
> > 
> > driver_create_bufs(...) /* optional */
> > {
> >     /* use create->fmt (or sizes) */
> >     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > plane_sizes, alloc_ctxs);
> >     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
> > have a common function for that */
> >     return ret;
> > }
> > 
> > driver_reqbufs(...)
> > {
> >     /* use current format */
> >     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
> > plane_sizes, alloc_ctxs);
> > }
> > 
> > And the call to both could easily converge into one in vb2, as the
> > only difference is that vb2_reqbufs would need to free first, if any
> > allocated buffers were present:
> > 
> > vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> > {
> >     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
> > plane_sizes, alloc_ctxs)) {
> >         free_buffers(...);
> >     }
> > 
> >     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > plane_sizes, alloc_ctxs);
> > }
> > 
> > If the driver didn't want create_bufs, it'd just not implement it.
> > What do you think?
> > 
> > -- 
> > Best regards,
> > Pawel Osciak
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-media" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil (hansverk) Aug. 22, 2011, 11:16 a.m. UTC | #27
On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> Hi Hans
> 
> On Mon, 22 Aug 2011, Hans Verkuil wrote:
> 
> > Sorry for starting this discussion and then disappearing. I've been very
> > busy lately, so my apologies for that.
> > 
> > On Tuesday, August 16, 2011 18:14:33 Pawel Osciak wrote:
> > > Hi Guennadi,
> > > 
> > > On Tue, Aug 16, 2011 at 06:13, Guennadi Liakhovetski
> > > <g.liakhovetski@gmx.de> wrote:
> > > > On Mon, 15 Aug 2011, Guennadi Liakhovetski wrote:
> > > >
> > > >> On Mon, 15 Aug 2011, Hans Verkuil wrote:
> > > >>
> > > >> > On Monday, August 15, 2011 13:28:23 Guennadi Liakhovetski wrote:
> > > >> > > Hi Hans
> > > >> > >
> > > >> > > On Mon, 8 Aug 2011, Hans Verkuil wrote:
> > > >
> > > > [snip]
> > > >
> > > >> > > > but I've changed my mind: I think
> > > >> > > > this should use a struct v4l2_format after all.
> > > >>
> > > >> While switching back, I have to change the struct 
vb2_ops::queue_setup()
> > > >> operation to take a struct v4l2_create_buffers pointer. An earlier 
> > version
> > > >> of this patch just added one more parameter to .queue_setup(), which 
is
> > > >> easier - changes to videobuf2-core.c are smaller, but it is then
> > > >> redundant. We could use the create pointer for both input and output. 
The
> > > >> video plane configuration in frame format is the same as what is
> > > >> calculated in .queue_setup(), IIUC. So, we could just let the driver 
fill
> > > >> that one in. This would require then the videobuf2-core.c to parse 
struct
> > > >> v4l2_format to decide which union member we need, depending on the 
buffer
> > > >> type. Do we want this or shall drivers duplicate plane sizes in 
separate
> > > >> .queue_setup() parameters?
> > > >
> > > > Let me explain my question a bit. The current .queue_setup() method is
> > > >
> > > >        int (*queue_setup)(struct vb2_queue *q, unsigned int 
*num_buffers,
> > > >                           unsigned int *num_planes, unsigned int 
sizes[],
> > > >                           void *alloc_ctxs[]);
> > > >
> > > > To support multiple-size buffers we also have to pass a pointer to 
struct
> > > > v4l2_create_buffers to this function now. We can either do it like 
this:
> > > >
> > > >        int (*queue_setup)(struct vb2_queue *q,
> > > >                           struct v4l2_create_buffers *create,
> > > >                           unsigned int *num_buffers,
> > > >                           unsigned int *num_planes, unsigned int 
sizes[],
> > > >                           void *alloc_ctxs[]);
> > > >
> > > > and let all drivers fill in respective fields in *create, e.g., either 
do
> > > >
> > > >        create->format.fmt.pix_mp.plane_fmt[i].sizeimage = ...;
> > > >        create->format.fmt.pix_mp.num_planes = ...;
> > > >
> > > > and also duplicate it in method parameters
> > > >
> > > >        *num_planes = create->format.fmt.pix_mp.num_planes;
> > > >        sizes[i] = create->format.fmt.pix_mp.plane_fmt[i].sizeimage;
> > > >
> > > > or with
> > > >
> > > >        create->format.fmt.pix.sizeimage = ...;
> > > >
> > > > for single-plane. Alternatively we make the prototype
> > > >
> > > >        int (*queue_setup)(struct vb2_queue *q,
> > > >                           struct v4l2_create_buffers *create,
> > > >                           unsigned int *num_buffers,
> > > >                           void *alloc_ctxs[]);
> > > >
> > > > then drivers only fill in *create, and the videobuf2-core will have to
> > > > check create->format.type to decide, which of create->format.fmt.* is
> > > > relevant and extract plane sizes from there.
> > > 
> > > 
> > > Could we try exploring an alternative idea?
> > > The queue_setup callback was added to decouple formats from vb2 (and
> > > add some asynchronousness). But now we are doing the opposite, adding
> > > format awareness to vb2. Does vb2 really need to know about formats? I
> > > really believe it doesn't. It only needs sizes and counts. Also, we
> > > are actually complicating things I think. The proposal, IIUC, would
> > > look like this:
> > > 
> > > driver_queue_setup(..., create, num_buffers, [num_planes], ...)
> > > {
> > >     if (create != NULL && create->format != NULL) {
> > >         /* use create->fmt to fill sizes */
> > 
> > Right.
> > 
> > >     } else if (create != NULL) { /* this assumes we have both format or 
> > sizes */
> > >         /* use create->sizes to fill sizes */
> > 
> > No, create->format should always be set. If the application can fill in 
the
> > sizeimage field(s), then there is no need for create->sizes.
> > 
> > >     } else {
> > >         /* use currently selected format to fill sizes */
> > 
> > Right.
> > 
> > >     }
> > > }
> > > 
> > > driver_s_fmt(format)
> > > {
> > >     /* ... */
> > >     driver_fill_format(&create->fmt);
> > >     /* ... */
> > > }
> > 
> > ???
> > 
> > > 
> > > driver_create_bufs(create)
> > > {
> > >     vb2_create_bufs(create);
> > > }
> > > 
> > > vb2_create_bufs(create)
> > > {
> > >     driver_queue_setup(..., create, ...);
> > >     vb2_fill_format(&create->fmt); /* note different from
> > > driver_fill_format(), but both needed */
> > 
> > Huh? Why call vb2_fill_format? vb2 should have no knowledge whatsoever 
about
> > formats. The driver needs that information in order to be able to allocate
> > buffers correctly since that depends on the required format. But vb2 
doesn't
> > need that knowledge.
> 
> It would be good if you also could have a look at my reply to this Pawel's 
> mail:
> 
> http://article.gmane.org/gmane.linux.drivers.video-input-
infrastructure/36905
> 
> and, specifically, at the vb2_parse_planes() function in it. That's my 
> understanding of what would be needed, if we preserve .queue_setup() and 
> use your last suggestion to include struct v4l2_format in struct 
> v4l2_create_buffers.

vb2_parse_planes can be useful as a utility function that 'normal' drivers can 
call from the queue_setup. But vb2 should not parse the format directly, it
should just pass it on to the driver through the queue_setup function.

You also mention: "All frame-format fields like fourcc code, width, height, 
colorspace are only input from the user. If the user didn't fill them in, they 
should not be used."

I disagree with that. The user should fill in a full format description, just 
as with S/TRY_FMT. That's the information that the driver will use to set up 
the buffers. It could have weird rules like: if the fourcc is this, and the 
size is less than that, then we can allocate in this memory bank.

It is also consistent with REQBUFS: there too the driver uses a full format 
(i.e. the last set format).

I would modify queue_setup to something like this:

int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
                     unsigned int *num_buffers,
                     unsigned int *num_planes, unsigned int sizes[],
                     void *alloc_ctxs[]);

Whether fmt is left to NULL in the reqbufs case, or whether the driver has to 
call g_fmt first before calling vb2 is something that could be decided by what 
is easiest to implement.

Regards,

	Hans

> However, from your reply I couldn't understand your attitude to removing 
> .queue_setup() altogether. Do you see any disadvantages in doing so? Is it 
> serving any special role, that we are overseeing?
> 
> Thanks
> Guennadi
> 
> > 
> > > }
> > > 
> > > vb2_reqbufs(reqbufs)
> > > {
> > >    driver_queue_setup(..., NULL, ...);
> > > }
> > > 
> > > The queue_setup not only becomes unnecessarily complicated, but I'm
> > > starting to question the convenience of it. And we are teaching vb2
> > > how to interpret format structs, even though vb2 only needs sizes, and
> > > even though the driver has to do it anyway and knows better how.
> > 
> > No, vb2 just needs to pass the format information from the user to the
> > driver.
> > 
> > There seems to be some misunderstanding here.
> > 
> > The point of my original suggestion that create_bufs should use 
v4l2_format
> > is that the driver needs the format information in order to decide how and
> > where the buffers have to be allocated. Having the format available is the
> > only reliable way to do that.
> > 
> > This is already done for REQBUFS since the driver will use the current 
format
> > to make these decisions.
> > 
> > One way of simplifying queue_setup is actually to always supply the 
format.
> > In the case of REQBUFS the driver might do something like this:
> > 
> > driver_reqbufs(requestbuffers)
> > {
> > 	struct v4l2_format fmt;
> > 	struct v4l2_create_buffers create;
> > 
> > 	vb2_free_bufs(); // reqbufs should free any existing bufs
> > 	if (requestbuffers->count == 0)
> > 		return 0;
> > 	driver_g_fmt(&fmt);	// call the g_fmt ioctl op
> > 	// fill in create
> > 	vb2_create_bufs(create);
> > }
> > 
> > So vb2 just sees a call requesting to create so many buffers for a 
particular
> > format, and it just hands that information over to the driver *without*
> > parsing it.
> > 
> > And the driver gets the request from vb2 to create X buffers for format F, 
and
> > will figure out how to do that and returns the buffer/plane/allocator 
context
> > information back to vb2.
> > 
> > Regards,
> > 
> > 	Hans
> > 
> > > As for the idea to fill fmt in vb2, even if vb2 was to do it in
> > > create_bufs, some code to parse and fill the format fields would need
> > > to be in the driver anyway, because it still has to support s_fmt and
> > > friends. So adding that code to vb2 would duplicate it, and if the
> > > driver wanted to be non-standard in a way it filled the format fields,
> > > we'd not be allowing that.
> > > 
> > > My suggestion would be to remove queue_setup callback and instead
> > > modify vb2_reqbufs and vb2_create_bufs to accept sizes and number of
> > > buffers. I think it should simplify things both for drivers and vb2,
> > > would keep vb2 format-unaware and save us some round trips between vb2
> > > and driver:
> > > 
> > > driver_create_bufs(...) /* optional */
> > > {
> > >     /* use create->fmt (or sizes) */
> > >     ret = vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > > plane_sizes, alloc_ctxs);
> > >     fill_format(&create->fmt) /* because s_fmt has to do it anyway, so
> > > have a common function for that */
> > >     return ret;
> > > }
> > > 
> > > driver_reqbufs(...)
> > > {
> > >     /* use current format */
> > >     return vb2_reqbufs(num_buffers, num_planes, buf_sizes,
> > > plane_sizes, alloc_ctxs);
> > > }
> > > 
> > > And the call to both could easily converge into one in vb2, as the
> > > only difference is that vb2_reqbufs would need to free first, if any
> > > allocated buffers were present:
> > > 
> > > vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> > > {
> > >     if (buffers_allocated(num_buffers, num_planes, buf_sizes,
> > > plane_sizes, alloc_ctxs)) {
> > >         free_buffers(...);
> > >     }
> > > 
> > >     return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> > > plane_sizes, alloc_ctxs);
> > > }
> > > 
> > > If the driver didn't want create_bufs, it'd just not implement it.
> > > What do you think?
> > > 
> > > -- 
> > > Best regards,
> > > Pawel Osciak
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-media" 
in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > 
> > 
> 
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Guennadi Liakhovetski Aug. 22, 2011, 1:54 p.m. UTC | #28
We discussed a bit more with Hans on IRC, and below is my attempt of a 
summary. Hans, please, correct me, if I misunderstood anything. Pawel, 
Sakari, Laurent: please, reply, whether you're ok with this.

On Mon, 22 Aug 2011, Hans Verkuil wrote:

> On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:

[snip]

> > It would be good if you also could have a look at my reply to this Pawel's 
> > mail:
> > 
> > http://article.gmane.org/gmane.linux.drivers.video-input-
> infrastructure/36905
> > 
> > and, specifically, at the vb2_parse_planes() function in it. That's my 
> > understanding of what would be needed, if we preserve .queue_setup() and 
> > use your last suggestion to include struct v4l2_format in struct 
> > v4l2_create_buffers.
> 
> vb2_parse_planes can be useful as a utility function that 'normal' drivers can 
> call from the queue_setup. But vb2 should not parse the format directly, it
> should just pass it on to the driver through the queue_setup function.
> 
> You also mention: "All frame-format fields like fourcc code, width, height, 
> colorspace are only input from the user. If the user didn't fill them in, they 
> should not be used."
> 
> I disagree with that. The user should fill in a full format description, just 
> as with S/TRY_FMT. That's the information that the driver will use to set up 
> the buffers. It could have weird rules like: if the fourcc is this, and the 
> size is less than that, then we can allocate in this memory bank.
> 
> It is also consistent with REQBUFS: there too the driver uses a full format 
> (i.e. the last set format).
> 
> I would modify queue_setup to something like this:
> 
> int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
>                      unsigned int *num_buffers,
>                      unsigned int *num_planes, unsigned int sizes[],
>                      void *alloc_ctxs[]);
> 
> Whether fmt is left to NULL in the reqbufs case, or whether the driver has to 
> call g_fmt first before calling vb2 is something that could be decided by what 
> is easiest to implement.

1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user to 
   the kernel, in which struct v4l2_format is embedded. The user _must_ 
   fill in .type member of struct v4l2_format. For .type == 
   V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix is 
   used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or 
   V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these 
   cases the user _must_ fill in .width, .height, .pixelformat, .field, 
   .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The 
   user also _may_ optionally fill in any further buffer-size related 
   fields, if it believes to have any special requirements to them. On 
   a successful return from the ioctl() .count and .index fields are 
   filled in by the kernel, .format stays unchanged. The user has to call 
   VIDIOC_QUERYBUF to retrieve specific buffer information.

2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation, call 
   vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a 
   second argument. vb2_create_bufs() in turn calls the .queue_setup() 
   driver callback, whose prototype is modified as follows:

int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
			unsigned int *num_buffers,
			unsigned int *num_planes, unsigned int sizes[],
			void *alloc_ctxs[]);

   with &create->format as a second argument. As pointed out above, this 
   struct is not modified by V4L, instead, the usual arguments 3-6 are 
   filled in by the driver, which are then used by vb2_create_bufs() to 
   call __vb2_queue_alloc().

3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will be 
   a signal to the driver to use the current format.

4. We keep .queue_setup(), because its removal would inevitably push a 
   part of the common code from vb2_reqbufs() and vb2_create_bufs() down 
   into drivers, thus creating code redundancy and increasing its 
   complexity.

You have 24 hours to object, before I proceed with the next version;-)

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hans Verkuil (hansverk) Aug. 22, 2011, 2:01 p.m. UTC | #29
On Monday, August 22, 2011 15:54:03 Guennadi Liakhovetski wrote:
> We discussed a bit more with Hans on IRC, and below is my attempt of a 
> summary. Hans, please, correct me, if I misunderstood anything.

Looks good, that's exactly what I meant.

Regards,

	Hans

> Pawel, 
> Sakari, Laurent: please, reply, whether you're ok with this.
> 
> On Mon, 22 Aug 2011, Hans Verkuil wrote:
> 
> > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> 
> [snip]
> 
> > > It would be good if you also could have a look at my reply to this 
Pawel's 
> > > mail:
> > > 
> > > http://article.gmane.org/gmane.linux.drivers.video-input-
> > infrastructure/36905
> > > 
> > > and, specifically, at the vb2_parse_planes() function in it. That's my 
> > > understanding of what would be needed, if we preserve .queue_setup() and 
> > > use your last suggestion to include struct v4l2_format in struct 
> > > v4l2_create_buffers.
> > 
> > vb2_parse_planes can be useful as a utility function that 'normal' drivers 
can 
> > call from the queue_setup. But vb2 should not parse the format directly, 
it
> > should just pass it on to the driver through the queue_setup function.
> > 
> > You also mention: "All frame-format fields like fourcc code, width, 
height, 
> > colorspace are only input from the user. If the user didn't fill them in, 
they 
> > should not be used."
> > 
> > I disagree with that. The user should fill in a full format description, 
just 
> > as with S/TRY_FMT. That's the information that the driver will use to set 
up 
> > the buffers. It could have weird rules like: if the fourcc is this, and 
the 
> > size is less than that, then we can allocate in this memory bank.
> > 
> > It is also consistent with REQBUFS: there too the driver uses a full 
format 
> > (i.e. the last set format).
> > 
> > I would modify queue_setup to something like this:
> > 
> > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> >                      unsigned int *num_buffers,
> >                      unsigned int *num_planes, unsigned int sizes[],
> >                      void *alloc_ctxs[]);
> > 
> > Whether fmt is left to NULL in the reqbufs case, or whether the driver has 
to 
> > call g_fmt first before calling vb2 is something that could be decided by 
what 
> > is easiest to implement.
> 
> 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user to 
>    the kernel, in which struct v4l2_format is embedded. The user _must_ 
>    fill in .type member of struct v4l2_format. For .type == 
>    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix is 
>    used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or 
>    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these 
>    cases the user _must_ fill in .width, .height, .pixelformat, .field, 
>    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The 
>    user also _may_ optionally fill in any further buffer-size related 
>    fields, if it believes to have any special requirements to them. On 
>    a successful return from the ioctl() .count and .index fields are 
>    filled in by the kernel, .format stays unchanged. The user has to call 
>    VIDIOC_QUERYBUF to retrieve specific buffer information.
> 
> 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation, call 
>    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a 
>    second argument. vb2_create_bufs() in turn calls the .queue_setup() 
>    driver callback, whose prototype is modified as follows:
> 
> int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> 			unsigned int *num_buffers,
> 			unsigned int *num_planes, unsigned int sizes[],
> 			void *alloc_ctxs[]);
> 
>    with &create->format as a second argument. As pointed out above, this 
>    struct is not modified by V4L, instead, the usual arguments 3-6 are 
>    filled in by the driver, which are then used by vb2_create_bufs() to 
>    call __vb2_queue_alloc().
> 
> 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will be 
>    a signal to the driver to use the current format.
> 
> 4. We keep .queue_setup(), because its removal would inevitably push a 
>    part of the common code from vb2_reqbufs() and vb2_create_bufs() down 
>    into drivers, thus creating code redundancy and increasing its 
>    complexity.
> 
> You have 24 hours to object, before I proceed with the next version;-)
> 
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> http://www.open-technology.de/
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Aug. 22, 2011, 3:42 p.m. UTC | #30
Hi Guennadi,

On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
> We discussed a bit more with Hans on IRC, and below is my attempt of a
> summary. Hans, please, correct me, if I misunderstood anything. Pawel,
> Sakari, Laurent: please, reply, whether you're ok with this.

Sakari is on holidays this week.

> On Mon, 22 Aug 2011, Hans Verkuil wrote:
> > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> [snip]
> 
> > > It would be good if you also could have a look at my reply to this
> > > Pawel's mail:
> > > 
> > > http://article.gmane.org/gmane.linux.drivers.video-input-
> > 
> > infrastructure/36905
> > 
> > > and, specifically, at the vb2_parse_planes() function in it. That's my
> > > understanding of what would be needed, if we preserve .queue_setup()
> > > and use your last suggestion to include struct v4l2_format in struct
> > > v4l2_create_buffers.
> > 
> > vb2_parse_planes can be useful as a utility function that 'normal'
> > drivers can call from the queue_setup. But vb2 should not parse the
> > format directly, it should just pass it on to the driver through the
> > queue_setup function.
> > 
> > You also mention: "All frame-format fields like fourcc code, width,
> > height, colorspace are only input from the user. If the user didn't fill
> > them in, they should not be used."
> > 
> > I disagree with that. The user should fill in a full format description,
> > just as with S/TRY_FMT. That's the information that the driver will use
> > to set up the buffers. It could have weird rules like: if the fourcc is
> > this, and the size is less than that, then we can allocate in this
> > memory bank.
> > 
> > It is also consistent with REQBUFS: there too the driver uses a full
> > format (i.e. the last set format).
> > 
> > I would modify queue_setup to something like this:
> > 
> > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> > 
> >                      unsigned int *num_buffers,
> >                      unsigned int *num_planes, unsigned int sizes[],
> >                      void *alloc_ctxs[]);
> > 
> > Whether fmt is left to NULL in the reqbufs case, or whether the driver
> > has to call g_fmt first before calling vb2 is something that could be
> > decided by what is easiest to implement.
> 
> 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user to
>    the kernel, in which struct v4l2_format is embedded. The user _must_
>    fill in .type member of struct v4l2_format. For .type ==
>    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix is
>    used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
>    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
>    cases the user _must_ fill in .width, .height, .pixelformat, .field,
>    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
>    user also _may_ optionally fill in any further buffer-size related
>    fields, if it believes to have any special requirements to them. On
>    a successful return from the ioctl() .count and .index fields are
>    filled in by the kernel, .format stays unchanged. The user has to call
>    VIDIOC_QUERYBUF to retrieve specific buffer information.
> 
> 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation, call
>    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
>    second argument. vb2_create_bufs() in turn calls the .queue_setup()
>    driver callback, whose prototype is modified as follows:
> 
> int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> 			unsigned int *num_buffers,
> 			unsigned int *num_planes, unsigned int sizes[],
> 			void *alloc_ctxs[]);
> 
>    with &create->format as a second argument. As pointed out above, this
>    struct is not modified by V4L, instead, the usual arguments 3-6 are
>    filled in by the driver, which are then used by vb2_create_bufs() to
>    call __vb2_queue_alloc().
> 
> 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will be
>    a signal to the driver to use the current format.
> 
> 4. We keep .queue_setup(), because its removal would inevitably push a
>    part of the common code from vb2_reqbufs() and vb2_create_bufs() down
>    into drivers, thus creating code redundancy and increasing its
>    complexity.

How much common code would be pushed down to drivers ? I don't think this is a 
real issue. I like Pawel's proposal of removing .queue_setup() better.

> You have 24 hours to object, before I proceed with the next version;-)
Hans Verkuil Aug. 22, 2011, 3:52 p.m. UTC | #31
On Monday, August 22, 2011 17:42:36 Laurent Pinchart wrote:
> Hi Guennadi,
> 
> On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
> > We discussed a bit more with Hans on IRC, and below is my attempt of a
> > summary. Hans, please, correct me, if I misunderstood anything. Pawel,
> > Sakari, Laurent: please, reply, whether you're ok with this.
> 
> Sakari is on holidays this week.
> 
> > On Mon, 22 Aug 2011, Hans Verkuil wrote:
> > > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> > [snip]
> > 
> > > > It would be good if you also could have a look at my reply to this
> > > > Pawel's mail:
> > > > 
> > > > http://article.gmane.org/gmane.linux.drivers.video-input-
> > > 
> > > infrastructure/36905
> > > 
> > > > and, specifically, at the vb2_parse_planes() function in it. That's my
> > > > understanding of what would be needed, if we preserve .queue_setup()
> > > > and use your last suggestion to include struct v4l2_format in struct
> > > > v4l2_create_buffers.
> > > 
> > > vb2_parse_planes can be useful as a utility function that 'normal'
> > > drivers can call from the queue_setup. But vb2 should not parse the
> > > format directly, it should just pass it on to the driver through the
> > > queue_setup function.
> > > 
> > > You also mention: "All frame-format fields like fourcc code, width,
> > > height, colorspace are only input from the user. If the user didn't fill
> > > them in, they should not be used."
> > > 
> > > I disagree with that. The user should fill in a full format description,
> > > just as with S/TRY_FMT. That's the information that the driver will use
> > > to set up the buffers. It could have weird rules like: if the fourcc is
> > > this, and the size is less than that, then we can allocate in this
> > > memory bank.
> > > 
> > > It is also consistent with REQBUFS: there too the driver uses a full
> > > format (i.e. the last set format).
> > > 
> > > I would modify queue_setup to something like this:
> > > 
> > > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> > > 
> > >                      unsigned int *num_buffers,
> > >                      unsigned int *num_planes, unsigned int sizes[],
> > >                      void *alloc_ctxs[]);
> > > 
> > > Whether fmt is left to NULL in the reqbufs case, or whether the driver
> > > has to call g_fmt first before calling vb2 is something that could be
> > > decided by what is easiest to implement.
> > 
> > 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user to
> >    the kernel, in which struct v4l2_format is embedded. The user _must_
> >    fill in .type member of struct v4l2_format. For .type ==
> >    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix is
> >    used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
> >    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
> >    cases the user _must_ fill in .width, .height, .pixelformat, .field,
> >    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
> >    user also _may_ optionally fill in any further buffer-size related
> >    fields, if it believes to have any special requirements to them. On
> >    a successful return from the ioctl() .count and .index fields are
> >    filled in by the kernel, .format stays unchanged. The user has to call
> >    VIDIOC_QUERYBUF to retrieve specific buffer information.
> > 
> > 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation, call
> >    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
> >    second argument. vb2_create_bufs() in turn calls the .queue_setup()
> >    driver callback, whose prototype is modified as follows:
> > 
> > int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> > 			unsigned int *num_buffers,
> > 			unsigned int *num_planes, unsigned int sizes[],
> > 			void *alloc_ctxs[]);
> > 
> >    with &create->format as a second argument. As pointed out above, this
> >    struct is not modified by V4L, instead, the usual arguments 3-6 are
> >    filled in by the driver, which are then used by vb2_create_bufs() to
> >    call __vb2_queue_alloc().
> > 
> > 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will be
> >    a signal to the driver to use the current format.
> > 
> > 4. We keep .queue_setup(), because its removal would inevitably push a
> >    part of the common code from vb2_reqbufs() and vb2_create_bufs() down
> >    into drivers, thus creating code redundancy and increasing its
> >    complexity.
> 
> How much common code would be pushed down to drivers ? I don't think this is a 
> real issue. I like Pawel's proposal of removing .queue_setup() better.

I still don't see what removing queue_setup will solve or improve. I'd say
leave it as it is to keep the diff as small as possible and someone can always
attempt to remove it later. Removing queue_setup is independent from multi-size
videobuffer management and we should not mix the two.

Regards,

	Hans

> > You have 24 hours to object, before I proceed with the next version;-)
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Laurent Pinchart Aug. 22, 2011, 5:21 p.m. UTC | #32
Hi Hans,

On Monday 22 August 2011 17:52:12 Hans Verkuil wrote:
> On Monday, August 22, 2011 17:42:36 Laurent Pinchart wrote:
> > On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
> > > We discussed a bit more with Hans on IRC, and below is my attempt of a
> > > summary. Hans, please, correct me, if I misunderstood anything. Pawel,
> > > Sakari, Laurent: please, reply, whether you're ok with this.
> > 
> > Sakari is on holidays this week.
> > 
> > > On Mon, 22 Aug 2011, Hans Verkuil wrote:
> > > > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> > > [snip]
> > > 
> > > > > It would be good if you also could have a look at my reply to this
> > > > > Pawel's mail:
> > > > > 
> > > > > http://article.gmane.org/gmane.linux.drivers.video-input-
> > > > 
> > > > infrastructure/36905
> > > > 
> > > > > and, specifically, at the vb2_parse_planes() function in it. That's
> > > > > my understanding of what would be needed, if we preserve
> > > > > .queue_setup() and use your last suggestion to include struct
> > > > > v4l2_format in struct v4l2_create_buffers.
> > > > 
> > > > vb2_parse_planes can be useful as a utility function that 'normal'
> > > > drivers can call from the queue_setup. But vb2 should not parse the
> > > > format directly, it should just pass it on to the driver through the
> > > > queue_setup function.
> > > > 
> > > > You also mention: "All frame-format fields like fourcc code, width,
> > > > height, colorspace are only input from the user. If the user didn't
> > > > fill them in, they should not be used."
> > > > 
> > > > I disagree with that. The user should fill in a full format
> > > > description, just as with S/TRY_FMT. That's the information that the
> > > > driver will use to set up the buffers. It could have weird rules
> > > > like: if the fourcc is this, and the size is less than that, then we
> > > > can allocate in this memory bank.
> > > > 
> > > > It is also consistent with REQBUFS: there too the driver uses a full
> > > > format (i.e. the last set format).
> > > > 
> > > > I would modify queue_setup to something like this:
> > > > 
> > > > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> > > > 
> > > >                      unsigned int *num_buffers,
> > > >                      unsigned int *num_planes, unsigned int sizes[],
> > > >                      void *alloc_ctxs[]);
> > > > 
> > > > Whether fmt is left to NULL in the reqbufs case, or whether the
> > > > driver has to call g_fmt first before calling vb2 is something that
> > > > could be decided by what is easiest to implement.
> > > 
> > > 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user
> > > to
> > > 
> > >    the kernel, in which struct v4l2_format is embedded. The user _must_
> > >    fill in .type member of struct v4l2_format. For .type ==
> > >    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix
> > >    is used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
> > >    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
> > >    cases the user _must_ fill in .width, .height, .pixelformat, .field,
> > >    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
> > >    user also _may_ optionally fill in any further buffer-size related
> > >    fields, if it believes to have any special requirements to them. On
> > >    a successful return from the ioctl() .count and .index fields are
> > >    filled in by the kernel, .format stays unchanged. The user has to
> > >    call VIDIOC_QUERYBUF to retrieve specific buffer information.
> > > 
> > > 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation,
> > > call
> > > 
> > >    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
> > >    second argument. vb2_create_bufs() in turn calls the .queue_setup()
> > > 
> > >    driver callback, whose prototype is modified as follows:
> > > int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> > > 
> > > 			unsigned int *num_buffers,
> > > 			unsigned int *num_planes, unsigned int sizes[],
> > > 			void *alloc_ctxs[]);
> > > 			
> > >    with &create->format as a second argument. As pointed out above,
> > >    this struct is not modified by V4L, instead, the usual arguments
> > >    3-6 are filled in by the driver, which are then used by
> > >    vb2_create_bufs() to call __vb2_queue_alloc().
> > > 
> > > 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will
> > > be
> > > 
> > >    a signal to the driver to use the current format.
> > > 
> > > 4. We keep .queue_setup(), because its removal would inevitably push a
> > > 
> > >    part of the common code from vb2_reqbufs() and vb2_create_bufs()
> > >    down into drivers, thus creating code redundancy and increasing its
> > >    complexity.
> > 
> > How much common code would be pushed down to drivers ? I don't think this
> > is a real issue. I like Pawel's proposal of removing .queue_setup()
> > better.
> 
> I still don't see what removing queue_setup will solve or improve.

It will remove handling of the format in vb2 (even if it's a pass-through 
operation). I think it would be cleaner that way. It will also avoid going 
back and forth between drivers and vb2, which would improve code readability.

> I'd say leave it as it is to keep the diff as small as possible and someone
> can always attempt to remove it later. Removing queue_setup is independent
> from multi-size videobuffer management and we should not mix the two.

Guennadi's patch will (at least in my opinion) be cleaner if built on top of 
queue_setup() removal.
Hans Verkuil Aug. 23, 2011, 6:31 a.m. UTC | #33
On Monday, August 22, 2011 19:21:18 Laurent Pinchart wrote:
> Hi Hans,
> 
> On Monday 22 August 2011 17:52:12 Hans Verkuil wrote:
> > On Monday, August 22, 2011 17:42:36 Laurent Pinchart wrote:
> > > On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
> > > > We discussed a bit more with Hans on IRC, and below is my attempt of a
> > > > summary. Hans, please, correct me, if I misunderstood anything. Pawel,
> > > > Sakari, Laurent: please, reply, whether you're ok with this.
> > > 
> > > Sakari is on holidays this week.
> > > 
> > > > On Mon, 22 Aug 2011, Hans Verkuil wrote:
> > > > > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> > > > [snip]
> > > > 
> > > > > > It would be good if you also could have a look at my reply to this
> > > > > > Pawel's mail:
> > > > > > 
> > > > > > http://article.gmane.org/gmane.linux.drivers.video-input-
> > > > > 
> > > > > infrastructure/36905
> > > > > 
> > > > > > and, specifically, at the vb2_parse_planes() function in it. That's
> > > > > > my understanding of what would be needed, if we preserve
> > > > > > .queue_setup() and use your last suggestion to include struct
> > > > > > v4l2_format in struct v4l2_create_buffers.
> > > > > 
> > > > > vb2_parse_planes can be useful as a utility function that 'normal'
> > > > > drivers can call from the queue_setup. But vb2 should not parse the
> > > > > format directly, it should just pass it on to the driver through the
> > > > > queue_setup function.
> > > > > 
> > > > > You also mention: "All frame-format fields like fourcc code, width,
> > > > > height, colorspace are only input from the user. If the user didn't
> > > > > fill them in, they should not be used."
> > > > > 
> > > > > I disagree with that. The user should fill in a full format
> > > > > description, just as with S/TRY_FMT. That's the information that the
> > > > > driver will use to set up the buffers. It could have weird rules
> > > > > like: if the fourcc is this, and the size is less than that, then we
> > > > > can allocate in this memory bank.
> > > > > 
> > > > > It is also consistent with REQBUFS: there too the driver uses a full
> > > > > format (i.e. the last set format).
> > > > > 
> > > > > I would modify queue_setup to something like this:
> > > > > 
> > > > > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> > > > > 
> > > > >                      unsigned int *num_buffers,
> > > > >                      unsigned int *num_planes, unsigned int sizes[],
> > > > >                      void *alloc_ctxs[]);
> > > > > 
> > > > > Whether fmt is left to NULL in the reqbufs case, or whether the
> > > > > driver has to call g_fmt first before calling vb2 is something that
> > > > > could be decided by what is easiest to implement.
> > > > 
> > > > 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user
> > > > to
> > > > 
> > > >    the kernel, in which struct v4l2_format is embedded. The user _must_
> > > >    fill in .type member of struct v4l2_format. For .type ==
> > > >    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix
> > > >    is used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
> > > >    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
> > > >    cases the user _must_ fill in .width, .height, .pixelformat, .field,
> > > >    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
> > > >    user also _may_ optionally fill in any further buffer-size related
> > > >    fields, if it believes to have any special requirements to them. On
> > > >    a successful return from the ioctl() .count and .index fields are
> > > >    filled in by the kernel, .format stays unchanged. The user has to
> > > >    call VIDIOC_QUERYBUF to retrieve specific buffer information.
> > > > 
> > > > 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation,
> > > > call
> > > > 
> > > >    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
> > > >    second argument. vb2_create_bufs() in turn calls the .queue_setup()
> > > > 
> > > >    driver callback, whose prototype is modified as follows:
> > > > int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> > > > 
> > > > 			unsigned int *num_buffers,
> > > > 			unsigned int *num_planes, unsigned int sizes[],
> > > > 			void *alloc_ctxs[]);
> > > > 			
> > > >    with &create->format as a second argument. As pointed out above,
> > > >    this struct is not modified by V4L, instead, the usual arguments
> > > >    3-6 are filled in by the driver, which are then used by
> > > >    vb2_create_bufs() to call __vb2_queue_alloc().
> > > > 
> > > > 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will
> > > > be
> > > > 
> > > >    a signal to the driver to use the current format.
> > > > 
> > > > 4. We keep .queue_setup(), because its removal would inevitably push a
> > > > 
> > > >    part of the common code from vb2_reqbufs() and vb2_create_bufs()
> > > >    down into drivers, thus creating code redundancy and increasing its
> > > >    complexity.
> > > 
> > > How much common code would be pushed down to drivers ? I don't think this
> > > is a real issue. I like Pawel's proposal of removing .queue_setup()
> > > better.
> > 
> > I still don't see what removing queue_setup will solve or improve.
> 
> It will remove handling of the format in vb2 (even if it's a pass-through 
> operation). I think it would be cleaner that way. It will also avoid going 
> back and forth between drivers and vb2, which would improve code readability.

I very much doubt it will be more readable or cleaner. For one thing it is
inconsistent with the other ioctl ops where you just call a vb2 function to
handle it. Suddenly here you have to do lots of things to make it work.

> > I'd say leave it as it is to keep the diff as small as possible and someone
> > can always attempt to remove it later. Removing queue_setup is independent
> > from multi-size videobuffer management and we should not mix the two.
> 
> Guennadi's patch will (at least in my opinion) be cleaner if built on top of 
> queue_setup() removal.

Really? Just adding a single v4l2_format pointer is less clean than removing
queue_setup? That would really surprise me.

Anyway, let Guennadi choose what is easiest. It's an implementation detail in
the end and I just want to get this functionality in.

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pawel Osciak Aug. 24, 2011, 4:05 a.m. UTC | #34
Hi,

On Mon, Aug 22, 2011 at 23:31, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> On Monday, August 22, 2011 19:21:18 Laurent Pinchart wrote:
>> Hi Hans,
>>
>> On Monday 22 August 2011 17:52:12 Hans Verkuil wrote:
>> > On Monday, August 22, 2011 17:42:36 Laurent Pinchart wrote:
>> > > On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
>> > > > We discussed a bit more with Hans on IRC, and below is my attempt of a
>> > > > summary. Hans, please, correct me, if I misunderstood anything. Pawel,
>> > > > Sakari, Laurent: please, reply, whether you're ok with this.
>> > >
>> > > Sakari is on holidays this week.
>> > >
>> > > > On Mon, 22 Aug 2011, Hans Verkuil wrote:
>> > > > > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
>> > > > [snip]
>> > > >
>> > > > > > It would be good if you also could have a look at my reply to this
>> > > > > > Pawel's mail:
>> > > > > >
>> > > > > > http://article.gmane.org/gmane.linux.drivers.video-input-
>> > > > >
>> > > > > infrastructure/36905
>> > > > >
>> > > > > > and, specifically, at the vb2_parse_planes() function in it. That's
>> > > > > > my understanding of what would be needed, if we preserve
>> > > > > > .queue_setup() and use your last suggestion to include struct
>> > > > > > v4l2_format in struct v4l2_create_buffers.
>> > > > >
>> > > > > vb2_parse_planes can be useful as a utility function that 'normal'
>> > > > > drivers can call from the queue_setup. But vb2 should not parse the
>> > > > > format directly, it should just pass it on to the driver through the
>> > > > > queue_setup function.
>> > > > >
>> > > > > You also mention: "All frame-format fields like fourcc code, width,
>> > > > > height, colorspace are only input from the user. If the user didn't
>> > > > > fill them in, they should not be used."
>> > > > >
>> > > > > I disagree with that. The user should fill in a full format
>> > > > > description, just as with S/TRY_FMT. That's the information that the
>> > > > > driver will use to set up the buffers. It could have weird rules
>> > > > > like: if the fourcc is this, and the size is less than that, then we
>> > > > > can allocate in this memory bank.
>> > > > >
>> > > > > It is also consistent with REQBUFS: there too the driver uses a full
>> > > > > format (i.e. the last set format).
>> > > > >
>> > > > > I would modify queue_setup to something like this:
>> > > > >
>> > > > > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
>> > > > >
>> > > > >                      unsigned int *num_buffers,
>> > > > >                      unsigned int *num_planes, unsigned int sizes[],
>> > > > >                      void *alloc_ctxs[]);
>> > > > >
>> > > > > Whether fmt is left to NULL in the reqbufs case, or whether the
>> > > > > driver has to call g_fmt first before calling vb2 is something that
>> > > > > could be decided by what is easiest to implement.
>> > > >
>> > > > 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user
>> > > > to
>> > > >
>> > > >    the kernel, in which struct v4l2_format is embedded. The user _must_
>> > > >    fill in .type member of struct v4l2_format. For .type ==
>> > > >    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix
>> > > >    is used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
>> > > >    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
>> > > >    cases the user _must_ fill in .width, .height, .pixelformat, .field,
>> > > >    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
>> > > >    user also _may_ optionally fill in any further buffer-size related
>> > > >    fields, if it believes to have any special requirements to them. On
>> > > >    a successful return from the ioctl() .count and .index fields are
>> > > >    filled in by the kernel, .format stays unchanged. The user has to
>> > > >    call VIDIOC_QUERYBUF to retrieve specific buffer information.
>> > > >

Sounds good, just one question: we deliberately don't want to allow
CREATE_BUFS to adjust the format in any way, as S_FMT could?

>> > > > 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation,
>> > > > call
>> > > >
>> > > >    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
>> > > >    second argument. vb2_create_bufs() in turn calls the .queue_setup()
>> > > >
>> > > >    driver callback, whose prototype is modified as follows:
>> > > > int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
>> > > >
>> > > >                         unsigned int *num_buffers,
>> > > >                         unsigned int *num_planes, unsigned int sizes[],
>> > > >                         void *alloc_ctxs[]);
>> > > >
>> > > >    with &create->format as a second argument. As pointed out above,
>> > > >    this struct is not modified by V4L, instead, the usual arguments
>> > > >    3-6 are filled in by the driver, which are then used by
>> > > >    vb2_create_bufs() to call __vb2_queue_alloc().
>> > > >
>> > > > 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will
>> > > > be
>> > > >
>> > > >    a signal to the driver to use the current format.
>> > > >
>> > > > 4. We keep .queue_setup(), because its removal would inevitably push a
>> > > >
>> > > >    part of the common code from vb2_reqbufs() and vb2_create_bufs()
>> > > >    down into drivers, thus creating code redundancy and increasing its
>> > > >    complexity.
>> > >

What part would be passed down to drivers? Please see my example
below. I actually feel the drivers would become slightly simpler with
this change.

>> > > How much common code would be pushed down to drivers ? I don't think this
>> > > is a real issue. I like Pawel's proposal of removing .queue_setup()
>> > > better.
>> >
>> > I still don't see what removing queue_setup will solve or improve.
>>
>> It will remove handling of the format in vb2 (even if it's a pass-through
>> operation). I think it would be cleaner that way. It will also avoid going
>> back and forth between drivers and vb2, which would improve code readability.
>
> I very much doubt it will be more readable or cleaner. For one thing it is
> inconsistent with the other ioctl ops where you just call a vb2 function to
> handle it. Suddenly here you have to do lots of things to make it work.
>

This flow:

REQBUFS->driver_reqbufs()->vb2_reqbufs()->queue_setup(fmt=NULL, nums,
sizes)->vb2_reqbufs->driver_reqbufs
CREATE_BUFS->driver_create_bufs()->vb2_create_bufs(fmt)->queue_setup(fmt,
nums, sizes)->vb2_create_bufs->driver_create_bufs

is more complicated than this flow:

REQBUFS->driver_reqbufs()->vb2_reqbufs(nums, sizes)->driver_reqbufs
CREATE_BUFS->driver_create_bufs()->vb2_create_bufs(nums,
sizes)->driver_create_bufs

without giving any clear advantage (at least from what I can see),
apart from making Guennadi's change simpler.


Below is what I'm proposing. This, in my opinion, makes vb2's
interface cleaner, as the format is never passed to it. I don't see
what code it'd be passing down to drivers. The goal is to pass
(return) nums/sizes to vb2 anyway. Existing queue_setup() could with
some modifications become figure_out_params():

driver_create_bufs(create) /* optional */
{
   /* use create->fmt to figure out num_* and *_sizes */
   figure_out_params(create->fmt, &num_buffers, &num_planes,
&buf_sizes, &plane_sizes);
   return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs);
}

driver_reqbufs()
{
   /* use current format to figure out num_* and *_sizes */
   figure_out_params(current_fmt, &num_buffers, &num_planes,
&buf_sizes, &plane_sizes);
   return vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes,
alloc_ctxs);
}

/* ---------- */

vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
{
   if (buffers_allocated)
       free_buffers(...);

   return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
plane_sizes, alloc_ctxs);
}

>> > I'd say leave it as it is to keep the diff as small as possible and someone
>> > can always attempt to remove it later. Removing queue_setup is independent
>> > from multi-size videobuffer management and we should not mix the two.
>>
>> Guennadi's patch will (at least in my opinion) be cleaner if built on top of
>> queue_setup() removal.
>
> Really? Just adding a single v4l2_format pointer is less clean than removing
> queue_setup? That would really surprise me.
> Anyway, let Guennadi choose what is easiest. It's an implementation detail in
> the end and I just want to get this functionality in.

I'm not completely opposed to your last suggestion. I agree the patch
would be much shorter. Your proposal is reasonable and simple enough.
I just feel that it'd pay off to put a little bit more effort to make
the changes I'm proposing, to make the interface cleaner and simplify
ping-ponging calls and parameters between drivers and vb2.

But I don't mind if we make it simple for now. As you suggested, I'll
be more than happy to look into removing queue_setup later.
Hans Verkuil Aug. 24, 2011, 6:44 a.m. UTC | #35
On Wednesday, August 24, 2011 06:05:44 Pawel Osciak wrote:
> Hi,
> 
> On Mon, Aug 22, 2011 at 23:31, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> > On Monday, August 22, 2011 19:21:18 Laurent Pinchart wrote:
> >> Hi Hans,
> >>
> >> On Monday 22 August 2011 17:52:12 Hans Verkuil wrote:
> >> > On Monday, August 22, 2011 17:42:36 Laurent Pinchart wrote:
> >> > > On Monday 22 August 2011 15:54:03 Guennadi Liakhovetski wrote:
> >> > > > We discussed a bit more with Hans on IRC, and below is my attempt of a
> >> > > > summary. Hans, please, correct me, if I misunderstood anything. Pawel,
> >> > > > Sakari, Laurent: please, reply, whether you're ok with this.
> >> > >
> >> > > Sakari is on holidays this week.
> >> > >
> >> > > > On Mon, 22 Aug 2011, Hans Verkuil wrote:
> >> > > > > On Monday, August 22, 2011 12:40:25 Guennadi Liakhovetski wrote:
> >> > > > [snip]
> >> > > >
> >> > > > > > It would be good if you also could have a look at my reply to this
> >> > > > > > Pawel's mail:
> >> > > > > >
> >> > > > > > http://article.gmane.org/gmane.linux.drivers.video-input-
> >> > > > >
> >> > > > > infrastructure/36905
> >> > > > >
> >> > > > > > and, specifically, at the vb2_parse_planes() function in it. That's
> >> > > > > > my understanding of what would be needed, if we preserve
> >> > > > > > .queue_setup() and use your last suggestion to include struct
> >> > > > > > v4l2_format in struct v4l2_create_buffers.
> >> > > > >
> >> > > > > vb2_parse_planes can be useful as a utility function that 'normal'
> >> > > > > drivers can call from the queue_setup. But vb2 should not parse the
> >> > > > > format directly, it should just pass it on to the driver through the
> >> > > > > queue_setup function.
> >> > > > >
> >> > > > > You also mention: "All frame-format fields like fourcc code, width,
> >> > > > > height, colorspace are only input from the user. If the user didn't
> >> > > > > fill them in, they should not be used."
> >> > > > >
> >> > > > > I disagree with that. The user should fill in a full format
> >> > > > > description, just as with S/TRY_FMT. That's the information that the
> >> > > > > driver will use to set up the buffers. It could have weird rules
> >> > > > > like: if the fourcc is this, and the size is less than that, then we
> >> > > > > can allocate in this memory bank.
> >> > > > >
> >> > > > > It is also consistent with REQBUFS: there too the driver uses a full
> >> > > > > format (i.e. the last set format).
> >> > > > >
> >> > > > > I would modify queue_setup to something like this:
> >> > > > >
> >> > > > > int (*queue_setup)(struct vb2_queue *q, struct v4l2_format *fmt,
> >> > > > >
> >> > > > >                      unsigned int *num_buffers,
> >> > > > >                      unsigned int *num_planes, unsigned int sizes[],
> >> > > > >                      void *alloc_ctxs[]);
> >> > > > >
> >> > > > > Whether fmt is left to NULL in the reqbufs case, or whether the
> >> > > > > driver has to call g_fmt first before calling vb2 is something that
> >> > > > > could be decided by what is easiest to implement.
> >> > > >
> >> > > > 1. VIDIOC_CREATE_BUFS passes struct v4l2_create_buffers from the user
> >> > > > to
> >> > > >
> >> > > >    the kernel, in which struct v4l2_format is embedded. The user _must_
> >> > > >    fill in .type member of struct v4l2_format. For .type ==
> >> > > >    V4L2_BUF_TYPE_VIDEO_CAPTURE or V4L2_BUF_TYPE_VIDEO_OUTPUT .fmt.pix
> >> > > >    is used, for .type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE or
> >> > > >    V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE .fmt.pix_mp is used. In both these
> >> > > >    cases the user _must_ fill in .width, .height, .pixelformat, .field,
> >> > > >    .colorspace by possibly calling VIDIOC_G_FMT or VIDIOC_TRY_FMT. The
> >> > > >    user also _may_ optionally fill in any further buffer-size related
> >> > > >    fields, if it believes to have any special requirements to them. On
> >> > > >    a successful return from the ioctl() .count and .index fields are
> >> > > >    filled in by the kernel, .format stays unchanged. The user has to
> >> > > >    call VIDIOC_QUERYBUF to retrieve specific buffer information.
> >> > > >
> 
> Sounds good, just one question: we deliberately don't want to allow
> CREATE_BUFS to adjust the format in any way, as S_FMT could?

That was my initial idea, but I don't think that holds water.

The sequence probably has to be (ideal for a utility function):

1) make a copy of the sizeimage fields
2) call try_fmt
3) replace the sizeimage fields with the max value of the 'try'
values and the copy.

Then this final fmt can be returned.

> >> > > > 2. Videobuf2 drivers, that implement .vidioc_create_bufs() operation,
> >> > > > call
> >> > > >
> >> > > >    vb2_create_bufs() with a pointer to struct v4l2_create_buffers as a
> >> > > >    second argument. vb2_create_bufs() in turn calls the .queue_setup()
> >> > > >
> >> > > >    driver callback, whose prototype is modified as follows:
> >> > > > int (*queue_setup)(struct vb2_queue *q, const struct v4l2_format *fmt,
> >> > > >
> >> > > >                         unsigned int *num_buffers,
> >> > > >                         unsigned int *num_planes, unsigned int sizes[],
> >> > > >                         void *alloc_ctxs[]);
> >> > > >
> >> > > >    with &create->format as a second argument. As pointed out above,
> >> > > >    this struct is not modified by V4L, instead, the usual arguments
> >> > > >    3-6 are filled in by the driver, which are then used by
> >> > > >    vb2_create_bufs() to call __vb2_queue_alloc().
> >> > > >
> >> > > > 3. vb2_reqbufs() shall call .queue_setup() with fmt == NULL, which will
> >> > > > be
> >> > > >
> >> > > >    a signal to the driver to use the current format.
> >> > > >
> >> > > > 4. We keep .queue_setup(), because its removal would inevitably push a
> >> > > >
> >> > > >    part of the common code from vb2_reqbufs() and vb2_create_bufs()
> >> > > >    down into drivers, thus creating code redundancy and increasing its
> >> > > >    complexity.
> >> > >
> 
> What part would be passed down to drivers? Please see my example
> below. I actually feel the drivers would become slightly simpler with
> this change.

Roughly speaking it has to do at least part of what is in vb2_reqbufs before
the call to queue_setup. In particular for reqbufs it will have to explicitly
test against count == 0 since that's a special case.

> >> > > How much common code would be pushed down to drivers ? I don't think this
> >> > > is a real issue. I like Pawel's proposal of removing .queue_setup()
> >> > > better.
> >> >
> >> > I still don't see what removing queue_setup will solve or improve.
> >>
> >> It will remove handling of the format in vb2 (even if it's a pass-through
> >> operation). I think it would be cleaner that way. It will also avoid going
> >> back and forth between drivers and vb2, which would improve code readability.
> >
> > I very much doubt it will be more readable or cleaner. For one thing it is
> > inconsistent with the other ioctl ops where you just call a vb2 function to
> > handle it. Suddenly here you have to do lots of things to make it work.
> >
> 
> This flow:
> 
> REQBUFS->driver_reqbufs()->vb2_reqbufs()->queue_setup(fmt=NULL, nums,
> sizes)->vb2_reqbufs->driver_reqbufs
> CREATE_BUFS->driver_create_bufs()->vb2_create_bufs(fmt)->queue_setup(fmt,
> nums, sizes)->vb2_create_bufs->driver_create_bufs
> 
> is more complicated than this flow:
> 
> REQBUFS->driver_reqbufs()->vb2_reqbufs(nums, sizes)->driver_reqbufs
> CREATE_BUFS->driver_create_bufs()->vb2_create_bufs(nums,
> sizes)->driver_create_bufs
> 
> without giving any clear advantage (at least from what I can see),
> apart from making Guennadi's change simpler.
> 
> 
> Below is what I'm proposing. This, in my opinion, makes vb2's
> interface cleaner, as the format is never passed to it. I don't see
> what code it'd be passing down to drivers. The goal is to pass
> (return) nums/sizes to vb2 anyway. Existing queue_setup() could with
> some modifications become figure_out_params():
> 
> driver_create_bufs(create) /* optional */
> {
>    /* use create->fmt to figure out num_* and *_sizes */
>    figure_out_params(create->fmt, &num_buffers, &num_planes,
> &buf_sizes, &plane_sizes);
>    return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }
> 
> driver_reqbufs()
> {
>    /* use current format to figure out num_* and *_sizes */
>    figure_out_params(current_fmt, &num_buffers, &num_planes,
> &buf_sizes, &plane_sizes);

So you have to set up the necessary variables etc. to store the
num_planes, buf_sizes, alloc_ctxs, etc. And you have to do that for
each driver as well.

>    return vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes,
> alloc_ctxs);
> }
> 
> /* ---------- */
> 
> vb2_reqbufs(num_buffers, num_planes, buf_sizes, plane_sizes, alloc_ctxs)
> {
>    if (buffers_allocated)
>        free_buffers(...);
> 
>    return vb2_create_bufs(num_buffers, num_planes, buf_sizes,
> plane_sizes, alloc_ctxs);
> }

Where I would simplify the flow is to change the vb2_reqbufs prototype to be
a precise match to the ioctl op. That way a driver no longer has to implement
a reqbufs op (or any of the others). The only thing necessary for that is to
add a vb2_queue pointer to struct video_device.

It would also solve another issue that's been bugging me for some time now:
vb2 has no knowledge of which filehandle is streaming. For non-mem2mem drivers
that's important information since you need to be able to check whether the
current filehandle is streaming or not. Right now each driver needs to store
that information itself, something that's easy to do wrong.

This would simplify the flow to:

REQBUFS->vb2_reqbufs()->queue_setup(fmt=NULL, nums, sizes)->vb2_reqbufs
CREATE_BUFS->vb2_create_bufs(fmt)->queue_setup(fmt, nums, sizes)->vb2_create_bufs

I like this much better since it allows for greater integration of vb2 with
the v4l2 framework.

> >> > I'd say leave it as it is to keep the diff as small as possible and someone
> >> > can always attempt to remove it later. Removing queue_setup is independent
> >> > from multi-size videobuffer management and we should not mix the two.
> >>
> >> Guennadi's patch will (at least in my opinion) be cleaner if built on top of
> >> queue_setup() removal.
> >
> > Really? Just adding a single v4l2_format pointer is less clean than removing
> > queue_setup? That would really surprise me.
> > Anyway, let Guennadi choose what is easiest. It's an implementation detail in
> > the end and I just want to get this functionality in.
> 
> I'm not completely opposed to your last suggestion. I agree the patch
> would be much shorter. Your proposal is reasonable and simple enough.
> I just feel that it'd pay off to put a little bit more effort to make
> the changes I'm proposing, to make the interface cleaner and simplify
> ping-ponging calls and parameters between drivers and vb2.
> 
> But I don't mind if we make it simple for now. As you suggested, I'll
> be more than happy to look into removing queue_setup later.

I think we should go for the simple solution right now. All this is independent
from adding createbufs.

Regards,

	Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index 227e7ac..ff03dd2 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -927,6 +927,23 @@  ioctl is called.</entry>
 Applications set or clear this flag before calling the
 <constant>VIDIOC_QBUF</constant> ioctl.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
+	    <entry>0x0400</entry>
+	    <entry>Caches do not have to be invalidated for this buffer.
+Typically applications shall use this flag if the data captured in the buffer
+is not going to be touched by the CPU, instead the buffer will, probably, be
+passed on to a DMA-capable hardware unit for further processing or output.
+</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
+	    <entry>0x0800</entry>
+	    <entry>Caches do not have to be cleaned for this buffer.
+Typically applications shall use this flag for output buffers if the data
+in this buffer has not been created by the CPU but by some DMA-capable unit,
+in which case caches have not been used.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index 0d05e87..06bb179 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -462,6 +462,7 @@  and discussions on the V4L mailing list.</revremark>
     &sub-close;
     &sub-ioctl;
     <!-- All ioctls go here. -->
+    &sub-create-bufs;
     &sub-cropcap;
     &sub-dbg-g-chip-ident;
     &sub-dbg-g-register;
@@ -504,6 +505,7 @@  and discussions on the V4L mailing list.</revremark>
     &sub-queryctrl;
     &sub-query-dv-preset;
     &sub-querystd;
+    &sub-prepare-buf;
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
     &sub-streamon;
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
new file mode 100644
index 0000000..b37b9a4
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
@@ -0,0 +1,161 @@ 
+<refentry id="vidioc-create-bufs">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_CREATE_BUFS</refname>
+    <refpurpose>Create buffers for Memory Mapped or User Pointer I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_create_buffers *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_CREATE_BUFS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>This ioctl is used to create buffers for <link linkend="mmap">memory
+mapped</link> or <link linkend="userp">user pointer</link>
+I/O. It can be used as an alternative or in addition to the
+<constant>VIDIOC_REQBUFS</constant> ioctl, when a tighter control over buffers
+is required. This ioctl can be called multiple times to create buffers of
+different sizes.</para>
+
+    <para>To allocate device buffers applications initialize relevant
+fields of the <structname>v4l2_create_buffers</structname> structure.
+They set the <structfield>type</structfield> field  to the respective stream
+or buffer type. <structfield>count</structfield> must be set to the number of
+required buffers. <structfield>memory</structfield> specifies the required I/O
+method. If <structfield>num_planes</structfield> == 0 or all elements of the
+<structfield>sizes</structfield> array are 0, then buffers, suitable for the
+currently configured video format, are allocated, exactly like for the
+<constant>VIDIOC_REQBUFS</constant> ioctl. If
+<structfield>num_planes</structfield> > 0 and at least some of the respective
+<structfield>sizes</structfield> elements are non-zero, this information will be
+used for buffer-allocation. The <structfield>reserved</structfield> array must
+be zeroed. When the ioctl is called with a pointer to this structure the driver
+will attempt to allocate up to the requested number of buffers and store the
+actual number allocated and the starting index in the
+<structfield>count</structfield> and the <structfield>index</structfield>
+fields respectively. On return <structfield>count</structfield> can be smaller
+than the number requested.</para>
+    <para>When the I/O method is not supported the ioctl
+returns an &EINVAL;.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-create-buffers">
+      <title>struct <structname>v4l2_create_buffers</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>The starting buffer index, returned by the driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>count</structfield></entry>
+	    <entry>The number of buffers requested or granted.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry>V4L2 buffer type: one of <constant>V4L2_BUF_TYPE_*</constant>
+values.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>memory</structfield></entry>
+	    <entry>Applications set this field to
+<constant>V4L2_MEMORY_MMAP</constant> or
+<constant>V4L2_MEMORY_USERPTR</constant>.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>fourcc</structfield></entry>
+	    <entry>One of V4L2_PIX_FMT_* FOURCCs of the video data.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>num_planes</structfield></entry>
+	    <entry>Number of planes or 0 to use the current format.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>size[VIDEO_MAX_PLANES]</structfield></entry>
+	    <entry>Explicit sizes of buffers, being created.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[18]</entry>
+	    <entry>A place holder for future extensions.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>ENOMEM</errorcode></term>
+	<listitem>
+	  <para>No memory to allocate buffers for <link linkend="mmap">memory
+mapped</link> I/O.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer type (<structfield>type</structfield> field) or the
+requested I/O method (<structfield>memory</structfield>) is not
+supported.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
new file mode 100644
index 0000000..509e752
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
@@ -0,0 +1,96 @@ 
+<refentry id="vidioc-prepare-buf">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_PREPARE_BUF</refname>
+    <refpurpose>Prepare a buffer for I/O</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_buffer *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_PREPARE_BUF</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Applications can optionally call the
+<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
+to the driver before actually enqueuing it, using the
+<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
+Such preparations may include cache invalidation or cleaning. Performing them
+in advance saves time during the actual I/O. In case such cache operations are
+not required, the application can use one of
+<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
+<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
+step.</para>
+
+    <para>The <structname>v4l2_buffer</structname> structure is
+specified in <xref linkend="buffer" />.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>File I/O is in progress.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The buffer <structfield>type</structfield> is not
+supported, or the <structfield>index</structfield> is out of bounds,
+or no buffers have been allocated yet, or the
+<structfield>userptr</structfield> or
+<structfield>length</structfield> are invalid.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
+
+<!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "v4l2.sgml"
+indent-tabs-mode: nil
+End:
+-->
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
index 61979b7..ee5eec8 100644
--- a/drivers/media/video/v4l2-compat-ioctl32.c
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -702,6 +702,7 @@  static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
 #define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
+#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
 
 #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
 #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
@@ -751,6 +752,7 @@  static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
 	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
 	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
+	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
 	}
 
 	switch (cmd) {
@@ -775,6 +777,7 @@  static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 		compatible_arg = 0;
 		break;
 
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
@@ -860,6 +863,7 @@  static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 		err = put_v4l2_format32(&karg.v2f, up);
 		break;
 
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
@@ -959,6 +963,8 @@  long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 	case VIDIOC_DQEVENT32:
 	case VIDIOC_SUBSCRIBE_EVENT:
 	case VIDIOC_UNSUBSCRIBE_EVENT:
+	case VIDIOC_CREATE_BUFS:
+	case VIDIOC_PREPARE_BUF32:
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 002ce13..3da87c0 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -260,6 +260,8 @@  static const char *v4l2_ioctls[] = {
 	[_IOC_NR(VIDIOC_DQEVENT)]	   = "VIDIOC_DQEVENT",
 	[_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)]  = "VIDIOC_SUBSCRIBE_EVENT",
 	[_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
+	[_IOC_NR(VIDIOC_CREATE_BUFS)]      = "VIDIOC_CREATE_BUFS",
+	[_IOC_NR(VIDIOC_PREPARE_BUF)]      = "VIDIOC_PREPARE_BUF",
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -2216,6 +2218,30 @@  static long __video_do_ioctl(struct file *file,
 		dbgarg(cmd, "type=0x%8.8x", sub->type);
 		break;
 	}
+	case VIDIOC_CREATE_BUFS:
+	{
+		struct v4l2_create_buffers *create = arg;
+
+		if (!ops->vidioc_create_bufs)
+			break;
+
+		ret = ops->vidioc_create_bufs(file, fh, create);
+
+		dbgarg(cmd, "count=%u @ %u\n", create->count, create->index);
+		break;
+	}
+	case VIDIOC_PREPARE_BUF:
+	{
+		struct v4l2_buffer *b = arg;
+
+		if (!ops->vidioc_prepare_buf)
+			break;
+
+		ret = ops->vidioc_prepare_buf(file, fh, b);
+
+		dbgarg(cmd, "index=%d", b->index);
+		break;
+	}
 	default:
 	{
 		bool valid_prio = true;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index fca24cc..3cd0cb3 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -653,6 +653,9 @@  struct v4l2_buffer {
 #define V4L2_BUF_FLAG_ERROR	0x0040
 #define V4L2_BUF_FLAG_TIMECODE	0x0100	/* timecode field is valid */
 #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
+/* Cache handling flags */
+#define V4L2_BUF_FLAG_NO_CACHE_INVALIDATE	0x0400
+#define V4L2_BUF_FLAG_NO_CACHE_CLEAN		0x0800
 
 /*
  *	O V E R L A Y   P R E V I E W
@@ -2092,6 +2095,18 @@  struct v4l2_dbg_chip_ident {
 	__u32 revision;    /* chip revision, chip specific */
 } __attribute__ ((packed));
 
+/* VIDIOC_CREATE_BUFS */
+struct v4l2_create_buffers {
+	__u32	index;	/* output: buffers index...index + count - 1 have been created */
+	__u32	count;
+	__u32	type;
+	__u32	memory;
+	__u32	fourcc;
+	__u32	num_planes;
+	__u32	sizes[VIDEO_MAX_PLANES];
+	__u32	reserved[18];
+};
+
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -2182,6 +2197,9 @@  struct v4l2_dbg_chip_ident {
 #define	VIDIOC_SUBSCRIBE_EVENT	 _IOW('V', 90, struct v4l2_event_subscription)
 #define	VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct v4l2_event_subscription)
 
+#define VIDIOC_CREATE_BUFS	_IOWR('V', 92, struct v4l2_create_buffers)
+#define VIDIOC_PREPARE_BUF	 _IOW('V', 93, struct v4l2_buffer)
+
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index dd9f1e7..4d1c74a 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -122,6 +122,8 @@  struct v4l2_ioctl_ops {
 	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
 	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
 
+	int (*vidioc_create_bufs)(struct file *file, void *fh, struct v4l2_create_buffers *b);
+	int (*vidioc_prepare_buf)(struct file *file, void *fh, struct v4l2_buffer *b);
 
 	int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
 	int (*vidioc_g_fbuf)   (struct file *file, void *fh,