Camera:Focus/AF mdoe

本文详细探讨了Android手机相机对焦功能的实现,从应用层手势事件监听开始,包括点击、长按等,解析了对焦流程,如检查环境、设置对焦区域、显示对焦UI、更新对焦区域、自动对焦等操作。同时,文章提到了对焦的lock状态管理和不同状态的管理机制。
摘要由CSDN通过智能技术生成

    手机相机的对焦处理,应用场景很多,今天可以通过应用层的相关处理代码来研究一下对焦需要走哪些流程以及容易遇到或引发什么样的问题。

 

1.应用层通过对一系列手势事件的监听触发聚焦功能

    因为这边涉及到Android开发上对点击、长按等手势事件的处理,我这边就把较全的手势监听处理事件粗略的描述了一下,手势处理不是重点,就先跳过了。

//点击屏幕即触发该事件
    @Override
    public boolean onDown(MotionEvent event) {
        return false;
    }

//点击屏幕后松开触发
    @Override
    public boolean onUp(MotionEvent event) {
        return false;
    }

//点击屏幕并滑动了一段距离后松开时触发
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }

//点击屏幕滑动时触发
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) {
        return false;
    }

//点击屏幕没有滑动,没有长时间按压然后松开时触发
    @Override
    public boolean onSingleTapUp(float x, float y) {
        //step1:Check whether auto focus can do
        if (!checkAfEnv()) {
            return false;
        }

        //step2:Check to restore af lock state and UI when needed.
        handleAfLockRestore();

        //step3:Clear any focus UI before show new touch focus UI
        mFocusViewController.clearFocusUi();
        if (mNeedShowFocusUi) {
            mFocusViewController.showActiveFocusAt((int) x, (int) y);
        }

        mIsAutoFocusTriggered = true;
        //step4:init focus and metering area and show focus UI
        try {
               initializeFocusAreas(x, y);
               initializeMeteringArea(x, y);
        } catch (IllegalArgumentException e) {
               LogHelper.e(mTag, "onSingleTapUp IllegalArgumentException");
               return;
        }

        //step5:notify focus area and parameter
        mFocusListener.updateFocusArea(mFocusArea, mMeteringArea);

        //step6:do auto focus
        mFocusListener.autoFocus();
        // exposure need onSingleTapUp to reset exposure progress,so
        return false;
    }

//单击屏幕之后短时间没有再次点击时触发
    @Override
    public boolean onSingleTapConfirmed(float x, float y) {
        return false;
    }

//点击屏幕不松开不移动及触发
    @Override
    public boolean onShowPress(MotionEvent event) {
        return false;
    }

//双击屏幕的第二下点击触发
    @Override
    public boolean onDoubleTap(float x, float y) {
        return false;
    }

//点击屏幕后不移动不松开一直长按触发
    @Override
    public boolean onLongPress(float x, float y) {

        //step1:Check whether auto focus can do
        if (!checkAfEnv()) {
            return false;
        }

        boolean isNeeedCancelAutoFocus = needCancelAutoFocus();

        mNeedDoAfLock = false;
        if (mFocusViewController == null) {
           return;
        }
        mIsAutoFocusTriggered = true;

        mLockPoint.set((int) x, (int) y);
        if (isNeeedCancelAutoFocus) {
           mFocusListener.cancelAutoFocus();
        }
        triggerAfLock();

        return false;
    }

//缩放手势的监听,缩放过程中触发
    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        return false;
    }

//缩放手势的监听,多个手指触碰屏幕是调用
    @Override
    public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
        return false;
    }

//全部手指离开屏幕时结束监听
    @Override
    public boolean onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
        return false;
    }

    当检测到单击屏幕事件后触发的聚焦UI相关的处理,此时触发的Focus状态为unlock状态

//1.检测聚焦功能可执行环境
private boolean checkAfEnv() {
        //ignore touch focus if preview not initialized.
        if (!mPreviewStarted) {
            LogHelper.w(mTag, "[checkAfEnv] preview not started ");
            return false;
        }

        // If focus view is not ready,do nothing.
        if (!mFocusViewController.isReadyTodoFocus()) {
            return false;
        }
        if (!mFocusListener.isFocusCanDo()) {
            return false;
        }

        // do not do touch focus if some one restriction focus to continue only
        List<String> entryValues = getEntryValues();
        if (entryValues != null && entryValues.size() == 1 &&
                (entryValues.contains("continuous-picture")
                        || entryValues.contains("continuous-video"))) {
            return false;
        }
        
        if (mFocusListener.isLastAfTriggerStillOnGoing()) {
            return false;
        }
        return true;
    }

//2.发送Focus功能没有触发的状态
private void handleAfLockRestore() {
        mSettingController.postRestriction(FocusRestriction.getAfLockRestriction()
                .getRelation(FocusRestriction.FOCUS_UNLOCK, true));
        mSettingController.postRestriction(FocusRestriction.getAeAfLockRestriction()
                .getRelation(FocusRestriction.FOCUS_UNLOCK, true));
        mLockState = LockState.STATE_UNLOCKED;
        mAppUi.hideScreenHint(mLockIndicatorHint);
    }

//Focus为Lock状态时,Exposure也为Lock状态
private static RelationGroup sAfLockRelationGroup = new RelationGroup();

    static {
        sAfLockRelationGroup.setHeaderKey(KEY_FOCUS);
        sAfLockRelationGroup.setBodyKeys(EXPOSURE_KEY);
        sAfLockRelationGroup.addRelation(
                new Relation.Builder(KEY_FOCUS, FOCUS_LOCK)
                        .addBody(EXPOSURE_KEY, EXPOSURE_LOCK, "true")
                        .build());
        sAfLockRelationGroup.addRelation(
                new Relation.Builder(KEY_FOCUS, FOCUS_UNLOCK)
                        .addBody(EXPOSURE_KEY, EXPOSURE_LOCK, "false")
                        .build());
    }

//Focus为Lock状态时,Flash为关闭状态
private static RelationGroup sAeAfLockRelationGroup = new RelationGroup();

    static {
        sAeAfLockRelationGroup.setHeaderKey(KEY_FOCUS);
        sAeAfLockRelationGroup.setBodyKeys(FLASH_KEY);
        sAeAfLockRelationGroup.addRelation(
                new Relation.Builder(KEY_FOCUS, FOCUS_LOCK)
                        .addBody(FLASH_KEY, "off", "off")
                        .build());
        sAeAfLockRelationGroup.addRelation(
                new Relation.Builder(KEY_FOCUS, FOCUS_UNLOCK)
                        .build());
    }

//3.显示聚焦框UI
 public void showActiveFocusAt(final int viewX, final int viewY) {
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (mFocusView == null) {
                    return;
                }
                mFeatureRootView.unRegisterView(mFocusView);
                mFeatureRootView.registerView(mFocusView, TOUCH_FOCUS_VIEW_PRIORITY);

                //Make sure focus view be added to root view when it is not null.
                makeSureViewOnTree();

                setFocusLocation(viewX, viewY);
                mFocusView.setFocusLocation(viewX, viewY);

                //Set Focus UI as VISIBLE
                mFocusView.startActiveFocus(mApp);
            }
        });
    }

//4.初始化Focus区域
    //这边是聚焦UI的区域
    private void initializeFocusAreas(float x, float y) {
        if (mFocusArea == null) {
            mFocusArea = new ArrayList<Area>();
            mFocusArea.add(new Area(new Rect(), 1));
        }
        Rect rect = new Rect();
        CameraUtil.rectFToRect(mPreviewRect, rect);

        //will dispatch mFocusArea to device
        int displayRotation = CameraUtil.getDisplayRotation(mActivity);
        mFocusArea.get(0).rect = CoordinatesTransform.uiToSensor(new Point((int) x,
                    (int) y), rect, displayRotation, AF_REGION_BOX,
                    mFocusRequestConfigure.getCropRegion(),
                    mFocusRequestConfigure.getCameraCharacteristics());
    }

    //这边初始的是曝光调节杆的区域
    private void initializeMeteringArea(float x, float y) {
        if (mMeteringArea == null) {
            mMeteringArea = new ArrayList<Area>();
            mMeteringArea.add(new Area(new Rect(), 1));
        }
        Rect rect = new Rect();
        CameraUtil.rectFToRect(mPreviewRect, rect);

        //will dispatch mMeteringAreato device
        int displayRotation = CameraUtil.getDisplayRotation(mActivity);
        mMeteringArea.get(0).rect = CoordinatesTransform.uiToSensor(new Point((int) x,
                            (int) y), rect, displayRotation, AE_REGION_BOX,
                    mFocusRequestConfigure.getCropRegion(),
                    mFocusRequestConfigure.getCameraCharacteristics());
        }
    }

//5.更新聚焦UI区域
@Override
    public void updateFocusArea(List<Camera.Area> focusArea, List<Camera.Area> meteringArea) {
        if (focusArea != null) {
            mAFRegions = new MeteringRectangle[]{new MeteringRectangle(focusArea.get(0).rect,
                    CAMERA2_REGION_WEIGHT)};
        }
        if (meteringArea != null) {
            mAERegions = new MeteringRectangle[]{new MeteringRectangle(meteringArea.get(0).rect,
                    CAMERA2_REGION_WEIGHT)};
        }
    }

//6.发送触发自动聚焦的相关底层tag,同时Flash、Exposure相关的底层配置Tag也会一同下发
@Override
    public void autoFocus() {
        sendAutoFocusTriggerCaptureRequest(false);
    }

长按屏幕此时触发Focus的lock状态

//1.判断是否可以执行自动聚焦功能
if (!checkAfEnv()) {
            return false;
        }

//2.判断是否需要取消上个状态的自动聚焦功能
boolean isNeeedCancelAutoFocus = needCancelAutoFocus();

private boolean needCancelAutoFocus() {
        if (mFocusViewController == null) {
            LogHelper.w(mTag, "[needCancelAutoFocus] mFocusViewController is null");
            return false;
        }
        FocusViewState state = mFocusViewController.getFocusState();

        //根据已知更新的Focus状态state去判断是否需要关闭
        boolean result = mFocusArea != null && (FocusViewState.STATE_ACTIVE_FOCUSING == state);
        return result;
    }

//下文会继续讲Focus的几个不同状态及其对应的时机,以及Focus状态的管理机制


//3.如果需要取消自动对焦,发送取消自动对焦的参数
if (isNeeedCancelAutoFocus) {
                    mFocusListener.cancelAutoFocus();
                }

@Override
    public void cancelAutoFocus() {
        LogHelper.d(TAG, "[cancelAutoFocus] ");
        sendAutoFocusCancelCaptureRequest();
    }

//4.触发AF mode为lock的转态
triggerAfLock();

/长按触发AF Lock状态处理流程貌似和单击触发自动对焦的流程一样,但是在Focus的状态管理中已经下发了AF Lock的状态
private void triggerAfLock() {
        LogHelper.d(mTag, "[triggerAfLock]+ ");
        mNeedResetTouchFocus = false;
        //Clear any focus UI before show touch focus UI
        mFocusViewController.clearFocusUi();

        //init focus and metering area and show focus UI
        try {
            initializeFocusAreas(mLockPoint.x, mLockPoint.y);
            initializeMeteringArea(mLockPoint.x, mLockPoint.y);
        } catch (IllegalArgumentException e) {
            LogHelper.e(mTag, "triggerAfLock IllegalArgumentException");
            return;
        }

        if (mNeedShowFocusUi) {
            mFocusViewController.showActiveFocusAt(mLockPoint.x, mLockPoint.y);
            mAppUi.hideScreenHint(mLockIndicatorHint);
            mAppUi.showScreenHint(mLockIndicatorHint);
        }

        //notify focus area and parameter
        mFocusListener.updateFocusArea(mFocusArea, mMeteringArea);
        mModeHandler.removeMessages(RESET_TOUCH_FOCUS);

        //post to to ae unlock
        //这边和单击触发自动聚焦相比就可以看出比较明显的区别,AEAF仍为Lock状态,只是曝光为UnLock
        mSettingController.postRestriction(FocusRestriction.getAfLockRestriction()
                .getRelation(FocusRestriction.FOCUS_UNLOCK, true));

        //fix focus mode to auto and do auto focus
        mFocusListener.autoFocus();
        mLockState = LockState.STATE_LOCKING;
        mNeedDoAfLock = true;
        LogHelper.d(mTag, "[Lock]-");
    }

 

小结:

    聚焦这一块的内容一篇文章根本讲不完,下文会继续深入研究Focus PASSIVE_SCAN、ACTIVE_SCAN、PASSIVE_FOCUSED、PASSIVE_UNFOCUSED、ACTIVE_FOCUSED、ACTIVE_UNFOCUSED等不同状态的管理,以及自动聚焦功能触发时下发到底层的Tag管理。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值