美文网首页
[Camera]v4l2框架内核空间解析

[Camera]v4l2框架内核空间解析

作者: Letcos | 来源:发表于2020-02-07 11:57 被阅读0次
参考:
1. YellowMax2001 https://blog.csdn.net/u013904227/category_9277668.html
2. linux Kernel source code: 4.4
3. Documentation/zh_CN/video4linux/v4l2-framework.txt
4. 杨柳 《Andorid 驱动开发权威指南》

v4l2框架简介

在这里插入图片描述

​ 大部分现代 V4L2 设备由多个 IC 组成,在 /dev 下导出多个设备节点,并同时创建非 V4L2 设备(如 DVB、ALSA、FB、I2C 和红外输入设备)。由于这种硬件的复杂性,V4L2 驱动也变得非常复杂。尤其是 V4L2 必须支持 IC 实现音视频的多路复用和编解码,这就更增加了其复杂性。通常这些 IC 通过一个或多个 I2C 总线连接到主桥驱动器,但也可使用其他总线。这些设备称为“子设备”。

​ 长期以来,这个框架仅限于通过 video_device 结构体创建 V4L 设备节点,并使用 video_buf 处理视频缓冲。

​ 这意味着所有驱动必须自己设置设备实例并连接到子设备。其中一部分要正确地完成是比较复杂的,使得许多驱动都没有正确地实现。由于框架的缺失,有很多通用代码都不可重复利用。因此,这个框架构建所有驱动都需要的基本结构块,而统一的框架将使通用代码创建成实用函数并在所有驱动中共享变得更加容易。

​ v4l2框架由4个主要的部分(数据结构)组成:v4l2_devices(包括v4l2_subdev); media_device; videobuf2; controls。v4l2_device管理所有的设备;meida_device框架管理运行时的pipeline;videobuf存储缓冲的数据;controls包含主要控制接口。

v4l2框架结构及关系

v4l2子模块划分

在这里插入图片描述

这是参考YellowMax2001专栏的划分方法。整体上没有问题,换个角度了解问题也是有好处的。

v4l2 结构图(UML)

在这里插入图片描述

​ 上图是v4l2框架的主要数据结构(不完整,部分成员和方法及关系没有表示出来),数据结构已经尽量画得很清楚了,可以下载或者在浏览器中打开大图查看。

v4l2 拓扑图

在这里插入图片描述

​ 上图是v4l2框架的拓扑图,着重展示了各数据结构之间的关系,可以下载或者在浏览器中打开大图查看。

主要数据结构

v4l2_device(v4l2_device.h)

​ 主设备使用 v4l2_device 进行抽象化表示。一般使用设备树来进行设备解析,使用平台驱动进行相应的驱动 probe。

  • 注册注销
//注册    
v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
//注销
v4l2_device_unregister(struct v4l2_device *v4l2_dev);

//对于热插拔设备断开时需要先调用disconnect函数然后再注销
v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
  • 引用计数操作
//增加引用计数
void v4l2_device_get(struct v4l2_device *v4l2_dev);

//减少引用计数
int v4l2_device_put(struct v4l2_device *v4l2_dev);
  • subdev注册注销
//注册
int  v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,struct v4l2_subdev *sd);

//一次注册所有subdev
int  v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);

//注销
void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
  • 遍历subdev
#define v4l2_device_for_each_subdev(sd, v4l2_dev)       list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
  • 回调
//调用所有指定的回调,忽略错误
#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...)        \
    do {                                \
        struct v4l2_subdev *__sd;               \
                                    \
        __v4l2_device_call_subdevs_p(v4l2_dev, __sd,        \
            !(grpid) || __sd->grp_id == (grpid), o, f , \
            ##args);                    \
    } while (0)

//调用所有指定的回调,不忽略错误
#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...)  \
({                                  \
    struct v4l2_subdev *__sd;                   \
    __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd,      \
            !(grpid) || __sd->grp_id == (grpid), o, f , \
            ##args);                    \
})

v4l2_subdev(v4l2_subdev.h)

该结构体是抽象化的子设备,用于管理子设备。

  • 初始化
void v4l2_subdev_init(struct v4l2_subdev *sd,const struct v4l2_subdev_ops *ops);
  • 设置/获取subdev私有数据
static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
{
    sd->dev_priv = p;
}

static inline void *v4l2_get_subdevdata(const struct v4l2_subdev *sd)
{
    return sd->dev_priv;
}
  • 设置/获取host私有数据
static inline void v4l2_set_subdev_hostdata(struct v4l2_subdev *sd, void *p)
{
    sd->host_priv = p;
}

static inline void *v4l2_get_subdev_hostdata(const struct v4l2_subdev *sd)
{
    return sd->host_priv;
}
  • 向v4l2_device发送notify
static inline void v4l2_subdev_notify(struct v4l2_subdev *sd,
                      unsigned int notification, void *arg)
{
    if (sd && sd->v4l2_dev && sd->v4l2_dev->notify)
        sd->v4l2_dev->notify(sd, notification, arg);
}

media_device

设及头文件:media-device.h/media-entity.h/meida-devnode.h具体helper函数可以参考对应头文件。

运行时设备控制,提供实时的 pipeline 管理。下图是一个pipeline的抽象示例图。

在这里插入图片描述

video_device(v4l2-dev.h)

​ 该结构体整合了数据流管理的终端模块功能,负责提供从内核空间到用户空间的数据交流。该结构体主要在v4l2 userspace介绍。

v4l2_ctrl_handler(v4l2-ctrls.h)

control 控制接口,这些接口通常用来实现一些特效控制、菜单控制等。下图是v4l2控制模块的一个示例图。

在这里插入图片描述

个人博客:www.letcos.top

相关文章

网友评论

      本文标题:[Camera]v4l2框架内核空间解析

      本文链接:https://www.haomeiwen.com/subject/lhdmxhtx.html