本实验以 ALINX AXU4EVB_E 开发平台为基础,接入 MIPI 摄像头和 USB 摄像头,同时在应用层生成测试彩条。通过 Qt + QML 构建交互界面,实现三路视频源切换、图像显示以及菜单叠加。
这次实验不仅要让图像显示出来,还要解决不同视频源如何统一管理、图像如何完成格式转换,以及菜单如何与视频画面协同显示等问题。
一、实验简介
例程组成:
PL端视频采集通路:接收MIPI摄像头的CSI-2数据流,完成格式规整、色彩空间处理和帧缓冲写入,数据最终落到PS DDR
Linux驱动与显示通路:把PL通路抽象为标准V4L2设备节点,同时提供DRM/KMS显示接口与Mali GPU驱动
Qt应用层程序:取帧、YUV转RGB、按屏幕比例缩放、叠加菜单浮层并经DP接口送上显示器,同时接收鼠标输入完成源切换
1.1 实验实现了什么
本实验最终实现了三路视频源的切换显示:
MIPI 摄像头: 通过 PL 端完成图像采集,采集分辨率为 1920×1080,帧率约 30 fps。
USB 摄像头: 通过 PS 端 USB 控制器接入,采用 UVC 协议,实验中实测帧率约 5 fps。
测试彩条: 由应用程序生成,用于验证显示流程,不依赖外部摄像头。
用户可以通过屏幕右上角的菜单选择视频源,画面随之切换;底部状态栏则显示当前视频源、分辨率和实时帧率等信息。
1.2 视频源参数一览
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
二、系统架构:图像怎样显示出来
要实现多路视频切换,首先需要明确图像从采集到显示的完整路径。本实验中,三路视频源的采集方式不同,但最终都需要进入 PS 端 DDR,再由显示模块读取并输出到屏幕。
整体流程可以概括为:
视频采集 → DDR 缓存 → 应用程序处理 → GPU 渲染 → DP 输出
其中,各部分承担的任务如下:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这里有一个需要注意的地方:无论图像来自 MIPI 还是 USB,都需要先进入 PS DDR,再由显示模块读取。本实验的 DP 显示由 PS 端内部显示控制器负责,PL 端不能直接驱动 DP。应用程序通过 DRM/KMS 等显示接口完成输出,最终由 DPDMA 从 DDR 中读取图像数据,输出至 DP 显示器。
三、关键技术点
3.1 多路视频源如何统一管理
MIPI 摄像头、USB 摄像头和测试彩条,数据来源和采集方式各不相同。如果分别编写显示逻辑,后续增加或更换视频源时,就需要修改大量代码。因此,本实验采用统一的视频源管理方式。
应用程序将三路视频源分别管理,并通过统一接口完成启动、停止和切换。无论当前选择哪一路视频源,后续图像处理和显示流程都保持一致。
在 Linux 系统中,摄像头设备通过 V4L2 接口进行管理。本实验中,MIPI 摄像头对应 /dev/video0,USB 摄像头对应 /dev/video1;测试彩条则由应用程序直接生成,不需要创建视频设备节点。
为了让采集和显示能够相对独立地运行,程序采用多缓冲机制。简单来说,采集线程负责将摄像头数据写入缓冲区,显示流程再从缓冲区获取图像。通过多个缓冲区轮流使用,可以减少采集与显示之间的相互等待。
本实验采用四缓冲方式:采集前申请缓冲区并将其加入队列,采集完成后取出已填充的缓冲区,处理完成后再归还队列,供后续采集使用。
3.2 YUV422 图像如何转换为 RGB
摄像头采集到的图像通常采用 YUV 格式,而显示渲染需要将其转换为 RGB 格式。本实验使用的摄像头图像格式为 YUV422,其中采用 YUYV 数据排列方式:
Y0 U0 Y1 V0
也就是说,两个相邻像素共用一组 U、V 色度信息。如果直接按照普通 RGB 图像的方式读取,就会出现数据解释错误。因此,在显示之前,需要先完成格式转换。
本实验没有将整幅图像的格式转换交给 CPU 逐像素处理,而是利用 GPU 的片元着色器完成 YUYV 到 RGB 的转换。
具体做法是:将原始 YUYV 数据作为纹理上传,着色器根据像素位置读取对应的 Y、U、V 数据,再完成颜色转换。
此外,实验采用最近邻插值方式进行采样,避免相邻像素的数据在采样过程中发生混合。
这里还有一个值得关注的细节:Mali-400 GPU 的纹理坐标精度存在限制。在处理 1080p 图像时,如果直接将整幅图像作为一个大纹理进行处理,可能出现细密条纹。因此,本实验将图像横向分成多个条带,分别上传和绘制,以改善显示效果。
3.3 视频画面与菜单如何叠加
本实验不仅需要显示视频,还需要在画面上叠加菜单和状态信息。如果将菜单直接绘制到视频图像中,界面交互和视频显示就会相互耦合,不利于后续修改。
因此,实验采用独立图层的方式:
Qt 负责应用程序逻辑,QML 负责界面展示。用户点击菜单后,程序通知视频源管理模块切换当前视频源,界面则通过属性绑定同步更新。
这种方式将视频处理与界面交互分开,既方便调整菜单样式,也便于后续扩展更多视频源或状态信息。
四、程序运行流程
了解了系统架构和关键技术后,再来看整个程序是如何运行的。
程序启动后,首先完成配置读取、Qt 类型注册和界面加载,随后创建视频源管理对象,并启动默认视频源的采集线程。
当采集线程获取到一帧图像后,会将图像数据交给显示流程。渲染部分获取最新帧,完成纹理上传、YUV422 到 RGB 的格式转换以及画面缩放,最后通过 DP 输出。
当用户点击右上角菜单切换视频源时,程序会停止当前视频源,再启动目标视频源,并更新界面中的当前源信息。
五、实验现象
程序运行后,DP 显示器可以正常显示视频画面和菜单界面。点击右上角菜单,可以在 MIPI 摄像头、USB 摄像头和测试彩条之间进行切换。
实验测试结果如下:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
测试彩条由八种颜色组成,画面中还包含一条移动的白色竖条,可用于观察图像显示和刷新情况。
从实验结果来看,三路视频源均能够正常显示,菜单交互和视频源切换功能也能够实现。
六、实验小结
本节综合例程将 MIPI 图像采集、USB 视频接入、Linux V4L2、Qt + QML 界面开发以及 GPU 图像处理等内容结合起来,完成了一个具备多路视频源切换和菜单叠加功能的视频显示应用。
通过本次实验,可以进一步理解嵌入式 Linux 平台下视频采集、图像缓存、格式转换和显示输出之间的关系。
对于 FPGA 视频应用开发而言,完成图像采集只是第一步。如何将不同来源的数据统一管理,并与应用层交互和显示模块结合起来,也是构建完整视频系统的重要环节。
完整视频讲解可前往 ALINX 视频号进行直播回看
更多细节欢迎关注我们黑金云课堂全年免费直播课,黑金云课堂11月直播日历 我们将在每周二、三、四,同步推进 Verilog开发、Vitis开发、Linux开发三大系列,带你从零开始,稳扎稳打掌握 FPGA 开发全流程!
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
43