usbcamera
android 外接 usbcamera,已经有比较成熟的技术方案UVCCamera,参考这个库,配置Andoird工程,依赖库接入,把外接usbcamera 流程跑通不难。
手头设备是海康威视的4K摄像头,run起立 camera画面也正常出来了。 如果都这么顺利的话,那就没这篇文章了 😂😂😂
4k
画面是出来了,发现分辨率最多只拉到2k(2560 x 1440),完全没有发挥出4k的能力。 比较容易想到的是 线 或者 hub 用的是usb2.0的(480Mbit/s),传输速度不够,所以出不了4K。
搞一根3.0的线 确定口子也是3.0的之后,再次跑起来,发现4k画面花了,只有顶上一点点内容,绝大部分是灰的,懵逼开始…
libXXX
懵逼没用 还是要解决问题的
简单梳理之后,问题应该不是android侧的,并没有什么java层的异常日志。 也是因为到目前为止,我们的工作也只是在android侧,各种lib 接入之后,目前不知道具体在做什么。
开始了解底层 native jni。
jni 进来对接的就是libuvc,libuvc 底层就是libusb
这两座大山全是C写的,懵逼升级…
闪烁
c/c++ 还给老师了, 但是 ctrl+c/v 那是不可能还的
很快发现 UVCCamera 都已经停留在5-6年前了,赶紧ctrl+c/v 把两座大山升级下,报错处理下、再次run起来。
出来了4k出来了,高兴不到3s,画面是出来了,新的问题出现了 画面闪烁,不是一直闪烁 偶尔闪那么几下。 几番来回实验下来,不单4k闪烁,连升级之前正常的2k也开始闪了。 懵逼继续…
闪烁的一帧画面如下:
log
硬着头皮看代码了,大概了解了调用流程之后(uvc usb的调用流程,官方的readme 跟 demo 也提到了),开始把一些日志开关打开,自己加一些log,mjpeg格式数据保存本地看看,把一些涉及到什么buffer_size 、timeout、payload 、lens等 可以调整参数的地方 改大 或者 改小。 一顿瞎操作之后,基本都是没用的。
不过倒是发现了一个日志,似乎跟闪烁有关系 “unrecognised urb status -1”,因为这个日志也是时不时的出现。
官方还真有这个issue
上面并没有说闪烁,也有想过是不是手上的海康4K摄像头有问题,驱动或者固件有问题。。。手上又没有其他的4k摄像头来测试。。。
但是说到 有没有在linux系统上试过,毕竟android不是真linux….
正好团队有一台ubuntu ,那就在linux上试试呗, 照着readme 把libuvc的example demo 跑起来,调整参数保持跟android一直,保存mjpeg数据到本地。 本地几百张图像没有一张是闪烁画面。。。 海康不背锅。。。
example demo 稍微做了写改造(配置makefile、opencv接入),把 libusb debug log开关打开了,使用 opencv 把画面显示出来了,参考下 demo
issue 里咨询下, 只说是android 内核问题,跟libusb没关系…. 懵逼升级….
uvc/usb
大概了解调用过程是不够的,那就继续了解。。。开始google大法。。。
无他,唯手熟尔
uvc usb的调用流程,官方的readme 跟 demo 都提到了 。
对着代码、协议、文档, 熟悉 uvc、usb、descriptor、transfer、urb 、ioctl 等等
慢慢开始熟悉 每个函数都在干嘛了 各个参数的意义了
知道 “unrecognised urb status -1”、”bad packet:xxx”、”submiturb failed, errno=-12” 这些日志的出处了,也就大概把范围缩小到几个关键的函数了
happy
在针对这几个函数 ,对比下libusb、libuvc 新老代码的代码实现,很快就发现了几处核心不同。
在新版本的libuvc (0.0.7)中, 有针对usb3.1 superspeed 端口的处理逻辑,老版本没有
1 | //steam.c |
新版本的libusb (1.0.26), 单个urb packet len更大
1 | //linux_usbfs.c |
老版本的libusb中 ,比新版本有更多的urb请求
1 | //linux_usbfs.c |
首先老的libuvc 没有针对 ss 端口做处理,肯定是有问题的 ,也就解释了懵逼的开始 为什么4k画面花了,只有顶上一点点内容,绝大部分是灰的,因为 usb 2.0算出来 传输 urb少了,只拿到前面的urb数据,也就是顶部的画面。
新版本的libusb中,urb size 比较大,4k参数 算下来只需要一个urb ,也就是出现 “bad packet:xxx”、”submiturb failed, errno=-12”这些异常日志的原因。为什么linux上正常,而andoird有问题,猜测 手机的内存、带宽等等跟pc还是没法比的。。
到这里能想到的可尝试方案 基本就出来了
- 老的uvc 增加对ss 的处理逻辑
- 新的usb 减少urb packet size,出更多的urb
最终 两种方案 尝试下 都可以解决问题。。
happy …
other
针对这两点 官方代码的提交历史
1 | libuvc |
1 | libusb |