一、概述
Media 子系统是一个用于处理多媒体设备的框架,它提供了一组 API 和驱动程序,用于管理和控制视频、音频和其他多媒体设备。而 V4L2 是 media 子系统的一部分,用于处理视频相关的功能。
了解 MIPI 摄像头后,发现 linux 系统下的流媒体驱动很复杂,而 MIPI 摄像头主要分为感光模组和 ISP 处理器,其中感光模组是用于生成 Bayer 数据(拜耳阵列),ISP 用于处理感光模组产生的数据(功能比较复杂这里就不介绍了)。对于 MIPI 摄像头而言,ISP 可以在摄像头前端或集成在SOC中,对于这两种情况,所需的驱动程序是不一样的。
Media 子系统刚好解决了这个问题,采用了分层式架构,可以粗暴的理解成为产线上的工位,每个工位处理的工作不一样,而每个工位之间通过传送带连接,只需要改变传送带的连接方式,即可实现不同的功能,接下来我们对 Media 的链路进行分析,目前我只用过 RV1126 开发板,不知道其他厂商的实现是方式是否一样
二、测试环境
- 开发板:RV1126
- ARM Linux 版本:4.19.111
三、Media 设备
Media 设备节点在 /dev 目录下,如下图所示
Media 设备之间的连接方式如下图所示
Media 设备信息
- entity:抽象的硬件设备模块(类比电路板上面的某个元器件)
- pad: 抽象的硬件设备端口(类比某个元器件的管脚)
- link: 抽象的硬件设备的连线(类比元器件管脚之间的连线)
四、节点关系
查看节点之间的拓扑关系,如下图所示
media-ctl -p -d /dev/mediaX
注意:
- Source和符号“->”表示输出
- Sink和符号“<-”就表示输入
- link表示连接,或者表示链路
根据上面关系很容易画出拓扑图,如下所示
五、RV1126 链路关系
通过查看设备树信息,可以得出开发板的链路关系,如下图所示
注意:从上面可以看出 RV1126 开发板中,imx415 摄像头的数据流向,只需要知道每个模块对应的节点,即可抓出我们想要的视屏数据
六、media 和 video 节点对应关系
查询 video 节点和 ISP/ISPP 节点的对应关系
grep "" /sys/class/video4linux/*/name
名称相同的 ISP 节点,可能属于不同的 media 设备下
media-ctl -d /dev/media3 -e "rkispp_scale1" media-ctl -d /dev/media4 -e "rkispp_scale1"
筛选
media-ctl -p -d /dev/media4 | grep rkispp_scale0
查看对应 video 节点支持的格式
v4l2-ctl --list-formats-ext --device /dev/videoX
七、抓图测试
v4l2-ctl 抓图命令
v4l2-ctl -d /dev/video30 \
--set-fmt-video=width=3840,height=2160,\
pixelformat=NV12 \
--stream-mmap=3 \
--stream-skip=3 \
--stream-to=/tmp/bypass0.raw \
--stream-count=1 \
--stream-poll
# -d:指定摄像头的设备节点
# --set-fmt-video:指定了宽高及pxielformat(用FourCC表示)。NV12即用FourCC表示的pixelformat;
# --Pixelformat:指定文件格式,NV12;
# --stream-mmap:指定 buffer 的类型为 mmap;
# --stream-skip:指定丢弃(不保存到文件)前3帧;
# --stream-to:指定帧数保存的文件路径;
# --stream-count:指定抓取的帧数,不包括--stream-skip丢弃的数量;
# --stream-poll:v4l2-ctl 采用异步 IO。
使用 v4l2-ctl 从 rkispp_m_bypass 抓 YUV 图
# 查看对应video节点支持的格式 media-ctl -d /dev/media3 -e "rkispp_m_bypass" v4l2-ctl --list-formats-ext --device /dev/video30 # 要开启ispserver,否则报错RKISP找不到iq ispserver & # 抓帧(IMX415摄像头插在MIPI CSI0接口上) v4l2-ctl -d /dev/video30 \ --set-fmt-video=width=2592,height=1944,\ pixelformat=NV12 \ --stream-mmap=3 \ --stream-skip=30 \ --stream-to=/tmp/bypass0.raw \ --stream-count=1 \ --stream-poll # 通过adb命令把文件拷贝到Ubuntu下 adb pull /tmp/bypass0.raw . # Ubuntu上查看 ffplay -f rawvideo -video_size 2592x1944 -pixel_format nv12 bypass0.raw
从 VICAP 抓 RAW 图
# 显示video0节点所有信息 v4l2-ctl -d /dev/video0 --all # 查看对应video0节点支持的格式 v4l2-ctl --list-formats-ext --device /dev/video0 # 设置数据以非紧凑型存储 echo 0 > /sys/devices/platform/rkcif_mipi_lvds/compact_test v4l2-ctl -d /dev/video0 \ --set-fmt-video=width=2592,height=1944,\ pixelformat=GB10 \ --stream-mmap=3 \ --stream-skip=30 \ --stream-to=/tmp/vicap.raw \ --stream-count=1 \ --stream-poll # 图片转换 ./test vicap.raw vicap_GB10.pgm 2592 1944 65535 1 # 图片显示 eog vicap_GB10.pgm
八、注意事项
(1)抓取 ISP 图像时需要开启 ispserver 服务
查看 ispserver 服务是否开启
ps -aux | grep ispserver
开启 ispserver 服务
# 表示不开启数据库服务dbserver ispserver --no-sync-db & # 或者 ispserver &
关闭 ispserver 服务
kill -9 PID
(2)抓图是链路之间必须是 ENABLED 状态
抓图时 rkisp-bridge-ispp 必须是ENABLED 的(1表示[ENABLED],0表示disable [ ]),设置命令如下
# 对应MIPI CSI0 media-ctl -d /dev/media1 -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[0]' media-ctl -d /dev/media1 -l '"rkisp-isp-subdev":2->"rkisp_selfpath":0[1]' media-ctl -d /dev/media1 -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[1]' media-ctl -d /dev/media3 -l '"rkispp_input_image":0->"rkispp-subdev":0[0]' # 对应MIPI CSI1 media-ctl -d /dev/media2 -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[0]' media-ctl -d /dev/media2 -l '"rkisp-isp-subdev":2->"rkisp_selfpath":0[1]' media-ctl -d /dev/media2 -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[1]' media-ctl -d /dev/media4 -l '"rkispp_input_image":0->"rkispp-subdev":0[0]'
(3)RKMedia 例程测试注意事项
开启和关闭 mediaserver
# 开启摄像头应用 /oem/RkLunch.sh & # 关闭摄像头应用 /oem/RkLunch-stop.sh &
(4)RAW 数据查看
在抓图 RAW 数据图像时,可以使用正点原子提供的 raw 转 pgm 图工具处理后,进行查看
参看资料
正点原子 PPT 课件
RV1126 相关手册