libuvc与webcam的开发(五) - 移动端(on Android)的UVC

移动端的UVC协议分析是基于github上开源项目UVCCamera的。
谷歌官方推荐使用该项目作为开发UVC相关APP的参考实现。

这个项目整合了libjpeg-turbo, libusb, libuvc和rapidjson等基础c开源库,封装了供Java层调用的native接口函数(jni),增加了logcat相关日志打印,然后封装成为libuvccamera的Java包。
同时,该项目也提供了8个例子供大家调试使用,每个例子都可以单独编译成独立APP。

UVCCamera工程的源文件结构

以usbCameraTest8为例,其源文件结构如下:



可以看到,就一个MainActivity.java文件。
打开这个文件,可以看到,这是一个标准的Android APP的activity类,里面实现了onCreate(),onDestroy(),onStart(),onStop()等基本接口函数。

onCreate()

在onCreate函数中,定义了两个实例:



注意一下mOnDeviceConnectListener这个listener,它的实现如下:

private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
    @Override
    public void onAttach(final UsbDevice device) {
        Toast.makeText(MainActivity.this, "USB_DEVICE_ATTACHED", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onConnect(final UsbDevice device, final UsbControlBlock ctrlBlock, final boolean createNew) {
        if (DEBUG) Log.v(TAG, "onConnect:");
        mCameraHandler.open(ctrlBlock);
        startPreview();
        updateItems();
    }

    @Override
    public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
        if (DEBUG) Log.v(TAG, "onDisconnect:");
        if (mCameraHandler != null) {
            queueEvent(new Runnable() {
                @Override
                public void run() {
                    mCameraHandler.close();
                }
            }, 0);
            setCameraButton(false);
            updateItems();
        }
    }
    @Override
    public void onDettach(final UsbDevice device) {
        Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onCancel(final UsbDevice device) {
        setCameraButton(false);
    }
};

在这个listener中,定义了USB摄像头与手机连接/断开等情况下,程序将如何执行,比如,当设备attach上后,会有一行提示语:“USB_DEVICE_ATTACHED”,当点击APP上的按钮去打开设备时,会调用onConnect()函数,调用UVCCameraHandler.open,同时启动预览。

onStart()

在onStart()中,注册了USBMonitor,从此刻起,系统开始监听USB口上的消息。

onStop()

关闭UVCCameraHandler,关闭相机控制相关按钮动作;

onDestroy()

释放UVCCameraHandler,关闭USBMonitor;

再回头看一下刚才在onCreate()中定义的那两个实例:
mUSBMonitor,mCameraHandler
它们的类USBMonitor和UVCCameraHandler分别位于:



USBMonitor用于监听手机USB口上的各种消息,并作出相应的动作,比如启动预览什么的。但是如果用户希望从APP上操作相机,比如拍照、录像或者设置相关相机参数,就需要调用UVCCameraHandler了。

UVCCameraHandler相关代码位于usbCameraCommon文件夹下,它继承了AbstractUVCCameraHandler这个类。在AbstractUVCCameraHandler这个类中,定义了一个名为CameraThread的类,在这个线程中,具体执行了拍照、录像、预览等相关函数;

到现在为止,可以看到,APP的MainActivity主要是调用USBCameraCommon中的UVCCameraHandler和AbstractUVCCameraHandler,而后者又进一步去调用libuvccamera文件夹下的UVCCamera.java。

可以看到,在libuvccamera目录里的文件如下:


UVCCamera.java是很薄的一层接口层,类似一个glue layer,向上对接UVCCameraHandler和APP,向下对接native层的c语言实现,显然,重头戏都在下面的c代码里,但是UVCCamera.java可以直观的展现手机APP可以操作相机的哪些功能,下面是native函数列表:

Get Method
Reset Method
Set Method
Camera Operation

USBMonitor.java的作用主要是用来监控USB口的事件(OnDeviceConnectListener : interface),获取相关usb设备信息(UsbControlBlock : class & UsbDeviceInfo : class)等。

上面基本就是java层代码的一个大概层次结构,接下来我们就进入底层的native函数,看看uvc到底是怎么运作的。

《============================================》

在UVCCamera.java中,声明了大量的native接口函数:

    // #nativeCreate and #nativeDestroy are not static methods.
    private final native long nativeCreate();
    private final native void nativeDestroy(final long id_camera);

    private final native int nativeConnect(long id_camera, int venderId, int productId, int fileDescriptor, int busNum, int devAddr, String usbfs);
    private static final native int nativeRelease(final long id_camera);

    private static final native int nativeSetStatusCallback(final long mNativePtr, final IStatusCallback callback);
    private static final native int nativeSetButtonCallback(final long mNativePtr, final IButtonCallback callback);

    private static final native int nativeSetPreviewSize(final long id_camera, final int width, final int height, final int min_fps, final int max_fps, final int mode, final float bandwidth);
    private static final native String nativeGetSupportedSize(final long id_camera);
    private static final native int nativeStartPreview(final long id_camera);
    private static final native int nativeStopPreview(final long id_camera);
    private static final native int nativeSetPreviewDisplay(final long id_camera, final Surface surface);
    private static final native int nativeSetFrameCallback(final long mNativePtr, final IFrameCallback callback, final int pixelFormat);

    private static final native int nativeSetCaptureDisplay(final long id_camera, final Surface surface);

    private static final native long nativeGetCtrlSupports(final long id_camera);
    private static final native long nativeGetProcSupports(final long id_camera);

    private final native int nativeUpdateScanningModeLimit(final long id_camera);
    private static final native int nativeSetScanningMode(final long id_camera, final int scanning_mode);
    private static final native int nativeGetScanningMode(final long id_camera);

    private final native int nativeUpdateExposureModeLimit(final long id_camera);
    private static final native int nativeSetExposureMode(final long id_camera, final int exposureMode);
    private static final native int nativeGetExposureMode(final long id_camera);

    private final native int nativeUpdateExposurePriorityLimit(final long id_camera);
    private static final native int nativeSetExposurePriority(final long id_camera, final int priority);
    private static final native int nativeGetExposurePriority(final long id_camera);

    private final native int nativeUpdateExposureLimit(final long id_camera);
    private static final native int nativeSetExposure(final long id_camera, final int exposure);
    private static final native int nativeGetExposure(final long id_camera);

    private final native int nativeUpdateExposureRelLimit(final long id_camera);
    private static final native int nativeSetExposureRel(final long id_camera, final int exposure_rel);
    private static final native int nativeGetExposureRel(final long id_camera);

    private final native int nativeUpdateAutoFocusLimit(final long id_camera);
    private static final native int nativeSetAutoFocus(final long id_camera, final boolean autofocus);
    private static final native int nativeGetAutoFocus(final long id_camera);

    private final native int nativeUpdateFocusLimit(final long id_camera);
    private static final native int nativeSetFocus(final long id_camera, final int focus);
    private static final native int nativeGetFocus(final long id_camera);

    private final native int nativeUpdateFocusRelLimit(final long id_camera);
    private static final native int nativeSetFocusRel(final long id_camera, final int focus_rel);
    private static final native int nativeGetFocusRel(final long id_camera);

    private final native int nativeUpdateIrisLimit(final long id_camera);
    private static final native int nativeSetIris(final long id_camera, final int iris);
    private static final native int nativeGetIris(final long id_camera);

    private final native int nativeUpdateIrisRelLimit(final long id_camera);
    private static final native int nativeSetIrisRel(final long id_camera, final int iris_rel);
    private static final native int nativeGetIrisRel(final long id_camera);

    private final native int nativeUpdatePanLimit(final long id_camera);
    private static final native int nativeSetPan(final long id_camera, final int pan);
    private static final native int nativeGetPan(final long id_camera);

    private final native int nativeUpdatePanRelLimit(final long id_camera);
    private static final native int nativeSetPanRel(final long id_camera, final int pan_rel);
    private static final native int nativeGetPanRel(final long id_camera);

    private final native int nativeUpdateTiltLimit(final long id_camera);
    private static final native int nativeSetTilt(final long id_camera, final int tilt);
    private static final native int nativeGetTilt(final long id_camera);

    private final native int nativeUpdateTiltRelLimit(final long id_camera);
    private static final native int nativeSetTiltRel(final long id_camera, final int tilt_rel);
    private static final native int nativeGetTiltRel(final long id_camera);

    private final native int nativeUpdateRollLimit(final long id_camera);
    private static final native int nativeSetRoll(final long id_camera, final int roll);
    private static final native int nativeGetRoll(final long id_camera);

    private final native int nativeUpdateRollRelLimit(final long id_camera);
    private static final native int nativeSetRollRel(final long id_camera, final int roll_rel);
    private static final native int nativeGetRollRel(final long id_camera);

    private final native int nativeUpdateAutoWhiteBlanceLimit(final long id_camera);
    private static final native int nativeSetAutoWhiteBlance(final long id_camera, final boolean autoWhiteBlance);
    private static final native int nativeGetAutoWhiteBlance(final long id_camera);

    private final native int nativeUpdateAutoWhiteBlanceCompoLimit(final long id_camera);
    private static final native int nativeSetAutoWhiteBlanceCompo(final long id_camera, final boolean autoWhiteBlanceCompo);
    private static final native int nativeGetAutoWhiteBlanceCompo(final long id_camera);

    private final native int nativeUpdateWhiteBlanceLimit(final long id_camera);
    private static final native int nativeSetWhiteBlance(final long id_camera, final int whiteBlance);
    private static final native int nativeGetWhiteBlance(final long id_camera);

    private final native int nativeUpdateWhiteBlanceCompoLimit(final long id_camera);
    private static final native int nativeSetWhiteBlanceCompo(final long id_camera, final int whiteBlance_compo);
    private static final native int nativeGetWhiteBlanceCompo(final long id_camera);

    private final native int nativeUpdateBacklightCompLimit(final long id_camera);
    private static final native int nativeSetBacklightComp(final long id_camera, final int backlight_comp);
    private static final native int nativeGetBacklightComp(final long id_camera);

    private final native int nativeUpdateBrightnessLimit(final long id_camera);
    private static final native int nativeSetBrightness(final long id_camera, final int brightness);
    private static final native int nativeGetBrightness(final long id_camera);

    private final native int nativeUpdateContrastLimit(final long id_camera);
    private static final native int nativeSetContrast(final long id_camera, final int contrast);
    private static final native int nativeGetContrast(final long id_camera);

    private final native int nativeUpdateAutoContrastLimit(final long id_camera);
    private static final native int nativeSetAutoContrast(final long id_camera, final boolean autocontrast);
    private static final native int nativeGetAutoContrast(final long id_camera);

    private final native int nativeUpdateSharpnessLimit(final long id_camera);
    private static final native int nativeSetSharpness(final long id_camera, final int sharpness);
    private static final native int nativeGetSharpness(final long id_camera);

    private final native int nativeUpdateGainLimit(final long id_camera);
    private static final native int nativeSetGain(final long id_camera, final int gain);
    private static final native int nativeGetGain(final long id_camera);

    private final native int nativeUpdateGammaLimit(final long id_camera);
    private static final native int nativeSetGamma(final long id_camera, final int gamma);
    private static final native int nativeGetGamma(final long id_camera);

    private final native int nativeUpdateSaturationLimit(final long id_camera);
    private static final native int nativeSetSaturation(final long id_camera, final int saturation);
    private static final native int nativeGetSaturation(final long id_camera);

    private final native int nativeUpdateHueLimit(final long id_camera);
    private static final native int nativeSetHue(final long id_camera, final int hue);
    private static final native int nativeGetHue(final long id_camera);

    private final native int nativeUpdateAutoHueLimit(final long id_camera);
    private static final native int nativeSetAutoHue(final long id_camera, final boolean autohue);
    private static final native int nativeGetAutoHue(final long id_camera);

    private final native int nativeUpdatePowerlineFrequencyLimit(final long id_camera);
    private static final native int nativeSetPowerlineFrequency(final long id_camera, final int frequency);
    private static final native int nativeGetPowerlineFrequency(final long id_camera);

    private final native int nativeUpdateZoomLimit(final long id_camera);
    private static final native int nativeSetZoom(final long id_camera, final int zoom);
    private static final native int nativeGetZoom(final long id_camera);

    private final native int nativeUpdateZoomRelLimit(final long id_camera);
    private static final native int nativeSetZoomRel(final long id_camera, final int zoom_rel);
    private static final native int nativeGetZoomRel(final long id_camera);

    private final native int nativeUpdateDigitalMultiplierLimit(final long id_camera);
    private static final native int nativeSetDigitalMultiplier(final long id_camera, final int multiplier);
    private static final native int nativeGetDigitalMultiplier(final long id_camera);

    private final native int nativeUpdateDigitalMultiplierLimitLimit(final long id_camera);
    private static final native int nativeSetDigitalMultiplierLimit(final long id_camera, final int multiplier_limit);
    private static final native int nativeGetDigitalMultiplierLimit(final long id_camera);

    private final native int nativeUpdateAnalogVideoStandardLimit(final long id_camera);
    private static final native int nativeSetAnalogVideoStandard(final long id_camera, final int standard);
    private static final native int nativeGetAnalogVideoStandard(final long id_camera);

    private final native int nativeUpdateAnalogVideoLockStateLimit(final long id_camera);
    private static final native int nativeSetAnalogVideoLoackState(final long id_camera, final int state);
    private static final native int nativeGetAnalogVideoLoackState(final long id_camera);

    private final native int nativeUpdatePrivacyLimit(final long id_camera);
    private static final native int nativeSetPrivacy(final long id_camera, final boolean privacy);
    private static final native int nativeGetPrivacy(final long id_camera);

这些native函数与libuvc库函数的对接位于UVCCamera/libuvccamera/src/main/jni/UVCCamera/serenegiant_usb_UVCCamera.cpp这个文件中。

我们以简单的nativeConnect函数为例,看看它的实现:



这个camera->connect定义在类UVCCamera中,进入UVCCamera.cpp文件,我们可以看到,其实现如下:


忍不住吐槽一句,这么知名的项目居然用日文注释,实在是不专业!

不过骂归骂,从这层函数开始,我们就开始真正调用libuvc库函数了。比如uvc_open()。接下来的故事,就可以参考本系列第二篇libuvc一文。

最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,947评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,709评论 2 59
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,975评论 3 119
  • 今日体验,今天一条不是特别忙,上午给现代做了一下保养,发现几个需要更换的项目,和客户进行了一下沟通,只做了几项,其...
    AA京心达小任阅读 135评论 0 0
  • 失眠小姐20岁了,不是20岁,是20岁了。 试过沿着跑道一圈一圈跑到双腿发抖,慢慢走回去洗澡躺在床上,很累很困,可...
    l洛洛lll阅读 249评论 0 0