经典驱动案例分析-V4L2的Camera子系统

本文详细介绍了Linux内核中的V4L2(Video for Linux Two)子系统,特别是camera部分。V4L2为应用程序提供了访问音视频驱动的统一接口,支持read/write和mmap两种IO访问方式。soc camera子系统是V4L2的一部分,负责摄像头驱动的实现,通过定义标准接口减少camera sensor和host间的依赖,提高可移植性。文章阐述了用户程序如何通过V4L2接口采集视频数据,以及camera设备的注册过程和驱动实现,包括soc_camera_device和soc_camera_host的注册及交互。
摘要由CSDN通过智能技术生成

一 简介

1 V4L2

定义:V4L2(Video ForLinux Two) 是内核提供给应用程序访问音、视频驱动的统一接口。

核心:v4L2的核心源码位于drivers/media/v4l2-core

应用:V4L2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛的应用。

基础结构:

在这里插入图片描述

可见V4L2是个树形结构,通过链表来管理注册其下的设备。里面包含很多的子系统。我们今天要讲的就是其中一个子系统:camera

V4L2支持两种 IO 访问方式:

  1. read/write:帧IO访问方式,每一帧都要通过IO操作。数据需要在内核和用户之间拷贝,访问速度可能会非常慢。常用于静态图片数据的采集
  2. mmap内存映射:流IO访问方式,不需要内存拷贝,访问速度比较快。一般用于连续视频数据的采集

参考:

  1. https://www.cnblogs.com/vedic/p/10763838.html
  2. https://blog.csdn.net/smartvincent88/article/details/18987207

2 camera

也就是 soc camera 子系统。是V4L2的一个子系统,用来写摄像头驱动

意义:

  1. 为soc camera device 和 soc camera host定义了标准的接口或者说是回调函数,在soc_camera.c中进行管理
  2. 将camera sensor 和camera host的实现独立起来,减少两者之间的依赖关系,提高camera sensor驱动在不同平台之间的可移植性。

名词解释:

  1. device:设备
  2. host:cpu内部的模块控制器
  3. sensor:嵌入进camera内部的传感器,一般是i2c接口
  4. i2c:也就是i2c总线,用来绑定设备和驱动

二 层次结构

1 用户程序方面

用户程序通过V4L2接口采集视频数据的步骤

  1. 开视频设备文件,进行视频采集的参数初始化,通过V4L2接口设置视频图像的采集窗口、采集的点阵大小和格式
  2. 申请若干视频采集的帧缓冲区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据
  3. 将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集
  4. 驱动开始视频数据的采集,应用程序从视频采集输出队列取出帧缓冲区,处理完后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据
  5. 停止视频采集

2 整体结构

整体结构图:

在这里插入图片描述

图片分析:

首先用户程序通过open、ioctl指令或者mmap内存映射访问到V4L2系统。就拿open举例。比如我们要打开一个摄像头设备:/dev/video0。它是个字符设备,所以是通过cdev的ops访问到v4l2_open函数,然后v4l2_open函数中会调用vdev->fops->open。对于soc camera来说也就是调用soc_camera_open函数。随之就进入soc camera sub-system,也就是camera子系统。它对应的就是soc_camera.c 和 soc_camera_platform.c两个文件。

soc camera host:camera模块控制器,由平台厂商实现。向上实现soc_camera_host_ops接口,向下操作Camera host硬件以及通过平台特定的接口操作Soc camera device。

soc camera device :平台的设备,系统会为设备创建设备节点/dev/videoX。比如,将笔记本电脑的摄像头连接到虚拟机之后就会出现这样两个设备:

在这里插入图片描述

v4l2_subdev:可以是camera内部的sensor、video AD芯片,每个soc_camera_device可以管理多个v4l2_subdev。v4l2_subdev可以通过i2c挂接到v4l2_device,也可以通过soc_camera_link提供的add_device来增加

核心源码位置:

  1. soc_camera.c 和 soc_camera_platform.c:在 drivers/media/platform/soc_camera/ 文件夹下(不同内核版本可能位置不同,也可能在drivers/media/video/下)
  2. soc_camera.h 和 soc_camera_platform.h:在include/media/下

参考:

  1. https://blog.csdn.net/kickxxx/article/details/8484498

三 具体驱动实现方法

0 soc_camera_link结构体

/* Prepare to replace this struct: don't change its layout any more! */
struct soc_camera_link {
   
	/*
	 * Subdevice part - keep at top and compatible to
	 * struct soc_camera_subdev_desc
	 */
  //...
	/*
	 * Host part - keep at bottom and compatible to
	 * struct soc_camera_host_desc
	 */
  //...
};

在系统实现中会被拆分为以下结构体,注释中也表明了兼容以下结构体:

/*
 * Platform data for "soc-camera-pdrv"
 * This MUST be kept binary-identical to struct soc_camera_link below, until
 * it is completely replaced by this one, after which we can split it into its
 * two components.
 */
struct soc_camera_desc {
   
	struct soc_camera_subdev_desc subdev_desc;
	struct soc_camera_host_desc host_desc;
};

这两个结构体的结构在soc_camera_link当中都有。在平台设备注册时会用到

1 soc_camera_device

系统中是如何注册camera_device。

首先看 soc_camera.c 文件中的module_platform_driver函数:

static struct platform_driver __refdata soc_camera_pdrv = {
   
	.probe = soc_camera_pdrv_probe,
  //...
};
module_platform_driver(soc_camera_pdrv)

module_platform_driver的参数是soc_camera_pdrv,是一个platform_driver结构体,其中最重要的就是probe,也就是soc_camera_pdrv_probe。probe字面意思就是探测的,就是循环来探测驱动的。soc_camera_pdrv_probe会probe系统内名称为"soc-camera-pdrv"的平台设备,系统内有几个这样的平台设备,那么就会创建几个soc_camera_device。

以ov7725传感器为例:

struct i2c_board_info jz_v4l2_camera_
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值