Android中Camera的聚焦流程---应用层

在Camera中,autofocus是个很重要的知识点,一般有移动对焦,点击聚焦和长按聚焦,这里我们以展锐平台相机的点击聚焦为例,分析下聚焦在app层的流程。

1、聚焦触发

点击屏幕事件的触发
PhotoModule.java的onSingleTapUp中

 public void onSingleTapUp(View view, int x, int y) {
 	......
 	//调用FocusManager的singletap
 	mFocusManager.onSingleTapUp(x, y);
 }

FocusOverlayManager.java的onSingleTapUp中

public void onSingleTapUp(int x, int y) {
         
        lastSingleTap.set(x,y);
        //如果当前已经是定焦的,取消定焦,重新对焦
        if(isAFLock) {
            sendCancleMsg(false);
            mListener.setAELock(false);
            isAFLock = false;
        }

        //没有初始化或者拍照前的聚焦的状态,直接返回
        if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) { 
            return;
        }
        //让用户可以取消掉之前未消失的触摸聚焦
        if ((mFocusArea != null) && (mState == STATE_FOCUSING ||
                mState == STATE_SUCCESS || mState == STATE_FAIL)) { 
            cancelAutoFocus();
        }
        if (mPreviewRect.width() == 0 || mPreviewRect.height() == 0) {
            return;
        }
     
        // Initialize variables.
        if (mAutoChasingSupported && mAutoChasingEnable){
            boolean isChasing = isAutoChasing();
            if (isChasing) {
                initializeAutoChasingRegion(0,0);
                Log.d(TAG,"set chasing Region x = 0 , y = 0");
                mListener.setAutoChasingParameters();
            }
        }

        //初始化聚焦的区域
        // Initialize mFocusArea.
        if (mFocusAreaSupported) {
            initializeFocusAreas(x, y);
            mFocusRing.setFocusLocation(x, y);
        }
        // Initialize mMeteringArea.
        if (mMeteringAreaSupported) {
            initializeMeteringAreas(x, y);
        }

        // Log manual tap to focus.
        mTouchCoordinate = new TouchCoordinate(x, y, mPreviewRect.width(), mPreviewRect.height());
        mTouchTime = System.currentTimeMillis();

        //停止人脸识别,因为要进行识别聚焦和测量area
        mListener.stopFaceDetection();

        //设置聚焦区域&测量区域
        mListener.setFocusParameters();

        
        if (mFocusAreaSupported) {
            autoFocus();//开始对焦
        } else {  // Just show the indicator in all other cases.
            // Reset the metering area in 4 seconds.
            mHandler.removeMessages(RESET_TOUCH_FOCUS);
            mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
        }
    }

接着看FocusOverlayManager这里的autoFocus()方法

private void autoFocus(int focusingState) {
        //监听autofocus,这里autofocus的实现是PhotoModule中
        mListener.autoFocus();
        //当前focus的状态设置成正在focus
        mState = focusingState;
        //更新正在对焦的对焦框ui
        updateFocusUI();
        mHandler.removeMessages(RESET_TOUCH_FOCUS);
        initializeCameraSound();
    }

在PhotoMudule.java中的autoFocus()中

@Override
    public void autoFocus() {
        if (mCameraDevice == null) {
            return;
        }
        mNeedCancelAutoFocus = true;
        mFocusStartTime = System.currentTimeMillis();
        //设置Camera的回调聚焦
        mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);
        //设置相机的状态为FOCUSING
        setCameraState(FOCUSING);
    }

2、聚焦完成回调

接着看上层对于聚焦的回调处理,在PhotoModule中有内部类AutoFocusCallback

private final class AutoFocusCallback implements CameraAFCallback {
        @Override
        public void onAutoFocus(boolean focused, CameraProxy camera) {
            //如果是暂停状态,不聚焦
            if (mPaused) {
                return;
            }
            //算出当前到聚焦开始的时间差
            mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime;
            //设置Camera状态为IDLE
            setCameraState(IDLE);
            //调用FocusManager中的onAutoFocus
            mFocusManager.onAutoFocus(focused, false);
        }
    }

接着去看聚焦完成的具体处理
在FocusManager的onAutoFocus中

public void onAutoFocus(boolean focused, boolean shutterButtonPressed) {
        //正在进行聚焦,拍照动作必须再聚焦完之后
        if (mState == STATE_FOCUSING_SNAP_ON_FINISH) {
            // 无论聚焦成功还是失败,都会拍照。如果要进行拍照发声,就无需AF发声了
            if (focused) {
                //聚焦成功
                mState = STATE_SUCCESS;
            } else {
                //聚焦失败
                mState = STATE_FAIL;
            }

            //更新聚焦完成的ui以及各种状态的设置
            updateFocusUI();
            //拍照,mState的状态变为STATE_IDLE
            capture();

            //如果是聚焦中的状态
        } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
            //此状态的发生分为两种,half-pressing按压聚焦或者触摸聚焦被触发,这个时候不要发生拍照动作
            if (focused) {
                mState = STATE_SUCCESS;
            } else {
                mState = STATE_FAIL;
            }
            //如果是触摸聚焦,需要延迟一下取消掉聚焦
            if (mFocusArea != null) {
                mFocusLocked = true;
                if(!isAFLock) {
                    mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY_MILLIS);
                }
            }
            //更新聚焦完成的ui
            if(!isAFLock) {
                updateFocusUI();
                autoChase();
            } else {
                mFocusRing.setAELockColor(true);
            }
            if (shutterButtonPressed) {
                // Lock AE & AWB so users can half-press shutter and recompose.
                lockAeAwbIfNeeded();
            }
        } else if (mState == STATE_IDLE) {
            // User has released the focus key before focus completes.
            // Do nothing.
        }
    }

3、取消聚焦

在FocusManager()中的cancleAutofocus()

private void cancelAutoFocus() {
        //清除聚焦区域
        clearAfArea();
        mMeteringArea = null;
        //监听cancelAutoFocus,在PhotoModule中实现
        mListener.cancelAutoFocus();
        //重置聚焦,聚焦框恢复到屏幕中间
        resetTouchFocus();
        //改变聚焦状态
        mState = STATE_IDLE;
        mFocusLocked = false;
        //移除msg
        mHandler.removeMessages(RESET_TOUCH_FOCUS);
    }

在PhotoModule的cancelAutoFocus()中

public void cancelAutoFocus() {
        if (mCameraDevice == null) {
            return;
        }
        //取消底层聚焦
        mCameraDevice.cancelAutoFocus();
        //设置相机状态
        setCameraState(IDLE);
        if (mFace != null && mFace
                && isCameraIdle() && !isHdr() ) {
            //开始人脸检测
            startFaceDetection();
        }
        setCameraParameters(UPDATE_PARAM_PREFERENCE);
    }

以上就是app层聚焦的大致流程

4、更新聚焦框ui

前面有好几处有更新ui的操作,我们来看一下具体做了些什么,其实就是对于聚焦框的改变与展示。
在FucusManager的updateFocusUI中:

public void updateFocusUI() {
        //没有初始化完成
        if (!mInitialized) {
            // Show only focus indicator or face indicator.
            return;
        }
        //聚焦开始,mFocusRing为聚焦框,可自定义
        if (mState == STATE_IDLE) {
            if (mFocusArea != null) {
                mFocusRing.startActiveFocus();
            }
            //正在聚焦
        } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) {
            if (mFocusArea == null) {
                mFocusRing.centerFocusLocation();
            }
            mFocusRing.startActiveFocus();
        } else {
            //聚焦成功
            if (mState == STATE_SUCCESS) {
                //拍照
                if (mTouchListener != null) {
                    mTouchListener.touchCapture();
                }
                //聚焦完成显示的对焦框
                mFocusRing.startActiveFocusedFocus();
                //聚焦成功的声音
                if (mFocusArea != null) {
                    if (mAppController.isPlaySoundEnable()) {
                        mCameraSound.play(MediaActionSound.FOCUS_COMPLETE);
                    }
                } else {
                    mFocusRing.centerFocusLocation();
                }
                //聚焦失败
            } else if (mState == STATE_FAIL) {
                if (mTouchListener != null) {
                    mTouchListener.touchCapture();
                }
                mFocusRing.startActiveFocusedFocus();
            }
        }
    }

5、相机状态和聚焦状态

聚焦过程中,相机状态的改变和聚焦状态的改变

相机状态:

在PhotoModule中设置相机状态:

protected void setCameraState(int state) {
        mCameraState = state;
        switch (state) {
        case PREVIEW_STOPPED:
        case SNAPSHOT_IN_PROGRESS:
        case SWITCHING_CAMERA:
            // TODO: Tell app UI to disable swipe
            break;
        case PhotoController.IDLE:
            // TODO: Tell app UI to enable swipe
            break;
        }
    }

聚焦状态:

STATE_IDLE:空闲状态

capture():空闲状态可以执行拍照
onAutoFocus(boolean focused):用户再聚焦完成前放掉了聚焦按钮,所以不做任何事。
onPreviewStarted()onPreviewStopped():状态都变为空闲
cancelAutoFocus():取消聚焦,状态变为空闲
updateFocusUI():如果空闲&有聚焦区域,显示聚焦框

STATE_FOCUSING:正在对焦

onShutterUp():如果是focusmode为自动聚焦,状态为正在聚焦,则取消掉聚焦
capture():如果是正在聚焦状态,将状态改为聚焦完拍照状态
onAutoFocus(boolean focused, boolean shutterButtonPressed):判断focused,为true变为聚焦成功状态,为false变为聚焦失败状态
onSingleTapUp(int x, int y):如果正在聚焦&之前有手动聚焦了,则取消掉之前的聚焦
autoFocus():状态变为聚焦状态
updateFocusUI():显示聚焦框

STATE_FOCUSING_SNAP_ON_FINISH:聚焦完拍照

onShutterUp():状态不是聚焦完拍照,可以设置FocusParameters
onAutoFocus(boolean focused, boolean shutterButtonPressed):判断focused,为true变为聚焦成功状态,为false变为聚焦失败状态,更新聚焦框UI
onSingleTapUp(int x, int y):直接不继续操作下去
updateFocusUI():显示聚焦框

STATE_SUCCESS:聚焦成功

onShutterDown():如果是自动聚焦mode,并且不为聚焦成功状态,执行聚焦
onShutterUp(): 如果是自动聚焦mode,并且为聚焦成功状态,执行取消聚焦
capture():拍照
onSingleTapUp(int x, int y):让用户可以取消掉之前未消失的触摸聚焦
updateFocusUI():聚焦框显示成功

STATE_FAIL:聚焦失败

onShutterDown():如果是自动聚焦mode,并且不为聚焦失败状态,执行聚焦
onShutterUp(): 如果是自动聚焦mode,并且为聚焦失败状态,执行取消聚焦
capture():拍照
onSingleTapUp(int x, int y):让用户可以取消掉之前未消失的触摸聚焦
updateFocusUI():聚焦框显示失败

关于底层的实现,主要是聚焦命令的下发(开始聚焦和结束聚焦),以及聚焦完成的回调

//开始聚焦
mCameraDevice.autoFocus(mHandler, mAutoFocusCallback);//mCameraDevice为CameraProxy的引用,mAutoFocusCallback为聚焦完成的回调

//取消聚焦
mCameraDevice.cancelAutoFocus();

CameraProxy为CameraAgent的内部类
具体实现又在AndroidCamera2AgentImpl中,有兴趣的朋友可以自行查看源码

你可能感兴趣的:(Camera)