一、什么是UVC
UVC,全稱(chēng)為:USB video(device) class,是微軟與另外幾家設(shè)備廠商聯(lián)合推出的為USB視頻捕獲設(shè)備定義的協(xié)議標(biāo)準(zhǔn),目前已成為USB org標(biāo)準(zhǔn)之一。
USB協(xié)議中,除了通用的軟硬件電氣接口規(guī)范等,還包含了各種各樣的Class協(xié)議,用來(lái)為不同的功能定義各自的標(biāo)準(zhǔn)接口和具體的總線(xiàn)上的數(shù)據(jù)交互格式和內(nèi)容。這些Class協(xié)議的數(shù)量非常多,最常見(jiàn)的比如支持U盤(pán)功能的Mass Storage Class,以及通用的數(shù)據(jù)交換協(xié)議:CDC class。此外還包括Video、Audio Class, Print Class等等。正是由于這些Class協(xié)議,大大促進(jìn)了USB設(shè)備的普及,比如說(shuō)各個(gè)廠商生產(chǎn)的U盤(pán)都能通過(guò)操作系統(tǒng)自帶的驅(qū)動(dòng)程序來(lái)使用。
所以說(shuō)UVC僅僅只是USB規(guī)范協(xié)議中設(shè)備類(lèi)規(guī)范的其中一種,是用作USB接口的視頻設(shè)備的一個(gè)統(tǒng)一的數(shù)據(jù)交換規(guī)范。使用 UVC 的好處 USB 在 Video這塊也成為一項(xiàng)標(biāo)準(zhǔn)了之后,硬件在各個(gè)程序之間彼此運(yùn)行會(huì)更加順利,而且也省略了驅(qū)動(dòng)程序安裝這一環(huán)節(jié),操作系統(tǒng)只要是 Windows XP SP2 之后的版本都可以支持 UVC,Linux系統(tǒng)自2.4以后的內(nèi)核都支持了大量的設(shè)備驅(qū)動(dòng),其中支持UVC設(shè)備。
http://www.usbzh.com/article/detail-80.html
二、Android-UVC開(kāi)源驅(qū)動(dòng)
目前Android端的開(kāi)源驅(qū)動(dòng)主要有UVCCamera,目前多數(shù)開(kāi)源項(xiàng)目都是基于此處,感謝saki4510t大神。https://github.com/saki4510t/UVCCamera
此處開(kāi)源項(xiàng)目的每個(gè)Demo實(shí)例:
1)USBCameraTest0
顯示如何使用SurfaceView來(lái)啟動(dòng)/停止預(yù)覽。
2)USBCameraTest
顯示如何啟動(dòng)/停止預(yù)覽。這與USBCameraTest0幾乎相同,
但是使用自定義的TextureView來(lái)顯示相機(jī)圖像而不是使用SurfaceView。
3)USBCameraTest2
演示如何使用MediaCodec編碼器將UVC相機(jī)(無(wú)音頻)的視頻記錄為.MP4文件。
此示例需要API>=18,因?yàn)镸ediaMuxer僅支持API>=18。
4)USBCameraTest3
演示如何將音頻(來(lái)自?xún)?nèi)部麥克風(fēng))的視頻(來(lái)自UVC相機(jī))錄制為.MP4文件。
這也顯示了幾種捕捉靜止圖像的方式。此示例可能最適用于您的定制應(yīng)用程序的基礎(chǔ)項(xiàng)目。
5)USBCameraTest4
顯示了訪問(wèn)UVC相機(jī)并將視頻圖像保存到后臺(tái)服務(wù)的方式。
這是最復(fù)雜的示例之一,因?yàn)檫@需要使用AIDL的IPC。
6)USBCameraTest5
和USBCameraTest3幾乎相同,但使用IFrameCallback接口保存視頻圖像,
而不是使用來(lái)自MediaCodec編碼器的輸入Surface。
在大多數(shù)情況下,您不應(yīng)使用IFrameCallback來(lái)保存圖像,因?yàn)镮FrameCallback比使用Surface要慢很多。
但是,如果您想獲取視頻幀數(shù)據(jù)并自行處理它們或?qū)⑺鼈冏鳛樽止?jié)緩沖區(qū)傳遞給其他外部庫(kù),
則IFrameCallback將非常有用。
7)USBCameraTest6
這顯示了如何將視頻圖像分割為多個(gè)Surface。你可以在這個(gè)應(yīng)用程序中看到視頻圖像并排觀看。
這個(gè)例子還展示了如何使用EGL來(lái)渲染圖像。
如果您想在添加視覺(jué)效果/濾鏡效果后顯示視頻圖像,則此示例可能會(huì)對(duì)您有所幫助。
8)USBCameraTest7
這顯示了如何使用兩個(gè)攝像頭并顯示來(lái)自每個(gè)攝像頭的視頻圖像。這仍然是實(shí)驗(yàn)性的,可能有一些問(wèn)題。
9)usbCameraTest8
這顯示了如何設(shè)置/獲取uvc控件。目前這只支持亮度和對(duì)比度。
目前此項(xiàng)目結(jié)構(gòu)驅(qū)動(dòng)層面-共用庫(kù)-示例
驅(qū)動(dòng)層面原生C#語(yǔ)言編寫(xiě),根據(jù)自己使用的架構(gòu)可以編譯不同架構(gòu)so
libuvccamera/src/main/jni/Application.mk
#NDK_TOOLCHAIN_VERSION := 4.9
# NDK編譯版版本根據(jù)issue修復(fù)NDK14版本錯(cuò)誤
APP_PLATFORM := android-15
# 修改支持平臺(tái)CPU架構(gòu)取消了x86mips編譯
APP_ABI := armeabi armeabi-v7a arm64-v8a
#APP_OPTIM := debug
APP_OPTIM := release
目前我是用的是ndk15版本編譯,其他版本編譯都有多少問(wèn)題
目前我將上傳我處理過(guò)的編譯版本給大家參考,修復(fù)了在issue提的問(wèn)題。并且對(duì)項(xiàng)目結(jié)構(gòu)進(jìn)行了調(diào)整其中的usblq和usbcw個(gè)人項(xiàng)目的lib庫(kù)大家可以去掉
三、打包aar/jar
一般我們添加依賴(lài)都是通過(guò)aar和jar方便管理
這里順帶說(shuō)下我是怎么打包aar和jar的,目前網(wǎng)上方法較多,我就以我覺(jué)得最為方便的方法示之。
-
aar
1.png

需要混淆壓縮的需要在此處編譯release版本

libuvccamera/build/outputs/aar/libuvccamera-debug.aar
libuvccamera/build/outputs/aar/libuvccamera-release.aar
- jar
在module的build.gradle的android中添加
//生成jar包
task makeJar(type: Copy) {
delete 'build/outputs/uvc_camera.jar'
// jar文件來(lái)源
from('build/intermediates/aar_main_jar/release/')
// 生成路徑
into('build/libs/')
include('classes.jar')
// 命名為network.jar
rename('classes.jar', 'uvc_camera.jar')
}
點(diǎn)擊運(yùn)行或者在task中找到名為makeJar的命令
四、常見(jiàn)錯(cuò)誤問(wèn)題
UVCCamera nativeConnect 返回的錯(cuò)誤碼 集合:
/** Success (no error) /
UVC_SUCCESS = 0,
/* Input/output error /
UVC_ERROR_IO = -1,
/* Invalid parameter /
UVC_ERROR_INVALID_PARAM = -2,
/* Access denied /
UVC_ERROR_ACCESS = -3,
/* No such device /
UVC_ERROR_NO_DEVICE = -4,
/* Entity not found /
UVC_ERROR_NOT_FOUND = -5,
/* Resource busy /
UVC_ERROR_BUSY = -6,
/* Operation timed out /
UVC_ERROR_TIMEOUT = -7,
/* Overflow /
UVC_ERROR_OVERFLOW = -8,
/* Pipe error /
UVC_ERROR_PIPE = -9,
/* System call interrupted /
UVC_ERROR_INTERRUPTED = -10,
/* Insufficient memory /
UVC_ERROR_NO_MEM = -11,
/* Operation not supported /
UVC_ERROR_NOT_SUPPORTED = -12,
/* Device is not UVC-compliant /
UVC_ERROR_INVALID_DEVICE = -50,
/* Mode not supported /
UVC_ERROR_INVALID_MODE = -51,
/* Resource has a callback (can’t use polling and async) /
UVC_ERROR_CALLBACK_EXISTS = -52,
/* Undefined error */
UVC_ERROR_OTHER = -99
項(xiàng)目中常見(jiàn)問(wèn)題:
- a查看是否支持UVC,adb命令
cd sys/bus/usb/drivers
ls dev/v*
- b下載以及修改ndk路徑
在Android studio 打開(kāi)sdk manager->sdk tool ->show package details 勾選ndk 本版
舊版本ndk 需要到官網(wǎng)下載
設(shè)置ndk路徑在AndroidStudio菜單欄,選擇File->Project Struture中配置ndk -
c拔出usb攝像頭,crash異常導(dǎo)致應(yīng)用退出
5.png
diff --git a/libuvccamera/src/main/jni/libusb/libusb/os/android_usbfs.c b/libuvccamera/src/main/jni/libusb/libusb/os/android_usbfs.c
index 8626595..c4842c4 100644
--- a/libuvccamera/src/main/jni/libusb/libusb/os/android_usbfs.c
+++ b/libuvccamera/src/main/jni/libusb/libusb/os/android_usbfs.c
@@ -2726,6 +2726,12 @@ static int handle_iso_completion(struct libusb_device_handle *handle, // XXX add
usbi_mutex_lock(&itransfer->lock);
for (i = 0; i < num_urbs; i++) {
+ //+Add by york.zhou on 2021.05.19,fix issue app crash on remove usb device
+ if (tpriv->iso_urbs == NULL){
+ break;
+ }
+ //-Add by york.zhou on 2021.05.19,fix issue app crash on remove usb device
+
if (urb == tpriv->iso_urbs[i]) {
urb_idx = i + 1;
break;
diff --git a/libuvccamera/src/main/jni/libuvc/src/stream.c b/libuvccamera/src/main/jni/libuvc/src/stream.c
index 8a1e90a..b7cedcc 100644
--- a/libuvccamera/src/main/jni/libuvc/src/stream.c
+++ b/libuvccamera/src/main/jni/libuvc/src/stream.c
@@ -641,7 +641,8 @@ static void _uvc_delete_transfer(struct libusb_transfer *transfer) {
libusb_cancel_transfer(strmh->transfers[i]); // XXX 20141112追加
UVC_DEBUG("Freeing transfer %d (%p)", i, transfer);
free(transfer->buffer);
- libusb_free_transfer(transfer);
+ //+Add york.zhou 2021.05-19,fix remove usb devices,app crash
+ //libusb_free_transfer(transfer);
strmh->transfers[i] = NULL;
break;
}
- d有些usb攝像頭識(shí)別不了
在xml 目錄下的device_filter.xml中配置下
<usb>
<usb-device class="239" subclass="2" /> <!-- all device of UVC -->
</usb>

