> ## Documentation Index
> Fetch the complete documentation index at: https://imsdkdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# v4l2h265enc

> Hardware-accelerated H.265/HEVC video encoder using the V4L2 stateful encoder API on Qualcomm hardware.

# Overview

`v4l2h265enc` is a hardware-accelerated video encoder that uses the Video4Linux2 (V4L2) stateful encoder API to offload H.265 (HEVC) video encoding to the Qualcomm Video Processing Unit (VPU).

This plugin is provided and maintained by the GStreamer community. This document focuses on its usage in conjunction with Qualcomm-specific QIM SDK GStreamer plugins, along with relevant use cases and internal architectural considerations.

`v4l2h265enc` is typically used in encoding pipelines for:

* Camera capture and local recording with higher compression efficiency than H.264
* Video transcoding (e.g., H.264 → H.265)
* Live streaming (RTSP, HLS, UDP)
* 4K and HDR10 content encoding
* Multi-stream simultaneous encoding

The element is responsible **only for encoding** raw video frames. It does not mux or parse streams on its own — those operations must be handled by peer GStreamer elements downstream (e.g., `h265parse`, `mp4mux`).

## Example Pipeline

<img src="https://mintcdn.com/qimsdk/xdnKhBBjxpS5mUYP/plugin-reference/images/v4l2h265enc_pipeline.png?fit=max&auto=format&n=xdnKhBBjxpS5mUYP&q=85&s=90cc3d49001a340d3ce193e1b525b088" alt="" width="896" height="71" data-path="plugin-reference/images/v4l2h265enc_pipeline.png" />

<Steps>
  <Step title="Download Required Files">
    | File         | Download                                                                                                                                               | Save as                     |
    | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------- |
    | Sample video | <a href="https://github.com/qualcomm/sample-apps-for-qualcomm-linux/raw/refs/heads/main/qualcomm-linux/artifacts/videos/demo_samples/">Input video</a> | `Draw_1080p_180s_30FPS.mp4` |
  </Step>

  <Step title="Copy files to device">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Replace $HOME to the appropriate device path before running the commands.
      # For QLI:    /root
      # For Ubuntu: /home/ubuntu
      # Modify this based on your platform and ensure files are copied to the correct location on the device.
      # Run from your host machine — replace <user> and <device-ip>

      ssh <user>@<device-ip> "mkdir -p $HOME/{media,media/output}"
      scp Draw_1080p_180s_30FPS.mp4   <user>@<device-ip>:$HOME/media/
      ```
    </CodeGroup>
  </Step>

  <Step title="Connect to device">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip>
      ```
    </CodeGroup>
  </Step>

  <Step title="Set environment variables">
    Run below command on your device

    ```bash theme={null}
    export SRC_VIDEO_NAME=Draw_1080p_180s_30FPS.mp4
    ```
  </Step>

  <Step title="Run the pipeline">
    ```bash theme={null}
    gst-launch-1.0 -e \
      qticamsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
      queue ! v4l2h265enc output-io-mode=dmabuf-import capture-io-mode=dmabuf ! \
      queue ! h265parse ! mp4mux ! \
      filesink location=$HOME/media/output/output.mp4
    ```
  </Step>
</Steps>

# Key Responsibilities

`v4l2h265enc` is responsible for:

* **Hardware acceleration** — offloads H.265/HEVC encoding to the dedicated VPU
* **V4L2 state management** — manages the V4L2 stateful encoder state machine (device open, buffer allocation, stream on/off)
* **Buffer I/O management** — handles buffer exchange between GStreamer and the V4L2 driver using DMABuf, MMAP, or UserPtr modes
* **Format negotiation** — negotiates raw input formats supported by the hardware, including UBWC-compressed formats for reduced memory bandwidth
* **Profile and level selection** — negotiates H.265 profile and level with downstream elements based on hardware capabilities probed at registration time
* **Encoder parameter control** — supports runtime configuration of encoding parameters (bitrate, GOP size, QP values, etc.) via the `extra-controls` property
* **Multi-stream support** — supports multiple concurrent encoder instances (subject to hardware resource limits)

# Hierarchy

[GObject](https://docs.gtk.org/gobject/)<br />
   <Icon icon="arrow-turn-down-right" iconType="solid" />[GstObject](https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html)<br />
      <Icon icon="arrow-turn-down-right" iconType="solid" />[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html)<br />
         <Icon icon="arrow-turn-down-right" iconType="solid" />GstVideoEncoder<br />
            <Icon icon="arrow-turn-down-right" iconType="solid" />GstV4l2VideoEnc<br />
               <Icon icon="arrow-turn-down-right" iconType="solid" />v4l2h265enc

# Pad Templates

### sink

| Capabilities           |                                                                                                           |
| ---------------------- | --------------------------------------------------------------------------------------------------------- |
| `video/x-raw`          | `format: { NV12_Q08C, NV12_Q10LE32C, NV12, NV21 }` <br /> `width: [1, 32768]` <br /> `height: [1, 32768]` |
| Availability: *Always* |                                                                                                           |
| Direction: *sink*      |                                                                                                           |

### src

| Capabilities           |                                                                                                                                     |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `video/x-h265`         | `stream-format: byte-stream` <br /> `alignment: au` <br /> `profiles: { main, main-still-picture, main-10 }` <br /> `levels: 1–6.2` |
| Availability: *Always* |                                                                                                                                     |
| Direction: *source*    |                                                                                                                                     |

<Note>
  The exact set of profiles and levels reported depends on what the underlying V4L2 driver enumerates via `V4L2_CID_MPEG_VIDEO_HEVC_PROFILE` and `V4L2_CID_MPEG_VIDEO_HEVC_LEVEL`.
</Note>

# Element Properties

| Property          | Description                                                                                                                                                                                                                                             |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `capture-io-mode` | I/O mode for the capture queue (src pad). Controls how compressed output buffers are received from the driver.<br /><br />`Type: Enum `<br />`Default: 0, "auto"`<br />`Flags: readable/writable`                                                       |
| `device`          | The V4L2 device node path. Set automatically at registration time and read-only after element creation.<br /><br />`Type: String`<br />`Default: "/dev/video32"`<br />`Flags: readable`                                                                 |
| `device-fd`       | File descriptor of the opened V4L2 device. A value of `-1` indicates that the device is not open.<br /><br />`Type: Integer`<br />`Default: -1`<br />`Flags: readable`                                                                                  |
| `device-name`     | Human-readable name of the V4L2 device as reported by the driver via VIDIOC\_QUERYCAP.<br /><br />`Type: String`<br />`Default: NULL`<br />`Flags: readable`                                                                                            |
| `extra-controls`  | Extra V4L2 controls (CIDs) to set on the device, specified as a GstStructure. Applied via VIDIOC\_S\_EXT\_CTRLS. Used to configure encoding parameters at runtime.<br /><br />`Type: GstStructure`<br />`Default: NULL`<br />`Flags: readable/writable` |
| `output-io-mode`  | I/O mode for the output queue (sink pad). Controls how raw input buffers are submitted to the driver.<br /><br />`Type: Enum `<br />`Default: 0, "auto"`<br />`Flags: readable/writable`                                                                |

## I/O Mode Values

Both `capture-io-mode` and `output-io-mode` accept the same `GstV4l2IOMode` enumeration:

| Value           | Integer | Description                                                                                                                                                      |
| --------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `auto`          | 0       | Automatically select the best I/O mode.                                                                                                                          |
| `rw`            | 1       | Use read/write system calls. Rarely used for M2M devices.                                                                                                        |
| `mmap`          | 2       | Use kernel memory-mapped buffers (`V4L2_MEMORY_MMAP`).                                                                                                           |
| `userptr`       | 3       | Use user-space pointer buffers (`V4L2_MEMORY_USERPTR`).                                                                                                          |
| `dmabuf`        | 4       | Export buffers as DMABuf file descriptors (`V4L2_MEMORY_DMABUF`). Use for `capture-io-mode` to export encoded output.                                            |
| `dmabuf-import` | 5       | Import DMABuf file descriptors from an external allocator. Use for `output-io-mode` when upstream (camera, decoder) provides DMABuf handles for zero-copy input. |

# Internal Architecture

`v4l2h265enc` operates using two V4L2 queue objects internally:

* **Output queue** (`V4L2_BUF_TYPE_VIDEO_OUTPUT`) — receives raw video frame buffers from upstream
* **Capture queue** (`V4L2_BUF_TYPE_VIDEO_CAPTURE`) — produces encoded H.265 bitstream buffers for downstream

<img src="https://mintcdn.com/qimsdk/xdnKhBBjxpS5mUYP/plugin-reference/images/v4l2h265enc_internal_architecture.png?fit=max&auto=format&n=xdnKhBBjxpS5mUYP&q=85&s=74b28d6b75fa5ecfa0f1cffdb25636d5" alt="" width="961" height="1093" data-path="plugin-reference/images/v4l2h265enc_internal_architecture.png" />

# State Transitions

| Transition               | Encoder Behavior                                                                       | Notes                                                                                                             |
| ------------------------ | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `NULL → READY`           | Element becomes ready. Static configuration available.                                 | Configure `capture-io-mode`, `output-io-mode`, and `extra-controls` before active encoding.                       |
| `READY → PAUSED`         | Encoder activates. V4L2 session setup begins.                                          | Caps negotiation: sink is `video/x-raw`, src is `video/x-h265`. Profile and level are negotiated with downstream. |
| `PAUSED → PLAYING`       | Continuous encoding starts. Raw frames consumed, H.265 AUs pushed downstream.          | Normal running state.                                                                                             |
| `PLAYING → PAUSED`       | Encoding paused at GStreamer scheduling level.                                         | No full encoder teardown. Resume continues from current position.                                                 |
| `PLAYING/PAUSED → READY` | Encoder stops. V4L2 streaming stopped, buffers released.                               | Key cleanup transition for stopping recording or preparing for reuse.                                             |
| `READY → NULL`           | Element fully shut down. All resources released.                                       |                                                                                                                   |
| EOS while PLAYING        | Encoder drains pending raw input, outputs remaining encoded frames, then forwards EOS. | Sends `V4L2_ENC_CMD_STOP` via `VIDIOC_ENCODER_CMD`.                                                               |
| FLUSH                    | Current encode interrupted. Queued buffers discarded.                                  | Common during seek or pipeline reset. Encoder waits for new valid input after flush.                              |

# Memory and Buffer Management

## DMABuf Usage

For zero-copy pipelines where raw frames originate from a hardware source (camera, GPU, or hardware decoder):

* Set `output-io-mode=dmabuf-import` (value `5`) to import DMABuf handles from upstream directly into the V4L2 output queue without CPU copies
* Set `capture-io-mode=dmabuf` (value `4`) to export encoded output as DMABuf file descriptors for downstream elements

## Alignment Requirements

Input buffers follow Qualcomm hardware alignment requirements (e.g., 128-byte stride alignment). UBWC-compressed input formats (`NV12_Q08C`, `NV12_Q10LE32C`) are supported for reduced memory bandwidth when the upstream source produces UBWC output.

## Encoder Parameter Control

Encoding parameters are configured via the `extra-controls` property using V4L2 control IDs. Common parameters include:

| Control                 | Description                                               |
| ----------------------- | --------------------------------------------------------- |
| `video_bitrate`         | Target bitrate in bits per second                         |
| `video_gop_size`        | GOP (Group of Pictures) size — interval between keyframes |
| `video_hevc_i_frame_qp` | QP value for I-frames                                     |
| `video_hevc_p_frame_qp` | QP value for P-frames                                     |
| `video_hevc_b_frame_qp` | QP value for B-frames                                     |

Example:

```bash theme={null}
extra-controls="controls,video_bitrate=4000000,video_gop_size=30"
```

## Drain and Flush

* **Drain** — sends `V4L2_ENC_CMD_STOP` via `VIDIOC_ENCODER_CMD`; waits for all remaining encoded frames to be produced
* **Flush** — stops both queues, resets buffer pools, and restarts streaming; used during seek operations

# Usage

<Note>
  Ensure you have followed the [prerequisites](v4l2h265enc#example-pipeline) before continuing
</Note>

### Record Camera to H.265 MP4 File

Captures raw video from a camera source, encodes to H.265 with DMABuf zero-copy, and muxes into an MP4 container.

<img src="https://mintcdn.com/qimsdk/xdnKhBBjxpS5mUYP/plugin-reference/images/v4l2h265enc_record_camera.png?fit=max&auto=format&n=xdnKhBBjxpS5mUYP&q=85&s=632f729f54e5bb194026ee6984ea4444" alt="" width="896" height="71" data-path="plugin-reference/images/v4l2h265enc_record_camera.png" />

```bash theme={null}
gst-launch-1.0 -e \
  qticamsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
  queue ! v4l2h265enc output-io-mode=dmabuf-import capture-io-mode=dmabuf ! \
  queue ! h265parse ! mp4mux ! \
  filesink location=$HOME/media/output/output.mp4
```

### Transcode H.264 to H.265

Decodes an H.264 stream from an MP4 file using the hardware decoder and re-encodes to H.265 using the hardware encoder. DMABuf is used for zero-copy transfer between decoder and encoder.

<img src="https://mintcdn.com/qimsdk/xdnKhBBjxpS5mUYP/plugin-reference/images/v4l2h265enc_transcode.png?fit=max&auto=format&n=xdnKhBBjxpS5mUYP&q=85&s=a7cf324f0253b3003bfbc64d903c0f54" alt="" width="1361" height="71" data-path="plugin-reference/images/v4l2h265enc_transcode.png" />

```bash theme={null}
gst-launch-1.0 -e \
  filesrc location=$SRC_VIDEO_NAME ! qtdemux ! h264parse ! \
  v4l2h264dec output-io-mode=4 capture-io-mode=4 ! \
  queue ! v4l2h265enc output-io-mode=5 capture-io-mode=4 ! \
  h265parse ! mp4mux ! \
  filesink location=$HOME/media/output/output_h265.mp4
```

### Four-Stream Simultaneous Encoding

Encodes four concurrent H.265 streams from four sources using four independent hardware encoder instances.

<img src="https://mintcdn.com/qimsdk/xdnKhBBjxpS5mUYP/plugin-reference/images/v4l2h265enc_4streams_encode.png?fit=max&auto=format&n=xdnKhBBjxpS5mUYP&q=85&s=5690d9d8701e15f3c2848ccb26af54a7" alt="" width="941" height="617" data-path="plugin-reference/images/v4l2h265enc_4streams_encode.png" />

```bash theme={null}
gst-launch-1.0 -e \
  videotestsrc num-buffers=200 ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
    queue ! v4l2h265enc output-io-mode=4 capture-io-mode=4 ! \
    h265parse ! mp4mux ! filesink location=$HOME/media/output/output0.mp4 \
  videotestsrc num-buffers=200 ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
    queue ! v4l2h265enc output-io-mode=4 capture-io-mode=4 ! \
    h265parse ! mp4mux ! filesink location=$HOME/media/output/output1.mp4 \
  videotestsrc num-buffers=200 ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
    queue ! v4l2h265enc output-io-mode=4 capture-io-mode=4 ! \
    h265parse ! mp4mux ! filesink location=$HOME/media/output/output2.mp4 \
  videotestsrc num-buffers=200 ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! \
    queue ! v4l2h265enc output-io-mode=4 capture-io-mode=4 ! \
    h265parse ! mp4mux ! filesink location=$HOME/media/output/output3.mp4
```
