diff --git a/api/rocdecode.h b/api/rocdecode.h index 70ead343aa..e9f1695737 100644 --- a/api/rocdecode.h +++ b/api/rocdecode.h @@ -261,26 +261,27 @@ typedef struct _RocdecReconfigureDecoderInfo { } RocdecReconfigureDecoderInfo; /*********************************************************/ -//! \struct RocdecH264Picture +//! \struct RocdecAvcPicture //! \ingroup group_amd_rocdecode -//! H.264 Picture Entry -//! This structure is used in RocdecH264PicParams structure +//! AVC/H.264 Picture Entry +//! This structure is used in RocdecAvcPicParams structure /*********************************************************/ -typedef struct _RocdecH264Picture { - int PicIdx; /**< picture index of reference frame */ - int FrameIdx; /**< frame_num(int16_t-term) or LongTermFrameIdx(long-term) */ - uint32_t RefFlags; /**< See below for definitions */ - int TopFieldOrderCnt; /**< field order count of top field */ - int BottomFieldOrderCnt; /**< field order count of bottom field */ -} RocdecH264Picture; +typedef struct _RocdecAvcPicture { + int PicIdx; /**< picture index of reference frame */ + uint32_t FrameIdx; /**< frame_num(int16_t-term) or LongTermFrameIdx(long-term) */ + uint32_t Flags; /**< See below for definitions */ + int32_t TopFieldOrderCnt; /**< field order count of top field */ + int32_t BottomFieldOrderCnt; /**< field order count of bottom field */ + uint32_t reserved[4]; +} RocdecAvcPicture; -/* flags in RocdecH264Picture could be OR of the following */ -#define RocdecH264Picture_FLAGS_INVALID 0x00000001 -#define RocdecH264Picture_FLAGS_TOP_FIELD 0x00000002 -#define RocdecH264Picture_FLAGS_BOTTOM_FIELD 0x00000004 -#define RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE 0x00000008 -#define RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE 0x00000010 -#define RocdecH264Picture_FLAGS_NON_EXISTING 0x00000020 +/* flags in RocdecAvcPicture could be OR of the following */ +#define RocdecH264Picture_FLAGS_INVALID 0x00000001 +#define RocdecH264Picture_FLAGS_TOP_FIELD 0x00000002 +#define RocdecH264Picture_FLAGS_BOTTOM_FIELD 0x00000004 +#define RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE 0x00000008 +#define RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE 0x00000010 +#define RocdecH264Picture_FLAGS_NON_EXISTING 0x00000020 /*********************************************************/ //! \struct RocdecHEVCPicture @@ -403,15 +404,25 @@ typedef struct _RocdecMpeg2PicParams { } RocdecMpeg2PicParams; /***********************************************************/ -//! \struct RocdecH264PicParams placeholder +//! \struct RocdecVc1PicParams placeholder //! \ingroup group_amd_rocdecode -//! H.264 picture parameters -//! This structure is used in RocdecH264PicParams structure -//! This structure is configured similar to VA-API VAPictureParameterBufferH264 structure +//! JPEG picture parameters +//! This structure is used in RocdecVc1PicParams structure /***********************************************************/ -typedef struct _RocdecH264PicParams { - RocdecH264Picture cur_pic; - RocdecH264Picture dpb[16]; /* in DPB */ +typedef struct _RocdecVc1PicParams { + int Reserved; +} RocdecVc1PicParams; + +/***********************************************************/ +//! \struct RocdecAvcPicParams placeholder +//! \ingroup group_amd_rocdecode +//! AVC picture parameters +//! This structure is used in RocdecAvcPicParams structure +//! This structure is configured to be the same as VA-API VAPictureParameterBufferH264 structure +/***********************************************************/ +typedef struct _RocdecAvcPicParams { + RocdecAvcPicture curr_pic; + RocdecAvcPicture ref_frames[16]; /* in DPB */ uint16_t picture_width_in_mbs_minus1; uint16_t picture_height_in_mbs_minus1; uint8_t bit_depth_luma_minus8; @@ -432,7 +443,16 @@ typedef struct _RocdecH264PicParams { uint32_t delta_pic_order_always_zero_flag : 1; } bits; uint32_t value; - } sps_fields; + } seq_fields; + + // FMO/ASO + uint8_t num_slice_groups_minus1; + uint8_t slice_group_map_type; + uint16_t slice_group_change_rate_minus1; + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + int8_t second_chroma_qp_index_offset; union { struct { uint32_t entropy_coding_mode_flag : 1; @@ -447,86 +467,79 @@ typedef struct _RocdecH264PicParams { uint32_t reference_pic_flag : 1; /* nal_ref_idc != 0 */ } bits; uint32_t value; - } pps_fields; - - // FMO/ASO - uint8_t num_slice_groups_minus1; - uint8_t slice_group_map_type; - uint16_t slice_group_change_rate_minus1; - int8_t pic_init_qp_minus26; - int8_t pic_init_qs_minus26; - int8_t chroma_qp_index_offset; - int8_t second_chroma_qp_index_offset; - + } pic_fields; uint16_t frame_num; - uint8_t num_ref_idx_l0_default_active_minus1; - uint8_t num_ref_idx_l1_default_active_minus1; - - // Quantization Matrices (raster-order) - uint8_t scaling_list_4x4[6][16]; - uint8_t scaling_list_8x8[2][64]; - // SVC/MVC : Not supported in this version - // union - // { - // ROCDECH264MVCEXT mvcext; - // ROCDECH264SVCEXT svcext; - // }; - uint32_t Reserved[12]; -} RocdecH264PicParams; + uint32_t Reserved[8]; +} RocdecAvcPicParams; /***********************************************************/ -//! \struct RocdecHevcIQMatrix +//! \struct RocdecAvcSliceParams placeholder //! \ingroup group_amd_rocdecode -//! HEVC IQMatrix -//! This structure is sent once per frame, -//! and only when scaling_list_enabled_flag = 1. -//! When sps_scaling_list_data_present_flag = 0, app still -//! needs to send in this structure with default matrix values. -//! This structure is used in RocdecHevcQMatrix structure +//! AVC slice parameter buffer +//! This structure is configured to be the same as VA-API VASliceParameterBufferH264 structure /***********************************************************/ -typedef struct _RocdecHevcIQMatrix { +typedef struct _RocdecAvcSliceParams { + uint32_t slice_data_size; // slice size in bytes + uint32_t slice_data_offset; // byte offset of the current slice in the slice data buffer + uint32_t slice_data_flag; /* see VA_SLICE_DATA_FLAG_XXX defintions */ /** - * \brief 4x4 scaling, - * correspongs i = 0, MatrixID is in the range of 0 to 5, - * inclusive. And j is in the range of 0 to 15, inclusive. + * \brief Bit offset from NAL Header Unit to the begining of slice_data(). + * + * This bit offset is relative to and includes the NAL unit byte + * and represents the number of bits parsed in the slice_header() + * after the removal of any emulation prevention bytes in + * there. However, the slice data buffer passed to the hardware is + * the original bitstream, thus including any emulation prevention + * bytes. */ - uint8_t ScalingList4x4[6][16]; - /** - * \brief 8x8 scaling, - * correspongs i = 1, MatrixID is in the range of 0 to 5, - * inclusive. And j is in the range of 0 to 63, inclusive. - */ - uint8_t ScalingList8x8[6][64]; - /** - * \brief 16x16 scaling, - * correspongs i = 2, MatrixID is in the range of 0 to 5, - * inclusive. And j is in the range of 0 to 63, inclusive. - */ - uint8_t ScalingList16x16[6][64]; - /** - * \brief 32x32 scaling, - * correspongs i = 3, MatrixID is in the range of 0 to 1, - * inclusive. And j is in the range of 0 to 63, inclusive. - */ - uint8_t ScalingList32x32[2][64]; - /** - * \brief DC values of the 16x16 scaling lists, - * corresponds to HEVC spec syntax - * scaling_list_dc_coef_minus8[ sizeID - 2 ][ matrixID ] + 8 - * with sizeID = 2 and matrixID in the range of 0 to 5, inclusive. - */ - uint8_t ScalingListDC16x16[6]; - /** - * \brief DC values of the 32x32 scaling lists, - * corresponds to HEVC spec syntax - * scaling_list_dc_coef_minus8[ sizeID - 2 ][ matrixID ] + 8 - * with sizeID = 3 and matrixID in the range of 0 to 1, inclusive. - */ - uint8_t ScalingListDC32x32[2]; + uint16_t slice_data_bit_offset; - uint32_t reserved[4]; -} RocdecHevcIQMatrix; + uint16_t first_mb_in_slice; + uint8_t slice_type; + uint8_t direct_spatial_mv_pred_flag; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t cabac_init_idc; + int8_t slice_qp_delta; + uint8_t disable_deblocking_filter_idc; + int8_t slice_alpha_c0_offset_div2; + int8_t slice_beta_offset_div2; + RocdecAvcPicture ref_pic_list_0[32]; // 8.2.4.2 + RocdecAvcPicture ref_pic_list_1[32]; // 8.2.4.2 + uint8_t luma_log2_weight_denom; + uint8_t chroma_log2_weight_denom; + uint8_t luma_weight_l0_flag; + int16_t luma_weight_l0[32]; + int16_t luma_offset_l0[32]; + uint8_t chroma_weight_l0_flag; + int16_t chroma_weight_l0[32][2]; + int16_t chroma_offset_l0[32][2]; + uint8_t luma_weight_l1_flag; + int16_t luma_weight_l1[32]; + int16_t luma_offset_l1[32]; + uint8_t chroma_weight_l1_flag; + int16_t chroma_weight_l1[32][2]; + int16_t chroma_offset_l1[32][2]; + + uint32_t va_reserved[4]; +} RocdecAvcSliceParams; + +/***********************************************************/ +//! \struct RocdecAvcIQMatrix placeholder +//! \ingroup group_amd_rocdecode +//! AVC Inverse Quantization Matrix +//! This structure is configured to be the same as VA-API VAIQMatrixBufferH264 structure +/***********************************************************/ +typedef struct _RocdecAvcIQMatrix { + /** \brief 4x4 scaling list, in raster scan order. */ + uint8_t scaling_list_4x4[6][16]; + /** \brief 8x8 scaling list, in raster scan order. */ + uint8_t scaling_list_8x8[2][64]; + + /** \brief Reserved bytes for future use, must be zero */ + uint32_t va_reserved[4]; +} RocdecAvcIQMatrix; /***********************************************************/ //! \struct RocdecHevcPicParams @@ -535,7 +548,7 @@ typedef struct _RocdecHevcIQMatrix { //! This structure is used in RocdecHevcPicParams structure /***********************************************************/ typedef struct _RocdecHevcPicParams { - RocdecHEVCPicture cur_pic; + RocdecHEVCPicture curr_pic; RocdecHEVCPicture ref_frames[15]; /* reference frame list in DPB */ uint16_t picture_width_in_luma_samples; uint16_t picture_height_in_luma_samples; @@ -649,16 +662,6 @@ typedef struct _RocdecHevcPicParams { uint32_t reserved[8]; } RocdecHevcPicParams; -/***********************************************************/ -//! \struct RocdecVc1PicParams placeholder -//! \ingroup group_amd_rocdecode -//! JPEG picture parameters -//! This structure is used in RocdecVc1PicParams structure -/***********************************************************/ -typedef struct _RocdecVc1PicParams { - int Reserved; -} RocdecVc1PicParams; - /***********************************************************/ //! \struct RocdecHevcSliceParams //! \ingroup group_amd_rocdecode @@ -746,6 +749,59 @@ typedef struct _RocdecHevcSliceParams { uint32_t reserved[2]; } RocdecHevcSliceParams; +/***********************************************************/ +//! \struct RocdecHevcIQMatrix +//! \ingroup group_amd_rocdecode +//! HEVC IQMatrix +//! This structure is sent once per frame, +//! and only when scaling_list_enabled_flag = 1. +//! When sps_scaling_list_data_present_flag = 0, app still +//! needs to send in this structure with default matrix values. +//! This structure is used in RocdecHevcQMatrix structure +/***********************************************************/ +typedef struct _RocdecHevcIQMatrix { + /** + * \brief 4x4 scaling, + * correspongs i = 0, MatrixID is in the range of 0 to 5, + * inclusive. And j is in the range of 0 to 15, inclusive. + */ + uint8_t ScalingList4x4[6][16]; + /** + * \brief 8x8 scaling, + * correspongs i = 1, MatrixID is in the range of 0 to 5, + * inclusive. And j is in the range of 0 to 63, inclusive. + */ + uint8_t ScalingList8x8[6][64]; + /** + * \brief 16x16 scaling, + * correspongs i = 2, MatrixID is in the range of 0 to 5, + * inclusive. And j is in the range of 0 to 63, inclusive. + */ + uint8_t ScalingList16x16[6][64]; + /** + * \brief 32x32 scaling, + * correspongs i = 3, MatrixID is in the range of 0 to 1, + * inclusive. And j is in the range of 0 to 63, inclusive. + */ + uint8_t ScalingList32x32[2][64]; + /** + * \brief DC values of the 16x16 scaling lists, + * corresponds to HEVC spec syntax + * scaling_list_dc_coef_minus8[ sizeID - 2 ][ matrixID ] + 8 + * with sizeID = 2 and matrixID in the range of 0 to 5, inclusive. + */ + uint8_t ScalingListDC16x16[6]; + /** + * \brief DC values of the 32x32 scaling lists, + * corresponds to HEVC spec syntax + * scaling_list_dc_coef_minus8[ sizeID - 2 ][ matrixID ] + 8 + * with sizeID = 3 and matrixID in the range of 0 to 1, inclusive. + */ + uint8_t ScalingListDC32x32[2]; + + uint32_t reserved[4]; +} RocdecHevcIQMatrix; + /******************************************************************************************/ //! \struct _RocdecPicParams //! \ingroup group_amd_rocdecode @@ -773,7 +829,7 @@ typedef struct _RocdecPicParams { // IN: Codec-specific data union { RocdecMpeg2PicParams mpeg2; /**< Also used for MPEG-1 */ - RocdecH264PicParams h264; + RocdecAvcPicParams avc; RocdecHevcPicParams hevc; RocdecVc1PicParams vc1; RocdecJPEGPicParams jpeg; @@ -782,11 +838,13 @@ typedef struct _RocdecPicParams { union { // Todo: Add slice params defines for other codecs. + RocdecAvcSliceParams avc; RocdecHevcSliceParams hevc; } slice_params; union { // Todo: Added IQ matrix defines for other codecs. + RocdecAvcIQMatrix avc; RocdecHevcIQMatrix hevc; } iq_matrix; } RocdecPicParams; diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index 1f79bc91e4..35e6c2ff29 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -55,6 +55,13 @@ rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { } new_sps_activated_ = false; } + + // Decode the picture + if (SendPicForDecode() != PARSER_OK) { + ERR(STR("Failed to decode!")); + return ROCDEC_RUNTIME_ERROR; + } + pic_count_++; } else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) { // If no payload and EOS is not set, treated as invalid. @@ -275,6 +282,222 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) { } } +ParserResult AvcVideoParser::SendPicForDecode() { + int i, j; + AvcSeqParameterSet *p_sps = &sps_list_[active_sps_id_]; + AvcPicParameterSet *p_pps = &pps_list_[active_pps_id_]; + AvcSliceHeader *p_slice_header = &slice_header_0_; + dec_pic_params_ = {0}; + + dec_pic_params_.PicWidth = pic_width_; + dec_pic_params_.PicHeight = pic_height_; + dec_pic_params_.CurrPicIdx = curr_pic_.pic_idx; + dec_pic_params_.field_pic_flag = p_slice_header->field_pic_flag; + dec_pic_params_.bottom_field_flag = p_slice_header->bottom_field_flag; + if (p_slice_header->field_pic_flag) { + dec_pic_params_.second_field = (pic_count_ & 1) ? 1 : 0; + } else { + dec_pic_params_.second_field = 1; + } + + dec_pic_params_.nBitstreamDataLen = pic_stream_data_size_; + dec_pic_params_.pBitstreamData = pic_stream_data_ptr_; + dec_pic_params_.nNumSlices = slice_num_; + dec_pic_params_.pSliceDataOffsets = nullptr; + + dec_pic_params_.ref_pic_flag = slice_nal_unit_header_.nal_ref_idc; + dec_pic_params_.intra_pic_flag = p_slice_header->slice_type == kAvcSliceTypeI || p_slice_header->slice_type == kAvcSliceTypeI_7 || p_slice_header->slice_type == kAvcSliceTypeSI || p_slice_header->slice_type == kAvcSliceTypeSI_9; + + // Set up the picture parameter buffer + RocdecAvcPicParams *p_pic_param = &dec_pic_params_.pic_params.avc; + + // Current picture + p_pic_param->curr_pic.PicIdx = curr_pic_.pic_idx; + if (curr_pic_.is_reference == kUsedForLongTerm) { + p_pic_param->curr_pic.FrameIdx = curr_pic_.long_term_pic_num; + } else { + p_pic_param->curr_pic.FrameIdx = curr_pic_.frame_num; + } + p_pic_param->curr_pic.Flags = 0; + if (curr_pic_.pic_structure != kFrame) { + p_pic_param->curr_pic.Flags |= curr_pic_.pic_structure == kBottomField ? RocdecH264Picture_FLAGS_BOTTOM_FIELD : RocdecH264Picture_FLAGS_TOP_FIELD; + } + if (curr_pic_.is_reference != kUnusedForReference) { + p_pic_param->curr_pic.Flags |= curr_pic_.is_reference == kUsedForShortTerm ? RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE : RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE; + } + p_pic_param->curr_pic.TopFieldOrderCnt = curr_pic_.top_field_order_cnt; + p_pic_param->curr_pic.BottomFieldOrderCnt = curr_pic_.bottom_field_order_cnt; + + // Reference pictures + int buf_index = 0; + for (i = 0; i < AVC_MAX_DPB_FRAMES; i++) { + AvcPicture *p_ref_pic = &dpb_buffer_.frame_buffer_list[i]; + if (p_ref_pic->is_reference != kUnusedForReference) { + p_pic_param->ref_frames[buf_index].PicIdx = p_ref_pic->pic_idx; + if ( p_ref_pic->is_reference == kUsedForLongTerm) { + p_pic_param->ref_frames[buf_index].FrameIdx = p_ref_pic->long_term_pic_num; + } else { + p_pic_param->ref_frames[buf_index].FrameIdx = p_ref_pic->frame_num; + } + p_pic_param->ref_frames[buf_index].Flags = 0; + if (p_ref_pic->pic_structure != kFrame) { + p_pic_param->ref_frames[buf_index].Flags |= p_ref_pic->pic_structure == kBottomField ? RocdecH264Picture_FLAGS_BOTTOM_FIELD : RocdecH264Picture_FLAGS_TOP_FIELD; + } + p_pic_param->ref_frames[buf_index].Flags |= p_ref_pic->is_reference == kUsedForShortTerm ? RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE : RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE; + buf_index++; + } + } + + for (i = buf_index; i < AVC_MAX_DPB_FRAMES; i++) { + p_pic_param->ref_frames[i].PicIdx = 0xFF; + } + + p_pic_param->picture_width_in_mbs_minus1 = p_sps->pic_width_in_mbs_minus1; + p_pic_param->picture_height_in_mbs_minus1 = (2 - p_sps->frame_mbs_only_flag) * (p_sps->pic_height_in_map_units_minus1 + 1) - 1; + p_pic_param->bit_depth_luma_minus8 = p_sps->bit_depth_luma_minus8; + p_pic_param->bit_depth_chroma_minus8 = p_sps->bit_depth_chroma_minus8; + p_pic_param->num_ref_frames = p_sps->max_num_ref_frames; + + p_pic_param->seq_fields.bits.chroma_format_idc = p_sps->chroma_format_idc; + p_pic_param->seq_fields.bits.residual_colour_transform_flag = p_sps->separate_colour_plane_flag; + p_pic_param->seq_fields.bits.gaps_in_frame_num_value_allowed_flag = p_sps->gaps_in_frame_num_value_allowed_flag; + p_pic_param->seq_fields.bits.frame_mbs_only_flag = p_sps->frame_mbs_only_flag; + p_pic_param->seq_fields.bits.mb_adaptive_frame_field_flag = p_sps->mb_adaptive_frame_field_flag; + p_pic_param->seq_fields.bits.direct_8x8_inference_flag = p_sps->direct_8x8_inference_flag; + p_pic_param->seq_fields.bits.MinLumaBiPredSize8x8 = p_sps->level_idc >= 31; // A.3.3.2 + p_pic_param->seq_fields.bits.log2_max_frame_num_minus4 = p_sps->log2_max_frame_num_minus4; + p_pic_param->seq_fields.bits.pic_order_cnt_type = p_sps->pic_order_cnt_type; + p_pic_param->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = p_sps->log2_max_pic_order_cnt_lsb_minus4; + p_pic_param->seq_fields.bits.delta_pic_order_always_zero_flag = p_sps->delta_pic_order_always_zero_flag; + + p_pic_param->pic_init_qp_minus26 = p_pps->pic_init_qp_minus26; + p_pic_param->pic_init_qs_minus26 = p_pps->pic_init_qs_minus26; + p_pic_param->chroma_qp_index_offset = p_pps->chroma_qp_index_offset; + p_pic_param->second_chroma_qp_index_offset = p_pps->second_chroma_qp_index_offset; + + p_pic_param->pic_fields.bits.entropy_coding_mode_flag = p_pps->entropy_coding_mode_flag; + p_pic_param->pic_fields.bits.weighted_pred_flag = p_pps->weighted_pred_flag; + p_pic_param->pic_fields.bits.weighted_bipred_idc = p_pps->weighted_bipred_idc; + p_pic_param->pic_fields.bits.transform_8x8_mode_flag = p_pps->transform_8x8_mode_flag; + p_pic_param->pic_fields.bits.field_pic_flag = p_slice_header->field_pic_flag; + p_pic_param->pic_fields.bits.constrained_intra_pred_flag = p_pps->constrained_intra_pred_flag; + p_pic_param->pic_fields.bits.pic_order_present_flag = p_pps->bottom_field_pic_order_in_frame_present_flag; + p_pic_param->pic_fields.bits.deblocking_filter_control_present_flag = p_pps->deblocking_filter_control_present_flag; + p_pic_param->pic_fields.bits.redundant_pic_cnt_present_flag = p_pps->redundant_pic_cnt_present_flag; + p_pic_param->pic_fields.bits.reference_pic_flag = slice_nal_unit_header_.nal_ref_idc != 0; + + p_pic_param->frame_num = p_slice_header->frame_num; + + // Set up slice parameters + RocdecAvcSliceParams *p_slice_param = &dec_pic_params_.slice_params.avc; + + p_slice_param->slice_data_size = pic_stream_data_size_; + p_slice_param->slice_data_offset = 0; + p_slice_param->slice_data_flag = 0; // VA_SLICE_DATA_FLAG_ALL; + p_slice_param->slice_data_bit_offset = 0; + p_slice_param->first_mb_in_slice = p_slice_header->first_mb_in_slice; + p_slice_param->slice_type = p_slice_header->slice_type; + p_slice_param->direct_spatial_mv_pred_flag = p_slice_header->direct_spatial_mv_pred_flag; + p_slice_param->num_ref_idx_l0_active_minus1 = p_slice_header->num_ref_idx_l0_active_minus1; + p_slice_param->num_ref_idx_l1_active_minus1 = p_slice_header->num_ref_idx_l1_active_minus1; + p_slice_param->cabac_init_idc = p_slice_header->cabac_init_idc; + p_slice_param->slice_qp_delta = p_slice_header->slice_qp_delta; + p_slice_param->disable_deblocking_filter_idc = p_slice_header->disable_deblocking_filter_idc; + p_slice_param->slice_alpha_c0_offset_div2 = p_slice_header->slice_alpha_c0_offset_div2; + p_slice_param->slice_beta_offset_div2 = p_slice_header->slice_beta_offset_div2; + p_slice_param->luma_log2_weight_denom = p_slice_header->pred_weight_table.luma_log2_weight_denom; + p_slice_param->chroma_log2_weight_denom = p_slice_header->pred_weight_table.chroma_log2_weight_denom; + + // Ref lists + for (i = 0; i < dpb_buffer_.num_short_term + dpb_buffer_.num_long_term; i++) { + AvcPicture *p_ref_pic = &ref_list_0_[i]; + if (p_ref_pic->is_reference != kUnusedForReference) { + p_slice_param->ref_pic_list_0[i].PicIdx = p_ref_pic->pic_idx; + if ( p_ref_pic->is_reference == kUsedForLongTerm) { + p_slice_param->ref_pic_list_0[i].FrameIdx = p_ref_pic->long_term_pic_num; + } else { + p_slice_param->ref_pic_list_0[i].FrameIdx = p_ref_pic->frame_num; + } + p_slice_param->ref_pic_list_0[i].Flags = 0; + if (p_ref_pic->pic_structure != kFrame) { + p_slice_param->ref_pic_list_0[i].Flags |= p_ref_pic->pic_structure == kBottomField ? RocdecH264Picture_FLAGS_BOTTOM_FIELD : RocdecH264Picture_FLAGS_TOP_FIELD; + } + p_slice_param->ref_pic_list_0[i].Flags |= p_ref_pic->is_reference == kUsedForShortTerm ? RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE : RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE; + } + } + + if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6 ) { + AvcPicture *p_ref_pic = &ref_list_1_[i]; + if (p_ref_pic->is_reference != kUnusedForReference) { + p_slice_param->ref_pic_list_1[i].PicIdx = p_ref_pic->pic_idx; + if ( p_ref_pic->is_reference == kUsedForLongTerm) { + p_slice_param->ref_pic_list_1[i].FrameIdx = p_ref_pic->long_term_pic_num; + } else { + p_slice_param->ref_pic_list_1[i].FrameIdx = p_ref_pic->frame_num; + } + p_slice_param->ref_pic_list_1[i].Flags = 0; + if (p_ref_pic->pic_structure != kFrame) { + p_slice_param->ref_pic_list_1[i].Flags |= p_ref_pic->pic_structure == kBottomField ? RocdecH264Picture_FLAGS_BOTTOM_FIELD : RocdecH264Picture_FLAGS_TOP_FIELD; + } + p_slice_param->ref_pic_list_1[i].Flags |= p_ref_pic->is_reference == kUsedForShortTerm ? RocdecH264Picture_FLAGS_SHORT_TERM_REFERENCE : RocdecH264Picture_FLAGS_LONG_TERM_REFERENCE; + } + } + + // Prediction weight table + // Note luma_weight_l0_flag should be an array. Set it using the first one in the table. + p_slice_param->luma_weight_l0_flag = p_slice_header->pred_weight_table.weight_factor[0].luma_weight_l0_flag; + for (i = 0; i <= p_slice_header->num_ref_idx_l0_active_minus1; i++) { + p_slice_param->luma_weight_l0[i] = p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l0; + p_slice_param->luma_offset_l0[i] = p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l0; + } + + // Note chroma_weight_l0_flag should be an array. Set it using the first one in the table. + p_slice_param->chroma_weight_l0_flag = p_slice_header->pred_weight_table.weight_factor[0].chroma_weight_l0_flag; + for (i = 0; i <= p_slice_header->num_ref_idx_l0_active_minus1; i++) { + for (j = 0; j < 2; j++) { + p_slice_param->chroma_weight_l0[i][j] = p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l0[j]; + p_slice_param->chroma_offset_l0[i][j] = p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l0[j]; + } + } + if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6 ) { + // Note luma_weight_l1_flag should be an array. Set it using the first one in the table. + p_slice_param->luma_weight_l1_flag = p_slice_header->pred_weight_table.weight_factor[0].luma_weight_l1_flag; + for (i = 0; i <= p_slice_header->num_ref_idx_l1_active_minus1; i++) { + p_slice_param->luma_weight_l1[i] = p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l1; + p_slice_param->luma_offset_l1[i] = p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l1; + } + // Note chroma_weight_l0_flag should be an array. Set it using the first one in the table. + p_slice_param->chroma_weight_l1_flag = p_slice_header->pred_weight_table.weight_factor[0].chroma_weight_l1_flag; + for (i = 0; i <= p_slice_header->num_ref_idx_l1_active_minus1; i++) { + for (j = 0; j < 2; j++) { + p_slice_param->chroma_weight_l1[i][j] = p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l1[j]; + p_slice_param->chroma_offset_l1[i][j] = p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l1[j]; + } + } + } + + // Set up scaling lists + RocdecAvcIQMatrix *p_iq_matrix = &dec_pic_params_.iq_matrix.avc; + for (i = 0; i < 6; i++) { + for (j = 0; j < 16; j++) { + p_iq_matrix->scaling_list_4x4[i][j] = p_pps->scaling_list_4x4[i][j]; + } + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 64; j++) { + p_iq_matrix->scaling_list_8x8[i][j] = p_pps->scaling_list_8x8[i][j]; + } + } + + if (pfn_decode_picture_cb_(parser_params_.pUserData, &dec_pic_params_) == 0) { + ERR("Decode error occurred."); + return PARSER_FAIL; + } else { + return PARSER_OK; + } +} + + AvcNalUnitHeader AvcVideoParser::ParseNalUnitHeader(uint8_t header_byte) { size_t bit_offset = 0; AvcNalUnitHeader nal_header; diff --git a/src/parser/avc_parser.h b/src/parser/avc_parser.h index f4870f5ec3..a3e336e2b9 100644 --- a/src/parser/avc_parser.h +++ b/src/parser/avc_parser.h @@ -54,10 +54,41 @@ public: protected: + enum PictureStructure { + kFrame, + kTopField, + kBottomField + }; + + enum AvcRefMarking { + kUnusedForReference = 0, + kUsedForShortTerm = 1, + kUsedForLongTerm = 2 + }; + + typedef struct { + int pic_idx; // picture index or id + PictureStructure pic_structure; + + int32_t pic_order_cnt; + int32_t top_field_order_cnt; + int32_t bottom_field_order_cnt; + int32_t frame_num; + int32_t frame_num_wrap; // FrameNumWrap + int32_t pic_num; // PicNum + int32_t long_term_pic_num; // LongTermPicNum + uint32_t long_term_frame_idx; // LongTermFrameIdx: long term reference frame/field identifier + + uint32_t is_reference; + } AvcPicture; + /*! \brief Decoded picture buffer */ typedef struct{ uint32_t dpb_size; // DPB buffer size in number of frames + uint32_t num_short_term; // numShortTerm; + uint32_t num_long_term; // numLongTerm; + AvcPicture frame_buffer_list[AVC_MAX_DPB_FRAMES]; } DecodedPictureBuffer; AvcNalUnitHeader nal_unit_header_; @@ -75,7 +106,10 @@ protected: int curr_ref_pic_bottom_field_; // DPB + AvcPicture curr_pic_; DecodedPictureBuffer dpb_buffer_; + AvcPicture ref_list_0_[AVC_MAX_REF_FRAME_NUM]; + AvcPicture ref_list_1_[AVC_MAX_REF_FRAME_NUM]; /*! \brief Function to notify decoder about video format change (new SPS) through callback * \param [in] p_sps Pointer to the current active SPS @@ -83,6 +117,11 @@ protected: */ ParserResult NotifyNewSps(AvcSeqParameterSet *p_sps); + /*! \brief Function to fill the decode parameters and call back decoder to decode a picture + * \return ParserResult + */ + ParserResult SendPicForDecode(); + /*! \brief Function to parse one picture bit stream received from the demuxer. * \param [in] p_stream A pointer of uint8_t for the input stream to be parsed * \param [in] pic_data_size Size of the input stream diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index 9dffcc8784..a3e48f5f32 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -287,8 +287,8 @@ int HevcVideoParser::SendPicForDecode() { RocdecHevcPicParams *pic_param_ptr = &dec_pic_params_.pic_params.hevc; // Current picture - pic_param_ptr->cur_pic.PicIdx = curr_pic_info_.pic_idx; - pic_param_ptr->cur_pic.POC = curr_pic_info_.pic_order_cnt; + pic_param_ptr->curr_pic.PicIdx = curr_pic_info_.pic_idx; + pic_param_ptr->curr_pic.POC = curr_pic_info_.pic_order_cnt; // Reference pictures ref_idx = 0; diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/src/rocdecode/vaapi/vaapi_videodecoder.cpp index da659d5dee..eb435c86db 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -212,7 +212,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { // Upload data buffers switch (decoder_create_info_.CodecType) { case rocDecVideoCodec_HEVC: { - pPicParams->pic_params.hevc.cur_pic.PicIdx = curr_surface_id; + pPicParams->pic_params.hevc.curr_pic.PicIdx = curr_surface_id; for (int i = 0; i < 15; i++) { if (pPicParams->pic_params.hevc.ref_frames[i].PicIdx != 0xFF) { if (pPicParams->pic_params.hevc.ref_frames[i].PicIdx >= va_surface_ids_.size() || pPicParams->pic_params.hevc.ref_frames[i].PicIdx < 0) { @@ -233,6 +233,7 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { slice_params_ptr = (void*)&pPicParams->slice_params.hevc; slice_params_size = sizeof(RocdecHevcSliceParams); + if ((pic_params_size != sizeof(VAPictureParameterBufferHEVC)) || (scaling_list_enabled && (iq_matrix_size != sizeof(VAIQMatrixBufferHEVC))) || (slice_params_size != sizeof(VASliceParameterBufferHEVC))) { ERR("HEVC data_buffer parameter_size not matching vaapi parameter buffer size!"); @@ -241,6 +242,34 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { break; } + case rocDecVideoCodec_H264: { + pPicParams->pic_params.avc.curr_pic.PicIdx = curr_surface_id; + for (int i = 0; i < 16; i++) { + if (pPicParams->pic_params.avc.ref_frames[i].PicIdx != 0xFF) { + if (pPicParams->pic_params.avc.ref_frames[i].PicIdx >= va_surface_ids_.size() || pPicParams->pic_params.avc.ref_frames[i].PicIdx < 0) { + ERR("Reference frame index exceeded the VAAPI surface pool limit."); + return ROCDEC_INVALID_PARAMETER; + } + pPicParams->pic_params.avc.ref_frames[i].PicIdx = va_surface_ids_[pPicParams->pic_params.avc.ref_frames[i].PicIdx]; + } + } + pic_params_ptr = (void*)&pPicParams->pic_params.avc; + pic_params_size = sizeof(RocdecAvcPicParams); + + scaling_list_enabled = true; + iq_matrix_ptr = (void*)&pPicParams->iq_matrix.avc; + iq_matrix_size = sizeof(RocdecAvcIQMatrix); + + slice_params_ptr = (void*)&pPicParams->slice_params.avc; + slice_params_size = sizeof(RocdecAvcSliceParams); + + if ((pic_params_size != sizeof(VAPictureParameterBufferH264)) || (iq_matrix_size != sizeof(VAIQMatrixBufferH264)) || (slice_params_size != sizeof(VASliceParameterBufferH264))) { + ERR("AVC data_buffer parameter_size not matching vaapi parameter buffer size!"); + return ROCDEC_RUNTIME_ERROR; + } + break; + } + default: { ERR("ERROR: the codec type is not supported!"); return ROCDEC_NOT_SUPPORTED;