您的位置:首页 > 编程语言

uvc摄像头代码解析4

2013-08-30 10:50 471 查看
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_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:



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格式的帧个数设置为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
, 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视频流

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: