- Prepare caps/props structs for future implementation of refcounting

Original commit message from CVS:
- Prepare caps/props structs for future implementation of refcounting
- Added some (yet unused) methods as to not introduce too much methods
for next release.
This commit is contained in:
Wim Taymans 2003-01-28 21:54:37 +00:00
parent fd70412057
commit eb80da297f
7 changed files with 253 additions and 67 deletions

View file

@ -56,9 +56,10 @@ transform_func (const GValue *src_value,
g_free (props);
caps = caps->next;
g_string_append_printf (result, " }%s", caps?", ":"");
g_string_append_printf (result, " }%s", (caps ? ", " : ""));
}
dest_value->data[0].v_pointer = result->str;
g_string_free (result, FALSE);
}
void
@ -142,14 +143,41 @@ gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props)
caps->properties = props;
caps->next = NULL;
caps->refcount = 1;
if (props)
caps->fixed = props->fixed;
GST_CAPS_FLAG_SET (caps, GST_CAPS_FLOATING);
if (props && !GST_PROPS_IS_FIXED (props))
GST_CAPS_FLAG_UNSET (caps, GST_CAPS_FIXED);
else
caps->fixed = TRUE;
GST_CAPS_FLAG_SET (caps, GST_CAPS_FIXED);
return caps;
}
void
gst_caps_replace (GstCaps **oldcaps, GstCaps *newcaps)
{
if (*oldcaps != newcaps) {
if (newcaps) gst_caps_ref (newcaps);
if (*oldcaps) gst_caps_unref (*oldcaps);
*oldcaps = newcaps;
}
}
/**
* gst_caps_replace_sink:
* @oldcaps: the caps to take replace
* @newcaps: the caps to take replace
*
* Replace the pointer to the caps and take ownership.
*/
void
gst_caps_replace_sink (GstCaps **oldcaps, GstCaps *newcaps)
{
gst_caps_replace (oldcaps, newcaps);
gst_caps_sink (newcaps);
}
/**
* gst_caps_destroy:
* @caps: the caps to destroy
@ -189,8 +217,10 @@ gst_caps_debug (GstCaps *caps, const gchar *label)
{
GST_DEBUG_ENTER ("caps debug: %s", label);
while (caps) {
GST_DEBUG (GST_CAT_CAPS, "caps: %p %s %s (%sfixed)", caps, caps->name, gst_caps_get_mime (caps),
caps->fixed ? "" : "NOT ");
GST_DEBUG (GST_CAT_CAPS, "caps: %p %s %s (%sfixed) (refcount %d) %s",
caps, caps->name, gst_caps_get_mime (caps),
GST_CAPS_IS_FIXED (caps) ? "" : "NOT ", caps->refcount,
GST_CAPS_IS_FLOATING (caps) ? "FLOATING" : "");
if (caps->properties) {
gst_props_debug (caps->properties);
@ -251,6 +281,26 @@ gst_caps_ref (GstCaps *caps)
return caps;
}
/**
* gst_caps_sink:
* @caps: the caps to take ownership of
*
* Take ownership of a GstCaps
*/
void
gst_caps_sink (GstCaps *caps)
{
if (caps == NULL)
return;
if (GST_CAPS_IS_FLOATING (caps)) {
GST_DEBUG (GST_CAT_CAPS, "sink %p", caps);
GST_CAPS_FLAG_UNSET (caps, GST_CAPS_FLOATING);
gst_caps_unref (caps);
}
}
/**
* gst_caps_copy_1:
* @caps: the caps to copy
@ -473,6 +523,23 @@ gst_caps_get_props (GstCaps *caps)
return caps->properties;
}
/**
* gst_caps_next:
* @caps: the caps to query
*
* Get the next caps of this chained caps.
*
* Returns: the next caps or NULL if the chain ended.
*/
GstCaps*
gst_caps_next (GstCaps *caps)
{
if (caps == NULL)
return NULL;
return caps->next;
}
/**
* gst_caps_chain:
* @caps: a capabilty
@ -836,13 +903,14 @@ gst_caps_load_thyself (xmlNodePtr parent)
xmlNodePtr subfield = field->xmlChildrenNode;
GstCaps *caps;
gchar *content;
gboolean fixed = TRUE;
GstCapsFlags fixed = GST_CAPS_FIXED;
g_mutex_lock (_gst_caps_chunk_lock);
caps = g_mem_chunk_alloc0 (_gst_caps_chunk);
g_mutex_unlock (_gst_caps_chunk_lock);
caps->refcount = 1;
GST_CAPS_FLAG_SET (caps, GST_CAPS_FLOATING);
caps->next = NULL;
while (subfield) {
@ -856,12 +924,12 @@ gst_caps_load_thyself (xmlNodePtr parent)
}
else if (!strcmp (subfield->name, "properties")) {
caps->properties = gst_props_load_thyself (subfield);
fixed &= caps->properties->fixed;
fixed &= GST_PROPS_IS_FIXED (caps->properties);
}
subfield = subfield->next;
}
caps->fixed = fixed;
GST_CAPS_FLAG_SET (caps, fixed);
result = gst_caps_append (result, caps);
}

View file

@ -34,27 +34,41 @@ extern GType _gst_caps_type;
#define GST_TYPE_CAPS (_gst_caps_type)
typedef enum {
GST_CAPS_FIXED = (1 << 0), /* caps has no variable properties */
GST_CAPS_FLOATING = (1 << 1) /* caps is floating */
} GstCapsFlags;
#define GST_CAPS(caps) ((GstCaps *)(caps))
#define GST_CAPS(caps) ((GstCaps *)(caps))
#define GST_CAPS_IS_FIXED(caps) ((caps)->fixed)
#define GST_CAPS_IS_CHAINED(caps) ((caps)->next)
#define GST_CAPS_FLAGS(caps) ((caps)->flags)
#define GST_CAPS_FLAG_IS_SET(caps,flag) (GST_CAPS_FLAGS (caps) & flag)
#define GST_CAPS_FLAG_SET(caps,flag) (GST_CAPS_FLAGS (caps) |= (flag))
#define GST_CAPS_FLAG_UNSET(caps,flag) (GST_CAPS_FLAGS (caps) &= ~(flag))
#define GST_CAPS_REFCOUNT(caps) ((caps)->refcount)
#define GST_CAPS_PROPERTIES(caps) ((caps)->properties)
#define GST_CAPS_NEXT(caps) ((caps)->next)
#define GST_CAPS_IS_FIXED(caps) (GST_CAPS_FLAGS (caps) & GST_CAPS_FIXED)
#define GST_CAPS_IS_FLOATING(caps) (GST_CAPS_FLAGS (caps) & GST_CAPS_FLOATING)
#define GST_CAPS_IS_CHAINED(caps) (GST_CAPS_NEXT (caps) != NULL)
/* CR1: id is an int corresponding to the quark for the mime type because
* it's really fast when doing a first-pass check for caps compatibility */
struct _GstCaps {
gchar *name; /* the name of this caps */
guint16 id; /* type id (major type) representing
the mime type */
/* --- public ReadOnly --- */
gchar *name; /* the name of this caps */
guint16 id; /* type id (major type) representing
the mime type, it's stored as a GQuark
for speed/space reasons */
guint refcount;
gboolean fixed; /* this caps doesn't contain variable properties */
guint16 flags; /* flags */
guint refcount;
GstProps *properties; /* properties for this capability */
GstCaps *next; /* not with a GList for efficiency */
GstProps *properties; /* properties for this capability */
GstCaps *next; /* not with a GList for efficiency */
};
/* factory macros which make it easier for plugins to instantiate */
#ifdef G_HAVE_ISO_VARARGS
@ -106,8 +120,14 @@ void _gst_caps_initialize (void);
GstCaps* gst_caps_new (const gchar *name, const gchar *mime, GstProps *props);
GstCaps* gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props);
/* replace pointer to caps, doing proper refcounting */
void gst_caps_replace (GstCaps **oldcaps, GstCaps *newcaps);
void gst_caps_replace_sink (GstCaps **oldcaps, GstCaps *newcaps);
/* caps lifecycle control */
GstCaps* gst_caps_unref (GstCaps *caps);
GstCaps* gst_caps_ref (GstCaps *caps);
void gst_caps_sink (GstCaps *caps);
void gst_caps_destroy (GstCaps *caps);
void gst_caps_debug (GstCaps *caps, const gchar *label);
@ -148,6 +168,7 @@ GstProps* gst_caps_get_props (GstCaps *caps);
GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name);
GstCaps* gst_caps_next (GstCaps *caps);
GstCaps* gst_caps_chain (GstCaps *caps, ...);
GstCaps* gst_caps_append (GstCaps *caps, GstCaps *capstoadd);
GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd);

View file

@ -2434,7 +2434,6 @@ gst_pad_template_new (const gchar *name_template,
va_start (var_args, caps);
while (caps) {
new->fixed &= caps->fixed;
thecaps = gst_caps_append (thecaps, gst_caps_ref (caps));
caps = va_arg (var_args, GstCaps*);
}

View file

@ -146,7 +146,7 @@ typedef const GstFormat* (*GstPadFormatsFunction) (GstPad *pad);
typedef const GstEventMask* (*GstPadEventMaskFunction) (GstPad *pad);
typedef const GstQueryType* (*GstPadQueryTypeFunction) (GstPad *pad);
typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstCaps *caps);
typedef GstPadLinkReturn (*GstPadLinkFunction) (GstPad *pad, GstCaps *caps);
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *caps);
typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
@ -276,7 +276,7 @@ struct _GstGhostPadClass {
#define GST_PAD_PEER(pad) GST_PAD_CAST(GST_RPAD_PEER(GST_PAD_REALIZE(pad)))
/* Some check functions (unused?) */
#define GST_PAD_IS_LINKED(pad) (GST_PAD_PEER(pad) != NULL)
#define GST_PAD_IS_LINKED(pad) (GST_PAD_PEER(pad) != NULL)
#define GST_PAD_IS_ACTIVE(pad) (!GST_FLAG_IS_SET(GST_PAD_REALIZE(pad), GST_PAD_DISABLED))
#define GST_PAD_IS_USABLE(pad) (GST_PAD_IS_LINKED (pad) && \
GST_PAD_IS_ACTIVE(pad) && GST_PAD_IS_ACTIVE(GST_PAD_PEER (pad)))
@ -301,22 +301,26 @@ typedef enum {
#define GST_PAD_TEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction)
#define GST_PAD_TEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence)
#define GST_PAD_TEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps)
#define GST_PAD_TEMPLATE_FIXED(templ) (((GstPadTemplate *)(templ))->fixed)
#define GST_PAD_TEMPLATE_IS_FIXED(templ) (GST_PAD_TEMPLATE_FIXED(templ) == TRUE)
typedef enum {
GST_PAD_TEMPLATE_FIXED = GST_OBJECT_FLAG_LAST,
GST_PAD_TEMPLATE_FLAG_LAST = GST_OBJECT_FLAG_LAST + 4
} GstPadTemplateFlags;
#define GST_PAD_TEMPLATE_IS_FIXED(templ) (GST_FLAG_IS_SET(templ), GST_PAD_TEMPLATE_FIXED)
struct _GstPadTemplate {
GstObject object;
GstObject object;
gchar *name_template;
GstPadDirection direction;
GstPadPresence presence;
GstPadDirection direction;
GstPadPresence presence;
GstCaps *caps;
gboolean fixed;
};
struct _GstPadTemplateClass {
GstObjectClass parent_class;
GstObjectClass parent_class;
/* signal callbacks */
void (*pad_created) (GstPadTemplate *templ, GstPad *pad);
@ -425,7 +429,7 @@ gboolean gst_pad_can_link_filtered (GstPad *srcpad, GstPad *s
gboolean gst_pad_link (GstPad *srcpad, GstPad *sinkpad);
gboolean gst_pad_link_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
void gst_pad_unlink (GstPad *srcpad, GstPad *sinkpad);
void gst_pad_unlink (GstPad *srcpad, GstPad *sinkpad);
GstPad* gst_pad_get_peer (GstPad *pad);
@ -437,7 +441,7 @@ gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
GstPadLinkReturn gst_pad_proxy_link (GstPad *pad, GstCaps *caps);
gboolean gst_pad_relink_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
gboolean gst_pad_relink_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
gboolean gst_pad_perform_negotiate (GstPad *srcpad, GstPad *sinkpad);
gboolean gst_pad_try_relink_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
GstCaps* gst_pad_get_allowed_caps (GstPad *pad);
@ -475,9 +479,9 @@ gboolean gst_pad_query (GstPad *pad, GstQueryType type,
gboolean gst_pad_query_default (GstPad *pad, GstQueryType type,
GstFormat *format, gint64 *value);
void gst_pad_set_internal_link_function(GstPad *pad, GstPadIntLinkFunction intlink);
GList* gst_pad_get_internal_links (GstPad *pad);
GList* gst_pad_get_internal_links_default (GstPad *pad);
void gst_pad_set_internal_link_function (GstPad *pad, GstPadIntLinkFunction intlink);
GList* gst_pad_get_internal_links (GstPad *pad);
GList* gst_pad_get_internal_links_default (GstPad *pad);
/* misc helper functions */
gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch,
@ -489,7 +493,7 @@ gboolean gst_pad_dispatcher (GstPad *pad, GstPadDispatcherFunction dispatch
(gst_probe_dispatcher_remove_probe (&(GST_REAL_PAD (pad)-probedisp), probe))
#ifndef GST_DISABLE_LOADSAVE
void gst_pad_load_and_link (xmlNodePtr self, GstObject *parent);
void gst_pad_load_and_link (xmlNodePtr self, GstObject *parent);
#endif

View file

@ -84,9 +84,6 @@ transform_func (const GValue *src_value,
const gchar *name = g_quark_to_string (entry->propid);
switch (entry->propstype) {
case GST_PROPS_STRING_TYPE:
g_string_append_printf (result, "%s=(string) '%s'", name, entry->data.string_data.string);
break;
case GST_PROPS_INT_TYPE:
g_string_append_printf (result, "%s=(int) %d", name, entry->data.int_data);
break;
@ -100,6 +97,9 @@ transform_func (const GValue *src_value,
g_string_append_printf (result, "%s=(boolean) %s", name,
(entry->data.bool_data ? "TRUE" : "FALSE"));
break;
case GST_PROPS_STRING_TYPE:
g_string_append_printf (result, "%s=(string) '%s'", name, entry->data.string_data.string);
break;
default:
break;
}
@ -111,6 +111,7 @@ transform_func (const GValue *src_value,
}
}
dest_value->data[0].v_pointer = result->str;
g_string_free (result, FALSE);
}
@ -353,11 +354,45 @@ gst_props_empty_new (void)
props->properties = NULL;
props->refcount = 1;
props->fixed = TRUE;
GST_PROPS_FLAG_SET (props, GST_PROPS_FLOATING);
GST_PROPS_FLAG_SET (props, GST_PROPS_FIXED);
return props;
}
/**
* gst_props_replace:
* @oldprops: the props to take replace
* @newprops: the props to take replace
*
* Replace the pointer to the props, doing proper
* refcounting.
*/
void
gst_props_replace (GstProps **oldprops, GstProps *newprops)
{
if (*oldprops != newprops) {
if (newprops) gst_props_ref (newprops);
if (*oldprops) gst_props_unref (*oldprops);
*oldprops = newprops;
}
}
/**
* gst_props_replace_sink:
* @oldprops: the props to take replace
* @newprops: the props to take replace
*
* Replace the pointer to the proppropsd take ownership.
*/
void
gst_props_replace_sink (GstProps **oldprops, GstProps *newprops)
{
gst_props_replace (oldprops, newprops);
gst_props_sink (newprops);
}
/**
* gst_props_add_entry:
* @props: the property to add the entry to
@ -371,8 +406,8 @@ gst_props_add_entry (GstProps *props, GstPropsEntry *entry)
g_return_if_fail (props);
g_return_if_fail (entry);
if (props->fixed && GST_PROPS_ENTRY_IS_VARIABLE (entry)) {
props->fixed = FALSE;
if (GST_PROPS_IS_FIXED (props) && GST_PROPS_ENTRY_IS_VARIABLE (entry)) {
GST_PROPS_FLAG_UNSET (props, GST_PROPS_FIXED);
}
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
}
@ -740,17 +775,23 @@ gst_props_set (GstProps *props, const gchar *name, ...)
*
* Decrease the refcount of the property structure, destroying
* the property if the refcount is 0.
*
* Returns: refcounted GstProps or NULL if props was destroyed.
*/
void
GstProps*
gst_props_unref (GstProps *props)
{
if (props == NULL)
return;
return NULL;
props->refcount--;
if (props->refcount == 0)
if (props->refcount == 0) {
gst_props_destroy (props);
return NULL;
}
return props;
}
/**
@ -758,15 +799,38 @@ gst_props_unref (GstProps *props)
* @props: the props to ref
*
* Increase the refcount of the property structure.
*
* Returns: refcounted GstProps.
*/
void
GstProps*
gst_props_ref (GstProps *props)
{
g_return_if_fail (props != NULL);
if (props == NULL)
return NULL;
props->refcount++;
return props;
}
/**
* gst_props_sink:
* @props: the props to sink
*
* If the props if floating, decrease its refcount. Usually used
* with gst_props_ref() to take ownership of the props.
*/
void
gst_props_sink (GstProps *props)
{
if (props == NULL)
return;
if (GST_PROPS_IS_FLOATING (props)) {
GST_PROPS_FLAG_UNSET (props, GST_PROPS_FLOATING);
gst_props_unref (props);
}
}
/**
* gst_props_destroy:
@ -806,11 +870,17 @@ gst_props_entry_copy (GstPropsEntry *entry)
newentry = gst_props_alloc_entry ();
memcpy (newentry, entry, sizeof (GstPropsEntry));
if (entry->propstype == GST_PROPS_LIST_TYPE) {
newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
}
else if (entry->propstype == GST_PROPS_STRING_TYPE) {
newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
switch (entry->propstype) {
case GST_PROPS_LIST_TYPE:
newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
break;
case GST_PROPS_STRING_TYPE:
newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
break;
default:
/* FIXME more? */
break;
}
return newentry;
@ -852,7 +922,7 @@ gst_props_copy (GstProps *props)
new = gst_props_empty_new ();
new->properties = gst_props_list_copy (props->properties);
new->fixed = props->fixed;
GST_PROPS_FLAGS (new) |= (GST_PROPS_FLAGS (props) & GST_PROPS_FIXED);
return new;
}
@ -1726,7 +1796,7 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
GstPropsEntry *iprops = NULL;
intersection = gst_props_empty_new ();
intersection->fixed = TRUE;
GST_PROPS_FLAG_SET (intersection, GST_PROPS_FIXED);
g_return_val_if_fail (props1 != NULL, NULL);
g_return_val_if_fail (props2 != NULL, NULL);
@ -1751,7 +1821,7 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
toadd = gst_props_entry_copy (entry1);
if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
intersection->fixed = FALSE;
GST_PROPS_FLAG_UNSET (intersection, GST_PROPS_FIXED);
intersection->properties = g_list_prepend (intersection->properties, toadd);
@ -1766,7 +1836,7 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
toadd = gst_props_entry_copy (entry2);
if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
intersection->fixed = FALSE;
GST_PROPS_FLAG_UNSET (intersection, GST_PROPS_FIXED);
intersection->properties = g_list_prepend (intersection->properties, toadd);
@ -1781,7 +1851,8 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
if (iprops) {
if (GST_PROPS_ENTRY_IS_VARIABLE (iprops))
intersection->fixed = FALSE;
GST_PROPS_FLAG_UNSET (intersection, GST_PROPS_FIXED);
intersection->properties = g_list_prepend (intersection->properties, iprops);
}
else {
@ -1807,7 +1878,8 @@ end:
entry = (GstPropsEntry *) leftovers->data;
if (GST_PROPS_ENTRY_IS_VARIABLE (entry))
intersection->fixed = FALSE;
GST_PROPS_FLAG_UNSET (intersection, GST_PROPS_FIXED);
intersection->properties = g_list_prepend (intersection->properties, gst_props_entry_copy (entry));
leftovers = g_list_next (leftovers);

View file

@ -83,11 +83,27 @@ extern GType _gst_props_entry_type;
#define GST_TYPE_PROPS_ENTRY (_gst_props_entry_type)
struct _GstProps {
gint refcount;
gboolean fixed;
typedef enum {
GST_PROPS_FIXED = (1 << 0), /* props has no variable entries */
GST_PROPS_FLOATING = (1 << 1) /* props is floating */
} GstPropsFlags;
GList *properties; /* real properties for this property */
#define GST_PROPS_FLAGS(props) ((props)->flags)
#define GST_PROPS_FLAG_IS_SET(props,flag) (GST_PROPS_FLAGS (props) & flag)
#define GST_PROPS_FLAG_SET(props,flag) (GST_PROPS_FLAGS (props) |= (flag))
#define GST_PROPS_FLAG_UNSET(props,flag) (GST_PROPS_FLAGS (props) &= ~(flag))
#define GST_PROPS_REFCOUNT(props) ((props)->refcount)
#define GST_PROPS_PROPERTIES(props) ((props)->properties)
#define GST_PROPS_IS_FIXED(props) (GST_PROPS_FLAGS (props) & GST_PROPS_FIXED)
#define GST_PROPS_IS_FLOATING(props) (GST_PROPS_FLAGS (props) & GST_PROPS_FLOATING)
struct _GstProps {
gint refcount;
gint flags;
GList *properties; /* real property entries for this property */
};
/* initialize the subsystem */
@ -97,8 +113,14 @@ GstProps* gst_props_new (const gchar *firstname, ...);
GstProps* gst_props_newv (const gchar *firstname, va_list var_args);
GstProps* gst_props_empty_new (void);
void gst_props_unref (GstProps *props);
void gst_props_ref (GstProps *props);
/* replace pointer to props, doing proper refcounting */
void gst_props_replace (GstProps **oldprops, GstProps *newprops);
void gst_props_replace_sink (GstProps **oldprops, GstProps *newprops);
/* lifecycle management */
GstProps* gst_props_unref (GstProps *props);
GstProps* gst_props_ref (GstProps *props);
void gst_props_sink (GstProps *props);
void gst_props_destroy (GstProps *props);
void gst_props_debug (GstProps *props);

View file

@ -113,7 +113,7 @@ print_caps (const GstCaps *caps, const gchar *pfx)
while (caps) {
GstType *type;
g_print ("%s'%s': (%sfixed)\n", pfx, caps->name, (caps->fixed ? "" : "NOT "));
g_print ("%s'%s': (%sfixed)\n", pfx, caps->name, (GST_CAPS_IS_FIXED (caps) ? "" : "NOT "));
type = gst_type_find_by_id (caps->id);
if (type)