Android Camera2

作者: 代码杂谈熊 | 来源:发表于2020-02-17 23:00 被阅读0次

    基础概念

    Camera2是Android5.0推出的新的相机api(在5.0以下系统没法使用)。它采用管道式的设计,支持单个或者顺序执行的多个请求。

    与Camera1的区别:

    Camera2采用CameraManager来管理,而不是像camera1一样返回camera对象让我们进行操作。camera2的预览,拍照都是请求一次会话(管道的输入然后输出)。

    新增了许多camera1不具备的功能,如对焦模式,曝光模式,快门,还有输出原始照片数据(RAW)等

    基本用法

    1. 创建TextureView,加入TextureView状态回调
    2. TextureView回调成功,获取CameraManager对象,打开连接camera,并加入camera调用回调方法
    3. camera连接回调成功,创建相机会话对象,并加入相机会话的回调方法
    4. 在相机会话的回调方法中处理拍照生成图片等操作

    接下来我们会一步步用真实的代码去讲解每一步操作

    第一步:创建TextureView,并加入TextureView的回调

    /**
    *  创建textureview回调方法
    **/
     private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
            @Override
            public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                openCamera(width, height);
            }
    
            @Override
            public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                configureTransform(width, height);
            }
    
            @Override
            public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                return false;
            }
    
            @Override
            public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    
            }
        };
        
    

    第二步:在onSurfaceTextureAvailable() 中去创建CameraDevice对象来连接Camera。当然其中要设置一些参数来配置我们需要的Camera。比如正反摄像头,自动对焦等。

    private void openCamera(int width, int height) {
    
            setUpCameraOutputs(width, height); // 该方法用于在系统返回的CameraId列表(不同分辨率,正反镜头等)获取最适合的CameraId
            configureTransform(width, height); // 根据返回的镜头去调整TextureView的大小
    
            CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            try {
                if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                    throw new RuntimeException("Time out waitting to lock camera opening");
                }
                manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);  // mStateCallback的代码在下面
            } catch (CameraAccessException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
            }
    
    
        }
    

    提前创建好的相机状态回调

    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(@NonNull CameraDevice camera) {
                mCameraOpenCloseLock.release();
                mCameraDevice = camera;
                createCameraPreviewSession(); 
    
            }
    
            @Override
            public void onDisconnected(@NonNull CameraDevice camera) {
    
            }
    
            @Override
            public void onError(@NonNull CameraDevice camera, int error) {
    
            }
        };
    

    第三步:camera连接回调成功,创建相机会话对象

     private void createCameraPreviewSession() {
            try {
                SurfaceTexture texture = mTextureView.getSurfaceTexture();
                assert texture != null;
    
                texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
    
                Surface surface = new Surface(texture);
    
                mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                mPreviewRequestBuilder.addTarget(surface);
    
                mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
                        new CameraCaptureSession.StateCallback() {
                            @Override
                            public void onConfigured(@NonNull CameraCaptureSession session) {
                                if (mCameraDevice == null) {
                                    return;
                                }
                                mCaptureSession = session;
                                try {
                                    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                                            CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                                    setAutoFlash(mPreviewRequestBuilder);
                                    mPreviewRequest = mPreviewRequestBuilder.build();
                                    mCaptureSession.setRepeatingRequest(mPreviewRequest,
                                            mCaptureCallback, mBackgroundHandler); 
                                } catch (CameraAccessException e) {
                                    e.printStackTrace();
                                }
    
    
                            }
    
                            @Override
                            public void onConfigureFailed(@NonNull CameraCaptureSession session) {
    
                            }
                        }, null);
    
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    

    第四步:最后看下相机会话的回调处理方法,用于处理拍照生成图片等操作

    private CameraCaptureSession.CaptureCallback mCaptureCallback =
                new CameraCaptureSession.CaptureCallback() {
    
                    private void process(CaptureResult result) {
                        switch (mState) {
                            case STATE_PREVIEW: {
                                break;
                            }
                            case STATE_WAITING_LOCK: {
                                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                                if (afState == null) {
                                    captureStillPicture();
                                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                                        mState = STATE_PICTURE_TAKEN;
                                        captureStillPicture();
                                    } else {
                                        runPrecaptureSequence();
                                    }
                                }
                                break;
                            }
                            case STATE_WAITING_PRECAPTURE: {
                                // CONTROL_AE_STATE can be null on some devices
                                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                                if (aeState == null ||
                                        aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
                                        aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
                                    mState = STATE_WAITING_NON_PRECAPTURE;
                                }
                                break;
                            }
                            case STATE_WAITING_NON_PRECAPTURE: {
                                // CONTROL_AE_STATE can be null on some devices
                                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                                if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                                    mState = STATE_PICTURE_TAKEN;
                                    captureStillPicture();
                                }
                                break;
                            }
    
    
                        }
                    }
    
                    @Override
                    public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
                        process(partialResult);
                    }
    
                    @Override
                    public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                        process(result);
                    }
                };
    

    相关文章

      网友评论

        本文标题:Android Camera2

        本文链接:https://www.haomeiwen.com/subject/qucwfhtx.html