uvc摄像头代码解析3(三)
L) {
ret = -ENOMEM;
goto error;
}
buflen -= buffer[0];
buffer += buffer[0]; //指向下一个描述符
_buffer = buffer;
_buflen = buflen; //指向同一个描述符
解析完vs header后解析剩下的vs描述符
第一次解析描述符 统计uvc帧、uvc格式、间隔,并分配内存
[cpp]
/* Count the format and frame descriptors. 计算格式描述符和帧描述符个数*/
while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
switch (_buffer[2]) {
case UVC_VS_FORMAT_UNCOMPRESSED:
case UVC_VS_FORMAT_MJPEG:
case UVC_VS_FORMAT_FRAME_BASED:
nformats++;
break;
case UVC_VS_FORMAT_DV:
/* DV format has no frame descriptor. We will create a dummy frame descriptor with a dummy frame interval. */
nformats++;
nframes++;
nintervals++;
break;
case UVC_VS_FORMAT_MPEG2TS:
case UVC_VS_FORMAT_STREAM_BASED:
uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d FORMAT %u is not supported.\n",dev->udev->devnum,alts->desc.bInterfaceNumber, _buffer[2]);
break;
case UVC_VS_FRAME_UNCOMPRESSED:
case UVC_VS_FRAME_MJPEG:
nframes++;
if (_buflen > 25)
nintervals += _buffer[25] _buffer[25] : 3;
break;
case UVC_VS_FRAME_FRAME_BASED:
nframes++;
if (_buflen > 21)
nintervals += _buffer[21] _buffer[21] : 3;
break;
} //计算uvc帧和uvc格式的个数及间隔个数
_buflen -= _buffer[0];
_buffer += _buffer[0]; //跳到下一个描述符
}
if (nformats == 0) {
uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface %d has no supported formats defined.\n",dev->udev->devnum, alts->desc.bInterfaceNumber);
goto error;
}
// uvc格式数 * uvc格式大小 + uvc帧 * uvc帧大小 + 间隔数 * 间隔大小
size = nformats * sizeof *format + nframes * sizeof *frame+ nintervals * sizeof *interval;
format = kzalloc(size, GFP_KERNEL); //分配uvc格式和uvc帧的内存
if (format == NULL) {
ret = -ENOMEM;
goto error;
}
frame = (struct uvc_frame *)&format[nformats]; //uvc帧存放在uvc格式数组后面
interval = (__u32 *)&frame[nframes]; //间隔放在帧后面
streaming->format = format; //uvc视频流捆绑uvc格式结构体
streaming->nformats = nformats; //uvc格式个数
第二次解析描述符
[cpp]
/* Parse the format descriptors.解析格式描述符 */
while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
switch (buffer[2]) { //bDescriptorSubtype描述符类型
case UVC_VS_FORMAT_UNCOMPRESSED:
case UVC_VS_FORMAT_MJPEG:
case UVC_VS_FORMAT_DV:
case UVC_VS_FORMAT_FRAME_BASED:
format->frame = frame; //uvc格式的帧指针 指向uvc帧地址
ret = uvc_parse_format(dev, streaming, format,&interval, buffer, buflen); //7.解析uvc格式描述符
if (ret < 0)
goto error;
frame += format->nframes; //uvc帧地址指向下一个uvc格式所属的uvc帧地址
format++; //指向下一个uvc格式
buflen -= ret;
buffer += ret; //指向下一个uvc格式描述符
continue;