uvc摄像头代码解析3

6.uvc解析uvc视频流

6.1 重要结构体

6.1.1 uvc数据流

[cpp]  view plain copy
  1. struct uvc_streaming {  
  2.     struct list_head list;  //uvc视频流链表头  
  3.     struct uvc_device *dev; //uvc设备  
  4.     struct video_device *vdev;  //V4L2视频设备  
  5.     struct uvc_video_chain *chain;  //uvc视频链  
  6.     atomic_t active;  
  7.     struct usb_interface *intf; //usb接口设备  
  8.     int intfnum;    //usb接口号  
  9.     __u16 maxpsize; //最大包尺寸  
  10.     struct uvc_streaming_header header; //uvc视频流头部  
  11.     enum v4l2_buf_type type;    //V4L2缓冲区类型 输入/输出  
  12.     unsigned int nformats;  //uvc格式个数  
  13.     struct uvc_format *format;  //uvc格式指针  
  14.     struct uvc_streaming_control ctrl;  //uvc数据流控制  
  15.     struct uvc_format *cur_format;  //当前uvc格式指针  
  16.     struct uvc_frame *cur_frame;    //当前uvc帧指针  
  17.     struct mutex mutex;  
  18.     unsigned int frozen : 1;  
  19.     struct uvc_video_queue queue;   //uvc视频队列  
  20.     void (*decode) (struct urb *urb, struct uvc_streaming *video,struct uvc_buffer *buf);//解码函数  
  21.     struct {  
  22.         __u8 header[256];  
  23.         unsigned int header_size;  
  24.         int skip_payload;  
  25.         __u32 payload_size;  
  26.         __u32 max_payload_size;  
  27.     } bulk;  
  28.     struct urb *urb[UVC_URBS];//urb数组  
  29.     char *urb_buffer[UVC_URBS]; //urb缓冲区  
  30.     dma_addr_t urb_dma[UVC_URBS];//urb DMA缓冲区  
  31.     unsigned int urb_size;    
  32.     __u32 sequence;  
  33.     __u8 last_fid;  
  34. };  


6.1.2 uvc格式

[cpp]  view plain copy
  1. struct uvc_format { //uvc格式  
  2.     __u8 type;  //类型  
  3.     __u8 index; //索引  
  4.     __u8 bpp;   //bits per pixel 每像素位数  
  5.     __u8 colorspace;    //颜色空间  
  6.     __u32 fcc;  //压缩格式  
  7.     __u32 flags;    //标记  
  8.     char name[32];  //名字  
  9.     unsigned int nframes;   //所含uvc帧个数  
  10.     struct uvc_frame *frame;    //uvc帧指针  
  11. };  


6.1.3 uvc帧

[cpp]  view plain copy
  1. struct uvc_frame {  //uvc帧  
  2.     __u8  bFrameIndex;  //帧索引号  
  3.     __u8  bmCapabilities;   //uvc帧兼容性  
  4.     __u16 wWidth;   //宽度  
  5.     __u16 wHeight;  //高度  
  6.     __u32 dwMinBitRate; //最新位流  
  7.     __u32 dwMaxBitRate; //最大位流  
  8.     __u32 dwMaxVideoFrameBufferSize;    //最大视频帧缓冲区  
  9.     __u8  bFrameIntervalType;   //间隙类型  
  10.     __u32 dwDefaultFrameInterval;   //默认帧间隙  
  11.     __u32 *dwFrameInterval; //帧间隙指针  
  12. };  


6.2 uvc_parse_streaming函数

[cpp]  view plain copy
  1. static int uvc_parse_streaming(struct uvc_device *dev,struct usb_interface *intf)  
  2. {  
  3.     struct uvc_streaming *streaming = NULL; //uvc数据流  
  4.     struct uvc_format *format;  //uvc格式  
  5.     struct uvc_frame *frame;    //uvc帧  
  6.     struct usb_host_interface *alts = &intf->altsetting[0];  //获取usb接口第一个usb_host_interface (Alt.Setting 0)  
  7.     unsigned char *_buffer, *buffer = alts->extra;   //获取额外描述符  
  8.     int _buflen, buflen = alts->extralen;    //获取额外描述符长度  
  9.     unsigned int nformats = 0, nframes = 0, nintervals = 0;  
  10.     unsigned int size, i, n, p;  
  11.     __u32 *interval;  
  12.     __u16 psize;  
  13.     int ret = -EINVAL;  
  14.     if (intf->cur_altsetting->desc.bInterfaceSubClass != UVC_SC_VIDEOSTREAMING) { //判读usb接口描述符子类是否为视频数据流接口子类  
  15.         uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a video streaming interface\n", dev->udev->devnum,intf->altsetting[0].desc.bInterfaceNumber);  
  16.         return -EINVAL;  
  17.     }  
  18.     if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {    //绑定uvc设备的usb驱动和usb接口  
  19.         uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already claimed\n", dev->udev->devnum,intf->altsetting[0].desc.bInterfaceNumber);  
  20.         return -EINVAL;  
  21.     }  
  22.     streaming = kzalloc(sizeof *streaming, GFP_KERNEL); //分配uvc数据流内存  
  23.     if (streaming == NULL) {  
  24.         usb_driver_release_interface(&uvc_driver.driver, intf);  
  25.         return -EINVAL;  
  26.     }  
  27.     mutex_init(&streaming->mutex);  
  28.     streaming->dev = dev;    //uvc数据流和uvc设备捆绑  
  29.     streaming->intf = usb_get_intf(intf);    //uvc数据流和usb接口捆绑,并增加引用计数  
  30.     streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;  //设置接口号  
  31.     /* The Pico iMage webcam has its class-specific interface descriptors after the endpoint descriptors. */  
  32.     if (buflen == 0) {  //Pico iMage webcam 特殊处理  
  33.         for (i = 0; i < alts->desc.bNumEndpoints; ++i) {  
  34.             struct usb_host_endpoint *ep = &alts->endpoint[i];  
  35.             if (ep->extralen == 0)  
  36.                 continue;  
  37.             if (ep->extralen > 2 && ep->extra[1] == USB_DT_CS_INTERFACE) {  
  38.                 uvc_trace(UVC_TRACE_DESCR, "trying extra data from endpoint %u.\n", i);  
  39.                 buffer = alts->endpoint[i].extra;  
  40.                 buflen = alts->endpoint[i].extralen;  
  41.                 break;  
  42.             }  
  43.         }  
  44.     }  
  45.     /* Skip the standard interface descriptors. 跳过标准的接口描述符*/  
  46.     while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {   
  47.         buflen -= buffer[0];  
  48.         buffer += buffer[0];  
  49.     }  
  50.     if (buflen <= 2) {  
  51.         uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming interface descriptors found.\n");  
  52.         goto error;  
  53.     }  
  54.     /* Parse the header descriptor. 解析header描述符*/   //Class-specific VS Interface Input Header Descriptor  
  55.     switch (buffer[2]) {    //bDescriptorSubtype  
  56.     case UVC_VS_OUTPUT_HEADER:  //输出类型的视频流  
  57.         streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;    //设置为V4L2视频buf输出  
  58.         size = 9;  
  59.         break;  
  60.     case UVC_VS_INPUT_HEADER:   //输入类型的视频流  
  61.         streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;   //设置为V4L2视频buf输入  
  62.         size = 13;  
  63.         break;  
  64.     default:  
  65.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d HEADER descriptor not found.\n", dev->udev->devnum,alts->desc.bInterfaceNumber);  
  66.         goto error;  
  67.     }  
  68.     p = buflen >= 4 ? buffer[3] : 0; //bNumFormats uvc格式format个数  
  69.     n = buflen >= size ? buffer[size-1] : 0; //bControlSize 控制位域大小  
  70.     if (buflen < size + p*n) {       //检测buflen长度是否合适  
  71.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d HEADER descriptor is invalid.\n",dev->udev->devnum, alts->desc.bInterfaceNumber);  
  72.         goto error;  
  73.     }  
  74.     //初始化uvc视频流头部  
  75.     streaming->header.bNumFormats = p;   //uvc格式format格式个数  
  76.     streaming->header.bEndpointAddress = buffer[6];  //端点地址  
  77.     if (buffer[2] == UVC_VS_INPUT_HEADER) { //输入的视频流  
  78.         streaming->header.bmInfo = buffer[7];            //信息位图(兼容性)  
  79.         streaming->header.bTerminalLink = buffer[8]; //连接到的输出Terminal ID号  
  80.         streaming->header.bStillCaptureMethod = buffer[9];   //静态图像捕捉方法(Method 1、Method 2、Method 3)  
  81.         streaming->header.bTriggerSupport = buffer[10];  //硬件触发支持  
  82.         streaming->header.bTriggerUsage = buffer[11];    //触发用例  
  83.     }   
  84.     else {  
  85.         streaming->header.bTerminalLink = buffer[7]; //连接到的输入Terminal ID号  
  86.     }  
  87.     streaming->header.bControlSize = n;  //控制位域大小  
  88.     streaming->header.bmaControls = kmemdup(&buffer[size], p * n,GFP_KERNEL);    //初始化bmaControls(x)位图(大小=帧数*位域大小)  
  89.     if (streaming->header.bmaControls == NULL) {  
  90.         ret = -ENOMEM;  
  91.         goto error;  
  92.     }  
  93.     buflen -= buffer[0];  
  94.     buffer += buffer[0];    //指向下一个描述符  
  95.     _buffer = buffer;  
  96.     _buflen = buflen;   //指向同一个描述符  

解析完vs header后解析剩下的vs描述符

第一次解析描述符 统计uvc帧、uvc格式、间隔,并分配内存

[cpp]  view plain copy
  1. /* Count the format and frame descriptors. 计算格式描述符和帧描述符个数*/  
  2.     while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {  
  3.         switch (_buffer[2]) {  
  4.         case UVC_VS_FORMAT_UNCOMPRESSED:  
  5.         case UVC_VS_FORMAT_MJPEG:  
  6.         case UVC_VS_FORMAT_FRAME_BASED:  
  7.             nformats++;  
  8.             break;  
  9.         case UVC_VS_FORMAT_DV:  
  10.             /* DV format has no frame descriptor. We will create a dummy frame descriptor with a dummy frame interval. */  
  11.             nformats++;  
  12.             nframes++;  
  13.             nintervals++;  
  14.             break;  
  15.         case UVC_VS_FORMAT_MPEG2TS:  
  16.         case UVC_VS_FORMAT_STREAM_BASED:  
  17.             uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT %u is not supported.\n",dev->udev->devnum,alts->desc.bInterfaceNumber, _buffer[2]);  
  18.             break;  
  19.         case UVC_VS_FRAME_UNCOMPRESSED:  
  20.         case UVC_VS_FRAME_MJPEG:  
  21.             nframes++;  
  22.             if (_buflen > 25)  
  23.                 nintervals += _buffer[25] ? _buffer[25] : 3;  
  24.             break;  
  25.         case UVC_VS_FRAME_FRAME_BASED:  
  26.             nframes++;  
  27.             if (_buflen > 21)  
  28.                 nintervals += _buffer[21] ? _buffer[21] : 3;  
  29.             break;  
  30.         }   //计算uvc帧和uvc格式的个数及间隔个数  
  31.         _buflen -= _buffer[0];    
  32.         _buffer += _buffer[0];  //跳到下一个描述符  
  33.     }  
  34.     if (nformats == 0) {  
  35.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d has no supported formats defined.\n",dev->udev->devnum, alts->desc.bInterfaceNumber);  
  36.         goto error;  
  37.     }  
  38.     //    uvc格式数 * uvc格式大小    + uvc帧   * uvc帧大小    + 间隔数     * 间隔大小  
  39.     size = nformats * sizeof *format + nframes * sizeof *frame+ nintervals * sizeof *interval;  
  40.     format = kzalloc(size, GFP_KERNEL); //分配uvc格式和uvc帧的内存  
  41.     if (format == NULL) {  
  42.         ret = -ENOMEM;  
  43.         goto error;  
  44.     }  
  45.     frame = (struct uvc_frame *)&format[nformats];  //uvc帧存放在uvc格式数组后面  
  46.     interval = (__u32 *)&frame[nframes];    //间隔放在帧后面  
  47.     streaming->format = format;  //uvc视频流捆绑uvc格式结构体  
  48.     streaming->nformats = nformats;  //uvc格式个数  

第二次解析描述符

[cpp]  view plain copy
  1. /* Parse the format descriptors.解析格式描述符 */  
  2. while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {  
  3.     switch (buffer[2]) {    //bDescriptorSubtype描述符类型  
  4.     case UVC_VS_FORMAT_UNCOMPRESSED:  
  5.     case UVC_VS_FORMAT_MJPEG:  
  6.     case UVC_VS_FORMAT_DV:  
  7.     case UVC_VS_FORMAT_FRAME_BASED:  
  8.         format->frame = frame;   //uvc格式的帧指针 指向uvc帧地址  
  9.         ret = uvc_parse_format(dev, streaming, format,&interval, buffer, buflen);   //7.解析uvc格式描述符  
  10.         if (ret < 0)  
  11.             goto error;  
  12.         frame += format->nframes;    //uvc帧地址指向下一个uvc格式所属的uvc帧地址  
  13.         format++;   //指向下一个uvc格式  
  14.         buflen -= ret;    
  15.         buffer += ret;  //指向下一个uvc格式描述符  
  16.         continue;  

[cpp]  view plain copy
  1. default:  
  2.     break;  
  3. }  

[cpp]  view plain copy
  1.         buflen -= buffer[0];  
  2.         buffer += buffer[0];        //指向下一个描述符  
  3.     }  
  4.     if (buflen)  
  5.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d has %u bytes of trailing descriptor garbage.\n",dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);  
  6.     /* Parse the alternate settings to find the maximum bandwidth. 解析设置并查找最大带宽*/  
  7.     for (i = 0; i < intf->num_altsetting; ++i) {  
  8.         struct usb_host_endpoint *ep;   //声明usb_host_endpoint 指针  
  9.         alts = &intf->altsetting[i];//获取usb_host_interface数组  
  10.         ep = uvc_find_endpoint(alts,streaming->header.bEndpointAddress); //查找对应usb_host_endpoint   
  11.         if (ep == NULL)  
  12.             continue;  
  13.         psize = le16_to_cpu(ep->desc.wMaxPacketSize);    //获取最大包尺寸  
  14.         psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); //换算  
  15.         if (psize > streaming->maxpsize)  
  16.             streaming->maxpsize = psize; //设置uvc视频流最大包尺寸对象  
  17.     }  
  18.     list_add_tail(&streaming->list, &dev->streams);   //添加到uvc设备视频流链表  
  19.     return 0;  
  20. error:  
  21.     usb_driver_release_interface(&uvc_driver.driver, intf);  
  22.     usb_put_intf(intf);  
  23.     kfree(streaming->format);  
  24.     kfree(streaming->header.bmaControls);  
  25.     kfree(streaming);  
  26.     return ret;  
  27. }  
6.3 添加uvc视频流到uvc设备视频流链表
list_add_tail(&streaming->list, &dev->streams);



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值