/*
 * Copyright (C) 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 "GPUExecutor"

#include "GPUExecutor.h"

extern "C" {
#include <ia_cipf_css/ia_cipf_css.h>
#include <ia_pal_types_isp_ids_autogen.h>
}

#include <map>
#include <memory>
#include <string>
#include <vector>

#include "3a/AiqResult.h"
#include "3a/AiqResultStorage.h"
#include "FormatUtils.h"
#include "PSysDAG.h"
#include "SyncManager.h"
#include "ia_pal_output_data.h"
#include "iutils/CameraDump.h"

using std::map;
using std::shared_ptr;
using std::string;
using std::vector;

#define external_gpu_stage_uid(id) ia_fourcc(((id & 0xFF00) >> 8), id, 'E', 'X')

namespace icamera {

std::mutex GPUExecutor::mGPULock;

GPUExecutor::GPUExecutor(int cameraId, const ExecutorPolicy& policy, vector<string> exclusivePGs,
                         PSysDAG* psysDag, shared_ptr<IGraphConfig> gc, bool useTnrOutBuffer)
        : PipeExecutor(cameraId, policy, exclusivePGs, psysDag, gc),
          mTnr7usParam(nullptr),
          mIntelTNR(nullptr),
          mLastSequence(UINT32_MAX),
          mUseInternalTnrBuffer(useTnrOutBuffer),
          mOutBufferSize(0) {
    mStillTnrTG = PlatformData::getTnrThresholdGain(mCameraId);
    LOG1("@%s %s", __func__, mName.c_str());
}

GPUExecutor::~GPUExecutor() {
    LOG1("@%s %s", __func__, mName.c_str());
    mPGExecutors.clear();
}

int GPUExecutor::initPipe() {
    LOG1("@%s:%s", __func__, getName());
    CheckError(mGraphConfig == nullptr, BAD_VALUE, "%s, the graph config is NULL, BUG!", __func__);

    vector<IGraphType::PipelineConnection> connVector;

    int ret = mGraphConfig->pipelineGetConnections(mPGNames, &connVector);
    CheckError(ret != OK || connVector.empty(), ret, "Failed to get connections for executor:%s",
               mName.c_str());

    ret = createPGs();
    CheckError(ret != OK, ret, "Failed to create PGs for executor: %s", mName.c_str());

    ret = analyzeConnections(connVector);
    CheckError(ret != OK, ret, "Failed to analyze connections for executor: %s", mName.c_str());

    assignDefaultPortsForTerminals();
    return OK;
}

// GPU executor doesn't have HW pg, create pg according to graph settings
int GPUExecutor::createPGs() {
    LOG1("@%s:%s", __func__, getName());

    for (auto const& pgName : mPGNames) {
        int pgId = mGraphConfig->getPgIdByPgName(pgName);
        CheckError(pgId == -1, BAD_VALUE, "Cannot get PG ID for %s", pgName.c_str());
        ExecutorUnit pgUnit;
        pgUnit.pgId = pgId;
        // GPU Executor doesn't have pg
        pgUnit.pg = nullptr;
        pgUnit.stageId = external_gpu_stage_uid(pgId);
        mPGExecutors.push_back(pgUnit);
    }
    return OK;
}

int GPUExecutor::start() {
    LOG1("%s executor:%s", __func__, mName.c_str());

    mProcessThread = new ProcessThread(this);

    CheckError(mPGExecutors.empty(), UNKNOWN_ERROR, "PGExecutors couldn't be empty");
    ExecutorUnit* tnrUnit = &mPGExecutors[0];
    int ret = OK;
    if (!tnrUnit->inputTerminals.empty()) {
        ia_uid term = tnrUnit->inputTerminals.at(0);
        CheckError(mTerminalsDesc.find(term) == mTerminalsDesc.end(), NO_INIT,
                   "Can't find TerminalDescriptor");

        const FrameInfo& frameInfo = mTerminalsDesc[term].frameDesc;
        mIntelTNR = std::unique_ptr<IntelTNR7US>(new IntelTNR7US(mCameraId));
        TnrType type = mStreamId == VIDEO_STREAM_ID ? TNR_INSTANCE0 : TNR_INSTANCE1;
        ret = mIntelTNR->init(frameInfo.mWidth, frameInfo.mHeight, type);
        if (ret) {
            mIntelTNR = nullptr;
            // when failed to init tnr, executor will run without tnr effect
            LOGW("%s executor:%s init tnr failed", __func__, mName.c_str());
        }
    }
    AutoMutex l(mBufferQueueLock);
    ret = allocBuffers();
    CheckError(ret, UNKNOWN_ERROR, "@%s: allocBuffers failed", __func__);
    dumpPGs();

    mThreadRunning = true;
    mProcessThread->run(mName.c_str(), PRIORITY_NORMAL);

    return ret;
}

void GPUExecutor::stop() {
    LOG1("%s executor:%s", __func__, mName.c_str());

    mProcessThread->requestExitAndWait();

    // Thread is not running. It is safe to clear the Queue
    releaseBuffers();
    clearBufferQueues();

    delete mProcessThread;
    mIntelTNR = nullptr;
}

int GPUExecutor::allocBuffers() {
    LOG1("%s executor:%s", __func__, mName.c_str());

    releaseBuffers();

    // Allocate buffers for producer executor (external)
    // don't need to check mPGExecutors and inputTerminals, already check before
    ia_uid term = mPGExecutors[0].inputTerminals.at(0);
    Port inputPort = mTerminalsDesc[term].assignedPort;

    int srcFmt = mTerminalsDesc[term].frameDesc.mFormat;
    int srcWidth = mTerminalsDesc[term].frameDesc.mWidth;
    int srcHeight = mTerminalsDesc[term].frameDesc.mHeight;
    int size = PGCommon::getFrameSize(srcFmt, srcWidth, srcHeight, true);

    for (int i = 0; i < MAX_BUFFER_COUNT; i++) {
        shared_ptr<CameraBuffer> buf;
        if (mIntelTNR) {
            buf = std::make_shared<CameraBuffer>(mCameraId, BUFFER_USAGE_PSYS_INPUT,
                                                 V4L2_MEMORY_USERPTR, size, i, srcFmt);
            CheckError(!buf, NO_MEMORY, "@%s: fail to alloc CameraBuffer", __func__);
            void* buffer = mIntelTNR->allocCamBuf(size, i);
            CheckError(!buffer, NO_MEMORY, "@%s: fail to alloc shared memory", __func__);
            buf->setUserBufferInfo(srcFmt, srcWidth, srcHeight, buffer);
        } else {
            buf = CameraBuffer::create(mCameraId, BUFFER_USAGE_PSYS_INPUT, V4L2_MEMORY_USERPTR,
                                       size, i, srcFmt, srcWidth, srcHeight);
        }

        mInternalBuffers[inputPort].push_back(buf);
        mBufferProducer->qbuf(inputPort, buf);
    }

    if (mIntelTNR) {
        int ret = allocTnrOutBufs(size);
        CheckError(ret, UNKNOWN_ERROR, "@%s: alloc tnr reference buffer failed", __func__);

        mTnr7usParam = mIntelTNR->allocTnr7ParamBuf();
        CheckError(!mTnr7usParam, NO_MEMORY, "@%s: Allocate Param buffer failed", __func__);
        CLEAR(*mTnr7usParam);
    }

    // Allocate internal output buffers to support pipe execution without user output buffer
    for (auto const& item : mOutputFrameInfo) {
        int fmt = item.second.format;
        int width = item.second.width;
        int height = item.second.height;
        int size = CameraUtils::getFrameSize(fmt, width, height, true);
        shared_ptr<CameraBuffer> buf = CameraBuffer::create(
            mCameraId, BUFFER_USAGE_PSYS_INPUT, V4L2_MEMORY_USERPTR, size, 0, fmt, width, height);
        CheckError(!buf, NO_MEMORY, "@%s: Allocate internal output buffer failed", __func__);
        mInternalOutputBuffers[item.first] = buf;
    }

    return OK;
}

bool GPUExecutor::fetchTnrOutBuffer(int64_t seq, std::shared_ptr<CameraBuffer> buf) {
    if (!mUseInternalTnrBuffer) return false;

    std::unique_lock<std::mutex> lock(mTnrOutBufMapLock);
    if (mTnrOutBufMap.find(seq) != mTnrOutBufMap.end()) {
        void* pSrcBuf = (buf->getMemory() == V4L2_MEMORY_DMABUF)
                            ? CameraBuffer::mapDmaBufferAddr(buf->getFd(), buf->getBufferSize())
                            : buf->getBufferAddr();
        CheckError(!pSrcBuf, false, "%s, pSrcBuf is nullptr", __func__);
        LOG2("%s, sequence %ld is used for output", __func__, seq);
        MEMCPY_S(pSrcBuf, buf->getBufferSize(), mTnrOutBufMap[seq], mOutBufferSize);
        if (buf->getMemory() == V4L2_MEMORY_DMABUF) {
            CameraBuffer::unmapDmaBufferAddr(pSrcBuf, buf->getBufferSize());
        }

        return true;
    }

    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;

    /* for yuv still stream, we use maxRaw buffer to do reprocessing, and for real still stream, 2
     * tnr buffers are enough */
    int maxTnrOutBufCount = (mStreamId == VIDEO_STREAM_ID && mUseInternalTnrBuffer)
                                ? PlatformData::getMaxRawDataNum(mCameraId)
                                : DEFAULT_TNR7US_BUFFER_COUNT;

    std::unique_lock<std::mutex> lock(mTnrOutBufMapLock);
    for (int i = 0; i < maxTnrOutBufCount; i++) {
        void* buffer = mIntelTNR->allocCamBuf(bufSize, MAX_BUFFER_COUNT + i);
        // will release all buffer in freeAllBufs
        CheckError(!buffer, UNKNOWN_ERROR, "@%s, alloc reference buffer fails", __func__);
        int index = i * (-1) - 1;  // initialize index as -1, -2, ...
        mTnrOutBufMap[index] = buffer;
    }
    return OK;
}

void GPUExecutor::releaseBuffers() {
    if (mIntelTNR) {
        mIntelTNR->freeAllBufs();
    }
    mTnrOutBufMap.clear();
    // Release internel frame buffers
    mInternalOutputBuffers.clear();
    mInternalBuffers.clear();
}

int GPUExecutor::processNewFrame() {
    PERF_CAMERA_ATRACE();

    int ret = OK;
    CameraBufferPortMap inBuffers, outBuffers;
    // Wait frame buffers.
    {
        ConditionLock lock(mBufferQueueLock);
        ret = waitFreeBuffersInQueue(lock, inBuffers, outBuffers);
        // Already stopped
        if (!mThreadRunning) return -1;

        if (ret != OK) return OK;  // Wait frame buffer error should not involve thread exit.

        CheckError(inBuffers.empty() || outBuffers.empty(), UNKNOWN_ERROR,
                   "Failed to get input or output buffers.");

        for (auto& output : mOutputQueue) {
            output.second.pop();
        }

        for (auto& input : mInputQueue) {
            input.second.pop();
        }
    }

    // Check if the executor needs to run the actual pipeline.
    // It only needs to run when there is at least one valid output buffer.
    if (!hasValidBuffers(outBuffers)) {
        // As an output edge, return the inBuffer when has no outBuffer,
        for (const auto& item : inBuffers) {
            mBufferProducer->qbuf(item.first, item.second);
        }
        return OK;
    }

    // Should find first not none input buffer instead of always use the first one.
    shared_ptr<CameraBuffer> inBuf = inBuffers.begin()->second;
    CheckError(!inBuf, UNKNOWN_ERROR, "@%s: no valid input buffer", __func__);
    v4l2_buffer_t inV4l2Buf = *inBuf->getV4L2Buffer().Get();

    // Fill real buffer to run pipe
    for (auto& item : outBuffers) {
        if (item.second.get() == nullptr) {
            item.second = mInternalOutputBuffers[item.first];
        }
    }

    std::shared_ptr<CameraBuffer> outBuf = outBuffers.begin()->second;
    CheckError(!outBuf, UNKNOWN_ERROR, "@%s: no valid output buffer", __func__);

    ret = runTnrFrame(inBuf, outBuf);
    CheckError(ret != OK, ret, "@%s: run tnr failed", __func__);

    // Remove internal output buffers
    for (auto& item : outBuffers) {
        if (item.second.get() == mInternalOutputBuffers[item.first].get()) {
            item.second = nullptr;
        }
    }

    notifyFrameDone(inV4l2Buf, outBuffers);

    // Return buffers for the executor which is NOT an input edge
    for (auto const& portBufferPair : inBuffers) {
        // Queue buffer to producer
        mBufferProducer->qbuf(portBufferPair.first, portBufferPair.second);
    }

    return OK;
}

/* get the tnr7 tuning data from ISP. PalOutput can help decode IPU tnr parameters from IPU result
** The GPU tnr7 parameters struct is different from IPU tnr parameters struct, so here we copy
** the useful parameter to tnr7 parameters object
*/
int GPUExecutor::updateTnrISPConfig(Tnr7Param* pbuffer, uint32_t sequence) {
    int ret = ia_err_none;
    if (mAdaptor) {
        CLEAR(*pbuffer);
        // only video stream pipe has tnr tuning data, still pipe use same tnr tuning data as video
        ia_isp_bxt_program_group* pg = mGraphConfig->getProgramGroup(mStreamId);
        CheckError(pg == nullptr, UNKNOWN_ERROR, "Can't get IPU program group");

        // Get ISP parameters
        LOG1(" %s update tnr parameters for sequence %d", __func__, sequence);

        ia_binary_data* ipuParameters = mAdaptor->getIpuParameter(sequence, mStreamId);
        CheckError(ipuParameters == nullptr, UNKNOWN_ERROR, "Failed to find ISP parameter");

        ia_isp_bxt_program_group tmpPg = *pg;
        tmpPg.kernel_count = 0;
        int blankKernelSize = mAdaptor->getPalOutputDataSize(&tmpPg);

        PalOutputData PalOutput(pg);
        ia_binary_data tmpTnr7BinData = {0};
        tmpTnr7BinData.size = ipuParameters->size - blankKernelSize;
        tmpTnr7BinData.data = reinterpret_cast<char*>(ipuParameters->data) + blankKernelSize;

        PalOutput.setPublicOutput(&tmpTnr7BinData);
        ia_pal_isp_tnr7_bc_1_0_t* pBc;
        ia_pal_isp_tnr7_blend_1_0_t* pBlend;
        ia_pal_isp_tnr7_ims_1_0_t* pIms;
        ret |= PalOutput.getKernelPublicOutput(ia_pal_uuid_isp_tnr7_bc_1_0, (void*&)pBc);
        ret |= PalOutput.getKernelPublicOutput(ia_pal_uuid_isp_tnr7_blend_1_0, (void*&)pBlend);
        ret |= PalOutput.getKernelPublicOutput(ia_pal_uuid_isp_tnr7_ims_1_0, (void*&)pIms);
        CheckError(ret != ia_err_none, UNKNOWN_ERROR, "Can't read isp tnr7 parameters");

        tnr7_bc_1_0_t* tnr7_bc = &(pbuffer->bc);
        tnr7_blend_1_0_t* tnr7_blend = &(pbuffer->blend);
        tnr7_ims_1_0_t* tnr7_ims = &(pbuffer->ims);

        // tnr7 ims params
        tnr7_ims->enable = pIms->enable;
        tnr7_ims->update_limit = pIms->update_limit;
        tnr7_ims->update_coeff = pIms->update_coeff;
        tnr7_ims->gpu_mode = pIms->gpu_mode;
        for (int i = 0; i < sizeof(pIms->d_ml) / sizeof(int32_t); i++) {
            tnr7_ims->d_ml[i] = pIms->d_ml[i];
            tnr7_ims->d_slopes[i] = pIms->d_slopes[i];
            tnr7_ims->d_top[i] = pIms->d_top[i];
            tnr7_ims->outofbounds[i] = pIms->outofbounds[i];
        }

        // tnr7 bc params
        tnr7_bc->enable = pBc->enable;
        tnr7_bc->is_first_frame = pBc->is_first_frame;
        tnr7_bc->do_update = pBc->do_update;
        tnr7_bc->gpu_mode = pBc->gpu_mode;
        tnr7_bc->tune_sensitivity = pBc->tune_sensitivity;
        for (int i = 0; i < sizeof(pBc->coeffs) / sizeof(int32_t); i++) {
            tnr7_bc->coeffs[i] = pBc->coeffs[i];
        }

        tnr7_bc->global_protection = pBc->global_protection;
        tnr7_bc->global_protection_motion_level = pBc->global_protection_motion_level;
        for (int i = 0; i < sizeof(pBc->global_protection_sensitivity_lut_values) / sizeof(int32_t);
             i++) {
            tnr7_bc->global_protection_sensitivity_lut_values[i] =
                pBc->global_protection_sensitivity_lut_values[i];
        }
        for (int i = 0; i < sizeof(pBc->global_protection_sensitivity_lut_slopes) / sizeof(int32_t);
             i++) {
            tnr7_bc->global_protection_sensitivity_lut_slopes[i] =
                pBc->global_protection_sensitivity_lut_slopes[i];
        }

        // tnr7 blend params
        tnr7_blend->enable = pBlend->enable;
        tnr7_blend->enable_main_output = pBlend->enable_main_output;
        tnr7_blend->enable_vision_output = pBlend->enable_vision_output;
        tnr7_blend->single_output_mode = pBlend->single_output_mode;
        tnr7_blend->spatial_weight_coeff = pBlend->spatial_weight_coeff;
        tnr7_blend->max_recursive_similarity = pBlend->max_recursive_similarity;
        tnr7_blend->spatial_alpha = pBlend->spatial_alpha;
        tnr7_blend->max_recursive_similarity_vsn = pBlend->max_recursive_similarity_vsn;
        for (int i = 0; i < sizeof(pBlend->w_out_prev_LUT) / sizeof(int32_t); i++) {
            tnr7_blend->w_out_prev_LUT[i] = pBlend->w_out_prev_LUT[i];
            tnr7_blend->w_out_spl_LUT[i] = pBlend->w_out_spl_LUT[i];
            tnr7_blend->w_vsn_out_prev_LUT[i] = pBlend->w_vsn_out_prev_LUT[i];
            tnr7_blend->w_vsn_out_spl_LUT[i] = pBlend->w_vsn_out_spl_LUT[i];
        }

        for (int i = 0; i < sizeof(pBlend->output_cu_a) / sizeof(int32_t); i++) {
            tnr7_blend->output_cu_a[i] = pBlend->output_cu_a[i];
            tnr7_blend->output_cu_b[i] = pBlend->output_cu_b[i];
        }

        for (int i = 0; i < sizeof(pBlend->output_cu_x) / sizeof(int32_t); i++) {
            tnr7_blend->output_cu_x[i] = pBlend->output_cu_x[i];
        }
    }

    return ret;
}

int GPUExecutor::runTnrFrame(const std::shared_ptr<CameraBuffer>& inBuf,
                             std::shared_ptr<CameraBuffer> outBuf) {
    PERF_CAMERA_ATRACE();
    CheckError(!inBuf->getBufferAddr(), UNKNOWN_ERROR, "%s invalid input buffer", __func__);

    if (mPolicyManager) {
        // Check if need to wait other executors.
        mPolicyManager->wait(mName);
    }
    LOG2("Enter %s executor name:%s, sequence: %u", __func__, mName.c_str(), inBuf->getSequence());
    TRACE_LOG_PROCESS(mName.c_str(), __func__, MAKE_COLOR(inBuf->getSequence()),
                      inBuf->getSequence());

    uint32_t sequence = inBuf->getSequence();
    int ret = OK;
    if (mIntelTNR && !isBypassStillTnr(sequence)) {
        ret = updateTnrISPConfig(mTnr7usParam, sequence);
        CheckError(ret != OK, UNKNOWN_ERROR, " %s Failed to update TNR parameters", __func__);
    }

    int fd = outBuf->getFd();
    int memoryType = outBuf->getMemory();
    int bufferSize = outBuf->getBufferSize();
    void* outPtr = (memoryType == V4L2_MEMORY_DMABUF)
                       ? CameraBuffer::mapDmaBufferAddr(fd, bufferSize)
                       : outBuf->getBufferAddr();
    if (!outPtr) return UNKNOWN_ERROR;

    if (!mIntelTNR || isBypassStillTnr(sequence)) {
        MEMCPY_S(outPtr, bufferSize, inBuf->getBufferAddr(), inBuf->getBufferSize());
        if (memoryType == V4L2_MEMORY_DMABUF) {
            CameraBuffer::unmapDmaBufferAddr(outPtr, bufferSize);
        }
        return OK;
    }

    if (icamera::PlatformData::isStillTnrPrior()) {
        // when running still stream tnr, should skip video tnr to decrease still capture duration.
        if (mStreamId == VIDEO_STREAM_ID && !mGPULock.try_lock()) {
            MEMCPY_S(outPtr, bufferSize, inBuf->getBufferAddr(), inBuf->getBufferSize());
            if (memoryType == V4L2_MEMORY_DMABUF) {
                CameraBuffer::unmapDmaBufferAddr(outPtr, bufferSize);
            }
            mLastSequence = UINT32_MAX;
            LOG2("%s executor name:%s, skip frame sequence: %ld", __func__, mName.c_str(),
                 inBuf->getSequence());
            return OK;
        } else if (mStreamId == STILL_STREAM_ID) {
            mGPULock.lock();
        }
    }

    if (mLastSequence == UINT32_MAX || sequence - mLastSequence >= TNR7US_RESTART_THRESHOLD) {
        mTnr7usParam->bc.is_first_frame = 1;
    } else {
        mTnr7usParam->bc.is_first_frame = 0;
    }

    void* dstBuf = outPtr;
    int dstSize = bufferSize;
    int dstFd = fd;
    std::map<int64_t, void*>::iterator tnrOutBuf;
    // use internal tnr buffer for ZSL and none APP buffer request usage
    bool useInternalBuffer = mUseInternalTnrBuffer || memoryType != V4L2_MEMORY_DMABUF;
    if (useInternalBuffer) {
        std::unique_lock<std::mutex> lock(mTnrOutBufMapLock);
        tnrOutBuf = mTnrOutBufMap.begin();
        dstBuf = tnrOutBuf->second;
        dstSize = mOutBufferSize;
        // when use internal tnr buffer, we don't need to use fd map buffer
        dstFd = -1;
    }
    ret = mIntelTNR->runTnrFrame(inBuf->getBufferAddr(), dstBuf, inBuf->getBufferSize(), dstSize,
                                 mTnr7usParam, dstFd);

    if (ret == OK) {
        if (useInternalBuffer) {
            MEMCPY_S(outPtr, bufferSize, tnrOutBuf->second, mOutBufferSize);
        }
    } else {
        LOG2("%s, Just copy source buffer if run TNR failed", __func__);
        MEMCPY_S(outPtr, bufferSize, inBuf->getBufferAddr(), inBuf->getBufferSize());
    }
    if (icamera::PlatformData::isStillTnrPrior()) {
        mGPULock.unlock();
    }

    if (useInternalBuffer) {
        std::unique_lock<std::mutex> lock(mTnrOutBufMapLock);
        mTnrOutBufMap.erase(tnrOutBuf->first);
        mTnrOutBufMap[sequence] = tnrOutBuf->second;
        LOG2("%s, outBuf->first %ld, outBuf->second %p", __func__, tnrOutBuf->first,
             tnrOutBuf->second);
    }

    if (memoryType == V4L2_MEMORY_DMABUF) {
        CameraBuffer::unmapDmaBufferAddr(outPtr, bufferSize);
    }
    CheckError(ret != OK, UNKNOWN_ERROR, " %s tnr7us run frame failed", __func__);
    mLastSequence = sequence;

    if (mStreamId != STILL_STREAM_ID) {
        // still stream will update params in tnr7us, skip async update
        float totalGain = 0.0f;
        ret = getTotalGain(sequence, &totalGain);
        CheckError(ret, UNKNOWN_ERROR, "@%s, Failed to get total gain", __func__);

        // update tnr param when total gain changes
        bool isTnrParamForceUpdate = icamera::PlatformData::isTnrParamForceUpdate();
        ret = mIntelTNR->asyncParamUpdate(static_cast<int>(totalGain), isTnrParamForceUpdate);
    }

    LOG2("Exit %s executor name:%s, sequence: %u", __func__, mName.c_str(), inBuf->getSequence());
    return ret;
}

int GPUExecutor::dumpTnrParameters(uint32_t sequence) {
    const int DUMP_FILE_SIZE = 0x1000;
    std::string dumpFileName =
        std::string("/home/tnr7-") + std::to_string(sequence) + std::string(".txt");

    LOG1("%s save tnr7 parameters to file %s", __func__, dumpFileName.c_str());
    tnr7_bc_1_0_t* tnr7_bc = &(mTnr7usParam->bc);
    tnr7_blend_1_0_t* tnr7_blend = &(mTnr7usParam->blend);
    tnr7_ims_1_0_t* tnr7_ims = &(mTnr7usParam->ims);
    char* dumpData = reinterpret_cast<char*>(malloc(DUMP_FILE_SIZE));
    CheckError(dumpData == nullptr, NO_MEMORY, "failed to allocate memory for dump tnr7");

    FILE* parFile = fopen(dumpFileName.c_str(), "wb");
    if (parFile) {
        int shift = 0;
        size_t length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%s\n", "tnr7_bc");
        shift += length;
        for (int i = 0; i < sizeof(tnr7_bc_1_0_t) / sizeof(int32_t); i++) {
            length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%u\n",
                              *(reinterpret_cast<int32_t*>(tnr7_bc) + i));
            shift += length;
        }
        length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%s\n", "tnr7_blend");
        shift += length;
        for (int i = 0; i < sizeof(tnr7_blend_1_0_t) / sizeof(int32_t); i++) {
            length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%u\n",
                              *(reinterpret_cast<int32_t*>(tnr7_blend) + i));
            shift += length;
        }
        length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%s\n", "tnr7_ims");
        shift += length;
        for (int i = 0; i < sizeof(tnr7_ims_1_0_t) / sizeof(int32_t); i++) {
            length = snprintf(dumpData + shift, DUMP_FILE_SIZE - shift, "%u\n",
                              *(reinterpret_cast<int32_t*>(tnr7_ims) + i));
            shift += length;
        }

        fwrite(dumpData, shift, 1, parFile);
        fclose(parFile);
    } else {
        LOGW("tnr7 failed to open dump file %s", (dumpFileName + std::to_string(sequence)).c_str());
    }
    free(dumpData);
    return OK;
}
}  // namespace icamera
