VPU
功能描述
MTT E300 SoC 内的 VPU(Video Processing Unit)模块包含多个视频编 解码器(codec),可用于视频和图像的编解码处理。在 Linux 系统中,VPU 驱动支持开源的 VA-API 标准,用户可基于 FFmpeg + VA-API 进行开发。此外,摩尔线程(MT)还提供了一套 Codec SDK(Direct Stream),该 SDK 对底层的 VA-API 接口进行了封装,用户也可基于此 SDK 进行开发。
VPU 内共有 5 个编解码核心:
core0[SMD]: 用于解码 H.264、H.265、AV1、VP9、AVS2 格式的视频
core1[SMD]: 用于解码 H.264、H.265、AV1、VP9、AVS2 格式的视频
core2[SMB]: 用于解码 MPEG2、MPEG4、VP8、AVS 格式的视频
core3[SMJ]: 用于编解码 JPEG 图片
core4[SME]: 用于编码 H.264、H.265、AV1 格式的视频
快速开始
验证驱动安装
系统默认已安装 MUSA 驱动。如需手动安装或更新,请参考 MUSA 安装。
确认 MUSA 驱动包已正确安装:
dpkg -l musa
||/ Name Version Architecture Description
+++-==============-===============-============-=================================
ii musa 5.1.0-M1000 arm64 Moore Threads MUSA driver
确认 VPU 固件 mtvpu*.bin 已安装:
ls -al /lib/firmware/mthreads
-rw-r--r-- 1 root root 133120 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-00-1.0.bin
-rw-r--r-- 1 root root 1590528 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-01-1.0.bin
-rw-r--r-- 1 root root 1590528 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-01-2.0.bin
-rw-r--r-- 1 root root 1073408 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-01-3.0.bin
-rwxr-xr-x 1 root root 213184 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-02-1.0.bin
-rw-r--r-- 1 root root 210368 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-02-2.0.bin
-rwxr-xr-x 1 root root 331904 Jun 17 08:15 /lib/firmware/mthreads/mtvpu-02-3.0.bin
确认视频驱动已安装:
ls -al /usr/lib/aarch64-linux-gnu/dri/ | grep m.*video
-rwxr-xr-x 1 dev dev 556600 Jun 23 11:45 /usr/lib/aarch64-linux-gnu/dri/mtgpu_drv_video_1.so
-rwxr-xr-x 1 dev dev 10262440 Jun 23 11:45 /usr/lib/aarch64-linux-gnu/dri/mtgpu_drv_video_2.so
-rwxr-xr-x 1 dev dev 15056 Jun 23 11:45 /usr/lib/aarch64-linux-gnu/dri/mtgpu_drv_video.so
确认 GPU 设备节点已创建:
ls /dev/dri
by-path card0 renderD128
确认 VPU 驱动正确加载:
dmesg | grep mtvpu
[ 0.658628] [mtvpu] Init Native, Version 30dc2e0
[ 0.658906] [mtvpu] dec core:0 offset:0 available
[ 0.658908] [mtvpu] dec core:1 offset:1 available
[ 0.658910] [mtvpu] dec core:2 offset:14 available
[ 0.658911] [mtvpu] jpu core:3 available
[ 0.658913] [mtvpu] enc core:4 offset:8 available
[ 0.659080] [mtvpu] core 0, mem base 0xff
[ 0.659083] [mtvpu] core 1, mem base 0xfe
[ 0.659084] [mtvpu] core 2, mem base 0xff
[ 0.659085] [mtvpu] core 3, mem base 0xff
[ 0.659086] [mtvpu] core 4, mem base 0xff
[ 0.659087] [mtvpu] iommu init done.
[ 0.659179] [mtvpu] sync task 0 start
确认 VPU 调试节点正常:
cat /sys/kernel/debug/mtvpu0/info
core 0 utilize 0%
core 1 utilize 0%
core 2 utilize 0%
core 3 utilize 0%
core 4 utilize 0%
当相关核心进行编解码时,此信息可显示核心的利用率以及帧率。
库版本管理
系统中安装了两个版本的 libva:
- 1.14 版本:
/usr/lib/aarch64-linux-gnu/(默认) - 1.20 版本:
/usr/local/mt_vaapi/lib/(MT 提供版本,支持更多 profile)
系统默认使用 1.14 版本的 libva。如需切换到 1.20 版本,需设置环境变量:
export LD_LIBRARY_PATH=/usr/local/mt_vaapi/lib:$LD_LIBRARY_PATH
如需基于 1.20 版本的 libva 进行编译,需指定 pkg-config 路径:
export PKG_CONFIG_PATH=/usr/local/mt_vaapi/lib/pkgconfig:$PKG_CONFIG_PATH
FFmpeg 配置
系统中安装了两个版本的 FFmpeg:
/usr/bin/ffmpeg:官方版本/usr/local/mt_vaapi/bin/ffmpeg:MT 定制版本(默认)
建议基于 /usr/local/mt_vaapi 目录下的 FFmpeg 二进制文件、头文件和库进行开发,因为 MT 定制版本支持更全面的视频格式。
如需基于 MT 版本的 FFmpeg 进行编译,需指定 pkg-config 路径:
export PKG_CONFIG_PATH=/usr/local/mt_vaapi/lib/pkgconfig:$PKG_CONFIG_PATH
配置流程
步骤 1:安装和验证工具
安装 vainfo 工具:
sudo apt install vainfo
执行 vainfo 验证 VA-API 支持:
vainfo
error: XDG_RUNTIME_DIR not set in the environment.
MoTTY X11 proxy: Unsupported authorisation protocol
error: can't connect to X server!
libva info: VA-API version 1.20.0
libva info: Trying to open /usr/lib/aarch64-linux-gnu/dri//mtgpu_drv_video.so
libva info: Found init function __vaDriverInit_1_20
trace path : /sys/kernel/debug/tracing/trace_marker_raw
Connecting to pvr device ID: 0 (128)
libva info: va_openDriver() returns 0
vainfo: VA-API version: (libva 2.12.0)
vainfo: Driver version: Mthreads VPU driver for MT(R) MTT M1000 Graphics - 0.0.1.f27a2f1a (f27a2f1a)
vainfo: Supported profile and entrypoints
VAProfileNone : VAEntrypointVideoProc
VAProfileNone : VAEntrypointStats
VAProfileMPEG2Simple : VAEntrypointVLD
VAProfileMPEG2Main : VAEntrypointVLD
VAProfileMPEG4Simple : VAEntrypointVLD
VAProfileMPEG4AdvancedSimple : VAEntrypointVLD
VAProfileMPEG4Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointVLD
VAProfileH264Main : VAEntrypointEncSlice
VAProfileH264Main : VAEntrypointEncSliceLP
VAProfileH264High : VAEntrypointVLD
VAProfileH264High : VAEntrypointEncSlice
VAProfileH264High : VAEntrypointEncSliceLP
VAProfileVC1Simple : VAEntrypointVLD
VAProfileVC1Main : VAEntrypointVLD
VAProfileVC1Advanced : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointVLD
VAProfileJPEGBaseline : VAEntrypointEncPicture
VAProfileH264ConstrainedBaseline: VAEntrypointVLD
VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
VAProfileVP8Version0_3 : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointVLD
VAProfileHEVCMain : VAEntrypointEncSlice
VAProfileHEVCMain : VAEntrypointEncSliceLP
VAProfileHEVCMain10 : VAEntrypointVLD
VAProfileHEVCMain10 : VAEntrypointEncSlice
VAProfileHEVCMain10 : VAEntrypointEncSliceLP
VAProfileVP9Profile0 : VAEntrypointVLD
VAProfileVP9Profile2 : VAEntrypointVLD
VAProfileAV1Profile0 : VAEntrypointVLD
VAProfileAV1Profile0 : VAEntrypointEncSlice
VAProfileAV1Profile0 : VAEntrypointEncSliceLP
VAProfileAV1Profile1 : VAEntrypointVLD
VAProfileAV1Profile1 : VAEntrypointEncSlice
VAProfileAV1Profile1 : VAEntrypointEncSliceLP
VAProfileH264High10 : VAEntrypointVLD
VAProfileH264High10 : VAEntrypointEncSlice
VAProfileH264High10 : VAEntrypointEncSliceLP
VAProfileAVSJizhun : VAEntrypointVLD
VAProfileAVSGuangdian : VAEntrypointVLD
VAProfileAVS2Main : VAEntrypointVLD
VAProfileAVS2Main10 : VAEntrypointVLD
确认设备打开正常,profile 显示完整。
步骤 2:设置环境变量
执行 FFmpeg 命令前,设置必要的环境变量:
export LIBVA_DRIVER_NAME=mtgpu
export LIBVA_DRIVERS_PATH=/usr/lib/aarch64-linux-gnu/dri # 可选
步骤 3:视频解码测试
- 将码流解码成 YUV 格式:
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -i input.mp4 -pix_fmt yuv420p -vframes 1000 -y out_1.yuv
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -i input.mp4 -pix_fmt nv12 -vframes 1000 -y out_1.yuv
- 仅测试解码能力,但不保存解码数据:
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i input.mp4 -f null -
步骤 4:视频编码测试
- 对 8bit YUV 视频源进行编码:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -v verbose -f rawvideo -pix_fmt yuv420p -s:v 1920x1080 -r 50 -i input.yuv -vf 'format=nv12,hwupload' -c:v h264_vaapi -profile:v main -rc_mode VBR -g 250 -b_depth 3 -refs 2 -bf:v 3 -b:v 3M encode_out_8bit.mp4
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -pix_fmt nv12 -s 320x240 -i QVGA_NV12.yuv -vf "hwupload" -c:v h264_vaapi -vframes 60 QVGA_encoded.h264 -y
- 对 10bit YUV 视频源进行编码:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -v verbose -f rawvideo -pix_fmt p010le -s:v 1920x1080 -r 50 -stream_loop 10 -i 1080p_P010LE.yuv -vf 'format=p010le,hwupload' -c:v hevc_vaapi -profile:v main10 -rc_mode VBR -g 250 -bf:v 0 -b:v 4000k -y encode_out_h264_10.mp4
- 对 YUV 视频源进行 ROI 编码:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi -v verbose -f rawvideo -pix_fmt yuv420p -s:v 1920x1080 -r 30 -i input.yuv -vf 'addroi=iw/5:ih/4:iw/5:ih/2:-1/3,format=nv12,hwupload' -c:v h264_vaapi -profile:v main -rc_mode CQP -qp 40 -b:v 5M -bf:v 3 encode_out_roi.mp4
步骤 5:视频转码测试
- 将原 H.264 格式的 MP4 视频转码成 H.265 格式的 MP4 码流:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i input_h264.mp4 -c:v hevc_vaapi transcode.mp4
- 将原 H.264 格式的 MP4 视频转码成 H.265 格式的 MP4 码流,并指定编码参数:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i input_h264.mp4 -c:v hevc_vaapi -profile:v main -rc_mode CBR -bf:v 3 -b:v 4M transcode.mp4
步骤 6:视频前处理测试
- Scale 1280x720 -> 960x800:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo -pix_fmt nv12 -s:v 1280x720 -i input_nv12.yuv -vf 'hwupload,scale_vaapi=960:800:nv12,hwdownload,format=nv12' -f rawvideo -vsync passthrough -an -vframes 20 -y output_scale.yuv
- CSC nv12->rgba:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -pix_fmt nv12 -s 1280x720 -i input_nv12.yuv -vf "hwupload,scale_vaapi=format=nv12,hwdownload,format=rgba" -y output_rgba.yuv
- CSC+CROP+SCALE+ENCODE:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -pix_fmt rgba -s 1280x720 -i input_rgba.yuv -vf "hwupload,crop=1280:600:0:60,scale_vaapi=800:480:nv12" -c:v h264_vaapi -y output.h264
步骤 7:JPEG 编解码测试
- 将 JPEG 文件解码为 YUV 文件:
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -i input.jpg -pix_fmt yuv420p -y output.yuv
- 将 YUV 文件编码为 JPEG 文件:
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -pix_fmt yuv420p -s 480x640 -i input.yuv -vf "hwupload" -c:v mjpeg_vaapi output.jpg -y
开发参考
FFmpeg 源码中包含 VA-API 相关的示例代码,可参考以下文件进行开发:
FFmpeg/doc/examples/hw_decode.cFFmpeg/doc/examples/vaapi_encode.cFFmpeg/doc/examples/vaapi_transcode.c
编译 FFmpeg 示例
cd FFmpeg
./configure --disable-x86asm
make examples

