我是靠谱客的博主 缓慢缘分,最近开发中收集的这篇文章主要介绍linux usb 带宽不足,uvc camera在usb带宽不足的情况下,如何正常出图?,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

uvc camera在usb带宽不足的情况下,如何正常出图?

发布时间:2018-06-07 09:25,

浏览次数:2265

, 标签:

uvc

camera

usb

在某些平台设备,如果同时使用多个uvc camera进行数据采集或者是同一个USB,既用作OTG功能,又用作USB host功能,会因为USB

带宽的的限制,导致camera无法正常使用,使用失败的现象如下:

uvcvideo: Failed to submit URB 0 (-28). No space left on device

在通过VIDIOC_STREAMON开启流数据传输时,将会产生以上错误,这个是由与USB的带宽不足导致的,出现这样的问题,可以尝试将分辨率调低,或者换为编码格式输出,如果还是不行,可以通过手动限制uvc

camera的输出带宽。

uvc驱动会在注册uvc camera的时候,在注册video节点之前,查询uvc

camera实际硬件的设备情况,并保存好,然后当使用的时候,设置完输出分辨率、格式等参数之后,在VIDIOC_STREAMON的时候,会根据设置的分辨率以及格式、注册video节点时查询得到的信息计算所需带宽,然后将该带宽与uvc

camera实际情况比较反馈得到一个合适的带宽设置到uvc camera中。

那么如何查看uvc camera支持的带宽信息呢?先通过lsusb命令查看得到uvc camera的厂家信息,比如得到下面的信息:

Bus 001 Device 041: ID 045e:0779 Microsoft Corp. LifeCam HD-3000

得知厂家id之后,比如从上面的信息可得知usb id为0x045e,接着通过lsusb -v -d 045e:

>info.txt命令,将查询uvc

camera的详细信息输出到info.txt。在info.txt中,通过搜索bAlternateSetting可以看到类似以下的信息:

Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1

bAlternateSetting 3 bNumEndpoints 1 bInterfaceClass 14 Video bInterfaceSubClass

2 Video Streaming bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor:

bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 5

Transfer Type Isochronous Synch Type Asynchronous Usage Type Data

wMaxPacketSize 0x0200 1x 512 bytes bInterval 1 Interface Descriptor: bLength 9

bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 4 bNumEndpoints 1

bInterfaceClass 14 Video bInterfaceSubClass 2 Video Streaming

bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor: bLength 7

bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 5 Transfer Type

Isochronous Synch Type Asynchronous Usage Type Data wMaxPacketSize 0x0400 1x

1024 bytes bInterval 1

其中的wMaxPacketSize变量说明的就是该uvc camera支持的带宽,它会支持多种带宽,以适应不同的USB传输速率。

在Linux内核中的uvc驱动就有usb带宽的匹配设置过程,代码位于drivers/media/usb/uvc下的uvc_video.c中,在uvc_init_video()函数中,就会根据所设置的分辨率以及格式等参数,计算得到的带宽与uvc

camera硬件支持的带宽进行一个适配,从而设置有效参数。

/* * Initialize isochronous/bulk URBs and allocate transfer buffers. */ static

int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) { struct

usb_interface *intf = stream->intf; struct usb_host_endpoint *ep; unsigned int

i; int ret; stream->sequence = -1; stream->last_fid = -1;

stream->bulk.header_size = 0; stream->bulk.skip_payload = 0;

stream->bulk.payload_size = 0; uvc_video_stats_start(stream); if

(intf->num_altsetting > 1) { struct usb_host_endpoint *best_ep = NULL; unsigned

int best_psize = UINT_MAX; unsigned int bandwidth; unsigned int

uninitialized_var(altsetting); int intfnum = stream->intfnum; /* Isochronous

endpoint, select the alternate setting. */ bandwidth =

stream->ctrl.dwMaxPayloadTransferSize; if (bandwidth == 0) {

uvc_trace(UVC_TRACE_VIDEO, "Device requested null " "bandwidth, defaulting to

lowest.n"); bandwidth = 1; } else { uvc_trace(UVC_TRACE_VIDEO, "Device

requested %u " "B/frame bandwidth.n", bandwidth); } for (i = 0; i <

intf->num_altsetting; ++i) { struct usb_host_interface *alts; unsigned int

psize; alts = &intf->altsetting[i]; ep = uvc_find_endpoint(alts,

stream->header.bEndpointAddress); if (ep == NULL) continue; /* Check if the

bandwidth is high enough. */ psize = uvc_endpoint_max_bpi(stream->dev->udev,

ep); if (psize >= bandwidth && psize <= best_psize) { altsetting =

alts->desc.bAlternateSetting; best_psize = psize; best_ep = ep; } } if (best_ep

== NULL) { uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " "for

requested bandwidth.n"); return -EIO; } uvc_trace(UVC_TRACE_VIDEO, "Selecting

alternate setting %u " "(%u B/frame bandwidth).n", altsetting, best_psize);

ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); if (ret < 0)

return ret; ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); } else { ...

}         ... return 0; }

在上述函数中,有以下这个操作:

/* Isochronous endpoint, select the alternate setting. */ bandwidth =

stream->ctrl.dwMaxPayloadTransferSize;

bandWidth就是根据分辨率以及格式得到的所需带宽,我们可以手动的修改这个值,将它调小,降低usb带宽,从而在带宽有限的情况下可以有效的使用uvc

camera,但是需要注意,并不是可以随便的修改该值,因为最终还需要通过该值与uvc

camera的实际支持的带宽进行匹配,即上面通过lsusb得到的info.txt中的wMaxPacketSize值进行适配。wMaxPacketSize代表着usb传输数据时,每个包的数据量大小,当改小时,降低带宽,相应的分辨率以及帧率也都会降低,这个可以尝试修改,得到一个最合适的带宽。

为了方便调试,看到相应的带宽设置参数,可通过修改drivers/media/usb/uvc中的uvc_driver.c的uvc_trace_param值,将其修改为如下

unsigned int uvc_trace_param = UVC_TRACE_VIDEO;

这样就可以将与带宽相关的信息打印出来。

在嵌入式中,如果出现这样的问题,如果是uvc

camera本身是支持高分辨率的,一般都是嵌入式的usb驱动没有做好导致的。建议检查usb驱动,是不是标准的hci驱动,同时,有没有调试过相应驱动的同步传输。

转载请注明出处!

最后

以上就是缓慢缘分为你收集整理的linux usb 带宽不足,uvc camera在usb带宽不足的情况下,如何正常出图?的全部内容,希望文章能够帮你解决linux usb 带宽不足,uvc camera在usb带宽不足的情况下,如何正常出图?所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部