mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
gst: encode: add property help functions for encoder properties.
The encoder is a true gstobject now and all the properties are using gobject's properties mechanism. Add help functions to handle the properties between encode and encoder class. The basic idea is mapping the same property between encoder and encode. All the encoder's properties will have the same name, the same type in encode. The set/get property function just forward the property setting/getting to the encoder using the same property name and value. Because the encoder is created on needed, we need to cache the property setting in encode.
This commit is contained in:
parent
bc2f8fd19e
commit
05643dadb5
2 changed files with 212 additions and 2 deletions
|
@ -104,7 +104,7 @@ gst_vaapiencode_src_query (GstVideoEncoder * encoder, GstQuery * query)
|
|||
|
||||
typedef struct
|
||||
{
|
||||
GstVaapiEncoderProp id;
|
||||
guint id;
|
||||
GParamSpec *pspec;
|
||||
GValue value;
|
||||
} PropValue;
|
||||
|
@ -158,6 +158,47 @@ prop_value_lookup (GstVaapiEncode * encode, guint prop_id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static PropValue *
|
||||
prop_value_new_entry (guint id, GParamSpec * pspec, const GValue * value)
|
||||
{
|
||||
PropValue *prop_value;
|
||||
|
||||
if (!pspec)
|
||||
return NULL;
|
||||
|
||||
prop_value = g_slice_new0 (PropValue);
|
||||
if (!prop_value)
|
||||
return NULL;
|
||||
|
||||
prop_value->id = id;
|
||||
prop_value->pspec = g_param_spec_ref (pspec);
|
||||
g_value_init (&prop_value->value, pspec->value_type);
|
||||
|
||||
g_assert (g_value_type_compatible (pspec->value_type, G_VALUE_TYPE (value)));
|
||||
g_value_copy (value, &prop_value->value);
|
||||
|
||||
return prop_value;
|
||||
}
|
||||
|
||||
static inline PropValue *
|
||||
prop_value_lookup_entry (GPtrArray * prop_values, guint prop_id)
|
||||
{
|
||||
guint i;
|
||||
PropValue *prop_value;
|
||||
|
||||
if (prop_values == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < prop_values->len; i++) {
|
||||
prop_value = g_ptr_array_index (prop_values, i);
|
||||
if (prop_value->id == prop_id)
|
||||
return prop_value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_vaapiencode_default_get_property (GstVaapiEncode * encode, guint prop_id,
|
||||
GValue * value)
|
||||
|
@ -1007,3 +1048,157 @@ gst_vaapiencode_class_init_properties (GstVaapiEncodeClass * klass)
|
|||
g_ptr_array_unref (props);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Only used by the drived class */
|
||||
void
|
||||
gst_vaapiencode_set_property_subclass (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
|
||||
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (object);
|
||||
PropValue *prop_value;
|
||||
|
||||
if (prop_id <= PROP_BASE || prop_id >= encode_class->prop_num) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
return;
|
||||
}
|
||||
|
||||
/* direct forward the property to encoder */
|
||||
if (encode->encoder) {
|
||||
g_object_set_property ((GObject *) encode->encoder,
|
||||
g_param_spec_get_name (pspec), value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (encode->prop_values) {
|
||||
/* Delete the same prop already in cache */
|
||||
prop_value = prop_value_lookup_entry (encode->prop_values, prop_id);
|
||||
if (prop_value)
|
||||
g_ptr_array_remove (encode->prop_values, prop_value);
|
||||
} else {
|
||||
encode->prop_values =
|
||||
g_ptr_array_new_with_free_func ((GDestroyNotify) prop_value_free);
|
||||
}
|
||||
|
||||
/* The encoder is delay created, we need to cache the property setting */
|
||||
prop_value = prop_value_new_entry (prop_id, pspec, value);
|
||||
g_ptr_array_add (encode->prop_values, prop_value);
|
||||
}
|
||||
|
||||
/* Only used by the drived class */
|
||||
void
|
||||
gst_vaapiencode_get_property_subclass (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
|
||||
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (object);
|
||||
PropValue *prop_value = NULL;
|
||||
|
||||
if (prop_id <= PROP_BASE || prop_id >= encode_class->prop_num) {
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
return;
|
||||
}
|
||||
|
||||
/* direct forward the property to encoder */
|
||||
if (encode->encoder) {
|
||||
g_object_get_property ((GObject *) encode->encoder,
|
||||
g_param_spec_get_name (pspec), value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (encode->prop_values)
|
||||
prop_value = prop_value_lookup_entry (encode->prop_values, prop_id);
|
||||
|
||||
if (prop_value) {
|
||||
/* In the cache */
|
||||
g_value_copy (&prop_value->value, value);
|
||||
} else {
|
||||
/* set the default value */
|
||||
g_param_value_set_default (pspec, value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called by drived class to install all properties. The encode base class
|
||||
does not have any property, all the properties of the according encoderXXX
|
||||
class are installed to encodeXXX class. */
|
||||
gboolean
|
||||
gst_vaapiencode_class_install_properties (GstVaapiEncodeClass * klass,
|
||||
GObjectClass * encoder_class)
|
||||
{
|
||||
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
|
||||
guint i, n_props, installed;
|
||||
GParamSpec **specs = NULL;
|
||||
GParamSpec *pspec;
|
||||
GParamSpec *new_spec;
|
||||
GParamFlags flags;
|
||||
|
||||
if (encoder_class)
|
||||
specs = g_object_class_list_properties (encoder_class, &n_props);
|
||||
if (!specs)
|
||||
return FALSE;
|
||||
|
||||
installed = 0;
|
||||
for (i = 0; i < n_props; i++) {
|
||||
pspec = specs[i];
|
||||
|
||||
/* Encoder do not want to expose */
|
||||
if (!(pspec->flags & G_PARAM_FLAG_VAAPI_ENCODER_EXPOSURE))
|
||||
continue;
|
||||
/* Can only set on encoder init time */
|
||||
if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
|
||||
continue;
|
||||
|
||||
/* filter out the G_PARAM_CONSTRUCT, the encoder created later, no need
|
||||
to set the init value in encode.
|
||||
Also no G_PARAM_FLAG_VAAPI_ENCODER_EXPOSURE */
|
||||
flags = pspec->flags & (~(G_PARAM_FLAG_VAAPI_ENCODER_EXPOSURE |
|
||||
G_PARAM_CONSTRUCT));
|
||||
|
||||
if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) {
|
||||
GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec);
|
||||
new_spec = g_param_spec_uint (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec), g_param_spec_get_blurb (pspec),
|
||||
pspecuint->minimum, pspecuint->maximum,
|
||||
pspecuint->default_value, flags);
|
||||
} else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) {
|
||||
GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec);
|
||||
new_spec = g_param_spec_int (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec), g_param_spec_get_blurb (pspec),
|
||||
pspecint->minimum, pspecint->maximum, pspecint->default_value, flags);
|
||||
} else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
|
||||
GParamSpecEnum *pspecenum = G_PARAM_SPEC_ENUM (pspec);
|
||||
new_spec = g_param_spec_enum (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec),
|
||||
g_param_spec_get_blurb (pspec),
|
||||
pspec->value_type, pspecenum->default_value, flags);
|
||||
} else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
|
||||
GParamSpecBoolean *pspecbool = G_PARAM_SPEC_BOOLEAN (pspec);
|
||||
new_spec = g_param_spec_boolean (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec), g_param_spec_get_blurb (pspec),
|
||||
pspecbool->default_value, flags);
|
||||
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
|
||||
GParamSpecFlags *pspecflags = G_PARAM_SPEC_FLAGS (pspec);
|
||||
new_spec = g_param_spec_flags (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec), g_param_spec_get_blurb (pspec),
|
||||
pspec->value_type, pspecflags->default_value, flags);
|
||||
} else if (GST_IS_PARAM_SPEC_ARRAY_LIST (pspec)) {
|
||||
GstParamSpecArray *pspecarray = GST_PARAM_SPEC_ARRAY_LIST (pspec);
|
||||
new_spec = gst_param_spec_array (g_param_spec_get_name (pspec),
|
||||
g_param_spec_get_nick (pspec), g_param_spec_get_blurb (pspec),
|
||||
pspecarray->element_spec, flags);
|
||||
} else {
|
||||
GST_WARNING ("encoder's %s property has a unimplemented"
|
||||
" type to expose to encode, the encode may lose the %s property",
|
||||
g_param_spec_get_name (pspec), g_param_spec_get_name (pspec));
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_class_install_property (object_class, PROP_BASE + 1 + installed,
|
||||
new_spec);
|
||||
installed++;
|
||||
}
|
||||
|
||||
g_free (specs);
|
||||
klass->prop_num = PROP_BASE + 1 + installed;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ struct _GstVaapiEncodeClass
|
|||
/*< private >*/
|
||||
GstVaapiPluginBaseClass parent_class;
|
||||
|
||||
guint prop_num;
|
||||
GPtrArray * (*get_properties) (void);
|
||||
gboolean (*get_property) (GstVaapiEncode * encode,
|
||||
guint prop_id, GValue * value);
|
||||
|
@ -98,7 +99,6 @@ struct _GstVaapiEncodeClass
|
|||
GstVaapiCodedBufferProxy *proxy);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
GType
|
||||
|
@ -112,6 +112,21 @@ G_GNUC_INTERNAL
|
|||
gboolean
|
||||
gst_vaapiencode_class_init_properties (GstVaapiEncodeClass * encode_class);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void
|
||||
gst_vaapiencode_set_property_subclass (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
void
|
||||
gst_vaapiencode_get_property_subclass (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean
|
||||
gst_vaapiencode_class_install_properties (GstVaapiEncodeClass * klass,
|
||||
GObjectClass * encoder_class);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GST_VAAPIENCODE_H */
|
||||
|
|
Loading…
Reference in a new issue