程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> uvc攝像頭代碼解析4

uvc攝像頭代碼解析4

編輯:C++入門知識

7.uvc_parse_format 7.1 uvc格式描述符 [cpp]   struct uvc_format_desc { //uvc格式描述符   char *name; //uvc格式描述符名字   __u8 guid[16];//全局唯一ID   __u32 fcc; //壓縮格式   };   7.2 uvc解析1個格式描述符 [cpp]  static int uvc_parse_format(struct uvc_device *dev,struct uvc_streaming *streaming, struct uvc_format *format,__u32 **intervals, unsigned char *buffer, int buflen)   {       struct usb_interface *intf = streaming->intf;    //獲取usb接口       struct usb_host_interface *alts = intf->cur_altsetting;  //獲取usb_host_interface       struct uvc_format_desc *fmtdesc;    //uvc格式描述符       struct uvc_frame *frame;    //uvc幀       const unsigned char *start = buffer;       unsigned int interval;       unsigned int i, n;       __u8 ftype;          format->type = buffer[2];    //uvc格式類型       format->index = buffer[3];   //uvc格式索引       switch (buffer[2]) {    //uvc格式類型       case UVC_VS_FORMAT_UNCOMPRESSED:     [cpp]   case UVC_VS_FORMAT_FRAME_BASED:     [cpp]       n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;  //獲取描述符大小       if (buflen < n) {    //檢驗buflen大小           uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);           return -EINVAL;       }       /* Find the format descriptor from its GUID. */       fmtdesc = uvc_format_by_guid(&buffer[5]);   //獲取uvc格式描述符       if (fmtdesc != NULL) {  //設置uvc格式編碼格式名字           strlcpy(format->name, fmtdesc->name,sizeof format->name);           format->fcc = fmtdesc->fcc;   //設置uvc格式的fcc(壓縮格式)       }        else {  //不能識別的格式           uvc_printk(KERN_INFO, "Unknown video format %pUl\n",&buffer[5]);           snprintf(format->name, sizeof(format->name), "%pUl\n",&buffer[5]);           format->fcc = 0;       }       format->bpp = buffer[21];    //設置uvc格式bpp(每像素多少位)       if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {           ftype = UVC_VS_FRAME_UNCOMPRESSED;  //設置ftype(frame type)       }     else {           ftype = UVC_VS_FRAME_FRAME_BASED;   //設置ftype(frame type)           if (buffer[27])               format->flags = UVC_FMT_FLAG_COMPRESSED; //設置uvc格式標志(壓縮的)       }       break;   case UVC_VS_FORMAT_MJPEG:     [cpp]      if (buflen < 11) {   //檢驗buflen大小           uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);           return -EINVAL;       }       strlcpy(format->name, "MJPEG", sizeof format->name);  //設置uvc格式編碼格式名字“MJPEG”       format->fcc = V4L2_PIX_FMT_MJPEG;    //設置uvc格式的fcc(壓縮格式)       format->flags = UVC_FMT_FLAG_COMPRESSED; //設置uvc格式標志(壓縮的)       format->bpp = 0; //設置uvc格式bpp(每像素多少位)       ftype = UVC_VS_FRAME_MJPEG; //設置ftype(frame type)       break;   case UVC_VS_FORMAT_DV:     [cpp]           if (buflen < 9) {    //檢驗buflen大小               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);               return -EINVAL;           }           switch (buffer[8] & 0x7f) { //bFormatType格式類型           case 0: //設置uvc格式編碼格式名字 "SD-DV"               strlcpy(format->name, "SD-DV", sizeof format->name);               break;           case 1: //設置uvc格式編碼格式名字 "SDL-DV"               strlcpy(format->name, "SDL-DV", sizeof format->name);               break;           case 2: //設置uvc格式編碼格式名字 "HD-DV"               strlcpy(format->name, "HD-DV", sizeof format->name);               break;           default:               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d: unknown DV format %u\n",dev->udev->devnum,alts->desc.bInterfaceNumber, buffer[8]);               return -EINVAL;           }           strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",sizeof format->name);    //掃描格式eg("HD-DV 60Hz")           format->fcc = V4L2_PIX_FMT_DV;   //設置uvc格式的fcc(壓縮格式)           format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;   //設置uvc格式標志(壓縮的|數據流)           format->bpp = 0; //設置uvc格式bpp(每像素多少位)           ftype = 0;  //設置ftype(frame type)           /* Create a dummy frame descriptor. 創建插入一個幀描述符*/           frame = &format->frame[0];   //獲取uvc格式的第一個幀地址           memset(&format->frame[0], 0, sizeof format->frame[0]);    //初始化uvc幀           frame->bFrameIntervalType = 1;   //uvc幀間隔類型           frame->dwDefaultFrameInterval = 1;   //uvc幀默認間隔           frame->dwFrameInterval = *intervals; //uvc幀間隔           *(*intervals)++ = 1;    //添加間隔           format->nframes = 1; //uvc格式的幀個數設置為1           break;       case UVC_VS_FORMAT_MPEG2TS:       case UVC_VS_FORMAT_STREAM_BASED:           /* Not supported yet. */       default:           uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d unsupported format %u\n",dev->udev->devnum, alts->desc.bInterfaceNumber,buffer[2]);           return -EINVAL;       }       uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);       buflen -= buffer[0];       buffer += buffer[0];    //下一個描述符(uvc幀描述符)       /* Parse the frame descriptors. Only uncompressed, MJPEG and frame based formats have frame descriptors.*/       while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == ftype) {   //buffer[2]=bDescriptorSubtype==frame type?           frame = &format->frame[format->nframes];  //獲取第二個uvc格式的uvc幀指針   //UVC_VS_FRAME_FRAME_BASED參看USB_Video_Payload_Frame_Based_1.5.pdf  P15           if (ftype != UVC_VS_FRAME_FRAME_BASED)  //獲取支持的不連續幀間隔數/連續幀間隔               n = buflen > 25 ? buffer[25] : 0;           else               n = buflen > 21 ? buffer[21] : 0;               n = n ? n : 3;  //支持不連續幀間隔?支持不連續幀間隔間隔數:連續幀間隔           if (buflen < 26 + 4*n) { //檢驗buflen大小               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FRAME error\n", dev->udev->devnum,alts->desc.bInterfaceNumber);               return -EINVAL;           }           frame->bFrameIndex = buffer[3];  //獲取uvc幀索引           frame->bmCapabilities = buffer[4];   //獲取uvc幀兼容性           frame->wWidth = get_unaligned_le16(&buffer[5]);  //解碼uvc視頻寬度           frame->wHeight = get_unaligned_le16(&buffer[7]); //解碼uvc視頻高度           frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);    //解碼uvc視頻最小位流           frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);   //解碼uvc視頻最大位流           if (ftype != UVC_VS_FRAME_FRAME_BASED) {               frame->dwMaxVideoFrameBufferSize =get_unaligned_le32(&buffer[17]);   //uvc最大視頻幀緩沖區大小               frame->dwDefaultFrameInterval =get_unaligned_le32(&buffer[21]);  //uvc默認幀間隔               frame->bFrameIntervalType = buffer[25];  //uvc幀間隔類型           }            else {               frame->dwMaxVideoFrameBufferSize = 0;    //uvc最大視頻幀緩沖區大小               frame->dwDefaultFrameInterval =get_unaligned_le32(&buffer[17]);  //uvc默認幀間隔               frame->bFrameIntervalType = buffer[21];  //uvc幀間隔類型           }           frame->dwFrameInterval = *intervals; //設置uvc幀間隔指針           if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))  //uvc格式標志(壓縮的)               frame->dwMaxVideoFrameBufferSize = format->bpp * frame->wWidth * frame->wHeight / 8;    //計算uvc幀最大視頻格式緩沖去大小(byte)           for (i = 0; i < n; ++i) {               interval = get_unaligned_le32(&buffer[26+4*i]); //獲取uvc幀間隔               *(*intervals)++ = interval ? interval : 1;  //調整uvc幀間隔大小           }           /* Make sure that the default frame interval stays between the boundaries.*/           n -= frame->bFrameIntervalType ? 1 : 2;  //uvc幀間隔邊界調整           frame->dwDefaultFrameInterval = min(frame->dwFrameInterval[n], max(frame->dwFrameInterval[0],frame->dwDefaultFrameInterval));           if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {               frame->bFrameIntervalType = 1;               frame->dwFrameInterval[0] = frame->dwDefaultFrameInterval;           }           uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",frame->wWidth, frame->wHeight,10000000/frame->dwDefaultFrameInterval,(100000000/frame->dwDefaultFrameInterval)%10);           format->nframes++;   //調整uvc格式幀數           buflen -= buffer[0];           buffer += buffer[0];    //指向下一個描述符(uvc幀描述符)       }       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {   //靜態圖像幀           buflen -= buffer[0];           buffer += buffer[0];    //跳過指向下一個描述符       }       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE && buffer[2] == UVC_VS_COLORFORMAT) { //顏色格式幀           if (buflen < 6) {               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d COLORFORMAT error\n",dev->udev->devnum,alts->desc.bInterfaceNumber);               return -EINVAL;           }           format->colorspace = uvc_colorspace(buffer[3]);  //buffer[3]=bColorPrimaries 設置顏色空間           buflen -= buffer[0];           buffer += buffer[0];    //指向下一描述符       }       return buffer - start;  //返回解析了的uvc格式描述符+所含的uvc幀描述符長度   }    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved