uvc摄像头代码解析4

来源:互联网 发布:java中函数调用 编辑:程序博客网 时间:2024/04/29 21:33

7.uvc_parse_format

7.1 uvc格式描述符

struct uvc_format_desc { //uvc格式描述符char *name; //uvc格式描述符名字__u8 guid[16];//全局唯一ID__u32 fcc; //压缩格式};
7.2 uvc解析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){struct usb_interface *intf = streaming->intf;//获取usb接口struct usb_host_interface *alts = intf->cur_altsetting;//获取usb_host_interfacestruct 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:

case UVC_VS_FORMAT_FRAME_BASED:

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:

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:

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格式的帧个数设置为1break;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  P15if (ftype != UVC_VS_FRAME_FRAME_BASED)//获取支持的不连续帧间隔数/连续帧间隔n = buflen > 25 ? buffer[25] : 0;elsen = 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帧描述符长度}

7.3 设置颜色空间

static __u32 uvc_colorspace(const __u8 primaries){static const __u8 colorprimaries[] = {0,V4L2_COLORSPACE_SRGB,V4L2_COLORSPACE_470_SYSTEM_M,V4L2_COLORSPACE_470_SYSTEM_BG,V4L2_COLORSPACE_SMPTE170M,V4L2_COLORSPACE_SMPTE240M,};if (primaries < ARRAY_SIZE(colorprimaries))return colorprimaries[primaries];//返回颜色空间数组项return 0;}
7.4 uvc格式/uvc帧/uvc视频流