| /* |
| * Copyright (c) 2017-2021, Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| //! |
| //! \file codechal_encode_avc_base.cpp |
| //! \brief Defines base class for AVC encoder. |
| //! |
| #include "codechal_encode_avc_base.h" |
| #include "codechal_vdenc_avc.h" |
| #include "codechal_encode_avc.h" |
| #include "codechal_mmc_encode_avc.h" |
| #include "hal_oca_interface.h" |
| |
| #define CODECHAL_ENCODE_AVC_CQP_NUM_OF_PASSES 2 |
| #define CODECHAL_ENCODE_AVC_ICQ_NUM_OF_PASSES 2 |
| #define CODECHAL_ENCODE_AVC_EXTENDED_SAR 255 |
| |
| const uint8_t CODECHAL_ENCODE_AVC_SFD_CostTable_P_FRAME[CODEC_AVC_NUM_QP] = |
| { |
| 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 60, 60, 60, 60, 73, 73, 73, 76, 76, 76, 88, 89, 89, 91, 92, 93, 104, 104, 106, 107, 108, 109, 120, 120, 122, 123, 124, 125, 136, 136, 138, 139, 140, 141, 143, 143}; |
| |
| const uint8_t CODECHAL_ENCODE_AVC_SFD_CostTable_B_FRAME[CODEC_AVC_NUM_QP] = |
| { |
| 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 73, 73, 73, 73, 77, 77, 77, 89, 89, 89, 91, 93, 93, 95, 105, 106, 107, 108, 110, 111, 121, 122, 123, 124, 125, 127, 137, 138, 139, 140, 142, 143, 143, 143, 143, 143}; |
| |
| uint32_t CodecHalAvcEncode_GetMaxVmvR(uint8_t levelIdc) |
| { |
| int maxVmvR = 128 * 4; |
| |
| // See JVT Spec Annex A Table A-1 Level limits for below mapping |
| // maxVmvR is in luma quarter pel unit |
| switch (levelIdc) |
| { |
| case CODEC_AVC_LEVEL_1: |
| case CODEC_AVC_LEVEL_1b: |
| maxVmvR = 64 * 4; |
| break; |
| case CODEC_AVC_LEVEL_11: |
| case CODEC_AVC_LEVEL_12: |
| case CODEC_AVC_LEVEL_13: |
| case CODEC_AVC_LEVEL_2: |
| maxVmvR = 128 * 4; |
| break; |
| case CODEC_AVC_LEVEL_21: |
| case CODEC_AVC_LEVEL_22: |
| case CODEC_AVC_LEVEL_3: |
| maxVmvR = 256 * 4; |
| break; |
| case CODEC_AVC_LEVEL_31: |
| case CODEC_AVC_LEVEL_32: |
| case CODEC_AVC_LEVEL_4: |
| case CODEC_AVC_LEVEL_41: |
| case CODEC_AVC_LEVEL_42: |
| case CODEC_AVC_LEVEL_5: |
| case CODEC_AVC_LEVEL_51: |
| case CODEC_AVC_LEVEL_52: |
| maxVmvR = 512 * 4; |
| break; |
| default: |
| CODECHAL_ENCODE_NORMALMESSAGE("Unsupported LevelIDC setting."); |
| CODECHAL_ENCODE_ASSERT(false); |
| break; |
| } |
| |
| return maxVmvR; |
| } |
| |
| uint32_t CodecHalAvcEncode_GetMaxMvLen(uint8_t levelIdc) |
| { |
| int maxMvLen = 127; |
| |
| // See JVT Spec Annex A Table A-1 Level limits for below mapping |
| // MaxVmvR is in luma quarter pel unit |
| switch (levelIdc) |
| { |
| case CODEC_AVC_LEVEL_1: |
| case CODEC_AVC_LEVEL_1b: |
| maxMvLen = 63; |
| break; |
| case CODEC_AVC_LEVEL_11: |
| case CODEC_AVC_LEVEL_12: |
| case CODEC_AVC_LEVEL_13: |
| case CODEC_AVC_LEVEL_2: |
| maxMvLen = 127; |
| break; |
| case CODEC_AVC_LEVEL_21: |
| case CODEC_AVC_LEVEL_22: |
| case CODEC_AVC_LEVEL_3: |
| maxMvLen = 255; |
| break; |
| case CODEC_AVC_LEVEL_31: |
| case CODEC_AVC_LEVEL_32: |
| case CODEC_AVC_LEVEL_4: |
| case CODEC_AVC_LEVEL_41: |
| case CODEC_AVC_LEVEL_42: |
| case CODEC_AVC_LEVEL_5: |
| case CODEC_AVC_LEVEL_51: |
| case CODEC_AVC_LEVEL_52: |
| maxMvLen = 511; |
| break; |
| default: |
| CODECHAL_ENCODE_NORMALMESSAGE("Unsupported LevelIDC setting."); |
| CODECHAL_ENCODE_ASSERT(false); |
| break; |
| } |
| |
| return maxMvLen; |
| } |
| |
| bool CodecHalAvcEncode_GetFieldParity( |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams, |
| uint32_t list, |
| uint32_t index) |
| { |
| uint32_t fieldParity = 0; |
| |
| if (slcParams == nullptr) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Invalid (NULL) Pointer."); |
| return false; |
| } |
| CODECHAL_ENCODE_ASSERT(list == LIST_0 || list == LIST_1); |
| CODECHAL_ENCODE_ASSERT(index < CODEC_AVC_MAX_NUM_REF_FRAME * 2); |
| |
| if (!CodecHal_PictureIsInvalid(slcParams->RefPicList[list][index])) |
| { |
| fieldParity = CodecHal_PictureIsBottomField(slcParams->RefPicList[list][index]); |
| } |
| |
| return (fieldParity ? true : false); |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::SendSlice( |
| PMOS_COMMAND_BUFFER cmdBuffer, |
| PMHW_VDBOX_AVC_SLICE_STATE params) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS avcSlcParams; |
| MHW_VDBOX_AVC_REF_IDX_PARAMS refIdxParams; |
| MHW_VDBOX_AVC_WEIGHTOFFSET_PARAMS weightOffsetParams; |
| MHW_BATCH_BUFFER secondLevelBatchBuffer; |
| MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams; |
| MHW_VDBOX_VDENC_WALKER_STATE_PARAMS vdencWalkerStateParams; |
| PMOS_COMMAND_BUFFER cmdBufferInUse; |
| PMHW_BATCH_BUFFER batchBufferInUse; |
| uint32_t bitSize, offSet; |
| uint32_t maxBytesInPakInsertObjCmd; |
| uint32_t nalunitPosiSize, nalunitPosiOffset; |
| bool insertZeroByteWA = false; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcPicIdx); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->presDataBuffer); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeAvcSeqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeAvcPicParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pEncodeAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNalUnitParams); |
| |
| avcSlcParams = params->pEncodeAvcSliceParams; |
| maxBytesInPakInsertObjCmd = ((2 << 11) - 1) * 4; // 12 bits for DwordLength field in PAK_INSERT_OBJ cmd |
| nalunitPosiSize = 0; |
| nalunitPosiOffset = 0; |
| |
| // VDENC does not use batch buffer for slice state |
| if (params->bSingleTaskPhaseSupported && !params->bVdencInUse) |
| { |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBatchBufferForPakSlices); |
| batchBufferInUse = params->pBatchBufferForPakSlices; |
| cmdBufferInUse = nullptr; |
| } |
| else |
| { |
| batchBufferInUse = nullptr; |
| cmdBufferInUse = cmdBuffer; |
| } |
| |
| // Add reference index and weight offset commands |
| refIdxParams.CurrPic = params->pEncodeAvcPicParams->CurrReconstructedPic; |
| refIdxParams.isEncode = true; |
| refIdxParams.bVdencInUse = params->bVdencInUse; |
| refIdxParams.pAvcPicIdx = params->pAvcPicIdx; |
| refIdxParams.avcRefList = (void **)m_refList; |
| refIdxParams.oneOnOneMapping = params->oneOnOneMapping; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( |
| &refIdxParams.RefPicList, |
| 2 * 32 * sizeof(CODEC_PICTURE), |
| avcSlcParams->RefPicList, |
| 2 * 32 * sizeof(CODEC_PICTURE))); |
| if (Slice_Type[avcSlcParams->slice_type] == SLICE_P) |
| { |
| refIdxParams.uiList = LIST_0; |
| refIdxParams.uiNumRefForList[LIST_0] = avcSlcParams->num_ref_idx_l0_active_minus1 + 1; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBufferInUse, batchBufferInUse, &refIdxParams)); |
| |
| if (params->pEncodeAvcPicParams->weighted_pred_flag == EXPLICIT_WEIGHTED_INTER_PRED_MODE) |
| { |
| weightOffsetParams.uiList = LIST_0; |
| weightOffsetParams.uiLumaLogWeightDenom = avcSlcParams->luma_log2_weight_denom; |
| weightOffsetParams.uiChromaLogWeightDenom = avcSlcParams->chroma_log2_weight_denom; |
| weightOffsetParams.uiLumaWeightFlag = avcSlcParams->luma_weight_flag[LIST_0]; |
| weightOffsetParams.uiChromaWeightFlag = avcSlcParams->chroma_weight_flag[LIST_0]; |
| weightOffsetParams.uiNumRefForList = avcSlcParams->num_ref_idx_l0_active_minus1 + 1; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( |
| &weightOffsetParams.Weights, |
| sizeof(weightOffsetParams.Weights), |
| &avcSlcParams->Weights, |
| sizeof(avcSlcParams->Weights))); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset( |
| cmdBufferInUse, |
| batchBufferInUse, |
| &weightOffsetParams)); |
| } |
| } |
| |
| else if (Slice_Type[avcSlcParams->slice_type] == SLICE_B) |
| { |
| refIdxParams.uiList = LIST_0; |
| refIdxParams.uiNumRefForList[LIST_0] = avcSlcParams->num_ref_idx_l0_active_minus1 + 1; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBufferInUse, batchBufferInUse, &refIdxParams)); |
| |
| refIdxParams.uiList = LIST_1; |
| refIdxParams.uiNumRefForList[LIST_1] = avcSlcParams->num_ref_idx_l1_active_minus1 + 1; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcRefIdx(cmdBufferInUse, batchBufferInUse, &refIdxParams)); |
| |
| if (params->pEncodeAvcPicParams->weighted_bipred_idc == EXPLICIT_WEIGHTED_INTER_PRED_MODE) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( |
| &weightOffsetParams.Weights, |
| sizeof(weightOffsetParams.Weights), |
| &avcSlcParams->Weights, |
| sizeof(avcSlcParams->Weights))); |
| weightOffsetParams.uiList = LIST_0; |
| weightOffsetParams.uiLumaLogWeightDenom = avcSlcParams->luma_log2_weight_denom; |
| weightOffsetParams.uiChromaLogWeightDenom = avcSlcParams->chroma_log2_weight_denom; |
| weightOffsetParams.uiLumaWeightFlag = avcSlcParams->luma_weight_flag[LIST_0]; |
| weightOffsetParams.uiChromaWeightFlag = avcSlcParams->chroma_weight_flag[LIST_0]; |
| weightOffsetParams.uiNumRefForList = avcSlcParams->num_ref_idx_l0_active_minus1 + 1; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset( |
| cmdBufferInUse, |
| batchBufferInUse, |
| &weightOffsetParams)); |
| |
| weightOffsetParams.uiList = LIST_1; |
| weightOffsetParams.uiLumaLogWeightDenom = avcSlcParams->luma_log2_weight_denom; |
| weightOffsetParams.uiChromaLogWeightDenom = avcSlcParams->chroma_log2_weight_denom; |
| weightOffsetParams.uiLumaWeightFlag = avcSlcParams->luma_weight_flag[LIST_1]; |
| weightOffsetParams.uiChromaWeightFlag = avcSlcParams->chroma_weight_flag[LIST_1]; |
| weightOffsetParams.uiNumRefForList = avcSlcParams->num_ref_idx_l1_active_minus1 + 1; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcWeightOffset( |
| cmdBufferInUse, |
| batchBufferInUse, |
| &weightOffsetParams)); |
| } |
| } |
| |
| // add AVC Slice state commands |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxAvcSlice(cmdBufferInUse, batchBufferInUse, params)); |
| |
| //insert AU, SPS, PSP headers before first slice header |
| if (params->bInsertBeforeSliceHeaders) |
| { |
| uint8_t *dataBase = (uint8_t *)(params->pBsBuffer->pBase); |
| uint32_t data = ((*dataBase) << 24) + ((*(dataBase + 1)) << 16) + ((*(dataBase + 2)) << 8) + (*(dataBase + 3)); |
| // Only apply the WaSuperSliceHeaderPacking for the cases with 00 00 00 01 start code |
| if (data == 0x00000001) |
| { |
| insertZeroByteWA = true; |
| } |
| |
| bool isInsert; |
| uint32_t i; |
| for (i = 0; i < CODECHAL_ENCODE_AVC_MAX_NAL_TYPE; i++) |
| { |
| nalunitPosiSize = params->ppNalUnitParams[i]->uiSize; |
| nalunitPosiOffset = params->ppNalUnitParams[i]->uiOffset; |
| while (nalunitPosiSize > 0) |
| { |
| isInsert = params->ppNalUnitParams[i]->bInsertEmulationBytes; |
| bitSize = MOS_MIN(maxBytesInPakInsertObjCmd * 8, nalunitPosiSize * 8); |
| offSet = nalunitPosiOffset; |
| |
| MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams)); |
| pakInsertObjectParams.bEmulationByteBitsInsert = isInsert; |
| pakInsertObjectParams.uiSkipEmulationCheckCount = params->ppNalUnitParams[i]->uiSkipEmulationCheckCount; |
| pakInsertObjectParams.pBsBuffer = params->pBsBuffer; |
| pakInsertObjectParams.dwBitSize = bitSize; |
| pakInsertObjectParams.dwOffset = offSet; |
| pakInsertObjectParams.bHeaderLengthExcludeFrmSize = true; // Exclude header length from size calculation for accurate Cabac Zero Word Insertion |
| |
| if (pakInsertObjectParams.bEmulationByteBitsInsert) |
| { |
| CODECHAL_ENCODE_VERBOSEMESSAGE("The emulation prevention bytes are not inserted by the app and are requested to be inserted by HW."); |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPakInsertObject( |
| cmdBufferInUse, batchBufferInUse, &pakInsertObjectParams)); |
| |
| if (nalunitPosiSize > maxBytesInPakInsertObjCmd) |
| { |
| nalunitPosiSize -= maxBytesInPakInsertObjCmd; |
| nalunitPosiOffset += maxBytesInPakInsertObjCmd; |
| } |
| else |
| { |
| nalunitPosiSize = 0; |
| } |
| |
| insertZeroByteWA = false; |
| } |
| } |
| } |
| |
| uint8_t *dataBase = (uint8_t *)(params->pBsBuffer->pBase + params->dwOffset); |
| uint32_t data = ((*dataBase) << 24) + ((*(dataBase + 1)) << 16) + ((*(dataBase + 2)) << 8) + (*(dataBase + 3)); |
| |
| if (data == 0x00000001) |
| { |
| insertZeroByteWA = true; |
| } |
| |
| // Insert 0x00 for super slice case when PPS/AUD is not inserted |
| if (MEDIA_IS_WA(m_hwInterface->GetWaTable(), WaSuperSliceHeaderPacking) && insertZeroByteWA && params->bVdencInUse && m_hwInterface->m_isVdencSuperSliceEnabled) |
| { |
| MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams)); |
| pakInsertObjectParams.pBsBuffer = params->pBsBuffer; |
| pakInsertObjectParams.dwBitSize = 8; |
| pakInsertObjectParams.dwOffset = params->dwOffset; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPakInsertObject( |
| cmdBufferInUse, batchBufferInUse, &pakInsertObjectParams)); |
| } |
| |
| // Insert slice header |
| MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams)); |
| pakInsertObjectParams.bLastHeader = true; |
| pakInsertObjectParams.bEmulationByteBitsInsert = true; |
| |
| if (params->bAcceleratorHeaderPackingCaps) |
| { |
| // If driver does slice header packing set the skip count to 4 |
| pakInsertObjectParams.uiSkipEmulationCheckCount = 4; |
| } |
| else |
| { |
| // App does the slice header packing, set the skip count passed by the app |
| pakInsertObjectParams.uiSkipEmulationCheckCount = params->uiSkipEmulationCheckCount; |
| } |
| pakInsertObjectParams.pBsBuffer = params->pBsBuffer; |
| // Slice Header Indicator should be set for VDENC for multi-slice case |
| pakInsertObjectParams.bSliceHeaderIndicator = (!params->bVdencInUse) ? false : true; |
| |
| // Remove one byte of 00 for super slice case when PPS/AUD is not inserted, so that HW could patch slice header correctly |
| if (MEDIA_IS_WA(m_hwInterface->GetWaTable(), WaSuperSliceHeaderPacking) && insertZeroByteWA && params->bVdencInUse && m_hwInterface->m_isVdencSuperSliceEnabled) |
| { |
| pakInsertObjectParams.dwBitSize = params->dwLength - 8; |
| pakInsertObjectParams.dwOffset = params->dwOffset + 1; |
| } |
| else |
| { |
| pakInsertObjectParams.dwBitSize = params->dwLength; |
| pakInsertObjectParams.dwOffset = params->dwOffset; |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPakInsertObject( |
| cmdBufferInUse, batchBufferInUse, &pakInsertObjectParams)); |
| |
| if (params->bVdencInUse) |
| { |
| //For CNL VDENC Walker command and WeightsOffsets cmds are sent per Super slice |
| if (m_hwInterface->m_isVdencSuperSliceEnabled) |
| { |
| weightOffsetParams.pAvcPicParams = params->pEncodeAvcPicParams; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdencAvcWeightsOffsetsStateCmd(cmdBuffer, &weightOffsetParams)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdencSliceStateCmd(cmdBuffer, params)); |
| |
| vdencWalkerStateParams.Mode = CODECHAL_ENCODE_MODE_AVC; |
| vdencWalkerStateParams.slcIdx = params->dwSliceIndex; |
| vdencWalkerStateParams.pAvcSeqParams = params->pEncodeAvcSeqParams; |
| vdencWalkerStateParams.pAvcPicParams = params->pEncodeAvcPicParams; |
| vdencWalkerStateParams.pAvcSlcParams = avcSlcParams; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_vdencInterface->AddVdencWalkerStateCmd(cmdBuffer, &vdencWalkerStateParams)); |
| } |
| } |
| else |
| { |
| if (params->bSingleTaskPhaseSupported) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, batchBufferInUse)); |
| |
| // Insert Batch Buffer Start command to send AVC_PAK_OBJ data for MBs in this slice |
| MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER)); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(batchBufferInUse); |
| secondLevelBatchBuffer.OsResource = batchBufferInUse->OsResource; |
| secondLevelBatchBuffer.dwOffset = params->dwBatchBufferForPakSlicesStartOffset; |
| secondLevelBatchBuffer.bSecondLevel = true; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer)); |
| } |
| |
| // Insert Batch Buffer Start command to send AVC_PAK_OBJ data for MBs in this slice |
| MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER)); |
| secondLevelBatchBuffer.OsResource = *params->presDataBuffer; |
| secondLevelBatchBuffer.dwOffset = params->dwDataBufferOffset; |
| secondLevelBatchBuffer.bSecondLevel = true; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| static int32_t GetMaxMBPS(uint8_t levelIdc) |
| { |
| int maxMBPS = 11880; |
| |
| // See JVT Spec Annex A Table A-1 Level limits for below mapping |
| // maxMBPS is in MB/s |
| switch (levelIdc) |
| { |
| case CODEC_AVC_LEVEL_1: |
| case CODEC_AVC_LEVEL_1b: |
| maxMBPS = 1485; |
| break; |
| case CODEC_AVC_LEVEL_11: |
| maxMBPS = 3000; |
| break; |
| case CODEC_AVC_LEVEL_12: |
| maxMBPS = 6000; |
| break; |
| case CODEC_AVC_LEVEL_13: |
| case CODEC_AVC_LEVEL_2: |
| maxMBPS = 11880; |
| break; |
| case CODEC_AVC_LEVEL_21: |
| maxMBPS = 19800; |
| break; |
| case CODEC_AVC_LEVEL_22: |
| maxMBPS = 20250; |
| break; |
| case CODEC_AVC_LEVEL_3: |
| maxMBPS = 40500; |
| break; |
| case CODEC_AVC_LEVEL_31: |
| maxMBPS = 108000; |
| break; |
| case CODEC_AVC_LEVEL_32: |
| maxMBPS = 216000; |
| break; |
| case CODEC_AVC_LEVEL_4: |
| case CODEC_AVC_LEVEL_41: |
| maxMBPS = 245760; |
| break; |
| case CODEC_AVC_LEVEL_42: |
| maxMBPS = 522240; |
| break; |
| case CODEC_AVC_LEVEL_5: |
| maxMBPS = 589824; |
| break; |
| case CODEC_AVC_LEVEL_51: |
| maxMBPS = 983040; |
| break; |
| case CODEC_AVC_LEVEL_52: |
| maxMBPS = 2073600; |
| break; |
| default: |
| maxMBPS = 0; |
| break; |
| } |
| |
| return maxMBPS; |
| } |
| |
| MOS_STATUS CodecHalAvcEncode_GetProfileLevelMaxFrameSize( |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams, |
| CodechalEncoderState * encoder, |
| uint32_t * pdwProfileLevelMaxFrame) |
| { |
| double bitsPerMB, tmpf; |
| int32_t iMaxMBPS, numMBPerFrame, minCR; |
| uint64_t maxBytePerPic, maxBytePerPicNot0; |
| uint32_t profileLevelMaxFrame, userMaxFrameSize; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| double frameRateD = 100; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(seqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(encoder); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(pdwProfileLevelMaxFrame); |
| |
| minCR = 4; |
| |
| if (seqParams->Level >= CODEC_AVC_LEVEL_31 && seqParams->Level <= CODEC_AVC_LEVEL_4) |
| { |
| bitsPerMB = 96; |
| } |
| else |
| { |
| bitsPerMB = 192; |
| minCR = 2; |
| } |
| |
| iMaxMBPS = GetMaxMBPS(seqParams->Level); |
| if (!iMaxMBPS) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported LevelIDC setting."); |
| return MOS_STATUS_UNKNOWN; |
| } |
| |
| numMBPerFrame = encoder->m_picWidthInMb * encoder->m_frameFieldHeightInMb; |
| |
| tmpf = (double)numMBPerFrame; |
| if (tmpf < iMaxMBPS / 172.) |
| { |
| tmpf = iMaxMBPS / 172.; |
| } |
| |
| maxBytePerPic = (uint64_t)(tmpf * bitsPerMB); |
| maxBytePerPicNot0 = |
| (uint64_t)((((double)iMaxMBPS * frameRateD) / |
| (double)seqParams->FramesPer100Sec) * |
| bitsPerMB); |
| userMaxFrameSize = seqParams->UserMaxFrameSize; |
| |
| if ((encoder->m_pictureCodingType != I_TYPE) && (seqParams->UserMaxPBFrameSize > 0)) |
| { |
| userMaxFrameSize = seqParams->UserMaxPBFrameSize; |
| } |
| |
| if (userMaxFrameSize != 0) |
| { |
| profileLevelMaxFrame = (uint32_t)MOS_MIN(userMaxFrameSize, maxBytePerPic); |
| profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, profileLevelMaxFrame); |
| } |
| else |
| { |
| profileLevelMaxFrame = (uint32_t)MOS_MIN(maxBytePerPicNot0, maxBytePerPic); |
| } |
| |
| // minCR related changes are added to match hardware behavior |
| if (encoder->m_vdencEnabled) |
| { |
| *pdwProfileLevelMaxFrame = (uint32_t)MOS_MIN((encoder->m_frameHeight * encoder->m_frameHeight), profileLevelMaxFrame); |
| } |
| else |
| { |
| *pdwProfileLevelMaxFrame = (uint32_t)MOS_MIN(encoder->m_frameHeight * encoder->m_frameWidth * 3 / (2 * minCR), profileLevelMaxFrame); |
| } |
| |
| return eStatus; |
| } |
| |
| static void PutVLCCode(BSBuffer *bsbuffer, uint32_t code) |
| { |
| uint8_t leadingZeroBits, bitcount; |
| uint32_t code1, bits; |
| |
| code1 = code + 1; |
| bitcount = 0; |
| while (code1) |
| { |
| code1 >>= 1; |
| bitcount++; |
| } |
| |
| if (bitcount == 1) |
| { |
| PutBit(bsbuffer, 1); |
| } |
| else |
| { |
| leadingZeroBits = bitcount - 1; |
| bits = code + 1 - (1 << leadingZeroBits); |
| PutBits(bsbuffer, 1, leadingZeroBits + 1); |
| PutBits(bsbuffer, bits, leadingZeroBits); |
| } |
| } |
| |
| //! |
| //! \brief Pack HRD data |
| //! |
| //! \param [in] params |
| //! Pointer to codechal encode Avc pack picture header parameter |
| //! |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if call success, else fail reason |
| //! |
| MOS_STATUS CodecHal_PackPictureHeader_HrdParams( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| PCODECHAL_ENCODE_AVC_VUI_PARAMS vuiParams; |
| PBSBuffer bsbuffer; |
| int schedSelIdx; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| |
| vuiParams = params->pAvcVuiParams; |
| bsbuffer = params->pBsBuffer; |
| |
| PutVLCCode(bsbuffer, vuiParams->cpb_cnt_minus1); |
| PutBits(bsbuffer, vuiParams->bit_rate_scale, 4); |
| PutBits(bsbuffer, vuiParams->cpb_size_scale, 4); |
| |
| for (schedSelIdx = 0; schedSelIdx <= vuiParams->cpb_cnt_minus1; schedSelIdx++) |
| { |
| PutVLCCode(bsbuffer, vuiParams->bit_rate_value_minus1[schedSelIdx]); |
| PutVLCCode(bsbuffer, vuiParams->cpb_size_value_minus1[schedSelIdx]); |
| PutBit(bsbuffer, ((vuiParams->cbr_flag >> schedSelIdx) & 1)); |
| } |
| |
| PutBits(bsbuffer, vuiParams->initial_cpb_removal_delay_length_minus1, 5); |
| PutBits(bsbuffer, vuiParams->cpb_removal_delay_length_minus1, 5); |
| PutBits(bsbuffer, vuiParams->dpb_output_delay_length_minus1, 5); |
| PutBits(bsbuffer, vuiParams->time_offset_length, 5); |
| |
| return eStatus; |
| } |
| |
| static void PackScalingList(BSBuffer *bsbuffer, uint8_t *scalingList, uint8_t sizeOfScalingList) |
| { |
| uint8_t lastScale, nextScale, j; |
| char delta_scale; |
| |
| lastScale = nextScale = 8; |
| |
| for (j = 0; j < sizeOfScalingList; j++) |
| { |
| if (nextScale != 0) |
| { |
| delta_scale = (char)(scalingList[j] - lastScale); |
| |
| PutVLCCode(bsbuffer, SIGNED(delta_scale)); |
| |
| nextScale = scalingList[j]; |
| } |
| lastScale = (nextScale == 0) ? lastScale : nextScale; |
| } |
| } |
| |
| //! |
| //! \brief Pack VUI data |
| //! |
| //! \param [in] params |
| //! Pointer to codechal encode Avc pack picture header parameter |
| //! |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if call success, else fail reason |
| //! |
| MOS_STATUS CodecHal_PackPictureHeader_VuiParams( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| PCODECHAL_ENCODE_AVC_VUI_PARAMS vuiParams; |
| PBSBuffer bsbuffer; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcVuiParams); |
| |
| vuiParams = params->pAvcVuiParams; |
| bsbuffer = params->pBsBuffer; |
| |
| PutBit(bsbuffer, vuiParams->aspect_ratio_info_present_flag); |
| if (vuiParams->aspect_ratio_info_present_flag) |
| { |
| PutBits(bsbuffer, vuiParams->aspect_ratio_idc, 8); |
| if (vuiParams->aspect_ratio_idc == CODECHAL_ENCODE_AVC_EXTENDED_SAR) |
| { |
| PutBits(bsbuffer, vuiParams->sar_width, 16); |
| PutBits(bsbuffer, vuiParams->sar_height, 16); |
| } |
| } |
| |
| PutBit(bsbuffer, vuiParams->overscan_info_present_flag); |
| if (vuiParams->overscan_info_present_flag) |
| { |
| PutBit(bsbuffer, vuiParams->overscan_appropriate_flag); |
| } |
| |
| PutBit(bsbuffer, vuiParams->video_signal_type_present_flag); |
| if (vuiParams->video_signal_type_present_flag) |
| { |
| PutBits(bsbuffer, vuiParams->video_format, 3); |
| PutBit(bsbuffer, vuiParams->video_full_range_flag); |
| PutBit(bsbuffer, vuiParams->colour_description_present_flag); |
| if (vuiParams->colour_description_present_flag) |
| { |
| PutBits(bsbuffer, vuiParams->colour_primaries, 8); |
| PutBits(bsbuffer, vuiParams->transfer_characteristics, 8); |
| PutBits(bsbuffer, vuiParams->matrix_coefficients, 8); |
| } |
| } |
| |
| PutBit(bsbuffer, vuiParams->chroma_loc_info_present_flag); |
| if (vuiParams->chroma_loc_info_present_flag) |
| { |
| PutVLCCode(bsbuffer, vuiParams->chroma_sample_loc_type_top_field); |
| PutVLCCode(bsbuffer, vuiParams->chroma_sample_loc_type_bottom_field); |
| } |
| |
| PutBit(bsbuffer, vuiParams->timing_info_present_flag); |
| if (vuiParams->timing_info_present_flag) |
| { |
| PutBits(bsbuffer, vuiParams->num_units_in_tick, 32); |
| PutBits(bsbuffer, vuiParams->time_scale, 32); |
| PutBit(bsbuffer, vuiParams->fixed_frame_rate_flag); |
| } |
| |
| PutBit(bsbuffer, vuiParams->nal_hrd_parameters_present_flag); |
| if (vuiParams->nal_hrd_parameters_present_flag) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_HrdParams(params)); |
| } |
| |
| PutBit(bsbuffer, vuiParams->vcl_hrd_parameters_present_flag); |
| if (vuiParams->vcl_hrd_parameters_present_flag) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_HrdParams(params)); |
| } |
| |
| if (vuiParams->nal_hrd_parameters_present_flag || vuiParams->vcl_hrd_parameters_present_flag) |
| { |
| PutBit(bsbuffer, vuiParams->low_delay_hrd_flag); |
| } |
| |
| PutBit(bsbuffer, vuiParams->pic_struct_present_flag); |
| PutBit(bsbuffer, vuiParams->bitstream_restriction_flag); |
| if (vuiParams->bitstream_restriction_flag) |
| { |
| PutBit(bsbuffer, vuiParams->motion_vectors_over_pic_boundaries_flag); |
| PutVLCCode(bsbuffer, vuiParams->max_bytes_per_pic_denom); |
| PutVLCCode(bsbuffer, vuiParams->max_bits_per_mb_denom); |
| PutVLCCode(bsbuffer, vuiParams->log2_max_mv_length_horizontal); |
| PutVLCCode(bsbuffer, vuiParams->log2_max_mv_length_vertical); |
| PutVLCCode(bsbuffer, vuiParams->num_reorder_frames); |
| PutVLCCode(bsbuffer, vuiParams->max_dec_frame_buffering); |
| } |
| |
| return eStatus; |
| } |
| |
| static void SetNalUnit(uint8_t **bsbuffer, uint8_t refIDC, CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalType) |
| { |
| uint8_t *byte = *bsbuffer; |
| |
| // for SPS and PPS NAL units zero_byte should exist |
| if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_SPS || nalType == CODECHAL_ENCODE_AVC_NAL_UT_PPS || nalType == CODECHAL_ENCODE_AVC_NAL_UT_AUD) |
| { |
| *byte++ = 0; |
| } |
| |
| *byte++ = 0; |
| *byte++ = 0; |
| *byte++ = 1; |
| *byte++ = (uint8_t)((refIDC << 5) | nalType); |
| *byte = 0; // Clear the next byte |
| *bsbuffer = byte; |
| } |
| |
| static void SetTrailingBits(BSBuffer *bsbuffer) |
| { |
| // Write Stop Bit |
| PutBits(bsbuffer, 1, 1); |
| // Make byte aligned |
| while (bsbuffer->BitOffset) |
| { |
| PutBit(bsbuffer, 0); |
| } |
| } |
| |
| static void CodecHal_PackSliceHeader_SetInitialRefPicList( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PCODEC_REF_LIST * refList; |
| CODEC_PIC_REORDER * picOrder, pTempPicOrder[32]; |
| CODEC_PICTURE picture; |
| uint8_t i, j, botField; |
| uint32_t picNum, picOC; |
| uint8_t topIdx, botIdx, listSize; |
| uint32_t defaultPicNumOrder[32]; |
| bool reorder; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params->pAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params->ppRefList); |
| |
| slcParams = params->pAvcSliceParams; |
| refList = params->ppRefList; |
| reorder = false; |
| topIdx = 0; |
| botIdx = 0; |
| listSize = 0; |
| |
| if (params->wPictureCodingType == P_TYPE) |
| { |
| CodecHal_PackSliceHeader_GetPicNum(params, 0); // list 0 |
| picOrder = &slcParams->PicOrder[0][0]; |
| // Save the default pic order. |
| for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++) |
| { |
| defaultPicNumOrder[i] = picOrder[i].PicNum; |
| } |
| for (i = 1; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++) |
| { |
| picNum = picOrder[i].PicNum; |
| picture = picOrder[i].Picture; |
| picOC = picOrder[i].POC; |
| j = i; |
| while ((j > 0) && (picOrder[j - 1].PicNum < picNum)) |
| { |
| picOrder[j].PicNum = picOrder[j - 1].PicNum; |
| picOrder[j].Picture = picOrder[j - 1].Picture; |
| picOrder[j].POC = picOrder[j - 1].POC; |
| j--; |
| reorder = true; |
| } |
| picOrder[j].PicNum = picNum; |
| picOrder[j].Picture = picture; |
| picOrder[j].POC = picOC; |
| } |
| |
| // Sort picOrder[] based on polarity in field case |
| if (CodecHal_PictureIsTopField(params->CurrPic)) |
| { |
| while ((topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)) || |
| (botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1))) |
| { |
| for (; topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); topIdx++) |
| { |
| if (CodecHal_PictureIsTopField(picOrder[topIdx].Picture)) //TOP_FIELD |
| { |
| pTempPicOrder[listSize].PicNum = picOrder[topIdx].PicNum; |
| pTempPicOrder[listSize].Picture = picOrder[topIdx].Picture; |
| pTempPicOrder[listSize].POC = picOrder[topIdx].POC; |
| listSize++; |
| topIdx++; |
| break; |
| } |
| } |
| for (; botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); botIdx++) |
| { |
| if (CodecHal_PictureIsBottomField(picOrder[botIdx].Picture)) //BOTTOM_FIELD |
| { |
| pTempPicOrder[listSize].PicNum = picOrder[botIdx].PicNum; |
| pTempPicOrder[listSize].Picture = picOrder[botIdx].Picture; |
| pTempPicOrder[listSize].POC = picOrder[botIdx].POC; |
| listSize++; |
| botIdx++; |
| break; |
| } |
| } |
| } |
| } |
| if (CodecHal_PictureIsBottomField(params->CurrPic)) |
| { |
| while ((topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1)) || |
| (botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1))) |
| { |
| for (; botIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); botIdx++) |
| { |
| if (CodecHal_PictureIsBottomField(picOrder[botIdx].Picture)) //BOTTOM_FIELD |
| { |
| pTempPicOrder[listSize].PicNum = picOrder[botIdx].PicNum; |
| pTempPicOrder[listSize].Picture = picOrder[botIdx].Picture; |
| pTempPicOrder[listSize].POC = picOrder[botIdx].POC; |
| listSize++; |
| botIdx++; |
| break; |
| } |
| } |
| for (; topIdx < (slcParams->num_ref_idx_l0_active_minus1 + 1); topIdx++) |
| { |
| if (CodecHal_PictureIsTopField(picOrder[topIdx].Picture)) //TOP_FIELD |
| { |
| pTempPicOrder[listSize].PicNum = picOrder[topIdx].PicNum; |
| pTempPicOrder[listSize].Picture = picOrder[topIdx].Picture; |
| pTempPicOrder[listSize].POC = picOrder[topIdx].POC; |
| listSize++; |
| topIdx++; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (!CodecHal_PictureIsFrame(params->CurrPic)) |
| { |
| listSize = MOS_MIN(listSize, 32); |
| // Copy temp array back to picOrder[] |
| for (i = 0; i < listSize; i++) |
| { |
| picOrder[i].PicNum = pTempPicOrder[i].PicNum; |
| picOrder[i].Picture = pTempPicOrder[i].Picture; |
| picOrder[i].POC = pTempPicOrder[i].POC; |
| } |
| |
| // Check if picOrder[] has been shuffled compared to the original list |
| reorder = false; |
| for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++) |
| { |
| if (defaultPicNumOrder[i] != picOrder[i].PicNum) |
| { |
| reorder = true; |
| break; |
| } |
| } |
| } |
| |
| if (reorder) |
| { |
| slcParams->ref_pic_list_reordering_flag_l0 = 1; |
| } |
| else |
| { |
| slcParams->ref_pic_list_reordering_flag_l0 = 0; |
| } |
| for (i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++) |
| { |
| botField = (CodecHal_PictureIsBottomField(picOrder[i].Picture)) ? 1 : 0; |
| refList[picOrder[i].Picture.FrameIdx]->ucInitialIdx[0][botField] = i; |
| } |
| } |
| if (params->wPictureCodingType == B_TYPE) |
| { |
| } |
| |
| return; |
| } |
| |
| static void CodecHal_PackSliceHeader_GetPicNum( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params, |
| uint8_t list) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PCODEC_REF_LIST * refList; |
| uint32_t frameNum, frameNumWrap, picNum; |
| uint8_t i, botField, size; |
| CODEC_PICTURE picture; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params->pAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_NO_STATUS_RETURN(params->ppRefList); |
| |
| slcParams = params->pAvcSliceParams; |
| refList = params->ppRefList; |
| |
| size = list ? (slcParams->num_ref_idx_l1_active_minus1 + 1) : (slcParams->num_ref_idx_l0_active_minus1 + 1); |
| |
| for (i = 0; i < size; i++) |
| { |
| picture = slcParams->PicOrder[list][i].Picture; |
| botField = (CodecHal_PictureIsBottomField(picture)) ? 1 : 0; |
| refList[picture.FrameIdx]->ucFinalIdx[list][botField] = i; |
| frameNum = refList[picture.FrameIdx]->sFrameNumber; |
| if (frameNum > (uint32_t)refList[params->CurrReconPic.FrameIdx]->sFrameNumber) |
| { |
| frameNumWrap = frameNum - slcParams->MaxFrameNum; |
| } |
| else |
| { |
| frameNumWrap = frameNum; |
| } |
| |
| if (CodecHal_PictureIsFrame(params->CurrPic)) |
| { |
| picNum = frameNumWrap; |
| } |
| else if ((CodecHal_PictureIsTopField(params->CurrPic) && |
| CodecHal_PictureIsTopField(picture)) || |
| (CodecHal_PictureIsBottomField(params->CurrPic) && |
| CodecHal_PictureIsBottomField(picture))) |
| { |
| // Same polarity |
| picNum = (frameNumWrap << 1) + 1; |
| } |
| else |
| { |
| picNum = frameNumWrap << 1; |
| } |
| slcParams->PicOrder[list][i].PicNum = picNum; |
| slcParams->PicOrder[list][i].POC = |
| refList[picture.FrameIdx]->iFieldOrderCnt[botField]; |
| } |
| |
| return; |
| } |
| |
| static MOS_STATUS CodecHal_PackSliceHeader_SetRefPicListParam( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params, |
| uint8_t list) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PCODEC_REF_LIST * refList; |
| PCODEC_PIC_REORDER picOrder; |
| uint8_t i, j, idx, picIdx, numReorder, numActiveMinus1, refPolarity; |
| uint32_t picNumPred, currPicNum, picNumNoWrap, maxPicNum; |
| int16_t frameNum; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppRefList); |
| |
| slcParams = params->pAvcSliceParams; |
| refList = params->ppRefList; |
| frameNum = refList[params->CurrReconPic.FrameIdx]->sFrameNumber; |
| |
| currPicNum = (CodecHal_PictureIsFrame(params->CurrPic)) ? frameNum : 2 * frameNum + 1; |
| picNumPred = currPicNum; |
| maxPicNum = (CodecHal_PictureIsFrame(params->CurrPic)) ? slcParams->MaxFrameNum : (2 * slcParams->MaxFrameNum); |
| |
| numActiveMinus1 = list ? slcParams->num_ref_idx_l1_active_minus1 : slcParams->num_ref_idx_l0_active_minus1; |
| |
| picOrder = &slcParams->PicOrder[list][0]; |
| |
| idx = 0; |
| picIdx = picOrder[idx].Picture.FrameIdx; |
| refPolarity = (CodecHal_PictureIsBottomField(picOrder[idx].Picture)) ? 1 : 0; |
| if (refList[picIdx]->ucFinalIdx[list][refPolarity] == |
| refList[picIdx]->ucInitialIdx[list][refPolarity]) |
| { |
| // Should never happen, something must be wrong in CodecHal_PackSliceHeader_SetInitialRefPicList() |
| CODECHAL_ENCODE_ASSERT(false); |
| if (list) // L1 |
| { |
| slcParams->ref_pic_list_reordering_flag_l1 = 0; |
| } |
| else // L0 |
| { |
| slcParams->ref_pic_list_reordering_flag_l0 = 0; |
| } |
| eStatus = MOS_STATUS_UNKNOWN; |
| return eStatus; |
| } |
| |
| numReorder = refList[picIdx]->ucFinalIdx[list][refPolarity] - refList[picIdx]->ucInitialIdx[list][refPolarity]; |
| if (numReorder > numActiveMinus1) |
| { |
| numReorder = numActiveMinus1; |
| } |
| slcParams->NumReorder = numReorder; |
| do |
| { |
| for (i = (idx + 1); i <= numActiveMinus1; i++) |
| { |
| picIdx = picOrder[i].Picture.FrameIdx; |
| refPolarity = (CodecHal_PictureIsBottomField(picOrder[i].Picture)) ? 1 : 0; |
| if (refList[picIdx]->ucFinalIdx[list][refPolarity] == idx) |
| { |
| break; |
| } |
| } |
| if (i == (numActiveMinus1 + 1)) |
| { |
| // Should never happen, something must be wrong |
| CODECHAL_ENCODE_ASSERT(false); |
| if (list) // L1 |
| { |
| slcParams->ref_pic_list_reordering_flag_l1 = 0; |
| } |
| else // L0 |
| { |
| slcParams->ref_pic_list_reordering_flag_l0 = 0; |
| } |
| eStatus = MOS_STATUS_UNKNOWN; |
| return eStatus; |
| } |
| |
| if (picOrder[i].PicNum > picNumPred) |
| { |
| picOrder[idx].ReorderPicNumIDC = 1; |
| } |
| else |
| { |
| picOrder[idx].ReorderPicNumIDC = 0; |
| } |
| |
| if (picOrder[i].PicNum > currPicNum) |
| { |
| picNumNoWrap = picOrder[i].PicNum + maxPicNum; |
| } |
| else |
| { |
| picNumNoWrap = picOrder[i].PicNum; |
| } |
| |
| if (picOrder[idx].ReorderPicNumIDC == 0) |
| { |
| if (picNumPred > picNumNoWrap) |
| { |
| picOrder[idx].DiffPicNumMinus1 = picNumPred - picNumNoWrap - 1; |
| } |
| else |
| { |
| picOrder[idx].DiffPicNumMinus1 = picNumPred + maxPicNum - picNumNoWrap - 1; |
| } |
| } |
| else |
| { |
| if (picNumNoWrap > picNumPred) |
| { |
| picOrder[idx].DiffPicNumMinus1 = picNumNoWrap - picNumPred - 1; |
| } |
| else |
| { |
| picOrder[idx].DiffPicNumMinus1 = picNumNoWrap + maxPicNum - picNumPred - 1; |
| } |
| } |
| picNumPred = picNumNoWrap; |
| |
| for (j = i; j > idx; j--) |
| { |
| picOrder[j].Picture = picOrder[j - 1].Picture; |
| picOrder[j].PicNum = picOrder[j - 1].PicNum; |
| picOrder[j].POC = picOrder[j - 1].POC; |
| } |
| |
| idx++; |
| } while (--numReorder); |
| picOrder[idx].ReorderPicNumIDC = 3; |
| |
| return eStatus; |
| } |
| |
| static MOS_STATUS CodecHal_PackSliceHeader_PredWeightTable( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PBSBuffer bsbuffer; |
| int16_t weight, offset, weight2, offset2; |
| uint8_t i, weight_flag, chromaIDC; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| |
| bsbuffer = params->pBsBuffer; |
| slcParams = params->pAvcSliceParams; |
| chromaIDC = params->pSeqParams->chroma_format_idc; |
| |
| PutVLCCode(bsbuffer, slcParams->luma_log2_weight_denom); |
| |
| if (chromaIDC) |
| { |
| PutVLCCode(bsbuffer, slcParams->chroma_log2_weight_denom); |
| } |
| |
| for (i = 0; i <= slcParams->num_ref_idx_l0_active_minus1; i++) |
| { |
| // Luma |
| weight = slcParams->Weights[0][i][0][0]; |
| offset = slcParams->Weights[0][i][0][1]; |
| weight_flag = (weight != (1 << slcParams->luma_log2_weight_denom)) || (offset != 0); |
| PutBit(bsbuffer, weight_flag); |
| if (weight_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(weight)); |
| PutVLCCode(bsbuffer, SIGNED(offset)); |
| } |
| |
| // Chroma |
| if (chromaIDC) |
| { |
| weight = slcParams->Weights[0][i][1][0]; |
| offset = slcParams->Weights[0][i][1][1]; |
| weight2 = slcParams->Weights[0][i][2][0]; |
| offset2 = slcParams->Weights[0][i][2][1]; |
| weight_flag = (weight != (1 << slcParams->chroma_log2_weight_denom)) || |
| (weight2 != (1 << slcParams->chroma_log2_weight_denom)) || |
| (offset != 0) || (offset2 != 0); |
| PutBit(bsbuffer, weight_flag); |
| if (weight_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(weight)); |
| PutVLCCode(bsbuffer, SIGNED(offset)); |
| PutVLCCode(bsbuffer, SIGNED(weight2)); |
| PutVLCCode(bsbuffer, SIGNED(offset2)); |
| } |
| } |
| } |
| |
| if (Slice_Type[slcParams->slice_type] == SLICE_B) |
| { |
| for (i = 0; i <= slcParams->num_ref_idx_l1_active_minus1; i++) |
| { |
| // Luma |
| weight = slcParams->Weights[1][i][0][0]; |
| offset = slcParams->Weights[1][i][0][1]; |
| weight_flag = (weight != (1 << slcParams->luma_log2_weight_denom)) || (offset != 0); |
| PutBit(bsbuffer, weight_flag); |
| if (weight_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(weight)); |
| PutVLCCode(bsbuffer, SIGNED(offset)); |
| } |
| |
| // Chroma |
| if (chromaIDC) |
| { |
| weight = slcParams->Weights[1][i][1][0]; |
| offset = slcParams->Weights[1][i][1][1]; |
| weight2 = slcParams->Weights[1][i][2][0]; |
| offset2 = slcParams->Weights[1][i][2][1]; |
| weight_flag = (weight != (1 << slcParams->chroma_log2_weight_denom)) || |
| (weight2 != (1 << slcParams->chroma_log2_weight_denom)) || |
| (offset != 0) || (offset2 != 0); |
| PutBit(bsbuffer, weight_flag); |
| if (weight_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(weight)); |
| PutVLCCode(bsbuffer, SIGNED(offset)); |
| PutVLCCode(bsbuffer, SIGNED(weight2)); |
| PutVLCCode(bsbuffer, SIGNED(offset2)); |
| } |
| } |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| //! |
| //! \brief Pack AUD parameters |
| //! |
| //! \param [in] params |
| //! Pointer to codechal encode Avc pack picture header parameter |
| //! |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if call success, else fail reason |
| //! |
| MOS_STATUS CodecHal_PackPictureHeader_AUDParams( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| uint32_t picType; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| |
| // refer table 7-5 in H.264 spec on primary_pic_type |
| // Here I,P,B types are included |
| // According BD Spec 9.5.1.1, 0 - I; 1 - P; 2 - B |
| |
| picType = (uint32_t)(params->wPictureCodingType) - 1; |
| PutBits(params->pBsBuffer, picType, 3); |
| |
| return eStatus; |
| } |
| |
| // Refer to H264 picture reordering session |
| static MOS_STATUS CodecHal_PackSliceHeader_RefPicListReordering( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PBSBuffer bsbuffer; |
| CODEC_PIC_REORDER * picOrder; |
| uint8_t sliceType; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams); |
| |
| slcParams = params->pAvcSliceParams; |
| bsbuffer = params->pBsBuffer; |
| sliceType = Slice_Type[slcParams->slice_type]; |
| |
| // Generate the initial reference list |
| CodecHal_PackSliceHeader_SetInitialRefPicList(params); |
| |
| if (sliceType != SLICE_I && sliceType != SLICE_SI) |
| { |
| if (slcParams->ref_pic_list_reordering_flag_l0) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackSliceHeader_SetRefPicListParam(params, 0)); |
| |
| PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l0); |
| |
| if (slcParams->ref_pic_list_reordering_flag_l0) |
| { |
| picOrder = &slcParams->PicOrder[0][0]; |
| do |
| { |
| PutVLCCode(bsbuffer, picOrder->ReorderPicNumIDC); |
| if (picOrder->ReorderPicNumIDC == 0 || |
| picOrder->ReorderPicNumIDC == 1) |
| { |
| PutVLCCode(bsbuffer, picOrder->DiffPicNumMinus1); |
| } |
| } while ((picOrder++)->ReorderPicNumIDC != 3); |
| } |
| } |
| else |
| { |
| PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l0); |
| } |
| } |
| if (sliceType == SLICE_B) |
| { |
| if (slcParams->ref_pic_list_reordering_flag_l1) |
| { |
| CodecHal_PackSliceHeader_SetRefPicListParam(params, 1); |
| |
| PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l1); |
| |
| if (slcParams->ref_pic_list_reordering_flag_l1) |
| { |
| picOrder = &slcParams->PicOrder[1][0]; |
| do |
| { |
| PutVLCCode(bsbuffer, picOrder->ReorderPicNumIDC); |
| if (picOrder->ReorderPicNumIDC == 0 || |
| picOrder->ReorderPicNumIDC == 1) |
| { |
| PutVLCCode(bsbuffer, picOrder->DiffPicNumMinus1); |
| } |
| } while ((picOrder++)->ReorderPicNumIDC != 3); |
| } |
| } |
| else |
| { |
| PutBit(bsbuffer, slcParams->ref_pic_list_reordering_flag_l1); |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| //! |
| //! \brief Pack sequence parameters |
| //! |
| //! \param [in] params |
| //! Pointer to codechal encode Avc pack picture header parameter |
| //! |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if call success, else fail reason |
| //! |
| MOS_STATUS CodecHal_PackPictureHeader_SeqParams( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams; |
| BSBuffer * bsbuffer; |
| uint8_t i; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams); |
| |
| seqParams = params->pSeqParams; |
| bsbuffer = params->pBsBuffer; |
| |
| PutBits(bsbuffer, seqParams->Profile, 8); |
| |
| PutBit(bsbuffer, seqParams->constraint_set0_flag); |
| PutBit(bsbuffer, seqParams->constraint_set1_flag); |
| PutBit(bsbuffer, seqParams->constraint_set2_flag); |
| PutBit(bsbuffer, seqParams->constraint_set3_flag); |
| |
| PutBits(bsbuffer, 0, 4); |
| PutBits(bsbuffer, seqParams->Level, 8); |
| PutVLCCode(bsbuffer, seqParams->seq_parameter_set_id); |
| |
| if (seqParams->Profile == CODEC_AVC_HIGH_PROFILE || |
| seqParams->Profile == CODEC_AVC_HIGH10_PROFILE || |
| seqParams->Profile == CODEC_AVC_HIGH422_PROFILE || |
| seqParams->Profile == CODEC_AVC_HIGH444_PROFILE || |
| seqParams->Profile == CODEC_AVC_CAVLC444_INTRA_PROFILE || |
| seqParams->Profile == CODEC_AVC_SCALABLE_BASE_PROFILE || |
| seqParams->Profile == CODEC_AVC_SCALABLE_HIGH_PROFILE) |
| { |
| PutVLCCode(bsbuffer, seqParams->chroma_format_idc); |
| if (seqParams->chroma_format_idc == 3) |
| { |
| PutBit(bsbuffer, seqParams->separate_colour_plane_flag); |
| } |
| PutVLCCode(bsbuffer, seqParams->bit_depth_luma_minus8); |
| PutVLCCode(bsbuffer, seqParams->bit_depth_chroma_minus8); |
| PutBit(bsbuffer, seqParams->qpprime_y_zero_transform_bypass_flag); |
| PutBit(bsbuffer, seqParams->seq_scaling_matrix_present_flag); |
| if (seqParams->seq_scaling_matrix_present_flag) |
| { |
| //Iterate thro' the scaling lists. Refer to ITU-T H.264 std. section 7.3.2.1 |
| for (i = 0; i < 8; i++) |
| { |
| // scaling list present flag |
| PutBit(bsbuffer, seqParams->seq_scaling_list_present_flag[i]); |
| if (seqParams->seq_scaling_list_present_flag[i]) |
| { |
| if (i < 6) |
| { |
| PackScalingList(bsbuffer, ¶ms->pAvcIQMatrixParams->ScalingList4x4[i][0], 16); |
| } |
| else |
| { |
| PackScalingList(bsbuffer, ¶ms->pAvcIQMatrixParams->ScalingList8x8[i - 6][0], 64); |
| } |
| } |
| } |
| } |
| } |
| |
| PutVLCCode(bsbuffer, seqParams->log2_max_frame_num_minus4); |
| PutVLCCode(bsbuffer, seqParams->pic_order_cnt_type); |
| if (seqParams->pic_order_cnt_type == 0) |
| { |
| PutVLCCode(bsbuffer, seqParams->log2_max_pic_order_cnt_lsb_minus4); |
| } |
| else if (seqParams->pic_order_cnt_type == 1) |
| { |
| PutBit(bsbuffer, seqParams->delta_pic_order_always_zero_flag); |
| PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_non_ref_pic)); |
| PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_top_to_bottom_field)); |
| PutVLCCode(bsbuffer, seqParams->num_ref_frames_in_pic_order_cnt_cycle); |
| for (i = 0; i < seqParams->num_ref_frames_in_pic_order_cnt_cycle; i++) |
| { |
| PutVLCCode(bsbuffer, SIGNED(seqParams->offset_for_ref_frame[i])); |
| } |
| } |
| |
| PutVLCCode(bsbuffer, seqParams->NumRefFrames); |
| PutBit(bsbuffer, seqParams->gaps_in_frame_num_value_allowed_flag); |
| PutVLCCode(bsbuffer, seqParams->pic_width_in_mbs_minus1); |
| PutVLCCode(bsbuffer, seqParams->pic_height_in_map_units_minus1); |
| PutBit(bsbuffer, seqParams->frame_mbs_only_flag); |
| |
| if (!seqParams->frame_mbs_only_flag) |
| { |
| PutBit(bsbuffer, seqParams->mb_adaptive_frame_field_flag); |
| } |
| |
| PutBit(bsbuffer, seqParams->direct_8x8_inference_flag); |
| |
| if ((!seqParams->frame_cropping_flag) && |
| (params->dwFrameHeight != params->dwOriFrameHeight)) |
| { |
| seqParams->frame_cropping_flag = 1; |
| seqParams->frame_crop_bottom_offset = |
| (int16_t)((params->dwFrameHeight - params->dwOriFrameHeight) >> |
| (2 - seqParams->frame_mbs_only_flag)); // 4:2:0 |
| } |
| |
| PutBit(bsbuffer, seqParams->frame_cropping_flag); |
| |
| if (seqParams->frame_cropping_flag) |
| { |
| PutVLCCode(bsbuffer, seqParams->frame_crop_left_offset); |
| PutVLCCode(bsbuffer, seqParams->frame_crop_right_offset); |
| PutVLCCode(bsbuffer, seqParams->frame_crop_top_offset); |
| PutVLCCode(bsbuffer, seqParams->frame_crop_bottom_offset); |
| } |
| |
| PutBit(bsbuffer, seqParams->vui_parameters_present_flag); |
| |
| if (seqParams->vui_parameters_present_flag) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_VuiParams(params)); |
| } |
| |
| *params->pbNewSeqHeader = 1; |
| |
| return eStatus; |
| } |
| |
| //! |
| //! \brief Pack picture parameters |
| //! |
| //! \param [in] params |
| //! Pointer to codechal encode Avc pack picture header parameter |
| //! |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if call success, else fail reason |
| //! |
| MOS_STATUS CodecHal_PackPictureHeader_PicParams( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams; |
| PCODEC_AVC_ENCODE_PIC_PARAMS picParams; |
| PBSBuffer bsbuffer; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pPicParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| |
| seqParams = params->pSeqParams; |
| picParams = params->pPicParams; |
| bsbuffer = params->pBsBuffer; |
| |
| PutVLCCode(bsbuffer, picParams->pic_parameter_set_id); |
| PutVLCCode(bsbuffer, picParams->seq_parameter_set_id); |
| |
| PutBit(bsbuffer, picParams->entropy_coding_mode_flag); |
| PutBit(bsbuffer, picParams->pic_order_present_flag); |
| |
| PutVLCCode(bsbuffer, picParams->num_slice_groups_minus1); |
| |
| PutVLCCode(bsbuffer, picParams->num_ref_idx_l0_active_minus1); |
| PutVLCCode(bsbuffer, picParams->num_ref_idx_l1_active_minus1); |
| |
| PutBit(bsbuffer, picParams->weighted_pred_flag); |
| PutBits(bsbuffer, picParams->weighted_bipred_idc, 2); |
| |
| PutVLCCode(bsbuffer, SIGNED(picParams->pic_init_qp_minus26)); |
| PutVLCCode(bsbuffer, SIGNED(picParams->pic_init_qs_minus26)); |
| PutVLCCode(bsbuffer, SIGNED(picParams->chroma_qp_index_offset)); |
| |
| PutBit(bsbuffer, picParams->deblocking_filter_control_present_flag); |
| PutBit(bsbuffer, picParams->constrained_intra_pred_flag); |
| PutBit(bsbuffer, picParams->redundant_pic_cnt_present_flag); |
| |
| // The syntax elements transform_8x8_mode_flag, pic_scaling_matrix_present_flag, and second_chroma_qp_index_offset |
| // shall not be present for main profile |
| if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE || seqParams->Profile == CODEC_AVC_BASE_PROFILE) |
| { |
| return eStatus; |
| } |
| |
| PutBit(bsbuffer, picParams->transform_8x8_mode_flag); |
| PutBit(bsbuffer, picParams->pic_scaling_matrix_present_flag); |
| if (picParams->pic_scaling_matrix_present_flag) |
| { |
| uint8_t i; |
| |
| //Iterate thro' the scaling lists. Refer to ITU-T H.264 std. section 7.3.2.2 |
| for (i = 0; i < 6 + 2 * picParams->transform_8x8_mode_flag; i++) |
| { |
| //Put scaling list present flag |
| PutBit(bsbuffer, picParams->pic_scaling_list_present_flag[i]); |
| if (picParams->pic_scaling_list_present_flag[i]) |
| { |
| if (i < 6) |
| { |
| PackScalingList(bsbuffer, ¶ms->pAvcIQMatrixParams->ScalingList4x4[i][0], 16); |
| } |
| else |
| { |
| PackScalingList(bsbuffer, ¶ms->pAvcIQMatrixParams->ScalingList8x8[i - 6][0], 64); |
| } |
| } |
| } |
| } |
| |
| PutVLCCode(bsbuffer, SIGNED(picParams->second_chroma_qp_index_offset)); |
| |
| *params->pbNewPPSHeader = 1; |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodecHalAvcEncode_PackPictureHeader( |
| PCODECHAL_ENCODE_AVC_PACK_PIC_HEADER_PARAMS params) |
| { |
| PBSBuffer bsbuffer; |
| uint32_t indexNALUnit; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->ppNALUnitParams); |
| |
| bsbuffer = params->pBsBuffer; |
| *(bsbuffer->pBase) = 0; // init first byte to 0 |
| bsbuffer->pCurrent = bsbuffer->pBase; |
| bsbuffer->SliceOffset = 0; |
| bsbuffer->BitOffset = 0; |
| bsbuffer->BitSize = 0; |
| |
| MOS_ZeroMemory(params->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE); |
| indexNALUnit = 0; |
| |
| // AU_Delimiter |
| // nal_ref_idc to be 0 for all nal_unit_type equal to 6, 9, 10, 11 or12 |
| params->ppNALUnitParams[indexNALUnit]->uiOffset = 0; |
| params->ppNALUnitParams[indexNALUnit]->uiNalUnitType = CODECHAL_ENCODE_AVC_NAL_UT_AUD; |
| params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes = true; |
| params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4; |
| SetNalUnit(&bsbuffer->pCurrent, 0, CODECHAL_ENCODE_AVC_NAL_UT_AUD); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_AUDParams(params)); |
| SetTrailingBits(bsbuffer); |
| //NAL unit are byte aligned, bsbuffer->BitOffset should be 0 |
| params->ppNALUnitParams[indexNALUnit]->uiSize = |
| (uint32_t)(bsbuffer->pCurrent - |
| bsbuffer->pBase - |
| params->ppNALUnitParams[indexNALUnit]->uiOffset); |
| indexNALUnit++; |
| |
| // If this is a new sequence, write the seq set |
| if (params->bNewSeq && !params->pSeqParams->bNoAcceleratorSPSInsertion) |
| { |
| // Pack SPS |
| params->ppNALUnitParams[indexNALUnit]->uiOffset = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase); |
| params->ppNALUnitParams[indexNALUnit]->uiNalUnitType = CODECHAL_ENCODE_AVC_NAL_UT_SPS; |
| params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes = true; |
| params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4; |
| SetNalUnit(&bsbuffer->pCurrent, 1, CODECHAL_ENCODE_AVC_NAL_UT_SPS); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_SeqParams(params)); |
| SetTrailingBits(bsbuffer); |
| params->ppNALUnitParams[indexNALUnit]->uiSize = |
| (uint32_t)(bsbuffer->pCurrent - |
| bsbuffer->pBase - |
| params->ppNALUnitParams[indexNALUnit]->uiOffset); |
| indexNALUnit++; |
| } |
| |
| // Pack PPS |
| params->ppNALUnitParams[indexNALUnit]->uiOffset = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase); |
| params->ppNALUnitParams[indexNALUnit]->uiNalUnitType = CODECHAL_ENCODE_AVC_NAL_UT_PPS; |
| params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes = true; |
| params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4; |
| SetNalUnit(&bsbuffer->pCurrent, 1, CODECHAL_ENCODE_AVC_NAL_UT_PPS); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackPictureHeader_PicParams(params)); |
| SetTrailingBits(bsbuffer); |
| params->ppNALUnitParams[indexNALUnit]->uiSize = |
| (uint32_t)(bsbuffer->pCurrent - |
| bsbuffer->pBase - |
| params->ppNALUnitParams[indexNALUnit]->uiOffset); |
| indexNALUnit++; |
| |
| // Pack SEI |
| if (params->pSeiData->newSEIData) |
| { |
| params->ppNALUnitParams[indexNALUnit]->uiOffset = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase); |
| params->ppNALUnitParams[indexNALUnit]->uiNalUnitType = CODECHAL_ENCODE_AVC_NAL_UT_SEI; |
| params->ppNALUnitParams[indexNALUnit]->bInsertEmulationBytes = false; |
| params->ppNALUnitParams[indexNALUnit]->uiSkipEmulationCheckCount = 4; |
| eStatus = MOS_SecureMemcpy(bsbuffer->pCurrent, |
| params->pSeiData->dwSEIBufSize, |
| params->pSeiData->pSEIBuffer, |
| params->pSeiData->dwSEIBufSize); |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Failed to copy memory."); |
| return eStatus; |
| } |
| bsbuffer->pCurrent += params->pSeiData->dwSEIDataSize; |
| params->pSeiData->newSEIData = false; |
| params->ppNALUnitParams[indexNALUnit]->uiSize = |
| (uint32_t)(bsbuffer->pCurrent - |
| bsbuffer->pBase - |
| params->ppNALUnitParams[indexNALUnit]->uiOffset); |
| indexNALUnit++; |
| } |
| |
| bsbuffer->SliceOffset = (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase); |
| |
| return eStatus; |
| } |
| |
| uint16_t CodecHalAvcEncode_GetMaxNumSlicesAllowed( |
| CODEC_AVC_PROFILE_IDC profileIdc, |
| CODEC_AVC_LEVEL_IDC levelIdc, |
| uint32_t framesPer100Sec) |
| { |
| uint16_t maxAllowedNumSlices = 0; |
| |
| if ((profileIdc == CODEC_AVC_MAIN_PROFILE) || |
| (profileIdc == CODEC_AVC_HIGH_PROFILE) || |
| (profileIdc == CODEC_AVC_HIGH10_PROFILE) || |
| (profileIdc == CODEC_AVC_HIGH422_PROFILE) || |
| (profileIdc == CODEC_AVC_HIGH444_PROFILE) || |
| (profileIdc == CODEC_AVC_CAVLC444_INTRA_PROFILE)) |
| { |
| switch (levelIdc) |
| { |
| case CODEC_AVC_LEVEL_3: |
| maxAllowedNumSlices = (uint16_t)(40500.0 * 100 / 22.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_31: |
| maxAllowedNumSlices = (uint16_t)(108000.0 * 100 / 60.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_32: |
| maxAllowedNumSlices = (uint16_t)(216000.0 * 100 / 60.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_4: |
| case CODEC_AVC_LEVEL_41: |
| maxAllowedNumSlices = (uint16_t)(245760.0 * 100 / 24.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_42: |
| maxAllowedNumSlices = (uint16_t)(522240.0 * 100 / 24.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_5: |
| maxAllowedNumSlices = (uint16_t)(589824.0 * 100 / 24.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_51: |
| maxAllowedNumSlices = (uint16_t)(983040.0 * 100 / 24.0 / framesPer100Sec); |
| break; |
| case CODEC_AVC_LEVEL_52: |
| maxAllowedNumSlices = (uint16_t)(2073600.0 * 100 / 24.0 / framesPer100Sec); |
| break; |
| default: |
| maxAllowedNumSlices = 0; |
| } |
| } |
| |
| return maxAllowedNumSlices; |
| } |
| |
| //Pack Slice Header |
| MOS_STATUS CodecHalAvcEncode_PackSliceHeader( |
| PCODECHAL_ENCODE_AVC_PACK_SLC_HEADER_PARAMS params) |
| { |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams; |
| PCODEC_AVC_ENCODE_PIC_PARAMS picParams; |
| PCODEC_AVC_ENCODE_SLICE_PARAMS slcParams; |
| PBSBuffer bsbuffer; |
| uint8_t sliceType; |
| CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE nalType; |
| bool ref; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSeqParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pPicParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pAvcSliceParams); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); |
| |
| slcParams = params->pAvcSliceParams; |
| picParams = params->pPicParams; |
| seqParams = params->pSeqParams; |
| bsbuffer = params->pBsBuffer; |
| sliceType = Slice_Type[slcParams->slice_type]; |
| nalType = params->NalUnitType; |
| ref = params->ppRefList[params->CurrReconPic.FrameIdx]->bUsedAsRef; |
| |
| // Make slice header uint8_t aligned |
| while (bsbuffer->BitOffset) |
| { |
| PutBit(bsbuffer, 0); |
| } |
| |
| // zero byte shall exist when the byte stream NAL unit syntax structure contains the first |
| // NAL unit of an access unit in decoding order, as specified by subclause 7.4.1.2.3. |
| // VDEnc Slice header packing handled by PAK does not need the 0 byte inserted |
| if (params->UserFlags.bDisableAcceleratorHeaderPacking && (!params->bVdencEnabled)) |
| { |
| *bsbuffer->pCurrent = 0; |
| bsbuffer->pCurrent++; |
| } |
| |
| SetNalUnit(&bsbuffer->pCurrent, (uint8_t)ref, nalType); |
| |
| // In the VDEnc mode, PAK only gets this command at the beginning of the frame for slice position X=0, Y=0 |
| PutVLCCode(bsbuffer, params->bVdencEnabled ? 0 : slcParams->first_mb_in_slice); |
| PutVLCCode(bsbuffer, slcParams->slice_type); |
| PutVLCCode(bsbuffer, slcParams->pic_parameter_set_id); |
| |
| if (seqParams->separate_colour_plane_flag) |
| { |
| PutBits(bsbuffer, slcParams->colour_plane_id, 2); |
| } |
| |
| PutBits(bsbuffer, slcParams->frame_num, seqParams->log2_max_frame_num_minus4 + 4); |
| |
| if (!seqParams->frame_mbs_only_flag) |
| { |
| PutBit(bsbuffer, slcParams->field_pic_flag); |
| if (slcParams->field_pic_flag) |
| { |
| PutBit(bsbuffer, slcParams->bottom_field_flag); |
| } |
| } |
| |
| if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE) |
| { |
| PutVLCCode(bsbuffer, slcParams->idr_pic_id); |
| } |
| |
| if (seqParams->pic_order_cnt_type == 0) |
| { |
| PutBits(bsbuffer, slcParams->pic_order_cnt_lsb, seqParams->log2_max_pic_order_cnt_lsb_minus4 + 4); |
| if (picParams->pic_order_present_flag && !slcParams->field_pic_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt_bottom)); |
| } |
| } |
| |
| if (seqParams->pic_order_cnt_type == 1 && !seqParams->delta_pic_order_always_zero_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt[0])); |
| if (picParams->pic_order_present_flag && !slcParams->field_pic_flag) |
| { |
| PutVLCCode(bsbuffer, SIGNED(slcParams->delta_pic_order_cnt[1])); |
| } |
| } |
| |
| if (picParams->redundant_pic_cnt_present_flag) |
| { |
| PutVLCCode(bsbuffer, slcParams->redundant_pic_cnt); |
| } |
| |
| if (sliceType == SLICE_B) |
| { |
| PutBit(bsbuffer, slcParams->direct_spatial_mv_pred_flag); |
| } |
| |
| if (sliceType == SLICE_P || sliceType == SLICE_SP || sliceType == SLICE_B) |
| { |
| PutBit(bsbuffer, slcParams->num_ref_idx_active_override_flag); |
| if (slcParams->num_ref_idx_active_override_flag) |
| { |
| PutVLCCode(bsbuffer, slcParams->num_ref_idx_l0_active_minus1); |
| if (sliceType == SLICE_B) |
| { |
| PutVLCCode(bsbuffer, slcParams->num_ref_idx_l1_active_minus1); |
| } |
| } |
| } |
| |
| // ref_pic_list_reordering() |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackSliceHeader_RefPicListReordering(params)); |
| |
| if ((picParams->weighted_pred_flag && |
| (sliceType == SLICE_P || sliceType == SLICE_SP)) || |
| (picParams->weighted_bipred_idc == EXPLICIT_WEIGHTED_INTER_PRED_MODE && |
| sliceType == SLICE_B)) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_PackSliceHeader_PredWeightTable(params)); |
| } |
| |
| // dec_ref_pic_marking() |
| if (nalType == CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE) |
| { |
| PutBit(bsbuffer, slcParams->no_output_of_prior_pics_flag); |
| PutBit(bsbuffer, slcParams->long_term_reference_flag); |
| } |
| else if (ref) |
| { |
| PutBit(bsbuffer, slcParams->adaptive_ref_pic_marking_mode_flag); |
| } |
| |
| if (picParams->entropy_coding_mode_flag && sliceType != SLICE_I && sliceType != SLICE_SI) |
| { |
| PutVLCCode(bsbuffer, slcParams->cabac_init_idc); |
| } |
| |
| PutVLCCode(bsbuffer, SIGNED(slcParams->slice_qp_delta)); |
| |
| if (sliceType == SLICE_SP || sliceType == SLICE_SI) |
| { |
| if (sliceType == SLICE_SP) |
| { |
| PutBit(bsbuffer, slcParams->sp_for_switch_flag); |
| } |
| PutVLCCode(bsbuffer, SIGNED(slcParams->slice_qs_delta)); |
| } |
| |
| if (picParams->deblocking_filter_control_present_flag) |
| { |
| PutVLCCode(bsbuffer, slcParams->disable_deblocking_filter_idc); |
| if (slcParams->disable_deblocking_filter_idc != 1) |
| { |
| PutVLCCode(bsbuffer, SIGNED(slcParams->slice_alpha_c0_offset_div2)); |
| PutVLCCode(bsbuffer, SIGNED(slcParams->slice_beta_offset_div2)); |
| } |
| } |
| |
| bsbuffer->BitSize = |
| (uint32_t)((bsbuffer->pCurrent - bsbuffer->SliceOffset - bsbuffer->pBase) * 8 + bsbuffer->BitOffset); |
| bsbuffer->SliceOffset = |
| (uint32_t)(bsbuffer->pCurrent - bsbuffer->pBase + (bsbuffer->BitOffset != 0)); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::InitMmcState() |
| { |
| #ifdef _MMC_SUPPORTED |
| m_mmcState = MOS_New(CodechalMmcEncodeAvc, m_hwInterface, this); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState); |
| #endif |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CodechalEncodeAvcBase::CodechalEncodeAvcBase( |
| CodechalHwInterface * hwInterface, |
| CodechalDebugInterface *debugInterface, |
| PCODECHAL_STANDARD_INFO standardInfo) : CodechalEncoderState(hwInterface, debugInterface, standardInfo) |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_ZeroMemory(m_avcPicParams, CODEC_AVC_MAX_PPS_NUM * sizeof(PCODEC_AVC_ENCODE_PIC_PARAMS)); |
| MOS_ZeroMemory(m_avcSeqParams, CODEC_AVC_MAX_SPS_NUM * sizeof(PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)); |
| MOS_ZeroMemory(&m_userFlags, sizeof(CODEC_AVC_ENCODE_USER_FLAGS)); |
| MOS_ZeroMemory(m_picIdx, CODEC_AVC_MAX_NUM_REF_FRAME * sizeof(CODEC_PIC_ID)); |
| MOS_ZeroMemory(m_refList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE * sizeof(PCODEC_REF_LIST)); |
| MOS_ZeroMemory(m_avcFrameStoreID, CODEC_AVC_MAX_NUM_REF_FRAME * sizeof(CODEC_AVC_FRAME_STORE_ID)); |
| MOS_ZeroMemory(&m_nalUnitType, sizeof(CODECHAL_ENCODE_AVC_NAL_UNIT_TYPE)); |
| MOS_ZeroMemory(&m_trellisQuantParams, sizeof(CODECHAL_ENCODE_AVC_TQ_PARAMS)); |
| MOS_ZeroMemory(m_distScaleFactorList0, 2 * CODEC_AVC_MAX_NUM_REF_FRAME * sizeof(uint32_t)); |
| MOS_ZeroMemory(m_batchBufferForVdencImgStat, CODECHAL_ENCODE_RECYCLED_BUFFER_NUM * sizeof(MHW_BATCH_BUFFER)); |
| MOS_ZeroMemory(&m_4xMeMvDataBuffer, sizeof(MOS_SURFACE)); |
| MOS_ZeroMemory(&m_16xMeMvDataBuffer, sizeof(MOS_SURFACE)); |
| MOS_ZeroMemory(&m_32xMeMvDataBuffer, sizeof(MOS_SURFACE)); |
| MOS_ZeroMemory(&m_4xMeDistortionBuffer, sizeof(MOS_SURFACE)); |
| MOS_ZeroMemory(&m_intraRowStoreScratchBuffer, sizeof(MOS_RESOURCE)); |
| MOS_ZeroMemory(m_batchBufferForPakSlices, CODECHAL_ENCODE_RECYCLED_BUFFER_NUM * sizeof(MHW_BATCH_BUFFER)); |
| MOS_ZeroMemory(&m_pakSliceSizeStreamoutBuffer, sizeof(MOS_RESOURCE)); |
| |
| m_hwInterface->GetStateHeapSettings()->dwNumSyncTags = CODECHAL_ENCODE_AVC_NUM_SYNC_TAGS; |
| m_hwInterface->GetStateHeapSettings()->dwDshSize = CODECHAL_ENCODE_AVC_INIT_DSH_SIZE; |
| } |
| |
| CodechalEncodeAvcBase::~CodechalEncodeAvcBase() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| // Release Ref Lists |
| CodecHalFreeDataList(m_refList, CODEC_AVC_NUM_UNCOMPRESSED_SURFACE); |
| |
| for (uint8_t i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++) |
| { |
| ReleaseBatchBufferForPakSlices(i); |
| } |
| |
| m_osInterface->pfnFreeResource(m_osInterface, &m_intraRowStoreScratchBuffer); |
| |
| if (m_encEnabled) |
| { |
| if (m_hmeSupported) |
| { |
| if (m_hmeKernel) |
| { |
| MOS_Delete(m_hmeKernel); |
| } |
| else |
| { |
| HmeParams hmeParams; |
| |
| MOS_ZeroMemory(&hmeParams, sizeof(hmeParams)); |
| hmeParams.b4xMeDistortionBufferSupported = true; |
| hmeParams.ps16xMeMvDataBuffer = &m_16xMeMvDataBuffer; |
| hmeParams.ps32xMeMvDataBuffer = &m_32xMeMvDataBuffer; |
| hmeParams.ps4xMeDistortionBuffer = &m_4xMeDistortionBuffer; |
| hmeParams.ps4xMeMvDataBuffer = &m_4xMeMvDataBuffer; |
| DestroyMeResources(&hmeParams); |
| } |
| } |
| } |
| |
| if (m_sliceSizeStreamoutSupported) |
| { |
| m_osInterface->pfnFreeResource(m_osInterface, &m_pakSliceSizeStreamoutBuffer); |
| } |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::Initialize(CodechalSetting *settings) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMmcState()); |
| return CodechalEncoderState::Initialize(settings); |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::UserFeatureKeyReport() |
| { |
| return CodechalEncoderState::UserFeatureKeyReport(); |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::Initialize() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| m_hwInterface->GetMfxPrimitiveCommandsDataSize( |
| m_mode, |
| &m_pakSliceSize, |
| &m_pakSlicePatchListSize, |
| false); |
| |
| // overwrite, must be zero, no patching into second level batch buffer allowed |
| m_pakSlicePatchListSize = 0; |
| |
| return eStatus; |
| } |
| |
| void CodechalEncodeAvcBase::ScalingListFlat() |
| { |
| // 4x4 block |
| for (uint8_t idx2 = 0; idx2 < 6; idx2++) |
| { |
| for (uint8_t idx1 = 0; idx1 < 16; idx1++) |
| { |
| m_avcIQWeightScaleLists->WeightScale4x4[idx2][idx1] = 16; |
| } |
| } |
| // 8x8 block |
| for (uint8_t idx2 = 0; idx2 < 2; idx2++) |
| { |
| for (uint8_t idx1 = 0; idx1 < 64; idx1++) |
| { |
| m_avcIQWeightScaleLists->WeightScale8x8[idx2][idx1] = 16; |
| } |
| } |
| } |
| |
| void CodechalEncodeAvcBase::ScalingListFallbackRuleA() |
| { |
| for (uint8_t idx1 = 0; idx1 < 16; idx1++) |
| { |
| for (uint8_t idx2 = 0; idx2 < 3; idx2++) |
| { |
| m_avcIQWeightScaleLists->WeightScale4x4[idx2][CODEC_AVC_Qmatrix_scan_4x4[idx1]] = |
| CODEC_AVC_Default_4x4_Intra[idx1]; |
| } |
| for (uint8_t idx2 = 3; idx2 < 6; idx2++) |
| { |
| m_avcIQWeightScaleLists->WeightScale4x4[idx2][CODEC_AVC_Qmatrix_scan_4x4[idx1]] = |
| CODEC_AVC_Default_4x4_Inter[idx1]; |
| } |
| } |
| // 8x8 block |
| for (uint8_t idx1 = 0; idx1 < 64; idx1++) |
| { |
| m_avcIQWeightScaleLists->WeightScale8x8[0][CODEC_AVC_Qmatrix_scan_8x8[idx1]] = |
| CODEC_AVC_Default_8x8_Intra[idx1]; |
| m_avcIQWeightScaleLists->WeightScale8x8[1][CODEC_AVC_Qmatrix_scan_8x8[idx1]] = |
| CODEC_AVC_Default_8x8_Inter[idx1]; |
| } |
| } |
| |
| void CodechalEncodeAvcBase::GetDistScaleFactor() |
| { |
| auto picParams = m_avcPicParam; |
| auto refList = &(m_refList[0]); |
| auto picIdx = &(m_picIdx[0]); |
| |
| bool bottom = CodecHal_PictureIsBottomField(picParams->CurrOriginalPic); |
| int pocCurr = picParams->CurrFieldOrderCnt[bottom]; |
| |
| MOS_ZeroMemory(m_distScaleFactorList0, sizeof(uint32_t) * CODEC_AVC_MAX_NUM_REF_FRAME * 2); |
| for (unsigned int index = 0; index <= m_avcSliceParams->num_ref_idx_l0_active_minus1; index++) |
| { |
| auto picture = m_avcSliceParams->RefPicList[LIST_0][index]; |
| if (!CodecHal_PictureIsInvalid(picture)) |
| { |
| auto pictureIdx = picIdx[picture.FrameIdx].ucPicIdx; |
| int pocPic0 = CodecHal_PictureIsBottomField(picture) ? refList[pictureIdx]->iFieldOrderCnt[1] : refList[pictureIdx]->iFieldOrderCnt[0]; |
| picture = m_avcSliceParams->RefPicList[LIST_1][0]; |
| pictureIdx = picIdx[picture.FrameIdx].ucPicIdx; |
| int pocPic1 = CodecHal_PictureIsBottomField(picture) ? refList[pictureIdx]->iFieldOrderCnt[1] : refList[pictureIdx]->iFieldOrderCnt[0]; |
| int tb = CodecHal_Clip3(-128, 127, (pocCurr - pocPic0)); |
| int td = CodecHal_Clip3(-128, 127, (pocPic1 - pocPic0)); |
| if (td == 0) |
| { |
| td = 1; |
| } |
| int tx = (16384 + ABS(td / 2)) / td; |
| |
| m_distScaleFactorList0[index] = CodecHal_Clip3(-1024, 1023, (tb * tx + 32) >> 6); |
| } |
| } |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::AllocateBatchBufferForPakSlices( |
| uint32_t numSlices, |
| uint8_t numPakPasses, |
| uint8_t currRecycledBufIdx) |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| MOS_ZeroMemory( |
| &m_batchBufferForPakSlices[currRecycledBufIdx], |
| sizeof(MHW_BATCH_BUFFER)); |
| |
| // Get the slice size |
| uint32_t size = (numPakPasses + 1) * numSlices * m_pakSliceSize; |
| |
| m_batchBufferForPakSlices[currRecycledBufIdx].bSecondLevel = true; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb( |
| m_osInterface, |
| &m_batchBufferForPakSlices[currRecycledBufIdx], |
| nullptr, |
| size)); |
| |
| MOS_LOCK_PARAMS lockFlags; |
| MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS)); |
| lockFlags.WriteOnly = 1; |
| uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource( |
| m_osInterface, |
| &m_batchBufferForPakSlices[currRecycledBufIdx].OsResource, |
| &lockFlags); |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(data); |
| |
| MOS_ZeroMemory(data, size); |
| m_osInterface->pfnUnlockResource( |
| m_osInterface, |
| &m_batchBufferForPakSlices[currRecycledBufIdx].OsResource); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::ReleaseBatchBufferForPakSlices( |
| uint8_t currRecycledBufIdx) |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| if (m_batchBufferForPakSlices[currRecycledBufIdx].iSize) |
| { |
| Mhw_FreeBb(m_osInterface, &m_batchBufferForPakSlices[currRecycledBufIdx], nullptr); |
| } |
| |
| return eStatus; |
| } |
| |
| //==<Functions>======================================================= |
| |
| // Calculate BiWeight for AVC B frame |
| // for AVC, we cannot use the CodecHal_GetBiWeight function since AVC can use B as reference and |
| // also supports PAFF |
| int32_t CodechalEncodeAvcBase::GetBiWeight( |
| uint32_t distScaleFactorRefID0List0, |
| uint16_t weightedBiPredIdc) |
| { |
| int32_t biWeight = 32; // default value |
| if (weightedBiPredIdc != IMPLICIT_WEIGHTED_INTER_PRED_MODE) |
| { |
| biWeight = 32; |
| } |
| else |
| { |
| biWeight = (distScaleFactorRefID0List0 + 2) >> 2; |
| |
| if (biWeight != 16 && biWeight != 21 && |
| biWeight != 32 && biWeight != 43 && biWeight != 48) |
| { |
| biWeight = 32; // If # of B-pics between two refs is more than 3. VME does not support it. |
| } |
| } |
| |
| return biWeight; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::AllocateEncResources() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| uint32_t fieldNumMBs = m_picWidthInMb * ((m_picHeightInMb + 1) >> 1); |
| |
| // to be used in CodecHalEncode_TrackedBuffer_AllocateMbCodeMvDataResources() later |
| m_mbCodeSize = MOS_ALIGN_CEIL(fieldNumMBs * 16 * 4, CODECHAL_PAGE_SIZE) + fieldNumMBs * 16 * 4; |
| m_mvDataSize = MOS_ALIGN_CEIL(fieldNumMBs * (32 * 4), CODECHAL_PAGE_SIZE) * 2; // top field MV + bottom field MV (both page aligned) |
| |
| // allocate 3 + 2 buffers initially |
| if ((m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) && (!m_vdencEnabled)) |
| { |
| for (uint8_t j = 0; j < 3; j++) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_trackedBuf->AllocateMbCodeResources(j)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_trackedBuf->AllocateMvDataResources(j)); |
| } |
| |
| for (uint8_t k = 0; k < 2; k++) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_trackedBuf->AllocateMbCodeResources(CODEC_NUM_REF_BUFFERS + k)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_trackedBuf->AllocateMvDataResources(CODEC_NUM_REF_BUFFERS + k)); |
| } |
| } |
| |
| if (m_encEnabled && m_hmeSupported) |
| { |
| if (m_hmeKernel) |
| { |
| m_hmeKernel->AllocateResources(); |
| } |
| else |
| { |
| HmeParams hmeParams; |
| MOS_ZeroMemory(&hmeParams, sizeof(hmeParams)); |
| hmeParams.b4xMeDistortionBufferSupported = true; |
| hmeParams.ps4xMeDistortionBuffer = &m_4xMeDistortionBuffer; |
| hmeParams.ps4xMeMvDataBuffer = &m_4xMeMvDataBuffer; |
| hmeParams.ps16xMeMvDataBuffer = &m_16xMeMvDataBuffer; |
| hmeParams.ps32xMeMvDataBuffer = &m_32xMeMvDataBuffer; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources4xMe(&hmeParams)); |
| if (m_16xMeSupported) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources16xMe(&hmeParams)); |
| } |
| if (m_32xMeSupported) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources32xMe(&hmeParams)); |
| } |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::AllocateResources() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources()); |
| |
| // initiate allocation parameters and lock flags |
| MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear; |
| MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS)); |
| allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER; |
| allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR; |
| allocParamsForBufferLinear.Format = Format_Buffer; |
| |
| AllocateEncResources(); |
| |
| // Allocate Ref Lists |
| CodecHalAllocateDataList( |
| m_refList, |
| CODEC_AVC_NUM_UNCOMPRESSED_SURFACE); |
| |
| if (m_pakEnabled && m_mfxInterface->IsIntraRowstoreCacheEnabled() == false) |
| { |
| // Intra Row Store Scratch buffer |
| // 1 cacheline per MB |
| allocParamsForBufferLinear.dwBytes = m_picWidthInMb * CODECHAL_CACHELINE_SIZE; |
| allocParamsForBufferLinear.pBufName = "Intra Row Store Scratch Buffer"; |
| |
| eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_intraRowStoreScratchBuffer); |
| |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate Intra Row Store Scratch Buffer."); |
| return eStatus; |
| } |
| } |
| |
| if (m_sliceSizeStreamoutSupported) |
| { |
| // PAK Slice Size Streamout Buffer |
| allocParamsForBufferLinear.dwBytes = MOS_ALIGN_CEIL(CODECHAL_ENCODE_SLICESIZE_BUF_SIZE, CODECHAL_PAGE_SIZE); |
| allocParamsForBufferLinear.pBufName = "PAK Slice Size Streamout Buffer"; |
| |
| eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource( |
| m_osInterface, |
| &allocParamsForBufferLinear, |
| &m_pakSliceSizeStreamoutBuffer); |
| |
| if (eStatus != MOS_STATUS_SUCCESS) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("%s: Failed to allocate Slice Size Streamout Buffer\n", __FUNCTION__); |
| return eStatus; |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::SetSequenceStructs() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| auto seqParams = m_avcSeqParam; |
| |
| // seq_scaling_matrix_present_flag and chroma_format_idc |
| // shall not be present for main profile |
| if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE) |
| { |
| seqParams->seq_scaling_matrix_present_flag = 0; |
| for (uint8_t i = 0; i < 12; i++) |
| { |
| seqParams->seq_scaling_list_present_flag[i] = 0; |
| } |
| seqParams->chroma_format_idc = 1; |
| } |
| // high profile chroma_format_idc in the range of 0 to 1 inclusive |
| if (seqParams->chroma_format_idc > 1) |
| { |
| seqParams->chroma_format_idc = 1; |
| } |
| |
| // main & high profile support only 8bpp |
| seqParams->bit_depth_luma_minus8 = 0; |
| seqParams->bit_depth_chroma_minus8 = 0; |
| |
| seqParams->NumRefFrames = seqParams->NumRefFrames * 2; |
| |
| // setup parameters corresponding to H264 bit stream definition |
| seqParams->pic_height_in_map_units_minus1 = seqParams->frame_mbs_only_flag ? CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight) - 1 : (CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight) + 1) / 2 - 1; |
| seqParams->pic_width_in_mbs_minus1 = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(seqParams->FrameWidth) - 1; |
| seqParams->constraint_set0_flag = 0; |
| seqParams->constraint_set1_flag = (seqParams->Profile == CODEC_AVC_BASE_PROFILE) ? 1 : 0; |
| seqParams->constraint_set2_flag = 0; |
| seqParams->constraint_set3_flag = 0; |
| seqParams->gaps_in_frame_num_value_allowed_flag = 0; |
| seqParams->qpprime_y_zero_transform_bypass_flag = 0; |
| seqParams->separate_colour_plane_flag = 0; |
| |
| // setup internal parameters |
| m_picWidthInMb = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(seqParams->FrameWidth); |
| m_picHeightInMb = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(seqParams->FrameHeight); |
| 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; |
| |
| // UltraHME Scaling WxH |
| m_downscaledWidthInMb32x = |
| CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_32x); |
| m_downscaledHeightInMb32x = |
| CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_32x); |
| m_downscaledWidth32x = |
| m_downscaledWidthInMb32x * CODECHAL_MACROBLOCK_WIDTH; |
| m_downscaledHeight32x = |
| m_downscaledHeightInMb32x * CODECHAL_MACROBLOCK_HEIGHT; |
| |
| MotionEstimationDisableCheck(); |
| |
| m_kernelMode = |
| CodecHal_TargetUsageToMode_AVC[seqParams->TargetUsage & 0x7]; |
| m_targetUsage = seqParams->TargetUsage & 0x7; |
| |
| if (!seqParams->frame_cropping_flag) |
| { |
| // do cropping only when the picture dimension is not MB aligned... |
| seqParams->frame_crop_left_offset = 0; |
| seqParams->frame_crop_top_offset = 0; |
| |
| if (m_frameWidth != seqParams->FrameWidth || |
| m_frameHeight != seqParams->FrameHeight) |
| { |
| seqParams->frame_cropping_flag = 1; |
| seqParams->frame_crop_right_offset = (uint16_t)((m_frameWidth - seqParams->FrameWidth) >> 1); // 4:2:0 |
| seqParams->frame_crop_bottom_offset = (uint16_t)((m_frameHeight - seqParams->FrameHeight) >> (2 - seqParams->frame_mbs_only_flag)); // 4:2:0 |
| } |
| else |
| { |
| seqParams->frame_cropping_flag = 0; |
| seqParams->frame_crop_right_offset = 0; |
| seqParams->frame_crop_bottom_offset = 0; |
| } |
| } |
| |
| if (m_mfxInterface->IsRowStoreCachingSupported()) |
| { |
| MHW_VDBOX_ROWSTORE_PARAMS rowstoreParams; |
| MOS_ZeroMemory(&rowstoreParams, sizeof(rowstoreParams)); |
| rowstoreParams.Mode = CODECHAL_ENCODE_MODE_AVC; |
| rowstoreParams.dwPicWidth = m_frameWidth; |
| rowstoreParams.bIsFrame = (seqParams->frame_mbs_only_flag == 1); |
| m_hwInterface->SetRowstoreCachingOffsets(&rowstoreParams); |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::SetPictureStructs() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| auto picParams = m_avcPicParam; |
| auto seqParams = m_avcSeqParam; |
| auto avcRefList = &m_refList[0]; |
| auto avcPicIdx = &m_picIdx[0]; |
| auto slcParams = m_avcSliceParams; |
| |
| if (seqParams->Profile == CODEC_AVC_MAIN_PROFILE || seqParams->Profile == CODEC_AVC_BASE_PROFILE) |
| { |
| picParams->transform_8x8_mode_flag = 0; |
| picParams->pic_scaling_matrix_present_flag = 0; |
| for (uint8_t i = 0; i < 12; i++) |
| { |
| picParams->pic_scaling_list_present_flag[i] = 0; |
| } |
| picParams->second_chroma_qp_index_offset = picParams->chroma_qp_index_offset; |
| } |
| if (picParams->QpY < 0) |
| { |
| picParams->QpY = 25; // Set to default, recommended value used in simulation. |
| } |
| else if (picParams->QpY > CODECHAL_ENCODE_AVC_MAX_SLICE_QP) |
| { |
| picParams->QpY = CODECHAL_ENCODE_AVC_MAX_SLICE_QP; // Crop to 51 if larger |
| } |
| picParams->pic_init_qp_minus26 = picParams->QpY - 26; |
| |
| if (!seqParams->seq_scaling_matrix_present_flag) |
| { |
| if (!picParams->pic_scaling_matrix_present_flag) |
| ScalingListFlat(); |
| else if (!picParams->pic_scaling_list_present_flag[0]) |
| ScalingListFallbackRuleA(); |
| } |
| else if (!seqParams->seq_scaling_list_present_flag[0] && |
| !picParams->pic_scaling_list_present_flag[0]) |
| { // fall-back rule A |
| ScalingListFallbackRuleA(); |
| } |
| |
| picParams->num_slice_groups_minus1 = 0; // do not support flexible MB ordering |
| picParams->deblocking_filter_control_present_flag = 1; // always set to 1 |
| picParams->redundant_pic_cnt_present_flag = 0; |
| picParams->pic_init_qs_minus26 = 0; // not used |
| |
| m_userFlags = picParams->UserFlags; |
| m_nalUnitType = picParams->bIdrPic ? CODECHAL_ENCODE_AVC_NAL_UT_IDR_SLICE : CODECHAL_ENCODE_AVC_NAL_UT_SLICE; |
| m_frameNum = picParams->frame_num; |
| m_lastPicInSeq = picParams->bLastPicInSeq; |
| m_lastPicInStream = picParams->bLastPicInStream; |
| // App handles tail insertion for VDEnc dynamic slice in non-cp case |
| if (m_vdencNoTailInsertion) |
| { |
| m_lastPicInSeq = m_lastPicInStream = 0; |
| } |
| m_statusReportFeedbackNumber = picParams->StatusReportFeedbackNumber; |
| |
| auto prevPic = m_currOriginalPic; |
| auto prevIdx = prevPic.FrameIdx; |
| auto currPic = picParams->CurrOriginalPic; |
| auto currIdx = currPic.FrameIdx; |
| auto prevRefIdx = m_currReconstructedPic.FrameIdx; |
| auto currRefIdx = picParams->CurrReconstructedPic.FrameIdx; |
| |
| m_prevReconFrameIdx = m_currReconFrameIdx; |
| m_currReconFrameIdx = picParams->CurrReconstructedPic.FrameIdx; |
| |
| avcRefList[currRefIdx]->sRefReconBuffer = m_reconSurface; |
| avcRefList[currRefIdx]->sRefRawBuffer = m_rawSurface; |
| avcRefList[currRefIdx]->sFrameNumber = picParams->frame_num; |
| avcRefList[currRefIdx]->RefPic = currPic; |
| m_currOriginalPic = currPic; |
| m_currReconstructedPic = picParams->CurrReconstructedPic; |
| |
| if (picParams->FieldCodingFlag) |
| { |
| m_frameFieldHeight = ((m_frameHeight + 1) >> 1); |
| m_frameFieldHeightInMb = ((m_picHeightInMb + 1) >> 1); |
| m_downscaledFrameFieldHeightInMb4x = ((m_downscaledHeightInMb4x + 1) >> 1); |
| m_downscaledFrameFieldHeightInMb16x = ((m_downscaledHeightInMb16x + 1) >> 1); |
| m_downscaledFrameFieldHeightInMb32x = ((m_downscaledHeightInMb32x + 1) >> 1); |
| m_currEncBbSet = MB_ENC_Field_BB; |
| if (CodecHal_PictureIsFrame(prevPic) || prevIdx != currIdx || |
| ((prevPic.PicFlags != currPic.PicFlags) && !(slcParams->pic_order_cnt_lsb & 1))) |
| { |
| m_firstField = 1; |
| // Enable self referencing for both IDR and I pics |
| m_firstFieldIdrPic = (picParams->CodingType == I_TYPE) ? 1 : 0; |
| } |
| else |
| { |
| m_firstField = 0; |
| } |
| } |
| else |
| { |
| m_frameFieldHeight = m_frameHeight; |
| m_frameFieldHeightInMb = m_picHeightInMb; |
| m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x; |
| m_downscaledFrameFieldHeightInMb16x = m_downscaledHeightInMb16x; |
| m_downscaledFrameFieldHeightInMb32x = m_downscaledHeightInMb32x; |
| m_firstField = 1; |
| m_currEncBbSet = MB_ENC_Frame_BB; |
| } |
| |
| if (picParams->FieldFrameCodingFlag) |
| { // Mbaff |
| seqParams->mb_adaptive_frame_field_flag = 1; |
| m_mbaffEnabled = 1; |
| } |
| else |
| { |
| seqParams->mb_adaptive_frame_field_flag = 0; |
| m_mbaffEnabled = 0; |
| } |
| |
| // P/B frames with empty ref lists are internally encoded as I frames, |
| // while picture header packing remains the original value |
| m_pictureCodingType = picParams->CodingType; |
| |
| bool emptyRefFrmList = true; |
| for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) |
| { |
| if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID) |
| { |
| emptyRefFrmList = false; |
| break; |
| } |
| } |
| |
| if (emptyRefFrmList && m_pictureCodingType != I_TYPE) |
| { |
| m_pictureCodingType = I_TYPE; |
| } |
| |
| avcRefList[currRefIdx]->bUsedAsRef = picParams->RefPicFlag; |
| avcRefList[currRefIdx]->resBitstreamBuffer = m_resBitstreamBuffer; |
| |
| for (uint8_t i = 0; i < 16; i++) |
| { |
| m_avcFrameStoreID[i].inUse = false; |
| } |
| |
| for (uint8_t i = 0; i < 16; i++) |
| { |
| avcPicIdx[i].bValid = false; |
| if (picParams->RefFrameList[i].PicFlags != PICTURE_INVALID) |
| { |
| auto index = picParams->RefFrameList[i].FrameIdx; |
| uint8_t duplicatedIdx = 0; |
| for (uint8_t ii = 0; ii < i; ii++) |
| { |
| if (avcPicIdx[ii].bValid && index == picParams->RefFrameList[ii].FrameIdx) |
| { |
| duplicatedIdx = 1; |
| break; |
| } |
| } |
| if (duplicatedIdx) |
| { |
| continue; |
| } |
| |
| avcRefList[index]->RefPic.PicFlags = |
| CodecHal_CombinePictureFlags(avcRefList[index]->RefPic, picParams->RefFrameList[i]); |
| avcRefList[index]->iFieldOrderCnt[0] = picParams->FieldOrderCntList[i][0]; |
| avcRefList[index]->iFieldOrderCnt[1] = picParams->FieldOrderCntList[i][1]; |
| avcPicIdx[i].bValid = true; |
| avcPicIdx[i].ucPicIdx = index; |
| if (prevPic.PicFlags != PICTURE_INVALID) |
| { |
| uint8_t ii; |
| for (ii = 0; ii < avcRefList[prevRefIdx]->ucNumRef; ii++) |
| { |
| if (index == avcRefList[prevRefIdx]->RefList[ii].FrameIdx) |
| { |
| if (avcRefList[index]->ucFrameId == 0x1f) |
| { |
| // Should never happen, something must be wrong |
| CODECHAL_ENCODE_ASSERT(false); |
| avcRefList[index]->ucFrameId = 0; |
| } |
| m_avcFrameStoreID[avcRefList[index]->ucFrameId].inUse = true; |
| break; |
| } |
| } |
| if (ii == avcRefList[prevRefIdx]->ucNumRef) |
| { |
| avcRefList[index]->ucFrameId = 0x1f; |
| } |
| } |
| } |
| } |
| |
| // Save the current RefList |
| uint8_t ii = 0; |
| for (uint8_t i = 0; i < 16; i++) |
| { |
| if (avcPicIdx[i].bValid) |
| { |
| avcRefList[currRefIdx]->RefList[ii] = picParams->RefFrameList[i]; |
| ii++; |
| } |
| } |
| avcRefList[currRefIdx]->ucNumRef = ii; |
| m_currRefList = avcRefList[currRefIdx]; |
| |
| if (m_codecFunction == CODECHAL_FUNCTION_ENC) |
| { |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeParams.presMbCodeSurface); |
| m_resMbCodeSurface = *(m_encodeParams.presMbCodeSurface); |
| } |
| else if (m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) |
| { |
| if (m_encodeParams.presMbCodeSurface == nullptr || |
| Mos_ResourceIsNull(m_encodeParams.presMbCodeSurface)) |
| { |
| // the actual MbCode/MvData surface to be allocated later |
| m_trackedBuf->SetAllocationFlag(true); |
| } |
| else |
| { |
| m_resMbCodeSurface = *(m_encodeParams.presMbCodeSurface); |
| m_resMvDataSurface = *(m_encodeParams.presMbCodeSurface); |
| } |
| } |
| else if (CodecHalIsFeiEncode(m_codecFunction)) |
| { |
| CodecEncodeAvcFeiPicParams *feiPicParams; |
| |
| feiPicParams = (CodecEncodeAvcFeiPicParams *)m_encodeParams.pFeiPicParams; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(feiPicParams); |
| |
| // Use app provided buffer if available. For FEI_ENC and FEI_PAK, MBCodeMvEnable needs to be set to true |
| if (feiPicParams->MbCodeMvEnable) |
| { |
| m_resMbCodeSurface = feiPicParams->resMBCode; |
| m_resMvDataSurface = feiPicParams->resMVData; |
| |
| // Inside the AvcRefList, mbCodesurface and mvdatasurface are stored at frame basis, |
| // For FEI, mbcode and mv data buffer are provided separately for each field picture and we need to store them separately. |
| if (CodecHal_PictureIsTopField(picParams->CurrOriginalPic)) |
| { |
| avcRefList[currRefIdx]->resRefTopFieldMbCodeBuffer = m_resMbCodeSurface; |
| avcRefList[currRefIdx]->resRefTopFieldMvDataBuffer = m_resMvDataSurface; |
| } |
| else if (CodecHal_PictureIsBottomField(picParams->CurrOriginalPic)) |
| { |
| avcRefList[currRefIdx]->resRefBotFieldMbCodeBuffer = m_resMbCodeSurface; |
| avcRefList[currRefIdx]->resRefBotFieldMvDataBuffer = m_resMvDataSurface; |
| } |
| |
| avcRefList[currRefIdx]->resRefMbCodeBuffer = m_resMbCodeSurface; |
| avcRefList[currRefIdx]->resRefMvDataBuffer = m_resMvDataSurface; |
| } |
| else |
| { |
| // the actual MbCode/MvData surface to be allocated later |
| m_trackedBuf->SetAllocationFlag(true); |
| } |
| |
| if (feiPicParams->DistortionEnable) |
| { |
| m_resDistortionBuffer = feiPicParams->resDistortion; |
| } |
| } |
| |
| SetFrameStoreIds(currRefIdx); |
| |
| avcRefList[currRefIdx]->iFieldOrderCnt[0] = picParams->CurrFieldOrderCnt[0]; |
| avcRefList[currRefIdx]->iFieldOrderCnt[1] = picParams->CurrFieldOrderCnt[1]; |
| m_refList[currRefIdx]->ucAvcPictureCodingType = (CodecHal_PictureIsFrame(picParams->CurrOriginalPic)) ? CODEC_AVC_PIC_CODING_TYPE_FRAME : ((picParams->CurrFieldOrderCnt[0] < picParams->CurrFieldOrderCnt[1]) ? CODEC_AVC_PIC_CODING_TYPE_TFF_FIELD : CODEC_AVC_PIC_CODING_TYPE_BFF_FIELD); |
| |
| m_hmeEnabled = m_hmeSupported && m_pictureCodingType != I_TYPE; |
| m_16xMeEnabled = m_16xMeSupported && m_pictureCodingType != I_TYPE; |
| m_32xMeEnabled = m_32xMeSupported && m_pictureCodingType != I_TYPE; |
| |
| if (m_pictureCodingType == B_TYPE) |
| { |
| GetDistScaleFactor(); |
| m_biWeight = GetBiWeight( |
| m_distScaleFactorList0[0], |
| m_avcPicParam->weighted_bipred_idc); |
| } |
| |
| m_verticalLineStride = CODECHAL_VLINESTRIDE_FRAME; |
| m_verticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_TOP_FIELD; |
| m_mbcodeBottomFieldOffset = 0; |
| m_mvBottomFieldOffset = 0; |
| m_meDistortionBottomFieldOffset = 0; |
| m_meMvBottomFieldOffset = 0; |
| m_meMv16xBottomFieldOffset = 0; |
| m_meMv32xBottomFieldOffset = 0; |
| m_sliceMapBottomFieldOffset = 0; |
| if (m_hmeKernel) |
| { |
| m_hmeKernel->Set4xMeMvBottomFieldOffset(0); |
| m_hmeKernel->Set16xMeMvBottomFieldOffset(0); |
| m_hmeKernel->Set32xMeMvBottomFieldOffset(0); |
| m_hmeKernel->SetDistortionBottomFieldOffset(0); |
| } |
| |
| if (CodecHal_PictureIsField(m_currOriginalPic)) |
| { |
| m_verticalLineStride = CODECHAL_VLINESTRIDE_FIELD; |
| m_frameHeight = m_frameFieldHeightInMb * 2 * 16; |
| m_picHeightInMb = (uint16_t)(m_frameHeight / 16); |
| if (CodecHal_PictureIsBottomField(m_currOriginalPic)) |
| { |
| m_sliceMapBottomFieldOffset = MOS_ALIGN_CEIL((m_picWidthInMb + 1) * sizeof(uint32_t), 64) * m_frameFieldHeightInMb; |
| m_verticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_BOT_FIELD; |
| |
| if (CodecHalIsFeiEncode(m_codecFunction)) |
| { |
| CodecEncodeAvcFeiPicParams *feiPicParams; |
| |
| feiPicParams = (CodecEncodeAvcFeiPicParams *)m_encodeParams.pFeiPicParams; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(feiPicParams); |
| |
| // for user provided MbCode and Mv data buffer, set BottomFieldOffset to 0 |
| if (feiPicParams->MbCodeMvEnable) |
| { |
| m_mbcodeBottomFieldOffset = 0; |
| m_mvBottomFieldOffset = 0; |
| } |
| else |
| { |
| m_mbcodeBottomFieldOffset = m_frameFieldHeightInMb * m_picWidthInMb * 64; |
| m_mvBottomFieldOffset = |
| MOS_ALIGN_CEIL(m_frameFieldHeightInMb * m_picWidthInMb * (32 * 4), CODECHAL_PAGE_SIZE); |
| } |
| } |
| else |
| { |
| m_mbcodeBottomFieldOffset = m_frameFieldHeightInMb * m_picWidthInMb * 64; |
| m_mvBottomFieldOffset = |
| MOS_ALIGN_CEIL(m_frameFieldHeightInMb * m_picWidthInMb * (32 * 4), CODECHAL_PAGE_SIZE); |
| } |
| |
| m_meDistortionBottomFieldOffset = |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * |
| MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4 * 10), 8); |
| m_meMvBottomFieldOffset = |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb4x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| if (m_16xMeEnabled) |
| { |
| m_meMv16xBottomFieldOffset = |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb16x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| if (m_32xMeEnabled) |
| { |
| m_meMv32xBottomFieldOffset = |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb32x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| } |
| } |
| |
| if (m_hmeKernel) |
| { |
| m_hmeKernel->SetDistortionBottomFieldOffset( |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * |
| MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4 * 10), 8)); |
| m_hmeKernel->Set4xMeMvBottomFieldOffset( |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb4x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER)); |
| if (m_hmeKernel->Is16xMeEnabled()) |
| { |
| m_hmeKernel->Set16xMeMvBottomFieldOffset( |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb16x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER)); |
| if (m_hmeKernel->Is32xMeEnabled()) |
| { |
| m_hmeKernel->Set32xMeMvBottomFieldOffset( |
| MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) * |
| (m_downscaledFrameFieldHeightInMb32x * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER)); |
| } |
| } |
| } |
| } |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::EncodeMeKernel( |
| EncodeBrcBuffers *brcBuffers, |
| HmeLevel hmeLevel) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| PerfTagSetting perfTag; |
| perfTag.Value = 0; |
| perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; |
| perfTag.CallType = m_singleTaskPhaseSupported ? CODECHAL_ENCODE_PERFTAG_CALL_SCALING_KERNEL : CODECHAL_ENCODE_PERFTAG_CALL_ME_KERNEL; |
| perfTag.PictureCodingType = m_pictureCodingType; |
| m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); |
| // Each ME kernel buffer counts as a separate perf task |
| m_osInterface->pfnResetPerfBufferID(m_osInterface); |
| |
| CODECHAL_MEDIA_STATE_TYPE encFunctionType = (hmeLevel == HME_LEVEL_32x) ? CODECHAL_MEDIA_STATE_32X_ME : (hmeLevel == HME_LEVEL_16x) ? CODECHAL_MEDIA_STATE_16X_ME : CODECHAL_MEDIA_STATE_4X_ME; |
| |
| bool vdencMeInUse = false; |
| if (m_vdencEnabled && (encFunctionType == CODECHAL_MEDIA_STATE_4X_ME)) |
| { |
| vdencMeInUse = true; |
| encFunctionType = CODECHAL_MEDIA_STATE_ME_VDENC_STREAMIN; |
| } |
| |
| uint32_t krnStateIdx = vdencMeInUse ? CODECHAL_ENCODE_ME_IDX_VDENC : ((m_pictureCodingType == P_TYPE) ? CODECHAL_ENCODE_ME_IDX_P : CODECHAL_ENCODE_ME_IDX_B); |
| auto kernelState = &m_meKernelStates[krnStateIdx]; |
| |
| // If Single Task Phase is not enabled, use BT count for the kernel state. |
| if (m_firstTaskInPhase || !m_singleTaskPhaseSupported) |
| { |
| uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf( |
| m_stateHeapInterface, |
| maxBtCount)); |
| m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable()); |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( |
| m_stateHeapInterface, |
| kernelState, |
| false, |
| 0, |
| false, |
| m_storeData)); |
| |
| MHW_INTERFACE_DESCRIPTOR_PARAMS idParams; |
| MOS_ZeroMemory(&idParams, sizeof(idParams)); |
| idParams.pKernelState = kernelState; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( |
| m_stateHeapInterface, |
| 1, |
| &idParams)); |
| |
| // Setup AVC Curbe |
| MeCurbeParams meParams; |
| MOS_ZeroMemory(&meParams, sizeof(meParams)); |
| meParams.hmeLvl = hmeLevel; |
| meParams.pKernelState = kernelState; |
| |
| if (!m_useCommonKernel) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeMe(&meParams)); |
| } |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_DSH_TYPE, |
| kernelState)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( |
| encFunctionType, |
| kernelState)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_ISH_TYPE, |
| kernelState));) |
| |
| MOS_COMMAND_BUFFER cmdBuffer; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); |
| |
| SendKernelCmdsParams sendKernelCmdsParams = SendKernelCmdsParams(); |
| sendKernelCmdsParams.EncFunctionType = encFunctionType; |
| sendKernelCmdsParams.pKernelState = kernelState; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams)); |
| |
| // Add binding table |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable( |
| m_stateHeapInterface, |
| kernelState)); |
| |
| //Add surface states |
| MeSurfaceParams meSurfaceParams; |
| MOS_ZeroMemory(&meSurfaceParams, sizeof(meSurfaceParams)); |
| meSurfaceParams.dwNumRefIdxL0ActiveMinus1 = m_avcSliceParams->num_ref_idx_l0_active_minus1; |
| meSurfaceParams.dwNumRefIdxL1ActiveMinus1 = m_avcSliceParams->num_ref_idx_l1_active_minus1; |
| meSurfaceParams.pL0RefFrameList = &(m_avcSliceParams->RefPicList[LIST_0][0]); |
| meSurfaceParams.pL1RefFrameList = &(m_avcSliceParams->RefPicList[LIST_1][0]); |
| meSurfaceParams.ppRefList = &m_refList[0]; |
| meSurfaceParams.pPicIdx = &m_picIdx[0]; |
| meSurfaceParams.pCurrOriginalPic = &m_currOriginalPic; |
| meSurfaceParams.ps4xMeMvDataBuffer = &m_4xMeMvDataBuffer; |
| meSurfaceParams.dw4xMeMvBottomFieldOffset = (uint32_t)m_meMvBottomFieldOffset; |
| meSurfaceParams.ps16xMeMvDataBuffer = &m_16xMeMvDataBuffer; |
| meSurfaceParams.dw16xMeMvBottomFieldOffset = (uint32_t)m_meMv16xBottomFieldOffset; |
| meSurfaceParams.ps32xMeMvDataBuffer = &m_32xMeMvDataBuffer; |
| meSurfaceParams.dw32xMeMvBottomFieldOffset = (uint32_t)m_meMv32xBottomFieldOffset; |
| meSurfaceParams.dw4xScaledBottomFieldOffset = (uint32_t)m_scaledBottomFieldOffset; |
| meSurfaceParams.dw16xScaledBottomFieldOffset = (uint32_t)m_scaled16xBottomFieldOffset; |
| meSurfaceParams.dw32xScaledBottomFieldOffset = (uint32_t)m_scaled32xBottomFieldOffset; |
| meSurfaceParams.psMeDistortionBuffer = &m_4xMeDistortionBuffer; |
| meSurfaceParams.dwMeDistortionBottomFieldOffset = (uint32_t)m_meDistortionBottomFieldOffset; |
| if (nullptr != brcBuffers) |
| { |
| meSurfaceParams.psMeBrcDistortionBuffer = &brcBuffers->sMeBrcDistortionBuffer; |
| meSurfaceParams.dwMeBrcDistortionBottomFieldOffset = brcBuffers->dwMeBrcDistortionBottomFieldOffset; |
| } |
| meSurfaceParams.psMeVdencStreamInBuffer = &m_resVdencStreamInBuffer[m_currRecycledBufIdx]; |
| meSurfaceParams.dwDownscaledWidthInMb = (hmeLevel == HME_LEVEL_32x) ? m_downscaledWidthInMb32x : (hmeLevel == HME_LEVEL_16x) ? m_downscaledWidthInMb16x : m_downscaledWidthInMb4x; |
| meSurfaceParams.dwDownscaledHeightInMb = (hmeLevel == HME_LEVEL_32x) ? m_downscaledFrameFieldHeightInMb32x : (hmeLevel == HME_LEVEL_16x) ? m_downscaledFrameFieldHeightInMb16x : m_downscaledFrameFieldHeightInMb4x; |
| meSurfaceParams.dwVerticalLineStride = m_verticalLineStride; |
| meSurfaceParams.dwVerticalLineStrideOffset = m_verticalLineStrideOffset; |
| meSurfaceParams.b32xMeInUse = (hmeLevel == HME_LEVEL_32x) ? true : false; |
| meSurfaceParams.b16xMeInUse = (hmeLevel == HME_LEVEL_16x) ? true : false; |
| meSurfaceParams.b32xMeEnabled = m_32xMeEnabled; |
| meSurfaceParams.b16xMeEnabled = m_16xMeEnabled; |
| meSurfaceParams.bVdencStreamInEnabled = m_vdencEnabled && (m_16xMeSupported || m_staticFrameDetectionInUse); |
| meSurfaceParams.pMeBindingTable = &m_meBindingTable; |
| meSurfaceParams.pKernelState = kernelState; |
| meSurfaceParams.dwVDEncStreamInSurfaceSize = MOS_BYTES_TO_DWORDS(m_picHeightInMb * m_picWidthInMb * 64); |
| |
| if (!m_useCommonKernel) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(SendMeSurfaces(&cmdBuffer, &meSurfaceParams)); |
| } |
| |
| // Dump SSH for ME kernel |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( |
| encFunctionType, |
| MHW_SSH_TYPE, |
| kernelState))); |
| |
| /* zero out the mv data memory and me distortion buffer for the driver ULT |
| kernel only writes out this data used for current frame, in some cases the the data used for |
| previous frames would be left in the buffer (for example, the L1 mv for B frame would still show |
| in the P frame mv data buffer */ |
| |
| /* Zeroing out the buffers has perf impact, so zero it out only when dumps are actually enabled */ |
| |
| CODECHAL_DEBUG_TOOL( |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface); |
| uint8_t * data; |
| uint32_t size; |
| bool driverMeDumpEnabled; |
| |
| driverMeDumpEnabled = m_debugInterface->DumpIsEnabled(CodechalDbgKernel::kernel4xMe) || |
| m_debugInterface->DumpIsEnabled(CodechalDbgKernel::kernel16xMe) || |
| m_debugInterface->DumpIsEnabled(CodechalDbgKernel::kernel32xMe); |
| |
| if (driverMeDumpEnabled) { |
| MOS_LOCK_PARAMS lockFlags; |
| MOS_ZeroMemory(&lockFlags, sizeof(MOS_LOCK_PARAMS)); |
| lockFlags.WriteOnly = 1; |
| |
| switch (hmeLevel) |
| { |
| case HME_LEVEL_32x: |
| data = (uint8_t *)m_osInterface->pfnLockResource( |
| m_osInterface, |
| &m_32xMeMvDataBuffer.OsResource, |
| &lockFlags); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(data); |
| size = MOS_ALIGN_CEIL((m_downscaledWidthInMb32x * 32), 64) * |
| (m_downscaledHeightInMb32x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| MOS_ZeroMemory(data, size); |
| m_osInterface->pfnUnlockResource( |
| m_osInterface, |
| &m_32xMeMvDataBuffer.OsResource); |
| break; |
| case HME_LEVEL_16x: |
| data = (uint8_t *)m_osInterface->pfnLockResource( |
| m_osInterface, |
| &m_16xMeMvDataBuffer.OsResource, |
| &lockFlags); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(data); |
| size = MOS_ALIGN_CEIL((m_downscaledWidthInMb16x * 32), 64) * |
| (m_downscaledHeightInMb16x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| MOS_ZeroMemory(data, size); |
| m_osInterface->pfnUnlockResource( |
| m_osInterface, |
| &m_16xMeMvDataBuffer.OsResource); |
| break; |
| case HME_LEVEL_4x: |
| if (!m_vdencEnabled) |
| { |
| data = (uint8_t *)m_osInterface->pfnLockResource( |
| m_osInterface, |
| &m_4xMeMvDataBuffer.OsResource, |
| &lockFlags); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(data); |
| size = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * |
| (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); |
| MOS_ZeroMemory(data, size); |
| m_osInterface->pfnUnlockResource( |
| m_osInterface, |
| &m_4xMeMvDataBuffer.OsResource); |
| } |
| break; |
| default: |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| // zeroing out ME dist buffer |
| if (m_4xMeDistortionBufferSupported) |
| { |
| data = (uint8_t *)m_osInterface->pfnLockResource( |
| m_osInterface, &m_4xMeDistortionBuffer.OsResource, &lockFlags); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(data); |
| size = m_4xMeDistortionBuffer.dwHeight * m_4xMeDistortionBuffer.dwPitch; |
| MOS_ZeroMemory(data, size); |
| m_osInterface->pfnUnlockResource( |
| m_osInterface, |
| &m_4xMeDistortionBuffer.OsResource); |
| } |
| }); |
| |
| uint32_t scalingFactor = (hmeLevel == HME_LEVEL_32x) ? SCALE_FACTOR_32x : (hmeLevel == HME_LEVEL_16x) ? SCALE_FACTOR_16x : SCALE_FACTOR_4x; |
| |
| uint32_t resolutionX = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / scalingFactor); |
| uint32_t resolutionY = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameFieldHeight / scalingFactor); |
| |
| CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams; |
| MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams)); |
| walkerCodecParams.WalkerMode = m_walkerMode; |
| walkerCodecParams.dwResolutionX = resolutionX; |
| walkerCodecParams.dwResolutionY = resolutionY; |
| walkerCodecParams.bNoDependency = true; |
| walkerCodecParams.bMbaff = m_mbaffEnabled; |
| walkerCodecParams.bGroupIdSelectSupported = m_groupIdSelectSupported; |
| walkerCodecParams.ucGroupId = m_groupId; |
| |
| MHW_WALKER_PARAMS walkerParams; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams( |
| m_hwInterface, |
| &walkerParams, |
| &walkerCodecParams)); |
| |
| HalOcaInterface::TraceMessage(cmdBuffer, *m_osInterface->pOsContext, __FUNCTION__, sizeof(__FUNCTION__)); |
| HalOcaInterface::OnDispatch(cmdBuffer, *m_osInterface->pOsContext, *m_miInterface, *m_renderEngineInterface->GetMmioRegisters()); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaObjectWalkerCmd( |
| &cmdBuffer, |
| &walkerParams)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType)); |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks( |
| m_stateHeapInterface, |
| kernelState)); |
| if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) |
| { |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId( |
| m_stateHeapInterface)); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); |
| } |
| |
| CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( |
| &cmdBuffer, |
| encFunctionType, |
| nullptr))); |
| |
| m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase); |
| |
| m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); |
| |
| if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) |
| { |
| HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); |
| m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw); |
| m_lastTaskInPhase = false; |
| } |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::SetSliceStructs() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| auto slcParams = m_avcSliceParams; |
| auto seqParams = m_avcSeqParam; |
| auto picParams = m_avcPicParam; |
| |
| // Save the QP value |
| if (CodecHal_PictureIsBottomField(picParams->CurrOriginalPic)) |
| { |
| m_refList[m_currReconstructedPic.FrameIdx]->ucQPValue[1] = |
| picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta; |
| } |
| else |
| { |
| m_refList[m_currReconstructedPic.FrameIdx]->ucQPValue[0] = |
| picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta; |
| } |
| |
| uint32_t numMbsInPrevSlice = slcParams->NumMbsForSlice; // Initiailize to num mbs in first slice |
| uint32_t numMbsForFirstSlice; |
| uint32_t numMbs = 0; |
| |
| for (uint32_t sliceCount = 0; sliceCount < m_numSlices; sliceCount++) |
| { |
| if (m_sliceStructCaps != CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE) |
| { |
| if (sliceCount == 0) |
| { |
| numMbsForFirstSlice = slcParams->NumMbsForSlice; |
| // In current kernel, the same MB number in the slice must be number of MB rows. |
| if (numMbsForFirstSlice % m_picWidthInMb) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| return eStatus; |
| } |
| m_sliceHeight = numMbsForFirstSlice / m_picWidthInMb; |
| // Slice height should be in power of 2 |
| if (m_sliceStructCaps == CODECHAL_SLICE_STRUCT_POW2ROWS && (m_sliceHeight & (m_sliceHeight - 1))) |
| { |
| // app can only pass orig numMBs in picture for single slice, set slice height to the nearest pow2 |
| if (m_numSlices == 1) |
| { |
| uint16_t sliceHeightPow2 = 1; |
| while (sliceHeightPow2 < m_sliceHeight) |
| { |
| sliceHeightPow2 <<= 1; |
| } |
| m_sliceHeight = sliceHeightPow2; |
| } |
| else |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| return eStatus; |
| } |
| } |
| } |
| // VME: In current kernel, all slices should have the same MBs except the last one, the last one should have no more MBs than the previous |
| else if (!m_vdencEnabled || (m_vdencEnabled && m_sliceStructCaps == CODECHAL_SLICE_STRUCT_ROWSLICE)) |
| { |
| if ((sliceCount < m_numSlices - 1 && numMbsForFirstSlice != slcParams->NumMbsForSlice) || |
| (sliceCount == m_numSlices - 1 && numMbsForFirstSlice < slcParams->NumMbsForSlice)) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| return eStatus; |
| } |
| } |
| |
| // Gaps between slices are not allowed |
| if (slcParams->first_mb_in_slice != numMbs) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| return eStatus; |
| } |
| numMbs += slcParams->NumMbsForSlice; |
| } |
| else // SLICE_STRUCT_ARBITRARYMBSLICE |
| { |
| uint8_t ppsIdx = m_avcSliceParams->pic_parameter_set_id; |
| uint8_t refPicListIdx = m_avcSliceParams[ppsIdx].RefPicList[0][0].FrameIdx; |
| uint8_t refFrameListIdx = m_avcPicParam[ppsIdx].RefFrameList[refPicListIdx].FrameIdx; |
| |
| bool dirtyRoiEnabled = (m_pictureCodingType == P_TYPE && m_avcPicParams[ppsIdx]->NumDirtyROI > 0 && m_prevReconFrameIdx == refFrameListIdx); |
| |
| if (m_mfeEnabled && m_numSlices > 1) |
| { |
| m_arbitraryNumMbsInSlice = 1; |
| if (sliceCount == 0) |
| { |
| m_sliceHeight = slcParams->NumMbsForSlice / m_picWidthInMb; |
| } |
| } |
| else if ((slcParams->NumMbsForSlice % m_picWidthInMb) || // If slice is partial MB row, |
| ((sliceCount < m_numSlices - 1) && (numMbsInPrevSlice != slcParams->NumMbsForSlice)) || // OR not the last slice and num mbs is not same as prev slice |
| ((sliceCount == m_numSlices - 1) && ((numMbsInPrevSlice < slcParams->NumMbsForSlice) || // OR it is the last slice and num mbs is not less than prev slice |
| (MEDIA_IS_WA(m_waTable, WaArbitraryNumMbsInSlice) && (m_numSlices > 16) && |
| (!m_vdencEnabled) && (!dirtyRoiEnabled))))) |
| { |
| m_arbitraryNumMbsInSlice = 1; // then set flag to use sliceMapSurface |
| m_sliceHeight = 1; // Slice height doesn't matter if using slicemap just set to any non-zero value. |
| } |
| else if ((m_numSlices == 1) || (sliceCount == 0)) |
| { |
| m_sliceHeight = slcParams->NumMbsForSlice / m_picWidthInMb; |
| m_arbitraryNumMbsInSlice = 0; |
| } |
| numMbsInPrevSlice = slcParams->NumMbsForSlice; |
| } |
| |
| if ((picParams->pic_init_qp_minus26 + 26 + slcParams->slice_qp_delta) > CODECHAL_ENCODE_AVC_MAX_SLICE_QP) |
| { |
| slcParams->slice_qp_delta = CODECHAL_ENCODE_AVC_MAX_SLICE_QP - (picParams->pic_init_qp_minus26 + 26); |
| } |
| else |
| { |
| slcParams->slice_qp_delta = slcParams->slice_qp_delta; |
| } |
| slcParams->redundant_pic_cnt = 0; |
| slcParams->sp_for_switch_flag = 0; |
| slcParams->slice_qs_delta = 0; |
| slcParams->ref_pic_list_reordering_flag_l0 = 0; |
| slcParams->ref_pic_list_reordering_flag_l1 = 0; |
| slcParams->adaptive_ref_pic_marking_mode_flag = 0; |
| slcParams->no_output_of_prior_pics_flag = 0; |
| slcParams->redundant_pic_cnt = 0; |
| |
| slcParams->MaxFrameNum = |
| 1 << (seqParams[picParams->seq_parameter_set_id].log2_max_frame_num_minus4 + 4); |
| slcParams->frame_num = m_frameNum; |
| slcParams->field_pic_flag = picParams->FieldCodingFlag; |
| slcParams->bottom_field_flag = |
| (CodecHal_PictureIsBottomField(picParams->CurrOriginalPic)) ? 1 : 0; |
| |
| if (m_pictureCodingType != I_TYPE) |
| { |
| for (uint8_t i = 0; i < (slcParams->num_ref_idx_l0_active_minus1 + 1); i++) |
| { |
| slcParams->PicOrder[0][i].Picture.FrameIdx = |
| m_picIdx[slcParams->RefPicList[0][i].FrameIdx].ucPicIdx; |
| slcParams->PicOrder[0][i].Picture.PicFlags = |
| slcParams->RefPicList[0][i].PicFlags; |
| } |
| } |
| if (m_pictureCodingType == B_TYPE) |
| { |
| for (uint8_t i = 0; i < (slcParams->num_ref_idx_l1_active_minus1 + 1); i++) |
| { |
| slcParams->PicOrder[1][i].Picture.FrameIdx = |
| m_picIdx[slcParams->RefPicList[1][i].FrameIdx].ucPicIdx; |
| slcParams->PicOrder[1][i].Picture.PicFlags = |
| slcParams->RefPicList[1][i].PicFlags; |
| } |
| } |
| slcParams++; |
| } |
| |
| if (eStatus == MOS_STATUS_INVALID_PARAMETER) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Invalid slice parameters."); |
| } |
| return eStatus; |
| } |
| |
| void CodechalEncodeAvcBase::SetMfxPipeModeSelectParams( |
| const CODECHAL_ENCODE_AVC_GENERIC_PICTURE_LEVEL_PARAMS &genericParam, |
| MHW_VDBOX_PIPE_MODE_SELECT_PARAMS & param) |
| { |
| // set MFX_PIPE_MODE_SELECT values |
| param = {}; |
| param.Mode = m_mode; |
| param.bStreamOutEnabled = (m_currPass != m_numPasses); // Disable Stream Out for final pass; its important for multiple passes, because , next pass will take the qp from stream out |
| param.bVdencEnabled = m_vdencEnabled; |
| param.bDeblockerStreamOutEnable = genericParam.bDeblockerStreamOutEnable; |
| param.bStreamOutEnabledExtEnabled = genericParam.bPerMBStreamOutEnable; |
| param.bPostDeblockOutEnable = genericParam.bPostDeblockOutEnable; |
| param.bPreDeblockOutEnable = genericParam.bPreDeblockOutEnable; |
| param.bDynamicSliceEnable = m_avcSeqParam->EnableSliceLevelRateCtrl; |
| param.bVdencStreamInEnable = m_vdencStreamInEnabled; |
| param.bTlbPrefetchEnable = m_tlbPrefetchEnable; |
| param.ChromaType = m_avcSeqParam->chroma_format_idc; |
| param.Format = m_rawSurfaceToPak->Format; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::SetMfxPipeBufAddrStateParams( |
| CODECHAL_ENCODE_AVC_GENERIC_PICTURE_LEVEL_PARAMS genericParam, |
| MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & param) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| param.Mode = m_mode; |
| param.psPreDeblockSurface = genericParam.psPreDeblockSurface; |
| param.psPostDeblockSurface = genericParam.psPostDeblockSurface; |
| |
| param.psRawSurface = m_rawSurfaceToPak; |
| param.presStreamOutBuffer = &m_resStreamOutBuffer[m_currRecycledBufIdx]; |
| param.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resDeblockingFilterRowStoreScratchBuffer; |
| param.presMfdIntraRowStoreScratchBuffer = &m_intraRowStoreScratchBuffer; |
| param.bVdencEnabled = m_vdencEnabled; |
| param.presMacroblockIldbStreamOutBuffer1 = genericParam.presMacroblockIldbStreamOutBuffer1; |
| param.presMacroblockIldbStreamOutBuffer2 = genericParam.presMacroblockIldbStreamOutBuffer2; |
| |
| CODECHAL_DEBUG_TOOL( |
| // PAK Input Raw Surface |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| m_rawSurfaceToPak, |
| CodechalDbgAttr::attrEncodeRawInputSurface, |
| "PAK_Input_SrcSurf"));); |
| |
| auto firstValidFrame = &m_reconSurface.OsResource; |
| |
| // Setting invalid entries to nullptr |
| for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) |
| param.presReferences[i] = nullptr; |
| |
| uint8_t firstValidFrameId = CODEC_AVC_MAX_NUM_REF_FRAME; |
| uint8_t numrefL0 = m_avcSliceParams->num_ref_idx_l0_active_minus1 + 1; |
| uint8_t numrefL1 = m_avcSliceParams->num_ref_idx_l1_active_minus1 + 1; |
| |
| for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) |
| { |
| if (m_picIdx[i].bValid) |
| { |
| auto picIdx = m_picIdx[i].ucPicIdx; |
| auto frameStoreId = m_refList[picIdx]->ucFrameId; |
| |
| CodecHalGetResourceInfo(m_osInterface, &(m_refList[picIdx]->sRefReconBuffer)); |
| param.presReferences[frameStoreId] = &(m_refList[picIdx]->sRefReconBuffer.OsResource); |
| |
| if (picIdx < firstValidFrameId) |
| { |
| firstValidFrameId = picIdx; |
| firstValidFrame = param.presReferences[picIdx]; |
| } |
| |
| } |
| } |
| CODECHAL_DEBUG_TOOL( |
| MOS_SURFACE refSurface; |
| for (uint8_t i = 0; i < numrefL0; i++) |
| { |
| if (m_pictureCodingType != I_TYPE && m_avcSliceParams->RefPicList[0][i].PicFlags != PICTURE_INVALID) |
| { |
| auto refPic = m_avcSliceParams->RefPicList[0][i]; |
| auto picIdx = m_picIdx[refPic.FrameIdx].ucPicIdx; |
| auto frameStoreId = m_refList[picIdx]->ucFrameId; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface); |
| |
| MOS_ZeroMemory(&refSurface, sizeof(refSurface)); |
| refSurface.Format = Format_NV12; |
| refSurface.OsResource = *(param.presReferences[frameStoreId]); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( |
| m_osInterface, |
| &refSurface)); |
| m_debugInterface->m_refIndex = frameStoreId; |
| std::string refSurfName = "RefSurfL0[" + std::to_string(static_cast<uint32_t>(i)) + "]"; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| &refSurface, |
| CodechalDbgAttr::attrReferenceSurfaces, |
| refSurfName.c_str())); |
| } |
| } |
| for (uint8_t i = 0; i < numrefL1; i++) |
| { |
| if (m_pictureCodingType == B_TYPE && m_avcSliceParams->RefPicList[1][i].PicFlags != PICTURE_INVALID) |
| { |
| auto refPic = m_avcSliceParams->RefPicList[1][i]; |
| auto picIdx = m_picIdx[refPic.FrameIdx].ucPicIdx; |
| auto frameStoreId = m_refList[picIdx]->ucFrameId; |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface); |
| //MOS_SURFACE refSurface; |
| MOS_ZeroMemory(&refSurface, sizeof(refSurface)); |
| refSurface.Format = Format_NV12; |
| refSurface.OsResource = *(param.presReferences[frameStoreId]); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( |
| m_osInterface, |
| &refSurface)); |
| m_debugInterface->m_refIndex = frameStoreId; |
| std::string refSurfName = "RefSurfL1[" + std::to_string(static_cast<uint32_t>(i)) + "]"; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( |
| &refSurface, |
| CodechalDbgAttr::attrReferenceSurfaces, |
| refSurfName.c_str())); |
| } |
| } |
| |
| ); |
| |
| for (uint8_t i = 0; i < CODEC_AVC_MAX_NUM_REF_FRAME; i++) |
| { |
| // error concealment for the unset reference addresses |
| if (!param.presReferences[i]) |
| { |
| param.presReferences[i] = firstValidFrame; |
| } |
| } |
| |
| if (m_sliceSizeStreamoutSupported) |
| { |
| param.presSliceSizeStreamOutBuffer = &m_pakSliceSizeStreamoutBuffer; |
| } |
| return eStatus; |
| } |
| |
| void CodechalEncodeAvcBase::SetMfxIndObjBaseAddrStateParams(MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS ¶m) |
| { |
| MOS_ZeroMemory(¶m, sizeof(param)); |
| param.Mode = CODECHAL_ENCODE_MODE_AVC; |
| param.presPakBaseObjectBuffer = &m_resBitstreamBuffer; |
| param.dwPakBaseObjectSize = m_bitstreamUpperBound; |
| } |
| |
| void CodechalEncodeAvcBase::SetMfxBspBufBaseAddrStateParams(MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS ¶m) |
| { |
| MOS_ZeroMemory(¶m, sizeof(param)); |
| param.presBsdMpcRowStoreScratchBuffer = &m_resMPCRowStoreScratchBuffer; |
| } |
| |
| void CodechalEncodeAvcBase::SetMfxQmStateParams(MHW_VDBOX_QM_PARAMS &qmParams, MHW_VDBOX_QM_PARAMS &fqmParams) |
| { |
| MOS_ZeroMemory(&qmParams, sizeof(qmParams)); |
| MOS_ZeroMemory(&fqmParams, sizeof(fqmParams)); |
| |
| qmParams.Standard = CODECHAL_AVC; |
| qmParams.pAvcIqMatrix = (PMHW_VDBOX_AVC_QM_PARAMS)m_avcIQWeightScaleLists; |
| |
| fqmParams.Standard = CODECHAL_AVC; |
| fqmParams.pAvcIqMatrix = (PMHW_VDBOX_AVC_QM_PARAMS)m_avcIQWeightScaleLists; |
| } |
| |
| void CodechalEncodeAvcBase::SetMfxAvcImgStateParams(MHW_VDBOX_AVC_IMG_PARAMS ¶m) |
| { |
| param = {}; |
| param.currPass = m_currPass; |
| param.pEncodeAvcPicParams = m_avcPicParam; |
| param.pEncodeAvcSeqParams = m_avcSeqParam; |
| param.pEncodeAvcSliceParams = m_avcSliceParams; |
| param.wPicWidthInMb = m_picWidthInMb; |
| param.wPicHeightInMb = m_picHeightInMb; |
| param.ppRefList = &(m_refList[0]); |
| param.pPicIdx = &(m_picIdx[0]); |
| param.dwTqEnabled = m_trellisQuantParams.dwTqEnabled; |
| param.dwTqRounding = m_trellisQuantParams.dwTqRounding; |
| param.ucKernelMode = m_kernelMode; |
| param.wSlcHeightInMb = m_sliceHeight; |
| param.dwMaxVmvR = CodecHalAvcEncode_GetMaxVmvR(m_avcSeqParam->Level); |
| param.bVdencStreamInEnabled = m_vdencStreamInEnabled; |
| param.bSliceSizeStreamOutEnabled = m_sliceSizeStreamoutSupported; |
| param.bCrePrefetchEnable = m_crePrefetchEnable; |
| |
| if (m_currPass && (m_currPass == m_numPasses) && (!m_vdencBrcEnabled)) |
| { |
| // Enable IPCM pass, excluding VDENC BRC case |
| param.bIPCMPass = true; |
| } |
| } |
| |
| void CodechalEncodeAvcBase::UpdateSSDSliceCount() |
| { |
| m_setRequestedEUSlices = ((m_frameHeight * m_frameWidth) >= m_ssdResolutionThreshold && |
| m_targetUsage <= m_ssdTargetUsageThreshold) |
| ? true |
| : false; |
| |
| m_hwInterface->m_numRequestedEuSlices = (m_setRequestedEUSlices) ? m_sliceShutdownRequestState : m_sliceShutdownDefaultState; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::AddIshSize(uint32_t kuid, uint8_t *kernelBase) |
| { |
| uint8_t *kernelBinary; |
| uint32_t kernelSize; |
| |
| MOS_STATUS status = CodecHalGetKernelBinaryAndSize(kernelBase, kuid, &kernelBinary, &kernelSize); |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(status); |
| m_hwInterface->GetStateHeapSettings()->dwIshSize += MOS_ALIGN_CEIL(kernelSize, (1 << MHW_KERNEL_OFFSET_SHIFT)); |
| return status; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::StoreNumPasses( |
| EncodeStatusBuffer *encodeStatusBuf, |
| MhwMiInterface * miInterface, |
| PMOS_COMMAND_BUFFER cmdBuffer, |
| uint32_t currPass) |
| { |
| MHW_MI_STORE_DATA_PARAMS storeDataParams; |
| uint32_t offset; |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_NULL_RETURN(encodeStatusBuf); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(miInterface); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); |
| |
| offset = |
| (encodeStatusBuf->wCurrIndex * encodeStatusBuf->dwReportSize) + |
| encodeStatusBuf->dwNumPassesOffset + // Num passes offset |
| sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource |
| |
| storeDataParams.pOsResource = &encodeStatusBuf->resStatusBuffer; |
| storeDataParams.dwResourceOffset = offset; |
| storeDataParams.dwValue = currPass + 1; |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiStoreDataImmCmd(cmdBuffer, &storeDataParams)); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| #if USE_CODECHAL_DEBUG_TOOL |
| static MOS_STATUS DumpEncodePicReorder( |
| std::ostringstream &oss, |
| uint32_t x, |
| uint32_t y, |
| CODEC_PIC_REORDER * picReorder) |
| { |
| uint8_t botField; |
| |
| CODECHAL_DEBUG_CHK_NULL(picReorder); |
| |
| botField = CodecHal_PictureIsBottomField(picReorder->Picture) ? 1 : 0; |
| |
| oss << "# PicOrder[" << std::dec << +x << "][" << std::dec << +y << "] =" << std::endl; |
| oss << "# \tPicNum = " << std::dec << +picReorder->PicNum << std::endl; |
| oss << "# \tPOC = " << std::dec << +picReorder->POC << std::endl; |
| oss << "# \tReorderPicNumIDC = " << std::dec << +picReorder->ReorderPicNumIDC << std::endl; |
| oss << "# \tDiffPicNumMinus1 = " << std::dec << +picReorder->DiffPicNumMinus1 << std::endl; |
| oss << "# \tFrameIdx = " << std::dec << +picReorder->Picture.FrameIdx << std::endl; |
| oss << "# \tBotField = " << std::dec << +botField << std::endl; |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DumpSeqParams( |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams, |
| PCODEC_AVC_IQ_MATRIX_PARAMS matrixParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSeqParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(seqParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "# DDI Parameters:" << std::endl; |
| oss << "FrameWidth = " << +seqParams->FrameWidth << std::endl; |
| oss << "FrameHeight = " << +seqParams->FrameHeight << std::endl; |
| oss << "Profile = " << +seqParams->Profile << std::endl; |
| oss << "Level = " << +seqParams->Level << std::endl; |
| oss << "GopPicSize = " << +seqParams->GopPicSize << std::endl; |
| oss << "GopRefDist = " << +seqParams->GopRefDist << std::endl; |
| oss << "GopOptFlag = " << +seqParams->GopOptFlag << std::endl; |
| oss << "TargetUsage = " << +seqParams->TargetUsage << std::endl; |
| oss << "RateControlMethod = " << +seqParams->RateControlMethod << std::endl; |
| oss << "TargetBitRate = " << +seqParams->TargetBitRate << std::endl; |
| oss << "MaxBitRate = " << +seqParams->MaxBitRate << std::endl; |
| oss << "MinBitRate = " << +seqParams->MinBitRate << std::endl; |
| oss << "FramesPer100Sec = " << +seqParams->FramesPer100Sec << std::endl; |
| oss << "InitVBVBufferFullnessInBit = " << +seqParams->InitVBVBufferFullnessInBit << std::endl; |
| oss << "VBVBufferSizeInBit = " << +seqParams->VBVBufferSizeInBit << std::endl; |
| oss << "NumRefFrames = " << +seqParams->NumRefFrames / 2 << std::endl; // this prints the value passed from DDI |
| oss << "# NumRefFrames (Actual Value in CodecHal is twice the value passed from DDI) = " |
| << +seqParams->NumRefFrames << std::endl; // this prints the actual value in CodecHal seq param structure |
| oss << "seq_parameter_set_id = " << +seqParams->seq_parameter_set_id << std::endl; |
| oss << "chroma_format_idc = " << +seqParams->chroma_format_idc << std::endl; |
| oss << "bit_depth_luma_minus8 = " << +seqParams->bit_depth_luma_minus8 << std::endl; |
| oss << "bit_depth_chroma_minus8 = " << +seqParams->bit_depth_chroma_minus8 << std::endl; |
| oss << "log2_max_frame_num_minus4 = " << +seqParams->log2_max_frame_num_minus4 << std::endl; |
| oss << "pic_order_cnt_type = " << +seqParams->pic_order_cnt_type << std::endl; |
| oss << "log2_max_pic_order_cnt_lsb_minus4 = " << +seqParams->log2_max_pic_order_cnt_lsb_minus4 << std::endl; |
| oss << "num_ref_frames_in_pic_order_cnt_cycle = " << +seqParams->num_ref_frames_in_pic_order_cnt_cycle << std::endl; |
| oss << "offset_for_non_ref_pic = " << +seqParams->offset_for_non_ref_pic << std::endl; |
| oss << "offset_for_top_to_bottom_field = " << +seqParams->offset_for_top_to_bottom_field << std::endl; |
| |
| // Conditionally printed (only when pic_order_cnt_type = 1). Contains 256 elements. |
| if (seqParams->pic_order_cnt_type == 1) |
| { |
| for (uint16_t i = 0; i < 256; ++i) |
| { |
| oss << "offset_for_ref_frame[" << +i << "] = " << +seqParams->offset_for_ref_frame[i] << std::endl; |
| } |
| } |
| |
| oss << "frame_crop_left_offset = " << +seqParams->frame_crop_left_offset << std::endl; |
| oss << "frame_crop_right_offset = " << +seqParams->frame_crop_right_offset << std::endl; |
| oss << "frame_crop_top_offset = " << +seqParams->frame_crop_top_offset << std::endl; |
| oss << "frame_crop_bottom_offset = " << +seqParams->frame_crop_bottom_offset << std::endl; |
| oss << "seq_scaling_matrix_present_flag = " << +seqParams->seq_scaling_matrix_present_flag << std::endl; |
| oss << "seq_scaling_list_present_flag = " << +seqParams->seq_scaling_list_present_flag[0] << std::endl; |
| |
| // seq_scaling_list_present_flag with 12 elements (only 1 element acknowledged in DDI doc) |
| oss << "# seq_scaling_list_present_flag[1-11]:"; |
| for (uint8_t i = 1; i < 12; i++) |
| oss << +seqParams->seq_scaling_list_present_flag[i] << " "; |
| oss << std::endl; |
| |
| oss << "delta_pic_order_always_zero_flag = " << +seqParams->delta_pic_order_always_zero_flag << std::endl; |
| oss << "frame_mbs_only_flag = " << +seqParams->frame_mbs_only_flag << std::endl; |
| oss << "direct_8x8_inference_flag = " << +seqParams->direct_8x8_inference_flag << std::endl; |
| oss << "vui_parameters_present_flag = " << +seqParams->vui_parameters_present_flag << std::endl; |
| oss << "frame_cropping_flag = " << +seqParams->frame_cropping_flag << std::endl; |
| oss << "EnableSliceLevelRateCtrl = " << +seqParams->EnableSliceLevelRateCtrl << std::endl; |
| oss << "ICQQualityFactor = " << +seqParams->ICQQualityFactor << std::endl; |
| oss << "InputColorSpace = " << +seqParams->InputColorSpace << std::endl; |
| |
| // begining of union/struct |
| oss << "# bResetBRC = " << +seqParams->bResetBRC << std::endl; |
| oss << "# bNoAcceleratorSPSInsertion = " << +seqParams->bNoAcceleratorSPSInsertion << std::endl; |
| oss << "# GlobalSearch = " << +seqParams->GlobalSearch << std::endl; |
| oss << "# LocalSearch = " << +seqParams->LocalSearch << std::endl; |
| oss << "# EarlySkip = " << +seqParams->EarlySkip << std::endl; |
| oss << "# Trellis = " << +seqParams->Trellis << std::endl; |
| oss << "# MBBRC = " << +seqParams->MBBRC << std::endl; |
| oss << "# bTemporalScalability = " << +seqParams->bTemporalScalability << std::endl; |
| oss << "# ROIValueInDeltaQP = " << +seqParams->ROIValueInDeltaQP << std::endl; |
| oss << "# bAutoMaxPBFrameSizeForSceneChange = " << +seqParams->bAutoMaxPBFrameSizeForSceneChange << std::endl; |
| oss << "sFlags = " << +seqParams->sFlags << std::endl; |
| |
| // end of union/struct |
| oss << "UserMaxIFrameSize = " << +seqParams->UserMaxFrameSize << std::endl; |
| oss << "UserMaxPBFrameSize = " << +seqParams->UserMaxPBFrameSize << std::endl; |
| |
| // Parameters not defined in DDI (Any non-DDI parameters printed should be preceeded by #) |
| oss << "# Non-DDI Parameters:" << std::endl; |
| oss << "# constraint_set0_flag = " << std::hex << +seqParams->constraint_set0_flag << std::endl; |
| oss << "# constraint_set1_flag = " << std::hex << +seqParams->constraint_set1_flag << std::endl; |
| oss << "# constraint_set2_flag = " << std::hex << +seqParams->constraint_set2_flag << std::endl; |
| oss << "# constraint_set3_flag = " << std::hex << +seqParams->constraint_set3_flag << std::endl; |
| |
| oss << "# separate_colour_plane_flag = " << std::hex << +seqParams->separate_colour_plane_flag << std::endl; |
| oss << "# qpprime_y_zero_transform_bypass_flag = " << std::hex << +seqParams->qpprime_y_zero_transform_bypass_flag << std::endl; |
| oss << "# gaps_in_frame_num_value_allowed_flag = " << std::hex << +seqParams->gaps_in_frame_num_value_allowed_flag << std::endl; |
| oss << "# pic_width_in_mbs_minus1 = " << std::hex << +seqParams->pic_width_in_mbs_minus1 << std::endl; |
| oss << "# pic_height_in_map_units_minus1 = " << std::hex << +seqParams->pic_height_in_map_units_minus1 << std::endl; |
| oss << "# mb_adaptive_frame_field_flag = " << std::hex << +seqParams->mb_adaptive_frame_field_flag << std::endl; |
| |
| // Dump ScalingList4x4 (6 x 16) |
| for (uint8_t i = 0; i < 16; ++i) |
| { |
| oss << "# ScalingList4x4[" << std::dec << +i * 6 << "-" << (+i * 6) + 5 << "][" << +i << "]"; |
| for (uint8_t j = 0; j < 6; j++) |
| oss << std::hex << +matrixParams->ScalingList4x4[j][i] << " "; |
| oss << std::endl; |
| } |
| |
| // ScalingList8x8 (2 x 64) |
| for (uint8_t i = 0; i < 64; ++i) |
| { |
| oss << "# ScalingList8x8[0 / 1][ " << std::dec << +i << "] = "; |
| oss << +matrixParams->ScalingList8x8[0][i] << " / " << +matrixParams->ScalingList8x8[1][i]; |
| oss << std::endl; |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DDIEnc", |
| CodechalDbgBufferType::bufSeqParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump)) |
| { |
| if (!m_debugInterface->m_ddiFileName.empty()) |
| { |
| std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app); |
| ofs << "SeqParamFile" |
| << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl; |
| ofs.close(); |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DumpPicParams( |
| PCODEC_AVC_ENCODE_PIC_PARAMS picParams, |
| PCODEC_AVC_IQ_MATRIX_PARAMS matrixParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(picParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "# DDI Parameters:" << std::endl; |
| oss << "TargetFrameSize = " << +picParams->TargetFrameSize << std::endl; |
| oss << "CurrOriginalPic = " << +picParams->CurrOriginalPic.PicEntry << std::endl; |
| oss << "CurrReconstructedPic = " << +picParams->CurrReconstructedPic.PicEntry << std::endl; |
| oss << "CodingType = " << +picParams->CodingType << std::endl; |
| oss << "FieldCodingFlag = " << +picParams->FieldCodingFlag << std::endl; |
| oss << "FieldFrameCodingFlag = " << +picParams->FieldFrameCodingFlag << std::endl; |
| oss << "NumSlice = " << +picParams->NumSlice << std::endl; |
| oss << "QpY = " << +picParams->QpY << std::endl; |
| |
| for (uint8_t i = 0; i < 16; ++i) |
| { |
| oss << "RefFrameList[" << +i << "] = " << +picParams->RefFrameList[i].PicEntry << std::endl; |
| } |
| |
| oss << "UsedForReferenceFlags = " << +picParams->UsedForReferenceFlags << std::endl; |
| oss << "CurrFieldOrderCnt[0] = " << +picParams->CurrFieldOrderCnt[0] << std::endl; |
| oss << "CurrFieldOrderCnt[1] = " << +picParams->CurrFieldOrderCnt[1] << std::endl; |
| |
| for (uint8_t i = 0; i < 16; ++i) |
| { |
| for (uint8_t j = 0; j < 2; ++j) |
| { |
| oss << "FieldOrderCntList[" << +i << "]" |
| << "[" << +j << "] = " << +picParams->FieldOrderCntList[i][j] << std::endl; |
| } |
| } |
| |
| oss << "frame_num = " << +picParams->frame_num << std::endl; |
| oss << "bLastPicInSeq = " << +picParams->bLastPicInSeq << std::endl; |
| oss << "bLastPicInStream = " << +picParams->bLastPicInStream << std::endl; |
| |
| // User Flags parameters |
| oss << "# bUseRawPicForRef = " << +picParams->UserFlags.bUseRawPicForRef << std::endl; |
| oss << "# bDisableAcceleratorHeaderPacking = " << +picParams->UserFlags.bDisableAcceleratorHeaderPacking << std::endl; |
| oss << "# bDisableSubMBPartition = " << +picParams->UserFlags.bDisableSubMBPartition << std::endl; |
| oss << "# bEmulationByteInsertion = " << +picParams->UserFlags.bEmulationByteInsertion << std::endl; |
| oss << "# bEnableRollingIntraRefresh = " << +picParams->UserFlags.bEnableRollingIntraRefresh << std::endl; |
| oss << "ForceRepartitionCheck = " << +picParams->UserFlags.ForceRepartitionCheck << std::endl; |
| oss << "UserFlags = " << +picParams->UserFlags.Value << std::endl; |
| oss << "StatusReportFeedbackNumber = " << +picParams->StatusReportFeedbackNumber << std::endl; |
| oss << "bIdrPic = " << +picParams->bIdrPic << std::endl; |
| oss << "pic_parameter_set_id = " << +picParams->pic_parameter_set_id << std::endl; |
| oss << "seq_parameter_set_id = " << +picParams->seq_parameter_set_id << std::endl; |
| oss << "num_ref_idx_l0_active_minus1 = " << +picParams->num_ref_idx_l0_active_minus1 << std::endl; |
| oss << "num_ref_idx_l1_active_minus1 = " << +picParams->num_ref_idx_l1_active_minus1 << std::endl; |
| oss << "chroma_qp_index_offset = " << +picParams->chroma_qp_index_offset << std::endl; |
| oss << "second_chroma_qp_index_offset = " << +picParams->second_chroma_qp_index_offset << std::endl; |
| oss << "entropy_coding_mode_flag = " << +picParams->entropy_coding_mode_flag << std::endl; |
| oss << "pic_order_present_flag = " << +picParams->pic_order_present_flag << std::endl; |
| oss << "weighted_pred_flag = " << +picParams->weighted_pred_flag << std::endl; |
| oss << "weighted_bipred_idc = " << +picParams->weighted_bipred_idc << std::endl; |
| oss << "constrained_intra_pred_flag = " << +picParams->constrained_intra_pred_flag << std::endl; |
| oss << "transform_8x8_mode_flag = " << +picParams->transform_8x8_mode_flag << std::endl; |
| oss << "pic_scaling_matrix_present_flag = " << +picParams->pic_scaling_matrix_present_flag << std::endl; |
| oss << "pic_scaling_list_present_flag = " << +picParams->pic_scaling_list_present_flag[0] << std::endl; |
| |
| // pic_scaling_list_present_flag buffer contains 12 elements (only 1 acknowledged DDI document) |
| oss << "# pic_scaling_list_present_flag[1-11]:"; |
| oss << +picParams->pic_scaling_list_present_flag[1] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[2] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[3] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[4] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[5] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[6] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[7] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[8] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[9] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[10] << " "; |
| oss << +picParams->pic_scaling_list_present_flag[11] << std::endl; |
| |
| oss << "RefPicFlag = " << +picParams->RefPicFlag << std::endl; |
| oss << "BRCPrecision = " << +picParams->BRCPrecision << std::endl; |
| oss << "bDisplayFormatSwizzle = " << +picParams->bDisplayFormatSwizzle << std::endl; |
| oss << "IntraInsertionLocation = " << +picParams->IntraRefreshMBNum << std::endl; |
| oss << "IntraInsertionSize = " << +picParams->IntraRefreshUnitinMB << std::endl; |
| oss << "QpDeltaForInsertedIntra = " << +picParams->IntraRefreshQPDelta << std::endl; |
| oss << "SliceSizeInBytes = " << +picParams->SliceSizeInBytes << std::endl; |
| oss << "bDisableRollingIntraRefreshOverlap = " << +picParams->bDisableRollingIntraRefreshOverlap << std::endl; |
| oss << "NumROI = " << +picParams->NumROI << std::endl; |
| oss << "MinDeltaQp = " << +picParams->MinDeltaQp << std::endl; |
| oss << "MaxDeltaQp = " << +picParams->MaxDeltaQp << std::endl; |
| |
| // Dump ROI coordinates and PriorityLevelOrDQp |
| for (uint16_t i = 0; i < picParams->NumROI; ++i) |
| { |
| oss << "ROI[" << +i << "] = ["; |
| oss << +picParams->ROI[i].Top << ","; |
| oss << +picParams->ROI[i].Bottom << ","; |
| oss << +picParams->ROI[i].Left << ","; |
| oss << +picParams->ROI[i].Right << "], "; |
| oss << "PriorityLevelOrDQp = " << +picParams->ROI[i].PriorityLevelOrDQp << std::endl; |
| } |
| |
| oss << "NumDirtyROI = " << +picParams->NumDirtyROI << std::endl; |
| |
| // Dump Dirty ROI coordinates and PriorityLevelOrDQp |
| for (uint16_t i = 0; i < picParams->NumDirtyROI; ++i) |
| { |
| oss << "DirtyROI[" << +i << "] = ["; |
| oss << +picParams->DirtyROI[i].Top << ","; |
| oss << +picParams->DirtyROI[i].Bottom << ","; |
| oss << +picParams->DirtyROI[i].Left << ","; |
| oss << +picParams->DirtyROI[i].Right << "], "; |
| oss << "PriorityLevelOrDQp = " << +picParams->DirtyROI[i].PriorityLevelOrDQp << std::endl; |
| } |
| |
| oss << "SkipFrameFlag = " << +picParams->SkipFrameFlag << std::endl; |
| oss << "NumSkipFrames = " << +picParams->NumSkipFrames << std::endl; |
| oss << "SizeSkipFrames = " << +picParams->SizeSkipFrames << std::endl; |
| |
| // Dump Min/Max QP params |
| oss << "BRCMinQp = " << +picParams->ucMinimumQP << std::endl; |
| oss << "BRCMaxQp = " << +picParams->ucMaximumQP << std::endl; |
| |
| // Dump SFD threshold |
| oss << "dwZMvThreshold = " << +picParams->dwZMvThreshold << std::endl; |
| |
| // Dump HME offset |
| oss << "bEnableHMEOffset = " << +picParams->bEnableHMEOffset << std::endl; |
| |
| for (uint8_t i = 0; i < 16; ++i) |
| { |
| for (uint8_t j = 0; j < 2; ++j) |
| { |
| for (uint8_t k = 0; k < 2; ++k) |
| { |
| oss << "HMEOffset[" << +i << "][" << +j << "][" << +k << "] = " << +picParams->HMEOffset[i][j][k] << std::endl; |
| } |
| } |
| } |
| |
| oss << "bDisableFrameSkip = " << +picParams->bDisableFrameSkip << std::endl; |
| oss << "bEnableSync = " << +picParams->bEnableSync << std::endl; |
| oss << "bRepeatFrame = " << +picParams->bRepeatFrame << std::endl; |
| oss << "bEnableQpAdjustment = " << +picParams->bEnableQpAdjustment << std::endl; |
| |
| oss << "NumDeltaQpForNonRectROI = " << +picParams->NumDeltaQpForNonRectROI << std::endl; |
| for (uint16_t i = 0; i < picParams->NumDeltaQpForNonRectROI; ++i) |
| { |
| oss << "NonRectROIDeltaQpList[" << +i << "] = " << +picParams->NonRectROIDeltaQpList[i] << std::endl; |
| } |
| |
| oss << "SyncMarkerX = " << +picParams->SyncMarkerX << std::endl; |
| oss << "SyncMarkerY = " << +picParams->SyncMarkerY << std::endl; |
| oss << "SyncMarkerSize = " << +picParams->SyncMarkerSize << std::endl; |
| oss << "HierarchLevelPlus1 = " << +picParams->HierarchLevelPlus1 << std::endl; |
| oss << "QpModulationStrength = " << +picParams->QpModulationStrength << std::endl; |
| |
| // Parameters not defined in DDI (Any non-DDI parameters printed should be preceeded by #) |
| oss << "# Non-DDI Parameters:" << std::endl; |
| oss << "# num_slice_groups_minus1 = " << +picParams->num_slice_groups_minus1 << std::endl; |
| oss << "# pic_init_qp_minus26 = " << +picParams->pic_init_qp_minus26 << std::endl; |
| oss << "# pic_init_qs_minus26 = " << +picParams->pic_init_qs_minus26 << std::endl; |
| oss << "# deblocking_filter_control_present_flag = " << +picParams->deblocking_filter_control_present_flag << std::endl; |
| oss << "# redundant_pic_cnt_present_flag = " << +picParams->redundant_pic_cnt_present_flag << std::endl; |
| oss << "# EnableRollingIntraRefresh = " << +picParams->EnableRollingIntraRefresh << std::endl; |
| oss << "# IntraRefreshMBx = " << +picParams->IntraRefreshMBx << std::endl; |
| oss << "# IntraRefreshMBy = " << +picParams->IntraRefreshMBy << std::endl; |
| oss << "# IntraRefreshUnitinMB = " << +picParams->IntraRefreshUnitinMB << std::endl; |
| oss << "# IntraRefreshQPDelta = " << +picParams->IntraRefreshQPDelta << std::endl; |
| |
| // Dump ScalingList4x4 (6 x 16) |
| for (uint8_t i = 0; i < 16; ++i) |
| { |
| oss << "# ScalingList4x4[" << +i << "] = "; |
| oss << +matrixParams->ScalingList4x4[0][i] << " "; |
| oss << +matrixParams->ScalingList4x4[1][i] << " "; |
| oss << +matrixParams->ScalingList4x4[2][i] << " "; |
| oss << +matrixParams->ScalingList4x4[3][i] << " "; |
| oss << +matrixParams->ScalingList4x4[4][i] << " "; |
| oss << +matrixParams->ScalingList4x4[5][i] << std::endl; |
| } |
| |
| // ScalingList8x8 (2 x 64) |
| for (uint8_t i = 0; i < 64; ++i) |
| { |
| oss << "# ScalingList8x8[0/1][" << +i << "] = " << +matrixParams->ScalingList8x8[0][i] << " / " << +matrixParams->ScalingList8x8[1][i] << std::endl; |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DDIEnc", |
| CodechalDbgBufferType::bufPicParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump)) |
| { |
| if (!m_debugInterface->m_ddiFileName.empty()) |
| { |
| std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app); |
| ofs << "PicNum" |
| << " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl; |
| ofs << "PicParamFile" |
| << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl; |
| ofs.close(); |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DumpFeiPicParams( |
| CodecEncodeAvcFeiPicParams *feiPicParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrFeiPicParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(feiPicParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "# DDI Parameters:" << std::endl; |
| oss << "SearchPath = " << +feiPicParams->SearchPath << std::endl; |
| oss << "LenSP = " << +feiPicParams->LenSP << std::endl; |
| oss << "SubMBPartMask = " << +feiPicParams->SubMBPartMask << std::endl; |
| oss << "IntraPartMask = " << +feiPicParams->IntraPartMask << std::endl; |
| oss << "MultiPredL0 = " << +feiPicParams->MultiPredL0 << std::endl; |
| oss << "MultiPredL1 = " << +feiPicParams->MultiPredL1 << std::endl; |
| oss << "SubPelMode = " << +feiPicParams->SubPelMode << std::endl; |
| oss << "InterSAD = " << +feiPicParams->InterSAD << std::endl; |
| oss << "IntraSAD = " << +feiPicParams->IntraSAD << std::endl; |
| oss << "NumMVPredictors = " << +feiPicParams->NumMVPredictorsL0 << std::endl; |
| oss << "NumMVPredictorsL1 = " << +feiPicParams->NumMVPredictorsL1 << std::endl; |
| oss << "DistortionType = " << +feiPicParams->DistortionType << std::endl; |
| oss << "DistortionEnable = " << +feiPicParams->DistortionEnable << std::endl; |
| oss << "RepartitionCheckEnable = " << +feiPicParams->RepartitionCheckEnable << std::endl; |
| oss << "AdaptiveSearch = " << +feiPicParams->AdaptiveSearch << std::endl; |
| oss << "MVPredictorEnable = " << +feiPicParams->MVPredictorEnable << std::endl; |
| oss << "bMBQp = " << +feiPicParams->bMBQp << std::endl; |
| oss << "bPerMBInput = " << +feiPicParams->bPerMBInput << std::endl; |
| oss << "bMBSizeCtrl = " << +feiPicParams->bMBSizeCtrl << std::endl; |
| oss << "RefWidth = " << +feiPicParams->RefWidth << std::endl; |
| oss << "RefHeight = " << +feiPicParams->RefHeight << std::endl; |
| oss << "SearchWindow = " << +feiPicParams->SearchWindow << std::endl; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DDIEnc", |
| CodechalDbgBufferType::bufFeiPicParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump)) |
| { |
| if (!m_debugInterface->m_ddiFileName.empty()) |
| { |
| std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app); |
| ofs << "PicNum" |
| << " = \"" << m_debugInterface->m_bufferDumpFrameNum << "\"" << std::endl; |
| ofs << "FeiPicParamFile" |
| << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl; |
| ofs.close(); |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DumpSliceParams( |
| PCODEC_AVC_ENCODE_SLICE_PARAMS sliceParams, |
| PCODEC_AVC_ENCODE_PIC_PARAMS picParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(sliceParams); |
| |
| m_debugInterface->m_sliceId = sliceParams->slice_id; // set here for constructing debug file name |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "# DDI Parameters:" << std::endl; |
| oss << "NumMbsForSlice = " << +sliceParams->NumMbsForSlice << std::endl; |
| |
| // RefPicList (2 x 32) |
| for (uint8_t i = 0; i < 2; ++i) |
| { |
| for (uint8_t j = 0; j < 32; ++j) |
| { |
| oss << "RefPicList[" << +i << "][" << +j << "] = " << +sliceParams->RefPicList[i][j].PicEntry << std::endl; |
| } |
| } |
| |
| // Conditionally printed (only when picture parameters weighted_pred_flag or weighted_bipred_idc are set). |
| // Weights contains 192 elements (2 x 32 x 3 x 2). |
| if (picParams->weighted_pred_flag || picParams->weighted_bipred_idc) |
| { |
| for (uint8_t i = 0; i < 2; ++i) |
| { |
| for (uint8_t j = 0; j < 32; ++j) |
| { |
| for (uint8_t k = 0; k < 3; ++k) |
| { |
| for (uint8_t l = 0; l < 2; ++l) |
| { |
| oss << "Weights[" << +i << "][" << +j << "][" << +k << "][" << +l << "]: " << +sliceParams->Weights[i][j][k][l] << std::endl; |
| } |
| } |
| } |
| } |
| } |
| |
| oss << "first_mb_in_slice = " << +sliceParams->first_mb_in_slice << std::endl; |
| oss << "slice_type = " << +sliceParams->slice_type << std::endl; |
| oss << "pic_parameter_set_id = " << +sliceParams->pic_parameter_set_id << std::endl; |
| oss << "direct_spatial_mv_pred_flag = " << +sliceParams->direct_spatial_mv_pred_flag << std::endl; |
| oss << "num_ref_idx_active_override_flag = " << +sliceParams->num_ref_idx_active_override_flag << std::endl; |
| oss << "long_term_reference_flag = " << +sliceParams->long_term_reference_flag << std::endl; |
| oss << "idr_pic_id = " << +sliceParams->idr_pic_id << std::endl; |
| oss << "pic_order_cnt_lsb = " << +sliceParams->pic_order_cnt_lsb << std::endl; |
| oss << "delta_pic_order_cnt_bottom = " << +sliceParams->delta_pic_order_cnt_bottom << std::endl; |
| oss << "delta_pic_order_cnt[0] = " << +sliceParams->delta_pic_order_cnt[0] << std::endl; |
| oss << "delta_pic_order_cnt[1] = " << +sliceParams->delta_pic_order_cnt[1] << std::endl; |
| oss << "num_ref_idx_l0_active_minus1 = " << +sliceParams->num_ref_idx_l0_active_minus1 << std::endl; |
| oss << "num_ref_idx_l1_active_minus1 = " << +sliceParams->num_ref_idx_l1_active_minus1 << std::endl; |
| oss << "luma_log2_weight_denom = " << +sliceParams->luma_log2_weight_denom << std::endl; |
| oss << "chroma_log2_weight_denom = " << +sliceParams->chroma_log2_weight_denom << std::endl; |
| oss << "cabac_init_idc = " << +sliceParams->cabac_init_idc << std::endl; |
| oss << "slice_qp_delta = " << +sliceParams->slice_qp_delta << std::endl; |
| oss << "disable_deblocking_filter_idc = " << +sliceParams->disable_deblocking_filter_idc << std::endl; |
| oss << "slice_alpha_c0_offset_div2 = " << +sliceParams->slice_alpha_c0_offset_div2 << std::endl; |
| oss << "slice_beta_offset_div2 = " << +sliceParams->slice_beta_offset_div2 << std::endl; |
| oss << "slice_id = " << +sliceParams->slice_id << std::endl; |
| oss << "luma_weight_flag[0] = " << +sliceParams->luma_weight_flag[0] << std::endl; |
| oss << "luma_weight_flag[1] = " << +sliceParams->luma_weight_flag[1] << std::endl; |
| oss << "chroma_weight_flag[0] = " << +sliceParams->chroma_weight_flag[0] << std::endl; |
| oss << "chroma_weight_flag[1] = " << +sliceParams->chroma_weight_flag[1] << std::endl; |
| |
| // Parameters not in DDI (Any non-DDI parameters printed should be preceeded by #) |
| oss << "# Non-DDI Parameters:" << std::endl; |
| |
| // PicOrder (2 x 32) - Dump in 32 blocks of 2 chunks per line |
| for (uint16_t i = 0; i < 32; ++i) |
| { |
| CODECHAL_DEBUG_CHK_STATUS(DumpEncodePicReorder( |
| oss, |
| 0, |
| i, |
| &(sliceParams->PicOrder[0][i]))); |
| CODECHAL_DEBUG_CHK_STATUS(DumpEncodePicReorder( |
| oss, |
| 1, |
| i, |
| &(sliceParams->PicOrder[1][i]))); |
| } |
| |
| oss << "# colour_plane_id = " << +sliceParams->colour_plane_id << std::endl; |
| oss << "# frame_num = " << +sliceParams->frame_num << std::endl; |
| oss << "# field_pic_flag = " << std::hex << +sliceParams->field_pic_flag << std::endl; |
| oss << "# bottom_field_flag = " << std::hex << +sliceParams->bottom_field_flag << std::endl; |
| oss << "# redundant_pic_cnt = " << std::dec << +sliceParams->redundant_pic_cnt << std::endl; |
| oss << "# sp_for_switch_flag = " << std::hex << +sliceParams->sp_for_switch_flag << std::endl; |
| oss << "# slice_qs_delta = " << std::dec << +sliceParams->slice_qs_delta << std::endl; |
| oss << "# ref_pic_list_reordering_flag_l0 = " << std::hex << +sliceParams->ref_pic_list_reordering_flag_l0 << std::endl; |
| oss << "# ref_pic_list_reordering_flag_l1 = " << std::hex << +sliceParams->ref_pic_list_reordering_flag_l1 << std::endl; |
| oss << "# no_output_of_prior_pics_flag = " << std::hex << +sliceParams->no_output_of_prior_pics_flag << std::endl; |
| oss << "# adaptive_ref_pic_marking_mode_flag = " << std::hex << +sliceParams->adaptive_ref_pic_marking_mode_flag << std::endl; |
| oss << "# MaxFrameNum = " << std::dec << +sliceParams->MaxFrameNum << std::endl; |
| oss << "# NumReorder = " << std::dec << +sliceParams->NumReorder << std::endl; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DDIEnc", |
| CodechalDbgBufferType::bufSlcParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump)) |
| { |
| if (!m_debugInterface->m_ddiFileName.empty()) |
| { |
| std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app); |
| ofs << "SlcParamFile" |
| << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl; |
| ofs.close(); |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DumpVuiParams( |
| PCODECHAL_ENCODE_AVC_VUI_PARAMS vuiParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrVuiParams)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_DEBUG_CHK_NULL(vuiParams); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| oss << "# DDI Parameters:" << std::endl; |
| oss << "aspect_ratio_info_present_flag = " << +vuiParams->aspect_ratio_info_present_flag << std::endl; |
| oss << "overscan_info_present_flag = " << +vuiParams->overscan_info_present_flag << std::endl; |
| oss << "overscan_appropriate_flag = " << +vuiParams->overscan_appropriate_flag << std::endl; |
| oss << "video_signal_type_present_flag = " << +vuiParams->video_signal_type_present_flag << std::endl; |
| oss << "video_full_range_flag = " << +vuiParams->video_full_range_flag << std::endl; |
| oss << "colour_description_present_flag = " << +vuiParams->colour_description_present_flag << std::endl; |
| oss << "chroma_loc_info_present_flag = " << +vuiParams->chroma_loc_info_present_flag << std::endl; |
| oss << "timing_info_present_flag = " << +vuiParams->timing_info_present_flag << std::endl; |
| oss << "fixed_frame_rate_flag = " << +vuiParams->fixed_frame_rate_flag << std::endl; |
| oss << "nal_hrd_parameters_present_flag = " << +vuiParams->nal_hrd_parameters_present_flag << std::endl; |
| oss << "vcl_hrd_parameters_present_flag = " << +vuiParams->vcl_hrd_parameters_present_flag << std::endl; |
| oss << "low_delay_hrd_flag = " << +vuiParams->low_delay_hrd_flag << std::endl; |
| oss << "pic_struct_present_flag = " << +vuiParams->pic_struct_present_flag << std::endl; |
| oss << "bitstream_restriction_flag = " << +vuiParams->bitstream_restriction_flag << std::endl; |
| oss << "motion_vectors_over_pic_boundaries_flag = " << +vuiParams->motion_vectors_over_pic_boundaries_flag << std::endl; |
| oss << "sar_width = " << +vuiParams->sar_width << std::endl; |
| oss << "sar_height = " << +vuiParams->sar_height << std::endl; |
| oss << "aspect_ratio_idc = " << +vuiParams->aspect_ratio_idc << std::endl; |
| oss << "video_format = " << +vuiParams->video_format << std::endl; |
| oss << "colour_primaries = " << +vuiParams->colour_primaries << std::endl; |
| oss << "transfer_characteristics = " << +vuiParams->transfer_characteristics << std::endl; |
| oss << "matrix_coefficients = " << +vuiParams->matrix_coefficients << std::endl; |
| oss << "chroma_sample_loc_type_top_field = " << +vuiParams->chroma_sample_loc_type_top_field << std::endl; |
| oss << "chroma_sample_loc_type_bottom_field = " << +vuiParams->chroma_sample_loc_type_bottom_field << std::endl; |
| oss << "max_bytes_per_pic_denom = " << +vuiParams->max_bytes_per_pic_denom << std::endl; |
| oss << "max_bits_per_mb_denom = " << +vuiParams->max_bits_per_mb_denom << std::endl; |
| oss << "log2_max_mv_length_horizontal = " << +vuiParams->log2_max_mv_length_horizontal << std::endl; |
| oss << "log2_max_mv_length_vertical = " << +vuiParams->log2_max_mv_length_vertical << std::endl; |
| oss << "num_reorder_frames = " << +vuiParams->num_reorder_frames << std::endl; |
| oss << "num_units_in_tick = " << +vuiParams->num_units_in_tick << std::endl; |
| oss << "time_scale = " << +vuiParams->time_scale << std::endl; |
| oss << "max_dec_frame_buffering = " << +vuiParams->max_dec_frame_buffering << std::endl; |
| oss << "cpb_cnt_minus1 = " << +vuiParams->cpb_cnt_minus1 << std::endl; |
| oss << "bit_rate_scale = " << +vuiParams->bit_rate_scale << std::endl; |
| oss << "cpb_size_scale = " << +vuiParams->cpb_size_scale << std::endl; |
| |
| // bit_rate_value_minus1 (32 in size) |
| for (uint8_t i = 0; i < 32; ++i) |
| { |
| oss << "bit_rate_value_minus1[" << +i << "] = " << +vuiParams->bit_rate_value_minus1[i] << std::endl; |
| } |
| |
| // cpb_size_value_minus1 (32 in size) |
| for (uint8_t i = 0; i < 32; ++i) |
| { |
| oss << "cpb_size_value_minus1[" << +i << "] = " << +vuiParams->cpb_size_value_minus1[i] << std::endl; |
| } |
| |
| oss << "cbr_flag = " << +vuiParams->cbr_flag << std::endl; |
| oss << "initial_cpb_removal_delay_length_minus1 = " << +vuiParams->initial_cpb_removal_delay_length_minus1 << std::endl; |
| oss << "cpb_removal_delay_length_minus1 = " << +vuiParams->cpb_removal_delay_length_minus1 << std::endl; |
| oss << "dpb_output_delay_length_minus1 = " << +vuiParams->dpb_output_delay_length_minus1 << std::endl; |
| oss << "time_offset_length = " << +vuiParams->time_offset_length << std::endl; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "_DDIEnc", |
| CodechalDbgBufferType::bufVuiParams, |
| CodechalDbgExtType::txt); |
| |
| std::ofstream ofs(fileName, std::ios::out); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDriverUltDump)) |
| { |
| if (!m_debugInterface->m_ddiFileName.empty()) |
| { |
| std::ofstream ofs(m_debugInterface->m_ddiFileName, std::ios::app); |
| ofs << "VuiParamFile" |
| << " = \"" << m_debugInterface->m_fileName << "\"" << std::endl; |
| ofs.close(); |
| } |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| bool SearchNALHeader( |
| PMHW_VDBOX_AVC_SLICE_STATE sliceState, |
| uint32_t startCode) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| for (auto i = 0; i < CODECHAL_ENCODE_AVC_MAX_NAL_TYPE; i++) |
| { |
| if (sliceState->ppNalUnitParams[i]->uiSize > 0) |
| { |
| uint32_t offset = 0; |
| uint8_t *dataBase = (uint8_t *)(sliceState->pBsBuffer->pBase + sliceState->ppNalUnitParams[i]->uiOffset); |
| |
| while (offset < sliceState->ppNalUnitParams[i]->uiSize) |
| { |
| uint8_t *dataBuf = dataBase + offset; |
| |
| if (*dataBuf == 0) |
| { |
| uint32_t data = ((*dataBuf) << 24) + ((*(dataBuf + 1)) << 16) + ((*(dataBuf + 2)) << 8) + (*(dataBuf + 3)); |
| |
| if ((data & 0xFFFFFF00) == 0x00000100) |
| { |
| if (data == startCode) |
| { |
| return true; |
| } |
| |
| offset += 4; |
| } |
| else |
| { |
| offset++; |
| } |
| } |
| else |
| { |
| offset++; |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::CreateAvcPar() |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_DEBUG_CHK_NULL(m_debugInterface); |
| |
| if (m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar)) |
| { |
| CODECHAL_DEBUG_CHK_NULL(m_avcPar = MOS_New(EncodeAvcPar)); |
| MOS_ZeroMemory(m_avcPar, sizeof(EncodeAvcPar)); |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::DestroyAvcPar() |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParFile()); |
| MOS_Delete(m_avcPar); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::PopulateConstParam() |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_DEBUG_CHK_NULL(m_debugInterface); |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| if (m_encodeParState->m_isConstDumped) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_ENCODE_CHK_STATUS_RETURN(PopulateTargetUsage()); |
| |
| std::ostringstream oss; |
| oss.setf(std::ios::showbase | std::ios::uppercase); |
| |
| // Constant |
| oss << "EnableStatistics = 0" << std::endl; |
| oss << "KernelDumpEnable = 16" << std::endl; |
| oss << "Kernel = 1" << std::endl; |
| oss << "StartMB = -1" << std::endl; |
| oss << "EndMB = -1" << std::endl; |
| oss << "GOPMode = 0" << std::endl; |
| oss << "BoxFilter = 1" << std::endl; |
| oss << "EnableBpyramid = 0" << std::endl; |
| oss << "EnableIPCM = 1" << std::endl; |
| oss << "EnableMVUnpacked = 1" << std::endl; |
| oss << "EnableNewModeCost = 1" << std::endl; |
| oss << "EnablePAFF = 0" << std::endl; |
| oss << "EnableSkip = 3" << std::endl; |
| oss << "EnableSkipBiasAdjustment = 1" << std::endl; |
| oss << "HierarchicalMEFlag = 3" << std::endl; |
| oss << "NumRefStartB = 1" << std::endl; |
| oss << "PAFFThreshold = 10000" << std::endl; |
| oss << "PicScalingList = 0" << std::endl; |
| oss << "SeqScalingList = 0" << std::endl; |
| oss << "SkipChromaCBPDetection = 1" << std::endl; |
| oss << "IdrInterval = 0" << std::endl; |
| oss << "AddEoSquenceNAL = 1" << std::endl; |
| oss << "AddEoStreamNAL = 1" << std::endl; |
| oss << "CabacZeroWordFlag = 0" << std::endl; |
| oss << "EncodeFrameSizeTolerance = 0" << std::endl; |
| oss << "ForceIntraDC = 0" << std::endl; |
| oss << "HMECoarseShape = 2" << std::endl; |
| oss << "HMESubPelMode = 3" << std::endl; |
| oss << "IntraDirectionBias = 1" << std::endl; |
| oss << "InterSADMeasure = 2" << std::endl; |
| oss << "IntraSADMeasure = 2" << std::endl; |
| oss << "CostingFeature = 3" << std::endl; |
| oss << "CostingType = 1" << std::endl; |
| oss << "ModeCosting = 1" << std::endl; |
| oss << "HighQPMvCostEnable = 1" << std::endl; |
| oss << "HighQPHMECostEnable = 1" << std::endl; |
| oss << "RefIDCostMode = 0" << std::endl; |
| oss << "EnableAdaptiveLambdaOffset = 1" << std::endl; |
| |
| m_encodeParState->m_isConstDumped = true; |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "EncodeSequence", |
| "EncodePar", |
| CodechalDbgExtType::par); |
| |
| std::ofstream ofs(fileName, std::ios::app); |
| ofs << oss.str(); |
| ofs.close(); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::PopulateTargetUsage() |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| if (m_populateTargetUsage == false) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| const char *fileName = m_debugInterface->CreateFileName( |
| "EncodeSequence", |
| "EncodePar", |
| CodechalDbgExtType::par); |
| |
| std::ifstream ifs(fileName); |
| std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); |
| ifs.close(); |
| std::ofstream ofs(fileName, std::ios::trunc); |
| ofs << "TargetUsage = " << static_cast<uint32_t>(m_avcSeqParam->TargetUsage) << std::endl; |
| ofs << str; |
| ofs.close(); |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::PopulateDdiParam( |
| PCODEC_AVC_ENCODE_SEQUENCE_PARAMS avcSeqParams, |
| PCODEC_AVC_ENCODE_PIC_PARAMS avcPicParams, |
| PCODEC_AVC_ENCODE_SLICE_PARAMS avcSlcParams) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_DEBUG_CHK_NULL(m_debugInterface); |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| if (Slice_Type[avcSlcParams->slice_type] == SLICE_I || Slice_Type[avcSlcParams->slice_type] == SLICE_SI) |
| { |
| m_avcPar->ProfileIDC = avcSeqParams->Profile; |
| m_avcPar->LevelIDC = avcSeqParams->Level; |
| m_avcPar->DisableVUIHeader = !avcSeqParams->vui_parameters_present_flag; |
| m_avcPar->ChromaFormatIDC = avcSeqParams->chroma_format_idc; |
| m_avcPar->ChromaQpOffset = avcPicParams->chroma_qp_index_offset; |
| m_avcPar->SecondChromaQpOffset = avcPicParams->second_chroma_qp_index_offset; |
| |
| uint8_t pictureCodingType = CodecHal_PictureIsFrame(avcPicParams->CurrOriginalPic) ? 0 : (CodecHal_PictureIsTopField(avcPicParams->CurrOriginalPic) ? 1 : 3); |
| m_avcPar->PictureCodingType = pictureCodingType; |
| |
| uint16_t gopP = (avcSeqParams->GopRefDist) ? ((avcSeqParams->GopPicSize - 1) / avcSeqParams->GopRefDist) : 0; |
| uint16_t gopB = avcSeqParams->GopPicSize - 1 - gopP; |
| m_avcPar->NumP = gopP; |
| m_avcPar->NumB = ((gopP > 0) ? (gopB / gopP) : 0); |
| |
| if ((avcPicParams->NumSlice * m_sliceHeight) >= |
| (uint32_t)(avcSeqParams->pic_height_in_map_units_minus1 + 1 + m_sliceHeight)) |
| { |
| m_avcPar->NumSlices = avcPicParams->NumSlice - 1; |
| } |
| else |
| { |
| m_avcPar->NumSlices = avcPicParams->NumSlice; |
| } |
| m_avcPar->SliceHeight = m_sliceHeight; |
| |
| m_avcPar->NumSuperSlices = m_avcPar->NumSlices; |
| if (m_avcPar->NumSuperSlices) |
| { |
| uint32_t sliceIdx = 0; |
| for (; sliceIdx < m_avcPar->NumSuperSlices - 1; sliceIdx++) |
| { |
| m_avcPar->SuperSliceHeight[sliceIdx] = m_sliceHeight; |
| } |
| m_avcPar->SuperSliceHeight[sliceIdx] = avcSeqParams->pic_height_in_map_units_minus1 + 1 - sliceIdx * m_sliceHeight; |
| } |
| |
| m_avcPar->ISliceQP = avcPicParams->QpY + avcSlcParams->slice_qp_delta; |
| m_avcPar->FrameRateM = ((avcSeqParams->FramesPer100Sec % 100) == 0) ? (avcSeqParams->FramesPer100Sec / 100) : avcSeqParams->FramesPer100Sec; |
| m_avcPar->FrameRateD = ((avcSeqParams->FramesPer100Sec % 100) == 0) ? 1 : 100; |
| |
| uint8_t brcMethod = 0; |
| uint8_t brcType = 0; |
| |
| if (CodecHalIsRateControlBrc(avcSeqParams->RateControlMethod, CODECHAL_AVC)) |
| { |
| brcMethod = 2; |
| |
| switch (avcSeqParams->RateControlMethod) |
| { |
| case RATECONTROL_ICQ: |
| brcMethod = m_vdencEnabled ? 2 : 3; |
| brcType = 16; |
| break; |
| case RATECONTROL_QVBR: |
| brcMethod = m_vdencEnabled ? 2 : 4; |
| brcType = 2; |
| break; |
| case RATECONTROL_CBR: |
| brcType = 1; |
| break; |
| case RATECONTROL_VBR: |
| brcType = 2; |
| break; |
| case RATECONTROL_VCM: |
| brcType = m_vdencEnabled ? 4 : 3; |
| break; |
| default: |
| brcMethod = 0; |
| brcType = 0; |
| break; |
| } |
| |
| if (avcSeqParams->FrameSizeTolerance == EFRAMESIZETOL_EXTREMELY_LOW) |
| { |
| // low delay mode |
| brcType = 8; |
| } |
| } |
| |
| m_avcPar->BRCMethod = brcMethod; |
| m_avcPar->BRCType = brcType; |
| |
| m_avcPar->DeblockingIDC = avcSlcParams->disable_deblocking_filter_idc; |
| m_avcPar->DeblockingFilterAlpha = avcSlcParams->slice_alpha_c0_offset_div2 << 1; |
| m_avcPar->DeblockingFilterBeta = avcSlcParams->slice_beta_offset_div2 << 1; |
| m_avcPar->EntropyCodingMode = avcPicParams->entropy_coding_mode_flag; |
| m_avcPar->DirectInference = avcSeqParams->direct_8x8_inference_flag; |
| m_avcPar->Transform8x8Mode = avcPicParams->transform_8x8_mode_flag; |
| m_avcPar->CRFQualityFactor = avcSeqParams->ICQQualityFactor; |
| m_avcPar->ConstrainedIntraPred = avcPicParams->constrained_intra_pred_flag; |
| |
| // This is only for header matching although I frame doesn't have references |
| if (avcSlcParams->num_ref_idx_active_override_flag) |
| { |
| m_avcPar->MaxRefIdxL0 = MOS_MAX(m_avcPar->MaxRefIdxL0, avcSlcParams->num_ref_idx_l0_active_minus1); |
| m_avcPar->MaxRefIdxL1 = MOS_MAX(m_avcPar->MaxRefIdxL1, avcSlcParams->num_ref_idx_l1_active_minus1); |
| } |
| else |
| { |
| m_avcPar->MaxRefIdxL0 = MOS_MAX(m_avcPar->MaxRefIdxL0, avcPicParams->num_ref_idx_l0_active_minus1); |
| m_avcPar->MaxRefIdxL1 = MOS_MAX(m_avcPar->MaxRefIdxL1, avcPicParams->num_ref_idx_l1_active_minus1); |
| } |
| |
| if (m_vdencEnabled) |
| { |
| m_avcPar->SliceMode = avcSeqParams->EnableSliceLevelRateCtrl ? 2 : 0; |
| } |
| } |
| else if (Slice_Type[avcSlcParams->slice_type] == SLICE_P || Slice_Type[avcSlcParams->slice_type] == SLICE_SP) |
| { |
| m_avcPar->PSliceQP = avcPicParams->QpY + avcSlcParams->slice_qp_delta; |
| m_avcPar->CabacInitIDC = avcSlcParams->cabac_init_idc; |
| |
| if (avcSlcParams->num_ref_idx_active_override_flag) |
| { |
| m_avcPar->MaxRefIdxL0 = MOS_MAX(m_avcPar->MaxRefIdxL0, avcSlcParams->num_ref_idx_l0_active_minus1); |
| m_avcPar->MaxRefIdxL1 = MOS_MAX(m_avcPar->MaxRefIdxL1, avcSlcParams->num_ref_idx_l1_active_minus1); |
| } |
| else |
| { |
| m_avcPar->MaxRefIdxL0 = MOS_MAX(m_avcPar->MaxRefIdxL0, avcPicParams->num_ref_idx_l0_active_minus1); |
| m_avcPar->MaxRefIdxL1 = MOS_MAX(m_avcPar->MaxRefIdxL1, avcPicParams->num_ref_idx_l1_active_minus1); |
| } |
| |
| if (m_avcPar->NumB == 0) // There's no B frame |
| { |
| m_avcPar->EnableWeightPredictionDetection = avcPicParams->weighted_pred_flag > 0 ? 1 : 0; |
| } |
| m_avcPar->WeightedPred = avcPicParams->weighted_pred_flag; |
| m_avcPar->UseOrigAsRef = avcPicParams->UserFlags.bUseRawPicForRef; |
| m_avcPar->BiSubMbPartMask = avcPicParams->UserFlags.bDisableSubMBPartition ? (bool)(CODECHAL_ENCODE_AVC_DISABLE_4X4_SUB_MB_PARTITION | CODECHAL_ENCODE_AVC_DISABLE_4X8_SUB_MB_PARTITION | CODECHAL_ENCODE_AVC_DISABLE_8X4_SUB_MB_PARTITION) : 0; |
| |
| if (m_vdencEnabled) |
| { |
| if (m_targetUsage == 1 || m_targetUsage == 2) |
| { |
| m_avcPar->StaticFrameZMVPercent = avcPicParams->dwZMvThreshold; |
| } |
| else |
| { |
| m_avcPar->StaticFrameZMVPercent = 100; |
| } |
| |
| if (avcPicParams->bEnableHMEOffset) |
| { |
| m_avcPar->hme0XOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[0][0][0], -128, 127); |
| m_avcPar->hme0YOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[0][0][1], -128, 127); |
| m_avcPar->hme1XOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[1][0][0], -128, 127); |
| m_avcPar->hme1YOffset = MOS_CLAMP_MIN_MAX(avcPicParams->HMEOffset[1][0][1], -128, 127); |
| } |
| } |
| } |
| else if (Slice_Type[avcSlcParams->slice_type] == SLICE_B) |
| { |
| m_avcPar->BSliceQP = avcPicParams->QpY + avcSlcParams->slice_qp_delta; |
| |
| if (avcSlcParams->num_ref_idx_active_override_flag) |
| { |
| m_avcPar->MaxBRefIdxL0 = MOS_MAX(m_avcPar->MaxBRefIdxL0, avcSlcParams->num_ref_idx_l0_active_minus1); |
| } |
| else |
| { |
| m_avcPar->MaxBRefIdxL0 = MOS_MAX(m_avcPar->MaxBRefIdxL0, avcPicParams->num_ref_idx_l0_active_minus1); |
| } |
| |
| m_avcPar->EnableWeightPredictionDetection = (avcPicParams->weighted_bipred_idc | avcPicParams->weighted_pred_flag) > 0 ? 1 : 0; |
| m_avcPar->WeightedBiPred = avcPicParams->weighted_bipred_idc; |
| m_avcPar->BiWeight = m_biWeight; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::PopulateSliceStateParam( |
| bool adaptiveRoundingInterEnable, |
| PMHW_VDBOX_AVC_SLICE_STATE sliceState) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_DEBUG_CHK_NULL(m_debugInterface); |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| if (m_pictureCodingType == I_TYPE) |
| { |
| m_avcPar->RoundingIntraEnabled = true; |
| m_avcPar->RoundingIntra = 5; |
| // Set to 1 first, we don't consider 0 case as we only dump I frame param once |
| m_avcPar->FrmHdrEncodingFrequency = 1; // 1: picture header in every IDR frame |
| |
| // Search SEI NAL |
| m_avcPar->EnableSEI = SearchNALHeader(sliceState, CODECHAL_DEBUG_ENCODE_AVC_NAL_START_CODE_SEI); |
| } |
| else if (m_pictureCodingType == P_TYPE) |
| { |
| m_avcPar->EnableAdaptiveRounding = adaptiveRoundingInterEnable; |
| m_avcPar->RoundingInterEnabled = sliceState->bRoundingInterEnable; |
| m_avcPar->RoundingInter = sliceState->dwRoundingValue; |
| |
| // Search PPS NAL |
| m_avcPar->FrmHdrEncodingFrequency = |
| SearchNALHeader(sliceState, CODECHAL_DEBUG_ENCODE_AVC_NAL_START_CODE_PPS) ? 2 : m_avcPar->FrmHdrEncodingFrequency; |
| } |
| else if (m_pictureCodingType == B_TYPE) |
| { |
| m_avcPar->RoundingInterB = sliceState->dwRoundingValue; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| MOS_STATUS CodechalEncodeAvcBase::PopulateSfdParam( |
| void *cmd) |
| { |
| CODECHAL_DEBUG_FUNCTION_ENTER; |
| |
| CODECHAL_DEBUG_CHK_NULL(m_debugInterface); |
| |
| if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrDumpEncodePar)) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CODECHAL_ENCODE_AVC_SFD_CURBE_COMMON *curbe = (CODECHAL_ENCODE_AVC_SFD_CURBE_COMMON *)cmd; |
| |
| if (m_pictureCodingType == P_TYPE) |
| { |
| m_avcPar->EnableIntraCostScalingForStaticFrame = curbe->DW0.EnableIntraCostScalingForStaticFrame; |
| m_avcPar->StaticFrameIntraCostScalingRatioP = 240; |
| m_avcPar->AdaptiveMvStreamIn = curbe->DW0.EnableAdaptiveMvStreamIn; |
| m_avcPar->LargeMvThresh = curbe->DW3.LargeMvThresh; |
| m_avcPar->LargeMvPctThreshold = 1; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| #endif |
| |
| MOS_STATUS CodechalEncodeAvcBase::SetFrameStoreIds(uint8_t frameIdx) |
| { |
| uint8_t invalidFrame = (m_mode == CODECHAL_DECODE_MODE_AVCVLD) ? 0x7f : 0x1f; |
| |
| for (uint8_t i = 0; i < m_refList[frameIdx]->ucNumRef; i++) |
| { |
| uint8_t index; |
| index = m_refList[frameIdx]->RefList[i].FrameIdx; |
| if (m_refList[index]->ucFrameId == invalidFrame) |
| { |
| uint8_t j; |
| for (j = 0; j < CODEC_AVC_MAX_NUM_REF_FRAME; j++) |
| { |
| if (!m_avcFrameStoreID[j].inUse) |
| { |
| m_refList[index]->ucFrameId = j; |
| m_avcFrameStoreID[j].inUse = true; |
| break; |
| } |
| } |
| if (j == CODEC_AVC_MAX_NUM_REF_FRAME) |
| { |
| // should never happen, something must be wrong |
| CODECHAL_PUBLIC_ASSERT(false); |
| m_refList[index]->ucFrameId = 0; |
| m_avcFrameStoreID[0].inUse = true; |
| } |
| } |
| } |
| return MOS_STATUS_SUCCESS; |
| } |