diff --git a/src/gstducatih264enc.c b/src/gstducatih264enc.c
index 74b8e4ec7104d43615771a01c86e80066210bdf0..e094a1b10930889b04f7792b015b42d62e5966a2 100644 (file)
--- a/src/gstducatih264enc.c
+++ b/src/gstducatih264enc.c
#define DEFAULT_PROFILE GST_DUCATI_H264ENC_PROFILE_HIGH
#define DEFAULT_LEVEL GST_DUCATI_H264ENC_LEVEL_40
+#define DEFAULT_QPI 28
+#define DEFAULT_QP_MAX_I 36
+#define DEFAULT_QP_MIN_I 10
+/* 2 x targetBitRate for VBR Rate Control */
+#define DEFAULT_HRD_BUFFER_SIZE 40960000
+#define DEFAULT_INTER_INTERVAL 4
#define GST_TYPE_DUCATI_H264ENC_PROFILE (gst_ducati_h264enc_profile_get_type ())
#define GST_TYPE_DUCATI_H264ENC_LEVEL (gst_ducati_h264enc_level_get_type ())
+#define GST_TYPE_DUCATI_H264ENC_RCPP (gst_ducati_h264enc_get_rate_control_params_preset_type ())
+#define GST_TYPE_DUCATI_H264ENC_RATE_CONTROL_ALGO (gst_ducati_h264enc_get_rate_control_algo_type ())
+#define GST_TYPE_DUCATI_H264ENC_ENTROPY_CODING_MODE (gst_ducati_h264enc_get_entropy_coding_mode_type ())
+#define GST_TYPE_DUCATI_H264ENC_SLICE_MODE (gst_ducati_h264enc_get_slice_mode_type ())
enum
PROP_0,
PROP_PROFILE,
PROP_LEVEL,
+ PROP_RATE_CONTROL_PARAMS_PRESET,
+ PROP_RATE_CONTROL_ALGO,
+ PROP_QPI,
+ PROP_QP_MAX_I,
+ PROP_QP_MIN_I,
+ PROP_HRD_BUFFER_SIZE,
+ PROP_ENTROPY_CODING_MODE,
+ PROP_INTER_INTERVAL,
+ PROP_SLICE_MODE,
};
static void gst_ducati_h264enc_set_property (GObject * object, guint prop_id,
self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
gint outargs_sz);
static gboolean gst_ducati_h264enc_configure (GstDucatiVidEnc * self);
+static gboolean gst_ducati_h264enc_is_sync_point (GstDucatiVidEnc * enc,
+ int type);
static GstStaticPadTemplate gst_ducati_h264enc_sink_template =
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS
- ("video/x-h264, align=(string)au, stream-format=(string)byte-stream")
+ ("video/x-h264, alignment=(string)au, stream-format=(string)byte-stream")
);
GST_BOILERPLATE (GstDucatiH264Enc, gst_ducati_h264enc, GstDucatiVidEnc,
return type;
}
+static GType
+gst_ducati_h264enc_get_rate_control_params_preset_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GEnumValue vals[] = {
+ {IH264_RATECONTROLPARAMS_DEFAULT, "Rate Control params preset default",
+ "rate-control-params-preset-default"},
+ {IH264_RATECONTROLPARAMS_USERDEFINED, "User defined rate control",
+ "rate-control-params-preset-user-defined"},
+ {IH264_RATECONTROLPARAMS_EXISTING, "Existing rate control params",
+ "rate-control-params-preset-existing"},
+ {IH264_RATECONTROLPARAMS_MAX, "Max rate control",
+ "rate-control-params-preset-control"},
+ {0, NULL, NULL},
+ };
+
+ type = g_enum_register_static ("GstDucatiH264EncRateControlParams", vals);
+ }
+
+ return type;
+}
+
+static GType
+gst_ducati_h264enc_get_rate_control_algo_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GEnumValue vals[] = {
+ {IH264_RATECONTROL_PRC, "Perceptual rate control",
+ "perceptual-rate-control"},
+ {IH264_RATECONTROL_PRC_LOW_DELAY, "Low delay rate control",
+ "low-delay-rate-control"},
+ {IH264_RATECONTROL_DEFAULT, "Default rcAlgo (PRC)",
+ "default-rate-control"},
+ {0, NULL, NULL},
+ };
+
+ type = g_enum_register_static ("GstDucatiH264EncRateControlAlgo", vals);
+ }
+
+ return type;
+}
+
static GType
gst_ducati_h264enc_level_get_type (void)
{
return type;
}
+static GType
+gst_ducati_h264enc_get_entropy_coding_mode_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GEnumValue vals[] = {
+ {IH264_ENTROPYCODING_CAVLC, "CAVLC coding type", "cavlc"},
+ {IH264_ENTROPYCODING_DEFAULT, "Default coding type (cavlc)", "default"},
+ {IH264_ENTROPYCODING_CABAC, "Cabac coding mode", "cabac"},
+ {0, NULL, NULL},
+ };
+
+ type = g_enum_register_static ("GstDucatiEntropyCodingMode", vals);
+ }
+
+ return type;
+}
+
+static GType
+gst_ducati_h264enc_get_slice_mode_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GEnumValue vals[] = {
+ {IH264_SLICEMODE_NONE, "No slice mode", "none"},
+ {IH264_SLICEMODE_DEFAULT, "Default slice coding mode is MB based",
+ "default"},
+ {IH264_SLICEMODE_MBUNIT,
+ "Slices are controlled based upon number of Macroblocks", "mbunit"},
+ {IH264_SLICEMODE_BYTES,
+ "Slices are controlled based upon number of bytes", "bytes"},
+ {IH264_SLICEMODE_OFFSET,
+ "Slices are controlled based upon user defined offset unit of Row",
+ "offset"},
+ {0, NULL, NULL},
+ };
+
+ type = g_enum_register_static ("GstDucatiSliceMode", vals);
+ }
+
+ return type;
+}
+
static void
gst_ducati_h264enc_base_init (gpointer g_class)
{
videnc_class->allocate_params = gst_ducati_h264enc_allocate_params;
videnc_class->configure = gst_ducati_h264enc_configure;
+ videnc_class->is_sync_point = gst_ducati_h264enc_is_sync_point;
g_object_class_install_property (gobject_class, PROP_PROFILE,
g_param_spec_enum ("profile", "H.264 Profile", "H.264 Profile",
g_object_class_install_property (gobject_class, PROP_LEVEL,
g_param_spec_enum ("level", "H.264 Level", "H.264 Level",
GST_TYPE_DUCATI_H264ENC_LEVEL, DEFAULT_LEVEL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_INTER_INTERVAL,
+ g_param_spec_uint ("inter-interval", "Inter-frame interval",
+ "Max inter frame interval (B frames are allowed between them if > 1)",
+ 1, 31, DEFAULT_INTER_INTERVAL, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_RATE_CONTROL_PARAMS_PRESET,
+ g_param_spec_enum ("rate-control-params-preset",
+ "H.264 rate control params preset",
+ "This preset controls the USER_DEFINED versus "
+ "DEFAULT mode. If you are not aware about the "
+ "fields, it should be set as IH264_RATECONTROLPARAMS_DEFAULT",
+ GST_TYPE_DUCATI_H264ENC_RCPP, IH264_RATECONTROLPARAMS_DEFAULT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RATE_CONTROL_ALGO,
+ g_param_spec_enum ("rate-control-algo", "H.264 rate control algorithm",
+ "This defines the rate control algorithm to be used. Only useful if "
+ " 'rate-control-params-preset' is set as "
+ "'rate-control-params-preset-user-defined'",
+ GST_TYPE_DUCATI_H264ENC_RATE_CONTROL_ALGO, IH264_RATECONTROL_DEFAULT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_QPI,
+ g_param_spec_int ("qpi", "Initial quantization parameter",
+ "Initial quantization parameter for I/IDR frames.", -1, 51,
+ DEFAULT_QPI, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_QP_MIN_I,
+ g_param_spec_int ("qp-min-i", "Minimum quantization parameter",
+ "Minimum quantization parameter for I/IDR frames.", 0, 51,
+ DEFAULT_QP_MIN_I, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_QP_MAX_I,
+ g_param_spec_int ("qp-max-i", "Maximum quantization parameter",
+ "Maximum quantization parameter for I/IDR frames.", 0, 51,
+ DEFAULT_QP_MAX_I, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_HRD_BUFFER_SIZE,
+ g_param_spec_uint ("hrd-buffer-size",
+ "Hypothetical reference decoder buffer size",
+ "Hypothetical reference decoder buffer size. This "
+ "size controls the frame skip logic of the encoder. "
+ "For low delay applications this size should be "
+ "small. This size is in bits. Maximum Value is level "
+ "dependant and min value is 4096",
+ 4096, G_MAXUINT, DEFAULT_HRD_BUFFER_SIZE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_ENTROPY_CODING_MODE,
+ g_param_spec_enum ("entropy-coding-mode", "H.264 entropy coding mode",
+ "Controls the entropy coding type.",
+ GST_TYPE_DUCATI_H264ENC_ENTROPY_CODING_MODE,
+ IH264_ENTROPYCODING_DEFAULT, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_SLICE_MODE,
+ g_param_spec_enum ("slice-mode", "H.264 slice mode",
+ "This defines the control mechanism to split a picture in slices."
+ " It can be either MB based or bytes based",
+ GST_TYPE_DUCATI_H264ENC_SLICE_MODE,
+ IH264_SLICEMODE_DEFAULT, G_PARAM_READWRITE));
+
}
static void
@@ -218,6 +393,13 @@ gst_ducati_h264enc_init (GstDucatiH264Enc * self, GstDucatiH264EncClass * klass)
self->profile = DEFAULT_PROFILE;
self->level = DEFAULT_LEVEL;
+ self->rate_control_params_preset = IH264_RATECONTROLPARAMS_DEFAULT;
+ self->rate_control_algo = IH264_RATECONTROL_DEFAULT;
+ self->qpi = DEFAULT_QPI;
+ self->qp_min_i = DEFAULT_QP_MIN_I;
+ self->qp_max_i = DEFAULT_QP_MAX_I;
+ self->hrd_buffer_size = DEFAULT_HRD_BUFFER_SIZE;
+ self->inter_interval = DEFAULT_INTER_INTERVAL;
}
static void
const GValue * value, GParamSpec * pspec)
{
GstDucatiH264Enc *self = GST_DUCATIH264ENC (object);
+ GstDucatiVidEnc *venc = GST_DUCATIVIDENC (object);
+ IH264ENC_DynamicParams *dynParams =
+ (IH264ENC_DynamicParams *) venc->dynParams;
- g_return_if_fail (GST_IS_DUCATIH264ENC (object));
self = GST_DUCATIH264ENC (object);
switch (prop_id) {
case PROP_LEVEL:
self->level = g_value_get_enum (value);
break;
+ case PROP_RATE_CONTROL_PARAMS_PRESET:
+ self->rate_control_params_preset = g_value_get_enum (value);
+ if (dynParams)
+ dynParams->rateControlParams.rateControlParamsPreset =
+ self->rate_control_params_preset;
+ break;
+ case PROP_RATE_CONTROL_ALGO:
+ self->rate_control_algo = g_value_get_enum (value);
+
+ if (self->rate_control_params_preset !=
+ IH264_RATECONTROLPARAMS_USERDEFINED)
+ GST_INFO_OBJECT (self,
+ "Setting rcAlgo but rateControlParamsPreset not "
+ "'rate-control-params-preset-user-defined' config won't be taken "
+ "into account");
+
+ if (dynParams)
+ dynParams->rateControlParams.rcAlgo = self->rate_control_algo;
+ break;
+ case PROP_QPI:
+ self->qpi = g_value_get_int (value);
+ if (dynParams)
+ dynParams->rateControlParams.qpI = self->qpi;
+
+ break;
+ case PROP_QP_MIN_I:
+ self->qp_min_i = g_value_get_int (value);
+ if (dynParams)
+ dynParams->rateControlParams.qpMinI = self->qp_min_i;
+ break;
+ case PROP_QP_MAX_I:
+ self->qp_max_i = g_value_get_int (value);
+ if (dynParams)
+ dynParams->rateControlParams.qpMaxI = self->qp_max_i;
+ break;
+ case PROP_HRD_BUFFER_SIZE:
+ self->hrd_buffer_size = g_value_get_uint (value);
+ break;
+ case PROP_ENTROPY_CODING_MODE:
+ self->entropy_coding_mode = g_value_get_enum (value);
+ break;
+ case PROP_SLICE_MODE:
+ self->slice_mode = g_value_get_enum (value);
+ break;
+ case PROP_INTER_INTERVAL:
+ self->inter_interval = g_value_get_uint (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
case PROP_LEVEL:
g_value_set_enum (value, self->level);
break;
+ case PROP_RATE_CONTROL_PARAMS_PRESET:
+ g_value_set_enum (value, self->rate_control_params_preset);
+ break;
+ case PROP_RATE_CONTROL_ALGO:
+ g_value_set_enum (value, self->rate_control_algo);
+ break;
+ case PROP_QPI:
+ g_value_set_int (value, self->qpi);
+ break;
+ case PROP_QP_MIN_I:
+ g_value_set_int (value, self->qp_min_i);
+ break;
+ case PROP_QP_MAX_I:
+ g_value_set_int (value, self->qp_max_i);
+ break;
+ case PROP_HRD_BUFFER_SIZE:
+ g_value_set_uint (value, self->hrd_buffer_size);
+ break;
+ case PROP_ENTROPY_CODING_MODE:
+ g_value_set_enum (value, self->entropy_coding_mode);
+ break;
+ case PROP_SLICE_MODE:
+ g_value_set_enum (value, self->slice_mode);
+ break;
+ case PROP_INTER_INTERVAL:
+ g_value_set_uint (value, self->inter_interval);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
+static const char *
+get_profile_name (guint profile)
+{
+ switch (profile) {
+ case GST_DUCATI_H264ENC_PROFILE_BASELINE:
+ return "baseline";
+ case GST_DUCATI_H264ENC_PROFILE_MAIN:
+ return "main";
+ case GST_DUCATI_H264ENC_PROFILE_EXTENDED:
+ return "extended";
+ case GST_DUCATI_H264ENC_PROFILE_HIGH:
+ return "high";
+ case GST_DUCATI_H264ENC_PROFILE_HIGH_10:
+ return "high-10";
+ case GST_DUCATI_H264ENC_PROFILE_HIGH_422:
+ return "high-422";
+ default:
+ return NULL;
+ }
+}
+
+static const char *
+get_level_name (guint level)
+{
+ switch (level) {
+ case GST_DUCATI_H264ENC_LEVEL_10:
+ return "1";
+ case GST_DUCATI_H264ENC_LEVEL_1b:
+ return "1b";
+ case GST_DUCATI_H264ENC_LEVEL_11:
+ return "1.1";
+ case GST_DUCATI_H264ENC_LEVEL_12:
+ return "1.2";
+ case GST_DUCATI_H264ENC_LEVEL_13:
+ return "1.3";
+ case GST_DUCATI_H264ENC_LEVEL_20:
+ return "2";
+ case GST_DUCATI_H264ENC_LEVEL_21:
+ return "2.1";
+ case GST_DUCATI_H264ENC_LEVEL_22:
+ return "2.2";
+ case GST_DUCATI_H264ENC_LEVEL_30:
+ return "3";
+ case GST_DUCATI_H264ENC_LEVEL_31:
+ return "3.1";
+ case GST_DUCATI_H264ENC_LEVEL_32:
+ return "3.2";
+ case GST_DUCATI_H264ENC_LEVEL_40:
+ return "4";
+ case GST_DUCATI_H264ENC_LEVEL_41:
+ return "4.1";
+ case GST_DUCATI_H264ENC_LEVEL_42:
+ return "4.2";
+ case GST_DUCATI_H264ENC_LEVEL_50:
+ return "5";
+ case GST_DUCATI_H264ENC_LEVEL_51:
+ return "5.1";
+ default:
+ return NULL;
+ }
+}
+
static gboolean
gst_ducati_h264enc_configure (GstDucatiVidEnc * videnc)
{
GstDucatiH264Enc *self = GST_DUCATIH264ENC (videnc);
IH264ENC_Params *params;
+ IH264ENC_DynamicParams *dynParams;
gboolean ret;
+ const char *s;
videnc->params->profile = self->profile;
videnc->params->level = self->level;
params->maxIntraFrameInterval = 0x7fffffff;
params->IDRFrameInterval = 1;
params->numTemporalLayer = 1;
+ params->entropyCodingMode = self->entropy_coding_mode;
+ videnc->params->maxInterFrameInterval = self->inter_interval;
+
+ /* Dynamic params */
+ dynParams = (IH264ENC_DynamicParams *) videnc->dynParams;
+ dynParams->rateControlParams.rateControlParamsPreset =
+ self->rate_control_params_preset;
+ dynParams->rateControlParams.rcAlgo = self->rate_control_algo;
+ dynParams->rateControlParams.qpI = self->qpi;
+ dynParams->rateControlParams.qpMaxI = self->qp_max_i;
+ dynParams->rateControlParams.qpMinI = self->qp_min_i;
+ dynParams->rateControlParams.HRDBufferSize = self->hrd_buffer_size;
+ dynParams->sliceCodingParams.sliceMode = self->slice_mode;
ret = GST_DUCATIVIDENC_CLASS (parent_class)->configure (videnc);
if (ret) {
"stream-format", G_TYPE_STRING, "byte-stream",
"align", G_TYPE_STRING, "au",
NULL);
+ s = get_profile_name (self->profile);
+ if (s)
+ gst_caps_set_simple (caps, "profile", G_TYPE_STRING, s, NULL);
+ s = get_level_name (self->level);
+ if (s)
+ gst_caps_set_simple (caps, "level", G_TYPE_STRING, s, NULL);
ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (self), caps);
}
videnc, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz,
gint outargs_sz)
{
- return GST_DUCATIVIDENC_CLASS (parent_class)->allocate_params (videnc,
- sizeof (IH264ENC_Params), sizeof (IVIDENC2_DynamicParams),
+ gboolean ret = GST_DUCATIVIDENC_CLASS (parent_class)->allocate_params (videnc,
+ sizeof (IH264ENC_Params), sizeof (IH264ENC_DynamicParams),
sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs),
sizeof (IVIDENC2_OutArgs));
+
+ GstDucatiH264Enc *self = GST_DUCATIH264ENC (videnc);
+
+ if (ret == TRUE) {
+ IH264ENC_DynamicParams *dynParams =
+ (IH264ENC_DynamicParams *) videnc->dynParams;
+
+ dynParams->rateControlParams.rateControlParamsPreset =
+ self->rate_control_params_preset;
+ dynParams->rateControlParams.rcAlgo = self->rate_control_algo;
+ dynParams->rateControlParams.qpI = self->qpi;
+ dynParams->rateControlParams.qpMaxI = self->qp_max_i;
+ dynParams->rateControlParams.qpMinI = self->qp_min_i;
+ dynParams->rateControlParams.HRDBufferSize = self->hrd_buffer_size;
+ dynParams->sliceCodingParams.sliceMode = self->slice_mode;
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_ducati_h264enc_is_sync_point (GstDucatiVidEnc * enc, int type)
+{
+ return type == IVIDEO_IDR_FRAME;
}