mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
- implement FLOATING flag on caps/props
Original commit message from CVS: - implement FLOATING flag on caps/props - use gstmemchunk for caps/props - implement remove_entry for props - various refcounting functions - fix refcounting on caps/props - use tracing for caps/props/propsentries - fix memleak in transform functions - fix refcounting on elementfactory padtemplates - add dispose for padtemplates - shortcut pad negotiation early on
This commit is contained in:
parent
f05a353f5c
commit
6ad8197d61
8 changed files with 710 additions and 314 deletions
228
gst/gstcaps.c
228
gst/gstcaps.c
|
@ -25,10 +25,15 @@
|
|||
|
||||
#include "gstcaps.h"
|
||||
#include "gsttype.h"
|
||||
#include "gstmemchunk.h"
|
||||
#include "gstlog.h"
|
||||
|
||||
static GMemChunk *_gst_caps_chunk;
|
||||
static GMutex *_gst_caps_chunk_lock;
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
|
||||
static GstMemChunk *_gst_caps_chunk;
|
||||
|
||||
static GstAllocTrace *_gst_caps_trace;
|
||||
|
||||
GType _gst_caps_type;
|
||||
|
||||
|
@ -52,22 +57,23 @@ transform_func (const GValue *src_value,
|
|||
g_value_set_boxed (&value, caps->properties);
|
||||
props = g_strdup_value_contents (&value);
|
||||
|
||||
g_value_unset (&value);
|
||||
g_string_append (result, props);
|
||||
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
|
||||
_gst_caps_initialize (void)
|
||||
{
|
||||
_gst_caps_chunk = g_mem_chunk_new ("GstCaps",
|
||||
_gst_caps_chunk = gst_mem_chunk_new ("GstCaps",
|
||||
sizeof (GstCaps), sizeof (GstCaps) * 256,
|
||||
G_ALLOC_AND_FREE);
|
||||
_gst_caps_chunk_lock = g_mutex_new ();
|
||||
|
||||
_gst_caps_type = g_boxed_type_register_static ("GstCaps",
|
||||
(GBoxedCopyFunc) gst_caps_ref,
|
||||
|
@ -76,6 +82,8 @@ _gst_caps_initialize (void)
|
|||
g_value_register_transform_func (_gst_caps_type,
|
||||
G_TYPE_STRING,
|
||||
transform_func);
|
||||
|
||||
_gst_caps_trace = gst_alloc_trace_register (GST_CAPS_TRACE_NAME);
|
||||
}
|
||||
|
||||
static guint16
|
||||
|
@ -133,23 +141,62 @@ gst_caps_new_id (const gchar *name, const guint16 id, GstProps *props)
|
|||
{
|
||||
GstCaps *caps;
|
||||
|
||||
g_mutex_lock (_gst_caps_chunk_lock);
|
||||
caps = g_mem_chunk_alloc (_gst_caps_chunk);
|
||||
g_mutex_unlock (_gst_caps_chunk_lock);
|
||||
caps = gst_mem_chunk_alloc (_gst_caps_chunk);
|
||||
gst_alloc_trace_new (_gst_caps_trace, caps);
|
||||
|
||||
GST_DEBUG (GST_CAT_CAPS, "new %p", caps);
|
||||
|
||||
gst_props_ref (props);
|
||||
gst_props_sink (props);
|
||||
|
||||
caps->name = g_strdup (name);
|
||||
caps->id = id;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_replace:
|
||||
* @oldcaps: the caps to take replace
|
||||
* @newcaps: the caps to take replace
|
||||
*
|
||||
* Replace the pointer to the caps, doing proper
|
||||
* refcounting.
|
||||
*/
|
||||
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
|
||||
|
@ -167,11 +214,13 @@ gst_caps_destroy (GstCaps *caps)
|
|||
|
||||
next = caps->next;
|
||||
|
||||
GST_DEBUG (GST_CAT_CAPS, "destroy %p", caps);
|
||||
|
||||
gst_props_unref (caps->properties);
|
||||
g_free (caps->name);
|
||||
g_mutex_lock (_gst_caps_chunk_lock);
|
||||
g_mem_chunk_free (_gst_caps_chunk, caps);
|
||||
g_mutex_unlock (_gst_caps_chunk_lock);
|
||||
|
||||
gst_alloc_trace_free (_gst_caps_trace, caps);
|
||||
gst_mem_chunk_free (_gst_caps_chunk, caps);
|
||||
|
||||
if (next)
|
||||
gst_caps_unref (next);
|
||||
|
@ -189,8 +238,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);
|
||||
|
@ -223,6 +274,9 @@ gst_caps_unref (GstCaps *caps)
|
|||
|
||||
g_return_val_if_fail (caps->refcount > 0, NULL);
|
||||
|
||||
GST_DEBUG (GST_CAT_CAPS, "unref %p (%d->%d) %d",
|
||||
caps, caps->refcount, caps->refcount-1, GST_CAPS_FLAGS (caps));
|
||||
|
||||
caps->refcount--;
|
||||
zero = (caps->refcount == 0);
|
||||
|
||||
|
@ -244,20 +298,46 @@ gst_caps_unref (GstCaps *caps)
|
|||
GstCaps*
|
||||
gst_caps_ref (GstCaps *caps)
|
||||
{
|
||||
g_return_val_if_fail (caps != NULL, NULL);
|
||||
if (caps == NULL)
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (caps->refcount > 0, NULL);
|
||||
|
||||
GST_DEBUG (GST_CAT_CAPS, "ref %p (%d->%d) %d",
|
||||
caps, caps->refcount, caps->refcount+1, GST_CAPS_FLAGS (caps));
|
||||
|
||||
caps->refcount++;
|
||||
|
||||
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
|
||||
*
|
||||
* Copies the caps, not copying any chained caps.
|
||||
*
|
||||
* Returns: a copy of the GstCaps structure.
|
||||
* Returns: a floating copy of the GstCaps structure.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_copy_1 (GstCaps *caps)
|
||||
|
@ -281,7 +361,7 @@ gst_caps_copy_1 (GstCaps *caps)
|
|||
*
|
||||
* Copies the caps.
|
||||
*
|
||||
* Returns: a copy of the GstCaps structure.
|
||||
* Returns: a floating copy of the GstCaps structure.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_copy (GstCaps *caps)
|
||||
|
@ -312,7 +392,7 @@ gst_caps_copy (GstCaps *caps)
|
|||
* Copies the caps if the refcount is greater than 1
|
||||
*
|
||||
* Returns: a pointer to a GstCaps strcuture that can
|
||||
* be safely written to
|
||||
* be safely written to.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_copy_on_write (GstCaps *caps)
|
||||
|
@ -360,9 +440,7 @@ gst_caps_set_name (GstCaps *caps, const gchar *name)
|
|||
{
|
||||
g_return_if_fail (caps != NULL);
|
||||
|
||||
if (caps->name)
|
||||
g_free (caps->name);
|
||||
|
||||
g_free (caps->name);
|
||||
caps->name = g_strdup (name);
|
||||
}
|
||||
|
||||
|
@ -449,10 +527,8 @@ GstCaps*
|
|||
gst_caps_set_props (GstCaps *caps, GstProps *props)
|
||||
{
|
||||
g_return_val_if_fail (caps != NULL, caps);
|
||||
g_return_val_if_fail (props != NULL, caps);
|
||||
g_return_val_if_fail (caps->properties == NULL, caps);
|
||||
|
||||
caps->properties = props;
|
||||
gst_props_replace_sink (&caps->properties, props);
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
@ -473,6 +549,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
|
||||
|
@ -523,7 +616,7 @@ gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
|
|||
while (caps->next) {
|
||||
caps = caps->next;
|
||||
}
|
||||
caps->next = capstoadd;
|
||||
gst_caps_replace_sink (&caps->next, capstoadd);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
@ -550,7 +643,7 @@ gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
|
|||
while (capstoadd->next) {
|
||||
capstoadd = capstoadd->next;
|
||||
}
|
||||
capstoadd->next = caps;
|
||||
gst_caps_replace_sink (&capstoadd->next, caps);
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
@ -679,6 +772,8 @@ gst_caps_intersect_func (GstCaps *caps1, GstCaps *caps2)
|
|||
props = gst_props_intersect (caps1->properties, caps2->properties);
|
||||
if (props) {
|
||||
result = gst_caps_new_id ("intersect", caps1->id, props);
|
||||
gst_caps_ref (result);
|
||||
gst_caps_sink (result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -692,7 +787,7 @@ gst_caps_intersect_func (GstCaps *caps1, GstCaps *caps2)
|
|||
* Make the intersection between two caps.
|
||||
*
|
||||
* Returns: The intersection of the two caps or NULL if the intersection
|
||||
* is empty.
|
||||
* is empty. unref the caps after use.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
|
||||
|
@ -704,11 +799,16 @@ gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
|
|||
|
||||
if (caps1 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "first caps is NULL, return other caps");
|
||||
return gst_caps_copy (caps2);
|
||||
return gst_caps_ref (caps2);
|
||||
}
|
||||
if (caps2 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "second caps is NULL, return other caps");
|
||||
return gst_caps_copy (caps1);
|
||||
return gst_caps_ref (caps1);
|
||||
}
|
||||
|
||||
/* same caps */
|
||||
if (caps1 == caps2) {
|
||||
return gst_caps_ref (caps1);
|
||||
}
|
||||
|
||||
while (caps1) {
|
||||
|
@ -729,7 +829,27 @@ gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
|
|||
}
|
||||
othercaps = othercaps->next;
|
||||
}
|
||||
caps1 = caps1->next;
|
||||
caps1 = caps1->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GstCaps*
|
||||
gst_caps_union (GstCaps *caps1, GstCaps *caps2)
|
||||
{
|
||||
GstCaps *result = NULL;
|
||||
|
||||
/* printing the name is not useful here since caps can be chained */
|
||||
GST_DEBUG (GST_CAT_CAPS, "making union of caps %p and %p", caps1, caps2);
|
||||
|
||||
if (caps1 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "first caps is NULL, return other caps");
|
||||
return gst_caps_ref (caps2);
|
||||
}
|
||||
if (caps2 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "second caps is NULL, return other caps");
|
||||
return gst_caps_ref (caps1);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -742,43 +862,40 @@ gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
|
|||
* Make the normalisation of the caps. This will return a new caps
|
||||
* that is equivalent to the input caps with the exception that all
|
||||
* lists are unrolled. This function is useful when you want to iterate
|
||||
* the caps.
|
||||
* the caps. unref the caps after use.
|
||||
*
|
||||
* Returns: The normalisation of the caps.
|
||||
* Returns: The normalisation of the caps. Unref after usage.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_normalize (GstCaps *caps)
|
||||
{
|
||||
GstCaps *result = NULL, *walk = caps;
|
||||
GstCaps *result = NULL, *walk;
|
||||
|
||||
if (caps == NULL)
|
||||
return caps;
|
||||
|
||||
GST_DEBUG (GST_CAT_CAPS, "normalizing caps %p ", caps);
|
||||
|
||||
walk = caps;
|
||||
|
||||
while (caps) {
|
||||
GList *proplist;
|
||||
|
||||
proplist = gst_props_normalize (caps->properties);
|
||||
if (proplist && g_list_next (proplist) == NULL) {
|
||||
if (result == NULL)
|
||||
walk = result = caps;
|
||||
else {
|
||||
walk = walk->next = caps;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
while (proplist) {
|
||||
GstProps *props = (GstProps *) proplist->data;
|
||||
GstCaps *newcaps = gst_caps_new_id (caps->name, caps->id, props);
|
||||
|
||||
gst_caps_ref (newcaps);
|
||||
gst_caps_sink (newcaps);
|
||||
|
||||
if (result == NULL)
|
||||
walk = result = newcaps;
|
||||
else {
|
||||
walk = walk->next = newcaps;
|
||||
walk = walk->next = newcaps;
|
||||
}
|
||||
proplist = g_list_next (proplist);
|
||||
}
|
||||
next:
|
||||
caps = caps->next;
|
||||
}
|
||||
return result;
|
||||
|
@ -836,13 +953,13 @@ 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 = gst_mem_chunk_alloc0 (_gst_caps_chunk);
|
||||
gst_alloc_trace_new (_gst_caps_trace, caps);
|
||||
|
||||
caps->refcount = 1;
|
||||
GST_CAPS_FLAG_SET (caps, GST_CAPS_FLOATING);
|
||||
caps->next = NULL;
|
||||
|
||||
while (subfield) {
|
||||
|
@ -855,13 +972,18 @@ gst_caps_load_thyself (xmlNodePtr parent)
|
|||
g_free (content);
|
||||
}
|
||||
else if (!strcmp (subfield->name, "properties")) {
|
||||
caps->properties = gst_props_load_thyself (subfield);
|
||||
fixed &= caps->properties->fixed;
|
||||
GstProps *props = gst_props_load_thyself (subfield);
|
||||
|
||||
gst_props_ref (props);
|
||||
gst_props_sink (props);
|
||||
caps->properties = props;
|
||||
|
||||
fixed &= (GST_PROPS_IS_FIXED (caps->properties) ? GST_CAPS_FIXED : 0 );
|
||||
}
|
||||
|
||||
subfield = subfield->next;
|
||||
}
|
||||
caps->fixed = fixed;
|
||||
GST_CAPS_FLAG_SET (caps, fixed);
|
||||
|
||||
result = gst_caps_append (result, caps);
|
||||
}
|
||||
|
|
|
@ -30,28 +30,43 @@ G_BEGIN_DECLS
|
|||
|
||||
typedef struct _GstCaps GstCaps;
|
||||
|
||||
#define GST_CAPS_TRACE_NAME "GstCaps"
|
||||
|
||||
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_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 {
|
||||
/* --- public --- */
|
||||
gchar *name; /* the name of this caps */
|
||||
guint16 id; /* type id (major type) representing
|
||||
the mime type */
|
||||
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 */
|
||||
};
|
||||
|
||||
|
@ -97,21 +112,30 @@ factoryname (void) \
|
|||
}
|
||||
#endif
|
||||
|
||||
/* get caps from a factory */
|
||||
#define GST_CAPS_GET(fact) (fact)()
|
||||
|
||||
|
||||
/* initialize the subsystem */
|
||||
void _gst_caps_initialize (void);
|
||||
|
||||
/* creating new caps */
|
||||
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);
|
||||
|
||||
/* write debug lines to the log */
|
||||
void gst_caps_debug (GstCaps *caps, const gchar *label);
|
||||
|
||||
/* copy caps */
|
||||
GstCaps* gst_caps_copy (GstCaps *caps);
|
||||
GstCaps* gst_caps_copy_1 (GstCaps *caps);
|
||||
GstCaps* gst_caps_copy_on_write (GstCaps *caps);
|
||||
|
@ -148,12 +172,18 @@ GstProps* gst_caps_get_props (GstCaps *caps);
|
|||
|
||||
GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name);
|
||||
|
||||
/* use and construct chained caps */
|
||||
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);
|
||||
|
||||
/* see if fromcaps is a subset of tocaps */
|
||||
gboolean gst_caps_is_always_compatible (GstCaps *fromcaps, GstCaps *tocaps);
|
||||
|
||||
/* operations on caps */
|
||||
GstCaps* gst_caps_intersect (GstCaps *caps1, GstCaps *caps2);
|
||||
GstCaps* gst_caps_union (GstCaps *caps1, GstCaps *caps2);
|
||||
GstCaps* gst_caps_normalize (GstCaps *caps);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
|
|
|
@ -122,11 +122,27 @@ gst_element_details_free (GstElementDetails *dp)
|
|||
static void
|
||||
gst_element_factory_cleanup (GstElementFactory *factory)
|
||||
{
|
||||
GList *padtemplates;
|
||||
|
||||
if (factory->details_dynamic) {
|
||||
gst_element_details_free (factory->details);
|
||||
factory->details_dynamic = FALSE;
|
||||
}
|
||||
|
||||
padtemplates = factory->padtemplates;
|
||||
|
||||
while (padtemplates) {
|
||||
GstPadTemplate *oldtempl = GST_PAD_TEMPLATE (padtemplates->data);
|
||||
|
||||
gst_object_unref (GST_OBJECT (oldtempl));
|
||||
|
||||
padtemplates = g_list_next (padtemplates);
|
||||
}
|
||||
g_list_free (factory->padtemplates);
|
||||
|
||||
factory->padtemplates = NULL;
|
||||
factory->numpadtemplates = 0;
|
||||
|
||||
g_free (GST_PLUGIN_FEATURE (factory)->name);
|
||||
}
|
||||
|
||||
|
@ -301,28 +317,14 @@ gst_element_factory_make_or_warn (const gchar *factoryname, const gchar *name)
|
|||
*/
|
||||
void
|
||||
gst_element_factory_add_pad_template (GstElementFactory *factory,
|
||||
GstPadTemplate *templ)
|
||||
GstPadTemplate *templ)
|
||||
{
|
||||
GList *padtemplates;
|
||||
|
||||
g_return_if_fail (factory != NULL);
|
||||
g_return_if_fail (templ != NULL);
|
||||
|
||||
padtemplates = factory->padtemplates;
|
||||
|
||||
gst_object_ref (GST_OBJECT (templ));
|
||||
gst_object_sink (GST_OBJECT (templ));
|
||||
|
||||
while (padtemplates) {
|
||||
GstPadTemplate *oldtempl = GST_PAD_TEMPLATE (padtemplates->data);
|
||||
|
||||
if (!strcmp (oldtempl->name_template, templ->name_template)) {
|
||||
gst_object_unref (GST_OBJECT (oldtempl));
|
||||
padtemplates->data = templ;
|
||||
return;
|
||||
}
|
||||
|
||||
padtemplates = g_list_next (padtemplates);
|
||||
}
|
||||
factory->padtemplates = g_list_append (factory->padtemplates, templ);
|
||||
factory->numpadtemplates++;
|
||||
}
|
||||
|
|
207
gst/gstpad.c
207
gst/gstpad.c
|
@ -842,15 +842,15 @@ gst_pad_unlink (GstPad *srcpad,
|
|||
|
||||
/* reset the filters, both filters are refcounted once */
|
||||
if (GST_RPAD_FILTER (realsrc)) {
|
||||
gst_caps_unref (GST_RPAD_FILTER (realsrc));
|
||||
GST_RPAD_FILTER (realsink) = NULL;
|
||||
GST_RPAD_FILTER (realsrc) = NULL;
|
||||
gst_caps_replace (&GST_RPAD_FILTER (realsink), NULL);
|
||||
gst_caps_replace (&GST_RPAD_FILTER (realsrc), NULL);
|
||||
}
|
||||
|
||||
/* now tell the scheduler */
|
||||
if (src_sched && src_sched == sink_sched) {
|
||||
gst_scheduler_pad_unlink (src_sched,
|
||||
GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
|
||||
GST_PAD_CAST (realsrc),
|
||||
GST_PAD_CAST (realsink));
|
||||
}
|
||||
|
||||
/* hold a reference, as they can go away in the signal handlers */
|
||||
|
@ -906,7 +906,7 @@ gst_pad_check_schedulers (GstRealPad *realsrc, GstRealPad *realsink)
|
|||
*/
|
||||
gboolean
|
||||
gst_pad_can_link_filtered (GstPad *srcpad, GstPad *sinkpad,
|
||||
GstCaps *filtercaps)
|
||||
GstCaps *filtercaps)
|
||||
{
|
||||
GstRealPad *realsrc, *realsink;
|
||||
|
||||
|
@ -1041,7 +1041,7 @@ gst_pad_link_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
|
|||
|
||||
/* try to negotiate the pads, we don't need to clear the caps here */
|
||||
if (!gst_pad_try_relink_filtered_func (realsrc, realsink,
|
||||
filtercaps, FALSE)) {
|
||||
filtercaps, FALSE)) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "relink_filtered_func failed, can't link");
|
||||
|
||||
GST_RPAD_PEER (realsrc) = NULL;
|
||||
|
@ -1063,13 +1063,11 @@ gst_pad_link_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps)
|
|||
/* now tell the scheduler */
|
||||
if (src_sched && src_sched == sink_sched) {
|
||||
gst_scheduler_pad_link (src_sched,
|
||||
GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
|
||||
GST_PAD_CAST (realsrc), GST_PAD_CAST (realsink));
|
||||
}
|
||||
|
||||
GST_INFO (GST_CAT_PADS, "linked %s:%s and %s:%s, successful",
|
||||
GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
|
||||
gst_caps_debug (gst_pad_get_caps (GST_PAD_CAST (realsrc)),
|
||||
"caps of newly linked src pad");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1271,7 +1269,7 @@ gst_pad_get_ghost_pad_list (GstPad *pad)
|
|||
static GstPadLinkReturn
|
||||
gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
||||
{
|
||||
GstCaps *oldcaps, *allowed = NULL;
|
||||
GstCaps *allowed = NULL;
|
||||
GstPadTemplate *template;
|
||||
GstElement *parent = GST_PAD_PARENT (pad);
|
||||
|
||||
|
@ -1290,8 +1288,9 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
|||
GST_INFO (GST_CAT_CAPS, "trying to set caps %p on pad %s:%s",
|
||||
caps, GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
/* first see if we have to check against a filter */
|
||||
if (!(allowed = GST_RPAD_FILTER (pad))) {
|
||||
/* first see if we have to check against a filter, we ref the caps here as we're
|
||||
* going to unref it later on */
|
||||
if (!(allowed = gst_caps_ref (GST_RPAD_FILTER (pad)))) {
|
||||
/* no filter, make sure we check against the padtemplate then */
|
||||
if ((template = gst_pad_get_pad_template (GST_PAD_CAST (pad)))) {
|
||||
allowed = gst_pad_template_get_caps (template);
|
||||
|
@ -1312,10 +1311,12 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
|||
gst_caps_debug (caps, "caps themselves (attemped to set)");
|
||||
gst_caps_debug (allowed,
|
||||
"allowed caps that did not agree with caps");
|
||||
gst_caps_unref (allowed);
|
||||
return GST_PAD_LINK_REFUSED;
|
||||
}
|
||||
/* caps checks out fine, we can unref the intersection now */
|
||||
gst_caps_unref (intersection);
|
||||
gst_caps_unref (allowed);
|
||||
/* given that the caps are fixed, we know that their intersection with the
|
||||
* padtemplate caps is the same as caps itself */
|
||||
}
|
||||
|
@ -1383,10 +1384,7 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
|||
GST_INFO (GST_CAT_CAPS, "setting caps on pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
/* if we got this far all is ok, remove the old caps, set the new one */
|
||||
oldcaps = GST_PAD_CAPS (pad);
|
||||
if (caps) gst_caps_ref (caps);
|
||||
GST_PAD_CAPS (pad) = caps;
|
||||
if (oldcaps) gst_caps_unref (oldcaps);
|
||||
gst_caps_replace_sink (&GST_PAD_CAPS (pad), caps);
|
||||
|
||||
g_object_notify (G_OBJECT (pad), "caps");
|
||||
}
|
||||
|
@ -1394,6 +1392,8 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
|||
GST_INFO (GST_CAT_CAPS,
|
||||
"caps are not fixed on pad %s:%s, not setting them yet",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
}
|
||||
return GST_PAD_LINK_OK;
|
||||
}
|
||||
|
@ -1403,7 +1403,8 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify)
|
|||
* @pad: a #GstPad to try to set the caps on.
|
||||
* @caps: the #GstCaps to set.
|
||||
*
|
||||
* Tries to set the caps on the given pad.
|
||||
* Tries to set the caps on the given pad. Ownership is always taken
|
||||
* of the caps, so you will need to unref non-floating caps.
|
||||
*
|
||||
* Returns: A #GstPadLinkReturn value indicating whether the caps
|
||||
* could be set.
|
||||
|
@ -1422,15 +1423,21 @@ gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
|
|||
|
||||
gst_caps_debug (caps, "caps that we are trying to set");
|
||||
|
||||
/* try to take ownership */
|
||||
gst_caps_ref (caps);
|
||||
gst_caps_sink (caps);
|
||||
|
||||
/* setting non fixed caps on a pad is not allowed */
|
||||
if (!GST_CAPS_IS_FIXED (caps)) {
|
||||
GST_INFO (GST_CAT_CAPS,
|
||||
"trying to set unfixed caps on pad %s:%s, not allowed",
|
||||
GST_DEBUG_PAD_NAME (realpad));
|
||||
GST_INFO (GST_CAT_CAPS,
|
||||
"trying to set unfixed caps on pad %s:%s, not allowed",
|
||||
GST_DEBUG_PAD_NAME (realpad));
|
||||
g_warning ("trying to set non fixed caps on pad %s:%s, not allowed",
|
||||
GST_DEBUG_PAD_NAME (realpad));
|
||||
|
||||
gst_caps_debug (caps, "unfixed caps");
|
||||
return GST_PAD_LINK_DELAYED;
|
||||
set_retval = GST_PAD_LINK_DELAYED;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* if we have a peer try to set the caps, notifying the peerpad
|
||||
|
@ -1439,7 +1446,7 @@ gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
|
|||
{
|
||||
GST_INFO (GST_CAT_CAPS, "tried to set caps on peerpad %s:%s but couldn't, return value %d",
|
||||
GST_DEBUG_PAD_NAME (peer), set_retval);
|
||||
return set_retval;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* then try to set our own caps, we don't need to be notified */
|
||||
|
@ -1447,12 +1454,16 @@ gst_pad_try_set_caps (GstPad *pad, GstCaps *caps)
|
|||
{
|
||||
GST_INFO (GST_CAT_CAPS, "tried to set own caps on pad %s:%s but couldn't, return value %d",
|
||||
GST_DEBUG_PAD_NAME (realpad), set_retval);
|
||||
return set_retval;
|
||||
goto done;
|
||||
}
|
||||
GST_INFO (GST_CAT_CAPS, "succeeded setting caps %p on pad %s:%s, return value %d",
|
||||
caps, GST_DEBUG_PAD_NAME (realpad), set_retval);
|
||||
g_assert (GST_PAD_CAPS (pad));
|
||||
|
||||
|
||||
done:
|
||||
/* if we took ownership, the caps will be freed */
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return set_retval;
|
||||
}
|
||||
|
||||
|
@ -1486,10 +1497,10 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
|
||||
|
||||
/* FIXME does this leak? */
|
||||
GST_PAD_CAPS (GST_PAD (realsrc)) = NULL;
|
||||
GST_PAD_CAPS (GST_PAD (realsink)) = NULL;
|
||||
GST_RPAD_FILTER (realsrc) = NULL;
|
||||
GST_RPAD_FILTER (realsink) = NULL;
|
||||
gst_caps_replace (&GST_PAD_CAPS (GST_PAD (realsrc)), NULL);
|
||||
gst_caps_replace (&GST_PAD_CAPS (GST_PAD (realsink)), NULL);
|
||||
gst_caps_replace (&GST_RPAD_FILTER (realsrc), NULL);
|
||||
gst_caps_replace (&GST_RPAD_FILTER (realsink), NULL);
|
||||
}
|
||||
else {
|
||||
GST_INFO (GST_CAT_PADS, "start relink filtered %s:%s and %s:%s",
|
||||
|
@ -1515,6 +1526,9 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
* this means they have no common format */
|
||||
GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s have no common type",
|
||||
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
|
||||
/* make sure any floating caps from gst_pad_get_caps are freed here */
|
||||
gst_caps_sink (srccaps);
|
||||
gst_caps_sink (sinkcaps);
|
||||
return FALSE;
|
||||
} else {
|
||||
GST_INFO (GST_CAT_PADS, "pads %s:%s and %s:%s intersected to %s caps",
|
||||
|
@ -1523,6 +1537,10 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
(GST_CAPS_IS_FIXED (intersection) ? "fixed" : "variable") :
|
||||
"NULL"));
|
||||
|
||||
/* we don't need those anymore, as the caps can be floating */
|
||||
gst_caps_sink (srccaps);
|
||||
gst_caps_sink (sinkcaps);
|
||||
|
||||
/* then filter this against the app filter */
|
||||
if (filtercaps) {
|
||||
GstCaps *filtered_intersection;
|
||||
|
@ -1530,7 +1548,6 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
filtered_intersection = gst_caps_intersect (intersection,
|
||||
filtercaps);
|
||||
|
||||
/* get rid of the old intersection here */
|
||||
gst_caps_unref (intersection);
|
||||
|
||||
if (!filtered_intersection) {
|
||||
|
@ -1542,8 +1559,8 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
intersection = filtered_intersection;
|
||||
|
||||
/* keep a reference to the app caps */
|
||||
GST_RPAD_APPFILTER (realsink) = filtercaps;
|
||||
GST_RPAD_APPFILTER (realsrc) = filtercaps;
|
||||
gst_caps_replace_sink (&GST_RPAD_APPFILTER (realsink), filtercaps);
|
||||
gst_caps_replace_sink (&GST_RPAD_APPFILTER (realsrc), filtercaps);
|
||||
}
|
||||
}
|
||||
GST_DEBUG (GST_CAT_CAPS, "setting filter for link to:");
|
||||
|
@ -1551,8 +1568,9 @@ gst_pad_try_relink_filtered_func (GstRealPad *srcpad, GstRealPad *sinkpad,
|
|||
|
||||
/* both the app filter and the filter, while stored on both peer pads,
|
||||
* are equal to the same thing on both */
|
||||
GST_RPAD_FILTER (realsrc) = intersection;
|
||||
GST_RPAD_FILTER (realsink) = intersection;
|
||||
gst_caps_replace_sink (&GST_RPAD_FILTER (realsrc), intersection);
|
||||
gst_caps_replace_sink (&GST_RPAD_FILTER (realsink), intersection);
|
||||
gst_caps_unref (intersection);
|
||||
|
||||
return gst_pad_perform_negotiate (GST_PAD (realsrc), GST_PAD (realsink));
|
||||
}
|
||||
|
@ -1572,6 +1590,9 @@ gst_pad_perform_negotiate (GstPad *srcpad, GstPad *sinkpad)
|
|||
GstCaps *intersection, *filtered_intersection;
|
||||
GstRealPad *realsrc, *realsink;
|
||||
GstCaps *srccaps, *sinkcaps, *filter;
|
||||
gboolean res = TRUE;
|
||||
GstElement *parent;
|
||||
|
||||
|
||||
g_return_val_if_fail (srcpad != NULL, FALSE);
|
||||
g_return_val_if_fail (sinkpad != NULL, FALSE);
|
||||
|
@ -1582,6 +1603,20 @@ gst_pad_perform_negotiate (GstPad *srcpad, GstPad *sinkpad)
|
|||
g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
|
||||
|
||||
/* shortcut negotiation */
|
||||
parent = GST_PAD_PARENT (realsrc);
|
||||
if (parent && GST_STATE (parent) < GST_STATE_READY) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "parent %s of pad %s:%s is not READY",
|
||||
GST_ELEMENT_NAME (parent), GST_DEBUG_PAD_NAME (realsrc));
|
||||
return TRUE;
|
||||
}
|
||||
parent = GST_PAD_PARENT (realsink);
|
||||
if (parent && GST_STATE (parent) < GST_STATE_READY) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "parent %s of pad %s:%s is not READY",
|
||||
GST_ELEMENT_NAME (parent), GST_DEBUG_PAD_NAME (realsink));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_INFO (GST_CAT_PADS, "perform negotiate for link %s:%s-%s:%s",
|
||||
GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink));
|
||||
|
||||
|
@ -1605,28 +1640,39 @@ gst_pad_perform_negotiate (GstPad *srcpad, GstPad *sinkpad)
|
|||
"sink caps, awaiting negotiation, after applying filter");
|
||||
intersection = gst_caps_intersect (srccaps, sinkcaps);
|
||||
filtered_intersection = gst_caps_intersect (intersection, filter);
|
||||
if (filtered_intersection) {
|
||||
gst_caps_unref (intersection);
|
||||
intersection = filtered_intersection;
|
||||
}
|
||||
gst_caps_unref (intersection);
|
||||
|
||||
/* no negotiation is performed if the pads have filtercaps */
|
||||
if (intersection) {
|
||||
GstPadLinkReturn res;
|
||||
if (filtered_intersection) {
|
||||
GstPadLinkReturn link_res;
|
||||
|
||||
res = gst_pad_try_set_caps_func (realsrc, intersection, TRUE);
|
||||
if (res == GST_PAD_LINK_REFUSED)
|
||||
return FALSE;
|
||||
if (res == GST_PAD_LINK_DONE)
|
||||
return TRUE;
|
||||
link_res = gst_pad_try_set_caps_func (realsrc, filtered_intersection, TRUE);
|
||||
if (link_res == GST_PAD_LINK_REFUSED)
|
||||
goto error;
|
||||
if (link_res == GST_PAD_LINK_DONE)
|
||||
goto success;
|
||||
|
||||
res = gst_pad_try_set_caps_func (realsink, intersection, TRUE);
|
||||
if (res == GST_PAD_LINK_REFUSED)
|
||||
return FALSE;
|
||||
if (res == GST_PAD_LINK_DONE)
|
||||
return TRUE;
|
||||
link_res = gst_pad_try_set_caps_func (realsink, filtered_intersection, TRUE);
|
||||
if (link_res == GST_PAD_LINK_REFUSED)
|
||||
goto error;
|
||||
if (link_res == GST_PAD_LINK_DONE)
|
||||
goto success;
|
||||
}
|
||||
return TRUE;
|
||||
/* no filtered_intersection, some pads had caps and ther was a filter */
|
||||
else if ((srccaps || sinkcaps) && filter) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
success:
|
||||
cleanup:
|
||||
gst_caps_sink (srccaps);
|
||||
gst_caps_sink (sinkcaps);
|
||||
gst_caps_unref (filtered_intersection);
|
||||
return res;
|
||||
|
||||
error:
|
||||
res = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1656,7 +1702,7 @@ gst_pad_try_relink_filtered (GstPad *srcpad, GstPad *sinkpad,
|
|||
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
|
||||
|
||||
return gst_pad_try_relink_filtered_func (realsrc, realsink,
|
||||
filtercaps, TRUE);
|
||||
filtercaps, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1686,8 +1732,9 @@ gst_pad_relink_filtered (GstPad *srcpad, GstPad *sinkpad,
|
|||
g_return_val_if_fail (GST_RPAD_PEER (realsrc) != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_RPAD_PEER (realsink) == realsrc, FALSE);
|
||||
|
||||
if (! gst_pad_try_relink_filtered_func (realsrc, realsink,
|
||||
filtercaps, TRUE)) {
|
||||
if (!gst_pad_try_relink_filtered_func (realsrc, realsink,
|
||||
filtercaps, TRUE))
|
||||
{
|
||||
gst_pad_unlink (srcpad, GST_PAD (GST_PAD_PEER (srcpad)));
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1729,7 +1776,9 @@ gst_pad_proxy_link (GstPad *pad, GstCaps *caps)
|
|||
*
|
||||
* Gets the capabilities of this pad.
|
||||
*
|
||||
* Returns: the #GstCaps of this pad.
|
||||
* Returns: the #GstCaps of this pad. This function potentially
|
||||
* returns a floating caps, so use gst_caps_sink to get rid of
|
||||
* it.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_pad_get_caps (GstPad *pad)
|
||||
|
@ -1744,6 +1793,8 @@ gst_pad_get_caps (GstPad *pad)
|
|||
GST_DEBUG (GST_CAT_CAPS, "get pad caps of %s:%s (%p)",
|
||||
GST_DEBUG_PAD_NAME (realpad), realpad);
|
||||
|
||||
/* note that we will not _ref the caps here as this function might be
|
||||
* called recursively */
|
||||
if (GST_PAD_CAPS (realpad)) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "using pad real caps %p", GST_PAD_CAPS (realpad));
|
||||
return GST_PAD_CAPS (realpad);
|
||||
|
@ -1769,7 +1820,8 @@ gst_pad_get_caps (GstPad *pad)
|
|||
*
|
||||
* Gets the template capabilities of this pad.
|
||||
*
|
||||
* Returns: the template #GstCaps of this pad.
|
||||
* Returns: the template #GstCaps of this pad, unref the caps
|
||||
* if you no longer need it.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_pad_get_pad_template_caps (GstPad *pad)
|
||||
|
@ -1778,7 +1830,7 @@ gst_pad_get_pad_template_caps (GstPad *pad)
|
|||
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
|
||||
|
||||
if (GST_PAD_PAD_TEMPLATE (pad))
|
||||
return GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad));
|
||||
return gst_caps_ref (GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1790,7 +1842,8 @@ gst_pad_get_pad_template_caps (GstPad *pad)
|
|||
*
|
||||
* Gets the capability with the given name from this pad template.
|
||||
*
|
||||
* Returns: the #GstCaps, or NULL if not found or in case of an error.
|
||||
* Returns: the #GstCaps, or NULL if not found or in case of an error. unref
|
||||
* the caps if you no longer need it.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
|
||||
|
@ -1803,7 +1856,7 @@ gst_pad_template_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
|
|||
if (!caps)
|
||||
return NULL;
|
||||
|
||||
return gst_caps_get_by_name (caps, name);
|
||||
return gst_caps_ref (gst_caps_get_by_name (caps, name));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1866,7 +1919,8 @@ gst_pad_get_peer (GstPad *pad)
|
|||
* Gets the capabilities of the allowed media types that can
|
||||
* flow through this pad. The caller must free the resulting caps.
|
||||
*
|
||||
* Returns: a newly allocated copy of the allowed #GstCaps.
|
||||
* Returns: the allowed #GstCaps of the pad link. unref the caps if
|
||||
* you no longer need it.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_pad_get_allowed_caps (GstPad *pad)
|
||||
|
@ -1879,7 +1933,7 @@ gst_pad_get_allowed_caps (GstPad *pad)
|
|||
GST_DEBUG (GST_CAT_PROPERTIES, "get allowed caps of %s:%s",
|
||||
GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
caps = gst_caps_copy (GST_RPAD_FILTER (pad));
|
||||
caps = gst_caps_ref (GST_RPAD_FILTER (pad));
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
@ -1909,7 +1963,7 @@ gst_pad_recalc_allowed_caps (GstPad *pad)
|
|||
peer = GST_RPAD_PEER (pad);
|
||||
if (peer)
|
||||
return gst_pad_try_relink_filtered (pad, GST_PAD (peer),
|
||||
GST_RPAD_APPFILTER (pad));
|
||||
GST_RPAD_APPFILTER (pad));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1992,6 +2046,9 @@ gst_real_pad_dispose (GObject *object)
|
|||
g_list_free (GST_REAL_PAD(pad)->ghostpads);
|
||||
}
|
||||
|
||||
gst_caps_replace (&GST_PAD_CAPS (pad), NULL);
|
||||
gst_caps_replace (&GST_RPAD_APPFILTER (pad), NULL);
|
||||
|
||||
if (GST_IS_ELEMENT (GST_OBJECT_PARENT (pad))) {
|
||||
GST_DEBUG (GST_CAT_REFCOUNTING, "removing pad from element '%s'",
|
||||
GST_OBJECT_NAME (GST_OBJECT (GST_ELEMENT (GST_OBJECT_PARENT (pad)))));
|
||||
|
@ -2319,6 +2376,7 @@ gst_pad_selectv (GstPad *pad, ...)
|
|||
*/
|
||||
static void gst_pad_template_class_init (GstPadTemplateClass *klass);
|
||||
static void gst_pad_template_init (GstPadTemplate *templ);
|
||||
static void gst_pad_template_dispose (GObject *object);
|
||||
|
||||
GType
|
||||
gst_pad_template_get_type (void)
|
||||
|
@ -2356,6 +2414,8 @@ gst_pad_template_class_init (GstPadTemplateClass *klass)
|
|||
NULL, NULL, gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
gobject_class->dispose = gst_pad_template_dispose;
|
||||
|
||||
gstobject_class->path_string_separator = "*";
|
||||
}
|
||||
|
||||
|
@ -2364,6 +2424,17 @@ gst_pad_template_init (GstPadTemplate *templ)
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pad_template_dispose (GObject *object)
|
||||
{
|
||||
GstPadTemplate *templ = GST_PAD_TEMPLATE (object);
|
||||
|
||||
g_free (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ));
|
||||
gst_caps_unref (GST_PAD_TEMPLATE_CAPS (templ));
|
||||
|
||||
G_OBJECT_CLASS (padtemplate_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
/* ALWAYS padtemplates cannot have conversion specifications, it doesn't make
|
||||
* sense.
|
||||
* SOMETIMES padtemplates can do whatever they want, they are provided by the
|
||||
|
@ -2442,14 +2513,19 @@ gst_pad_template_new (const gchar *name_template,
|
|||
|
||||
va_start (var_args, caps);
|
||||
|
||||
GST_FLAG_SET (GST_OBJECT (new), GST_PAD_TEMPLATE_FIXED);
|
||||
while (caps) {
|
||||
new->fixed &= caps->fixed;
|
||||
thecaps = gst_caps_append (thecaps, gst_caps_ref (caps));
|
||||
if (!GST_CAPS_IS_FIXED (caps)) {
|
||||
GST_FLAG_UNSET (GST_OBJECT (new), GST_PAD_TEMPLATE_FIXED);
|
||||
}
|
||||
thecaps = gst_caps_append (thecaps, caps);
|
||||
caps = va_arg (var_args, GstCaps*);
|
||||
}
|
||||
va_end (var_args);
|
||||
|
||||
GST_PAD_TEMPLATE_CAPS (new) = thecaps;
|
||||
gst_caps_ref (thecaps);
|
||||
gst_caps_sink (thecaps);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -2460,14 +2536,15 @@ gst_pad_template_new (const gchar *name_template,
|
|||
*
|
||||
* Gets the capabilities of the pad template.
|
||||
*
|
||||
* Returns: the #GstCaps of the pad template.
|
||||
* Returns: the #GstCaps of the pad template. unref the caps
|
||||
* after use.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_pad_template_get_caps (GstPadTemplate *templ)
|
||||
{
|
||||
g_return_val_if_fail (templ != NULL, NULL);
|
||||
|
||||
return GST_PAD_TEMPLATE_CAPS (templ);
|
||||
return gst_caps_ref (GST_PAD_TEMPLATE_CAPS (templ));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
34
gst/gstpad.h
34
gst/gstpad.h
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -262,6 +262,9 @@ make_links (graph_t *g, GError **error)
|
|||
a = c->src_pads;
|
||||
b = c->sink_pads;
|
||||
caps = c->caps;
|
||||
gst_caps_ref (caps);
|
||||
gst_caps_sink (caps);
|
||||
|
||||
gst_caps_debug (caps, "foo");
|
||||
/* g_print ("a: %p, b: %p\n", a, b); */
|
||||
if (a && b) {
|
||||
|
@ -363,6 +366,7 @@ make_links (graph_t *g, GError **error)
|
|||
}
|
||||
}
|
||||
next:
|
||||
gst_caps_unref (caps);
|
||||
l = g_list_next (l);
|
||||
}
|
||||
|
||||
|
|
414
gst/gstprops.c
414
gst/gstprops.c
|
@ -25,10 +25,17 @@
|
|||
|
||||
#include "gstlog.h"
|
||||
#include "gstprops.h"
|
||||
#include "gstmemchunk.h"
|
||||
|
||||
/* #define GST_WITH_ALLOC_TRACE */
|
||||
#include "gsttrace.h"
|
||||
|
||||
GType _gst_props_type;
|
||||
GType _gst_props_entry_type;
|
||||
|
||||
static GstAllocTrace *_props_trace;
|
||||
static GstAllocTrace *_entries_trace;
|
||||
|
||||
#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_TYPE)
|
||||
|
||||
struct _GstPropsEntry {
|
||||
|
@ -60,11 +67,8 @@ struct _GstPropsEntry {
|
|||
} data;
|
||||
};
|
||||
|
||||
static GMemChunk *_gst_props_entries_chunk;
|
||||
static GMutex *_gst_props_entries_chunk_lock;
|
||||
|
||||
static GMemChunk *_gst_props_chunk;
|
||||
static GMutex *_gst_props_chunk_lock;
|
||||
static GstMemChunk *_gst_props_entries_chunk;
|
||||
static GstMemChunk *_gst_props_chunk;
|
||||
|
||||
static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
|
||||
static GList* gst_props_list_copy (GList *propslist);
|
||||
|
@ -84,9 +88,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;
|
||||
|
@ -98,7 +99,10 @@ transform_func (const GValue *src_value,
|
|||
break;
|
||||
case GST_PROPS_BOOLEAN_TYPE:
|
||||
g_string_append_printf (result, "%s=(boolean) %s", name,
|
||||
(entry->data.bool_data ? "TRUE" : "FALSE"));
|
||||
(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,21 +115,20 @@ transform_func (const GValue *src_value,
|
|||
}
|
||||
}
|
||||
dest_value->data[0].v_pointer = result->str;
|
||||
g_string_free (result, FALSE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gst_props_initialize (void)
|
||||
{
|
||||
_gst_props_entries_chunk = g_mem_chunk_new ("GstPropsEntries",
|
||||
sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 256,
|
||||
_gst_props_entries_chunk = gst_mem_chunk_new ("GstPropsEntries",
|
||||
sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 1024,
|
||||
G_ALLOC_AND_FREE);
|
||||
_gst_props_entries_chunk_lock = g_mutex_new ();
|
||||
|
||||
_gst_props_chunk = g_mem_chunk_new ("GstProps",
|
||||
_gst_props_chunk = gst_mem_chunk_new ("GstProps",
|
||||
sizeof (GstProps), sizeof (GstProps) * 256,
|
||||
G_ALLOC_AND_FREE);
|
||||
_gst_props_chunk_lock = g_mutex_new ();
|
||||
|
||||
_gst_props_type = g_boxed_type_register_static ("GstProps",
|
||||
(GBoxedCopyFunc) gst_props_ref,
|
||||
|
@ -138,6 +141,9 @@ _gst_props_initialize (void)
|
|||
_gst_props_entry_type = g_boxed_type_register_static ("GstPropsEntry",
|
||||
(GBoxedCopyFunc) gst_props_entry_copy,
|
||||
(GBoxedFreeFunc) gst_props_entry_destroy);
|
||||
|
||||
_props_trace = gst_alloc_trace_register (GST_PROPS_TRACE_NAME);
|
||||
_entries_trace = gst_alloc_trace_register (GST_PROPS_ENTRY_TRACE_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -147,34 +153,34 @@ gst_props_debug_entry (GstPropsEntry *entry)
|
|||
|
||||
switch (entry->propstype) {
|
||||
case GST_PROPS_INT_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d", name, entry->data.int_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: int %d", entry, name, entry->data.int_data);
|
||||
break;
|
||||
case GST_PROPS_FLOAT_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f", name, entry->data.float_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: float %f", entry, name, entry->data.float_data);
|
||||
break;
|
||||
case GST_PROPS_FOURCC_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %c%c%c%c", name,
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: fourcc %c%c%c%c", entry, name,
|
||||
(entry->data.fourcc_data>>0)&0xff,
|
||||
(entry->data.fourcc_data>>8)&0xff,
|
||||
(entry->data.fourcc_data>>16)&0xff,
|
||||
(entry->data.fourcc_data>>24)&0xff);
|
||||
break;
|
||||
case GST_PROPS_BOOLEAN_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d", name, entry->data.bool_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: bool %d", entry, name, entry->data.bool_data);
|
||||
break;
|
||||
case GST_PROPS_STRING_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: string \"%s\"", name, entry->data.string_data.string);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: string \"%s\"", entry, name, entry->data.string_data.string);
|
||||
break;
|
||||
case GST_PROPS_INT_RANGE_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d", name, entry->data.int_range_data.min,
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: int range %d-%d", entry, name, entry->data.int_range_data.min,
|
||||
entry->data.int_range_data.max);
|
||||
break;
|
||||
case GST_PROPS_FLOAT_RANGE_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f", name, entry->data.float_range_data.min,
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: %s: float range %f-%f", entry, name, entry->data.float_range_data.min,
|
||||
entry->data.float_range_data.max);
|
||||
break;
|
||||
case GST_PROPS_LIST_TYPE:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "[list]");
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%p: [list]", entry);
|
||||
{
|
||||
GList *entries = entry->data.list_data.entries;
|
||||
|
||||
|
@ -185,7 +191,7 @@ gst_props_debug_entry (GstPropsEntry *entry)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown property type %d", entry->propstype);
|
||||
g_warning ("unknown property type %d at %p", entry->propstype, entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -302,15 +308,16 @@ gst_props_alloc_entry (void)
|
|||
{
|
||||
GstPropsEntry *entry;
|
||||
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
entry = g_mem_chunk_alloc (_gst_props_entries_chunk);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
entry = gst_mem_chunk_alloc (_gst_props_entries_chunk);
|
||||
gst_alloc_trace_new (_entries_trace, entry);
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "new entry %p", entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void
|
||||
gst_props_entry_destroy (GstPropsEntry *entry)
|
||||
static void
|
||||
gst_props_entry_clean (GstPropsEntry *entry)
|
||||
{
|
||||
switch (entry->propstype) {
|
||||
case GST_PROPS_STRING_TYPE:
|
||||
|
@ -330,9 +337,17 @@ gst_props_entry_destroy (GstPropsEntry *entry)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
}
|
||||
|
||||
void
|
||||
gst_props_entry_destroy (GstPropsEntry *entry)
|
||||
{
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "destroy entry %p", entry);
|
||||
|
||||
gst_props_entry_clean (entry);
|
||||
|
||||
gst_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||
gst_alloc_trace_free (_entries_trace, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,17 +362,52 @@ gst_props_empty_new (void)
|
|||
{
|
||||
GstProps *props;
|
||||
|
||||
g_mutex_lock (_gst_props_chunk_lock);
|
||||
props = g_mem_chunk_alloc (_gst_props_chunk);
|
||||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
props = gst_mem_chunk_alloc (_gst_props_chunk);
|
||||
gst_alloc_trace_new (_props_trace, props);
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "new %p", props);
|
||||
|
||||
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 props and 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,12 +421,52 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_remove_entry:
|
||||
* @props: the property to remove the entry from
|
||||
* @entry: the entry to remove
|
||||
*
|
||||
* Removes the given propsentry from the props.
|
||||
*/
|
||||
void
|
||||
gst_props_remove_entry (GstProps *props, GstPropsEntry *entry)
|
||||
{
|
||||
g_return_if_fail (props != NULL);
|
||||
g_return_if_fail (entry != NULL);
|
||||
|
||||
props->properties = g_list_remove (props->properties, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_remove_entry_by_name:
|
||||
* @props: the property to remove the entry from
|
||||
* @name: the name of the entry to remove
|
||||
*
|
||||
* Removes the propsentry with the given name from the props.
|
||||
*/
|
||||
void
|
||||
gst_props_remove_entry_by_name (GstProps *props, const gchar *name)
|
||||
{
|
||||
GList *lentry;
|
||||
GQuark quark;
|
||||
|
||||
g_return_if_fail (props != NULL);
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
quark = g_quark_from_string (name);
|
||||
|
||||
lentry = g_list_find_custom (props->properties, GINT_TO_POINTER (quark), props_find_func);
|
||||
if (lentry) {
|
||||
gst_props_remove_entry (props, (GstPropsEntry *)lentry->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_new:
|
||||
* @firstname: the first property name
|
||||
|
@ -413,6 +503,8 @@ gst_props_debug (GstProps *props)
|
|||
{
|
||||
GList *propslist = props->properties;
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "props %p, refcount %d, flags %d", props, props->refcount, props->flags);
|
||||
|
||||
while (propslist) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
|
||||
|
||||
|
@ -434,7 +526,7 @@ gst_props_debug (GstProps *props)
|
|||
* Returns: TRUE if the entries were merged, FALSE otherwise.
|
||||
*/
|
||||
static gboolean
|
||||
gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
|
||||
gst_props_merge_int_entries(GstPropsEntry *newentry, GstPropsEntry *oldentry)
|
||||
{
|
||||
gint new_min, new_max, old_min, old_max;
|
||||
gboolean can_merge = FALSE;
|
||||
|
@ -501,21 +593,20 @@ gst_props_merge_int_entries(GstPropsEntry * newentry, GstPropsEntry * oldentry)
|
|||
*
|
||||
* Returns: a pointer to a list with the new entry added.
|
||||
*/
|
||||
static GList *
|
||||
gst_props_add_to_int_list (GList * entries, GstPropsEntry * newentry)
|
||||
static GList*
|
||||
gst_props_add_to_int_list (GList *entries, GstPropsEntry *newentry)
|
||||
{
|
||||
GList * i;
|
||||
GList *i;
|
||||
|
||||
i = entries;
|
||||
while (i) {
|
||||
GstPropsEntry * oldentry = (GstPropsEntry *)(i->data);
|
||||
GstPropsEntry *oldentry = (GstPropsEntry *)(i->data);
|
||||
gboolean merged = gst_props_merge_int_entries(newentry, oldentry);
|
||||
|
||||
if (merged) {
|
||||
/* replace the existing one with the merged one */
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, oldentry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
gst_props_entry_destroy (oldentry);
|
||||
|
||||
entries = g_list_remove_link (entries, i);
|
||||
g_list_free_1 (i);
|
||||
|
||||
|
@ -634,30 +725,24 @@ gst_props_newv (const gchar *firstname, va_list var_args)
|
|||
|
||||
/* if list was of size 1, replace the list by a the item it contains */
|
||||
if (g_list_length(list_entry->data.list_data.entries) == 1) {
|
||||
GstPropsEntry * subentry = (GstPropsEntry *)(list_entry->data.list_data.entries->data);
|
||||
GstPropsEntry *subentry = (GstPropsEntry *)(list_entry->data.list_data.entries->data);
|
||||
list_entry->propstype = subentry->propstype;
|
||||
list_entry->data = subentry->data;
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, subentry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
gst_props_entry_destroy (subentry);
|
||||
}
|
||||
else {
|
||||
list_entry->data.list_data.entries =
|
||||
g_list_reverse (list_entry->data.list_data.entries);
|
||||
}
|
||||
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
gst_props_entry_destroy (entry);
|
||||
inlist = FALSE;
|
||||
list_entry = NULL;
|
||||
prop_name = va_arg (var_args, gchar*);
|
||||
continue;
|
||||
default:
|
||||
g_warning ("unknown property type found %d for '%s'\n", entry->propstype, prop_name);
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
gst_props_entry_destroy (entry);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -721,9 +806,8 @@ gst_props_set (GstProps *props, const gchar *name, ...)
|
|||
entry = (GstPropsEntry *)lentry->data;
|
||||
|
||||
va_start (var_args, name);
|
||||
|
||||
gst_props_entry_clean (entry);
|
||||
GST_PROPS_ENTRY_FILL (entry, var_args);
|
||||
|
||||
va_end (var_args);
|
||||
}
|
||||
else {
|
||||
|
@ -740,17 +824,27 @@ gst_props_set (GstProps *props, const gchar *name, ...)
|
|||
*
|
||||
* Decrease the refcount of the property structure, destroying
|
||||
* the property if the refcount is 0.
|
||||
*
|
||||
* Returns: handle to unrefed props or NULL when it was
|
||||
* destroyed.
|
||||
*/
|
||||
void
|
||||
GstProps*
|
||||
gst_props_unref (GstProps *props)
|
||||
{
|
||||
if (props == NULL)
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (props->refcount > 0, NULL);
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "unref %p (%d->%d)", props, props->refcount, props->refcount-1);
|
||||
props->refcount--;
|
||||
|
||||
if (props->refcount == 0)
|
||||
if (props->refcount == 0) {
|
||||
gst_props_destroy (props);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -758,15 +852,44 @@ gst_props_unref (GstProps *props)
|
|||
* @props: the props to ref
|
||||
*
|
||||
* Increase the refcount of the property structure.
|
||||
*
|
||||
* Returns: handle to refed props.
|
||||
*/
|
||||
void
|
||||
GstProps*
|
||||
gst_props_ref (GstProps *props)
|
||||
{
|
||||
g_return_if_fail (props != NULL);
|
||||
if (props == NULL)
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (props->refcount > 0, NULL);
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "ref %p (%d->%d)", props, props->refcount, props->refcount+1);
|
||||
|
||||
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;
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "sink %p", props);
|
||||
|
||||
if (GST_PROPS_IS_FLOATING (props)) {
|
||||
GST_PROPS_FLAG_UNSET (props, GST_PROPS_FLOATING);
|
||||
gst_props_unref (props);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_destroy:
|
||||
|
@ -791,26 +914,31 @@ gst_props_destroy (GstProps *props)
|
|||
}
|
||||
g_list_free (props->properties);
|
||||
|
||||
g_mutex_lock (_gst_props_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_chunk, props);
|
||||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
gst_mem_chunk_free (_gst_props_chunk, props);
|
||||
gst_alloc_trace_free (_props_trace, props);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy entries
|
||||
*/
|
||||
GstPropsEntry*
|
||||
gst_props_entry_copy (GstPropsEntry *entry)
|
||||
gst_props_entry_copy (const GstPropsEntry *entry)
|
||||
{
|
||||
GstPropsEntry *newentry;
|
||||
|
||||
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 +980,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_FLOATING;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -1076,7 +1204,7 @@ gst_props_getv (GstProps *props, gboolean safe, gchar *first_name, va_list var_a
|
|||
gboolean result;
|
||||
|
||||
if (!entry) return FALSE;
|
||||
GST_PROPS_ENTRY_READ (entry, var_args, FALSE, &result);
|
||||
GST_PROPS_ENTRY_READ (entry, var_args, safe, &result);
|
||||
if (!result) return FALSE;
|
||||
|
||||
first_name = va_arg (var_args, gchar *);
|
||||
|
@ -1091,8 +1219,9 @@ gst_props_getv (GstProps *props, gboolean safe, gchar *first_name, va_list var_a
|
|||
* @...: a pointer to a datastructure that can hold the value.
|
||||
*
|
||||
* Gets the contents of the props into given key/value pairs.
|
||||
* Make sure you pass a NULL terminated list.
|
||||
*
|
||||
* Returns: TRUE is the props entry could be fetched.
|
||||
* Returns: TRUE if all of the props entries could be fetched.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_get (GstProps *props, gchar *first_name, ...)
|
||||
|
@ -1115,7 +1244,7 @@ gst_props_get (GstProps *props, gchar *first_name, ...)
|
|||
*
|
||||
* Gets the contents of the props into given key/value pairs.
|
||||
*
|
||||
* Returns: TRUE is the props entry could be fetched.
|
||||
* Returns: TRUE if all of the props entries could be fetched.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_get_safe (GstProps *props, gchar *first_name, ...)
|
||||
|
@ -1138,7 +1267,7 @@ gst_props_get_safe (GstProps *props, gchar *first_name, ...)
|
|||
* Get the contents of the entry into the given gint.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_int (const GstPropsEntry *entry, gint *val)
|
||||
|
@ -1154,7 +1283,7 @@ gst_props_entry_get_int (const GstPropsEntry *entry, gint *val)
|
|||
* Get the contents of the entry into the given gfloat.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_float (const GstPropsEntry *entry, gfloat *val)
|
||||
|
@ -1170,7 +1299,7 @@ gst_props_entry_get_float (const GstPropsEntry *entry, gfloat *val)
|
|||
* Get the contents of the entry into the given guint32.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_fourcc_int (const GstPropsEntry *entry, guint32 *val)
|
||||
|
@ -1186,7 +1315,7 @@ gst_props_entry_get_fourcc_int (const GstPropsEntry *entry, guint32 *val)
|
|||
* Get the contents of the entry into the given gboolean.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_boolean (const GstPropsEntry *entry, gboolean *val)
|
||||
|
@ -1202,7 +1331,7 @@ gst_props_entry_get_boolean (const GstPropsEntry *entry, gboolean *val)
|
|||
* Get the contents of the entry into the given gchar*.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_string (const GstPropsEntry *entry, const gchar **val)
|
||||
|
@ -1219,7 +1348,7 @@ gst_props_entry_get_string (const GstPropsEntry *entry, const gchar **val)
|
|||
* Get the contents of the entry into the given gints.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_int_range (const GstPropsEntry *entry, gint *min, gint *max)
|
||||
|
@ -1236,7 +1365,7 @@ gst_props_entry_get_int_range (const GstPropsEntry *entry, gint *min, gint *max)
|
|||
* Get the contents of the entry into the given gfloats.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_float_range (const GstPropsEntry *entry, gfloat *min, gfloat *max)
|
||||
|
@ -1252,7 +1381,7 @@ gst_props_entry_get_float_range (const GstPropsEntry *entry, gfloat *min, gfloat
|
|||
* Get the contents of the entry into the given GList.
|
||||
*
|
||||
* Returns: TRUE is the value could be fetched. FALSE if the
|
||||
* entry is not of given type.
|
||||
* entry is not of given type or did not exist.
|
||||
*/
|
||||
gboolean
|
||||
gst_props_entry_get_list (const GstPropsEntry *entry, const GList **val)
|
||||
|
@ -1530,7 +1659,7 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
if (intersectentry) {
|
||||
if (intersectentry->propstype == GST_PROPS_LIST_TYPE) {
|
||||
intersection = g_list_concat (intersection,
|
||||
g_list_copy (intersectentry->data.list_data.entries));
|
||||
intersectentry->data.list_data.entries);
|
||||
/* set the list to NULL because the entries are concatenated to the above
|
||||
* list and we don't want to free them */
|
||||
intersectentry->data.list_data.entries = NULL;
|
||||
|
@ -1590,7 +1719,7 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
result->propstype = GST_PROPS_LIST_TYPE;
|
||||
result->data.list_data.entries = NULL;
|
||||
while (entries) {
|
||||
GstPropsEntry * this = (GstPropsEntry *)entries->data;
|
||||
GstPropsEntry *this = (GstPropsEntry *)entries->data;
|
||||
if (this->propstype != GST_PROPS_INT_TYPE) {
|
||||
/* no hope, this list doesn't even contain ints! */
|
||||
gst_props_entry_destroy (result);
|
||||
|
@ -1598,18 +1727,24 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
break;
|
||||
}
|
||||
if (this->data.int_data >= entry1->data.int_range_data.min &&
|
||||
this->data.int_data <= entry1->data.int_range_data.max) {
|
||||
result->data.list_data.entries = g_list_append (result->data.list_data.entries,
|
||||
gst_props_entry_copy (this));
|
||||
this->data.int_data <= entry1->data.int_range_data.max)
|
||||
{
|
||||
/* prepend and reverse at the end */
|
||||
result->data.list_data.entries = g_list_prepend (result->data.list_data.entries,
|
||||
gst_props_entry_copy (this));
|
||||
}
|
||||
entries = g_list_next (entries);
|
||||
}
|
||||
if (result) {
|
||||
result->data.list_data.entries = g_list_reverse (result->data.list_data.entries);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_PROPS_INT_TYPE:
|
||||
{
|
||||
if (entry1->data.int_range_data.min <= entry2->data.int_data &&
|
||||
entry1->data.int_range_data.max >= entry2->data.int_data) {
|
||||
entry1->data.int_range_data.max >= entry2->data.int_data)
|
||||
{
|
||||
result = gst_props_entry_copy (entry2);
|
||||
}
|
||||
break;
|
||||
|
@ -1644,7 +1779,8 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
}
|
||||
case GST_PROPS_FLOAT_TYPE:
|
||||
if (entry1->data.float_range_data.min <= entry2->data.float_data &&
|
||||
entry1->data.float_range_data.max >= entry2->data.float_data) {
|
||||
entry1->data.float_range_data.max >= entry2->data.float_data)
|
||||
{
|
||||
result = gst_props_entry_copy (entry2);
|
||||
}
|
||||
default:
|
||||
|
@ -1706,6 +1842,17 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* when running over the entries in sorted order we can
|
||||
* optimize addition with _prepend and a reverse at the end */
|
||||
#define gst_props_entry_add_sorted_prepend(props, entry) \
|
||||
G_STMT_START { \
|
||||
/* avoid double evaluation of input */ \
|
||||
GstPropsEntry *toadd = (entry); \
|
||||
if (GST_PROPS_ENTRY_IS_VARIABLE (toadd)) \
|
||||
GST_PROPS_FLAG_UNSET ((props), GST_PROPS_FIXED); \
|
||||
props->properties = g_list_prepend ((props)->properties, toadd); \
|
||||
} G_STMT_END
|
||||
|
||||
/**
|
||||
* gst_props_intersect:
|
||||
* @props1: a property
|
||||
|
@ -1714,7 +1861,8 @@ gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
|||
* Calculates the intersection bewteen two GstProps.
|
||||
*
|
||||
* Returns: a GstProps with the intersection or NULL if the
|
||||
* intersection is empty.
|
||||
* intersection is empty. The new GstProps is floating and must
|
||||
* be unreffed afetr use.
|
||||
*/
|
||||
GstProps*
|
||||
gst_props_intersect (GstProps *props1, GstProps *props2)
|
||||
|
@ -1725,11 +1873,10 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
|
|||
GList *leftovers;
|
||||
GstPropsEntry *iprops = NULL;
|
||||
|
||||
intersection = gst_props_empty_new ();
|
||||
intersection->fixed = TRUE;
|
||||
|
||||
g_return_val_if_fail (props1 != NULL, NULL);
|
||||
g_return_val_if_fail (props2 != NULL, NULL);
|
||||
|
||||
intersection = gst_props_empty_new ();
|
||||
|
||||
props1list = props1->properties;
|
||||
props2list = props2->properties;
|
||||
|
@ -1742,74 +1889,47 @@ gst_props_intersect (GstProps *props1, GstProps *props2)
|
|||
entry2 = (GstPropsEntry *)props2list->data;
|
||||
|
||||
while (entry1->propid < entry2->propid) {
|
||||
GstPropsEntry *toadd;
|
||||
|
||||
/* FIXME: this needs more explanation;
|
||||
* I've had format "int" < format "int" ! */
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "source is more specific in \"%s\"",
|
||||
g_quark_to_string (entry1->propid));
|
||||
|
||||
toadd = gst_props_entry_copy (entry1);
|
||||
if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
|
||||
intersection->fixed = FALSE;
|
||||
|
||||
intersection->properties = g_list_prepend (intersection->properties, toadd);
|
||||
gst_props_entry_add_sorted_prepend (intersection, gst_props_entry_copy (entry1));
|
||||
|
||||
props1list = g_list_next (props1list);
|
||||
if (props1list)
|
||||
entry1 = (GstPropsEntry *)props1list->data;
|
||||
else
|
||||
if (!props1list)
|
||||
goto end;
|
||||
|
||||
entry1 = (GstPropsEntry *)props1list->data;
|
||||
}
|
||||
while (entry1->propid > entry2->propid) {
|
||||
GstPropsEntry *toadd;
|
||||
|
||||
toadd = gst_props_entry_copy (entry2);
|
||||
if (GST_PROPS_ENTRY_IS_VARIABLE (toadd))
|
||||
intersection->fixed = FALSE;
|
||||
|
||||
intersection->properties = g_list_prepend (intersection->properties, toadd);
|
||||
gst_props_entry_add_sorted_prepend (intersection, gst_props_entry_copy (entry2));
|
||||
|
||||
props2list = g_list_next (props2list);
|
||||
if (props2list)
|
||||
entry2 = (GstPropsEntry *)props2list->data;
|
||||
else
|
||||
if (!props2list)
|
||||
goto end;
|
||||
|
||||
entry2 = (GstPropsEntry *)props2list->data;
|
||||
}
|
||||
/* at this point we are talking about the same property */
|
||||
iprops = gst_props_entry_intersect (entry1, entry2);
|
||||
|
||||
if (iprops) {
|
||||
if (GST_PROPS_ENTRY_IS_VARIABLE (iprops))
|
||||
intersection->fixed = FALSE;
|
||||
intersection->properties = g_list_prepend (intersection->properties, iprops);
|
||||
}
|
||||
else {
|
||||
if (!iprops) {
|
||||
/* common properties did not intersect, intersection is empty */
|
||||
gst_props_unref (intersection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_props_entry_add_sorted_prepend (intersection, iprops);
|
||||
|
||||
props1list = g_list_next (props1list);
|
||||
props2list = g_list_next (props2list);
|
||||
}
|
||||
|
||||
end:
|
||||
/* at this point one of the lists could contain leftover properties */
|
||||
if (props1list)
|
||||
leftovers = props1list;
|
||||
else if (props2list)
|
||||
/* at this point one of the lists could contain leftover properties, while
|
||||
* the other one is NULL */
|
||||
leftovers = props1list;
|
||||
if (!leftovers)
|
||||
leftovers = props2list;
|
||||
else
|
||||
leftovers = NULL;
|
||||
|
||||
while (leftovers) {
|
||||
GstPropsEntry *entry;
|
||||
|
||||
entry = (GstPropsEntry *) leftovers->data;
|
||||
if (GST_PROPS_ENTRY_IS_VARIABLE (entry))
|
||||
intersection->fixed = FALSE;
|
||||
intersection->properties = g_list_prepend (intersection->properties, gst_props_entry_copy (entry));
|
||||
|
||||
gst_props_entry_add_sorted_prepend (intersection,
|
||||
gst_props_entry_copy ((GstPropsEntry *) leftovers->data));
|
||||
leftovers = g_list_next (leftovers);
|
||||
}
|
||||
|
||||
|
@ -1825,7 +1945,8 @@ end:
|
|||
* Unrolls all lists in the given GstProps. This is usefull if you
|
||||
* want to loop over the props.
|
||||
*
|
||||
* Returns: A GList with the unrolled props entries.
|
||||
* Returns: A GList with the unrolled props entries. g_list_free
|
||||
* after usage.
|
||||
*/
|
||||
GList*
|
||||
gst_props_normalize (GstProps *props)
|
||||
|
@ -1850,11 +1971,11 @@ gst_props_normalize (GstProps *props)
|
|||
GstProps *newprops;
|
||||
GList *lentry;
|
||||
|
||||
newprops = gst_props_empty_new ();
|
||||
newprops->properties = gst_props_list_copy (props->properties);
|
||||
/* FIXME fixed flags is probably messed up here */
|
||||
newprops = gst_props_copy (props);
|
||||
lentry = g_list_find_custom (newprops->properties, GINT_TO_POINTER (list_entry->propid), props_find_func);
|
||||
if (lentry) {
|
||||
GList *new_list = NULL;
|
||||
GList *new_list;
|
||||
|
||||
new_entry = (GstPropsEntry *) lentry->data;
|
||||
memcpy (new_entry, list_entry, sizeof (GstPropsEntry));
|
||||
|
@ -1863,6 +1984,7 @@ gst_props_normalize (GstProps *props)
|
|||
result = g_list_concat (new_list, result);
|
||||
}
|
||||
else {
|
||||
/* FIXME append or prepend */
|
||||
result = g_list_append (result, newprops);
|
||||
}
|
||||
|
||||
|
@ -1875,11 +1997,11 @@ gst_props_normalize (GstProps *props)
|
|||
entries = g_list_next (entries);
|
||||
}
|
||||
if (!result) {
|
||||
/* no result, create list with input props */
|
||||
result = g_list_prepend (result, props);
|
||||
}
|
||||
else {
|
||||
result = g_list_reverse (result);
|
||||
gst_props_unref (props);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2073,9 +2195,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
|
|||
entry->data.string_data.string = xmlGetProp (field, "value");
|
||||
}
|
||||
else {
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
g_mem_chunk_free (_gst_props_entries_chunk, entry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
gst_props_entry_destroy (entry);
|
||||
entry = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstProps GstProps;
|
||||
extern GType _gst_props_type;
|
||||
|
||||
#define GST_PROPS_TRACE_NAME "GstProps"
|
||||
|
||||
#define GST_TYPE_PROPS (_gst_props_type)
|
||||
|
||||
typedef enum {
|
||||
|
@ -78,56 +80,91 @@ typedef enum {
|
|||
#define GST_PROPS_INT_NEGATIVE GST_PROPS_INT_RANGE(G_MININT,0)
|
||||
#define GST_PROPS_INT_ANY GST_PROPS_INT_RANGE(G_MININT,G_MAXINT)
|
||||
|
||||
/* propsentries are private */
|
||||
typedef struct _GstPropsEntry GstPropsEntry;
|
||||
extern GType _gst_props_entry_type;
|
||||
|
||||
#define GST_PROPS_ENTRY_TRACE_NAME "GstPropsEntry"
|
||||
|
||||
#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 */
|
||||
void _gst_props_initialize (void);
|
||||
|
||||
/* creating new properties */
|
||||
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);
|
||||
|
||||
/* dump property debug info to the log */
|
||||
void gst_props_debug (GstProps *props);
|
||||
|
||||
/* copy */
|
||||
GstProps* gst_props_copy (GstProps *props);
|
||||
GstProps* gst_props_copy_on_write (GstProps *props);
|
||||
|
||||
GstProps* gst_props_merge (GstProps *props, GstProps *tomerge);
|
||||
|
||||
/* check if fromprops is subset of toprops */
|
||||
gboolean gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops);
|
||||
|
||||
/* operation on props */
|
||||
GstProps* gst_props_merge (GstProps *props, GstProps *tomerge);
|
||||
GstProps* gst_props_intersect (GstProps *props1, GstProps *props2);
|
||||
GList* gst_props_normalize (GstProps *props);
|
||||
|
||||
/* modify entries */
|
||||
GstProps* gst_props_set (GstProps *props, const gchar *name, ...);
|
||||
gboolean gst_props_get (GstProps *props, gchar *first_name, ...);
|
||||
gboolean gst_props_get_safe (GstProps *props, gchar *first_name, ...);
|
||||
|
||||
/* query entries */
|
||||
gboolean gst_props_has_property (GstProps *props, const gchar *name);
|
||||
gboolean gst_props_has_property_typed (GstProps *props, const gchar *name, GstPropsType type);
|
||||
gboolean gst_props_has_fixed_property (GstProps *props, const gchar *name);
|
||||
|
||||
/* add/get entries */
|
||||
const GstPropsEntry* gst_props_get_entry (GstProps *props, const gchar *name);
|
||||
void gst_props_add_entry (GstProps *props, GstPropsEntry *entry);
|
||||
void gst_props_remove_entry (GstProps *props, GstPropsEntry *entry);
|
||||
void gst_props_remove_entry_by_name (GstProps *props, const gchar *name);
|
||||
|
||||
/* working with props entries */
|
||||
GstPropsEntry* gst_props_entry_new (const gchar *name, ...);
|
||||
|
||||
void gst_props_entry_destroy (GstPropsEntry *entry);
|
||||
GstPropsEntry* gst_props_entry_copy (GstPropsEntry *entry);
|
||||
GstPropsEntry* gst_props_entry_copy (const GstPropsEntry *entry);
|
||||
GstPropsType gst_props_entry_get_type (const GstPropsEntry *entry);
|
||||
const gchar* gst_props_entry_get_name (const GstPropsEntry *entry);
|
||||
gboolean gst_props_entry_is_fixed (const GstPropsEntry *entry);
|
||||
|
|
Loading…
Reference in a new issue