开源项目UVCCamera,实现了手机无需root就支持USB Camera设备的检测、连接、预览和音视频数据采集等功能,下面简要介绍下它的使用。

UVC,全称为:USB video class 或USB video device class。是Microsoft与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准。

一.下载地址

saki4510t/UVCCamera:https://github.com/saki4510t/UVCCamera

现在有8个样例可供使用。
1)USBCameraTest0
这是最简单的项目,只显示如何使用SurfaceView来启动/停止预览。

2)USBCameraTest
这是最简单的项目,只显示如何启动/停止预览。这与USBCameraTest0几乎相同,但是使用自定义的TextureView来显示相机图像而不是使用SurfaceView。

3)USBCameraTest2
这是一个示例项目,演示如何使用MediaCodec编码器将UVC相机(无音频)的视频记录为.MP4​​文件。此示例需要API> = 18,因为MediaMuxer仅支持API> = 18。

4)USBCameraTest3
这是一个示范项目,演示如何将音频(来自内部麦克风)的视频(来自UVC相机)录制为.MP4​​文件。这也显示了几种捕捉静止图像的方式。此示例可能最适用于您的定制应用程序的基础项目。

5)USBCameraTest4
本示例显示了访问UVC相机并将视频图像保存到后台服务的方式。这是最复杂的示例之一,因为这需要使用AIDL的IPC。

6)USBCameraTest5
这与USBCameraTest3几乎相同,但使用IFrameCallback接口保存视频图像,而不是使用来自MediaCodec编码器的输入Surface。
在大多数情况下,您不应使用IFrameCallback来保存图像,因为IFrameCallback比使用Surface要慢很多。但是,如果您想获取视频帧数据并自行处理它们或将它们作为字节缓冲区传递给其他外部库,则IFrameCallback将非常有用。

7)USBCameraTest6
这显示了如何将视频图像分割为多个Surface。你可以在这个应用程序中看到视频图像并排观看。这个例子还展示了如何使用EGL来渲染图像。如果您想在添加视觉效果/滤镜效果后显示视频图像,则此示例可能会对您有所帮助。

8)USBCameraTest7
这显示了如何使用两个摄像头并显示来自每个摄像头的视频图像。这仍然是实验性的,可能有一些问题。

9)usbCameraTest8这显示了如何设置/获取uvc控件。目前这只支持亮度和对比度。

二.UVC Camera的简单使用

1.首先需要实例化一个USBMonitor检测usb camera的连接和移除。

mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);

2.在onStart中注册USBMonitor,onStop中取消注册,onDestory中销毁对象。

@Override
    protected void onStart() {
        super.onStart();
        if (DEBUG) Log.v(TAG, "onStart:");
        synchronized (mSync) {
            if (mUSBMonitor != null) {
                mUSBMonitor.register();
            }
        }
    }

    @Override
    protected void onStop() {
        if (DEBUG) Log.v(TAG, "onStop:");
        synchronized (mSync) {
            if (mUSBMonitor != null) {
                mUSBMonitor.unregister();
            }
        }
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        if (DEBUG) Log.v(TAG, "onDestroy:");
        synchronized (mSync) {
            isActive = isPreview = false;
            if (mUVCCamera != null) {
                mUVCCamera.destroy();
                mUVCCamera = null;
            }
            if (mUSBMonitor != null) {
                mUSBMonitor.destroy();
                mUSBMonitor = null;
            }
        }
        mUVCCameraView = null;
        mCameraButton = null;
        super.onDestroy();
    }

3.Activity实现CameraDialog.CameraDialogParent接口,并实现其抽象方法返回mUSBMonitor。
接口:

public interface CameraDialogParent {
        public USBMonitor getUSBMonitor();
        public void onDialogResult(boolean canceled);
    }

实现:

public USBMonitor getUSBMonitor() {
        return mUSBMonitor;
    }

    @Override
    public void onDialogResult(boolean canceled) {
        if (canceled) {
            finsh();
        }
    }

4.实现设备监听,并在onConnect中设置相机参数,预览界面并开始预览,在onDisconnect中释放资源。

private final OnDeviceConnectListener mOnDeviceConnectListener = new OnDeviceConnectListener() {
        @Override
        public void onAttach(final UsbDevice device) {
            if (DEBUG) Log.v(TAG, "onAttach:");
            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:");
            synchronized (mSync) {
                if (mUVCCamera != null) {
                    mUVCCamera.destroy();
                }
                isActive = isPreview = false;
            }
            queueEvent(new Runnable() {
                @Override
                public void run() {
                    synchronized (mSync) {
                        final UVCCamera camera = new UVCCamera();
                        camera.open(ctrlBlock);
                        if (DEBUG) Log.i(TAG, "supportedSize:" + camera.getSupportedSize());
                        try {
                            camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.FRAME_FORMAT_MJPEG);
                        } catch (final IllegalArgumentException e) {
                            try {
                                // fallback to YUV mode
                                camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.DEFAULT_PREVIEW_MODE);
                            } catch (final IllegalArgumentException e1) {
                                camera.destroy();
                                return;
                            }
                        }
                        mPreviewSurface = mUVCCameraView.getHolder().getSurface();
                        if (mPreviewSurface != null) {
                            isActive = true;
                            camera.setPreviewDisplay(mPreviewSurface);
                            camera.startPreview();
                            isPreview = true;
                        }
                        synchronized (mSync) {
                            mUVCCamera = camera;
                        }
                    }
                }
            }, 0);
        }

        @Override
        public void onDisconnect(final UsbDevice device, final UsbControlBlock ctrlBlock) {
            if (DEBUG) Log.v(TAG, "onDisconnect:");
            // XXX you should check whether the comming device equal to camera device that currently using
            queueEvent(new Runnable() {
                @Override
                public void run() {
                    synchronized (mSync) {
                        if (mUVCCamera != null) {
                            mUVCCamera.close();
                            if (mPreviewSurface != null) {
                                mPreviewSurface.release();
                                mPreviewSurface = null;
                            }
                            isActive = isPreview = false;
                        }
                    }
                }
            }, 0);
        }

        @Override
        public void onDettach(final UsbDevice device) {
            if (DEBUG) Log.v(TAG, "onDettach:");
            Toast.makeText(MainActivity.this, "USB_DEVICE_DETACHED", Toast.LENGTH_SHORT).show();
        }

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

5.在surfaceChanged中重新设置预览,在surfaceDestroyed中停止预览。

private final SurfaceHolder.Callback mSurfaceViewCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(final SurfaceHolder holder) {
            if (DEBUG) Log.v(TAG, "surfaceCreated:");
        }

        @Override
        public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {
            if ((width == 0) || (height == 0)) return;
            if (DEBUG) Log.v(TAG, "surfaceChanged:");
            mPreviewSurface = holder.getSurface();
            synchronized (mSync) {
                if (isActive && !isPreview && (mUVCCamera != null)) {
                    mUVCCamera.setPreviewDisplay(mPreviewSurface);
                    mUVCCamera.startPreview();
                    isPreview = true;
                }
            }
        }

        @Override
        public void surfaceDestroyed(final SurfaceHolder holder) {
            if (DEBUG) Log.v(TAG, "surfaceDestroyed:");
            synchronized (mSync) {
                if (mUVCCamera != null) {
                    mUVCCamera.stopPreview();
                }
                isPreview = false;
            }
            mPreviewSurface = null;
        }
    };

三. UVC Camera 方法介绍

1.setFocus(final int focus) 设置焦点

2.setAutoFocus(final boolean autoFocus) 设置是否自动对焦

3.setBrightness(final int brightness) 设置亮度

4.setFrameCallback(final IFrameCallback callback, final int pixelFormat) 设置每一帧的回掉,第二个参数为格式。
设置回调:

camera.setFrameCallback(VideoRecorderView.this,UVCCamera.PIXEL_FORMAT_YUV420SP);

在onFrame中获取数据并处理

@Override
    public void onFrame(ByteBuffer frame) {
        byte[] data=new byte[frame.remaining()];
        frame.get(data);
    }

5.setContrast(final int contrast) 设置对比度

6.setGain(final int gain) 设置增益,它是RGB颜色值的一个乘数。范围为[1.0,16.0];默认值是1.0。

7.setGamma(final int gamma) 设置集合gamma,这是一种用于编码亮度数据的非线性运算。范围为[1.0,2.8];默认值是2.2。

8.setHue(final int hue) 设置饱和度

9.setPowerlineFrequency() 设置电源线频率。范围由NUI_POWER_LINE_FREQUENCY枚举中的值决定;默认值是nui_power_line_ency_disabled。

10.setSaturation(final int saturation) 设置饱和度,它是相对于自身亮度的颜色的颜色。范围为[0.0,2.0];默认值是1.0。

11.setSharpness(final int sharpness)设置锐度,它描述可见的细节量。范围为[0,1.0];默认值是0.5

四.其他

每天进步一点点,待续。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐