typedef struct
{
- GstVaapiEncoderProp id;
+ guint id;
GParamSpec *pspec;
GValue value;
} PropValue;
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)
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;
+}