/* * Copyright (c) 2014-2018, 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 mhw_sfc.cpp //! \brief MHW interface for constructing commands for the SFC //! \details Impelements the functionalities common across all platforms for MHW_SFC //! #include "mhw_sfc.h" #include "mhw_utilities.h" MhwSfcInterface::MhwSfcInterface(PMOS_INTERFACE pOsInterface) { MHW_FUNCTION_ENTER; MOS_ZeroMemory(&m_outputSurfCtrl, sizeof(m_outputSurfCtrl)); MOS_ZeroMemory(&m_avsLineBufferCtrl, sizeof(m_avsLineBufferCtrl)); MOS_ZeroMemory(&m_iefLineBufferCtrl, sizeof(m_iefLineBufferCtrl)); MOS_ZeroMemory(&m_sfdLineBufferCtrl, sizeof(m_sfdLineBufferCtrl)); pfnAddResourceToCmd = nullptr; m_scalingMode = MHW_SCALING_AVS; if (pOsInterface == nullptr) { MHW_ASSERTMESSAGE("Invalid input pointers provided"); return; } if (!pOsInterface->bUsesGfxAddress && !pOsInterface->bUsesPatchList) { MHW_ASSERTMESSAGE("No valid addressing mode indicated"); return; } m_osInterface = pOsInterface; if (m_osInterface->bUsesGfxAddress) { pfnAddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress; } else //PatchList { pfnAddResourceToCmd = Mhw_AddResourceToCmd_PatchList; } } void MhwSfcInterface::SetSfcAVSChromaTable( PSFC_AVS_CHROMA_FILTER_COEFF pUVCoeffTable, int32_t *piUVCoefsX, int32_t *piUVCoefsY) { int32_t i; MHW_CHK_NULL_NO_STATUS_RETURN(pUVCoeffTable); MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsX); MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsY); for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pUVCoeffTable++) { pUVCoeffTable->DW0.Table1XFilterCoefficient2 = *(piUVCoefsX++); pUVCoeffTable->DW0.Table1XFilterCoefficient3 = *(piUVCoefsX++); pUVCoeffTable->DW1.Table1XFilterCoefficient4 = *(piUVCoefsX++); pUVCoeffTable->DW1.Table1XFilterCoefficient5 = *(piUVCoefsX++); pUVCoeffTable->DW0.Table1YFilterCoefficient2 = *(piUVCoefsY++); pUVCoeffTable->DW0.Table1YFilterCoefficient3 = *(piUVCoefsY++); pUVCoeffTable->DW1.Table1YFilterCoefficient4 = *(piUVCoefsY++); pUVCoeffTable->DW1.Table1YFilterCoefficient5 = *(piUVCoefsY++); } } void MhwSfcInterface::SetSfcAVSLumaTable( MOS_FORMAT SrcFormat, PSFC_AVS_LUMA_FILTER_COEFF pCoeffTable, int32_t *piYCoefsX, int32_t *piYCoefsY, bool bUse8x8Filter) { int32_t i; MHW_CHK_NULL_NO_STATUS_RETURN(pCoeffTable); MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsX); MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsY); for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pCoeffTable++) { // 4-tap filtering for G-channel, update only center 4 coeffs. if (IS_RGB32_FORMAT(SrcFormat) && (!bUse8x8Filter)) { pCoeffTable->DW0.Table0XFilterCoefficient0 = 0; pCoeffTable->DW0.Table0XFilterCoefficient1 = 0; pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++); pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++); pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++); pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++); pCoeffTable->DW3.Table0XFilterCoefficient6 = 0; pCoeffTable->DW3.Table0XFilterCoefficient7 = 0; pCoeffTable->DW0.Table0YFilterCoefficient0 = 0; pCoeffTable->DW0.Table0YFilterCoefficient1 = 0; pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++); pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++); pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++); pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++); pCoeffTable->DW3.Table0YFilterCoefficient6 = 0; pCoeffTable->DW3.Table0YFilterCoefficient7 = 0; } else { pCoeffTable->DW0.Table0XFilterCoefficient0 = *(piYCoefsX++); pCoeffTable->DW0.Table0XFilterCoefficient1 = *(piYCoefsX++); pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++); pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++); pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++); pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++); pCoeffTable->DW3.Table0XFilterCoefficient6 = *(piYCoefsX++); pCoeffTable->DW3.Table0XFilterCoefficient7 = *(piYCoefsX++); pCoeffTable->DW0.Table0YFilterCoefficient0 = *(piYCoefsY++); pCoeffTable->DW0.Table0YFilterCoefficient1 = *(piYCoefsY++); pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++); pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++); pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++); pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++); pCoeffTable->DW3.Table0YFilterCoefficient6 = *(piYCoefsY++); pCoeffTable->DW3.Table0YFilterCoefficient7 = *(piYCoefsY++); } } } MOS_STATUS MhwSfcInterface::SetSfcSamplerTable( PMHW_SFC_AVS_LUMA_TABLE pLumaTable, PMHW_SFC_AVS_CHROMA_TABLE pChromaTable, PMHW_AVS_PARAMS pAvsParams, MOS_FORMAT SrcFormat, float fScaleX, float fScaleY, uint32_t dwChromaSiting, bool bUse8x8Filter, float fHPStrength, float fLanczosT) { int32_t iPhaseOffset; int32_t *piYCoefsX, *piYCoefsY; int32_t *piUVCoefsX, *piUVCoefsY; MHW_PLANE Plane; MHW_CHK_NULL_RETURN(pLumaTable); MHW_CHK_NULL_RETURN(pChromaTable); MHW_CHK_NULL_RETURN(pAvsParams); piYCoefsX = pAvsParams->piYCoefsX; piYCoefsY = pAvsParams->piYCoefsY; piUVCoefsX = pAvsParams->piUVCoefsX; piUVCoefsY = pAvsParams->piUVCoefsY; // Skip calculation if no changes to AVS parameters if (SrcFormat == pAvsParams->Format && fScaleX == pAvsParams->fScaleX && fScaleY == pAvsParams->fScaleY) { return MOS_STATUS_SUCCESS; } // AVS Coefficients don't change for Scaling Factors > 1.0x // Hence recalculation is avoided if (fScaleX > 1.0F && pAvsParams->fScaleX > 1.0F) { pAvsParams->fScaleX = fScaleX; } // AVS Coefficients don't change for Scaling Factors > 1.0x // Hence recalculation is avoided if (fScaleY > 1.0F && pAvsParams->fScaleY > 1.0F) { pAvsParams->fScaleY = fScaleY; } // Recalculate Horizontal scaling table if (SrcFormat != pAvsParams->Format || fScaleX != pAvsParams->fScaleX) { MOS_ZeroMemory( piYCoefsX, 8 * 32 * sizeof(int32_t)); MOS_ZeroMemory( piUVCoefsX, 4 * 32 * sizeof(int32_t)); // 4-tap filtering for RGB format G-channel. Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE; pAvsParams->fScaleX = fScaleX; // Nearest, overwrite the coefficients. if (m_scalingMode == MHW_SCALING_NEAREST) { MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piYCoefsX, Plane, true)); MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piUVCoefsX, MHW_U_PLANE, true)); } else { // By default AVS coefficients // For 1x scaling in horizontal direction and not force polyphase coefs, use special coefficients for filtering if (fScaleX == 1.0F && !pAvsParams->bForcePolyPhaseCoefs) { MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piYCoefsX, Plane, true)); MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piUVCoefsX, MHW_U_PLANE, true)); } else { // Clamp the Scaling Factor if > 1.0x fScaleX = MOS_MIN(1.0F, fScaleX); MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY( piYCoefsX, fScaleX, Plane, SrcFormat, fHPStrength, bUse8x8Filter, NUM_HW_POLYPHASE_TABLES, fLanczosT)); } // If Chroma Siting info is present if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_LEFT) { // No Chroma Siting MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV( piUVCoefsX, 2.0F, fScaleX)); } else { // Chroma siting offset needs to be added if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) { iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F); // U0.4 } else //if (ChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) { iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F); // U0.4 } MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset( piUVCoefsX, 3.0F, fScaleX, iPhaseOffset)); } } } // Recalculate Vertical scaling table if (SrcFormat != pAvsParams->Format || fScaleY != pAvsParams->fScaleY) { MOS_ZeroMemory(piYCoefsY, 8 * 32 * sizeof(int32_t)); MOS_ZeroMemory(piUVCoefsY, 4 * 32 * sizeof(int32_t)); // 4-tap filtering for RGB format G-channel. Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE; pAvsParams->fScaleY = fScaleY; // Nearest, overwrite the coefficients. if (m_scalingMode == MHW_SCALING_NEAREST) { MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piYCoefsY, Plane, true)); MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piUVCoefsY, MHW_U_PLANE, true)); } else { // For 1x scaling in vertical direction and not force polyphase coefs, use special coefficients for filtering if (fScaleY == 1.0F && !pAvsParams->bForcePolyPhaseCoefs) { MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piYCoefsY, Plane, true)); MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable( piUVCoefsY, MHW_U_PLANE, true)); } else { // Clamp the Scaling Factor if > 1.0x fScaleY = MOS_MIN(1.0F, fScaleY); MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY( piYCoefsY, fScaleY, Plane, SrcFormat, fHPStrength, bUse8x8Filter, NUM_HW_POLYPHASE_TABLES, fLanczosT)); } // If Chroma Siting info is present if (dwChromaSiting & MHW_CHROMA_SITING_VERT_TOP) { // No Chroma Siting MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV( piUVCoefsY, 2.0F, fScaleY)); } else { // Chroma siting offset needs to be added if (dwChromaSiting & MHW_CHROMA_SITING_VERT_CENTER) { iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F); // U0.4 } else //if (ChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) { iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F); // U0.4 } MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset( piUVCoefsY, 3.0F, fScaleY, iPhaseOffset)); } } } // Save format used to calculate AVS parameters pAvsParams->Format = SrcFormat; SetSfcAVSLumaTable( SrcFormat, pLumaTable->LumaTable, piYCoefsX, piYCoefsY, bUse8x8Filter); SetSfcAVSChromaTable( pChromaTable->ChromaTable, piUVCoefsX, piUVCoefsY); return MOS_STATUS_SUCCESS; } MOS_STATUS MhwSfcInterface::GetInputFrameWidthHeightAlignUnit(uint32_t &widthAlignUnit, uint32_t &heightAlignUnit, bool bVdbox, CODECHAL_STANDARD codecStandard, CodecDecodeJpegChromaType jpegChromaType) { if (bVdbox) { if (CODECHAL_JPEG == codecStandard &&( jpegYUV400 == jpegChromaType || jpegYUV444 == jpegChromaType || jpegYUV422H2Y == jpegChromaType) || jpegBGR == jpegChromaType || jpegRGB == jpegChromaType) { widthAlignUnit = 8; heightAlignUnit = 8; return MOS_STATUS_SUCCESS; } else if (CODECHAL_HEVC == codecStandard || CODECHAL_VP9 == codecStandard) { widthAlignUnit = 8; heightAlignUnit = 8; return MOS_STATUS_SUCCESS; } else if (CODECHAL_AV1 == codecStandard) { widthAlignUnit = 1; heightAlignUnit = 1; return MOS_STATUS_SUCCESS; } else { widthAlignUnit = 16; heightAlignUnit = 16; return MOS_STATUS_SUCCESS; } } else { widthAlignUnit = m_veWidthAlignment; heightAlignUnit = m_veHeightAlignment; return MOS_STATUS_SUCCESS; } }