/*
* Copyright (c) 2017-2021, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file     media_libva_caps.h
//! \brief    This file defines the base C++ class/interface for media capbilities.
//!

#ifndef __MEDIA_LIBVA_CAPS_H__
#define __MEDIA_LIBVA_CAPS_H__

#include "va/va.h"

#include <vector>
#include <map>

#ifndef CONTEXT_PRIORITY_MAX
#define CONTEXT_PRIORITY_MAX 1024
#endif

struct DDI_MEDIA_CONTEXT;
class MediaLibvaCapsCpInterface;

typedef std::map<VAConfigAttribType, uint32_t> AttribMap;

//!
//! \class  MediaLibvaCaps
//! \brief  Media libva caps
//!
class MediaLibvaCaps
{
protected:
    MediaLibvaCaps(DDI_MEDIA_CONTEXT *mediaCtx);
public:

    //!
    //! \brief    Destructor
    //!
    virtual ~MediaLibvaCaps();

    //!
    //! \brief    Get attributes for a given profile/entrypoint pair
    //! \details  The caller must provide an "attribList" with all attributes to be
    //!           retrieved.  Upon return, the attributes in "attribList" have been
    //!           updated with their value.  Unknown attributes or attributes that are
    //!           not supported for the given profile/entrypoint pair will have their
    //!           value set to VA_ATTRIB_NOT_SUPPORTED.
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypoint
    //!           VA entrypoint
    //!
    //! \param    [in,out] attribList
    //!           Pointer to VAConfigAttrib array. The attribute type is set by caller and
    //!           attribute value is set by this function.
    //!
    //! \param    [in] numAttribs
    //!           Number of VAConfigAttrib in the array attribList
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetConfigAttributes(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttrib *attribList,
            int32_t numAttribs);

    //!
    //! \brief    Check a profile valid or not
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CheckProfile(VAProfile profile);
    //!
    //!
    //! \brief    Create a configuration for the encode/decode/vp pipeline
    //! \details  It passes in the attribute list that specifies the attributes it
    //!           cares about, with the rest taking default values.
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypoint
    //!           VA entrypoint
    //!
    //! \param    [in] attribList
    //!           Pointer to VAConfigAttrib array that specifies the attributes
    //!
    //! \param    [in] numAttribs
    //!           Number of VAConfigAttrib in the array attribList
    //!
    //! \param    [out] configId
    //!           Pointer to returned VAConfigID if success
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateConfig(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttrib *attribList,
            int32_t numAttribs,
            VAConfigID *configId);

    //!
    //! \brief    Query supported profiles
    //!
    //! \param    [in] profileList
    //!           Pointer to VAProfile array that can hold at least vaMaxNumProfile() entries
    //!
    //! \param    [out] numProfiles
    //!           Pointer to int32_t. It returns the actual number of supported profiles.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus QueryConfigProfiles(
            VAProfile *profileList,
            int32_t *numProfiles);

    //!
    //! \brief    Query supported entrypoints for a given profile
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypointList
    //!           Pointer to VAEntrypoint array that can hold at least vaMaxNumEntrypoints() entries
    //!
    //! \param    [out] numEntryPoints
    //!           It returns the actual number of supported VAEntrypoints.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus QueryConfigEntrypoints(
            VAProfile profile,
            VAEntrypoint *entrypointList,
            int32_t *numEntryPoints);

    //!
    //! \brief    Query all attributes for a given configuration
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in,out] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \param    [in,out] attribList
    //!           Pointer to VAConfigAttrib array that can hold at least
    //!           vaMaxNumConfigAttributes() entries.
    //!
    //! \param    [in,out] numAttribs
    //!           The actual number of VAConfigAttrib returned in the array attribList
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus QueryConfigAttributes(
            VAConfigID configId,
            VAProfile *profile,
            VAEntrypoint *entrypoint,
            VAConfigAttrib *attribList,
            int32_t *numAttribs);

    //!
    //! \brief    Get attributes for a given encode config ID
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in,out] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \param    [in,out] rcMode
    //!           Return the rcMode for the config ID.
    //!
    //! \param    [in,out] feiFunction
    //!           Return the fei function type for the config ID.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetEncConfigAttr(
            VAConfigID configId,
            VAProfile *profile,
            VAEntrypoint *entrypoint,
            uint32_t *rcMode,
            uint32_t *feiFunction);

    //!
    //! \brief    Get attributes for a given decode config ID
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in,out] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \param    [in,out] slicemode
    //!           Return the slice mode for the config ID.
    //!
    //! \param    [in,out] encrypttype
    //!           Return the encryption type for the config ID.
    //!
    //! \param    [in,out] processmode
    //!           Return the process mode for the config ID.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetDecConfigAttr(
            VAConfigID configId,
            VAProfile *profile,
            VAEntrypoint *entrypoint,
            uint32_t *slicemode,
            uint32_t *encrypttype,
            uint32_t *processmode);

    //!
    //! \brief    Get attributes for a given Vp config ID
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in,out] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetVpConfigAttr(
            VAConfigID configId,
            VAProfile *profile,
            VAEntrypoint *entrypoint);

    //!
    //! \brief    Get process rate for a given config ID
    //!
    //! \param    [in] config_id
    //!           VA configuration
    //!
    //! \param    [in,out] procBuf
    //!           Pointer to VAProcessingRateParameter
    //!
    //! \param    [in,out] processingRate
    //!           Return the process rate
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus QueryProcessingRate(
            VAConfigID config_id,
            VAProcessingRateParameter *procBuf,
            uint32_t *processingRate);

    //!
    //! \brief    Get surface attributes for a given config ID
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] attribList
    //!           Pointer to VASurfaceAttrib array. It returns
    //!           the supported  surface attributes
    //!
    //! \param    [in,out] numAttribs
    //!           The number of elements allocated on input
    //!           Return the number of elements actually filled in output
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!           VA_STATUS_ERROR_MAX_NUM_EXCEEDED if size of attribList is too small
    //!
    virtual VAStatus QuerySurfaceAttributes(
            VAConfigID configId,
            VASurfaceAttrib *attribList,
            uint32_t *numAttribs);

    //!
    //! \brief    Query display attributes
    //!
    //! \param    [in, out] attribList
    //!           it returns the supported display attributes
    //!
    //!
    //! \param    [in, out] numAttribs
    //!           it returns the actual number of supported attributes
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!           VA_STATUS_ERROR_MAX_NUM_EXCEEDED if size of attribList is too small
    //!
    virtual VAStatus QueryDisplayAttributes(
            VADisplayAttribute *attribList,
            int32_t *numAttribs);

    //!
    //! \brief    Get display attributes
    //!           returns the current attributes values in "attribList"
    //!
    //! \param    [in, out] attribList
    //!           the attrib type should be filled.
    //!           returns the supported display attributes
    //!
    //! \param    [in] numAttribs
    //!           the number of supported attributes
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!           VA_STATUS_ERROR_MAX_NUM_EXCEEDED if size of attribList is too small
    //!
    virtual VAStatus GetDisplayAttributes(
            VADisplayAttribute *attribList,
            int32_t numAttribs);
  
    //!
    //! \brief    Check if the resolution is valid for a given decode codec mode
    //!
    //! \param    [in] codecMode
    //!           Specify the codec mode
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] width
    //!           Specify the width for checking
    //!
    //! \param    [in] height
    //!           Specify the height for checking
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if the resolution is supported
    //!           VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED if the resolution isn't valid
    //!
    virtual VAStatus CheckDecodeResolution(
            int32_t codecMode,
            VAProfile profile,
            uint32_t width,
            uint32_t height);

    //!
    //! \brief    Check if the resolution is valid for a encode profile
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \param    [in] width
    //!           Specify the width for checking
    //!
    //! \param    [in] height
    //!           Specify the height for checking
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if the resolution is supported
    //!           VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED if the resolution isn't valid
    //!
    virtual VAStatus CheckEncodeResolution(
            VAProfile profile,
            uint32_t width,
            uint32_t height);

    //!
    //! \brief    Check if the give profile is VC1
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a VC1 profile
    //!           False if the profile isn't a VC1 profile
    //!
    static bool IsVc1Profile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is MPEG2
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a MPEG2 profile
    //!           False if the profile isn't a MPEG2 profile
    //!
    static bool IsMpeg2Profile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is AVC
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a AVC profile
    //!           False if the profile isn't a AVC profile
    //!
    static bool IsAvcProfile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is HEVC
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a HEVC profile
    //!           False if the profile isn't a HEVC profile
    //!
    virtual bool IsHevcProfile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is VP8
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   true if the profile is a VP8 profile
    //!           false if the profile isn't a VP8 profile
    //!
    static bool IsVp8Profile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is VP9
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a VP9 profile
    //!           False if the profile isn't a VP9 profile
    //!
    static bool IsVp9Profile(VAProfile profile);

    //!
    //! \brief    Check if the give profile is JPEG
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   True if the profile is a JPEG profile
    //!           False if the profile isn't a JPEG profile
    //!
    static bool IsJpegProfile(VAProfile profile);

    //!
    //! \brief    Check if current FeiFuncton or give entrypoint is FEI
    //!
    //! \param    [in] entrypoint
    //!           Specify the VAEntrypoint for checking
    //!
    //! \param    [in] feiFunction
    //!           Specify the VA_FEI_FUNCTION for checking
    //!
    //! \return   True if the entrypoint or the feiFuncton belong to FEI
    //!           False if the entrypoint and the FeiFuncton aren't FEI
    //!
    bool IsEncFei(VAEntrypoint entrypoint, uint32_t feiFunction);

    //!
    //! \brief    Return the CODECHAL_FUNCTION type for give profile and entrypoint
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \param    [in] entrypoint
    //!           Specify the VAEntrypoint
    //!
    //! \param    [in] feiFunction
    //!           Specify the VA_FEI_FUNCTION
    //!
    //! \return   Codehal function
    //!
    CODECHAL_FUNCTION GetEncodeCodecFunction(VAProfile profile, VAEntrypoint entrypoint, uint32_t feiFunction);

    //!
    //! \brief    Return internal encode mode for given profile and entrypoint
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \param    [in] entrypoint
    //!           Specify the VAEntrypoint
    //!
    //! \return   Codehal mode
    //!
    virtual CODECHAL_MODE GetEncodeCodecMode(VAProfile profile, VAEntrypoint entrypoint);

    //!
    //! \brief    Return internal decode mode for given profile
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   Codehal mode: decode codec mode
    //!
    virtual CODECHAL_MODE GetDecodeCodecMode(VAProfile profile);

    //!
    //! \brief    Return the decode codec key for given profile
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   Std::string decode codec key
    //!
    virtual std::string GetDecodeCodecKey(VAProfile profile);

    //!
    //! \brief    Return the encode codec key for given profile and entrypoint
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \param    [in] entrypoint
    //!           Specify the entrypoint
    //!
    //! \param    [in] feiFunction
    //!           Specify the feiFunction
    //!
    //! \return   Std::string encode codec key
    //!
    virtual std::string GetEncodeCodecKey(VAProfile profile, VAEntrypoint entrypoint, uint32_t feiFunction);

    //!
    //! \brief    Query the suppported image formats
    //!
    //! \param    [in,out] formatList
    //!           Pointer to a VAImageFormat array. The array size shouldn't be less than vaMaxNumImageFormats
    //!           It will return the supported image formats.
    //!
    //! \param    [in,out] num_formats
    //!           Pointer to a integer that will return the real size of formatList.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if succeed
    //!
    virtual VAStatus QueryImageFormats(VAImageFormat *formatList, int32_t *num_formats) = 0;

    //!
    //! \brief    Return the maxinum number of supported image formats
    //!
    //! \return   The maxinum number of supported image formats
    //!
    virtual uint32_t GetImageFormatsMaxNum() = 0;

    //!
    //! \brief    Populate the color masks info
    //!
    //! \param    [in,out] Image format
    //!           Pointer to a VAImageFormat array. Color masks information will be populated to this
    //!           structure.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if succeed
    //!
    virtual VAStatus PopulateColorMaskInfo(VAImageFormat *vaImgFmt) = 0;

    virtual bool IsImageSupported(uint32_t fourcc) = 0;

    //!
    //! \brief    Query AVC ROI maxinum numbers and if support ROI in delta QP
    //!
    //! \param    [in] rcMode
    //!           Specify the rate control mode to query
    //!
    //! \param    [in] isVdenc
    //!           Specify whether it is vdenc or not
    //!
    //! \param    [in,out] maxNum
    //!           Pointer to a integer that will return the maximum number of ROI.
    //!
    //! \param    [in,out] isRoiInDeltaQP
    //!           Pointer to a bool that will return if ROI in delta QP is supported
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if succeed
    //!
    virtual VAStatus QueryAVCROIMaxNum(uint32_t rcMode, bool isVdenc, uint32_t *maxNum, bool *isRoiInDeltaQP) = 0;

    //!
    //! \brief    Check if the configID is a valid decode config
    //!
    //! \param    [in] configId
    //!           Specify the VAConfigID
    //!
    //! \return   True if the configID is a valid decode config, otherwise false
    //!
    bool IsDecConfigId(VAConfigID configId);

    //!
    //! \brief    Check if the configID is a valid encode config
    //!
    //! \param    [in] configId
    //!           Specify the VAConfigID
    //!
    //! \return   True if the configID is a valid encode config, otherwise false
    //!
    bool IsEncConfigId(VAConfigID configId);

    //!
    //! \brief    Check if the configID is a valid vp config
    //!
    //! \param    [in] configId
    //!           Specify the VAConfigID
    //!
    //! \return   True if the configID is a valid vp config, otherwise false
    //!
    bool IsVpConfigId(VAConfigID configId);

    //!
    //! \brief    Get CP Caps object
    //!
    //! \return   return MediaLibvaCapsCpInterface*
    //!
    MediaLibvaCapsCpInterface* GetCpCaps();

    //!
    //! \brief    Check if the entrypoint is supported by MFE
    //!
    //! \param    [in] entrypoint
    //!           Specify the VAEntrypoint
    //!
    //! \return   true if supported, otherwise false
    //!
    bool IsMfeSupportedEntrypoint(VAEntrypoint entrypoint);

    //!
    //! \brief    Check if the profile is supported by MFE
    //!
    //! \param    [in] profile
    //!           Specify the VAProfile
    //!
    //! \return   true if supported, otherwise false
    //!
    bool IsMfeSupportedProfile(VAProfile profile);

    //!
    //! \brief    Destory the VAConfigID
    //!
    //! \param    [in] configId
    //!           Specify the VAConfigID
    //!
    //! \return   VAStatus
    //!       VA_STATUS_SUCCESS if succeed
    //!           VA_STATUS_ERROR_INVALID_CONFIG if the conifgId is invalid
    //!
    VAStatus DestroyConfig(VAConfigID configId);

    //!
    //! \brief    Create MediaLibvaCaps instance for current platform
    //!
    //! \param    [in] mediaCtx
    //!           Pointer to DDI_MEDIA_CONTEXT
    //!
    //! \return   MediaLibvaCaps *
    //!           Pointer to Gen specific MediaLibvaCaps if success, otherwise return nullptr
    //!
    static MediaLibvaCaps * CreateMediaLibvaCaps(DDI_MEDIA_CONTEXT *mediaCtx);

    //!
    //! \brief convert Media Format to Gmm Format for GmmResCreate parameter.
    //!
    //! \param    [in] format
    //!         Pointer to DDI_MEDIA_FORMAT
    //!
    //! \return GMM_RESOURCE_FORMAT
    //!         Pointer to gmm format type
    //!
    virtual GMM_RESOURCE_FORMAT ConvertMediaFmtToGmmFmt(DDI_MEDIA_FORMAT format);

    //!
    //! \brief convert FOURCC to Gmm Format.
    //!
    //! \param    [in] fourcc
    //!
    //! \return GMM_RESOURCE_FORMAT
    //!         Pointer to gmm format type
    //!
    virtual GMM_RESOURCE_FORMAT ConvertFourccToGmmFmt(uint32_t fourcc);

    //!
    //! \brief    Check if MFE is supported on the platform
    //!
    //! \param    [in] PLATFORM
    //!
    //! \return   true if supported, otherwise false
    //!
    virtual bool IsMfeSupportedOnPlatform(const PLATFORM &platform);

    //!
    //! \brief    Initialize the MediaLibvaCaps instance for current platform
    //!
    //! \return   VAStatus
    //!           return VA_STATUS_SUCCESS for success
    //!
    virtual VAStatus Init()
    {
        // do nothing by default
        return VA_STATUS_SUCCESS;
    }

    //! \brief Get surface drm modifier
    //!
    //! \param    [in] mediaSurface
    //!           Pointer to the media surface
    //! \param    [out] modifier
    //!           reference of the modifier
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus GetSurfaceModifier(DDI_MEDIA_SURFACE* mediaSurface, uint64_t &modifier);

    //! \brief Set tile format according to external surface's modifier
    //!
    //! \param    [in] mediaSurface
    //!           Pointer to the media surface
    //! \param    [out] tileformat
    //!           Reference to the tileformat
    //! \param    [out] bMemCompEnable
    //!           Reference to the memory compress flag
    //! \param    [out] bMemCompRC
    //!           Reference to the memory compress rate control
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus SetExternalSurfaceTileFormat(DDI_MEDIA_SURFACE* mediaSurface, uint32_t &tileformat, bool &bMemCompEnable, bool &bMemCompRC);

protected:
    //!
    //! \class    ProfileEntrypoint
    //! \brief    Profile entrypoint
    //!
    class ProfileEntrypoint
    {
        public:
            VAProfile m_profile = VAProfileNone; //!< Profile
            VAEntrypoint m_entrypoint = (VAEntrypoint)0; //!< Entrypoint
            AttribMap *m_attributes = nullptr; //!< Pointer to attributes map
            int32_t m_configStartIdx = 0; //!< Config Id offset to the decode or encode or vp config Id base
            //! \brief  The number of config Id that this profile & entrypoint combination supports
            //!
            int32_t m_configNum = 0; //!< Number of configs that above profile & entrypoint combination supports
    };

    //!
    //! \struct   DecConfig
    //! \brief    Decode configuration
    //!
    struct DecConfig
    {
        uint32_t m_sliceMode;   //!< Decode slice mode
        uint32_t m_encryptType; //!< Decode entrypoint Type
        uint32_t m_processType; //!< Decode processing Type

        DecConfig(const uint32_t sliceMode, const uint32_t encryptType, const uint32_t processType)
        : m_sliceMode(sliceMode), m_encryptType(encryptType), m_processType(processType) {}
    };

    //!
    //! \struct   EncConfig
    //! \brief    Encode configuration
    //!
    struct EncConfig
    {
        uint32_t m_rcMode;      //!< RateControl Mode
        uint32_t m_FeiFunction; //!< Decode entrypoint Type
        EncConfig(const uint32_t rcMode, const uint32_t FeiFunction)
        : m_rcMode(rcMode), m_FeiFunction(FeiFunction) {}
    };

    //!
    //! \enum     CodecType
    //! \brief    Codec type
    //!
    enum CodecType
    {
        videoEncode, //!< Video encode
        videoDecode, //!< Video decode
        videoProcess,//!< Video processing
        videoProtect //!< Video protection
    };

    enum EncodeFormat
    {
        AVC = 0,
        HEVC,
        VP9,
        AV1,
        Others = 0xff,
    };

    enum EncodeType
    {
        DualPipe = 0,
        Vdenc,
    };

    struct EncodeFormatTable
    {
        EncodeFormat    encodeFormat;
        EncodeType      encodeType;
        uint32_t        colorFormat;
    };

#if VA_CHECK_VERSION(1, 10, 0)
    static const uint32_t m_numEncRcMode = 10;
#else
    static const uint32_t m_numEncRcMode = 9;
#endif
    static const uint16_t m_maxProfiles = 17; //!< Maximum number of supported profiles
    static const uint16_t m_maxProfileEntries = 64; //!< Maximum number of supported profile & entrypoint combinations
    static const uint32_t m_numVpSurfaceAttr = 21; //!< Number of VP surface attributes
    static const uint32_t m_numJpegSurfaceAttr = 8; //!< Number of JPEG surface attributes
    static const uint32_t m_numJpegEncSurfaceAttr = 5; //!< Number of JPEG encode surface attributes
    static const uint16_t m_maxEntrypoints = 7; //!<  Maximum number of supported entrypoints
    static const uint32_t m_decSliceMode[2]; //!< Store 2 decode slices modes
    static const uint32_t m_decProcessMode[2]; //!< Store 2 decode process modes
    static const uint32_t m_encRcMode[m_numEncRcMode]; //!< Store encode rate control modes
    static const uint32_t m_vpSurfaceAttr[m_numVpSurfaceAttr]; //!< Store the VP surface attributes
    static const uint32_t m_jpegSurfaceAttr[m_numJpegSurfaceAttr]; //!< Store the JPEG surface attributes
    static const uint32_t m_jpegEncSurfaceAttr[m_numJpegEncSurfaceAttr]; //!< Store the JPEG encode surface attributes

    static const uint32_t m_decMpeg2MaxWidth = 2048; //!< Maximum width for Mpeg2 decode
    static const uint32_t m_decMpeg2MaxHeight = 2048; //!< Maximum height for Mpeg2 decode
    static const uint32_t m_decVc1MaxWidth = 3840; //!< Maximum width for VC1 decode
    static const uint32_t m_decVc1MaxHeight = 3840; //!< Maximum height for VC1 decode
    static const uint32_t m_decJpegMaxWidth = 16384;  //!< Maximum width for JPEG decode
    static const uint32_t m_decJpegMaxHeight = 16384; //!< Maximum height for JPEG decode
    static const uint32_t m_decHevcMaxWidth = 8192; //!< Maximum width for HEVC decode
    static const uint32_t m_decHevcMaxHeight = 8192; //!< Maximum height for HEVC decode
    static const uint32_t m_decVp9MaxWidth = 8192; //!< Maximum width for VP9 decode
    static const uint32_t m_decVp9MaxHeight = 8192; //!< Maximum height for VP9 decode
    static const uint32_t m_decDefaultMaxWidth = 4096; //!< Default maximum width for decode
    static const uint32_t m_decDefaultMaxHeight = 4096; //!< Default maximum height for decode

    static const uint32_t m_encMinWidth = 32; //!< Minimum width for encoding
    static const uint32_t m_encMinHeight = 32; //!< Minimum height for encoding
    static const uint32_t m_hevcVDEncMinWidth = 128; //!< Minimum width for HEVC VDEnc
    static const uint32_t m_hevcVDEncMinHeight = 128; //!< Minimum height for HEVC VDEnc
    static const uint32_t m_encMax4kWidth =
        CODEC_4K_MAX_PIC_WIDTH; //!< Minimum width for encoding
    static const uint32_t m_encMax4kHeight =
        CODEC_4K_MAX_PIC_HEIGHT; //!< Minimum height for encoding
    static const uint32_t m_encJpegMinWidth = 16; //!< Minimum width for encoding
    static const uint32_t m_encJpegMinHeight = 16; //!< Minimum height for encoding
    static const uint32_t m_encJpegMaxWidth =
        ENCODE_JPEG_MAX_PIC_WIDTH; //!< Maximum width for JPEG encoding
    static const uint32_t m_encJpegMaxHeight =
        ENCODE_JPEG_MAX_PIC_HEIGHT; //!< Maximum height for JPEG encoding
    DDI_MEDIA_CONTEXT *m_mediaCtx; //!< Pointer to media context

    friend class MediaLibvaCapsCpInterface;
    MediaLibvaCapsCpInterface* m_CapsCp;

    static constexpr uint32_t m_configAttribNone = 0x00000000; //!< Define for empty attrib

    //!
    //! \brief  Store all the supported encode format
    //!
    struct EncodeFormatTable* m_encodeFormatTable = nullptr;
    uint32_t m_encodeFormatCount = 0;

    //!
    //! \brief  Store all the profile and entrypoint combinations
    //!
    ProfileEntrypoint m_profileEntryTbl[m_maxProfileEntries];
    uint16_t m_profileEntryCount = 0; //!< Count valid entries in m_profileEntryTbl

    //!
    //! \brief  Store attribute list pointers
    //!
    std::vector<AttribMap *> m_attributeLists;

    bool m_isEntryptSupported = false; //!< If decode encryption is supported on current platform

    std::vector<EncConfig> m_encConfigs; //!< Store supported encode configs
    std::vector<DecConfig> m_decConfigs; //!< Store supported decode configs
    std::vector<uint32_t> m_vpConfigs;   //!< Store supported vp configs

    bool m_vdencActive = false;  //!< If vdenc is active on current platform

    //!
    //! \brief    Check entrypoint codec type
    //!
    //! \param    [in] entrypoint
    //!       VA entrypoint
    //! \param    [in] codecType
    //!       Codec type
    //!
    //! \return   True if entrypoint match the codecType
    //!
    bool CheckEntrypointCodecType(VAEntrypoint entrypoint, CodecType codecType);

    //!
    //! \brief    Add one decode configuration
    //!
    //! \param    [in] slicemode
    //!           VA_DEC_SLICE_MODE_xxx
    //!
    //! \param    [in] encryptType
    //!           Encryption Type
    //!
    //! \param    [in]  processType
    //!           VA_DEC_PROCESSINGxxx
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus AddDecConfig(uint32_t slicemode, uint32_t encryptType, uint32_t processType);

    //!
    //! \brief    Add one encode configuration
    //!
    //! \param    [in] rcMode
    //!           VA_RC_XXX
    //! \param    [in] feiFunction
    //!           VA_FEI_FUNCTION_XXX [optional parameter]
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus AddEncConfig(uint32_t rcMode, uint32_t feiFunction = 0);

    //!
    //! \brief    Add one vp configuration
    //!
    //! \param    [in] attrib
    //!           VP attribute
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus AddVpConfig(uint32_t attrib);

    //!
    //! \brief    Return profile and entrypoint for a give config ID
    //!
    //! \param    [in] configId
    //!           VA configuration
    //!
    //! \param    [in,out] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in,out] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \param    [in,out] profileTableIdx
    //!           The index in m_profileEntryTbl. Return -1 if config ID is invalid
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetProfileEntrypointFromConfigId(VAConfigID configId,
            VAProfile *profile,
            VAEntrypoint *entrypoint,
            int32_t *profileTableIdx);

    //!
    //! \brief    Add one entry to profile & entrypoint table
    //!
    //! \param    [in] profile
    //!           Pointer to VAProfile of the configuration
    //!
    //! \param    [in] entrypoint
    //!           Pointer to VAEntrypoint of the configuration
    //!
    //! \param    [in] attributeList
    //!           Pointer to VAConfigAttrib vector that stores attributes
    //!
    //! \param    [in] configIdxStart
    //!           Offset of config index in m_encConfigs, m_decConfigs or m_vpConfigs
    //!
    //! \param    [in] configNum
    //!           The number of supported configs.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus AddProfileEntry(VAProfile profile,
            VAEntrypoint entrypoint,
            AttribMap *attributeList,
            int32_t configIdxStart,
            int32_t configNum);

    //!
    //! \brief    Return the index in m_profileEntryTble by given profile and entrypoint
    //!
    //! \param    [in] profile
    //!           Specify VAProfile
    //!
    //! \param    [in] entrypoint
    //!           Specify VAEntrypoint
    //!
    //! \return   int32_t
    //!           Equal or bigger than zero if success, otherwise return -1
    //!
    int32_t GetProfileTableIdx(VAProfile profile, VAEntrypoint entrypoint);

    //!
    //! \brief    Create attributes map
    //!
    //! \param    [in,out] attributeList
    //!           Return the pointer to AttribMap
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateAttributeList(AttribMap **attributeList);

    //!
    //! \brief    Free attribuate lists
    //!
    VAStatus FreeAttributeList();

    //!
    //! \brief    Initialize the attribute types of a VAConfigAttrib array
    //!
    //! \param    [in,out] attribList
    //!           Pointer to VAConfigAttrib vector
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus InitAttributeTypes(std::vector<VAConfigAttrib> *attribList);

    //!
    //! \brief    Return index of given attribute type in a VAConfigAttrib vector
    //!
    //! \param    [in] attribList
    //!           Pointer to VAConfigAttrib vector.
    //!
    //! \param    [in] type
    //!           Specify the VAConfigAttribType to query
    //!
    //! \return   int32_t
    //!           Equal or bigger than zero if success, otherwise return -1
    //!
    int32_t GetAttributeIndex(std::vector<VAConfigAttrib> *attribList, VAConfigAttribType type);

    //!
    //! \brief    Set the attribute in a VAConfigAttrib array
    //!
    //! \param    [in,out] attributeList
    //!           Pointer to VAConfigAttrib vector
    //!
    //! \param    [in] type
    //!           VAConfigAttribType
    //!
    //! \param    [in] value
    //!           Attribute value
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus SetAttribute(
            std::vector<VAConfigAttrib> *attributeList,
            VAConfigAttribType type,
            uint32_t value);

    //!
    //! \brief    Set the attribute for the given profile and entrypoint
    //!
    //! \param    [in] profile
    //!           Specify VAProfile
    //!
    //! \param    [in] entrypoint
    //!           Specify VAEntrypoint
    //!
    //! \param    [in] type
    //!           VAConfigAttribType
    //!
    //! \param    [in] value
    //!           Attribute value
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus SetAttribute(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttribType type,
            uint32_t value);

    //!
    //! \brief    Create and intialize an attribute vector give encode profile and entrypoint
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypoint
    //!           VA entrypoint
    //!
    //! \param    [in,out] attributeList
    //!           Pointer to a pointer of AttribMap that will be created
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus CreateEncAttributes(
            VAProfile profile,
            VAEntrypoint entrypoint,
            AttribMap **attributeList);

    //!
    //! \brief    Create and intialize an attribute array give decode profile and entrypoint
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypoint
    //!           VA entrypoint
    //!
    //! \param    [in,out] attributeList
    //!           Pointer to a pointer of AttribMap that will be created
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus CreateDecAttributes(
            VAProfile profile,
            VAEntrypoint entrypoint,
            AttribMap **attributeList);

    //!
    //! \brief    Create and intialize an attribute array give Vp profile and entrypoint
    //!
    //! \param    [in] profile
    //!           VA profile
    //!
    //! \param    [in] entrypoint
    //!           VA entrypoint
    //!
    //! \param    [in,out] attributeList
    //!           Pointer to a pointer of AttribMap that will be created
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateVpAttributes(
            VAProfile profile,
            VAEntrypoint entrypoint,
            AttribMap **attributeList);

    //!
    //! \brief    Initialize AVC decode profiles, entrypoints and attributes
    //!
    VAStatus LoadAvcDecProfileEntrypoints();

    //!
    //! \brief    Initialize AVC encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadAvcEncProfileEntrypoints();

    //!
    //! \brief    Initialize AVC Low-power encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadAvcEncLpProfileEntrypoints();

    //!
    //! \brief    Initialize MPEG2 decode profiles, entrypoints and attributes
    //!
    VAStatus LoadMpeg2DecProfileEntrypoints();

    //!
    //! \brief    Initialize MPEG2 encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadMpeg2EncProfileEntrypoints();

    //!
    //! \brief    Initialize JPEG decode profiles, entrypoints and attributes
    //!
    VAStatus LoadJpegDecProfileEntrypoints();

    //!
    //! \brief    Initialize JPEG encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadJpegEncProfileEntrypoints();

    //!
    //! \brief    Initialize VC1 decode profiles, entrypoints and attributes
    //!
    VAStatus LoadVc1DecProfileEntrypoints();

    //!
    //! \brief    Initialize VP8 decode profiles, entrypoints and attributes
    //!
    VAStatus LoadVp8DecProfileEntrypoints();

    //!
    //! \brief    Initialize VP8 encode profiles, entrypoints and attributes
    //!
    VAStatus LoadVp8EncProfileEntrypoints();

    //!
    //! \brief    Initialize VP9 decode profiles, entrypoints and attributes
    //!
    VAStatus LoadVp9DecProfileEntrypoints();

    //!
    //! \brief    Initialize VP9 encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadVp9EncProfileEntrypoints();

    //!
    //! \brief    Initialize HEVC decode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadHevcDecProfileEntrypoints();

    //!
    //! \brief    Initialize HEVC decode profiles, entrypoints and attributes for specified hevc profile
    //!
    VAStatus LoadDecProfileEntrypoints(VAProfile profile);

    //!
    //! \brief    Initialize HEVC encode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadHevcEncProfileEntrypoints();

    //!
    //! \brief    Initialize none profiles, entrypoints and attributes
    //!
    VAStatus LoadNoneProfileEntrypoints();

    //!
    //! \brief    Initialize Advanced decode profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadAdvancedDecProfileEntrypoints();

    //!
    //! \brief    Initialize encode/decode/vp profiles, entrypoints and attributes
    //!
    virtual VAStatus LoadProfileEntrypoints() = 0;

    //!
    //! \brief    Create decode config by given attributes
    //!
    //! \param    [in] profileTableIdx
    //!           The index in m_profileEntryTbl.
    //!
    //! \param    [in] attribList
    //!           Pointer to VAConfigAttrib array
    //!
    //! \param    [in] numAttribs
    //!           Number of VAConfigAttrib in attribList
    //!
    //! \param    [in,out] configId
    //!           Pointer to VAConfigID.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateDecConfig(
        int32_t profileTableIdx,
        VAConfigAttrib *attribList,
        int32_t numAttribs,
        VAConfigID *configId);

    //!
    //! \brief    Create encode config by given attributes
    //!
    //! \param    [in] profileTableIdx
    //!           The index in m_profileEntryTbl.
    //!
    //! \param    [in] attribList
    //!           Pointer to VAConfigAttrib array
    //!
    //! \param    [in] numAttribs
    //!           Number of VAConfigAttrib in attribList
    //!
    //! \param    [in,out] configId
    //!           Pointer to VAConfigID.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateEncConfig(
        int32_t profileTableIdx,
        VAEntrypoint entrypoint,
        VAConfigAttrib *attribList,
        int32_t numAttribs,
        VAConfigID *configId);

    //!
    //! \brief    Create vp config by given attributes
    //!
    //! \param    [in] profileTableIdx
    //!           The index in m_profileEntryTbl.
    //!
    //! \param    [in] attribList
    //!           Pointer to VAConfigAttrib array
    //!
    //! \param    [in] numAttribs
    //!           Number of VAConfigAttrib in attribList
    //!
    //! \param    [in,out] configId
    //!           Pointer to VAConfigID.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CreateVpConfig(
        int32_t profileTableIdx,
        VAConfigAttrib *attribList,
        int32_t numAttribs,
        VAConfigID *configId);

    //!
    //! \brief    Return the platform specific value by given attribute type
    //!
    //! \param    [in] profile
    //!           VAProfile
    //!
    //! \param    [in] entrypoint
    //!           VAEntrypoint
    //!
    //! \param    [in] type
    //!           VAConfigAttribType
    //!
    //! \param    [in,out] value
    //!           Pointer to uint32_t that stores the returned value.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus GetPlatformSpecificAttrib(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttribType type,
            uint32_t *value) = 0;

    //!
    //! \brief    Return encode Mb processing rate on current platform
    //!
    //! \param    [in] skuTable
    //!           Point to MEDIA_FEATURE_TABLE
    //!
    //! \param    [in] tuIdx
    //!           Specify the index of target usage
    //!
    //! \param    [in] codecMode
    //!           Specify the codec mode
    //!
    //! \param    [in] vdencActive
    //!           Specify if vdenc is used
    //!
    //! \param    [in,out] mbProcessingRatePerSec
    //!           Pointer to uint32_t that stores the returned value.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus GetMbProcessingRateEnc(
            MEDIA_FEATURE_TABLE *skuTable,
            uint32_t tuIdx,
            uint32_t codecMode,
            bool vdencActive,
            uint32_t *mbProcessingRatePerSec);

    //!
    //! \brief    Return decode Mb processing rate on current platform
    //!
    //! \param    [in] skuTable
    //!           Point to MEDIA_FEATURE_TABLE
    //!
    //! \param    [in,out] mbProcessingRatePerSec
    //!           Pointer to uint32_t that stores the returned value.
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus GetMbProcessingRateDec(
            MEDIA_FEATURE_TABLE *skuTable,
            uint32_t *mbProcessingRatePerSec);

    //!
    //! \brief    Check the encode RT format according to platform and encode format
    //!
    //! \param    [in] profile
    //!           VAProfile
    //!
    //! \param    [in] entrypoint
    //!           VAEntrypoint
    //!
    //! \param    [in,out] attrib
    //!           Pointer to a pointer of VAConfigAttrib that will be created
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    virtual VAStatus CheckEncRTFormat(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttrib* attrib);
    //!
    //! \brief    Check the encode attribute list  according to profile and entrypoint
    //!
    //! \param    [in] profile
    //!           VAProfile
    //!
    //! \param    [in] entrypoint
    //!           VAEntrypoint
    //!
    //! \param    [in] attrib
    //!           Pointer to a pointer of VAConfigAttrib
    //!
    //! \param    [in] numAttribs
    //!           number of of VAConfigAttrib
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus CheckAttribList(
            VAProfile profile,
            VAEntrypoint entrypoint,
            VAConfigAttrib* attrib,
            int32_t numAttribs);

    //! \brief Get the general attribute
    //!
    //! \param    [in,out] attrib
    //!           Pointer to the CAConfigAttrib
    //!
    //! \return   VAStatus
    //!           VA_STATUS_SUCCESS if success
    //!
    VAStatus GetGeneralConfigAttrib(VAConfigAttrib* attrib);

};
#endif
