요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. c:namespace:: V4L
.. _VIDIOC_QBUF:
*******************************
ioctl VIDIOC_QBUF, VIDIOC_DQBUF
*******************************
Name
====
VIDIOC_QBUF - VIDIOC_DQBUF - Exchange a buffer with the driver
Synopsis
========
.. c:macro:: VIDIOC_QBUF
``int ioctl(int fd, VIDIOC_QBUF, struct v4l2_buffer *argp)``
.. c:macro:: VIDIOC_DQBUF
``int ioctl(int fd, VIDIOC_DQBUF, struct v4l2_buffer *argp)``
Arguments
=========
``fd``
File descriptor returned by :c:func:`open()`.
``argp``
Pointer to struct :c:type:`v4l2_buffer`.
Description
===========
Applications call the ``VIDIOC_QBUF`` ioctl to enqueue an empty
(capturing) or filled (output) buffer in the driver's incoming queue.
The semantics depend on the selected I/O method.
To enqueue a buffer applications set the ``type`` field of a struct
:c:type:`v4l2_buffer` to the same buffer type as was
previously used with struct :c:type:`v4l2_format` ``type``
and struct :c:type:`v4l2_requestbuffers` ``type``.
Applications must also set the ``index`` field. Valid index numbers
range from zero to the number of buffers allocated with
:ref:`VIDIOC_REQBUFS` (struct
:c:type:`v4l2_requestbuffers` ``count``) minus
one. The contents of the struct :c:type:`v4l2_buffer` returned
by a :ref:`VIDIOC_QUERYBUF` ioctl will do as well.
When the buffer is intended for output (``type`` is
``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE``,
or ``V4L2_BUF_TYPE_VBI_OUTPUT``) applications must also initialize the
``bytesused``, ``field`` and ``timestamp`` fields, see :ref:`buffer`
for details. Applications must also set ``flags`` to 0. The
``reserved2`` and ``reserved`` fields must be set to 0. When using the
:ref:`multi-planar API <planar-apis>`, the ``m.planes`` field must
contain a userspace pointer to a filled-in array of struct
:c:type:`v4l2_plane` and the ``length`` field must be set
to the number of elements in that array.
To enqueue a :ref:`memory mapped <mmap>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_MMAP``. When ``VIDIOC_QBUF`` is called
with a pointer to this structure the driver sets the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
``EINVAL`` error code.
To enqueue a :ref:`user pointer <userp>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
the address of the buffer and ``length`` to its size. When the
multi-planar API is used, ``m.userptr`` and ``length`` members of the
passed array of struct :c:type:`v4l2_plane` have to be used
instead. When ``VIDIOC_QBUF`` is called with a pointer to this structure
the driver sets the ``V4L2_BUF_FLAG_QUEUED`` flag and clears the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_DONE`` flags in the
``flags`` field, or it returns an error code. This ioctl locks the
memory pages of the buffer in physical memory, they cannot be swapped
out to disk. Buffers remain locked until dequeued, until the
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or
:ref:`VIDIOC_REQBUFS` ioctl is called, or until the
device is closed.
To enqueue a :ref:`DMABUF <dmabuf>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_DMABUF`` and the ``m.fd`` field to a
file descriptor associated with a DMABUF buffer. When the multi-planar
API is used the ``m.fd`` fields of the passed array of struct
:c:type:`v4l2_plane` have to be used instead. When
``VIDIOC_QBUF`` is called with a pointer to this structure the driver
sets the ``V4L2_BUF_FLAG_QUEUED`` flag and clears the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_DONE`` flags in the
``flags`` field, or it returns an error code. This ioctl locks the
buffer. Locking a buffer means passing it to a driver for a hardware
access (usually DMA). If an application accesses (reads/writes) a locked
buffer then the result is undefined. Buffers remain locked until
dequeued, until the :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or
:ref:`VIDIOC_REQBUFS` ioctl is called, or until the
device is closed.
The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to specify
the file descriptor of a :ref:`request <media-request-api>`, if requests are
in use. Setting it means that the buffer will not be passed to the driver
until the request itself is queued. Also, the driver will apply any
settings associated with the request for this buffer. This field will
be ignored unless the ``V4L2_BUF_FLAG_REQUEST_FD`` flag is set.
If the device does not support requests, then ``EBADR`` will be returned.
If requests are supported but an invalid request file descriptor is given,
then ``EINVAL`` will be returned.
.. caution::
It is not allowed to mix queuing requests with queuing buffers directly.
``EBUSY`` will be returned if the first buffer was queued directly and
then the application tries to queue a request, or vice versa. After
closing the file descriptor, calling
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or calling :ref:`VIDIOC_REQBUFS`
the check for this will be reset.
For :ref:`memory-to-memory devices <mem2mem>` you can specify the
``request_fd`` only for output buffers, not for capture buffers. Attempting
to specify this for a capture buffer will result in an ``EBADR`` error.
Applications call the ``VIDIOC_DQBUF`` ioctl to dequeue a filled
(capturing) or displayed (output) buffer from the driver's outgoing
queue. They just set the ``type``, ``memory`` and ``reserved`` fields of
a struct :c:type:`v4l2_buffer` as above, when
``VIDIOC_DQBUF`` is called with a pointer to this structure the driver
fills all remaining fields or returns an error code. The driver may also
set ``V4L2_BUF_FLAG_ERROR`` in the ``flags`` field. It indicates a
non-critical (recoverable) streaming error. In such case the application
may continue as normal, but should be aware that data in the dequeued
buffer might be corrupted. When using the multi-planar API, the planes
array must be passed in as well.
If the application sets the ``memory`` field to ``V4L2_MEMORY_DMABUF`` to
dequeue a :ref:`DMABUF <dmabuf>` buffer, the driver fills the ``m.fd`` field
with a file descriptor numerically the same as the one given to ``VIDIOC_QBUF``
when the buffer was enqueued. No new file descriptor is created at dequeue time
and the value is only for the application convenience. When the multi-planar
API is used the ``m.fd`` fields of the passed array of struct
:c:type:`v4l2_plane` are filled instead.
By default ``VIDIOC_DQBUF`` blocks when no buffer is in the outgoing
queue. When the ``O_NONBLOCK`` flag was given to the
:c:func:`open()` function, ``VIDIOC_DQBUF`` returns
immediately with an ``EAGAIN`` error code when no buffer is available.
The struct :c:type:`v4l2_buffer` structure is specified in
:ref:`buffer`.
Return Value
============
On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter.
EAGAIN
Non-blocking I/O has been selected using ``O_NONBLOCK`` and no
buffer was in the outgoing queue.
EINVAL
The buffer ``type`` is not supported, or the ``index`` is out of
bounds, or no buffers have been allocated yet, or the ``userptr`` or
``length`` are invalid, or the ``V4L2_BUF_FLAG_REQUEST_FD`` flag was
set but the given ``request_fd`` was invalid, or ``m.fd`` was
an invalid DMABUF file descriptor.
EIO
``VIDIOC_DQBUF`` failed due to an internal error. Can also indicate
temporary problems like signal loss.
.. note::
The driver might dequeue an (empty) buffer despite returning
an error, or even stop capturing. Reusing such buffer may be unsafe
though and its details (e.g. ``index``) may not be returned either.
It is recommended that drivers indicate recoverable errors by setting
the ``V4L2_BUF_FLAG_ERROR`` and returning 0 instead. In that case the
application should be able to safely reuse the buffer and continue
streaming.
EPIPE
``VIDIOC_DQBUF`` returns this on an empty capture queue for mem2mem
codecs if a buffer with the ``V4L2_BUF_FLAG_LAST`` was already
dequeued and no new buffers are expected to become available.
EBADR
The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was set but the device does not
support requests for the given buffer type, or
the ``V4L2_BUF_FLAG_REQUEST_FD`` flag was not set but the device requires
that the buffer is part of a request.
EBUSY
The first buffer was queued via a request, but the application now tries
to queue it directly, or vice versa (it is not permitted to mix the two
APIs).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
목적, 호출 형식과 인자
1-34`VIDIOC_QBUF`는 capture용 빈 buffer 또는 output용으로 채운 buffer를 드라이버의 incoming queue에 넣고, `VIDIOC_DQBUF`는 처리된 capture/output buffer를 outgoing queue에서 꺼냅니다. 둘 다 `struct v4l2_buffer *argp`를 사용합니다.
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
.. c:namespace:: V4L
.. _VIDIOC_QBUF:
*******************************
ioctl VIDIOC_QBUF, VIDIOC_DQBUF
*******************************
Name
====
VIDIOC_QBUF - VIDIOC_DQBUF - Exchange a buffer with the driver
Synopsis
========
.. c:macro:: VIDIOC_QBUF
``int ioctl(int fd, VIDIOC_QBUF, struct v4l2_buffer *argp)``
.. c:macro:: VIDIOC_DQBUF
``int ioctl(int fd, VIDIOC_DQBUF, struct v4l2_buffer *argp)``
Arguments
=========
``fd``
File descriptor returned by :c:func:`open()`.
``argp``
Pointer to struct :c:type:`v4l2_buffer`.
공통 enqueue 필드
35-62`type`은 이전에 `v4l2_format.type`과 `v4l2_requestbuffers.type`에 사용한 buffer type과 같아야 합니다. `index`는 0부터 `VIDIOC_REQBUFS`가 할당한 `count - 1`까지이며, `VIDIOC_QUERYBUF` 결과 구조체를 그대로 바탕으로 사용할 수 있습니다.
모든 memory 방식에 공통으로 준비할 필드입니다.
Output type인 `V4L2_BUF_TYPE_VIDEO_OUTPUT`, `V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE`, `V4L2_BUF_TYPE_VBI_OUTPUT`에서는 `bytesused`, `field`, `timestamp`도 초기화해야 합니다.
Description
===========
Applications call the ``VIDIOC_QBUF`` ioctl to enqueue an empty
(capturing) or filled (output) buffer in the driver's incoming queue.
The semantics depend on the selected I/O method.
To enqueue a buffer applications set the ``type`` field of a struct
:c:type:`v4l2_buffer` to the same buffer type as was
previously used with struct :c:type:`v4l2_format` ``type``
and struct :c:type:`v4l2_requestbuffers` ``type``.
Applications must also set the ``index`` field. Valid index numbers
range from zero to the number of buffers allocated with
:ref:`VIDIOC_REQBUFS` (struct
:c:type:`v4l2_requestbuffers` ``count``) minus
one. The contents of the struct :c:type:`v4l2_buffer` returned
by a :ref:`VIDIOC_QUERYBUF` ioctl will do as well.
When the buffer is intended for output (``type`` is
``V4L2_BUF_TYPE_VIDEO_OUTPUT``, ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE``,
or ``V4L2_BUF_TYPE_VBI_OUTPUT``) applications must also initialize the
``bytesused``, ``field`` and ``timestamp`` fields, see :ref:`buffer`
for details. Applications must also set ``flags`` to 0. The
``reserved2`` and ``reserved`` fields must be set to 0. When using the
:ref:`multi-planar API <planar-apis>`, the ``m.planes`` field must
contain a userspace pointer to a filled-in array of struct
:c:type:`v4l2_plane` and the ``length`` field must be set
to the number of elements in that array.
Memory-mapped buffer 큐잉
63-69MMAP buffer는 `memory = V4L2_MEMORY_MMAP`으로 지정합니다. 성공하면 드라이버가 `V4L2_BUF_FLAG_MAPPED`와 `V4L2_BUF_FLAG_QUEUED`를 설정하고 `V4L2_BUF_FLAG_DONE`을 지웁니다. 입력이 유효하지 않으면 `EINVAL`입니다.
To enqueue a :ref:`memory mapped <mmap>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_MMAP``. When ``VIDIOC_QBUF`` is called
with a pointer to this structure the driver sets the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_QUEUED`` flags and clears
the ``V4L2_BUF_FLAG_DONE`` flag in the ``flags`` field, or it returns an
``EINVAL`` error code.
User pointer buffer 큐잉
70-84USERPTR 방식은 `memory = V4L2_MEMORY_USERPTR`, `m.userptr = buffer 주소`, `length = buffer 크기`로 설정합니다. Multi-planar API에서는 각 `v4l2_plane`의 `m.userptr`와 `length`를 사용합니다.
성공 시 `QUEUED`를 설정하고 `MAPPED`와 `DONE`을 지웁니다. 호출은 buffer의 memory page를 물리 메모리에 고정해 swap-out을 막습니다.
Page lock은 buffer가 dequeue되거나 `VIDIOC_STREAMOFF`·`VIDIOC_REQBUFS`를 호출하거나 장치를 닫을 때까지 유지됩니다.
To enqueue a :ref:`user pointer <userp>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_USERPTR``, the ``m.userptr`` field to
the address of the buffer and ``length`` to its size. When the
multi-planar API is used, ``m.userptr`` and ``length`` members of the
passed array of struct :c:type:`v4l2_plane` have to be used
instead. When ``VIDIOC_QBUF`` is called with a pointer to this structure
the driver sets the ``V4L2_BUF_FLAG_QUEUED`` flag and clears the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_DONE`` flags in the
``flags`` field, or it returns an error code. This ioctl locks the
memory pages of the buffer in physical memory, they cannot be swapped
out to disk. Buffers remain locked until dequeued, until the
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or
:ref:`VIDIOC_REQBUFS` ioctl is called, or until the
device is closed.
DMABUF 큐잉과 잠금
85-100DMABUF 방식은 `memory = V4L2_MEMORY_DMABUF`과 해당 DMABUF의 file descriptor인 `m.fd`를 설정합니다. Multi-planar API에서는 각 plane의 `m.fd`를 사용합니다.
성공 시 `QUEUED`를 설정하고 `MAPPED`와 `DONE`을 지웁니다. 잠금은 보통 DMA인 하드웨어 접근을 위해 buffer를 드라이버에 넘긴다는 뜻이며, 잠긴 buffer를 애플리케이션이 읽거나 쓰면 결과가 정의되지 않습니다.
DMABUF lock도 dequeue, `STREAMOFF`, `REQBUFS`, 장치 close 중 하나가 일어날 때까지 유지됩니다.
To enqueue a :ref:`DMABUF <dmabuf>` buffer applications set the
``memory`` field to ``V4L2_MEMORY_DMABUF`` and the ``m.fd`` field to a
file descriptor associated with a DMABUF buffer. When the multi-planar
API is used the ``m.fd`` fields of the passed array of struct
:c:type:`v4l2_plane` have to be used instead. When
``VIDIOC_QBUF`` is called with a pointer to this structure the driver
sets the ``V4L2_BUF_FLAG_QUEUED`` flag and clears the
``V4L2_BUF_FLAG_MAPPED`` and ``V4L2_BUF_FLAG_DONE`` flags in the
``flags`` field, or it returns an error code. This ioctl locks the
buffer. Locking a buffer means passing it to a driver for a hardware
access (usually DMA). If an application accesses (reads/writes) a locked
buffer then the result is undefined. Buffers remain locked until
dequeued, until the :ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or
:ref:`VIDIOC_REQBUFS` ioctl is called, or until the
device is closed.
Media request와 큐잉 규칙
101-122Request API를 사용할 때 `request_fd`에 request file descriptor를 넣고 `V4L2_BUF_FLAG_REQUEST_FD`를 설정할 수 있습니다. Buffer는 request 자체가 queue될 때까지 드라이버로 전달되지 않으며, request에 연결된 설정이 이 buffer에 적용됩니다.
`REQUEST_FD` flag가 없으면 `request_fd`는 무시됩니다. 장치가 request를 지원하지 않으면 `EBADR`, 지원하지만 descriptor가 잘못되면 `EINVAL`입니다.
직접 큐잉과 request 큐잉은 한 streaming 세션에서 섞을 수 없습니다.
The ``request_fd`` field can be used with the ``VIDIOC_QBUF`` ioctl to specify
the file descriptor of a :ref:`request <media-request-api>`, if requests are
in use. Setting it means that the buffer will not be passed to the driver
until the request itself is queued. Also, the driver will apply any
settings associated with the request for this buffer. This field will
be ignored unless the ``V4L2_BUF_FLAG_REQUEST_FD`` flag is set.
If the device does not support requests, then ``EBADR`` will be returned.
If requests are supported but an invalid request file descriptor is given,
then ``EINVAL`` will be returned.
.. caution::
It is not allowed to mix queuing requests with queuing buffers directly.
``EBUSY`` will be returned if the first buffer was queued directly and
then the application tries to queue a request, or vice versa. After
closing the file descriptor, calling
:ref:`VIDIOC_STREAMOFF <VIDIOC_STREAMON>` or calling :ref:`VIDIOC_REQBUFS`
the check for this will be reset.
For :ref:`memory-to-memory devices <mem2mem>` you can specify the
``request_fd`` only for output buffers, not for capture buffers. Attempting
to specify this for a capture buffer will result in an ``EBADR`` error.
Buffer dequeue와 오류 표시
123-150DQBUF 호출자는 `type`, `memory`, `reserved`를 준비하고, multi-planar API라면 plane 배열도 전달합니다. 드라이버는 나머지 필드를 채워 outgoing queue의 처리된 buffer를 반환합니다.
드라이버가 `V4L2_BUF_FLAG_ERROR`를 설정하면 복구 가능한 비치명적 streaming 오류입니다. 애플리케이션은 계속 진행할 수 있지만 dequeued buffer의 데이터가 손상됐을 수 있음을 고려해야 합니다.
DMABUF를 dequeue하면 `m.fd`에는 QBUF 때 전달한 것과 숫자가 같은 descriptor가 기록됩니다. 새 descriptor를 만들지 않으며 편의를 위한 값입니다. Multi-planar에서는 각 plane의 `m.fd`가 채워집니다.
기본적으로 outgoing queue가 비면 DQBUF가 block합니다. 장치를 `O_NONBLOCK`으로 열었다면 즉시 `EAGAIN`을 반환합니다. 구조체 필드 정의는 `buffer` 절을 따릅니다.
Applications call the ``VIDIOC_DQBUF`` ioctl to dequeue a filled
(capturing) or displayed (output) buffer from the driver's outgoing
queue. They just set the ``type``, ``memory`` and ``reserved`` fields of
a struct :c:type:`v4l2_buffer` as above, when
``VIDIOC_DQBUF`` is called with a pointer to this structure the driver
fills all remaining fields or returns an error code. The driver may also
set ``V4L2_BUF_FLAG_ERROR`` in the ``flags`` field. It indicates a
non-critical (recoverable) streaming error. In such case the application
may continue as normal, but should be aware that data in the dequeued
buffer might be corrupted. When using the multi-planar API, the planes
array must be passed in as well.
If the application sets the ``memory`` field to ``V4L2_MEMORY_DMABUF`` to
dequeue a :ref:`DMABUF <dmabuf>` buffer, the driver fills the ``m.fd`` field
with a file descriptor numerically the same as the one given to ``VIDIOC_QBUF``
when the buffer was enqueued. No new file descriptor is created at dequeue time
and the value is only for the application convenience. When the multi-planar
API is used the ``m.fd`` fields of the passed array of struct
:c:type:`v4l2_plane` are filled instead.
By default ``VIDIOC_DQBUF`` blocks when no buffer is in the outgoing
queue. When the ``O_NONBLOCK`` flag was given to the
:c:func:`open()` function, ``VIDIOC_DQBUF`` returns
immediately with an ``EAGAIN`` error code when no buffer is available.
The struct :c:type:`v4l2_buffer` structure is specified in
:ref:`buffer`.
반환값과 오류
151-197성공하면 0, 오류이면 -1을 반환하고 `errno`를 설정합니다.
큐 상태, buffer 설명자, request 방식에 따른 전용 오류입니다.
`EIO`를 반환하면서 드라이버가 빈 buffer를 dequeue하거나 capture를 중지할 수도 있어 그 buffer를 재사용하는 것은 안전하지 않을 수 있고 `index` 같은 세부 정보도 없을 수 있습니다.
복구 가능한 오류는 드라이버가 `V4L2_BUF_FLAG_ERROR`를 설정하고 0을 반환하는 방식이 권장됩니다. 이 경우 애플리케이션은 buffer를 안전하게 재사용하고 streaming을 계속할 수 있어야 합니다.
Return Value
============
On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter.
EAGAIN
Non-blocking I/O has been selected using ``O_NONBLOCK`` and no
buffer was in the outgoing queue.
EINVAL
The buffer ``type`` is not supported, or the ``index`` is out of
bounds, or no buffers have been allocated yet, or the ``userptr`` or
``length`` are invalid, or the ``V4L2_BUF_FLAG_REQUEST_FD`` flag was
set but the given ``request_fd`` was invalid, or ``m.fd`` was
an invalid DMABUF file descriptor.
EIO
``VIDIOC_DQBUF`` failed due to an internal error. Can also indicate
temporary problems like signal loss.
.. note::
The driver might dequeue an (empty) buffer despite returning
an error, or even stop capturing. Reusing such buffer may be unsafe
though and its details (e.g. ``index``) may not be returned either.
It is recommended that drivers indicate recoverable errors by setting
the ``V4L2_BUF_FLAG_ERROR`` and returning 0 instead. In that case the
application should be able to safely reuse the buffer and continue
streaming.
EPIPE
``VIDIOC_DQBUF`` returns this on an empty capture queue for mem2mem
codecs if a buffer with the ``V4L2_BUF_FLAG_LAST`` was already
dequeued and no new buffers are expected to become available.
EBADR
The ``V4L2_BUF_FLAG_REQUEST_FD`` flag was set but the device does not
support requests for the given buffer type, or
the ``V4L2_BUF_FLAG_REQUEST_FD`` flag was not set but the device requires
that the buffer is part of a request.
EBUSY
The first buffer was queued via a request, but the application now tries
to queue it directly, or vice versa (it is not permitted to mix the two
APIs).
요약·해설
vidioc-qbuf.rst:1-197Memory 방식별 필드와 소유권 전환을 지키고 직접 큐잉과 request 큐잉을 섞지 않는 것이 핵심입니다.