summaryrefslogtreecommitdiff
path: root/vaenc/hevcencode.c
diff options
context:
space:
mode:
Diffstat (limited to 'vaenc/hevcencode.c')
-rw-r--r--vaenc/hevcencode.c920
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;
}