From 44945ac9eb7cc468640d358e3018504a4585b6fd Mon Sep 17 00:00:00 2001 From: Gwenole Beauchesne Date: Fri, 30 Nov 2012 17:25:07 +0100 Subject: [PATCH] Add GstVaapiMiniObject. Introduce a new reference counted object that is very lightweight and also provides flags and user-data functionalities. Initialization and finalization times are reduced by up to a factor 5x vs GstMiniObject from GStreamer 0.10 stack. This is a libgstvaapi internal object. --- gst-libs/gst/vaapi/Makefile.am | 2 + gst-libs/gst/vaapi/gstvaapiminiobject.c | 253 ++++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapiminiobject.h | 155 +++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 gst-libs/gst/vaapi/gstvaapiminiobject.c create mode 100644 gst-libs/gst/vaapi/gstvaapiminiobject.h diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am index 8eb2235f4c..fe1e44bb55 100644 --- a/gst-libs/gst/vaapi/Makefile.am +++ b/gst-libs/gst/vaapi/Makefile.am @@ -55,6 +55,7 @@ libgstvaapi_source_c = \ gstvaapiimage.c \ gstvaapiimageformat.c \ gstvaapiimagepool.c \ + gstvaapiminiobject.c \ gstvaapiobject.c \ gstvaapiparamspecs.c \ gstvaapiprofile.c \ @@ -105,6 +106,7 @@ libgstvaapi_source_priv_h = \ gstvaapidecoder_objects.h \ gstvaapidecoder_priv.h \ gstvaapidisplay_priv.h \ + gstvaapiminiobject.h \ gstvaapiobject_priv.h \ gstvaapisurface_priv.h \ gstvaapiutils.h \ diff --git a/gst-libs/gst/vaapi/gstvaapiminiobject.c b/gst-libs/gst/vaapi/gstvaapiminiobject.c new file mode 100644 index 0000000000..039f2058b1 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiminiobject.c @@ -0,0 +1,253 @@ +/* + * gstvaapiminiobject.c - A lightweight reference counted object + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include "gstvaapiminiobject.h" + +typedef struct _GstVaapiMiniObjectBase GstVaapiMiniObjectBase; +struct _GstVaapiMiniObjectBase { + gconstpointer object_class; + gint ref_count; + GDestroyNotify user_data_destroy_notify; +}; + +static inline GstVaapiMiniObjectBase * +object2base(GstVaapiMiniObject *object) +{ + return GUINT_TO_POINTER(GPOINTER_TO_UINT(object) - + sizeof(GstVaapiMiniObjectBase)); +} + +static inline GstVaapiMiniObject * +base2object(GstVaapiMiniObjectBase *base_object) +{ + return GUINT_TO_POINTER(GPOINTER_TO_UINT(base_object) + + sizeof(GstVaapiMiniObjectBase)); +} + +static void +gst_vaapi_mini_object_free(GstVaapiMiniObject *object) +{ + GstVaapiMiniObjectBase * const base_object = object2base(object); + const GstVaapiMiniObjectClass * const klass = base_object->object_class; + + g_atomic_int_inc(&base_object->ref_count); + + if (klass->finalize) + klass->finalize(object); + + if (G_LIKELY(g_atomic_int_dec_and_test(&base_object->ref_count))) { + if (object->user_data && base_object->user_data_destroy_notify) + base_object->user_data_destroy_notify(object->user_data); + g_slice_free1(sizeof(*base_object) + klass->size, base_object); + } +} + +const GstVaapiMiniObjectClass * +gst_vaapi_mini_object_get_class(GstVaapiMiniObject *object) +{ + g_return_val_if_fail(object != NULL, NULL); + + return object2base(object)->object_class; +} + +/** + * gst_vaapi_mini_object_new: + * @object_class: (optional): The object class + * + * Creates a new #GstVaapiMiniObject. If @object_class is NULL, then the + * size of the allocated object is the same as sizeof(GstVaapiMiniObject). + * If @object_class is not NULL, typically when a sub-class is implemented, + * that pointer shall reference a statically allocated descriptor. + * + * This function does *not* zero-initialize the derived object data, + * use gst_vaapi_mini_object_new0() to fill this purpose. + * + * Returns: The newly allocated #GstVaapiMiniObject + */ +GstVaapiMiniObject * +gst_vaapi_mini_object_new(const GstVaapiMiniObjectClass *object_class) +{ + GstVaapiMiniObject *object; + GstVaapiMiniObjectBase *base_object; + + static const GstVaapiMiniObjectClass default_object_class = { + .size = sizeof(GstVaapiMiniObject), + }; + + if (!object_class) + object_class = &default_object_class; + + g_return_val_if_fail(object_class->size >= sizeof(*object), NULL); + + base_object = g_slice_alloc(sizeof(*base_object) + object_class->size); + if (!base_object) + return NULL; + + object = base2object(base_object); + object->flags = 0; + object->user_data = 0; + + base_object->object_class = object_class; + base_object->ref_count = 1; + base_object->user_data_destroy_notify = NULL; + return object; +} + +/** + * gst_vaapi_mini_object_new0: + * @object_class: (optional): The object class + * + * Creates a new #GstVaapiMiniObject. This function is similar to + * gst_vaapi_mini_object_new() but derived object data is initialized + * to zeroes. + * + * Returns: The newly allocated #GstVaapiMiniObject + */ +GstVaapiMiniObject * +gst_vaapi_mini_object_new0(const GstVaapiMiniObjectClass *object_class) +{ + GstVaapiMiniObject *object; + guint sub_size; + + object = gst_vaapi_mini_object_new(object_class); + if (!object) + return NULL; + + object_class = object2base(object)->object_class; + + sub_size = object_class->size - sizeof(*object); + if (sub_size > 0) + memset(((guchar *)object) + sizeof(*object), 0, sub_size); + return object; +} + +/** + * gst_vaapi_mini_object_ref: + * @object: a #GstVaapiMiniObject + * + * Atomically increases the reference count of the given @object by one. + * + * Returns: The same @object argument + */ +GstVaapiMiniObject * +gst_vaapi_mini_object_ref(GstVaapiMiniObject *object) +{ + g_return_val_if_fail(object != NULL, NULL); + + g_atomic_int_inc(&object2base(object)->ref_count); + return object; +} + +/** + * gst_vaapi_mini_object_unref: + * @object: a #GstVaapiMiniObject + * + * Atomically decreases the reference count of the @object by one. If + * the reference count reaches zero, the object will be free'd. + */ +void +gst_vaapi_mini_object_unref(GstVaapiMiniObject *object) +{ + g_return_if_fail(object != NULL); + g_return_if_fail(object2base(object)->ref_count > 0); + + if (g_atomic_int_dec_and_test(&object2base(object)->ref_count)) + gst_vaapi_mini_object_free(object); +} + +/** + * gst_vaapi_mini_object_replace: + * @old_object_ptr: a pointer to a #GstVaapiMiniObject + * @new_object: a #GstVaapiMiniObject + * + * Atomically replaces the object held in @old_object_ptr with + * @new_object. This means that @old_object_ptr shall reference a + * valid object. However, @new_object can be NULL. + */ +void +gst_vaapi_mini_object_replace(GstVaapiMiniObject **old_object_ptr, + GstVaapiMiniObject *new_object) +{ + GstVaapiMiniObject *old_object; + + g_return_if_fail(old_object_ptr != NULL); + + old_object = g_atomic_pointer_get((gpointer *)old_object_ptr); + + if (old_object == new_object) + return; + + if (new_object) + gst_vaapi_mini_object_ref(new_object); + + while (!g_atomic_pointer_compare_and_exchange((gpointer *)old_object_ptr, + old_object, new_object)) + old_object = g_atomic_pointer_get((gpointer *)old_object_ptr); + + if (old_object) + gst_vaapi_mini_object_unref(old_object); +} + +/** + * gst_vaapi_mini_object_get_user_data: + * @object: a #GstVaapiMiniObject + * + * Gets user-provided data set on the object via a previous call to + * gst_vaapi_mini_object_set_user_data(). + * + * Returns: (transfer none): The previously set user_data + */ +gpointer +gst_vaapi_mini_object_get_user_data(GstVaapiMiniObject *object) +{ + g_return_val_if_fail(object != NULL, NULL); + + return object->user_data; +} + +/** + * gst_vaapi_mini_object_set_user_data: + * @object: a #GstVaapiMiniObject + * @user_data: user-provided data + * @destroy_notify: (closure user_data): a #GDestroyNotify + * + * Sets @user_data on the object and the #GDestroyNotify that will be + * called when the data is freed. + * + * If some @user_data was previously set, then the former @destroy_notify + * function will be called before the @user_data is replaced. + */ +void +gst_vaapi_mini_object_set_user_data(GstVaapiMiniObject *object, + gpointer user_data, GDestroyNotify destroy_notify) +{ + GstVaapiMiniObjectBase *base_object; + + g_return_if_fail(object != NULL); + + base_object = object2base(object); + if (object->user_data && base_object->user_data_destroy_notify) + base_object->user_data_destroy_notify(object->user_data); + + object->user_data = user_data; + base_object->user_data_destroy_notify = destroy_notify; +} diff --git a/gst-libs/gst/vaapi/gstvaapiminiobject.h b/gst-libs/gst/vaapi/gstvaapiminiobject.h new file mode 100644 index 0000000000..4cf27d9621 --- /dev/null +++ b/gst-libs/gst/vaapi/gstvaapiminiobject.h @@ -0,0 +1,155 @@ +/* + * gstvaapiminiobject.h - A lightweight reference counted object + * + * Copyright (C) 2012 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GST_VAAPI_MINI_OBJECT_H +#define GST_VAAPI_MINI_OBJECT_H + +#include + +G_BEGIN_DECLS + +typedef struct _GstVaapiMiniObject GstVaapiMiniObject; +typedef struct _GstVaapiMiniObjectClass GstVaapiMiniObjectClass; + +/** + * GST_VAAPI_MINI_OBJECT: + * @object: a #GstVaapiMiniObject + * + * Casts the @object to a #GstVaapiMiniObject + */ +#define GST_VAAPI_MINI_OBJECT(object) \ + ((GstVaapiMiniObject *)(object)) + +/** + * GST_VAAPI_MINI_OBJECT_GET_CLASS: + * @object: a #GstVaapiMiniObject + * + * Retrieves the #GstVaapiMiniObjectClass associated with the @object + */ +#define GST_VAAPI_MINI_OBJECT_GET_CLASS(object) \ + gst_vaapi_mini_object_get_class(GST_VAAPI_MINI_OBJECT(object)) + +/** + * GST_VAAPI_MINI_OBJECT_FLAGS: + * @object: a #GstVaapiMiniObject + * + * The entire set of flags for the @object + */ +#define GST_VAAPI_MINI_OBJECT_FLAGS(object) \ + (GST_VAAPI_MINI_OBJECT(object)->flags) + +/** + * GST_VAAPI_MINI_OBJECT_FLAG_IS_SET: + * @object: a #GstVaapiMiniObject + * @flag: a flag to check for + * + * Checks whether the given @flag is set + */ +#define GST_VAAPI_MINI_OBJECT_FLAG_IS_SET(object, flag) \ + ((GST_VAAPI_MINI_OBJECT_FLAGS(object) & (flag)) != 0) + +/** + * GST_VAAPI_MINI_OBJECT_FLAG_SET: + * @object: a #GstVaapiMiniObject + * @flags: flags to set + * + * This macro sets the given bits + */ +#define GST_VAAPI_MINI_OBJECT_FLAG_SET(object, flags) \ + (GST_VAAPI_MINI_OBJECT_FLAGS(object) |= (flags)) + +/** + * GST_VAAPI_MINI_OBJECT_FLAG_UNSET: + * @object: a #GstVaapiMiniObject + * @flags: flags to unset + * + * This macro unsets the given bits. + */ +#define GST_VAAPI_MINI_OBJECT_FLAG_UNSET(object, flags) \ + (GST_VAAPI_MINI_OBJECT_FLAGS(object) &= ~(flags)) + +/** + * GstVaapiMiniObject: + * @flags: set of flags that should be manipulated through + * GST_VAAPI_MINI_OBJECT_FLAG_*() functions + * @user_data: user-provided data from gst_vaapi_mini_object_set_user_data() + * + * A #GstVaapiMiniObject represents a minimal reference counted data + * structure that can hold a set of flags and user-provided data. + */ +struct _GstVaapiMiniObject { + /*< private >*/ + guint flags; + gpointer user_data; +}; + +/** + * GstVaapiMiniObjectClass: + * @size: size in bytes of the #GstVaapiMiniObject, plus any + * additional data for derived classes + * @finalize: function called to destroy data in derived classes + * + * A #GstVaapiMiniObjectClass represents the base object class that + * defines the size of the #GstVaapiMiniObject and utility function to + * dispose child objects + */ +struct _GstVaapiMiniObjectClass { + guint size; + GDestroyNotify finalize; +}; + +G_GNUC_INTERNAL +const GstVaapiMiniObjectClass * +gst_vaapi_mini_object_get_class(GstVaapiMiniObject *object) G_GNUC_CONST; + +G_GNUC_INTERNAL +GstVaapiMiniObject * +gst_vaapi_mini_object_new(const GstVaapiMiniObjectClass *object_class); + +G_GNUC_INTERNAL +GstVaapiMiniObject * +gst_vaapi_mini_object_new0(const GstVaapiMiniObjectClass *object_class); + +G_GNUC_INTERNAL +GstVaapiMiniObject * +gst_vaapi_mini_object_ref(GstVaapiMiniObject *object); + +G_GNUC_INTERNAL +void +gst_vaapi_mini_object_unref(GstVaapiMiniObject *object); + +G_GNUC_INTERNAL +void +gst_vaapi_mini_object_replace(GstVaapiMiniObject **old_object_ptr, + GstVaapiMiniObject *new_object); + +G_GNUC_INTERNAL +gpointer +gst_vaapi_mini_object_get_user_data(GstVaapiMiniObject *object); + +G_GNUC_INTERNAL +void +gst_vaapi_mini_object_set_user_data(GstVaapiMiniObject *object, + gpointer user_data, GDestroyNotify destroy_notify); + +G_END_DECLS + +#endif /* GST_VAAPI_MINI_OBJECT_H */ -- 2.34.1