caps: Store a pointer to GstCaps in GstStaticCaps

...instead of using hackish subclass of GstCaps, which also
had some thread-safety problems.
This commit is contained in:
Sebastian Dröge 2012-01-26 14:33:12 +01:00
parent dc4d96d54c
commit 5d1d7d95b2
4 changed files with 18 additions and 42 deletions

View file

@ -356,7 +356,6 @@ gst_static_caps_get_type (void)
return staticcaps_type; return staticcaps_type;
} }
/** /**
* gst_static_caps_get: * gst_static_caps_get:
* @static_caps: the #GstStaticCaps to convert * @static_caps: the #GstStaticCaps to convert
@ -370,20 +369,19 @@ gst_static_caps_get_type (void)
GstCaps * GstCaps *
gst_static_caps_get (GstStaticCaps * static_caps) gst_static_caps_get (GstStaticCaps * static_caps)
{ {
GstCaps *caps; GstCaps **caps;
g_return_val_if_fail (static_caps != NULL, NULL); g_return_val_if_fail (static_caps != NULL, NULL);
caps = (GstCaps *) static_caps; caps = &static_caps->caps;
/* refcount is 0 when we need to convert */ /* refcount is 0 when we need to convert */
if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) == 0)) { if (G_UNLIKELY (*caps == NULL)) {
const char *string; const char *string;
GstCaps temp;
G_LOCK (static_caps_lock); G_LOCK (static_caps_lock);
/* check if other thread already updated */ /* check if other thread already updated */
if (G_UNLIKELY (GST_CAPS_REFCOUNT_VALUE (caps) > 0)) if (G_UNLIKELY (*caps != NULL))
goto done; goto done;
string = static_caps->string; string = static_caps->string;
@ -393,28 +391,21 @@ gst_static_caps_get (GstStaticCaps * static_caps)
GST_CAT_TRACE (GST_CAT_CAPS, "creating %p", static_caps); GST_CAT_TRACE (GST_CAT_CAPS, "creating %p", static_caps);
/* we construct the caps on the stack, then copy over the struct into our *caps = gst_caps_from_string (string);
* real caps, refcount last. We do this because we must leave the refcount
* of the result caps to 0 so that other threads don't run away with the
* caps while we are constructing it. */
gst_caps_init (&temp, sizeof (GstCaps));
/* convert to string */ /* convert to string */
if (G_UNLIKELY (!gst_caps_from_string_inplace (&temp, string))) if (G_UNLIKELY (*caps == NULL))
g_critical ("Could not convert static caps \"%s\"", string); g_critical ("Could not convert static caps \"%s\"", string);
GST_MINI_OBJECT_REFCOUNT (&temp) = 0;
memcpy (caps, &temp, sizeof (GstCaps));
gst_caps_ref (caps);
GST_CAT_TRACE (GST_CAT_CAPS, "created %p", static_caps); GST_CAT_TRACE (GST_CAT_CAPS, "created %p", static_caps);
done: done:
G_UNLOCK (static_caps_lock); G_UNLOCK (static_caps_lock);
} }
/* ref the caps, makes it not writable */ /* ref the caps, makes it not writable */
gst_caps_ref (caps); if (G_LIKELY (*caps != NULL))
gst_caps_ref (*caps);
return caps; return *caps;
/* ERRORS */ /* ERRORS */
no_string: no_string:
@ -427,30 +418,16 @@ no_string:
/** /**
* gst_static_caps_cleanup: * gst_static_caps_cleanup:
* @static_caps: the #GstStaticCaps to convert * @static_caps: the #GstStaticCaps to clean
* *
* Clean up the caps contained in @static_caps when the refcount is 0. * Clean up the cached caps contained in @static_caps.
*/ */
void void
gst_static_caps_cleanup (GstStaticCaps * static_caps) gst_static_caps_cleanup (GstStaticCaps * static_caps)
{ {
GstCaps *caps = (GstCaps *) static_caps; G_LOCK (static_caps_lock);
gst_caps_replace (&static_caps->caps, NULL);
/* FIXME: this is not threadsafe */ G_UNLOCK (static_caps_lock);
if (GST_CAPS_REFCOUNT_VALUE (caps) == 1) {
GstStructure *structure;
guint i, clen;
clen = GST_CAPS_LEN (caps);
for (i = 0; i < clen; i++) {
structure = (GstStructure *) gst_caps_get_structure (caps, i);
gst_structure_set_parent_refcount (structure, NULL);
gst_structure_free (structure);
}
g_ptr_array_free (GST_CAPS_ARRAY (caps), TRUE);
GST_CAPS_REFCOUNT (caps) = 0;
}
} }
/* manipulation */ /* manipulation */

View file

@ -129,8 +129,7 @@ typedef enum {
*/ */
#define GST_STATIC_CAPS(string) \ #define GST_STATIC_CAPS(string) \
{ \ { \
/* miniobject */ { { 0, 0, 0, 0, NULL, NULL, NULL, 0, NULL }, \ /* caps */ NULL, \
/* caps */ NULL }, \
/* string */ string, \ /* string */ string, \
GST_PADDING_INIT \ GST_PADDING_INIT \
} }
@ -361,7 +360,7 @@ struct _GstCaps {
*/ */
struct _GstStaticCaps { struct _GstStaticCaps {
/*< public >*/ /*< public >*/
GstCaps caps; GstCaps *caps;
const char *string; const char *string;
/*< private >*/ /*< private >*/

View file

@ -253,7 +253,7 @@ gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
newt->name_template = g_intern_string (templ->name_template); newt->name_template = g_intern_string (templ->name_template);
newt->direction = templ->direction; newt->direction = templ->direction;
newt->presence = templ->presence; newt->presence = templ->presence;
newt->static_caps.caps.mini_object.refcount = 0; newt->static_caps.caps = NULL;
newt->static_caps.string = g_intern_string (caps_string); newt->static_caps.string = g_intern_string (caps_string);
factory->staticpadtemplates = factory->staticpadtemplates =
g_list_append (factory->staticpadtemplates, newt); g_list_append (factory->staticpadtemplates, newt);

View file

@ -493,7 +493,7 @@ gst_registry_chunks_load_pad_template (GstElementFactory * factory, gchar ** in,
template = g_slice_new (GstStaticPadTemplate); template = g_slice_new (GstStaticPadTemplate);
template->presence = pt->presence; template->presence = pt->presence;
template->direction = (GstPadDirection) pt->direction; template->direction = (GstPadDirection) pt->direction;
template->static_caps.caps.mini_object.refcount = 0; template->static_caps.caps = NULL;
/* unpack pad template strings */ /* unpack pad template strings */
unpack_const_string (*in, template->name_template, end, fail); unpack_const_string (*in, template->name_template, end, fail);