UVC for USBCamera in Android

基于UVC 协议,完成USBCamera 开发

文章目录


一、目的:

1)依托于以前公司项目中自己折腾出来的USBCamera 基于 UVC协议,特别有必要总结一次,总结核心内容和知识点。

2)对于需要USBCamera 项目需求的新手一些指导性 建议、思路,特别适用,并不是所有的人都能上手直接折腾出来的

二、USBCamera 技术实现方案

  • 基于UVC协议 来实现
  • 基于Android 体系下的SDK API来实现,底层就是Camera 或者 Camera2 框架下来实现

难点

UVC 协议相机开发,资料很少很少 还比较老旧,基于UVC协议开发USBCamera 解决了UVC协议 库文件 等基本库方法问题,还需要知晓USB通讯相关知识。

三、误区:

基本常识是 USBCamera 是无驱的,那么跟底层系统不相关,USB相机插着就能用,系统本身支持的想法其实是错误的。

大家可以自行查阅相关资料,这里重点说明的是:

1)使用UVC协议来实现USBCamera ,作为一个系统应用 具备系统签名,不用考虑各种权限,是没有问题的。

2)使用Android SDK 框架下的API来实现USBCamera 是不可取的,官方文档明确说明Camera2 是不支持的。但是我们在不同半导体平台下不一样,比如RK上面是支持Camera2 开发USBCamera,

但是在MTK上面 Camera2 是不支持USBCamera,就是打不开相机的。 所以,要想实现Camera2 API来写一个USBCamera 务必驱动层、framework层在芯片平台支持的情况下适配好才行。

四、基础补充、资源参考

对于相机开发,还是建议无论是UVC协议开发USBCamera,还是 Android SDK API框架下Camera api 来开发相机,都需要了解最基本的相关资料。UVC和Camera 架构体系是两套完全不同的体系,可分别参考。

相机整个模块确实太专业、复杂了。 无论从硬件外设、驱动【USBCamera免驱】、相机 都比较专业、覆盖面及广,针对思考中的问题 给出自己认为比较好相关博客,方便了解,助于梳理流程、提升认知。

对于上层应用或者Framework 系统应用开发者,只需要了解基本的架构、API、使用方法,当然这些也不简单的

下面提供部分资源,方便快速了解,充电

架构图了解

MTKCamera2相机架构
Camera2架构
Android Camera架构简析

Camera相关专栏

Camera Framework 专栏
小驰私房菜系列
小驰私房菜MTK系列
小驰Camera 开发系列
Camera 相机开发
展讯平台 Camera
官方文档:谷歌官方 API 描述

零散知识了解

MTK 相机UI介绍
Camera2 相机认知
Camera2学习笔记
camera2关于拍照预览方向旋转90度和拍照图片镜像功能实现
Camera2 预览集成、简单拍照:熟悉预览步骤流程比较有用
Camera镜像上下左右颠倒问题的解决办法
MTK相机成像质量差
Camera应用分析

部分相机源码参考,学习API使用,梳理流程,偏应用层

极客相机 Camera2 API
Camera2 API详解
极客相机源码
Camera2 相机Demo
Camera2 专业相机Demo
拍照、预览、录像Demo
使用Camera2 拍照

Camera2 系统相关

Camera2 Service 启动

五)具体项目参考

参考gitHub项目:
UVCCamera 原始项目 需要自己配置NDK,编译
USBCamera 自己就是通过这个开源代码进行修改,定制,实现自身USBCamera 业务
AndroidUSBCamera 比较好的,支持多个USBCamera 并行展示,功能齐全,但是分辨率无法全部加载、存在.so 崩溃导致无解。

项目参考优劣:

  • UVCCamera:基本功能,需要自己封装方法,编译,搭建环境。 项目太老,很难跑通,需要自己封装。
  • USBCamera:封装比较好,单个摄像头显示 基本功能都有的 预览、拍照、录像OK,USB检测,查找、注册流程 都有,方便熟悉 USBCamera 使用流程,USBCamera的思想。上层相关USBManager 相关api 参考,到底层 native层不用管他们。
  • AndroidUSBCamera:封装最好,功能特别齐全,也可以实现多个摄像头同时显示。 但是预览尺寸会显示不全、部分预览尺寸点击会崩溃。
    这个目前无解,需要源码重新编译.so,无解,仅供学习使用。

建议直接从 USBCamera、AndroidUSBCamera 两个开源项目选择其中一个,根据自己实际需求来选择适合自己的项目。 如果指定了分辨率,对分辨率无选择要求,可以选择AndroidUSBCamera 。

如果通用版本,强烈建议选择USBCamera项目,稳定性更强。

当然:两个项目都有崩溃,特别在定制自己应用,在各种复杂场景下,各种崩溃需要自己去解决 适配。


六) 核心源码逻辑说明

权限、过滤器

java 复制代码
 AndroidMenifest.xml 中
	 
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
      <uses-permission android:name="android.permission.CAMERA"
          tools:ignore="PermissionImpliesUnsupportedChromeOsHardware" />
    <uses-feature android:name="android.hardware.usb.host"/>





  res/xml/device_filter.xml 过滤usb 设备
  
<usb>
	<usb-device class="239" subclass="2" />	<!-- all device of UVC -->
	<!-- a few android 9.0 -->
	<usb-device class="14" subclass="9" />
	<usb-device class="2" subclass="0" />
	<usb-device class="6" subclass="-1" />
	<usb-device class="39" subclass="0" />
	<usb-device class="0" subclass="0" />
	<usb-device class="239" subclass="2" />
	<usb-device class="239" subclass="2" />
	<usb-device product-id="4836" vendor-id="9573" />
	<usb-device product-id="2229" vendor-id="1133" />
	<usb-device product-id="640" vendor-id="1409" />
	<usb-device product-id="258" vendor-id="9228" />
	<usb-device product-id="61" vendor-id="65366" />
	<usb-device product-id="4867" vendor-id="10071" />
	<usb-device product-id="7995" vendor-id="4130" />
	<!--
	classData:0   subClassData:0  productId:61   vendorId1Id:65366
	 classData:239   subClassData:2  productId:4867   vendorId1Id:10071
classData:0   subClassData:0  productId:61   vendorId1Id:65366
 classData:0   subClassData:0  productId:61   vendorId1Id:65366
	-->
</usb>

通过USBManager 获取服务 得到USB外设

获取UsbManager 对象

java 复制代码
mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE)

得到 detected devices

java 复制代码
final HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList()

得到过滤条件,加载xml 过滤器

java 复制代码
    List<DeviceFilter> deviceFilters = DeviceFilter
                .getDeviceFilters(mActivity.getApplicationContext(), R.xml.device_filter);

过滤得到所有的 有效的外设 USBDevice

java 复制代码
final List<UsbDevice> result = new ArrayList<UsbDevice>();
		if (deviceList != null) {
			if ((filters == null) || filters.isEmpty()) {
				result.addAll(deviceList.values());
			} else {
				for (final UsbDevice device: deviceList.values() ) {
					// match devices
					for (final DeviceFilter filter: filters) {
						if ((filter != null) && filter.matches(device) || (filter != null && filter.mSubclass == device.getDeviceSubclass())) {
							// when filter matches
							if (!filter.isExclude) {
								result.add(device);
							}
							break;
						} else {
						.....
						}
					}
				}
			}
		}

判断USBDevice 是否有权限

java 复制代码
mUsbManager.hasPermission(device)

UVC 进行打开和预览操作

打开设备: 在有了权限之后开始打开设备,进行设备连接. 后面就是通过UVC协议进行Camera 的打开和预览操作了

java 复制代码
onConnect -> openCamera、startPreview


 openCamera(ctrlBlock);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // wait for camera created
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // start previewing
                        Log.d(TAG,"onConnect   mCamView:"+mCamView);
                        startPreview(mCamView);
                    }
                }).start();

实际对camera 的处理,预览、拍照、录像 都是通过UVC协议编译的.so 文件来处理的,上面只是简单介绍了上层的USBManager 查找、检测、过滤 找到USB Camera 设备,之后的Camera 都通过封装好的 方法,最终通过native 方法实现。

实际项目效果:


相关推荐
_一条咸鱼_22 分钟前
Android Glide 的显示与回调模块原理分析
android
_一条咸鱼_26 分钟前
Android Glide 图片解码与转换模块原理分析
android
QING61826 分钟前
Android_BLE开发——扫描
android·kotlin·app
QING61826 分钟前
Android_BLE开发——绑定
android·kotlin·app
顾林海28 分钟前
深入理解 Dart 函数:从基础到高阶应用
android·前端·flutter
QING61828 分钟前
Android_BLE开发——连接
android·kotlin·app
QING61829 分钟前
Android_BLE开发——优化(深入解决 STATUS=133 连接错误)
android·kotlin·app
QING61829 分钟前
Android_BLE开发——读写
android·kotlin·app
_一条咸鱼_1 小时前
Android Glide 缓存模块源码深度解析
android
harry235day1 小时前
kotlin 协程创建启动 源码初探(一)
android·kotlin