/* * Copyright (C) 2017 Intel Corporation. * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "RKISP2ControlUnit" #include #include "LogHelper.h" #include "PerformanceTraces.h" #include "RKISP2ControlUnit.h" #include "RKISP1CameraHw.h" #include "RKISP2CameraHw.h" #include "RKISP2ImguUnit.h" #include "CameraStream.h" #include "RKISP2CameraCapInfo.h" #include "CameraMetadataHelper.h" #include "PlatformData.h" #include "RKISP2ProcUnitSettings.h" #include "RKISP2SettingsProcessor.h" #include "RKISP2Metadata.h" #include "MediaEntity.h" #include "rkcamera_vendor_tags.h" //#include "TuningServer.h" USING_METADATA_NAMESPACE; static const int SETTINGS_POOL_SIZE = MAX_REQUEST_IN_PROCESS_NUM * 2; #define FLASH_OFFSET 8.0 //ms #define FLASH_TRIGGER_TH 5.0f namespace android { namespace camera2 { namespace rkisp2 { SocCamFlashCtrUnit::SocCamFlashCtrUnit(const char* name, int CameraId) : mFlSubdev(new V4L2Subdevice(name)), mV4lFlashMode(V4L2_FLASH_LED_MODE_NONE), mAePreTrigger(0), mAeTrigFrms(0), mMeanLuma(1.0f), mAeFlashMode(ANDROID_FLASH_MODE_OFF), mAeMode(ANDROID_CONTROL_AE_MODE_ON), mAeState(ANDROID_CONTROL_AE_STATE_INACTIVE) { LOGD("%s:%d", __FUNCTION__, __LINE__); if (mFlSubdev.get()) mFlSubdev->open(); } SocCamFlashCtrUnit::~SocCamFlashCtrUnit() { LOGD("%s:%d", __FUNCTION__, __LINE__); if (mFlSubdev.get()) { setV4lFlashMode(CAM_AE_FLASH_MODE_OFF, 100, 0, 0); mFlSubdev->close(); } } void SocCamFlashCtrUnit::setMeanLuma(float luma) { if (mAeTrigFrms == 0) mMeanLuma = luma; } int SocCamFlashCtrUnit::setFlashSettings(const CameraMetadata *settings) { int ret = 0; // parse flash mode, ae mode, ae precap trigger uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON; camera_metadata_ro_entry entry = settings->find(ANDROID_CONTROL_AE_MODE); if (entry.count == 1) aeMode = entry.data.u8[0]; uint8_t flash_mode = ANDROID_FLASH_MODE_OFF; entry = settings->find(ANDROID_FLASH_MODE); if (entry.count == 1) { flash_mode = entry.data.u8[0]; } mAeFlashMode = flash_mode; mAeMode = aeMode; // if aemode is *_flash, overide the flash mode of ANDROID_FLASH_MODE int flashMode; if (aeMode == ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH) flashMode = CAM_AE_FLASH_MODE_AUTO; // TODO: set always on for soc now else if (aeMode == ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH) flashMode = CAM_AE_FLASH_MODE_ON; else if (flash_mode == ANDROID_FLASH_MODE_TORCH) flashMode = CAM_AE_FLASH_MODE_TORCH; else if (flash_mode == ANDROID_FLASH_MODE_SINGLE) flashMode = CAM_AE_FLASH_MODE_SINGLE; else flashMode = CAM_AE_FLASH_MODE_OFF; // TODO: set always on for soc now if (flashMode == CAM_AE_FLASH_MODE_AUTO || flashMode == CAM_AE_FLASH_MODE_SINGLE) flashMode = CAM_AE_FLASH_MODE_ON; if (flashMode == CAM_AE_FLASH_MODE_ON || flashMode == CAM_AE_FLASH_MODE_AUTO) { entry = settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER); if (entry.count == 1) { if (!(entry.data.u8[0] == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE && mAePreTrigger == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START)) mAePreTrigger = entry.data.u8[0]; } } mAeState = ANDROID_CONTROL_AE_STATE_CONVERGED; int setToDrvFlMode = (flashMode == CAM_AE_FLASH_MODE_AUTO || flashMode == CAM_AE_FLASH_MODE_SINGLE) ? CAM_AE_FLASH_MODE_ON : flashMode; if (flashMode == CAM_AE_FLASH_MODE_TORCH) setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; else if (flashMode == CAM_AE_FLASH_MODE_ON || (flashMode == CAM_AE_FLASH_MODE_AUTO)) { // assume SoC sensor has only torch flash mode, and for // ANDROID_CONTROL_CAPTURE_INTENT usecase, flash should keep // on until the jpeg image captured. if (mAePreTrigger == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START) { if (flashMode == CAM_AE_FLASH_MODE_AUTO && mMeanLuma < 18.0f) setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; else if (flashMode == CAM_AE_FLASH_MODE_ON) setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; else setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; mAeState = ANDROID_CONTROL_AE_STATE_PRECAPTURE; mAeTrigFrms++; // keep on precap for 10 frames to wait flash ae stable if (mAeTrigFrms > 10) mAeState = ANDROID_CONTROL_AE_STATE_CONVERGED; // keep flash on another 10 frames to make sure capture the // flashed frame if (mAeTrigFrms > 20) { setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; mAeTrigFrms = 0; mAePreTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL; mAeState = ANDROID_CONTROL_AE_STATE_CONVERGED; } } else if (mAePreTrigger == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) { setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; mAeTrigFrms = 0; } LOGD("aePreTrigger %d, mAeTrigFrms %d", mAePreTrigger, mAeTrigFrms); } else setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; LOGD("%s:%d aePreTrigger %d, mAeTrigFrms %d, setToDrvFlMode %d", __FUNCTION__, __LINE__, mAePreTrigger, mAeTrigFrms, setToDrvFlMode); return setV4lFlashMode(setToDrvFlMode, 100, 500, 0); } int SocCamFlashCtrUnit::updateFlashResult(CameraMetadata *result) { result->update(ANDROID_CONTROL_AE_MODE, &mAeMode, 1); result->update(ANDROID_CONTROL_AE_STATE, &mAeState, 1); result->update(ANDROID_FLASH_MODE, &mAeFlashMode, 1); uint8_t flashState = ANDROID_FLASH_STATE_READY; if (mV4lFlashMode == V4L2_FLASH_LED_MODE_FLASH || mV4lFlashMode == V4L2_FLASH_LED_MODE_TORCH) { flashState = ANDROID_FLASH_STATE_FIRED; if (mAeMode >= ANDROID_CONTROL_AE_MODE_ON && mAeFlashMode == ANDROID_FLASH_MODE_OFF) { flashState = ANDROID_FLASH_STATE_PARTIAL; } } /* Using android.flash.mode == TORCH or SINGLE will always return FIRED.*/ if (mAeFlashMode == ANDROID_FLASH_MODE_TORCH || mAeFlashMode == ANDROID_FLASH_MODE_SINGLE) { ALOGD("%s:%d mAeFlashMode: %d, set flashState FIRED!", __FUNCTION__, __LINE__, mAeFlashMode); flashState = ANDROID_FLASH_STATE_FIRED; } //# ANDROID_METADATA_Dynamic android.flash.state done result->update(ANDROID_FLASH_STATE, &flashState, 1); return 0; } int SocCamFlashCtrUnit::setV4lFlashMode(int mode, int power, int timeout, int strobe) { struct v4l2_control control; int fl_v4l_mode; #define set_fl_contol_to_dev(control_id,val) \ memset(&control, 0, sizeof(control)); \ control.id = control_id; \ control.value = val; \ if (mFlSubdev.get()) { \ if (pioctl(mFlSubdev->getFd(), VIDIOC_S_CTRL, &control, 0) < 0) { \ LOGE(" set fl %s to %d failed", #control_id, val); \ return -1; \ } \ LOGD("set fl %s to %d, success", #control_id, val); \ } \ if (mode == CAM_AE_FLASH_MODE_OFF) fl_v4l_mode = V4L2_FLASH_LED_MODE_NONE; else if (mode == CAM_AE_FLASH_MODE_ON) fl_v4l_mode = V4L2_FLASH_LED_MODE_FLASH; else if (mode == CAM_AE_FLASH_MODE_TORCH) fl_v4l_mode = V4L2_FLASH_LED_MODE_TORCH; else { LOGE(" set fl to mode %d failed", mode); return -1; } if (mV4lFlashMode == fl_v4l_mode) return 0; if (fl_v4l_mode == V4L2_FLASH_LED_MODE_NONE) { set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_NONE); } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_FLASH) { set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_FLASH); set_fl_contol_to_dev(V4L2_CID_FLASH_TIMEOUT, timeout * 1000); // TODO: should query intensity range before setting /* set_fl_contol_to_dev(V4L2_CID_FLASH_INTENSITY, mfl_intensity); */ set_fl_contol_to_dev(strobe ? V4L2_CID_FLASH_STROBE : V4L2_CID_FLASH_STROBE_STOP, 0); } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_TORCH) { // TODO: should query intensity range before setting /* set_fl_contol_to_dev(V4L2_CID_FLASH_TORCH_INTENSITY, mfl_intensity); */ set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_TORCH); } else { LOGE("setV4lFlashMode error fl mode %d", mode); return -1; } mV4lFlashMode = fl_v4l_mode; return 0; } RawCamFlashCtrUnit::RawCamFlashCtrUnit(const char* name, int CameraId) : mFlSubdev(new V4L2Subdevice(name)), mV4lFlashMode(V4L2_FLASH_LED_MODE_NONE), isNeedFlash(false), mAeTrigFrms(0), mMeanLuma(1.0f), mAeFlashMode(ANDROID_FLASH_MODE_OFF), mAeMode(ANDROID_CONTROL_AE_MODE_ON), mAeState(ANDROID_CONTROL_AE_STATE_INACTIVE) { LOGD_FLASH("%s:%d", __FUNCTION__, __LINE__); mStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE; mLastStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE; mStilCapPreCapreqId = -1; if (mFlSubdev.get()) mFlSubdev->open(); get_flash_info(); mfl_intensity = 0.8; } int RawCamFlashCtrUnit::get_flash_info(void) { struct v4l2_queryctrl ctrl; int flash_power, torch_power; LOGD_FLASH("%s:%d", __FUNCTION__, __LINE__); memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = V4L2_CID_FLASH_INTENSITY; if (pioctl(mFlSubdev->getFd(), VIDIOC_QUERYCTRL, &ctrl, 0) < 0) { LOGD_FLASH("query V4L2_CID_FLASH_INTENSITY failed. cmd = 0x%x", V4L2_CID_FLASH_INTENSITY); return -1; } flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MIN] = ctrl.minimum; flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX] = ctrl.maximum; flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_DEFAULT] = ctrl.default_value; flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_STEP] = ctrl.step; fl_strth_adj_enable = !(ctrl.flags & V4L2_CTRL_FLAG_READ_ONLY); LOGD_FLASH("flash power range:[%d,%d], adjust enable %d", ctrl.minimum, ctrl.maximum, fl_strth_adj_enable); memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = V4L2_CID_FLASH_TORCH_INTENSITY; if (pioctl(mFlSubdev->getFd(), VIDIOC_QUERYCTRL, &ctrl, 0) < 0) { LOGD_FLASH("query V4L2_CID_FLASH_INTENSITY failed. cmd = 0x%x", V4L2_CID_FLASH_INTENSITY); return -1; } torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MIN] = ctrl.minimum; torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX] = ctrl.maximum; torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_DEFAULT] = ctrl.default_value; torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_STEP] = ctrl.step; tc_strth_adj_enable = !(ctrl.flags & V4L2_CTRL_FLAG_READ_ONLY); LOGD_FLASH("torch power range:[%d,%d], adjust enable %d", ctrl.minimum, ctrl.maximum, tc_strth_adj_enable); return 0; } RawCamFlashCtrUnit::~RawCamFlashCtrUnit() { LOGD_FLASH("%s:%d", __FUNCTION__, __LINE__); if (mFlSubdev.get()) { setV4lFlashMode(CAM_AE_FLASH_MODE_OFF, 0, 0, 0); mFlSubdev->close(); } } void RawCamFlashCtrUnit::updateStillPreCapreqId(int reqId) { mStilCapPreCapreqId = reqId; } void RawCamFlashCtrUnit::setMeanLuma(float luma, int reqId) { mMeanLuma = luma; } void RawCamFlashCtrUnit::updateStillCapSyncState(StillCapSyncState_e stillCapSyncState) { mStillCapSyncState = stillCapSyncState; } void RawCamFlashCtrUnit::updateStillCapExpTime(int64_t ExposureTimens) { mExposureTimens = ExposureTimens; } int RawCamFlashCtrUnit::setFlashSettings(const CameraMetadata *settings) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); int ret = 0; int strobe = 0; LOGD_FLASH("@%s enter!", __FUNCTION__); // parse flash mode, ae mode, ae precap trigger uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON; camera_metadata_ro_entry entry = settings->find(ANDROID_CONTROL_AE_MODE); if (entry.count == 1) aeMode = entry.data.u8[0]; uint8_t flash_mode = ANDROID_FLASH_MODE_OFF; entry = settings->find(ANDROID_FLASH_MODE); if (entry.count == 1) { flash_mode = entry.data.u8[0]; } mAeFlashMode = flash_mode; mAeMode = aeMode; #if 0 if ((mLastAeFlashMode == mAeFlashMode) && (mLastAeMode == mAeMode)) { LOGD_FLASH("@%s:%d flash_mode & aeMode not changed, return!", __FUNCTION__); return 0; } /* alreay in torch or flash, don't change flash state */ if (mLastStillCapSyncState == mStillCapSyncState) { LOGD_FLASH("@%s alreay in torch or flash, don't change flash state!", __FUNCTION__); return 0; } #endif // if aemode is *_flash, overide the flash mode of ANDROID_FLASH_MODE int aeFlashMode = CAM_AE_FLASH_MODE_OFF; if (aeMode == ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH) aeFlashMode = CAM_AE_FLASH_MODE_AUTO; else if (aeMode == ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH) aeFlashMode = CAM_AE_FLASH_MODE_ON; else if (flash_mode == ANDROID_FLASH_MODE_TORCH) aeFlashMode = CAM_AE_FLASH_MODE_TORCH; else if (flash_mode == ANDROID_FLASH_MODE_SINGLE) aeFlashMode = CAM_AE_FLASH_MODE_SINGLE; else aeFlashMode = CAM_AE_FLASH_MODE_OFF; int setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; LOGD_FLASH("%s:%d aeMode(%d), flash_mode(%d) aeFlashMode %d, setToDrvFlMode(%d)", __FUNCTION__, __LINE__, aeMode, flash_mode, aeFlashMode, setToDrvFlMode); if (aeFlashMode == CAM_AE_FLASH_MODE_TORCH) { setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; } else if (aeFlashMode == CAM_AE_FLASH_MODE_ON || (aeFlashMode == CAM_AE_FLASH_MODE_AUTO)) { if (mStillCapSyncState == STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP) { if (aeFlashMode == CAM_AE_FLASH_MODE_AUTO && mMeanLuma < FLASH_TRIGGER_TH) setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; else if (aeFlashMode == CAM_AE_FLASH_MODE_ON) setToDrvFlMode = CAM_AE_FLASH_MODE_TORCH; else setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; isNeedFlash = setToDrvFlMode; } else if (mStillCapSyncState == STILL_CAP_SYNC_STATE_FROM_ENGINE_DONE) { /* not go into this*/ setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; } else if (mStillCapSyncState == STILL_CAP_SYNC_STATE_WATING_JPEG_FRAME) { if (aeFlashMode == CAM_AE_FLASH_MODE_AUTO && mMeanLuma < FLASH_TRIGGER_TH) setToDrvFlMode = CAM_AE_FLASH_MODE_ON; else if (aeFlashMode == CAM_AE_FLASH_MODE_ON) setToDrvFlMode = CAM_AE_FLASH_MODE_ON; strobe = 1; isNeedFlash = setToDrvFlMode; } else if (mStillCapSyncState == STILL_CAP_SYNC_STATE_JPEG_FRAME_DONE) { setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; isNeedFlash = setToDrvFlMode; } } else { setToDrvFlMode = CAM_AE_FLASH_MODE_OFF; } LOGD("@%s: set mMeanLuma > %f to trigger flash!", __FUNCTION__, FLASH_TRIGGER_TH); LOGD_FLASH("%s:%d mStillCapSyncState %d, setToDrvFlMode %d, isNeedFlash(%d)", __FUNCTION__, __LINE__, mStillCapSyncState, setToDrvFlMode, isNeedFlash); mLastStillCapSyncState = mStillCapSyncState; return setV4lFlashMode(setToDrvFlMode, 100, 500, strobe); } int RawCamFlashCtrUnit::updateFlashResult(CameraMetadata *result) { result->update(ANDROID_CONTROL_AE_MODE, &mAeMode, 1); result->update(ANDROID_CONTROL_AE_STATE, &mAeState, 1); result->update(ANDROID_FLASH_MODE, &mAeFlashMode, 1); uint8_t flashState = ANDROID_FLASH_STATE_READY; if (mV4lFlashMode == V4L2_FLASH_LED_MODE_FLASH || mV4lFlashMode == V4L2_FLASH_LED_MODE_TORCH) { flashState = ANDROID_FLASH_STATE_FIRED; if (mAeMode >= ANDROID_CONTROL_AE_MODE_ON && mAeFlashMode == ANDROID_FLASH_MODE_OFF) { flashState = ANDROID_FLASH_STATE_PARTIAL; } } /* Using android.flash.mode == TORCH or SINGLE will always return FIRED.*/ if (mAeFlashMode == ANDROID_FLASH_MODE_TORCH || mAeFlashMode == ANDROID_FLASH_MODE_SINGLE) { LOGD_FLASH("%s:%d mAeFlashMode: %d, set flashState FIRED!", __FUNCTION__, __LINE__, mAeFlashMode); flashState = ANDROID_FLASH_STATE_FIRED; } //# ANDROID_METADATA_Dynamic android.flash.state done result->update(ANDROID_FLASH_STATE, &flashState, 1); return 0; } int RawCamFlashCtrUnit::setStillChangeFlash(void) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); int ret = 0; if (isNeedFlash) { LOGD_FLASH("%s:%d set flash for still_change_resolution capture!", __FUNCTION__, __LINE__); ret = setV4lFlashMode(CAM_AE_FLASH_MODE_ON, 100, 500, 1); if (ret < 0) LOGE_FLASH("%s:%d set flash settings failed", __FUNCTION__, __LINE__); } return ret ; } int RawCamFlashCtrUnit::setV4lFlashMode(int mode, int power, int fl_timeout, int strobe) { struct v4l2_control control; int fl_v4l_mode; #define set_fl_contol_to_dev(control_id,val) \ memset(&control, 0, sizeof(control)); \ control.id = control_id; \ control.value = val; \ if (mFlSubdev.get()) { \ if (pioctl(mFlSubdev->getFd(), VIDIOC_S_CTRL, &control, 0) < 0) { \ LOGE_FLASH(" set fl %s to %d failed", #control_id, val); \ } else {\ LOGD_FLASH("set fl %s to %d, success", #control_id, val); \ } \ } \ if (mode == CAM_AE_FLASH_MODE_OFF) fl_v4l_mode = V4L2_FLASH_LED_MODE_NONE; else if (mode == CAM_AE_FLASH_MODE_ON) fl_v4l_mode = V4L2_FLASH_LED_MODE_FLASH; else if (mode == CAM_AE_FLASH_MODE_TORCH) fl_v4l_mode = V4L2_FLASH_LED_MODE_TORCH; else { LOGE(" set fl to mode %d failed", mode); return -1; } if (mV4lFlashMode == fl_v4l_mode) return 0; if (fl_v4l_mode == V4L2_FLASH_LED_MODE_NONE) { set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_NONE); } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_FLASH) { set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_FLASH); set_fl_contol_to_dev(V4L2_CID_FLASH_TIMEOUT, fl_timeout * 1000); // TODO: should query intensity range before setting if (fl_strth_adj_enable) { int flash_power = mfl_intensity * (flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX]); set_fl_contol_to_dev(V4L2_CID_FLASH_TORCH_INTENSITY, flash_power); LOGE_FLASH("set flash: flash:%f max:%d set:%d\n", mfl_intensity, flash_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX], flash_power); } set_fl_contol_to_dev(strobe ? V4L2_CID_FLASH_STROBE : V4L2_CID_FLASH_STROBE_STOP, 0); } else if (fl_v4l_mode == V4L2_FLASH_LED_MODE_TORCH) { // TODO: should query intensity range before setting /* set_fl_contol_to_dev(V4L2_CID_FLASH_TORCH_INTENSITY, mfl_intensity); */ if (tc_strth_adj_enable) { int torch_power = mfl_intensity * (torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX]); set_fl_contol_to_dev(V4L2_CID_FLASH_TORCH_INTENSITY, torch_power);; LOGE_FLASH("set flash: torch:%f max:%d set:%d\n", mfl_intensity, torch_power_info[RK_HAL_V4L_FLASH_QUERY_TYPE_E_MAX], torch_power); } set_fl_contol_to_dev(V4L2_CID_FLASH_LED_MODE, V4L2_FLASH_LED_MODE_TORCH); } else { LOGE_FLASH("setV4lFlashMode error fl mode %d", mode); return -1; } mV4lFlashMode = fl_v4l_mode; return 0; } RKISP2ControlUnit::RKISP2ControlUnit(RKISP2ImguUnit *thePU, int cameraId, RKISP2IStreamConfigProvider &aStreamCfgProv, std::shared_ptr mc) : mRequestStatePool("CtrlReqState"), mCaptureUnitSettingsPool("CapUSettings"), mProcUnitSettingsPool("ProcUSettings"), mLatestRequestId(-1), mImguUnit(thePU), mCtrlLoop(nullptr), mEnable3A(true), mCameraId(cameraId), mMediaCtl(mc), mThreadRunning(false), mMessageQueue("CtrlUnitThread", static_cast(MESSAGE_ID_MAX)), mMessageThread(nullptr), mStreamCfgProv(aStreamCfgProv), mRKISP2SettingsProcessor(nullptr), mMetadata(nullptr), mSensorSettingsDelay(0), mGainDelay(0), mLensSupported(false), mFlashSupported(false), mSofSequence(0), mShutterDoneReqId(-1), mSensorSubdev(nullptr), mSocCamFlashCtrUnit(nullptr), mStillCapSyncNeeded(0), mStillCapSyncState(STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE), mFlushForUseCase(FLUSH_FOR_NOCHANGE) { cl_result_callback_ops::metadata_result_callback = &sMetadatCb; mExposureTimens = 1000; //0.001ms mFrameTimens = 33000000; //33ms mSofSyncStae = false; mSofSyncId = -1; mStilCapPreCapreqId = -1; } status_t RKISP2ControlUnit::getDevicesPath() { std::shared_ptr mediaEntity = nullptr; std::string entityName; const CameraHWInfo* camHwInfo = PlatformData::getCameraHWInfo(); std::shared_ptr subdev = nullptr; status_t status = OK; const struct SensorDriverDescriptor* sensorInfo = camHwInfo->getSensorDrvDes(mCameraId); // get lens device path if (!sensorInfo || sensorInfo->mModuleLensDevName == "") { LOGW("%s: No lens found", __FUNCTION__); } else { struct stat sb; int PathExists = stat(sensorInfo->mModuleLensDevName.c_str(), &sb); if (PathExists != 0) { LOGE("Error, could not find lens subdev %s !", entityName.c_str()); } else { mDevPathsMap[KDevPathTypeLensNode] = sensorInfo->mModuleLensDevName; } } // get sensor device path camHwInfo->getSensorEntityName(mCameraId, entityName); if (entityName == "none") { LOGE("%s: No pixel_array found", __FUNCTION__); return UNKNOWN_ERROR; } else { status = mMediaCtl->getMediaEntity(mediaEntity, entityName.c_str()); if (mediaEntity == nullptr || status != NO_ERROR) { LOGE("Could not retrieve media entity %s", entityName.c_str()); return UNKNOWN_ERROR; } mediaEntity->getDevice((std::shared_ptr&) subdev); if (subdev.get()) { mDevPathsMap[KDevPathTypeSensorNode] = subdev->name(); mSensorSubdev = subdev; } } #if 0 // get flashlight device path if (!sensorInfo || sensorInfo->mModuleFlashDevName == "") { LOGW("%s: No flashlight found", __FUNCTION__); } else { struct stat sb; int PathExists = stat(sensorInfo->mModuleFlashDevName.c_str(), &sb); if (PathExists != 0) { LOGE("Error, could not find flashlight subdev %s !", entityName.c_str()); } else { mDevPathsMap[KDevPathTypeFlNode] = sensorInfo->mModuleFlashDevName; } } #endif std::vector links; mediaEntity->getLinkDesc(links); if (links.size()) { struct media_pad_desc* pad = &links[0].sink; struct media_entity_desc entityDesc; mMediaCtl->findMediaEntityById(pad->entity, entityDesc); string name = entityDesc.name; // check linked to cif or isp if (name.find("cif") != std::string::npos) return OK; } // get isp subdevice path entityName = "rkisp-isp-subdev"; status = mMediaCtl->getMediaEntity(mediaEntity, entityName.c_str()); if (mediaEntity == nullptr || status != NO_ERROR) { LOGE("Could not retrieve media entity %s", entityName.c_str()); return UNKNOWN_ERROR; } mediaEntity->getDevice((std::shared_ptr&) subdev); if (subdev.get()) mDevPathsMap[KDevPathTypeIspDevNode] = subdev->name(); // get isp input params device path entityName = "rkisp-input-params"; status = mMediaCtl->getMediaEntity(mediaEntity, entityName.c_str()); if (mediaEntity == nullptr || status != NO_ERROR) { LOGE("%s, Could not retrieve Media Entity %s", __FUNCTION__, entityName.c_str()); return UNKNOWN_ERROR; } mediaEntity->getDevice((std::shared_ptr&) subdev); if (subdev.get()) mDevPathsMap[KDevPathTypeIspInputParamsNode] = subdev->name(); // get isp stats device path entityName = "rkisp-statistics"; status = mMediaCtl->getMediaEntity(mediaEntity, entityName.c_str()); if (mediaEntity == nullptr || status != NO_ERROR) { LOGE("%s, Could not retrieve Media Entity %s", __FUNCTION__, entityName.c_str()); return UNKNOWN_ERROR; } mediaEntity->getDevice((std::shared_ptr&) subdev); if (subdev.get()) mDevPathsMap[KDevPathTypeIspStatsNode] = subdev->name(); return OK; } /** * initStaticMetadata * * Create CameraMetadata object to retrieve the static tags used in this class * we cache them as members so that we do not need to query CameraMetadata class * everytime we need them. This is more efficient since find() is not cheap */ status_t RKISP2ControlUnit::initStaticMetadata() { //Initialize the CameraMetadata object with the static metadata tags camera_metadata_t* plainStaticMeta; plainStaticMeta = (camera_metadata_t*)PlatformData::getStaticMetadata(mCameraId); if (plainStaticMeta == nullptr) { LOGE("Failed to get camera %d StaticMetadata", mCameraId); return UNKNOWN_ERROR; } CameraMetadata staticMeta(plainStaticMeta); camera_metadata_entry entry; entry = staticMeta.find(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE); if (entry.count == 1) { LOGI("camera %d minimum focus distance:%f", mCameraId, entry.data.f[0]); mLensSupported = (entry.data.f[0] > 0) ? true : false; LOGI("Lens movement %s for camera id %d", mLensSupported ? "supported" : "NOT supported", mCameraId); } entry = staticMeta.find(ANDROID_FLASH_INFO_AVAILABLE); if (entry.count == 1) { mFlashSupported = (entry.data.u8[0] > 0) ? true : false; LOGI("Flash %s for camera id %d", mFlashSupported ? "supported" : "NOT supported", mCameraId); } staticMeta.release(); const RKISP2CameraCapInfo *cap = getRKISP2CameraCapInfo(mCameraId); if (cap == nullptr) { LOGE("Failed to get cameraCapInfo"); return UNKNOWN_ERROR; } mSensorSettingsDelay = MAX(cap->mExposureLag, cap->mGainLag); mGainDelay = cap->mGainLag; return NO_ERROR; } status_t RKISP2ControlUnit::init() { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); status_t status = OK; const char *sensorName = nullptr; //Cache the static metadata values we are going to need in the capture unit if (initStaticMetadata() != NO_ERROR) { LOGE("Cannot initialize static metadata"); return NO_INIT; } mMessageThread = std::unique_ptr(new MessageThread(this, "CtrlUThread")); mMessageThread->run(); const RKISP2CameraCapInfo *cap = getRKISP2CameraCapInfo(mCameraId); if (!cap) { LOGE("Not enough information for getting NVM data"); return UNKNOWN_ERROR; } else { sensorName = cap->getSensorName(); } // In the case: CAMERA_DUMP_RAW + no rawPath, disable 3a. // because isp is bypassed in this case // Note: only isp support rawPath, hal report the raw capability, // so the case "raw stream + no rawPath" shouln't exists if (cap->sensorType() == SENSOR_TYPE_RAW && !(LogHelper::isDumpTypeEnable(CAMERA_DUMP_RAW) && !PlatformData::getCameraHWInfo()->isIspSupportRawPath())) { mCtrlLoop = new RKISP2CtrlLoop(mCameraId); if (mCtrlLoop->init(sensorName, this) != NO_ERROR) { LOGE("Error initializing 3A control"); return UNKNOWN_ERROR; } mImguUnit->setCtrlLoop(mCtrlLoop); } else { LOGW("No need 3A control, isSocSensor: %s, rawDump:%d", cap->sensorType() == SENSOR_TYPE_SOC ? "Yes" : "No", LogHelper::isDumpTypeEnable(CAMERA_DUMP_RAW)); //return UNKNOWN_ERROR; } mRKISP2SettingsProcessor = new RKISP2SettingsProcessor(mCameraId); mRKISP2SettingsProcessor->init(); mMetadata = new RKISP2Metadata(mCameraId); status = mMetadata->init(); if (CC_UNLIKELY(status != OK)) { LOGE("Error Initializing metadata"); return UNKNOWN_ERROR; } /* * init the pools of Request State structs and CaptureUnit settings * and Processing Unit Settings */ mRequestStatePool.init(MAX_REQUEST_IN_PROCESS_NUM, RKISP2RequestCtrlState::reset); mCaptureUnitSettingsPool.init(SETTINGS_POOL_SIZE + 2); mProcUnitSettingsPool.init(SETTINGS_POOL_SIZE, RKISP2ProcUnitSettings::reset); mSettingsHistory.clear(); /* Set digi gain support */ bool supportDigiGain = false; if (cap) supportDigiGain = cap->digiGainOnSensor(); getDevicesPath(); const CameraHWInfo* camHwInfo = PlatformData::getCameraHWInfo(); const struct SensorDriverDescriptor* sensorInfo = camHwInfo->getSensorDrvDes(mCameraId); if (sensorInfo->mFlashNum > 0 && mFlashSupported) { if (cap->sensorType() == SENSOR_TYPE_SOC) { mSocCamFlashCtrUnit = std::unique_ptr( new SocCamFlashCtrUnit( // TODO: support only one flash for SoC now sensorInfo->mModuleFlashDevName[0].c_str(), mCameraId)); LOGD("use mSocCamFlashCtrUnit"); } else if (cap->sensorType() == SENSOR_TYPE_RAW) { mRawCamFlashCtrUnit = std::unique_ptr( new RawCamFlashCtrUnit( sensorInfo->mModuleFlashDevName[0].c_str(), mCameraId)); LOGD("use mRawCamFlashCtrUnit"); } } return status; } /** * reset * * This method is called by the SharedPoolItem when the item is recycled * At this stage we can cleanup before recycling the struct. * In this case we reset the TracingSP of the capture unit settings and buffers * to remove this reference. Other references may be still alive. */ void RKISP2RequestCtrlState::reset(RKISP2RequestCtrlState* me) { if (CC_LIKELY(me != nullptr)) { me->captureSettings.reset(); me->processingSettings.reset(); me->graphConfig.reset(); } else { LOGE("Trying to reset a null CtrlState structure !! - BUG "); } } void RKISP2RequestCtrlState::init(Camera3Request *req, std::shared_ptr aGraphConfig) { request = req; graphConfig = aGraphConfig; if (CC_LIKELY(captureSettings)) { captureSettings->aeRegion.init(0); captureSettings->makernote.data = nullptr; captureSettings->makernote.size = 0; } else { LOGE(" Failed to init Ctrl State struct: no capture settings!! - BUG"); return; } if (CC_LIKELY(processingSettings.get() != nullptr)) { processingSettings->captureSettings = captureSettings; processingSettings->graphConfig = aGraphConfig; processingSettings->request = req; } else { LOGE(" Failed to init Ctrl State: no processing settings!! - BUG"); return; } ctrlUnitResult = request->getPartialResultBuffer(CONTROL_UNIT_PARTIAL_RESULT); shutterDone = false; intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; if (CC_UNLIKELY(ctrlUnitResult == nullptr)) { LOGE("no partial result buffer - BUG"); return; } mClMetaReceived = false; mShutterMetaReceived = false; mImgProcessDone = false; /** * Apparently we need to have this tags in the results */ const CameraMetadata* settings = request->getSettings(); if (CC_UNLIKELY(settings == nullptr)) { LOGE("no settings in request - BUG"); return; } int64_t id = request->getId(); camera_metadata_ro_entry entry; entry = settings->find(ANDROID_REQUEST_ID); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_REQUEST_ID, (int *)&id, entry.count); } ctrlUnitResult->update(ANDROID_SYNC_FRAME_NUMBER, &id, 1); entry = settings->find(ANDROID_CONTROL_CAPTURE_INTENT); if (entry.count == 1) { intent = entry.data.u8[0]; } uint8_t AePreTrigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE; entry = settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER); if (entry.count == 1) { AePreTrigger = entry.data.u8[0]; } uint8_t AeLock = ANDROID_CONTROL_AE_LOCK_OFF; entry = settings->find(ANDROID_CONTROL_AE_LOCK); if (entry.count == 1) { AeLock = entry.data.u8[0]; } LOGI("%s:%d: request id(%lld), ae_lock(%d) capture_intent(%d), ae_precapture_trigger(%d)", __FUNCTION__, __LINE__, id, AeLock, intent, AePreTrigger); ctrlUnitResult->update(ANDROID_CONTROL_CAPTURE_INTENT, entry.data.u8, entry.count); } RKISP2ControlUnit::~RKISP2ControlUnit() { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); mSettingsHistory.clear(); requestExitAndWait(); if (mMessageThread != nullptr) { mMessageThread.reset(); mMessageThread = nullptr; } if (mRKISP2SettingsProcessor) { delete mRKISP2SettingsProcessor; mRKISP2SettingsProcessor = nullptr; } if (mCtrlLoop) { mCtrlLoop->deinit(); delete mCtrlLoop; mCtrlLoop = nullptr; } delete mMetadata; mMetadata = nullptr; } status_t RKISP2ControlUnit::configStreams(std::vector &activeStreams, bool configChanged, bool isStillStream) { PERFORMANCE_ATRACE_NAME("RKISP2ControlUnit::configStreams"); HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); LOGI("@%s %d: configChanged :%d", __FUNCTION__, __LINE__, configChanged); status_t status = OK; if(configChanged) { // this will be necessary when configStream called twice without calling // destruct function which called in the close camera stack mLatestRequestId = -1; mStilCapPreCapreqId = -1; mWaitingForCapture.clear(); mSettingsHistory.clear(); mIsStillChangeStream = isStillStream; struct rkisp_cl_prepare_params_s prepareParams; memset(&prepareParams, 0, sizeof(struct rkisp_cl_prepare_params_s)); prepareParams.staticMeta = PlatformData::getStaticMetadata(mCameraId); if (prepareParams.staticMeta == nullptr) { LOGE("Failed to get camera %d StaticMetadata for CL", mCameraId); return UNKNOWN_ERROR; } //start 3a when config video stream done for (auto &it : mDevPathsMap) { switch (it.first) { case KDevPathTypeIspDevNode: prepareParams.isp_sd_node_path = it.second.c_str(); break; case KDevPathTypeIspStatsNode: prepareParams.isp_vd_stats_path = it.second.c_str(); break; case KDevPathTypeIspInputParamsNode: prepareParams.isp_vd_params_path = it.second.c_str(); break; case KDevPathTypeSensorNode: prepareParams.sensor_sd_node_path = it.second.c_str(); break; case KDevPathTypeLensNode: if (mLensSupported) prepareParams.lens_sd_node_path = it.second.c_str(); break; // deprecated case KDevPathTypeFlNode: if (mFlashSupported) prepareParams.flashlight_sd_node_path[0] = it.second.c_str(); break; default: continue; } } const CameraHWInfo* camHwInfo = PlatformData::getCameraHWInfo(); const struct SensorDriverDescriptor* sensorInfo = camHwInfo->getSensorDrvDes(mCameraId); if (mFlashSupported) { for (int i = 0; i < sensorInfo->mFlashNum; i++) { prepareParams.flashlight_sd_node_path[i] = sensorInfo->mModuleFlashDevName[i].c_str(); } } mEnable3A = true; for (auto it = activeStreams.begin(); it != activeStreams.end(); ++it) { prepareParams.width = (*it)->width; prepareParams.height = (*it)->height; LOGD("@%s : mEnable3A :%d, prepareParams.width*height(%dx%d).", __FUNCTION__, mEnable3A, prepareParams.width, prepareParams.height); if((*it)->format == HAL_PIXEL_FORMAT_RAW_OPAQUE && !PlatformData::getCameraHWInfo()->isIspSupportRawPath()) { mEnable3A = false; break; } } LOGD("@%s : mEnable3A :%d", __FUNCTION__, mEnable3A); const RKISP2CameraCapInfo *cap = getRKISP2CameraCapInfo(mCameraId); prepareParams.work_mode = cap->getAiqWorkingMode(); if (mCtrlLoop && mEnable3A ) { status = mCtrlLoop->start(prepareParams); if (CC_UNLIKELY(status != OK)) { LOGE("Failed to start 3a control loop!"); return status; } /* used for switch resolution take picture */ if (mStillCapSyncState && isStillStream && mRawCamFlashCtrUnit.get()) { int ret = mRawCamFlashCtrUnit->setStillChangeFlash(); if (ret < 0) LOGE_FLASH("%s:%d set Still change Flash failed.", __FUNCTION__, __LINE__); } } } return NO_ERROR; } status_t RKISP2ControlUnit::requestExitAndWait() { Message msg; msg.id = MESSAGE_ID_EXIT; status_t status = mMessageQueue.send(&msg, MESSAGE_ID_EXIT); status |= mMessageThread->requestExitAndWait(); return status; } status_t RKISP2ControlUnit::handleMessageExit() { mThreadRunning = false; return NO_ERROR; } /** * acquireRequestStateStruct * * acquire a free request control state structure. * Since this structure contains also a capture settings item that are also * stored in a pool we need to acquire one of those as well. * */ status_t RKISP2ControlUnit::acquireRequestStateStruct(std::shared_ptr& state) { status_t status = NO_ERROR; status = mRequestStatePool.acquireItem(state); if (status != NO_ERROR) { LOGE("Failed to acquire free request state struct - BUG"); /* * This should not happen since AAL is holding clients to send more * requests than we can take */ return UNKNOWN_ERROR; } status = mCaptureUnitSettingsPool.acquireItem(state->captureSettings); if (status != NO_ERROR) { LOGE("Failed to acquire free CapU settings struct - BUG"); /* * This should not happen since AAL is holding clients to send more * requests than we can take */ return UNKNOWN_ERROR; } // set a unique ID for the settings state->captureSettings->settingsIdentifier = systemTime(); status = mProcUnitSettingsPool.acquireItem(state->processingSettings); if (status != NO_ERROR) { LOGE("Failed to acquire free ProcU settings struct - BUG"); /* * This should not happen since AAL is holding clients to send more * requests than we can take */ return UNKNOWN_ERROR; } return OK; } /** * processRequest * * Acquire the control structure to keep the state of the request in the control * unit and send the message to be handled in the internal message thread. */ status_t RKISP2ControlUnit::processRequest(Camera3Request* request, std::shared_ptr graphConfig) { Message msg; status_t status = NO_ERROR; std::shared_ptr state; status = acquireRequestStateStruct(state); if (CC_UNLIKELY(status != OK) || CC_UNLIKELY(state.get() == nullptr)) { return status; // error log already done in the helper method } state->init(request, graphConfig); msg.id = MESSAGE_ID_NEW_REQUEST; msg.state = state; status = mMessageQueue.send(&msg); return status; } status_t RKISP2ControlUnit::handleNewRequest(Message &msg) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); status_t status = NO_ERROR; std::shared_ptr reqState = msg.state; /** * PHASE 1: Process the settings * In this phase we analyze the request's metadata settings and convert them * into either: * - input parameters for 3A algorithms * - parameters used for SoC sensors * - Capture Unit settings * - Processing Unit settings */ const CameraMetadata *reqSettings = reqState->request->getSettings(); if (reqSettings == nullptr) { LOGE("no settings in request - BUG"); return UNKNOWN_ERROR; } status = mRKISP2SettingsProcessor->processRequestSettings(*reqSettings, *reqState); if (status != NO_ERROR) { LOGE("Could not process all settings, reporting request as invalid"); } status = processRequestForCapture(reqState); if (CC_UNLIKELY(status != OK)) { LOGE("Failed to process req %d for capture [%d]", reqState->request->getId(), status); // TODO: handle error ! } return status; } status_t RKISP2ControlUnit::processSoCSettings(const CameraMetadata *settings) { uint8_t reqTemplate; camera_metadata_ro_entry entry; //# ANDROID_METADATA_Dynamic android.control.captureIntent copied entry = settings->find(ANDROID_CONTROL_CAPTURE_INTENT); if (entry.count == 1) { reqTemplate = entry.data.u8[0]; LOGD("%s:%d reqTemplate(%d)!\n ", __FUNCTION__, __LINE__, reqTemplate); } // fill target fps range, it needs to be proper in results anyway entry = settings->find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE); if (entry.count == 2) { int32_t minFps = entry.data.i32[0]; int32_t maxFps = entry.data.i32[1]; // set to driver LOGD("%s:%d enter: minFps= %d maxFps = %d!\n ", __FUNCTION__, __LINE__, minFps, maxFps); if(reqTemplate != ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT) { //case ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW: //case ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD: if (mSensorSubdev.get()) mSensorSubdev->setFramerate(0, maxFps); } } if (mSocCamFlashCtrUnit.get()) { int ret = mSocCamFlashCtrUnit->setFlashSettings(settings); if (ret < 0) LOGE("%s:%d set flash settings failed", __FUNCTION__, __LINE__); } return OK; } /** * processRequestForCapture * * Run 3A algorithms and send the results to capture unit for capture * * This is the second phase in the request processing flow. * * The request settings have been processed in the first phase * * If this step is successful the request will be moved to the * mWaitingForCapture waiting for the pixel buffers. */ status_t RKISP2ControlUnit::processRequestForCapture(std::shared_ptr &reqState) { status_t status = NO_ERROR; if (CC_UNLIKELY(reqState.get() == nullptr)) { LOGE("Invalid parameters passed- request not captured - BUG"); return BAD_VALUE; } reqState->request->dumpSetting(); if (CC_UNLIKELY(reqState->captureSettings.get() == nullptr)) { LOGE("capture Settings not given - BUG"); return BAD_VALUE; } /* Write the dump flag into capture settings, so that the PAL dump can be * done all the way down at PgParamAdaptor. For the time being, only dump * during jpeg captures. */ reqState->processingSettings->dump = LogHelper::isDumpTypeEnable(CAMERA_DUMP_RAW) && reqState->request->getBufferCountOfFormat(HAL_PIXEL_FORMAT_BLOB) > 0; // dump the PAL run from ISA also reqState->captureSettings->dump = reqState->processingSettings->dump; int reqId = reqState->request->getId(); /** * Move the request to the vector mWaitingForCapture */ mWaitingForCapture.insert(std::make_pair(reqId, reqState)); mLatestRequestId = reqId; int jpegBufCount = reqState->request->getBufferCountOfFormat(HAL_PIXEL_FORMAT_BLOB); int implDefinedBufCount = reqState->request->getBufferCountOfFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED); int yuv888BufCount = reqState->request->getBufferCountOfFormat(HAL_PIXEL_FORMAT_YCbCr_420_888); LOGD("@%s jpegs:%d impl defined:%d yuv888:%d inputbufs:%d req id %d", __FUNCTION__, jpegBufCount, implDefinedBufCount, yuv888BufCount, reqState->request->getNumberInputBufs(), reqState->request->getId()); if (jpegBufCount > 0) { // NOTE: Makernote should be get after isp_bxt_run() // NOTE: makernote.data deleted in JpegEncodeTask::handleMakernote() /* TODO */ /* const unsigned mknSize = MAKERNOTE_SECTION1_SIZE + MAKERNOTE_SECTION2_SIZE; */ /* MakernoteData mkn = {nullptr, mknSize}; */ /* mkn.data = new char[mknSize]; */ /* m3aWrapper->getMakerNote(ia_mkn_trg_section_2, mkn); */ /* reqState->captureSettings->makernote = mkn; */ } else { // No JPEG buffers in request. Reset MKN info, just in case. reqState->captureSettings->makernote.data = nullptr; reqState->captureSettings->makernote.size = 0; } // if this request is a reprocess request, no need to setFrameParam to CL. if (reqState->request->getNumberInputBufs() == 0) { if (mCtrlLoop && mEnable3A) { const CameraMetadata *settings = reqState->request->getSettings(); rkisp_cl_frame_metadata_s frame_metas; /* frame_metas.metas = settings->getAndLock(); */ /* frame_metas.id = reqId; */ CameraMetadata tempCamMeta = *settings; camera_metadata_ro_entry entry = settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER); if (entry.count == 1) { if (entry.data.u8[0] == ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START) { mStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP; LOGD_CAP("@%s reqId(%d) AE_PRECAPTURE_TRIGGER state(%d), mStillCapSyncState(%d)", __FUNCTION__, reqId, entry.data.u8[0], mStillCapSyncState); mStilCapPreCapreqId = reqId; if (mRawCamFlashCtrUnit.get()) mRawCamFlashCtrUnit->updateStillPreCapreqId(mStilCapPreCapreqId); } } entry = settings->find(ANDROID_CONTROL_AE_STATE); if (entry.count == 1) { LOGD_CAP("@%s reqId(%d) ANDROID_CONTROL_AE_STATE state(%d), mStillCapSyncState(%d)", __FUNCTION__, reqId, entry.data.u8[0], mStillCapSyncState); } if(jpegBufCount == 0) { uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW; tempCamMeta.update(ANDROID_CONTROL_CAPTURE_INTENT, &intent, 1); } else { LOGD_CAP("@%s(%d), reqId(%d) mStillCapSyncState(%d)", __FUNCTION__, __LINE__, reqId, mStillCapSyncState); if (mStillCapSyncNeeded) { if (mStillCapSyncState == STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE) { LOGD_CAP("forcely trigger ae precapture"); uint8_t precap = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START; tempCamMeta.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &precap, 1); mStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP; } if (mStillCapSyncState == STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP) { uint8_t syncCmd = RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD_SYNCSTART; tempCamMeta.update(RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD, &syncCmd, 1); mStillCapSyncState = STILL_CAP_SYNC_STATE_WAITING_ENGINE_DONE; LOGD_CAP("@%s(%d), reqId(%d), process still_cap_req set syncCmd to(%d), set mStillCapSyncState to(%d)", __FUNCTION__, __LINE__, reqId, syncCmd, mStillCapSyncState); } else LOGW_CAP("already in stillcap_sync state %d", mStillCapSyncState); } } // TuningServer *pserver = TuningServer::GetInstance(); // if (pserver && pserver->isTuningMode()) { // pserver->set_tuning_params(tempCamMeta); // } frame_metas.metas = tempCamMeta.getAndLock(); frame_metas.id = reqId; status = mCtrlLoop->setFrameParams(&frame_metas); if (status != OK) LOGE("CtrlLoop setFrameParams error"); /* status = settings->unlock(frame_metas.metas); */ status = tempCamMeta.unlock(frame_metas.metas); if (status != OK) { LOGE("unlock frame frame_metas failed"); return UNKNOWN_ERROR; } int max_counts = 500; while (mStillCapSyncState == STILL_CAP_SYNC_STATE_WAITING_ENGINE_DONE && max_counts > 0) { LOGD_CAP("waiting for stillcap_sync_done"); usleep(10*1000); max_counts--; } if (max_counts == 0) { mStillCapSyncState = STILL_CAP_SYNC_STATE_FROM_ENGINE_DONE; LOGD_CAP("waiting for stillcap_sync_done timeout!"); } /* if flash current is sof, now start flash */ if(jpegBufCount != 0 && (mStillCapSyncState == STILL_CAP_SYNC_STATE_FROM_ENGINE_DONE)) { while (!mIsStillChangeStream && !mSofSyncStae && max_counts > 0) { LOGD_CAP("waiting for SOF received!"); usleep(10*1000); max_counts--; } mStillCapSyncState = STILL_CAP_SYNC_STATE_WATING_JPEG_FRAME; LOGD_CAP("%s:%d set mStillCapSyncState to (%d).", __FUNCTION__, __LINE__, mStillCapSyncState); } if (!mIsStillChangeStream && mRawCamFlashCtrUnit.get()) { mRawCamFlashCtrUnit->updateStillCapSyncState(mStillCapSyncState); int ret = mRawCamFlashCtrUnit->setFlashSettings(settings); if (ret < 0) LOGE_FLASH("%s:%d set flash settings failed", __FUNCTION__, __LINE__); /*add delay = frameduration - exptime - FLASH_OFFSET, for start main Flash*/ if (mStillCapSyncState == STILL_CAP_SYNC_STATE_WATING_JPEG_FRAME && jpegBufCount) { nsecs_t delayns = mFrameTimens - mExposureTimens - FLASH_OFFSET * 1000 * 1000; LOGD_FLASH("%s:%d delayns(%lld)ns, mStillCapSyncState(%d).", __FUNCTION__, __LINE__, delayns, mStillCapSyncState); /* if current frame not support exp_t, flash two frame to guarantee exposure time */ if (delayns < 0) delayns = mFrameTimens * 1.1; usleep(delayns/1000); LOGD_FLASH("%s:%d delayns(%lld)ns, mStillCapSyncState(%d).", __FUNCTION__, __LINE__, delayns, mStillCapSyncState); } } LOGD_CAP("%s:%d, mStillCapSyncState %d", __FUNCTION__, __LINE__, mStillCapSyncState); } else { // set SoC sensor's params const CameraMetadata *settings = reqState->request->getSettings(); processSoCSettings(settings); } } else { LOGD("@%s %d: reprocess request:%d, no need setFrameParam", __FUNCTION__, __LINE__, reqId); reqState->mClMetaReceived = true; /* Result as reprocessing request: The HAL can expect that a reprocessing request is a copy */ /* of one of the output results with minor allowed setting changes. */ reqState->ctrlUnitResult->append(*reqState->request->getSettings()); } /*TODO, needn't this anymore ? zyc*/ status = completeProcessing(reqState); if (status != OK) LOGE("Cannot complete the buffer processing - fix the bug!"); return status; } status_t RKISP2ControlUnit::fillMetadata(std::shared_ptr &reqState) { /** * Apparently we need to have this tags in the results */ const CameraMetadata* settings = reqState->request->getSettings(); CameraMetadata* ctrlUnitResult = reqState->ctrlUnitResult; if (CC_UNLIKELY(settings == nullptr)) { LOGE("no settings in request - BUG"); return UNKNOWN_ERROR; } camera_metadata_ro_entry entry; entry = settings->find(ANDROID_CONTROL_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_CONTROL_MODE, entry.data.u8, entry.count); } //# ANDROID_METADATA_Dynamic android.control.videoStabilizationMode copied entry = settings->find(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, entry.data.u8, entry.count); } //# ANDROID_METADATA_Dynamic android.lens.opticalStabilizationMode copied entry = settings->find(ANDROID_LENS_OPTICAL_STABILIZATION_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_LENS_OPTICAL_STABILIZATION_MODE, entry.data.u8, entry.count); } //# ANDROID_METADATA_Dynamic android.control.effectMode done entry = settings->find(ANDROID_CONTROL_EFFECT_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_CONTROL_EFFECT_MODE, entry.data.u8, entry.count); } //# ANDROID_METADATA_Dynamic android.noiseReduction.mode done entry = settings->find(ANDROID_NOISE_REDUCTION_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_NOISE_REDUCTION_MODE, entry.data.u8, entry.count); } //# ANDROID_METADATA_Dynamic android.edge.mode done entry = settings->find(ANDROID_EDGE_MODE); if (entry.count == 1) { ctrlUnitResult->update(ANDROID_EDGE_MODE, entry.data.u8, entry.count); } /** * We don't have AF, so just update metadata now */ // return 0.0f for the fixed-focus if (!mLensSupported) { float focusDistance = 0.0f; reqState->ctrlUnitResult->update(ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1); // framework says it can't be off mode for zsl, // so we report EDOF for fixed focus // TODO: need to judge if the request is ZSL ? /* uint8_t afMode = ANDROID_CONTROL_AF_MODE_EDOF; */ uint8_t afMode = ANDROID_CONTROL_AF_MODE_OFF; ctrlUnitResult->update(ANDROID_CONTROL_AF_MODE, &afMode, 1); uint8_t afTrigger = ANDROID_CONTROL_AF_TRIGGER_IDLE; ctrlUnitResult->update(ANDROID_CONTROL_AF_TRIGGER, &afTrigger, 1); uint8_t afState = ANDROID_CONTROL_AF_STATE_INACTIVE; ctrlUnitResult->update(ANDROID_CONTROL_AF_STATE, &afState, 1); } bool flash_available = false; uint8_t flash_mode = ANDROID_FLASH_MODE_OFF; mRKISP2SettingsProcessor->getStaticMetadataCache().getFlashInfoAvailable(flash_available); if (!flash_available) { reqState->ctrlUnitResult->update(ANDROID_FLASH_MODE, &flash_mode, 1); uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE; //# ANDROID_METADATA_Dynamic android.flash.state done reqState->ctrlUnitResult->update(ANDROID_FLASH_STATE, &flashState, 1); } mMetadata->writeJpegMetadata(*reqState); uint8_t pipelineDepth; mRKISP2SettingsProcessor->getStaticMetadataCache().getPipelineDepth(pipelineDepth); //# ANDROID_METADATA_Dynamic android.request.pipelineDepth done reqState->ctrlUnitResult->update(ANDROID_REQUEST_PIPELINE_DEPTH, &pipelineDepth, 1); // for soc camera if (!mCtrlLoop || !mEnable3A) { uint8_t awbMode = ANDROID_CONTROL_AWB_MODE_AUTO; ctrlUnitResult->update(ANDROID_CONTROL_AWB_MODE, &awbMode, 1); uint8_t awbState = ANDROID_CONTROL_AWB_STATE_CONVERGED; ctrlUnitResult->update(ANDROID_CONTROL_AWB_STATE, &awbState, 1); if (mSocCamFlashCtrUnit.get()) { mSocCamFlashCtrUnit->updateFlashResult(ctrlUnitResult); } else { uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON; ctrlUnitResult->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1); uint8_t aeState = ANDROID_CONTROL_AE_STATE_CONVERGED; ctrlUnitResult->update(ANDROID_CONTROL_AE_STATE, &aeState, 1); } reqState->mClMetaReceived = true; } else { if (mRawCamFlashCtrUnit.get()) { mRawCamFlashCtrUnit->updateFlashResult(ctrlUnitResult); } } return OK; } status_t RKISP2ControlUnit::handleNewRequestDone(Message &msg) { status_t status = OK; std::shared_ptr reqState = nullptr; int reqId = msg.requestId; std::map>::iterator it = mWaitingForCapture.find(reqId); if (it == mWaitingForCapture.end()) { LOGE("Unexpected request done event received for request %d - Fix the bug", reqId); return UNKNOWN_ERROR; } reqState = it->second; if (CC_UNLIKELY(reqState.get() == nullptr || reqState->request == nullptr)) { LOGE("No valid state or settings for request Id = %d" "- Fix the bug!", reqId); return UNKNOWN_ERROR; } reqState->mImgProcessDone = true; Camera3Request* request = reqState->request; // when deviceError, should not wait for meta and metadataDone an error index if ((!reqState->mClMetaReceived) && !request->getError()) return OK; request->mCallback->metadataDone(request, request->getError() ? -1 : CONTROL_UNIT_PARTIAL_RESULT); /* * Remove the request from Q once we have received all pixel data buffers * we expect from ISA. Query the graph config for that. */ mWaitingForCapture.erase(reqId); return status; } /** * completeProcessing * * Forward the pixel buffer to the Processing Unit to complete the processing. * If all the buffers from Capture Unit have arrived then: * - it updates the metadata * - it removes the request from the vector mWaitingForCapture. * * The metadata update is now transferred to the ProcessingUnit. * This is done only on arrival of the last pixel data buffer. RKISP2ControlUnit still * keeps the state, so it is responsible for triggering the update. */ status_t RKISP2ControlUnit::completeProcessing(std::shared_ptr &reqState) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); int reqId = reqState->request->getId(); if (CC_LIKELY((reqState->request != nullptr) && (reqState->captureSettings.get() != nullptr))) { /* TODO: cleanup * This struct copy from state is only needed for JPEG creation. * Ideally we should directly write inside members of processingSettings * whatever settings are needed for Processing Unit. * This should be moved to any of the processXXXSettings. */ fillMetadata(reqState); mImguUnit->completeRequest(reqState->processingSettings, true); } else { LOGE("request or captureSetting is nullptr - Fix the bug!"); return UNKNOWN_ERROR; } return NO_ERROR; } status_t RKISP2ControlUnit::handleNewShutter(Message &msg) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); std::shared_ptr reqState = nullptr; int reqId = msg.data.shutter.requestId; //check whether this reqId has been shutter done if (reqId <= mShutterDoneReqId) return OK; std::map>::iterator it = mWaitingForCapture.find(reqId); if (it == mWaitingForCapture.end()) { LOGE("Unexpected shutter event received for request %d - Fix the bug", reqId); return UNKNOWN_ERROR; } reqState = it->second; if (CC_UNLIKELY(reqState.get() == nullptr || reqState->captureSettings.get() == nullptr)) { LOGE("No valid state or settings for request Id = %d" "- Fix the bug!", reqId); return UNKNOWN_ERROR; } const CameraMetadata* metaData = reqState->request->getSettings(); if (metaData == nullptr) { LOGE("Metadata should not be nullptr. Fix the bug!"); return UNKNOWN_ERROR; } int jpegBufCount = reqState->request->getBufferCountOfFormat(HAL_PIXEL_FORMAT_BLOB); if (jpegBufCount && (mStillCapSyncState == STILL_CAP_SYNC_STATE_WATING_JPEG_FRAME)) { mStillCapSyncState = STILL_CAP_SYNC_STATE_JPEG_FRAME_DONE; mSofSyncStae = false; status_t status = OK; const CameraMetadata *settings = reqState->request->getSettings(); rkisp_cl_frame_metadata_s frame_metas; CameraMetadata tempCamMeta = *settings; uint8_t stillCapSyncEnd = RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD_SYNCEND; tempCamMeta.update(RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD, &stillCapSyncEnd, 1); mStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE; frame_metas.metas = tempCamMeta.getAndLock(); frame_metas.id = -1; status = mCtrlLoop->setFrameParams(&frame_metas); if (status != OK) LOGE_CAP("CtrlLoop setFrameParams error"); /* status = settings->unlock(frame_metas.metas); */ status = tempCamMeta.unlock(frame_metas.metas); if (status != OK) { LOGE_CAP("unlock frame frame_metas failed"); return UNKNOWN_ERROR; } LOGD_CAP("%s:%d, reqId: %d, stillcap_sync_state %d", __FUNCTION__, __LINE__, reqId, mStillCapSyncState); } int64_t ts = msg.data.shutter.tv_sec * 1000000000; // seconds to nanoseconds ts += msg.data.shutter.tv_usec * 1000; // microseconds to nanoseconds //# ANDROID_METADATA_Dynamic android.sensor.timestamp done reqState->ctrlUnitResult->update(ANDROID_SENSOR_TIMESTAMP, &ts, 1); reqState->mShutterMetaReceived = true; if(reqState->mClMetaReceived) { mMetadata->writeRestMetadata(*reqState); reqState->request->notifyFinalmetaFilled(); } reqState->request->mCallback->shutterDone(reqState->request, ts); reqState->shutterDone = true; reqState->captureSettings->timestamp = ts; mShutterDoneReqId = reqId; if (jpegBufCount) LOGD_CAP("%s:%d, reqId: %d, tv_ns(%lld), buf_sequence(%d) done!", __FUNCTION__, __LINE__, reqId, ts, msg.data.shutter.sof_syncId); return NO_ERROR; } status_t RKISP2ControlUnit::flush(int configChanged) { PERFORMANCE_ATRACE_NAME("RKISP2ControlUnit::flush"); HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); Message msg; msg.id = MESSAGE_ID_FLUSH; msg.configChanged = configChanged; mMessageQueue.remove(MESSAGE_ID_NEW_REQUEST); mMessageQueue.remove(MESSAGE_ID_NEW_SHUTTER); mMessageQueue.remove(MESSAGE_ID_NEW_REQUEST_DONE); return mMessageQueue.send(&msg, MESSAGE_ID_FLUSH); } status_t RKISP2ControlUnit::handleMessageFlush(Message &msg) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); status_t status = NO_ERROR; if (CC_UNLIKELY(status != OK)) { LOGE("Failed to stop 3a control loop!"); } mFlushForUseCase = msg.configChanged; if(msg.configChanged && mCtrlLoop && mEnable3A) { if (0/*mStillCapSyncNeeded && mStillCapSyncState != STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP && mFlushForUseCase == FLUSH_FOR_STILLCAP*/) { rkisp_cl_frame_metadata_s frame_metas; // force precap uint8_t precap = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START; mLatestCamMeta.update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, &precap, 1); frame_metas.metas = mLatestCamMeta.getAndLock(); frame_metas.id = -1; status = mCtrlLoop->setFrameParams(&frame_metas); if (status != OK) LOGE("CtrlLoop setFrameParams error"); status = mLatestCamMeta.unlock(frame_metas.metas); if (status != OK) { LOGE("unlock frame frame_metas failed"); return UNKNOWN_ERROR; } mStillCapSyncState = STILL_CAP_SYNC_STATE_FORCE_TO_ENGINE_PRECAP; // wait precap 3A done while (mStillCapSyncState != STILL_CAP_SYNC_STATE_FORCE_PRECAP_DONE) { LOGD("%d:wait forceprecap done...", __LINE__); usleep(10*1000); } mStillCapSyncState = STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP; } /* used for switch resolution take picture */ if (mIsStillChangeStream && mRawCamFlashCtrUnit.get()) { int ret = mRawCamFlashCtrUnit->setV4lFlashMode(CAM_AE_FLASH_MODE_OFF, 0, 0, 0); if (ret < 0) LOGE("%s:%d set flash settings failed", __FUNCTION__, __LINE__); } } mImguUnit->flush(); mWaitingForCapture.clear(); mSettingsHistory.clear(); return NO_ERROR; } void RKISP2ControlUnit::messageThreadLoop() { LOGD("@%s - Start", __FUNCTION__); mThreadRunning = true; while (mThreadRunning) { status_t status = NO_ERROR; PERFORMANCE_ATRACE_BEGIN("CtlU-PollMsg"); Message msg; mMessageQueue.receive(&msg); PERFORMANCE_ATRACE_END(); PERFORMANCE_ATRACE_NAME_SNPRINTF("CtlU-%s", ENUM2STR(CtlUMsg_stringEnum, msg.id)); PERFORMANCE_HAL_ATRACE_PARAM1("msg", msg.id); LOGD("@%s, receive message id:%d", __FUNCTION__, msg.id); switch (msg.id) { case MESSAGE_ID_EXIT: status = handleMessageExit(); break; case MESSAGE_ID_NEW_REQUEST: status = handleNewRequest(msg); break; case MESSAGE_ID_NEW_SHUTTER: status = handleNewShutter(msg); break; case MESSAGE_ID_NEW_REQUEST_DONE: status = handleNewRequestDone(msg); break; case MESSAGE_ID_METADATA_RECEIVED: status = handleMetadataReceived(msg); break; case MESSAGE_ID_FLUSH: status = handleMessageFlush(msg); break; default: LOGE("ERROR Unknown message %d", msg.id); status = BAD_VALUE; break; } if (status != NO_ERROR) LOGE("error %d in handling message: %d", status, static_cast(msg.id)); LOGD("@%s, finish message id:%d", __FUNCTION__, msg.id); mMessageQueue.reply(msg.id, status); PERFORMANCE_ATRACE_END(); } LOGD("%s: Exit", __FUNCTION__); } bool RKISP2ControlUnit::notifyCaptureEvent(CaptureMessage *captureMsg) { HAL_TRACE_CALL(CAM_GLBL_DBG_HIGH); if (captureMsg == nullptr) { return false; } if (captureMsg->id == CAPTURE_MESSAGE_ID_ERROR) { // handle capture error return true; } Message msg; switch (captureMsg->data.event.type) { case CAPTURE_EVENT_SHUTTER: msg.id = MESSAGE_ID_NEW_SHUTTER; msg.data.shutter.requestId = captureMsg->data.event.reqId; msg.data.shutter.tv_sec = captureMsg->data.event.timestamp.tv_sec; msg.data.shutter.tv_usec = captureMsg->data.event.timestamp.tv_usec; msg.data.shutter.sof_syncId = captureMsg->data.event.sequence; mMessageQueue.send(&msg, MESSAGE_ID_NEW_SHUTTER); break; case CAPTURE_EVENT_NEW_SOF: mSofSequence = captureMsg->data.event.sequence; LOGD("sof event sequence = %u", mSofSequence); break; case CAPTURE_REQUEST_DONE: msg.id = MESSAGE_ID_NEW_REQUEST_DONE; msg.requestId = captureMsg->data.event.reqId; mMessageQueue.send(&msg, MESSAGE_ID_NEW_REQUEST_DONE); break; default: LOGW("Unsupported Capture event "); break; } return true; } nsecs_t RKISP2ControlUnit::getFrameDuration(int id) { double fps = 0; nsecs_t now = systemTime(); nsecs_t diff = now - mLastFpsTime; LOGD("%s:%d, reqId(%d) FrameDuration: %" PRId64 "ns", __FUNCTION__, __LINE__, id, diff); mLastFpsTime = now; return diff; } status_t RKISP2ControlUnit::metadataReceived(int id, const camera_metadata_t *metas, int sof_frameId) { Message msg; status_t status = NO_ERROR; camera_metadata_entry entry; static std::map sLastAeStateMap; /* id = -2, just for sync sof for flash control */ if (-2 == id) { mFrameTimens = getFrameDuration(id); if (mStillCapSyncState == STILL_CAP_SYNC_STATE_FROM_ENGINE_DONE) { mSofSyncStae = true; mSofSyncId = sof_frameId; LOGD_FLASH("%s:%d get flash_sof_sync, sof_frameId(%d) !.", __FUNCTION__, __LINE__, mSofSyncId); } if (sof_frameId <= 5) { ALOGD("@%s get sof_frameId(%d) from aiq!", __FUNCTION__, sof_frameId); } #if 0 /* used for switch resolution take picture, reduce flash time */ if (mIsStillChangeStream && mRawCamFlashCtrUnit.get() && sof_frameId == 1) { LOGD_FLASH("@%s: sof_frameId(%d), capture done, set flash off!.", __FUNCTION__, sof_frameId); int ret = mRawCamFlashCtrUnit->setV4lFlashMode(CAM_AE_FLASH_MODE_OFF, 0, 0, 0); if (ret < 0) LOGE_FLASH("%s:%d set flash settings failed", __FUNCTION__, __LINE__); } #endif return status; } CameraMetadata result(const_cast(metas)); entry = result.find(RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_NEEDED); if (entry.count == 1) { mStillCapSyncNeeded = !!entry.data.u8[0]; LOGD_CAP("%s:%d, mStillCapSyncNeeded %d", __FUNCTION__, __LINE__, mStillCapSyncNeeded); } entry = result.find(RK_MEANLUMA_VALUE); if (entry.count == 1) { LOGD_FLASH("metadataReceived meanluma:%f", entry.data.f[0]); if (mRawCamFlashCtrUnit.get()) { if (mStillCapSyncState == STILL_CAP_SYNC_STATE_TO_ENGINE_IDLE) mRawCamFlashCtrUnit->setMeanLuma(entry.data.f[0], id); } } entry = result.find(RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD); if (entry.count == 1) { LOGD_FLASH("metadataReceived RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD:%d, mStillCapSyncState(%d), mFlushForUseCase(%d)", entry.data.u8[0], mStillCapSyncState, mFlushForUseCase); if (entry.data.u8[0] == RKCAMERA3_PRIVATEDATA_STILLCAP_SYNC_CMD_SYNCDONE && (mStillCapSyncState == STILL_CAP_SYNC_STATE_WAITING_ENGINE_DONE || mFlushForUseCase == FLUSH_FOR_STILLCAP)) { if(id >= 0) { mStillCapSyncState = STILL_CAP_SYNC_STATE_FROM_ENGINE_DONE; LOGD_CAP("%s:%d, reqid(%d) set mStillCapSyncState to %d", __FUNCTION__, __LINE__, id, mStillCapSyncState); } } } entry = result.find(ANDROID_CONTROL_AE_STATE); if (entry.count == 1) { LOGD_FLASH("reqid(%d) metadataReceived ANDROID_CONTROL_AE_STATE:%d", id, entry.data.u8[0]); if (entry.data.u8[0] == ANDROID_CONTROL_AE_STATE_CONVERGED && mStillCapSyncState == STILL_CAP_SYNC_STATE_TO_ENGINE_PRECAP) { LOGD_FLASH("%s:%d, mStillCapSyncState %d", __FUNCTION__, __LINE__, mStillCapSyncState); //get ae coveraged sensor.exposureTime entry = result.find(ANDROID_SENSOR_EXPOSURE_TIME); if (entry.count == 1) { mExposureTimens = entry.data.i64[0]; LOGD_FLASH("%s:%d, reqid(%d) exposure_time %" PRId64 "ns", __FUNCTION__, __LINE__, id, mExposureTimens); } } else { LOGD_FLASH("reqid(%d) metadataReceived ANDROID_CONTROL_AE_STATE:%d, mStillCapSyncState(%d)", id, entry.data.u8[0], mStillCapSyncState); } } result.release(); if (id != -1) { msg.id = MESSAGE_ID_METADATA_RECEIVED; msg.requestId = id; msg.metas = metas; status = mMessageQueue.send(&msg); } return status; } status_t RKISP2ControlUnit::handleMetadataReceived(Message &msg) { status_t status = OK; std::shared_ptr reqState = nullptr; int reqId = msg.requestId; std::map>::iterator it = mWaitingForCapture.find(reqId); if(reqId == -1) return OK; if (it == mWaitingForCapture.end()) { LOGE("Unexpected request done event received for request %d - Fix the bug", reqId); return UNKNOWN_ERROR; } reqState = it->second; if (CC_UNLIKELY(reqState.get() == nullptr || reqState->request == nullptr)) { LOGE("No valid state or request for request Id = %d" "- Fix the bug!", reqId); return UNKNOWN_ERROR; } mLatestCamMeta = msg.metas; //Metadata reuslt are mainly divided into three parts //1. some settings from app //2. 3A metas from Control loop //3. some items like sensor timestamp from shutter reqState->ctrlUnitResult->append(msg.metas); reqState->mClMetaReceived = true; if(reqState->mShutterMetaReceived) { mMetadata->writeRestMetadata(*reqState); reqState->request->notifyFinalmetaFilled(); } if (!reqState->mImgProcessDone) return OK; Camera3Request* request = reqState->request; request->mCallback->metadataDone(request, request->getError() ? -1 : CONTROL_UNIT_PARTIAL_RESULT); mWaitingForCapture.erase(reqId); return status; } /** * Static callback forwarding methods from CL to instance */ void RKISP2ControlUnit::sMetadatCb(const struct cl_result_callback_ops* ops, struct rkisp_cl_frame_metadata_s *result) { LOGI("@%s %d: frame %d result meta received", __FUNCTION__, __LINE__, result->id); // TuningServer *pserver = TuningServer::GetInstance(); RKISP2ControlUnit *ctl = const_cast(static_cast(ops)); ctl->metadataReceived(result->id, result->metas, result->sof_frameId); // if(pserver && pserver->isTuningMode()){ // CameraMetadata uvcCamMeta(const_cast(result->metas)); // pserver->get_tuning_params(uvcCamMeta); // uvcCamMeta.release(); // } } } // namespace rkisp2 } // namespace camera2 } // namespace android