首页 > 其他分享 >UVC(1)-v4l2框架分析

UVC(1)-v4l2框架分析

时间:2024-04-02 19:35:32浏览次数:32  
标签:vid 框架 fmt cap vidioc UVC v4l2 out

此节是韦东山第三期学习资料   当插入一个网上买的UVC时,内核UVC驱动会打印出下面的Log信息出来 0 对应的UVC驱动位于:/drivers/media/usb/uvc 0   当插入的UVC与uvc_ids匹配了,就会调用uvc_probe函数枚举设备

 struct uvc_driver uvc_driver = {
         .driver = {
                 .name           = "uvcvideo",
                 .probe          = uvc_probe,
                 .disconnect     = uvc_disconnect,
                 .suspend        = uvc_suspend,
                 .resume         = uvc_resume,
                 .reset_resume   = uvc_reset_resume,
                 .id_table       = uvc_ids,
                 .supports_autosuspend = 1,
         },
 };
  在uvc_probe函数中,
uvc_probe
    ->v4l2_device_register
    ->uvc_register_chains
        ->uvc_register_terms
            ->uuv_register_video
                ->video_register_device    // 注册video_device,video_device使用cdev方式注册,cdev_ops = v4l2_fops
  虚拟视频驱动vivid.c分析: 1、分配video_device 2、设置video_device结构体 3、注册video_device结构体   代码位置:linux/drivers/platform/vivid vivid-core.c
 static const struct v4l2_file_operations vivid_fops = {
         .owner          = THIS_MODULE,
         .open           = v4l2_fh_open,
         .release        = vivid_fop_release,
         .read           = vb2_fop_read,
         .write          = vb2_fop_write,
         .poll           = vb2_fop_poll,
         .unlocked_ioctl = video_ioctl2,
         .mmap           = vb2_fop_mmap,
 };
 
  static const struct v4l2_file_operations vivid_radio_fops = {
         .owner          = THIS_MODULE,
         .open           = v4l2_fh_open,
         .release        = vivid_fop_release,
         .read           = vivid_radio_read,
         .write          = vivid_radio_write,
         .poll           = vivid_radio_poll,
         .unlocked_ioctl = video_ioctl2,
 };

 static const struct v4l2_ioctl_ops vivid_ioctl_ops = {
         .vidioc_querycap                = vidioc_querycap,

         .vidioc_enum_fmt_vid_cap        = vidioc_enum_fmt_vid,
         .vidioc_g_fmt_vid_cap           = vidioc_g_fmt_vid_cap,
         .vidioc_try_fmt_vid_cap         = vidioc_try_fmt_vid_cap,
         .vidioc_s_fmt_vid_cap           = vidioc_s_fmt_vid_cap,
         .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_mplane,
         .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap_mplane,
         .vidioc_try_fmt_vid_cap_mplane  = vidioc_try_fmt_vid_cap_mplane,
         .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap_mplane,

         .vidioc_enum_fmt_vid_out        = vidioc_enum_fmt_vid,
         .vidioc_g_fmt_vid_out           = vidioc_g_fmt_vid_out,
         .vidioc_try_fmt_vid_out         = vidioc_try_fmt_vid_out,
         .vidioc_s_fmt_vid_out           = vidioc_s_fmt_vid_out,
         .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_mplane,
         .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out_mplane,
         .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt_vid_out_mplane,
         .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,

         .vidioc_g_selection             = vidioc_g_selection,
         .vidioc_s_selection             = vidioc_s_selection,
         .vidioc_cropcap                 = vidioc_cropcap,

         .vidioc_g_fmt_vbi_cap           = vidioc_g_fmt_vbi_cap,
         .vidioc_try_fmt_vbi_cap         = vidioc_g_fmt_vbi_cap,
         .vidioc_s_fmt_vbi_cap           = vidioc_s_fmt_vbi_cap,

         .vidioc_g_fmt_sliced_vbi_cap    = vidioc_g_fmt_sliced_vbi_cap,
         .vidioc_try_fmt_sliced_vbi_cap  = vidioc_try_fmt_sliced_vbi_cap,
         .vidioc_s_fmt_sliced_vbi_cap    = vidioc_s_fmt_sliced_vbi_cap,
         .vidioc_g_sliced_vbi_cap        = vidioc_g_sliced_vbi_cap,

         .vidioc_g_fmt_vbi_out           = vidioc_g_fmt_vbi_out,
         .vidioc_try_fmt_vbi_out         = vidioc_g_fmt_vbi_out,
         .vidioc_s_fmt_vbi_out           = vidioc_s_fmt_vbi_out,
         .vidioc_g_fmt_sliced_vbi_out    = vidioc_g_fmt_sliced_vbi_out,
         .vidioc_try_fmt_sliced_vbi_out  = vidioc_try_fmt_sliced_vbi_out,
         .vidioc_s_fmt_sliced_vbi_out    = vidioc_s_fmt_sliced_vbi_out,

         .vidioc_enum_fmt_sdr_cap        = vidioc_enum_fmt_sdr_cap,
         .vidioc_g_fmt_sdr_cap           = vidioc_g_fmt_sdr_cap,
         .vidioc_try_fmt_sdr_cap         = vidioc_g_fmt_sdr_cap,
         .vidioc_s_fmt_sdr_cap           = vidioc_g_fmt_sdr_cap,

         .vidioc_overlay                 = vidioc_overlay,
         .vidioc_enum_framesizes         = vidioc_enum_framesizes,
         .vidioc_enum_frameintervals     = vidioc_enum_frameintervals,
         .vidioc_g_parm                  = vidioc_g_parm,
         .vidioc_s_parm                  = vidioc_s_parm,

         .vidioc_enum_fmt_vid_overlay    = vidioc_enum_fmt_vid_overlay,
         .vidioc_g_fmt_vid_overlay       = vidioc_g_fmt_vid_overlay,
         .vidioc_try_fmt_vid_overlay     = vidioc_try_fmt_vid_overlay,
         .vidioc_s_fmt_vid_overlay       = vidioc_s_fmt_vid_overlay,
         .vidioc_g_fmt_vid_out_overlay   = vidioc_g_fmt_vid_out_overlay,
         .vidioc_try_fmt_vid_out_overlay = vidioc_try_fmt_vid_out_overlay,
         .vidioc_s_fmt_vid_out_overlay   = vidioc_s_fmt_vid_out_overlay,
         .vidioc_g_fbuf                  = vidioc_g_fbuf,
         .vidioc_s_fbuf                  = vidioc_s_fbuf,

         .vidioc_reqbufs                 = vb2_ioctl_reqbufs,
         .vidioc_create_bufs             = vb2_ioctl_create_bufs,
         .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
         .vidioc_querybuf                = vb2_ioctl_querybuf,
         .vidioc_qbuf                    = vb2_ioctl_qbuf,
         .vidioc_dqbuf                   = vb2_ioctl_dqbuf,
         .vidioc_expbuf                  = vb2_ioctl_expbuf,
         .vidioc_streamon                = vb2_ioctl_streamon,
         .vidioc_streamoff               = vb2_ioctl_streamoff,

         .vidioc_enum_input              = vidioc_enum_input,
         .vidioc_g_input                 = vidioc_g_input,
         .vidioc_s_input                 = vidioc_s_input,
         .vidioc_s_audio                 = vidioc_s_audio,
         .vidioc_g_audio                 = vidioc_g_audio,
         .vidioc_enumaudio               = vidioc_enumaudio,
         .vidioc_s_frequency             = vidioc_s_frequency,
         .vidioc_g_frequency             = vidioc_g_frequency,
         .vidioc_s_tuner                 = vidioc_s_tuner,
         .vidioc_g_tuner                 = vidioc_g_tuner,
         .vidioc_s_modulator             = vidioc_s_modulator,
         .vidioc_g_modulator             = vidioc_g_modulator,
         .vidioc_s_hw_freq_seek          = vidioc_s_hw_freq_seek,
         .vidioc_enum_freq_bands         = vidioc_enum_freq_bands,

         .vidioc_enum_output             = vidioc_enum_output,
         .vidioc_g_output                = vidioc_g_output,
         .vidioc_s_output                = vidioc_s_output,
         .vidioc_s_audout                = vidioc_s_audout,
         .vidioc_g_audout                = vidioc_g_audout,
         .vidioc_enumaudout              = vidioc_enumaudout,

         .vidioc_querystd                = vidioc_querystd,
         .vidioc_g_std                   = vidioc_g_std,
         .vidioc_s_std                   = vidioc_s_std,
         .vidioc_s_dv_timings            = vidioc_s_dv_timings,
         .vidioc_g_dv_timings            = vidioc_g_dv_timings,
         .vidioc_query_dv_timings        = vidioc_query_dv_timings,
         .vidioc_enum_dv_timings         = vidioc_enum_dv_timings,
         .vidioc_dv_timings_cap          = vidioc_dv_timings_cap,
         .vidioc_g_edid                  = vidioc_g_edid,
         .vidioc_s_edid                  = vidioc_s_edid,

         .vidioc_log_status              = v4l2_ctrl_log_status,
         .vidioc_subscribe_event         = vidioc_subscribe_event,
         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
 };    
 
vivid_init
    ->vivid_probe
        ->vivid_create_instance
            ->设置ctrl(用于app的ioctl):事先添加属性
                例如dev->brightness = v4l2_ctrl_new_std(hdl_user_vid, &vivid_user_vid_ctrl_ops,
                    V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
            ->v4l2_device_register    // 不是主要,主要初始化一些东西,比如自旋锁,引用计数
            ->video_register_device(vfd, VFL_TYPE_GRABBER, vid_cap_nr[inst]);    // 根据不同的功能,实现不同的节点注册
                ->__video_register_device
                    vdev->cdev = cdev_alloc();
                    vdev->cdev->ops = &v4l2_fops;
                    cdev_add



分析vivid的open、read、write、ioctl过程:
app: open("/dev/video0",...)
--------------------------------------------------------------------------------
drv: v4l2_open
        vdev = video_devdata(filp);    // 根据次设备号从数组中得到video_device
        ret = vdev->fops->open(filp);    // 也就是vivid_fops->v4l2_fh_open函数

app: ioctl
--------------------------------------------------------------------------------
drv: v4l2_fops.unlocked_ioctl
        v4l2-ioctl
            struct video_device vdev = video_devdata(filp);
            ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                    video_ioctl2
                        video_usercopy(file, cmd, arg, __video_do_ioctl);
                            __video_do_ioctl
                                struct video_device *vfd = video_devdata(file);
                                根据app传入的cmn来获取设置某些属性

 

如何填写v4l2驱动: 1、分配设置注册v4l2_device:v4l2_device_register,得到v4l2_device(辅助作用,提供自旋锁引用计数) 2、分配设置注册一个video_device结构体,video_register_device,video_device.v4l2_device指向第一步分配的v4l2_device 3、video_device.v4l2_file_operations会被上层应用调用到的open/read/ioctl所调用 4、video_device.v4l2_ioctl_ops会被上层应用调用到的ioctl所间接调用 5、app可以通过ioctl来设置亮度等等信息,驱动程序使用v4l2_ctrl属性来表示接收存储设置到硬件 属性:v4l2_ctrl 管理:v4l2_ctrl_handler 初始化一个v4l2_ctrl_hander:v4l2_ctrl_handler_init 添加v4l2_ctrl属性项:v4l2_ctrl_new_std和v4l2_ctrl_new_custom,创建个个v4l2_ctrl,放入v4l2_ctrl_handler管理的链表 6、v4l2_dev.ctrl_handler和video_dev->v4l2_dev相关联  
v4l2_vtrl_handler的使用过程:
    IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL _CLEAR(v4l2_queryctrl, id)),
->
    static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
                                 struct file *file, void *fh, void *arg)
 {
         struct video_device *vfd = video_devdata(file);
         struct v4l2_queryctrl *p = arg;
         struct v4l2_fh *vfh =
                 test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;

         if (vfh && vfh->ctrl_handler)
                 return v4l2_queryctrl(vfh->ctrl_handler, p);
         if (vfd->ctrl_handler)
                 return v4l2_queryctrl(vfd->ctrl_handler, p);
         if (ops->vidioc_queryctrl)
                 return ops->vidioc_queryctrl(file, fh, p);
         return -ENOTTY;
 }

 

 

 

标签:vid,框架,fmt,cap,vidioc,UVC,v4l2,out
From: https://www.cnblogs.com/lethe1203/p/18111343

相关文章

  • 若依框架新建用户强密码验证
    代码:若以框架中ruoyi-ui/src/views/system/user/index.vue页面中:在data()里加:constcheckPassword=(rule,value,callback)=>{if(!/[A-Z]+/.test(value)||!/[a-z]+/.test(value)||!/\d+/.test(value)||!/[`~!@#$%^&*()\-=_+,.?<>/;':"\[\]{}|\......
  • 若以框架修改密码时强密码校验
     代码:若以框架中ruoyi-ui/src/views/system/user/profile/resetPwd.vue页面中:在data()里加:constcheckPassword=(rule,value,callback)=>{if(!/[A-Z]+/.test(value)||!/[a-z]+/.test(value)||!/\d+/.test(value)||!/[`~!@#$%^&*()\-=_+,.?<>/;'......
  • Sentinel 高可用流量管理框架
    软件简介国产数据库圈,为啥那么多水货?”Sentinel是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。Sentinel具有以下特性:丰富的应用场景:Sentinel承接了......
  • 前端学习-UI框架学习-Bootstrap5-015-列表组
    菜鸟教程链接列表组+active激活+disabled禁用要创建列表组,可以在元素上添加.list-group类,在元素上添加.list-group-item类:<template><divclass="containermt-3"><h2>列表组</h2><p>列表组+active激活+disabled禁用</p><......
  • HTML——5.表单、框架、颜色
    一、表单HTML表单用于在网页中收集用户输入的数据,例如登录信息、搜索查询等。HTML提供了一系列的表单元素,允许用户输入文本、选择选项、提交数据等。<!DOCTYPEhtml><htmllang="en"><head>  <metacharset="UTF-8">  <metaname="viewport"content="width=......
  • C#/.NET/.NET Core优秀项目和框架2024年3月简报
    前言公众号每月定期推广和分享的C#/.NET/.NETCore优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架......
  • C#/.NET/.NET Core优秀项目和框架
    C#/.NET/.NETCore优秀项目和框架2024年3月简报 前言公众号每月定期推广和分享的C#/.NET/.NETCore优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学......
  • Python快速入门系列-7(Python Web开发与框架介绍)
    第七章:PythonWeb开发与框架介绍7.1Flask与Django简介7.1.1Flask框架Flask的特点Flask的安装一个简单的Flask应用示例7.1.2Django框架Django的特点Django的安装一个简单的Django应用示例7.2前后端交互与数据传输7.2.1前后端交互7.2.2......
  • 基于 Python + Requests + Unitest + HwTestReport的API自动化测试框架
    一、框架目录结构概览 二、框架执行流程简介 三、框架目录结构简介▹case:存放测试用例▹data:存放测试数据及测试数据的处理▹config:存放相关配置文件(Token获取、Excel测试数据读取、requests二次封装等)▹file:存放测试接口信息▹report:存放测试报告▹to......
  • rt-thread 设备驱动框架
    RT-Thread设备框架属于组件和服务层,是基于RT-Thread内核之上的上层软件。设备框架是针对某一类外设,抽象出来的一套统一的操作方法及接入标准,可以屏蔽硬件差异,为应用层提供统一的操作方法。RT-Thread设备框架分为三层:设备驱动层、设备驱动框架层、I/O设备管理层。其中设备驱......