Rockchip 视频编解码案例
压缩包包含样片准备脚本 prepare-video.sh,按第 3 节解压运行。视频不包含在压缩包中,脚本从 Blender 官方网站下载《Sintel》,并生成后续案例所需的短片。编解码命令见各案例。
1. 视频编解码简介
本文通过三个案例介绍如何在 ArmSoM 板卡上处理 H.264 和 H.265 视频。案例一用 GStreamer 调用 Rockchip MPP,将 1080p H.264 视频硬解、硬编码为 MP4,并在 HDMI 上回放。案例二用 FFmpeg 做 H.265 软件编解码,再验证 GStreamer 硬件方案。案例三用 MPP 自带工具直接处理两种格式的裸码流和 NV12 原始帧。
H.264(AVC)和 H.265(HEVC)是视频编码格式。解码把压缩码流还原成画面,编码把画面压缩成码流。MP4 是容器,可以封装码流并记录播放时间等信息。第三个案例还会接触两种中间文件:没有 MP4 容器的裸码流,以及解码后未压缩的 NV12 帧。NV12 将亮度和交错的色度分别存放。
| 技术 | 在本文中的作用 | 对应案例 |
|---|---|---|
| GStreamer | 用管线连接解封装、解析、编解码、封装和显示元件。本文用 mppvideodec 硬解,用 mpph264enc 或 mpph265enc 硬编码。 | 案例一、二 |
| FFmpeg | 准备样片、提取码流,并用 ffprobe 检查输出。案例二使用板上自带的 FFmpeg 进行 H.265 软件编解码,再用 GStreamer + MPP 回放输出。 | 案例二,也用于其他案例的文件检查 |
| Rockchip MPP | 为应用提供访问 Rockchip 视频编解码硬件的接口。案例三用 mpi_dec_test 和 mpi_enc_test 分别验证硬解和硬编码,可单独检查 NV12 数据与裸码流。 | 案例三,也是 GStreamer Rockchip 插件使用的底层库 |
第一次验证可播放的 MP4,从案例一开始。想对照 H.265 的软件与硬件流程,读案例二。需要排查裸码流、像素格式或帧步长时,读案例三。
1.1 视频数据如何在管线中流转
MP4 先经过解封装,取出视频轨。解析器整理压缩码流,解码器将码流还原为原始帧。接下来可以把帧交给显示元件,也可以交给编码器,再将新的码流封装为 MP4。
| 阶段 | 本文用到的元件 | 如何检查 |
|---|---|---|
| 读取与解析 | filesrc、qtdemux、h264parse 或 h265parse | 按输入编码格式选解析器。Annex B 裸码流可以跳过 MP4 解封装。 |
| 解码 | mppvideodec | 接 fakesink 时不会显示画面。收到 EOS 表示管线已处理到流末尾。 |
| 编码与保存 | mpph264enc 或 mpph265enc、解析器、mp4mux | 等待 EOS 完成封装,再用 ffprobe 核对编码格式、分辨率、帧率和帧数。 |
| 显示 | xvimagesink | 单独检查桌面会话和显示元件。即使 MP4 正常,显示元件不接受解码帧的格式时也可能无法播放。 |
MPP 工具可以导出 NV12 原始帧。对于宽高均为偶数、无填充的 8 位 NV12,Y 平面占宽 × 高字节,交错的 UV 平面占其一半。硬件缓冲区可能有填充,读取时应使用帧的实际行步长和垂直步长。
2. 实测环境与准备
2.1 适用板型与镜像
ArmSoM SDK 的 ARM64 构建配置覆盖以下板型。这里列出 Debian 12 和 Ubuntu 22.04 两套镜像:
| 芯片 | 板型 | SDK 镜像配置 |
|---|---|---|
| RK3528 | Sige1 | Debian 12 |
| RK3576 | AIM5、CM5(CM5-IO 和 CM4 Nano B IO)、Sige5 | Debian 12、Ubuntu 22.04 |
| RK3588 / RK3588S | AIM7、CM7S、LM7、Sige7、Sige7S | Debian 12、Ubuntu 22.04 |
SDK 的两套 rootfs 都提供 Rockchip MPP 和 GStreamer Rockchip 插件。换用其他板型时,请选对应的官方镜像,先执行第 2.3 节的元件检查,再按第 4 节确认解码正常结束、输出 MP4 通过文件检查。SDK 有构建配置,只说明有对应镜像可用于验证,具体编解码能力还需在板端确认。
硬解和硬编码可以在无桌面环境运行。第 4.1 节的 HDMI 回放命令需要已登录的 X11 桌面,并且 xvimagesink 能正常显示画面。查到元件后,仍需实际播放一次确认 XVideo 可用。本文完整流程在 CM7S 的 Debian 12 XFCE/X11 上实测通过。表中其他板型和镜像组合(含 Ubuntu 22.04)可按同一流程验证。
2.2 本次实测环境
实测板为 ArmSoM CM7S(RK3588S),系统为 Debian 12 arm64 XFCE/X11,内核为 6.1.118-rk3588。HDMI 输出模式为 1920×1080、60 Hz。板上 GStreamer 工具包为 1.22.9-1,Rockchip GStreamer 插件包为 1.14-4,MPP 库为 1.5.0-1。
2.3 安装与检查依赖
刚刷完镜像,请先检查板端时间,再下载样片或运行 APT。时间不准时,在桌面设置中校准当前日期和时间。若 HTTPS 提示证书尚未生效,请校时后重试下载。
date -Is
接好 HDMI 并登录桌面。缺少工具时,先联网,再在板端安装。
实测镜像已自带这些工具。root 用户可以省略 sudo。
更新索引前,请按更新 APT 软件源检查系统时间和软件源。
sudo apt update
sudo apt install gstreamer1.0-tools ffmpeg curl
接着检查 GStreamer 元件。若找不到 MPP 编解码器,请核对板型对应的官方桌面镜像和 Rockchip 插件包。
mkdir -p ~/rockchip-video
cd ~/rockchip-video
for element in qtdemux h264parse mppvideodec mpph264enc mp4mux fpsdisplaysink xvimagesink; do
gst-inspect-1.0 "$element" >/dev/null || break
printf '%s OK\n' "$element"
done
本例使用系统 FFmpeg 准备输入和检查文件。若要使用 FFmpeg 自身的 Rockchip 编解码器或 RGA 滤镜,请参阅 FFmpeg 安装指南。
3. 准备 1080p H.264 视频
离线也可以生成 5 秒、30 fps 的测试图案。生成完成后,将它设为后续步骤的输入。
ffmpeg -nostdin -n -f lavfi -i testsrc2=size=1920x1080:rate=30 -frames:v 150 -c:v libx264 -preset ultrafast -pix_fmt yuv420p input-1080p.mp4
INPUT=input-1080p.mp4
OUTPUT=output-mpp.mp4
联网时可改用 Blender 官方《Sintel》1080p 预告片。使用压缩包中的 prepare-video.sh 从第 12 秒截取 8 秒、移除音轨,并统一为 1080p30。素材 © Blender Foundation | durian.blender.org,采用 CC BY 3.0 许可。
cd ~/rockchip-video
curl -fL https://docs.armsom.org/downloads/rockchip-video/rockchip-video-examples.tar.gz -o rockchip-video-examples.tar.gz
tar -xzf rockchip-video-examples.tar.gz
bash prepare-video.sh
原视频保存在 ~/rockchip-video/sintel-source.mp4,测试短片保存在 ~/rockchip-video/sintel-1080p.mp4。脚本复用已有原视频;若短片已存在,请直接使用,或先重命名再运行。
INPUT=sintel-1080p.mp4
OUTPUT=sintel-output-mpp.mp4
继续案例二和三前,请先在第 3 节准备《Sintel》样片。在同一个终端继续操作,以保留 INPUT 和 OUTPUT。
4. 案例一:H.264 硬解与硬编码输出 MP4
先用 mppvideodec 单独验证硬解。这里不打开窗口,sync=false 让管线尽快处理完输入。
time gst-launch-1.0 filesrc location="$INPUT" ! qtdemux ! h264parse ! mppvideodec ! fakesink sync=false
用 mpph264enc 按 6 Mbps 目标码率编码,再用 mp4mux 封装。
若已有同名文件,请改用新文件名。等待 EOS 后再退出,确保 MP4 完成封装。
time gst-launch-1.0 -e filesrc location="$INPUT" ! qtdemux ! h264parse ! mppvideodec ! mpph264enc bps=6000000 ! h264parse ! mp4mux ! filesink location="$OUTPUT"
先进入工作目录,再查看输出文件。测试图案生成 output-mpp.mp4,《Sintel》生成 sintel-output-mpp.mp4。如果换了终端,请先把 OUTPUT 设为对应的文件名。
cd ~/rockchip-video
ls -lh -- "$OUTPUT"
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,avg_frame_rate,nb_frames:format=duration -of default=nw=1 "$OUTPUT"
4.1 HDMI 回放与板端实测
在 XFCE/X11 桌面回放,统计写入 ~/rockchip-video/playback-xv.log。
桌面终端可沿用当前 DISPLAY。从串口运行时,请将 :0 换成实际的显示编号。
DISPLAY=:0 gst-launch-1.0 -v filesrc location="$OUTPUT" ! qtdemux ! h264parse ! mppvideodec ! fpsdisplaysink video-sink=xvimagesink text-overlay=false sync=true > playback-xv.log 2>&1
echo "PLAY_EXIT=$?"
grep -E 'rendered:|Got EOS' playback-xv.log | tail -4
| CM7S 合成样片测试 | 结果 |
|---|---|
| 输入与输出 | H.264、1920×1080、30 fps、150 帧、5 秒 |
| 仅硬解耗时 | 0.231 秒 |
| 硬解、硬编码与封装耗时 | 0.676 秒 |
| 输出文件 | output-mpp.mp4,约 3.5 MiB |
| HDMI 回放 | 正常收到 EOS,退出码 0。末次周期统计为 140 帧已渲染、0 帧丢弃、平均 30.12 fps |
耗时为单次运行结果。回放统计采样早于 EOS,反映显示元件的帧数,不代表显示器刷新率。
实测中,直连 ximagesink 会出现格式协商错误,加 videoconvert 后仍有丢帧。本文使用 xvimagesink。
4.2 《Sintel》预告片实测
公开样片同样在 CM7S 上通过测试。输出为 H.264、1920×1080、30 fps,保留全部 240 帧(8 秒)。仅硬解耗时 0.322 秒,硬解、硬编码与封装耗时 1.310 秒,输出文件大小为 5,355,119 字节。HDMI 回放正常收到 EOS,退出码为 0。末次周期采样显示已渲染 236 帧、丢弃 0 帧,平均 30.23 fps。

Sintel © Blender Foundation | durian.blender.org · CC BY 3.0
5. 案例二:用 FFmpeg 和 GStreamer 处理 H.265
5.1 FFmpeg 软件编解码
实测镜像自带的 FFmpeg 未列出 RKMPP 编解码器。本节截取《Sintel》的另一段 4 秒画面,用 CPU 上的 libx265 编码,再用 FFmpeg 软件解码验收,最后用 MPP 回放输出。FFmpeg 编码 120 帧耗时 23.25 秒(5.16 fps),软件解码退出码为 0。下图是 FFmpeg 输出文件在板端经 MPP 回放的画面。
mkdir -p ~/rockchip-video/advanced
cd ~/rockchip-video/advanced
ffmpeg -nostdin -n -ss 19 -i ../sintel-source.mp4 -t 4 -an -r 30 -c:v libx265 -preset ultrafast -x265-params pools=2 -pix_fmt yuv420p sintel-ffmpeg-hevc.mp4
ffmpeg -nostdin -v error -xerror -i sintel-ffmpeg-hevc.mp4 -f null -
DISPLAY=:0 gst-launch-1.0 filesrc location=sintel-ffmpeg-hevc.mp4 ! qtdemux ! h265parse ! mppvideodec ! xvimagesink

5.2 GStreamer 硬件编解码
用第 3 节的 sintel-1080p.mp4 硬转码为 HEVC,再用 MPP 硬解验收。输出位于 ~/rockchip-video/advanced/output-hevc.mp4。
若已有同名文件,请改用新文件名。
检查 H.265 硬件编码器和码流解析器。
gst-inspect-1.0 mpph265enc
gst-inspect-1.0 h265parse创建并进入工作目录。
mkdir -p ~/rockchip-video/advanced
cd ~/rockchip-video/advanced硬转码为 H.265 MP4,等待封装完成后再继续。
gst-launch-1.0 -e filesrc location=../sintel-1080p.mp4 ! qtdemux ! h264parse ! mppvideodec ! mpph265enc bps=6000000 ! h265parse ! mp4mux ! filesink location=output-hevc.mp4单独验证输出文件的硬解。看到
Got EOS表示管线读到文件末尾。fakesink不显示画面。gst-launch-1.0 filesrc location=output-hevc.mp4 ! qtdemux ! h265parse ! mppvideodec ! fakesink sync=false单独检查输出文件。预期为
hevc、1920×1080、30 fps、240 帧。ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,avg_frame_rate,nb_frames -of default=nw=1 output-hevc.mp4
CM7S 上两条 GStreamer 管线均正常退出。输出为 HEVC、1920×1080、30 fps、240 帧。这里验证的是文件转码和无窗口硬解,前面的 HDMI 截图对应 H.264 输出。
6. 案例三:直接使用 MPP 工具验证 H.264 和 H.265
实测镜像的 rockchip-mpp-demos(1.5.0-1)已提供两个工具。使用第 3 节的 H.264 样片和第 5.2 节的 HEVC MP4。
至少预留 400 MiB 磁盘空间,并先保留同名输出文件。
command -v mpi_dec_test mpi_enc_test
cd ~/rockchip-video/advanced
提取 H.264 码流,再硬解、硬编码 60 帧。
ffmpeg -nostdin -n -i ../sintel-1080p.mp4 -an -c:v copy -bsf:v h264_mp4toannexb input.h264
mpi_dec_test -i input.h264 -t 7 -n 60 -f 0 -o decoded.nv12
mpi_enc_test -i decoded.nv12 -w 1920 -h 1080 -hstride 1920 -vstride 1080 -f 0 -t 7 -n 60 -fps 30 -bps 6000000 -o encoded.h264
用第 5.2 节生成的 H.265 文件重复测试。
ffmpeg -nostdin -n -i output-hevc.mp4 -an -c:v copy -bsf:v hevc_mp4toannexb input.hevc
mpi_dec_test -i input.hevc -t 16777220 -n 60 -f 0 -o decoded-hevc.nv12
mpi_enc_test -i decoded-hevc.nv12 -w 1920 -h 1080 -hstride 1920 -vstride 1080 -f 0 -t 16777220 -n 60 -fps 30 -bps 6000000 -o encoded.hevc
检查两份编码产物是否各有 60 帧。
for file in encoded.h264 encoded.hevc; do
ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=codec_name,width,height,nb_read_frames -of default=nw=1 "$file"
done
FFmpeg 的 -c:v copy 只提取码流,位流过滤器将 MP4 中的码流转换成 Annex B。MPP 工具使用 -t 7 表示 H.264,-t 16777220 表示 H.265,-f 0 表示 NV12。每种格式只测试 60 帧,产物位于 ~/rockchip-video/advanced/。
| 输入 | 解码产物 | 硬编码产物 | 板端复核 |
|---|---|---|---|
| H.264 | decoded.nv12 | encoded.h264 | H.264,1920×1080,60 帧 |
| H.265 | decoded-hevc.nv12 | encoded.hevc | HEVC,1920×1080,60 帧 |
测试工具导出的 NV12 文件各为 186,624,000 字节,使用紧凑布局。读取硬件帧时,应从元数据获取行步长和垂直步长。
开发 C/C++ 程序时,可从 SDK 的 MPP 开发包和 demos 入手。初始化上下文后提交输入、取出结果,在 EOS 后取完剩余帧并释放资源。分辨率或布局变化时,按新的帧信息准备缓冲区。
6.1 回放 MPP 裸码流
直接回放 mpi_enc_test 生成的 HEVC 裸码流。文件没有 MP4 容器,管线从 h265parse 开始,无需 qtdemux。
cd ~/rockchip-video/advanced
DISPLAY=:0 gst-launch-1.0 filesrc location=encoded.hevc ! h265parse ! mppvideodec ! xvimagesink

Sintel © Blender Foundation | durian.blender.org · CC BY 3.0
