Flash app tuning flow

一、 app  flow , qcom camera

    /**
     * Initiate a still image capture.
     */
    private void takePicture() {
        Log.d(TAG, "takePicture");
        ...
        ...
            if (mUI.getCurrentProMode() == ProMode.MANUAL_MODE) {
                captureStillPicture(cameraId);
            } else {
                if (mLongshotActive) {
                    parallelLockFocusExposure(cameraId);
                } else {
                    if (mPreviewCaptureResult != null) {
                        Integer aeState = mPreviewCaptureResult.get(CaptureResult.CONTROL_AE_STATE);
                        //1.---- is need flash -----
                        isFlashRequiredInDriver = aeState != null && aeState == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED;
                    }
                    lockFocus(cameraId);
                }
            }
        }
    }
  /**
     * Lock the focus as the first step for a still image capture.
     */
    private void lockFocus(int id) {
        Log.d(TAG, "lockFocus " + id);
        try {
         ......
         ......
         mTakingPicture[id] = true;
        //if touch focuing ?
        if (mState[id] == STATE_WAITING_TOUCH_FOCUS) {
            mCameraHandler.removeMessages(CANCEL_TOUCH_FOCUS, mCameraId[id]);
            mState[id] = STATE_WAITING_AF_LOCK;
            mLockRequestHashCode[id] = 0;
            return;
        }

        try {
            //2. ----- start af  ---------------------
            CaptureRequest.Builder builder = getRequestBuilder(id);
            builder.setTag(id);
            addPreviewSurface(builder, null, id);
            applySettingsForLockFocus(builder, id);
            /**private void applySettingsForLockFocus(CaptureRequest.Builder builder, int id) {
                builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
                applyAFRegions(builder, id);
                applyAERegions(builder, id);
                applyCommonSettings(builder, id);
            }**/
            CaptureRequest request = builder.build();
            mLockRequestHashCode[id] = request.hashCode();
            mState[id] = STATE_WAITING_AF_LOCK;
            mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
        } catch (CameraAccessException | IllegalStateException e) {
            e.printStackTrace();
        }
    }

 

 

  /**
         * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
         */
        private CameraCaptureSession.CaptureCallback mCaptureCallback
                = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureProgressed(CameraCaptureSession session,
                                            CaptureRequest request,
                                            CaptureResult partialResult) {
                ....
            }

            @Override
            public void onCaptureCompleted(CameraCaptureSession session,
                                           CaptureRequest request,
                                           TotalCaptureResult result) {
                ...
                //3. ----- handle af ae -> up code -------
                processCaptureResult(result);
                ...
            }

            private void processCaptureResult(CaptureResult result) {
                int id = (int) result.getRequest().getTag();
                .....
                updateCaptureStateMachine(id, result);
                ....
        };

 

  

   private void updateCaptureStateMachine(int id, CaptureResult result) {
        Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
        Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
        Log.d(TAG, "updateCaptureStateMachine state:"+ mState[id]
                +" camera id: " + id + " afState:" + afState + " aeState:" + aeState);
        switch (mState[id]) {
            case STATE_PREVIEW: {
                break;
            }
            case STATE_WAITING_AF_LOCK: {
                //4. AF_PASSIVE is added for continous auto focus mode
                if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState ||
                        CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState ||
                        (mLockRequestHashCode[id] == result.getRequest().hashCode() &&
                                afState == CaptureResult.CONTROL_AF_STATE_INACTIVE)) {

                    if(id == MONO_ID && getCameraMode() == DUAL_MODE && isBackCamera()) {
                    // in dual mode, mono AE dictated by bayer AE.
                        // if not already locked, wait for lock update from bayer
                        if(aeState == CaptureResult.CONTROL_AE_STATE_LOCKED)
                            checkAfAeStatesAndCapture(id);
                        else
                            mState[id] = STATE_WAITING_AE_LOCK;
                    } else {
                        if ((mLockRequestHashCode[id] == result.getRequest().hashCode()) || (mLockRequestHashCode[id] == 0)) {

                            // CONTROL_AE_STATE can be null on some devices
                            if(aeState == null || (aeState == CaptureResult
                                    .CONTROL_AE_STATE_CONVERGED) && isFlashOff(id)) {
                                lockExposure(id);
                            } else {
                                //5.----  start Precapture Sequence ---------------
                                runPrecaptureSequence(id);
                            }
                        }
                    }
                } else if (mLockRequestHashCode[id] == result.getRequest().hashCode()){
                    Log.i(TAG, "AF lock request result received, but not focused");
                    mLockRequestHashCode[id] = 0;
                } else if (mSettingsManager.isFixedFocus(id)) {
                // CONTROL_AE_STATE can be null on some devices
                    if(aeState == null || (aeState == CaptureResult
                            .CONTROL_AE_STATE_CONVERGED) && isFlashOff(id)) {
                        lockExposure(id);
                    } else {
                        runPrecaptureSequence(id);
                    }
                }
                break;
            }
            case STATE_WAITING_PRECAPTURE: {
            // CONTROL_AE_STATE can be null on some devices
                if (aeState == null ||
                        aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
                        aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED ||
                        aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                    if ((mPrecaptureRequestHashCode[id] == result.getRequest().hashCode()) || (mPrecaptureRequestHashCode[id] == 0)) {
                        if (mLongshotActive && isFlashOn(id)) {
                            //---------------- capture -----------------------------
                            checkAfAeStatesAndCapture(id);
                        } else {
                            //6. ---------- lock exposure -------------------------
                            lockExposure(id);
                        }
                    }
                } else if (aeState == null ||
                        aeState == CaptureResult.CONTROL_AE_STATE_INACTIVE) {
                // AE Mode is OFF, the AE state is always CONTROL_AE_STATE_INACTIVE
                    // then begain capture and ignore lock AE.
                    checkAfAeStatesAndCapture(id);
                } else if (mPrecaptureRequestHashCode[id] == result.getRequest().hashCode()) {
                    Log.i(TAG, "AE trigger request result received, but not converged");
                    mPrecaptureRequestHashCode[id] = 0;
                }
                break;
            }
            case STATE_WAITING_AE_LOCK: {
                // CONTROL_AE_STATE can be null on some devices
                if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_LOCKED) {
                    //7.  ------- capture -------------
                    checkAfAeStatesAndCapture(id);
                }
                break;
            }
            ...
        }
    }

 

  

    /**Precapture Sequence
     * Run the precapture sequence for capturing a still image. This method should be called when
     * we get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
     */
    private void runPrecaptureSequence(int id) {
        Log.d(TAG, "runPrecaptureSequence: " + id);
        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
            return;
        }
        try {
            CaptureRequest.Builder builder = getRequestBuilder(id);
            builder.setTag(id);
            addPreviewSurface(builder, null, id);
            //----- apply precapture build -------------------
            applySettingsForPrecapture(builder, id);
            CaptureRequest request = builder.build();
            mPrecaptureRequestHashCode[id] = request.hashCode();
            mState[id] = STATE_WAITING_PRECAPTURE;
            mCaptureSession[id].capture(request, mCaptureCallback, mCameraHandler);
            isFlashRequiredInDriver = false;
        } catch (CameraAccessException | IllegalStateException e) {
            e.printStackTrace();
        }
    }

    private void  applySettingsForPrecapture(CaptureRequest.Builder builder, int id) {
        String redeye = mSettingsManager.getValue(SettingsManager.KEY_REDEYE_REDUCTION);
        if (redeye != null && redeye.equals("on") && !isFlashRequiredInDriver) {
            if (DEBUG)
                Log.d(TAG, "Red Eye Reduction is On. " +
                        "Don't set CONTROL_AE_PRECAPTURE_TRIGGER to Start");
        } else {
            builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
        }
        // For long shot, torch mode is used
        if (!mLongshotActive) {
            // -------- flash mode -------------------------
            applyFlash(builder, id);
        /**private void applyFlash(CaptureRequest.Builder request, int id) {
          if (mSettingsManager.isFlashSupported(id)) {
            String value = mSettingsManager.getValue(mCurrentSceneMode.mode == CameraMode.PRO_MODE ?
                    SettingsManager.KEY_VIDEO_FLASH_MODE : SettingsManager.KEY_FLASH_MODE);
            applySnapshotFlash(request, value);
          } else {
            request.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
         }
        }**/
        }
        applyCommonSettings(builder, id);
    }

 

  

    /**
     * Lock the exposure for capture
     */
    private void lockExposure(int id) {
        if (!checkSessionAndBuilder(mCaptureSession[id], mPreviewRequestBuilder[id])) {
            return;
        }
        Log.d(TAG, "lockExposure: " + id);
        try {
            applySettingsForLockExposure(mPreviewRequestBuilder[id], id);
            /**private void applySettingsForLockExposure(CaptureRequest.Builder builder, int id) {
                builder.set(CaptureRequest.CONTROL_AE_LOCK, Boolean.TRUE);
            }**/
            //change state
            mState[id] = STATE_WAITING_AE_LOCK;
            mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(),
                    mCaptureCallback, mCameraHandler);
        } catch (CameraAccessException | IllegalStateException e) {
            e.printStackTrace();
        }
    }

 

tuning flow

1. 先统计 ae 送给算法
2. 预闪 , 预闪结束后 ae 收敛完成 送给算法
3. 预闪前 ae 和 预闪后 ae 值都有了, 然后给 算法, 算出来 主闪需要打多少光

PS: 为了保护闪光灯不被烧坏, 所以需要 预闪 和 主闪之间的冷却时间

你可能感兴趣的:(android,Camera)