///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017-2023 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxchinodeutil.h
/// @brief CamX CHI node specific utility implementation
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CAMXCHINODEUTILS_H
#define CAMXCHINODEUTILS_H

#if defined (_WIN32)
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#elif defined (_LINUX)

#include <stdarg.h>
#include <stdio.h>
#include <dlfcn.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#endif // (_WIN32) (_LINUX)

#include "camxcdktypes.h"
#include "chinode.h"
#include "chivendortag.h"
#include "chxdebugprint.h"
#include "chistaticdata.h"


// Define target type
#if defined(__aarch64__)
#define TARGET_ARM64
#elif defined(__arm__)
#define TARGET_ARM
#endif

/** @addtogroup chi_node_macros
@{ */

typedef VOID* CHILIBRARYHANDLE;                       ///< Pointer to the handle for the dynamic library.

static const UINT64 NSEC_PER_SEC = 1000000000ull;     ///< Constant offset between the Android elapsedRealTimeNano clock and
                                                      ///  the Qtimer.

static const UINT32 DEFAULT_FLUSH_RESPONSE_TIME = 5;  ///< Default flush response time (in milliseconds).

#define NanoToMicro(x) (x / 1000)                     ///< Convert from nanoseconds to microseconds.
#define MicroToNano(x) (x * 1000)                     ///< Convert from microseconds to nanoseconds.
#define NanoToSec(x) (x / 1000000000)                 ///< Convert from nanoseconds to seconds.

#define CHI_UNREFERENCED_PARAM(param) (void)param     ///< Unreferenced macro helper.


#ifndef DOXYGEN_SHOULD_SKIP_THIS
// NOWHINE FILE CP049: Use static_assert instead of CAMX_STATIC_ASSERT(_MESSAGE)
#define CHI_STATIC_ASSERT(condition) static_assert(condition, #condition)

// NOWHINE FILE CP049: Use assert instead of CAMX_ASSERT(_MESSAGE)
#define CHI_ASSERT(condition) assert(condition)
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


// Macros for calloc and free
#define CHI_CALLOC ChiNodeUtils::MemCalloc       ///< Allocate memory resources.
#define CHI_FREE   ChiNodeUtils::MemFree         ///< Free memory resources.

/** @} */ /* end_addtogroup chi_node_macros */


/// @ingroup chi_node_specific_util
/// @brief General node-specific utility class implementation.
class ChiNodeUtils
{
public:

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetMetaData @endcond
    ///
    /// @brief Gets the required metadata from the camera system.
    ///
    /// @datatypes
    /// #CHIMETADATATYPE \n
    /// #CHINODEINTERFACE
    /// #CHIHANDLE
    ///
    /// @param[in] requestId          Identifier for the current request.
    /// @param[in] tagId              Identifier for the tag to get from the camera system.
    /// @param[in] metadataType       Type of metadata: static or dynamic.
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    /// @param[in] typeId             Identifier for the tag to get from the camera system.
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* GetMetaData(
        UINT64            requestId,
        UINT32            tagId,
        CHIMETADATATYPE   metadataType,
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession,
        const UINT32      typeId = 0);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetDataList @endcond
    ///
    /// @brief Gets a list of all required metadata from the camera system.
    ///
    /// @datatypes
    /// #CHIMETADATATYPE \n
    /// #CHINODEINTERFACE \n
    /// #CHIHANDLE
    ///
    /// @param[in] requestId          Identifier for the current request.
    /// @param[in] tagId              Identifier for the tag to get from the camera system.
    /// @param[in] metadataType       Type of metadata: static or dynamic.
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    /// @param[in] typeId             Identifier for the context that corresponds to a metadata tag.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* GetDataList(
        UINT64            requestId,
        UINT32            tagId,
        CHIMETADATATYPE   metadataType,
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession,
        const UINT32      typeId = 0);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond ForceDRQtoRemoveDependencies @endcond
    ///
    /// @brief Forces the deferred request queue (DRQ) to remove the dependencies of a node for all previous requests
    ///
    /// @datatypes
    /// #CHINODEINTERFACE \n
    /// #CHIHANDLE
    ///
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    /// @param[in] requestId          RequestId
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID ForceDRQtoRemoveDependencies(
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession,
        UINT64            requestId);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetMulticamDynamicMetaByCamId @endcond
    ///
    /// @brief Gets the required dynamic metadata for a camera ID.
    ///
    /// @datatypes
    /// #CHIMETADATATYPE \n
    /// #CHINODEINTERFACE \n
    /// #CHIHANDLE
    ///
    /// @param[in] requestId          Identifier for the current request.
    /// @param[in] tagId              Identifier for the tag to get from the camera system.
    /// @param[in] metadataType       Type of metadata: static or dynamic.
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    /// @param[in] cameraId           Identifier for the camera associated with the metadata from which the list of tags must
    ///                               be fetched.
    /// @param[in] typeId             Identifier for the context that corresponds to a metadata tag.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* GetMulticamDynamicMetaByCamId(
        UINT64            requestId,
        UINT32            tagId,
        CHIMETADATATYPE   metadataType,
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession,
        UINT32            cameraId,
        const UINT32      typeId = 0);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetStaticMetaData @endcond
    ///
    /// @brief Gets the required static metadata from the camera system.
    ///
    /// @datatypes
    /// #CHINODEINTERFACE \n
    /// #CHIHANDLE
    ///
    /// @param[in] cameraId           ID of the camera for the current request.
    /// @param[in] tagId              ID of the tag to get from the camera system.
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* GetStaticMetaData(
        UINT32            cameraId,
        UINT32            tagId,
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetPSMetaData @endcond
    ///
    /// @brief Gets the required port-specific metadata from the camera system.
    ///
    /// @datatypes
    /// #CHINODEINTERFACE \n
    /// #CHIHANDLE
    ///
    /// @param[in] requestId          Identifier for the current request.
    /// @param[in] tagId              Identifier for the tag to get from the camera system.
    /// @param[in] inputPortId        Identifier for the input that corresponds to the request
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* GetPSMetaData(
        UINT64            requestId,
        UINT32            tagId,
        UINT32            inputPortId,
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond SetNodeInterface @endcond
    ///
    /// @brief Implements a generic method to handle PFCHINODESETNODEINTERFACE() for all CHI nodes.
    ///
    /// @datatypes
    /// #CHINODEINTERFACE
    ///
    /// @param[in] pNodeInterface             Pointer to the CHI node interface structure passed as part of
    ///                                       PFCHINODESETNODEINTERFACE().
    /// @param[in] pComponentName             Pointer to the name of the CHI node instance.
    /// @param[in] pNodeInstChiNodeInterface  Pointer to the CHI node interface associated with the instance of the calling
    ///                                       CHI node.
    /// @param[in] pNodeVendorTagBase         Pointer to the vendor tag base for the CHI node.
    ///
    /// @return #CDKResultSuccess or an error code (see Section @xref{hdr:resultMessages}). @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult SetNodeInterface(
        CHINODEINTERFACE* pNodeInterface,
        const CHAR*       pComponentName,
        CHINODEINTERFACE* pNodeInstChiNodeInterface,
        UINT32*           pNodeVendorTagBase);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond QueryVendorTag @endcond
    ///
    /// @brief Implements an instance of PFNCHIQUERYVENDORTAG().
    ///
    /// @datatypes
    /// #CHIQUERYVENDORTAG \n
    /// #CHIVENDORTAGINFO
    ///
    /// @param[in] pQueryVendorTag     Pointer to the structure that returns the exported vendor tag.
    /// @param[in] pNodeVendorTagInfo  Pointer to the vendor tag information for the CHI node.
    ///
    /// @return #CDKResultSuccess or an error code (see Section @xref{hdr:resultMessages}).
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult QueryVendorTag(
        CHIQUERYVENDORTAG* pQueryVendorTag,
        CHIVENDORTAGINFO*  pNodeVendorTagInfo);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetOutputOptimalSize @endcond
    ///
    /// @brief Implements to get the optimal size for output port.
    ///
    /// @param[in] width         the input port requirement optimal width.
    /// @param[in] height        the input port requirement optimal height.
    /// @param[in] maxWidth      max optimal width of one o/p port.
    /// @param[in] maxHeight     max optimal height of one o/p port.
    /// @param[in] maxFOVAR      AR with max FOV for different stream AR requirement
    /// @param[in] isAR43        is the current connected stream is 4:3
    /// @param[in] isAR169       is the current connected stream is 16:9
    /// @param[in] ignoreOptimal flag to indicate that this optimal requirement can be ignored
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID GetOutputOptimalSize(
        UINT32  width,
        UINT32  height,
        UINT32& maxWidth,
        UINT32& maxHeight,
        UINT32& maxFOVAR,
        BOOL&   isAR43,
        BOOL&   isAR169,
        BOOL    ignoreOptimal);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond DefaultBufferNegotiation @endcond
    ///
    /// @brief Implements the default buffer negotiation logic.
    ///
    /// @datatypes
    /// #CHINODEQUERYBUFFERINFO
    ///
    /// @param[in] pQueryBufferInfo  Pointer to the structure that contains the required output/input buffer information.
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID DefaultBufferNegotiation(
        CHINODEQUERYBUFFERINFO* pQueryBufferInfo);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond SNPrintF @endcond
    ///
    /// @brief Writes formatted data from a variable argument list to a sized buffer.
    ///
    /// @param[in] pDst     Pointer to the destination buffer.
    /// @param[in] sizeDst  Size of the destination buffer
    /// @param[in] pFormat  Pointer to the format string (in printf style).
    /// @param[in] ...      Parameters required by the format.
    ///
    /// @return Number of characters written.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline INT SNPrintF(
        CHAR*       pDst,
        SIZE_T      sizeDst,
        const CHAR* pFormat,
        ...)
    {
        INT     numCharWritten;
        va_list args;

        va_start(args, pFormat);
        numCharWritten = VSNPrintF(pDst, sizeDst, pFormat, args);
        va_end(args);

        return numCharWritten;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond VSNPrintF @endcond
    ///
    /// @brief Writes formatted data from a variable argument list to a sized buffer.
    ///
    /// @param[in] pDst     Pointer to the destination buffer.
    /// @param[in] sizeDst  Size of the destination buffer.
    /// @param[in] pFormat  Pointer to the format string (in printf style).
    /// @param[in] argptr   Parameters required by the format.
    ///
    /// @return Number of characters written. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC INT VSNPrintF(
        CHAR*       pDst,
        SIZE_T      sizeDst,
        const CHAR* pFormat,
        va_list     argptr);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond AddSoctoPath @endcond
    ///
    /// @brief Gets a handle to the named library (*.dll, *.so, and so on).
    ///
    /// @param[in] pLibraryPath  Pointer to the path of the library.
    ///
    /// @return updated soc id library path to map
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const CHAR* AddSoctoPath(const CHAR* pLibraryPath);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond LibMap @endcond
    ///
    /// @brief Gets a handle to the named library (*.dll, *.so, and so on).
    ///
    /// @note1hang We recommend using use LibMapFullName() instead of this function.
    ///
    /// @param[in] pLibraryName  Pointer to the name of library.
    /// @param[in] pLibraryPath  Pointer to the path of the library.
    ///
    /// @return Handle of the named module upon success. Otherwise, NULL upon a failure.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CHILIBRARYHANDLE LibMap(
        const CHAR* pLibraryName,
        const CHAR* pLibraryPath);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond LibMapFullName @endcond
    ///
    /// @brief Gets a handle to the named library (*.dll, *.so, and so on).
    ///
    /// @param[in] pLibraryName  Pointer to the name of the library.
    ///
    /// @return Handle of the named module upon success. Otherwise, NULL upon a failure.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CHILIBRARYHANDLE LibMapFullName(
        const CHAR* pLibraryName);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond LibUnmap @endcond
    ///
    /// @brief Unmaps a library previously mapped by LibMap().
    ///
    /// @datatypes
    /// #CHILIBRARYHANDLE
    ///
    /// @param[in] hLibrary  Handle to the library from LibMap().
    ///
    /// @return #CDKResultSuccess or #CDKResultEFailed. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult LibUnmap(
        CHILIBRARYHANDLE hLibrary);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond LibGetAddr @endcond
    ///
    /// @brief Finds an entry point in a library that was previously loaded by LibMap().
    ///
    /// @datatypes
    /// #CHILIBRARYHANDLE
    ///
    /// @param[in] hLibrary   Handle to the library from LibMap().
    /// @param[in] pProcName  Pointer to the name of the entry point to find.
    ///
    /// @return Pointer to the named entry point in the library upon success. Otherwise, NULL upon a failure.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* LibGetAddr(
        CHILIBRARYHANDLE hLibrary,
        const CHAR*      pProcName);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FloatToHalf @endcond
    ///
    /// @brief Converts a float value to a half float value.
    ///
    /// @param[in] f  Float value.
    ///
    /// @return Converted value. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC UINT16 FloatToHalf(
        FLOAT f);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond StrLCpy @endcond
    ///
    /// @brief Static function to copy a string with a maximum destination string length. Will always terminate. Source and
    ///        destination must not overlap
    ///
    /// @param[in, out]  pDst   Pointer to the char array to copy to.
    /// @param[in]       pSrc   Pointer to the char array to copy from.
    /// @param[in]       sizeDst  Size of destination buffer, in bytes
    ///
    /// @return VOID
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline VOID StrLCpy(
        CHAR*        pDst,
        const CHAR*  pSrc,
        SIZE_T       sizeDst)
    {
        if ((NULL != pDst) && (NULL != pSrc) && (sizeDst > 0))
        {
            strlcpy(pDst, pSrc, sizeDst);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetVendorTagBase @endcond
    ///
    /// @brief Gets the vendor tag base from a section and tag name.
    ///
    /// @datatypes
    /// #CHINODEINTERFACE \n
    /// #CHIVENDORTAGBASEINFO
    ///
    /// @param[in] pSectionName       Pointer to the name of the defined vendor tag section.
    /// @param[in] pTagname           Pointer to the defined vendor tag name.
    /// @param[in] pChiNodeInterface  Pointer to the CHI node interface associated with the instance of the calling CHI node.
    /// @param[in] pVendorTagBase     Pointer to the vendor tag base to be filled.
    ///
    /// @return #CDKResultSuccess or #CDKResultEFailed.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline CDKResult GetVendorTagBase(
        const CHAR*           pSectionName,
        const CHAR*           pTagname,
        CHINODEINTERFACE*     pChiNodeInterface,
        CHIVENDORTAGBASEINFO* pVendorTagBase)
    {
        CDKResult result = CDKResultSuccess;

        pVendorTagBase->size = sizeof(CHIVENDORTAGBASEINFO);
        pVendorTagBase->pComponentName = pSectionName;
        pVendorTagBase->pTagName = pTagname;
        result = pChiNodeInterface->pGetVendorTagBase(pVendorTagBase);

        return result;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FOpen @endcond
    ///
    /// @brief Opens a file in the file system.
    ///
    /// @param[in] pFilename  Pointer to the file.
    /// @param[in] pMode      Pointer to the file access mode string.
    ///
    /// @return File handle upon success, or NULL upon a failure. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC FILE* FOpen(
        const CHAR* pFilename,
        const CHAR* pMode);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FileNo @endcond
    ///
    /// @brief Gets a file handle for the descriptor.
    ///
    /// @param[in] pFile  Pointer to the file handle.
    ///
    /// @return File descriptor.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC  INT FileNo(
    FILE* pFile);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FClose @endcond
    ///
    /// @brief Closes the given file handle.
    ///
    /// @param[in] pFile  Pointer to the file handle.
    ///
    /// @return #CDKResultSuccess or #CDKResultEFailed.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult FClose(
        FILE* pFile);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FPrintF @endcond
    ///
    /// @brief Outputs a formatted string to the given file handle.
    ///
    /// @param[in] pFile   Pointer to the file handle.
    /// @param[in] format  Pointer to the format string, which is in printf style.
    /// @param[in] ...     Parameters required by the format string.
    ///
    /// @return Number of characters written. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC INT FPrintF(
        FILE*       pFile,
        const CHAR* format,
        ...);

    /** @weakgroup weakb_chi_node_specific_fseek
    @{ */
    static const INT SeekSet = SEEK_SET;    ///< Beginning of the file origin for %Fseek().
    static const INT SeekEnd = SEEK_END;    ///< End of the file origin for %Fseek().
    static const INT SeekCur = SEEK_CUR;    ///< Current position of the file pointer origin for %Fseek().
    /** @} */ /* end_weakgroupb weakb_chi_node_specific_fseek */

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FSeek @endcond
    ///
    /// @brief Moves the file pointer to a specified location.
    ///
    /// @param[in] pFile    Pointer to the file handle.
    /// @param[in] offset   Number of bytes from the file origin.
    /// @param[in] origin   Initial position of the file origin.
    ///
    /// @return #CDKResultSuccess or #CDKResultEFailed.
    ///
    /// @inputfile{group__weakb__chi__node__specific__fseek.tex} @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult FSeek(
        FILE*   pFile,
        INT64   offset,
        INT     origin);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FTell @endcond
    ///
    /// @brief Gets the current position of a file pointer.
    ///
    /// @param[in] pFile  Pointer to the file handle.
    ///
    /// @return Current file position upon success, or -1 for an error.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC INT64 FTell(
        FILE* pFile);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FRead @endcond
    ///
    /// @brief Reads data from a file handle.
    ///
    /// @param[in] pDst     Pointer to the destination memory.
    /// @param[in] dstSize  Size of the destination memory.
    /// @param[in] size     Size of the objects to read.
    /// @param[in] count    Maximum number of objects to read.
    /// @param[in] pFile    Pointer to the file handle.
    ///
    /// @return Number of objects that were read successfully.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC SIZE_T FRead(
        VOID*   pDst,
        SIZE_T  dstSize,
        SIZE_T  size,
        SIZE_T  count,
        FILE*   pFile);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FWrite @endcond
    ///
    /// @brief Writes data to a file handle.
    ///
    /// @param[in] pSrc   Pointer to the source memory.
    /// @param[in] size   Size of the objects to write.
    /// @param[in] count  Maximum number of objects to write.
    /// @param[in] pFile  Pointer to the file handle.
    ///
    /// @return Number of objects that were written successfully. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC SIZE_T FWrite(
        const VOID* pSrc,
        SIZE_T      size,
        SIZE_T      count,
        FILE*       pFile);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FFlush @endcond
    ///
    /// @brief Flushes data from a file handle.
    ///
    /// @param[in] pFile  Pointer to the file handle.
    ///
    /// @return #CDKResultSuccess or #CDKResultEFailed.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult FFlush(
        FILE* pFile);


#ifndef DOXYGEN_SHOULD_SKIP_THIS  /* Until the function is commented */
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond EvenFloorUINT32 @endcond
    ///
    /// @brief needs comment.
    ///
    /// @param[in] input  comment
    ///
    /// @return comment.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC UINT32 EvenFloorUINT32(
        UINT32 input)
    {
        return (input & 0xFFFFFFFE);
    }
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MaxUINT32 @endcond
    ///
    /// @brief Returns the largest of two UINT32 values.
    ///
    /// @param[in] input1  First number to compare.
    /// @param[in] input2  Second number to compare.
    ///
    /// @return Largest UINT32 value. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline UINT32 MaxUINT32(
        UINT32 input1,
        UINT32 input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MinUINT32 @endcond
    ///
    /// @brief Returns the smallest of two UINT32 values.
    ///
    /// @param[in] input1  First number to compare.
    /// @param[in] input2  Second number to compare.
    ///
    /// @return Smallest UINT32 value.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline UINT32 MinUINT32(
        UINT32 input1,
        UINT32 input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MaxFLOAT @endcond
    ///
    /// @brief Returns the largest of two float values.
    ///
    /// @param[in] input1  First number to compare.
    /// @param[in] input2  Second number to compare.
    ///
    /// @return Largest float value.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline FLOAT MaxFLOAT(
        FLOAT input1,
        FLOAT input2)
    {
        return ((input1 > input2) ? input1 : input2);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond FEqualCoarse @endcond
    ///
    /// @brief Compares the floating point numbers with reduced precision
    ///
    /// @param[in] value1  First number to compare.
    /// @param[in] value2  Second number to compare.
    ///
    /// @return
    /// - TRUE if the values are equal.
    /// - FALSE if the values are not equal. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static  CDK_VISIBILITY_PUBLIC inline BOOL FEqualCoarse(
        FLOAT value1, FLOAT value2)
    {
        return ((fabs(value1 - value2) < 1e-2) ? (TRUE) : (FALSE));
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MinFLOAT @endcond
    ///
    /// @brief Returns the smallest of two float values.
    ///
    /// @param[in] input1  First number to compare.
    /// @param[in] input2  Second number to compare.
    ///
    /// @return Smallest float value.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline FLOAT MinFLOAT(
        FLOAT input1,
        FLOAT input2)
    {
        return ((input1 < input2) ? input1 : input2);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond AlignGeneric32 @endcond
    ///
    /// @brief Aligns any UINT32 value with any alignment value.
    ///
    /// @param[in] operand    Value to be aligned.
    /// @param[in] alignment  Specified alignment value.
    ///
    /// @return Aligned value.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC UINT32 AlignGeneric32(
        UINT32 operand,
        UINT   alignment)
    {
        UINT remainder = (operand % alignment);

        return (0 == remainder) ? operand : operand - remainder + alignment;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond DivideAndCeil @endcond
    ///
    /// @brief Calculates the ceil after dividing a UINT32 value.
    ///
    /// @param[in] val      UINT32 value to be divided and ceiled.
    /// @param[in] divisor  UINT32 to use as the divisor in the operation.
    ///
    /// @return Ceil of the quotient. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline UINT32 DivideAndCeil(
        UINT32 val,
        UINT32 divisor)
    {
        return (val + (divisor - 1)) / divisor;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetDateTime @endcond
    ///
    /// @brief Gets the current date and time.
    ///
    /// @datatypes
    /// #CHIDateTime
    ///
    /// @param[in] pDateTime  Pointer to the structure to be filled.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID GetDateTime(
        CHIDateTime* pDateTime);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetRequestIdOffset @endcond
    ///
    /// @brief Computes the offset from the lastID that was flushed and the current request ID.
    ///
    /// @param[in] requestId             Identifier for the current request.
    /// @param[in] lastFlushedRequestId  Identifier for the last flushed request.
    ///
    /// @return Offset from the last flushed request ID.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC UINT64 GetRequestIdOffset(
        UINT64 requestId,
        UINT64 lastFlushedRequestId)
    {
        return (requestId > lastFlushedRequestId) ? (requestId - lastFlushedRequestId) : requestId;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MemCalloc @endcond
    ///
    /// @brief Allocates memory for CHI nodes.
    ///
    /// @param[in] count  Maximum number of elements to allocate.
    /// @param[in] size   Size of the elements to allocate.
    ///
    /// @return Pointer to the allocated memory. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* MemCalloc(
        SIZE_T count,
        SIZE_T size)
    {
        return calloc(count, size);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond MemFree @endcond
    ///
    /// @brief Releases memory that was allocated for CHI nodes.
    ///
    /// @param[in] ptr  Pointer to the allocated memory.
    ///
    /// @return None.
    ///
    /// @dependencies
    /// Memory must have been previously allocated via MemCalloc().
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID MemFree(
        VOID* ptr)
    {
        free(ptr);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond Memcpy @endcond
    ///
    /// @brief Copies specified data to another memory buffer.
    ///
    /// @param[in] pDst      Pointer to the destination buffer.
    /// @param[in] pSrc      Pointer to the source buffer.
    /// @param[in] numBytes  Size of the data in the source buffer.
    ///
    /// @return Destination pointer.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* Memcpy(
        VOID*       pDst,
        const VOID* pSrc,
        SIZE_T      numBytes)
    {
        return memcpy(pDst, pSrc, numBytes);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond Memset @endcond
    ///
    /// @brief Wraps the standard memset function and sets numBytes at the destination pointer to the specified pattern.
    ///
    /// @param[in] pDst      Pointer to the destination.
    /// @param[in] setVal    Character value to set.
    /// @param[in] numBytes  Number of characters (bytes) to copy from pSrc to pDst.
    ///
    /// @return Destination pointer. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID* Memset(
        VOID*    pDst,
        INT      setVal,
        SIZE_T   numBytes)
    {
        return memset(pDst, setVal, numBytes);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond StrTokReentrant @endcond
    ///
    /// @brief Parses a string into a sequence of tokens.
    ///
    /// @param[in] pSrc        Pointer to the string.
    /// @param[in] pDelimiter  Pointer to a set of bytes that delimit the tokens in the parsed string. The caller can specify
    ///                        different delimiter strings in successive calls that parse the same string.
    /// @param[in] ppContext   Double pointer to a CHAR* variable that is used internally to maintain the context between
    ///                        successive calls that parse the same string.
    ///
    /// @detdesc
    /// On the first call, the string to be parsed is specified in pSrc and the value of pContext should be valid, although
    /// it is ignored.
    /// @par
    /// In each subsequent call that parses the same string, pSrc should be NULL and pContext should be unchanged since the
    /// since the previous call.
    /// @par
    /// This function is re-entrant, and different strings can be parsed concurrently using sequences of calls to
    /// strtok_r() that specify different saveptr arguments.
    ///
    /// @return
    /// - Pointer to a NULL-terminated string that contains the next token,.
    /// - NULL if there are no more tokens.l
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CHAR* StrTokReentrant(
        CHAR*       pSrc,
        const CHAR* pDelimiter,
        CHAR**      ppContext)
    {
        #if defined (_LINUX)
                return strtok_r(pSrc, pDelimiter, ppContext);
        #elif defined (_WINDOWS)
                return strtok_s(pSrc, pDelimiter, ppContext);
        #else
        #error Unsupported target defined
        #endif // defined(_LINUX) || defined(_WINDOWS)
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond StrStrip @endcond
    ///
    /// @brief Strips all whitespace characters (space, tab, newline, carriage return, form feed, vertical tab) from a string.
    ///
    /// @param[in] pDst     Pointer to the destination string.
    /// @param[in] pSrc     Pointer to the source string.
    /// @param[in] sizeDst  Size of the destination string.
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID StrStrip(
        CHAR*   pDst,
        CHAR*   pSrc,
        SIZE_T  sizeDst);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetAlignment @endcond
    ///
    /// @brief Gets stride and scanline alignment for a specified format and resolution.
    ///
    /// @param[in] width               Width of the buffer in pixels.
    /// @param[in] height              Height of a buffer in pixels.
    /// @param[in] planeId             Plane index.
    /// @param[in] format              Format of the buffer.
    /// @param[in] pStrideAlignment    Pointer to the buffer for the returned stride alignment.
    /// @param[in] pScanlineAlignment  Pointer to the buffer for the returned scanline alignment.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID GetAlignment(
        INT          width,
        INT          height,
        UINT         planeId,
        ChiFormat    format,
        INT*         pStrideAlignment,
        INT*         pScanlineAlignment);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetVendorTagBase @endcond
    ///
    /// @brief Gets the required metadata vendor tag base from the camera system.
    ///
    /// @datatypes
    /// #CHINODEINTERFACE \n
    /// #CHIVENDORTAGBASEINFO
    ///
    /// @param[in] pComponentName     Pointer to the name of the metadata component.
    /// @param[in] pTagName           Pointer to the defined vendor tag name.
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    ///
    /// @return None. @newpage
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC UINT32 GetVendorTagBase(
        const CHAR*       pComponentName,
        const CHAR*       pTagName,
        ChiNodeInterface* pChiNodeInterface);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond RemoveMarginPixels @endcond
    ///
    /// @brief Removes margin pixels.
    ///
    /// @param[in] dimension     Width and height dimensions.
    /// @param[in] marginRatioX  Coefficient of the horizontal margin ratio.
    /// @param[in] marginRatioY  Coefficient of the  vertical margin ratio.
    ///
    /// @return #CDKResultSuccess or an error code (see Section @xref{hdr:resultMessages}).
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC CDKResult RemoveMarginPixels(
        CHIDimension* dimension,
        float         marginRatioX,
        float         marginRatioY);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetCameraRunningOnBPS @endcond
    ///
    /// @brief Checks whether the BPS performs camera real-time processing.
    ///
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    ///
    /// @return TRUE or FALSE.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC BOOL GetCameraRunningOnBPS(
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond GetImageStabilizationModeRT @endcond
    ///
    /// @brief Gets the image stabilization mode.
    ///
    /// @param[in] pChiNodeInterface  Pointer to the instance of the CHI node interface.
    /// @param[in] hChiSession        Handle of the CHI session.
    ///
    /// @return Image stabilization mode.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC ImageStabilizationMode GetImageStabilizationModeRT(
        CHINODEINTERFACE* pChiNodeInterface,
        CHIHANDLE         hChiSession);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond SleepMicroseconds @endcond
    ///
    /// @brief Puts the current thread to sleep.
    ///
    /// @param[in] microseconds  Sleep duration in microseconds.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC VOID SleepMicroseconds(
        UINT microseconds);

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond CDKResultToString @endcond
    ///
    /// @brief Converts a CDKResult result code to a string that represents the error.
    ///
    /// @param[in] result  Result code to convert.
    ///
    /// @return String representation of the result code.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static CDK_VISIBILITY_PUBLIC inline const CHAR* CDKResultToString(
        CDKResult result)
    {
        CDKResult resultDefault = CDKResultEFailed;

        if ((result >= 0) &&
            (result < CDKResultCount))
        {
            resultDefault = result;
        }
        else
        {
            CHX_LOG_ERROR(ChxLogGroupUtils, "Result: %d out of bounds", result);
        }

        return CDKResultStrings[resultDefault];
    }

private:

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// @cond CreateMetadataInfo @endcond
    ///
    /// @brief Creates a metadata information object.
    ///
    /// @param[in] requestId         Identifier for the current request.
    /// @param[in] pTagId            Pointer to the ID of the tag to get from the camera system.
    /// @param[in] metadataType      Type of metadata: static or dynamic.
    /// @param[in] hChiSession       Handle of the CHI session.
    /// @param[in] pTagData          Pointer to the CHI tag data structure.
    /// @param[in] pOutMetadataInfo  Pointer to the output metadata information.
    /// @param[in] pTypeIdList       Array of type IDs that represent the types for given meta data.
    ///
    /// @return None.
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID CreateMetadataInfo(
    UINT64            requestId,
    UINT32*           pTagId,
    CHIMETADATATYPE   metadataType,
    CHIHANDLE         hChiSession,
    CHITAGDATA*       pTagData,
    CHIMETADATAINFO*  pOutMetadataInfo,
    const UINT32*     pTypeIdList = NULL);
};

#endif
