| /* |
| * Copyright (c) 2015-2017, 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_vc1.cpp |
| //! \brief libva(and its extension) decoder implementation |
| //! |
| #include "media_libva_decoder.h" |
| #include "media_libva_util.h" |
| |
| #include "media_ddi_decode_vc1.h" |
| #include "mos_solo_generic.h" |
| #include "codechal_memdecomp.h" |
| #include "media_ddi_decode_const.h" |
| #include "media_ddi_factory.h" |
| |
| static const int32_t FractionToScaleFactor[21] = { |
| 128, 85, 170, 64, 192, |
| 51, 102, 153, 204, 43, |
| 215, 37, 74, 111, 148, |
| 185, 222, 32, 96, 160, |
| 224, |
| }; |
| |
| void DdiDecodeVC1::CalculateQuantParams( |
| VAPictureParameterBufferVC1 *picParam, |
| uint32_t *outAltPquantConfig, |
| uint32_t *outAltPquantEdgeMask) |
| { |
| uint32_t dquant = picParam->pic_quantizer_fields.bits.dquant; |
| uint32_t dqFrame = picParam->pic_quantizer_fields.bits.dq_frame; |
| uint32_t dqProfile = picParam->pic_quantizer_fields.bits.dq_profile; |
| uint32_t dqDbedge = picParam->pic_quantizer_fields.bits.dq_db_edge; |
| uint32_t dqSbedge = picParam->pic_quantizer_fields.bits.dq_sb_edge; |
| uint32_t dqBilevel = picParam->pic_quantizer_fields.bits.dq_binary_level; |
| |
| uint32_t altPquantConfig = 0; |
| uint32_t altPquantEdgeMask = 0; |
| |
| if (dquant == 0) |
| { |
| altPquantConfig = 0; |
| altPquantEdgeMask = 0; |
| } |
| else if (dquant == 1) |
| { |
| if (dqFrame == 0) |
| { |
| altPquantConfig = 0; |
| altPquantEdgeMask = 0; |
| } |
| else if (dqFrame == 1) |
| { |
| altPquantConfig = 1; |
| altPquantEdgeMask = 0; |
| switch (dqProfile) |
| { |
| case 0: //all edge with altpquant |
| altPquantEdgeMask = 0xf; |
| break; |
| |
| case 1: //double edge with altpquant |
| if (dqDbedge == 3) |
| { |
| altPquantEdgeMask = 0x9; |
| } |
| else |
| { |
| altPquantEdgeMask = (0x3 << dqDbedge); |
| } |
| break; |
| |
| case 2: //single edge with altpquant |
| altPquantEdgeMask = (0x1 << dqSbedge); |
| break; |
| |
| case 3: //all mbs |
| if (dqBilevel == 0) |
| { |
| altPquantConfig = 2; |
| altPquantEdgeMask = 0; |
| } |
| else |
| { |
| altPquantConfig = 3; |
| altPquantEdgeMask = 0; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| } |
| else |
| { |
| altPquantConfig = 1; |
| altPquantEdgeMask = 0xf; |
| } |
| |
| *outAltPquantConfig = altPquantConfig; |
| *outAltPquantEdgeMask = altPquantEdgeMask; |
| } |
| |
| static inline bool IsBIField( |
| bool isFirstField, |
| int16_t picType) |
| { |
| bool isBI = false; |
| |
| if (picType == vc1BBIField) |
| { |
| isBI = (!isFirstField); |
| } |
| else if (picType == vc1BIBField) |
| { |
| isBI = isFirstField; |
| } |
| else if (picType == vc1BIBIField) |
| { |
| isBI = true; |
| } |
| |
| return isBI; |
| } |
| |
| static inline bool IsBField( |
| bool isFirstField, |
| int16_t picType) |
| { |
| bool isBottom = false; |
| |
| if (picType == vc1BBIField) |
| { |
| isBottom = isFirstField; |
| } |
| else if (picType == vc1BIBField) |
| { |
| isBottom = (!isFirstField); |
| } |
| else if (picType == vc1BBField) |
| { |
| isBottom = true; |
| } |
| |
| return isBottom; |
| } |
| |
| static inline bool IsIField( |
| bool isFirstField, |
| int16_t picType) |
| { |
| bool isIF = false; |
| |
| if (picType == vc1IPField) |
| { |
| isIF = isFirstField; |
| } |
| else if (picType == vc1PIField) |
| { |
| isIF = !isFirstField; |
| } |
| else if (picType == vc1IIField) |
| { |
| isIF = true; |
| } |
| |
| return isIF; |
| } |
| |
| VAStatus DdiDecodeVC1::ParsePicParams( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| VAPictureParameterBufferVC1 *picParam) |
| { |
| PCODEC_VC1_PIC_PARAMS codecPicParam = (PCODEC_VC1_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams); |
| |
| if ((codecPicParam == nullptr) || |
| (picParam == nullptr)) |
| { |
| DDI_ASSERTMESSAGE("nullptr pointer in Parsing VC1 Picture parameter\n"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| uint32_t scaleFactor = 0; |
| // See spec, table 40 && Figure 70 |
| if ((picParam->b_picture_fraction >= 0) && (picParam->b_picture_fraction < 21)) |
| { |
| scaleFactor = FractionToScaleFactor[picParam->b_picture_fraction]; |
| } |
| else |
| { |
| // Use one value for it if the picParam->b_picture_fraction is out of range. |
| // Since in some cases, although driver gets the invalid bFraction, HW still can handle this. |
| scaleFactor = FractionToScaleFactor[0]; |
| } |
| |
| uint32_t fwdRefDist = picParam->reference_fields.bits.reference_distance; |
| int32_t bwdRefDist = 0; |
| |
| if (picParam->inloop_decoded_picture != DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| codecPicParam->DeblockedPicIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT); |
| DDI_CHK_RET(RegisterRTSurfaces(&m_ddiDecodeCtx->RTtbl, DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->inloop_decoded_picture)), "RegisterRTSurfaces failed!"); |
| |
| codecPicParam->CurrPic.FrameIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), |
| DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->inloop_decoded_picture)); |
| m_deblockPicIdx = codecPicParam->DeblockedPicIdx; |
| m_currPicIdx = codecPicParam->CurrPic.FrameIdx; |
| } |
| else |
| { |
| codecPicParam->CurrPic.FrameIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT); |
| codecPicParam->DeblockedPicIdx = codecPicParam->CurrPic.FrameIdx; |
| m_deblockPicIdx = DDI_CODEC_INVALID_FRAME_INDEX; |
| m_currPicIdx = codecPicParam->CurrPic.FrameIdx; |
| } |
| |
| if (picParam->forward_reference_picture == DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| codecPicParam->ForwardRefIdx = codecPicParam->CurrPic.FrameIdx; |
| } |
| else |
| { |
| if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)) != VA_STATUS_SUCCESS) |
| { |
| DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)), "RegisterRTSurfaces failed!"); |
| } |
| codecPicParam->ForwardRefIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)); |
| } |
| |
| if (picParam->backward_reference_picture == DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| codecPicParam->BackwardRefIdx = codecPicParam->CurrPic.FrameIdx; |
| } |
| else |
| { |
| if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)) != VA_STATUS_SUCCESS) |
| { |
| DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)), "RegisterRTSurfaces failed!"); |
| } |
| codecPicParam->BackwardRefIdx = (uint16_t)GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)); |
| } |
| |
| //add protection checking to prevent ref pic index larger than DPB size |
| if (codecPicParam->ForwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1) |
| { |
| codecPicParam->ForwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1 - 1; |
| } |
| if (codecPicParam->BackwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1) |
| { |
| codecPicParam->BackwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1 - 1; |
| } |
| |
| if (picParam->picture_fields.bits.frame_coding_mode == 0) |
| { |
| codecPicParam->CurrPic.PicFlags = PICTURE_FRAME; |
| } |
| else if (picParam->picture_fields.bits.frame_coding_mode == 1) |
| { |
| codecPicParam->CurrPic.PicFlags = PICTURE_INTERLACED_FRAME; |
| } |
| else |
| { |
| codecPicParam->CurrPic.PicFlags = (picParam->picture_fields.bits.is_first_field ^ picParam->picture_fields.bits.top_field_first) ? PICTURE_BOTTOM_FIELD : PICTURE_TOP_FIELD; |
| } |
| |
| if (picParam->picture_fields.bits.frame_coding_mode < 2) //frame structure |
| { |
| codecPicParam->picture_fields.frame_coding_mode = picParam->picture_fields.bits.frame_coding_mode; |
| codecPicParam->luma_scale = (uint16_t)picParam->luma_scale; |
| codecPicParam->luma_shift = (uint16_t)picParam->luma_shift; |
| } |
| else |
| { |
| if (picParam->picture_fields.bits.top_field_first) |
| { |
| codecPicParam->picture_fields.frame_coding_mode = 2; |
| } |
| else |
| { |
| codecPicParam->picture_fields.frame_coding_mode = 3; |
| } |
| if (picParam->picture_fields.bits.picture_type >= vc1BBField) // B interlaced frames |
| { |
| fwdRefDist = (scaleFactor * picParam->reference_fields.bits.reference_distance) >> 8; |
| bwdRefDist = picParam->reference_fields.bits.reference_distance - fwdRefDist - 1; |
| if (bwdRefDist < 0) |
| { |
| bwdRefDist = 0; |
| } |
| } |
| codecPicParam->luma_scale = (uint16_t)(picParam->luma_scale2 + (picParam->luma_scale << 8)); |
| codecPicParam->luma_shift = (uint16_t)(picParam->luma_shift2 + (picParam->luma_shift << 8)); |
| } |
| |
| codecPicParam->sequence_fields.AdvancedProfileFlag = (picParam->sequence_fields.bits.profile == 3) ? 1 : 0; |
| codecPicParam->picture_fields.picture_type = picParam->picture_fields.bits.picture_type; |
| |
| if (codecPicParam->sequence_fields.AdvancedProfileFlag) |
| { |
| codecPicParam->sequence_fields.overlap = picParam->sequence_fields.bits.overlap; |
| } |
| else |
| { |
| // see 7.1.1.14 in VC spec |
| if ((picParam->b_picture_fraction == 0x7F) && (picParam->picture_fields.bits.picture_type == vc1IFrame)) |
| { |
| codecPicParam->picture_fields.picture_type = vc1BIFrame; |
| } |
| |
| codecPicParam->sequence_fields.overlap = picParam->sequence_fields.bits.overlap && (picParam->pic_quantizer_fields.bits.pic_quantizer_scale >= 9); |
| } |
| |
| codecPicParam->coded_width = picParam->coded_width; |
| codecPicParam->coded_height = picParam->coded_height; |
| codecPicParam->sequence_fields.syncmarker = picParam->sequence_fields.bits.syncmarker; |
| codecPicParam->sequence_fields.pulldown = picParam->sequence_fields.bits.pulldown; |
| codecPicParam->sequence_fields.interlace = picParam->sequence_fields.bits.interlace; |
| codecPicParam->sequence_fields.tfcntrflag = picParam->sequence_fields.bits.tfcntrflag; |
| codecPicParam->sequence_fields.psf = picParam->sequence_fields.bits.psf; |
| codecPicParam->sequence_fields.multires = picParam->sequence_fields.bits.multires; |
| codecPicParam->sequence_fields.rangered = picParam->sequence_fields.bits.rangered; |
| codecPicParam->sequence_fields.max_b_frames = picParam->sequence_fields.bits.max_b_frames; |
| codecPicParam->entrypoint_fields.loopfilter = picParam->entrypoint_fields.bits.loopfilter; |
| codecPicParam->entrypoint_fields.broken_link = picParam->entrypoint_fields.bits.broken_link; |
| codecPicParam->entrypoint_fields.closed_entry = picParam->entrypoint_fields.bits.closed_entry; |
| codecPicParam->entrypoint_fields.panscan_flag = picParam->entrypoint_fields.bits.panscan_flag; |
| codecPicParam->picture_fields.is_first_field = picParam->picture_fields.bits.is_first_field; |
| codecPicParam->picture_fields.top_field_first = picParam->picture_fields.bits.top_field_first; |
| codecPicParam->picture_fields.intensity_compensation = picParam->picture_fields.bits.intensity_compensation; |
| |
| if (picParam->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation) |
| { |
| codecPicParam->mv_fields.UnifiedMvMode = (picParam->mv_fields.bits.mv_mode2 + 1) & 0x3; |
| ; |
| } |
| else |
| { |
| codecPicParam->mv_fields.UnifiedMvMode = (picParam->mv_fields.bits.mv_mode + 1) & 0x3; |
| } |
| |
| if (picParam->mv_fields.bits.mv_mode == VAMvMode1MvHalfPelBilinear || |
| (picParam->mv_fields.bits.mv_mode == VAMvModeIntensityCompensation && picParam->mv_fields.bits.mv_mode2 == VAMvMode1MvHalfPelBilinear)) |
| { |
| codecPicParam->mv_fields.MvMode = picParam->fast_uvmc_flag ? 9 : 8; |
| } |
| else |
| { |
| codecPicParam->mv_fields.MvMode = picParam->fast_uvmc_flag ? 1 : 0; |
| } |
| |
| uint32_t altPquantConfig = 0; |
| uint32_t altPquantEdgeMask = 0; |
| CalculateQuantParams(picParam, &altPquantConfig, &altPquantEdgeMask); |
| |
| codecPicParam->pic_quantizer_fields.quantizer = picParam->pic_quantizer_fields.bits.quantizer; |
| codecPicParam->pic_quantizer_fields.pic_quantizer_scale = picParam->pic_quantizer_fields.bits.pic_quantizer_scale; |
| codecPicParam->pic_quantizer_fields.alt_pic_quantizer = picParam->pic_quantizer_fields.bits.alt_pic_quantizer; |
| codecPicParam->pic_quantizer_fields.pic_quantizer_type = picParam->pic_quantizer_fields.bits.pic_quantizer_type; |
| codecPicParam->pic_quantizer_fields.half_qp = picParam->pic_quantizer_fields.bits.half_qp; |
| codecPicParam->pic_quantizer_fields.AltPQuantConfig = altPquantConfig; |
| codecPicParam->pic_quantizer_fields.AltPQuantEdgeMask = altPquantEdgeMask; |
| codecPicParam->pic_quantizer_fields.dquant = picParam->pic_quantizer_fields.bits.dquant; |
| codecPicParam->mv_fields.extended_mv_flag = picParam->mv_fields.bits.extended_mv_flag; |
| codecPicParam->mv_fields.extended_dmv_flag = picParam->mv_fields.bits.extended_dmv_flag; |
| codecPicParam->mv_fields.extended_mv_range = picParam->mv_fields.bits.extended_mv_range; |
| codecPicParam->mv_fields.extended_dmv_range = picParam->mv_fields.bits.extended_dmv_range; |
| codecPicParam->mv_fields.four_mv_switch = picParam->mv_fields.bits.four_mv_switch; |
| codecPicParam->mv_fields.two_mv_block_pattern_table = picParam->mv_fields.bits.two_mv_block_pattern_table; |
| codecPicParam->mv_fields.four_mv_block_pattern_table = picParam->mv_fields.bits.four_mv_block_pattern_table; |
| codecPicParam->mv_fields.mv_table = picParam->mv_fields.bits.mv_table; |
| codecPicParam->reference_fields.reference_distance_flag = picParam->reference_fields.bits.reference_distance_flag; |
| codecPicParam->reference_fields.reference_distance = fwdRefDist; //picParam->reference_fields.bits.reference_distance; |
| codecPicParam->reference_fields.BwdReferenceDistance = bwdRefDist; //picParam->reference_fields.bits.reference_distance; |
| codecPicParam->reference_fields.num_reference_pictures = picParam->reference_fields.bits.num_reference_pictures; |
| codecPicParam->reference_fields.reference_field_pic_indicator = picParam->reference_fields.bits.reference_field_pic_indicator; |
| |
| codecPicParam->raw_coding.value = 0xFE; |
| if (picParam->picture_fields.bits.frame_coding_mode < 2) //frame structure |
| { |
| if ((picParam->picture_fields.bits.picture_type == vc1IFrame) || |
| (picParam->picture_fields.bits.picture_type == vc1BIFrame)) |
| { |
| if (picParam->picture_fields.bits.frame_coding_mode == 1) //interlaced frame |
| { |
| codecPicParam->raw_coding.field_tx = !picParam->bitplane_present.flags.bp_field_tx; |
| } |
| codecPicParam->raw_coding.ac_pred = !picParam->bitplane_present.flags.bp_ac_pred; |
| codecPicParam->raw_coding.overflags = !picParam->bitplane_present.flags.bp_overflags; |
| } |
| else if (picParam->picture_fields.bits.picture_type == vc1PFrame) |
| { |
| codecPicParam->raw_coding.skip_mb = !picParam->bitplane_present.flags.bp_skip_mb; |
| if (picParam->picture_fields.bits.frame_coding_mode == 0) //progressive frame |
| { |
| codecPicParam->raw_coding.mv_type_mb = !picParam->bitplane_present.flags.bp_mv_type_mb; |
| } |
| } |
| else |
| { |
| codecPicParam->raw_coding.direct_mb = !picParam->bitplane_present.flags.bp_direct_mb; |
| codecPicParam->raw_coding.skip_mb = !picParam->bitplane_present.flags.bp_skip_mb; |
| } |
| } |
| else |
| { |
| if ((IsIField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type)) || |
| (IsBIField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type))) |
| { |
| codecPicParam->raw_coding.ac_pred = !picParam->bitplane_present.flags.bp_ac_pred; |
| codecPicParam->raw_coding.overflags = !picParam->bitplane_present.flags.bp_overflags; |
| } |
| else if (IsBField(picParam->picture_fields.bits.is_first_field, picParam->picture_fields.bits.picture_type)) |
| { |
| codecPicParam->raw_coding.forward_mb = !picParam->bitplane_present.flags.bp_forward_mb; |
| } |
| } |
| uint32_t rawCoding = codecPicParam->raw_coding.value & 0xFE; |
| codecPicParam->raw_coding.bitplane_present = (rawCoding == 0xFE) ? 0 : 1; |
| |
| codecPicParam->transform_fields.intra_transform_dc_table = picParam->transform_fields.bits.intra_transform_dc_table; |
| codecPicParam->transform_fields.transform_ac_codingset_idx1 = picParam->transform_fields.bits.transform_ac_codingset_idx1; |
| codecPicParam->transform_fields.transform_ac_codingset_idx2 = picParam->transform_fields.bits.transform_ac_codingset_idx2; |
| codecPicParam->transform_fields.variable_sized_transform_flag = picParam->transform_fields.bits.variable_sized_transform_flag; |
| codecPicParam->transform_fields.mb_level_transform_type_flag = picParam->transform_fields.bits.mb_level_transform_type_flag; |
| codecPicParam->transform_fields.frame_level_transform_type = picParam->transform_fields.bits.frame_level_transform_type; |
| |
| codecPicParam->conditional_overlap_flag = picParam->conditional_overlap_flag ? (picParam->conditional_overlap_flag + 1) : 0; |
| codecPicParam->fast_uvmc_flag = picParam->fast_uvmc_flag; |
| codecPicParam->cbp_table = picParam->cbp_table; |
| codecPicParam->mb_mode_table = picParam->mb_mode_table; |
| codecPicParam->b_picture_fraction = picParam->b_picture_fraction; //not used |
| codecPicParam->range_reduction_frame = picParam->range_reduction_frame; |
| codecPicParam->ScaleFactor = scaleFactor; |
| codecPicParam->post_processing = picParam->post_processing; |
| codecPicParam->picture_resolution_index = 0; |
| codecPicParam->rounding_control = picParam->rounding_control; |
| |
| codecPicParam->UpsamplingFlag = picParam->sequence_fields.bits.multires ? (picParam->picture_resolution_index & 0x3) : 0; |
| |
| //rangemap |
| if (codecPicParam->sequence_fields.AdvancedProfileFlag) |
| { |
| codecPicParam->range_mapping_fields.luma_flag = picParam->range_mapping_fields.bits.luma_flag; |
| codecPicParam->range_mapping_fields.luma = picParam->range_mapping_fields.bits.luma; |
| codecPicParam->range_mapping_fields.chroma_flag = picParam->range_mapping_fields.bits.chroma_flag; |
| codecPicParam->range_mapping_fields.chroma = picParam->range_mapping_fields.bits.chroma; |
| codecPicParam->range_mapping_fields.range_mapping_enabled = picParam->range_mapping_fields.value; |
| } |
| else |
| { |
| codecPicParam->range_mapping_fields.range_mapping_enabled = picParam->range_reduction_frame; |
| } |
| |
| // Check if OLP is needed |
| // OLP output surface must be present |
| if ((m_deblockPicIdx != DDI_CODEC_INVALID_FRAME_INDEX) && |
| ((codecPicParam->DeblockedPicIdx != codecPicParam->CurrPic.FrameIdx) || |
| codecPicParam->UpsamplingFlag || |
| codecPicParam->range_mapping_fields.range_mapping_enabled)) |
| { |
| m_olpNeeded = 1; |
| } |
| else |
| { |
| m_olpNeeded = 0; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeVC1::ParseSliceParams( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| VASliceParameterBufferVC1 *slcParam, |
| uint32_t numSlices) |
| { |
| PCODEC_VC1_SLICE_PARAMS codecSlcParam = (PCODEC_VC1_SLICE_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_sliceParams); |
| |
| codecSlcParam += m_ddiDecodeCtx->DecodeParams.m_numSlices; |
| |
| if ((slcParam == nullptr) || (codecSlcParam == nullptr)) |
| { |
| DDI_ASSERTMESSAGE("Null pointer for Parsing VC1 Slice parameter\n"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| uint32_t sliceBaseOffset = GetBsBufOffset(m_groupIndex); |
| for (uint32_t slcCount = 0; slcCount < numSlices; slcCount++) |
| { |
| codecSlcParam[slcCount].slice_data_size = slcParam[slcCount].slice_data_size << 3; |
| codecSlcParam[slcCount].slice_data_offset = slcParam[slcCount].slice_data_offset + |
| sliceBaseOffset; |
| if (slcParam[slcCount].slice_data_flag) |
| { |
| DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call"); |
| } |
| codecSlcParam[slcCount].macroblock_offset = slcParam[slcCount].macroblock_offset; |
| codecSlcParam[slcCount].slice_vertical_position = slcParam[slcCount].slice_vertical_position; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeVC1::AllocBitPlaneBuffer() |
| { |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| |
| DDI_CHK_NULL(bufMgr, "Null bufMgr in AllocBpBuffer", VA_STATUS_ERROR_INVALID_PARAMETER); |
| |
| if (bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex].bUsed) |
| { |
| // wait until decode complete |
| mos_bo_wait_rendering(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex]->bo); |
| } |
| |
| bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[bufMgr->Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex].bUsed = true; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeVC1::AllocSliceParamContext( |
| uint32_t numSlices) |
| { |
| uint32_t baseSize = sizeof(CODEC_VC1_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; |
| } |
| |
| void DdiDecodeVC1::DestroyContext( |
| VADriverContextP ctx) |
| { |
| FreeResourceBuffer(); |
| // explicitly call the base function to do the further clean-up |
| DdiMediaDecode::DestroyContext(ctx); |
| } |
| |
| uint8_t* DdiDecodeVC1::GetPicParamBuf( |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr) |
| { |
| return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_VC1.PicParamVC1)); |
| } |
| |
| VAStatus DdiDecodeVC1::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(availSize < buf->uiNumElements) |
| { |
| newSize = sizeof(VASliceParameterBufferVC1) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements); |
| bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = (VASliceParameterBufferVC1 *)realloc(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1, newSize); |
| if(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 == nullptr) |
| { |
| return VA_STATUS_ERROR_ALLOCATION_FAILED; |
| } |
| MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferVC1) * (buf->uiNumElements - availSize)); |
| m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements; |
| } |
| buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1; |
| buf->uiOffset = sizeof(VASliceParameterBufferVC1) * bufMgr->dwNumSliceControl; |
| |
| bufMgr->dwNumSliceControl += buf->uiNumElements; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| void DdiDecodeVC1::ContextInit( |
| int32_t picWidth, |
| int32_t picHeight) |
| { |
| // call the function in base class to initialize it. |
| DdiMediaDecode::ContextInit(picWidth, picHeight); |
| |
| m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_VC1VLD; |
| m_olpNeeded = false; |
| m_currPicIdx = DDI_CODEC_INVALID_FRAME_INDEX; |
| m_deblockPicIdx = DDI_CODEC_INVALID_FRAME_INDEX; |
| |
| if (m_ddiDecodeAttr->profile == VAProfileVC1Advanced) |
| { |
| int32_t alignedHeight = MOS_ALIGN_CEIL(picHeight, 32); |
| m_height = alignedHeight; |
| m_picHeightInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_HEIGHT(alignedHeight)); |
| } |
| } |
| |
| VAStatus DdiDecodeVC1::BeginPicture( |
| VADriverContextP ctx, |
| VAContextID context, |
| VASurfaceID renderTarget) |
| { |
| VAStatus vaStatus = DdiMediaDecode::BeginPicture(ctx, context, renderTarget); |
| |
| if (vaStatus != VA_STATUS_SUCCESS) |
| { |
| return vaStatus; |
| } |
| |
| m_ddiDecodeCtx->DecodeParams.m_vc1BitplaneSize = 0; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| void DdiDecodeVC1::ParseBitPlane( |
| struct _DDI_MEDIA_BUFFER *bitPlaneBuffObject, |
| uint8_t *buf) |
| { |
| if (bitPlaneBuffObject->pData) |
| { |
| PCODEC_VC1_PIC_PARAMS picParam = (PCODEC_VC1_PIC_PARAMS)(m_ddiDecodeCtx->DecodeParams.m_picParams); |
| |
| uint8_t *destBp = (uint8_t *)bitPlaneBuffObject->pData; |
| uint8_t *srcBp = (uint8_t *)buf; |
| |
| uint32_t heightInMbs = MOS_ALIGN_CEIL(picParam->coded_height, CODECHAL_MACROBLOCK_HEIGHT) / CODECHAL_MACROBLOCK_HEIGHT; |
| uint32_t widthInMbs = MOS_ALIGN_CEIL(picParam->coded_width, CODECHAL_MACROBLOCK_WIDTH) / CODECHAL_MACROBLOCK_WIDTH; |
| uint32_t bitPlanePitch = MOS_ALIGN_CEIL(widthInMbs, 2) / 2; |
| |
| uint32_t srcIdx, dstIdx; |
| uint32_t srcShift; |
| uint32_t i, j; |
| uint8_t srcValue = 0; |
| for (i = 0; i < heightInMbs; i++) |
| { |
| for (j = 0; j < widthInMbs; j++) |
| { |
| srcIdx = (i * widthInMbs + j) / 2; |
| dstIdx = j / 2; |
| srcShift = ((i * widthInMbs + j) & 1) ? 0 : 4; |
| srcValue = (srcBp[srcIdx] >> srcShift) & 0xf; |
| if (j % 2) |
| destBp[dstIdx] = destBp[dstIdx] + (srcValue << 4); |
| else |
| destBp[dstIdx] = srcValue; |
| } |
| destBp += bitPlanePitch; |
| } |
| } |
| } |
| |
| VAStatus DdiDecodeVC1::RenderPicture( |
| VADriverContextP ctx, |
| VAContextID context, |
| VABufferID *buffers, |
| int32_t numBuffers) |
| { |
| DDI_FUNCTION_ENTER(); |
| |
| VAStatus va = VA_STATUS_SUCCESS; |
| PDDI_MEDIA_CONTEXT mediaCtx; |
| |
| mediaCtx = DdiMedia_GetMediaContext(ctx); |
| |
| void *data = nullptr; |
| for (int32_t i = 0; i < numBuffers; i++) |
| { |
| if (!buffers || (buffers[i] == VA_INVALID_ID)) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| |
| 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 VABitPlaneBufferType: |
| { |
| int32_t index = m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex; |
| if (index == DDI_CODEC_INVALID_BUFFER_INDEX) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| if (index >= DDI_CODEC_MAX_BITSTREAM_BUFFER) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| DDI_CHK_RET(AllocBitPlaneBuffer(),"AllocBitPlaneBuffer failed!"); |
| /* Before accessing it on CPU, Use the DdiMediaUtil_LockBuffer to map it into CPU */ |
| DdiMediaUtil_LockBuffer(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], MOS_LOCKFLAG_WRITEONLY); |
| ParseBitPlane(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], (uint8_t *)data); |
| |
| DdiMediaUtil_UnlockBuffer(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index]); |
| |
| DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[index], &m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.resBitPlaneBuffer); |
| m_ddiDecodeCtx->DecodeParams.m_vc1BitplaneSize = dataSize; |
| |
| m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex++; |
| if (m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex >= DDI_CODEC_MAX_BITSTREAM_BUFFER) |
| { |
| m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.dwVC1BitPlaneIndex = 0; |
| } |
| break; |
| } |
| |
| 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: |
| { |
| if (buf->uiNumElements == 0) |
| { |
| return VA_STATUS_ERROR_INVALID_BUFFER; |
| } |
| |
| VASliceParameterBufferVC1 *slcInfo = |
| (VASliceParameterBufferVC1 *)data; |
| uint32_t numSlices = buf->uiNumElements; |
| DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!"); |
| DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfo, numSlices),"ParseSliceParams failed!"); |
| m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices; |
| m_groupIndex++; |
| break; |
| } |
| case VAPictureParameterBufferType: |
| { |
| VAPictureParameterBufferVC1 *picParam = (VAPictureParameterBufferVC1 *)data; |
| DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!"); |
| break; |
| } |
| case VADecodeStreamoutBufferType: |
| { |
| DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer); |
| m_streamOutEnabled = true; |
| break; |
| } |
| default: |
| va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE; |
| break; |
| } |
| DdiMedia_UnmapBuffer(ctx, buffers[i]); |
| } |
| |
| DDI_FUNCTION_EXIT(va); |
| return va; |
| } |
| |
| VAStatus DdiDecodeVC1::SetDecodeParams() |
| { |
| if ((&m_ddiDecodeCtx->DecodeParams)->m_numSlices == 0) |
| { |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| m_destSurface.dwOffset = 0; |
| MOS_FORMAT expectedFormat = Format_NV12; |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| m_destSurface.Format = expectedFormat; |
| |
| if (m_deblockPicIdx != DDI_CODEC_INVALID_FRAME_INDEX) |
| { |
| DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pRT[m_currPicIdx], &(m_destSurface.OsResource)); |
| } |
| else |
| { |
| DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pCurrentRT, &(m_destSurface.OsResource)); |
| } |
| |
| if (m_destSurface.OsResource.Format != expectedFormat) |
| { |
| DDI_NORMALMESSAGE("Surface fomrat of decoded surface is inconsistent with Mpeg2 bitstream\n"); |
| return VA_STATUS_ERROR_INVALID_PARAMETER; |
| } |
| |
| (&m_ddiDecodeCtx->DecodeParams)->m_destSurface = &m_destSurface; |
| |
| memset(&m_deblockSurface, 0, sizeof(MOS_SURFACE)); |
| if (m_olpNeeded) |
| { |
| memset(&m_deblockSurface, 0, sizeof(MOS_SURFACE)); |
| m_deblockSurface.Format = Format_NV12; |
| m_deblockSurface.dwOffset = 0; |
| DdiMedia_MediaSurfaceToMosResource((&(m_ddiDecodeCtx->RTtbl))->pRT[m_deblockPicIdx], &(m_deblockSurface.OsResource)); |
| (&m_ddiDecodeCtx->DecodeParams)->m_deblockSurface = &m_deblockSurface; |
| } |
| else |
| { |
| (&m_ddiDecodeCtx->DecodeParams)->m_deblockSurface = nullptr; |
| } |
| |
| (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer = &bufMgr->resBitstreamBuffer; |
| (&m_ddiDecodeCtx->DecodeParams)->m_bitStreamBufData = bufMgr->pBitstreamBuffer; |
| Mos_Solo_OverrideBufferSize((&m_ddiDecodeCtx->DecodeParams)->m_dataSize, (&m_ddiDecodeCtx->DecodeParams)->m_dataBuffer); |
| |
| (&m_ddiDecodeCtx->DecodeParams)->m_bitplaneBuffer = &(m_ddiDecodeCtx->BufMgr.Codec_Param.Codec_Param_VC1.resBitPlaneBuffer); |
| |
| if (m_streamOutEnabled) |
| { |
| (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled = true; |
| (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = &bufMgr->resExternalStreamOutBuffer; |
| } |
| else |
| { |
| (&m_ddiDecodeCtx->DecodeParams)->m_streamOutEnabled = false; |
| (&m_ddiDecodeCtx->DecodeParams)->m_externalStreamOutBuffer = nullptr; |
| } |
| |
| m_olpNeeded = false; |
| m_currPicIdx = DDI_CODEC_INVALID_FRAME_INDEX; |
| m_deblockPicIdx = DDI_CODEC_INVALID_FRAME_INDEX; |
| |
| return VA_STATUS_SUCCESS; |
| } |
| |
| VAStatus DdiDecodeVC1::InitResourceBuffer(DDI_MEDIA_CONTEXT *mediaCtx) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| |
| bufMgr->pSliceData = nullptr; |
| |
| bufMgr->ui64BitstreamOrder = 0; |
| bufMgr->dwMaxBsSize = m_width * |
| m_height * 3 / 2; |
| // 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; |
| // 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; |
| } |
| |
| 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; |
| } |
| |
| for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++) |
| { |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER)); |
| if (bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->iSize = MOS_ALIGN_CEIL(m_width, CODECHAL_MACROBLOCK_WIDTH) * MOS_ALIGN_CEIL(m_height, CODECHAL_MACROBLOCK_HEIGHT) * 2 / (CODECHAL_MACROBLOCK_HEIGHT * CODECHAL_MACROBLOCK_WIDTH); |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->uiType = VABitPlaneBufferType; |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->format = Media_Format_Buffer; |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->uiOffset = 0; |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]->pMediaCtx = mediaCtx; |
| |
| vaStatus = DdiMediaUtil_CreateBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i], mediaCtx->pDrmBufMgr); |
| if (vaStatus != VA_STATUS_SUCCESS) |
| { |
| goto finish; |
| } |
| |
| bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[i].pBitPlaneBase = nullptr; |
| bufMgr->Codec_Param.Codec_Param_VC1.VC1BitPlane[i].bUsed = false; |
| } |
| |
| bufMgr->dwNumSliceData = 0; |
| bufMgr->dwNumSliceControl = 0; |
| |
| m_sliceCtrlBufNum = m_picHeightInMB; |
| bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = (VASliceParameterBufferVC1 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferVC1) * m_sliceCtrlBufNum); |
| if (bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer = (uint8_t *)MOS_AllocAndZeroMemory(m_picWidthInMB * m_picHeightInMB); |
| if (bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto finish; |
| } |
| |
| return VA_STATUS_SUCCESS; |
| |
| finish: |
| FreeResourceBuffer(); |
| return vaStatus; |
| } |
| |
| void DdiDecodeVC1::FreeResourceBuffer() |
| { |
| DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr); |
| |
| int32_t i; |
| 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_VC1.pVASliceParaBufVC1) |
| { |
| MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1); |
| bufMgr->Codec_Param.Codec_Param_VC1.pVASliceParaBufVC1 = nullptr; |
| } |
| if (bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer) |
| { |
| MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer); |
| bufMgr->Codec_Param.Codec_Param_VC1.pBitPlaneBuffer = nullptr; |
| } |
| for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++) |
| { |
| if (bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]) |
| { |
| DdiMediaUtil_UnlockBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]); |
| DdiMediaUtil_FreeBuffer(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]); |
| MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i]); |
| bufMgr->Codec_Param.Codec_Param_VC1.pVC1BitPlaneBuffObject[i] = nullptr; |
| } |
| } |
| |
| // free decode bitstream buffer object |
| MOS_FreeMemory(bufMgr->pSliceData); |
| bufMgr->pSliceData = nullptr; |
| |
| return; |
| } |
| |
| VAStatus DdiDecodeVC1::CodecHalInit( |
| DDI_MEDIA_CONTEXT *mediaCtx, |
| void *ptr) |
| { |
| VAStatus vaStatus = VA_STATUS_SUCCESS; |
| MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr; |
| |
| CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE; |
| m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings); |
| |
| 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; |
| |
| m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS; |
| |
| m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse; |
| |
| m_codechalSettings->mode = CODECHAL_DECODE_MODE_VC1VLD; |
| m_codechalSettings->standard = CODECHAL_VC1; |
| /* VC1 uses the Intel-specific Format */ |
| m_codechalSettings->intelEntrypointInUse = true; |
| |
| m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CODEC_VC1_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 = MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CODEC_VC1_SLICE_PARAMS)); |
| if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr) |
| { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| goto CleanUpandReturn; |
| } |
| |
| vaStatus = CreateCodecHal(mediaCtx, |
| ptr, |
| &standardInfo); |
| |
| if (vaStatus != VA_STATUS_SUCCESS) |
| { |
| goto CleanUpandReturn; |
| } |
| |
| if (InitResourceBuffer(mediaCtx) != 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_picParams); |
| m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr; |
| MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams); |
| m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr; |
| |
| return vaStatus; |
| } |
| |
| extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>; |
| |
| static bool vc1Registered = |
| MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeVC1>(DECODE_ID_VC1); |