VABufferID seq_param_id;
VABufferID pic_param_id;
VABufferID slice_param_id;
+ VABufferID misc_param_hdr_id;
VABufferID packed_seq_param_id;
VABufferID packed_seq_data_id;
VABufferID packed_pic_param_id;
encoder->init_qp = H264_DEFAULT_INIT_QP;
}
if (-1 == encoder->min_qp) {
- encoder->min_qp = H264_DEFAULT_MIN_QP;
+ if (GST_VAAPI_RATECONTROL_CQP == ENCODER_RATE_CONTROL(encoder))
+ encoder->min_qp = encoder->init_qp;
+ else
+ encoder->min_qp = H264_DEFAULT_MIN_QP;
}
if (encoder->min_qp > encoder->init_qp) {
}
/* default compress ratio 1: (4*8*1.5) */
- if (!encoder->bitrate) {
- encoder->bitrate = 0; //ENCODER_WIDTH(encoder)*ENCODER_HEIGHT(encoder)*ENCODER_FPS(encoder)/4;
- }
+ if (GST_VAAPI_RATECONTROL_CBR == ENCODER_RATE_CONTROL(encoder) ||
+ GST_VAAPI_RATECONTROL_VBR == ENCODER_RATE_CONTROL(encoder) ||
+ GST_VAAPI_RATECONTROL_VBR_CONSTRAINED == ENCODER_RATE_CONTROL(encoder))
+ {
+ if (!encoder->bitrate)
+ encoder->bitrate = ENCODER_WIDTH(encoder) *
+ ENCODER_HEIGHT(encoder) *
+ ENCODER_FPS(encoder) / 4 / 1024;
+ } else
+ encoder->bitrate = 0;
if (!encoder->slice_num) {
encoder->slice_num = H264_DEFAULT_SLICE_NUM;
va_status = vaDestroyBuffer(va_dpy, priv->slice_param_id);
priv->slice_param_id = VA_INVALID_ID;
}
+ if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+ va_status = vaDestroyBuffer(va_dpy, priv->misc_param_hdr_id);
+ priv->misc_param_hdr_id = VA_INVALID_ID;
+ }
if (VA_INVALID_ID != priv->packed_seq_param_id) {
va_status = vaDestroyBuffer(va_dpy, priv->packed_seq_param_id);
seq_param->picture_width_in_mbs = (ENCODER_WIDTH(encoder)+15)/16;
seq_param->picture_height_in_mbs = (ENCODER_HEIGHT(encoder)+15)/16;
- seq_param->bits_per_second = encoder->bitrate;
+ seq_param->bits_per_second = encoder->bitrate * 1024;
seq_param->frame_rate = ENCODER_FPS(encoder);
seq_param->initial_qp = encoder->init_qp; /*qp_value; 15, 24, 26?*/
seq_param->min_qp = encoder->min_qp; /*1, 6, 10*/
seq_param->intra_period = encoder->intra_period;
seq_param->ip_period = 0; // ?
if (encoder->bitrate> 0)
- seq_param->bits_per_second = encoder->bitrate; /* use kbps as input */
+ seq_param->bits_per_second = encoder->bitrate * 1024;
else
seq_param->bits_per_second = 0;
#endif
/*vui not set*/
- seq_param->vui_parameters_present_flag = FALSE;
+ seq_param->vui_parameters_present_flag = (encoder->bitrate> 0 ? TRUE : FALSE);
+ if (seq_param->vui_parameters_present_flag) {
+ seq_param->vui_fields.bits.aspect_ratio_info_present_flag = FALSE;
+ seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
+ seq_param->vui_fields.bits.timing_info_present_flag = (encoder->bitrate> 0 ? TRUE : FALSE);
+ if (seq_param->vui_fields.bits.timing_info_present_flag) {
+ seq_param->num_units_in_tick = 100;
+ seq_param->time_scale = ENCODER_FPS(encoder)*2*100;
+ }
+ }
return TRUE;
}
pic_param->frame_num = (priv->cur_slice_type == SLICE_TYPE_B ?
(priv->cur_decode_num + 1) : priv->cur_decode_num);
//pic_param.coding_type = 0;
- pic_param->pic_init_qp = (encoder->init_qp >= 0 ? encoder->init_qp : 26);
+ pic_param->pic_init_qp = encoder->init_qp;
pic_param->num_ref_idx_l0_active_minus1 = 0; /* only 1 reference */
pic_param->num_ref_idx_l1_active_minus1 = 0; /* B frames only have 1 backward and 1 forward reference*/
pic_param->chroma_qp_index_offset = 0;
memset(slice_param->chroma_offset_l1, 0, sizeof(slice_param->chroma_offset_l1));
slice_param->cabac_init_idc = 0;
- slice_param->slice_qp_delta = 0;
+ slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
+ if (slice_param->slice_qp_delta > 4)
+ slice_param->slice_qp_delta = 4;
slice_param->disable_deblocking_filter_idc = 0;
slice_param->slice_alpha_c0_offset_div2 = 2;
slice_param->slice_beta_offset_div2 = 2;
return TRUE;
}
+static gboolean
+h264_fill_hdr_buffer(GstVaapiEncoderH264 *encoder)
+{
+ GstVaapiEncoderH264Private *priv = encoder->priv;
+ VAEncMiscParameterBuffer *misc_param;
+ VAEncMiscParameterHRD *misc_hrd_param;
+ VADisplay va_dpy = ENCODER_VA_DISPLAY(encoder);
+ VAContextID context_id = ENCODER_VA_CONTEXT(encoder);
+ gboolean ret = TRUE;
+ VAStatus va_status = VA_STATUS_SUCCESS;
+
+ if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+ vaDestroyBuffer(va_dpy, priv->misc_param_hdr_id);
+ priv->misc_param_hdr_id = VA_INVALID_ID;
+ }
+
+ /* hrd parameter */
+ va_status = vaCreateBuffer(
+ va_dpy,
+ context_id,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterRateControl),
+ 1,
+ NULL,
+ &priv->misc_param_hdr_id);
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+ FALSE,
+ "vaCreateEncMiscParameterBuffer failed");
+
+ va_status = vaMapBuffer(va_dpy,
+ priv->misc_param_hdr_id,
+ (void **)&misc_param);
+ ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+ FALSE,
+ "H264 HDR buffer map failed");
+ misc_param->type = VAEncMiscParameterTypeHRD;
+ misc_hrd_param = (VAEncMiscParameterHRD *)misc_param->data;
+
+ if (encoder->bitrate > 0) {
+ misc_hrd_param->initial_buffer_fullness = encoder->bitrate * 1024 * 4;
+ misc_hrd_param->buffer_size = encoder->bitrate * 1024 * 8;
+ } else {
+ misc_hrd_param->initial_buffer_fullness = 0;
+ misc_hrd_param->buffer_size = 0;
+ }
+
+ vaUnmapBuffer(va_dpy, priv->misc_param_hdr_id);
+
+end:
+ return ret;
+}
#endif
static gboolean
ENCODER_CHECK_STATUS(is_params_ok,
ENCODER_PARAMETER_ERR,
"h264_recreate_pic_param failed");
+
+#if !HAVE_OLD_H264_ENCODER
+ /* set misc_hdr_parameters*/
+ is_params_ok = h264_fill_hdr_buffer(encoder);
+ ENCODER_CHECK_STATUS(is_params_ok,
+ ENCODER_PARAMETER_ERR,
+ "h264_fill_hdr__param failed");
+#endif
+
/* set slice parameters, support multiple slices */
is_params_ok = h264_fill_slice_buffers(encoder);
ENCODER_CHECK_STATUS(is_params_ok,
if (VA_INVALID_ID != priv->pic_param_id) {
va_buffers[va_buffers_count++] = priv->pic_param_id;
}
+ if (VA_INVALID_ID != priv->misc_param_hdr_id) {
+ va_buffers[va_buffers_count++] = priv->misc_param_hdr_id;
+ }
if (VA_INVALID_ID != priv->slice_param_id) {
va_buffers[va_buffers_count++] = priv->slice_param_id;
}
priv->seq_param_id = VA_INVALID_ID;
priv->pic_param_id = VA_INVALID_ID;
priv->slice_param_id = VA_INVALID_ID;
+ priv->misc_param_hdr_id = VA_INVALID_ID;
priv->packed_seq_param_id = VA_INVALID_ID;
priv->packed_seq_data_id = VA_INVALID_ID;
priv->packed_pic_param_id = VA_INVALID_ID;
guint32 constraint_set0_flag, constraint_set1_flag;
guint32 constraint_set2_flag, constraint_set3_flag;
guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
+ gboolean nal_hrd_parameters_present_flag;
guint32 b_qpprime_y_zero_transform_bypass = 0;
guint32 residual_color_transform_flag = 0;
/* frame_crop_bottom_offset */
h264_bitstream_write_ue(bitstream, seq->frame_crop_bottom_offset);
}
- ENCODER_ASSERT(seq->vui_parameters_present_flag == FALSE);
/* vui_parameters_present_flag */
h264_bitstream_write_uint(bitstream, seq->vui_parameters_present_flag, 1);
if (seq->vui_parameters_present_flag) {
- /*FIXME, to write vui parameters*/
+ /* aspect_ratio_info_present_flag */
+ h264_bitstream_write_uint(bitstream,
+ seq->vui_fields.bits.aspect_ratio_info_present_flag,
+ 1);
+ if (seq->vui_fields.bits.aspect_ratio_info_present_flag) {
+ h264_bitstream_write_uint(bitstream, seq->aspect_ratio_idc, 8);
+ if (seq->aspect_ratio_idc == 0xFF) {
+ h264_bitstream_write_uint(bitstream, seq->sar_width, 16);
+ h264_bitstream_write_uint(bitstream, seq->sar_height, 16);
+ }
+ }
+
+ /* overscan_info_present_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+ /* video_signal_type_present_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+ /* chroma_loc_info_present_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+
+ /* timing_info_present_flag */
+ h264_bitstream_write_uint(bitstream,
+ seq->vui_fields.bits.timing_info_present_flag,
+ 1);
+ if (seq->vui_fields.bits.timing_info_present_flag) {
+ h264_bitstream_write_uint(bitstream, seq->num_units_in_tick, 32);
+ h264_bitstream_write_uint(bitstream, seq->time_scale, 32);
+ h264_bitstream_write_uint(bitstream, 1, 1); /* fixed_frame_rate_flag */
+ }
+
+ nal_hrd_parameters_present_flag = (seq->bits_per_second > 0 ? TRUE : FALSE);
+ /* nal_hrd_parameters_present_flag */
+ h264_bitstream_write_uint(bitstream, nal_hrd_parameters_present_flag, 1);
+ if (nal_hrd_parameters_present_flag) {
+ /* hrd_parameters */
+ /* cpb_cnt_minus1 */
+ h264_bitstream_write_ue(bitstream, 0);
+ h264_bitstream_write_uint(bitstream, 4, 4); /* bit_rate_scale */
+ h264_bitstream_write_uint(bitstream, 6, 4); /* cpb_size_scale */
+
+ for (i = 0; i < 1; ++i) {
+ /* bit_rate_value_minus1[0] */
+ h264_bitstream_write_ue(bitstream, seq->bits_per_second/1024- 1);
+ /* cpb_size_value_minus1[0] */
+ h264_bitstream_write_ue(bitstream, seq->bits_per_second/1024*8 - 1);
+ /* cbr_flag[0] */
+ h264_bitstream_write_uint(bitstream, 1, 1);
+ }
+ /* initial_cpb_removal_delay_length_minus1 */
+ h264_bitstream_write_uint(bitstream, 23, 5);
+ /* cpb_removal_delay_length_minus1 */
+ h264_bitstream_write_uint(bitstream, 23, 5);
+ /* dpb_output_delay_length_minus1 */
+ h264_bitstream_write_uint(bitstream, 23, 5);
+ /* time_offset_length */
+ h264_bitstream_write_uint(bitstream, 23, 5);
+ }
+ /* vcl_hrd_parameters_present_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+ if (nal_hrd_parameters_present_flag || 0/*vcl_hrd_parameters_present_flag*/) {
+ /* low_delay_hrd_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+ }
+ /* pic_struct_present_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
+ /* bitstream_restriction_flag */
+ h264_bitstream_write_uint(bitstream, 0, 1);
}
/* rbsp_trailing_bits */
h264_bitstream_write_trailing_bits(bitstream);