风的彷徨 · 10月22日 · 山东

【“星睿O6”AI PC开发套件评测】VPU编解码能力测评

瑞莎星睿 O6 (Radxa Orion O6) 是一款面向 AI 计算和多媒体应用的专业级 Mini-ITX 主板。相信很多同学买来这个板子是用来做NAS或者家庭影院的,于是这个板子的视频编解码能力和功耗就成为选购板子的重要指标。

星睿O6采用Armv9架构CPU,Arm Immortalis™ GPU,以及有额外的VPU(视频处理器)和NPU。Armv9架构本就相对省电,再Armv9基础上还有单独的VPU实现硬件加速,相信在视频处理上能更上一层楼。让我们看看星睿O6具体的表现吧。

开箱!

IMG_20251015_223933.jpg
箱子外包装上写着4K
IMG_20251016_155204.jpg

背面是产品的规格说明,台积电6nm工艺,双5G网卡(软路由狂喜),最高支持DP 4k@120Hz输出。目光转移到VPU(Codec)上:

  • 支持AV1 H265 H264 等常见的视频解码
  • 支持H265 H264的视频编码

不支持AV1的视频编码还是比较可惜。虽然H265在大多数情况下也够用了。

IMG_20251015_224311.jpg

IMG_20251015_224333.jpg

上电后的效果

IMG_20251015_234945.jpg

进系统功耗(系统为Debian & Gnome)为12W左右,感觉静态情况下功耗还是比较大的,要是能更小一点就好了。

查看编码器状态

O6的VPU采用标准的V4L2接口,可以这样查看

cix@cix-localhost:~$ ls /dev/ | grep 'video'
video-cixdec0
video0
video1

有两个视频处理设备,其中一个是编码器,一个是解码器。

使用v4l2看看哪个是编码器,哪个是解码器:

cix@cix-localhost:~$ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture Multiplanar

        [0]: 'Y0A8' (YUV420 AFBC 8 bit)
        [1]: 'Y0AA' (YUV420 AFBC 10 bit)
        [2]: 'Y2A8' (YUV422 AFBC 8 bit)
        [3]: 'Y2AA' (YUV422 AFBC 10 bit)
        [4]: 'YXA8' (GREY AFBC 8 bit)
        [5]: 'YXAA' (GREY AFBC 10 bit)
        [6]: 'NM12' (Y/UV 4:2:0 (N-C))
        [7]: 'NV12' (Y/UV 4:2:0)
        [8]: 'YM12' (Planar YUV 4:2:0 (N-C))
        [9]: 'YU12' (Planar YUV 4:2:0)
        [10]: 'NM21' (Y/VU 4:2:0 (N-C))
        [11]: 'NV21' (Y/VU 4:2:0)
        [12]: 'M010' (YUV 4:2:0 P010 (Microsoft forma)
        [13]: 'P010' (10-bit Y/UV 4:2:0)
        [14]: 'YUYV' (YUYV 4:2:2)
        [15]: 'UYVY' (UYVY 4:2:2)
        [16]: 'Y210' (10-bit YUYV Packed)
        [17]: 'RGB3' (24-bit RGB 8-8-8)
        [18]: 'RGBM' (24-bit RGB 8-8-8 3PLANNER)
        [19]: 'GREY' (8-bit Greyscale)
        [20]: 'Y10L' (10-bit GREY 16BIT LSB 1PLANNER)

video0输入的是原始的像素信息,说明这个是个编码器

cix@cix-localhost:~$ v4l2-ctl -d /dev/video1 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture Multiplanar

        [0]: 'H264' (H.264, compressed)
        [1]: 'HEVC' (HEVC, compressed)
        [2]: 'VP80' (VP8, compressed)
        [3]: 'VP90' (VP9, compressed)
        [4]: 'JPEG' (JFIF JPEG, compressed)
        [5]: 'MJPG' (Motion-JPEG, compressed)

video1输入的是视频码流,说明这个是解码器。

ffmpeg可以直接使用这个VPU

cix@cix-localhost:~$ ffmpeg -encoders | grep 'v4l2'
ffmpeg version 5.1.6-0+deb12u1+cix Copyright (c) 2000-2024 the FFmpeg 
...
DSP API version: DSP Wrapper Build On Jun 10 2025 23:33:39 c1e3772
 V..... h263_v4l2m2m         V4L2 mem2mem H.263 encoder wrapper (codec h263)
 V..... h264_v4l2m2m         V4L2 mem2mem H.264 encoder wrapper (codec h264)
 V..... hevc_v4l2m2m         V4L2 mem2mem HEVC encoder wrapper (codec hevc)
 V..... mpeg4_v4l2m2m        V4L2 mem2mem MPEG4 encoder wrapper (codec mpeg4)
 V..... vp8_v4l2m2m          V4L2 mem2mem VP8 encoder wrapper (codec vp8)
 
 
cix@cix-localhost:~$ ffmpeg -decoders | grep 'v4l2'
ffmpeg version 5.1.6-0+deb12u1+cix Copyright (c) 2000-2024 the FFmpeg 
...
DSP API version: DSP Wrapper Build On Jun 10 2025 23:33:39 c1e3772
 V..... av1_v4l2m2m          V4L2 mem2mem AV1 decoder wrapper (codec av1)
 V..... h263_v4l2m2m         V4L2 mem2mem H.263 decoder wrapper (codec h263)
 V..... h264_v4l2m2m         V4L2 mem2mem H.264 decoder wrapper (codec h264)
 V..... hevc_v4l2m2m         V4L2 mem2mem HEVC decoder wrapper (codec hevc)
 V..... mpeg1_v4l2m2m        V4L2 mem2mem MPEG1 decoder wrapper (codec mpeg1video)
 V..... mpeg2_v4l2m2m        V4L2 mem2mem MPEG2 decoder wrapper (codec mpeg2video)
 V..... mpeg4_v4l2m2m        V4L2 mem2mem MPEG4 decoder wrapper (codec mpeg4)
 V..... vc1_v4l2m2m          V4L2 mem2mem VC1 decoder wrapper (codec vc1)
 V..... vp8_v4l2m2m          V4L2 mem2mem VP8 decoder wrapper (codec vp8)
 V..... vp9_v4l2m2m          V4L2 mem2mem VP9 decoder wrapper (codec vp9)

可以看出可以使用ffmpeg直接编码h263、h264、h265、mpeg4、vp8,解码av1、h263、h264、h265、mpeg、vc1、vp8、vp9

编解码测试

为了方便测试编解码性能,我Vibe Coding了一个脚本用来统计性能的脚本

#!/bin/bash

# FFmpeg 性能测试脚本
#
# 这个脚本会测试不同编解码器 (H.264, H.265, AV1) 在不同硬件加速模式下的性能
# 包括 CPU, VA-API, NVENC/NVDEC, Vulkan, 和 V4L2.
#
# 使用方法:
# 1. 将输入视频文件 'hevc_4k60P_main_dji_mavic3.mov' 放置在与此脚本相同的目录中。
# 2. 赋予脚本执行权限: chmod +x ffmpeg_benchmark.sh
# 3. 运行脚本: ./ffmpeg_benchmark.sh

# --- 配置 ---
INPUT_FILE="hevc_4k60P_main_dji_mavic3.mov"
LOG_DIR="ffmpeg_logs"
RESULTS_FILE="performance_results.csv"
RESOLUTION="3840x2160" # 输入视频的分辨率,用于编码测试

# --- 检查输入文件 ---
if [ ! -f "$INPUT_FILE" ]; then
    echo "错误: 输入文件 '$INPUT_FILE' 未找到。"
    echo "请将视频文件放置在脚本所在的目录中。"
    exit 1
fi

# --- 初始化 ---
mkdir -p "$LOG_DIR"
echo "测试名称,耗时 (秒),帧率 (FPS),备注" > "$RESULTS_FILE"
echo "FFmpeg 性能测试已开始..."
echo "详细日志将保存在 '$LOG_DIR' 目录中。"
echo "结果将汇总到 '$RESULTS_FILE' 文件中。"
echo "============================================================"

# --- 辅助函数 ---
# $1: 测试名称
# $2: ffmpeg 命令字符串
run_test() {
    local test_name="$1"
    local command_str="$2"
    local log_file="${LOG_DIR}/${test_name//\//_}.log"
    local start_time time_taken fps

    echo -n "正在运行测试: $test_name..."

    # 使用 `time` 命令来测量真实时间
    # 将 stderr 和 stdout 都重定向到日志文件和管道
    start_time=$(date +%s.%N)
    (eval "$command_str") > "$log_file" 2>&1
    local exit_code=$?
    time_taken=$(echo "$(date +%s.%N) - $start_time" | bc)

    if [ $exit_code -ne 0 ]; then
        echo " 失败"
        echo "$test_name,N/A,N/A,失败 (查看日志: $log_file)" >> "$RESULTS_FILE"
        return
    fi

    # 从 ffmpeg 输出中提取 FPS
    # 兼容不同 ffmpeg 版本的输出格式
    fps=$(grep -oP 'fps=\s*\K[0-9.]+' "$log_file" | tail -n 1)
    if [ -z "$fps" ]; then
        # 如果找不到 'fps=', 尝试从 benchmark 输出中提取
        local total_frames=$(grep -oP 'frame=\s*\K[0-9]+' "$log_file" | tail -n 1)
        if [ -n "$total_frames" ] && [ "$total_frames" -gt 0 ] && (( $(echo "$time_taken > 0" | bc -l) )); then
            fps=$(echo "scale=2; $total_frames / $time_taken" | bc)
        else
            fps="N/A"
        fi
    fi

    echo " 完成"
    echo "$test_name,$time_taken,$fps,成功" >> "$RESULTS_FILE"
}

# ============================================================
# 解码性能测试 (DECODING)
# 将解码后的数据丢弃 (-f null -)
# ============================================================
echo -e "\n--- 开始解码性能测试 ---"

# 1. HEVC/H.265 解码
run_test "Decode-HEVC-CPU" "ffmpeg -benchmark -i $INPUT_FILE -f null -"
run_test "Decode-HEVC-VAAPI" "ffmpeg -benchmark -hwaccel vaapi -hwaccel_output_format vaapi -i $INPUT_FILE -f null -"
run_test "Decode-HEVC-NVDEC" "ffmpeg -benchmark -hwaccel cuda -hwaccel_output_format cuda -i $INPUT_FILE -f null -"
run_test "Decode-HEVC-VULKAN" "ffmpeg -benchmark -hwaccel vulkan -hwaccel_output_format vulkan -i $INPUT_FILE -f null -"
# V4L2 需要指定解码器
run_test "Decode-HEVC-V4L2" "ffmpeg -benchmark -c:v hevc_v4l2m2m -i $INPUT_FILE -f null -"

# 2. H.264 解码 (需要先将输入文件转码为 H.264)
H264_TEMP_FILE="${LOG_DIR}/temp_h264_for_decoding.mp4"
echo -n "准备 H.264 测试文件..."
ffmpeg -y -i "$INPUT_FILE" -c:v libx264 -preset ultrafast -f mp4 "$H264_TEMP_FILE" > "${LOG_DIR}/temp_h264_prep.log" 2>&1
echo " 完成"
run_test "Decode-H264-CPU" "ffmpeg -benchmark -i $H264_TEMP_FILE -f null -"
run_test "Decode-H264-VAAPI" "ffmpeg -benchmark -hwaccel vaapi -hwaccel_output_format vaapi -i $H264_TEMP_FILE -f null -"
run_test "Decode-H264-NVDEC" "ffmpeg -benchmark -hwaccel cuda -hwaccel_output_format cuda -i $H264_TEMP_FILE -f null -"
run_test "Decode-H264-VULKAN" "ffmpeg -benchmark -hwaccel vulkan -hwaccel_output_format vulkan -i $H264_TEMP_FILE -f null -"
run_test "Decode-H264-V4L2" "ffmpeg -benchmark -c:v h264_v4l2m2m -i $H264_TEMP_FILE -f null -"

# 3. AV1 解码 (需要先将输入文件转码为 AV1)
AV1_TEMP_FILE="${LOG_DIR}/temp_av1_for_decoding.mkv"
echo -n "准备 AV1 测试文件 (这可能需要一些时间)..."
# 使用速度最快的 AV1 CPU 编码器 `libsvtav1`,如果不支持则跳过
if ffmpeg -encoders | grep -q 'libsvtav1'; then
    ffmpeg -y -i "$INPUT_FILE" -c:v libsvtav1 -preset 10 -g 240 -f matroska "$AV1_TEMP_FILE" > "${LOG_DIR}/temp_av1_prep.log" 2>&1
    echo " 完成"
    run_test "Decode-AV1-CPU" "ffmpeg -benchmark -i $AV1_TEMP_FILE -f null -"
    run_test "Decode-AV1-VAAPI" "ffmpeg -benchmark -hwaccel vaapi -hwaccel_output_format vaapi -i $AV1_TEMP_FILE -f null -"
    run_test "Decode-AV1-NVDEC" "ffmpeg -benchmark -hwaccel cuda -hwaccel_output_format cuda -i $AV1_TEMP_FILE -f null -"
    run_test "Decode-AV1-VULKAN" "ffmpeg -benchmark -hwaccel vulkan -hwaccel_output_format vulkan -i $AV1_TEMP_FILE -f null -"
    run_test "Decode-AV1-V4L2" "ffmpeg -benchmark -c:v av1_v4l2m2m -i $AV1_TEMP_FILE -f null -"
else
    echo " 跳过 (libsvtav1 编码器不可用)"
fi


# ============================================================
# 编码性能测试 (ENCODING)
# 从解码后的原始 YUV 流进行编码,以保证输入一致
# ============================================================
echo -e "\n--- 开始编码性能测试 ---"

# 1. H.264 编码
run_test "Encode-H264-CPU" "ffmpeg -benchmark -i $INPUT_FILE -c:v libx264 -preset medium -f null -"
run_test "Encode-H264-VAAPI" "ffmpeg -benchmark -i $INPUT_FILE -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' -c:v h264_vaapi -f null -"
run_test "Encode-H264-NVENC" "ffmpeg -benchmark -i $INPUT_FILE -c:v h264_nvenc -preset p5 -tune hq -f null -"run_test "Encode-H264-V4L2" "ffmpeg -benchmark -i $INPUT_FILE -c:v h264_v4l2m2m -f null -"

# 2. HEVC/H.265 编码
run_test "Encode-HEVC-CPU" "ffmpeg -benchmark -i $INPUT_FILE -c:v libx265 -preset medium -f null -"
run_test "Encode-HEVC-VAAPI" "ffmpeg -benchmark -i $INPUT_FILE -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' -c:v hevc_vaapi -f null -"
run_test "Encode-HEVC-NVENC" "ffmpeg -benchmark -i $INPUT_FILE -c:v hevc_nvenc -preset p5 -tune hq -f null -"run_test "Encode-HEVC-V4L2" "ffmpeg -benchmark -i $INPUT_FILE -c:v hevc_v4l2m2m -f null -"

# 3. AV1 编码
run_test "Encode-AV1-CPU(SVT)" "ffmpeg -benchmark -i $INPUT_FILE -c:v libsvtav1 -preset 8 -f null -"
run_test "Encode-AV1-VAAPI" "ffmpeg -benchmark -i $INPUT_FILE -vaapi_device /dev/dri/renderD128 -vf 'format=nv12,hwupload' -c:v av1_vaapi -f null -"
run_test "Encode-AV1-NVENC" "ffmpeg -benchmark -i $INPUT_FILE -c:v av1_nvenc -preset p5 -tune hq -f null -"
# V4L2 的 AV1 编码器名称可能不同,这里使用一个通用名称
run_test "Encode-AV1-V4L2" "ffmpeg -benchmark -i $INPUT_FILE -c:v av1_v4l2m2m -f null -"

# --- 清理临时文件 ---
rm -f "$H264_TEMP_FILE" "$AV1_TEMP_FILE"

# --- 显示结果 ---
echo "============================================================"
echo "所有测试完成。性能摘要:"
echo "============================================================"
column -s, -t < "$RESULTS_FILE"
echo "============================================================"
echo "CSV 格式的结果已保存到: $RESULTS_FILE"

性能对比

测试环境:
视频 4k@60fps

笔记本CPU:i9 13900hx

笔记本GPU:4060Laptop

笔记本系统:Win11 WSL

首先来看看解码器情况:
image-20251016171506319.png

O6的VPU远远地甩开了CPU的解码性能,接近4060Laptop的编码效果。

image-20251016171526715.png

H265的表现和AV1也类似。

image-20251016171546042.png
H264有些不一样。CPU解码也非常快甚至反超了VPU,但是意外的是CPU解码速度甚至比i9 13900HX还要快,可能是因为软件优化的比较好。

image-20251016171606197.png

比较可惜,O6的VPU不兼容编码AV1,CPU编码AV1目前也是处于一个不太可用的状态。

image-20251016171619791.png

在编码H265视频中,VPU的性能远远甩开了CPU的性能,大约是4060Laptop一半的性能。

image-20251016171630451.png

H264情况和H265差不多。

推荐阅读
关注数
1
内容数
2
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息