摄像头数据如何在Linux内核中走完"采集→处理→显示"全程?本文用一张全景图+一次采集追踪,讲清楚V4L2、DRM/DMABUF三者的关系,每个模块标注输入输出,1分钟搞懂Linux视频管线。
---
一、三层架构全景图
视频数据在Linux内核中流经三个子系统:V4L2负责采集,DRM负责显示,DMA-BUF负责零拷贝桥接。
三层职责速记:
层 | 核心组件 | 一句话 |
① V4L2 | /dev/video0+ vb2_queue | 把传感器数据送入内核缓冲区 |
② DMA-BUF | EXPBUF + PRIME | 把内核缓冲区"借"给显示驱动,不拷贝 |
③ DRM | FB → Plane → CRTC → Connector | 把像素数据扫描到屏幕 |
---
二、一次采集请求的完整旅程
摄像头按下录制键,数据走了一条怎样的路?追踪一帧图像从镜头到屏幕的完整路径。
镜头光信号 → CMOS 传感器 → MIPI CSI-2 串行传输
ISP 完成 Bayer 解码/去噪/白平衡 → 原始图像
open("/dev/video0") → VIDIOC_S_FMT 设置格式(1920×1080 NV12)
VIDIOC_REQBUFS + VIDIOC_QBUF 申请并入队缓冲区
VIDIOC_STREAMON 启动流 → 驱动开始填充帧
VIDIOC_DQBUF 出队 → 拿到已填充帧的句柄
VIDIOC_EXPBUF 导出 DMA-BUF fd → 零拷贝关键
drmPrimeFDToHandle 导入 fd → 创建 Framebuffer
CRTC 持续扫描 → HDMI 输出到屏幕
---
三、V4L2 三种缓冲区模式对比
模式 | 原理 | 适用场景 |
| MMAP | 内核分配缓冲区,导出dma句柄实现零拷贝 | 简单采集,最常用 |
| USERPTR | 用户空间分配内存,传地址给驱动 | 已有内存池复用 |
| DMABUF | 内核缓冲区通过 fd 跨设备共享 | V4L2DRM 零拷贝 |
---
四、DMA-BUF 零拷贝 vs 传统拷贝路径
五、总结
记一个口诀:采集入队→DQBUF取帧→EXPBUF导出→PRIME导入→CRTC扫描。
整个Linux视频管线的本质就是零拷贝句柄传递:数据从摄像头到屏幕全程是DMA句柄流转,不触发一次CPU拷贝。理解这个传递链,就理解了V4L2和DRM的协作方式。