// NOWHINE ENTIRE FILE
//-------------------------------------------------------------------------
// Copyright (c) 2021, 2023 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
//------------------------------------------------------------------------

#ifndef __NCLIBVBSEUTILS_H__
#define __NCLIBVBSEUTILS_H__

#include <stdint.h>
#include "GeoLib.h"
#include "Depth_Chromatix_v10.h"

//-------------------------------------------------------------------------
// Stereo Params to Ica Transform
//-------------------------------------------------------------------------

enum NcLbVbseRotation
{
    NCLIB_VBSE_ROTATION_NONE,
    NCLIB_VBSE_ROTATION_90,
    NCLIB_VBSE_ROTATION_MINUS_90
};


/** Domain of alignment matrix */
enum NcLibDepthRoiMode
{
    NCLIB_DEPTH_ROI_MODE_GET       = 0,     /**< Use input ROI */
    NCLIB_DEPTH_ROI_MODE_CALC,              /**< Calculate ROI based on AF (auto focus) map*/

    NCLIB_DEPTH_ROI_MODE_NUM,               /**< not real mode, for SW purpose */
};

// These fields are set based on tags. The source of the information comes from the structure AFFocusMapInfo
struct PDGridConfig
{
    uint32_t horiRegionOffset;
    uint32_t vertRegionOffset;
    uint32_t widhtOfRegion;
    uint32_t heightOfRegion;
    uint32_t horiNumOfRegion;
    uint32_t vertNumOfRegion;
};

struct NcLibFocusMapData
{
    int32_t*              defocusMap;                              /**< defocus map (from pdlib) */
    uint32_t*             confidenceMap;                           /**< confidence of each entry in focus_map */
    NcLibImageSize        inputImageSize;                          /**< The input image size in pixels that was processed by pdlib.
                                                                        mapData.pdlibConfig parameters are expressed based on this image size.*/
    DEPTH_CALC_FOCUS_ROI* calibParams;                             /**< Chromatix parameters */
    PDGridConfig*         pdlibConfig;                             /**< pdlib that arrived from tags*/
    bool                  forceSceneChange;                        /**< Reset the focus roi calculation (cancel out "history") */
    float                 resetPositionDifferenceInMap;            /**< Temporal threshold, Valid range between [0.f, 32.f] */
    uint32_t*             intermediateBuffer;                      /**< Buffer that is used for internal calculations,
                                                                        size of buffer should be at least:
                                                                        2* sizeof(uint32_t) *(defocusMapSize.widthPixels+1) * (defocusMapSize.heightLines+1) in bytes  */
    uint32_t              intermediateBufferSize;                  /**< intermediateBuffer in bytes */
};

struct NclibStereoParams
{
    uint16_t stereoCalibVersion;                            /**< Stereo calibration params definition may be updated, this flag will indicate which version we are using.
                                                            *    0 - opencv like, two cameras rectification. */
    uint16_t stereoCalibSubVersion;                         /**< Subversion of stereo calibration. */
    float distCoeffsMain[8];                                /**< Lens distortion coefficients identified as:
                                                            *    k1, k2, p1, p2, k3, k4, k5, k6
                                                            *    k3-k6 are optional and, if not available, should be set to zero when parsing the data and creating this struct.
                                                            *    Given around the "optical center" of the calibration image after it is normalized by image size. */
    NcLibPerspTransformSingle   cameraMatrixMain;           /**< Original camera matrix - 3x3 matrix. Given in the calibration image coordinate system. */
    NcLibPerspTransformSingle   newCameraMatrixMain;        /**< Virtual camera matrix to describe the perspective after rotation - 3x3 matrix.
                                                            *    Given in the calibration image coordinate system. */
    NcLibPerspTransformSingle   rotationMatrixMain;         /**< 3D rotation matrix for making the epipolar lines parallel to the baseline.
                                                            *    Given in the undistorted and normalized calibration image coordinate system. */
    NcLbVbseRotation            rotationFlagMain;           /**< 0: No rotation, 1: 90 degrees, 2: -90 degrees. */
    float                       calibFocalLengthRatioMain;  /**< Focus length ratio that matches calibration params. */
    float                       distCoeffsAux[8];           /**< Lens distortion coefficients identified as:
                                                            *    k1, k2, p1, p2, k3, k4, k5, k6
                                                            *    k3-k6 are optional and should be set to zero when parsing the data and creating this struct.
                                                            *    Given around the "optic center" of the calibration image after it is normalized by image size. */
    NcLibPerspTransformSingle   cameraMatrixAux;            /**< Original camera matrix - 3x3 matrix. Given in the calibration image coordinate system. */
    NcLibPerspTransformSingle   newCameraMatrixAux;         /**< Virtual camera matrix to describe the perspective after rotation - 3x3 matrix.
                                                            *    Given in the calibration image coordinate system.
                                                            *    Currently not used, expected to be identical to newCameraMatrixMain. */
    NcLibPerspTransformSingle   rotationMatrixAux;          /**< 3D rotation matrix for making the epipolar lines parallel to the baseline.
                                                            *    Given in the undistorted and normalized calibration image coordinate system. */
    NcLbVbseRotation            rotationFlagAux;            /**< 0: No rotation, 1: 90 degrees, 2: -90 degrees. */
    float                       calibFocalLengthRatioAux;   /**< Focus length ratio that matches calibration params. */

    NcLibROI calibImageCropMain;                            /**<  Main image crop with respect to the full frame without scaling
                                                            *    performed at calibration time. Domain size is for debugging purposes only. */
    float calibImageScaleMain;                              /**< Main image scaling ratio performed at calibration time. */
    NcLibROI calibImageCropAux;                             /**< Auxiliary image crop with respect to the full frame without scaling
                                                            *    performed at calibration time. Domain size is for debugging purposes only. */
    float calibImageScaleAux;                               /**< Auxiliary image scaling ratio performed at calibration time. */
};

struct NcLibStereoParams2IcaTransformIn
{
    NcLibROI cropMain;                  /**< Crop of the main image with respect to the full frame without scaling. Domain size for debugging purposes only. */
    float scaleMain;                    /**< Scaling ratio that was done to the image compared to native resolution.
                                             For example, with 4K sensor and 1080p video, main IFE full output goes through ~x1/2 scale and after additional DS4 we have ~x1/8 scale.
                                             Scale should be exact and consistent with calibImageScaleMain. */
    NcLibROI cropAux;                   /**< Crop of the auxiliary image with respect to the full frame without scaling. Domain size for debugging purposes only. */
    float scaleAux;                     /**< Scaling ratio that was done to the image compared to native resolution.
                                             For example, with 4K sensor and 1080p video, main IFE full output goes through ~x1/2 scale and after additional DS4 we have ~x1/8 scale.
                                             Scale should be exact and consistent with calibImageScaleAux. */
    bool bApplyFocalLengthCorrection;   /**< if iFOVC isn't active, set to true in order to adjust intrinsic parameters. Default: 0 */
    float focalLengthRatioMain;         /**< iFOVC should do the trick. Default to 1. */
    float focalLengthRatioAux;          /**< iFOVC should do the trick. Default to 1. */
};

struct NcLibStereoParams2IcaTransformOut
{
    NcLibIcaGrid rectificationTransformMain;     /** < Main rectification grid */
    NcLibIcaGrid rectificationTransformAux;      /** < Aux rectification grid */
    NcLibIcaGrid derectificationTransformMain;   /** < Main derectification grid */
};

/**
*  Deprecated: Will be removed in the future version.
*              Please use NcLibStereoParams2IcaTransform() that returns NcLibStereoParams2IcaPerspTransformOut.
*
*  @brief  Calculate ICA transforms from stereo calibration results parameters.
*
*  @param [in]      stereoParams              Stereo calibrations input struct.
*  @param [in]      in                        Current frame data.
*  @param [out]     out                       Output struct filled by the function.
*
* @return NC_LIB_SUCCESS on success or appropriate error code on failure.
*/
int32_t NcLibStereoParams2IcaTransform(
    const NclibStereoParams* stereoParams,
    const NcLibStereoParams2IcaTransformIn* in,
    NcLibStereoParams2IcaTransformOut* out);

struct NcLibStereoParams2IcaPerspTransformOut
{
    NcLibWarpMatrices rectificationTransformMain;     /** < Main rectification perspective */
    NcLibWarpMatrices rectificationTransformAux;      /** < Aux rectification perspective */
    NcLibWarpMatrices derectificationTransformMain;   /** < Main derectification perspective */
};

/**
*  @brief  Calculate ICA perspective transform from stereo calibration results parameters.
*
*  @param [in]      stereoParams              Stereo calibrations input struct.
*  @param [in]      in                        Current frame data.
*  @param [out]     out                       Output struct filled by the function.
*
* @return NC_LIB_SUCCESS on success or appropriate error code on failure.
*/
int32_t NcLibStereoParams2IcaTransform(
    const NclibStereoParams* stereoParams,
    const NcLibStereoParams2IcaTransformIn* in,
    NcLibStereoParams2IcaPerspTransformOut* out);

//-------------------------------------------------------------------------
// Calculate focus ROI
//-------------------------------------------------------------------------

/**
*  @brief   This function calculates the focus ROI that will be delivered to depth post processing.
*           The function works in two modes:
*           1. Gets distorted ROI as input
*           2. Calculates ROI based on focus map
*           In both cases, the function warps the ROI to depth post process domain (i.e. undistorted+rectified)
*
*  @param [in]      mode               Operation mode. Should be equal to the vale that is defined
*                                      in Chromatix (Depth::calc_focus_roi:mode).
*  @param [in]      inputFocusRoi      The input focus ROI. Can be NULL if (mode != NCLIB_DEPTH_ROI_MODE_GET).
                                        // todo: review the next line
*                                      inputFocusRoi.imageSize is expected to be IFE_OUT image size.
*  @param [in]      mapData            Information about AF map. Can be NULL if (mode != NCLIB_DEPTH_ROI_MODE_CALC).
*  @param [in]      transform          out2in grid transform ( undistortion + rectification
*                                      should be represented by the grid). The grid is defined in virtual domain.
*  @param [in]      transformInputRoi  ROI on which the transform is defined.
*  @param [in]      outputImageSize    DFS size.
*  @param [out]     outputFocusRoi     Focus roi in the image dimensions.
*  @param [in,out]  context            Internal Frame to frame context. Init to zeros in first frame or scene change.
*                                      The context should be preserved between frames.
*                                      The context is only used in PDnet case.
*
* @return NC_LIB_SUCCESS in case of success, otherwise failed.
*/
int32_t NcLibDepthCalcFocusRoi( NcLibDepthRoiMode mode,
                                const NcLibROI* inputFocusRoi,
                                const NcLibFocusMapData* mapData,
                                const NcLibIcaGrid* transform,
                                const NcLibROI* transformInputRoi,
                                const NcLibImageSize* outputImageSize,
                                NcLibROI* outputFocusRoi,
                                uint8_t context[256] );


// Dumps to file NcLibDepthCalcFocusRoi input parameters
void DumpNcLibDepthCalcFocusRoi(
    NcLibDepthRoiMode mode,
    const NcLibROI* inputFocusRoi,
    const NcLibFocusMapData* mapData,
    const NcLibIcaGrid* icaGrid,
    const NcLibROI* transformInputRoi,
    const NcLibImageSize* outputImageSize,
    FILE* dumpFile);

//-------------------------------------------------------------------------
// Map IPE config
//-------------------------------------------------------------------------

struct DepthMapIpeCfgIn
{
    NcLibImageSize ipeInSize;   /**< Main IPE full pass YUV420 input Image size (== input ROI) */
    NcLibROI dfsIpeInRoi;       /**< DFS map IPE YUV420 input map ROI */
    NcLibFloat2 ipeMaxFovSize;  /**< Main IPE full pass Input max Fov size ( fractional ) */
    bool isRoiRotated;          /**< Whether dfsIpeInRoi is 90 degrees rotated */
};

/**
*  @brief  Calculate IPE Map Configurations for DFS.
*
*  @param [in]      in                        Struct of input parameters.
*  @param [out]     out                       IPE configurations (ICA & striping) filled by the function.
*
* @return NC_LIB_SUCCESS on success or appropriate error code on failure.
*/
int32_t NcLibDepthMapIpeCfg(const DepthMapIpeCfgIn* in, GeoLib2IpeFrameCfg* out);

// Validates IPE configuration (DepthMapIpeCfg output) struct
bool ValidateNcLibDepthMapIpeCfg(const GeoLib2IpeFrameCfg* frameCfg);

/**
* @brief Per-frame Depth Map ICA configuration
* Can be skipped for Video or no-zoom case, where ICA configuration is trivial
*
* @param [in]  mapCfg       Initial AI IPE configuration (output by NcLibDepthMapIpeCfg)
* @param [in]  dfsInRoi     Current stream ROI normalized to DepthMap
* @param [out] icaFull      Per frame 1:1 ICA mapping of DepthMap FOV for this frame
*
* @return NC_LIB_SUCCESS or appropriate error code on failure.
*/
int32_t NcLibDepthMapCalcFrame(const GeoLib2IpeFrameCfg* mapCfg,
                               const NcLibROI* dfsInRoi,
                               GeoLib2IcaMapping* icaFull);

//-------------------------------------------------------------------------
// DFS AUX DSX calc
//-------------------------------------------------------------------------

struct NcLibDfsCalcDsxIn
{
    NcLibROI auxIfeOut;         /**< Aux IFE output 1:1 Domain (YUV420) & ROI */
    float sensorFovRatio;       /**< Ratio of FOV between sensors (Aux/Main) */
    float maxIfeDzRatio;        /**< Ratio of IFE DS at DZ = 1 between sensors (Aux/Main) */
    float auxMarginRatio;       /**< Rectification margins, range [0:1] (1 = 100% margins)
                                     Defined in Chromatix (Depth::top:aux_margin_ratio) */
};

struct NcLibDfsCalcDsxOut
{
    GeoLib2CropAndScale dfsDsxConfig;   /**< Aux DSX config, should be passed to DSX and to NcLibCalcAuxRectificationRoi */
    NcLibROI dfsMainRoi;                /**< Main ROI in DSX output buffer */
    NcLibROI dfsAuxRoi;                 /**< Aux ROI with rect margins in DSX output buffer */
};

/**
*  @brief  Calculate DSX Configurations for DFS.
*
*  @param[in]      in                        Struct of input parameters.
*  @param[out]     out                       Aux configurations filled by the function.
*
* @return NC_LIB_SUCCESS on success or appropriate error code on failure.
*/
int32_t NcLibDfsCalcDsx(const NcLibDfsCalcDsxIn* in,
                        NcLibDfsCalcDsxOut* out);

// Validates DFS DSX (NcLibDfsCalcDsx output) struct
bool ValidateNcLibDfsCalcDsx(const NcLibDfsCalcDsxOut* dsx);

// Dumps to file DFS DSX configuration (NcLibDfsCalcDsx output) struct
void DumpNcLibDfsCalcDsx(const NcLibDfsCalcDsxOut* dsx, const char* prefix, FILE* dumpFile);


//-------------------------------------------------------------------------
// Rectification configuration
//-------------------------------------------------------------------------

struct NcLibRectificationCfgIn
{
    NcLibImageSize mainFullSize;       /**< Size of the Full main image. Rectification is assumed to receive DC4 of this size. */
    NcLbVbseRotation mainRotation;     /**< Rotation flag of main image, defined in sensor stereo params */
    NcLibImageSize tunedDfsSize[3];    /**< Requested DFS size LUT (Depth Chromatix: top.dfs_width/height)*/
    NcLibFloat2 preCropRatio;          /**< Sensor and IFE crop ratio at DZ=1. E.g. for full sensor aspect ratio 4:3
                                       *    and IFE output 16:9, preCropRatio is expected to be around (1, 0.75). */
    NcLibFloat2 maxExtraScaling;       /**< Max allowed upscaling (Depth Chromatix: common_params.dfs_max_extra_scale_x/y) */
    bool dppEnabled;                   /**< If DPP is enabled, rectified size will adhere to its size constraints. */
};

struct NcLibRectificationCfgOut
{
    NcLibImageSize outSize;     /**< GCE output size. Passed as part of ICONFIG_OUTPUT_IMAGE_INFO_DSX. */
    bool dsxEn;                 /**< Whether DSX is enabled, ICONFIG_WARP_SCALE_DSX_EN in EVA API. */
    NcLibFloat2 scale;          /**< Required scale ratio, >1 for downscale, <1 for upscale by 1/scale.
                                *    ICONFIG_SCALE_RATIO_WIDTH & ICONFIG_SCALE_RATIO_HEIGHT in EVA API. */
    NcLibROI mainTransformRoi;  /**< If the transform is defined on the full image, this ROI specifies the transform area
                                *    relative to the main rectification input. Warp engine should be mapped to this ROI.
                                *    FCONFIG_TRANSFORM_ROI in EVA API. */
};

/**
*  @brief  Calculate configuration for rectification warp engine (EVA Warp).
*          The configuration is same for main and auxiliary image and does not change between frames, except for the Aux
*          transform ROI is. See NcLibCalcAuxRectificationRoi for the latter.
*
*  @param[in]      in                        Struct of input parameters.
*  @param[out]     out                       Aux configurations filled by the function.
*
*  @return NC_LIB_SUCCESS on success or error code on failure.
*/
int32_t NcLibCalcRectificationCfg(const NcLibRectificationCfgIn* in, NcLibRectificationCfgOut* out);

/**
*  @brief  Calculate transform ROI for aux image rectification warp engine (EVA Warp).
*          The function is needed if the image is cropped before rectification (i.e. IFE DSX scale ratio is not constant 4),
*          and the transform matches the full image.
*          The function is not needed if:
*          1. IFE DSX does not crop and its scale ratio is constant 4. In this case mainTransformRoi returned by
*             NcLibCalcRectificationCfg can be used for aux image too.
*          2. The transform matches the cropped rectification input, e.g. it's resampled to the IFE DSX crop. In this case warp
*             engine will be mapped to the entire image and the ROI does not need to be explicitly specified.
*
*  @param[in]      dfsDsxConfig              DSX configuration returned by NcLibDfsCalcDsx.
*  @param[out]     auxTransformRoi           Transform ROI relative to aux rectification input. Warp engine should be mapped to
*                                            this ROI. FCONFIG_TRANSFORM_ROI in EVA API.
*
*  @return NC_LIB_SUCCESS on success or error code on failure.
*/
int32_t NcLibCalcAuxRectificationRoi(const GeoLib2CropAndScale* dfsDsxConfig, NcLibROI* auxTransformRoi);


#endif //__NCLIBVBSEUTILS_H__
