uvc摄像头代码解析4

7.uvc_parse_format

7.1 uvc格式描述符

[cpp]  view plain copy
  1. struct uvc_format_desc { //uvc格式描述符  
  2. char *name; //uvc格式描述符名字  
  3. __u8 guid[16];//全局唯一ID  
  4. __u32 fcc; //压缩格式  
  5. };  
7.2 uvc解析1个格式描述符

[cpp]  view plain copy
  1. static int uvc_parse_format(struct uvc_device *dev,struct uvc_streaming *streaming, struct uvc_format *format,__u32 **intervals, unsigned char *buffer, int buflen)  
  2. {  
  3.     struct usb_interface *intf = streaming->intf;    //获取usb接口  
  4.     struct usb_host_interface *alts = intf->cur_altsetting;  //获取usb_host_interface  
  5.     struct uvc_format_desc *fmtdesc;    //uvc格式描述符  
  6.     struct uvc_frame *frame;    //uvc帧  
  7.     const unsigned char *start = buffer;  
  8.     unsigned int interval;  
  9.     unsigned int i, n;  
  10.     __u8 ftype;  
  11.   
  12.     format->type = buffer[2];    //uvc格式类型  
  13.     format->index = buffer[3];   //uvc格式索引  
  14.     switch (buffer[2]) {    //uvc格式类型  
  15.     case UVC_VS_FORMAT_UNCOMPRESSED:  

[cpp]  view plain copy
  1. case UVC_VS_FORMAT_FRAME_BASED:  

[cpp]  view plain copy
  1.     n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;  //获取描述符大小  
  2.     if (buflen < n) {    //检验buflen大小  
  3.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);  
  4.         return -EINVAL;  
  5.     }  
  6.     /* Find the format descriptor from its GUID. */  
  7.     fmtdesc = uvc_format_by_guid(&buffer[5]);   //获取uvc格式描述符  
  8.     if (fmtdesc != NULL) {  //设置uvc格式编码格式名字  
  9.         strlcpy(format->name, fmtdesc->name,sizeof format->name);  
  10.         format->fcc = fmtdesc->fcc;   //设置uvc格式的fcc(压缩格式)  
  11.     }   
  12.     else {  //不能识别的格式  
  13.         uvc_printk(KERN_INFO, "Unknown video format %pUl\n",&buffer[5]);  
  14.         snprintf(format->name, sizeof(format->name), "%pUl\n",&buffer[5]);  
  15.         format->fcc = 0;  
  16.     }  
  17.     format->bpp = buffer[21];    //设置uvc格式bpp(每像素多少位)  
  18.     if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {  
  19.         ftype = UVC_VS_FRAME_UNCOMPRESSED;  //设置ftype(frame type)  
  20.     }   
  21.  else {  
  22.         ftype = UVC_VS_FRAME_FRAME_BASED;   //设置ftype(frame type)  
  23.         if (buffer[27])  
  24.             format->flags = UVC_FMT_FLAG_COMPRESSED; //设置uvc格式标志(压缩的)  
  25.     }  
  26.     break;  
  27. case UVC_VS_FORMAT_MJPEG:  

[cpp]  view plain copy
  1.     if (buflen < 11) {   //检验buflen大小  
  2.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);  
  3.         return -EINVAL;  
  4.     }  
  5.     strlcpy(format->name, "MJPEG"sizeof format->name);  //设置uvc格式编码格式名字“MJPEG”  
  6.     format->fcc = V4L2_PIX_FMT_MJPEG;    //设置uvc格式的fcc(压缩格式)  
  7.     format->flags = UVC_FMT_FLAG_COMPRESSED; //设置uvc格式标志(压缩的)  
  8.     format->bpp = 0; //设置uvc格式bpp(每像素多少位)  
  9.     ftype = UVC_VS_FRAME_MJPEG; //设置ftype(frame type)  
  10.     break;  
  11. case UVC_VS_FORMAT_DV:  

[cpp]  view plain copy
  1.         if (buflen < 9) {    //检验buflen大小  
  2.             uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);  
  3.             return -EINVAL;  
  4.         }  
  5.         switch (buffer[8] & 0x7f) { //bFormatType格式类型  
  6.         case 0: //设置uvc格式编码格式名字 "SD-DV"  
  7.             strlcpy(format->name, "SD-DV"sizeof format->name);  
  8.             break;  
  9.         case 1: //设置uvc格式编码格式名字 "SDL-DV"  
  10.             strlcpy(format->name, "SDL-DV"sizeof format->name);  
  11.             break;  
  12.         case 2: //设置uvc格式编码格式名字 "HD-DV"  
  13.             strlcpy(format->name, "HD-DV"sizeof format->name);  
  14.             break;  
  15.         default:  
  16.             uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d: unknown DV format %u\n",dev->udev->devnum,alts->desc.bInterfaceNumber, buffer[8]);  
  17.             return -EINVAL;  
  18.         }  
  19.         strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",sizeof format->name);    //扫描格式eg("HD-DV 60Hz")  
  20.         format->fcc = V4L2_PIX_FMT_DV;   //设置uvc格式的fcc(压缩格式)  
  21.         format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;   //设置uvc格式标志(压缩的|数据流)  
  22.         format->bpp = 0; //设置uvc格式bpp(每像素多少位)  
  23.         ftype = 0;  //设置ftype(frame type)  
  24.         /* Create a dummy frame descriptor. 创建插入一个帧描述符*/  
  25.         frame = &format->frame[0];   //获取uvc格式的第一个帧地址  
  26.         memset(&format->frame[0], 0, sizeof format->frame[0]);    //初始化uvc帧  
  27.         frame->bFrameIntervalType = 1;   //uvc帧间隔类型  
  28.         frame->dwDefaultFrameInterval = 1;   //uvc帧默认间隔  
  29.         frame->dwFrameInterval = *intervals; //uvc帧间隔  
  30.         *(*intervals)++ = 1;    //添加间隔  
  31.         format->nframes = 1; //uvc格式的帧个数设置为1  
  32.         break;  
  33.     case UVC_VS_FORMAT_MPEG2TS:  
  34.     case UVC_VS_FORMAT_STREAM_BASED:  
  35.         /* Not supported yet. */  
  36.     default:  
  37.         uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d unsupported format %u\n",dev->udev->devnum, alts->desc.bInterfaceNumber,buffer[2]);  
  38.         return -EINVAL;  
  39.     }  
  40.     uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);  
  41.     buflen -= buffer[0];  
  42.     buffer += buffer[0];    //下一个描述符(uvc帧描述符)  
  43.     /* Parse the frame descriptors. Only uncompressed, MJPEG and frame based formats have frame descriptors.*/  
  44.     while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) {   //buffer[2]=bDescriptorSubtype==frame type?  
  45.         frame = &format->frame[format->nframes];  //获取第二个uvc格式的uvc帧指针  
  46. //UVC_VS_FRAME_FRAME_BASED参看USB_Video_Payload_Frame_Based_1.5.pdf  P15  
  47.         if (ftype != UVC_VS_FRAME_FRAME_BASED)  //获取支持的不连续帧间隔数/连续帧间隔  
  48.             n = buflen > 25 ? buffer[25] : 0;  
  49.         else  
  50.             n = buflen > 21 ? buffer[21] : 0;      
  51.         n = n ? n : 3;  //支持不连续帧间隔?支持不连续帧间隔间隔数:连续帧间隔  
  52.         if (buflen < 26 + 4*n) { //检验buflen大小  
  53.             uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FRAME error\n", dev->udev->devnum,alts->desc.bInterfaceNumber);  
  54.             return -EINVAL;  
  55.         }  
  56.         frame->bFrameIndex = buffer[3];  //获取uvc帧索引  
  57.         frame->bmCapabilities = buffer[4];   //获取uvc帧兼容性  
  58.         frame->wWidth = get_unaligned_le16(&buffer[5]);  //解码uvc视频宽度  
  59.         frame->wHeight = get_unaligned_le16(&buffer[7]); //解码uvc视频高度  
  60.         frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);    //解码uvc视频最小位流  
  61.         frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);   //解码uvc视频最大位流  
  62.         if (ftype != UVC_VS_FRAME_FRAME_BASED) {  
  63.             frame->dwMaxVideoFrameBufferSize =get_unaligned_le32(&buffer[17]);   //uvc最大视频帧缓冲区大小  
  64.             frame->dwDefaultFrameInterval =get_unaligned_le32(&buffer[21]);  //uvc默认帧间隔  
  65.             frame->bFrameIntervalType = buffer[25];  //uvc帧间隔类型  
  66.         }   
  67.         else {  
  68.             frame->dwMaxVideoFrameBufferSize = 0;    //uvc最大视频帧缓冲区大小  
  69.             frame->dwDefaultFrameInterval =get_unaligned_le32(&buffer[17]);  //uvc默认帧间隔  
  70.             frame->bFrameIntervalType = buffer[21];  //uvc帧间隔类型  
  71.         }  
  72.         frame->dwFrameInterval = *intervals; //设置uvc帧间隔指针  
  73.         if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))  //uvc格式标志(压缩的)  
  74.             frame->dwMaxVideoFrameBufferSize = format->bpp * frame->wWidth * frame->wHeight / 8;    //计算uvc帧最大视频格式缓冲去大小(byte)  
  75.         for (i = 0; i < n; ++i) {  
  76.             interval = get_unaligned_le32(&buffer[26+4*i]); //获取uvc帧间隔  
  77.             *(*intervals)++ = interval ? interval : 1;  //调整uvc帧间隔大小  
  78.         }  
  79.         /* Make sure that the default frame interval stays between the boundaries.*/  
  80.         n -= frame->bFrameIntervalType ? 1 : 2;  //uvc帧间隔边界调整  
  81.         frame->dwDefaultFrameInterval = min(frame->dwFrameInterval[n], max(frame->dwFrameInterval[0],frame->dwDefaultFrameInterval));  
  82.         if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {  
  83.             frame->bFrameIntervalType = 1;  
  84.             frame->dwFrameInterval[0] = frame->dwDefaultFrameInterval;  
  85.         }  
  86.         uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",frame->wWidth, frame->wHeight,10000000/frame->dwDefaultFrameInterval,(100000000/frame->dwDefaultFrameInterval)%10);  
  87.         format->nframes++;   //调整uvc格式帧数  
  88.         buflen -= buffer[0];  
  89.         buffer += buffer[0];    //指向下一个描述符(uvc帧描述符)  
  90.     }  
  91.     if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {   //静态图像帧  
  92.         buflen -= buffer[0];  
  93.         buffer += buffer[0];    //跳过指向下一个描述符  
  94.     }  
  95.     if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == UVC_VS_COLORFORMAT) { //颜色格式帧  
  96.         if (buflen < 6) {  
  97.             uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d COLORFORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);  
  98.             return -EINVAL;  
  99.         }  
  100.         format->colorspace = uvc_colorspace(buffer[3]);  //buffer[3]=bColorPrimaries 设置颜色空间  
  101.         buflen -= buffer[0];  
  102.         buffer += buffer[0];    //指向下一描述符  
  103.     }  
  104.     return buffer - start;  //返回解析了的uvc格式描述符+所含的uvc帧描述符长度  
  105. }  

7.3 设置颜色空间

[cpp]  view plain copy
  1. static __u32 uvc_colorspace(const __u8 primaries)  
  2. {  
  3.     static const __u8 colorprimaries[] = {  
  4.         0,  
  5.         V4L2_COLORSPACE_SRGB,  
  6.         V4L2_COLORSPACE_470_SYSTEM_M,  
  7.         V4L2_COLORSPACE_470_SYSTEM_BG,  
  8.         V4L2_COLORSPACE_SMPTE170M,  
  9.         V4L2_COLORSPACE_SMPTE240M,  
  10.     };  
  11.     if (primaries < ARRAY_SIZE(colorprimaries))  
  12.         return colorprimaries[primaries];   //返回颜色空间数组项  
  13.     return 0;  
  14. }  
7.4 uvc格式/uvc帧/uvc视频流




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值