整个v4l2的框架分为三层:

在应用层,我们可以在 /dev 目录发现 video0 类似的设备节点,上层的摄像头程序打开设备节点进行数据捕获,显示视频画面。设备节点的名字很统一,video0 video1 video2...这些设备节点在是核心层注册。

核心层 v4l2-dev.c,承上启下,对于每一个硬件相关层注册进来的设备,设置一个统一的接口 v4l2_fops ,既然是统一的接口必然不是具体的视频设备的操作函数,应用层调用 v4l2_fops 中的函数最终将调用到硬件相关层的 video_device 的 fops 。

硬件相关层,与具体的视频硬件打交道,分配、设置、注册 video_device 结构体。

static int __init videodev_init(void)
{/* 申请设备号,留给 video 设备使用 */dev_t dev = MKDEV(VIDEO_MAJOR, 0);ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME);/* 创建 video 类 */ret = class_register(&video_class);return 0;
}

struct video_device
{/* device ops */const struct v4l2_file_operations *fops;/* sysfs */struct device dev;        /* v4l device */struct cdev *cdev;        /* character device *//* Set either parent or v4l2_dev if your driver uses v4l2_device */struct device *parent;            /* device parent */struct v4l2_device *v4l2_dev;    /* v4l2_device parent *//* Control handler associated with this device node. May be NULL. */struct v4l2_ctrl_handler *ctrl_handler;/* Priority state. If NULL, then v4l2_dev->prio will be used. */struct v4l2_prio_state *prio;/* device info */char name[32];int vfl_type;/* 'minor' is set to -1 if the registration failed */int minor;u16 num;/* use bitops to set/clear/test flags */unsigned long flags;/* attribute to differentiate multiple indices on one physical device */int index;/* V4L2 file handles */spinlock_t        fh_lock; /* Lock for all v4l2_fhs */struct list_head    fh_list; /* List of struct v4l2_fh */int debug;            /* Activates debug level*//* Video standard vars */v4l2_std_id tvnorms;        /* Supported tv norms */v4l2_std_id current_norm;    /* Current tvnorm *//* callbacks */void (*release)(struct video_device *vdev);/* ioctl callbacks */const struct v4l2_ioctl_ops *ioctl_ops;DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);/* serialization lock */DECLARE_BITMAP(disable_locking, BASE_VIDIOC_PRIVATE);struct mutex *lock;
};

struct v4l2_device {struct device *dev;/* used to keep track of the registered subdevs */struct list_head subdevs;spinlock_t lock;char name[V4L2_DEVICE_NAME_SIZE];void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg);struct v4l2_ctrl_handler *ctrl_handler;struct v4l2_prio_state prio;struct mutex ioctl_lock;struct kref ref;void (*release)(struct v4l2_device *v4l2_dev);
};

static inline int __must_check video_register_device(struct video_device *vdev,int type, int nr)
{return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
}int __video_register_device(struct video_device *vdev, int type, int nr,int warn_if_nr_in_use, struct module *owner)
{int i = 0;int ret;int minor_offset = 0;int minor_cnt = VIDEO_NUM_DEVICES;const char *name_base;/* A minor value of -1 marks this video device as never having been registered */vdev->minor = -1;/* 视频设备的设备节点一般为 video0 ..video 就是由此而来 */switch (type) {case VFL_TYPE_GRABBER:name_base = "video";break;case VFL_TYPE_VBI:name_base = "vbi";break;...}vdev->vfl_type = type;vdev->cdev = NULL;/* Part 2: find a free minor, device node number and device index. */
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGESswitch (type) {case VFL_TYPE_GRABBER:minor_offset = 0;minor_cnt = 64;break;...
#endif/* 寻找一个空的项,这个好像并不重要 */mutex_lock(&videodev_lock);nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);if (nr == minor_cnt)nr = devnode_find(vdev, 0, minor_cnt);if (nr == minor_cnt) {printk(KERN_ERR "could not get a free device node number\n");mutex_unlock(&videodev_lock);return -ENFILE;}
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES/* 1-on-1 mapping of device node number to minor number */i = nr;
#else/* 在全局 video_deivce 数组中寻找一个空的项,下标+minor_offset作为设备的次设备号 */for (i = 0; i < VIDEO_NUM_DEVICES; i++)if (video_device[i] == NULL)break;if (i == VIDEO_NUM_DEVICES) {mutex_unlock(&videodev_lock);printk(KERN_ERR "could not get a free minor\n");return -ENFILE;}
#endifvdev->minor = i + minor_offset;vdev->num = nr;devnode_set(vdev);if (vdev->ioctl_ops)determine_valid_ioctls(vdev);/* 注册字符设备 */vdev->cdev = cdev_alloc();vdev->cdev->ops = &v4l2_fops;vdev->cdev->owner = owner;ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);/* 得把device注册进内核,mdev才能自动创建设备节点,/dev 目录下的video0 等就是来自这里 */vdev->dev.class = &video_class;vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);if (vdev->parent)vdev->dev.parent = vdev->parent;dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);ret = device_register(&vdev->dev);vdev->dev.release = v4l2_device_release;/* Part 6: Activate this minor. The char device can now be used. */set_bit(V4L2_FL_REGISTERED, &vdev->flags);mutex_lock(&videodev_lock);video_device[vdev->minor] = vdev;mutex_unlock(&videodev_lock);return 0;}
EXPORT_SYMBOL(__video_register_device);

static const struct file_operations v4l2_fops = {.owner = THIS_MODULE,.read = v4l2_read,.write = v4l2_write,.open = v4l2_open,.get_unmapped_area = v4l2_get_unmapped_area,.mmap = v4l2_mmap,.unlocked_ioctl = v4l2_ioctl,
#ifdef CONFIG_COMPAT.compat_ioctl = v4l2_compat_ioctl32,
#endif.release = v4l2_release,.poll = v4l2_poll,.llseek = no_llseek,
};

static int v4l2_open(struct inode *inode, struct file *filp)
{struct video_device *vdev = video_devdata(filp);if (vdev->fops->open) {if (video_is_registered(vdev))ret = vdev->fops->open(filp);}
}
static ssize_t v4l2_read(struct file *filp, char __user *buf,size_t sz, loff_t *off)
{struct video_device *vdev = video_devdata(filp);if (!vdev->fops->read)return -EINVAL;if (video_is_registered(vdev))ret = vdev->fops->read(filp, buf, sz, off);
}
static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
{struct video_device *vdev = video_devdata(filp);if (!vdev->fops->mmap)return ret;ret = vdev->fops->mmap(filp, vm);
}static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{struct video_device *vdev = video_devdata(filp);if (vdev->fops->unlocked_ioctl) {if (video_is_registered(vdev))ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);} else if (vdev->fops->ioctl) {if (video_is_registered(vdev))ret = vdev->fops->ioctl(filp, cmd, arg);}
}

转载于:https://www.cnblogs.com/Lxk0825/p/10400013.html

V4L2学习(三)框架分析相关推荐

  1. Yolo学习(框架分析)

    Yolo中文意思是You only look once.意思就是只需要看一次就可以识别出图中的这个物体. Yolo是单阶段的,不同于之前的双阶段的RCNN.Fast-RCNN. 一.框架 Input: ...

  2. linux v4l2系统详解,Linux摄像头驱动学习之:(一)V4L2_框架分析

    这段时间开始搞安卓camera底层驱动了,把以前的的Linux视频驱动回顾一下,本篇主要概述一下vfl2(video for linux 2). 一. V4L2框架: video for linux ...

  3. Linux v4l2框架分析

    背景 说明: Kernel版本:4.14 ARM64处理器,Contex-A53,双核 使用工具:Source Insight 3.5, Visio 1. 概述 V4L2(Video for Linu ...

  4. 《迅雷链精品课》第三课:区块链主流框架分析

    上一节课我们学习了区块链的技术架构,系统地分析了区块链平台的6个层次:数据层.网络层.共识层.合约层.应用层.接口层.这节课我们将结合实际看看现在主流区块链项目的技术架构:思考我们在设计具体的业务架构 ...

  5. 【通知】有三AI发布150页深度学习开源框架指导手册与GitHub项目,欢迎加入我们的开源团队...

    之前我们公众号输出了很多深度学习开源框架相关的内容,今天整理成技术手册给大家分享以方便阅读,下面是详细信息. 开源框架背景 现如今开源生态非常完善,深度学习相关的开源框架众多,光是为人熟知的就有caf ...

  6. PyTorch框架学习三——张量操作

    PyTorch框架学习三--张量操作 一.拼接 1.torch.cat() 2.torch.stack() 二.切分 1.torch.chunk() 2.torch.split() 三.索引 1.to ...

  7. JNI开发笔记(三)--JNI工程的框架分析

    JNI工程的框架分析 引 1. JNI工程的组成部分 2. 各个部分之间的关系 引 JNI开发笔记(一)–Android Studio安装与环境搭建 JNI开发笔记(二)–创建JNI基础工程并运行 1 ...

  8. darknet框架_【通知】有三AI发布150页深度学习开源框架指导手册与GitHub项目,欢迎加入我们的开源团队...

    之前我们公众号输出了很多深度学习开源框架相关的内容,今天整理成技术手册给大家分享以方便阅读,下面是详细信息. 开源框架背景 现如今开源生态非常完善,深度学习相关的开源框架众多,光是为人熟知的就有caf ...

  9. 因果推断三种分析框架

    目录 因果推断三种分析框架 相关和因果 因果推断的基本概念 反事实框架 潜在结果模型<

  10. nrf52832 学习笔记(二)SDK框架分析

    nrf52832 学习笔记(二)SDK框架分析 个人对SDK框架的一些理解,如有错误欢迎斧正. flash 分区 在不包含DFU的情况下,nrf52832 flash划分为: MBR 0x000000 ...

最新文章

  1. C#命名规范 C#控件的缩写大全
  2. pelee yuface 手势模型
  3. 20200314 SQ Intel Realsense D435 USB 线长、转接线个数测试数据表
  4. ajax多文件上传,js限制上传文件大小,文件上传前在浏览器展示
  5. 零基础Python小游戏
  6. .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类
  7. rust拆掉墙_rust怎么拆自己的墙
  8. 微软推出的在线代码查看神器github1s
  9. 汉字转换成拼音、获取拼音转换
  10. android开发 问卷调查案例_基于-Android问卷调查APP开发与设计.pdf
  11. codeforces 558 D Guess Your Way Out! II
  12. Cisco路由器配置Ipsec
  13. 如何利用【百度地图API】,制作房产酒店地图?(上)——制作自定义标注和自定义信息窗口
  14. ADB读取和备份安卓应用数据(无Root)
  15. ettercap 中间人攻击
  16. Java将16进制字符串,转换成字符串
  17. 在查找预编译头时遇到意外的文件结尾 是否忘记了向源中添加 include StdAfx h
  18. 【连载】大学物理笔记——内力做功
  19. Python办公自动化之收发邮件--163和qq邮箱
  20. 基于51单片机密码锁-舵机开锁-CXM

热门文章

  1. python中spider的用法_Spider-PyQuery基本用法(示例代码)
  2. SpringBoot 配置文件(yml)
  3. Java Spring AOP
  4. VSAN效能监控利器-VSAN Observer
  5. Horizon View 7 发布Win10桌面二:即时克隆桌面池配置
  6. Docker学习总结(69)—— 不用 Docker 如何构建容器
  7. linux只能用一半的内存,linux可用内存足够为什么还用swap
  8. 深入浅出 python epub_《机器学习从认知到实践(第2辑)(套装共3册,Python+TensorFlow)》epub+mobi+azw3...
  9. markdown 本地链接_Markdown的使用
  10. 一分钟看懂mysql_冬天发财树“最怕”它,遇上就烂根,一分钟看懂就能养好