android6.0源码分析之Camera API2.0下的Preview(预览)流程分析

本文将基于android6.0的源码,对Camera API2.0下Camera的preview的流程进行分析。在文章android6.0源码分析之Camera API2.0下的初始化流程分析中,已经对Camera2内置应用的Open即初始化流程进行了详细的分析,而在open过程中,定义了一个PreviewCallback,当时并未详细分析,即Open过程中,会自动开启预览过程,即会调用OneCameraImpl的startPreview方法,它是捕获和绘制屏幕预览帧的开始,预览才会真正开始提供一个表面。
Camera2文章分析目录:
android6.0源码分析之Camera API2.0简介
android6.0源码分析之Camera2 HAL分析
android6.0源码分析之Camera API2.0下的初始化流程分析
android6.0源码分析之Camera API2.0下的Preview(预览)流程分析
android6.0源码分析之Camera API2.0下的Capture流程分析
android6.0源码分析之Camera API2.0下的video流程分析
Camera API2.0的应用


1、Camera2 preview的应用层流程分析

preview流程都是从startPreview开始的,所以来看startPreview方法的代码:

//OneCameraImpl.java
@Override
public void startPreview(Surface previewSurface, CaptureReadyCallback listener) {
    mPreviewSurface = previewSurface;
    //根据Surface以及CaptureReadyCallback回调来建立preview环境
    setupAsync(mPreviewSurface, listener);
}

这其中有一个比较重要的回调CaptureReadyCallback,先分析setupAsync方法:

//OneCameraImpl.java
private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) {
    mCameraHandler.post(new Runnable() {
        @Override
        public void run() {
            //建立preview环境
            setup(previewSurface, listener);
        }
    });
}

这里通过CameraHandler来post一个Runnable对象,它只会调用Runnable的run方法,它仍然属于UI线程,并没有创建新的线程。所以,继续分析setup方法:

// OneCameraImpl.java
private void setup(Surface previewSurface, final CaptureReadyCallback listener) {
    try {
        if (mCaptureSession != null) {
            mCaptureSession.abortCaptures();
            mCaptureSession = null;
        }
        List<Surface> outputSurfaces = new ArrayList<Surface>(2);
        outputSurfaces.add(previewSurface);
        outputSurfaces.add(mCaptureImageReader.getSurface());
        //创建CaptureSession会话来与Camera Device发送Preview请求
        mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {

            @Override
            public void onConfigureFailed(CameraCaptureSession session) {
                //如果配置失败,则回调CaptureReadyCallback的onSetupFailed方法
                listener.onSetupFailed();
            }

            @Override
            public void onConfigured(CameraCaptureSession session) {
                mCaptureSession = session;
                mAFRegions = ZERO_WEIGHT_3A_REGION;
                mAERegions = ZERO_WEIGHT_3A_REGION;
                mZoomValue = 1f;
                mCropRegion = cropRegionForZoom(mZoomValue);
                //调用repeatingPreview来启动preview
                boolean success = repeatingPreview(null);
                if (success) {
                    //若启动成功,则回调CaptureReadyCallback的onReadyForCapture,表示准备拍照成功
                    listener.onReadyForCapture();
                } else {
                    //若启动失败,则回调CaptureReadyCallback的onSetupFailed,表示preview建立失败
                    listener.onSetupFailed();
                }
            }

            @Override
            public void onClosed(CameraCaptureSession session) {
                super.onClosed(session);
            }
        }, mCameraHandler);
    } catch (CameraAccessException ex) {
        Log.e(TAG, "Could not set up capture session", ex);
        listener.onSetupFailed();
    }
}

首先,调用Device的createCaptureSession方法来创建一个会话,并定义了会话的状态回调CameraCaptureSession.StateCallback(),其中,当会话创建成功,则会回调onConfigured()方法,在其中,首先调用repeatingPreview来启动preview,然后处理preview的结果并调用先前定义的CaptureReadyCallback来通知用户进行Capture操作。先分析repeatingPreview方法:

// OneCameraImpl.java
private boolean repeatingPreview(Object tag) {
    try {
        //通过CameraDevice对象创建一个CaptureRequest的preview请求
        CaptureRequest.Builder builder = mDevice.createCaptureRequest(
                CameraDevice.TEMPLATE_PREVIEW);
        //添加预览的目标Surface
        builder.addTarget(mPreviewSurface);
        //设置预览模式
        builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
        addBaselineCaptureKeysToRequest(builder);
        //利用会话发送请求,mCaptureCallback为
        mCaptureSession.setRepeatingRequest(builder.build(), mCaptureCallback,mCameraHandler);
        Log.v(TAG, String.format("Sent repeating Preview request, zoom = %.2f", mZoomValue));
        return true;
    } catch (CameraAccessException ex) {
        Log.e(TAG, "Could not access camera setting up preview.", ex);
        return false;
    }
}

首先调用CameraDeviceImpl的createCaptureRequest方法创建类型为TEMPLATE_PREVIEW 的CaptureRequest,然后调用CameraCaptureSessionImpl的setRepeatingRequest方法将此请求发送出去:

//CameraCaptureSessionImpl.java
  • 9
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值