1. 摄像头¶
本文主要介绍如何采集摄像头数据。
1.1. v4l2-utils介绍¶
V4L2-Utils是一个Linux下的视频设备管理和调试工具集,主要用于配置和控制Linux内核中的V4L2(Video for Linux version 2)视频设备。
1.1.1. 基本概念¶
V4L2:Video for Linux version 2,是Linux内核中用于视频设备驱动程序的标准接口。它提供了一套丰富的API,允许应用程序访问和控制视频设备。
V4L2-Utils:基于V4L2 API开发的一套命令行工具集,包含了多个用于查询、设置和调试视频设备的工具。
1.1.2. 主要功能¶
列出视频设备:可以列出系统中所有支持V4L2的视频设备,包括设备名称、设备节点等信息。
查询设备参数:可以查询视频设备的各种参数,如分辨率、帧率、像素格式、亮度、对比度等。
设置设备参数:可以根据需要设置视频设备的参数,以满足不同的应用场景需求。
视频捕获:支持通过内存映射(mmap)或用户指针(read)方式捕获视频流,并将其保存为文件或进行其他处理。
设备测试与调试:提供了多种测试和调试功能,如测试图案生成、设备兼容性测试等,有助于用户快速定位和解决视频设备相关的问题。
1.1.3. 常用工具¶
v4l2-ctl:主要用于控制和查询视频设备的参数。它提供了丰富的命令选项,如列出设备、查询和设置控制值、捕获视频流等。
media-ctl:主要用于查看和配置Media Framework中的实体(Entity)信息,如格式、裁剪、链接使能等。
1.2. 使用v4l2-ctl采集USB摄像头数据¶
开发板上电,插入USB摄像头,系统检测到USB摄像头插入后,会有如下打印信息:

查看USB摄像头的视频捕获节点:
1 | v4l2-ctl --list-devices
|

/dev/video* : 视频捕获设备节点(这里只有/dev/video10具有视频捕获功能)
/dev/media* : media子系统设备节点
对于USB摄像头而言,只需要关注/dev/video*节点。
查看摄像头支持的格式:
1 | v4l2-ctl -d /dev/video10 --list-formats-ext
|

设置/dev/video10设备节点的视频格式为MJPG,分辨率为640*480,帧率30fps:
1 2 | v4l2-ctl -d /dev/video10 --set-fmt-video=width=640,height=480,pixelformat=MJPG
v4l2-ctl -d /dev/video10 --set-parm=30
|
捕获一帧视频图像,并保存到当前目录:
1 | v4l2-ctl --verbose -d /dev/video10 --stream-mmap=4 --stream-skip=3 --stream-count=5 --stream-to=./01.jpg --stream-poll
|

查看刚刚捕获的图像:

1.3. 使用v4l2-ctl、media-ctl采集MIPI摄像头数据¶
MIPI Sensor通路往往会涉及传感器Sensor、CSI接口、ISP等多个模块,每个模块都有其相应的驱动程序, 内核驱动会将这些模块注册为一个个/dev/v4l-subdev*节点,以供用户态使用,但这不是必须的,如ISP驱动不一定会提供相应的设备节点供用户态使用。 MIPI摄像头的驱动程序会比USB摄像头驱动程序复杂的多,于是需要引入media子系统来管理各个模块之间的连接,如/dev/media*节点可以用来查看模块之间的拓扑结构。
这里以猫1和MIPI接口的OV8858摄像头为例,执行如下命令开启OV8858设备树插件:

查看MIPI通路中的相关节点:
1 | v4l2-ctl --list-devices
|

执行如下命令查看拓扑结构:
1 | media-ctl -p -d /dev/media0
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | Media controller API version 5.10.198
Media device information
------------------------
driver rkisp-vir0
model rkisp0
serial
bus info
hw revision 0x0
driver version 5.10.198
Device topology
- entity 1: rkisp-isp-subdev (4 pads, 8 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[fmt:SBGGR10_1X10/3264x2448 field:none
crop.bounds:(0,0)/3264x2448
crop:(0,0)/3264x2448]
<- "rkisp-csi-subdev":1 [ENABLED]
<- "rkisp_rawrd0_m":0 []
<- "rkisp_rawrd2_s":0 []
pad1: Sink
<- "rkisp-input-params":0 [ENABLED]
pad2: Source
[fmt:YUYV8_2X8/3264x2448 field:none colorspace:smpte170m quantization:full-range
crop.bounds:(0,0)/3264x2448
crop:(0,0)/3264x2448]
-> "rkisp_mainpath":0 [ENABLED]
-> "rkisp_selfpath":0 [ENABLED]
-> "rkisp_iqtool":0 [ENABLED]
pad3: Source
-> "rkisp-statistics":0 [ENABLED]
- entity 6: rkisp-csi-subdev (6 pads, 5 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[fmt:SBGGR10_1X10/3264x2448 field:none]
<- "rockchip-csi2-dphy1":1 [ENABLED]
pad1: Source
[fmt:SBGGR10_1X10/3264x2448 field:none]
-> "rkisp-isp-subdev":0 [ENABLED]
pad2: Source
-> "rkisp_rawwr0":0 [ENABLED]
pad3: Source
pad4: Source
-> "rkisp_rawwr2":0 [ENABLED]
pad5: Source
-> "rkisp_rawwr3":0 [ENABLED]
- entity 13: rkisp_mainpath (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "rkisp-isp-subdev":2 [ENABLED]
- entity 19: rkisp_selfpath (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video1
pad0: Sink
<- "rkisp-isp-subdev":2 [ENABLED]
- entity 25: rkisp_rawwr0 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video2
pad0: Sink
<- "rkisp-csi-subdev":2 [ENABLED]
- entity 31: rkisp_rawwr2 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video3
pad0: Sink
<- "rkisp-csi-subdev":4 [ENABLED]
- entity 37: rkisp_rawwr3 (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video4
pad0: Sink
<- "rkisp-csi-subdev":5 [ENABLED]
- entity 43: rkisp_iqtool (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video5
pad0: Sink
<- "rkisp-isp-subdev":2 [ENABLED]
- entity 49: rkisp_rawrd0_m (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video6
pad0: Source
-> "rkisp-isp-subdev":0 []
- entity 55: rkisp_rawrd2_s (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video7
pad0: Source
-> "rkisp-isp-subdev":0 []
- entity 61: rkisp-statistics (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video8
pad0: Sink
<- "rkisp-isp-subdev":3 [ENABLED]
- entity 67: rkisp-input-params (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video9
pad0: Source
-> "rkisp-isp-subdev":1 [ENABLED]
- entity 73: rockchip-csi2-dphy1 (2 pads, 2 links)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[fmt:SBGGR10_1X10/3264x2448@10000/230000 field:none]
<- "m00_b_ov8858 1-0036":0 [ENABLED]
pad1: Source
-> "rkisp-csi-subdev":0 [ENABLED]
- entity 76: m00_b_ov8858 1-0036 (1 pad, 1 link)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[fmt:SBGGR10_1X10/3264x2448@10000/230000 field:none]
-> "rockchip-csi2-dphy1":0
|
执行如下命令确认视频捕获设备:
1 2 | media-ctl -d /dev/media0 -e "rkisp_selfpath"
media-ctl -d /dev/media0 -e "rkisp_mainpath"
|

查看摄像头支持的格式:
1 | v4l2-ctl -d /dev/video0 --list-formats-ext
|

采集一帧视频图像,并保存到当前目录:
1 | v4l2-ctl --verbose -d /dev/video0 --set-fmt-video=width=640,height=480,pixelformat=NV21 --stream-mmap=4 --stream-skip=3 --stream-count=1 --stream-to=./video0.yuv --stream-poll
|

windows下使用yuv播放软件查看图像:

1.4. UVC摄像头应用程序编写¶
本例将使用支持MJPEG格式输出的USB摄像头,程序中,会采集摄像头数据并保存为一张张 的.jpg格式的图片。
1.4.1. 获取程序¶
程序位于lubancat_rk_code_storage/expansion_board/camera/uvc_to_jpg.c, 将uvc_to_jpg.c文件夹拷贝到板卡。
1.4.2. 代码测试¶
将USB摄像头插到板卡上,执行如下命令编译运行程序:
1 2 3 4 5 | # 编译程序
sudo gcc -o uvc_to_jpg uvc_to_jpg.c
# 运行程序
sudo ./uvc_to_jpg /dev/video10
|


1.5. MIPI摄像头应用程序编写¶
本应用程序和上一个应用程序的操作流程是一致的,主要区别在于单平面视频采集和多平面视频采集。 本例将使用支持NV21格式输出的MIPI OV8588摄像头,程序中,会采集摄像头数据并保存为一帧帧的.yuv格式的视频帧文件。
1.5.1. 获取程序¶
程序位于lubancat_rk_code_storage/expansion_board/camera/uvc_to_yuv.c, 将uvc_to_yuv.c文件夹拷贝到板卡。
1.5.2. 代码测试¶
将MIPI摄像头连接到板卡上的MIPI CSI接口,执行如下命令编译运行程序:
1 2 3 4 5 | # 编译程序
sudo gcc -o mipi_to_yuv mipi_to_yuv.c
# 运行程序
sudo ./mipi_to_yuv /dev/video0
|

