doc-rst: mmap: Add ioctl cross references
There are lots of ioctls mentioned there that aren't cross-referenced. Convert the const to cross references. That makes it visually better, and improves navigation along the document. While here, remove bad whitespaces. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
Родитель
5c591aa13d
Коммит
6970f299db
|
@ -58,8 +58,8 @@ possible with the :ref:`munmap() <func-munmap>` function.
|
||||||
|
|
||||||
struct v4l2_requestbuffers reqbuf;
|
struct v4l2_requestbuffers reqbuf;
|
||||||
struct {
|
struct {
|
||||||
void *start;
|
void *start;
|
||||||
size_t length;
|
size_t length;
|
||||||
} *buffers;
|
} *buffers;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
@ -69,57 +69,57 @@ possible with the :ref:`munmap() <func-munmap>` function.
|
||||||
reqbuf.count = 20;
|
reqbuf.count = 20;
|
||||||
|
|
||||||
if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
|
if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
printf("Video capturing or mmap-streaming is not supported\\n");
|
printf("Video capturing or mmap-streaming is not supported\\n");
|
||||||
else
|
else
|
||||||
perror("VIDIOC_REQBUFS");
|
perror("VIDIOC_REQBUFS");
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want at least five buffers. */
|
/* We want at least five buffers. */
|
||||||
|
|
||||||
if (reqbuf.count < 5) {
|
if (reqbuf.count < 5) {
|
||||||
/* You may need to free the buffers here. */
|
/* You may need to free the buffers here. */
|
||||||
printf("Not enough buffer memory\\n");
|
printf("Not enough buffer memory\\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
||||||
assert(buffers != NULL);
|
assert(buffers != NULL);
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
struct v4l2_buffer buffer;
|
struct v4l2_buffer buffer;
|
||||||
|
|
||||||
memset(&buffer, 0, sizeof(buffer));
|
memset(&buffer, 0, sizeof(buffer));
|
||||||
buffer.type = reqbuf.type;
|
buffer.type = reqbuf.type;
|
||||||
buffer.memory = V4L2_MEMORY_MMAP;
|
buffer.memory = V4L2_MEMORY_MMAP;
|
||||||
buffer.index = i;
|
buffer.index = i;
|
||||||
|
|
||||||
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
|
if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
|
||||||
perror("VIDIOC_QUERYBUF");
|
perror("VIDIOC_QUERYBUF");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers[i].length = buffer.length; /* remember for munmap() */
|
buffers[i].length = buffer.length; /* remember for munmap() */
|
||||||
|
|
||||||
buffers[i].start = mmap(NULL, buffer.length,
|
buffers[i].start = mmap(NULL, buffer.length,
|
||||||
PROT_READ | PROT_WRITE, /* recommended */
|
PROT_READ | PROT_WRITE, /* recommended */
|
||||||
MAP_SHARED, /* recommended */
|
MAP_SHARED, /* recommended */
|
||||||
fd, buffer.m.offset);
|
fd, buffer.m.offset);
|
||||||
|
|
||||||
if (MAP_FAILED == buffers[i].start) {
|
if (MAP_FAILED == buffers[i].start) {
|
||||||
/* If you do not exit here you should unmap() and free()
|
/* If you do not exit here you should unmap() and free()
|
||||||
the buffers mapped so far. */
|
the buffers mapped so far. */
|
||||||
perror("mmap");
|
perror("mmap");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup. */
|
/* Cleanup. */
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++)
|
for (i = 0; i < reqbuf.count; i++)
|
||||||
munmap(buffers[i].start, buffers[i].length);
|
munmap(buffers[i].start, buffers[i].length);
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
@ -130,8 +130,8 @@ possible with the :ref:`munmap() <func-munmap>` function.
|
||||||
#define FMT_NUM_PLANES = 3
|
#define FMT_NUM_PLANES = 3
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void *start[FMT_NUM_PLANES];
|
void *start[FMT_NUM_PLANES];
|
||||||
size_t length[FMT_NUM_PLANES];
|
size_t length[FMT_NUM_PLANES];
|
||||||
} *buffers;
|
} *buffers;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
|
@ -141,66 +141,66 @@ possible with the :ref:`munmap() <func-munmap>` function.
|
||||||
reqbuf.count = 20;
|
reqbuf.count = 20;
|
||||||
|
|
||||||
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
|
||||||
if (errno == EINVAL)
|
if (errno == EINVAL)
|
||||||
printf("Video capturing or mmap-streaming is not supported\\n");
|
printf("Video capturing or mmap-streaming is not supported\\n");
|
||||||
else
|
else
|
||||||
perror("VIDIOC_REQBUFS");
|
perror("VIDIOC_REQBUFS");
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want at least five buffers. */
|
/* We want at least five buffers. */
|
||||||
|
|
||||||
if (reqbuf.count < 5) {
|
if (reqbuf.count < 5) {
|
||||||
/* You may need to free the buffers here. */
|
/* You may need to free the buffers here. */
|
||||||
printf("Not enough buffer memory\\n");
|
printf("Not enough buffer memory\\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
buffers = calloc(reqbuf.count, sizeof(*buffers));
|
||||||
assert(buffers != NULL);
|
assert(buffers != NULL);
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++) {
|
for (i = 0; i < reqbuf.count; i++) {
|
||||||
struct v4l2_buffer buffer;
|
struct v4l2_buffer buffer;
|
||||||
struct v4l2_plane planes[FMT_NUM_PLANES];
|
struct v4l2_plane planes[FMT_NUM_PLANES];
|
||||||
|
|
||||||
memset(&buffer, 0, sizeof(buffer));
|
memset(&buffer, 0, sizeof(buffer));
|
||||||
buffer.type = reqbuf.type;
|
buffer.type = reqbuf.type;
|
||||||
buffer.memory = V4L2_MEMORY_MMAP;
|
buffer.memory = V4L2_MEMORY_MMAP;
|
||||||
buffer.index = i;
|
buffer.index = i;
|
||||||
/* length in struct v4l2_buffer in multi-planar API stores the size
|
/* length in struct v4l2_buffer in multi-planar API stores the size
|
||||||
* of planes array. */
|
* of planes array. */
|
||||||
buffer.length = FMT_NUM_PLANES;
|
buffer.length = FMT_NUM_PLANES;
|
||||||
buffer.m.planes = planes;
|
buffer.m.planes = planes;
|
||||||
|
|
||||||
if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) {
|
if (ioctl(fd, VIDIOC_QUERYBUF, &buffer) < 0) {
|
||||||
perror("VIDIOC_QUERYBUF");
|
perror("VIDIOC_QUERYBUF");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every plane has to be mapped separately */
|
/* Every plane has to be mapped separately */
|
||||||
for (j = 0; j < FMT_NUM_PLANES; j++) {
|
for (j = 0; j < FMT_NUM_PLANES; j++) {
|
||||||
buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
|
buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
|
||||||
|
|
||||||
buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
|
buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
|
||||||
PROT_READ | PROT_WRITE, /* recommended */
|
PROT_READ | PROT_WRITE, /* recommended */
|
||||||
MAP_SHARED, /* recommended */
|
MAP_SHARED, /* recommended */
|
||||||
fd, buffer.m.planes[j].m.offset);
|
fd, buffer.m.planes[j].m.offset);
|
||||||
|
|
||||||
if (MAP_FAILED == buffers[i].start[j]) {
|
if (MAP_FAILED == buffers[i].start[j]) {
|
||||||
/* If you do not exit here you should unmap() and free()
|
/* If you do not exit here you should unmap() and free()
|
||||||
the buffers and planes mapped so far. */
|
the buffers and planes mapped so far. */
|
||||||
perror("mmap");
|
perror("mmap");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cleanup. */
|
/* Cleanup. */
|
||||||
|
|
||||||
for (i = 0; i < reqbuf.count; i++)
|
for (i = 0; i < reqbuf.count; i++)
|
||||||
for (j = 0; j < FMT_NUM_PLANES; j++)
|
for (j = 0; j < FMT_NUM_PLANES; j++)
|
||||||
munmap(buffers[i].start[j], buffers[i].length[j]);
|
munmap(buffers[i].start[j], buffers[i].length[j]);
|
||||||
|
|
||||||
Conceptually streaming drivers maintain two buffer queues, an incoming
|
Conceptually streaming drivers maintain two buffer queues, an incoming
|
||||||
and an outgoing queue. They separate the synchronous capture or output
|
and an outgoing queue. They separate the synchronous capture or output
|
||||||
|
@ -224,37 +224,38 @@ mapped buffers, then to start capturing and enter the read loop. Here
|
||||||
the application waits until a filled buffer can be dequeued, and
|
the application waits until a filled buffer can be dequeued, and
|
||||||
re-enqueues the buffer when the data is no longer needed. Output
|
re-enqueues the buffer when the data is no longer needed. Output
|
||||||
applications fill and enqueue buffers, when enough buffers are stacked
|
applications fill and enqueue buffers, when enough buffers are stacked
|
||||||
up the output is started with ``VIDIOC_STREAMON``. In the write loop,
|
up the output is started with :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`.
|
||||||
when the application runs out of free buffers, it must wait until an
|
In the write loop, when the application runs out of free buffers, it
|
||||||
empty buffer can be dequeued and reused.
|
must wait until an empty buffer can be dequeued and reused.
|
||||||
|
|
||||||
To enqueue and dequeue a buffer applications use the
|
To enqueue and dequeue a buffer applications use the :ref:`VIDIOC_QBUF`
|
||||||
:ref:`VIDIOC_QBUF` and
|
and :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The status of a buffer
|
||||||
:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. The status of a buffer being
|
being mapped, enqueued, full or empty can be determined at any time
|
||||||
mapped, enqueued, full or empty can be determined at any time using the
|
using the :ref:`VIDIOC_QUERYBUF` ioctl. Two methods exist to suspend
|
||||||
:ref:`VIDIOC_QUERYBUF` ioctl. Two methods exist to
|
execution of the application until one or more buffers can be dequeued.
|
||||||
suspend execution of the application until one or more buffers can be
|
By default :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` blocks when no buffer is
|
||||||
dequeued. By default ``VIDIOC_DQBUF`` blocks when no buffer is in the
|
in the outgoing queue. When the ``O_NONBLOCK`` flag was given to the
|
||||||
outgoing queue. When the ``O_NONBLOCK`` flag was given to the
|
:ref:`open() <func-open>` function, :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>`
|
||||||
:ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns
|
returns immediately with an ``EAGAIN`` error code when no buffer is
|
||||||
immediately with an ``EAGAIN`` error code when no buffer is available. The
|
available. The :ref:`select() <func-select>` or :ref:`poll()
|
||||||
:ref:`select() <func-select>` or :ref:`poll() <func-poll>` functions
|
<func-poll>` functions are always available.
|
||||||
are always available.
|
|
||||||
|
|
||||||
To start and stop capturing or output applications call the
|
To start and stop capturing or output applications call the
|
||||||
:ref:`VIDIOC_STREAMON` and
|
:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` and :ref:`VIDIOC_STREAMOFF
|
||||||
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctl. Note
|
<VIDIOC_STREAMON>` ioctl. Note :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>`
|
||||||
``VIDIOC_STREAMOFF`` removes all buffers from both queues as a side
|
removes all buffers from both queues as a side effect. Since there is
|
||||||
effect. Since there is no notion of doing anything "now" on a
|
no notion of doing anything "now" on a multitasking system, if an
|
||||||
multitasking system, if an application needs to synchronize with another
|
application needs to synchronize with another event it should examine
|
||||||
event it should examine the struct :ref:`v4l2_buffer <v4l2-buffer>`
|
the struct ::ref:`v4l2_buffer <v4l2-buffer>` ``timestamp`` of captured
|
||||||
``timestamp`` of captured or outputted buffers.
|
or outputted buffers.
|
||||||
|
|
||||||
Drivers implementing memory mapping I/O must support the
|
Drivers implementing memory mapping I/O must support the
|
||||||
``VIDIOC_REQBUFS``, ``VIDIOC_QUERYBUF``, ``VIDIOC_QBUF``,
|
:ref:`VIDIOC_REQBUFS <VIDIOC_REQBUFS>`, :ref:`VIDIOC_QUERYBUF
|
||||||
``VIDIOC_DQBUF``, ``VIDIOC_STREAMON`` and ``VIDIOC_STREAMOFF`` ioctl,
|
<VIDIOC_QUERYBUF>`, :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, :ref:`VIDIOC_DQBUF
|
||||||
the :ref:`mmap() <func-mmap>`, :ref:`munmap() <func-munmap>`, :ref:`select() <func-select>` and
|
<VIDIOC_QBUF>`, :ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>`
|
||||||
:ref:`poll() <func-poll>` function. [3]_
|
and :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` ioctls, the :ref:`mmap()
|
||||||
|
<func-mmap>`, :ref:`munmap() <func-munmap>`, :ref:`select()
|
||||||
|
<func-select>` and :ref:`poll() <func-poll>` function. [3]_
|
||||||
|
|
||||||
[capture example]
|
[capture example]
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче