uvc摄像头代码解析4

7.u vc _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帧描述符长度  
}  
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值