mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
x264enc: Add option-string property
Adds support for an x264 format option-string to specify advanced parameters Addresses part of bug #607798
This commit is contained in:
parent
d462cdee4d
commit
f2be62695c
2 changed files with 87 additions and 1 deletions
|
@ -121,7 +121,8 @@ enum
|
|||
ARG_RC_MB_TREE,
|
||||
ARG_RC_LOOKAHEAD,
|
||||
ARG_NR,
|
||||
ARG_INTERLACED
|
||||
ARG_INTERLACED,
|
||||
ARG_OPTION_STRING
|
||||
};
|
||||
|
||||
#define ARG_THREADS_DEFAULT 1
|
||||
|
@ -159,6 +160,8 @@ enum
|
|||
#define ARG_RC_LOOKAHEAD_DEFAULT 40
|
||||
#define ARG_INTRA_REFRESH_DEFAULT FALSE
|
||||
|
||||
#define ARG_OPTION_STRING_DEFAULT ""
|
||||
|
||||
enum
|
||||
{
|
||||
GST_X264_ENC_PASS_CBR = 0,
|
||||
|
@ -318,6 +321,11 @@ gst_x264_enc_class_init (GstX264EncClass * klass)
|
|||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_x264_enc_change_state);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_OPTION_STRING,
|
||||
g_param_spec_string ("option-string", "Option string",
|
||||
"String of x264 options (overridden by element properties)",
|
||||
ARG_OPTION_STRING_DEFAULT, G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_THREADS,
|
||||
g_param_spec_uint ("threads", "Threads",
|
||||
"Number of threads used by the codec (0 for automatic)",
|
||||
|
@ -546,6 +554,7 @@ gst_x264_enc_init (GstX264Enc * encoder, GstX264EncClass * klass)
|
|||
encoder->rc_lookahead = ARG_RC_LOOKAHEAD_DEFAULT;
|
||||
encoder->noise_reduction = ARG_NR_DEFAULT;
|
||||
encoder->interlaced = ARG_INTERLACED_DEFAULT;
|
||||
encoder->option_string_prop = g_string_new (ARG_OPTION_STRING_DEFAULT);
|
||||
|
||||
/* resources */
|
||||
encoder->delay = g_queue_new ();
|
||||
|
@ -588,6 +597,14 @@ gst_x264_enc_finalize (GObject * object)
|
|||
{
|
||||
GstX264Enc *encoder = GST_X264_ENC (object);
|
||||
|
||||
#define FREE_STRING(ptr) \
|
||||
if (ptr) \
|
||||
ptr = (GString *)g_string_free (ptr, TRUE);
|
||||
|
||||
FREE_STRING (encoder->option_string_prop);
|
||||
|
||||
#undef FREE_STRING
|
||||
|
||||
g_free (encoder->mp_cache_file);
|
||||
encoder->mp_cache_file = NULL;
|
||||
g_free (encoder->buffer);
|
||||
|
@ -600,6 +617,54 @@ gst_x264_enc_finalize (GObject * object)
|
|||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/*
|
||||
* gst_x264_enc_parse_options
|
||||
* @encoder: Encoder to which options are assigned
|
||||
* @str: Option string
|
||||
*
|
||||
* Parse option string and assign to x264 parameters
|
||||
*
|
||||
*/
|
||||
static gboolean
|
||||
gst_x264_enc_parse_options (GstX264Enc * encoder, const gchar * str)
|
||||
{
|
||||
GStrv kvpairs;
|
||||
guint npairs, i;
|
||||
gint parse_result = 0, ret = 0;
|
||||
gchar *options = (gchar *) str;
|
||||
|
||||
while (*options == ':')
|
||||
options++;
|
||||
|
||||
kvpairs = g_strsplit (options, ":", 0);
|
||||
npairs = g_strv_length (kvpairs);
|
||||
|
||||
for (i = 0; i < npairs; i++) {
|
||||
GStrv key_val = g_strsplit (kvpairs[i], "=", 2);
|
||||
|
||||
parse_result =
|
||||
x264_param_parse (&encoder->x264param, key_val[0], key_val[1]);
|
||||
|
||||
if (parse_result == X264_PARAM_BAD_NAME) {
|
||||
GST_ERROR_OBJECT (encoder, "Bad name for option %s=%s",
|
||||
key_val[0] ? key_val[0] : "", key_val[1] ? key_val[1] : "");
|
||||
}
|
||||
if (parse_result == X264_PARAM_BAD_VALUE) {
|
||||
GST_ERROR_OBJECT (encoder,
|
||||
"Bad value for option %s=%s (Note: a NULL value for a non-boolean triggers this)",
|
||||
key_val[0] ? key_val[0] : "", key_val[1] ? key_val[1] : "");
|
||||
}
|
||||
|
||||
g_strfreev (key_val);
|
||||
|
||||
if (parse_result)
|
||||
ret++;
|
||||
}
|
||||
|
||||
g_strfreev (kvpairs);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* gst_x264_enc_init_encoder
|
||||
* @encoder: Encoder which should be initialized.
|
||||
|
@ -623,6 +688,16 @@ gst_x264_enc_init_encoder (GstX264Enc * encoder)
|
|||
encoder->x264param.b_sliced_threads = encoder->sliced_threads;
|
||||
encoder->x264param.i_sync_lookahead = encoder->sync_lookahead;
|
||||
#endif
|
||||
|
||||
/* apply user set properties */
|
||||
if (encoder->option_string_prop && encoder->option_string_prop->len
|
||||
&& gst_x264_enc_parse_options (encoder,
|
||||
encoder->option_string_prop->str) == FALSE) {
|
||||
GST_DEBUG_OBJECT (encoder, "Your option-string contains errors.");
|
||||
goto unlock_and_return;
|
||||
}
|
||||
|
||||
/* set up encoder parameters */
|
||||
encoder->x264param.i_fps_num = encoder->fps_num;
|
||||
encoder->x264param.i_fps_den = encoder->fps_den;
|
||||
encoder->x264param.i_width = encoder->width;
|
||||
|
@ -760,6 +835,10 @@ gst_x264_enc_init_encoder (GstX264Enc * encoder)
|
|||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
unlock_and_return:
|
||||
GST_OBJECT_UNLOCK (encoder);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* gst_x264_enc_close_encoder
|
||||
|
@ -1291,6 +1370,9 @@ gst_x264_enc_set_property (GObject * object, guint prop_id,
|
|||
goto wrong_state;
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_OPTION_STRING:
|
||||
g_string_assign (encoder->option_string_prop, g_value_get_string (value));
|
||||
break;
|
||||
case ARG_THREADS:
|
||||
encoder->threads = g_value_get_uint (value);
|
||||
break;
|
||||
|
@ -1518,6 +1600,9 @@ gst_x264_enc_get_property (GObject * object, guint prop_id,
|
|||
case ARG_INTERLACED:
|
||||
g_value_set_boolean (value, encoder->interlaced);
|
||||
break;
|
||||
case ARG_OPTION_STRING:
|
||||
g_value_set_string (value, encoder->option_string_prop->str);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
|
@ -87,6 +87,7 @@ struct _GstX264Enc
|
|||
gint rc_lookahead;
|
||||
guint noise_reduction;
|
||||
gboolean interlaced;
|
||||
GString *option_string_prop; /* option-string property */
|
||||
|
||||
/* input description */
|
||||
GstVideoFormat format;
|
||||
|
|
Loading…
Reference in a new issue