////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
// All rights reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxstatsdebugdatawriter.h
/// @brief Debug data writer class declaration & implementation
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXSTATSDEBUGDATAWRITER_H
#define CAMXSTATSDEBUGDATAWRITER_H

#include "camxstatsdebugdatatypes.h"

enum class WriterId : UINT8
{
    AECWriter,
    AWBWriter,
    AFWriter,
    ASDWriter,
    AFDWriter,
    AFCWriter,
    ConciseAECXWriter,
    ConciseAWBWriter,
    ConciseAFWriter,
    OtherWriter,
    WriterMax
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief The class that implements things for the DebugDataWriter class.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class DebugDataWriter
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DebugDataWriter
    ///
    /// @brief  Constructor
    ///
    /// @param  writerType       Specify the id of writer
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    DebugDataWriter(
        WriterId writerType)
        : m_pBuffer(NULL)
        , m_bufferSize(0)
        , m_bytesWritten(0)
    {
        m_writerId             = writerType;
        m_enableCustomizedTags = FALSE;
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~DebugDataWriter
    ///
    /// @brief  Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~DebugDataWriter() { };

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetBufferPointer
    ///
    /// @brief  Set the buffer pointer
    ///
    /// @param  pBuffer       Pointer to buffer allocated outside
    /// @param  bufferSize    The size of the buffer
    ///
    /// @return  Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetBufferPointer(
        BYTE*  pBuffer,
        SIZE_T bufferSize)
    {
        CamxResult result = CamxResultSuccess;
        m_pBuffer       = pBuffer;
        m_bytesWritten  = 0;

        if (NULL == pBuffer)
        {
            m_bufferSize = 0;
        }
        else
        {
            if (bufferSize < sizeof(DebugDataTag))
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: The buffer is not sufficiently large to hold UnusedSpace tag",
                              WriterToString(m_writerId));
                result = CamxResultEInvalidArg;
            }
            else
            {
                CAMX_LOG_VERBOSE(CamxLogGroupDebugData, "%s: Set buffer: %p size: %zu", WriterToString(m_writerId), pBuffer, bufferSize);
                m_bufferSize = bufferSize - sizeof(DebugDataTag);   // Reserved for an unused tag
                result = SealUnusedSpace();
            }
            if (CamxResultSuccess == result)
            {
                result = AddTypeDefinitionTags();
            }
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeOfType
    ///
    /// @brief  Get the size of customer type
    ///
    /// @param  type    The data type to get the size of
    ///
    /// @return Size of data
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual SIZE_T GetSizeOfType(DebugDataTagType type) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsSameBufferPointer
    ///
    /// @brief  Compare the buffer pointer
    ///
    /// @param  pBuffer       Pointer to buffer allocated outside
    /// @param  bufferSize    The size of the buffer
    ///
    /// @return  True if same buffer pointer is currently in use
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL IsSameBufferPointer(
        BYTE*   pBuffer,
        SIZE_T  bufferSize)
    {
        return ((pBuffer == m_pBuffer) && (bufferSize == (m_bufferSize + sizeof(DebugDataTag))));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeWritten
    ///
    /// @brief      Gets the size of the data written to the buffer.
    ///
    /// @return     Size in bytes.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T GetSizeWritten()
    {
        return m_bytesWritten;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSize
    ///
    /// @brief      Get the total size of the buffer which was set via SetBufferPointer()
    ///
    /// @return     Size in bytes.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T GetSize()
    {
        return (m_bufferSize + sizeof(DebugDataTag));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsCustomType
    ///
    /// @brief  If type is custom type
    ///
    /// @param  type    The tag type to be check
    ///
    /// @return BOOL
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsCustomType(
        DebugDataTagType type)
    {
        return ((type >= DebugDataTagType::CustomStart) && (type <= DebugDataTagType::CustomEnd));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeOfFormating
    ///
    /// @brief  Return size of the formatting for buffer
    ///
    /// @return SIZE_T
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T GetSizeOfFormating()
    {
        // size of formatting (seal)
        return sizeof(DebugDataTag);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetTotalSizeToStoreType
    ///
    /// @brief  Returns total size to store debugdata type
    ///
    /// @param  type    The data type to get the name of
    /// @param  count   The count of each tag
    ///
    /// @return SIZE_T
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual SIZE_T GetTotalSizeToStoreType(
        DebugDataTagType type,
        UINT32           count)
    {
        SIZE_T result      = 0;
        SIZE_T sizePerType = GetSizeOfType(type);

        result = sizePerType * count + sizeof(DebugDataTag);
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeOfTypeDefinitions
    ///
    /// @brief  If implemented, return size required to store all type definitions
    ///
    /// @return  Size required to store type definitions
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual SIZE_T GetSizeOfTypeDefinitions()
    {
        CAMX_LOG_VERBOSE(CamxLogGroupDebugData, "Not implemented returning Zero");
        return 0;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetTypeName
    ///
    /// @brief  Get the type name of debug data type
    ///
    /// @param  type    The data type to get the name of
    ///
    /// @return Name of datatype
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    const CHAR* GetTypeName(
        DebugDataTagType type)
    {
        const CHAR* pName;

        switch (type)
        {
            // AEC Custom (non-basic) types - START
            case DebugDataTagType::AECROIDim:
                pName = "AECROIDim";
                break;
            case DebugDataTagType::AECConfiguration:
                pName = "AECConfiguration";
                break;
            case DebugDataTagType::AECFrameHistory:
                pName = "AECFrameHistory";
                break;
            case DebugDataTagType::AECModeHistory:
                pName = "AECModeHistory";
                break;
            case DebugDataTagType::AECMetering:
                pName = "AECMetering";
                break;
            case DebugDataTagType::AECConvergence:
                pName = "AECConvergence";
                break;
            case DebugDataTagType::AECArbitration:
                pName = "AECArbitration";
                break;
            case DebugDataTagType::AECExtension:
                pName = "AECExtension";
                break;
            case DebugDataTagType::AECStatsLumaRegion:
                pName = "AECStatsLumaRegion";
                break;
            case DebugDataTagType::AECExtremeColor:
                pName = "AECExtremeColor";
                break;
            case DebugDataTagType::AECHistogram:
                pName = "AECHistogram";
                break;
            case DebugDataTagType::AECLEDSetting:
                pName = "AECLEDSetting";
                break;
            case DebugDataTagType::AECLEDTable:
                pName = "AECLEDTable";
                break;
            case DebugDataTagType::AECFlash:
                pName = "AECFlash";
                break;
            case DebugDataTagType::AECBGProcInfo:
                pName = "AECBGProcInfo";
                break;
            case DebugDataTagType::AECParsedBGRegionType:
                pName = "AECParsedBGRegionType";
                break;
            case DebugDataTagType::AECParsedLegacyYRegionType:
                pName = "AECParsedLegacyYRegionType";
                break;
            case DebugDataTagType::AECBGProcResult:
                pName = "AECBGProcResult";
                break;
            case DebugDataTagType::AECBHistProcInfo:
                pName = "AECBHistProcInfo";
                break;
            case DebugDataTagType::AECBHistProcResult:
                pName = "AECBHistProcResult";                 ///< Deprecated
                break;
            case DebugDataTagType::AECBayerChannel:
                pName = "AECBayerChannel";
                break;
            case DebugDataTagType::AECStatsRectangle:
                pName = "AECStatsRectangle";
                break;
            case DebugDataTagType::AECBayerStats:
                pName = "AECBayerStats";
                break;
            case DebugDataTagType::AECHistogramChannel:
                pName = "AECHistogramChannel";
                break;
            case DebugDataTagType::AECHistogramStats:
                pName = "AECHistogramStats";
                break;
            case DebugDataTagType::AECBHistProcResultV1:
                pName = "AECBHistProcResultV1";
                break;
            case DebugDataTagType::AECAlgoVersion:
                pName = "AECAlgoVersion";
                break;
            // ------------------- AECX tags -------------------
            case DebugDataTagType::AECXROIDim:
                pName = "AECXROIDim";
                break;
            case DebugDataTagType::AECXContext:
                pName = "AECXContext";
                break;
            case DebugDataTagType::AECXFrameHistory:
                pName = "AECXFrameHistory";
                break;
            case DebugDataTagType::AECXMetering:
                pName = "AECXMetering";
                break;
            case DebugDataTagType::AECXConvergence:
                pName = "AECXConvergence";
                break;
            case DebugDataTagType::AECXArbitration:
                pName = "AECXArbitration";
                break;
            case DebugDataTagType::AECXExtension:
                pName = "AECXExtension";
                break;
            case DebugDataTagType::AECXLEDSetting:
                pName = "AECXLEDSetting";
                break;
            case DebugDataTagType::AECXLEDTable:
                pName = "AECXLEDTable";
                break;
            case DebugDataTagType::AECXFlash:
                pName = "AECXFlash";
                break;
            case DebugDataTagType::AECXStatsROIInfo:
                pName = "AECXStatsROIInfo";
                break;
            case DebugDataTagType::AECXStatsResolution:
                pName = "AECXStatsResolution";
                break;
            case DebugDataTagType::AECXStatsChInfo:
                pName = "AECXStatsChInfo";
                break;
            case DebugDataTagType::AECXStatsChList:
                pName = "AECXStatsChList";
                break;
            case DebugDataTagType::AECXStats:
                pName = "AECXStats";
                break;
            case DebugDataTagType::AECXStatsRectangle:
                pName = "AECXStatsRectangle";
                break;
            case DebugDataTagType::AECXOneArbitration:
                pName = "AECXOneArbitration";
                break;
            case DebugDataTagType::AECXConvHistory:
                pName = "AECXConvHistory";
                break;
            case DebugDataTagType::AECXExpRngType:
                pName = "AECXExpRngType";
                break;
            case DebugDataTagType::AECXROIInfo:
                pName = "AECXROIInfo";
                break;
            case DebugDataTagType::AECXManualSetting:
                pName = "AECXManualSetting";
                break;
            case DebugDataTagType::AECXAWBState:
                pName = "AECXAWBState";
                break;
            case DebugDataTagType::AECXOverrideSetting:
                pName = "AECXOverrideSetting";
                break;
            case DebugDataTagType::AECXSensorInfo:
                pName = "AECXSensorInfo";
                break;
            case DebugDataTagType::AECXCameraInfo:
                pName = "AECXCameraInfo";
                break;
            case DebugDataTagType::AECXInputConfig:
                pName = "AECXInputConfig";
                break;
            case DebugDataTagType::AECXGeneralSAType:
                pName = "AECXGeneralSAType";
                break;
            case DebugDataTagType::AECXGeneralSCType:
                pName = "AECXGeneralSCType";
                break;
            case DebugDataTagType::AECXSAComponentType:
                pName = "AECXSAComponentType";
                break;
            case DebugDataTagType::AECXSAArithOpType:
                pName = "AECXSAArithOpType";
                break;
            case DebugDataTagType::AECXDataBankType:
                pName = "AECXDataBankType";
                break;
            case DebugDataTagType::AECXStartEndType:
                pName = "AECXStartEndType";
                break;
            case DebugDataTagType::AECXExposureSetType:
                pName = "AECXExposureSetType";
                break;
            case DebugDataTagType::AECXExposureInfoType:
                pName = "AECXExposureInfoType";
                break;
            case DebugDataTagType::AECXFrameHistoryInfoType:
                pName = "AECXFrameHistoryInfoType";
                break;
            case DebugDataTagType::AECX3HDRSnapShot:
                pName = "AECX3HDRSnapShot";
                break;
            case DebugDataTagType::AECXPrecisionFlash:
                pName = "AECXPrecisionFlash";
                break;
            case DebugDataTagType::AECXAlgoVersion:
                pName = "AECXAlgoVersion";
                break;
            case DebugDataTagType::AECXNZSLMetering:
                pName = "AECXNZSLMetering";
                break;
            case DebugDataTagType::AECXNZSLArbitration:
                pName = "AECXNZSLArbitration";
                break;
            case DebugDataTagType::AECXCamSync:
                pName = "AECXCamSync";
                break;
            case DebugDataTagType::AECXAutoHDRDebugTag:
                pName = "AECXAutoHDRDebugTag";
                break;
            case DebugDataTagType::AECXFrameControlDebugTag:
                pName = "AECXFrameControlDebugTag";
                break;
            case DebugDataTagType::AECXSetInputDebugTag:
                pName = "AECXSetInputDebugTag";
                break;
            case DebugDataTagType::AECXFaceROIDebugTag:
                pName = "AECXFaceROIDebugTag";
                break;
            case DebugDataTagType::AECXPointDebugTag:
                pName = "AECXPointDebugTag";
                break;
            case DebugDataTagType::AECXFace3DPoseDebugTag:
                pName = "AECXFace3DPoseDebugTag";
                break;
            // AEC Custom (non-basic) types - END

            // AWB Custom (non-basic) types - START
            case DebugDataTagType::AWBPoint:
                pName = "AWBPoint";
                break;
            case DebugDataTagType::AWBZone:
                pName = "AWBZone";
                break;
            case DebugDataTagType::AWBZonePData:
                pName = "AWBZonePData";
                break;
            case DebugDataTagType::AWBDecisionPData:
                pName = "AWBDecisionPData";
                break;
            case DebugDataTagType::AWBModulePData:
                pName = "AWBModulePData";
                break;
            case DebugDataTagType::AWBGains:
                pName = "AWBGains";
                break;
            case DebugDataTagType::AWBTriggerPoint:
                pName = "AWBTriggerPoint";
                break;
            case DebugDataTagType::AWBTriggerFloatData:
                pName = "AWBTriggerFloatData";
                break;
            case DebugDataTagType::AWBStatsRectangle:
                pName = "AWBStatsRectangle";
                break;
            case DebugDataTagType::AWBTriggerNonLastLevelPData:
                pName = "AWBTriggerNonLastLevelPData";
                break;
            case DebugDataTagType::AWBcustRefPt:
                pName = "AWBcustRefPt";
                break;
            case DebugDataTagType::AWBSATargetPData:
                pName = "AWBSATargetPData";
                break;
            case DebugDataTagType::AWBSAConfidencePData:
                pName = "AWBSAConfidencePData";
                break;
            case DebugDataTagType::AWBSFSubSmpPData:
                pName = "AWBSFSubSmpPData";
                break;
            case DebugDataTagType::AWBSFStatsScrPData:
                pName = "AWBSFStatsScrPData";
                break;
            case DebugDataTagType::AWBSFIlluWVPData:
                pName = "AWBSFIlluWVPData";
                break;
            case DebugDataTagType::AWBSFDistWVPData:
                pName = "AWBSFDistWVPData";
                break;
            case DebugDataTagType::AWBSFCustRefPtPData:
                pName = "AWBSFCustRefPtPData";
                break;
            case DebugDataTagType::AWBSFMLCZPData:
                pName = "AWBSFMLCZPData";
                break;
            case DebugDataTagType::AWBSAAGWPData:
                pName = "AWBSAAGWPData";
                break;
            case DebugDataTagType::AWBDASAData:
                pName = "AWBDASAData";
                break;
            case DebugDataTagType::AWBFaceAssistSAPData:
                pName = "AWBFaceAssistSAPData";
                break;
            case DebugDataTagType::AWBDAPData:
                pName = "AWBDAPData";
                break;
            case DebugDataTagType::AWBTriglGAPData:
                pName = "AWBTriglGAPData";
                break;
            case DebugDataTagType::AWBTmpConvPData:
                pName = "AWBTmpConvPData";
                break;
            case DebugDataTagType::AWBDSFPData:
                pName = "AWBDSFPData";
                break;
            case DebugDataTagType::AWBSensorCalPData:
                pName = "AWBSensorCalPData";
                break;
            case DebugDataTagType::AWBSAGen1PData:
                pName = "AWBSAGen1PData";
                break;
            case DebugDataTagType::AWBHistPData:
                pName = "AWBHistPData";
                break;
            case DebugDataTagType::AWBFlashPData:
                pName = "AWBFlashPData";
                break;
            case DebugDataTagType::AWBStatInfo:
                pName = "AWBStatInfo";
                break;
            case DebugDataTagType::AWBStatPData:
                pName = "AWBStatPData";
                break;
            case DebugDataTagType::AWBBestShotPData:
                pName = "AWBBestShotPData";
                break;
            case DebugDataTagType::AWBSpecIlluPData:
                pName = "AWBSpecIlluPData";
                break;
            case DebugDataTagType::AWBLCDFlashPData:
                pName = "AWBLCDFlashPData";
                break;
            case DebugDataTagType::AWBLEDTorchPData:
                pName = "AWBLEDTorchPData";
                break;
            case DebugDataTagType::AWBStatsSensorInfo:
                pName = "AWBStatsSensorInfo";                 ///< Deprecated
                break;
            case DebugDataTagType::AWBStatsWindowInfo:
                pName = "AWBStatsWindowInfo";                 ///< Deprecated
                break;
            case DebugDataTagType::AWBIlluminatFactor:
                pName = "AWBIlluminatFactor";                 ///< Deprecated
                break;
            case DebugDataTagType::AWBIlluminantsCalibrationFactor:
                pName = "AWBIlluminantsCalibrationFactor";    ///< Deprecated
                break;
            case DebugDataTagType::AWBGeometricalDisparityCalibration:
                pName = "AWBGeometricalDisparityCalibration"; ///< Deprecated
                break;
            case DebugDataTagType::AWBStatsLEDCalibrationDataInput:
                pName = "AWBStatsLEDCalibrationDataInput";    ///< Deprecated
                break;
            case DebugDataTagType::AWBManualConfiguration:
                pName = "AWBManualConfiguration";             ///< Deprecated
                break;
            case DebugDataTagType::AWBStatsFaceData:
                pName = "AWBStatsFaceData";                   ///< Deprecated
                break;
            case DebugDataTagType::AWBStatsFaceHistogram:
                pName = "AWBStatsFaceHistogram";              ///< Deprecated
                break;
            case DebugDataTagType::AWBStatsFaceInformation:
                pName = "AWBStatsFaceInformation";            ///< Deprecated
                break;
            case DebugDataTagType::AWBProcessTrigGain:
                pName = "AWBProcessTrigGain";
                break;
            case DebugDataTagType::AWBFlashInformation:
                pName = "AWBFlashInformation";                ///< Deprecated
                break;
            case DebugDataTagType::AWBSetParamInfo:
                pName = "AWBSetParamInfo";                    ///< Deprecated
                break;
            case DebugDataTagType::AWBSFDistWVPTrigger2D:
                pName = "AWBSFDistWVPTrigger2D";
                break;
            case DebugDataTagType::AWBBGChannelData:
                pName = "AWBBGChannelData";
                break;
            case DebugDataTagType::AWBBGStatsData:
                pName = "AWBBGStatsData";
                break;
            case DebugDataTagType::AWBSADualcamSyncPData:
                pName = "AWBSADualcamSyncPData";
                break;
            case DebugDataTagType::AWBSCBasedConvergeData:
                pName = "AWBSCBasedConvergeData";
                break;
            case DebugDataTagType::AWBExternalInfo:
                pName = "AWBExternalInfo";
                break;
            case DebugDataTagType::AWBCustomizedSAInfo:
                pName = "AWBCustomizedSAInfo";
                break;
            case DebugDataTagType::AWBWeightedZone:
                pName = "AWBWeightedZone";
                break;
            case DebugDataTagType::AWBWeightedZonePData:
                pName = "AWBWeightedZonePData";
                break;
            case DebugDataTagType::AWBSFMLCZV2PData:
                pName = "AWBSFMLCZV2PData";
                break;
            case DebugDataTagType::AWBSAGen2PData:
                pName = "AWBSAGen2PData";
                break;
            case DebugDataTagType::AWBGlobalEnvPData:
                pName = "AWBGlobalEnvPData";
                break;
            case DebugDataTagType::AWBSFGenWVPTrigger2D:
                pName = "AWBSFGenWVPTrigger2D";
                break;
            case DebugDataTagType::AWBSFGenWVPData:
                pName = "AWBSFGenWVPData";
                break;
            case DebugDataTagType::AWBWeightedZonePDataV2:
                pName = "AWBWeightedZonePDataV2";
                break;
            case DebugDataTagType::AWBSFMLCZV3PData:
                pName = "AWBSFMLCZV3PData";
                break;
            case DebugDataTagType::AWBGenWVPData:
                pName = "AWBGenWVPData";
                break;
            case DebugDataTagType::AWBSFSpectralSensorAssistWVPData:
                pName = "AWBSFSpectralSensorAssistWVPData";
                break;
            case DebugDataTagType::AWBAlgoVersion:
                pName = "AWBAlgoVersion";
                break;
            case DebugDataTagType::AWBFaceStatsCntData:
                pName = "AWBFaceStatsCntData";
                break;
            case DebugDataTagType::AWBBGChannelDataExtension:
                pName = "AWBBGChannelDataExtension";
                break;
            case DebugDataTagType::AWBBGStatsDataExtension:
                pName = "AWBBGStatsDataExtension";
                break;
            case DebugDataTagType::AWBTemporalAWBPData:
                pName = "AWBTemporalAWBPData";
                break;
            case DebugDataTagType::AWBTemporalAWBDecisionsPData:
                pName = "AWBTemporalAWBDecisionsPData";
                break;
            case DebugDataTagType::AWBHDRStatsMergerData:
                pName = "AWBHDRStatsMergerData";
                break;
            case DebugDataTagType::AWBSMControlData:
                pName = "AWBSMControlData";
                break;
            case DebugDataTagType::AWBFaceStatsROI:
                pName = "AWBFaceStatsROI";
                break;
            case DebugDataTagType::AWBFaceStatInfo:
                pName = "AWBFaceStatInfo";
                break;
            case DebugDataTagType::AWBFaceStatFilterData:
                pName = "AWBFaceStatFilterData";
                break;
            case DebugDataTagType::AWBFaceRefIlluCCT:
                pName = "AWBFaceRefIlluCCT";
                break;
            case DebugDataTagType::AWBFaceRefIlluResults:
                pName = "AWBFaceRefIlluResults";
                break;
            case DebugDataTagType::AWBStatsRange:
                pName = "AWBStatsRange";
                break;
            case DebugDataTagType::AWBStatsSensorData:
                pName = "AWBStatsSensorData";
                break;
            case DebugDataTagType::AWBStatsWindowData:
                pName = "AWBStatsWindowData";
                break;
            case DebugDataTagType::AWBIllumaFactor:
                pName = "AWBIllumaFactor";
                break;
            case DebugDataTagType::AWBIllumaCalibrationFactor:
                pName = "AWBIllumaCalibrationFactor";
                break;
            case DebugDataTagType::AWBGeometricalDispCalibration:
                pName = "AWBGeometricalDispCalibration";
                break;
            case DebugDataTagType::AWBStatsLEDCalibDataInput:
                pName = "AWBStatsLEDCalibDataInput";
                break;
            case DebugDataTagType::AWBManualConfig:
                pName = "AWBManualConfig";
                break;
            case DebugDataTagType::AWBStatsUnsignRectangle:
                pName = "AWBStatsUnsignRectangle";
                break;
            case DebugDataTagType::AWBStats3DPose:
                pName = "AWBStats3DPose";
                break;
            case DebugDataTagType::AWBStatsFaceROIData:
                pName = "AWBStatsFaceROIData";
                break;
            case DebugDataTagType::AWBStatsUnstableFaceInfo:
                pName = "AWBStatsUnstableFaceInfo";
                break;
            case DebugDataTagType::AWBFlashInfo:
                pName = "AWBFlashInfo";
                break;
            case DebugDataTagType::AWBStatsCameraInfo:
                pName = "AWBStatsCameraInfo";
                break;
            case DebugDataTagType::AWBWarmStartInfo:
                pName = "AWBWarmStartInfo";
                break;
            case DebugDataTagType::AWBExternalData:
                pName = "AWBExternalData";
                break;
            case DebugDataTagType::AWBSpectralSensorInfo:
                pName = "AWBSpectralSensorInfo";
                break;
            case DebugDataTagType::AWBOverrideSetting:
                pName = "AWBOverrideSetting";
                break;
            case DebugDataTagType::AWBROINormalized:
                pName = "AWBROINormalized";
                break;
            case DebugDataTagType::AWBROIAWBData:
                pName = "AWBROIAWBData";
                break;
            case DebugDataTagType::AWBStatsGyroInfo:
                pName = "AWBStatsGyroInfo";
                break;
            case DebugDataTagType::AWBStatsAcceInfo:
                pName = "AWBStatsAcceInfo";
                break;
            case DebugDataTagType::AWBCVPMetaData:
                pName = "AWBCVPMetaData";
                break;
            case DebugDataTagType::AWBSetParamPData:
                pName = "AWBSetParamPData";
                break;
            // AWB Custom (non-basic) types - END

            // AF Custom (non-basic) types - START
            case DebugDataTagType::AFROIInfo:
                pName = "AFROIInfo";
                break;
            case DebugDataTagType::AFCommonHistory:
                pName = "AFCommonHistory";
                break;
            case DebugDataTagType::AFConvergeCommon:
                pName = "AFConvergeCommon";
                break;
            case DebugDataTagType::AFSingleAFHistory:
                pName = "AFSingleAFHistory";
                break;
            case DebugDataTagType::AFSingleAFData:
                pName = "AFSingleAFData";
                break;
            case DebugDataTagType::AFCAFFineScanHistory:
                pName = "AFCAFFineScanHistory";
                break;
            case DebugDataTagType::AFCAFFineScanData:
                pName = "AFCAFFineScanData";
                break;
            case DebugDataTagType::AFTOFHistory:
                pName = "AFTOFHistory";
                break;
            case DebugDataTagType::AFTimeOfFlight:
                pName = "AFTimeOfFlight";
                break;
            case DebugDataTagType::AFPDData:
                pName = "AFPDData";
                break;
            case DebugDataTagType::AFPDHistory:
                pName = "AFPDHistory";
                break;
            case DebugDataTagType::AFPhaseDifference:
                pName = "AFPhaseDifference";
                break;
            case DebugDataTagType::AFFollower:
                pName = "AFFollower";
                break;
            case DebugDataTagType::AFMonitorCommon:
                pName = "AFMonitorCommon";
                break;
            case DebugDataTagType::AFValueMonitorData:
                pName = "AFValueMonitorData";
                break;
            case DebugDataTagType::AFMonitorCAF:
                pName = "AFMonitorCAF";
                break;
            case DebugDataTagType::AFMonitorPDAF:
                pName = "AFMonitorPDAF";
                break;
            case DebugDataTagType::AFMonitorTOF:
                pName = "AFMonitorTOF";
                break;
            case DebugDataTagType::AFGammaTable:
                pName = "AFGammaTable";
                break;
            case DebugDataTagType::AFFocusROI:
                pName = "AFFocusROI";
                break;
            case DebugDataTagType::AFFIRFilter:
                pName = "AFFIRFilter";
                break;
            case DebugDataTagType::AFIIRFilter:
                pName = "AFIIRFilter";
                break;
            case DebugDataTagType::AFCoringInfo:
                pName = "AFCoringInfo";
                break;
            case DebugDataTagType::AFFilterKernel:
                pName = "AFFilterKernel";
                break;
            case DebugDataTagType::AFSWKernel:
                pName = "AFSWKernel";
                break;
            case DebugDataTagType::AFAlgoVersion:
                pName = "AFAlgoVersion";
                break;
            case DebugDataTagType::PDLibMajorVersion:
                pName = "PDLibMajorVersion";
                break;
            // AF Custom (non-basic) types - END

            // ASD Custom (non-basic) types - START
            case DebugDataTagType::ASDTypeBegin:
                pName = "ASDTypeBegin";
                break;
            case DebugDataTagType::ASDTypeEnd:
                pName = "ASDTypeEnd";
                break;
            // ASD Custom (non-basic) types - END

            // Tuning metadata custom - START
            case DebugDataTagType::TuningAECExposureData:
                pName = "TuningAECExposureData";
                break;
            case DebugDataTagType::TuningAECFrameControl:
                pName = "TuningAECFrameControl";
                break;
            case DebugDataTagType::TuningAWBFrameControl:
                pName = "TuningAWBFrameControl";
                break;
            case DebugDataTagType::TuningAWBRFrameControl:
                pName = "TuningAWBRFrameControl";
                break;
            case DebugDataTagType::TuningSensorResolution:
                pName = "TuningSensorResolution";
                break;
            case DebugDataTagType::TuningSensorCropInfo:
                pName = "TuningSensorCropInfo";
                break;
            case DebugDataTagType::TuningLSC34MeshLUT:
                pName = "TuningLSC34MeshLUT";
                break;
            case DebugDataTagType::TuningGammaCurve:
                pName = "TuningGammaCurve";
                break;
            case DebugDataTagType::TuningGTMLUT:
                pName = "TuningGTMLUT";
                break;
            case DebugDataTagType::TuningPedestalLUT:
                pName = "TuningPedestalLUT";
                break;
            case DebugDataTagType::TuningBPSBPCPDPC20Config:
                pName = "TuningBPSBPCPDPC20Config";
                break;
            case DebugDataTagType::TuningBPSHDR22Config:
                pName = "TuningBPSHDR22Config";
                break;
            case DebugDataTagType::TuningABFLUT:
                pName = "TuningABFLUT";
                break;
            case DebugDataTagType::TuningHNR10LUT:
                pName = "TuningHNR10LUT";
                break;
            case DebugDataTagType::TuningIPEHNR11LUT:
                pName = "TuningIPEHNR11LUT";
                break;
            case DebugDataTagType::TuningIPESTMP10LUT:
                pName = "TuningIPESTMP10LUT";
                break;
            case DebugDataTagType::TuningIPESBLUR10LUT:
                pName = "TuningIPESBLUR10LUT";
                break;
            case DebugDataTagType::TuningBPSTriggerData:
                pName = "TuningBPSTriggerData";
                break;
            case DebugDataTagType::TuningBPSSensorConfig:
                pName = "TuningBPSSensorConfig";
                break;
            case DebugDataTagType::TuningICA10LUT:
                pName = "TuningICA10LUT";
                break;
            case DebugDataTagType::TuningANR10Config:
                pName = "TuningANR10Config";
                break;
            case DebugDataTagType::TuningTF10Config:
                pName = "TuningTF10Config";
                break;
            case DebugDataTagType::TuningLTM13LUT:
                pName = "TuningLTM13LUT";
                break;
            case DebugDataTagType::Tuning2DLUT10LUT:
                pName = "Tuning2DLUT10LUT";
                break;
            case DebugDataTagType::TuningIPE2DLUT11LUT:
                pName = "TuningIPE2DLUT11LUT";
                break;
            case DebugDataTagType::TuningASF30LUT:
                pName = "TuningASF30LUT";
                break;
            case DebugDataTagType::TuningUpscaler20LUT:
                pName = "TuningUpscaler20LUT";
                break;
            case DebugDataTagType::TuningGrainAdder10LUT:
                pName = "TuningGrainAdder10LUT";
                break;
            case DebugDataTagType::TuningFaceData:
                pName = "TuningFaceData";
                break;
            case DebugDataTagType::TuningIPEGamma15Curve:
                pName = "TuningIPEGamma15Curve";
                break;
            case DebugDataTagType::TuningIQNodeInfo:
                pName = "TuningIQNodeInfo";
                break;
            case DebugDataTagType::TuningIQNodeInfoV2:
                pName = "TuningIQNodeInfoV2";
                break;
            case DebugDataTagType::TuningIPEAISW10ControlData:
                pName = "TuningIPEAISW10ControlData";
                break;
            case DebugDataTagType::TuningModeInfo:
                pName = "TuningModeInfo";
                break;
            case DebugDataTagType::TuningIFEEnableConfig:
                pName = "TuningIFEEnableConfig";
                break;
            case DebugDataTagType::TuningIFETriggerData:
                pName = "TuningIFETriggerData";
                break;
            case DebugDataTagType::TuningIFE2xHDR:
                pName = "TuningIFE2xHDR";
                break;
            case DebugDataTagType::TuningIFESensorConfig:
                pName = "TuningIFESensorConfig";
                break;
            case DebugDataTagType::TuningBPSBPCPDPC30LUT:
                pName = "TuningBPSBPCPDPC30LUT";
                break;
            case DebugDataTagType::TuningBPSBPCPDPC30Config:
                pName = "TuningBPSBPCPDPC30Config";
                break;
            case DebugDataTagType::TuningLSC40MeshLUT:
                pName = "TuningLSC40MeshLUT";
                break;
            case DebugDataTagType::TuningBPSFirmwareHeader:
                pName = "TuningBPSFirmwareHeader";
                break;
            case DebugDataTagType::TuningIFELSC40Config:
                pName = "TuningIFELSC40Config";
                break;
            case DebugDataTagType::TuningIFE30HDR:
                pName = "TuningIFE30HDR";
                break;
            case DebugDataTagType::TuningICA30LUT:
                pName = "TuningICA30LUT";
                break;
            case DebugDataTagType::TuningLTM14LUT:
                pName = "TuningLTM14LUT";
                break;
            case DebugDataTagType::TuningTF20Config:
                pName = "TuningTF20Config";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader:
                pName = "TuningIPEFirmwareHeader";
                break;
            case DebugDataTagType::TuningIPETriggerData:
                pName = "TuningIPETriggerData";
                break;
            case DebugDataTagType::TuningLSC351MeshLUT:
                pName = "TuningLSC351MeshLUT";
                break;
            case DebugDataTagType::TuningRegistrationOutputsizeType:
                pName = "TuningRegistrationOutputsizeType";
                break;
            // Header version 1 - basic types
            case DebugDataTagType::DebugDataHeaderV1:
                pName = "DebugDataHeaderV1";                                                  ///< Payload: DebugDataHeaderV1 only
                break;
            case DebugDataTagType::H1Char:
                pName = "H1Char";                                                             ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1Bool:
                pName = "H1Bool";                                                             ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1UInt8:
                pName = "H1UInt8";                                                            ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1UInt16:
                pName = "H1UInt16";                                                           ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1UInt32:
                pName = "H1UInt32";                                                           ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1UInt64:
                pName = "H1UInt64";                                                           ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1UQNumber:
                pName = "H1UQNumber";                                                         ///< Payload: DebugDataHeaderV1 + DebugDataUQNumber
                break;
            case DebugDataTagType::H1URational:
                pName = "H1URational";                                                        ///< Payload: DebugDataHeaderV1 + DebugDataURational
                break;
            case DebugDataTagType::H1Int8:
                pName = "H1Int8";                                                             ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1Int16:
                pName = "H1Int16";                                                            ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1Int32:
                pName = "H1Int32";                                                            ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1Int64:
                pName = "H1Int64";                                                            ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1QNumber:
                pName = "H1QNumber";                                                          ///< Payload: DebugDataHeaderV1 + DebugDataQNumber
                break;
            case DebugDataTagType::H1Rational:
                pName = "H1Rational";                                                         ///< Payload: DebugDataHeaderV1 + DebugDataRational
                break;
            case DebugDataTagType::H1Float:
                pName = "H1Float";                                                            ///< Payload: DebugDataHeaderV1 + base type
                break;
            case DebugDataTagType::H1Double:
                pName = "H1Double";                                                           ///< Payload: DebugDataHeaderV1 + base type
                break;
            // End-of-header version 1 basic types
            case DebugDataTagType::TuningTMCTriggerData:
                pName = "TuningTMCTriggerData";
                break;
            case DebugDataTagType::TuningDSX10LUT:
                pName = "TuningDSX10LUT";
                break;
            case DebugDataTagType::TuningDSX10Data:
                pName = "TuningDSX10Data";
                break;
            case DebugDataTagType::TuningGamma16Curve:
                pName = "TuningGamma16Curve";
                break;
            case DebugDataTagType::TuningMFHDRMACLUT:
                pName = "TuningMFHDRMACLUT";
                break;
            case DebugDataTagType::TuningIPEMFHDRMAC50LUT:
                pName = "TuningIPEMFHDRMAC50LUT";
                break;
            case DebugDataTagType::TuningIPEMFHDRMAC51LUT:
                pName = "TuningIPEMFHDRMAC51LUT";
                break;
            case DebugDataTagType::TuningMFHDRGTMLUT:
                pName = "TuningMFHDRGTMLUT";
                break;
            case DebugDataTagType::TuningMFHDRGTMData:
                pName = "TuningMFHDRGTMData";
                break;
            case DebugDataTagType::TuningLTM16LUT:
                pName = "TuningLTM16LUT";
                break;
            case DebugDataTagType::TuningIPELTM20LUT:
                pName = "TuningIPELTM20LUT";
                break;
            case DebugDataTagType::TuningBHistConfig:
                pName = "TuningBHistConfig";
                break;
            case DebugDataTagType::TuningBHistStatsConfig:
                pName = "TuningBHistStatsConfig";
                break;
            case DebugDataTagType::TuningRectangleCoordinate:
                pName = "TuningRectangleCoordinate";
                break;
            case DebugDataTagType::TuningBGBEConfig:
                pName = "TuningBGBEConfig";
                break;
            case DebugDataTagType::TuningBHistStatsOutput:
                pName = "TuningBHistStatsOutput";
                break;
            case DebugDataTagType::TuningIHistStatsOutput:
                pName = "TuningIHistStatsOutput";
                break;
            case DebugDataTagType::TuningTintlessBGStatsConfig:
                pName = "TuningTintlessBGStatsConfig";
                break;
            case DebugDataTagType::TuningTintlessBGStatsOutput:
                pName = "TuningTintlessBGStatsOutput";
                break;
            case DebugDataTagType::TuningBHistStatsOutputHeader:
                pName = "TuningBHistStatsOutputHeader";
                break;
            case DebugDataTagType::TuningIHistStatsOutputHeader:
                pName = "TuningIHistStatsOutputHeader";
                break;
            case DebugDataTagType::TuningTintlessBGStatsOutputHeader:
                pName = "TuningTintlessBGStatsOutputHeader";
                break;
            case DebugDataTagType::TuningHDRBEChannelData:
                pName = "TuningHDRBEChannelData";
                break;
            case DebugDataTagType::TuningMFHDRCSTTuningMetadataHeader:
                pName = "TuningMFHDRCSTTuningMetadataHeader";
                break;
            case DebugDataTagType::TuningMFHDRMACTuningMetadataHeader:
                pName = "TuningMFHDRMACTuningMetadataHeader";
                break;
            case DebugDataTagType::TuningIPEMFHDRMAC50TuningMetadataHeader:
                pName = "TuningIPEMFHDRMAC50TuningMetadataHeader";
                break;
            case DebugDataTagType::TuningIPEMFHDRMAC51TuningMetadataHeader:
                pName = "TuningIPEMFHDRMAC51TuningMetadataHeader";
                break;
            case DebugDataTagType::TuningDSX10LUTHeader:
                pName = "TuningDSX10LUTHeader";
                break;
            case DebugDataTagType::TuningBPSAWBBGStats17Config:
                pName = "TuningBPSAWBBGStats17Config";
                break;
            case DebugDataTagType::TuningBPSBayerGTM101Config:
                pName = "TuningBPSBayerGTM101Config";
                break;
            case DebugDataTagType::TuningBPSBayerLTM101Config:
                pName = "TuningBPSBayerLTM101Config";
                break;
            case DebugDataTagType::TuningBPSBC101Config:
                pName = "TuningBPSBC101Config";
                break;
            case DebugDataTagType::TuningBPSBHist16Config:
                pName = "TuningBPSBHist16Config";
                break;
            case DebugDataTagType::TuningBPSBLS121Config:
                pName = "TuningBPSBLS121Config";
                break;
            case DebugDataTagType::TuningBPSABF411Config:
                pName = "TuningBPSABF411Config";
                break;
            case DebugDataTagType::TuningBPSBPCPDPC311Config:
                pName = "TuningBPSBPCPDPC311Config";
                break;
            case DebugDataTagType::TuningBPSCC131Config:
                pName = "TuningBPSCC131Config";
                break;
            case DebugDataTagType::TuningBPSCG141Config:
                pName = "TuningBPSCG141Config";
                break;
            case DebugDataTagType::TuningBPSCST12Config680:
                pName = "TuningBPSCST12Config680";
                break;
            case DebugDataTagType::TuningBPSCompDecomp20Config:
                pName = "TuningBPSCompDecomp20Config";
                break;
            case DebugDataTagType::TuningBPSDemosaic361Config:
                pName = "TuningBPSDemosaic361Config";
                break;
            case DebugDataTagType::TuningBPSGIC311Config:
                pName = "TuningBPSGIC311Config";
                break;
            case DebugDataTagType::TuningBPSGTM131Config:
                pName = "TuningBPSGTM131Config";
                break;
            case DebugDataTagType::TuningBPSLCAC111Config:
                pName = "TuningBPSLCAC111Config";
                break;
            case DebugDataTagType::TuningBPSLSC411Config:
                pName = "TuningBPSLSC411Config";
                break;
            case DebugDataTagType::TuningBPSWB201Config:
                pName = "TuningBPSWB201Config";
                break;
            case DebugDataTagType::TuningBayerGTM101LUT:
                pName = "TuningBayerGTM101LUT";
                break;
            case DebugDataTagType::TuningBPSBayerLTM101LUT:
                pName = "TuningBPSBayerLTM101LUT";
                break;
            case DebugDataTagType::TuningABF411LUT:
                pName = "TuningABF411LUT";
                break;
            case DebugDataTagType::TuningPDPC311LUT:
                pName = "TuningPDPC311LUT";
                break;
            case DebugDataTagType::TuningGamma151LUT:
                pName = "TuningGamma151LUT";
                break;
            case DebugDataTagType::TuningBGamma101LUT:
                pName = "TuningBGamma101LUT";
                break;
            case DebugDataTagType::TuningGIC311LUT:
                pName = "TuningGIC311LUT";
                break;
            case DebugDataTagType::TuningGTM131LUT:
                pName = "TuningGTM131LUT";
                break;
            case DebugDataTagType::TuningLCAC111LUT:
                pName = "TuningLCAC111LUT";
                break;
            case DebugDataTagType::TuningLSC411LUT:
                pName = "TuningLSC411LUT";
                break;
            case DebugDataTagType::TuningUVGamma101LUT:
                pName = "TuningUVGamma101LUT";
                break;
            case DebugDataTagType::TuningBPSFirmwareHeader680:
                pName = "TuningBPSFirmwareHeader680";
                break;
            case DebugDataTagType::TuningIFEBPCABF411Config:
                pName = "TuningIFEBPCABF411Config";
                break;
            case DebugDataTagType::TuningIFEBLS121Config:
                pName = "TuningIFEBLS121Config";
                break;
            case DebugDataTagType::TuningIFECC131Config:
                pName = "TuningIFECC131Config";
                break;
            case DebugDataTagType::TuningIFECST12Config:
                pName = "TuningIFECST12Config";
                break;
            case DebugDataTagType::TuningIFEDemosaic361Config:
                pName = "TuningIFEDemosaic361Config";
                break;
            case DebugDataTagType::TuningIFEDemuxBLS141Config:
                pName = "TuningIFEDemuxBLS141Config";
                break;
            case DebugDataTagType::TuningIFEDemuxBLS161Config:
                pName = "TuningIFEDemuxBLS161Config";
                break;
            case DebugDataTagType::TuningIFEBayerGTM101Config:
                pName = "TuningIFEBayerGTM101Config";
                break;
            case DebugDataTagType::TuningIFEGTM131Config:
                pName = "TuningIFEGTM131Config";
                break;
            case DebugDataTagType::TuningIFEGTMfd131Config:
                pName = "TuningIFEGTMfd131Config";
                break;
            case DebugDataTagType::TuningIFEGTMfd131LUT:
                pName = "TuningIFEGTMfd131LUT";
                break;
            case DebugDataTagType::TuningIFELCAC111Config:
                pName = "TuningIFELCAC111Config";
                break;
            case DebugDataTagType::TuningIFELCAC111LUT:
                pName = "TuningIFELCAC111LUT";
                break;
            case DebugDataTagType::TuningIFELSC411Config:
                pName = "TuningIFELSC411Config";
                break;
            case DebugDataTagType::TuningIFEPDPC311Config:
                pName = "TuningIFEPDPC311Config";
                break;
            case DebugDataTagType::TuningIFEWB201Config:
                pName = "TuningIFEWB201Config";
                break;
            case DebugDataTagType::TuningIFEWB141Config:
                pName = "TuningIFEWB141Config";
                break;
            case DebugDataTagType::TuningIFEBC101Config:
                pName = "TuningIFEBC101Config";
                break;
            case DebugDataTagType::TuningIFECompdecomp20Config:
                pName = "TuningIFECompdecomp20Config";
                break;
            case DebugDataTagType::TuningIFEGIC311Config:
                pName = "TuningIFEGIC311Config";
                break;
            case DebugDataTagType::TuningIFEBayerLTM101Config:
                pName = "TuningIFEBayerLTM101Config";
                break;
            case DebugDataTagType::TuningIFEBayerLTM111Config:
                pName = "TuningIFEBayerLTM111Config";
                break;
            case DebugDataTagType::TuningIFEBayerLTM101LUT:
                pName = "TuningIFEBayerLTM101LUT";
                break;
            case DebugDataTagType::TuningBayerLTM101LUT:
                pName = "TuningBayerLTM101LUT";
                break;
            case DebugDataTagType::TuningBayerLTM111LUT:
                pName = "TuningBayerLTM111LUT";
                break;
            case DebugDataTagType::TuningIFEUVGamma101Config:
                pName = "TuningIFEUVGamma101Config";
                break;
            case DebugDataTagType::TuningIFEUnifiedHDRData:
                pName = "TuningIFEUnifiedHDRData";
                break;
            case DebugDataTagType::TuningIPETF211Config:
                pName = "TuningIPETF211Config";
                break;
            case DebugDataTagType::TuningIPEASF341Config:
                pName = "TuningIPEASF341Config";
                break;
            case DebugDataTagType::TuningIPEASF341LUT:
                pName = "TuningIPEASF341LUT";
                break;
            case DebugDataTagType::TuningIPEASF351Config:
                pName = "TuningIPEASF351Config";
                break;
            case DebugDataTagType::TuningIPEASF351LUT:
                pName = "TuningIPEASF351LUT";
                break;
            case DebugDataTagType::TuningIPELENR101Config:
                pName = "TuningIPELENR101Config";
                break;
            case DebugDataTagType::TuningIPECAC231Config:
                pName = "TuningIPECAC231Config";
                break;
            case DebugDataTagType::TuningIPECC131Config:
                pName = "TuningIPECC131Config";
                break;
            case DebugDataTagType::TuningIPECC141Config:
                pName = "TuningIPECC141Config";
                break;
            case DebugDataTagType::TuningIPECE121Config:
                pName = "TuningIPECE121Config";
                break;
            case DebugDataTagType::TuningIPECS201Config:
                pName = "TuningIPECS201Config";
                break;
            case DebugDataTagType::TuningIPECST12Config:
                pName = "TuningIPECST12Config";
                break;
            case DebugDataTagType::TuningIPESCE111Config:
                pName = "TuningIPESCE111Config";
                break;
            case DebugDataTagType::TuningIPELTM161Config:
                pName = "TuningIPELTM161Config";
                break;
            case DebugDataTagType::TuningIPELTM20Config:
                pName = "TuningIPELTM20Config";
                break;
            case DebugDataTagType::TuningIPEHNR11Config:
                pName = "TuningIPEHNR11Config";
                break;
            case DebugDataTagType::TuningIPESTMP10Config:
                pName = "TuningIPESTMP10Config";
                break;
            case DebugDataTagType::TuningIPEWB15Config:
                pName = "TuningIPEWB15Config";
                break;
            case DebugDataTagType::TuningIPEGS10Config:
                pName = "TuningIPEGS10Config";
                break;
            case DebugDataTagType::TuningIPESBLUR10Config:
                pName = "TuningIPESBLUR10Config";
                break;
            case DebugDataTagType::TuningIPECMUS10Config:
                pName = "TuningIPECMUS10Config";
                break;
            case DebugDataTagType::TuningIPE2DLUT11Config:
                pName = "TuningIPE2DLUT11Config";
                break;
            case DebugDataTagType::TuningIPEICA401LUT:
                pName = "TuningIPEICA401LUT";
                break;
            case DebugDataTagType::TuningIPEICA411LUT:
                pName = "TuningIPEICA411LUT";
                break;
            case DebugDataTagType::TuningIPEICA431LUT:
                pName = "TuningIPEICA431LUT";
                break;
            case DebugDataTagType::TuningIPEBLUR101Config:
                pName = "TuningIPEBLUR101Config";
                break;
            case DebugDataTagType::TuningIPEBLUR101LUT:
                pName = "TuningIPEBLUR101LUT";
                break;
            case DebugDataTagType::TuningIPEVSE101Config:
                pName = "TuningIPEVSE101Config";
                break;
            case DebugDataTagType::TuningIPEVSE101LUT:
                pName = "TuningIPEVSE101LUT";
                break;
            case DebugDataTagType::TuningIPEHDR10p101Config:
                pName = "TuningIPEHDR10p101Config";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader680:
                pName = "TuningIPEFirmwareHeader680";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader780:
                pName = "TuningIPEFirmwareHeader780";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader880:
                pName = "TuningIPEFirmwareHeader880";
                break;
            case DebugDataTagType::TuningBPSFirmwareHeader640:
                pName = "TuningBPSFirmwareHeader640";
                break;
            case DebugDataTagType::TuningGIC311Config:
                pName = "TuningGIC311Config";
                break;
            case DebugDataTagType::TuningABF411Config:
                pName = "TuningABF411Config";
                break;
            case DebugDataTagType::TuningBLS121Config:
                pName = "TuningBLS121Config";
                break;
            case DebugDataTagType::TuningDemosaic381Config:
                pName = "TuningDemosaic381Config";
                break;
            case DebugDataTagType::TuningANR121Config:
                pName = "TuningANR121Config";
                break;
            case DebugDataTagType::TuningTF121Config:
                pName = "TuningTF121Config";
                break;
            case DebugDataTagType::TuningGTM121LUT:
                pName = "TuningGTM121LUT";
                break;
            case DebugDataTagType::TuningLTM151Config:
                pName = "TuningLTM151Config";
                break;
            case DebugDataTagType::TuningLTM151LUT:
                pName = "TuningLTM151LUT";
                break;
            case DebugDataTagType::TuningCSMCE111Config:
                pName = "TuningCSMCE111Config";
                break;
            case DebugDataTagType::TuningASF331Config:
                pName = "TuningASF331Config";
                break;
            case DebugDataTagType::TuningASF331LUT:
                pName = "TuningASF331LUT";
                break;
            case DebugDataTagType::TuningICA321LUT:
                pName = "TuningICA321LUT";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader640:
                pName = "TuningIPEFirmwareHeader640";
                break;
            case DebugDataTagType::TuningSFEHDR501Config:
                pName = "TuningSFEHDR501Config";
                break;
            case DebugDataTagType::TuningSFEHDR501LUT:
                pName = "TuningSFEHDR501LUT";
                break;
            case DebugDataTagType::TuningSFERemosaicBin101Config:
                pName = "TuningSFERemosaicBin101Config";
                break;
            case DebugDataTagType::TuningSFERemosaicBin101LUT:
                pName = "TuningSFERemosaicBin101LUT";
                break;
            case DebugDataTagType::TuningSFEQPDPC101Config:
                pName = "TuningSFEQPDPC101Config";
                break;
            case DebugDataTagType::TuningSFEQPDPC101LUT:
                pName = "TuningSFEQPDPC101LUT";
                break;
            case DebugDataTagType::TuningSFELSC361Config:
                pName = "TuningSFELSC361Config";
                break;
            case DebugDataTagType::TuningSFELSC361LUT:
                pName = "TuningSFELSC361LUT";
                break;
            case DebugDataTagType::TuningSFECrop12Config:
                pName = "TuningSFECrop12Config";
                break;
            case DebugDataTagType::TuningSFELCR11Config:
                pName = "TuningSFELCR11Config";
                break;
            case DebugDataTagType::TuningSFEQCFADemux20Config:
                pName = "TuningSFEQCFADemux20Config";
                break;
            case DebugDataTagType::TuningSFEQCFADemux20LUT:
                pName = "TuningSFEQCFADemux20LUT";
                break;
            case DebugDataTagType::TuningSFEQCFADemux20ExpLUT:
                pName = "TuningSFEQCFADemux20ExpLUT";
                break;
            case DebugDataTagType::TuningANR141Config:
                pName = "TuningANR141Config";
                break;
            case DebugDataTagType::TuningANR141LUT:
                pName = "TuningANR141LUT";
                break;
            case DebugDataTagType::TuningTF221Config:
                pName = "TuningTF221Config";
                break;
            case DebugDataTagType::TuningTF221LUT:
                pName = "TuningTF221LUT";
                break;
            case DebugDataTagType::TuningIPETF231Config:
                pName = "TuningIPETF231Config";
                break;
            case DebugDataTagType::TuningIPETF231LUT:
                pName = "TuningIPETF231LUT";
                break;
            case DebugDataTagType::TuningIFELSC421LUT:
                pName = "TuningIFELSC421LUT";
                break;
            case DebugDataTagType::TuningIFEPDPC151Config:
                pName = "TuningIFEPDPC151Config";
                break;
            case DebugDataTagType::TuningIFEPDPC151LUT:
                pName = "TuningIFEPDPC151LUT";
                break;
            case DebugDataTagType::TuningIFELSC421Config:
                pName = "TuningIFELSC421Config";
                break;
            case DebugDataTagType::TuningIFEPDAF30Config:
                pName = "TuningIFEPDAF30Config";
                break;
            case DebugDataTagType::TuningTFEPDAF31Config:
                pName = "TuningTFEPDAF31Config";
                break;
            case DebugDataTagType::TuningSFEXCFAChGain151Config:
                pName = "TuningSFEXCFAChGain151Config";
                break;
            case DebugDataTagType::TuningSFEXCFADemux301Config:
                pName = "TuningSFEXCFADemux301Config";
                break;
            case DebugDataTagType::TuningSFEXCFADemuxPDAF301LUT:
                pName = "TuningSFEXCFADemuxPDAF301LUT";
                break;
            case DebugDataTagType::TuningSFEXCFADemuxExposure301LUT:
                pName = "TuningSFEXCFADemuxExposure301LUT";
                break;
            case DebugDataTagType::TuningSFEXCFADemuxNoise301LUT:
                pName = "TuningSFEXCFADemuxNoise301LUT";
                break;
            case DebugDataTagType::TuningSFEXPDPC201Config:
                pName = "TuningSFEXPDPC201Config";
                break;
            case DebugDataTagType::TuningSFEXPDPC201LUT:
                pName = "TuningSFEXPDPC201LUT";
                break;
            case DebugDataTagType::TuningSFEXPDPC201MaskLUT:
                pName = "TuningSFEXPDPC201MaskLUT";
                break;
            case DebugDataTagType::TuningSFEHDR511Config:
                pName = "TuningSFEHDR511Config";
                break;
            case DebugDataTagType::TuningSFELSC371Config:
                pName = "TuningSFELSC371Config";
                break;
            case DebugDataTagType::TuningSFELSC371LUT:
                pName = "TuningSFELSC371LUT";
                break;
            case DebugDataTagType::TuningSFERemosaicBin201Config:
                pName = "TuningSFERemosaicBin201Config";
                break;
            case DebugDataTagType::TuningSFERemosaicBin201LUT:
                pName = "TuningSFERemosaicBin201LUT";
                break;
            case DebugDataTagType::TuningSFERemosaicBin201NoiseLUT:
                pName = "TuningSFERemosaicBin201NoiseLUT";
                break;
            case DebugDataTagType::TuningSFERemosaicBin201PDAFLUT:
                pName = "TuningSFERemosaicBin201PDAFLUT";
                break;
            case DebugDataTagType::TuningSFECrop121Config:
                pName = "TuningSFECrop121Config";
                break;
            case DebugDataTagType::TuningBPSLSC421Config:
                pName = "TuningBPSLSC421Config";
                break;
            case DebugDataTagType::TuningLSC421LUT:
                pName = "TuningLSC421LUT";
                break;
            case DebugDataTagType::TuningBPSWB211Config:
                pName = "TuningBPSWB211Config";
                break;
            case DebugDataTagType::TuningBPSPDPCBPC1D151Config:
                pName = "TuningBPSPDPCBPC1D151Config";
                break;
            case DebugDataTagType::TuningPDPCBPC1D151LUT:
                pName = "TuningPDPCBPC1D151LUT";
                break;
            case DebugDataTagType::TuningBPSFirmwareHeader780:
                pName = "TuningBPSFirmwareHeader780";
                break;
            case DebugDataTagType::TuningRawMIPIPortConfig:
                pName = "TuningRawMIPIPortConfig";
                break;
            case DebugDataTagType::TuningBPSBHist17Config:
                pName = "TuningBPSBHist17Config";
                break;
            case DebugDataTagType::TuningSFEHDR521Config:
                pName = "TuningSFEHDR521Config";
                break;
            case DebugDataTagType::TuningIFELSC501LUT:
                pName = "TuningIFELSC501LUT";
                break;
            case DebugDataTagType::TuningIFELSC501Config:
                pName = "TuningIFELSC501Config";
                break;
            case DebugDataTagType::TuningBPSFirmwareHeader880:
                pName = "TuningBPSFirmwareHeader880";
                break;
            case DebugDataTagType::TuningBPSFCG10Config:
                pName = "TuningBPSFCG10Config";
                break;
            case DebugDataTagType::TuningFCG10LUT:
                pName = "TuningFCG10LUT";
                break;
            case DebugDataTagType::TuningBPSLSC501Config:
                pName = "TuningBPSLSC501Config";
                break;
            case DebugDataTagType::TuningLSC501LUT:
                pName = "TuningLSC501LUT";
                break;
            case DebugDataTagType::TuningIFEFCG10Config:
                pName = "TuningIFEFCG10Config";
                break;
            case DebugDataTagType::TuningIFEFCG10LUT:
                pName = "TuningIFEFCG10LUT";
                break;
            case DebugDataTagType::TuningIPEFirmwareHeader670:
                pName = "TuningIPEFirmwareHeader670";
                break;
            case DebugDataTagType::TuningIPEBayerLTM121Config:
                pName = "TuningIPEBayerLTM121Config";
                break;
            case DebugDataTagType::TuningBayerLTM121LUT:
                pName = "TuningBayerLTM121LUT";
                break;
            // Tuning metadata custom - END

            // AWB Custom (non-basic) types for concise - Start
            case DebugDataTagType::ConciseAWBPoint:
                pName = "ConciseAWBPoint";
                break;
            case DebugDataTagType::ConciseAWBDecisionPData:
                pName = "ConciseAWBDecisionPData";
                break;
            case DebugDataTagType::ConciseAWBModulePData:
                pName = "ConciseAWBModulePData";
                break;
            case DebugDataTagType::ConciseAWBGains:
                pName = "ConciseAWBGains";
                break;
            case DebugDataTagType::ConciseAWBSAConfidencePData:
                pName = "ConciseAWBSAConfidencePData";
                break;
            case DebugDataTagType::ConciseAWBTriggerPoint:
                pName = "ConciseAWBTriggerPoint";
                break;
            case DebugDataTagType::ConciseAWBSpecIlluPData:
                pName = "ConciseAWBSpecIlluPData";
                break;
            case DebugDataTagType::ConciseAWBSFStatsScrPData:
                pName = "ConciseAWBSFStatsScrPData";
                break;
            case DebugDataTagType::ConciseAWBSAAGWPData:
                pName = "ConciseAWBSAAGWPData";
                break;
            case DebugDataTagType::ConciseAWBFaceAssistSAPData:
                pName = "ConciseAWBFaceAssistSAPData";
                break;
            case DebugDataTagType::ConciseAWBTmpConvPData:
                pName = "ConciseAWBTmpConvPData";
                break;
            case DebugDataTagType::ConciseAWBSensorCalPData:
                pName = "ConciseAWBSensorCalPData";
                break;
            case DebugDataTagType::ConciseAWBFlashPData:
                pName = "ConciseAWBFlashPData";
                break;
            case DebugDataTagType::ConciseAWBLCDFlashPData:
                pName = "ConciseAWBLCDFlashPData";
                break;
            case DebugDataTagType::ConciseAWBLEDTorchPData:
                pName = "ConciseAWBLEDTorchPData";
                break;
            case DebugDataTagType::ConciseAWBFaceStatsCntData:
                pName = "ConciseAWBFaceStatsCntData";
                break;
            // AWB Custom (non-basic) types for concise - END

            // AF Custom (non-basic) types for concise - Start
            case DebugDataTagType::ConciseAFFilterKernel:
                pName = "ConciseAFFilterKernel";
                break;
            case DebugDataTagType::ConciseAFIIRFilter:
                pName = "ConciseAFIIRFilter";
                break;
            case DebugDataTagType::ConciseAFFIRFilter:
                pName = "ConciseAFFIRFilter";
                break;
            case DebugDataTagType::ConciseAFCoringInfo:
                pName = "ConciseAFCoringInfo";
                break;
            case DebugDataTagType::ConciseAFROIInfo:
                pName = "ConciseAFROIInfo";
                break;
            case DebugDataTagType::ConciseAFCommonHistory:
                pName = "ConciseAFCommonHistory";
                break;
            case DebugDataTagType::ConciseAFConvergeCommon:
                pName = "ConciseAFConvergeCommon";
                break;
            // AF Custom (non-basic) types for concise - END

            // TFE/OPE metadata custom - START
            case DebugDataTagType::TuningTFELSC35MeshLUT:
                pName = "TuningTFELSC35MeshLUT";
                break;
            case DebugDataTagType::TuningTFEDemux14Config:
                pName = "TuningTFEDemux14Config";
                break;
            case DebugDataTagType::TuningTFEWBBDSDPC10Config:
                pName = "TuningTFEWBBDSDPC10Config";
                break;
            case DebugDataTagType::TuningTFELSC35Config:
                pName = "TuningTFELSC35Config";
                break;
            case DebugDataTagType::TuningOPEBPCABF41LUT:
                pName = "TuningOPEBPCABF41LUT";
                break;
            case DebugDataTagType::TuningOPEGTM12LUT:
                pName = "TuningOPEGTM12LUT";
                break;
            case DebugDataTagType::TuningOPELTM15LUT:
                pName = "TuningOPELTM15LUT";
                break;
            case DebugDataTagType::TuningOPEGamma15Curve:
                pName = "TuningOPEGamma15Curve";
                break;
            case DebugDataTagType::TuningOPEASF32LUT:
                pName = "TuningOPEASF32LUT";
                break;
            case DebugDataTagType::TuningOPEBPCABF41Config:
                pName = "TuningOPEBPCABF41Config";
                break;
            case DebugDataTagType::TuningOPEBLS12Config:
                pName = "TuningOPEBLS12Config";
                break;
            case DebugDataTagType::TuningOPEDemosaic36Config:
                pName = "TuningOPEDemosaic36Config";
                break;
            case DebugDataTagType::TuningOPECC13Config:
                pName = "TuningOPECC13Config";
                break;
            case DebugDataTagType::TuningOPECE12Config:
                pName = "TuningOPECE12Config";
                break;
            case DebugDataTagType::TuningOPESCE11Config:
                pName = "TuningOPESCE11Config";
                break;
            case DebugDataTagType::TuningOPEWNR24Config:
                pName = "TuningOPEWNR24Config";
                break;
            case DebugDataTagType::TuningOPEASF32Config:
                pName = "TuningOPEASF32Config";
                break;
            case DebugDataTagType::TuningOPEUpscaler13Config:
                pName = "TuningOPEUpscaler13Config";
                break;
            case DebugDataTagType::TuningOPEWB14Config:
                pName = "TuningOPEWB14Config";
                break;
            case DebugDataTagType::TuningOPEGTM12Config:
                pName = "TuningOPEGTM12Config";
                break;
            case DebugDataTagType::TuningOPELTM15Config:
                pName = "TuningOPELTM15Config";
                break;
            case DebugDataTagType::TuningOPEGamma15Config:
                pName = "TuningOPEGamma15Config";
                break;
            case DebugDataTagType::TuningOPECST12Config:
                pName = "TuningOPECST12Config";
                break;
            case DebugDataTagType::TuningTFETriggerData:
                pName = "TuningTFETriggerData";
                break;
            case DebugDataTagType::TuningTFESensorConfig:
                pName = "TuningTFESensorConfig";
                break;
            case DebugDataTagType::TuningOPEModeInfo:
                pName = "TuningOPEModeInfo";
                break;
            case DebugDataTagType::TuningOPETriggerData:
                pName = "TuningOPETriggerData";
                break;
            case DebugDataTagType::TuningOPEDemux14Config:
                pName = "TuningOPEDemux14Config";
                break;
            case DebugDataTagType::TuningOPELSC35LUT:
                pName = "TuningOPELSC35LUT";
                break;
            case DebugDataTagType::TuningOPELSC35Config:
                pName = "TuningOPELSC35Config";
                break;
            case DebugDataTagType::TuningTFEDemuxBLS141Config:
                pName = "TuningTFEDemuxBLS141Config";
                break;
            case DebugDataTagType::TuningTFELSC351Config:
                pName = "TuningTFELSC351Config";
                break;
            case DebugDataTagType::TuningTFEPDPC321Config:
                pName = "TuningTFEPDPC321Config";
                break;
            case DebugDataTagType::TuningTFEWBBDS111Config:
                pName = "TuningTFEWBBDS111Config";
                break;
            case DebugDataTagType::TuningTFEBDS4Config:
                pName = "TuningTFEBDS4Config";
                break;
            case DebugDataTagType::TuningTFEBDS2Config:
                pName = "TuningTFEBDS2Config";
                break;
            case DebugDataTagType::TuningTFEWB14Config:
                pName = "TuningTFEWB14Config";
                break;
            case DebugDataTagType::TuningTFEDS4CSTConfig:
                pName = "TuningTFEDS4CSTConfig";
                break;
            case DebugDataTagType::TuningTFEAICSTConfig:
                pName = "TuningTFEAICSTConfig";
                break;
            case DebugDataTagType::TuningTFEBLS121Config:
                pName = "TuningTFEBLS121Config";
                break;
            case DebugDataTagType::TuningTFEABF211Config:
                pName = "TuningTFEABF211Config";
                break;
            case DebugDataTagType::TuningTFEGTM121Config:
                pName = "TuningTFEGTM121Config";
                break;
            case DebugDataTagType::TuningTFEGamma101Config:
                pName = "TuningTFEGamma101Config";
                break;
            case DebugDataTagType::TuningTFELSC351LUT:
                pName = "TuningTFELSC351LUT";
                break;
            case DebugDataTagType::TuningTFEPDPC321LUT:
                pName = "TuningTFEPDPC321LUT";
                break;
            case DebugDataTagType::TuningTFEGTM121LUT:
                pName = "TuningTFEGTM121LUT";
                break;
            case DebugDataTagType::TuningTFEGamma101Curve:
                pName = "TuningTFEGamma101Curve";
                break;
            case DebugDataTagType::TuningTFEAECBG18Config:
                pName = "TuningTFEAECBG18Config";
                break;
            case DebugDataTagType::TuningTFEBHist15Config:
                pName = "TuningTFEBHist15Config";
                break;
            case DebugDataTagType::TuningTFETintlessBG18Config:
                pName = "TuningTFETintlessBG18Config";
                break;
            case DebugDataTagType::TuningTFEAWBBG18Config:
                pName = "TuningTFEAWBBG18Config";
                break;
            case DebugDataTagType::TuningTFERS16Config:
                pName = "TuningTFERS16Config";
                break;
            case DebugDataTagType::TuningTFEBAF27Config:
                pName = "TuningTFEBAF27Config";
                break;
            case DebugDataTagType::TuningTFEBAF27GammaCurve:
                pName = "TuningTFEBAF27GammaCurve";
                break;
            case DebugDataTagType::TuningTFENodeInfo:
                pName = "TuningTFENodeInfo";
                break;
            case DebugDataTagType::TuningTFEUnifiedHDRData:
                pName = "TuningTFEUnifiedHDRData";
                break;
            case DebugDataTagType::TuningTFEBAF28Config:
                pName = "TuningTFEBAF28Config";
                break;
            case DebugDataTagType::TuningTFEBAF28LUT:
                pName = "TuningTFEBAF28LUT";
                break;
            case DebugDataTagType::TuningIPEHDRC531Config:
                pName = "TuningIPEHDRC531Config";
                break;
            case DebugDataTagType::TuningHDRC531LUT:
                pName = "TuningHDRC531LUT";
                break;
            case DebugDataTagType::TuningIFEBayerLTM111LUT:
                pName = "TuningIFEBayerLTM111LUT";
                break;
            case DebugDataTagType::TuningIFEDecomp21Config:
                pName = "TuningIFEDecomp21Config";
                break;
            case DebugDataTagType::TuningGamma151LUTRGBout:
                pName = "TuningGamma151LUTRGBout";
                break;
            // TFE/OPE metadata custom - END
            default:
                if ((type >= DebugDataTagType::AECTypeBegin) && (type <= DebugDataTagType::AECXTypeBegin ))
                pName = "AECTypeBegin";
                else if ((type >= DebugDataTagType::AECXContext) && (type <= DebugDataTagType::AECTypeMax ))
                pName = "AECXcontext";
                else if ((type >= DebugDataTagType::AWBPoint) && (type <= DebugDataTagType::AWBTypeEnd))
                pName = "AWBtypeEnd";
                else if ((type >= DebugDataTagType::AFROIInfo) && (type <= DebugDataTagType::PDLibMajorVersion))
                pName = "AFRoi";
                else if ((type >= DebugDataTagType::TuningAECExposureData) && (type <= DebugDataTagType::TuningIPETriggerData))
                pName = "AECExp";
                else if ((type >= DebugDataTagType::DebugDataHeaderV1) && (type <= DebugDataTagType::H1Double))
                pName = "DebugDataV1";
                else if ((type >= DebugDataTagType::TuningTMCTriggerData) && (type <= DebugDataTagType::TuningTypeEnd1))
                pName = "Tuning type1";
                else if ((type >= DebugDataTagType::TuningIPEHDRC531Config) && (type <= DebugDataTagType::TuningTypeEnd2))
                pName = "Tuning type2";
                else if ((type >= DebugDataTagType::ConciseAECTypeBegin) && (type <= DebugDataTagType::ConciseAFTypeEnd))
                pName = "ConciseAEC";
                else if ((type >= DebugDataTagType::TuningTFELSC35MeshLUT) && (type <= DebugDataTagType::TuningTFEOPETypeEnd))
                pName = "ConciseAEC";
                else
                pName = "None";
                break;
        }

        return pName;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypeDefinitionTag
    ///
    /// @brief  Add a type definition tag
    ///
    /// @param  type    The tag type to be added
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AddTypeDefinitionTag(
        DebugDataTagType type)
    {
        CamxResult      result          = CamxResultSuccess;
        BYTE*           pBuffer         = GetCurBufferPos();    // Current buffer position
        DebugDataTag*   pTag            = NULL;

        pTag                = reinterpret_cast<DebugDataTag*>(pBuffer);
        m_bufferRemaining   = static_cast<INT32>(m_bufferSize - m_bytesWritten);
        m_bufferRemaining  -= static_cast<INT32>(sizeof(DebugDataTag));
        m_fieldsID          = 0;
        m_sanitySize        = 0;

        if (NULL == pBuffer)
        {
            result = CamxResultEInvalidPointer;
            return result;
        }
        if (m_bufferRemaining <= 0)
        {
            result = CamxResultENoMemory;
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Insufficient size to write data", WriterToString(m_writerId));
            return result;
        }

        // Have our specific implementation populate our buffer with type information
        result = PopulateTypeDefinitionTag(type);
        if (CamxResultSuccess != result)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData,
                          "%s: Error! Unrecognized type or the given type is not a custom type: %u",
                          WriterToString(m_writerId), type);
            result = CamxResultEUnsupported;
        }

        if (CamxResultSuccess == result)
        {
            if (m_sanitySize != GetSizeOfType(type))
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData,
                              "%s: Implementation Error! Typedef tag-type: [Dec:%d | Hex:0x%x], total-field size: %u bytes. "
                              "Expected size returned by GetSizeOfType(): %u bytes. This is caused by incorrect code change "
                              "by developer. Debug data  Name %s",
                              WriterToString(m_writerId),
                              type, type,
                              m_sanitySize,
                              GetSizeOfType(type),
                              GetTypeName(type));
                result = CamxResultENotImplemented;
            }
            else
            {
                pTag->id        = static_cast<DebugDataTagID>(type);
                pTag->type      = DebugDataTagType::TypeDefinition;
                pTag->count     = m_fieldsID;
                m_bytesWritten  = m_bufferSize - m_bufferRemaining;

                result = SealUnusedSpace();
            }
        }
        else
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Error, failed to add the type definition tag-ID 0x%x name %s",
                          WriterToString(m_writerId), type, GetTypeName(type));
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// UpdateWriterId
    ///
    /// @brief  Updates writer ID.
    ///
    /// @param  Id  WriterId
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult UpdateWriterId(
        WriterId Id)
    {
        m_writerId = Id;
        return CamxResultSuccess;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PopulateTypeDefinitionTag
    ///
    /// @brief  Adds all fields for this specific type of tag. This is a pure virtual function.
    ///
    /// @param  type    The tag type to be added
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult PopulateTypeDefinitionTag(
        DebugDataTagType type) = 0;

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeTypeDefinitionTag
    ///
    /// @brief  Get size for the definition of a TagType
    ///
    /// @param  type    TagType definition to get the size from
    ///
    /// @return size
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T GetSizeTypeDefinitionTag(
        DebugDataTagType type)
    {
        m_sizeTagTypes  = 0;
        m_getSizeMode   = TRUE;

        // Have our specific implementation populate our buffer with type information
        m_sizeTagTypes += sizeof(DebugDataTag);
        PopulateTypeDefinitionTag(type);

        m_getSizeMode = FALSE; // Restore to default mode

        return m_sizeTagTypes;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypeDefinitionTags
    ///
    /// @brief  Add a set of type definition tags
    ///
    /// @param  typeBegin    The first tag type to be added
    /// @param  typeEnd      The last tag type to be added
    ///
    /// @return  CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AddTypeDefinitionTags(
        DebugDataTagType typeBegin,
        DebugDataTagType typeEnd)
    {
        CamxResult result = CamxResultSuccess;
        UINT16 begin      = static_cast<UINT16>(typeBegin);
        UINT16 end        = static_cast<UINT16>(typeEnd);

        if (begin >= end)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Error, invalid input!", WriterToString(m_writerId));
            result = CamxResultEInvalidArg;
        }
        else
        {
            for (UINT16 type = begin; type <= end; type++)
            {
                BOOL bDeprecated = FALSE;
                // Ensure the type definition which we are adding is not deprecated
                for (UINT32 i = 0; i < CAMX_ARRAY_SIZE(DebugDataTagTypeDeprecated); i++)
                {
                    if (type == static_cast<UINT16>(DebugDataTagTypeDeprecated[i]))
                    {
                        bDeprecated = TRUE;
                        break;
                    }
                }

                if (FALSE == bDeprecated)
                {
                    result = AddTypeDefinitionTag(static_cast<DebugDataTagType>(type));
                }
            }
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeOfTypeDefinitions
    ///
    /// @brief  Get size required to store this range of tags types
    ///
    /// @param  typeBegin    The first tag type to be added
    /// @param  typeEnd      The last tag type to be added
    ///
    /// @return  CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    SIZE_T GetSizeOfTypeDefinitions(
        DebugDataTagType typeBegin,
        DebugDataTagType typeEnd)
    {
        UINT16 begin        = static_cast<UINT16>(typeBegin);
        UINT16 end          = static_cast<UINT16>(typeEnd);
        SIZE_T totalSize    = 0;

        if (begin >= end)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Error, invalid input!", WriterToString(m_writerId));
        }
        else
        {
            for (UINT16 type = begin; type <= end; type++)
            {
                BOOL bDeprecated = FALSE;
                // Ensure the type definition which we are adding is not deprecated
                for (UINT32 i = 0; i < CAMX_ARRAY_SIZE(DebugDataTagTypeDeprecated); i++)
                {
                    if (type == static_cast<UINT16>(DebugDataTagTypeDeprecated[i]))
                    {
                        bDeprecated = TRUE;
                        break;
                    }
                }

                if (FALSE == bDeprecated)
                {
                    totalSize += GetSizeTypeDefinitionTag(static_cast<DebugDataTagType>(type));
                }
            }
        }

        return totalSize;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddDataTag
    ///
    /// @brief  Add tag to header
    ///
    /// @param  id          The tag id of the data
    /// @param  type        The tag type of the data
    /// @param  count       Count of the data elements. If the count is zero then nothing will be written
    /// @param  pData       Pointer to the data to be written to the debug data buffer
    /// @apram  dataSize    The size of the data pointed to by pData parameter
    ///
    /// @return DebugDataTagHeader
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AddDataTag(
        DebugDataTagID   id,
        DebugDataTagType type,
        TagCount         count,
        VOID*            pData,
        SIZE_T           dataSize)
    {
        CamxResult      result          = CamxResultSuccess;
        DebugDataTag*   pTag            = reinterpret_cast<DebugDataTag*>(GetCurBufferPos());
        SIZE_T          sizeLeft        = m_bufferSize - m_bytesWritten;
        SIZE_T          expectedSize    = GetSizeOfType(type) * count;

        if (DebugDataTagID::UnusedSpace == id)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Called with invalid argument of UnusedSpace",
                          WriterToString(m_writerId));
            result = CamxResultEInvalidArg;
        }
        else if (NULL == pTag)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Debug data buffer is NULL", WriterToString(m_writerId));
            result = CamxResultEInvalidState;
        }
        else if (NULL == pData && dataSize > 0)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData,
                          "%s: Invalid! Tag ID %u has no payload but tag size indicates presence of a payload",
                          WriterToString(m_writerId), id);
            result = CamxResultEInvalidArg;
        }
        else if (sizeof(DebugDataTag) + dataSize > sizeLeft)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData,
                          "%s: Insufficient size to write data for tag ID: %u name %s. Free space left: %zu bytes. "
                          "payload size: %u bytes",
                          WriterToString(m_writerId), id, GetTypeName(type), sizeLeft, dataSize);
            result = CamxResultEOverflow;
        }

        if (CamxResultSuccess == result)
        {
            // Ensure that the tag ID is not deprecated
            for (UINT32 i = 0; i < CAMX_ARRAY_SIZE(DebugDataTagIDDeprecated); i++)
            {
                if (id == DebugDataTagIDDeprecated[i])
                {
                    CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Deprecated tag ID %u!", WriterToString(m_writerId), id);
                    result = CamxResultEUnsupported;
                    break;
                }
            }
        }

        if ((CamxResultSuccess == result) && (TRUE == m_enableCustomizedTags))
        {
            // If customized tag array enable, ensure that the tag ID is in the array
            UINT32 index    = 0;
            result          = CamxResultEUnsupported;

            for (index = 0; index < m_CustomizedTagSize; index++)
            {
                if (static_cast<UINT16>(id) == m_pCustomizedTagArray[index])
                {
                    result = CamxResultSuccess;
                    break;
                }
            }

            if (m_CustomizedTagSize == index)
            {
                CAMX_LOG_VERBOSE(CamxLogGroupDebugData, "%s: Skipping tag ID: %u(0x%x), because it was not selected or used",
                                WriterToString(m_writerId), id, id);
            }
        }

        if (CamxResultSuccess == result)
        {
            if (count == 0)
            {
                CAMX_LOG_VERBOSE(CamxLogGroupDebugData, "%s: Skipping tag ID: %u because the data count is zero",
                                 WriterToString(m_writerId), id);
                result = CamxResultSuccess;
            }
            else if (dataSize != expectedSize)
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData,
                              "%s: Payload size of %u does not match the expected size of %u. Tag ID %u, Type: %u",
                              WriterToString(m_writerId), dataSize, expectedSize, id, type);
                result = CamxResultEInvalidArg;
            }
            else
            {
                pTag->id    = id;
                pTag->type  = type;
                pTag->count = count;
                m_bytesWritten += sizeof(DebugDataTag);
                if (NULL != pData)
                {
                    CamX::Utils::Memcpy(GetCurBufferPos(), pData, dataSize);
                    m_bytesWritten += dataSize;
                }

                // Reference logs, but very verbose
                // CAMX_LOG_VERBOSE(CamxLogGroupDebugData,
                //                  "%s: Add TagID: %d (0x%x), type: %s %u (0x%x) count %u, space left: %zu",
                //                  WriterToString(m_writerId), id, id,
                //                  GetTypeName(type), type, type,
                //                  count, (m_bufferSize - m_bytesWritten));

                result = SealUnusedSpace();
            }
        }
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTwoDimArrayDataTag
    ///
    /// @brief  Add a two dim array data tag to debug data
    ///
    /// @param  id              The tag id of the data
    /// @param  dimension1      Dimension 1 of two dim array
    /// @param  dimension2      Dimension 2 of two dim array
    /// @param  elementType     The element type of the array
    /// @param  pData           The pointer of the data
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult AddTwoDimArrayDataTag(
        DebugDataTagID      id,
        UINT16              dimension1,
        UINT16              dimension2,
        DebugDataTagType    elementType,
        VOID*               pData)
    {
        CamxResult              result          = CamxResultSuccess;
        DebugDataTag*           pTag            = reinterpret_cast<DebugDataTag*>(GetCurBufferPos());
        DebugData2DArrayHeader* p2DArrayHeader  = NULL;
        SIZE_T                  arraySize       = 0;
        SIZE_T                  totalSize       = 0;

        if (NULL == pTag)
        {
            result = CamxResultEInvalidPointer;
            return result;
        }

        arraySize   = dimension1 * dimension2 * GetSizeOfType(elementType);
        totalSize   = sizeof(DebugDataTag) + sizeof(DebugData2DArrayHeader) + arraySize;
        if (m_bytesWritten + totalSize > m_bufferSize)
        {
            result = CamxResultENoMemory;
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Insufficient size to write data", WriterToString(m_writerId));
            return result;
        }

        // Write the tag header
        pTag->id                        = id;
        pTag->type                      = DebugDataTagType::TwoDimArray;
        pTag->count                     = static_cast<TagCount>(sizeof(DebugData2DArrayHeader) + arraySize);
        m_bytesWritten                 += sizeof(DebugDataTag);
        // Write the array header
        p2DArrayHeader                  = reinterpret_cast<DebugData2DArrayHeader*>(GetCurBufferPos());
        p2DArrayHeader->underlyingType  = elementType;
        p2DArrayHeader->dimension1      = dimension1;
        p2DArrayHeader->dimension2      = dimension2;
        m_bytesWritten                 += sizeof(DebugData2DArrayHeader);
        // Write the array payload
        CamX::Utils::Memcpy(GetCurBufferPos(), pData, arraySize);
        m_bytesWritten                 += arraySize;
        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FillTuningMetadataHeader
    ///
    /// @brief  Helper function to fill information into debug-data header
    ///
    /// @param  pHeader         Header to be fill, with the data provided by the other parameters.
    /// @param  pipelineID      Pipeline identification number
    /// @param  pathID          If multiple HW modules in same pipeline, but different path
    /// @param  order           If multiple HW modules in same path. ID number starting with 0 from input to output
    /// @param  reservedID0     Reserved parameter for feature use
    /// @param  reservedID1     Reserved parameter for feature use
    /// @param  reservedID2     Reserved parameter for feature use
    /// @param  reservedID3     Reserved parameter for feature use
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult FillTuningMetadataHeader(
        DebugDataHeaderV1*  pHeader,
        DebugDataPipelineID pipelineID,
        UINT8               pathID      = 0,
        UINT8               order       = 0,
        UINT16              reservedID0 = 0,
        UINT16              reservedID1 = 0,
        UINT16              reservedID2 = 0,
        UINT16              reservedID3 = 0)
    {
        CamxResult result = CamxResultSuccess;

        if (NULL == pHeader)
        {
            result = CamxResultEInvalidPointer;
        }

        if (result == CamxResultSuccess)
        {
            pHeader->pipelineID     = pipelineID;
            pHeader->pathID         = pathID;
            pHeader->orderID        = order;
            pHeader->reservedID[0]  = reservedID0;
            pHeader->reservedID[1]  = reservedID1;
            pHeader->reservedID[2]  = reservedID2;
            pHeader->reservedID[3]  = reservedID3;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// WriterToString
    ///
    /// @brief  Converts a WriterId into a human readable string
    ///
    /// @param  writerId    WriterId to be converted into string
    ///
    /// @return Stringized WriterId
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static const CHAR* WriterToString(
            WriterId writerId)
    {
        const CHAR* pString = NULL;

        switch (writerId)
        {
            case WriterId::AECWriter:          pString = "[AECWriter]";            break;
            case WriterId::AWBWriter:          pString = "[AWBWriter]";            break;
            case WriterId::AFWriter:           pString = "[AFWriter]";             break;
            case WriterId::ASDWriter:          pString = "[ASDWriter]";            break;
            case WriterId::AFDWriter:          pString = "[AFDWriter]";            break;
            case WriterId::AFCWriter:          pString = "[AFCWriter]";            break;
            case WriterId::ConciseAECXWriter:  pString = "[ConciseAECXWriter]";    break;
            case WriterId::ConciseAWBWriter:   pString = "[ConciseAWBWriter]";     break;
            case WriterId::ConciseAFWriter:    pString = "[ConciseAFWriter]";      break;
            case WriterId::OtherWriter:        pString = "[OtherWriter]";          break;
            case WriterId::WriterMax:          pString = "[WriterMax]";            break;
            default:                           pString = "[UNKNOWN_Writer]";       break;
        }

        return pString;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConfigureCustomizedTags
    ///
    /// @brief  Configure customized tag array
    ///
    /// @param  pCustomizedTagArray     Pointer of Customized tag array
    /// @param  arraySize               Customized tag array size
    ///
    /// @return CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ConfigureCustomizedTags(
        UINT16*       pCustomizedTagArray,
        UINT32        arraySize)
    {
        CamxResult result      = CamxResultSuccess;

        if ((0 < arraySize) && (NULL != pCustomizedTagArray))
        {
            m_pCustomizedTagArray  = pCustomizedTagArray;
            m_CustomizedTagSize    = arraySize;
            m_enableCustomizedTags = TRUE;
        }
        else
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Customized tag array is not valid", WriterToString(m_writerId));
            m_CustomizedTagSize    = 0;
            m_pCustomizedTagArray  = NULL;
            m_enableCustomizedTags = FALSE;
            result = CamxResultEFailed;
        }

        return result;
    }

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypedefFieldArray
    ///
    /// @brief  Declares a field of a type. This is for arrays
    ///
    /// @param  fieldType   A field type from our predeclared list
    /// @param  count       The number of fields. This should be greater than or equal to 1
    ///
    /// @return TRUE on success adding type definition
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL AddTypedefFieldArray(
        DebugDataTagType    fieldType,
        UINT16              count)
    {
        BOOL result = TRUE;

        if (TRUE == m_getSizeMode)
        {
            // Get how much size will be required
            m_sizeTagTypes += sizeof(TypedefFieldInfo);

            result = FALSE; // No tag definition was added
        }
        else {
            if (static_cast<SIZE_T>(m_bufferRemaining) < sizeof(TypedefFieldInfo))
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Insufficient size to write data", WriterToString(m_writerId));
                result = FALSE;
            }
            else if (count <= 0)
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Invalid field count of %u. Value must be greater than zero",
                              WriterToString(m_writerId), count);
                result = FALSE;
            }
            else if (DebugDataTagType::TypeDefinition == fieldType)
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Invalid field type! Cannot use typedefs as a field type",
                              WriterToString(m_writerId));
                result = FALSE;
            }
            else
            {

                TypedefFieldInfo* pField = reinterpret_cast<TypedefFieldInfo*>(m_pBuffer + m_bufferSize - m_bufferRemaining);
                pField->fieldID    = ++m_fieldsID;
                pField->type       = fieldType;
                pField->count      = static_cast<TypedefFieldLen>(count);
                m_bufferRemaining -= static_cast<INT32>(sizeof(TypedefFieldInfo));
                m_sanitySize      += (count * GetSizeOfType(fieldType));
            }
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypedefField2DArray
    ///
    /// @brief  Declares a field of a type in two dimensions
    ///
    /// @param  fieldType   A field type from our predeclared list
    /// @param  dimension1  Count of the elements of the 2D array's first dimension (number of rows)
    /// @param  dimension2  Count of the elements of the 2D array's first dimension (number of columns)
    ///
    /// @return Size of data written in this field
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL AddTypedefField2DArray(
        DebugDataTagType    fieldType,
        UINT16              dimension1,
        UINT16              dimension2)
    {
        BOOL result = TRUE;

        if (TRUE == m_getSizeMode)
        {
            // Get how much size will be required
            m_sizeTagTypes += (2 * sizeof(TypedefFieldInfo));

            result = FALSE; // No tag definition added
        }
        else
        {
            if (static_cast<SIZE_T>(m_bufferRemaining) < 2 * sizeof(TypedefFieldInfo))
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Insufficient size to write data", WriterToString(m_writerId));
                return FALSE;
            }
            else if (dimension1 <= 0 || dimension2 <= 0)
            {
                CAMX_LOG_WARN(CamxLogGroupDebugData,
                              "%s: Invalid dimensions for the 2D array! Values must be greater than zero",
                              WriterToString(m_writerId));
                return FALSE;
            }

            TypedefFieldInfo* pField = reinterpret_cast<TypedefFieldInfo*>(m_pBuffer + m_bufferSize - m_bufferRemaining);
            pField->fieldID    = ++m_fieldsID;
            pField->type       = DebugDataTagType::TwoDimArray;
            pField->count      = static_cast<TypedefFieldLen>(dimension1);
            m_bufferRemaining -= static_cast<INT32>(sizeof(TypedefFieldInfo));

            pField++;
            // Corner case: 2D arrays require two repeating field-info's with the same IDs. Don't increment the ID again
            pField->fieldID    = m_fieldsID;
            pField->type       = fieldType;
            pField->count      = static_cast<TypedefFieldLen>(dimension2);
            m_bufferRemaining -= sizeof(TypedefFieldInfo);
            m_sanitySize      += (dimension1 * dimension2 * GetSizeOfType(fieldType));

            result = TRUE;
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypedefField
    ///
    /// @brief  Declares a field of a type
    ///
    /// @param  fieldType   A field type from our predeclared list
    ///
    /// @return Size of data written in this field
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CAMX_INLINE BOOL AddTypedefField(
        DebugDataTagType    fieldType)
    {
        return AddTypedefFieldArray(fieldType, 1);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetSizeOfBuiltInType
    ///
    /// @brief  Get the size of a built-in type. Inheritors of this class should call this from their
    ///         GetSizeOfType function
    ///
    /// @param  type    The data type to get the size of
    ///
    /// @return Size of data
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    UINT32 GetSizeOfBuiltInType(
        DebugDataTagType type)
    {
        UINT32 size = 0;
        switch(type)
        {
            case DebugDataTagType::TypeDefinition:
                // Special case: payload of a type definition tag is an array of TypedefFieldInfo[]
                size = sizeof(TypedefFieldInfo);
                break;
            case DebugDataTagType::Char:
                // Byte stream. Tag count describes the overall size of tag
                size = sizeof(CHAR);
                break;
            case DebugDataTagType::Bool:
                // Explicitly ensure that bool is one byte. Depending on implementation, BOOL/bool could be 4 bytes
                size = sizeof(UINT8);
                break;
            case DebugDataTagType::UInt8:
                size = sizeof(UINT8);
                break;
            case DebugDataTagType::UInt16:
                size = sizeof(UINT16);
                break;
            case DebugDataTagType::UInt32:
                size = sizeof(UINT32);
                break;
            case DebugDataTagType::UInt64:
                size = sizeof(UINT64);
                break;
            case DebugDataTagType::Int8:
                size = sizeof(INT8);
                break;
            case DebugDataTagType::Int16:
                size = sizeof(INT16);
                break;
            case DebugDataTagType::Int32:
                size = sizeof(INT32);
                break;
            case DebugDataTagType::Int64:
                size = sizeof(INT64);
                break;
            case DebugDataTagType::Float:
                size = sizeof(float);
                break;
            case DebugDataTagType::Double:
                size = sizeof(double);
                break;
            case DebugDataTagType::QNumber:
                size = sizeof(DebugDataQNumber);
                break;
            case DebugDataTagType::UQNumber:
                size = sizeof(DebugDataUQNumber);
                break;
            case DebugDataTagType::Rational:
                size = sizeof(DebugDataRational);
                break;
            case DebugDataTagType::URational:
                size = sizeof(DebugDataURational);
                break;
            case DebugDataTagType::TwoDimArray:
                // Byte stream. Tag count describes the overall size of tag
                // The payload contains the header 'DebugDataTwoDimArrayHeader' to describe the array dimensions
                size = sizeof(char);
                break;

            default :
                break;
        }
        return size;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetCurBufferPos
    ///
    /// @brief  Gets a pointer to the current buffer position, or NULL if no buffer is used
    ///
    /// @return Pointer to the current buffer location
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BYTE* GetCurBufferPos()
    {
        return (NULL == m_pBuffer ? m_pBuffer : (m_pBuffer + m_bytesWritten));
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SealUnusedSpace
    ///
    /// @brief  Ensures that the last tag in the data is a DebugDataTagID::UnusedSpace tag, containing the remainder of the
    ///         Debug Data buffer
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SealUnusedSpace()
    {
        CamxResult      result      = CamxResultSuccess;
        DebugDataTag*   pTag        = reinterpret_cast<DebugDataTag*>(GetCurBufferPos());
        UINT64          unusedBytes = 0;
        if (NULL == pTag)
        {
            CAMX_LOG_WARN(CamxLogGroupDebugData, "%s: Debug data buffer is NULL", WriterToString(m_writerId));
            result = CamxResultEInvalidState;
        }
        else
        {
            // NOTE: The UnusedSpace tag can always be added at the end of the buffer because we have adjusted the buffer size
            // to take that into account. Ignore size checks for that tag, and intentionally don't increment the bytes written
            // member variable. This tag is intended to be overwritten by the next call to AddDataTag()
            pTag->id    = DebugDataTagID::UnusedSpace;
            pTag->type  = DebugDataTagType::UInt8;
            if ((m_bufferSize < m_bytesWritten))
            {
                unusedBytes = 0;
            }
            else
            {
                unusedBytes = m_bufferSize - m_bytesWritten;
            }
            pTag->count = static_cast<TagCount>(unusedBytes);
        }

        return result;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// AddTypeDefinitionTags
    ///
    /// @brief  Add a set of type definition tags based on the implementation requirements
    ///
    /// @return  CamxResult
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult AddTypeDefinitionTags() = 0;

    WriterId    m_writerId;             ///< The writer identifier
    BYTE*       m_pBuffer;              ///< Pointer to buffer allocated outside
    SIZE_T      m_bufferSize;           ///< The size of the buffer
    SIZE_T      m_bytesWritten;         ///< The number of bytes written to the buffer

    // These are reset with each call to AddTypeDefinitionTag() and should not be referenced anywhere else
    UINT8       m_fieldsID;             ///< What's the next field ID?
    INT32       m_bufferRemaining;      ///< How many bytes are left in the buffer
    SIZE_T      m_sanitySize;           ///< Sanity check: size of the current typedef fields defined

    // Helper to get size for Tag definitions
    SIZE_T      m_sizeTagTypes;         ///< Size for TagType definitions
    BOOL        m_getSizeMode;          ///< TRUE if getting size for TagType definitions and NOT writing them on buffer

    BOOL        m_enableCustomizedTags;         ///< Enable concise tags or not
    UINT16*     m_pCustomizedTagArray;          ///< Pointer of customized tag array
    UINT32      m_CustomizedTagSize;            ///< Active size of customized tags
};

#endif // CAMXSTATSDEBUGDATAWRITER_H
