| /* |
| * Copyright (c) 2019-2022, 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 encode_vp9_basic_feature.cpp |
| //! \brief Defines the common interface for encode vp9 parameter |
| //! |
| |
| #include "encode_utils.h" |
| #include "encode_allocator.h" |
| |
| #include "encode_vp9_basic_feature.h" |
| #include "encode_vp9_vdenc_const_settings.h" |
| #include "encode_vp9_brc.h" |
| #include "encode_vp9_segmentation.h" |
| |
| #include "media_feature_manager.h" |
| #include "media_vp9_feature_defs.h" |
| |
| namespace encode |
| { |
| MOS_STATUS Vp9BasicFeature::Init(void *setting) |
| { |
| ENCODE_FUNC_CALL(); |
| ENCODE_CHK_NULL_RETURN(setting); |
| |
| EncodeBasicFeature::Init(setting); |
| CodechalSetting *codecSettings = (CodechalSetting *)setting; |
| |
| // Need to convert from VP9_ENCODE_CHROMA_FORMAT to HCP_CHROMA_FORMAT_IDC type |
| m_chromaFormat += 1; |
| |
| if (CodecHalUsesVideoEngine(m_codecFunction)) |
| { |
| m_pakEnabled = true; |
| } |
| |
| if (CodecHalUsesRenderEngine(m_codecFunction, m_standard)) |
| { |
| m_encEnabled = true; |
| } |
| |
| m_adaptiveRepakSupported = true; |
| |
| // HME Scaling WxH |
| m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x); |
| m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x); |
| m_downscaledWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; |
| m_downscaledHeight4x = m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| // SuperHME Scaling WxH |
| m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_16x); |
| m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_16x); |
| m_downscaledWidth16x = m_downscaledWidthInMb16x * CODECHAL_MACROBLOCK_WIDTH; |
| m_downscaledHeight16x = m_downscaledHeightInMb16x * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| m_minScaledDimension = CODECHAL_ENCODE_MIN_SCALED_SURFACE_SIZE; |
| m_minScaledDimensionInMb = (CODECHAL_ENCODE_MIN_SCALED_SURFACE_SIZE + 15) >> 4; |
| |
| // Max tile numbers = max of number tiles for single pipe or max number of tiles for scalable pipes |
| m_maxTileNumber = CODECHAL_GET_WIDTH_IN_BLOCKS(m_frameWidth, CODECHAL_ENCODE_VP9_MIN_TILE_SIZE_WIDTH) * |
| CODECHAL_GET_HEIGHT_IN_BLOCKS(m_frameHeight, CODECHAL_ENCODE_VP9_MIN_TILE_SIZE_HEIGHT); |
| |
| // Picture (width, height, size) in SB units |
| m_picWidthInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameWidth, CODEC_VP9_SUPER_BLOCK_WIDTH); |
| m_picHeightInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT); |
| m_picSizeInSb = m_picWidthInSb * m_picHeightInSb; |
| |
| // Application needs to pass the maxinum frame width/height |
| m_maxPicWidth = m_frameWidth; |
| m_maxPicHeight = m_frameHeight; |
| m_maxPicWidthInSb = MOS_ROUNDUP_DIVIDE(m_maxPicWidth, CODEC_VP9_SUPER_BLOCK_WIDTH); |
| m_maxPicHeightInSb = MOS_ROUNDUP_DIVIDE(m_maxPicHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT); |
| m_maxPicSizeInSb = m_maxPicWidthInSb * m_maxPicHeightInSb; |
| |
| if (m_pakEnabled) |
| { |
| // m_mvoffset looks not correct here, and corresponding setting of buffer offset in HCP_IND_OBJ, need to check with HW team. |
| // keep current logic unchanged but increase the buffer size for now in case regression before we know how to correctly program these. |
| m_mvOffset = MOS_ALIGN_CEIL((m_maxPicSizeInSb * 4 * sizeof(uint32_t)), CODECHAL_PAGE_SIZE); // 3 uint32_t for HCP_PAK_OBJECT and 1 uint32_t for padding zero in kernel |
| |
| // We need additional buffer for |
| // (1) 1 CL for size info at the beginning of each tile column (max of 4 vdbox in scalability mode) |
| // (2) CL alignment at the end of every tile column for every SB of width |
| // As a result, increase the height by 1 for allocation purposes |
| uint32_t numOfLCU = m_maxPicSizeInSb + m_maxPicWidthInSb; |
| uint32_t maxNumCUInLCU = (m_maxLCUSize / m_minLCUSize) * (m_maxLCUSize / m_minLCUSize); |
| m_mbCodeSize = MOS_ALIGN_CEIL(2 * sizeof(uint32_t) * numOfLCU * (NUM_PAK_DWS_PER_LCU + 64 * NUM_DWS_PER_CU), CODECHAL_PAGE_SIZE); |
| } |
| |
| #if (_DEBUG || _RELEASE_INTERNAL) |
| MediaUserSetting::Value outValue; |
| |
| // HUC enabled by default for VP9 |
| ReadUserSettingForDebug( |
| m_userSettingPtr, |
| outValue, |
| "VP9 Encode HUC Enable", |
| MediaUserSetting::Group::Sequence); |
| m_hucEnabled = outValue.Get<bool>(); |
| |
| // Single pass dynamic scaling enabled by default |
| ReadUserSettingForDebug( |
| m_userSettingPtr, |
| outValue, |
| "VP9 Encode Single Pass Dys Enable", |
| MediaUserSetting::Group::Sequence); |
| m_dysVdencMultiPassEnabled = !outValue.Get<bool>(); |
| |
| // HME enabled by default for VP9 |
| ReadUserSettingForDebug( |
| m_userSettingPtr, |
| outValue, |
| "VP9 Encode HME", |
| MediaUserSetting::Group::Sequence); |
| m_hmeSupported = outValue.Get<bool>(); |
| |
| ReadUserSettingForDebug( |
| m_userSettingPtr, |
| outValue, |
| "VP9 Encode SuperHME", |
| MediaUserSetting::Group::Sequence); |
| m_16xMeSupported = outValue.Get<bool>(); |
| #endif |
| |
| // Disable superHME when HME is disabled |
| if (m_hmeSupported == false) |
| { |
| m_16xMeSupported = false; |
| } |
| |
| ENCODE_CHK_STATUS_RETURN(m_ref.Init(this)); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::Update(void *params) |
| { |
| ENCODE_FUNC_CALL(); |
| ENCODE_CHK_NULL_RETURN(params); |
| |
| ENCODE_CHK_STATUS_RETURN(EncodeBasicFeature::Update(params)); |
| |
| EncoderParams *encodeParams = (EncoderParams *)params; |
| |
| m_vp9SeqParams = static_cast<PCODEC_VP9_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams); |
| ENCODE_CHK_NULL_RETURN(m_vp9SeqParams); |
| m_vp9PicParams = static_cast<PCODEC_VP9_ENCODE_PIC_PARAMS>(encodeParams->pPicParams); |
| ENCODE_CHK_NULL_RETURN(m_vp9PicParams); |
| m_vp9SegmentParams = static_cast<PCODEC_VP9_ENCODE_SEGMENT_PARAMS>(encodeParams->pSegmentParams); |
| ENCODE_CHK_NULL_RETURN(m_vp9SegmentParams); |
| |
| m_nalUnitParams = encodeParams->ppNALUnitParams; |
| ENCODE_CHK_NULL_RETURN(m_nalUnitParams); |
| m_NumNalUnits = encodeParams->uiNumNalUnits; |
| ENCODE_ASSERT(m_NumNalUnits == 1); |
| |
| m_targetUsage = m_vp9SeqParams->TargetUsage; |
| m_currOriginalPic = m_vp9PicParams->CurrOriginalPic; |
| m_currReconstructedPic = m_vp9PicParams->CurrReconstructedPic; |
| m_pictureCodingType = m_vp9PicParams->PicFlags.fields.frame_type == 0 ? I_TYPE : P_TYPE; |
| |
| m_bitstreamUpperBound = encodeParams->dwBitstreamSize; |
| |
| if (m_newSeq) |
| { |
| ENCODE_CHK_STATUS_RETURN(SetSequenceStructs()); |
| } |
| |
| // Set picture structs here |
| ENCODE_CHK_STATUS_RETURN(SetPictureStructs()) |
| |
| if (m_resolutionChanged) |
| { |
| ENCODE_CHK_STATUS_RETURN(UpdateTrackedBufferParameters()); |
| } |
| |
| ENCODE_CHK_STATUS_RETURN(GetTrackedBuffers()); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| uint32_t Vp9BasicFeature::GetProfileLevelMaxFrameSize() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| uint32_t profileLevelMaxFrame = m_frameWidth * m_frameHeight; |
| if (m_vp9SeqParams->UserMaxFrameSize > 0) |
| { |
| profileLevelMaxFrame = MOS_MIN(profileLevelMaxFrame, m_vp9SeqParams->UserMaxFrameSize); |
| } |
| |
| return profileLevelMaxFrame; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::Resize4x8xforDS(uint8_t bufIdx) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| // Calculate the expected 4x dimensions |
| uint32_t downscaledSurfaceWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; |
| uint32_t downscaledSurfaceHeight4x = ((m_downscaledHeightInMb4x + 1) >> 1) * CODECHAL_MACROBLOCK_HEIGHT; |
| downscaledSurfaceHeight4x = MOS_ALIGN_CEIL(downscaledSurfaceHeight4x, MOS_YTILE_H_ALIGNMENT) << 1; |
| |
| // Calculate the expected 8x dimensions |
| uint32_t downscaledSurfaceWidth8x = downscaledSurfaceWidth4x >> 1; |
| uint32_t downscaledSurfaceHeight8x = downscaledSurfaceHeight4x >> 1; |
| |
| ENCODE_CHK_NULL_RETURN(m_trackedBuf); |
| |
| // Get the 8x and 4x ds downscaled surfaces from tracked buffers |
| auto trackedBuf8xDsReconSurface = m_trackedBuf->GetSurface(BufferType::ds8xSurface, bufIdx); |
| auto trackedBuf4xDsReconSurface = m_trackedBuf->GetSurface(BufferType::ds4xSurface, bufIdx); |
| |
| ENCODE_CHK_NULL_RETURN(trackedBuf8xDsReconSurface); |
| ENCODE_CHK_NULL_RETURN(trackedBuf4xDsReconSurface); |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D; |
| MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBuffer2D.Type = MOS_GFXRES_2D; |
| allocParamsForBuffer2D.TileType = MOS_TILE_Y; |
| allocParamsForBuffer2D.Format = Format_NV12; |
| |
| // If any dimensions of allocated surface are smaller, reallocation is needed |
| if (trackedBuf8xDsReconSurface->dwWidth < downscaledSurfaceWidth8x || trackedBuf8xDsReconSurface->dwHeight < downscaledSurfaceHeight8x) |
| { |
| // Get the previously assigned dimensions to make sure we do not lower any dimension |
| auto previous8xWidth = trackedBuf8xDsReconSurface->dwWidth; |
| auto previous8xHeight = trackedBuf8xDsReconSurface->dwHeight; |
| |
| auto new8xWidth = MOS_MAX(previous8xWidth, downscaledSurfaceWidth8x); |
| auto new8xHeight = MOS_MAX(previous8xHeight, downscaledSurfaceHeight8x); |
| |
| allocParamsForBuffer2D.dwWidth = new8xWidth; |
| allocParamsForBuffer2D.dwHeight = new8xHeight; |
| allocParamsForBuffer2D.pBufName = "8xDSSurface"; |
| allocParamsForBuffer2D.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds8xSurface, allocParamsForBuffer2D)); |
| } |
| |
| if (trackedBuf4xDsReconSurface->dwWidth < downscaledSurfaceWidth4x || trackedBuf4xDsReconSurface->dwHeight < downscaledSurfaceHeight4x) |
| { |
| // Get the previously assigned dimensions to make sure we do not lower any dimension |
| auto previous4xWidth = trackedBuf4xDsReconSurface->dwWidth; |
| auto previous4xHeight = trackedBuf4xDsReconSurface->dwHeight; |
| |
| auto new4xWidth = MOS_MAX(previous4xWidth, downscaledSurfaceWidth4x); |
| auto new4xHeight = MOS_MAX(previous4xHeight, downscaledSurfaceHeight4x); |
| |
| allocParamsForBuffer2D.dwWidth = new4xWidth; |
| allocParamsForBuffer2D.dwHeight = new4xHeight; |
| allocParamsForBuffer2D.pBufName = "4xDSSurface"; |
| allocParamsForBuffer2D.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds4xSurface, allocParamsForBuffer2D)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::UpdateParameters() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| m_prevFrameInfo.KeyFrame = !m_vp9PicParams->PicFlags.fields.frame_type; |
| m_prevFrameInfo.IntraOnly = (m_vp9PicParams->PicFlags.fields.frame_type == CODEC_VP9_KEY_FRAME) || m_vp9PicParams->PicFlags.fields.intra_only; |
| m_prevFrameInfo.ShowFrame = m_vp9PicParams->PicFlags.fields.show_frame; |
| m_prevFrameInfo.FrameWidth = m_oriFrameWidth; |
| m_prevFrameInfo.FrameHeight = m_oriFrameHeight; |
| |
| m_lastMvTemporalBufferIndex = m_currMvTemporalBufferIndex; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::UpdateTrackedBufferParameters() |
| { |
| ENCODE_FUNC_CALL(); |
| ENCODE_CHK_NULL_RETURN(m_trackedBuf); |
| |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->OnSizeChange()); |
| |
| m_mvDataSize = 0; |
| |
| uint32_t downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x); |
| uint32_t downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x); |
| |
| m_downscaledWidth4x = downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; |
| |
| // Account for field case, offset needs to be 4K aligned if tiled for DI surface state |
| // Width will be allocated tile Y aligned, so also tile align height |
| uint32_t downscaledSurfaceHeight4x = ((downscaledHeightInMb4x + 1) >> 1) * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| m_downscaledHeight4x = MOS_ALIGN_CEIL(downscaledSurfaceHeight4x, MOS_YTILE_H_ALIGNMENT) << 1; |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParams; |
| MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParams.Type = MOS_GFXRES_BUFFER; |
| allocParams.TileType = MOS_TILE_LINEAR; |
| allocParams.Format = Format_Buffer; |
| |
| // Segment ID buffer |
| uint32_t sizeOfSegmentIdMap = m_maxPicSizeInSb * CODECHAL_CACHELINE_SIZE; |
| if (sizeOfSegmentIdMap > 0) |
| { |
| allocParams.dwBytes = sizeOfSegmentIdMap; |
| allocParams.pBufName = "SegmentIdBuffer"; |
| allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::segmentIdStreamOutBuffer, allocParams)); |
| } |
| |
| // Current MV temporal buffer |
| uint32_t sizeOfMvTemporalBuffer = m_maxPicSizeInSb * 9 * CODECHAL_CACHELINE_SIZE; |
| if (sizeOfMvTemporalBuffer > 0) |
| { |
| allocParams.dwBytes = sizeOfMvTemporalBuffer; |
| allocParams.pBufName = "mvTemporalBuffer"; |
| allocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::mvTemporalBuffer, allocParams)); |
| } |
| |
| ENCODE_CHK_STATUS_RETURN(EncodeBasicFeature::UpdateTrackedBufferParameters()); |
| |
| ENCODE_CHK_STATUS_RETURN(ResizeDsReconSurfacesVdenc()); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::GetTrackedBuffers() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| ENCODE_CHK_NULL_RETURN(m_trackedBuf); |
| ENCODE_CHK_NULL_RETURN(m_vp9PicParams); |
| ENCODE_CHK_NULL_RETURN(m_allocator); |
| |
| auto currRefList = m_ref.GetCurrRefList(); |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->Acquire(currRefList, false, true)); |
| |
| auto currIndex = m_trackedBuf->GetCurrIndex(); |
| |
| m_resMbCodeBuffer = m_trackedBuf->GetBuffer(BufferType::mbCodedBuffer, currIndex); |
| ENCODE_CHK_NULL_RETURN(m_resMbCodeBuffer); |
| |
| currRefList->ucMbCodeIdx = currIndex; |
| currRefList->resRefMbCodeBuffer = *m_resMbCodeBuffer; |
| |
| m_4xDSSurface = m_trackedBuf->GetSurface(BufferType::ds4xSurface, currIndex); |
| ENCODE_CHK_NULL_RETURN(m_4xDSSurface); |
| ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(m_4xDSSurface)); |
| |
| m_8xDSSurface = m_trackedBuf->GetSurface(BufferType::ds8xSurface, currIndex); |
| ENCODE_CHK_NULL_RETURN(m_8xDSSurface); |
| ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(m_8xDSSurface)); |
| |
| m_resMvTemporalBuffer = m_trackedBuf->GetBuffer(BufferType::mvTemporalBuffer, currIndex); |
| ENCODE_CHK_NULL_RETURN(m_resMvTemporalBuffer); |
| m_currMvTemporalBufferIndex = currIndex; |
| |
| m_resSegmentIdBuffer = m_trackedBuf->GetBuffer(BufferType::segmentIdStreamOutBuffer, currIndex); |
| ENCODE_CHK_NULL_RETURN(m_resSegmentIdBuffer); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::SetSequenceStructs() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| if (m_adaptiveRepakSupported) |
| { |
| ENCODE_CHK_STATUS_RETURN(CalculateRePakThresholds()); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::SetPictureStructs() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| if (false == isHmeEnabledForTargetUsage(m_vp9SeqParams->TargetUsage)) |
| { |
| m_hmeEnabled = m_16xMeSupported = m_32xMeSupported = false; |
| m_16xMeEnabled = false; |
| } |
| |
| // Setup internal parameters |
| uint32_t frameWidth = m_vp9PicParams->SrcFrameWidthMinus1 + 1; |
| uint32_t frameHeight = m_vp9PicParams->SrcFrameHeightMinus1 + 1; |
| |
| // dwOriFrameWidth and dwOriFrameHeight are encoded by resolution. |
| // If dynamic scaling is enabled, current resolution may differ from the source resolution. |
| // Only for the first frame |
| if (m_frameNum == 0) |
| { |
| m_oriFrameWidth = frameWidth; |
| m_oriFrameHeight = frameHeight; |
| m_resolutionChanged = true; |
| } |
| else |
| { |
| // Check if there is a dynamic resolution change |
| if ((m_oriFrameWidth && (m_oriFrameWidth != frameWidth)) || |
| (m_oriFrameHeight && (m_oriFrameHeight != frameHeight))) |
| { |
| m_resolutionChanged = true; |
| m_oriFrameWidth = frameWidth; |
| m_oriFrameHeight = frameHeight; |
| } |
| else |
| { |
| m_resolutionChanged = false; |
| } |
| } |
| |
| if (m_oriFrameWidth == 0 || m_oriFrameWidth > m_maxPicWidth || |
| m_oriFrameHeight == 0 || m_oriFrameHeight > m_maxPicHeight) |
| { |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| // Picture (width, height, size) in SB units |
| m_picWidthInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameWidth, CODEC_VP9_SUPER_BLOCK_WIDTH); |
| m_picHeightInSb = MOS_ROUNDUP_DIVIDE(m_oriFrameHeight, CODEC_VP9_SUPER_BLOCK_HEIGHT); |
| m_picSizeInSb = m_picWidthInSb * m_picHeightInSb; |
| |
| // Picture (width, height) in MB units |
| m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth); |
| m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight); |
| m_frameWidth = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH; |
| m_frameHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| // HME Scaling WxH |
| m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x); |
| m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x); |
| m_downscaledWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; |
| m_downscaledHeight4x = m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| // SuperHME Scaling WxH |
| m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_16x); |
| m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_16x); |
| m_downscaledWidth16x = m_downscaledWidthInMb16x * CODECHAL_MACROBLOCK_WIDTH; |
| m_downscaledHeight16x = m_downscaledHeightInMb16x * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| m_frameFieldHeight = m_frameHeight; |
| m_frameFieldHeightInMb = m_picHeightInMb; |
| m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x; |
| m_downscaledFrameFieldHeightInMb16x = m_downscaledHeightInMb16x; |
| |
| MotionEstimationDisableCheck(); |
| |
| if (m_vp9SeqParams->SeqFlags.fields.EnableDynamicScaling) |
| { |
| m_rawSurface.dwWidth = MOS_ALIGN_CEIL(m_vp9PicParams->SrcFrameWidthMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH); |
| m_rawSurface.dwHeight = MOS_ALIGN_CEIL(m_vp9PicParams->SrcFrameHeightMinus1 + 1, CODEC_VP9_MIN_BLOCK_HEIGHT); |
| } |
| |
| if (Mos_ResourceIsNull(&m_reconSurface.OsResource) && |
| (!m_vp9SeqParams->SeqFlags.fields.bUseRawReconRef || m_codecFunction != CODECHAL_FUNCTION_ENC)) |
| { |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| m_dysBrc = false; |
| m_dysCqp = false; |
| |
| // Update reference frames |
| ENCODE_CHK_STATUS_RETURN(m_ref.Update()); |
| |
| m_vdencPakonlyMultipassEnabled = false; |
| |
| m_txMode = CODEC_VP9_TX_SELECTABLE; |
| |
| // For VDEnc disable HME if HME hasn't been disabled by reg key AND TU != TU1 |
| m_hmeSupported = m_hmeSupported && isHmeEnabledForTargetUsage(m_vp9SeqParams->TargetUsage); |
| m_16xMeSupported = m_16xMeSupported && m_hmeSupported; |
| // Enable HME/SHME for frame |
| m_hmeEnabled = m_hmeSupported && m_pictureCodingType != I_TYPE && !m_vp9PicParams->PicFlags.fields.intra_only; |
| m_16xMeEnabled = m_16xMeSupported && m_hmeEnabled; |
| |
| // We cannot use refresh_frame_context if HuC isn't enabled to update probs |
| if (m_vp9PicParams->PicFlags.fields.refresh_frame_context && !m_hucEnabled) |
| { |
| ENCODE_ASSERTMESSAGE("Refresh_frame_context cannot be enabled while HuC is disabled. HuC is needed for refresh_frame_context to be enabled."); |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| void Vp9BasicFeature::MotionEstimationDisableCheck() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb || |
| m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb) |
| { |
| m_32xMeSupported = false; |
| m_16xMeSupported = false; |
| if (m_downscaledWidth4x < m_minScaledDimension || m_downscaledWidthInMb4x < m_minScaledDimensionInMb) |
| { |
| m_downscaledWidth4x = m_minScaledDimension; |
| m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth4x); |
| } |
| if (m_downscaledHeight4x < m_minScaledDimension || m_downscaledHeightInMb4x < m_minScaledDimensionInMb) |
| { |
| m_downscaledHeight4x = m_minScaledDimension; |
| m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight4x); |
| } |
| } |
| else if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb || |
| m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb) |
| { |
| m_32xMeSupported = false; |
| if (m_downscaledWidth16x < m_minScaledDimension || m_downscaledWidthInMb16x < m_minScaledDimensionInMb) |
| { |
| m_downscaledWidth16x = m_minScaledDimension; |
| m_downscaledWidthInMb16x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth16x); |
| } |
| if (m_downscaledHeight16x < m_minScaledDimension || m_downscaledHeightInMb16x < m_minScaledDimensionInMb) |
| { |
| m_downscaledHeight16x = m_minScaledDimension; |
| m_downscaledHeightInMb16x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight16x); |
| } |
| } |
| else |
| { |
| if (m_downscaledWidth32x < m_minScaledDimension || m_downscaledWidthInMb32x < m_minScaledDimensionInMb) |
| { |
| m_downscaledWidth32x = m_minScaledDimension; |
| m_downscaledWidthInMb32x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_downscaledWidth32x); |
| } |
| if (m_downscaledHeight32x < m_minScaledDimension || m_downscaledHeightInMb32x < m_minScaledDimensionInMb) |
| { |
| m_downscaledHeight32x = m_minScaledDimension; |
| m_downscaledHeightInMb32x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_downscaledHeight32x); |
| } |
| } |
| } |
| |
| MOS_STATUS Vp9BasicFeature::ResizeDsReconSurfacesVdenc() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| ENCODE_CHK_NULL_RETURN(m_trackedBuf); |
| |
| auto allocated8xWidth = m_downscaledWidth4x >> 1; |
| auto allocated8xHeight = MOS_ALIGN_CEIL(m_downscaledHeight4x >> 1, MOS_YTILE_H_ALIGNMENT) << 1; |
| |
| // Calculate the expected 4x dimensions |
| uint32_t downscaledSurfaceWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; |
| |
| // Account for field case, offset needs to be 4K aligned if tiled for DI surface state. |
| // Width will be allocated tile Y aligned, so also tile align height. |
| uint32_t downscaledSurfaceHeight4x = ((m_downscaledHeightInMb4x + 1) >> 1) * CODECHAL_MACROBLOCK_HEIGHT; |
| downscaledSurfaceHeight4x = MOS_ALIGN_CEIL(downscaledSurfaceHeight4x, MOS_YTILE_H_ALIGNMENT) << 1; |
| |
| // Calculate the expected 8x dimensions |
| uint32_t downscaledSurfaceWidth8x = downscaledSurfaceWidth4x >> 1; |
| uint32_t downscaledSurfaceHeight8x = downscaledSurfaceHeight4x >> 1; |
| |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D; |
| MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBuffer2D.Type = MOS_GFXRES_2D; |
| allocParamsForBuffer2D.TileType = MOS_TILE_Y; |
| allocParamsForBuffer2D.Format = Format_NV12; |
| |
| // If any dimensions of allocated surface are smaller, reallocation is needed |
| if ((downscaledSurfaceHeight4x != m_downscaledHeight4x) || (downscaledSurfaceWidth4x != m_downscaledWidth4x)) |
| { |
| allocParamsForBuffer2D.dwWidth = downscaledSurfaceWidth4x; |
| allocParamsForBuffer2D.dwHeight = downscaledSurfaceHeight4x; |
| allocParamsForBuffer2D.pBufName = "4xDSSurface"; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds4xSurface, allocParamsForBuffer2D)); |
| } |
| |
| if ((downscaledSurfaceHeight8x != allocated8xHeight) || (downscaledSurfaceWidth8x != allocated8xWidth)) |
| { |
| allocParamsForBuffer2D.dwWidth = downscaledSurfaceWidth8x; |
| allocParamsForBuffer2D.dwHeight = downscaledSurfaceHeight8x; |
| allocParamsForBuffer2D.pBufName = "8xDSSurface"; |
| ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds8xSurface, allocParamsForBuffer2D)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS Vp9BasicFeature::CalculateRePakThresholds() |
| { |
| ENCODE_FUNC_CALL(); |
| |
| ENCODE_CHK_NULL_RETURN(m_vp9SeqParams); |
| |
| int32_t repakSavingThreshold = 0; |
| |
| if (m_prevFrameInfo.FrameWidth != m_oriFrameWidth || |
| m_prevFrameInfo.FrameHeight != m_oriFrameHeight) |
| { |
| if (TargetUsage::isQuality(m_oriTargetUsage)) |
| { |
| repakSavingThreshold = 2; // Quality mode |
| } |
| else if (TargetUsage::isSpeed(m_oriTargetUsage)) |
| { |
| repakSavingThreshold = 80; // Speed mode |
| } |
| else |
| { |
| repakSavingThreshold = 10; // Normal mode |
| } |
| |
| int32_t scale = (m_oriFrameWidth * m_oriFrameHeight) / (176 * 144); |
| if (!scale) |
| { |
| scale = 1; |
| } |
| |
| for (auto i = 0; i < CODEC_VP9_QINDEX_RANGE; ++i) |
| { |
| double tempQp = i - 144.0; |
| |
| int32_t b = (int32_t)(92.5 * i); |
| int32_t c = (int32_t)(1.6 * tempQp * tempQp); |
| int32_t d = (int32_t)(0.01 * tempQp * tempQp * tempQp); |
| int32_t threshold = (int32_t)((18630 - b + c - d) / 10); |
| int32_t calculatedRepakSavingThreshold = repakSavingThreshold * scale; |
| |
| // To avoid overflow of the integer threshold, it must be (RepakSavingThreshold * scale) <= 40342 |
| if (calculatedRepakSavingThreshold > CODEC_VP9_MAX_REPAK_THRESHOLD) |
| { |
| calculatedRepakSavingThreshold = CODEC_VP9_MAX_REPAK_THRESHOLD; |
| } |
| m_rePakThreshold[i] = calculatedRepakSavingThreshold * threshold; |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| uint32_t Vp9BasicFeature::Convert2SignMagnitude(int32_t val, uint32_t signBitPos) const |
| { |
| uint32_t retVal = 0; |
| uint32_t magnitudeMask = (1 << (signBitPos - 1)) - 1; |
| |
| if (val < 0) |
| { |
| retVal = ((magnitudeMask + 1) | (-val & magnitudeMask)); |
| } |
| else |
| { |
| retVal = val & magnitudeMask; |
| } |
| return retVal; |
| } |
| |
| bool Vp9BasicFeature::isHmeEnabledForTargetUsage(uint8_t targetUsage) const |
| { |
| if (TargetUsage::QUALITY == targetUsage) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| MHW_SETPAR_DECL_SRC(HCP_VP9_PIC_STATE, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| uint32_t curFrameWidth = m_vp9PicParams->SrcFrameWidthMinus1 + 1; |
| uint32_t curFrameHeight = m_vp9PicParams->SrcFrameHeightMinus1 + 1; |
| |
| params.frameWidthInPixelsMinus1 = MOS_ALIGN_CEIL(curFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH) - 1; |
| params.frameHeightInPixelsMinus1 = MOS_ALIGN_CEIL(curFrameHeight, CODEC_VP9_MIN_BLOCK_WIDTH) - 1; |
| |
| params.frameType = m_vp9PicParams->PicFlags.fields.frame_type; |
| params.adaptProbabilitiesFlag = !m_vp9PicParams->PicFlags.fields.error_resilient_mode && !m_vp9PicParams->PicFlags.fields.frame_parallel_decoding_mode; |
| params.intraOnlyFlag = m_vp9PicParams->PicFlags.fields.intra_only; |
| params.allowHiPrecisionMv = m_vp9PicParams->PicFlags.fields.allow_high_precision_mv; |
| params.mcompFilterType = m_vp9PicParams->PicFlags.fields.mcomp_filter_type; |
| params.hybridPredictionMode = m_vp9PicParams->PicFlags.fields.comp_prediction_mode == 2; |
| params.selectableTxMode = m_txMode == 4; |
| params.refreshFrameContext = m_vp9PicParams->PicFlags.fields.refresh_frame_context; |
| params.errorResilientMode = m_vp9PicParams->PicFlags.fields.error_resilient_mode; |
| params.frameParallelDecodingMode = m_vp9PicParams->PicFlags.fields.frame_parallel_decoding_mode; |
| params.filterLevel = m_vp9PicParams->filter_level; |
| params.sharpnessLevel = m_vp9PicParams->sharpness_level; |
| params.segmentationEnabled = m_vp9PicParams->PicFlags.fields.segmentation_enabled; |
| params.segmentationUpdateMap = m_vp9PicParams->PicFlags.fields.segmentation_update_map; |
| params.segmentationTemporalUpdate = m_vp9PicParams->PicFlags.fields.segmentation_temporal_update; |
| params.losslessMode = m_vp9PicParams->PicFlags.fields.LosslessFlag; |
| |
| params.log2TileRow = m_vp9PicParams->log2_tile_rows; |
| params.log2TileColumn = m_vp9PicParams->log2_tile_columns; |
| |
| params.chromaSamplingFormat = m_vp9SeqParams->SeqFlags.fields.EncodedFormat; |
| params.bitdepthMinus8 = (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth == VP9_ENCODED_BIT_DEPTH_10) ? 2 : 0; |
| |
| params.baseQIndexSameAsLumaAc = m_vp9PicParams->LumaACQIndex; |
| params.headerInsertionEnable = 1; |
| |
| params.chromaAcQIndexDelta = Convert2SignMagnitude(m_vp9PicParams->ChromaACQIndexDelta, 5); |
| params.chromaDcQIndexDelta = Convert2SignMagnitude(m_vp9PicParams->ChromaDCQIndexDelta, 5); |
| params.lumaDcQIndexDelta = Convert2SignMagnitude(m_vp9PicParams->LumaDCQIndexDelta, 5); |
| |
| params.bitOffsetForLfRefDelta = m_vp9PicParams->BitOffsetForLFRefDelta; |
| params.bitOffsetForLfModeDelta = m_vp9PicParams->BitOffsetForLFModeDelta; |
| params.bitOffsetForLfLevel = m_vp9PicParams->BitOffsetForLFLevel; |
| params.bitOffsetForQIndex = m_vp9PicParams->BitOffsetForQIndex; |
| params.bitOffsetForFirstPartitionSize = m_vp9PicParams->BitOffsetForFirstPartitionSize; |
| |
| params.vdencPakOnlyPass = m_vdencPakonlyMultipassEnabled; |
| |
| m_ref.MHW_SETPAR_F(HCP_VP9_PIC_STATE)(params); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| static inline uint8_t getNumRefFrames(uint8_t frameType, uint8_t numRefFrames) |
| { |
| return (frameType ? numRefFrames : 0); // frame_type == 1 ? NON_KEY_FRAME : KEY_FRAME |
| } |
| |
| static inline bool refIdxEqual(PCODEC_VP9_ENCODE_PIC_PARAMS vp9PicParams) |
| { |
| uint32_t lastRefIdx = vp9PicParams->RefFlags.fields.LastRefIdx; |
| uint32_t altRefIdx = vp9PicParams->RefFlags.fields.AltRefIdx; |
| uint32_t goldenRefIdx = vp9PicParams->RefFlags.fields.GoldenRefIdx; |
| |
| if (lastRefIdx == altRefIdx && altRefIdx == goldenRefIdx) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| static inline bool isTemporalMvpEnabledForTargetUsage(uint8_t targetUsage) |
| { |
| if (TargetUsage::QUALITY == targetUsage) |
| { |
| return false; |
| } |
| return true; |
| } |
| |
| static inline bool isTemporalMvpEnabled(uint8_t targetUsage, uint32_t frameType, uint32_t lastFrameType, PCODEC_VP9_ENCODE_PIC_PARAMS vp9PicParams) |
| { |
| if (false == isTemporalMvpEnabledForTargetUsage(targetUsage) || true == refIdxEqual(vp9PicParams)) |
| { |
| return false; |
| } |
| return frameType && !lastFrameType; // frame_type == 1 ? NON_KEY_FRAME : KEY_FRAME |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| MHW_SETPAR_DECL_SRC(VDENC_CMD1, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| auto settings = static_cast<Vp9VdencFeatureSettings *>(m_constSettings); |
| ENCODE_CHK_NULL_RETURN(settings); |
| |
| for (const auto &lambda : settings->vdencCmd1Settings) |
| { |
| ENCODE_CHK_STATUS_RETURN(lambda(params, false)); |
| } |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(VDENC_SRC_SURFACE_STATE, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| MHW_MI_CHK_NULL(m_vp9SeqParams); |
| MHW_MI_CHK_NULL(m_rawSurfaceToPak); |
| |
| // DW2..5 - DW0 |
| |
| params.width = MOS_ALIGN_CEIL(m_oriFrameWidth, CODEC_VP9_MIN_BLOCK_WIDTH); |
| params.height = MOS_ALIGN_CEIL(m_oriFrameHeight, CODEC_VP9_MIN_BLOCK_HEIGHT); |
| params.displayFormatSwizzle = m_vp9SeqParams->SeqFlags.fields.DisplayFormatSwizzle; |
| |
| // DW2..5 - DW1 |
| |
| params.tileType = m_rawSurfaceToPak->TileType; |
| params.tileModeGmm = m_rawSurfaceToPak->TileModeGMM; |
| params.format = m_rawSurfaceToPak->Format; |
| params.gmmTileEn = m_rawSurfaceToPak->bGMMTileEnabled; |
| params.pitch = m_rawSurfaceToPak->dwPitch; |
| params.chromaDownsampleFilterControl = 7; |
| |
| // DW2..5 - DW2 |
| |
| params.uOffset = m_rawSurfaceToPak->YoffsetForUplane; |
| |
| // DW2..5 - DW3 |
| |
| params.vOffset = m_rawSurfaceToPak->YoffsetForVplane; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(VDENC_DS_REF_SURFACE_STATE, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| MHW_MI_CHK_NULL(m_8xDSSurface); |
| |
| // DW2..5 |
| |
| params.pitchStage1 = m_8xDSSurface->dwPitch; |
| params.tileTypeStage1 = m_8xDSSurface->TileType; |
| params.tileModeGmmStage1 = m_8xDSSurface->TileModeGMM; |
| params.gmmTileEnStage1 = m_8xDSSurface->bGMMTileEnabled; |
| params.uOffsetStage1 = m_8xDSSurface->YoffsetForUplane; |
| params.vOffsetStage1 = m_8xDSSurface->YoffsetForVplane; |
| params.heightStage1 = m_8xDSSurface->dwHeight; |
| params.widthStage1 = m_8xDSSurface->dwWidth; |
| |
| MHW_MI_CHK_NULL(m_4xDSSurface); |
| |
| // DW 6..9 |
| |
| params.pitchStage2 = m_4xDSSurface->dwPitch; |
| params.tileTypeStage2 = m_4xDSSurface->TileType; |
| params.tileModeGmmStage2 = m_4xDSSurface->TileModeGMM; |
| params.gmmTileEnStage2 = m_4xDSSurface->bGMMTileEnabled; |
| params.uOffsetStage2 = m_4xDSSurface->YoffsetForUplane; |
| params.vOffsetStage2 = m_4xDSSurface->YoffsetForVplane; |
| params.heightStage2 = m_4xDSSurface->dwHeight; |
| params.widthStage2 = m_4xDSSurface->dwWidth; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(VDENC_CMD2, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| MHW_MI_CHK_NULL(m_vp9PicParams); |
| auto vp9PicParams = m_vp9PicParams; |
| uint8_t frameType = vp9PicParams->PicFlags.fields.frame_type; // frame_type == 1 ? NON_KEY_FRAME : KEY_FRAME |
| |
| MHW_MI_CHK_NULL(m_vp9SeqParams); |
| uint8_t targetUsage = m_vp9SeqParams->TargetUsage; |
| |
| ENCODE_CHK_COND_RETURN(!TargetUsage::isValid(targetUsage), "TargetUsage is invalid"); |
| |
| uint32_t lastFrameType = m_prevFrameInfo.KeyFrame; // frame_type == 1 ? NON_KEY_FRAME : KEY_FRAME |
| |
| uint8_t numRefFrames = getNumRefFrames(frameType, m_ref.NumRefFrames()); |
| |
| bool segmentationEnabled = vp9PicParams->PicFlags.fields.segmentation_enabled; |
| |
| // DW1 |
| params.width = MOS_ALIGN_CEIL(vp9PicParams->SrcFrameWidthMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH) - 1; // FrameWidthInPixelsMinusOne |
| params.height = MOS_ALIGN_CEIL(vp9PicParams->SrcFrameHeightMinus1 + 1, CODEC_VP9_MIN_BLOCK_WIDTH) - 1; // FrameHeightInPixelsMinusOne |
| |
| // DW2 |
| params.transformSkip = 0; |
| params.temporalMvp = isTemporalMvpEnabled(targetUsage, frameType, lastFrameType, vp9PicParams); |
| params.pictureType = frameType; |
| |
| // DW3 |
| params.pocL1Ref1 = (int8_t)0xfe; // PocNumberForRefid1InL1 |
| params.pocL0Ref1 = (int8_t)0x02; // PocNumberForRefid1InL0 |
| params.pocL1Ref0 = (int8_t)0xff; // BwdPocNumberForRefid0InL1 |
| params.pocL0Ref0 = (int8_t)0x01; // FwdPocNumberForRefid0InL0 |
| |
| // DW4 |
| params.pocL1Ref3 = (int8_t)0xfc; // PocNumberForRefid3InL1 |
| params.pocL0Ref3 = (int8_t)0x04; // PocNumberForRefid3InL0 |
| params.pocL1Ref2 = (int8_t)0xfd; // PocNumberForRefid2InL1 |
| params.pocL0Ref2 = (int8_t)0x03; // PocNumberForRefid2InL0 |
| |
| // DW5 |
| params.numRefL1 = 0; // NumRefIdxL1Minus1 + 1 |
| params.numRefL0 = numRefFrames; // NumRefIdxL0Minus1 + 1 |
| |
| // DW7 |
| params.pakOnlyMultiPass = m_vdencPakonlyMultipassEnabled; |
| params.tiling = (vp9PicParams->log2_tile_columns != 0) || (vp9PicParams->log2_tile_rows != 0); // TilingEnable |
| params.segmentationTemporal = frameType ? m_prevFrameSegEnabled : 0; // SegmentationMapTemporalPredictionEnable |
| params.segmentation = segmentationEnabled; // SegmentationEnable |
| |
| // DW16 |
| params.maxQp = 0xff; // MaxQp |
| params.minQp = 0; // MinQp |
| |
| // DW17 |
| params.temporalMvEnableForIntegerSearch = params.temporalMvp; // TemporalMVEnableForIntegerSearch |
| |
| // DW20 |
| params.intraRefreshMbSizeMinus1 = 0; |
| |
| // DW21 |
| params.qpAdjustmentForRollingI = 0; |
| params.intraRefresh = 0; |
| |
| |
| // DW26 |
| params.vp9DynamicSlice = ((m_ref.DysRefFrameFlags() != DYS_REF_NONE) && !m_dysVdencMultiPassEnabled); |
| |
| // DW27 |
| params.qpPrimeYAc = vp9PicParams->LumaACQIndex; |
| params.qpPrimeYDc = params.qpPrimeYAc + vp9PicParams->LumaDCQIndexDelta; |
| |
| // DW61 |
| params.av1RefId[0][0] = 0; |
| params.av1RefId[0][1] = 0; |
| params.av1RefId[0][2] = 0; |
| params.av1RefId[0][3] = 0; |
| params.av1RefId[1][0] = 0; |
| params.av1RefId[1][1] = 0; |
| params.av1RefId[1][2] = 0; |
| params.av1RefId[1][3] = 0; |
| |
| auto settings = static_cast<Vp9VdencFeatureSettings *>(m_constSettings); |
| ENCODE_CHK_NULL_RETURN(settings); |
| |
| for (const auto &lambda : settings->vdencCmd2Settings) |
| { |
| ENCODE_CHK_STATUS_RETURN(lambda(params, false)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(VDENC_PIPE_MODE_SELECT, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| MHW_MI_CHK_NULL(m_vp9SeqParams); |
| |
| // DW1 |
| |
| params.chromaType = m_vp9SeqParams->SeqFlags.fields.EncodedFormat + 1; |
| |
| params.bitDepthMinus8 = 0; |
| if (m_vp9SeqParams->SeqFlags.fields.EncodedBitDepth == VP9_ENCODED_BIT_DEPTH_10) |
| { |
| params.bitDepthMinus8 = 2; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(VDENC_PIPE_BUF_ADDR_STATE, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| params.surfaceRaw = m_rawSurfaceToPak; |
| params.surfaceDsStage1 = m_8xDSSurface; |
| params.surfaceDsStage2 = m_4xDSSurface; |
| |
| params.streamInBuffer = m_recycleBuf->GetBuffer(RecycleResId::StreamInBuffer, m_frameNum); |
| |
| #ifdef _MMC_SUPPORTED |
| ENCODE_CHK_NULL_RETURN(m_mmcState); |
| |
| if (m_mmcState->IsMmcEnabled()) |
| { |
| params.mmcEnabled = true; |
| ENCODE_CHK_STATUS_RETURN(m_mmcState->GetSurfaceMmcState(const_cast<PMOS_SURFACE>(&m_rawSurface), ¶ms.mmcStateRaw)); |
| } |
| else |
| { |
| params.mmcEnabled = false; |
| params.mmcStateRaw = MOS_MEMCOMP_DISABLED; |
| } |
| #endif |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(MFX_WAIT, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| params.iStallVdboxPipeline = true; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MHW_SETPAR_DECL_SRC(MFX_PIPE_MODE_SELECT, Vp9BasicFeature) |
| { |
| ENCODE_FUNC_CALL(); |
| |
| params.decoderShortFormatMode = 1; |
| |
| if (m_decodeInUse) |
| { |
| params.Mode = CODECHAL_DECODE_MODE_AVCVLD; |
| params.codecSelect = decoderCodec; |
| } |
| else |
| { |
| params.Mode = m_mode; |
| params.codecSelect = encoderCodec; |
| params.vdencMode = 1; |
| params.scaledSurfaceEnable = true; |
| params.frameStatisticsStreamoutEnable = true; |
| } |
| |
| params.standardSelect = CodecHal_GetStandardFromMode(params.Mode); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| } // namespace encode |