diff options
Diffstat (limited to 'vaenc/hevcencode.c')
| -rw-r--r-- | vaenc/hevcencode.c | 920 |
1 files changed, 638 insertions, 282 deletions
diff --git a/vaenc/hevcencode.c b/vaenc/hevcencode.c index 8079075..af9d3f0 100644 --- a/vaenc/hevcencode.c +++ b/vaenc/hevcencode.c @@ -46,6 +46,17 @@ #define NAL_PPS 8 #define NAL_SEI 6 +#define NAL_VPS_HEVC 0x20 +#define NAL_SPS_HEVC 0x21 +#define NAL_PPS_HEVC 0x22 +#define NAL_AUD_HEVC 0x09 + +#define TRAIL_R 1 +#define IDR_W_RADL 19 +#define IDR_N_LP 20 +#define BLA_W_LP 16 +#define RSV_IRAP_VCL23 23 + #define SLICE_TYPE_P 0 #define SLICE_TYPE_B 1 #define SLICE_TYPE_I 2 @@ -59,10 +70,13 @@ #define BITSTREAM_ALLOCATE_STEPPING 4096 +#define NUM_MAX_REF_FRAME_HEVC 15 + static VAConfigAttrib hevc_attrib[VAConfigAttribTypeMax]; static VAEncSequenceParameterBufferHEVC seq_param; -static VAPictureParameterBufferHEVC pic_param; +static VAEncPictureParameterBufferHEVC pic_param; +static VAEncSliceParameterBufferHEVC slc_param; static VAPictureHEVC CurrentCurrPic; static VAPictureHEVC ReferenceFrames[16], RefPicList0_P[32], RefPicList0_B[32], RefPicList1_B[32]; @@ -75,14 +89,20 @@ static unsigned int num_ref_frames = 2; static unsigned int numShortTerm = 0; static int constraint_set_flag = 0; static int hevc_packedheader = 0; /* support pack header? */ -static int hevc_maxref = (1<<16|1); +static int hevc_maxref = 15; static int hevc_autoref = 0; +static int frame_poc = 0; + static VAProfile hevc_profile = -1; int hevc_entropy_mode = 1; /* cabac */ int hevc_8x8_dct = 0; +#define LCU_SIZE 32 +#define ALIGN(x, align) (((x) + (align) - 1 ) & (~((align) - 1))) +#define GET_CTU_NUM(x, LCU_SIZE) ((ALIGN(x, LCU_SIZE))/LCU_SIZE) + struct __bitstream { unsigned int *buffer; int bit_offset; @@ -205,149 +225,253 @@ rbsp_trailing_bits(bitstream *bs) bitstream_byte_aligning(bs, 0); } -static void nal_start_code_prefix(bitstream *bs) +static unsigned char get_va_frame_type(int frame_type) { + switch (frame_type) { + case FRAME_IDR: + return 7; + case FRAME_I: + return 2; + case FRAME_P: + return 0; + case FRAME_B: + return 1; + default: + fprintf(stderr, "%s Invalid frame type:%d\n", __FUNCTION__, frame_type); + return 0; + } +} + + +static void nal_start_code_prefix_HEVC(bitstream *bs, bool flag) { - bitstream_put_ui(bs, 0x00000001, 32); + if (!flag) + bitstream_put_ui(bs, 0x00, 8); + bitstream_put_ui(bs, 0x000001, 24); } -static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type) +static void nal_header_HEVC(bitstream *bs, int nal_ref_idc, int nal_unit_type) { bitstream_put_ui(bs, 0, 1); /* forbidden_zero_bit: 0 */ - bitstream_put_ui(bs, nal_ref_idc, 2); - bitstream_put_ui(bs, nal_unit_type, 5); + bitstream_put_ui(bs, nal_unit_type, 6); + bitstream_put_ui(bs, 0, 6); + bitstream_put_ui(bs, 1, 3); } -static void sps_rbsp(bitstream *bs) +static void profile_tier_level(bitstream *bs) { - int profile_idc = PROFILE_IDC_BASELINE; + int i = 0; + bitstream_put_ui(bs, 0, 2); + bitstream_put_ui(bs, 0, 1); + bitstream_put_ui(bs, 1, 5); + + for(i = 0; i < 32; i++) + bitstream_put_ui(bs, 0, 1); - bitstream_put_ui(bs, 0, 32); - bitstream_put_ui(bs, 0, 32); + bitstream_put_ui(bs, 1, 1); + bitstream_put_ui(bs, 0, 1); + bitstream_put_ui(bs, 0, 1); + bitstream_put_ui(bs, 1, 1); + bitstream_put_ui(bs, 0/*ps.general_reserved_zero_44bits*/, 44); + bitstream_put_ui(bs, 51*3, 8); +} - //profile_tier_level(0) +static void sps_rbsp(bitstream *bs) +{ + int conformance_window_flag = 0; + bitstream_put_ui(bs, 0, 4); //sps_video_parameter_set_id + bitstream_put_ui(bs, 0, 3); + bitstream_put_ui(bs, 1, 1); //sps_temporal_id_nesting_flag - bitstream_put_ui(bs, seq_param.general_profile_idc, 8); //general_profile_idc = 1; - bitstream_put_ui(bs, 0, 32); //eneral_profile_compatibility_flag[] = 0; - //general_progressive_source_flag = 1 general_interlaced_source_flag = 0 - //general_non_packed_constraint_flag = 1 general_frame_only_constraint_flag = 0 - bitstream_put_ui(bs, 0xb<<4, 8); - bitstream_put_ui(bs, 0, 32); - bitstream_put_ui(bs, 0, 8); - //general_level_idc = 123, i.e. L4.1 - bitstream_put_ui(bs, seq_param.general_level_idc * 30, 8); - bitstream_put_ue(bs, 0); //sps_seq_parameter_set_id - bitstream_put_ue(bs, seq_param.seq_fields.chroma_format_idc); //chroma_format_idc + profile_tier_level(bs); - bitstream_put_ue(bs, frame_width_mbaligned); - bitstream_put_ue(bs, frame_height_mbaligned); + bitstream_put_ue(bs, 0); + bitstream_put_ue(bs, 1); //4:2:0 seq_param.seq_fields.bits.chroma_format_idc + if (seq_param.seq_fields.bits.chroma_format_idc == 3) + bitstream_put_ui(bs, 0, 1); - //conformance_window_flag = 0 - bitstream_put_ui(bs, seq_param.frame_cropping_flag, 1); /* frame_cropping_flag */ + int wFrameWidthInMinCbMinus1 = (ALIGN(frame_width, 16) >> 3) - 1; + seq_param.pic_width_in_luma_samples = (wFrameWidthInMinCbMinus1 + 1) * (1 << 3); + bitstream_put_ue(bs, seq_param.pic_width_in_luma_samples); + int wFrameHeightInMinCbMinus1 = (ALIGN(frame_height, 16) >> 3) - 1; + seq_param.pic_height_in_luma_samples = (wFrameHeightInMinCbMinus1 + 1) * (1 << 3); + bitstream_put_ue(bs, seq_param.pic_height_in_luma_samples); - if (seq_param.frame_cropping_flag) { - bitstream_put_ue(bs, seq_param.frame_crop_left_offset); /* frame_crop_left_offset */ - bitstream_put_ue(bs, seq_param.frame_crop_right_offset); /* frame_crop_right_offset */ - bitstream_put_ue(bs, seq_param.frame_crop_top_offset); /* frame_crop_top_offset */ - bitstream_put_ue(bs, seq_param.frame_crop_bottom_offset); /* frame_crop_bottom_offset */ + if((ALIGN(frame_width, 16) != frame_width) || (ALIGN(frame_height, 16) != frame_height)) + { + conformance_window_flag = 1; + bitstream_put_ui(bs, conformance_window_flag, 1); //conformance_window_flag + bitstream_put_ue(bs, 0); //conf_win_left_offset + //bitstream_put_ue(bs, (frame_width_mbaligned - frame_width)/2); + bitstream_put_ue(bs, (ALIGN(frame_width, 16) - frame_width)/2); //conf_win_right_offset + bitstream_put_ue(bs, 0); // conf_win_top_offset + //bitstream_put_ue(bs, (frame_height_mbaligned - frame_height)/2); + bitstream_put_ue(bs, (ALIGN(frame_height, 16) - frame_height)/2); // conf_win_bottom_offset } - - //bit_depth_luma_minus8 bit_depth_chroma_minus8 - bitstream_put_ue(bs, 0); - bitstream_put_ue(bs, 0); + else + bitstream_put_ui(bs, conformance_window_flag, 1); //conformance_window_flag - bitstream_put_ue(bs, seq_param.seq_fields.bits.log2_max_pic_order_cnt_cnt_lsb_minus4); - - //sps_sub_layer_ordering_info_present_flag - bitstream_put_ui(bs, 0, 1); - //log2_min_luma_coding_block_size_minus3 - bitstream_put_ue(bs, 1); - bitstream_put_ue(bs, 0); - bitstream_put_ue(bs, 1); - bitstream_put_ue(bs, 0); - bitstream_put_ue(bs, 1); - bitstream_put_ue(bs, 1); + bitstream_put_ue(bs, 0); //seq_fields.bits.bit_depth_luma_minus8 + bitstream_put_ue(bs, 0); //seq_fields.bits.bit_depth_chroma_minus8 + bitstream_put_ue(bs, 0); // log2_max_pic_order_cnt_lsb_minus4); + bitstream_put_ui(bs, 0, 1); //sps_sub_layer_ordering_info_present_flag + bitstream_put_ue(bs, 6); // sps_max_dec_pic_buffering[0] + bitstream_put_ue(bs, 0); //sps.sps_num_reorder_pics[0]); + bitstream_put_ue(bs, 0); //sps.sps_max_latency_increase[0]); - bitstream_put_ui(bs, 0, 4); + bitstream_put_ue(bs, 0);// seq_param.log2_min_luma_coding_block_size_minus3); + bitstream_put_ue(bs, 2); //seq_param.log2_diff_max_min_luma_coding_block_size); + bitstream_put_ue(bs, 0); //seq_param.log2_min_transform_block_size_minus2); + bitstream_put_ue(bs, 3); //seq_param.log2_diff_max_min_transform_block_size); + bitstream_put_ue(bs, 2); //seq_param.max_transform_hierarchy_depth_inter); + bitstream_put_ue(bs, 2); //seq_param.max_transform_hierarchy_depth_intra); + bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.scaling_list_enabled_flag, 1); + bitstream_put_ui(bs, 1, 1); //seq_param.seq_fields.bits.amp_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.sample_adaptive_offset_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.pcm_enabled_flag, 1); - //num_short_term_ref_pic_sets - bitstream_put_ue(bs, 0); - //num_long_term_ref_pic_sets - bitstream_put_ue(bs, 0); + bitstream_put_ue(bs, 1); //sps.num_short_term_ref_pic_sets); + bitstream_put_ue(bs, 1); // num_negative_pics port from short_term_ref_pic_set() + bitstream_put_ue(bs, 0); // ps.num_positive_pics[refIdx==0?0:1] + bitstream_put_ue(bs, 0); // ps.delta_poc_s0_minus1[refIdx] + bitstream_put_ui(bs, 1, 1); // ps.used_by_curr_pic_s0_flag[refIdx], 1) - //sps_temporal_mvp_enabled_flag strong_intra_smoothing_enabled_flag - //vui_parameters_present_flag - bitstream_put_ui(bs, 0, 3); - + bitstream_put_ui(bs, 0, 1); //sps.long_term_ref_pics_present_flag, 1); + bitstream_put_ui(bs, 1, 1); //seq_param.seq_fields.bits.sps_temporal_mvp_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.strong_intra_smoothing_enabled_flag , 1); + bitstream_put_ui(bs, 0, 1); //seq_param.vui_parameters_present_flag, 1); + bitstream_put_ui(bs, 0, 1); //sps.sps_extension_flag, 1); - rbsp_trailing_bits(bs); /* rbsp_trailing_bits */ + rbsp_trailing_bits(bs); } static void pps_rbsp(bitstream *bs) { - bitstream_put_ue(bs, pic_param.pic_parameter_set_id); /* pic_parameter_set_id */ - bitstream_put_ue(bs, pic_param.seq_parameter_set_id); /* seq_parameter_set_id */ + bitstream_put_ue(bs, 0); //pps.pic_parameter_set_id); + bitstream_put_ue(bs, 0); //sps.sps_seq_parameter_set_id); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.dependent_slice_segments_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //pps.output_flag_present_flag, 1); + bitstream_put_ui(bs, 0, 3); //pps.num_extra_slice_header_bits, 3); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.sign_data_hiding_enabled_flag, 1); + bitstream_put_ui(bs, 1, 1); //pps.cabac_init_present_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.dependent_slice_segments_enabled_flag, 1); + bitstream_put_ue(bs, 0); //pps.num_ref_idx_l0_default_active_minus1); + bitstream_put_ue(bs, 0); //pic_param.num_ref_idx_l1_default_active_minus1); + bitstream_put_se(bs, 2); //pic_param.pic_init_qp + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.constrained_intra_pred_flag, 1); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.transform_skip_enabled_flag , 1); + if (rc_mode == VA_RC_CQP) + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.cu_qp_delta_enabled_flag , 1); + else + { + bitstream_put_ui(bs, 1, 1); + bitstream_put_ue(bs, 0); //pic_param.diff_cu_qp_delta_depth); + } - bitstream_put_ui(bs, 0, 4); + bitstream_put_se(bs, 0); //pic_param.pps_cb_qp_offset); + bitstream_put_se(bs, 0); //pic_param.pps_cr_qp_offset); + bitstream_put_ui(bs, 0, 1); //pps.pps_slice_chroma_qp_offsets_present_flag, 1) + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.weighted_pred_flag, 1); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.weighted_bipred_flag, 1); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.transquant_bypass_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.tiles_enabled_flag, 1); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.entropy_coding_sync_enabled_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.sign_data_hiding_enabled_flag); + /* skip pic_param.pic_fields.bits.tiles_enabled_fla part */ - //cabac_init_present_flag - bitstream_put_ui(bs, 1, 1); - bitstream_put_ue(bs, pic_param.num_ref_idx_l0_active_minus1); /* num_ref_idx_l0_active_minus1 */ - bitstream_put_ue(bs, pic_param.num_ref_idx_l1_active_minus1); /* num_ref_idx_l1_active_minus1 1 */ + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.pps_loop_filter_across_slices_enabled_flag, 1); + bitstream_put_ui(bs, 1, 1); //pps.deblocking_filter_control_present_flag, 1); - bitstream_put_se(bs, pic_param.pic_init_qp - 26); /* pic_init_qp_minus26 */ + bitstream_put_ui(bs, 1, 1); //pps.deblocking_filter_override_enabled_flag, 1); + bitstream_put_ui(bs, 1, 1); //pps.disable_deblocking_filter_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.constrained_intra_pred_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.transform_skip_enabled_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.cu_qp_delta_enabled_flag, 1); - bitstream_put_ui(bs, pic_param.pic_fields.bits.entropy_coding_mode_flag, 1); /* entropy_coding_mode_flag */ - if (pic_param.pic_fields.bits.entropy_coding_mode_flag) - bitstream_put_ue(bs, pic_param.diff_cu_qp_delta_depth); - bitstrea_put_se(se, pic_param.pps_cb_qp_offset); - bitstrea_put_se(se, pic_param.pps_cr_qp_offset); + bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.scaling_list_data_present_flag, 1); - //pps_slice_chroma_qp_offsets_present_flag - bitstream_put_ui(bs, 0, 1); - //weighted_pred_flag - bitstream_put_ui(bs, pic_param.pic_fields.weighted_pred_flag, 1); - //weighted_bipred_flag - bitstream_put_ui(bs, 0, 1); + bitstream_put_ui(bs, 0, 1); //pps.lists_modification_present_flag, 1); + bitstream_put_ue(bs, 0); //pic_param.log2_parallel_merge_level_minus2); + bitstream_put_ui(bs, 0, 1); //pps.slice_segment_header_extension_present_flag, 1); + bitstream_put_ui(bs, 0, 1); //pps.pps_extension_flag, 1); + + rbsp_trailing_bits(bs); +} + +static void slice_rbsp(bitstream *bs) +{ + unsigned char frame_type = get_va_frame_type(current_frame_type); + unsigned char slice_type = (frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type; + unsigned char nal_type = (frame_type == FRAME_IDR) ? IDR_W_RADL : TRAIL_R; + + bitstream_put_ui(bs, 1, 1); // sliceps.first_slice_in_pic_flag, 1); + + if (nal_type >= BLA_W_LP && nal_type <= RSV_IRAP_VCL23) + bitstream_put_ui(bs, 0, 1); //sliceps.no_output_of_prior_pics_flag, 1); - bitstream_put_ui(bs,pic_param.pic_fields.transquant_bypass_enabled_flag, 1); - bitstream_put_ui(bs,pic_param.pic_fields.tiles_enabled_flag, 1); - bitstream_put_ui(bs,pic_param.pic_fields.entropy_coding_sync_enabled_flag, 1); + bitstream_put_ue(bs, 0); //slc_param.slice_pic_parameter_set_id); - if (pic_param.pic_fields.tiles_enabled_flag) { - bitstream_put_ue(bs, pic_param.num_tile_columns_minus1); - bitstream_put_ue(bs, pic_param.num_tile_rows_minus1); - //uniform_spacing_flag - bitstream_put_ui(bs, 0, 1); - for( i = 0; i < pic_param.num_tile_columns_minus1; i++ ) - bitstream_put_ue(bs, pic_param.column_width_minus1[i]); + bitstream_put_ue(bs, slice_type); //sliceps.slice_type); - for( i = 0; i < pic_param.num_tile_rows_minus1; i++ ) - bitstream_put_ue(bs, pic_param.row_height_minus1[i]); - bistream_put_ui(bs, pic_param.pic_fields.loop_filter_across_tiles_enabled_flag, 1); + if (nal_type != IDR_W_RADL && nal_type != IDR_N_LP) + { + bitstream_put_ui(bs, frame_poc, 4); // or 8 sliceps.pic_order_cnt_lsb/2, (sps.log2_max_pic_order_cnt_lsb_minus4+4)); + bitstream_put_ui(bs, 1, 1); //sliceps.short_term_ref_pic_set_sps_flag, 1); + + bitstream_put_ui(bs, 1, 1); //sliceps.slice_fields.bits.slice_temporal_mvp_enabled_flag, 1); } - //pps_loop_filter_across_slices_enabled_flag - //deblocking_filter_control_present_flag - //pps_scaling_list_data_present_flag - //lists_modification_present_flag - bitstream_put_ui(bs, 0, 4); - bitstream_put_ue(bs, pic_param.log2_parallel_merge_level_minus2); - //slice_segment_header_extension_present_flag - //pps_extension_flag - bitstream_put_ui(bs, 0, 2); + /* skip seq_fields.bits.sample_adaptive_offset_enabled part */ + + if (slice_type == SLICE_TYPE_P) + { + bitstream_put_ui(bs, 0, 1); //slc_param.slice_fields.bits.num_ref_idx_active_override_flag/*0*/, 1); + if (slice_type == SLICE_TYPE_P) + bitstream_put_ui(bs, 0, 1);//slc_param.slice_fields.bits.mvd_l1_zero_flag, 1); + + bitstream_put_ui(bs, 0, 1); //.slice_fields.bits.cabac_init_flag + bitstream_put_ui(bs, 1, 1);//slc_param.slice_fields.bits.collocated_from_l0_flag, 1); + + bitstream_put_ue(bs, 0);//5 - sliceps.max_num_merge_cand + } + + + bitstream_put_se(bs, 0); //slc_param.slice_qp_delta); + + bitstream_put_ui(bs, 1, 1); //sliceps.deblocking_filter_override_flag, 1); + bitstream_put_ui(bs, 0, 1); //slc_param.slice_fields.bits.slice_deblocking_filter_disabled_flag, 1); + bitstream_put_se(bs, 0); //slc_param.slice_beta_offset_div2); + bitstream_put_se(bs, 0); //slc_param.slice_tc_offset_div2); rbsp_trailing_bits(bs); + frame_poc++; } +static void vps_rbsp(bitstream *bs) +{ + bitstream_put_ui(bs, 0, 4); + bitstream_put_ui(bs, 3, 2); + bitstream_put_ui(bs, 0, 6); //vps.vps_max_layers_minus1, + bitstream_put_ui(bs, 0, 3); //vps.vps_max_sub_layers_minus1, 3); + bitstream_put_ui(bs, 1, 1); //vps.vps_temporal_id_nesting_flag, 1); + bitstream_put_ui(bs, 0xFFFF, 16); + + profile_tier_level(bs); + bitstream_put_ui(bs, 0, 1); //vps.vps_sub_layer_ordering_info_present_flag, 1); + + bitstream_put_ue(bs, 6); //?vps.vps_max_dec_pic_buffering[i]); + bitstream_put_ue(bs, 0); //vps.vps_num_reorder_pics[i]); + bitstream_put_ue(bs, 0); //vps.vps_max_latency_increase[i]); + + bitstream_put_ui(bs, 0, 6); //vps.max_nuh_reserved_zero_layer_id, 6); + bitstream_put_ue(bs, 0); //vps.max_op_sets-1); + + bitstream_put_ui(bs, 0, 1); //vps.vps_timing_info_present_flag, 1); + + /* skip vps_timing_info_present_flag part */ + + bitstream_put_ui(bs, 0, 1); + + rbsp_trailing_bits(bs); +} static int build_packed_pic_buffer(unsigned char **header_buffer) @@ -355,8 +479,8 @@ build_packed_pic_buffer(unsigned char **header_buffer) bitstream bs; bitstream_start(&bs); - nal_start_code_prefix(&bs); - nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS); + nal_start_code_prefix_HEVC(&bs, false); + nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_PPS_HEVC); pps_rbsp(&bs); bitstream_end(&bs); @@ -370,8 +494,8 @@ build_packed_seq_buffer(unsigned char **header_buffer) bitstream bs; bitstream_start(&bs); - nal_start_code_prefix(&bs); - nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS); + nal_start_code_prefix_HEVC(&bs, false); + nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_SPS_HEVC); sps_rbsp(&bs); bitstream_end(&bs); @@ -379,6 +503,38 @@ build_packed_seq_buffer(unsigned char **header_buffer) return bs.bit_offset; } +static int +build_packed_slice_buffer(unsigned char **header_buffer) +{ + unsigned char frame_type = get_va_frame_type(current_frame_type); + unsigned char nal_type = (frame_type == FRAME_IDR) ? IDR_W_RADL : TRAIL_R; + bitstream bs; + + bitstream_start(&bs); + nal_start_code_prefix_HEVC(&bs, true); + nal_header_HEVC(&bs, NAL_REF_IDC_LOW, nal_type); + slice_rbsp(&bs); + bitstream_end(&bs); + + *header_buffer = (unsigned char *)bs.buffer; + return bs.bit_offset; +} + +static int +build_packed_vps_buffer(unsigned char **header_buffer) +{ + bitstream bs; + + bitstream_start(&bs); + nal_start_code_prefix_HEVC(&bs, false); + nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_VPS_HEVC); + vps_rbsp(&bs); + bitstream_end(&bs); + + *header_buffer = (unsigned char *)bs.buffer; + return bs.bit_offset; +} + static int build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length, unsigned int init_cpb_removal_delay, @@ -415,8 +571,8 @@ build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length, pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8; bitstream_start(&nal_bs); - nal_start_code_prefix(&nal_bs); - nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI); + nal_start_code_prefix_HEVC(&nal_bs, false); + nal_header_HEVC(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI); /* Write the SEI buffer period data */ bitstream_put_ui(&nal_bs, 0, 8); @@ -467,42 +623,42 @@ build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length, } \ } \ -static void sort_one(VAPictureH264 ref[], int left, int right, - int ascending, int frame_idx) +static void sort_one(VAPictureHEVC ref[], int left, int right, + int ascending, int pic_order_cnt) { int i = left, j = right; unsigned int key; - VAPictureH264 tmp; + VAPictureHEVC tmp; - if (frame_idx) { - key = ref[(left + right) / 2].frame_idx; - partition(ref, frame_idx, key, ascending); + if (pic_order_cnt) { + key = ref[(left + right) / 2].pic_order_cnt; + partition(ref, pic_order_cnt, key, ascending); } else { - key = ref[(left + right) / 2].TopFieldOrderCnt; - partition(ref, TopFieldOrderCnt, (signed int)key, ascending); + key = ref[(left + right) / 2].pic_order_cnt; + partition(ref, pic_order_cnt, (signed int)key, ascending); } /* recursion */ if (left < j) - sort_one(ref, left, j, ascending, frame_idx); + sort_one(ref, left, j, ascending, pic_order_cnt); if (i < right) - sort_one(ref, i, right, ascending, frame_idx); + sort_one(ref, i, right, ascending, pic_order_cnt); } -static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx, +static void sort_two(VAPictureHEVC ref[], int left, int right, unsigned int key, unsigned int pic_order_cnt, int partition_ascending, int list0_ascending, int list1_ascending) { int i = left, j = right; - VAPictureH264 tmp; + VAPictureHEVC tmp; - if (frame_idx) { - partition(ref, frame_idx, key, partition_ascending); + if (pic_order_cnt) { + partition(ref, pic_order_cnt, key, partition_ascending); } else { - partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending); + partition(ref, pic_order_cnt, (signed int)key, partition_ascending); } - sort_one(ref, left, i-1, list0_ascending, frame_idx); - sort_one(ref, j+1, right, list1_ascending, frame_idx); + sort_one(ref, left, i-1, list0_ascending, pic_order_cnt); + sort_one(ref, j+1, right, list1_ascending, pic_order_cnt); } static int update_ReferenceFrames(void) @@ -512,7 +668,7 @@ static int update_ReferenceFrames(void) if (current_frame_type == FRAME_B) return 0; - CurrentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE; + CurrentCurrPic.flags = 0;//VA_PICTURE_HEVC_LONG_TERM_REFERENCE; numShortTerm++; if (numShortTerm > num_ref_frames) numShortTerm = num_ref_frames; @@ -531,68 +687,80 @@ static int update_ReferenceFrames(void) static int update_RefPicList(void) { - unsigned int current_poc = CurrentCurrPic.TopFieldOrderCnt; - + unsigned int current_poc = CurrentCurrPic.pic_order_cnt; + int i = 0; + + /* Init reference frame list */ + for (i = 0; i < 15; i++) { + RefPicList0_P[i].picture_id = VA_INVALID_SURFACE; + RefPicList0_P[i].flags = VA_PICTURE_HEVC_INVALID; + RefPicList0_B[i].picture_id = VA_INVALID_SURFACE; + RefPicList0_B[i].flags = VA_PICTURE_HEVC_INVALID; + RefPicList1_B[i].picture_id = VA_INVALID_SURFACE; + RefPicList1_B[i].flags = VA_PICTURE_HEVC_INVALID; + } + if (current_frame_type == FRAME_P) { - memcpy(RefPicList0_P, ReferenceFrames, numShortTerm * sizeof(VAPictureH264)); + memcpy(RefPicList0_P, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC)); sort_one(RefPicList0_P, 0, numShortTerm-1, 0, 1); } if (current_frame_type == FRAME_B) { - memcpy(RefPicList0_B, ReferenceFrames, numShortTerm * sizeof(VAPictureH264)); - sort_two(RefPicList0_B, 0, numShortTerm-1, current_poc, 0, - 1, 0, 1); + memcpy(RefPicList0_B, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC)); + sort_two(RefPicList0_B, 0, numShortTerm-1, current_poc, 0, 1, 0, 1); - memcpy(RefPicList1_B, ReferenceFrames, numShortTerm * sizeof(VAPictureH264)); - sort_two(RefPicList1_B, 0, numShortTerm-1, current_poc, 0, - 0, 1, 0); + memcpy(RefPicList1_B, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC)); + sort_two(RefPicList1_B, 0, numShortTerm-1, current_poc, 0, 0, 1, 0); } - + return 0; } -static int render_sequence(rc_param_t *rc_param) +static int render_sequence(struct rc_param_t *rc_param) { VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2]; VAStatus va_status; VAEncMiscParameterBuffer *misc_param, *misc_param_tmp; VAEncMiscParameterRateControl *misc_rate_ctrl; - seq_param.general_profile_idc = 1 /* 1: main profile 2: main 10 profile*/; - seq_param.general_level_idc = 3 * 30 /* level 3 */ + seq_param.general_profile_idc = 1; /* 1: main profile 2: main 10 profile*/ + seq_param.general_level_idc = 51; /* level 3 */ seq_param.general_tier_flag = 0; seq_param.intra_period = intra_period; - seq_param.intra_idr_period = (intra_period == 0) ? 0 : (intra_idr_period / intra_period); - seq_param.ip_period = 1; + seq_param.intra_idr_period = intra_idr_period; //(intra_period == 0) ? 0 : (intra_idr_period / intra_period); + seq_param.ip_period = ip_period; //1; seq_param.bits_per_second = rc_param->bits_per_second; - - seq_param.picture_width_in_min_cu_minus1 = frame_width_mbaligned / 8; - seq_param.picture_height_in_min_cu_minus1 = frame_height_mbaligned / 8; - seq_param.seq_fields.chroma_format_idc = 1; /* 420 */ - seq_param.seq_fields.separate_colour_plane_flag = 0; - //seq_param.seq_fields.bit_depth_luma_minus8 = 0; - //seq_param.seq_fields.bit_depth_chroma_minus8 = 0; + seq_param.seq_fields.bits.chroma_format_idc = 1; /* 420 */ seq_param.log2_min_luma_coding_block_size_minus3 = 0; //min CU = 8; - seq_param.log2_max_luma_coding_block_size_minus3 = 3;//max CU = 64; + seq_param.log2_diff_max_min_luma_coding_block_size = 2; seq_param.log2_min_transform_block_size_minus2 = 0; - seq_param.log2_max_transform_block_size_minus2 = 3; - - seq_param.max_num_ref_frames = num_ref_frames; - seq_param.seq_fields.bits.frame_mbs_only_flag = 1; - seq_param.vui_time_scale = frame_rate * 2; - seq_param.vui_num_units_in_tick = 2; /* Tc = num_units_in_tick / time_sacle */ - - if (frame_width != frame_width_mbaligned || - frame_height != frame_height_mbaligned) { - seq_param.frame_cropping_flag = 1; - seq_param.frame_crop_left_offset = 0; - seq_param.frame_crop_right_offset = (frame_width_mbaligned - frame_width)/2; - seq_param.frame_crop_top_offset = 0; - seq_param.frame_crop_bottom_offset = (frame_height_mbaligned - frame_height)/2; - } + seq_param.log2_diff_max_min_transform_block_size = 3; + seq_param.max_transform_hierarchy_depth_inter = 2; + seq_param.max_transform_hierarchy_depth_intra= 2; + + seq_param.pic_width_in_luma_samples = ALIGN(frame_width, 16); //frame_width_mbaligned; + seq_param.pic_height_in_luma_samples = ALIGN(frame_height, 16); //frame_height_mbaligned; + seq_param.seq_fields.bits.separate_colour_plane_flag = 0; + seq_param.seq_fields.bits.bit_depth_luma_minus8 = 0; + seq_param.seq_fields.bits.bit_depth_chroma_minus8 = 0; + seq_param.seq_fields.bits.scaling_list_enabled_flag = 0; + seq_param.seq_fields.bits.strong_intra_smoothing_enabled_flag = 0; + seq_param.seq_fields.bits.amp_enabled_flag = 1; + seq_param.seq_fields.bits.sample_adaptive_offset_enabled_flag = 0; + seq_param.seq_fields.bits.pcm_enabled_flag = 0; + seq_param.seq_fields.bits.pcm_loop_filter_disabled_flag = 1; + seq_param.seq_fields.bits.sps_temporal_mvp_enabled_flag = 1; + seq_param.pcm_sample_bit_depth_luma_minus1 = 7; + seq_param.pcm_sample_bit_depth_chroma_minus1 = 7; + seq_param.log2_min_pcm_luma_coding_block_size_minus3 = 0; + seq_param.log2_max_pcm_luma_coding_block_size_minus3 = 0; + + seq_param.vui_time_scale = 0; + seq_param.vui_num_units_in_tick = 0; /* Tc = num_units_in_tick / time_sacle */ + va_status = vaCreateBuffer(va_dpy, context_id, VAEncSequenceParameterBufferType, sizeof(seq_param),1,&seq_param,&seq_param_buf); @@ -600,20 +768,6 @@ static int render_sequence(rc_param_t *rc_param) va_status = vaRenderPicture(va_dpy,context_id, &seq_param_buf, 1); CHECK_VASTATUS(va_status,"vaRenderPicture");; - - if (misc_priv_type != 0) { - va_status = vaCreateBuffer(va_dpy, context_id, - VAEncMiscParameterBufferType, - sizeof(VAEncMiscParameterBuffer), - 1, NULL, &misc_param_tmpbuf); - CHECK_VASTATUS(va_status,"vaCreateBuffer"); - vaMapBuffer(va_dpy, misc_param_tmpbuf,(void **)&misc_param_tmp); - misc_param_tmp->type = misc_priv_type; - misc_param_tmp->data[0] = misc_priv_value; - vaUnmapBuffer(va_dpy, misc_param_tmpbuf); - - va_status = vaRenderPicture(va_dpy,context_id, &misc_param_tmpbuf, 1); - } return va_status; } @@ -638,7 +792,9 @@ static int render_framerate() misc_param->type = VAEncMiscParameterTypeFrameRate; misc_frame_rate = (VAEncMiscParameterFrameRate *)misc_param->data; - misc_frame_rate->framerate = frame_rate; + /* If framerate=30, the coded data is very big. */ + /* Compare with mv_encode, which pass 3000 here */ + misc_frame_rate->framerate = frame_rate * 100; vaUnmapBuffer(va_dpy, frame_rate_param_buf); @@ -674,7 +830,7 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param) if (mask & RC_MASK_target_percentage) misc_rate_ctrl->target_percentage = rc_param->target_percentage; else - misc_rate_ctrl->target_percentage = 66; + misc_rate_ctrl->target_percentage = 95; if (mask & RC_MASK_window_size) misc_rate_ctrl->window_size = rc_param->window_size; @@ -684,7 +840,7 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param) if (mask & RC_MASK_initial_qp) misc_rate_ctrl->initial_qp = rc_param->initial_qp; else - misc_rate_ctrl->initial_qp = initial_qp; + misc_rate_ctrl->initial_qp = 28; // 28 for HEVC if (mask & RC_MASK_min_qp) misc_rate_ctrl->min_qp = rc_param->min_qp; @@ -706,6 +862,79 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param) return 0; } +static int render_roi(void) +{ + VAStatus va_status; + VABufferID misc_roi_buf_id = VA_INVALID_ID; + VAEncMiscParameterBuffer *misc_param; + VAEncMiscParameterBufferROI *misc_roi_param; + VAEncROI encroi; + + roi_rec_x = (!roi_rec_x)?frame_width / 3:roi_rec_x; + roi_rec_y = (!roi_rec_x)?frame_height / 3:roi_rec_y; + roi_rec_w = (!roi_rec_w)?frame_width / 3:roi_rec_w; + roi_rec_h = (!roi_rec_h)?frame_height / 3:roi_rec_h; + + va_status = vaCreateBuffer(va_dpy, context_id, + VAEncMiscParameterBufferType, + sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterBufferROI), + 1, + NULL, + &misc_roi_buf_id); + CHECK_VASTATUS(va_status, "vaCreateBuffer"); + + vaMapBuffer(va_dpy, + misc_roi_buf_id, + (void **)&misc_param); + + misc_param->type = VAEncMiscParameterTypeROI; + misc_roi_param = (VAEncMiscParameterBufferROI *)misc_param->data; + + misc_roi_param->num_roi = 1; + misc_roi_param->max_delta_qp = roi_maxqp; + misc_roi_param->min_delta_qp = roi_minqp; + + encroi.roi_rectangle.x = roi_rec_x; + encroi.roi_rectangle.y = roi_rec_y; + encroi.roi_rectangle.width = roi_rec_w; + encroi.roi_rectangle.height = roi_rec_h; + + encroi.roi_value = roi_value; + + misc_roi_param->roi = &encroi; + + vaUnmapBuffer(va_dpy, misc_roi_buf_id); + + va_status = vaRenderPicture(va_dpy, context_id, &misc_roi_buf_id, 1); + CHECK_VASTATUS(va_status,"vaRenderPicture"); + + if (buf_destroy) + destroy_vabuffers(va_dpy, 1, misc_roi_buf_id); + + return va_status; +} + +static int render_qualitylevel(void) +{ + VAStatus va_status; + VABufferID misc_param_tmpbuf; + VAEncMiscParameterBuffer *misc_param, *misc_param_tmp; + VAEncMiscParameterBufferQualityLevel *misc_quality_param; + + va_status = vaCreateBuffer(va_dpy, context_id, + VAEncMiscParameterBufferType, + sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterBufferQualityLevel), + 1, NULL, &misc_param_tmpbuf); + CHECK_VASTATUS(va_status,"vaCreateBuffer"); + vaMapBuffer(va_dpy, misc_param_tmpbuf,(void **)&misc_param_tmp); + misc_param_tmp->type = VAEncMiscParameterTypeQualityLevel; + misc_quality_param = (VAEncMiscParameterBufferQualityLevel *)misc_param_tmp->data; + misc_quality_param->quality_level = misc_tu_value; + vaUnmapBuffer(va_dpy, misc_param_tmpbuf); + va_status = vaRenderPicture(va_dpy,context_id, &misc_param_tmpbuf, 1); + + return va_status; +} static int calc_poc(int pic_order_cnt_lsb) { @@ -739,62 +968,53 @@ static int calc_poc(int pic_order_cnt_lsb) return TopFieldOrderCnt; } -static unsigned char get_va_frame_type(int frame_type) { - switch (frame_type) { - case FRAME_IDR: - case FRAME_I: - return 1; - case FRAME_P: - return 2; - case FRAME_B: - return 3; - default: - fprintf(stderr, "%s Invalid frame type:%d\n", __FUNCTION__, frame_type); - return 1; -} - static int render_picture(void) { VABufferID pic_param_buf; VAStatus va_status; int i = 0; - pic_param.CurrPic.picture_id = ref_surface[current_slot]; - pic_param.CurrPic.flags = 0; - pic_param.CurrPic.PicOrderCnt = calc_poc((current_frame_display - current_IDR_display) % MaxPicOrderCntLsb); - CurrentCurrPic = pic_param.CurrPic; + pic_param.decoded_curr_pic.picture_id = ref_surface[current_slot]; + pic_param.decoded_curr_pic.pic_order_cnt = current_frame_num; + pic_param.decoded_curr_pic.flags = 0; + + CurrentCurrPic = pic_param.decoded_curr_pic; if (getenv("TO_DEL")) { /* set RefPicList into ReferenceFrames */ update_RefPicList(); /* calc RefPicList */ - memset(pic_param.ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */ + memset(pic_param.reference_frames, 0xff, 15 * sizeof(VAPictureHEVC)); /* invalid all */ if (current_frame_type == FRAME_P) { - pic_param.ReferenceFrames[0] = RefPicList0_P[0]; + pic_param.reference_frames[0] = RefPicList0_P[0]; } else if (current_frame_type == FRAME_B) { - pic_param.ReferenceFrames[0] = RefPicList0_B[0]; - pic_param.ReferenceFrames[1] = RefPicList1_B[0]; + pic_param.reference_frames[0] = RefPicList0_B[0]; + pic_param.reference_frames[1] = RefPicList1_B[0]; } } else { if (hevc_autoref == 0) { - memcpy(pic_param.ReferenceFrames, ReferenceFrames, numShortTerm*sizeof(VAPictureH264)); - for (i = numShortTerm; i < surface_num; i++) { - pic_param.ReferenceFrames[i].picture_id = VA_INVALID_SURFACE; - pic_param.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID; + memcpy(pic_param.reference_frames, ReferenceFrames, numShortTerm*sizeof(VAPictureHEVC)); + for (i = numShortTerm; i < 15; i++) { + pic_param.reference_frames[i].picture_id = VA_INVALID_SURFACE; + pic_param.reference_frames[i].flags = VA_PICTURE_HEVC_INVALID; } } else { - for (i=0; i<surface_num; i++) { - pic_param.ReferenceFrames[i].picture_id = ref_surface[i]; - pic_param.ReferenceFrames[i].flags = 0; + for (i = 0; i < 15; i++) { + pic_param.reference_frames[i].picture_id = ref_surface[i]; + pic_param.reference_frames[i].flags = 0;//VA_PICTURE_HEVC_LONG_TERM_REFERENCE; } } } - + + unsigned char frame_type = get_va_frame_type(current_frame_type); + unsigned char coding_type = (frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type; + pic_param.pic_fields.bits.cu_qp_delta_enabled_flag = 1; + pic_param.pic_fields.bits.screen_content_flag = 1; + pic_param.pic_init_qp = 28; + pic_param.last_picture = (current_frame_encoding == frame_count); + pic_param.pic_fields.bits.reference_pic_flag = (current_frame_type != FRAME_B); + pic_param.pic_fields.bits.coding_type = coding_type; pic_param.pic_fields.bits.idr_pic_flag = (current_frame_type == FRAME_IDR); pic_param.pic_fields.bits.reference_pic_flag = (current_frame_type != FRAME_B); - pic_param.pic_fields.bits.transform_8x8_mode_flag = hevc_8x8_dct; pic_param.coded_buf = coded_buf[current_slot]; - pic_param.last_picture = (current_frame_encoding == frame_count); - pic_param.pic_init_qp = initial_qp; - pic_param.coding_type = get_va_frame_type(current_frame_type); va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferType, sizeof(pic_param),1,&pic_param, &pic_param_buf); @@ -881,6 +1101,81 @@ static int render_packedpicture(void) return 0; } +static int render_packedslice(void) +{ + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; + VABufferID packedslc_para_bufid, packedslc_data_bufid, render_id[2]; + unsigned int length_in_bits; + unsigned char *packedslc_buffer = NULL; + VAStatus va_status; + + length_in_bits = build_packed_slice_buffer(&packedslc_buffer); + packedheader_param_buffer.type = VAEncPackedHeaderSlice; + packedheader_param_buffer.bit_length = length_in_bits; + packedheader_param_buffer.has_emulation_bytes = 0; + + va_status = vaCreateBuffer(va_dpy, + context_id, + VAEncPackedHeaderParameterBufferType, + sizeof(packedheader_param_buffer), 1, &packedheader_param_buffer, + &packedslc_para_bufid); + CHECK_VASTATUS(va_status,"vaCreateBuffer"); + + va_status = vaCreateBuffer(va_dpy, + context_id, + VAEncPackedHeaderDataBufferType, + (length_in_bits + 7) / 8, 1, packedslc_buffer, + &packedslc_data_bufid); + CHECK_VASTATUS(va_status,"vaCreateBuffer"); + + render_id[0] = packedslc_para_bufid; + render_id[1] = packedslc_data_bufid; + va_status = vaRenderPicture(va_dpy,context_id, render_id, 2); + CHECK_VASTATUS(va_status,"vaRenderPicture"); + + free(packedslc_buffer); + + return 0; +} + +static int render_packedvps(void) +{ + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; + VABufferID packedvps_para_bufid, packedvps_data_bufid, render_id[2]; + unsigned int length_in_bits; + unsigned char *packedvps_buffer = NULL; + VAStatus va_status; + + length_in_bits = build_packed_vps_buffer(&packedvps_buffer); + packedheader_param_buffer.type = VAEncPackedHeaderSequence; + packedheader_param_buffer.bit_length = length_in_bits; + packedheader_param_buffer.has_emulation_bytes = 0; + + va_status = vaCreateBuffer(va_dpy, + context_id, + VAEncPackedHeaderParameterBufferType, + sizeof(packedheader_param_buffer), 1, &packedheader_param_buffer, + &packedvps_para_bufid); + CHECK_VASTATUS(va_status,"vaCreateBuffer"); + + va_status = vaCreateBuffer(va_dpy, + context_id, + VAEncPackedHeaderDataBufferType, + (length_in_bits + 7) / 8, 1, packedvps_buffer, + &packedvps_data_bufid); + CHECK_VASTATUS(va_status,"vaCreateBuffer"); + + render_id[0] = packedvps_para_bufid; + render_id[1] = packedvps_data_bufid; + va_status = vaRenderPicture(va_dpy,context_id, render_id, 2); + CHECK_VASTATUS(va_status,"vaRenderPicture"); + + free(packedvps_buffer); + + return 0; +} + + static void render_packedsei(void) { VAEncPackedHeaderParameterBuffer packed_header_param_buffer; @@ -912,7 +1207,7 @@ static void render_packedsei(void) &packed_sei_buffer); //offset_in_bytes = 0; - packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI; + packed_header_param_buffer.type = VAEncPackedHeaderHEVC_SEI; packed_header_param_buffer.bit_length = length_in_bits; packed_header_param_buffer.has_emulation_bytes = 0; @@ -1031,10 +1326,10 @@ static int render_hrd(void) misc_hrd_param->initial_buffer_fullness = misc_hrd_param->buffer_size * 0.875; } else { if (windows_size != 0) { - misc_hrd_param->buffer_size = (uint32_t)((bits_size * (uint64_t)windows_size) / 1000); + misc_hrd_param->buffer_size = 0; //(uint32_t)((bits_size * (uint64_t)windows_size) / 1000); } else misc_hrd_param->buffer_size = frame_bitrate; - misc_hrd_param->initial_buffer_fullness = misc_hrd_param->buffer_size * 0.875; + misc_hrd_param->initial_buffer_fullness = 0; //misc_hrd_param->buffer_size * 0.875; } vaUnmapBuffer(va_dpy, misc_parameter_hrd_buf_id); @@ -1047,73 +1342,88 @@ static int render_hrd(void) static int render_slice(void) { - VABufferID slice_param_buf; + VABufferID slice_param_buf_id = VA_INVALID_ID; VAStatus va_status; - VAEncSliceParameterBufferH264 *slice_param, *current_slice; + VAEncSliceParameterBufferHEVC *slice_param, *current_slice; int i, j, frame_slice_cc = frame_slice_count; int mb_rendered = 0; + slc_param.slice_beta_offset_div2 = 2; + slc_param.slice_fields.bits.slice_temporal_mvp_enabled_flag = 1; + slc_param.slice_fields.bits.collocated_from_l0_flag = 1; + slc_param.max_num_merge_cand = 5; + va_status = vaCreateBuffer(va_dpy, context_id, VAEncSliceParameterBufferType, - sizeof(VAEncSliceParameterBufferH264), frame_slice_count, NULL, &slice_param_buf); + sizeof(VAEncSliceParameterBufferHEVC), frame_slice_count, &slc_param, &slice_param_buf_id); CHECK_VASTATUS(va_status,"vaCreateBuffer"); - va_status = vaMapBuffer(va_dpy, slice_param_buf, + va_status = vaMapBuffer(va_dpy, slice_param_buf_id, (void **)&slice_param); CHECK_VASTATUS(va_status,"vaMapBuffer"); - memset((void *)slice_param, 0, sizeof(VAEncSliceParameterBufferH264) * frame_slice_count); - + update_RefPicList(); for (j = 0; j < frame_slice_cc; j++) { current_slice = slice_param + j; - current_slice->disable_deblocking_filter_idc = 1; - current_slice->macroblock_address = mb_rendered; + current_slice->slice_segment_address = mb_rendered; if (j == frame_slice_cc - 1) { - current_slice->num_macroblocks = (frame_width_mbaligned * frame_height_mbaligned) / (16 * 16) - mb_rendered; + // current_slice->num_ctu_in_slice = GET_CTU_NUM(frame_width_mbaligned, 32) * GET_CTU_NUM(frame_height_mbaligned, 32) - mb_rendered; + current_slice->num_ctu_in_slice = (frame_width_mbaligned * frame_height_mbaligned) / (32 * 32) - mb_rendered; } else { - current_slice->num_macroblocks = (frame_width_mbaligned * frame_slice_height) / (16 * 16); - mb_rendered += current_slice->num_macroblocks; + //current_slice->num_ctu_in_slice = GET_CTU_NUM(frame_width_mbaligned, 32) * GET_CTU_NUM(frame_height_mbaligned, 32); + current_slice->num_ctu_in_slice = (frame_width_mbaligned * frame_slice_height) / (32 * 32); + mb_rendered += current_slice->num_ctu_in_slice; } - current_slice->slice_type = (current_frame_type == FRAME_IDR)? 2 : current_frame_type; - if (current_frame_type == FRAME_IDR) { - if (current_frame_encoding != 0) - ++current_slice->idr_pic_id; + + current_slice->slice_type = (current_frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type; + if ((current_frame_type == FRAME_IDR) || (current_frame_type == FRAME_I)) { + /* Reset reference for IDR also */ + for (i = 0; i < 15; i++) { + current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; + current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; + } } else if (current_frame_type == FRAME_P) { int refpiclist0_max = hevc_maxref & 0xffff; - memcpy(current_slice->RefPicList0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureH264)); + //printf("refpiclist0_max %d\n", refpiclist0_max); + memcpy(current_slice->ref_pic_list0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureHEVC)); - for (i = refpiclist0_max; i < 32; i++) { - current_slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE; - current_slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + for (i = refpiclist0_max; i < 15; i++) { + current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; + } + + for (i = 0; i < 15; i++) { + current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; } } else if (current_frame_type == FRAME_B) { int refpiclist0_max = hevc_maxref & 0xffff; int refpiclist1_max = (hevc_maxref >> 16) & 0xffff; - memcpy(current_slice->RefPicList0, RefPicList0_B, refpiclist0_max*sizeof(VAPictureH264)); - for (i = refpiclist0_max; i < 32; i++) { - current_slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE; - current_slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID; + memcpy(current_slice->ref_pic_list0, RefPicList0_B, refpiclist0_max*sizeof(VAPictureHEVC)); + for (i = refpiclist0_max; i < 15; i++) { + current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID; } - memcpy(current_slice->RefPicList1, RefPicList1_B, refpiclist1_max*sizeof(VAPictureH264)); - for (i = refpiclist1_max; i < 32; i++) { - current_slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE; - current_slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID; + memcpy(current_slice->ref_pic_list1, RefPicList1_B, refpiclist1_max*sizeof(VAPictureHEVC)); + for (i = refpiclist1_max; i < 15; i++) { + current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE; + current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID; } } - current_slice->slice_alpha_c0_offset_div2 = 0; current_slice->slice_beta_offset_div2 = 0; - current_slice->direct_spatial_mv_pred_flag = 1; - current_slice->pic_order_cnt_lsb = (current_frame_display - current_IDR_display) % MaxPicOrderCntLsb; } - va_status = vaUnmapBuffer(va_dpy, slice_param_buf); + va_status = vaUnmapBuffer(va_dpy, slice_param_buf_id); CHECK_VASTATUS(va_status,"vaUnmapBuffer"); - va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf, 1); + va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf_id, 1); CHECK_VASTATUS(va_status,"vaRenderPicture"); + return 0; } @@ -1159,15 +1469,20 @@ static VAStatus hevc_render_frame(unsigned int mask, struct rc_param_t *rc_param numShortTerm = 0; current_frame_num = 0; current_IDR_display = current_frame_display; + frame_poc = 0; } if (current_frame_type == FRAME_IDR) { - render_framerate(); - render_sequence(rc_param); - render_picture(); if (hevc_packedheader) { + render_packedvps(); render_packedsequence(); render_packedpicture(); } + render_sequence(rc_param); + render_picture(); + render_hrd(); + render_rcparam(mask, rc_param); + render_framerate(); + render_qualitylevel(); if (rc_mode == VA_RC_CBR) { //render_packedsei(); render_hrd(); @@ -1181,20 +1496,23 @@ static VAStatus hevc_render_frame(unsigned int mask, struct rc_param_t *rc_param if (max_slice_size) { render_max_slice_size(); } + if (roi_enable) + render_roi(); } else { - //render_sequence(); + render_packedpicture(); + //render_sequence(rc_param); render_picture(); - //if (rc_mode == VA_RC_CBR) - // render_packedsei(); - //render_hrd(); + if (roi_enable) + render_roi(); } if (mask) render_rcparam(mask, rc_param); + render_packedslice(); render_slice(); - - update_ReferenceFrames(); - + + update_ReferenceFrames(); + return VA_STATUS_SUCCESS; } @@ -1207,14 +1525,15 @@ static VAStatus hevc_get_config(void) int support_encode = 0; VAStatus va_status; unsigned int i; + unsigned int rc_value = 0; if (va_profile_str) { if (strncmp(va_profile_str, "MP", 2) == 0) hevc_profile = VAProfileHEVCMain; - else if (strncmp(va_profile_str, "MP10", 2) == 0) + else if (strncmp(va_profile_str, "MP10", 4) == 0) hevc_profile = VAProfileHEVCMain10; } - + /* use the highest profile */ for (i = 0; i < sizeof(profile_list)/sizeof(profile_list[0]); i++) { if ((hevc_profile != -1) && hevc_profile != profile_list[i]) @@ -1223,7 +1542,8 @@ static VAStatus hevc_get_config(void) hevc_profile = profile_list[i]; vaQueryConfigEntrypoints(va_dpy, hevc_profile, entrypoints, &num_entrypoints); for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) { - if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice) { + printf("entrypoint support %d\n", entrypoints[slice_entrypoint]); + if (entrypoints[slice_entrypoint] == va_entrypoint) { support_encode = 1; break; } @@ -1296,12 +1616,39 @@ static VAStatus hevc_get_config(void) printf("Desired rc mode %s is not supported, exit\n", rc_to_string(rc_mode)); exit(1); } - + config_attrib[config_attrib_num].type = VAConfigAttribRateControl; - config_attrib[config_attrib_num].value = rc_mode; + if (rc_mode == VA_RC_CBR || rc_mode == VA_RC_VBR) + rc_value = VA_RC_MB | rc_mode; + else + rc_value = rc_mode; + config_attrib[config_attrib_num].value = rc_value; //rc_mode; config_attrib_num++; } + if (hevc_attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support %d slices\n", hevc_attrib[VAConfigAttribEncMaxSlices].value); + config_attrib[config_attrib_num].type = VAConfigAttribEncMaxSlices; + config_attrib[config_attrib_num].value = 256; + config_attrib_num++; + } + + if (hevc_attrib[VAConfigAttribEncSliceStructure].value != VA_ATTRIB_NOT_SUPPORTED) { + int tmp = hevc_attrib[VAConfigAttribEncSliceStructure].value; + + printf("Support VAConfigAttribEncSliceStructure\n"); + config_attrib[config_attrib_num].type = VAConfigAttribEncSliceStructure; + config_attrib[config_attrib_num].value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS; + config_attrib_num++; +#if 0 + if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS) + printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS\n"); + if (tmp & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) + printf("Support VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS\n"); + if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) + printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS\n"); +#endif + } if (hevc_attrib[VAConfigAttribEncPackedHeaders].value != VA_ATTRIB_NOT_SUPPORTED) { int tmp = hevc_attrib[VAConfigAttribEncPackedHeaders].value; @@ -1359,32 +1706,40 @@ static VAStatus hevc_get_config(void) printf("Support %d RefPicList0 and %d RefPicList1\n", hevc_maxref & 0xffff, (hevc_maxref >> 16) & 0xffff ); + config_attrib[config_attrib_num].type = VAConfigAttribEncMaxRefFrames; + config_attrib[config_attrib_num].value = hevc_maxref; + config_attrib_num++; } - if (hevc_attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED) - printf("Support %d slices\n", hevc_attrib[VAConfigAttribEncMaxSlices].value); - - if (hevc_attrib[VAConfigAttribEncSliceStructure].value != VA_ATTRIB_NOT_SUPPORTED) { - int tmp = hevc_attrib[VAConfigAttribEncSliceStructure].value; - - printf("Support VAConfigAttribEncSliceStructure\n"); + if (hevc_attrib[VAConfigAttribEncQualityRange].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support VAConfigAttribEncQualityRange\n"); + config_attrib[config_attrib_num].type = VAConfigAttribEncQualityRange; + config_attrib[config_attrib_num].value = 7; + config_attrib_num++; + } - if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS) - printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS\n"); - if (tmp & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) - printf("Support VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS\n"); - if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) - printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS\n"); + if (hevc_attrib[VAConfigAttribEncIntraRefresh].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support VAConfigAttribEncIntraRefresh\n"); + config_attrib[config_attrib_num].type = VAConfigAttribEncIntraRefresh; + config_attrib_num++; } - if (hevc_attrib[VAConfigAttribEncMacroblockInfo].value != VA_ATTRIB_NOT_SUPPORTED) { - printf("Support VAConfigAttribEncMacroblockInfo\n"); + if (hevc_attrib[VAConfigAttribEncROI].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support VAConfigAttribEncROI\n"); + config_attrib[config_attrib_num].type = VAConfigAttribEncROI; + config_attrib_num++; + } + + if (hevc_attrib[VAConfigAttribEncFunctionTypeIntel].value != VA_ATTRIB_NOT_SUPPORTED) { + printf("Support VAConfigAttribEncFunctionTypeIntel\n"); + config_attrib[config_attrib_num].type = VAConfigAttribEncFunctionTypeIntel; + config_attrib_num++; } if (hevc_attrib[VAConfigAttribEncAutoReference].value != VA_ATTRIB_NOT_SUPPORTED) { printf("Support VAConfigAttribEncAutoReference\n"); hevc_autoref = 1; } - + va_profile = hevc_profile; va_entrypoint = VAEntrypointEncSlice; @@ -1412,6 +1767,7 @@ static int hevc_save_codeddata(FILE *coded_fp, VACodedBufferSegment *buf_list, while (p != NULL) { *rec_surfaceid = ref_surface[p->reserved]; + coded_size += fwrite(p->buf, 1, p->size, coded_fp); p = (VACodedBufferSegment *) p->next; } |
