| /* |
| * Copyright (c) 2017-2020, Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| //! |
| //! \file media_ddi_decode_avc.cpp |
| //! \brief The class implementation of DdiDecodeAVC for Avc decode |
| //! |
| |
| #include "media_libva_decoder.h" |
| #include "media_libva_util.h" |
| #include "media_ddi_decode_avc.h" |
| #include "mos_solo_generic.h" |
| #include "codechal_memdecomp.h" |
| #include "media_ddi_decode_const.h" |
| #include "media_ddi_factory.h" |
| #include "media_interfaces.h" |
| |
| VAStatus DdiDecodeAVC::ParseSliceParams( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| VASliceParameterBufferH264 *slcParam, |
| uint32_t numSlices) |
| { |
| PCODEC_AVC_SLICE_PARAMS avcSliceParams; |
| avcSliceParams = (PCODEC_AVC_SLICE_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_sliceParams); |
| avcSliceParams += m_ddiDecodeCtx->DecodeParams.m_numSlices; |
| |
| if ((slcParam == nullptr) || (avcSliceParams == nullptr)) |
| { |
| DDI_ASSERTMESSAGE("Invalid Parameter for Parsing AVC Slice parameter\n"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| VASliceParameterBufferH264 *slc; |
| slc = (VASliceParameterBufferH264 *)slcParam; |
| |
| VASliceParameterBufferBase *slcBase; |
| slcBase = (VASliceParameterBufferBase *)slcParam; |
| |
| PCODEC_AVC_PIC_PARAMS avcPicParams; |
| avcPicParams = (PCODEC_AVC_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams); |
| avcPicParams->pic_fields.IntraPicFlag = (slc->slice_type == 2) ? 1 : 0; |
| |
| bool useCABAC = (bool)(avcPicParams->pic_fields.entropy_coding_mode_flag); |
| |
| uint32_t sliceBaseOffset; |
| sliceBaseOffset = GetBsBufOffset(m_groupIndex); |
| |
| uint32_t i, slcCount, refCount; |
| for (slcCount = 0; slcCount < numSlices; slcCount++) |
| { |
| if (m_ddiDecodeCtx->bShortFormatInUse) |
| { |
| avcSliceParams->slice_data_size = slcBase->slice_data_size; |
| avcSliceParams->slice_data_offset = sliceBaseOffset + |
| slcBase->slice_data_offset; |
| if (slcBase->slice_data_flag) |
| { |
| DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call"); |
| } |
| slcBase++; |
| } |
| else |
| { |
| if (useCABAC) |
| { |
| // add the alignment bit |
| slc->slice_data_bit_offset = MOS_ALIGN_CEIL(slc->slice_data_bit_offset, 8); |
| } |
| |
| // remove 1 byte of NAL unit code |
| slc->slice_data_bit_offset = slc->slice_data_bit_offset - 8; |
| |
| avcSliceParams->slice_data_size = slc->slice_data_size; |
| avcSliceParams->slice_data_offset = sliceBaseOffset + |
| slc->slice_data_offset; |
| if (slc->slice_data_flag) |
| { |
| DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call"); |
| } |
| |
| avcSliceParams->slice_data_bit_offset = slc->slice_data_bit_offset; |
| avcSliceParams->first_mb_in_slice = slc->first_mb_in_slice; |
| avcSliceParams->NumMbsForSlice = 0; // not in LibVA slc->NumMbsForSlice; |
| avcSliceParams->slice_type = slc->slice_type; |
| avcSliceParams->direct_spatial_mv_pred_flag = slc->direct_spatial_mv_pred_flag; |
| avcSliceParams->num_ref_idx_l0_active_minus1 = slc->num_ref_idx_l0_active_minus1; |
| avcSliceParams->num_ref_idx_l1_active_minus1 = slc->num_ref_idx_l1_active_minus1; |
| if(slcCount == 0) |
| { |
| avcPicParams->num_ref_idx_l0_active_minus1 = avcSliceParams->num_ref_idx_l0_active_minus1; |
| avcPicParams->num_ref_idx_l1_active_minus1 = avcSliceParams->num_ref_idx_l1_active_minus1; |
| } |
| avcSliceParams->cabac_init_idc = slc->cabac_init_idc; |
| avcSliceParams->slice_qp_delta = slc->slice_qp_delta; |
| avcSliceParams->disable_deblocking_filter_idc = slc->disable_deblocking_filter_idc; |
| avcSliceParams->slice_alpha_c0_offset_div2 = slc->slice_alpha_c0_offset_div2; |
| avcSliceParams->slice_beta_offset_div2 = slc->slice_beta_offset_div2; |
| // reference list 0 |
| refCount = std::min(avcSliceParams->num_ref_idx_l0_active_minus1 + 1, CODEC_MAX_NUM_REF_FIELD); |
| for (i = 0; i < refCount; i++) |
| { |
| SetupCodecPicture( |
| mediaCtx, |
| &(m_ddiDecodeCtx->RTtbl), |
| &(avcSliceParams->RefPicList[0][i]), |
| slc->RefPicList0[i], |
| avcPicParams->pic_fields.field_pic_flag, |
| false, |
| true); |
| |
| GetSlcRefIdx(&(avcPicParams->RefFrameList[0]), &(avcSliceParams->RefPicList[0][i])); |
| } |
| // reference list 1 |
| refCount = std::min(avcSliceParams->num_ref_idx_l1_active_minus1 + 1, CODEC_MAX_NUM_REF_FIELD); |
| for (i = 0; i < refCount; i++) |
| { |
| SetupCodecPicture( |
| mediaCtx, |
| &(m_ddiDecodeCtx->RTtbl), |
| &(avcSliceParams->RefPicList[1][i]), |
| slc->RefPicList1[i], |
| avcPicParams->pic_fields.field_pic_flag, |
| false, |
| true); |
| |
| GetSlcRefIdx(&(avcPicParams->RefFrameList[0]), &(avcSliceParams->RefPicList[1][i])); |
| } |
| |
| avcSliceParams->luma_log2_weight_denom = slc->luma_log2_weight_denom; |
| avcSliceParams->chroma_log2_weight_denom = slc->chroma_log2_weight_denom; |
| for (i = 0; i < 32; i++) |
| { |
| // list 0 |
| avcSliceParams->Weights[0][i][0][0] = slc->luma_weight_l0[i]; // Y weight |
| avcSliceParams->Weights[0][i][0][1] = slc->luma_offset_l0[i]; // Y offset |
| |
| avcSliceParams->Weights[0][i][1][0] = slc->chroma_weight_l0[i][0]; // Cb weight |
| avcSliceParams->Weights[0][i][1][1] = slc->chroma_offset_l0[i][0]; // Cb offset |
| |
| avcSliceParams->Weights[0][i][2][0] = slc->chroma_weight_l0[i][1]; // Cr weight |
| avcSliceParams->Weights[0][i][2][1] = slc->chroma_offset_l0[i][1]; // Cr offset |
| |
| // list 1 |
| avcSliceParams->Weights[1][i][0][0] = slc->luma_weight_l1[i]; // Y weight |
| avcSliceParams->Weights[1][i][0][1] = slc->luma_offset_l1[i]; // Y offset |
| |
| avcSliceParams->Weights[1][i][1][0] = slc->chroma_weight_l1[i][0]; // Cb weight |
| avcSliceParams->Weights[1][i][1][1] = slc->chroma_offset_l1[i][0]; // Cb offset |
| |
| avcSliceParams->Weights[1][i][2][0] = slc->chroma_weight_l1[i][1]; // Cr weight |
| avcSliceParams->Weights[1][i][2][1] = slc->chroma_offset_l1[i][1]; // Cr offset |
| } |
| slc++; |
| } |
| avcSliceParams->slice_id = 0; |
| avcSliceParams++; |
| } |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeAVC::ParsePicParams( |
| DDI_MEDIA_CONTEXT * mediaCtx, |
| VAPictureParameterBufferH264 *picParam) |
| { |
| PCODEC_AVC_PIC_PARAMS avcPicParams; |
| avcPicParams = (PCODEC_AVC_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams); |
| |
| if ((picParam == nullptr) || |
| (avcPicParams == nullptr)) |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| |
| SetupCodecPicture(mediaCtx, |
| &(m_ddiDecodeCtx->RTtbl), |
| &avcPicParams->CurrPic, |
| picParam->CurrPic, |
| picParam->pic_fields.bits.field_pic_flag, |
| false, |
| false); |
| |
| //Check the current frame index |
| //Add the invalid surface id to RecList |
| if (avcPicParams->CurrPic.FrameIdx < CODEC_AVC_NUM_UNCOMPRESSED_SURFACE) |
| { |
| m_ddiDecodeCtx->RecListSurfaceID[avcPicParams->CurrPic.FrameIdx] = |
| picParam->CurrPic.picture_id; |
| } |
| |
| uint32_t i; |
| uint32_t j; |
| avcPicParams->UsedForReferenceFlags = 0x0; |
| for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) |
| { |
| if (picParam->ReferenceFrames[i].picture_id != VA_INVALID_SURFACE) |
| { |
| UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), |
| DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, |
| picParam->ReferenceFrames[i].picture_id)); |
| } |
| |
| SetupCodecPicture( |
| mediaCtx, |
| &(m_ddiDecodeCtx->RTtbl), |
| &(avcPicParams->RefFrameList[i]), |
| picParam->ReferenceFrames[i], |
| picParam->pic_fields.bits.field_pic_flag, |
| true, |
| false); |
| |
| if ((picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_SHORT_TERM_REFERENCE) || |
| (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_LONG_TERM_REFERENCE)) |
| { |
| if (!m_ddiDecodeCtx->bShortFormatInUse) |
| { |
| avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (3 << (i * 2)); |
| } |
| else if ((picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) || |
| (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD)) |
| { |
| if (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_BOTTOM_FIELD) |
| avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (2 << (i * 2)); |
| |
| if (picParam->ReferenceFrames[i].flags & VA_PICTURE_H264_TOP_FIELD) |
| avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (1 << (i * 2)); |
| } |
| else |
| { |
| avcPicParams->UsedForReferenceFlags = avcPicParams->UsedForReferenceFlags | (3 << (i * 2)); |
| } |
| } |
| } |
| |
| //Accoding to RecList, if the surface id is invalid, set PicFlags equal to PICTURE_INVALID |
| for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) |
| { |
| //Check the surface id of reference list |
| if (VA_INVALID_ID == m_ddiDecodeCtx->RecListSurfaceID[avcPicParams->RefFrameList[i].FrameIdx]) |
| { |
| //Set invalid flag |
| avcPicParams->RefFrameList[i].PicFlags = PICTURE_INVALID; |
| } |
| } |
| |
| avcPicParams->pic_width_in_mbs_minus1 = picParam->picture_width_in_mbs_minus1; |
| avcPicParams->pic_height_in_mbs_minus1 = picParam->picture_height_in_mbs_minus1; |
| avcPicParams->bit_depth_luma_minus8 = picParam->bit_depth_luma_minus8; |
| avcPicParams->bit_depth_chroma_minus8 = picParam->bit_depth_chroma_minus8; |
| avcPicParams->num_ref_frames = picParam->num_ref_frames; |
| avcPicParams->CurrFieldOrderCnt[0] = picParam->CurrPic.TopFieldOrderCnt; |
| avcPicParams->CurrFieldOrderCnt[1] = picParam->CurrPic.BottomFieldOrderCnt; |
| for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) |
| { |
| avcPicParams->FieldOrderCntList[i][0] = picParam->ReferenceFrames[i].TopFieldOrderCnt; |
| avcPicParams->FieldOrderCntList[i][1] = picParam->ReferenceFrames[i].BottomFieldOrderCnt; |
| } |
| |
| avcPicParams->seq_fields.chroma_format_idc = picParam->seq_fields.bits.chroma_format_idc; |
| avcPicParams->seq_fields.residual_colour_transform_flag = picParam->seq_fields.bits.residual_colour_transform_flag; |
| avcPicParams->seq_fields.frame_mbs_only_flag = picParam->seq_fields.bits.frame_mbs_only_flag; |
| avcPicParams->seq_fields.mb_adaptive_frame_field_flag = picParam->seq_fields.bits.mb_adaptive_frame_field_flag; |
| avcPicParams->seq_fields.direct_8x8_inference_flag = picParam->seq_fields.bits.direct_8x8_inference_flag; |
| avcPicParams->seq_fields.log2_max_frame_num_minus4 = picParam->seq_fields.bits.log2_max_frame_num_minus4; |
| avcPicParams->seq_fields.pic_order_cnt_type = picParam->seq_fields.bits.pic_order_cnt_type; |
| avcPicParams->seq_fields.log2_max_pic_order_cnt_lsb_minus4 = picParam->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4; |
| avcPicParams->seq_fields.delta_pic_order_always_zero_flag = picParam->seq_fields.bits.delta_pic_order_always_zero_flag; |
| |
| avcPicParams->num_slice_groups_minus1 = 0; |
| avcPicParams->slice_group_map_type = 0; |
| avcPicParams->slice_group_change_rate_minus1 = 0; |
| avcPicParams->pic_init_qp_minus26 = picParam->pic_init_qp_minus26; |
| avcPicParams->chroma_qp_index_offset = picParam->chroma_qp_index_offset; |
| avcPicParams->second_chroma_qp_index_offset = picParam->second_chroma_qp_index_offset; |
| |
| avcPicParams->pic_fields.entropy_coding_mode_flag = picParam->pic_fields.bits.entropy_coding_mode_flag; |
| avcPicParams->pic_fields.weighted_pred_flag = picParam->pic_fields.bits.weighted_pred_flag; |
| avcPicParams->pic_fields.weighted_bipred_idc = picParam->pic_fields.bits.weighted_bipred_idc; |
| avcPicParams->pic_fields.transform_8x8_mode_flag = picParam->pic_fields.bits.transform_8x8_mode_flag; |
| avcPicParams->pic_fields.field_pic_flag = picParam->pic_fields.bits.field_pic_flag; |
| avcPicParams->pic_fields.constrained_intra_pred_flag = picParam->pic_fields.bits.constrained_intra_pred_flag; |
| avcPicParams->pic_fields.pic_order_present_flag = picParam->pic_fields.bits.pic_order_present_flag; |
| avcPicParams->pic_fields.deblocking_filter_control_present_flag = picParam->pic_fields.bits.deblocking_filter_control_present_flag; |
| avcPicParams->pic_fields.redundant_pic_cnt_present_flag = picParam->pic_fields.bits.redundant_pic_cnt_present_flag; |
| avcPicParams->pic_fields.reference_pic_flag = picParam->pic_fields.bits.reference_pic_flag; |
| |
| for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) |
| { |
| avcPicParams->FrameNumList[i] = picParam->ReferenceFrames[i].frame_idx; |
| } |
| |
| avcPicParams->frame_num = picParam->frame_num; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeAVC::ParseIQMatrix( |
| DDI_MEDIA_CONTEXT * mediaCtx, |
| VAIQMatrixBufferH264 *matrix) |
| { |
| PCODEC_AVC_IQ_MATRIX_PARAMS avcIqMatrix; |
| |
| avcIqMatrix = (PCODEC_AVC_IQ_MATRIX_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer); |
| |
| if ((matrix == nullptr) || (avcIqMatrix == nullptr)) |
| { |
| DDI_ASSERTMESSAGE("Invalid Parameter for Parsing AVC IQMatrix parameter\n"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| // 4x4 block |
| int32_t i; |
| for (i = 0; i < 6; i++) |
| { |
| MOS_SecureMemcpy(avcIqMatrix->ScalingList4x4[i], |
| 16, |
| matrix->ScalingList4x4[i], |
| 16); |
| } |
| // 8x8 block |
| for (i = 0; i < 2; i++) |
| { |
| MOS_SecureMemcpy(avcIqMatrix->ScalingList8x8[i], |
| 64, |
| matrix->ScalingList8x8[i], |
| 64); |
| } |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeAVC::AllocSliceParamContext( |
| uint32_t numSlices) |
| { |
| uint32_t baseSize = sizeof(CODEC_AVC_SLICE_PARAMS); |
| |
| if (m_sliceParamBufNum < (m_ddiDecodeCtx->DecodeParams.m_numSlices + numSlices)) |
| { |
| // in order to avoid that the buffer is reallocated multi-times, |
| // extra 10 slices are added. |
| uint32_t extraSlices = numSlices + 10; |
| m_ddiDecodeCtx->DecodeParams.m_sliceParams = realloc(m_ddiDecodeCtx->DecodeParams.m_sliceParams, |
| baseSize * (m_sliceParamBufNum + extraSlices)); |
| |
| if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr) |
| { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| |
| memset((void *)((uint8_t *)m_ddiDecodeCtx->DecodeParams.m_sliceParams + baseSize * m_sliceParamBufNum), |
| 0, |
| baseSize * extraSlices); |
| |
| m_sliceParamBufNum += extraSlices; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeAVC::RenderPicture( |
| VADriverContextP ctx, |
| VAContextID context, |
| VABufferID * buffers, |
| int32_t numBuffers) |
| { |
| VAStatus va = VA_STATUS_SUCCESS; |
| |
| DDI_FUNCTION_ENTER(); |
| |
| PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx); |
| void * data; |
| for (int32_t i = 0; i < numBuffers; i++) |
| { |
| DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]); |
| if (nullptr == buf) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| uint32_t dataSize = buf->iSize; |
| |
| DdiMedia_MapBuffer(ctx, buffers[i], &data); |
| |
| if (data == nullptr) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| |
| switch ((int32_t)buf->uiType) |
| { |
| case VASliceDataBufferType: |
| { |
| int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf); |
| if (index == DDI_CODEC_INVALID_BUFFER_INDEX) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| |
| DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer); |
| m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize; |
| break; |
| } |
| case VASliceParameterBufferType: |
| { |
| VASliceParameterBufferH264 *slcInfoH264; |
| if (buf->uiNumElements == 0) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| |
| slcInfoH264 = (VASliceParameterBufferH264 *)data; |
| uint32_t numSlices = buf->uiNumElements; |
| DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!"); |
| DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoH264, numSlices),"ParseSliceParams failed!"); |
| m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices; |
| m_groupIndex++; |
| break; |
| } |
| case VAIQMatrixBufferType: |
| { |
| VAIQMatrixBufferH264 *imxBuf = (VAIQMatrixBufferH264 *)data; |
| DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!"); |
| break; |
| } |
| case VAPictureParameterBufferType: |
| { |
| VAPictureParameterBufferH264 *picParam; |
| picParam = (VAPictureParameterBufferH264 *)data; |
| DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!"); |
| break; |
| } |
| case VAProcPipelineParameterBufferType: |
| { |
| DDI_CHK_RET(ParseProcessingBuffer(mediaCtx, data),"ParseProcessingBuffer failed!"); |
| break; |
| } |
| case VADecodeStreamoutBufferType: |
| { |
| DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer); |
| m_streamOutEnabled = true; |
| break; |
| } |
| |
| default: |
| va = m_ddiDecodeCtx->pCpDdiInterface->RenderCencPicture(ctx, context, buf, data); |
| break; |
| } |
| DdiMedia_UnmapBuffer(ctx, buffers[i]); |
| } |
| |
| DDI_FUNCTION_EXIT(va); |
| return va; |
| } |
| |
| VAStatus DdiDecodeAVC::SetDecodeParams() |
| { |
| DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!"); |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| // Bridge the SFC input with VDBOX output |
| if (m_decProcessingType == VA_DEC_PROCESSING) |
| { |
| auto procParams = |
| (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams; |
| procParams->m_inputSurface = (&m_ddiDecodeCtx->DecodeParams)->m_destSurface; |
| // codechal_decode_sfc.c expects Input Width/Height information. |
| procParams->m_inputSurface->dwWidth = procParams->m_inputSurface->OsResource.iWidth; |
| procParams->m_inputSurface->dwHeight = procParams->m_inputSurface->OsResource.iHeight; |
| procParams->m_inputSurface->dwPitch = procParams->m_inputSurface->OsResource.iPitch; |
| procParams->m_inputSurface->Format = procParams->m_inputSurface->OsResource.Format; |
| } |
| #endif |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| void DdiDecodeAVC::DestroyContext( |
| VADriverContextP ctx) |
| { |
| FreeResourceBuffer(); |
| // explicitly call the base function to do the further clean-up |
| DdiMediaDecode::DestroyContext(ctx); |
| return; |
| } |
| |
| void DdiDecodeAVC::ContextInit(int32_t picWidth, int32_t picHeight) |
| { |
| // call the function in base class to initialize it. |
| DdiMediaDecode::ContextInit(picWidth, picHeight); |
| |
| if (m_ddiDecodeAttr->uiDecSliceMode == VA_DEC_SLICE_MODE_BASE) |
| { |
| m_ddiDecodeCtx->bShortFormatInUse = true; |
| } |
| m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_AVCVLD; |
| return; |
| } |
| |
| uint8_t* DdiDecodeAVC::GetPicParamBuf( |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr) |
| { |
| return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_H264.PicParam264)); |
| } |
| |
| VAStatus DdiDecodeAVC::AllocSliceControlBuffer( |
| DDI_MEDIA_BUFFER *buf) |
| { |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr; |
| uint32_t availSize; |
| uint32_t newSize; |
| |
| bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| availSize = m_sliceCtrlBufNum - bufMgr->dwNumSliceControl; |
| |
| if(m_ddiDecodeCtx->bShortFormatInUse) |
| { |
| if(availSize < buf->uiNumElements) |
| { |
| newSize = sizeof(VASliceParameterBufferBase) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements); |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = (VASliceParameterBufferBase *)realloc(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base, newSize); |
| if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base == nullptr) |
| { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferBase) * (buf->uiNumElements - availSize)); |
| m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements; |
| } |
| buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base; |
| buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferBase); |
| } |
| else |
| { |
| if(availSize < buf->uiNumElements) |
| { |
| newSize = sizeof(VASliceParameterBufferH264) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements); |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = (VASliceParameterBufferH264 *)realloc(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264, newSize); |
| if(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 == nullptr) |
| { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferH264) * (buf->uiNumElements - availSize)); |
| m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements; |
| } |
| buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264; |
| buf->uiOffset = bufMgr->dwNumSliceControl * sizeof(VASliceParameterBufferH264); |
| } |
| |
| bufMgr->dwNumSliceControl += buf->uiNumElements; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeAVC::CodecHalInit( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| void *ptr) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr; |
| |
| m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse; |
| |
| CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE; |
| |
| CODECHAL_STANDARD_INFO standardInfo; |
| memset(&standardInfo, 0, sizeof(standardInfo)); |
| |
| standardInfo.CodecFunction = codecFunction; |
| standardInfo.Mode = (CODECHAL_MODE)m_ddiDecodeCtx->wMode; |
| |
| m_codechalSettings->codecFunction = codecFunction; |
| m_codechalSettings->width = m_width; |
| m_codechalSettings->height = m_height; |
| //For Avc Decoding: |
| // if the slice header contains the emulation_prevention_three_byte, we need to set bIntelEntrypointInUse to false. |
| // Because in this case, driver can not get the correct BsdStartAddress by itself. We need to turn to GEN to calculate the correct address. |
| m_codechalSettings->intelEntrypointInUse = false; |
| |
| m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS; |
| |
| m_codechalSettings->mode = CODECHAL_DECODE_MODE_AVCVLD; |
| m_codechalSettings->standard = CODECHAL_AVC; |
| |
| m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings); |
| |
| m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = (void*)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_IQ_MATRIX_PARAMS)); |
| if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| m_ddiDecodeCtx->DecodeParams.m_picParams = (void*)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_PIC_PARAMS)); |
| if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| |
| m_sliceParamBufNum = m_picHeightInMB; |
| m_ddiDecodeCtx->DecodeParams.m_sliceParams = (void*)MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CODEC_AVC_SLICE_PARAMS)); |
| if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| if (m_decProcessingType == VA_DEC_PROCESSING) |
| { |
| DecodeProcessingParams *procParams = nullptr; |
| |
| m_codechalSettings->downsamplingHinted = true; |
| |
| procParams = (DecodeProcessingParams *)MOS_AllocAndZeroMemory(sizeof(DecodeProcessingParams)); |
| if (procParams == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| |
| m_ddiDecodeCtx->DecodeParams.m_procParams = procParams; |
| procParams->m_outputSurface = (PMOS_SURFACE)MOS_AllocAndZeroMemory(sizeof(MOS_SURFACE)); |
| if (procParams->m_outputSurface == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| } |
| #endif |
| vaStatus = CreateCodecHal(mediaCtx, |
| ptr, |
| &standardInfo); |
| |
| if (vaStatus != VA_STATUS_SUCCESS) |
| { |
| goto CleanUpandReturn; |
| } |
| |
| if (InitResourceBuffer() != VA_STATUS_SUCCESS) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| |
| return vaStatus; |
| |
| CleanUpandReturn: |
| FreeResourceBuffer(); |
| |
| if (m_ddiDecodeCtx->pCodecHal) |
| { |
| m_ddiDecodeCtx->pCodecHal->Destroy(); |
| MOS_Delete(m_ddiDecodeCtx->pCodecHal); |
| m_ddiDecodeCtx->pCodecHal = nullptr; |
| } |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer); |
| m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr; |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams); |
| m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr; |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_huffmanTable); |
| m_ddiDecodeCtx->DecodeParams.m_huffmanTable = nullptr; |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams); |
| m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr; |
| |
| #ifdef _DECODE_PROCESSING_SUPPORTED |
| if (m_ddiDecodeCtx->DecodeParams.m_procParams) |
| { |
| auto procParams = |
| (DecodeProcessingParams *)m_ddiDecodeCtx->DecodeParams.m_procParams; |
| MOS_FreeMemory(procParams->m_outputSurface); |
| |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_procParams); |
| m_ddiDecodeCtx->DecodeParams.m_procParams = nullptr; |
| } |
| #endif |
| return vaStatus; |
| } |
| |
| VAStatus DdiDecodeAVC::InitResourceBuffer() |
| { |
| VAStatus vaStatus; |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr; |
| |
| vaStatus = VA_STATUS_SUCCESS; |
| bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| bufMgr->pSliceData = nullptr; |
| |
| bufMgr->ui64BitstreamOrder = 0; |
| |
| if(m_width * m_height < CODEC_720P_MAX_PIC_WIDTH * CODEC_720P_MAX_PIC_HEIGHT) |
| { |
| bufMgr->dwMaxBsSize = m_width * m_height * 3 / 2; |
| } |
| else if(m_width * m_height < CODEC_4K_MAX_PIC_WIDTH * CODEC_4K_MAX_PIC_HEIGHT) |
| { |
| bufMgr->dwMaxBsSize = m_width * m_height * 3 / 8; |
| } |
| else |
| { |
| bufMgr->dwMaxBsSize = m_width * m_height * 3 / 16; |
| } |
| |
| // minimal 10k bytes for some special case. Will refractor this later |
| if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE) |
| { |
| bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE; |
| } |
| |
| int32_t i, count; |
| // init decode bitstream buffer object |
| for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++) |
| { |
| bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER)); |
| if (bufMgr->pBitStreamBuffObject[i] == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| bufMgr->pBitStreamBuffObject[i]->iSize = bufMgr->dwMaxBsSize; |
| bufMgr->pBitStreamBuffObject[i]->uiType = VASliceDataBufferType; |
| bufMgr->pBitStreamBuffObject[i]->format = Media_Format_Buffer; |
| bufMgr->pBitStreamBuffObject[i]->uiOffset = 0; |
| bufMgr->pBitStreamBuffObject[i]->bo = nullptr; |
| bufMgr->pBitStreamBase[i] = nullptr; |
| } |
| |
| // The pSliceData can be allocated on demand. So the default size is wPicHeightInMB. |
| bufMgr->m_maxNumSliceData = m_picHeightInMB; |
| bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO*)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) * |
| bufMgr->m_maxNumSliceData); |
| |
| if (bufMgr->pSliceData == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| |
| bufMgr->dwNumSliceData = 0; |
| bufMgr->dwNumSliceControl = 0; |
| |
| m_sliceCtrlBufNum = m_picHeightInMB; |
| if (m_ddiDecodeCtx->bShortFormatInUse) |
| { |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = (VASliceParameterBufferBase *) |
| MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferBase) * m_sliceCtrlBufNum); |
| if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| } |
| else |
| { |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = (VASliceParameterBufferH264 *) |
| MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferH264) * m_sliceCtrlBufNum); |
| if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| } |
| |
| return VA_STATUS_SUCCESS; |
| |
| finish: |
| FreeResourceBuffer(); |
| return vaStatus; |
| } |
| |
| void DdiDecodeAVC::FreeResourceBuffer() |
| { |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr; |
| int32_t i; |
| |
| bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| |
| for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++) |
| { |
| if (bufMgr->pBitStreamBase[i]) |
| { |
| DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]); |
| bufMgr->pBitStreamBase[i] = nullptr; |
| } |
| if (bufMgr->pBitStreamBuffObject[i]) |
| { |
| DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]); |
| MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]); |
| bufMgr->pBitStreamBuffObject[i] = nullptr; |
| } |
| } |
| |
| if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264) |
| { |
| MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264); |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264 = nullptr; |
| } |
| if (bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base) |
| { |
| MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base); |
| bufMgr->Codec_Param.Codec_Param_H264.pVASliceParaBufH264Base = nullptr; |
| } |
| |
| // free decode bitstream buffer object |
| MOS_FreeMemory(bufMgr->pSliceData); |
| bufMgr->pSliceData = nullptr; |
| } |
| |
| void DdiDecodeAVC::GetSlcRefIdx(CODEC_PICTURE *picReference, CODEC_PICTURE *slcReference) |
| { |
| if (nullptr == picReference|| nullptr == slcReference) |
| {return;} |
| |
| int32_t i = 0; |
| if (slcReference->FrameIdx != CODEC_AVC_NUM_UNCOMPRESSED_SURFACE) |
| { |
| for (i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) |
| { |
| if (slcReference->FrameIdx == picReference[i].FrameIdx) |
| { |
| slcReference->FrameIdx = i; |
| break; |
| } |
| } |
| if (i == CODEC_MAX_NUM_REF_FRAME) |
| { |
| slcReference->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE; |
| } |
| } |
| } |
| |
| void DdiDecodeAVC::SetupCodecPicture( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| DDI_CODEC_RENDER_TARGET_TABLE *rtTbl, |
| CODEC_PICTURE *codecHalPic, |
| VAPictureH264 vaPic, |
| bool fieldPicFlag, |
| bool picReference, |
| bool sliceReference) |
| { |
| if(vaPic.picture_id != DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| DDI_MEDIA_SURFACE *surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, vaPic.picture_id); |
| vaPic.frame_idx = GetRenderTargetID(rtTbl, surface); |
| codecHalPic->FrameIdx = (uint8_t)vaPic.frame_idx; |
| } |
| else |
| { |
| vaPic.frame_idx = DDI_CODEC_INVALID_FRAME_INDEX; |
| codecHalPic->FrameIdx = CODEC_AVC_NUM_UNCOMPRESSED_SURFACE - 1; |
| } |
| |
| if (picReference) |
| { |
| if (vaPic.frame_idx == DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| codecHalPic->PicFlags = PICTURE_INVALID; |
| } |
| else if ((vaPic.flags&VA_PICTURE_H264_LONG_TERM_REFERENCE) == VA_PICTURE_H264_LONG_TERM_REFERENCE) |
| { |
| codecHalPic->PicFlags = PICTURE_LONG_TERM_REFERENCE; |
| } |
| else |
| { |
| codecHalPic->PicFlags = PICTURE_SHORT_TERM_REFERENCE; |
| } |
| } |
| else |
| { |
| if (fieldPicFlag) |
| { |
| if ((vaPic.flags&VA_PICTURE_H264_BOTTOM_FIELD) == VA_PICTURE_H264_BOTTOM_FIELD) |
| { |
| codecHalPic->PicFlags = PICTURE_BOTTOM_FIELD; |
| } |
| else |
| { |
| codecHalPic->PicFlags = PICTURE_TOP_FIELD; |
| } |
| } |
| else |
| { |
| codecHalPic->PicFlags = PICTURE_FRAME; |
| } |
| } |
| |
| if (sliceReference && (vaPic.picture_id == VA_INVALID_ID))//VA_INVALID_ID is used to indicate invalide picture in LIBVA. |
| { |
| codecHalPic->PicFlags = PICTURE_INVALID; |
| } |
| } |
| |
| extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>; |
| |
| static bool h264Registered = |
| MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>:: |
| RegisterCodec<DdiDecodeAVC>(DECODE_ID_AVC); |