diff --git a/gst-libs/gst/vaapi/gstvaapiencoder.c b/gst-libs/gst/vaapi/gstvaapiencoder.c index f222361211..1a99147185 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder.c +++ b/gst-libs/gst/vaapi/gstvaapiencoder.c @@ -115,6 +115,8 @@ gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass) const GstVaapiEncoderClassData *const cdata = klass->class_data; GPtrArray *props = NULL; + g_assert (cdata->rate_control_get_type != NULL); + /** * GstVaapiEncoder:rate-control: * @@ -124,7 +126,7 @@ gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass) GST_VAAPI_ENCODER_PROP_RATECONTROL, g_param_spec_enum ("rate-control", "Rate Control", "Rate control mode", - GST_VAAPI_TYPE_RATE_CONTROL, cdata->default_rate_control, + cdata->rate_control_get_type (), cdata->default_rate_control, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** diff --git a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h index d473a0508a..81549d58cf 100644 --- a/gst-libs/gst/vaapi/gstvaapiencoder_priv.h +++ b/gst-libs/gst/vaapi/gstvaapiencoder_priv.h @@ -27,6 +27,7 @@ #include #include #include +#include G_BEGIN_DECLS @@ -197,13 +198,21 @@ struct _GstVaapiEncoderClassData /*< private >*/ GstVaapiCodec codec; + GType (*rate_control_get_type)(void); GstVaapiRateControl default_rate_control; guint32 rate_control_mask; }; #define GST_VAAPI_ENCODER_DEFINE_CLASS_DATA(CODEC) \ + GST_VAAPI_TYPE_DEFINE_ENUM_SUBSET_FROM_MASK( \ + G_PASTE (GstVaapiRateControl, CODEC), \ + G_PASTE (gst_vaapi_rate_control_, CODEC), \ + GST_VAAPI_TYPE_RATE_CONTROL, SUPPORTED_RATECONTROLS); \ + \ static const GstVaapiEncoderClassData g_class_data = { \ .codec = G_PASTE (GST_VAAPI_CODEC_, CODEC), \ + .rate_control_get_type = \ + G_PASTE (G_PASTE (gst_vaapi_rate_control_, CODEC), _get_type), \ .default_rate_control = DEFAULT_RATECONTROL, \ .rate_control_mask = SUPPORTED_RATECONTROLS, \ } diff --git a/gst-libs/gst/vaapi/gstvaapivalue.c b/gst-libs/gst/vaapi/gstvaapivalue.c index 2f4c239b27..07d99233b4 100644 --- a/gst-libs/gst/vaapi/gstvaapivalue.c +++ b/gst-libs/gst/vaapi/gstvaapivalue.c @@ -150,3 +150,54 @@ gst_vaapi_rate_control_get_type(void) } return g_type; } + +static gboolean +build_enum_subset_values_from_mask (GstVaapiEnumSubset *subset, guint32 mask) +{ + GEnumClass *enum_class; + const GEnumValue *value; + guint i, n; + + enum_class = g_type_class_ref(subset->parent_type); + if (!enum_class) + return FALSE; + + for (i = 0, n = 0; i < 32 && n < subset->num_values; i++) { + if (!(mask & (1U << i))) + continue; + value = g_enum_get_value(enum_class, i); + if (!value) + continue; + subset->values[n++] = *value; + } + g_type_class_unref(enum_class); + if (n != subset->num_values - 1) + goto error_invalid_num_values; + return TRUE; + + /* ERRORS */ +error_invalid_num_values: + { + g_error("invalid number of static values for `%s'", subset->type_name); + return FALSE; + } +} + +GType +gst_vaapi_type_define_enum_subset_from_mask(GstVaapiEnumSubset *subset, + guint32 mask) +{ + if (g_once_init_enter(&subset->type)) { + GType type; + + build_enum_subset_values_from_mask(subset, mask); + memset(&subset->type_info, 0, sizeof(subset->type_info)); + g_enum_complete_type_info(subset->parent_type, &subset->type_info, + subset->values); + + type = g_type_register_static (G_TYPE_ENUM, subset->type_name, + &subset->type_info, 0); + g_once_init_leave(&subset->type, type); + } + return subset->type; +} diff --git a/gst-libs/gst/vaapi/gstvaapivalue.h b/gst-libs/gst/vaapi/gstvaapivalue.h index 4c4d7982d9..2f6f431b54 100644 --- a/gst-libs/gst/vaapi/gstvaapivalue.h +++ b/gst-libs/gst/vaapi/gstvaapivalue.h @@ -92,6 +92,71 @@ gst_vaapi_rotation_get_type(void) G_GNUC_CONST; GType gst_vaapi_rate_control_get_type(void) G_GNUC_CONST; +/** + * GST_VAAPI_POPCOUNT32: + * @x: the value from which to compute population count + * + * Computes the number of bits set in the supplied 32-bit value @x. + * + * Return value: the number of bits set in @x + */ +#define GST_VAAPI_POPCOUNT32(x) \ + GST_VAAPI_POPCOUNT32_0(x) +#define GST_VAAPI_POPCOUNT32_0(x) \ + GST_VAAPI_POPCOUNT32_1((x) - (((x) >> 1) & 0x55555555)) +#define GST_VAAPI_POPCOUNT32_1(x) \ + GST_VAAPI_POPCOUNT32_2(((x) & 0x33333333) + (((x) >> 2) & 0x33333333)) +#define GST_VAAPI_POPCOUNT32_2(x) \ + GST_VAAPI_POPCOUNT32_3((x) + ((x) >> 4)) +#define GST_VAAPI_POPCOUNT32_3(x) \ + GST_VAAPI_POPCOUNT32_4((x) & 0x0f0f0f0f) +#define GST_VAAPI_POPCOUNT32_4(x) \ + (((x) * 0x01010101) >> 24) + +/* --- GstVaapiEnumSubset --- */ + +/** + * GstVaapiEnumSubset: + * @name: name of the enum subset + * @parent_type: parent enum type + * @type: registered #GType + * @type_info: #GTypeInfo used to build the @type + * @values: pointer to a static array of #GEnumValue elements + * @num_values: number of elements in the @values array, including the + * terminator + * + * Structure that holds the required information to build a GEnum + * subset from the supplied @parent_type, i.e. a subset of its values. + */ +typedef struct { + GType parent_type; + GType type; + GTypeInfo type_info; + const gchar *type_name; + GEnumValue *values; + guint num_values; +} GstVaapiEnumSubset; + +G_GNUC_INTERNAL +GType +gst_vaapi_type_define_enum_subset_from_mask(GstVaapiEnumSubset *subset, + guint32 mask); + +#define GST_VAAPI_TYPE_DEFINE_ENUM_SUBSET_FROM_MASK(NAME, name, TYPE, MASK) \ +static GType \ +G_PASTE(name,_get_type)(void) \ +{ \ + static GEnumValue enum_values[GST_VAAPI_POPCOUNT32(MASK) + 1]; \ + static GstVaapiEnumSubset subset = { \ + .type_name = G_STRINGIFY(NAME), \ + .values = enum_values, \ + .num_values = G_N_ELEMENTS(enum_values), \ + }; \ + if (g_once_init_enter(&subset.parent_type)) \ + g_once_init_leave(&subset.parent_type, TYPE); \ + return gst_vaapi_type_define_enum_subset_from_mask(&subset, MASK); \ +} + G_END_DECLS #endif /* GST_VAAPI_VALUE_H */