前言
前段时间捣鼓多USB摄像头的方案,一阵手忙脚乱算是勉强跑起来了。整个流程主要还是依赖于网上大神们封装好的库。之前想仔细分析一下整套底层实现,然而一直拖到现在……也没有完全看完,于是想着干脆分阶段总结吧。未来打算用几篇文章的篇幅来分析启动、拍照、视频录制等几个环节。
本篇就从相机的初始化、启动预览说起吧。废话少说,进入正题。
先贴链接:
整个UVCCamera框架包括了Java层封装,c层UVCCamera、c层libuvc以及c层libusb这几个库。
Java层
我们先从业务方直接可以调用的最上层(Java层)说起。
在初始化阶段,整个Java层会涉及到的类有:
com.serenegiant.usb.USBMonitor
com.serenegiant.usb.USBMonitor.UsbControlBlock
com.serenegiant.usb.USBMonitor.OnDeviceConnectListener
com.serenegiant.usb.common.UVCCameraHandler
com.serenegiant.usb.common.AbstractUVCCameraHandler.CameraThread
稍微画了一下整个调用流程,读者可以粗略看一下有个大概印象:
Java层时序图
当我们启动相机的时候,第一件要做的事情就是要连接上摄像头,依然是usb摄像头,那么自然我们会需要尝试建立usb连接。而连接usb设备要做的第一件事就是获取权限:
/**
* request permission to access to USB device
* @param device
* @return true if fail to request permission
*/
public synchronized boolean requestPermission(final UsbDevice device) {
// if (DEBUG) Log.v(TAG, "requestPermission:device=" + device);
boolean result = false;
if (isRegistered()) {
if (device != null) {
if (mUsbManager.hasPermission(device)) {
// call onConnect if app already has permission
processConnect(device);
} else {
try {
// パーミッションがなければ要求する
mUsbManager.requestPermission(device, mPermissionIntent);
} catch (final Exception e) {
// Android5.1.xのGALAXY系でandroid.permission.sec.MDM_APP_MGMTという意味不明の例外生成するみたい
Log.w(TAG, e);
processCancel(device);
result = true;
}
}
} else {
processCancel(device);
result = true;
}
} else {
processCancel(device);
result = true;
}
return result;
}
从代码中可以看到,在获取到权限之后继而调用了processConnect方法来尝试建立usb连接:
/**
* open specific USB device
* @param device
*/
private final void processConnect(final UsbDevice device) {
if (destroyed) return;
updatePermission(device, true);
mAsyncHandler.post(new Runn