| /* |
| * Copyright (c) 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 media_ddi_encode_fei_hevc.cpp |
| //! \brief Implements class for DDI media hevc fei encode |
| //! |
| |
| #include "media_libva.h" |
| #include "media_libva_encoder.h" |
| #include "media_libva_util.h" |
| #include "hwinfo_linux.h" |
| #include "codechal_encode_hevc_base.h" |
| #include "media_ddi_encode_base.h" |
| #include "media_ddi_encode_fei_hevc.h" |
| #include "media_ddi_encode_const.h" |
| #include "media_ddi_factory.h" |
| |
| extern template class MediaDdiFactoryNoArg<DdiEncodeBase>; |
| |
| static bool isEncodeHevcFeiRegistered = |
| MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeHevcFei>(ENCODE_ID_HEVCFEI); |
| |
| DdiEncodeHevcFei::~DdiEncodeHevcFei() |
| { |
| if (nullptr == m_encodeCtx) |
| { |
| return; |
| } |
| MOS_FreeMemory(m_encodeCtx->pFeiPicParams); |
| m_encodeCtx->pFeiPicParams = nullptr; |
| |
| } |
| |
| VAStatus DdiEncodeHevcFei::ContextInitialize(CodechalSetting * codecHalSettings) |
| { |
| VAStatus status = DdiEncodeHevc::ContextInitialize(codecHalSettings); |
| if (VA_STATUS_SUCCESS != status) |
| { |
| return status; |
| } |
| |
| codecHalSettings->codecFunction = m_encodeCtx->codecFunction; |
| |
| m_encodeCtx->pFeiPicParams = (void *)MOS_AllocAndZeroMemory(CODECHAL_HEVC_MAX_PPS_NUM * sizeof(CodecEncodeHevcFeiPicParams)); |
| DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_ALLOCATION_FAILED); |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiEncodeHevcFei::EncodeInCodecHal(uint32_t numSlices) |
| { |
| DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl); |
| |
| EncoderParams encodeParams; |
| MOS_ZeroMemory(&encodeParams, sizeof(encodeParams)); |
| |
| CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams); |
| |
| if(CodecHalIsFeiEncode(m_encodeCtx->codecFunction)) |
| { |
| encodeParams.ExecCodecFunction = m_encodeCtx->codecFunction; |
| } |
| else |
| { |
| DDI_ASSERTMESSAGE("DDI:Failed in HEVC FEI Function check!"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| // Raw Surface |
| MOS_SURFACE rawSurface; |
| MOS_ZeroMemory(&rawSurface, sizeof(rawSurface)); |
| rawSurface.dwOffset = 0; |
| if (m_encodeCtx->vaProfile == VAProfileHEVCMain10) |
| { |
| rawSurface.Format = Format_P010; |
| } |
| else //VAProfileHEVCMain |
| { |
| rawSurface.Format = Format_NV12; |
| } |
| |
| DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface.OsResource)); |
| |
| // Recon Surface |
| MOS_SURFACE reconSurface; |
| MOS_ZeroMemory(&reconSurface, sizeof(reconSurface)); |
| reconSurface.dwOffset = 0; |
| if (m_encodeCtx->vaProfile == VAProfileHEVCMain10) |
| { |
| reconSurface.Format = Format_P010; |
| } |
| else //VAProfileHEVCMain |
| { |
| reconSurface.Format = Format_NV12; |
| } |
| |
| DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface.OsResource)); |
| |
| //clear registered recon/ref surface flags |
| DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, true), "ClearRefList failed!"); |
| |
| // Bitstream surface |
| MOS_RESOURCE bitstreamSurface; |
| MOS_ZeroMemory(&bitstreamSurface, sizeof(bitstreamSurface)); |
| bitstreamSurface = m_encodeCtx->resBitstreamBuffer; // in render picture |
| bitstreamSurface.Format = Format_Buffer; |
| |
| encodeParams.psRawSurface = &rawSurface; |
| encodeParams.psReconSurface = &reconSurface; |
| encodeParams.presBitstreamBuffer = &bitstreamSurface; |
| |
| MOS_SURFACE mbQpSurface; |
| if(feiPicParams->bPerBlockQP) |
| { |
| // MBQp surface |
| MOS_ZeroMemory(&mbQpSurface, sizeof(mbQpSurface)); |
| mbQpSurface.Format = Format_Buffer_2D; |
| mbQpSurface.dwOffset = 0; |
| mbQpSurface.OsResource = feiPicParams->resCTBQp; |
| |
| encodeParams.psMbQpDataSurface = &mbQpSurface; |
| encodeParams.bMbQpDataEnabled = true; |
| } |
| |
| encodeParams.pSeqParams = m_encodeCtx->pSeqParams; |
| encodeParams.pVuiParams = m_encodeCtx->pVuiParams; |
| encodeParams.pPicParams = m_encodeCtx->pPicParams; |
| encodeParams.pSliceParams = m_encodeCtx->pSliceParams; |
| encodeParams.pFeiPicParams = feiPicParams; |
| |
| // Sequence data |
| encodeParams.bNewSeq = m_encodeCtx->bNewSeq; |
| |
| // VUI |
| encodeParams.bNewVuiData = m_encodeCtx->bNewVuiData; |
| |
| // Slice level data |
| encodeParams.dwNumSlices = numSlices; |
| |
| // IQmatrix params |
| encodeParams.bNewQmatrixData = m_encodeCtx->bNewQmatrixData; |
| encodeParams.bPicQuant = m_encodeCtx->bPicQuant; |
| encodeParams.ppNALUnitParams = m_encodeCtx->ppNALUnitParams; |
| encodeParams.pSeiData = m_encodeCtx->pSEIFromApp; |
| encodeParams.pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer; |
| encodeParams.dwSEIDataOffset = 0; |
| |
| CODECHAL_HEVC_IQ_MATRIX_PARAMS hevcIqMatrixParams; |
| encodeParams.pIQMatrixBuffer = &hevcIqMatrixParams; |
| |
| // whether driver need to pack slice header |
| if (m_encodeCtx->bHavePackedSliceHdr) |
| { |
| encodeParams.bAcceleratorHeaderPackingCaps = false; |
| } |
| else |
| { |
| encodeParams.bAcceleratorHeaderPackingCaps = true; |
| } |
| |
| encodeParams.pBSBuffer = m_encodeCtx->pbsBuffer; |
| encodeParams.pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData; |
| |
| MOS_STATUS status = m_encodeCtx->pCodecHal->Execute(&encodeParams); |
| if (MOS_STATUS_SUCCESS != status) |
| { |
| DDI_ASSERTMESSAGE("DDI:Failed in Codechal!"); |
| return VA_STATUS_ERROR_ENCODING_ERROR; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| |
| } |
| |
| VAStatus DdiEncodeHevcFei::ResetAtFrameLevel() |
| { |
| DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| // Assume there is only one SPS parameter |
| PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams); |
| hevcSeqParams->bResetBRC = 0x0; |
| |
| m_encodeCtx->dwNumSlices = 0x0; |
| m_encodeCtx->indexNALUnit = 0x0; |
| m_encodeCtx->uiSliceHeaderCnt = 0x0; |
| |
| // reset bsbuffer every frame |
| m_encodeCtx->pbsBuffer->pCurrent = m_encodeCtx->pbsBuffer->pBase; |
| m_encodeCtx->pbsBuffer->SliceOffset = 0x0; |
| m_encodeCtx->pbsBuffer->BitOffset = 0x0; |
| m_encodeCtx->pbsBuffer->BitSize = 0x0; |
| |
| CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams); |
| |
| m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK; |
| feiPicParams->NumMVPredictorsL0 = 0; // number of MV Predictors L0 provided, max is 4 |
| feiPicParams->NumMVPredictorsL1 = 0; // number of MV Predictors L1 provided, max is 2 |
| feiPicParams->SearchPath = 0; // search path, default is 0, 0 and 2 mean full search, 1 means diamond search |
| feiPicParams->LenSP = 57; // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63] |
| feiPicParams->MultiPredL0 = 0; // 000: no neighbor MVs will be used as predictor for L0, 001: spatial MVs, 010 temporal MVs, others: reserved. |
| feiPicParams->MultiPredL1 = 0; // 000: no neighbor MVs will be used as predictor for L1, 001: spatial MVs, 010 temporal MVs, others: reserved. |
| feiPicParams->SubPelMode = 3; // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search |
| feiPicParams->AdaptiveSearch = true; // whether adaptive searching is enabled for IME |
| feiPicParams->MVPredictorInput = 0; // 000: disable MV Predictor input, 001: enabled per 16x16 block, |
| // 010: enabled per 32x32 block, |
| // 011: enabled per 64x64 block, |
| // 111: block size can vary and is determined by BlockSize in MVP |
| // others: reserved |
| feiPicParams->bPerBlockQP = false; // if enable per block QP input |
| feiPicParams->bPerCTBInput = false; // if enable per MB control/special input |
| feiPicParams->bForceLCUSplit = false; // specifies whether CTB should be forced to split to remove Inter big LCU |
| feiPicParams->bEnableCU64Check = true; // specifies whether 64x64 CB should be forced to split |
| feiPicParams->bEnableCU64AmpCheck = false; // specifies if 64x64 CB AMP should be checked, 0: No CU 64x64 AMP check, 1: check LCU64x64 AMP |
| feiPicParams->bCU64SkipCheckOnly = false; // specifies if check the 64x64 merge candidate, 0: after skip check, also run merge for TU1, 1: only skip check for 64x64 for TU4 |
| feiPicParams->bColocatedCTBDistortion = false; // if enable, extra distortion between current CTB and co-located CTB is provided |
| feiPicParams->RefWidth = 48; |
| feiPicParams->RefHeight = 40; |
| feiPicParams->SearchWindow = 0; |
| feiPicParams->MaxNumIMESearchCenter = 6; // specifies number [1~6] of MV predictors for IME searches |
| feiPicParams->NumConcurrentEncFramePartition = 1; // specifies number [1, 2, 4] of splits that encoder could be run concurrently |
| feiPicParams->dwMaxFrameSize = 0; // specifies max frame size in bytes for multi-pass pak, 0 means disabling multi-pass pak |
| |
| feiPicParams->bDistortionEnable = false; |
| feiPicParams->bCTBCmdCuRecordEnable = false; |
| |
| // clear the packed header information |
| if (nullptr != m_encodeCtx->ppNALUnitParams) |
| { |
| MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * HEVC_MAX_NAL_UNIT_TYPE); |
| } |
| |
| m_encodeCtx->bHavePackedSliceHdr = false; |
| m_encodeCtx->bLastPackedHdrIsSlice = false; |
| m_encodeCtx->bMBQpEnable = false; |
| |
| return VA_STATUS_SUCCESS; |
| |
| } |
| |
| VAStatus DdiEncodeHevcFei::RenderPicture(VADriverContextP ctx, VAContextID context, VABufferID *buffers, int32_t numBuffers) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| |
| DDI_FUNCTION_ENTER(); |
| |
| DDI_CHK_NULL(ctx, "nullptr context", VA_STATUS_ERROR_INVALID_CONTEXT); |
| |
| DDI_MEDIA_CONTEXT *mediaCtx = DdiMedia_GetMediaContext(ctx); |
| DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT); |
| |
| DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT); |
| |
| for (int32_t i = 0; i < numBuffers; i++) |
| { |
| DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]); |
| DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER); |
| if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType) |
| { |
| DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer)); |
| m_encodeCtx->bMbDisableSkipMapEnabled = true; |
| continue; |
| } |
| uint32_t dataSize = buf->iSize; |
| // can use internal function instead of DdiMedia_MapBuffer here? |
| void *data = nullptr; |
| DdiMedia_MapBuffer(ctx, buffers[i], &data); |
| |
| DDI_CHK_NULL(data, "Null data.", VA_STATUS_ERROR_INVALID_BUFFER); |
| |
| switch (buf->uiType) |
| { |
| case VAEncSequenceParameterBufferType: |
| DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER); |
| m_encodeCtx->bNewSeq = true; |
| break; |
| |
| case VAEncPictureParameterBufferType: |
| DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER); |
| DDI_CHK_STATUS( |
| AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo), |
| VA_STATUS_ERROR_INVALID_BUFFER); |
| break; |
| |
| case VAEncSliceParameterBufferType: |
| { |
| uint32_t numSlices = buf->uiNumElements; |
| DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER); |
| break; |
| } |
| |
| case VAEncPackedHeaderParameterBufferType: |
| vaStatus = ParsePackedHeaderParams(data); |
| break; |
| |
| case VAEncPackedHeaderDataBufferType: |
| vaStatus = ParsePackedHeaderData(data); |
| break; |
| |
| case VAEncMiscParameterBufferType: |
| DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER); |
| break; |
| |
| case VAEncQPBufferType: |
| DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer); |
| m_encodeCtx->bMBQpEnable = true; |
| break; |
| |
| case VAEncFEIMBControlBufferType: |
| case VAEncFEIMVPredictorBufferType: |
| case VAEncFEIMBCodeBufferType: |
| case VAEncFEICTBCmdBufferType: |
| case VAEncFEICURecordBufferType: |
| case VAEncFEIDistortionBufferType: |
| { |
| // handled in VAEncMiscParameterBufferType/VAEncMiscParameterTypeFEIFrameControlIntel case by vaBufferID |
| break; |
| } |
| |
| default: |
| DDI_ASSERTMESSAGE("not supported buffer type."); |
| break; |
| } |
| DdiMedia_UnmapBuffer(ctx, buffers[i]); |
| } |
| |
| DDI_FUNCTION_EXIT(vaStatus); |
| return vaStatus; |
| |
| } |
| |
| VAStatus DdiEncodeHevcFei::ParseMiscParamFeiPic(void *data) |
| { |
| DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER); |
| CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams); |
| DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER); |
| VAEncMiscParameterFEIFrameControlHEVC *vaEncMiscParamFeiPic = (VAEncMiscParameterFEIFrameControlHEVC *)data; |
| |
| m_encodeCtx->codecFunction = CODECHAL_FUNCTION_INVALID; |
| if(vaEncMiscParamFeiPic->function & VA_FEI_FUNCTION_ENC_PAK) |
| m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK; |
| if(vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_ENC) |
| m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC; |
| if(vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_PAK) |
| m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_PAK; |
| |
| feiPicParams->NumMVPredictorsL0 = vaEncMiscParamFeiPic->num_mv_predictors_l0; |
| feiPicParams->NumMVPredictorsL1 = vaEncMiscParamFeiPic->num_mv_predictors_l1; |
| feiPicParams->SearchPath = vaEncMiscParamFeiPic->search_path; |
| feiPicParams->LenSP = vaEncMiscParamFeiPic->len_sp; |
| feiPicParams->MultiPredL0 = vaEncMiscParamFeiPic->multi_pred_l0; |
| feiPicParams->MultiPredL1 = vaEncMiscParamFeiPic->multi_pred_l1; |
| feiPicParams->SubPelMode = vaEncMiscParamFeiPic->sub_pel_mode; |
| feiPicParams->AdaptiveSearch = vaEncMiscParamFeiPic->adaptive_search; |
| feiPicParams->MVPredictorInput = vaEncMiscParamFeiPic->mv_predictor_input; |
| feiPicParams->bPerBlockQP = vaEncMiscParamFeiPic->per_block_qp; |
| feiPicParams->bPerCTBInput = vaEncMiscParamFeiPic->per_ctb_input; |
| feiPicParams->bColocatedCTBDistortion = vaEncMiscParamFeiPic->colocated_ctb_distortion; |
| feiPicParams->bForceLCUSplit = vaEncMiscParamFeiPic->force_lcu_split; |
| feiPicParams->bEnableCU64Check = vaEncMiscParamFeiPic->enable_cu64_check; |
| feiPicParams->bEnableCU64AmpCheck = vaEncMiscParamFeiPic->enable_cu64_amp_check; |
| feiPicParams->bCU64SkipCheckOnly = vaEncMiscParamFeiPic->cu64_skip_check_only; |
| feiPicParams->RefWidth = vaEncMiscParamFeiPic->ref_width; |
| feiPicParams->RefHeight = vaEncMiscParamFeiPic->ref_height; |
| feiPicParams->SearchWindow = vaEncMiscParamFeiPic->search_window; |
| feiPicParams->MaxNumIMESearchCenter = vaEncMiscParamFeiPic->max_num_ime_search_center; |
| feiPicParams->FastIntraMode = vaEncMiscParamFeiPic->fast_intra_mode; |
| feiPicParams->NumConcurrentEncFramePartition = vaEncMiscParamFeiPic->num_concurrent_enc_frame_partition; |
| feiPicParams->dwMaxFrameSize = vaEncMiscParamFeiPic->max_frame_size; |
| |
| DDI_MEDIA_BUFFER *mediaBuffer; |
| VAStatus status = VA_STATUS_SUCCESS; |
| if(feiPicParams->bPerCTBInput) |
| { |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->ctb_ctrl); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBCtrl)); |
| } |
| if(feiPicParams->MVPredictorInput) |
| { |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_predictor); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVPredictor)); |
| } |
| else if((feiPicParams->NumMVPredictorsL0 !=0) || (feiPicParams->NumMVPredictorsL1 != 0)) |
| { |
| DDI_ASSERTMESSAGE("feiPicParams->NumMVPredictorsL0 and NumMVPredictorsL1 should be set to 0 when feiPicParams->MVPredictorInput is false!"); |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| if(feiPicParams->bPerBlockQP) |
| { |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->qp); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBQp)); |
| } |
| |
| feiPicParams->bCTBCmdCuRecordEnable = false; |
| if(vaEncMiscParamFeiPic->ctb_cmd != VA_INVALID_ID) |
| { |
| feiPicParams->bCTBCmdCuRecordEnable = true; |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->ctb_cmd); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBCmd)); |
| if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC) |
| { |
| RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MVDATA); |
| if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue( (void *)(feiPicParams->resCTBCmd.bo), FEI_ENC_BUFFER_TYPE_MVDATA) ) |
| { |
| DDI_ASSERTMESSAGE("feiPicParams->resCTBCmd is invalid for FEI ENC only"); |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } |
| } |
| if(vaEncMiscParamFeiPic->cu_record != VA_INVALID_ID) |
| { |
| if(feiPicParams->bCTBCmdCuRecordEnable == false) |
| { |
| DDI_ASSERTMESSAGE("CTB cmd and CU record should be enabled or disabled together!"); |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->cu_record); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCURecord)); |
| if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC) |
| { |
| RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MBCODE); |
| if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resCURecord.bo), FEI_ENC_BUFFER_TYPE_MBCODE) ) |
| { |
| DDI_ASSERTMESSAGE("feiPicParams->resCURecord is invalid for FEI ENC only"); |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } |
| } |
| |
| if(vaEncMiscParamFeiPic->distortion != VA_INVALID_ID) |
| { |
| feiPicParams->bDistortionEnable = true; |
| mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->distortion); |
| DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resDistortion)); |
| if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC) |
| { |
| RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_DISTORTION); |
| if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resDistortion.bo), FEI_ENC_BUFFER_TYPE_DISTORTION) ) |
| { |
| DDI_ASSERTMESSAGE("feiPicParams->resDistortion is invalid for FEI ENC only"); |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } |
| } |
| if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC) |
| { |
| AddToEncStatusReportQueueUpdatePos(); |
| } |
| |
| //add for mutlple pass pak |
| feiPicParams->dwMaxFrameSize = vaEncMiscParamFeiPic->max_frame_size; |
| if (feiPicParams->dwMaxFrameSize) |
| { |
| feiPicParams->dwNumPasses = vaEncMiscParamFeiPic->num_passes; |
| if ((feiPicParams->dwNumPasses == 0) || (feiPicParams->dwNumPasses > feiHevcMaxPassesNum)) |
| { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| if (feiPicParams->pDeltaQp != nullptr) |
| { |
| MOS_FreeMemory(feiPicParams->pDeltaQp); |
| } |
| feiPicParams->pDeltaQp = (uint8_t *)MOS_AllocAndZeroMemory(sizeof(uint8_t) * feiPicParams->dwNumPasses); |
| if (!feiPicParams->pDeltaQp) |
| { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| if (MOS_STATUS_SUCCESS != MOS_SecureMemcpy(feiPicParams->pDeltaQp, feiPicParams->dwNumPasses, vaEncMiscParamFeiPic->delta_qp, feiPicParams->dwNumPasses)) |
| { |
| status = VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| } |
| |
| finish: |
| return status; |
| } |
| |
| VAStatus DdiEncodeHevcFei::AddToEncStatusReportQueue( |
| void *encBuf, |
| DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx) |
| { |
| DDI_CHK_NULL(encBuf, "nullptr encBuf", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams); |
| DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC) |
| { |
| DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! ."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX)) |
| { |
| DDI_ASSERTMESSAGE("ENC output buffers status checking, gets invalid buffer type index! ."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| int32_t idx = m_encodeCtx->statusReportBuf.ulHeadPosition; |
| m_encodeCtx->statusReportBuf.encInfos[idx].pEncBuf[typeIdx] = encBuf; |
| m_encodeCtx->statusReportBuf.encInfos[idx].uiStatus = 0; |
| m_encodeCtx->statusReportBuf.encInfos[idx].uiBuffers++; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiEncodeHevcFei::AddToEncStatusReportQueueUpdatePos() |
| { |
| CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams); |
| DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| if(m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC) |
| { |
| DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! ."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition; |
| if((m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers == (feiPicParams->bCTBCmdCuRecordEnable * 2 + feiPicParams->bDistortionEnable)) && m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers != 0) |
| { |
| m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; |
| } |
| |
| finish: |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiEncodeHevcFei::ParseMiscParams(void *ptr) |
| { |
| DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DDI_CHK_NULL(m_encodeCtx->pSeqParams, "nullptr m_encodeCtx->pSeqParams", VA_STATUS_ERROR_INVALID_PARAMETER); |
| DDI_CHK_NULL(m_encodeCtx->pPicParams, "nullptr m_encodeCtx->pPicParams", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams); |
| PCODEC_HEVC_ENCODE_PICTURE_PARAMS picParams = (PCODEC_HEVC_ENCODE_PICTURE_PARAMS)(m_encodeCtx->pPicParams); |
| |
| VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr; |
| DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| switch ((int32_t)(miscParamBuf->type)) |
| { |
| case VAEncMiscParameterTypeQualityLevel: |
| { |
| VAEncMiscParameterBufferQualityLevel *vaEncMiscParamQualityLevel = (VAEncMiscParameterBufferQualityLevel *)miscParamBuf->data; |
| seqParams->TargetUsage = (uint8_t)vaEncMiscParamQualityLevel->quality_level; |
| |
| // HEVC only supports TU=1, 4, and 7 |
| if (1 != seqParams->TargetUsage && 4 != seqParams->TargetUsage && 7 != seqParams->TargetUsage) |
| { |
| DDI_ASSERTMESSAGE("unsupported target usage in HEVC encoder."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| break; |
| } |
| case VAEncMiscParameterTypeHRD: |
| { |
| VAEncMiscParameterHRD *vaEncMiscParamHRD = (VAEncMiscParameterHRD *)miscParamBuf->data; |
| seqParams->VBVBufferSizeInBit = vaEncMiscParamHRD->buffer_size; |
| seqParams->InitVBVBufferFullnessInBit = vaEncMiscParamHRD->initial_buffer_fullness; |
| seqParams->RateControlMethod = RATECONTROL_CBR; |
| break; |
| } |
| case VAEncMiscParameterTypeFrameRate: |
| { |
| VAEncMiscParameterFrameRate *vaEncMiscParamFR = (VAEncMiscParameterFrameRate *)miscParamBuf->data; |
| seqParams->FrameRate.Numerator = vaEncMiscParamFR->framerate & 0xffff; |
| seqParams->FrameRate.Denominator = (vaEncMiscParamFR->framerate >> 16 ) & 0xffff; |
| if(seqParams->FrameRate.Denominator == 0) |
| { |
| seqParams->FrameRate.Denominator = 1; |
| } |
| break; |
| } |
| case VAEncMiscParameterTypeRateControl: |
| { |
| // Assume only one SPS here, modify when enable multiple SPS support |
| VAEncMiscParameterRateControl *vaEncMiscParamRC = (VAEncMiscParameterRateControl *)miscParamBuf->data; |
| |
| seqParams->TargetBitRate = MOS_ROUNDUP_DIVIDE(vaEncMiscParamRC->bits_per_second, CODECHAL_ENCODE_BRC_KBPS); |
| seqParams->MBBRC = (vaEncMiscParamRC->rc_flags.bits.mb_rate_control <= mbBrcDisabled) ? vaEncMiscParamRC->rc_flags.bits.mb_rate_control : 0; |
| //enable parallelBRC for Android and Linux |
| seqParams->ParallelBRC = vaEncMiscParamRC->rc_flags.bits.enable_parallel_brc; |
| |
| // Assuming picParams are sent before MiscParams |
| picParams->BRCMinQp = vaEncMiscParamRC->min_qp; |
| picParams->BRCMaxQp = vaEncMiscParamRC->max_qp; |
| |
| if (VA_RC_NONE == m_encodeCtx->uiRCMethod || VA_RC_CQP == m_encodeCtx->uiRCMethod) |
| { |
| seqParams->RateControlMethod = RATECONTROL_CQP; |
| seqParams->MBBRC = 0; |
| } |
| else if ((VA_RC_CBR | VA_RC_MB) == m_encodeCtx->uiRCMethod || (VA_RC_CBR | VA_RC_MB | VA_RC_PARALLEL) == m_encodeCtx->uiRCMethod) |
| { |
| seqParams->MaxBitRate = seqParams->TargetBitRate; |
| seqParams->MinBitRate = seqParams->TargetBitRate; |
| seqParams->RateControlMethod = RATECONTROL_CBR; |
| } |
| else if (VA_RC_ICQ == m_encodeCtx->uiRCMethod || (VA_RC_ICQ | VA_RC_PARALLEL) == m_encodeCtx->uiRCMethod) |
| { |
| seqParams->ICQQualityFactor = vaEncMiscParamRC->ICQ_quality_factor; |
| seqParams->RateControlMethod = RATECONTROL_ICQ; |
| seqParams->MBBRC = 1; |
| } |
| else |
| { |
| switch (m_encodeCtx->uiRCMethod) |
| { |
| case (VA_RC_VCM | VA_RC_PARALLEL): |
| case VA_RC_VCM: |
| seqParams->RateControlMethod = RATECONTROL_VCM; |
| seqParams->MBBRC = 0; |
| break; |
| case (VA_RC_VBR | VA_RC_MB | VA_RC_PARALLEL): |
| case (VA_RC_VBR | VA_RC_MB): |
| seqParams->RateControlMethod = RATECONTROL_VBR; |
| break; |
| default: |
| DDI_ASSERTMESSAGE("invalid RC method."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| seqParams->MaxBitRate = seqParams->TargetBitRate; |
| seqParams->MinBitRate = seqParams->TargetBitRate * (2 * vaEncMiscParamRC->target_percentage - 100) / 100; |
| seqParams->TargetBitRate = seqParams->TargetBitRate * vaEncMiscParamRC->target_percentage / 100; |
| |
| if ((m_encodeCtx->uiTargetBitRate != seqParams->TargetBitRate) || |
| (m_encodeCtx->uiMaxBitRate != seqParams->MaxBitRate)) |
| { |
| if ((m_encodeCtx->uiTargetBitRate != 0) && (m_encodeCtx->uiMaxBitRate != 0)) |
| { |
| seqParams->bResetBRC = 0x1; |
| } |
| m_encodeCtx->uiTargetBitRate = seqParams->TargetBitRate; |
| m_encodeCtx->uiMaxBitRate = seqParams->MaxBitRate; |
| } |
| } |
| |
| break; |
| } |
| case VAEncMiscParameterTypeParallelBRC: |
| { |
| VAEncMiscParameterParallelRateControl *vaEncMiscParameterParallel = (VAEncMiscParameterParallelRateControl *)miscParamBuf->data; |
| |
| seqParams->NumOfBInGop[0] = vaEncMiscParameterParallel->num_b_in_gop[0]; |
| seqParams->NumOfBInGop[1] = vaEncMiscParameterParallel->num_b_in_gop[1]; |
| seqParams->NumOfBInGop[2] = vaEncMiscParameterParallel->num_b_in_gop[2]; |
| |
| break; |
| } |
| case VAEncMiscParameterTypeRIR: |
| { |
| VAEncMiscParameterRIR *vaEncMiscParamRIR = (VAEncMiscParameterRIR *)miscParamBuf->data; |
| picParams->bEnableRollingIntraRefresh = vaEncMiscParamRIR->rir_flags.value & 0x3; //only lower two bits are valid |
| |
| // Set for all frames since pic type is not known yet. Disable in slice params if its I or B type. |
| if ((ROLLING_I_COLUMN == picParams->bEnableRollingIntraRefresh) || (ROLLING_I_ROW == picParams->bEnableRollingIntraRefresh)) |
| { |
| picParams->IntraInsertionLocation = (uint16_t)vaEncMiscParamRIR->intra_insertion_location; |
| picParams->IntraInsertionSize = (uint8_t)vaEncMiscParamRIR->intra_insert_size; |
| picParams->QpDeltaForInsertedIntra = vaEncMiscParamRIR->qp_delta_for_inserted_intra; |
| } |
| else if ((ROLLING_I_ROW | ROLLING_I_COLUMN) == picParams->bEnableRollingIntraRefresh) // cannot have row and column rolling |
| { |
| picParams->bEnableRollingIntraRefresh = ROLLING_I_DISABLED; |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| break; |
| } |
| case VAEncMiscParameterTypeROI: |
| { |
| VAEncMiscParameterBufferROI *vaEncMiscParamROI = (VAEncMiscParameterBufferROI *)miscParamBuf->data; |
| uint32_t maxROIsupported = CODECHAL_ENCODE_HEVC_MAX_NUM_ROI; |
| uint8_t blockSize = (m_encodeCtx->bVdencActive) ? vdencRoiBlockSize : CODECHAL_MACROBLOCK_WIDTH; |
| |
| if (vaEncMiscParamROI->num_roi) |
| { |
| for (uint32_t i = 0; i < vaEncMiscParamROI->num_roi; ++i) |
| { |
| picParams->ROI[i].PriorityLevelOrDQp = vaEncMiscParamROI->roi[i].roi_value; |
| picParams->ROI[i].Top = vaEncMiscParamROI->roi[i].roi_rectangle.y; |
| picParams->ROI[i].Left = vaEncMiscParamROI->roi[i].roi_rectangle.x; |
| picParams->ROI[i].Bottom = vaEncMiscParamROI->roi[i].roi_rectangle.y + |
| vaEncMiscParamROI->roi[i].roi_rectangle.height - 1; |
| picParams->ROI[i].Right = vaEncMiscParamROI->roi[i].roi_rectangle.x + |
| vaEncMiscParamROI->roi[i].roi_rectangle.width - 1; |
| |
| if (m_encodeCtx->bVdencActive == false) |
| { |
| // align to CTB edge (32 on Gen9) to avoid QP average issue |
| picParams->ROI[i].Left = MOS_ALIGN_FLOOR(picParams->ROI[i].Left, 32); |
| picParams->ROI[i].Right = MOS_ALIGN_CEIL(picParams->ROI[i].Right, 32); |
| picParams->ROI[i].Top = MOS_ALIGN_FLOOR(picParams->ROI[i].Top, 32); |
| picParams->ROI[i].Bottom = MOS_ALIGN_CEIL(picParams->ROI[i].Bottom, 32); |
| } |
| |
| // Convert from pixel units to block size units |
| picParams->ROI[i].Left /= blockSize; |
| picParams->ROI[i].Right /= blockSize; |
| picParams->ROI[i].Top /= blockSize; |
| picParams->ROI[i].Bottom /= blockSize; |
| } |
| picParams->NumROI = MOS_MIN(vaEncMiscParamROI->num_roi, maxROIsupported); |
| } |
| #ifndef ANDROID |
| // support DeltaQP based ROI by default |
| seqParams->ROIValueInDeltaQP = vaEncMiscParamROI->roi_flags.bits.roi_value_is_qp_delta; |
| #endif |
| break; |
| } |
| case VAEncMiscParameterTypeSkipFrame: |
| { |
| VAEncMiscParameterSkipFrame *vaEncMiscParamSkipFrame = (VAEncMiscParameterSkipFrame *)miscParamBuf->data; |
| // populate skipped frame params from DDI |
| if (FRAME_SKIP_NORMAL != vaEncMiscParamSkipFrame->skip_frame_flag) |
| { |
| DDI_ASSERTMESSAGE("unsupported misc parameter type."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| picParams->SkipFrameFlag = vaEncMiscParamSkipFrame->skip_frame_flag; |
| picParams->NumSkipFrames = vaEncMiscParamSkipFrame->num_skip_frames; |
| picParams->SizeSkipFrames = vaEncMiscParamSkipFrame->size_skip_frames; |
| break; |
| } |
| case VAEncMiscParameterTypeMaxSliceSize: |
| { |
| VAEncMiscParameterMaxSliceSize *vaEncMiscParamMaxSliceSize = (VAEncMiscParameterMaxSliceSize *)miscParamBuf->data; |
| m_encodeCtx->EnableSliceLevelRateCtrl = true; |
| seqParams->SliceSizeControl = true; |
| picParams->MaxSliceSizeInBytes = vaEncMiscParamMaxSliceSize->max_slice_size; |
| break; |
| } |
| case VAEncMiscParameterTypeEncQuality: |
| { |
| VAEncMiscParameterEncQuality *vaEncMiscParamEncQuality = (VAEncMiscParameterEncQuality *)miscParamBuf->data; |
| picParams->bUseRawPicForRef = vaEncMiscParamEncQuality->useRawPicForRef; |
| break; |
| } |
| case VAEncMiscParameterTypeFEIFrameControl: |
| { |
| if (VA_STATUS_SUCCESS != ParseMiscParamFeiPic((void *)miscParamBuf->data)) |
| { |
| DDI_ASSERTMESSAGE("parse misc FEI picture parameters error."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| break; |
| } |
| default: |
| DDI_ASSERTMESSAGE("unsupported misc parameter type."); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |