| /* |
| * Copyright (c) 2020, 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 codechal_encode_sfc_base.cpp |
| //! \brief Implements the encode interface extension for CSC via VEBox/SFC. |
| //! \details Downsampling in this case is supported by the VEBox fixed function HW unit. |
| //! |
| |
| #include "codechal_encode_sfc_base.h" |
| #include "codechal_encoder_base.h" |
| #include "hal_oca_interface.h" |
| |
| #define CODECHAL_IS_BT601_CSPACE(format) \ |
| ( (format == MHW_CSpace_BT601) || \ |
| (format == MHW_CSpace_xvYCC601) || \ |
| (format == MHW_CSpace_BT601Gray) || \ |
| (format == MHW_CSpace_BT601_FullRange) || \ |
| (format == MHW_CSpace_BT601Gray_FullRange) ) |
| |
| #define CODECHAL_IS_BT709_CSPACE(format) \ |
| ( (format == MHW_CSpace_BT709) || \ |
| (format == MHW_CSpace_xvYCC709) || \ |
| (format == MHW_CSpace_BT709_FullRange) ) |
| |
| // Generic YUV to RGB conversion matrix from BT.601 standard |
| const float CODECHAL_CSC_BT601_YUV_RGB[9] = |
| { |
| 1.000000f, 0.000000f, 1.402000f, |
| 1.000000f, -0.344136f, -0.714136f, |
| 1.000000f, 1.772000f, 0.000000f |
| }; |
| |
| // Generic YUV to RGB conversion matrix from BT.709 standard |
| const float CODECHAL_CSC_BT709_YUV_RGB[9] = |
| { |
| 1.000000f, 0.000000f, 1.574800f, |
| 1.000000f, -0.187324f, -0.468124f, |
| 1.000000f, 1.855600f, 0.000000f |
| }; |
| |
| // Generic RGB to YUV conversion matrix from BT.601 standard |
| const float CODECHAL_CSC_BT601_RGB_YUV[9] = |
| { |
| 0.299000f, 0.587000f, 0.114000f, |
| -0.168736f, -0.331264f, 0.500000f, |
| 0.500000f, -0.418688f, -0.081312f |
| }; |
| |
| // Generic RGB to YUV conversion matrix from BT.709 standard |
| const float CODECHAL_CSC_BT709_RGB_YUV[9] = |
| { |
| 0.212600f, 0.715200f, 0.072200f, |
| -0.114572f, -0.385428f, 0.500000f, |
| 0.500000f, -0.454153f, -0.045847f |
| }; |
| |
| // BT2020 RGB to Non-constant YUV conversion matrix from R-REC-BT.2020-1-201406-I!!PDF-E.pdf |
| const float CODECHAL_CSC_BT2020_RGB_YUV[9] = |
| { |
| 0.262700f, 0.678000f, 0.059300f, // Y |
| -0.139630f, -0.360370f, 0.500000f, // U |
| 0.500000f, -0.459786f, -0.040214f // V |
| }; |
| |
| // BT2020 Non-constant YUV to RGB conversion matrix from R-REC-BT.2020-1-201406-I!!PDF-E.pdf |
| const float CODECHAL_CSC_BT2020_YUV_RGB[9] = |
| { |
| 1.000000f, 0.000000f, 1.474600f, //R |
| 1.000000f, -0.164553f, -0.571353f, //G |
| 1.000000f, 1.881400f, 0.000000f //B |
| }; |
| |
| CodecHalEncodeSfcBase::~CodecHalEncodeSfcBase() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| // pVeboxInterface->pfnDestroy() will be called in CodecHal_HwDestroy(), no need to destroy here |
| |
| FreeResources(); |
| } |
| |
| bool CodecHalEncodeSfcBase::IsCspace(MHW_CSPACE srcCspace, MHW_CSPACE dstCspace) |
| { |
| switch (dstCspace) |
| { |
| case MHW_CSpace_RGB: |
| return (srcCspace == MHW_CSpace_sRGB || |
| srcCspace == MHW_CSpace_stRGB); |
| |
| case MHW_CSpace_YUV: |
| return (srcCspace == MHW_CSpace_BT709 || |
| srcCspace == MHW_CSpace_BT601 || |
| srcCspace == MHW_CSpace_BT601_FullRange || |
| srcCspace == MHW_CSpace_BT709_FullRange || |
| srcCspace == MHW_CSpace_xvYCC709 || |
| srcCspace == MHW_CSpace_xvYCC601); |
| |
| case MHW_CSpace_Gray: |
| return (srcCspace == MHW_CSpace_BT601Gray || |
| srcCspace == MHW_CSpace_BT601Gray_FullRange); |
| |
| case MHW_CSpace_Any: |
| return (srcCspace != MHW_CSpace_None); |
| |
| case MHW_CSpace_BT2020: |
| return (srcCspace == MHW_CSpace_BT2020 || |
| srcCspace == MHW_CSpace_BT2020_FullRange); |
| |
| case MHW_CSpace_BT2020_RGB: |
| return (srcCspace == MHW_CSpace_BT2020_RGB || |
| srcCspace == MHW_CSpace_BT2020_stRGB); |
| |
| default: |
| return (srcCspace == dstCspace); |
| } |
| |
| return false; |
| } |
| |
| bool CodecHalEncodeSfcBase::GetRgbRangeAndOffset( |
| MHW_CSPACE srcCspace, |
| float *rgbOffset, |
| float *rgbExcursion) |
| { |
| bool ret = true; |
| |
| switch (srcCspace) |
| { |
| case MHW_CSpace_sRGB: |
| case MHW_CSpace_BT2020_RGB: |
| *rgbOffset = 0.0f; |
| *rgbExcursion = 255.0f; |
| break; |
| |
| case MHW_CSpace_stRGB: |
| case MHW_CSpace_BT2020_stRGB: |
| *rgbOffset = 16.0f; |
| *rgbExcursion = 219.0f; |
| break; |
| |
| default: |
| ret = false; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| bool CodecHalEncodeSfcBase::GetYuvRangeAndOffset( |
| MHW_CSPACE srcCspace, |
| float *lumaOffset, |
| float *lumaExcursion, |
| float *chromaZero, |
| float *chromaExcursion) |
| { |
| bool ret = true; |
| |
| switch (srcCspace) |
| { |
| case MHW_CSpace_BT601_FullRange: |
| case MHW_CSpace_BT709_FullRange: |
| case MHW_CSpace_BT601Gray_FullRange: |
| case MHW_CSpace_BT2020_FullRange: |
| *lumaOffset = 0.0f; |
| *lumaExcursion = 255.0f; |
| *chromaZero = 128.0f; |
| *chromaExcursion = 255.0f; |
| break; |
| |
| case MHW_CSpace_BT601: |
| case MHW_CSpace_BT709: |
| case MHW_CSpace_xvYCC601: // since matrix is the same as 601, use the same range |
| case MHW_CSpace_xvYCC709: // since matrix is the same as 709, use the same range |
| case MHW_CSpace_BT601Gray: |
| case MHW_CSpace_BT2020: |
| *lumaOffset = 16.0f; |
| *lumaExcursion = 219.0f; |
| *chromaZero = 128.0f; |
| *chromaExcursion = 224.0f; |
| break; |
| |
| default: |
| ret = false; |
| break; |
| } |
| |
| return ret; |
| } |
| |
| bool CodecHalEncodeSfcBase::CalcYuvToRgbMatrix( |
| MHW_CSPACE srcCspace, // [in] YUV Color space |
| MHW_CSPACE dstCspace, // [in] RGB Color space |
| float *transferMatrix, // [in] Transfer matrix (3x3) |
| float *outMatrix) // [out] Conversion matrix (3x4) |
| { |
| bool ret = true; |
| float lumaOffset, lumaExcursion, chromaZero, chromaExcursion; |
| float rgbOffset, rgbExcursion; |
| |
| ret = GetRgbRangeAndOffset(dstCspace, &rgbOffset, &rgbExcursion); |
| if (ret) |
| { |
| ret = GetYuvRangeAndOffset(srcCspace, &lumaOffset, &lumaExcursion, &chromaZero, &chromaExcursion); |
| } |
| if (ret) |
| { |
| |
| // after + (3x3)(3x3) |
| outMatrix[0] = transferMatrix[0] * rgbExcursion / lumaExcursion; |
| outMatrix[4] = transferMatrix[3] * rgbExcursion / lumaExcursion; |
| outMatrix[8] = transferMatrix[6] * rgbExcursion / lumaExcursion; |
| outMatrix[1] = transferMatrix[1] * rgbExcursion / chromaExcursion; |
| outMatrix[5] = transferMatrix[4] * rgbExcursion / chromaExcursion; |
| outMatrix[9] = transferMatrix[7] * rgbExcursion / chromaExcursion; |
| outMatrix[2] = transferMatrix[2] * rgbExcursion / chromaExcursion; |
| outMatrix[6] = transferMatrix[5] * rgbExcursion / chromaExcursion; |
| outMatrix[10] = transferMatrix[8] * rgbExcursion / chromaExcursion; |
| |
| // (3x1) - (3x3)(3x3)(3x1) |
| outMatrix[3] = rgbOffset - (outMatrix[0] * lumaOffset + outMatrix[1] * chromaZero + outMatrix[2] * chromaZero); |
| outMatrix[7] = rgbOffset - (outMatrix[4] * lumaOffset + outMatrix[5] * chromaZero + outMatrix[6] * chromaZero); |
| outMatrix[11] = rgbOffset - (outMatrix[8] * lumaOffset + outMatrix[9] * chromaZero + outMatrix[10] * chromaZero); |
| } |
| return ret; |
| } |
| |
| bool CodecHalEncodeSfcBase::CalcRgbToYuvMatrix( |
| MHW_CSPACE srcCspace, // [in] RGB Color space |
| MHW_CSPACE dstCspace, // [in] YUV Color space |
| float *transferMatrix, // [in] Transfer matrix (3x3) |
| float *outMatrix) // [out] Conversion matrix (3x4) |
| { |
| bool ret = true; |
| float lumaOffset, lumaExcursion, chromaZero, chromaExcursion; |
| float rgbOffset, rgbExcursion; |
| |
| ret = GetRgbRangeAndOffset(srcCspace, &rgbOffset, &rgbExcursion); |
| if (ret) |
| { |
| ret = GetYuvRangeAndOffset(dstCspace, &lumaOffset, &lumaExcursion, &chromaZero, &chromaExcursion); |
| } |
| if (ret) |
| { |
| // multiplication of + onwards |
| outMatrix[0] = transferMatrix[0] * lumaExcursion / rgbExcursion; |
| outMatrix[1] = transferMatrix[1] * lumaExcursion / rgbExcursion; |
| outMatrix[2] = transferMatrix[2] * lumaExcursion / rgbExcursion; |
| outMatrix[4] = transferMatrix[3] * chromaExcursion / rgbExcursion; |
| outMatrix[5] = transferMatrix[4] * chromaExcursion / rgbExcursion; |
| outMatrix[6] = transferMatrix[5] * chromaExcursion / rgbExcursion; |
| outMatrix[8] = transferMatrix[6] * chromaExcursion / rgbExcursion; |
| outMatrix[9] = transferMatrix[7] * chromaExcursion / rgbExcursion; |
| outMatrix[10] = transferMatrix[8] * chromaExcursion / rgbExcursion; |
| |
| // before + |
| outMatrix[3] = lumaOffset - lumaExcursion * rgbOffset / rgbExcursion; |
| outMatrix[7] = chromaZero; |
| outMatrix[11] = chromaZero; |
| } |
| return ret; |
| } |
| |
| void CodecHalEncodeSfcBase::GetCSCMatrix( |
| MHW_CSPACE srcCspace, // [in] Source Color space |
| MHW_CSPACE dstCspace, // [in] Destination Color space |
| float *cscMatrix) // [out] CSC matrix to use |
| { |
| int32_t i; |
| |
| // BT601/709 YUV to sRGB/stRGB conversion |
| if (IsCspace(srcCspace, MHW_CSpace_YUV)) |
| { |
| if(IsCspace(dstCspace, MHW_CSpace_RGB)) |
| { |
| if (CODECHAL_IS_BT601_CSPACE(srcCspace)) |
| { |
| CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *) CODECHAL_CSC_BT601_YUV_RGB, cscMatrix); |
| } |
| else // if (IS_BT709_CSPACE(srcCspace)) |
| { |
| CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *) CODECHAL_CSC_BT709_YUV_RGB, cscMatrix); |
| } |
| } |
| } |
| // sRGB/stRGB to BT601/709 YUV conversion |
| else if (IsCspace(srcCspace, MHW_CSpace_RGB)) |
| { |
| if (IsCspace(dstCspace, MHW_CSpace_YUV)) |
| { |
| if (CODECHAL_IS_BT601_CSPACE(dstCspace)) |
| { |
| CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT601_RGB_YUV, cscMatrix); |
| } |
| else // if (IS_BT709_CSPACE(srcCspace)) |
| { |
| CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT709_RGB_YUV, cscMatrix); |
| } |
| } |
| } |
| // BT2020 YUV to RGB conversion |
| else if (IsCspace(srcCspace, MHW_CSpace_BT2020)) |
| { |
| if (IsCspace(dstCspace, MHW_CSpace_BT2020_RGB)) |
| { |
| CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT2020_YUV_RGB, cscMatrix); |
| } |
| } |
| // BT2020 RGB to YUV conversion |
| else if (IsCspace(srcCspace, MHW_CSpace_BT2020_RGB)) |
| { |
| if (IsCspace(dstCspace, MHW_CSpace_BT2020)) |
| { |
| CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT2020_RGB_YUV, cscMatrix); |
| } |
| } |
| else |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Not supported color space conversion(from %d to %d)", srcCspace, dstCspace); |
| } |
| |
| CODECHAL_ENCODE_NORMALMESSAGE(""); |
| for(i = 0; i < 3; i++) |
| { |
| CODECHAL_ENCODE_NORMALMESSAGE("%f\t%f\t%f\t%f", |
| cscMatrix[4 * i], |
| cscMatrix[4 * i + 1], |
| cscMatrix[4 * i + 2], |
| cscMatrix[4 * i + 3]); |
| } |
| } |
| |
| void CodecHalEncodeSfcBase::GetCscMatrix( |
| MHW_CSPACE srcCspace, // [in] Source Cspace |
| MHW_CSPACE dstCspace, // [in] Destination Cspace |
| float *cscCoeff, // [out] [3x3] Coefficients matrix |
| float *cscInOffset, // [out] [3x1] Input Offset matrix |
| float *cscOutOffset) // [out] [3x1] Output Offset matrix |
| { |
| float cscMatrix[12]; |
| int32_t i; |
| |
| GetCSCMatrix( |
| srcCspace, |
| dstCspace, |
| cscMatrix); |
| |
| // Copy [3x3] into Coeff |
| for (i = 0; i < 3; i++) |
| { |
| MOS_SecureMemcpy( |
| &cscCoeff[i*3], |
| sizeof(float) * 3, |
| &cscMatrix[i*4], |
| sizeof(float) * 3); |
| } |
| |
| // Get the input offsets |
| switch(srcCspace) |
| { |
| case MHW_CSpace_BT601: |
| case MHW_CSpace_BT601Gray: |
| case MHW_CSpace_xvYCC601: |
| case MHW_CSpace_BT709: |
| case MHW_CSpace_xvYCC709: |
| cscInOffset[0] = -16.0F; |
| cscInOffset[1] = -128.0F; |
| cscInOffset[2] = -128.0F; |
| break; |
| |
| case MHW_CSpace_BT601_FullRange: |
| case MHW_CSpace_BT601Gray_FullRange: |
| case MHW_CSpace_BT709_FullRange: |
| cscInOffset[0] = 0.0F; |
| cscInOffset[1] = -128.0F; |
| cscInOffset[2] = -128.0F; |
| break; |
| |
| case MHW_CSpace_sRGB: |
| cscInOffset[0] = 0.0F; |
| cscInOffset[1] = 0.0F; |
| cscInOffset[2] = 0.0F; |
| break; |
| |
| case MHW_CSpace_stRGB: |
| cscInOffset[0] = -16.0F; |
| cscInOffset[1] = -16.0F; |
| cscInOffset[2] = -16.0F; |
| break; |
| |
| //BT2020 YUV->RGB |
| case MHW_CSpace_BT2020: |
| cscInOffset[0] = -16.0F; |
| cscInOffset[1] = -128.0F; |
| cscInOffset[2] = -128.0F; |
| break; |
| |
| case MHW_CSpace_BT2020_FullRange: |
| cscInOffset[0] = 0.0F; |
| cscInOffset[1] = -128.0F; |
| cscInOffset[2] = -128.0F; |
| break; |
| |
| //BT2020 RGB->YUV |
| case MHW_CSpace_BT2020_RGB: |
| cscInOffset[0] = 0.0F; |
| cscInOffset[1] = 0.0F; |
| cscInOffset[2] = 0.0F; |
| break; |
| |
| //BT2020 RGB->YUV |
| case MHW_CSpace_BT2020_stRGB: |
| cscInOffset[0] = -16.0F; |
| cscInOffset[1] = -16.0F; |
| cscInOffset[2] = -16.0F; |
| break; |
| |
| default: |
| CODECHAL_PUBLIC_ASSERTMESSAGE("Unsupported Input ColorSpace for Vebox."); |
| } |
| |
| // Get the output offsets |
| switch(dstCspace) |
| { |
| case MHW_CSpace_BT601: |
| case MHW_CSpace_BT601Gray: |
| case MHW_CSpace_xvYCC601: |
| case MHW_CSpace_BT709: |
| case MHW_CSpace_xvYCC709: |
| cscOutOffset[0] = 16.0F; |
| cscOutOffset[1] = 128.0F; |
| cscOutOffset[2] = 128.0F; |
| break; |
| |
| case MHW_CSpace_BT601_FullRange: |
| case MHW_CSpace_BT601Gray_FullRange: |
| case MHW_CSpace_BT709_FullRange: |
| cscOutOffset[0] = 0.0F; |
| cscOutOffset[1] = 128.0F; |
| cscOutOffset[2] = 128.0F; |
| break; |
| |
| case MHW_CSpace_sRGB: |
| cscOutOffset[0] = 0.0F; |
| cscOutOffset[1] = 0.0F; |
| cscOutOffset[2] = 0.0F; |
| break; |
| |
| case MHW_CSpace_stRGB: |
| cscOutOffset[0] = 16.0F; |
| cscOutOffset[1] = 16.0F; |
| cscOutOffset[2] = 16.0F; |
| break; |
| |
| //BT2020 RGB->YUV |
| case MHW_CSpace_BT2020: |
| cscOutOffset[0] = 16.0F; |
| cscOutOffset[1] = 128.0F; |
| cscOutOffset[2] = 128.0F; |
| break; |
| |
| case MHW_CSpace_BT2020_FullRange: |
| cscOutOffset[0] = 0.0F; |
| cscOutOffset[1] = 128.0F; |
| cscOutOffset[2] = 128.0F; |
| break; |
| |
| case MHW_CSpace_BT2020_RGB: |
| cscOutOffset[0] = 0.0F; |
| cscOutOffset[1] = 0.0F; |
| cscOutOffset[2] = 0.0F; |
| break; |
| |
| case MHW_CSpace_BT2020_stRGB: |
| cscOutOffset[0] = 16.0F; |
| cscOutOffset[1] = 16.0F; |
| cscOutOffset[2] = 16.0F; |
| break; |
| |
| default: |
| CODECHAL_PUBLIC_ASSERTMESSAGE("Unsupported Output ColorSpace for Vebox."); |
| } |
| } |
| |
| inline int32_t CodecHalEncodeSfcBase::GetAvsLineBufferSize() const |
| { |
| if (!m_inputSurface || m_inputSurface->dwHeight == 0) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0"); |
| return 0; |
| } |
| return MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * CODECHAL_SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL; |
| } |
| |
| inline int32_t CodecHalEncodeSfcBase::GetStatisticsOutputBufferSize() const |
| { |
| if (!m_inputSurface || m_inputSurface->dwHeight == 0 || m_inputSurface->dwWidth == 0) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0 or dwWidth == 0"); |
| return 0; |
| } |
| return MOS_ALIGN_CEIL(m_inputSurface->dwWidth, 64) * |
| (MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 4) + MOS_ROUNDUP_DIVIDE(GetSfcVeboxStatisticsSize() * sizeof(uint32_t), m_inputSurface->dwWidth)); |
| } |
| |
| inline int32_t CodecHalEncodeSfcBase::GetVeboxRgbHistogramSize() const |
| { |
| return CODECHAL_SFC_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE * |
| CODECHAL_SFC_NUM_RGB_CHANNEL * |
| GetVeboxMaxSlicesNum(); |
| } |
| |
| inline int32_t CodecHalEncodeSfcBase::GetResLaceOrAceOrRgbHistogramBufferSize() const |
| { |
| if (!m_inputSurface || m_inputSurface->dwHeight == 0 || m_inputSurface->dwWidth == 0) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0 or dwWidth == 0"); |
| return 0; |
| } |
| |
| int32_t sizeLace = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 64) * |
| MOS_ROUNDUP_DIVIDE(m_inputSurface->dwWidth, 64) * |
| CODECHAL_SFC_VEBOX_LACE_HISTOGRAM_256_BIN_PER_BLOCK; |
| |
| int32_t sizeNoLace = CODECHAL_SFC_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE * |
| CODECHAL_SFC_NUM_FRAME_PREVIOUS_CURRENT * |
| GetVeboxMaxSlicesNum(); |
| |
| return GetVeboxRgbHistogramSize() + GetVeboxRgbAceHistogramSizeReserved() + MOS_MAX(sizeLace, sizeNoLace); |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::AllocateResources() |
| { |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| uint32_t ycoeffTableSize; |
| uint32_t uvcoeffTableSize; |
| int32_t size; |
| char* ptr; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface); |
| |
| // Allocate AVS line buffer |
| if (Mos_ResourceIsNull(&m_resAvsLineBuffer)) |
| { |
| size = GetAvsLineBufferSize(); |
| CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size"); |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| allocParamsForBufferLinear.dwBytes = size; |
| |
| allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer"; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resAvsLineBuffer)); |
| } |
| |
| //Initialize AVS parameters, try to do once |
| if (m_scaling && !m_avsParams.piYCoefsX) |
| { |
| m_avsParams.Format = Format_None; |
| m_avsParams.fScaleX = 0.0F; |
| m_avsParams.fScaleY = 0.0F; |
| m_avsParams.piYCoefsX = nullptr; |
| |
| ycoeffTableSize = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9; |
| uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9; |
| |
| size = (ycoeffTableSize + uvcoeffTableSize) * 2; |
| |
| ptr = (char*)MOS_AllocAndZeroMemory(size); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(ptr); |
| |
| m_avsParams.piYCoefsX = (int32_t*)ptr; |
| |
| ptr += ycoeffTableSize; |
| m_avsParams.piUVCoefsX = (int32_t*)ptr; |
| |
| ptr += uvcoeffTableSize; |
| m_avsParams.piYCoefsY = (int32_t*)ptr; |
| |
| ptr += ycoeffTableSize; |
| m_avsParams.piUVCoefsY = (int32_t*)ptr; |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::FreeResources() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface); |
| |
| // Free AVS Line Buffer |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer); |
| |
| // Free resLaceOrAceOrRgbHistogram |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram); |
| |
| // Free resStatisticsOutput |
| m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput); |
| |
| // Free buffers in AVS parameters |
| MOS_FreeMemory(m_avsParams.piYCoefsX); |
| m_avsParams.piYCoefsX = nullptr; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetVeboxStateParams( |
| PMHW_VEBOX_STATE_CMD_PARAMS params) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| params->bNoUseVeboxHeap = 0; |
| |
| params->VeboxMode.ColorGamutExpansionEnable = 0; |
| params->VeboxMode.ColorGamutCompressionEnable = 0; |
| // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC |
| params->VeboxMode.GlobalIECPEnable = 1; |
| params->VeboxMode.DNEnable = 0; |
| params->VeboxMode.DIEnable = 0; |
| params->VeboxMode.DNDIFirstFrame = 0; |
| params->VeboxMode.DIOutputFrames = 0; |
| params->VeboxMode.PipeSynchronizeDisable = 0; |
| params->VeboxMode.DemosaicEnable = 0; |
| params->VeboxMode.VignetteEnable = 0; |
| params->VeboxMode.AlphaPlaneEnable = 0; |
| params->VeboxMode.HotPixelFilteringEnable = 0; |
| // 0-both slices enabled 1-Slice 0 enabled 2-Slice 1 enabled |
| // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used |
| params->VeboxMode.SingleSliceVeboxEnable = 1; |
| params->VeboxMode.LACECorrectionEnable = 0; |
| params->VeboxMode.DisableEncoderStatistics = 1; |
| params->VeboxMode.DisableTemporalDenoiseFilter = 1; |
| params->VeboxMode.SinglePipeIECPEnable = 0; |
| params->VeboxMode.SFCParallelWriteEnable = 0; |
| params->VeboxMode.ScalarMode = 0; |
| params->VeboxMode.ForwardGammaCorrectionEnable = 0; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetVeboxSurfaceStateParams( |
| PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS params) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| // Initialize SurfInput |
| params->SurfInput.bActive = true; |
| params->SurfInput.Format = m_inputSurface->Format; |
| params->SurfInput.dwWidth = m_inputSurface->dwWidth; |
| params->SurfInput.dwHeight = m_inputSurface->dwHeight; |
| params->SurfInput.dwPitch = m_inputSurface->dwPitch; |
| params->SurfInput.TileType = m_inputSurface->TileType; |
| params->SurfInput.TileModeGMM = m_inputSurface->TileModeGMM; |
| params->SurfInput.bGMMTileEnabled = m_inputSurface->bGMMTileEnabled; |
| params->SurfInput.dwYoffset = m_inputSurface->YPlaneOffset.iYOffset; |
| params->SurfInput.pOsResource = &m_inputSurface->OsResource; |
| params->SurfInput.rcMaxSrc.left = m_inputSurfaceRegion.X; |
| params->SurfInput.rcMaxSrc.top = m_inputSurfaceRegion.Y; |
| params->SurfInput.rcMaxSrc.right = m_inputSurfaceRegion.X + m_inputSurfaceRegion.Width; |
| params->SurfInput.rcMaxSrc.bottom = m_inputSurfaceRegion.Y + m_inputSurfaceRegion.Height; |
| |
| // Initialize SurfSTMM |
| params->SurfSTMM.dwPitch = m_inputSurface->dwPitch; |
| |
| params->bDIEnable = false; |
| params->bOutputValid = (m_veboxOutputSurface != nullptr) ? true : false; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetVeboxDiIecpParams( |
| PMHW_VEBOX_DI_IECP_CMD_PARAMS params) |
| { |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| int32_t size; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| params->dwStartingX = 0; |
| params->dwEndingX = m_inputSurfaceRegion.Width - 1; // Must be taken from SPS |
| params->dwCurrInputSurfOffset = m_inputSurface->dwOffset; |
| params->pOsResCurrInput = &m_inputSurface->OsResource; |
| params->CurrInputSurfCtrl.Value = 0; //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition. |
| |
| CodecHalGetResourceInfo( |
| m_osInterface, |
| m_inputSurface); |
| |
| m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, &m_inputSurface->OsResource, &mmcMode); |
| if (mmcMode && |
| (m_inputSurface->TileType == MOS_TILE_Y || |
| m_inputSurface->TileType == MOS_TILE_YS)) |
| { |
| m_inputSurface->bCompressible = true; |
| m_inputSurface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode; |
| } |
| else |
| { |
| m_inputSurface->CompressionMode = MOS_MMC_DISABLED; |
| } |
| |
| params->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode); |
| |
| // Allocate Resource to avoid Page Fault issue since HW will access it |
| if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram)) |
| { |
| size = GetResLaceOrAceOrRgbHistogramBufferSize(); |
| CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size"); |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| allocParamsForBufferLinear.dwBytes = size; |
| allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram"; |
| |
| m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resLaceOrAceOrRgbHistogram); |
| } |
| |
| params->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram; |
| |
| // Allocate Resource to avoid Page Fault issue since HW will access it |
| if (Mos_ResourceIsNull(&m_resStatisticsOutput)) |
| { |
| size = GetStatisticsOutputBufferSize(); |
| CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size"); |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| allocParamsForBufferLinear.dwBytes = size; |
| allocParamsForBufferLinear.pBufName = "ResStatisticsOutput"; |
| |
| m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_resStatisticsOutput); |
| } |
| |
| params->pOsResStatisticsOutput = &m_resStatisticsOutput; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::VeboxSetIecpParams( |
| PMHW_VEBOX_IECP_PARAMS mhwVeboxIecpParams) |
| { |
| // Calculate matrix if not done so before. CSC is expensive! |
| if ((m_cscInputCspace != m_inputSurfaceColorSpace) || |
| (m_cscOutputCspace != m_outputSurfaceColorSpace)) |
| { |
| float fTemp[3]; |
| |
| // Get the matrix to use for conversion |
| GetCscMatrix( |
| m_inputSurfaceColorSpace, |
| m_outputSurfaceColorSpace, |
| m_cscCoeff, |
| m_cscInOffset, |
| m_cscOutOffset); |
| |
| // Vebox CSC converts RGB input to YUV for SFC |
| // Vebox only supports A8B8G8R8 input, swap the 1st and 3rd |
| // columns of the transfer matrix for A8R8G8B8 and X8R8G8B8 |
| // This only happens when SFC output is used |
| if ((m_inputSurface->Format == Format_A8R8G8B8) || |
| (m_inputSurface->Format == Format_X8R8G8B8)) |
| { |
| fTemp[0] = m_cscCoeff[0]; |
| fTemp[1] = m_cscCoeff[3]; |
| fTemp[2] = m_cscCoeff[6]; |
| |
| m_cscCoeff[0] = m_cscCoeff[2]; |
| m_cscCoeff[3] = m_cscCoeff[5]; |
| m_cscCoeff[6] = m_cscCoeff[8]; |
| |
| m_cscCoeff[2] = fTemp[0]; |
| m_cscCoeff[5] = fTemp[1]; |
| m_cscCoeff[8] = fTemp[2]; |
| } |
| } |
| // Store it for next BLT |
| m_cscInputCspace = m_inputSurfaceColorSpace; |
| m_cscOutputCspace = m_outputSurfaceColorSpace; |
| CODECHAL_ENCODE_VERBOSEMESSAGE("Input color space: %d, output color space: %d", |
| m_cscInputCspace, m_cscOutputCspace); |
| |
| // copy into MHW parameters |
| |
| mhwVeboxIecpParams->ColorSpace = m_inputSurfaceColorSpace; |
| mhwVeboxIecpParams->dstFormat = m_sfcOutputSurface->Format; |
| mhwVeboxIecpParams->srcFormat = m_inputSurface->Format; |
| mhwVeboxIecpParams->bCSCEnable = m_veboxCsc; |
| mhwVeboxIecpParams->pfCscCoeff = m_cscCoeff; |
| mhwVeboxIecpParams->pfCscInOffset = m_cscInOffset; |
| mhwVeboxIecpParams->pfCscOutOffset = m_cscOutOffset; |
| //mhwVeboxIecpParams->bAlphaEnable = m_alphaEnable; ?? |
| //mhwVeboxIecpParams->wAlphaValue = m_alphaValue; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| #if (_DEBUG || _RELEASE_INTERNAL) |
| MOS_STATUS CodecHalEncodeSfcBase::DumpBuffers(CodechalDebugInterface* debugInterface) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer( |
| &m_resAvsLineBuffer, |
| CodechalDbgAttr::attrSfcBuffers, |
| "AvsLine", |
| GetAvsLineBufferSize())); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer( |
| &m_resLaceOrAceOrRgbHistogram, |
| CodechalDbgAttr::attrSfcBuffers, |
| "LaceOrAceOrRgbHistogram", |
| GetResLaceOrAceOrRgbHistogramBufferSize())); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer( |
| &m_resStatisticsOutput, |
| CodechalDbgAttr::attrSfcBuffers, |
| "StatisticsOutput", |
| GetStatisticsOutputBufferSize())); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| #endif |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetSfcStateParams( |
| PMHW_SFC_INTERFACE sfcInterface, |
| PMHW_SFC_STATE_PARAMS params, |
| PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams) |
| { |
| uint16_t widthAlignUnit; |
| uint16_t heightAlignUnit; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_sfcOutputSurface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| params->sfcPipeMode = MEDIASTATE_SFC_PIPE_VE_TO_SFC; |
| params->dwAVSFilterMode = MEDIASTATE_SFC_AVS_FILTER_8x8; |
| params->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8; |
| |
| params->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444; |
| |
| // Adjust SFC input surface alignment. |
| // As VEBOX doesn't do scaling, input size equals to output size |
| // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4 |
| widthAlignUnit = sfcInterface->m_veWidthAlignment; |
| heightAlignUnit = sfcInterface->m_veHeightAlignment; |
| |
| // Width and height must be set using SPS params instead of real surface size |
| if (m_inputSurface->dwWidth < m_inputSurfaceRegion.Width || |
| m_inputSurface->dwHeight < m_inputSurfaceRegion.Height) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("width and height must be less than surface size"); |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| params->dwInputFrameWidth = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Width, widthAlignUnit); |
| params->dwInputFrameHeight = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Height, heightAlignUnit); |
| |
| params->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO420; |
| params->bAVSChromaUpsamplingEnable = m_scaling; |
| |
| if ((params->fAVSXScalingRatio > 1.0F) || (params->fAVSYScalingRatio > 1.0F)) |
| { |
| params->bBypassXAdaptiveFilter = false; |
| params->bBypassYAdaptiveFilter = false; |
| } |
| else |
| { |
| params->bBypassXAdaptiveFilter = true; |
| params->bBypassYAdaptiveFilter = true; |
| } |
| |
| params->fChromaSubSamplingXSiteOffset = 0.0F; |
| params->fChromaSubSamplingYSiteOffset = 0.0F; |
| |
| widthAlignUnit = 1; |
| heightAlignUnit = 1; |
| |
| switch(m_sfcOutputSurface->Format) |
| { |
| case Format_NV12: |
| case Format_P010: |
| widthAlignUnit = 2; |
| heightAlignUnit = 2; |
| break; |
| case Format_YUY2: |
| case Format_UYVY: |
| widthAlignUnit = 2; |
| break; |
| default: |
| break; |
| } |
| |
| // Default to Horizontal Left, Vertical Top |
| params->dwChromaDownSamplingHorizontalCoef = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : |
| ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8); |
| |
| params->dwChromaDownSamplingVerticalCoef = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 : |
| ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 : |
| MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8); |
| |
| outSurfaceParams->dwWidth = m_sfcOutputSurface->dwWidth; |
| outSurfaceParams->dwHeight = m_sfcOutputSurface->dwHeight; |
| outSurfaceParams->dwPitch = m_sfcOutputSurface->dwPitch; |
| outSurfaceParams->TileType = m_sfcOutputSurface->TileType; |
| outSurfaceParams->TileModeGMM = m_sfcOutputSurface->TileModeGMM; |
| outSurfaceParams->bGMMTileEnabled = m_sfcOutputSurface->bGMMTileEnabled; |
| outSurfaceParams->ChromaSiting = m_chromaSiting; |
| outSurfaceParams->dwUYoffset = m_sfcOutputSurface->UPlaneOffset.iYOffset; |
| |
| params->dwOutputFrameWidth = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit); |
| params->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit); |
| params->OutputFrameFormat = m_sfcOutputSurface->Format; |
| params->dwOutputSurfaceOffset = m_sfcOutputSurface->dwOffset; |
| params->pOsResOutputSurface = &m_sfcOutputSurface->OsResource; |
| params->pOsResAVSLineBuffer = &m_resAvsLineBuffer; |
| |
| params->dwSourceRegionHeight = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Height, heightAlignUnit); |
| params->dwSourceRegionWidth = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Width, widthAlignUnit); |
| params->dwSourceRegionVerticalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Y, heightAlignUnit); |
| params->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.X, widthAlignUnit); |
| params->dwScaledRegionHeight = MOS_UF_ROUND(m_scaleY * params->dwSourceRegionHeight); |
| params->dwScaledRegionWidth = MOS_UF_ROUND(m_scaleX * params->dwSourceRegionWidth); |
| params->dwScaledRegionVerticalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.Y, heightAlignUnit); |
| params->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.X, widthAlignUnit); |
| params->fAVSXScalingRatio = m_scaleX; |
| params->fAVSYScalingRatio = m_scaleY; |
| |
| params->fAlphaPixel = 1.0F; |
| params->bColorFillEnable = m_colorFill; |
| params->bCSCEnable = m_CSC; |
| |
| // ARGB8,ABGR10,A16B16G16R16,VYUY and YVYU output format need to enable swap |
| if (m_sfcOutputSurface->Format == Format_X8R8G8B8 || |
| m_sfcOutputSurface->Format == Format_A8R8G8B8 || |
| m_sfcOutputSurface->Format == Format_R10G10B10A2 || |
| m_sfcOutputSurface->Format == Format_A16B16G16R16 || |
| m_sfcOutputSurface->Format == Format_VYUY || |
| m_sfcOutputSurface->Format == Format_YVYU) |
| { |
| params->bRGBASwapEnable = true; |
| } |
| else |
| { |
| params->bRGBASwapEnable = false; |
| } |
| |
| |
| // CodecHal does not support SFC rotation |
| params->RotationMode = MHW_ROTATION_IDENTITY; |
| |
| // For downsampling, expect output surface to be MMC disabled |
| // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC |
| params->bMMCEnable = false; |
| params->MMCMode = MOS_MMC_DISABLED; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetSfcAvsStateParams( |
| PMHW_SFC_INTERFACE sfcInterface) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| PMHW_SFC_AVS_STATE mhwSfcAvsState; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface); |
| |
| mhwSfcAvsState = &m_avsState; |
| |
| if (m_chromaSiting == MHW_CHROMA_SITING_NONE) |
| { |
| m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER; |
| } |
| |
| mhwSfcAvsState->dwInputHorizontalSiting = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : |
| ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : |
| SFC_AVS_INPUT_SITING_COEF_0_OVER_8); |
| |
| mhwSfcAvsState->dwInputVerticalSitting = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 : |
| ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 : |
| SFC_AVS_INPUT_SITING_COEF_0_OVER_8); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->SetSfcSamplerTable( |
| &m_lumaTable, |
| &m_chromaTable, |
| &m_avsParams, |
| m_inputSurface->Format, |
| m_scaleX, |
| m_scaleY, |
| m_chromaSiting, |
| true, |
| 0, |
| 0)); |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetSfcIefStateParams( |
| PMHW_SFC_IEF_STATE_PARAMS params) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| params->bIEFEnable = false; |
| params->bCSCEnable = true; |
| |
| params->pfCscCoeff = m_cscCoeff; |
| params->pfCscInOffset = m_cscInOffset; |
| params->pfCscOutOffset = m_cscOutOffset; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::Initialize( |
| CodechalHwInterface *hwInterface, |
| PMOS_INTERFACE osInterface) |
| { |
| |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface()); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(osInterface); |
| |
| m_hwInterface = hwInterface; |
| m_osInterface = osInterface; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetVeboxInterface()->CreateHeap()); |
| |
| // Create VEBOX Context |
| MOS_GPUCTX_CREATOPTIONS createOption; |
| // |
| // VeboxgpuContext could be created from both VP and Codec. |
| // If there is no such as a GPU context it will create a new one and set the GPU component ID. |
| // If there has been a valid GPU context it will not create another one anymore and the component ID will not be updated either. |
| // Therefore if a codec veboxgpu context creation happens earlier than a vp veboxgpu context creation and set its component ID to MOS_GPU_COMPONENT_ENCODE, |
| // VPBLT callstack would index a GpuAppTaskEvent of MOS_GPU_COMPONENT_ENCODE. |
| // |
| MOS_COMPONENT originalComponent = m_osInterface->Component; |
| m_osInterface->Component = COMPONENT_VPCommon; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( |
| m_osInterface, |
| MOS_GPU_CONTEXT_VEBOX, |
| MOS_GPU_NODE_VE, |
| &createOption)); |
| |
| m_osInterface->Component = originalComponent; |
| |
| // Register Vebox GPU context with the Batch Buffer completion event |
| // Ignore if creation fails |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent( |
| m_osInterface, |
| MOS_GPU_CONTEXT_VEBOX)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::SetParams( |
| CODECHAL_ENCODE_SFC_PARAMS* params) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pInputSurface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pOutputSurface); |
| |
| m_inputSurface = params->pInputSurface; |
| // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr |
| m_veboxOutputSurface = nullptr; |
| m_sfcOutputSurface = params->pOutputSurface; |
| |
| // no scaling. |
| m_scaling = false; |
| m_colorFill = false; |
| |
| // No CSC for SFC pipe |
| m_veboxCsc = true; |
| |
| m_scaleX = 1.0; |
| m_scaleY = 1.0; |
| m_chromaSiting = params->uiChromaSitingType; |
| |
| eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion, |
| sizeof(m_inputSurfaceRegion), |
| ¶ms->rcInputSurfaceRegion, |
| sizeof(params->rcInputSurfaceRegion)); |
| |
| eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion, |
| sizeof(m_outputSurfaceRegion), |
| ¶ms->rcOutputSurfaceRegion, |
| sizeof(params->rcOutputSurfaceRegion)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources()); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::AddSfcCommands( |
| PMHW_SFC_INTERFACE sfcInterface, |
| PMOS_COMMAND_BUFFER cmdBuffer) |
| { |
| MHW_SFC_LOCK_PARAMS sfcLockParams; |
| MHW_SFC_STATE_PARAMS sfcStateParams; |
| MHW_SFC_OUT_SURFACE_PARAMS sfcOutSurfaceParams; |
| MHW_SFC_IEF_STATE_PARAMS sfcIefStateParams; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); |
| |
| MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams)); |
| |
| sfcLockParams.sfcPipeMode = MhwSfcInterface::SFC_PIPE_MODE_VEBOX; |
| sfcLockParams.bOutputToMemory = false; |
| |
| MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams)); |
| MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcStateParams(sfcInterface, &sfcStateParams, &sfcOutSurfaceParams)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams)); |
| |
| if (m_scaling) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcAvsStateParams(sfcInterface)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable)); |
| } |
| |
| if (m_CSC) |
| { |
| MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams)); |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcFrameStart(cmdBuffer, MhwSfcInterface::SFC_PIPE_MODE_VEBOX)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalEncodeSfcBase::RenderStart( |
| CodechalEncoderState* encoder) |
| { |
| MHW_VEBOX_STATE_CMD_PARAMS veboxStateCmdParams; |
| MHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfaceStateCmdParams; |
| MHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpCmdParams; |
| MHW_VEBOX_IECP_PARAMS veboxIecpParams; |
| MHW_VEBOX_SURFACE_CNTL_PARAMS veboxSurfCntlParams; |
| MhwVeboxInterface *veboxInterface; |
| PMHW_SFC_INTERFACE sfcInterface; |
| MhwMiInterface *miInterface; |
| PMOS_CONTEXT pOsContext = nullptr; |
| MHW_MI_MMIOREGISTERS *mmioVeboxRegisters = nullptr; |
| MOS_COMMAND_BUFFER cmdBuffer; |
| bool requestFrameTracking; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(pOsContext = m_osInterface->pOsContext); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(encoder); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface = m_hwInterface->GetSfcInterface()); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(veboxInterface = m_hwInterface->GetVeboxInterface()); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(miInterface = m_hwInterface->GetMiInterface()); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(mmioVeboxRegisters = miInterface->GetMmioRegisters()); |
| |
| // Switch GPU context to VEBOX |
| m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX); |
| // Reset allocation list and house keeping |
| m_osInterface->pfnResetOsStates(m_osInterface); |
| |
| // Send command buffer header at the beginning |
| MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); |
| |
| // the first task? |
| requestFrameTracking = false; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking, mmioVeboxRegisters)); |
| |
| // If m_pollingSyncEnabled is set, insert HW semaphore to wait for external |
| // raw surface processing to complete, before start CSC. Once the marker in |
| // raw surface is overwritten by external operation, HW semaphore will be |
| // signalled and CSC will start. This is to reduce SW latency between |
| // external raw surface processing and CSC, in usages like remote gaming. |
| if (encoder->m_pollingSyncEnabled) |
| { |
| MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams; |
| MOS_ZeroMemory((&miSemaphoreWaitParams), sizeof(miSemaphoreWaitParams)); |
| miSemaphoreWaitParams.presSemaphoreMem = &m_inputSurface->OsResource; |
| miSemaphoreWaitParams.dwResourceOffset = encoder->m_syncMarkerOffset; |
| miSemaphoreWaitParams.bPollingWaitMode = true; |
| miSemaphoreWaitParams.dwSemaphoreData = encoder->m_syncMarkerValue; |
| miSemaphoreWaitParams.CompareOperation = MHW_MI_SAD_NOT_EQUAL_SDD; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiSemaphoreWaitCmd(&cmdBuffer, &miSemaphoreWaitParams)); |
| } |
| |
| // Setup cmd prameters |
| MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams)); |
| |
| MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams)); |
| |
| MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams)); |
| |
| MOS_ZeroMemory(&veboxSurfCntlParams, sizeof(veboxSurfCntlParams)); |
| veboxSurfCntlParams.bIsCompressed = m_inputSurface->bIsCompressed; |
| veboxSurfCntlParams.CompressionMode = m_inputSurface->CompressionMode; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaceControlBits( |
| &veboxSurfCntlParams, |
| (uint32_t *)&(veboxDiIecpCmdParams.CurrInputSurfCtrl.Value))); |
| |
| // get csc matrix |
| MOS_ZeroMemory(&veboxIecpParams, sizeof(veboxIecpParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(VeboxSetIecpParams(&veboxIecpParams)); |
| |
| // send matrix into heap |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxIecpState( |
| &veboxIecpParams)); |
| |
| // send Vebox and SFC cmds |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaces( &cmdBuffer, &veboxSurfaceStateCmdParams)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AddSfcCommands(sfcInterface, &cmdBuffer)); |
| |
| HalOcaInterface::TraceMessage(cmdBuffer, *pOsContext, __FUNCTION__, sizeof(__FUNCTION__)); |
| HalOcaInterface::OnDispatch(cmdBuffer, *pOsContext, *miInterface, *mmioVeboxRegisters); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams)); |
| |
| // If m_pollingSyncEnabled is set, write the marker to source surface for next MI_SEMAPHORE_WAIT to check. |
| if (encoder->m_pollingSyncEnabled) |
| { |
| MHW_MI_STORE_DATA_PARAMS storeDataParams; |
| storeDataParams.pOsResource = &m_inputSurface->OsResource; |
| storeDataParams.dwResourceOffset = encoder->m_syncMarkerOffset; |
| storeDataParams.dwValue = encoder->m_syncMarkerValue; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams)); |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd( |
| &cmdBuffer, |
| nullptr)); |
| |
| CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->GetDebugInterface()->DumpCmdBuffer( |
| &cmdBuffer, |
| CODECHAL_MEDIA_STATE_CSC_DS_COPY, |
| nullptr))); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( |
| m_osInterface, |
| &cmdBuffer, |
| encoder->m_videoContextUsesNullHw)); |
| return eStatus; |
| } |