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

# 使用 qrb_ros_video 编码和解码视频

`qrb_ros_video` 示例应用是一个 ROS 包，可在 Qualcomm 机器人平台上提供硬件加速的视频处理。它使用 Qualcomm 视频处理单元 (VPU) 将原始 YUV 帧编码为 H.264 或 H.265 流，并将这些流解码回原始帧。缓冲区通过 `qrb_ros_transport` 作为 DMA 缓冲区传递，因此帧传递无需拷贝，并且编码器可直接从 `qrb_ros_camera` 接受输入。

<Note>
  **注意**

  有关更多信息，请参见 [qrb\_ros\_video](https://github.com/qualcomm-qrb-ros/qrb_ros_video) GitHub 仓库。
</Note>

## `qrb_ros_video` 的流水线流程

`encoder_launch.py` 和 `decoder_launch.py` 启动文件启动两个独立的可组合节点容器，每个容器在各自的命名空间中运行。编码器容器使用 `ImageReader` 读取原始帧，对其进行编码，并使用 `CompressedWriter` 将压缩流写入文件。解码器容器使用 `CompressedReader` 读取压缩流，对其进行解码，并使用 `ImageWriter` 写入帧。如果你重映射编码器的输入，编码器也可以直接从 `qrb_ros_camera` 接受帧。

<img
  src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/QIR-SDK-2.0/media/80-65220-2-qirp-sdk-qsg/qrb-ros-video-pipeline-regenerate.svg"
  style={{
width: "100%",
display: "block",
margin: "0 auto" }}
/>

<p style={{ textAlign: 'center', fontWeight: 'bold' }}>
  图：qrb\_ros\_video 流水线
</p>

## `qrb_ros_video` 流水线中使用的 ROS 节点

|             **ROS 节点**             |                    **说明**                    |
| :--------------------------------: | :------------------------------------------: |
|      `qrb_ros::video::Encoder`     | 使用 Qualcomm VPU 将原始图像转换为压缩的 H.264 或 H.265 流。 |
|      `qrb_ros::video::Decoder`     |         将压缩的 H.264 或 H.265 流解码回原始图像帧。        |
|    `qrb_ros::video::ImageReader`   |            从文件读取原始 YUV 帧并将其发布到编码器。           |
|    `qrb_ros::video::ImageWriter`   |                订阅解码后的帧并将其写入文件。               |
| `qrb_ros::video::CompressedReader` |              从文件读取压缩流并将其发布到解码器。              |
| `qrb_ros::video::CompressedWriter` |                 订阅压缩流并将其写入文件。                |

## `qrb_ros_video` 流水线中使用的 ROS topic

|                 **ROS topic**                |               **消息类型**              |                         **发布者/订阅者**                        |         **说明**         |
| :------------------------------------------: | :---------------------------------: | :--------------------------------------------------------: | :--------------------: |
|      `/recording_ns/encoder_node/input`      |  `qrb_ros::transport::type::Image`  |    由 `reader_node`（`ImageReader`）发布，由 `encoder_node` 订阅。   |       未压缩的 YUV 帧。      |
| `/recording_ns/writer_node/compressed_image` | `sensor_msgs::msg::CompressedImage` | 由 `encoder_node` 发布，由 `writer_node`（`CompressedWriter`）订阅。 | 压缩的 H.264 或 H.265 视频流。 |
|       `/playback_ns/decoder_node/input`      | `sensor_msgs::msg::CompressedImage` | 由 `reader_node`（`CompressedReader`）发布，由 `decoder_node` 订阅。 | 压缩的 H.264 或 H.265 视频流。 |
|     `/playback_ns/writer_node/raw_image`     |  `qrb_ros::transport::type::Image`  |    由 `decoder_node` 发布，由 `writer_node`（`ImageWriter`）订阅。   |       解码后的 YUV 帧。      |

<Note>
  **注意**

  每个节点将其端点声明为相对名称 `input` 和 `output`。启动文件将它们重映射为上述名称，并将每个节点放置在 `recording_ns` 或 `playback_ns` 命名空间中，因此 `/input` 和 `/output` 在运行时不存在。运行 `ros2 topic list` 查看有效名称。
</Note>

## `qrb_ros_video` 的 ROS 参数

**表：编码器参数**

| **参数**         | **类型** | **默认值**    | **说明**                                                |
| :------------- | :----- | :--------- | :---------------------------------------------------- |
| `format`       | string | `h264`     | 视频编解码器格式：`h264` 或 `h265`。                             |
| `pixel-format` | string | `nv12`     | 输入像素格式：`nv12` 或 `p010`。                               |
| `width`        | int    | `1920`     | 视频宽度。                                                 |
| `height`       | int    | `1080`     | 视频高度。                                                 |
| `framerate`    | int    | `30`       | 每秒帧数。                                                 |
| `bitrate`      | int    | `5000000`  | 目标比特率，单位为每秒比特数。`encoder_launch.py` 会将其覆盖为 `20000000`。 |
| `rate-control` | string | `variable` | 码率控制模式：`variable` 或 `cbr`。                            |
| `profile`      | string | `main`     | 编解码器配置文件：`baseline`、`main` 或 `high`。                  |
| `level`        | string | `4.1`      | 编解码器级别。                                               |

**表：解码器参数**

| **参数**         | **类型** | **默认值** | **说明**    |
| :------------- | :----- | :------ | :-------- |
| `format`       | string | `h264`  | 输入编解码器格式。 |
| `pixel-format` | string | `nv12`  | 输出像素格式。   |

## 前提条件

* 你已根据 [设置运行示例应用的环境](./set-up-env-for-sample-app) **设置设备**。

## 开箱即用运行 `qrb_ros_video`

<Accordion title="试一试">
  <Steps>
    <Step title="设置运行环境">
      在设备上启动命令行终端并运行以下命令。

      ```bash theme={null}
      ssh root@[ip-addr]
      ```

      ```bash title="SSH Session" theme={null}
      source /usr/share/qirp-setup.sh
      export ROS_DOMAIN_ID=xx
      ```

      <Note>
        **注意**

        `ROS_DOMAIN_ID` 的取值范围：\[0, 232]
      </Note>
    </Step>

    <Step title="编码本地 YUV 文件">
      1. 将原始 YUV 示例文件拷贝到设备上的 `/data/` 目录。
         ```bash theme={null}
         scp 1920_1080_nv12.yuv root@[ip-addr]:/data/
         ```
      2. 运行编码器。
         ```bash title="SSH Session" theme={null}
         ros2 launch qrb_ros_video encoder_launch.py
         ```
         `reader_node` 读取 `/data/1920_1080_nv12.yuv`，`writer_node` 将编码后的流写入 `/data/1920_1080_nv12.mp4`。可通过相应节点的 `url` 参数覆盖任一路径。
    </Step>

    <Step title="解码本地视频文件">
      1. 将视频示例文件拷贝到设备上的 `/data/` 目录。
         ```bash theme={null}
         scp 1920_1080.mp4 root@[ip-addr]:/data/
         ```
      2. 运行解码器。
         ```bash title="SSH Session" theme={null}
         ros2 launch qrb_ros_video decoder_launch.py
         ```
         `reader_node` 读取 `/data/1920_1080.mp4`。`writer_node` 默认将解码后的帧写入 `/dev/null`，因此不会生成输出文件；设置其 `url` 参数以保留解码后的 YUV。
    </Step>

    <Step title="验证 ROS topic">
      在第二个 SSH 终端中，列出 topic 并检查编码器或解码器发布的流。

      ```bash title="SSH Session" theme={null}
      source /usr/share/qirp-setup.sh
      export ROS_DOMAIN_ID=xx
      ros2 topic list
      ros2 topic hz /recording_ns/writer_node/compressed_image
      ros2 topic hz /playback_ns/writer_node/raw_image
      ```
    </Step>
  </Steps>
</Accordion>

## 构建并运行 `qrb_ros_video`

<Accordion title="试一试">
  <Steps>
    <Step title="在主机上克隆 qrb_ros_video">
      ```bash theme={null}
      cd <qirp_decompressed_workspace>
      source setup.sh
      git clone -b stable/0.1.7 https://github.com/qualcomm-qrb-ros/qrb_ros_video.git
      ```
    </Step>

    <Step title="在主机上构建 qrb_ros_video">
      ```bash theme={null}
      cd qrb_ros_video
      colcon build --merge-install --cmake-args ${CMAKE_ARGS}
      ```
    </Step>

    <Step title="将 qrb_ros_video 推送到设备">
      ```bash theme={null}
      cd qrb_ros_video/install
      tar czvf qrb_ros_video.tar.gz lib share include
      scp qrb_ros_video.tar.gz root@[ip-addr]:/opt/
      ssh root@[ip-addr]
      ```

      ```bash title="SSH Session" theme={null}
      tar --no-overwrite-dir --no-same-owner -zxf /opt/qrb_ros_video.tar.gz -C /usr/ros/jazzy/
      ```
    </Step>

    <Step title="在设备上运行 qrb_ros_video">
      按照 [开箱即用运行 qrb\_ros\_video](#run-out-of-the-box-qrb_ros_video) 在设备上运行 `qrb_ros_video`。
    </Step>
  </Steps>
</Accordion>

## 限制

* 硬件加速的编码和解码需要 Qualcomm VPU，因此设备上必须启用视频叠加层。
* 支持的编解码器格式为 H.264 和 H.265。支持的输入像素格式为 NV12 和 P010。
