title: UVC框架分析

date: 2019/4/23 19:50:00

toc: true

UVC框架分析

源码的位置在drivers\media\video\uvc,查看下Makefile,我们可以从入口uvc_driver.c中分析

uvcvideo-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
uvc_status.o uvc_isight.o uvc_debugfs.o
ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
uvcvideo-objs += uvc_entity.o
endif
obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o

入口函数

module_init(uvc_init);
>usb_register(&uvc_driver.driver) 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,
},
};

这里的id_table表示能够支持哪些设备,probe表示匹配到之后执行probe函数

uvc_probe

uvc_register_chains
uvc_register_terms
uvc_register_video
uvc_video_init
// 这里就是以前vivi中讲的 设置
video_device_alloc
vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
//注册
video_register_device(vdev, VFL_TYPE_GRABBER, -1);

文件ops

const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.unlocked_ioctl = uvc_v4l2_ioctl,
.read = uvc_v4l2_read,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll, };

UVC规格书一览

搜索下uvc Specification,链接在此,主要是USB_Video_Example 1.5.pdfUVC 1.5 Class specification.pdf

先来看下USB_Video_Example 中的图

再来看下规格书的基本描述,参考链接,这个unit实际上就是一个个内部的功能模块,terminal是用于连接内外的功能模块.

Unit

Unit提供了基础模块来全面描述大部分的视频功能,一个Unit可以由一个或多个输入引脚和仅一个输出引脚(这里的每一个pin代表一个逻辑上的数据流) ,Unit可以通过pin引脚连接在一起,一个输出pin可以连接多个输入pin,但一个输入pin只能连接一个输出pin

Select Unit

这个就是多路选择unit

Processing Unit

处理Unit (PU)控制流经它的视频流图像属性。

User Controls

  • Brightness
  • Hue
  • Saturation
  • Sharpness
  • Gamma
  • Digital Multiplier (Zoom)

Auto Controls

  • White Balance Temperature
  • White Balance Component
  • Backlight Compensation
  • Contrast
  • Other

Gain

  • Power Line Frequency
  • Analog Video Standard
  • Analog Video Lock Status

Terminal

链接内外的功能模块,一个输入和一个输出

  • Input Terminal
  • Out Terminal
  • Camera Terminal 控制端点.有些设备可能没有
    • Scanning Mode扫描模式
    • Auto-Exposure Mode自动曝光模式
    • Auto-Exposure Priority自动曝光优先级
    • Exposure Time 曝光时间
    • Focus聚焦
    • Auto-Focus自动聚焦
    • Simple Focus简单聚焦
    • Iris红外
    • Zoom放大
    • Pan摇动
    • Roll滚动
    • Tilt倾斜
    • Digital Windowing数字窗口

总的来说就是一个摄像头,一定会有起码1个的VS视频流接口,但不一定有vs控制接口.通过VideoControl Interface来控制,通过VideoStreaming Interface来读视频数据,VC里含有多个Unit/Terminal等功能模块,可以通过访问这些模块进行控制,比如调亮度

APP使用UVC驱动过程

uvc_register_chains
uvc_register_terms
uvc_register_video
uvc_video_init
// 这里就是以前vivi中讲的 设置
video_device_alloc
vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
//注册
video_register_device(vdev, VFL_TYPE_GRABBER, -1); APP调用过程
open
uvc_v4l2_open
unlocked_ioctl
uvc_v4l2_ioctl
uvc_v4l2_do_ioctl
case VIDIOC_QUERYCAP:
..... VIDIOC_QUERYCAP
//通过 stream->type 来设置,这个type 应该是在设备枚举时设置
if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING;
else
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
| V4L2_CAP_STREAMING; VIDIOC_ENUM_FMT
//通过 stream->format
format = &stream->format[fmt->index];
VIDIOC_G_FMT
// USB摄像头支持多种格式fromat, 每种格式下有多种frame(比如分辨率)
uvc_v4l2_get_format(stream, arg)
format = stream->cur_format;
frame = stream->cur_frame;
fmt->fmt.pix.pixelformat = format->fcc;
fmt->fmt.pix.width = frame->wWidth;
fmt->fmt.pix.height = frame->wHeight;
VIDIOC_TRY_FMT
uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL)
/* Check if the hardware supports the requested format. */
// 根据 stream中的format 来比较
format = &stream->format[i]
if(format->fcc == fmt->fmt.pix.pixelformat)
/* Find the closest image size */
//找到最接近的图像大小
VIDIOC_S_FMT
uvc_v4l2_set_format(stream, arg)
// 只是尝试把参数保存,并没有发起usb传输
uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame) VIDIOC_REQBUFS
uvc_alloc_buffers(&stream->queue, arg);
vb2_reqbufs(&queue->queue, rb); VIDIOC_QUERYBUF
//查询buf
uvc_query_buffer
vb2_querybuf
__fill_v4l2_buffer
mmap
uvc_v4l2_mmap
uvc_queue_mmap
vb2_mmap VIDIOC_QBUF
uvc_queue_buffer
vb2_qbuf VIDIOC_STREAMON
uvc_video_enable // 把所设置的参数发给硬件,然后启动摄像头
uvc_queue_enable
vb2_streamon
q->streaming = 1;
/* Commit the streaming parameters. */
ret = uvc_commit_video(stream, &stream->ctrl);
uvc_set_video_ctrl /* 设置格式fromat, frame */
__uvc_query_ctrl
usb_control_msg //usb传输
//启动urb传输
uvc_init_video
uvc_video_stats_start(stream); uvc_init_video_isoc
// 分配 设置 urb
uvc_alloc_urb_buffers
usb_fill_bulk_urb
urb->complete = uvc_video_complete; // usb传输完成的函数,这里应该会去唤醒uvc驱动
/* Submit the URBs. */
usb_submit_urb
urb传输完成函数.这里会有wakeup
uvc_video_complete
stream->decode(urb, stream, buf); //此函数搜索下
stream->decode = uvc_video_decode_isight;
stream->decode = uvc_video_decode_isoc;
uvc_queue_next_buffer
vb2_buffer_done
wake_up(&q->done_wq); poll
uvc_v4l2_poll
uvc_queue_poll
vb2_poll
poll_wait(file, &q->done_wq, wait);
//这里会接着判断状态
if (vb && (vb->state == VB2_BUF_STATE_DONE
|| vb->state == VB2_BUF_STATE_ERROR)) {
return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM :
POLLIN | POLLRDNORM; VIDIOC_DQBUF
uvc_dequeue_buffer
vb2_dqbuf
list_del(&vb->queued_entry); VIDIOC_STREAMOFF
uvc_video_enable(video, 0);
uvc_uninit_video
usb_kill_urb(urb);
usb_free_urb(urb); 分析设置亮度过程:
ioctl: VIDIOC_S_CTRL
uvc_ctrl_set
uvc_ctrl_commit
__uvc_ctrl_commit(video, 0);
uvc_ctrl_commit_entity(video->dev, entity, rollback);
ret = uvc_query_ctrl(dev /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id /* 哪一个unit/terminal */,
dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
ctrl->info->size);

小结

1. UVC设备有2个interface: VideoControl Interface, VideoStreaming Interface
2. VideoControl Interface用于控制,比如设置亮度。它内部有多个Unit/Terminal(在程序里Unit/Terminal都称为entity)
可以通过类似的函数来访问:
ret = uvc_query_ctrl(dev /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id /* 哪一个unit/terminal */,
dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
ctrl->info->size);
3. VideoStreaming Interface用于获得视频数据,也可以用来选择fromat/frame(VS可能有多种format, 一个format支持多种frame, frame用来表示分辨率等信 息)
可以通过类似的函数来访问:
ret = __uvc_query_ctrl(video->dev /* 哪一个USB设备 */, SET_CUR, 0,
video->streaming->intfnum /* 哪一个接口: VS */,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
uvc_timeout_param);
4. 我们在设置FORMAT时只是简单的使用video->streaming->format[fmt->index]等数据,
这些数据哪来的?
应是设备被枚举时设置的,也就是分析它的描述符时设置的。 5. UVC驱动的重点在于:
描述符的分析
属性的控制: 通过VideoControl Interface来设置
格式的选择:通过VideoStreaming Interface来设置
数据的获得:通过VideoStreaming Interface的URB来获得

(七) UVC框架分析的更多相关文章

  1. Android/Linux下CGroup框架分析及其使用

    1 cgroup介绍 CGroup是control group的简称,它为Linux kernel提供一种任务聚集和划分的机制,可以限制.记录.隔离进程组(process groups)所使用的资源( ...

  2. 几款开源的hybird移动app框架分析

    几款开源的Hybrid移动app框架分析 Ionic Onsen UI 与 ionic 相比 jQuery Mobile Mobile Angular UI 结论 很多移动开发者喜欢使用原生代码开发, ...

  3. 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一

    作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...

  4. 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析

    作者:唐老师,华清远见嵌入式学院讲师. 1. HAL Stub框架分析 HAL stub的框架比较简单,三个结构体.两个常量.一个函数,简称321架构,它的定义在:@hardware/libhardw ...

  5. openwrt: Makefile 框架分析

    openwrt: Makefile 框架分析 原文链接:blog.chinaunix.net/uid-26675482-id-4704952.html 本篇的主要目的是想通过分析Makefile,了解 ...

  6. Android 核心分析 之六 IPC框架分析 Binder,Service,Service manager

    IPC框架分析 Binder,Service,Service manager 我首先从宏观的角度观察Binder,Service,Service Manager,并阐述各自的概念.从Linux的概念空 ...

  7. VS2010/MFC编程入门之四(MFC应用程序框架分析)

    VS2010/MFC编程入门之四(MFC应用程序框架分析)-软件开发-鸡啄米 http://www.jizhuomi.com/software/145.html   上一讲鸡啄米讲的是VS2010应用 ...

  8. Yii PHP 框架分析(二)

    Yii PHP 框架分析(二)作者:wdy http://hi.baidu.com/delphiss/blog/item/54597af595085ad3f3d38552.html Yii是基于组件( ...

  9. Yii PHP 框架分析 (一)

    Yii PHP 框架分析 (一)作者:wdy http://hi.baidu.com/delphiss/blog/item/f7da86d787adb72506088b4b.html 基于yii1.0 ...

随机推荐

  1. 如何创建ChromeApp

    一个ChromeAPP 包含以下内容: 1. 清单文件 manifest.json,列出应用的一些基本信息例如:如何启动应用,应用的权限等等. 2. 事件处理页面也就是我们常说的后台脚本(backgr ...

  2. JDBC获取数据库连接

    是什么? JDBC:Java Data Base Connectivity(java数据库连接) 为什么用? sun公司提供JDBC API接口,数据库厂商来提供实现 我们需要用哪个数据库就加载那个数 ...

  3. Linux学习历程——SUID、SGID、SBIT简介

    一.SUID.SGID.SBIT简介 SUID:对一个可执行文件,不是以发起者身份来获取资源,而是以可执行文件的属主身份来执行.SGID:对一个可执行文件,不是以发起者身份来获取资源,而是以可执行文件 ...

  4. js坚持不懈之13:JavaScript查找HTML元素的方法

    1. 通过 id 查找 HTML 元素 <!DOCTYPE html> <html> <body> <p id = "intro"> ...

  5. .Net Core 在Linux服务器下部署程序--(1). Windows 连接 Linux服务器

    下载Linux服务器连接软件,市面上有Putty,FinalShell等,我以FinalShell为例,下载地址为 :http://www.hostbuf.com/t/988.html,软件安装结束后 ...

  6. crontab的笔试题随想

    最近看到一道题目,具体如下: 下列哪个是创建一个每周三01:00~04:00每3分钟执行一次的crontab指令? A: 1,4 3 /bin/bash /home/sijiaomao/ok.sh B ...

  7. HTML基础-------HTML标签(3)

    HTML标签(3) 表格 作用:制作一个表格 属性: 标签;table>tr>td(或者th) 语义; table:一个表格 tr:一行 td:一个单元格 th:单元格的表头 captio ...

  8. NOIP 2018 大翻车记

    都9102年了我才想起来写游记啊 Day -1 肚子里翻江倒海,一天去了七次厕所.吃了PPA把病压下去.安慰一下自己,说这样会涨人品. Loli讲述学长们的翻车笔记.我大概像是玩笑一样听过去了.(伏笔 ...

  9. C语言之各个位数上的数值之和

    #include<stdio.h> #include<stdlib.h> void main() { int num; ; int x,y; printf("请输入一 ...

  10. 01-Django介绍和安装

    01-Django介绍和安装 1.Django介绍 1.1介绍 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的框架模式,即模型M(Model),视图V(View)和控 ...