<title>Input/Output</title>
<para>The V4L2 API defines several different methods to read from or
write to a device. All drivers exchanging data with applications must
support at least one of them.</para>
<para>The classic I/O method using the <function>read()</function>
and <function>write()</function> function is automatically selected
after opening a V4L2 device. When the driver does not support this
method attempts to read or write will fail at any time.</para>
<para>Other methods must be negotiated. To select the streaming I/O
method with memory mapped or user buffers applications call the
&VIDIOC-REQBUFS; ioctl. The asynchronous I/O method is not defined
yet.</para>
<para>Video overlay can be considered another I/O method, although
the application does not directly receive the image data. It is
selected by initiating video overlay with the &VIDIOC-S-FMT; ioctl.
For more information see <xref linkend="overlay" />.</para>
<para>Generally exactly one I/O method, including overlay, is
associated with each file descriptor. The only exceptions are
applications not exchanging data with a driver ("panel applications",
see <xref linkend="open" />) and drivers permitting simultaneous video capturing
and overlay using the same file descriptor, for compatibility with V4L
and earlier versions of V4L2.</para>
<para><constant>VIDIOC_S_FMT</constant> and
<constant>VIDIOC_REQBUFS</constant> would permit this to some degree,
but for simplicity drivers need not support switching the I/O method
(after first switching away from read/write) other than by closing
and reopening the device.</para>
<para>The following sections describe the various I/O methods in
more detail.</para>
<section id="rw">
<title>Read/Write</title>
<para>Input and output devices support the
<function>read()</function> and <function>write()</function> function,
respectively, when the <constant>V4L2_CAP_READWRITE</constant> flag in
the <structfield>capabilities</structfield> field of &v4l2-capability;
returned by the &VIDIOC-QUERYCAP; ioctl is set.</para>
<para>Drivers may need the CPU to copy the data, but they may also
support DMA to or from user memory, so this I/O method is not
necessarily less efficient than other methods merely exchanging buffer
pointers. It is considered inferior though because no meta-information
like frame counters or timestamps are passed. This information is
necessary to recognize frame dropping and to synchronize with other
data streams. However this is also the simplest I/O method, requiring
little or no setup to exchange data. It permits command line stunts
like this (the <application>vidctrl</application> tool is
fictitious):</para>
<informalexample>
<screen>
> vidctrl /dev/video --input=0 --format=YUYV --size=352x288
> dd if=/dev/video of=myimage.422 bs=202752 count=1
</screen>
</informalexample>
<para>To read from the device applications use the
&func-read; function, to write the &func-write; function.
Drivers must implement one I/O method if they
exchange data with applications, but it need not be this.<footnote>
<para>It would be desirable if applications could depend on
drivers supporting all I/O interfaces, but as much as the complex
memory mapping I/O can be inadequate for some devices we have no
reason to require this interface, which is most useful for simple
applications capturing still images.</para>
</footnote> When reading or writing is supported, the driver
must also support the &func-select; and &func-poll;
function.<footnote>
<para>At the driver level <function>select()</function> and
<function>poll()</function> are the same, and
<function>select()</function> is too important to be optional.</para>
</footnote></para>
</section>
<section id="mmap">
<title>Streaming I/O (Memory Mapping)</title>
<para>Input and output devices support this I/O method when the
<constant>V4L2_CAP_STREAMING</constant> flag in the
<structfield>capabilities</structfield> field of &v4l2-capability;
returned by the &VIDIOC-QUERYCAP; ioctl is set. There are two
streaming methods, to determine if the memory mapping flavor is
supported applications must call the &VIDIOC-REQBUFS; ioctl.</para>
<para>Streaming is an I/O method where only pointers to buffers
are exchanged between application and driver, the data itself is not
copied. Memory mapping is primarily intended to map buffers in device
memory into the application's address space. Device memory can be for
example the video memory on a graphics card with a video capture
add-on. However, being the most efficient I/O method available for a
long time, many other drivers support streaming as well, allocating
buffers in DMA-able main memory.</para>
<para>A driver can support many sets of buffers. Each set is
identified by a unique buffer type value. The sets are independent and
each set can hold a different type of data. To access different sets
at the same time different file descriptors must be used.<footnote>
<para>One could use one file descriptor and set the buffer
type field accordingly when calling &VIDIOC-QBUF; etc., but it makes
the <function>select()</function> function ambiguous. We also like the
clean approach of one file descriptor per logical stream. Video
overlay for example is also a logical stream, although the CPU is not
needed for continuous operation.</para>
</footnote></para>
<para>To allocate device buffers applications call the
&VIDIOC-REQBUFS; ioctl with the desired number of buffers and buffer
type, for example <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>.
This ioctl can also be used to change the number of buffers or to free
the allocated memory, provided none of the buffers are still
mapped.</para>
<para>Before applications can access the buffers they must map
them into their address space with the &func-mmap; function. The
location of the buffers in device memory can be determined with the
&VIDIOC-QUERYBUF; ioctl. In the single-planar API case, the
<structfield>m.offset</structfield> and <structfield>length</structfield>
returned in a &v4l2-buffer; are passed as sixth and second parameter to the
<function>mmap()</function> function. When using the multi-planar API,
struct &v4l2-buffer; contains an array of &v4l2-plane; structures, each
containing its own <structfield>m.offset</structfield> and
<structfield>length</structfield>. When using the multi-planar API, every
plane of every buffer has to be mapped separately, so the number of
calls to &func-mmap; should be equal to number of buffers times number of
planes in each b
|