encoder: add bitrate API.

Add gst_vaapi_encoder_set_bitrate() interface to allow the user control
the bitrate for encoding. Currently, changing this parameter is only
valid before the first frame is encoded. Should the value be modified
afterwards, then GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED is
returned.

https://bugzilla.gnome.org/show_bug.cgi?id=719529
This commit is contained in:
Gwenole Beauchesne 2014-01-06 18:01:33 +01:00
parent a24c52e4d0
commit 70b3600f11
10 changed files with 70 additions and 29 deletions

View file

@ -491,6 +491,39 @@ error_unsupported_rate_control:
}
}
/**
* gst_vaapi_encoder_set_bitrate:
* @encoder: a #GstVaapiEncoder
* @bitrate: the requested bitrate (in kbps)
*
* Notifies the @encoder to use the supplied @bitrate value.
*
* Note: currently, the bitrate can only be specified before the first
* frame is encoded. Afterwards, any change to this parameter is
* invalid and @GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED is
* returned.
*
* Return value: a #GstVaapiEncoderStatus
*/
GstVaapiEncoderStatus
gst_vaapi_encoder_set_bitrate (GstVaapiEncoder * encoder, guint bitrate)
{
g_return_val_if_fail (encoder != NULL, 0);
if (encoder->bitrate != bitrate && encoder->num_codedbuf_queued > 0)
goto error_operation_failed;
encoder->bitrate = bitrate;
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
/* ERRORS */
error_operation_failed:
{
GST_ERROR ("could not change bitrate value after encoding started");
return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
}
}
/* Base encoder initialization (internal) */
static gboolean
gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)

View file

@ -90,6 +90,9 @@ GstVaapiEncoderStatus
gst_vaapi_encoder_set_rate_control (GstVaapiEncoder * encoder,
GstVaapiRateControl rate_control);
GstVaapiEncoderStatus
gst_vaapi_encoder_set_bitrate (GstVaapiEncoder * encoder, guint bitrate);
GstVaapiEncoderStatus
gst_vaapi_encoder_put_frame (GstVaapiEncoder * encoder,
GstVideoCodecFrame * frame);

View file

@ -852,6 +852,7 @@ static gboolean
fill_va_sequence_param (GstVaapiEncoderH264 * encoder,
GstVaapiEncSequence * sequence)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
VAEncSequenceParameterBufferH264 *seq = sequence->param;
guint width_in_mbs, height_in_mbs;
@ -863,8 +864,8 @@ fill_va_sequence_param (GstVaapiEncoderH264 * encoder,
seq->level_idc = encoder->level;
seq->intra_period = encoder->intra_period;
seq->ip_period = 0; // ?
if (encoder->bitrate > 0)
seq->bits_per_second = encoder->bitrate * 1024;
if (base_encoder->bitrate > 0)
seq->bits_per_second = base_encoder->bitrate * 1024;
else
seq->bits_per_second = 0;
@ -912,12 +913,12 @@ fill_va_sequence_param (GstVaapiEncoderH264 * encoder,
}
/*vui not set */
seq->vui_parameters_present_flag = (encoder->bitrate > 0 ? TRUE : FALSE);
seq->vui_parameters_present_flag = (base_encoder->bitrate > 0 ? TRUE : FALSE);
if (seq->vui_parameters_present_flag) {
seq->vui_fields.bits.aspect_ratio_info_present_flag = FALSE;
seq->vui_fields.bits.bitstream_restriction_flag = FALSE;
seq->vui_fields.bits.timing_info_present_flag =
(encoder->bitrate > 0 ? TRUE : FALSE);
(base_encoder->bitrate > 0 ? TRUE : FALSE);
if (seq->vui_fields.bits.timing_info_present_flag) {
seq->num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
seq->time_scale = GST_VAAPI_ENCODER_FPS_N (encoder) * 2;
@ -1209,6 +1210,7 @@ ensure_slices (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
static gboolean
ensure_misc (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
GstVaapiEncMiscParam *misc = NULL;
VAEncMiscParameterHRD *hrd;
VAEncMiscParameterRateControl *rate_control;
@ -1220,9 +1222,9 @@ ensure_misc (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
return FALSE;
gst_vaapi_enc_picture_add_misc_buffer (picture, misc);
hrd = misc->impl;
if (encoder->bitrate > 0) {
hrd->initial_buffer_fullness = encoder->bitrate * 1024 * 4;
hrd->buffer_size = encoder->bitrate * 1024 * 8;
if (base_encoder->bitrate > 0) {
hrd->initial_buffer_fullness = base_encoder->bitrate * 1024 * 4;
hrd->buffer_size = base_encoder->bitrate * 1024 * 8;
} else {
hrd->initial_buffer_fullness = 0;
hrd->buffer_size = 0;
@ -1239,8 +1241,8 @@ ensure_misc (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
gst_vaapi_enc_picture_add_misc_buffer (picture, misc);
rate_control = misc->impl;
memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
if (encoder->bitrate)
rate_control->bits_per_second = encoder->bitrate * 1024;
if (base_encoder->bitrate)
rate_control->bits_per_second = base_encoder->bitrate * 1024;
else
rate_control->bits_per_second = 0;
rate_control->target_percentage = 70;
@ -1257,6 +1259,7 @@ ensure_misc (GstVaapiEncoderH264 * encoder, GstVaapiEncPicture * picture)
gboolean
init_encoder_public_attributes (GstVaapiEncoderH264 * encoder)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
guint width_mbs, height_mbs, total_mbs;
if (!GST_VAAPI_ENCODER_WIDTH (encoder) ||
@ -1298,13 +1301,13 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder)
GST_VAAPI_RATECONTROL_VBR == GST_VAAPI_ENCODER_RATE_CONTROL (encoder) ||
GST_VAAPI_RATECONTROL_VBR_CONSTRAINED ==
GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
if (!encoder->bitrate)
encoder->bitrate = GST_VAAPI_ENCODER_WIDTH (encoder) *
if (!base_encoder->bitrate)
base_encoder->bitrate = GST_VAAPI_ENCODER_WIDTH (encoder) *
GST_VAAPI_ENCODER_HEIGHT (encoder) *
GST_VAAPI_ENCODER_FPS_N (encoder) /
GST_VAAPI_ENCODER_FPS_D (encoder) / 4 / 1024;
} else
encoder->bitrate = 0;
base_encoder->bitrate = 0;
if (!encoder->slice_num)
encoder->slice_num = GST_VAAPI_ENCODER_H264_DEFAULT_SLICE_NUM;
@ -1706,7 +1709,6 @@ gst_vaapi_encoder_h264_init (GstVaapiEncoder * base)
/* init attributes */
encoder->profile = 0;
encoder->level = 0;
encoder->bitrate = 0;
encoder->idr_period = 0;
encoder->intra_period = 0;
encoder->init_qp = -1;

View file

@ -70,7 +70,6 @@ struct _GstVaapiEncoderH264
/* public */
guint32 profile;
guint32 level;
guint32 bitrate; /*kbps */
guint32 intra_period;
guint32 idr_period;
guint32 init_qp; /*default 24 */

View file

@ -105,6 +105,8 @@ ensure_sampling_desity (GstVaapiEncoderMpeg2 * encoder)
static gboolean
ensure_public_attributes (GstVaapiEncoderMpeg2 * encoder)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
if (!GST_VAAPI_ENCODER_WIDTH (encoder) ||
!GST_VAAPI_ENCODER_HEIGHT (encoder) ||
!GST_VAAPI_ENCODER_FPS_N (encoder) ||
@ -128,13 +130,13 @@ ensure_public_attributes (GstVaapiEncoderMpeg2 * encoder)
/* default compress ratio 1: (4*8*1.5) */
if (GST_VAAPI_RATECONTROL_CBR == GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
if (!encoder->bitrate)
encoder->bitrate = GST_VAAPI_ENCODER_WIDTH (encoder) *
if (!base_encoder->bitrate)
base_encoder->bitrate = GST_VAAPI_ENCODER_WIDTH (encoder) *
GST_VAAPI_ENCODER_HEIGHT (encoder) *
GST_VAAPI_ENCODER_FPS_N (encoder) /
GST_VAAPI_ENCODER_FPS_D (encoder) / 4 / 1024;
} else
encoder->bitrate = 0;
base_encoder->bitrate = 0;
return TRUE;
}
@ -176,6 +178,7 @@ make_profile_and_level_indication (guint32 profile, guint32 level)
static gboolean
fill_sequence (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncSequence * sequence)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
VAEncSequenceParameterBufferMPEG2 *seq = sequence->param;
memset (seq, 0, sizeof (VAEncSequenceParameterBufferMPEG2));
@ -185,8 +188,8 @@ fill_sequence (GstVaapiEncoderMpeg2 * encoder, GstVaapiEncSequence * sequence)
seq->picture_width = GST_VAAPI_ENCODER_WIDTH (encoder);
seq->picture_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
if (encoder->bitrate > 0)
seq->bits_per_second = encoder->bitrate * 1024;
if (base_encoder->bitrate > 0)
seq->bits_per_second = base_encoder->bitrate * 1024;
else
seq->bits_per_second = 0;
@ -418,6 +421,7 @@ static gboolean
set_misc_parameters (GstVaapiEncoderMpeg2 * encoder,
GstVaapiEncPicture * picture)
{
GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
GstVaapiEncMiscParam *misc = NULL;
VAEncMiscParameterHRD *hrd;
VAEncMiscParameterRateControl *rate_control;
@ -429,9 +433,9 @@ set_misc_parameters (GstVaapiEncoderMpeg2 * encoder,
return FALSE;
gst_vaapi_enc_picture_add_misc_buffer (picture, misc);
hrd = misc->impl;
if (encoder->bitrate > 0) {
hrd->initial_buffer_fullness = encoder->bitrate * 1024 * 4;
hrd->buffer_size = encoder->bitrate * 1024 * 8;
if (base_encoder->bitrate > 0) {
hrd->initial_buffer_fullness = base_encoder->bitrate * 1024 * 4;
hrd->buffer_size = base_encoder->bitrate * 1024 * 8;
} else {
hrd->initial_buffer_fullness = 0;
hrd->buffer_size = 0;
@ -447,8 +451,8 @@ set_misc_parameters (GstVaapiEncoderMpeg2 * encoder,
gst_vaapi_enc_picture_add_misc_buffer (picture, misc);
rate_control = misc->impl;
memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
if (encoder->bitrate)
rate_control->bits_per_second = encoder->bitrate * 1024;
if (base_encoder->bitrate)
rate_control->bits_per_second = base_encoder->bitrate * 1024;
else
rate_control->bits_per_second = 0;
rate_control->target_percentage = 70;

View file

@ -80,7 +80,6 @@ struct _GstVaapiEncoderMpeg2
/* public */
guint32 profile;
guint32 level;
guint32 bitrate; /*kbps */
guint32 cqp;
guint32 intra_period;
guint32 ip_period;

View file

@ -98,6 +98,7 @@ struct _GstVaapiEncoder
GstVideoInfo video_info;
GstVaapiRateControl rate_control;
guint32 rate_control_mask;
guint bitrate; /* kbps */
GMutex mutex;
GCond surface_free;

View file

@ -318,6 +318,10 @@ ensure_encoder (GstVaapiEncode * encode)
encode->rate_control);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
status = gst_vaapi_encoder_set_bitrate (encode->encoder, encode->bitrate);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
return TRUE;
}

View file

@ -162,7 +162,6 @@ gst_vaapiencode_h264_create_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
{
GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (base);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (base);
GstVaapiEncoder *base_encoder;
GstVaapiEncoderH264 *encoder;
@ -173,7 +172,6 @@ gst_vaapiencode_h264_create_encoder (GstVaapiEncode * base,
encoder->profile = GST_VAAPI_PROFILE_UNKNOWN;
encoder->level = GST_VAAPI_ENCODER_H264_DEFAULT_LEVEL;
encoder->bitrate = base_encode->bitrate;
encoder->intra_period = encode->intra_period;
encoder->init_qp = encode->init_qp;
encoder->min_qp = encode->min_qp;

View file

@ -153,7 +153,6 @@ gst_vaapiencode_mpeg2_create_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
{
GstVaapiEncodeMpeg2 *const encode = GST_VAAPIENCODE_MPEG2_CAST (base);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (base);
GstVaapiEncoder *base_encoder;
GstVaapiEncoderMpeg2 *encoder;
@ -164,7 +163,6 @@ gst_vaapiencode_mpeg2_create_encoder (GstVaapiEncode * base,
encoder->profile = GST_VAAPI_ENCODER_MPEG2_DEFAULT_PROFILE;
encoder->level = GST_VAAPI_ENCODER_MPEG2_DEFAULT_LEVEL;
encoder->bitrate = base_encode->bitrate;
encoder->cqp = encode->quantizer;
encoder->intra_period = encode->intra_period;
encoder->ip_period = encode->ip_period;