| /* |
| * Copyright (C) 2015-2020 Intel Corporation. |
| * |
| * 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 "IspParamAdaptor" |
| |
| #include "IspParamAdaptor.h" |
| |
| #include <stdio.h> |
| #include <utility> |
| |
| #include "3a/AiqResult.h" |
| #include "3a/AiqResultStorage.h" |
| #include "iutils/Utils.h" |
| #include "iutils/CameraLog.h" |
| #include "iutils/CameraDump.h" |
| #include "iutils/Errors.h" |
| #include "PlatformData.h" |
| #include "IGraphConfig.h" |
| |
| #include "ia_pal_types_isp_ids_autogen.h" |
| #include "ia_pal_types_isp.h" |
| |
| namespace icamera { |
| |
| IspParamAdaptor::IspParamAdaptor(int cameraId, PgParamType type) : |
| mIspAdaptorState(ISP_ADAPTOR_NOT_INIT), |
| mCameraId(cameraId), |
| mPgParamType(type), |
| mTuningMode(TUNING_MODE_VIDEO), |
| mIspAdaptHandle(nullptr), |
| mBCompResults(nullptr), |
| mGCM(nullptr), |
| mAdaptor(nullptr) |
| { |
| LOG1("IspParamAdaptor was created for id:%d type:%d", mCameraId, mPgParamType); |
| CLEAR(mFrameParam); |
| CLEAR(mLastPalDataForVideoPipe); |
| |
| if (PlatformData::getGraphConfigNodes(cameraId)) { |
| mGCM = IGraphConfigManager::getInstance(cameraId); |
| } |
| |
| mAdaptor = std::unique_ptr<IntelIspParamAdaptor>(new IntelIspParamAdaptor()); |
| |
| PalRecord palRecordArray[] = { |
| { ia_pal_uuid_isp_call_info, -1 }, |
| { ia_pal_uuid_isp_bnlm_3_2, -1 }, |
| { ia_pal_uuid_isp_lsc_1_1, -1 } |
| }; |
| for (uint32_t i = 0; i < sizeof(palRecordArray) / sizeof(PalRecord); i++) { |
| mPalRecords.push_back(palRecordArray[i]); |
| } |
| } |
| |
| IspParamAdaptor::~IspParamAdaptor() |
| { |
| LOG1("IspParamAdaptor was created for id:%d type:%d", mCameraId, mPgParamType); |
| } |
| |
| int IspParamAdaptor::init() |
| { |
| PERF_CAMERA_ATRACE(); |
| HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1); |
| AutoMutex l(mIspAdaptorLock); |
| |
| mIspAdaptorState = ISP_ADAPTOR_INIT; |
| return OK; |
| } |
| |
| int IspParamAdaptor::deinit() |
| { |
| LOG1("ISP HW param adaptor de-initialized for camera id:%d type:%d", mCameraId, mPgParamType); |
| AutoMutex l(mIspAdaptorLock); |
| |
| deinitIspAdaptHandle(); |
| |
| { |
| AutoMutex l(mIpuParamLock); |
| |
| // Release the memory and clear the mapping |
| for (auto& pgMap: mStreamIdToProgramGroupMap) { |
| delete[] pgMap.second.run_kernels; |
| } |
| mStreamIdToProgramGroupMap.clear(); |
| mStreamIdToPGOutSizeMap.clear(); |
| releaseIspParamBuffers(); |
| } |
| |
| CLEAR(mFrameParam); |
| CLEAR(mLastPalDataForVideoPipe); |
| for (uint32_t i = 0; i < mPalRecords.size(); i++) { |
| mPalRecords[i].offset = -1; |
| } |
| |
| mIspAdaptorState = ISP_ADAPTOR_NOT_INIT; |
| return OK; |
| } |
| |
| int IspParamAdaptor::initIspAdaptHandle(ConfigMode configMode, TuningMode tuningMode) |
| { |
| int ret = OK; |
| |
| if (!PlatformData::isEnableAIQ(mCameraId)) { |
| return ret; |
| } |
| |
| ia_binary_data ispData; |
| ia_cmc_t *cmcData = nullptr; |
| uintptr_t cmcHandle = reinterpret_cast<uintptr_t>(nullptr); |
| |
| ret = PlatformData::getCpfAndCmc(mCameraId, &ispData, nullptr, nullptr, |
| &cmcHandle, tuningMode, &cmcData); |
| CheckError(ret != OK, NO_INIT, "get cpf and cmc data failed"); |
| |
| int statsNum = PlatformData::getExposureNum(mCameraId, |
| CameraUtils::isMultiExposureCase(tuningMode)); |
| mIspAdaptHandle = mAdaptor->init(&ispData, reinterpret_cast<ia_cmc_t*>(cmcHandle), |
| MAX_STATISTICS_WIDTH, MAX_STATISTICS_HEIGHT, |
| statsNum, nullptr); |
| CheckError(!mIspAdaptHandle, NO_INIT, "ISP adaptor failed to initialize"); |
| |
| /* |
| * The number of streamId is identified in configure stream, |
| * fill the mStreamIdToProgramGroupMap and allocate the IspParameter memory |
| */ |
| if (mGCM != nullptr && mGCM->isGcConfigured()) { |
| AutoMutex l(mIpuParamLock); |
| |
| ret = initProgramGroupForAllStreams(configMode); |
| CheckError(ret != OK, ret, "%s, Failed to init programGroup for all streams", __func__); |
| ret = allocateIspParamBuffers(); |
| CheckError(ret != OK, ret, "%s, Failed to allocate isp parameter buffers", __func__); |
| } |
| |
| LOG1("ISP HW param adaptor initialized successfully camera id:%d", mCameraId); |
| |
| return ret; |
| } |
| |
| void IspParamAdaptor::deinitIspAdaptHandle() |
| { |
| if (mIspAdaptHandle) { |
| mAdaptor->deInit(mIspAdaptHandle); |
| mIspAdaptHandle = nullptr; |
| } |
| |
| } |
| |
| int IspParamAdaptor::initProgramGroupForAllStreams(ConfigMode configMode) |
| { |
| HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1); |
| |
| std::vector<int32_t> streamIds; |
| |
| //Release the memory and clear the mapping |
| for (auto& pgMap: mStreamIdToProgramGroupMap) { |
| delete[] pgMap.second.run_kernels; |
| } |
| mStreamIdToProgramGroupMap.clear(); |
| mStreamIdToPGOutSizeMap.clear(); |
| mStreamIdToMbrDataMap.clear(); |
| |
| std::shared_ptr<IGraphConfig> graphConfig = mGCM->getGraphConfig(configMode); |
| if(graphConfig == nullptr) { |
| LOGW("There isn't GraphConfig for camera configMode: %d", configMode); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (mPgParamType == PG_PARAM_ISYS) { |
| int streamId = 0; // 0 is for PG_PARAM_ISYS |
| streamIds.push_back(streamId); |
| } else { |
| status_t ret = graphConfig->graphGetStreamIds(streamIds); |
| CheckError(ret != OK, UNKNOWN_ERROR, "Failed to get the PG streamIds"); |
| } |
| |
| for (auto id : streamIds) { |
| ia_isp_bxt_program_group *pgPtr = graphConfig->getProgramGroup(id); |
| if (pgPtr != nullptr) { |
| ia_isp_bxt_program_group programGroup; |
| CLEAR(programGroup); |
| programGroup.run_kernels = new ia_isp_bxt_run_kernels_t[pgPtr->kernel_count]; |
| |
| // Skip those kernels with 0 uuid which isn't PAL uuid |
| for (unsigned int i = 0; i < pgPtr->kernel_count; i++) { |
| if (pgPtr->run_kernels[i].kernel_uuid != 0) { |
| MEMCPY_S(&programGroup.run_kernels[programGroup.kernel_count], |
| sizeof(ia_isp_bxt_run_kernels_t), |
| &pgPtr->run_kernels[i], |
| sizeof(ia_isp_bxt_run_kernels_t)); |
| programGroup.kernel_count++; |
| } else { |
| LOG1("There is 0 uuid found, stream id %d", id); |
| } |
| } |
| |
| // Override the stream id in kernel list with the one in sensor's config file. |
| // Remove this after the sensor's tuning file uses correct stream id. |
| int streamId = PlatformData::getStreamIdByConfigMode(mCameraId, configMode); |
| if (streamId != -1) { |
| programGroup.run_kernels->stream_id = streamId; |
| } |
| |
| mStreamIdToProgramGroupMap[id] = programGroup; |
| mStreamIdToPGOutSizeMap[id] = mAdaptor->getPalDataSize(&programGroup); |
| ia_isp_bxt_gdc_limits mbrData; |
| status_t ret = graphConfig->getMBRData(id, &mbrData); |
| if (ret == OK) { |
| mStreamIdToMbrDataMap[id] = mbrData; |
| LOG2("get mbr data for stream:%d:%f,%f,%f,%f", |
| id, mbrData.rectilinear.zoom, mbrData.rectilinear.pitch, |
| mbrData.rectilinear.yaw, mbrData.rectilinear.roll); |
| } |
| } |
| } |
| |
| return OK; |
| } |
| |
| void IspParamAdaptor::initInputParams(ia_isp_bxt_input_params_v2 *params, PgParamType type) |
| { |
| CheckError(params == nullptr, VOID_VALUE, "NULL input parameter"); |
| |
| if (type == PG_PARAM_PSYS_ISA) { |
| params->ee_setting.feature_level = ia_isp_feature_level_low; |
| params->ee_setting.strength = 0; |
| LOG2("%s: set initial default edge enhancement setting: level: %d, strengh: %d", |
| __func__, params->ee_setting.feature_level, params->ee_setting.strength); |
| |
| params->nr_setting.feature_level = ia_isp_feature_level_high; |
| params->nr_setting.strength = 0; |
| LOG2("%s: set initial default noise setting: level: %d, strengh: %d", |
| __func__, params->nr_setting.feature_level, params->nr_setting.strength); |
| } |
| } |
| |
| int IspParamAdaptor::postConfigure(int width, int height, ia_binary_data *binaryData) |
| { |
| // The PG wrapper init is done by the imaging controller. |
| if(mPgParamType == PG_PARAM_PSYS_ISA) { |
| mIspAdaptorState = ISP_ADAPTOR_CONFIGURED; |
| return OK; //No need to do anything for P2P. It id done by libiacss |
| } |
| |
| return OK; |
| } |
| |
| /** |
| * configure |
| * |
| * (graph config version) |
| * This is the method used when the spatial parameters change, usually during |
| * stream configuration. |
| * |
| * We initialize the ISP adaptor to produce worst case scenario for memory |
| * allocation. |
| * |
| * At this state we initialize the wrapper code that helps encoding the PG |
| * descriptor and terminal payloads (i.e. the parameters for the PG). |
| * |
| * \param configMode[IN]: The real configure mode. |
| * \param tuningMode[IN]: The tuning mode. |
| * \param stream[IN]: frame info. |
| * \return OK: everything went ok. |
| * \return UNKNOWN_ERROR: First run of ISP adaptation failed. |
| * \return NO_INIT: Initialization of P2P or PG_DIE wrapper failed. |
| */ |
| int IspParamAdaptor::configure(const stream_t &stream, |
| ConfigMode configMode, TuningMode tuningMode) |
| { |
| HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL1); |
| AutoMutex l(mIspAdaptorLock); |
| |
| mTuningMode = tuningMode; |
| CLEAR(mLastPalDataForVideoPipe); |
| for (uint32_t i = 0; i < mPalRecords.size(); i++) { |
| mPalRecords[i].offset = -1; |
| } |
| |
| ia_isp_bxt_input_params_v2 inputParams; |
| CLEAR(inputParams); |
| ia_aiq_sa_results_v1 fakeSaResults; |
| CLEAR(fakeSaResults); |
| |
| deinitIspAdaptHandle(); |
| int ret = initIspAdaptHandle(configMode, tuningMode); |
| CheckError(ret != OK, ret, "%s, init Isp Adapt Handle failed %d", __func__, ret); |
| |
| SensorFrameParams param; |
| int status = PlatformData::calculateFrameParams(mCameraId, param); |
| CheckError(status != OK, status, "%s: Failed to calculate frame params", __func__); |
| AiqUtils::convertToAiqFrameParam(param, mFrameParam); |
| |
| LOG1("horizontal_crop_offset:%d", mFrameParam.horizontal_crop_offset); |
| LOG1("vertical_crop_offset:%d", mFrameParam.vertical_crop_offset); |
| LOG1("cropped_image_width:%d", mFrameParam.cropped_image_width); |
| LOG1("cropped_image_height:%d", mFrameParam.cropped_image_height); |
| LOG1("horizontal_scaling_numerator:%d", mFrameParam.horizontal_scaling_numerator); |
| LOG1("horizontal_scaling_denominator:%d", mFrameParam.horizontal_scaling_denominator); |
| LOG1("vertical_scaling_numerator:%d", mFrameParam.vertical_scaling_numerator); |
| LOG1("vertical_scaling_denominator:%d", mFrameParam.vertical_scaling_denominator); |
| |
| /* |
| * Construct the dummy Shading Adaptor results to force the creation of |
| * the LSC table. |
| * Assign them to the AIC input parameter structure. |
| */ |
| unsigned short fakeLscTable[4] = {1,1,1,1}; |
| for (int i = 0; i < MAX_BAYER_ORDER_NUM; i++) { |
| for (int j = 0; j < MAX_BAYER_ORDER_NUM; j++) { |
| fakeSaResults.lsc_grid[i][j] = fakeLscTable; |
| } |
| } |
| fakeSaResults.fraction_bits = 0; |
| fakeSaResults.color_order = cmc_bayer_order_grbg; |
| fakeSaResults.lsc_update = true; |
| fakeSaResults.width = 2; |
| fakeSaResults.height = 2; |
| inputParams.sa_results = &fakeSaResults; |
| |
| initInputParams(&inputParams, mPgParamType); |
| |
| /* |
| * IA_ISP_BXT can run without 3A results to produce the defaults for a |
| * given sensor configuration. |
| */ |
| ia_binary_data binaryData = {}; |
| for (auto& ispParamIt : mStreamIdToIspParameterMap) { |
| inputParams.program_group = &(mStreamIdToProgramGroupMap[ispParamIt.first]); |
| inputParams.sensor_frame_params = &mFrameParam; |
| { |
| AutoMutex l(mIpuParamLock); |
| binaryData = ispParamIt.second.mSequenceToDataMap.begin()->second; |
| } |
| binaryData.size = mStreamIdToPGOutSizeMap[ispParamIt.first]; |
| |
| PERF_CAMERA_ATRACE_PARAM1_IMAGING("ia_isp_bxt_run", 1); |
| |
| int ret = mAdaptor->runPal(mIspAdaptHandle, &inputParams, &binaryData); |
| CheckError(ret != OK, UNKNOWN_ERROR, "ISP parameter adaptation has failed %d", ret); |
| |
| AutoMutex l(mIpuParamLock); |
| updateIspParameterMap(&(ispParamIt.second), -1, -1, binaryData); |
| ispParamIt.second.mSequenceToDataMap.erase(ispParamIt.second.mSequenceToDataMap.begin()); |
| } |
| |
| dumpIspParameter(0, binaryData); |
| |
| return postConfigure(stream.width, stream.height, &binaryData); |
| } |
| |
| int IspParamAdaptor::getParameters(Parameters& param) |
| { |
| AutoMutex l(mIspAdaptorLock); |
| |
| return OK; |
| } |
| |
| int IspParamAdaptor::decodeStatsData(TuningMode tuningMode, |
| std::shared_ptr<CameraBuffer> statsBuffer, |
| std::shared_ptr<IGraphConfig> graphConfig) |
| { |
| CheckError(mIspAdaptorState != ISP_ADAPTOR_CONFIGURED, |
| INVALID_OPERATION, "%s, wrong state %d", __func__, mIspAdaptorState); |
| |
| long sequence = statsBuffer->getSequence(); |
| AiqResultStorage *aiqResultStorage = AiqResultStorage::getInstance(mCameraId); |
| |
| const AiqResult *feedback = aiqResultStorage->getAiqResult(sequence); |
| if (feedback == nullptr) { |
| LOGW("No aiq result of sequence %ld! Use the latest instead", sequence); |
| feedback = aiqResultStorage->getAiqResult(); |
| } |
| |
| camera_resolution_t dvsInReso = {}; |
| if (graphConfig) { |
| ia_isp_bxt_resolution_info_t resolution = {}; |
| uint32_t gdcKernelId; |
| graphConfig->getGdcKernelSetting(&gdcKernelId, &resolution); |
| dvsInReso.width = resolution.input_width; |
| dvsInReso.height = resolution.input_height; |
| } |
| |
| ia_binary_data *hwStatsData = (ia_binary_data *)(statsBuffer->getBufferAddr()); |
| ConvertInputParam inputParams = {CameraUtils::isMultiExposureCase(tuningMode), |
| hwStatsData, &dvsInReso, &feedback->mAeResults, mBCompResults}; |
| |
| ConvertResult result; |
| ia_isp_bxt_statistics_query_results_t queryResults; |
| CLEAR(result); |
| CLEAR(queryResults); |
| result.queryResults = &queryResults; |
| |
| int ret = mAdaptor->queryAndConvertStats(mIspAdaptHandle, &inputParams, &result); |
| CheckError(ret != OK, ret, "%s, Faield to query and convert statistics", __func__); |
| |
| // Decode DVS statistics |
| if (queryResults.dvs_stats) { |
| if (CameraDump::isDumpTypeEnable(DUMP_PSYS_DECODED_STAT) && hwStatsData != nullptr) { |
| BinParam_t bParam; |
| bParam.bType = BIN_TYPE_GENERAL; |
| bParam.mType = M_PSYS; |
| bParam.sequence = statsBuffer->getSequence(); |
| bParam.gParam.appendix = "dvs_p2p_decoded_stats"; |
| CameraDump::dumpBinary(mCameraId, hwStatsData->data, hwStatsData->size, &bParam); |
| } |
| |
| if (result.dvsStats) { |
| DvsStatistics dvsStatsStorage(result.dvsStats, statsBuffer->getSequence()); |
| aiqResultStorage->updateDvsStatistics(dvsStatsStorage); |
| } else { |
| LOGW("Failed to get GDC kernel setting, DVS stats not decoded"); |
| } |
| } |
| |
| if (queryResults.rgbs_grid && queryResults.af_grid) { |
| int exposureNum = PlatformData::getExposureNum(mCameraId, false); |
| AiqStatistics *aiqStatistics = aiqResultStorage->acquireAiqStatistics(); |
| |
| if (*(result.rgbsGrid)) { |
| dumpRgbsStats(*(result.rgbsGrid), |
| statsBuffer->getSequence(), feedback->mAeResults.num_exposures); |
| } |
| if (result.afGrid) { |
| dumpAfStats(result.afGrid, statsBuffer->getSequence()); |
| } |
| |
| aiqStatistics->saveRgbsGridData(result.rgbsGrid, exposureNum); |
| aiqStatistics->saveAfGridData(result.afGrid); |
| aiqStatistics->mSequence = sequence; |
| aiqStatistics->mTimestamp = TIMEVAL2USECS(statsBuffer->getTimestamp()); |
| aiqStatistics->mTuningMode = tuningMode; |
| aiqResultStorage->updateAiqStatistics(sequence); |
| } |
| |
| return OK; |
| } |
| |
| void IspParamAdaptor::updateKernelToggles(ia_isp_bxt_program_group programGroup) { |
| |
| if (!Log::isDebugLevelEnable(CAMERA_DEBUG_LOG_KERNEL_TOGGLE)) return; |
| |
| const char* ENABLED_KERNELS = "/tmp/enabledKernels"; |
| const char* DISABLED_KERNELS = "/tmp/disabledKernels"; |
| const int FLIE_CONT_MAX_LENGTH = 1024; |
| ia_isp_bxt_run_kernels_t* curKernel = programGroup.run_kernels; |
| char enabledKernels[FLIE_CONT_MAX_LENGTH] = { 0 }; |
| char disabledKernels[FLIE_CONT_MAX_LENGTH] = { 0 }; |
| |
| int enLen = CameraUtils::getFileContent(ENABLED_KERNELS, enabledKernels, FLIE_CONT_MAX_LENGTH - 1); |
| int disLen = CameraUtils::getFileContent(DISABLED_KERNELS, disabledKernels, FLIE_CONT_MAX_LENGTH - 1); |
| |
| if (enLen == 0 && disLen == 0) { |
| LOG2("%s: no explicit kernel toggle.", __func__); |
| return; |
| } |
| |
| LOG2("%s: enabled kernels: %s, disabled kernels %s", __func__, |
| enabledKernels, disabledKernels); |
| |
| for (unsigned int i = 0; i < programGroup.kernel_count; i++) { |
| |
| std::string curKernelUUID = std::to_string(curKernel->kernel_uuid); |
| |
| LOG2("%s: checking kernel %s", __func__, curKernelUUID.c_str()); |
| |
| if (strstr(enabledKernels, curKernelUUID.c_str()) != nullptr) { |
| curKernel->enable = 1; |
| LOG2("%s: kernel %d is explicitly enabled", __func__, |
| curKernel->kernel_uuid); |
| } |
| |
| if (strstr(disabledKernels, curKernelUUID.c_str()) != nullptr) { |
| curKernel->enable = 0; |
| LOG2("%s: kernel %d is explicitly disabled", __func__, |
| curKernel->kernel_uuid); |
| } |
| |
| curKernel ++; |
| } |
| } |
| |
| /* |
| * PAL output buffer is a reference data for next output buffer, |
| * but currently a ring buffer is used in HAL, which caused logic mismatching issue. |
| * So temporarily copy latest PAL data into PAL output buffer. |
| */ |
| void IspParamAdaptor::updatePalDataForVideoPipe(ia_binary_data dest) |
| { |
| if (mLastPalDataForVideoPipe.data == nullptr || mLastPalDataForVideoPipe.size == 0) |
| return; |
| |
| if (mPalRecords.empty()) return; |
| |
| ia_pal_record_header *header = nullptr; |
| char* src = static_cast<char*>(mLastPalDataForVideoPipe.data); |
| // find uuid offset in saved PAL buffer |
| if (mPalRecords[0].offset < 0) { |
| uint32_t offset = 0; |
| while (offset < mLastPalDataForVideoPipe.size) { |
| ia_pal_record_header *header = reinterpret_cast<ia_pal_record_header*>(src + offset); |
| // check if header is valid or not |
| if (header->uuid == 0 || header->size == 0) { |
| LOGW("%s, source header info isn't correct", __func__); |
| return; |
| } |
| |
| for (uint32_t i = 0; i < mPalRecords.size(); i++) { |
| if (mPalRecords[i].offset < 0 && mPalRecords[i].uuid == header->uuid) { |
| mPalRecords[i].offset = offset; |
| LOG2("find uuid %d, offset %d, size %d", header->uuid, offset, header->size); |
| break; |
| } |
| } |
| offset += header->size; |
| } |
| } |
| |
| char* destData = static_cast<char*>(dest.data); |
| ia_pal_record_header *headerSrc = nullptr; |
| for (uint32_t i = 0; i < mPalRecords.size(); i++) { |
| if (mPalRecords[i].offset >= 0) { |
| // find source record header |
| header = reinterpret_cast<ia_pal_record_header*>(src + mPalRecords[i].offset); |
| if (header->uuid == mPalRecords[i].uuid) { |
| headerSrc = header; |
| } |
| |
| if (!headerSrc) { |
| LOGW("Failed to find PAL recorder header %d", mPalRecords[i].uuid); |
| continue; |
| } |
| header = reinterpret_cast<ia_pal_record_header*>(destData + mPalRecords[i].offset); |
| if (header->uuid == mPalRecords[i].uuid) { |
| MEMCPY_S(header, header->size, headerSrc, headerSrc->size); |
| LOG2("%s, PAL data of kernel uuid %d has been updated", __func__, header->uuid); |
| } |
| } |
| } |
| } |
| |
| void IspParamAdaptor::updateIspParameterMap(IspParameter* ispParam, int64_t dataSeq, |
| int64_t settingSeq, ia_binary_data binaryData) |
| { |
| LOG2("%s, data seq %ld, setting sequence %ld", __func__, dataSeq, settingSeq); |
| |
| // if dataSeq doesn't equal to settingSeq, only update sequence map |
| if (dataSeq == settingSeq) { |
| std::pair<int64_t, ia_binary_data> p(settingSeq, binaryData); |
| ispParam->mSequenceToDataMap.insert(p); |
| } |
| if (ispParam->mSequenceToDataId.size() >= ISP_PARAM_QUEUE_SIZE) { |
| ispParam->mSequenceToDataId.erase(ispParam->mSequenceToDataId.begin()); |
| } |
| ispParam->mSequenceToDataId[settingSeq] = dataSeq; |
| } |
| |
| /** |
| * runIspAdapt |
| * Convert the results of the 3A algorithms and parse with P2P. |
| */ |
| int IspParamAdaptor::runIspAdapt(const IspSettings* ispSettings, long settingSequence, int32_t streamId) |
| { |
| PERF_CAMERA_ATRACE(); |
| HAL_TRACE_CALL(CAMERA_DEBUG_LOG_LEVEL2); |
| AutoMutex l(mIspAdaptorLock); |
| CheckError(mIspAdaptorState != ISP_ADAPTOR_CONFIGURED, INVALID_OPERATION, "%s, wrong state %d", |
| __func__, mIspAdaptorState); |
| |
| for (auto& it : mStreamIdToIspParameterMap) { |
| if (streamId != -1 && it.first != streamId) continue; |
| |
| ia_binary_data binaryData = {}; |
| IspParameter *ispParam = &(it.second); |
| auto dataIt = ispParam->mSequenceToDataMap.end(); |
| { |
| AutoMutex l(mIpuParamLock); |
| // Only one sequence key will be saved if settingSequence is larger than 0 |
| if (settingSequence >= 0) { |
| dataIt = ispParam->mSequenceToDataMap.find(settingSequence); |
| } |
| |
| if (dataIt == ispParam->mSequenceToDataMap.end()) { |
| dataIt = ispParam->mSequenceToDataMap.begin(); |
| } |
| CheckError(dataIt == ispParam->mSequenceToDataMap.end(), UNKNOWN_ERROR, "No PAL buf!"); |
| binaryData = dataIt->second; |
| |
| LOG2("%s, PAL data buffer seq:%ld, for sequence: %ld, stream %d", |
| __func__, dataIt->first, settingSequence, it.first); |
| } |
| |
| ia_isp_bxt_gdc_limits* mbrData = nullptr; |
| binaryData.size = mStreamIdToPGOutSizeMap[it.first]; |
| if (mStreamIdToMbrDataMap.find(it.first) != mStreamIdToMbrDataMap.end()) |
| mbrData = &(mStreamIdToMbrDataMap[it.first]); |
| |
| // Update some PAL data to latest PAL result |
| if (it.first == VIDEO_STREAM_ID) { |
| updatePalDataForVideoPipe(binaryData); |
| } |
| int ret = runIspAdaptL(mStreamIdToProgramGroupMap[it.first], mbrData, |
| ispSettings, settingSequence, &binaryData, it.first); |
| CheckError(ret != OK, ret, "run isp adaptor error for streamId %d, sequence: %ld", |
| it.first, settingSequence); |
| |
| { |
| AutoMutex l(mIpuParamLock); |
| int64_t dataSequence = settingSequence; |
| if (binaryData.size == 0) { |
| dataSequence = ispParam->mSequenceToDataMap.rbegin()->first; |
| } |
| |
| updateIspParameterMap(ispParam, dataSequence, settingSequence, binaryData); |
| if (binaryData.size > 0) { |
| ispParam->mSequenceToDataMap.erase(dataIt); |
| |
| if (it.first == VIDEO_STREAM_ID) { |
| mLastPalDataForVideoPipe = binaryData; |
| } |
| } |
| } |
| } |
| |
| // Only Store the new sequence |
| LOG2("%s, the sequence list size: %zu", __func__, mSequenceList.size()); |
| if (mSequenceList.size() >= PlatformData::getMaxRawDataNum(mCameraId)) { |
| mSequenceList.pop_front(); |
| } |
| mSequenceList.push_back(settingSequence); |
| |
| return OK; |
| } |
| |
| ia_binary_data* IspParamAdaptor::getIpuParameter(long sequence, int streamId) |
| { |
| AutoMutex l(mIpuParamLock); |
| |
| // This is only for getting the default ipu parameter |
| if (sequence == -1 && streamId == -1) { |
| return &(mStreamIdToIspParameterMap.begin()->second.mSequenceToDataMap.begin()->second); |
| } |
| CheckError(streamId == -1, nullptr, "stream id is -1, but seq isn't -1"); |
| |
| IspParameter& ispParam = mStreamIdToIspParameterMap[streamId]; |
| ia_binary_data* binaryData = nullptr; |
| if (sequence == -1) { |
| // get the latest ipu param when sequence is -1 |
| auto rit = ispParam.mSequenceToDataMap.rbegin(); |
| for (; rit != ispParam.mSequenceToDataMap.rend(); ++rit) { |
| // sequence -1 is valid for default PAL data |
| if (rit->first >= -1) { |
| binaryData = &(rit->second); |
| break; |
| } |
| } |
| } else { |
| auto seqIt =ispParam.mSequenceToDataId.find(sequence); |
| if (seqIt != ispParam.mSequenceToDataId.end()) { |
| auto dataIt = ispParam.mSequenceToDataMap.find(seqIt->second); |
| if (dataIt != ispParam.mSequenceToDataMap.end()) |
| binaryData = &(dataIt->second); |
| } |
| } |
| |
| if (!binaryData) { |
| LOG1("Failed to find ISP parameter for stream id %d, sequence: %ld", streamId, sequence); |
| } |
| |
| return binaryData; |
| } |
| |
| int IspParamAdaptor::getPalOutputDataSize(const ia_isp_bxt_program_group* programGroup) |
| { |
| CheckError(programGroup == nullptr, 0, "Request programGroup is nullptr"); |
| return mAdaptor->getPalDataSize(const_cast<ia_isp_bxt_program_group*>(programGroup)); |
| } |
| |
| /* |
| * Allocate memory for mSequenceToDataMap |
| * TODO: Let PAL to expose the max ia_binary_data buffer size which |
| * come from mIspAdaptHandle->ia_pal.m_output_isp_parameters_size |
| */ |
| int IspParamAdaptor::allocateIspParamBuffers() |
| { |
| releaseIspParamBuffers(); |
| |
| for (int i = 0; i < ISP_PARAM_QUEUE_SIZE; i++) { |
| for (auto& pgMap : mStreamIdToProgramGroupMap) { |
| ia_binary_data binaryData = {}; |
| int size = mStreamIdToPGOutSizeMap[pgMap.first]; |
| binaryData.size = size; |
| binaryData.data = mAdaptor->allocatePalBuffer(pgMap.first, i, size); |
| CheckError(binaryData.data == nullptr, NO_MEMORY, "Faile to calloc PAL data"); |
| int64_t index = i * (-1) - 2; // default index list: -2, -3, -4, ... |
| std::pair<int64_t, ia_binary_data> p(index, binaryData); |
| mStreamIdToIspParameterMap[pgMap.first].mSequenceToDataMap.insert(p); |
| } |
| } |
| |
| return OK; |
| } |
| |
| void IspParamAdaptor::releaseIspParamBuffers() |
| { |
| for (int i = 0; i < ISP_PARAM_QUEUE_SIZE; i++) { |
| for (auto& it : mStreamIdToIspParameterMap) { |
| for (auto& binaryMap : it.second.mSequenceToDataMap) { |
| mAdaptor->freePalBuffer(binaryMap.second.data); |
| } |
| |
| it.second.mSequenceToDataId.clear(); |
| it.second.mSequenceToDataMap.clear(); |
| } |
| } |
| } |
| |
| int IspParamAdaptor::runIspAdaptL(ia_isp_bxt_program_group programGroup, |
| ia_isp_bxt_gdc_limits *mbrData, |
| const IspSettings* ispSettings, long settingSequence, |
| ia_binary_data *binaryData, int32_t streamId) |
| { |
| PERF_CAMERA_ATRACE_IMAGING(); |
| AiqResult* aiqResults = const_cast<AiqResult*>(AiqResultStorage::getInstance(mCameraId)->getAiqResult(settingSequence)); |
| if (aiqResults == nullptr) { |
| LOGW("%s: no result for sequence %ld! use the latest instead", __func__, settingSequence); |
| aiqResults = const_cast<AiqResult*>(AiqResultStorage::getInstance(mCameraId)->getAiqResult()); |
| CheckError((aiqResults == nullptr), INVALID_OPERATION, "Cannot find available aiq result."); |
| } |
| CheckError((aiqResults->mSaResults.width * aiqResults->mSaResults.height == 0), |
| INVALID_OPERATION, "No invalid aiq result needed to run Generic AIC"); |
| |
| LOG2("%s: device type: %d", __func__, mPgParamType); |
| |
| ia_isp_bxt_input_params_v2 inputParams; |
| ia_view_config_t viewConfig; |
| CLEAR(inputParams); |
| CLEAR(viewConfig); |
| |
| // LOCAL_TONEMAP_S |
| bool hasLtm = PlatformData::isLtmEnabled(mCameraId); |
| |
| if (hasLtm) { |
| size_t ltmLag = PlatformData::getLtmGainLag(mCameraId); |
| long ltmSequence = settingSequence; |
| |
| // Consider there may be skipped frames, so according to the gain lag and current |
| // sequence to find the actual ltm sequence in history list. |
| if (mSequenceList.size() > ltmLag) { |
| size_t index = 0; |
| for(auto iter = mSequenceList.begin(); iter != mSequenceList.end(); iter++) { |
| if (*iter == settingSequence && index >= ltmLag) { |
| ltmSequence = *(std::prev(iter, ltmLag)); |
| break; |
| } |
| index++; |
| } |
| } |
| ltm_result_t* ltmResult = const_cast<ltm_result_t*>(AiqResultStorage::getInstance(mCameraId)->getLtmResult(ltmSequence)); |
| if (ltmResult != nullptr) { |
| LOG2("%s: frame sequence %ld, ltm sequence %ld, actual sequence: %ld", |
| __func__, settingSequence, ltmSequence, ltmResult->sequence); |
| inputParams.ltm_results = <mResult->ltmResults; |
| inputParams.ltm_drc_params = <mResult->ltmDrcParams; |
| } |
| } |
| // LOCAL_TONEMAP_E |
| |
| // update metadata of runnning kernels |
| if (mPgParamType == PG_PARAM_PSYS_ISA) { |
| for (unsigned int i=0; i<programGroup.kernel_count; i++) { |
| switch (programGroup.run_kernels[i].kernel_uuid) { |
| case ia_pal_uuid_isp_tnr5_21: |
| case ia_pal_uuid_isp_tnr5_22: |
| case ia_pal_uuid_isp_tnr5_25: |
| programGroup.run_kernels[i].metadata[0] = aiqResults->mSequence; |
| LOG2("ia_pal_uuid_isp_tnr5_2x frame count = %d", programGroup.run_kernels[i].metadata[0]); |
| break; |
| case ia_pal_uuid_isp_bxt_ofa_dp: |
| case ia_pal_uuid_isp_bxt_ofa_mp: |
| case ia_pal_uuid_isp_bxt_ofa_ppp: |
| programGroup.run_kernels[i].metadata[2] = aiqResults->mAiqParam.flipMode; |
| LOG2("%s: flip mode set to %d", __func__, programGroup.run_kernels[i].metadata[2]); |
| |
| programGroup.run_kernels[i].metadata[3] = aiqResults->mAiqParam.yuvColorRangeMode; |
| LOG2("ofa yuv color range mode %d", programGroup.run_kernels[i].metadata[3]); |
| break; |
| case ia_pal_uuid_isp_gammatm_v3: |
| // Bypass the GammaTM for manual color transform awb mode |
| programGroup.run_kernels[i].enable = |
| (aiqResults->mAiqParam.awbMode == AWB_MODE_MANUAL_COLOR_TRANSFORM) ? 0 : 1; |
| LOG2("GammaTM enabled: %d", programGroup.run_kernels[i].enable); |
| break; |
| } |
| } |
| } |
| |
| // Enable or disable kernels according to environment variables for debug purpose. |
| updateKernelToggles(programGroup); |
| |
| inputParams.timestamp = aiqResults->mTimestamp; |
| inputParams.program_group = &programGroup; |
| inputParams.sensor_frame_params = &mFrameParam; |
| |
| inputParams.ae_results = &aiqResults->mAeResults; |
| inputParams.gbce_results = &aiqResults->mGbceResults; |
| inputParams.awb_results = &aiqResults->mAwbResults; |
| inputParams.pa_results = &aiqResults->mPaResults; |
| inputParams.sa_results = &aiqResults->mSaResults; |
| inputParams.weight_grid = aiqResults->mAeResults.weight_grid; |
| |
| inputParams.media_format = media_format_legacy; |
| if (aiqResults->mAiqParam.tonemapMode != TONEMAP_MODE_FAST && |
| aiqResults->mAiqParam.tonemapMode != TONEMAP_MODE_HIGH_QUALITY) { |
| inputParams.media_format = media_format_custom; |
| } |
| LOG2("%s, media format: 0x%x", __func__, inputParams.media_format); |
| |
| float saturationFactor = PlatformData::getManualSaturationFactor(mCameraId); |
| if (saturationFactor > 0.0f && |
| aiqResults->mAiqParam.awbMode == AWB_MODE_MANUAL_COLOR_TRANSFORM) { |
| inputParams.pa_results->saturation_factor = saturationFactor; |
| } |
| LOG2("%s, saturation_factor: %f", __func__, inputParams.pa_results->saturation_factor); |
| |
| if (VIDEO_STREAM_ID == streamId) { |
| inputParams.call_rate_control.mode = ia_isp_call_rate_never_on_converged; |
| } else { |
| inputParams.call_rate_control.mode = ia_isp_call_rate_always; |
| inputParams.sa_results->lsc_update = true; |
| } |
| |
| if (aiqResults->mCustomControls.count > 0) { |
| inputParams.custom_controls = &aiqResults->mCustomControls; |
| } |
| |
| if (ispSettings) { |
| inputParams.nr_setting = ispSettings->nrSetting; |
| inputParams.ee_setting = ispSettings->eeSetting; |
| LOG2("%s: ISP NR setting, level: %d, strength: %d", |
| __func__, (int)ispSettings->nrSetting.feature_level, |
| (int)ispSettings->nrSetting.strength); |
| inputParams.effects = ispSettings->effects; |
| inputParams.manual_brightness = ispSettings->manualSettings.manualBrightness; |
| inputParams.manual_contrast = ispSettings->manualSettings.manualContrast; |
| inputParams.manual_hue = ispSettings->manualSettings.manualHue; |
| inputParams.manual_saturation = ispSettings->manualSettings.manualSaturation; |
| LOG2("%s: ISP EE setting, level: %d, strength: %d", |
| __func__, ispSettings->eeSetting.feature_level, |
| ispSettings->eeSetting.strength); |
| // INTEL_DVS_S |
| if (ispSettings->videoStabilization) { |
| int dvsType = PlatformData::getDVSType(mCameraId); |
| LOG2("%s: ISP Video Stabilization Mode Enable, dvs type %d", __func__, dvsType); |
| DvsResult* dvsResult = const_cast<DvsResult*>(AiqResultStorage::getInstance(mCameraId)->getDvsResult()); |
| if (dvsType == MORPH_TABLE) { |
| inputParams.dvs_morph_table = (dvsResult == nullptr) ? nullptr : &dvsResult->mMorphTable; |
| } else if (dvsType == IMG_TRANS) { |
| inputParams.gdc_transformation = (dvsResult == nullptr) ? nullptr : &dvsResult->mTransformation; |
| } |
| } |
| // INTEL_DVS_E |
| |
| inputParams.pal_override = ispSettings->palOverride; |
| } |
| |
| if (CameraUtils::isUllPsysPipe(mTuningMode)) { |
| CheckError((aiqResults->mAeResults.exposures[0].exposure == nullptr), BAD_VALUE, "Aiq exposure is NULL."); |
| // The situation that all DG passed to ISP, not sensor. |
| if (!PlatformData::isUsingSensorDigitalGain(mCameraId)) { |
| inputParams.manual_digital_gain = aiqResults->mAeResults.exposures[0].exposure->digital_gain; |
| } |
| // Fine-tune DG passed to ISP if partial ISP DG is needed. |
| if (PlatformData::isUsingIspDigitalGain(mCameraId)) { |
| inputParams.manual_digital_gain = PlatformData::getIspDigitalGain(mCameraId, |
| aiqResults->mAeResults.exposures[0].exposure->digital_gain); |
| } |
| |
| LOG3A("%s: set digital gain for ULL pipe: %f", __func__, inputParams.manual_digital_gain); |
| } else if (CameraUtils::isMultiExposureCase(mTuningMode) && |
| PlatformData::getSensorGainType(mCameraId) == ISP_DG_AND_SENSOR_DIRECT_AG) { |
| CheckError((aiqResults->mAeResults.exposures[0].exposure == nullptr), BAD_VALUE, "Aiq exposure is NULL."); |
| |
| LOG3A("%s: all digital gain is passed to ISP, DG(%ld): %f", |
| __func__, aiqResults->mSequence, aiqResults->mAeResults.exposures[0].exposure->digital_gain); |
| inputParams.manual_digital_gain = aiqResults->mAeResults.exposures[0].exposure->digital_gain; |
| } |
| |
| int ret = OK; |
| { |
| PERF_CAMERA_ATRACE_PARAM1_IMAGING("ia_isp_bxt_run", 1); |
| ret = mAdaptor->runPal(mIspAdaptHandle, &inputParams, binaryData); |
| } |
| CheckError(ret != OK, UNKNOWN_ERROR, "ISP parameter adaptation has failed %d", ret); |
| |
| dumpIspParameter(aiqResults->mSequence, *binaryData); |
| |
| return OK; |
| } |
| |
| void IspParamAdaptor::dumpAfStats(const ia_aiq_af_grid *afGrid, long sequence) |
| { |
| if (!afGrid) return; |
| |
| if (mPgParamType == PG_PARAM_PSYS_ISA && !CameraDump::isDumpTypeEnable(DUMP_PSYS_AIQ_STAT)) |
| return; |
| if (mPgParamType == PG_PARAM_ISYS && !CameraDump::isDumpTypeEnable(DUMP_ISYS_AIQ_STAT)) |
| return; |
| |
| BinParam_t bParam; |
| bParam.bType = BIN_TYPE_STATISTIC; |
| bParam.mType = mPgParamType == PG_PARAM_PSYS_ISA ? M_PSYS : M_ISYS; |
| bParam.sequence = sequence; |
| bParam.sParam.gridWidth = afGrid->grid_width; |
| bParam.sParam.gridHeight = afGrid->grid_height; |
| bParam.sParam.appendix = "af_stats_filter_response_1"; |
| CameraDump::dumpBinary(mCameraId, afGrid->filter_response_1, |
| afGrid->grid_width * afGrid->grid_height * sizeof(int), &bParam); |
| bParam.sParam.appendix = "af_stats_filter_response_2"; |
| CameraDump::dumpBinary(mCameraId, afGrid->filter_response_2, |
| afGrid->grid_width * afGrid->grid_height * sizeof(int), &bParam); |
| } |
| |
| void IspParamAdaptor::dumpRgbsStats(ia_aiq_rgbs_grid *rgbsGrid, long sequence, unsigned int num) |
| { |
| if (rgbsGrid == nullptr) return; |
| |
| if (Log::isDebugLevelEnable(CAMERA_DEBUG_LOG_AIQ)) { |
| for (unsigned int i = 0; i < num; i++ ) { |
| rgbs_grid_block *rgbsPtr = rgbsGrid[i].blocks_ptr; |
| int size = rgbsGrid[i].grid_width * rgbsGrid[i].grid_height; |
| // Print out some value to check if it's reasonable |
| for (int j = 100; j < 105 && j < size; j++) { |
| LOG3A("RGBS: [%d]:%d, %d, %d, %d, %d", j, rgbsPtr[j].avg_b, rgbsPtr[j].avg_gb, |
| rgbsPtr[j].avg_gr, rgbsPtr[j].avg_r, rgbsPtr[j].sat); |
| } |
| |
| // Only print last Rgbs Stats's y_mean for validation purpose |
| if (i < num - 1) continue; |
| |
| int sumLuma = 0; |
| for (int j = 0; j < size; j++) { |
| sumLuma += (rgbsPtr[j].avg_b + rgbsPtr[j].avg_r + (rgbsPtr[j].avg_gb + rgbsPtr[j].avg_gr) / 2) / 3; |
| } |
| LOG3A("RGB stat grid[%d] %dx%d, y_mean %d", i, rgbsGrid[i].grid_width, rgbsGrid[i].grid_height, sumLuma/size); |
| } |
| } |
| |
| if ((mPgParamType == PG_PARAM_PSYS_ISA && CameraDump::isDumpTypeEnable(DUMP_PSYS_AIQ_STAT)) || |
| (mPgParamType == PG_PARAM_ISYS && CameraDump::isDumpTypeEnable(DUMP_ISYS_AIQ_STAT))) { |
| char name[30]; |
| BinParam_t bParam; |
| bParam.bType = BIN_TYPE_STATISTIC; |
| bParam.mType = mPgParamType == PG_PARAM_PSYS_ISA ? M_PSYS : M_ISYS; |
| bParam.sequence = sequence; |
| for (unsigned int i = 0; i < num; i++ ) { |
| CLEAR(name); |
| snprintf(name, sizeof(name), "%s_stats_%u_%u", |
| mPgParamType == PG_PARAM_PSYS_ISA ? "hdr_rgbs" : "rgbs", num, i); |
| bParam.sParam.gridWidth = rgbsGrid[i].grid_width; |
| bParam.sParam.gridHeight = rgbsGrid[i].grid_height; |
| bParam.sParam.appendix = name; |
| if (rgbsGrid[i].grid_width != 0 && rgbsGrid[i].grid_height != 0) { |
| CameraDump::dumpBinary(mCameraId, rgbsGrid[i].blocks_ptr, |
| rgbsGrid[i].grid_width * rgbsGrid[i].grid_height * sizeof(rgbs_grid_block), |
| &bParam); |
| } |
| } |
| } |
| } |
| |
| void IspParamAdaptor::dumpIspParameter(long sequence, ia_binary_data binaryData) { |
| if (mPgParamType == PG_PARAM_PSYS_ISA && !CameraDump::isDumpTypeEnable(DUMP_PSYS_PAL)) return; |
| if (mPgParamType == PG_PARAM_ISYS && !CameraDump::isDumpTypeEnable(DUMP_ISYS_PAL)) return; |
| |
| BinParam_t bParam; |
| bParam.bType = BIN_TYPE_GENERAL; |
| bParam.mType = mPgParamType == PG_PARAM_PSYS_ISA ? M_PSYS : M_ISYS; |
| bParam.sequence = sequence; |
| bParam.gParam.appendix = "pal"; |
| CameraDump::dumpBinary(mCameraId, binaryData.data, binaryData.size, &bParam); |
| } |
| |
| } // namespace icamera |