camera: intel: ipu6: Bypass still tnr when total gain < threshold

Read the threshold gain in xml
skip the extra frame request from psysprocessor
bypass the tnr7us process in GPUExecutor

BUG=b:149068439, b:149068672
TEST=Full tested pass for camera functions.

Change-Id: I8fabbfbec26fa92e1d1e2e3f91d494c5a974c97b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2594540
Tested-by: Zong Li <zong.li@intel.com>
Reviewed-by: Ren-Pei Zeng <kamesan@chromium.org>
Commit-Queue: Ren-Pei Zeng <kamesan@chromium.org>
diff --git a/camera/hal/intel/ipu6/src/core/PSysProcessor.cpp b/camera/hal/intel/ipu6/src/core/PSysProcessor.cpp
index 6bc03b7..b317173 100644
--- a/camera/hal/intel/ipu6/src/core/PSysProcessor.cpp
+++ b/camera/hal/intel/ipu6/src/core/PSysProcessor.cpp
@@ -793,7 +793,8 @@
     LOG2("@%s, seq %ld, hold raw %d, last still seq %ld, still %d", __func__, sequence,
          mHoldRawBuffers, mLastStillTnrSequence, hasStill);
 
-    if (hasStill && sequence != (mLastStillTnrSequence + 1) && mHoldRawBuffers) {
+    bool bypass = mPSysDAGs[mCurConfigMode]->isBypassStillTnr(sequence);
+    if (!bypass && hasStill && sequence != (mLastStillTnrSequence + 1) && mHoldRawBuffers) {
         CameraBufferPortMap fakeTaskBuffers = *dstBuffers;
         for (const auto& item : fakeTaskBuffers) {
             if (item.second && item.second->getStreamUsage() != CAMERA_STREAM_STILL_CAPTURE) {
diff --git a/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.cpp b/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.cpp
index 14ff2c5..b65e1b3 100644
--- a/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.cpp
+++ b/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.cpp
@@ -55,6 +55,7 @@
           mLastSequence(UINT32_MAX),
           mUseInternalTnrBuffer(useTnrOutBuffer),
           mOutBufferSize(0) {
+    mStillTnrTG = PlatformData::getTnrThresholdGain(mCameraId);
     LOG1("@%s %s", __func__, mName.c_str());
 }
 
@@ -225,6 +226,27 @@
     return false;
 }
 
+int GPUExecutor::getTotalGain(int64_t seq, float* totalGain) {
+    CheckError(!totalGain, UNKNOWN_ERROR, "Invalid input");
+    AiqResult* aiqResults =
+        const_cast<AiqResult*>(AiqResultStorage::getInstance(mCameraId)->getAiqResult(seq));
+    CheckError(!aiqResults, UNKNOWN_ERROR, "Cannot find available aiq result.");
+
+    *totalGain = (aiqResults->mAeResults.exposures[0].exposure->analog_gain *
+                  aiqResults->mAeResults.exposures[0].exposure->digital_gain);
+    return OK;
+}
+
+bool GPUExecutor::isBypassStillTnr(int64_t seq) {
+    if (mStreamId != STILL_STREAM_ID) return false;
+
+    float totalGain = 0.0f;
+    int ret = getTotalGain(seq, &totalGain);
+    CheckError(ret, true, "@%s, Failed to get total gain", __func__);
+    if (totalGain <= mStillTnrTG) return true;
+    return false;
+}
+
 int GPUExecutor::allocTnrOutBufs(uint32_t bufSize) {
     mOutBufferSize = bufSize;
 
@@ -446,7 +468,7 @@
 
     uint32_t sequence = inBuf->getSequence();
     int ret = OK;
-    if (mIntelTNR) {
+    if (mIntelTNR && !isBypassStillTnr(sequence)) {
         ret = updateTnrISPConfig(mTnr7usParam, sequence);
         CheckError(ret != OK, UNKNOWN_ERROR, " %s Failed to update TNR parameters", __func__);
     }
@@ -459,7 +481,7 @@
                        : outBuf->getBufferAddr();
     if (!outPtr) return UNKNOWN_ERROR;
 
-    if (!mIntelTNR) {
+    if (!mIntelTNR || isBypassStillTnr(sequence)) {
         MEMCPY_S(outPtr, bufferSize, inBuf->getBufferAddr(), inBuf->getBufferSize());
         if (memoryType == V4L2_MEMORY_DMABUF) {
             CameraBuffer::unmapDmaBufferAddr(outPtr, bufferSize);
@@ -534,21 +556,13 @@
 
     if (mStreamId != STILL_STREAM_ID) {
         // still stream will update params in tnr7us, skip async update
-        AiqResult* aiqResults = const_cast<AiqResult*>(
-            AiqResultStorage::getInstance(mCameraId)->getAiqResult(sequence));
-        if (aiqResults == nullptr) {
-            LOGW("%s: no result for sequence %ld! use the latest instead", __func__, sequence);
-            aiqResults =
-                const_cast<AiqResult*>(AiqResultStorage::getInstance(mCameraId)->getAiqResult());
-            CheckError((aiqResults == nullptr), UNKNOWN_ERROR, "Cannot find available aiq result.");
-        }
+        float totalGain = 0.0f;
+        ret = getTotalGain(sequence, &totalGain);
+        CheckError(ret, UNKNOWN_ERROR, "@%s, Failed to get total gain", __func__);
 
-        int gain = static_cast<int>(aiqResults->mAeResults.exposures[0].exposure->analog_gain *
-                                    aiqResults->mAeResults.exposures[0].exposure->digital_gain);
-
-        // update tnr param when total gain changes, gain set to analog_gain * digital_gain.
+        // update tnr param when total gain changes
         bool isTnrParamForceUpdate = icamera::PlatformData::isTnrParamForceUpdate();
-        ret = mIntelTNR->asyncParamUpdate(gain, isTnrParamForceUpdate);
+        ret = mIntelTNR->asyncParamUpdate(static_cast<int>(totalGain), isTnrParamForceUpdate);
     }
 
     LOG2("Exit %s executor name:%s, sequence: %u", __func__, mName.c_str(), inBuf->getSequence());
diff --git a/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.h b/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.h
index d8a598d..4ad8781 100644
--- a/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.h
+++ b/camera/hal/intel/ipu6/src/core/psysprocessor/GPUExecutor.h
@@ -44,6 +44,7 @@
 
     // fetch TNR reference buffer for user output, return true if found successfully
     virtual bool fetchTnrOutBuffer(int64_t seq, std::shared_ptr<CameraBuffer> buf);
+    virtual bool isBypassStillTnr(int64_t seq);
 
  private:
     int createPGs();
@@ -53,6 +54,7 @@
     int updateTnrISPConfig(Tnr7Param* pbuffer, uint32_t sequence);
     int allocTnrOutBufs(uint32_t bufSize);
     int dumpTnrParameters(uint32_t sequence);
+    int getTotalGain(int64_t seq, float *totalGain);
     int runTnrFrame(const std::shared_ptr<CameraBuffer>& inBuf,
                     std::shared_ptr<CameraBuffer> outbuf);
 
@@ -65,6 +67,8 @@
      * should require this lock. */
     static std::mutex mGPULock;
     int mOutBufferSize;
+    // threshold gain for still tnr, only run still tnr when gain > TG
+    float mStillTnrTG;
     std::mutex mTnrOutBufMapLock;  // used to guard mTnrOutBufMap
     // first: sequence of source buffer, second: the reference buffer address
     std::map<int64_t, void*> mTnrOutBufMap;
diff --git a/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.cpp b/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.cpp
index 4900490..e0d979d 100644
--- a/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.cpp
+++ b/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.cpp
@@ -35,6 +35,7 @@
 #endif
     mDefaultMainInputPort(MAIN_PORT),
     mVideoTnrExecutor(nullptr),
+    mStillTnrExecutor(nullptr),
     mRunAicAfterQbuf(false)
 {
     LOG1("@%s, mCameraId:%d", __func__, mCameraId);
@@ -142,6 +143,7 @@
             executor = new GPUExecutor(mCameraId, item, cfg->exclusivePgs, this, gc,
                                        useTnrOutBuffer);
             if (streamId == VIDEO_STREAM_ID) mVideoTnrExecutor = executor;
+            else if (streamId == STILL_STREAM_ID) mStillTnrExecutor = executor;
         } else {
             executor = new PipeExecutor(mCameraId, item, cfg->exclusivePgs, this, gc);
         }
@@ -200,6 +202,11 @@
     return mVideoTnrExecutor != nullptr ? mVideoTnrExecutor->fetchTnrOutBuffer(seq, buf) : false;
 }
 
+bool PSysDAG::isBypassStillTnr(int64_t seq)
+{
+    return mStillTnrExecutor != nullptr ? mStillTnrExecutor->isBypassStillTnr(seq) : true;
+}
+
 int PSysDAG::linkAndConfigExecutors()
 {
     for (auto& consumer : mExecutorsPool) {
diff --git a/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.h b/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.h
index 2ce3b18..9c41eba 100644
--- a/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.h
+++ b/camera/hal/intel/ipu6/src/core/psysprocessor/PSysDAG.h
@@ -95,6 +95,7 @@
     int prepareIpuParams(long sequence, bool forceUpdate = false, TaskInfo *task = nullptr);
 
     bool fetchTnrOutBuffer(int64_t seq, std::shared_ptr<CameraBuffer> buf);
+    bool isBypassStillTnr(int64_t seq);
 
     /**
      * Use to handle the frame done event from the executors.
@@ -140,6 +141,7 @@
     std::unordered_map<PipeExecutor*, int32_t> mExecutorStreamId;
     std::map<Port, std::vector<int32_t> > mOutputPortToStreamIds;
     PipeExecutor* mVideoTnrExecutor;
+    PipeExecutor* mStillTnrExecutor;
 
     // A lock for protecting task data from being accessed by different threads.
     Mutex mTaskLock;
diff --git a/camera/hal/intel/ipu6/src/core/psysprocessor/PipeLiteExecutor.h b/camera/hal/intel/ipu6/src/core/psysprocessor/PipeLiteExecutor.h
index 5122c3b..16452c6 100644
--- a/camera/hal/intel/ipu6/src/core/psysprocessor/PipeLiteExecutor.h
+++ b/camera/hal/intel/ipu6/src/core/psysprocessor/PipeLiteExecutor.h
@@ -49,6 +49,7 @@
     void notifyStop();
 
     virtual bool fetchTnrOutBuffer(int64_t seq, std::shared_ptr<CameraBuffer> buf) { return false; }
+    virtual bool isBypassStillTnr(int64_t seq) { return true; }
     int releaseStatsBuffer(const std::shared_ptr<CameraBuffer> &statsBuf);
 
     void setStreamId(int streamId) { mStreamId = streamId; }
diff --git a/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp b/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
index 857a586..444555c 100644
--- a/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
+++ b/camera/hal/intel/ipu6/src/platformdata/CameraParser.cpp
@@ -483,6 +483,9 @@
     } else if (strcmp(name, "tnrExtraFrameNum") == 0) {
         int val = atoi(atts[1]);
         pCurrentCam->mTnrExtraFrameNum = val > 0 ? val : DEFAULT_TNR_EXTRA_FRAME_NUM;
+    } else if (strcmp(name, "tnrThresholdGain") == 0) {
+        float val = atof(atts[1]);
+        pCurrentCam->mTnrThresholdGain = val > 0 ? val : DEFAULT_TNR_THRESHOLD_GAIN;
     }
 }
 
diff --git a/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp b/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
index 13ecb1f..d534f12 100644
--- a/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
+++ b/camera/hal/intel/ipu6/src/platformdata/PlatformData.cpp
@@ -1394,4 +1394,9 @@
 {
     return getInstance()->mStaticCfg.mCameras[cameraId].mTnrExtraFrameNum;
 }
+
+float PlatformData::getTnrThresholdGain(int cameraId)
+{
+    return getInstance()->mStaticCfg.mCameras[cameraId].mTnrThresholdGain;
+}
 } // namespace icamera
diff --git a/camera/hal/intel/ipu6/src/platformdata/PlatformData.h b/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
index aa6499a..5a2ab1c 100644
--- a/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
+++ b/camera/hal/intel/ipu6/src/platformdata/PlatformData.h
@@ -53,6 +53,8 @@
 #define FACE_ENGINE_DEFAULT_RUNNING_INTERVAL 1
 
 #define DEFAULT_TNR_EXTRA_FRAME_NUM 2
+#define DEFAULT_TNR_THRESHOLD_GAIN 2.0f
+
 /* Max number of the RAW buffer number is 32.
  * Max number size of the pipeline depth is 6.
  * Max setting count should be larger than raw buffer number + pipeline depth.
@@ -142,7 +144,8 @@
                 mSwProcessingAlignWithIsp(false),
                 mMaxNvmDataSize(0),
                 mVideoStreamNum(DEFAULT_VIDEO_STREAM_NUM),
-                mTnrExtraFrameNum(DEFAULT_TNR_EXTRA_FRAME_NUM)
+                mTnrExtraFrameNum(DEFAULT_TNR_EXTRA_FRAME_NUM),
+                mTnrThresholdGain(DEFAULT_TNR_THRESHOLD_GAIN)
             {
             }
 
@@ -232,6 +235,7 @@
             std::vector<IGraphType::ScalerInfo> mScalerInfo;
             int mVideoStreamNum;
             int mTnrExtraFrameNum;
+            float mTnrThresholdGain;
         };
 
         std::vector<CameraInfo> mCameras;
@@ -1194,5 +1198,9 @@
      * the extra frame count for still stream
      */
      static int getTnrExtraFrameCount(int cameraId);
+     /**
+     * the threshold gain to trigger still tnr
+     */
+     static float getTnrThresholdGain(int cameraId);
 };
 } /* namespace icamera */
diff --git a/camera/hal/intel/ipu6/src/platformdata/gc/IGraphConfig.h b/camera/hal/intel/ipu6/src/platformdata/gc/IGraphConfig.h
index 8771706..b932da6 100644
--- a/camera/hal/intel/ipu6/src/platformdata/gc/IGraphConfig.h
+++ b/camera/hal/intel/ipu6/src/platformdata/gc/IGraphConfig.h
@@ -40,16 +40,13 @@
 
 namespace icamera {
 
-/**
- * Stream id associated with still capture.
- */
-static const int32_t STILL_STREAM_ID = 60000;
-/**
- * Stream id associated with video stream.
- */
 #ifdef TNR7_CM
+// Stream id associated with still capture.
+static const int32_t STILL_STREAM_ID = 60009;
+// Stream id associated with video stream.
 static const int32_t VIDEO_STREAM_ID = 60006;
 #else
+static const int32_t STILL_STREAM_ID = 60000;
 static const int32_t VIDEO_STREAM_ID = 60001;
 #endif