요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
.. _encoder:
*************************************************
Memory-to-Memory Stateful Video Encoder Interface
*************************************************
A stateful video encoder takes raw video frames in display order and encodes
them into a bytestream. It generates complete chunks of the bytestream, including
all metadata, headers, etc. The resulting bytestream does not require any
further post-processing by the client.
Performing software stream processing, header generation etc. in the driver
in order to support this interface is strongly discouraged. In case such
operations are needed, use of the Stateless Video Encoder Interface (in
development) is strongly advised.
Conventions and Notations Used in This Document
===============================================
1. The general V4L2 API rules apply if not specified in this document
otherwise.
2. The meaning of words "must", "may", "should", etc. is as per `RFC
2119 <https://tools.ietf.org/html/rfc2119>`_.
3. All steps not marked "optional" are required.
4. :c:func:`VIDIOC_G_EXT_CTRLS` and :c:func:`VIDIOC_S_EXT_CTRLS` may be used
interchangeably with :c:func:`VIDIOC_G_CTRL` and :c:func:`VIDIOC_S_CTRL`,
unless specified otherwise.
5. Single-planar API (see :ref:`planar-apis`) and applicable structures may be
used interchangeably with multi-planar API, unless specified otherwise,
depending on encoder capabilities and following the general V4L2 guidelines.
6. i = [a..b]: sequence of integers from a to b, inclusive, i.e. i =
[0..2]: i = 0, 1, 2.
7. Given an ``OUTPUT`` buffer A, then A' represents a buffer on the ``CAPTURE``
queue containing data that resulted from processing buffer A.
Glossary
========
Refer to :ref:`decoder-glossary`.
State Machine
=============
.. kernel-render:: DOT
:alt: DOT digraph of encoder state machine
:caption: Encoder State Machine
digraph encoder_state_machine {
node [shape = doublecircle, label="Encoding"] Encoding;
node [shape = circle, label="Initialization"] Initialization;
node [shape = circle, label="Stopped"] Stopped;
node [shape = circle, label="Drain"] Drain;
node [shape = circle, label="Reset"] Reset;
node [shape = point]; qi
qi -> Initialization [ label = "open()" ];
Initialization -> Encoding [ label = "Both queues streaming" ];
Encoding -> Drain [ label = "V4L2_ENC_CMD_STOP" ];
Encoding -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
Encoding -> Stopped [ label = "VIDIOC_STREAMOFF(OUTPUT)" ];
Encoding -> Encoding;
Drain -> Stopped [ label = "All CAPTURE\nbuffers dequeued\nor\nVIDIOC_STREAMOFF(OUTPUT)" ];
Drain -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
Reset -> Encoding [ label = "VIDIOC_STREAMON(CAPTURE)" ];
Reset -> Initialization [ label = "VIDIOC_REQBUFS(OUTPUT, 0)" ];
Stopped -> Encoding [ label = "V4L2_ENC_CMD_START\nor\nVIDIOC_STREAMON(OUTPUT)" ];
Stopped -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
}
Querying Capabilities
=====================
1. To enumerate the set of coded formats supported by the encoder, the
client may call :c:func:`VIDIOC_ENUM_FMT` on ``CAPTURE``.
* The full set of supported formats will be returned, regardless of the
format set on ``OUTPUT``.
2. To enumerate the set of supported raw formats, the client may call
:c:func:`VIDIOC_ENUM_FMT` on ``OUTPUT``.
* Only the formats supported for the format currently active on ``CAPTURE``
will be returned.
* In order to enumerate raw formats supported by a given coded format,
the client must first set that coded format on ``CAPTURE`` and then
enumerate the formats on ``OUTPUT``.
3. The client may use :c:func:`VIDIOC_ENUM_FRAMESIZES` to detect supported
resolutions for a given format, passing the desired pixel format in
:c:type:`v4l2_frmsizeenum` ``pixel_format``.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMESIZES` for a coded pixel
format will include all possible coded resolutions supported by the
encoder for the given coded pixel format.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMESIZES` for a raw pixel format
will include all possible frame buffer resolutions supported by the
encoder for the given raw pixel format and coded format currently set on
``CAPTURE``.
4. The client may use :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` to detect supported
frame intervals for a given format and resolution, passing the desired pixel
format in :c:type:`v4l2_frmivalenum` ``pixel_format`` and the resolution
in :c:type:`v4l2_frmivalenum` ``width`` and :c:type:`v4l2_frmivalenum`
``height``.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` for a coded pixel
format and coded resolution will include all possible frame intervals
supported by the encoder for the given coded pixel format and resolution.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` for a raw pixel
format and resolution will include all possible frame intervals supported
by the encoder for the given raw pixel format and resolution and for the
coded format, coded resolution and coded frame interval currently set on
``CAPTURE``.
* Support for :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` is optional. If it is
not implemented, then there are no special restrictions other than the
limits of the codec itself.
5. Supported profiles and levels for the coded format currently set on
``CAPTURE``, if applicable, may be queried using their respective controls
via :c:func:`VIDIOC_QUERYCTRL`.
6. Any additional encoder capabilities may be discovered by querying
their respective controls.
Initialization
==============
1. Set the coded format on the ``CAPTURE`` queue via :c:func:`VIDIOC_S_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
``pixelformat``
the coded format to be produced.
``sizeimage``
desired size of ``CAPTURE`` buffers; the encoder may adjust it to
match hardware requirements.
``width``, ``height``
ignored (read-only).
other fields
follow standard semantics.
* **Returned fields:**
``sizeimage``
adjusted size of ``CAPTURE`` buffers.
``width``, ``height``
the coded size selected by the encoder based on current state, e.g.
``OUTPUT`` format, selection rectangles, etc. (read-only).
.. important::
Changing the ``CAPTURE`` format may change the currently set ``OUTPUT``
format. How the new ``OUTPUT`` format is determined is up to the encoder
and the client must ensure it matches its needs afterwards.
2. **Optional.** Enumerate supported ``OUTPUT`` formats (raw formats for
source) for the selected coded format via :c:func:`VIDIOC_ENUM_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
other fields
follow standard semantics.
* **Returned fields:**
``pixelformat``
raw format supported for the coded format currently selected on
the ``CAPTURE`` queue.
other fields
follow standard semantics.
3. Set the raw source format on the ``OUTPUT`` queue via
:c:func:`VIDIOC_S_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``pixelformat``
raw format of the source.
``width``, ``height``
source resolution.
other fields
follow standard semantics.
* **Returned fields:**
``width``, ``height``
may be adjusted to match encoder minimums, maximums and alignment
requirements, as required by the currently selected formats, as
reported by :c:func:`VIDIOC_ENUM_FRAMESIZES`.
other fields
follow standard semantics.
* Setting the ``OUTPUT`` format will reset the selection rectangles to their
default values, based on the new resolution, as described in the next
step.
4. Set the raw frame interval on the ``OUTPUT`` queue via
:c:func:`VIDIOC_S_PARM`. This also sets the coded frame interval on the
``CAPTURE`` queue to the same value.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``parm.output``
set all fields except ``parm.output.timeperframe`` to 0.
``parm.output.timeperframe``
the desired frame interval; the encoder may adjust it to
match hardware requirements.
* **Returned fields:**
``parm.output.timeperframe``
the adjusted frame interval.
.. important::
Changing the ``OUTPUT`` frame interval *also* sets the framerate that
the encoder uses to encode the video. So setting the frame interval
to 1/24 (or 24 frames per second) will produce a coded video stream
that can be played back at that speed. The frame interval for the
``OUTPUT`` queue is just a hint, the application may provide raw
frames at a different rate. It can be used by the driver to help
schedule multiple encoders running in parallel.
In the next step the ``CAPTURE`` frame interval can optionally be
changed to a different value. This is useful for off-line encoding
were the coded frame interval can be different from the rate at
which raw frames are supplied.
.. important::
``timeperframe`` deals with *frames*, not fields. So for interlaced
formats this is the time per two fields, since a frame consists of
a top and a bottom field.
.. note::
It is due to historical reasons that changing the ``OUTPUT`` frame
interval also changes the coded frame interval on the ``CAPTURE``
queue. Ideally these would be independent settings, but that would
break the existing API.
5. **Optional** Set the coded frame interval on the ``CAPTURE`` queue via
:c:func:`VIDIOC_S_PARM`. This is only necessary if the coded frame
interval is different from the raw frame interval, which is typically
the case for off-line encoding. Support for this feature is signalled
by the :ref:`V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL <fmtdesc-flags>` format flag.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
``parm.capture``
set all fields except ``parm.capture.timeperframe`` to 0.
``parm.capture.timeperframe``
the desired coded frame interval; the encoder may adjust it to
match hardware requirements.
* **Returned fields:**
``parm.capture.timeperframe``
the adjusted frame interval.
.. important::
Changing the ``CAPTURE`` frame interval sets the framerate for the
coded video. It does *not* set the rate at which buffers arrive on the
``CAPTURE`` queue, that depends on how fast the encoder is and how
fast raw frames are queued on the ``OUTPUT`` queue.
.. important::
``timeperframe`` deals with *frames*, not fields. So for interlaced
formats this is the time per two fields, since a frame consists of
a top and a bottom field.
.. note::
Not all drivers support this functionality, in that case just set
the desired coded frame interval for the ``OUTPUT`` queue.
However, drivers that can schedule multiple encoders based on the
``OUTPUT`` frame interval must support this optional feature.
6. **Optional.** Set the visible resolution for the stream metadata via
:c:func:`VIDIOC_S_SELECTION` on the ``OUTPUT`` queue if it is desired
to be different than the full OUTPUT resolution.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``target``
set to ``V4L2_SEL_TGT_CROP``.
``r.left``, ``r.top``, ``r.width``, ``r.height``
visible rectangle; this must fit within the `V4L2_SEL_TGT_CROP_BOUNDS`
rectangle and may be subject to adjustment to match codec and
hardware constraints.
* **Returned fields:**
``r.left``, ``r.top``, ``r.width``, ``r.height``
visible rectangle adjusted by the encoder.
* The following selection targets are supported on ``OUTPUT``:
``V4L2_SEL_TGT_CROP_BOUNDS``
equal to the full source frame, matching the active ``OUTPUT``
format.
``V4L2_SEL_TGT_CROP_DEFAULT``
equal to ``V4L2_SEL_TGT_CROP_BOUNDS``.
``V4L2_SEL_TGT_CROP``
rectangle within the source buffer to be encoded into the
``CAPTURE`` stream; defaults to ``V4L2_SEL_TGT_CROP_DEFAULT``.
.. note::
A common use case for this selection target is encoding a source
video with a resolution that is not a multiple of a macroblock,
e.g. the common 1920x1080 resolution may require the source
buffers to be aligned to 1920x1088 for codecs with 16x16 macroblock
size. To avoid encoding the padding, the client needs to explicitly
configure this selection target to 1920x1080.
.. warning::
The encoder may adjust the crop/compose rectangles to the nearest
supported ones to meet codec and hardware requirements. The client needs
to check the adjusted rectangle returned by :c:func:`VIDIOC_S_SELECTION`.
7. Allocate buffers for both ``OUTPUT`` and ``CAPTURE`` via
:c:func:`VIDIOC_REQBUFS`. This may be performed in any order.
* **Required fields:**
``count``
requested number of buffers to allocate; greater than zero.
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT`` or
``CAPTURE``.
other fields
follow standard semantics.
* **Returned fields:**
``count``
actual number of buffers allocated.
.. warning::
The actual number of allocated buffers may differ from the ``count``
given. The client must check the updated value of ``count`` after the
call returns.
.. note::
To allocate more than the minimum number of OUTPUT buffers (for pipeline
depth), the client may query the ``V4L2_CID_MIN_BUFFERS_FOR_OUTPUT``
control to get the minimum number of buffers required, and pass the
obtained value plus the number of additional buffers needed in the
``count`` field to :c:func:`VIDIOC_REQBUFS`.
Alternatively, :c:func:`VIDIOC_CREATE_BUFS` can be used to have more
control over buffer allocation.
* **Required fields:**
``count``
requested number of buffers to allocate; greater than zero.
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
other fields
follow standard semantics.
* **Returned fields:**
``count``
adjusted to the number of allocated buffers.
8. Begin streaming on both ``OUTPUT`` and ``CAPTURE`` queues via
:c:func:`VIDIOC_STREAMON`. This may be performed in any order. The actual
encoding process starts when both queues start streaming.
.. note::
If the client stops the ``CAPTURE`` queue during the encode process and then
restarts it again, the encoder will begin generating a stream independent
from the stream generated before the stop. The exact constraints depend
on the coded format, but may include the following implications:
* encoded frames produced after the restart must not reference any
frames produced before the stop, e.g. no long term references for
H.264/HEVC,
* any headers that must be included in a standalone stream must be
produced again, e.g. SPS and PPS for H.264/HEVC.
Encoding
========
This state is reached after the `Initialization` sequence finishes
successfully. In this state, the client queues and dequeues buffers to both
queues via :c:func:`VIDIOC_QBUF` and :c:func:`VIDIOC_DQBUF`, following the
standard semantics.
The content of encoded ``CAPTURE`` buffers depends on the active coded pixel
format and may be affected by codec-specific extended controls, as stated
in the documentation of each format.
Both queues operate independently, following standard behavior of V4L2 buffer
queues and memory-to-memory devices. In addition, the order of encoded frames
dequeued from the ``CAPTURE`` queue may differ from the order of queuing raw
frames to the ``OUTPUT`` queue, due to properties of the selected coded format,
e.g. frame reordering.
The client must not assume any direct relationship between ``CAPTURE`` and
``OUTPUT`` buffers and any specific timing of buffers becoming
available to dequeue. Specifically:
* a buffer queued to ``OUTPUT`` may result in more than one buffer produced on
``CAPTURE`` (for example, if returning an encoded frame allowed the encoder
to return a frame that preceded it in display, but succeeded it in the decode
order; however, there may be other reasons for this as well),
* a buffer queued to ``OUTPUT`` may result in a buffer being produced on
``CAPTURE`` later into encode process, and/or after processing further
``OUTPUT`` buffers, or be returned out of order, e.g. if display
reordering is used,
* buffers may become available on the ``CAPTURE`` queue without additional
buffers queued to ``OUTPUT`` (e.g. during drain or ``EOS``), because of the
``OUTPUT`` buffers queued in the past whose encoding results are only
available at later time, due to specifics of the encoding process,
* buffers queued to ``OUTPUT`` may not become available to dequeue instantly
after being encoded into a corresponding ``CAPTURE`` buffer, e.g. if the
encoder needs to use the frame as a reference for encoding further frames.
.. note::
To allow matching encoded ``CAPTURE`` buffers with ``OUTPUT`` buffers they
originated from, the client can set the ``timestamp`` field of the
:c:type:`v4l2_buffer` struct when queuing an ``OUTPUT`` buffer. The
``CAPTURE`` buffer(s), which resulted from encoding that ``OUTPUT`` buffer
will have their ``timestamp`` field set to the same value when dequeued.
In addition to the straightforward case of one ``OUTPUT`` buffer producing
one ``CAPTURE`` buffer, the following cases are defined:
* one ``OUTPUT`` buffer generates multiple ``CAPTURE`` buffers: the same
``OUTPUT`` timestamp will be copied to multiple ``CAPTURE`` buffers,
* the encoding order differs from the presentation order (i.e. the
``CAPTURE`` buffers are out-of-order compared to the ``OUTPUT`` buffers):
``CAPTURE`` timestamps will not retain the order of ``OUTPUT`` timestamps.
.. note::
To let the client distinguish between frame types (keyframes, intermediate
frames; the exact list of types depends on the coded format), the
``CAPTURE`` buffers will have corresponding flag bits set in their
:c:type:`v4l2_buffer` struct when dequeued. See the documentation of
:c:type:`v4l2_buffer` and each coded pixel format for exact list of flags
and their meanings.
Should an encoding error occur, it will be reported to the client with the level
of details depending on the encoder capabilities. Specifically:
* the ``CAPTURE`` buffer (if any) that contains the results of the failed encode
operation will be returned with the ``V4L2_BUF_FLAG_ERROR`` flag set,
* if the encoder is able to precisely report the ``OUTPUT`` buffer(s) that triggered
the error, such buffer(s) will be returned with the ``V4L2_BUF_FLAG_ERROR`` flag
set.
.. note::
If a ``CAPTURE`` buffer is too small then it is just returned with the
``V4L2_BUF_FLAG_ERROR`` flag set. More work is needed to detect that this
error occurred because the buffer was too small, and to provide support to
free existing buffers that were too small.
In case of a fatal failure that does not allow the encoding to continue, any
further operations on corresponding encoder file handle will return the -EIO
error code. The client may close the file handle and open a new one, or
alternatively reinitialize the instance by stopping streaming on both queues,
releasing all buffers and performing the Initialization sequence again.
Encoding Parameter Changes
==========================
The client is allowed to use :c:func:`VIDIOC_S_CTRL` to change encoder
parameters at any time. The availability of parameters is encoder-specific
and the client must query the encoder to find the set of available controls.
The ability to change each parameter during encoding is encoder-specific, as
per the standard semantics of the V4L2 control interface. The client may
attempt to set a control during encoding and if the operation fails with the
-EBUSY error code, the ``CAPTURE`` queue needs to be stopped for the
configuration change to be allowed. To do this, it may follow the `Drain`
sequence to avoid losing the already queued/encoded frames.
The timing of parameter updates is encoder-specific, as per the standard
semantics of the V4L2 control interface. If the client needs to apply the
parameters exactly at specific frame, using the Request API
(:ref:`media-request-api`) should be considered, if supported by the encoder.
Drain
=====
To ensure that all the queued ``OUTPUT`` buffers have been processed and the
related ``CAPTURE`` buffers are given to the client, the client must follow the
drain sequence described below. After the drain sequence ends, the client has
received all encoded frames for all ``OUTPUT`` buffers queued before the
sequence was started.
1. Begin the drain sequence by issuing :c:func:`VIDIOC_ENCODER_CMD`.
* **Required fields:**
``cmd``
set to ``V4L2_ENC_CMD_STOP``.
``flags``
set to 0.
``pts``
set to 0.
.. warning::
The sequence can be only initiated if both ``OUTPUT`` and ``CAPTURE``
queues are streaming. For compatibility reasons, the call to
:c:func:`VIDIOC_ENCODER_CMD` will not fail even if any of the queues is
not streaming, but at the same time it will not initiate the `Drain`
sequence and so the steps described below would not be applicable.
2. Any ``OUTPUT`` buffers queued by the client before the
:c:func:`VIDIOC_ENCODER_CMD` was issued will be processed and encoded as
normal. The client must continue to handle both queues independently,
similarly to normal encode operation. This includes:
* queuing and dequeuing ``CAPTURE`` buffers, until a buffer marked with the
``V4L2_BUF_FLAG_LAST`` flag is dequeued,
.. warning::
The last buffer may be empty (with :c:type:`v4l2_buffer`
``bytesused`` = 0) and in that case it must be ignored by the client,
as it does not contain an encoded frame.
.. note::
Any attempt to dequeue more ``CAPTURE`` buffers beyond the buffer
marked with ``V4L2_BUF_FLAG_LAST`` will result in a -EPIPE error from
:c:func:`VIDIOC_DQBUF`.
* dequeuing processed ``OUTPUT`` buffers, until all the buffers queued
before the ``V4L2_ENC_CMD_STOP`` command are dequeued,
* dequeuing the ``V4L2_EVENT_EOS`` event, if the client subscribes to it.
.. note::
For backwards compatibility, the encoder will signal a ``V4L2_EVENT_EOS``
event when the last frame has been encoded and all frames are ready to be
dequeued. It is deprecated behavior and the client must not rely on it.
The ``V4L2_BUF_FLAG_LAST`` buffer flag should be used instead.
3. Once all ``OUTPUT`` buffers queued before the ``V4L2_ENC_CMD_STOP`` call are
dequeued and the last ``CAPTURE`` buffer is dequeued, the encoder is stopped
and it will accept, but not process any newly queued ``OUTPUT`` buffers
until the client issues any of the following operations:
* ``V4L2_ENC_CMD_START`` - the encoder will not be reset and will resume
operation normally, with all the state from before the drain,
* a pair of :c:func:`VIDIOC_STREAMOFF` and :c:func:`VIDIOC_STREAMON` on the
``CAPTURE`` queue - the encoder will be reset (see the `Reset` sequence)
and then resume encoding,
* a pair of :c:func:`VIDIOC_STREAMOFF` and :c:func:`VIDIOC_STREAMON` on the
``OUTPUT`` queue - the encoder will resume operation normally, however any
source frames queued to the ``OUTPUT`` queue between ``V4L2_ENC_CMD_STOP``
and :c:func:`VIDIOC_STREAMOFF` will be discarded.
.. note::
Once the drain sequence is initiated, the client needs to drive it to
completion, as described by the steps above, unless it aborts the process by
issuing :c:func:`VIDIOC_STREAMOFF` on any of the ``OUTPUT`` or ``CAPTURE``
queues. The client is not allowed to issue ``V4L2_ENC_CMD_START`` or
``V4L2_ENC_CMD_STOP`` again while the drain sequence is in progress and they
will fail with -EBUSY error code if attempted.
For reference, handling of various corner cases is described below:
* In case of no buffer in the ``OUTPUT`` queue at the time the
``V4L2_ENC_CMD_STOP`` command was issued, the drain sequence completes
immediately and the encoder returns an empty ``CAPTURE`` buffer with the
``V4L2_BUF_FLAG_LAST`` flag set.
* In case of no buffer in the ``CAPTURE`` queue at the time the drain
sequence completes, the next time the client queues a ``CAPTURE`` buffer
it is returned at once as an empty buffer with the ``V4L2_BUF_FLAG_LAST``
flag set.
* If :c:func:`VIDIOC_STREAMOFF` is called on the ``CAPTURE`` queue in the
middle of the drain sequence, the drain sequence is canceled and all
``CAPTURE`` buffers are implicitly returned to the client.
* If :c:func:`VIDIOC_STREAMOFF` is called on the ``OUTPUT`` queue in the
middle of the drain sequence, the drain sequence completes immediately and
next ``CAPTURE`` buffer will be returned empty with the
``V4L2_BUF_FLAG_LAST`` flag set.
Although not mandatory, the availability of encoder commands may be queried
using :c:func:`VIDIOC_TRY_ENCODER_CMD`.
Reset
=====
The client may want to request the encoder to reinitialize the encoding, so
that the following stream data becomes independent from the stream data
generated before. Depending on the coded format, that may imply that:
* encoded frames produced after the restart must not reference any frames
produced before the stop, e.g. no long term references for H.264/HEVC,
* any headers that must be included in a standalone stream must be produced
again, e.g. SPS and PPS for H.264/HEVC.
This can be achieved by performing the reset sequence.
1. Perform the `Drain` sequence to ensure all the in-flight encoding finishes
and respective buffers are dequeued.
2. Stop streaming on the ``CAPTURE`` queue via :c:func:`VIDIOC_STREAMOFF`. This
will return all currently queued ``CAPTURE`` buffers to the client, without
valid frame data.
3. Start streaming on the ``CAPTURE`` queue via :c:func:`VIDIOC_STREAMON` and
continue with regular encoding sequence. The encoded frames produced into
``CAPTURE`` buffers from now on will contain a standalone stream that can be
decoded without the need for frames encoded before the reset sequence,
starting at the first ``OUTPUT`` buffer queued after issuing the
`V4L2_ENC_CMD_STOP` of the `Drain` sequence.
This sequence may be also used to change encoding parameters for encoders
without the ability to change the parameters on the fly.
Commit Points
=============
Setting formats and allocating buffers triggers changes in the behavior of the
encoder.
1. Setting the format on the ``CAPTURE`` queue may change the set of formats
supported/advertised on the ``OUTPUT`` queue. In particular, it also means
that the ``OUTPUT`` format may be reset and the client must not rely on the
previously set format being preserved.
2. Enumerating formats on the ``OUTPUT`` queue always returns only formats
supported for the current ``CAPTURE`` format.
3. Setting the format on the ``OUTPUT`` queue does not change the list of
formats available on the ``CAPTURE`` queue. An attempt to set the ``OUTPUT``
format that is not supported for the currently selected ``CAPTURE`` format
will result in the encoder adjusting the requested ``OUTPUT`` format to a
supported one.
4. Enumerating formats on the ``CAPTURE`` queue always returns the full set of
supported coded formats, irrespective of the current ``OUTPUT`` format.
5. While buffers are allocated on any of the ``OUTPUT`` or ``CAPTURE`` queues,
the client must not change the format on the ``CAPTURE`` queue. Drivers will
return the -EBUSY error code for any such format change attempt.
To summarize, setting formats and allocation must always start with the
``CAPTURE`` queue and the ``CAPTURE`` queue is the master that governs the
set of supported formats for the ``OUTPUT`` queue.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
상태 유지형 encoder와 문서 규칙
1-43상태 유지형 비디오 encoder는 display order의 raw video frame을 받아 bytestream으로 encode합니다. metadata와 header를 포함한 완전한 bytestream chunk를 생성하므로 결과 stream에 client의 추가 후처리가 필요하지 않습니다.
이 인터페이스를 지원하려고 드라이버에서 software stream 처리나 header 생성을 수행하는 것은 강하게 권장되지 않습니다. 이런 작업이 필요하다면 개발 중인 Stateless Video Encoder Interface를 사용하는 것이 바람직합니다.
별도 규정이 없으면 일반 V4L2 API 규칙을 적용하고 must·may·should 등은 RFC 2119 의미를 따릅니다. optional 표시가 없는 모든 단계는 필수입니다.
별도 규정이 없으면 `VIDIOC_G_EXT_CTRLS`와 `VIDIOC_S_EXT_CTRLS`는 각각 `VIDIOC_G_CTRL`과 `VIDIOC_S_CTRL` 대신 사용할 수 있고 그 반대도 가능합니다.
planar API와 buffer 대응을 포함한 공통 표기 규칙입니다.
.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
.. _encoder:
*************************************************
Memory-to-Memory Stateful Video Encoder Interface
*************************************************
A stateful video encoder takes raw video frames in display order and encodes
them into a bytestream. It generates complete chunks of the bytestream, including
all metadata, headers, etc. The resulting bytestream does not require any
further post-processing by the client.
Performing software stream processing, header generation etc. in the driver
in order to support this interface is strongly discouraged. In case such
operations are needed, use of the Stateless Video Encoder Interface (in
development) is strongly advised.
Conventions and Notations Used in This Document
===============================================
1. The general V4L2 API rules apply if not specified in this document
otherwise.
2. The meaning of words "must", "may", "should", etc. is as per `RFC
2119 <https://tools.ietf.org/html/rfc2119>`_.
3. All steps not marked "optional" are required.
4. :c:func:`VIDIOC_G_EXT_CTRLS` and :c:func:`VIDIOC_S_EXT_CTRLS` may be used
interchangeably with :c:func:`VIDIOC_G_CTRL` and :c:func:`VIDIOC_S_CTRL`,
unless specified otherwise.
5. Single-planar API (see :ref:`planar-apis`) and applicable structures may be
used interchangeably with multi-planar API, unless specified otherwise,
depending on encoder capabilities and following the general V4L2 guidelines.
6. i = [a..b]: sequence of integers from a to b, inclusive, i.e. i =
[0..2]: i = 0, 1, 2.
7. Given an ``OUTPUT`` buffer A, then A' represents a buffer on the ``CAPTURE``
queue containing data that resulted from processing buffer A.
공유 glossary와 encoder 상태 기계
44-83encoder의 용어 정의는 `decoder-glossary`를 참조합니다. encoder에서는 `OUTPUT`이 raw source frame queue이고 `CAPTURE`가 encoded bytestream destination queue라는 점이 핵심입니다.
원문의 DOT 상태 기계는 Initialization, Encoding, Drain, Stopped, Reset으로 구성됩니다. 두 queue가 모두 streaming일 때 encode가 시작되고, 어느 queue를 STREAMOFF하는지에 따라 Stopped와 Reset이 갈립니다.
초기화, 정상 encode, drain과 독립 stream reset의 흐름입니다.
DOT graph의 사건별 출발 상태와 도착 상태입니다.
Glossary
========
Refer to :ref:`decoder-glossary`.
State Machine
=============
.. kernel-render:: DOT
:alt: DOT digraph of encoder state machine
:caption: Encoder State Machine
digraph encoder_state_machine {
node [shape = doublecircle, label="Encoding"] Encoding;
node [shape = circle, label="Initialization"] Initialization;
node [shape = circle, label="Stopped"] Stopped;
node [shape = circle, label="Drain"] Drain;
node [shape = circle, label="Reset"] Reset;
node [shape = point]; qi
qi -> Initialization [ label = "open()" ];
Initialization -> Encoding [ label = "Both queues streaming" ];
Encoding -> Drain [ label = "V4L2_ENC_CMD_STOP" ];
Encoding -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
Encoding -> Stopped [ label = "VIDIOC_STREAMOFF(OUTPUT)" ];
Encoding -> Encoding;
Drain -> Stopped [ label = "All CAPTURE\nbuffers dequeued\nor\nVIDIOC_STREAMOFF(OUTPUT)" ];
Drain -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
Reset -> Encoding [ label = "VIDIOC_STREAMON(CAPTURE)" ];
Reset -> Initialization [ label = "VIDIOC_REQBUFS(OUTPUT, 0)" ];
Stopped -> Encoding [ label = "V4L2_ENC_CMD_START\nor\nVIDIOC_STREAMON(OUTPUT)" ];
Stopped -> Reset [ label = "VIDIOC_STREAMOFF(CAPTURE)" ];
}
지원 format, 해상도와 frame interval 조회
84-142encoder가 지원하는 coded format 전체는 `CAPTURE`에서 `VIDIOC_ENUM_FMT`를 호출해 열거합니다. 현재 `OUTPUT` format과 관계없이 지원 coded format 전체를 반환합니다.
지원 raw format은 `OUTPUT`의 `VIDIOC_ENUM_FMT`로 열거하며 현재 `CAPTURE`에 활성화된 coded format과 호환되는 항목만 반환합니다. 특정 coded format의 raw format을 확인하려면 먼저 CAPTURE에 coded format을 설정해야 합니다.
`VIDIOC_ENUM_FRAMESIZES`에 원하는 `struct v4l2_frmsizeenum.pixel_format`을 전달하면 해상도를 조회할 수 있습니다. coded pixel format에는 가능한 coded resolution 전체가, raw pixel format에는 현재 CAPTURE coded format과 조합할 수 있는 frame buffer resolution 전체가 포함됩니다.
`VIDIOC_ENUM_FRAMEINTERVALS`에는 `struct v4l2_frmivalenum`의 `pixel_format`, `width`, `height`를 전달합니다. coded format과 resolution에는 encoder가 지원하는 coded frame interval 전체가, raw format과 resolution에는 현재 CAPTURE의 coded format·resolution·frame interval과 함께 사용할 수 있는 interval이 반환됩니다.
FRAMEINTERVALS 구현은 선택 사항입니다. 구현하지 않았다면 codec 자체 한계 외의 특별한 interval 제한은 없습니다. 현재 CAPTURE coded format의 profile과 level은 각각의 control을 `VIDIOC_QUERYCTRL`로 조회하며, 추가 encoder capability도 해당 control을 조회해 발견합니다.
CAPTURE가 coded master이고 OUTPUT이 raw source입니다.
Querying Capabilities
=====================
1. To enumerate the set of coded formats supported by the encoder, the
client may call :c:func:`VIDIOC_ENUM_FMT` on ``CAPTURE``.
* The full set of supported formats will be returned, regardless of the
format set on ``OUTPUT``.
2. To enumerate the set of supported raw formats, the client may call
:c:func:`VIDIOC_ENUM_FMT` on ``OUTPUT``.
* Only the formats supported for the format currently active on ``CAPTURE``
will be returned.
* In order to enumerate raw formats supported by a given coded format,
the client must first set that coded format on ``CAPTURE`` and then
enumerate the formats on ``OUTPUT``.
3. The client may use :c:func:`VIDIOC_ENUM_FRAMESIZES` to detect supported
resolutions for a given format, passing the desired pixel format in
:c:type:`v4l2_frmsizeenum` ``pixel_format``.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMESIZES` for a coded pixel
format will include all possible coded resolutions supported by the
encoder for the given coded pixel format.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMESIZES` for a raw pixel format
will include all possible frame buffer resolutions supported by the
encoder for the given raw pixel format and coded format currently set on
``CAPTURE``.
4. The client may use :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` to detect supported
frame intervals for a given format and resolution, passing the desired pixel
format in :c:type:`v4l2_frmivalenum` ``pixel_format`` and the resolution
in :c:type:`v4l2_frmivalenum` ``width`` and :c:type:`v4l2_frmivalenum`
``height``.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` for a coded pixel
format and coded resolution will include all possible frame intervals
supported by the encoder for the given coded pixel format and resolution.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` for a raw pixel
format and resolution will include all possible frame intervals supported
by the encoder for the given raw pixel format and resolution and for the
coded format, coded resolution and coded frame interval currently set on
``CAPTURE``.
* Support for :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` is optional. If it is
not implemented, then there are no special restrictions other than the
limits of the codec itself.
5. Supported profiles and levels for the coded format currently set on
``CAPTURE``, if applicable, may be queried using their respective controls
via :c:func:`VIDIOC_QUERYCTRL`.
6. Any additional encoder capabilities may be discovered by querying
their respective controls.
CAPTURE coded format과 OUTPUT raw format
143-230초기화는 `CAPTURE` queue의 `VIDIOC_S_FMT`로 생성할 coded format을 설정하는 것부터 시작합니다. 필수 입력은 CAPTURE용 `type`, coded `pixelformat`, 원하는 CAPTURE buffer 크기 `sizeimage`입니다. 입력 width와 height는 무시되는 read-only 필드이고 나머지는 표준 의미를 따릅니다.
encoder는 하드웨어 요구에 맞춘 `sizeimage`와 현재 OUTPUT format, selection rectangle 등 상태를 바탕으로 선택한 coded `width`와 `height`를 반환합니다. CAPTURE format을 바꾸면 현재 OUTPUT format도 바뀔 수 있으므로 client는 결과가 요구에 맞는지 다시 확인해야 합니다.
선택적으로 `OUTPUT`의 `VIDIOC_ENUM_FMT`를 사용해 선택한 CAPTURE coded format이 지원하는 raw source format을 열거할 수 있습니다. 입력은 OUTPUT용 type이고 반환 `pixelformat`이 현재 coded format과 호환되는 raw format입니다.
그 다음 `VIDIOC_S_FMT(OUTPUT)`으로 raw source format을 설정합니다. 필수 입력은 OUTPUT용 type, source raw pixelformat, source resolution인 width와 height입니다. encoder는 현재 format 조합의 최소·최대·정렬 조건에 맞춰 width와 height를 조정할 수 있으며 이 범위는 `VIDIOC_ENUM_FRAMESIZES`로 보고됩니다.
OUTPUT format을 설정하면 새 resolution을 기준으로 selection rectangle이 다음 단계에서 설명하는 기본값으로 초기화됩니다.
coded destination과 raw source queue의 S_FMT 역할입니다.
master CAPTURE coded format을 먼저 선택합니다.
Initialization
==============
1. Set the coded format on the ``CAPTURE`` queue via :c:func:`VIDIOC_S_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
``pixelformat``
the coded format to be produced.
``sizeimage``
desired size of ``CAPTURE`` buffers; the encoder may adjust it to
match hardware requirements.
``width``, ``height``
ignored (read-only).
other fields
follow standard semantics.
* **Returned fields:**
``sizeimage``
adjusted size of ``CAPTURE`` buffers.
``width``, ``height``
the coded size selected by the encoder based on current state, e.g.
``OUTPUT`` format, selection rectangles, etc. (read-only).
.. important::
Changing the ``CAPTURE`` format may change the currently set ``OUTPUT``
format. How the new ``OUTPUT`` format is determined is up to the encoder
and the client must ensure it matches its needs afterwards.
2. **Optional.** Enumerate supported ``OUTPUT`` formats (raw formats for
source) for the selected coded format via :c:func:`VIDIOC_ENUM_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
other fields
follow standard semantics.
* **Returned fields:**
``pixelformat``
raw format supported for the coded format currently selected on
the ``CAPTURE`` queue.
other fields
follow standard semantics.
3. Set the raw source format on the ``OUTPUT`` queue via
:c:func:`VIDIOC_S_FMT`.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``pixelformat``
raw format of the source.
``width``, ``height``
source resolution.
other fields
follow standard semantics.
* **Returned fields:**
``width``, ``height``
may be adjusted to match encoder minimums, maximums and alignment
requirements, as required by the currently selected formats, as
reported by :c:func:`VIDIOC_ENUM_FRAMESIZES`.
other fields
follow standard semantics.
* Setting the ``OUTPUT`` format will reset the selection rectangles to their
default values, based on the new resolution, as described in the next
step.
raw와 coded frame interval
231-324`VIDIOC_S_PARM(OUTPUT)`으로 raw frame interval을 설정합니다. OUTPUT용 `type`을 지정하고 `parm.output.timeperframe`을 제외한 `parm.output` 필드는 0으로 만들며, 원하는 timeperframe을 전달합니다. encoder는 하드웨어 요구에 맞춰 조정된 값을 반환합니다.
역사적 API 동작 때문에 OUTPUT frame interval을 바꾸면 CAPTURE의 coded frame interval도 같은 값으로 설정됩니다. 예를 들어 1/24를 주면 초당 24 frame으로 재생할 coded stream을 만듭니다. OUTPUT interval은 raw frame 공급률에 대한 hint이므로 애플리케이션은 다른 속도로 frame을 공급할 수 있고, driver는 병렬 encoder scheduling에 이 값을 사용할 수 있습니다.
offline encoding처럼 raw 공급률과 coded 재생률이 다르면 다음 단계에서 CAPTURE interval을 별도로 바꿀 수 있습니다. `timeperframe`은 field가 아니라 frame 기준이므로 interlaced format에서는 top과 bottom 두 field를 합친 한 frame의 시간입니다.
선택적인 `VIDIOC_S_PARM(CAPTURE)`는 `V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL`이 광고될 때 사용할 수 있습니다. CAPTURE용 type과 `parm.capture.timeperframe`만 설정하고 다른 parm.capture 필드는 0으로 만들며, 조정된 coded interval을 반환받습니다.
CAPTURE interval은 coded video의 framerate를 정하지만 CAPTURE buffer 도착 속도를 정하지는 않습니다. 실제 도착 속도는 encoder 성능과 OUTPUT raw frame queue 속도에 달려 있습니다. 이 기능을 지원하지 않는 driver는 원하는 coded interval을 OUTPUT에 설정하면 됩니다. 다만 OUTPUT interval로 여러 encoder를 scheduling할 수 있는 driver는 별도 CAPTURE interval 기능을 지원해야 합니다.
raw 공급 hint와 coded 재생률의 관계입니다.
일반 실시간 encode와 offline encode를 구분합니다.
4. Set the raw frame interval on the ``OUTPUT`` queue via
:c:func:`VIDIOC_S_PARM`. This also sets the coded frame interval on the
``CAPTURE`` queue to the same value.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``parm.output``
set all fields except ``parm.output.timeperframe`` to 0.
``parm.output.timeperframe``
the desired frame interval; the encoder may adjust it to
match hardware requirements.
* **Returned fields:**
``parm.output.timeperframe``
the adjusted frame interval.
.. important::
Changing the ``OUTPUT`` frame interval *also* sets the framerate that
the encoder uses to encode the video. So setting the frame interval
to 1/24 (or 24 frames per second) will produce a coded video stream
that can be played back at that speed. The frame interval for the
``OUTPUT`` queue is just a hint, the application may provide raw
frames at a different rate. It can be used by the driver to help
schedule multiple encoders running in parallel.
In the next step the ``CAPTURE`` frame interval can optionally be
changed to a different value. This is useful for off-line encoding
were the coded frame interval can be different from the rate at
which raw frames are supplied.
.. important::
``timeperframe`` deals with *frames*, not fields. So for interlaced
formats this is the time per two fields, since a frame consists of
a top and a bottom field.
.. note::
It is due to historical reasons that changing the ``OUTPUT`` frame
interval also changes the coded frame interval on the ``CAPTURE``
queue. Ideally these would be independent settings, but that would
break the existing API.
5. **Optional** Set the coded frame interval on the ``CAPTURE`` queue via
:c:func:`VIDIOC_S_PARM`. This is only necessary if the coded frame
interval is different from the raw frame interval, which is typically
the case for off-line encoding. Support for this feature is signalled
by the :ref:`V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL <fmtdesc-flags>` format flag.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
``parm.capture``
set all fields except ``parm.capture.timeperframe`` to 0.
``parm.capture.timeperframe``
the desired coded frame interval; the encoder may adjust it to
match hardware requirements.
* **Returned fields:**
``parm.capture.timeperframe``
the adjusted frame interval.
.. important::
Changing the ``CAPTURE`` frame interval sets the framerate for the
coded video. It does *not* set the rate at which buffers arrive on the
``CAPTURE`` queue, that depends on how fast the encoder is and how
fast raw frames are queued on the ``OUTPUT`` queue.
.. important::
``timeperframe`` deals with *frames*, not fields. So for interlaced
formats this is the time per two fields, since a frame consists of
a top and a bottom field.
.. note::
Not all drivers support this functionality, in that case just set
the desired coded frame interval for the ``OUTPUT`` queue.
However, drivers that can schedule multiple encoders based on the
``OUTPUT`` frame interval must support this optional feature.
visible resolution과 crop
325-374visible resolution이 전체 OUTPUT resolution과 달라야 한다면 선택적으로 `VIDIOC_S_SELECTION(OUTPUT)`을 사용합니다. OUTPUT용 type, `target = V4L2_SEL_TGT_CROP`, 원하는 `r.left`, `r.top`, `r.width`, `r.height`를 전달합니다.
visible rectangle은 `V4L2_SEL_TGT_CROP_BOUNDS` 안에 들어가야 하며 codec과 하드웨어 제약에 따라 조정될 수 있습니다. encoder가 반환한 rectangle을 client가 반드시 확인해야 합니다.
raw source buffer 중 encode할 visible 영역을 정의합니다.
대표적인 용도는 source resolution이 macroblock 배수가 아닐 때 padding을 제외하는 것입니다. 16x16 macroblock codec에서 일반적인 1920x1080 영상은 source buffer를 1920x1088로 정렬해야 할 수 있으므로, client가 CROP target을 1920x1080으로 명시해 아래 8줄의 padding이 encode되지 않게 합니다.
frame buffer 정렬과 실제 영상 크기를 분리합니다.
6. **Optional.** Set the visible resolution for the stream metadata via
:c:func:`VIDIOC_S_SELECTION` on the ``OUTPUT`` queue if it is desired
to be different than the full OUTPUT resolution.
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
``target``
set to ``V4L2_SEL_TGT_CROP``.
``r.left``, ``r.top``, ``r.width``, ``r.height``
visible rectangle; this must fit within the `V4L2_SEL_TGT_CROP_BOUNDS`
rectangle and may be subject to adjustment to match codec and
hardware constraints.
* **Returned fields:**
``r.left``, ``r.top``, ``r.width``, ``r.height``
visible rectangle adjusted by the encoder.
* The following selection targets are supported on ``OUTPUT``:
``V4L2_SEL_TGT_CROP_BOUNDS``
equal to the full source frame, matching the active ``OUTPUT``
format.
``V4L2_SEL_TGT_CROP_DEFAULT``
equal to ``V4L2_SEL_TGT_CROP_BOUNDS``.
``V4L2_SEL_TGT_CROP``
rectangle within the source buffer to be encoded into the
``CAPTURE`` stream; defaults to ``V4L2_SEL_TGT_CROP_DEFAULT``.
.. note::
A common use case for this selection target is encoding a source
video with a resolution that is not a multiple of a macroblock,
e.g. the common 1920x1080 resolution may require the source
buffers to be aligned to 1920x1088 for codecs with 16x16 macroblock
size. To avoid encoding the padding, the client needs to explicitly
configure this selection target to 1920x1080.
.. warning::
The encoder may adjust the crop/compose rectangles to the nearest
supported ones to meet codec and hardware requirements. The client needs
to check the adjusted rectangle returned by :c:func:`VIDIOC_S_SELECTION`.
Buffer 할당과 streaming 시작
375-445`VIDIOC_REQBUFS`로 OUTPUT과 CAPTURE 양쪽 buffer를 할당하며 순서는 상관없습니다. 요청 `count`는 0보다 커야 하고 `type`은 해당 queue에 맞아야 하며 나머지는 표준 의미를 따릅니다. 실제 할당 수는 요청과 다를 수 있으므로 반환 count를 확인합니다.
pipeline depth를 위해 최소 수보다 많은 OUTPUT buffer를 원하면 `V4L2_CID_MIN_BUFFERS_FOR_OUTPUT` control로 최소 수를 조회하고 필요한 추가 수를 더해 REQBUFS count로 전달합니다.
더 세밀한 할당에는 `VIDIOC_CREATE_BUFS`를 사용할 수 있습니다. 원문이 명시한 필수 입력은 0보다 큰 count, OUTPUT용 type, 그 밖의 표준 필드이며 조정된 실제 count를 반환합니다.
두 queue 모두에 `VIDIOC_STREAMON`을 호출하며 순서는 상관없습니다. 실제 encode는 OUTPUT과 CAPTURE가 모두 streaming을 시작했을 때 진행됩니다.
encode 중 CAPTURE를 멈췄다가 다시 시작하면 이전 stream과 독립된 새 stream을 생성해야 합니다. coded format별 세부 조건은 다르지만 H.264/HEVC의 long-term reference처럼 정지 전 frame을 참조해서는 안 되고, 독립 stream에 필요한 SPS와 PPS 같은 header를 다시 생성해야 합니다.
두 queue의 할당 및 시작 규칙입니다.
중단 전 stream에 의존하지 않는 새 coded stream을 만듭니다.
7. Allocate buffers for both ``OUTPUT`` and ``CAPTURE`` via
:c:func:`VIDIOC_REQBUFS`. This may be performed in any order.
* **Required fields:**
``count``
requested number of buffers to allocate; greater than zero.
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT`` or
``CAPTURE``.
other fields
follow standard semantics.
* **Returned fields:**
``count``
actual number of buffers allocated.
.. warning::
The actual number of allocated buffers may differ from the ``count``
given. The client must check the updated value of ``count`` after the
call returns.
.. note::
To allocate more than the minimum number of OUTPUT buffers (for pipeline
depth), the client may query the ``V4L2_CID_MIN_BUFFERS_FOR_OUTPUT``
control to get the minimum number of buffers required, and pass the
obtained value plus the number of additional buffers needed in the
``count`` field to :c:func:`VIDIOC_REQBUFS`.
Alternatively, :c:func:`VIDIOC_CREATE_BUFS` can be used to have more
control over buffer allocation.
* **Required fields:**
``count``
requested number of buffers to allocate; greater than zero.
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
other fields
follow standard semantics.
* **Returned fields:**
``count``
adjusted to the number of allocated buffers.
8. Begin streaming on both ``OUTPUT`` and ``CAPTURE`` queues via
:c:func:`VIDIOC_STREAMON`. This may be performed in any order. The actual
encoding process starts when both queues start streaming.
.. note::
If the client stops the ``CAPTURE`` queue during the encode process and then
restarts it again, the encoder will begin generating a stream independent
from the stream generated before the stop. The exact constraints depend
on the coded format, but may include the following implications:
* encoded frames produced after the restart must not reference any
frames produced before the stop, e.g. no long term references for
H.264/HEVC,
* any headers that must be included in a standalone stream must be
produced again, e.g. SPS and PPS for H.264/HEVC.
Encoding queue와 오류 처리
446-536Initialization을 성공적으로 마치면 Encoding 상태에 도달합니다. client는 표준 의미에 따라 `VIDIOC_QBUF`와 `VIDIOC_DQBUF`로 두 queue의 buffer를 넣고 빼며, encoded CAPTURE 내용은 coded pixel format과 codec별 extended control의 영향을 받습니다.
두 queue는 독립적이고 frame reordering 때문에 CAPTURE의 encoded frame 순서가 OUTPUT raw frame queue 순서와 다를 수 있습니다. client는 queue 사이의 직접적인 1:1 관계나 특정 dequeue 시점을 가정해서는 안 됩니다.
raw source와 coded 결과 사이에 허용되는 동작입니다.
origin을 맞추려면 OUTPUT을 queue할 때 `struct v4l2_buffer.timestamp`를 설정합니다. 해당 OUTPUT에서 나온 CAPTURE buffer는 dequeue할 때 같은 timestamp를 갖습니다. 하나의 OUTPUT이 여러 CAPTURE를 만들면 모두 같은 값이 복사되고, encode order와 presentation order가 다르면 CAPTURE timestamp 순서는 OUTPUT 순서를 보존하지 않습니다.
client가 keyframe과 intermediate frame 등 frame type을 구분할 수 있도록 CAPTURE의 `struct v4l2_buffer`에는 coded format에 맞는 flag bit가 설정됩니다. 정확한 종류와 의미는 v4l2_buffer 및 각 coded pixel format 문서를 따릅니다.
encode 오류가 나면 실패 결과를 담은 CAPTURE buffer가 있다면 `V4L2_BUF_FLAG_ERROR`로 반환됩니다. encoder가 오류를 유발한 OUTPUT buffer를 정확히 식별할 수 있으면 그 buffer에도 같은 flag를 설정합니다. CAPTURE buffer가 너무 작아도 ERROR flag만 설정해 반환되며, 작은 크기가 원인임을 별도로 감지하고 기존 buffer를 해제하는 지원은 아직 추가 작업이 필요합니다.
encode를 계속할 수 없는 치명적 failure 뒤에는 해당 file handle의 후속 작업이 `-EIO`를 반환합니다. handle을 닫고 다시 열거나, 두 queue를 정지하고 모든 buffer를 해제한 뒤 Initialization을 다시 수행해 instance를 재초기화할 수 있습니다.
raw source와 encoded 결과의 비동기 대응을 기록합니다.
복구 가능한 buffer 오류와 치명적 instance 오류입니다.
Encoding
========
This state is reached after the `Initialization` sequence finishes
successfully. In this state, the client queues and dequeues buffers to both
queues via :c:func:`VIDIOC_QBUF` and :c:func:`VIDIOC_DQBUF`, following the
standard semantics.
The content of encoded ``CAPTURE`` buffers depends on the active coded pixel
format and may be affected by codec-specific extended controls, as stated
in the documentation of each format.
Both queues operate independently, following standard behavior of V4L2 buffer
queues and memory-to-memory devices. In addition, the order of encoded frames
dequeued from the ``CAPTURE`` queue may differ from the order of queuing raw
frames to the ``OUTPUT`` queue, due to properties of the selected coded format,
e.g. frame reordering.
The client must not assume any direct relationship between ``CAPTURE`` and
``OUTPUT`` buffers and any specific timing of buffers becoming
available to dequeue. Specifically:
* a buffer queued to ``OUTPUT`` may result in more than one buffer produced on
``CAPTURE`` (for example, if returning an encoded frame allowed the encoder
to return a frame that preceded it in display, but succeeded it in the decode
order; however, there may be other reasons for this as well),
* a buffer queued to ``OUTPUT`` may result in a buffer being produced on
``CAPTURE`` later into encode process, and/or after processing further
``OUTPUT`` buffers, or be returned out of order, e.g. if display
reordering is used,
* buffers may become available on the ``CAPTURE`` queue without additional
buffers queued to ``OUTPUT`` (e.g. during drain or ``EOS``), because of the
``OUTPUT`` buffers queued in the past whose encoding results are only
available at later time, due to specifics of the encoding process,
* buffers queued to ``OUTPUT`` may not become available to dequeue instantly
after being encoded into a corresponding ``CAPTURE`` buffer, e.g. if the
encoder needs to use the frame as a reference for encoding further frames.
.. note::
To allow matching encoded ``CAPTURE`` buffers with ``OUTPUT`` buffers they
originated from, the client can set the ``timestamp`` field of the
:c:type:`v4l2_buffer` struct when queuing an ``OUTPUT`` buffer. The
``CAPTURE`` buffer(s), which resulted from encoding that ``OUTPUT`` buffer
will have their ``timestamp`` field set to the same value when dequeued.
In addition to the straightforward case of one ``OUTPUT`` buffer producing
one ``CAPTURE`` buffer, the following cases are defined:
* one ``OUTPUT`` buffer generates multiple ``CAPTURE`` buffers: the same
``OUTPUT`` timestamp will be copied to multiple ``CAPTURE`` buffers,
* the encoding order differs from the presentation order (i.e. the
``CAPTURE`` buffers are out-of-order compared to the ``OUTPUT`` buffers):
``CAPTURE`` timestamps will not retain the order of ``OUTPUT`` timestamps.
.. note::
To let the client distinguish between frame types (keyframes, intermediate
frames; the exact list of types depends on the coded format), the
``CAPTURE`` buffers will have corresponding flag bits set in their
:c:type:`v4l2_buffer` struct when dequeued. See the documentation of
:c:type:`v4l2_buffer` and each coded pixel format for exact list of flags
and their meanings.
Should an encoding error occur, it will be reported to the client with the level
of details depending on the encoder capabilities. Specifically:
* the ``CAPTURE`` buffer (if any) that contains the results of the failed encode
operation will be returned with the ``V4L2_BUF_FLAG_ERROR`` flag set,
* if the encoder is able to precisely report the ``OUTPUT`` buffer(s) that triggered
the error, such buffer(s) will be returned with the ``V4L2_BUF_FLAG_ERROR`` flag
set.
.. note::
If a ``CAPTURE`` buffer is too small then it is just returned with the
``V4L2_BUF_FLAG_ERROR`` flag set. More work is needed to detect that this
error occurred because the buffer was too small, and to provide support to
free existing buffers that were too small.
In case of a fatal failure that does not allow the encoding to continue, any
further operations on corresponding encoder file handle will return the -EIO
error code. The client may close the file handle and open a new one, or
alternatively reinitialize the instance by stopping streaming on both queues,
releasing all buffers and performing the Initialization sequence again.
Encoding 중 parameter 변경
537-555client는 언제든 `VIDIOC_S_CTRL`로 encoder parameter 변경을 시도할 수 있습니다. 제공되는 parameter 집합과 encode 중 변경 가능 여부는 encoder별로 다르므로 control을 조회해야 합니다.
encode 중 control 설정이 `-EBUSY`로 실패하면 configuration 변경을 허용하기 위해 CAPTURE queue를 정지해야 합니다. 이미 queue되거나 encode된 frame을 잃지 않으려면 먼저 Drain sequence를 수행할 수 있습니다.
parameter가 실제 적용되는 시점도 encoder별 V4L2 control 표준 의미를 따릅니다. 특정 frame에 정확히 적용해야 하고 encoder가 지원한다면 Request API를 고려해야 합니다.
on-the-fly 지원 여부와 정확한 적용 시점에 따른 선택입니다.
Encoding Parameter Changes
==========================
The client is allowed to use :c:func:`VIDIOC_S_CTRL` to change encoder
parameters at any time. The availability of parameters is encoder-specific
and the client must query the encoder to find the set of available controls.
The ability to change each parameter during encoding is encoder-specific, as
per the standard semantics of the V4L2 control interface. The client may
attempt to set a control during encoding and if the operation fails with the
-EBUSY error code, the ``CAPTURE`` queue needs to be stopped for the
configuration change to be allowed. To do this, it may follow the `Drain`
sequence to avoid losing the already queued/encoded frames.
The timing of parameter updates is encoder-specific, as per the standard
semantics of the V4L2 control interface. If the client needs to apply the
parameters exactly at specific frame, using the Request API
(:ref:`media-request-api`) should be considered, if supported by the encoder.
Drain과 정지 후 재개
556-667Drain은 이미 queue한 모든 OUTPUT을 처리하고 관련 encoded CAPTURE를 전부 client에 전달하는 절차입니다. 완료되면 시작 전에 넣은 모든 raw frame의 encoded 결과를 받은 상태가 됩니다.
`VIDIOC_ENCODER_CMD`에 `cmd = V4L2_ENC_CMD_STOP`, `flags = 0`, `pts = 0`을 주어 시작합니다. OUTPUT과 CAPTURE가 모두 streaming일 때만 실제 drain이 시작됩니다. 호환성 때문에 queue가 정지 상태여도 ioctl 자체는 실패하지 않지만 이후 단계는 적용되지 않습니다.
STOP 전에 queue한 OUTPUT은 정상 encode하고 두 queue를 계속 독립 처리합니다. CAPTURE는 `V4L2_BUF_FLAG_LAST`가 붙은 buffer까지 queue/dequeue하고, `bytesused = 0`인 빈 LAST는 frame이 없으므로 무시합니다. LAST 뒤 DQBUF는 `-EPIPE`입니다.
STOP 전 OUTPUT도 모두 dequeue해야 합니다. 마지막 frame 준비 시 구형 호환성용 `V4L2_EVENT_EOS`가 발생할 수 있지만 deprecated이므로 의존하지 말고 LAST flag를 사용합니다.
기존 OUTPUT과 마지막 CAPTURE를 모두 dequeue하면 encoder는 멈추며 새 OUTPUT을 받아도 처리하지 않습니다. `V4L2_ENC_CMD_START`는 state를 보존해 정상 재개합니다. CAPTURE STREAMOFF/ON은 Reset 뒤 encode를 재개합니다. OUTPUT STREAMOFF/ON은 정상 재개하지만 STOP과 STREAMOFF 사이에 queue한 source frame을 버립니다.
drain을 시작하면 어느 queue든 STREAMOFF해 중단하지 않는 한 끝까지 수행해야 합니다. 진행 중 START나 STOP을 다시 호출하면 `-EBUSY`입니다. encoder command 지원 여부는 선택적으로 `VIDIOC_TRY_ENCODER_CMD`로 조회할 수 있습니다.
V4L2_ENC_CMD_STOP 요청의 필수 값입니다.
STOP 이전 frame을 모두 encode하고 정지합니다.
선택한 동작에 따른 state와 buffer 처리 차이입니다.
buffer 부재 또는 중간 STREAMOFF 때의 LAST 처리입니다.
Drain
=====
To ensure that all the queued ``OUTPUT`` buffers have been processed and the
related ``CAPTURE`` buffers are given to the client, the client must follow the
drain sequence described below. After the drain sequence ends, the client has
received all encoded frames for all ``OUTPUT`` buffers queued before the
sequence was started.
1. Begin the drain sequence by issuing :c:func:`VIDIOC_ENCODER_CMD`.
* **Required fields:**
``cmd``
set to ``V4L2_ENC_CMD_STOP``.
``flags``
set to 0.
``pts``
set to 0.
.. warning::
The sequence can be only initiated if both ``OUTPUT`` and ``CAPTURE``
queues are streaming. For compatibility reasons, the call to
:c:func:`VIDIOC_ENCODER_CMD` will not fail even if any of the queues is
not streaming, but at the same time it will not initiate the `Drain`
sequence and so the steps described below would not be applicable.
2. Any ``OUTPUT`` buffers queued by the client before the
:c:func:`VIDIOC_ENCODER_CMD` was issued will be processed and encoded as
normal. The client must continue to handle both queues independently,
similarly to normal encode operation. This includes:
* queuing and dequeuing ``CAPTURE`` buffers, until a buffer marked with the
``V4L2_BUF_FLAG_LAST`` flag is dequeued,
.. warning::
The last buffer may be empty (with :c:type:`v4l2_buffer`
``bytesused`` = 0) and in that case it must be ignored by the client,
as it does not contain an encoded frame.
.. note::
Any attempt to dequeue more ``CAPTURE`` buffers beyond the buffer
marked with ``V4L2_BUF_FLAG_LAST`` will result in a -EPIPE error from
:c:func:`VIDIOC_DQBUF`.
* dequeuing processed ``OUTPUT`` buffers, until all the buffers queued
before the ``V4L2_ENC_CMD_STOP`` command are dequeued,
* dequeuing the ``V4L2_EVENT_EOS`` event, if the client subscribes to it.
.. note::
For backwards compatibility, the encoder will signal a ``V4L2_EVENT_EOS``
event when the last frame has been encoded and all frames are ready to be
dequeued. It is deprecated behavior and the client must not rely on it.
The ``V4L2_BUF_FLAG_LAST`` buffer flag should be used instead.
3. Once all ``OUTPUT`` buffers queued before the ``V4L2_ENC_CMD_STOP`` call are
dequeued and the last ``CAPTURE`` buffer is dequeued, the encoder is stopped
and it will accept, but not process any newly queued ``OUTPUT`` buffers
until the client issues any of the following operations:
* ``V4L2_ENC_CMD_START`` - the encoder will not be reset and will resume
operation normally, with all the state from before the drain,
* a pair of :c:func:`VIDIOC_STREAMOFF` and :c:func:`VIDIOC_STREAMON` on the
``CAPTURE`` queue - the encoder will be reset (see the `Reset` sequence)
and then resume encoding,
* a pair of :c:func:`VIDIOC_STREAMOFF` and :c:func:`VIDIOC_STREAMON` on the
``OUTPUT`` queue - the encoder will resume operation normally, however any
source frames queued to the ``OUTPUT`` queue between ``V4L2_ENC_CMD_STOP``
and :c:func:`VIDIOC_STREAMOFF` will be discarded.
.. note::
Once the drain sequence is initiated, the client needs to drive it to
completion, as described by the steps above, unless it aborts the process by
issuing :c:func:`VIDIOC_STREAMOFF` on any of the ``OUTPUT`` or ``CAPTURE``
queues. The client is not allowed to issue ``V4L2_ENC_CMD_START`` or
``V4L2_ENC_CMD_STOP`` again while the drain sequence is in progress and they
will fail with -EBUSY error code if attempted.
For reference, handling of various corner cases is described below:
* In case of no buffer in the ``OUTPUT`` queue at the time the
``V4L2_ENC_CMD_STOP`` command was issued, the drain sequence completes
immediately and the encoder returns an empty ``CAPTURE`` buffer with the
``V4L2_BUF_FLAG_LAST`` flag set.
* In case of no buffer in the ``CAPTURE`` queue at the time the drain
sequence completes, the next time the client queues a ``CAPTURE`` buffer
it is returned at once as an empty buffer with the ``V4L2_BUF_FLAG_LAST``
flag set.
* If :c:func:`VIDIOC_STREAMOFF` is called on the ``CAPTURE`` queue in the
middle of the drain sequence, the drain sequence is canceled and all
``CAPTURE`` buffers are implicitly returned to the client.
* If :c:func:`VIDIOC_STREAMOFF` is called on the ``OUTPUT`` queue in the
middle of the drain sequence, the drain sequence completes immediately and
next ``CAPTURE`` buffer will be returned empty with the
``V4L2_BUF_FLAG_LAST`` flag set.
Although not mandatory, the availability of encoder commands may be queried
using :c:func:`VIDIOC_TRY_ENCODER_CMD`.
독립 stream을 위한 Reset
668-699client는 이후 coded data가 이전 stream과 독립적이 되도록 encoder 재초기화를 요청할 수 있습니다. format에 따라 재시작 뒤 frame은 정지 전 frame을 참조하지 않아야 하고, H.264/HEVC의 SPS와 PPS처럼 standalone stream에 필요한 header를 다시 만들어야 합니다.
먼저 Drain을 수행해 in-flight encoding을 끝내고 관련 buffer를 모두 dequeue합니다. 그 다음 `VIDIOC_STREAMOFF(CAPTURE)`로 streaming을 멈추면 현재 queue된 CAPTURE buffer가 유효 frame data 없이 client에 반환됩니다.
`VIDIOC_STREAMON(CAPTURE)`으로 다시 시작하면 Drain의 `V4L2_ENC_CMD_STOP` 뒤 처음 queue한 OUTPUT부터, reset 전 encoded frame 없이 decode할 수 있는 standalone stream이 CAPTURE에 생성됩니다.
on-the-fly parameter 변경을 지원하지 않는 encoder에서는 이 Reset sequence를 encoding parameter 변경에도 사용할 수 있습니다.
정지 전 stream 의존성을 끊고 새 standalone stream을 시작합니다.
Reset
=====
The client may want to request the encoder to reinitialize the encoding, so
that the following stream data becomes independent from the stream data
generated before. Depending on the coded format, that may imply that:
* encoded frames produced after the restart must not reference any frames
produced before the stop, e.g. no long term references for H.264/HEVC,
* any headers that must be included in a standalone stream must be produced
again, e.g. SPS and PPS for H.264/HEVC.
This can be achieved by performing the reset sequence.
1. Perform the `Drain` sequence to ensure all the in-flight encoding finishes
and respective buffers are dequeued.
2. Stop streaming on the ``CAPTURE`` queue via :c:func:`VIDIOC_STREAMOFF`. This
will return all currently queued ``CAPTURE`` buffers to the client, without
valid frame data.
3. Start streaming on the ``CAPTURE`` queue via :c:func:`VIDIOC_STREAMON` and
continue with regular encoding sequence. The encoded frames produced into
``CAPTURE`` buffers from now on will contain a standalone stream that can be
decoded without the need for frames encoded before the reset sequence,
starting at the first ``OUTPUT`` buffer queued after issuing the
`V4L2_ENC_CMD_STOP` of the `Drain` sequence.
This sequence may be also used to change encoding parameters for encoders
without the ability to change the parameters on the fly.
CAPTURE master와 format commit point
700-729format 설정과 buffer 할당은 encoder 동작을 바꾸는 commit point입니다. CAPTURE format을 설정하면 OUTPUT이 광고하는 raw format 집합과 현재 OUTPUT format이 바뀔 수 있으므로 이전 설정 보존을 기대해서는 안 됩니다.
OUTPUT ENUM_FMT는 항상 현재 CAPTURE coded format이 지원하는 raw format만 반환합니다. OUTPUT format 설정은 CAPTURE 목록을 바꾸지 않으며, 현재 CAPTURE와 호환되지 않는 OUTPUT format을 요청하면 encoder가 지원 format으로 조정합니다.
CAPTURE ENUM_FMT는 현재 OUTPUT과 관계없이 전체 coded format을 반환합니다. 어느 queue든 buffer가 할당된 동안 CAPTURE format을 바꿀 수 없으며 driver는 `-EBUSY`를 반환합니다. 따라서 format 설정과 할당은 언제나 master인 CAPTURE queue에서 시작해야 합니다.
CAPTURE가 OUTPUT 지원 집합을 지배하는 다섯 가지 규칙입니다.
master queue인 CAPTURE에서 format 협상을 시작합니다.
Commit Points
=============
Setting formats and allocating buffers triggers changes in the behavior of the
encoder.
1. Setting the format on the ``CAPTURE`` queue may change the set of formats
supported/advertised on the ``OUTPUT`` queue. In particular, it also means
that the ``OUTPUT`` format may be reset and the client must not rely on the
previously set format being preserved.
2. Enumerating formats on the ``OUTPUT`` queue always returns only formats
supported for the current ``CAPTURE`` format.
3. Setting the format on the ``OUTPUT`` queue does not change the list of
formats available on the ``CAPTURE`` queue. An attempt to set the ``OUTPUT``
format that is not supported for the currently selected ``CAPTURE`` format
will result in the encoder adjusting the requested ``OUTPUT`` format to a
supported one.
4. Enumerating formats on the ``CAPTURE`` queue always returns the full set of
supported coded formats, irrespective of the current ``OUTPUT`` format.
5. While buffers are allocated on any of the ``OUTPUT`` or ``CAPTURE`` queues,
the client must not change the format on the ``CAPTURE`` queue. Drivers will
return the -EBUSY error code for any such format change attempt.
To summarize, setting formats and allocation must always start with the
``CAPTURE`` queue and the ``CAPTURE`` queue is the master that governs the
set of supported formats for the ``OUTPUT`` queue.
요약·해설
dev-encoder.rst:1-729상태 유지형 encoder에서는 CAPTURE가 coded format을 지배하는 master queue이고 OUTPUT이 display-order raw frame을 공급합니다. 두 queue의 독립 동작, frame interval, LAST flag와 Reset 경계를 기준으로 안전하게 stream을 구성해야 합니다.