UVC camera 封裝類

下述代碼是關於UVC camera處理的封裝類,具體依賴的aar請參考https://github.com/saki4510t/UVCCamera

借用該類,在接入UVC 攝像頭設備時可以很方便的進行使用,只需要在對應的Activity中,先初始化該類,綁定一個SurfaceView,便於展示攝像視頻數據,再在onStart生命週期回調中調用onStart方法、onStop生命週期回調中調用onStop方法、在onDestroy生命週期回調中調用release即可。

public class UVCCameraManager {

    private static final String TAG = UVCCameraManager.class.getSimpleName();
    
    private final USBMonitor mUSBMonitor;
    private UVCCamera mUVCCamera;
    private SurfaceView mUVCCameraView;
    private Surface mPreviewSurface;
    private final Object mSync = new Object();
    private boolean isActive, isPreview;
    private final HandlerThreadHandler mWorkerHandler;
    private final Handler mUIHandler = new Handler(Looper.getMainLooper());
    private long mWorkerThreadID;

    public UVCCameraManager(@NonNull Context context, @NonNull SurfaceView surfaceView) {
        mUSBMonitor = new USBMonitor(context, mConnectListener);
        mWorkerHandler = HandlerThreadHandler.createHandler(TAG);
        mWorkerThreadID = mWorkerHandler.getLooper().getThread().getId();
        mUVCCameraView = surfaceView;
        mUVCCameraView.getHolder().addCallback(mSurfaceViewCallback);
    }

    public void onStart() {
        L.d(TAG, "onStart:");
        synchronized (mSync) {
            mUSBMonitor.register();
        }
    }

    public void onStop() {
        L.d(TAG, "onStop:");
        synchronized (mSync) {
            mUSBMonitor.unregister();
        }
    }

    public void release() {
        synchronized (mSync) {
            isActive = isPreview = false;
            if (mUVCCamera != null) {
                mUVCCamera.destroy();
                mUVCCamera = null;
            }
            mUSBMonitor.destroy();
        }
        try {
            mWorkerHandler.getLooper().quit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private synchronized void queueEvent(final Runnable task, final long delayMillis) {
        if (task == null) return;
        try {
            mWorkerHandler.removeCallbacks(task);
            if (delayMillis > 0) {
                mWorkerHandler.postDelayed(task, delayMillis);
            } else if (mWorkerThreadID == Thread.currentThread().getId()) {
                task.run();
            } else {
                mWorkerHandler.post(task);
            }
        } catch (final Exception e) {
            // ignore
        }
    }

    private final USBMonitor.OnDeviceConnectListener mConnectListener = new USBMonitor.OnDeviceConnectListener() {

        @Override
        public void onAttach(UsbDevice usbDevice) {
            L.d(TAG, "onAttach");
            if (usbDevice != null) {
                mUSBMonitor.requestPermission(usbDevice);
            } else {
                L.d(TAG, "usbDevice is null");
            }
        }

        @Override
        public void onDettach(UsbDevice usbDevice) {
            L.d(TAG, "onDettach");
        }

        @Override
        public void onConnect(UsbDevice usbDevice, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
            L.d(TAG, "onConnect:");
            synchronized (mSync) {
                if (mUVCCamera != null) {
                    mUVCCamera.destroy();
                }
                isActive = isPreview = false;
            }
            queueEvent(() -> {
                synchronized (mSync) {
                    final UVCCamera camera = new UVCCamera();
                    camera.open(ctrlBlock);
                    L.d(TAG, "supportedSize:" + camera.getSupportedSize());
                    try {
                        camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.FRAME_FORMAT_MJPEG);
                    } catch (IllegalArgumentException e) {
                        try {
                            // fallback to YUV mode
                            camera.setPreviewSize(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, UVCCamera.DEFAULT_PREVIEW_MODE);
                        } catch (IllegalArgumentException ex) {
                            camera.destroy();
                            return;
                        }
                    }
                    mPreviewSurface = mUVCCameraView.getHolder().getSurface();
                    if (mPreviewSurface != null) {
                        isActive = true;
                        camera.setPreviewDisplay(mPreviewSurface);
                        //第一次在這裏會黑屏???
                        //isPreview = camera.startPreview()>=0;
                        //L.d(TAG,"startPreview:"+isPreview);

                    }
                    synchronized (mSync) {
                        mUVCCamera = camera;
                    }
                }
            }, 0);
            mUIHandler.post(() -> {
                mUVCCameraView.setVisibility(View.VISIBLE);
                mUVCCameraView.bringToFront();
            });
        }

        @Override
        public void onDisconnect(UsbDevice usbDevice, USBMonitor.UsbControlBlock usbControlBlock) {
            L.d(TAG, "onDisconnect:");
            // XXX you should check whether the comming device equal to camera device that currently using
            queueEvent(() -> {
                synchronized (mSync) {
                    if (mUVCCamera != null) {
                        mUVCCamera.close();
                        if (mPreviewSurface != null) {
                            mPreviewSurface.release();
                            mPreviewSurface = null;
                        }
                        isActive = isPreview = false;
                    }
                }
            }, 0);
            mUIHandler.post(() -> mUVCCameraView.setVisibility(View.GONE));
        }

        @Override
        public void onCancel(UsbDevice usbDevice) {
            L.d(TAG, "onCancel:");
        }
    };

    private final SurfaceHolder.Callback mSurfaceViewCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(final SurfaceHolder holder) {
            L.d(TAG, "surfaceCreated:");
        }

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

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章