博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(七) UVC框架分析
阅读量:5790 次
发布时间:2019-06-18

本文共 8187 字,大约阅读时间需要 27 分钟。


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.oifeq ($(CONFIG_MEDIA_CONTROLLER),y)uvcvideo-objs  += uvc_entity.oendifobj-$(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中的图

mark

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

Unit

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

mark

Select Unit

这个就是多路选择unit

mark

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_buffermmap    uvc_v4l2_mmap        uvc_queue_mmap            vb2_mmap            VIDIOC_QBUF    uvc_queue_buffer        vb2_qbufVIDIOC_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_urburb传输完成函数.这里会有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 Interface2. 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来获得

转载于:https://www.cnblogs.com/zongzi10010/p/10764246.html

你可能感兴趣的文章
oracle备份与恢复--rman
查看>>
图片变形的抗锯齿处理方法
查看>>
Effective C++ Item 32 确保你的 public 继承模子里出来 is-a 关联
查看>>
phpstorm安装laravel-ide-helper实现自动完成、代码提示和跟踪
查看>>
python udp编程实例
查看>>
TortoiseSVN中图标的含义
查看>>
Tasks and Back stack 详解
查看>>
关于EXPORT_SYMBOL的作用浅析
查看>>
成功的背后!(给所有IT人)
查看>>
在SpringMVC利用MockMvc进行单元测试
查看>>
Nagios监控生产环境redis群集服务战
查看>>
Angular - -ngKeydown/ngKeypress/ngKeyup 键盘事件和鼠标事件
查看>>
Android BlueDroid(一):BlueDroid概述
查看>>
Java利用httpasyncclient进行异步HTTP请求
查看>>
宿舍局域网的应用
查看>>
html代码究竟什么用途
查看>>
Hadoop HDFS编程 API入门系列之路径过滤上传多个文件到HDFS(二)
查看>>
Python version 2.7 required, which was not foun...
查看>>
context:annotation-config vs component-scan
查看>>
经典sql
查看>>