RK3568 MIPI 摄像头驱动的 V4L2 多平面视频格式解析

在嵌入式 Linux 系统中,摄像头的视频采集通常通过 V4L2(Video4Linux2)接口完成。不同的摄像头驱动会支持不同的像素格式,这些格式直接影响到应用是否能够正常解析、显示或编码视频数据。

本文基于实际在 RK3568 平台 MIPI 摄像头下运行 v4l2-ctl --list-formats 的输出,详细解析每种格式的含义和用途,并解释单平面与多平面模式的区别。


1. 获取格式列表

在系统中,我们运行:

bash 复制代码
v4l2-ctl --device=/dev/video18 --list-formats

输出为:

复制代码
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture Multiplanar

        [0]: 'UYVY'  (UYVY 4:2:2)
        [1]: '422P'  (Planar YUV 4:2:2)
        [2]: 'NV16'  (Y/CbCr 4:2:2)
        [3]: 'NV61'  (Y/CrCb 4:2:2)
        [4]: 'YM16'  (Planar YUV 4:2:2 (N-C))
        [5]: 'NV21'  (Y/CrCb 4:2:0)
        [6]: 'NV12'  (Y/CbCr 4:2:0)
        [7]: 'NM21'  (Y/CrCb 4:2:0 (N-C))
        [8]: 'NM12'  (Y/CbCr 4:2:0 (N-C))
        [9]: 'YU12'  (Planar YUV 4:2:0)
        [10]: 'YM24' (Planar YUV 4:4:4 (N-C))

第一行 Type: Video Capture Multiplanar 说明:

  • 这是 多平面(multi-planar) 模式的设备
  • 每帧图像数据会分成多个 plane(如 NV12 有两个 plane:Y 和 UV)
  • 和单平面设备相比,API 调用时使用 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE

2. 格式逐一解析

0 UYVY (UYVY 4:2:2)

  • 排列方式:交错存储(Packed)
  • 每两个像素共享一对 U/V 分量,格式为:U0, Y0, V0, Y1
  • 常用于视频采集和回放,带宽占用比 RGB 高,但颜色分量压缩了一半

1 422P (Planar YUV 4:2:2)

  • 排列方式:平面式(每个分量存放在不同内存区域)
  • 4:2:2 意味着水平色度采样减半
  • 通常用于视频编解码器输入输出,有利于硬件做快速访问

2 NV16 (Y/CbCr 4:2:2)

  • 排列方式:半平面 (semi-planar)
  • Plane 0: 所有 Y 分量(亮度)
  • Plane 1: 交错的 CbCr(色度),水平采样比为 4:2:2
  • 适合硬件加速视频处理

3 NV61 (Y/CrCb 4:2:2)

  • 与 NV16 类似,但第二 plane 中的色度顺序颠倒为 CrCb
  • 某些视频编解码器或 ISP 的内部格式

4 YM16 (Planar YUV 4:2:2 (N-C))

  • "N-C"= Non-Contiguous(非连续内存)
  • 三个平面分别存 Y、U、V,水平色度采样减半
  • Non-Contiguous 意味着每个 plane 独立分配内存,不一定连续

5 NV21 (Y/CrCb 4:2:0)

  • 半平面格式,Y 独立,色度采样为垂直和水平都减半
  • 第二 plane 存储交错的 CrCb,与 NV12 色度分量顺序不同
  • 常见于 Android Camera HAL

6 NV12 (Y/CbCr 4:2:0)

  • 半平面格式,Y 在 plane0,交错的 CbCr 在 plane1
  • 色度采样为 4:2:0(水平、垂直都减半)
  • 注意 :此处 NV12 是多平面版本(V4L2_PIX_FMT_NV12M),并非单平面 NV12
  • 应用需用 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE 来访问

7 NM21 (Y/CrCb 4:2:0 (N-C))

  • NV21 的 Non-Contiguous(非连续内存)版本
  • 在某些 ISP 分配策略下更易优化内存带宽

8 NM12 (Y/CbCr 4:2:0 (N-C))

  • NV12 的 Non-Contiguous 版本
  • 两个 plane 分离且不连续存储

9 YU12 (Planar YUV 4:2:0)

  • Y、U、V 三个 plane
  • 经典的 I420 格式,用于编解码标准中(如 H.264 / VP8)

10 YM24 (Planar YUV 4:4:4 (N-C))

  • 每像素都有完整的 Y、U、V 信息
  • 不做色度采样压缩,色彩信息最完整,带宽需求也最高
  • Non-Contiguous 存储方式

3. 单平面 vs 多平面 NV12

  • 单平面 NV12:亮度 + 色度交错的两个 plane 在一个缓冲区里
  • 多平面 NV12:亮度 plane0 和色度 plane1 分成两个缓冲区独立管理
  • 在 V4L2 API 调用上,单平面用 VIDIOC_REQBUFStype = V4L2_BUF_TYPE_VIDEO_CAPTURE
    多平面则用 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE 并处理 struct v4l2_plane

4. 应用开发注意事项

  1. 必须匹配驱动输出的采集类型
    • 多平面格式必须用 VIDEO_CAPTURE_MPLANE
  2. 色度顺序敏感
    • NV12 与 NV21 的 UV 分量顺序不同,颜色会偏差
  3. Non-Contiguous 内存
    • 某些应用假设 plane 在内存中连续,这在 N-C 格式中不成立

  • RK3568 MIPI 摄像头驱动暴露的是 多平面格式集合,包括 NV12M、NM12、NV21M、NM21 等
  • GStreamer 等现代多媒体框架可透明适配多平面格式
  • 旧版 V4L2 应用若只支持单平面 NV12,会报"不支持"
  • 要在应用中使用这些格式,需要根据实际驱动类型调整缓冲区申请和数据解析逻辑

NV12 内存布局对比图

text 复制代码
============================================================
NV12 单平面格式 (V4L2_PIX_FMT_NV12, Video Capture 单平面)
============================================================

[Plane0+Plane1 放在同一个连续 buffer 中]
------------------------------------------------------------
| Y0 | Y1 | Y2 | ... | Y(Width*Height -1)                  |  --> 亮度(Y)数据
------------------------------------------------------------
| Cb0 | Cr0 | Cb1 | Cr1 | ... | Cb/Cr(Width*Height/2 -1)    |  --> 色度(CbCr交错)数据
------------------------------------------------------------
(总大小 = Y分量大小 + UV分量大小)

特点:
- 一个缓冲区里顺序存储亮度和色度
- V4L2 应用用 struct v4l2_buffer,无 planes[]
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE


============================================================
NV12 多平面格式 (V4L2_PIX_FMT_NV12M, Video Capture Multiplanar)
============================================================

[Plane0 和 Plane1 分开存储在两个缓冲区/plane 中]
------------------------------------------------------------
Plane0: 亮度(Y)数据
| Y0 | Y1 | Y2 | ... | Y(Width*Height -1)                  |
------------------------------------------------------------

Plane1: 色度(CbCr交错)数据
| Cb0 | Cr0 | Cb1 | Cr1 | ... | Cb/Cr(Width*Height/2 -1)    |
------------------------------------------------------------

特点:
- 多平面 API,每个 plane 独立分配内存
- V4L2 应用使用 struct v4l2_buffer 内 planes[] 数组访问
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
- plane[0].length = 宽 x 高
- plane[1].length = 宽 x 高 / 2
- 可以是 Contiguous(连续)或 N-C(非连续内存)

图形化的直观示意

单平面 NV12:

复制代码
+----------------- 整个内存缓冲区 ------------------+
|            Y 分量 (亮度)  Width*Height 字节        |
+---------------------------------------------------+
|  Cb / Cr 交错的色度分量 Width*Height/2 字节        |
+---------------------------------------------------+

多平面 NV12:

复制代码
Plane 0 (亮度Y)
+--------------------+
| Y 数据 (W*H 字节)   |
+--------------------+

Plane 1 (色度UV交错)
+--------------------+
| Cb/Cr 数据 (W*H/2) |
+--------------------+

应用开发要点

  1. 单平面V4L2_BUF_TYPE_VIDEO_CAPTURE,数据一次性取出,解析时按大小拆分成 Y 和 UV 两段
  2. 多平面V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,取两个 plane 分别处理
  3. 如果驱动只支持多平面 NV12,而应用只写了单平面 NV12 解析代码,就会不兼容 → 这正是你测试中应用报"不支持 NV12"的原因。

📌引用:

在 RK3568 + MIPI 摄像头的驱动实现中,由于硬件 ISP 输出采用多平面 NV12(NV12M),需要在应用端匹配使用 VIDEO_CAPTURE_MPLANE 类型,并通过 struct v4l2_buffer 的 planes\[\] 分别读取 Y plane 和 UV plane。

如果应用只支持单平面 NV12,必须增加单平面兼容路径或在驱动端做格式转换,否则会出现"不支持 NV12"的提示。


相关推荐
奈斯先生Vector21 小时前
当 Agent 配置变成控制平面:从 RelayRouter 的网关思路重新理解 DeepSeek Harness
平面
陈天伟教授3 天前
【30天学会机械制图 第11 天】项目二 简单的立体变成平面图形 任务3 认识曲面立体的三视图
平面·信息可视化·工程制图·机械制图·工程制图,机械制图
陈天伟教授4 天前
【30天学会机械制图 第10 天】项目二 简单的立体变成平面图形 任务2 认识平面立体的三视图
平面·工程制图·机械制图·工程制图,机械制图
陈天伟教授5 天前
【30天学会机械制图 第4天】项目一 从平面图形开始 任务1 按标准来画图,秒懂!
人工智能·平面·ai编程·具身智能机器人技术·机械制图
陈天伟教授6 天前
【30天学会机械制图】项目一 从平面图形开始 任务1 机械制图国家标准篇
平面
陈天伟教授6 天前
【30天学会机械制图】项目一 从平面图形开始 任务1 按标准来画图,都懂你!
大数据·人工智能·平面·机器人·具身智能机器人技术
ltqvibe6 天前
Agent OS:企业智能体的控制平面
人工智能·平面·agent·智能体·企业ai
三言老师7 天前
kubeadm + haproxy + keepalived 三节点高可用控制平面
linux·服务器·平面·容器·kubernetes
xiaopai9457 天前
工程合同数字化:从WPS平面台账到业务关系型管理系统的演进与验证
平面·wps·工程管理·建米软件·项目合同管理
Evand J9 天前
【MATLAB例程,PDR11】二维平面下的PDR(行人航位推算)步态检测与EKF融合定位,附代码的下载链接
开发语言·matlab·平面·pdr·行人导航·步态检测