凡是做过视频处理的朋友应该都有同感:一台RK3588,CPU规格看着不算差,A76大核也给了四个,可真要拿它做一路1080P的H.264实时软编码,x264一跑起来,四个大核直接被你拉去干苦力,剩下跑算法、跑业务逻辑的资源所剩无几。这不是板子不行,是“软编软解”这条路本身就不是嵌入式平台该走的道。RK3588板卡上明明有一颗专门干视频编解码的VPU(Video Processing Unit),却被晾在一边,这种浪费太可惜了。
这次要聊的FFMedia,说白了就是把RK3588这颗VPU用起来的常规打开方式。FFMedia这个叫法,社区里有人叫rockchip-ffmpeg,有人叫rkffmpeg,本质都是同一个东西:基于FFmpeg做封装,把Rockchip MPP的硬件编解码能力包装成FFmpeg标准的解码器/编码器,比如大家常见的h264_rkmpp、hevc_rkmpp就是它的核心成员。搞定了它,你就能直接在命令行或C代码里走硬件编解码通道,H.264的1080P/4K实时编解码CPU占用可以压到很低。
这篇教程适合三类人:在RK3588上做视频监控、图传、边缘AI盒子、录播一体机的开发;被软编CPU占用折磨过、想换硬编又怕踩坑的新手;还有手里有板子但一直没跑通rkmpp的朋友。我会按“原理 → 环境 → 编码 → 解码 → 排错”的顺序,把从编译FFMedia到跑通H.264硬编硬解的全过程拆开讲清楚,每一步都给可直接抄的配置和代码。
1. 先搞清楚FFMedia在RK3588上到底解决了什么问题
1.1 CPU软编解码为什么是“吃亏”的
先算一笔账。H.264编码本身是个计算密集型的活:运动估计、DCT变换、熵编码,每一步都在做大量重复运算。用软件做,比如x264,靠的是CPU通用算力硬扛。1080P30的H.264编码,在RK3588上用x264的veryfast档位,实测下来CPU占用大概在300%到400%之间,也就是四个A76大核基本被吃满。这时候你如果还想在板子上跑一个yolov8检测、推一个GUI界面,资源就非常紧张了。
软件解码相对好一点,但也谈不上轻松。纯软解1080P H.264,一个A76大核能吃掉30%到50%的占用,4K就更明显了。问题是嵌入式设备往往同时要做好几路视频,比如四路摄像头同时解码显示,一路软解你都嫌多,四路软解直接能把你CPU打穿。
那VPU是什么?VPU就是一颗专门的视频处理单元,芯片里集成的“编解码专用员工”。你给它一份H.264码流,它自己完成所有解码运算,把YUV帧吐给你;你要编码,把原始YUV帧喂给它,它把H.264码流给你。整个过程CPU只需要做“调度”和“搬运”这类轻量工作,而不是参与像素级计算。用生活类比来说,软编软解就像你让一个十项全能运动员既跑马拉松又去拧螺丝,硬编硬解则是给这个运动员配了一个专用工具台,他只需按一下按钮,工序就自动完成了。
所以结论很直接:在RK3588这种带VPU的平台上做视频处理,硬编硬解不是“可选项”,而是“默认项”。CPU应该留给业务逻辑、留给AI推理,不该去干像素苦力。
1.2 FFMedia与MPP、RGA的分工逻辑
要理解FFMedia,得先知道它底下站着谁。
Rockchip MPP(Media Process Platform)是瑞芯微官方提供的媒体处理用户态库,负责直接跟VPU驱动打交道,封装了硬件编解码、JPEG编解码等能力。但MPP的接口是偏底层的,你要自己管理输入输出缓冲、处理帧率控制、处理codec的数据格式,开发效率很低。
FFMedia做的事情,就是把MPP包进FFmpeg的框架里。这样一来,你不需要学MPP那套复杂的API,只要按FFmpeg的习惯创建AVCodecContext、调avcodec_send_frame和avcodec_receive_packet就行。FFMedia在内部帮你完成了AVFrame/AVPacket和MPP内部的MppFrame/MppPacket之间的转换。这就是h264_rkmpp这个编码器/解码器的来历。
另外还有一个容易被忽略的组件:RGA(Raster Graphic Acceleration)。它是RK平台上的2D硬件加速单元,负责图像格式转换、缩放、旋转、裁剪。解码之后得到的NV12原始帧,如果要转成RGB送显示、缩放后送NPU推理,用CPU做会拖慢整条流水线;用RGA做,CPU占用几乎可以忽略。rockchip的FFmpeg分支也集成了rkrga相关的滤镜,比如 scale_rkrga,这样你在FFmpeg命令行里也能直接调用RGA能力。
把这三层关系理清之后,你就知道FFMedia的实际价值:它把“用VPU编解码”这件事,从底层开发降维成了普通FFmpeg开发。你的技术栈只需要懂FFmpeg,不需要懂MPP内部细节。
1.3 哪些场景真正需要这套方案
不是所有项目都需要硬编硬解,但以下场景基本属于“用了就真香”的类型。
第一类是视频监控类。典型需求是拉取一路或多路RTSP摄像头流,在板卡上做实时预览、录制或算法分析。用FFMedia硬解,可以同时处理多路1080P,CPU占用比纯软解低一个数量级。
第二类是图传和直播推流。无人机图传、机器人第一视角、直播推流,都需要实时把视频编码成H.264/H.265再发送。这类场景对延迟敏感,要求编码不能拖后腿。硬编码的延迟通常在毫秒级到十几毫秒级,而且不会占用CPU,能保证主控系统稳定运行。
第三类是边缘AI盒子。很多人拿RK3588做目标检测,比如用yolov8跑检测。但摄像头采集回来的通常是一路H.264码流,你必须先解码成YUV帧,再缩放成模型需要的尺寸,然后送给NPU。如果这整条链路都用CPU硬扛,NPU算力还没用完,CPU先成了瓶颈。用硬解+RGA缩放,CPU可以被释放出来跑后处理逻辑。
第四类是录播一体机或视频会议终端。需要把采集到的HDMI或摄像头画面实时编码存储,同时可能还要解码显示远端画面。这类设备普遍是多路并发,硬编硬解几乎是刚需。
2. 环境准备:刷系统、确认VPU、编译FFMedia
2.1 板子系统与基础依赖准备
先说系统。RK3588上最常见的开发系统是Ubuntu,20.04、22.04、24.04我都试过,FFMedia这套方案在20.04和22.04上最稳定,网上资料也最多。不管你用的是官方Ubuntu镜像还是自己移植的根文件系统,底层原理差别不大,这套教程通用。
拿到板子之后,第一步先更新软件源并安装编译FFMedia需要的基础依赖。在终端里执行:
sudo apt update sudo apt install -y build-essential \ libdrm-dev \ libx11-dev \ libxext-dev \ libxfixes-dev \ libomxil-bellagio-dev \ libx264-dev \ cmake \ gitlibdrm比较关键,rockchip-ffmpeg在编译时处理DRM内存相关逻辑会用到,建议提前装好。如果你后面还想用OpenGL显示或硬解转给GPU,可以再加libegl1-mesa-dev和libgles2-mesa-dev。
2.2 确认VPU设备是否正常工作
编译前,先确认你的板子VPU驱动是正常的,不然编译半天最后跑不起来,排查起来很痛苦。
先看设备节点:
ls -l /dev/mpp_service正常情况下应该能看到类似/dev/mpp_service的字符设备。如果没有,说明内核配置里MPP驱动没编进去,或者系统镜像本身不带MPP支持。这时候优先检查内核配置,确认CONFIG_ROCKCHIP_MPP_SERVICE这类选项有没有打开。
再看内核日志:
dmesg | grep -i mpp能看到类似 “rockchip-mpp” 的初始化信息就说明驱动加载正常。如果这段日志都没有,多半是设备树或者内核模块有问题。
最后,可以用一个最简单的命令验证VPU能不能干活:直接让ffmpeg硬解一段小视频。不过这一步要等FFMedia编译完才能做,所以先记着这个方法,后面会用到。还有一个小经验,有些板子的mpp_service设备节点权限是root且是600,普通用户访问会报错,最简单粗暴的做法是:
sudo chmod 666 /dev/mpp_service或者写一个udev规则,让开机自动处理权限。后面在代码里跑通之后,建议补上udev规则,不然每次重启都要手动改权限。
2.3 编译rockchip-ffmpeg(FFMedia)的完整步骤
下载源码建议直接拉rockchip-linux的官方仓库:
git clone https://github.com/rockchip-linux/ffmpeg.git cd ffmpeg如果直接拉GitHub觉得慢,也可以用能找到的国内镜像或离线包,版本逻辑是一样的。拉下来之后,编译配置是关键。RK3588平台我建议这样configure:
./configure \ --target-os=linux \ --prefix=/usr/local/ffmpeg-rk \ --enable-gpl \ --enable-version3 \ --enable-rkmpp \ --enable-rkrga \ --enable-libdrm \ --enable-opengl \ --enable-ffplay \ --enable-ffprobe \ --enable-ffmpeg \ --disable-x86asm解释几个关键点:
--enable-rkmpp:必须开,不开就没有h264_rkmpp解码器/编码器。--enable-rkrga:必须开,这是启用RGA滤镜的开关,后面做NV12转RGB、缩放就靠它。--enable-libdrm:配合MPP的DRM内存管理,建议开。--enable-opengl:如果后续要硬解显示到屏幕,这个有用,可以一并编上。--disable-x86asm:因为是ARM平台,x86优化汇编完全不适用,不开会影响部分组件的编译。
配置完成后:
make -j$(nproc) sudo make install编译时间取决于你的板子性能。直接在RK3588上编,大概十几到二十分钟;如果你用交叉编译环境,时间会快很多,但交叉编译的环境变量配置比较繁琐,这个后面有机会单独展开。
编译完验证一下:
/usr/local/ffmpeg-rk/bin/ffmpeg -decoders | grep rkmpp /usr/local/ffmpeg-rk/bin/ffmpeg -encoders | grep rkmpp如果能分别看到 h264_rkmpp、hevc_rkmpp 甚至 av1_rkmpp 相关的解码器,以及 h264_rkmpp、hevc_rkmpp 编码器,说明FFMedia编译成功了。
注意:如果你系统里原来装过Ubuntu自带的ffmpeg,建议直接用/usr/local/ffmpeg-rk/bin/下的可执行文件,避免和系统版本混用。你可以在/usr/local/bin下做一个软链接,方便全局调用。
3. H.264硬编码实操:推流、直播和本地录制都能用
3.1 编码前的参数选择逻辑
硬件编码器和软件编码器的参数逻辑基本一致,但硬编有它自己要注意的地方,直接说结论。
码率控制。H.264硬编码推荐用固定码率(ABR)或恒定质量模式(CQP),具体看场景。直播、网络传输场景用固定码率更稳,1080P30通常给2Mbps到4Mbps;本地录制存储场景可以用CQP,画质更稳定,但码率会波动。命令行里固定码率用-b:v 4M,CQP用-qp 22这类参数。
GOP大小。GOP就是两个关键帧之间的距离。直播场景建议设置成帧率的整数倍,比如30fps给60,也就是2秒一个IDR帧;如果网络环境差,可以把GOP缩短到1秒,这样丢包后恢复更快,但码率会有所上升。
B帧。B帧能提升压缩率,但会增加延迟。低延迟图传、视频通话场景,直接把B帧关掉,也就是-bf 0。大部分RK硬编码配置里,B帧设置比较保守,你显式指定0会更稳妥。
Profile和Level。RK3588硬编码基本支持到High profile,1080P建议设-profile:v high。Level可以直接交给编码器自动算,也可以手动指定4.1或4.2,取决于你的码率和分辨率。
分辨率与帧率。VPU不是万能的,8K编码虽然标称支持,但实际项目里跑4K30或1080P60最稳。你要明白,硬编码虽然不占CPU,但还是占VPU算力的,分辨率越高、帧率越高,VPU负载越大,建议按需配置,别盲目上高规格。
3.2 用FFMedia实现H.264硬编码的代码骨架
命令行能跑通之后,迟早要落到代码里。下面给一个C语言硬编码的最小骨架,逻辑是读取NV12原始帧,用h264_rkmpp编码成H.264码流写到文件里。
#include <stdio.h> #include <stdint.h> #include <libavcodec/avcodec.h> int main() { const AVCodec *codec = avcodec_find_encoder_by_name("h264_rkmpp"); if (!codec) { fprintf(stderr, "h264_rkmpp encoder not found\n"); return -1; } AVCodecContext *ctx = avcodec_alloc_context3(codec); ctx->width = 1920; ctx->height = 1080; ctx->time_base = (AVRational){1, 30}; ctx->framerate = (AVRational){30, 1}; ctx->pix_fmt = AV_PIX_FMT_NV12; ctx->bit_rate = 4 * 1000 * 1000; ctx->gop_size = 60; ctx->max_b_frames = 0; ctx->profile = FF_PROFILE_H264_HIGH; if (avcodec_open2(ctx, codec, NULL) < 0) { fprintf(stderr, "open codec failed\n"); return -1; } FILE *out = fopen("output.h264", "wb"); AVFrame *frame = av_frame_alloc(); frame->format = ctx->pix_fmt; frame->width = ctx->width; frame->height = ctx->height; av_frame_get_buffer(frame, 32); AVPacket *pkt = av_packet_alloc(); for (int i = 0; i < 300; i++) { // 正常情况下这里应该读摄像头或解码器的NV12数据 // 测试时可以直接用av_frame_fill? 手动在data数组里填Y和UV frame->pts = i; avcodec_send_frame(ctx, frame); while (avcodec_receive_packet(ctx, pkt) == 0) { fwrite(pkt->data, 1, pkt->size, out); av_packet_unref(pkt); } } // 冲刷编码器 avcodec_send_frame(ctx, NULL); while (avcodec_receive_packet(ctx, pkt) == 0) { fwrite(pkt->data, 1, pkt->size, out); av_packet_unref(pkt); } fclose(out); return 0; }有几个细节要注意:
- 输入格式用NV12。RK平台的硬编码器对NV12支持最好,虽然你传YUV420P有时也能转,但多一次转换就多一分CPU占用,不如直接用对齐格式。
av_frame_get_buffer(frame, 32)里的32是字节对齐数。NV12的宽高对齐在硬件编码里很重要,1080P没问题,但如果分辨率不是常规值,比如1280x720这种还简单,遇到特殊尺寸建议手动按16或32对齐。- 编码完成后必须冲刷一次编码器,把缓冲区的帧吐出来,不然文件结尾会少GOP数据的尾巴。
3.3 命令行也能直接硬编:从YUV到MP4再到RTSP
代码骨架懂原理,但日常调试我更多直接用命令行。最基础的YUV转MP4硬编命令:
/usr/local/ffmpeg-rk/bin/ffmpeg \ -s 1920x1080 \ -pix_fmt nv12 \ -r 30 \ -i input.yuv \ -c:v h264_rkmpp \ -b:v 4M \ -g 60 \ -bf 0 \ -profile:v high \ -f mp4 output.mp4如果采集设备是USB摄像头或者MIPI摄像头,直接让ffmpeg读v4l2设备:
/usr/local/ffmpeg-rk/bin/ffmpeg \ -f v4l2 \ -video_size 1920x1080 \ -i /dev/video0 \ -c:v h264_rkmpp \ -b:v 4M \ -g 60 \ -bf 0 \ -f flv rtmp://192.168.1.100:1935/live/stream0对于图传或直播推流,这个命令基本够用。我实测过一路1080P30硬编码推流,CPU占用能控制在30%到50%左右,注意这里面还包含v4l2采集、内存拷贝和网络发送的开销。如果去掉采集和推流,单纯硬编码1080P30,CPU占用可以更低。同样场景用x264软编,CPU直接被打到300%以上,对比非常明显。
我建议你拿到板子后先跑这个软硬对比实验:同一个YUV文件,分别用libx264和h264_rkmpp编码,top命令记录CPU占用,再看输出文件大小和画面质量。做完这个实验,你对硬编的价值会非常有体感。
4. H.264硬解码实操:从RTSP拉流到YUV输出
4.1 解码链路与数据格式
硬解码的链路和编码正好相反。输入是H.264的AVPacket,经过h264_rkmpp解码器,输出是AVFrame。重点在于输出的像素格式。
Rockchip MPP硬件解码器最擅长的输出格式是NV12,也就是YUV420SP,Y平面单独一份,UV交错存放。你在FFmpeg里设置ctx->pix_fmt = AV_PIX_FMT_NV12后,解码器会尽量直接输出NV12,避免额外的格式转换。
另一个需要了解的是DRM内存。MPP解码时使用的不一定是普通内存,可能是DRM/ION分配的内存。在FFmpeg框架里,这通常体现为帧的data指针指向映射后的用户态地址。如果只是普通取帧数据,不需要关心底层;但要追求零拷贝,直接把解码后的DRM buffer送到显示或NPU,那就要用到Rockchip特定的硬件缓冲管理,复杂度会上去。新手阶段建议先走普通内存拷贝,性能足够满足大部分场景。
4.2 硬解码代码骨架
解码的代码骨架和编码对称,核心就是avcodec_send_packet和avcodec_receive_frame的循环。下面是从H.264文件解码成NV12 YUV文件的例子:
#include <stdio.h> #include <stdint.h> #include <libavcodec/avcodec.h> int main() { const AVCodec *codec = avcodec_find_decoder_by_name("h264_rkmpp"); if (!codec) { fprintf(stderr, "h264_rkmpp decoder not found\n"); return -1; } AVCodecContext *ctx = avcodec_alloc_context3(codec); ctx->pix_fmt = AV_PIX_FMT_NV12; if (avcodec_open2(ctx, codec, NULL) < 0) { fprintf(stderr, "open codec failed\n"); return -1; } FILE *in = fopen("input.h264", "rb"); FILE *out = fopen("output.yuv", "wb"); AVPacket *pkt = av_packet_alloc(); AVFrame *frame = av_frame_alloc(); uint8_t buf[512 * 1024]; int len; while ((len = fread(buf, 1, sizeof(buf), in)) > 0) { pkt->data = buf; pkt->size = len; avcodec_send_packet(ctx, pkt); while (avcodec_receive_frame(ctx, frame) == 0) { // NV12: Y平面和UV平面分开输出 fwrite(frame->data[0], 1, frame->linesize[0] * frame->height, out); fwrite(frame->data[1], 1, frame->linesize[1] * frame->height / 2, out); av_frame_unref(frame); } } // 冲刷解码器 avcodec_send_packet(ctx, NULL); while (avcodec_receive_frame(ctx, frame) == 0) { fwrite(frame->data[0], 1, frame->linesize[0] * frame->height, out); fwrite(frame->data[1], 1, frame->linesize[1] * frame->height / 2, out); av_frame_unref(frame); } return 0; }这里有一个新手容易踩的坑:linesize不等于width。硬件解码器输出的帧为了提高访问效率,往往会对每一行做对齐,实际一行的字节数会比图像宽度多。写入YUV文件时,绝对不能一行一行按width写,要按linesize写完整行数据。上面的代码里我直接用linesize乘高度,能保证写出来的YUV文件没有花屏和错位。
如果你是读取MP4这类容器,而不是裸H.264文件,建议用avformat打开输入、avcodec参数从容器流里拷贝,也就是走avformat_find_stream_info、avcodec_parameters_to_context这条路。裸流用parser切帧也可以,但要处理H.264的起始码和SPS/PPS,稍微麻烦一点。
4.3 用硬件解码拉RTSP:低延迟参数调优
实际项目里解码对象很少是本地文件,更多是RTSP摄像头流。命令行硬解RTSP最简形式:
/usr/local/ffmpeg-rk/bin/ffmpeg \ -rtsp_transport tcp \ -max_delay 100000 \ -probesize 32 \ -fflags nobuffer \ -i rtsp://192.168.1.64:554/stream0 \ -c:v h264_rkmpp \ -f rawvideo \ -pix_fmt nv12 output.yuv几个参数的经验:
-rtsp_transport tcp:局域网内优先用TCP,UDP虽然延迟略低,但容易丢包导致花屏。想稳就用TCP。-fflags nobuffer:告诉ffmpeg不要做深缓冲,降低首帧延迟。-probesize 32:因为已知是RTSP的H.264流,不需要花太多时间去探测格式,提高启动速度。-max_delay 100000:限制缓冲包的时长,单位是微秒,100000就是100ms。数值越大越稳但延迟越高,越小延迟越低但网络抖动时更容易卡顿,自己按实际网络调整。
我实测拉一路1080P H.264的RTSP摄像头流硬解码,CPU占用大概在10%到20%之间,而且这个占用主要花在内存拷贝和RTSP协议解析上,解码本身几乎不占CPU。同样一路流用h264软解,CPU占用轻松上到60%以上。多路摄像头场景下,这个差距会被指数级放大,硬解几乎是唯一可行方案。
5. 常见问题与排查技巧实录
5.1 编译和初始化踩坑
编译方面,最常见的报错是找不到rkmpp头文件和库。原因通常是系统里没有装rockchip-mpp的开发包,或者configure时没有指定mpp的路径。RK3588的Ubuntu官方镜像一般自带MPP,但如果你是精简根文件系统,可能没有。建议先把rockchip-mpp源码编一遍并安装到系统,再回头编FFMedia,顺序不要搞反。
另一个高频问题是我前面提到过的设备节点权限。如果你运行ffmpeg时出现类似 “mpp_create_group failed” 或 “open mpp_service failed” 的错误,第一反应去查/dev/mpp_service的权限。
还有一点,很多人在代码里用avcodec_find_decoder(AV_CODEC_ID_H264)去找解码器,结果找到的是软解码器,而不是h264_rkmpp。FFmpeg的默认解码器查找顺序不保证返回硬解,你必须显式用名字查找:
avcodec_find_decoder_by_name("h264_rkmpp")5.2 花屏、丢帧、时间戳问题
硬解码花屏,问题往往不在解码器,而在输入码流。常见原因是RTSP传输丢包,导致H.264码流里出现了残缺的NALU,解码器输出就会花屏或者直接丢帧。排查方法是先用软解跑一遍同样的流,如果软解也花屏,那铁定是码流问题,别去怀疑硬解。
帧率不对、线程不同步这类问题,多半是时间戳没有正确传递。硬编场景里,你喂给编码器的AVFrame的pts必须是递增的,否则封装进MP4后播放器会乱跳。硬解场景,如果拿到的AVFrame的pts是NOPTS,说明容器层的解析没把时间信息传过来,需要自己在外部维护帧序。
首帧延迟大,主要看两点:一是GOP长度,IDR帧间隔越长,设备启动后要等关键帧才能出图;二是ffmpeg的探测缓冲,用-probesize和-analyzeduration控制,默认值偏大,实时流场景要调小。
5.3 解码后图像去哪:NV12转RGB与送显
解码得到NV12后,最常见的需求是转RGB送显示,或者缩放后送NPU推理。
如果用CPU做NV12转RGB,1080P每帧大概要消耗不少CPU时间,视频只有一路还能接受,两路以上就开始吃力。更推荐用RGA,FFMedia编译时如果开了--enable-rkrga,可以使用rkrga滤镜:
/usr/local/ffmpeg-rk/bin/ffmpeg \ -c:v h264_rkmpp \ -i input.h264 \ -vf "scale_rkrga=1920:1080:format=rgb0" \ -f rawvideo output.rgb这个滤镜内部走RGA硬件,CPU占用非常低。如果你的业务是“解码后直接送NPU推理”,建议把解码输出的NV12直接通过RGA缩放到模型输入尺寸,转成RGB并做数据布局调整,最后一次性拷给NPU。这样做整条流水线CPU占用都极低,yolov8这类推理业务才能跑得流畅。
5.4 问题速查表
| 现象 | 大概率原因 | 解决方案 |
|---|---|---|
| ffmpeg看不到h264_rkmpp | 编译时没开--enable-rkmpp | 重新configure并编译 |
| avcodec_open2报mpp相关错误 | /dev/mpp_service权限或驱动异常 | 查看设备节点、dmesg、chmod 666 |
| 硬解码花屏 | 输入码流丢包/NALU不完整 | 先用软解对比,优化RTSP传输为TCP |
| 编码MP4播放器不识别 | GOP、profile或level不合理 | 显式设置profile high、bf 0、gop 60 |
| 延迟过大 | 缓冲过多或探测时间过长 | 加-fflags nobuffer、调小probesize |
| 解码输出帧数据错位 | 忽略了linesize对齐 | 写入时按linesize逐行处理 |
| RGA滤镜找不到 | 编译没开--enable-rkrga | 重新编译FFMedia |
| 编码帧率低于预期 | 分辨率/帧率超VPU能力范围 | 降低到4K30或1080P60,检查输入帧率 |
最后再分享一个我个人的实操体会。刚开始接触RK3588硬件编解码的时候,我最大的问题是迷信“代码”。其实最快的路径是先把ffmpeg命令行跑通,用命令行验证板子的VPU、验证码流、验证参数,然后再把同样的参数迁移到C/C++代码里。命令行能跑通,说明驱动、权限、库都OK,这时候再调试代码就只剩下业务逻辑。编码那块也是一样,先用软解软编确定源没问题,再切硬编硬解,出了问题才有方向。
至于后续扩展,我最近正在做的一件事就是把解码后的NV12帧直接通过RGA缩放,再送给RK3588的NPU跑yolov8检测。做完之后整个链路CPU占用都很低,视频流水线几乎不抢AI算力的资源。等我把这套完整流水线再打磨得顺一点,后面单独整理一篇出来,到时候再跟你细聊那些具体的坑。