summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSreerenj Balachandran <sreerenj.balachandran@intel.com>2016-08-09 15:53:47 +0300
committerSreerenj Balachandran <sreerenj.balachandran@intel.com>2016-08-09 15:53:47 +0300
commite1a4f29a0487341f5c6841e31c286d9ba5e87a89 (patch)
treeaf188f7846a44a6ddcea4650c50c7af94acab2c0
parentf182b8be2ba05965e6d31a4d380d6563b9b53a77 (diff)
encoder: VP9: Add CBR encoding supportvp9_enc_cbr
https://bugzilla.gnome.org/show_bug.cgi?id=749950
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_vp9.c101
-rw-r--r--gst-libs/gst/vaapi/gstvaapiencoder_vp9.h4
2 files changed, 102 insertions, 3 deletions
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c
index 6006f682..01b0d6ed 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.c
@@ -39,7 +39,8 @@
/* Supported set of VA rate controls, within this implementation */
#define SUPPORTED_RATECONTROLS \
- (GST_VAAPI_RATECONTROL_MASK (CQP))
+ (GST_VAAPI_RATECONTROL_MASK (CQP) | \
+ GST_VAAPI_RATECONTROL_MASK (CBR))
/* Supported set of tuning options, within this implementation */
#define SUPPORTED_TUNE_OPTIONS \
@@ -56,6 +57,9 @@
#define MAX_FRAME_WIDTH 4096
#define MAX_FRAME_HEIGHT 4096
+/* Default CPB length (in milliseconds) */
+#define DEFAULT_CPB_LENGTH 1500
+
typedef enum
{
GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0 = 0,
@@ -101,8 +105,47 @@ struct _GstVaapiEncoderVP9
guint frame_num;
GstVaapiSurfaceProxy *ref_list[GST_VP9_REF_FRAMES]; /* reference list */
guint ref_list_idx; /* next free slot in ref_list */
+
+ /* Bitrate contral parameters, CPB = Coded Picture Buffer */
+ guint bitrate_bits; // bitrate (bits)
+ guint cpb_length; // length of CPB buffer (ms)
};
+/* Estimates a good enough bitrate if none was supplied */
+static void
+ensure_bitrate (GstVaapiEncoderVP9 * encoder)
+{
+ GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
+ guint bitrate;
+
+ switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
+ case GST_VAAPI_RATECONTROL_CBR:
+ case GST_VAAPI_RATECONTROL_VBR:
+ if (!base_encoder->bitrate) {
+ /* Fixme: Provide better estimation */
+ /* Using a 1/6 compression ratio */
+ /* 12 bits per pixel fro yuv420 */
+ base_encoder->bitrate =
+ (GST_VAAPI_ENCODER_WIDTH (encoder) *
+ GST_VAAPI_ENCODER_HEIGHT (encoder) * 12 / 6) *
+ GST_VAAPI_ENCODER_FPS_N (encoder) /
+ GST_VAAPI_ENCODER_FPS_D (encoder) / 1000;
+ GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
+ }
+
+ bitrate = (base_encoder->bitrate * 1000);
+ if (bitrate != encoder->bitrate_bits) {
+ GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
+ encoder->bitrate_bits = bitrate;
+ }
+
+ break;
+ default:
+ base_encoder->bitrate = 0;
+ break;
+ }
+}
+
/* Derives the profile that suits best to the configuration */
static GstVaapiEncoderStatus
ensure_profile (GstVaapiEncoderVP9 * encoder)
@@ -110,6 +153,9 @@ ensure_profile (GstVaapiEncoderVP9 * encoder)
/* Always start from "simple" profile for maximum compatibility */
encoder->profile = GST_VAAPI_PROFILE_VP9_0;
+ /* Ensure bitrate if not set already */
+ ensure_bitrate (encoder);
+
return GST_VAAPI_ENCODER_STATUS_SUCCESS;
}
@@ -183,6 +229,7 @@ fill_sequence (GstVaapiEncoderVP9 * encoder, GstVaapiEncSequence * sequence)
seq_param->kf_max_dist = base_encoder->keyframe_period;
seq_param->intra_period = base_encoder->keyframe_period;
+ seq_param->bits_per_second = encoder->bitrate_bits;
return TRUE;
}
@@ -212,6 +259,37 @@ error:
return FALSE;
}
+static gboolean
+ensure_misc_params (GstVaapiEncoderVP9 * encoder, GstVaapiEncPicture * picture)
+{
+ GstVaapiEncMiscParam *misc = NULL;
+ VAEncMiscParameterRateControl *rate_control;
+
+ /* RateControl params */
+ if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CBR ||
+ GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_VBR) {
+
+ misc = GST_VAAPI_ENC_MISC_PARAM_NEW (RateControl, encoder);
+ g_assert (misc);
+ if (!misc)
+ return FALSE;
+
+ rate_control = misc->data;
+ memset (rate_control, 0, sizeof (VAEncMiscParameterRateControl));
+ rate_control->bits_per_second = encoder->bitrate_bits;
+ rate_control->target_percentage = 70;
+ rate_control->window_size = encoder->cpb_length;
+ rate_control->initial_qp = encoder->yac_qi;
+ rate_control->min_qp = 1; /* Fixme: provide user control */
+ rate_control->basic_unit_size = 0;
+
+ gst_vaapi_enc_picture_add_misc_param (picture, misc);
+ gst_vaapi_codec_object_replace (&misc, NULL);
+ }
+
+ return TRUE;
+}
+
static void
get_ref_indices (guint ref_pic_mode, guint ref_list_idx, guint * last_idx,
guint * gf_idx, guint * arf_idx, guint8 * refresh_frame_flags)
@@ -356,6 +434,8 @@ gst_vaapi_encoder_vp9_encode (GstVaapiEncoder * base_encoder,
if (!ensure_sequence (encoder, picture))
goto error;
+ if (!ensure_misc_params (encoder, picture))
+ goto error;
if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
goto error;
if (!gst_vaapi_enc_picture_encode (picture))
@@ -432,10 +512,11 @@ gst_vaapi_encoder_vp9_init (GstVaapiEncoder * base_encoder)
encoder->loop_filter_level = DEFAULT_LOOP_FILTER_LEVEL;
encoder->sharpness_level = DEFAULT_SHARPNESS_LEVEL;
encoder->yac_qi = DEFAULT_YAC_QINDEX;
+ encoder->bitrate_bits = 0;
+ encoder->cpb_length = DEFAULT_CPB_LENGTH;
memset (encoder->ref_list, 0, G_N_ELEMENTS (encoder->ref_list));
encoder->ref_list_idx = 0;
-
return TRUE;
}
@@ -463,6 +544,9 @@ gst_vaapi_encoder_vp9_set_property (GstVaapiEncoder * base_encoder,
case GST_VAAPI_ENCODER_VP9_PROP_REF_PIC_MODE:
encoder->ref_pic_mode = g_value_get_enum (value);
break;
+ case GST_VAAPI_ENCODER_VP9_PROP_CPB_LENGTH:
+ encoder->cpb_length = g_value_get_uint (value);
+ break;
default:
return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
}
@@ -548,6 +632,19 @@ gst_vaapi_encoder_vp9_get_default_properties (void)
gst_vaapi_encoder_vp9_ref_pic_mode_type (),
GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_0,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstVaapiEncoderVP9:cpb-length:
+ *
+ * The size of the Coded Picture Buffer , which means
+ * the window size in milliseconds.
+ *
+ */
+ GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+ GST_VAAPI_ENCODER_VP9_PROP_CPB_LENGTH,
+ g_param_spec_uint ("cpb-length",
+ "CPB Length", "Length of the CPB_buffer/window_size in milliseconds",
+ 1, 10000, DEFAULT_CPB_LENGTH,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
return props;
diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.h b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.h
index 2ddcbd40..7967a980 100644
--- a/gst-libs/gst/vaapi/gstvaapiencoder_vp9.h
+++ b/gst-libs/gst/vaapi/gstvaapiencoder_vp9.h
@@ -38,6 +38,7 @@ typedef struct _GstVaapiEncoderVP9 GstVaapiEncoderVP9;
* @GST_VAAPI_ENCODER_VP9_PROP_LOOP_SHARPNESS_LEVEL: Sharpness Level(uint).
* @GST_VAAPI_ENCODER_VP9_PROP_YAC_Q_INDEX: Quantization table index for luma AC
* @GST_VAAPI_ENCODER_VP9_PROP_REF_PIC_MODE: Reference picute selection modes
+ * @GST_VAAPI_ENCODER_VP9_PROP_CPB_LENGTH:Length of CPB buffer in milliseconds
*
* The set of VP9 encoder specific configurable properties.
*/
@@ -45,7 +46,8 @@ typedef enum {
GST_VAAPI_ENCODER_VP9_PROP_LOOP_FILTER_LEVEL = -1,
GST_VAAPI_ENCODER_VP9_PROP_SHARPNESS_LEVEL = -2,
GST_VAAPI_ENCODER_VP9_PROP_YAC_Q_INDEX = -3,
- GST_VAAPI_ENCODER_VP9_PROP_REF_PIC_MODE = -4
+ GST_VAAPI_ENCODER_VP9_PROP_REF_PIC_MODE = -4,
+ GST_VAAPI_ENCODER_VP9_PROP_CPB_LENGTH = -5
} GstVaapiEncoderVP9Prop;
GstVaapiEncoder *