mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
Landed the new improved capsnegotiation system.
Original commit message from CVS: Landed the new improved capsnegotiation system. The main idea is to keep track of the possible data types that can pass through a connection. plugins can at any time inspect, adjust and refine these caps. plugins also get notified when something changes to the types so that they can reconfigure themselves. Look at the updated plugins and the soon to be finished doc.
This commit is contained in:
parent
0a0598f97a
commit
b2ee38575d
19 changed files with 1536 additions and 941 deletions
|
@ -187,10 +187,10 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink)
|
|||
|
||||
/* if we have a match, connect the pads */
|
||||
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
|
||||
!GST_PAD_CONNECTED (pad) && !GST_PAD_CONNECTED(sinkpad))
|
||||
!GST_PAD_IS_CONNECTED (pad) && !GST_PAD_IS_CONNECTED(sinkpad))
|
||||
{
|
||||
|
||||
if ((connected = gst_pad_try_connect (pad, sinkpad))) {
|
||||
if ((connected = gst_pad_connect (pad, sinkpad))) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -133,26 +133,6 @@ gst_identity_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (identity->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_identity_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
identity = GST_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, identity->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_identity_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
identity = GST_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, identity->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_init (GstIdentity *identity)
|
||||
{
|
||||
|
@ -160,11 +140,9 @@ gst_identity_init (GstIdentity *identity)
|
|||
gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
|
||||
gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
|
||||
gst_pad_set_bufferpool_function (identity->sinkpad, gst_identity_get_bufferpool);
|
||||
gst_pad_set_negotiate_function (identity->sinkpad, gst_identity_negotiate_sink);
|
||||
|
||||
identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
|
||||
gst_pad_set_negotiate_function (identity->srcpad, gst_identity_negotiate_src);
|
||||
|
||||
identity->loop_based = FALSE;
|
||||
identity->sleep_time = 0;
|
||||
|
|
|
@ -146,26 +146,6 @@ gst_statistics_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (statistics->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_statistics_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
statistics = GST_STATISTICS (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, statistics->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_statistics_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
statistics = GST_STATISTICS (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, statistics->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_init (GstStatistics *statistics)
|
||||
{
|
||||
|
@ -173,11 +153,9 @@ gst_statistics_init (GstStatistics *statistics)
|
|||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
|
||||
gst_pad_set_chain_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_chain));
|
||||
gst_pad_set_bufferpool_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_get_bufferpool));
|
||||
gst_pad_set_negotiate_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_sink));
|
||||
|
||||
statistics->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
|
||||
gst_pad_set_negotiate_function (statistics->srcpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_src));
|
||||
|
||||
statistics->timer = NULL;
|
||||
statistics->last_timer = NULL;
|
||||
|
|
|
@ -66,7 +66,6 @@ static void gst_tee_get_property (GObject *object, guint prop_id,
|
|||
|
||||
static void gst_tee_chain (GstPad *pad, GstBuffer *buf);
|
||||
|
||||
static GstPadNegotiateReturn gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
/*static guint gst_tee_signals[LAST_SIGNAL] = { 0 };*/
|
||||
|
@ -110,20 +109,44 @@ gst_tee_class_init (GstTeeClass *klass)
|
|||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_tee_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_tee_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_tee_request_new_pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_tee_sinkconnect (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstTee *tee;
|
||||
GList *pads;
|
||||
|
||||
tee = GST_TEE (gst_pad_get_parent (pad));
|
||||
|
||||
/* go through all the src pads */
|
||||
pads = gst_element_get_pad_list (GST_ELEMENT (tee));
|
||||
|
||||
while (pads) {
|
||||
GstPad *outpad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_IS_CONNECTED (outpad))
|
||||
continue;
|
||||
|
||||
if (!(gst_pad_try_set_caps (outpad, caps))) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tee_init (GstTee *tee)
|
||||
{
|
||||
tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
|
||||
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
|
||||
gst_pad_set_negotiate_function (tee->sinkpad, GST_DEBUG_FUNCPTR(gst_tee_handle_negotiate_sink));
|
||||
gst_pad_set_connect_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sinkconnect));
|
||||
|
||||
tee->silent = FALSE;
|
||||
}
|
||||
|
@ -152,7 +175,7 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
GST_PAD_ELEMENT_PRIVATE (srcpad) = NULL;
|
||||
|
||||
if (GST_PAD_CAPS (tee->sinkpad)) {
|
||||
gst_pad_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
|
||||
gst_pad_try_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
|
||||
}
|
||||
|
||||
return srcpad;
|
||||
|
@ -253,18 +276,18 @@ gst_tee_chain (GstPad *pad, GstBuffer *buf)
|
|||
GstEvent *event = GST_EVENT (GST_PAD_ELEMENT_PRIVATE (outpad));
|
||||
|
||||
GST_PAD_ELEMENT_PRIVATE (outpad) = NULL;
|
||||
if (GST_PAD_CONNECTED (outpad))
|
||||
if (GST_PAD_IS_CONNECTED (outpad))
|
||||
gst_pad_push (outpad, GST_BUFFER (event));
|
||||
else
|
||||
gst_event_free (event);
|
||||
}
|
||||
|
||||
if (!tee->silent) {
|
||||
gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu) \n",
|
||||
gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (outpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
if (GST_PAD_CONNECTED (outpad))
|
||||
if (GST_PAD_IS_CONNECTED (outpad))
|
||||
gst_pad_push (outpad, buf);
|
||||
else
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -279,30 +302,3 @@ gst_tee_factory_init (GstElementFactory *factory)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer* data)
|
||||
{
|
||||
GstCaps* tempcaps;
|
||||
gint i;
|
||||
GstTee* tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
GList *pads;
|
||||
|
||||
if (*caps==NULL)
|
||||
return GST_PAD_NEGOTIATE_FAIL;
|
||||
|
||||
/* go through all the src pads */
|
||||
pads = gst_element_get_pad_list (GST_ELEMENT (tee));
|
||||
|
||||
while (pads) {
|
||||
GstPad *outpad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_CONNECTED (outpad))
|
||||
continue;
|
||||
|
||||
if (!(gst_pad_set_caps (outpad, *caps))) {
|
||||
return GST_PAD_NEGOTIATE_FAIL;
|
||||
}
|
||||
}
|
||||
return GST_PAD_NEGOTIATE_AGREE;
|
||||
}
|
||||
|
|
200
gst/gstcaps.c
200
gst/gstcaps.c
|
@ -75,20 +75,40 @@ get_type_for_mime (const gchar *mime)
|
|||
GstCaps*
|
||||
gst_caps_new (const gchar *name, const gchar *mime, GstProps *props)
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
g_return_val_if_fail (mime != NULL, NULL);
|
||||
|
||||
return gst_caps_new_id (name, get_type_for_mime (mime), props);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_new_id:
|
||||
* @name: the name of this capability
|
||||
* @id: the id of the mime type
|
||||
* @props: the properties to add to this capability
|
||||
*
|
||||
* Create a new capability with the given mime typeid and properties.
|
||||
*
|
||||
* Returns: a new capability
|
||||
*/
|
||||
GstCaps*
|
||||
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->name = g_strdup (name);
|
||||
caps->id = get_type_for_mime (mime);
|
||||
caps->id = id;
|
||||
caps->properties = props;
|
||||
caps->next = NULL;
|
||||
caps->refcount = 1;
|
||||
caps->lock = g_mutex_new ();
|
||||
if (props)
|
||||
caps->fixed = props->fixed;
|
||||
else
|
||||
caps->fixed = TRUE;
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
@ -105,18 +125,43 @@ gst_caps_destroy (GstCaps *caps)
|
|||
{
|
||||
GstCaps *next;
|
||||
|
||||
g_return_if_fail (caps != NULL);
|
||||
|
||||
if (caps == NULL)
|
||||
return;
|
||||
|
||||
GST_CAPS_LOCK (caps);
|
||||
next = caps->next;
|
||||
g_free (caps->name);
|
||||
g_free (caps);
|
||||
GST_CAPS_UNLOCK (caps);
|
||||
|
||||
g_mutex_free (caps->lock);
|
||||
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);
|
||||
|
||||
if (next)
|
||||
gst_caps_unref (next);
|
||||
}
|
||||
|
||||
void
|
||||
gst_caps_debug (GstCaps *caps)
|
||||
{
|
||||
GST_DEBUG_ENTER ("caps debug");
|
||||
while (caps) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "caps: %p %s %s\n", caps, caps->name, gst_caps_get_mime (caps));
|
||||
|
||||
if (caps->properties) {
|
||||
gst_props_debug (caps->properties);
|
||||
}
|
||||
else {
|
||||
GST_DEBUG (GST_CAT_CAPS, "no properties\n");
|
||||
}
|
||||
|
||||
caps = caps->next;
|
||||
}
|
||||
GST_DEBUG_LEAVE ("caps debug");
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_unref:
|
||||
* @caps: the caps to unref
|
||||
|
@ -132,7 +177,9 @@ gst_caps_unref (GstCaps *caps)
|
|||
gboolean zero;
|
||||
GstCaps **next;
|
||||
|
||||
g_return_val_if_fail (caps != NULL, NULL);
|
||||
if (caps == NULL)
|
||||
return NULL;
|
||||
|
||||
g_return_val_if_fail (caps->refcount > 0, NULL);
|
||||
|
||||
GST_CAPS_LOCK (caps);
|
||||
|
@ -182,16 +229,24 @@ gst_caps_ref (GstCaps *caps)
|
|||
GstCaps*
|
||||
gst_caps_copy (GstCaps *caps)
|
||||
{
|
||||
GstCaps *new = caps;;
|
||||
GstCaps *new = NULL, *walk = NULL;
|
||||
|
||||
g_return_val_if_fail (caps != NULL, NULL);
|
||||
while (caps) {
|
||||
GstCaps *newcaps;
|
||||
|
||||
GST_CAPS_LOCK (caps);
|
||||
new = gst_caps_new (
|
||||
newcaps = gst_caps_new_id (
|
||||
caps->name,
|
||||
(gst_type_find_by_id (caps->id))->mime,
|
||||
caps->id,
|
||||
gst_props_copy (caps->properties));
|
||||
GST_CAPS_UNLOCK (caps);
|
||||
|
||||
if (new == NULL) {
|
||||
new = walk = newcaps;
|
||||
}
|
||||
else {
|
||||
walk = walk->next = newcaps;
|
||||
}
|
||||
caps = caps->next;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -437,11 +492,11 @@ gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
|
|||
{
|
||||
GstCaps *orig = capstoadd;
|
||||
|
||||
g_return_val_if_fail (caps != capstoadd, caps);
|
||||
|
||||
if (capstoadd == NULL)
|
||||
return caps;
|
||||
|
||||
g_return_val_if_fail (caps != capstoadd, caps);
|
||||
|
||||
while (capstoadd->next) {
|
||||
capstoadd = capstoadd->next;
|
||||
}
|
||||
|
@ -545,6 +600,118 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_caps_intersect_func (GstCaps *caps1, GstCaps *caps2)
|
||||
{
|
||||
GstCaps *result = NULL;
|
||||
GstProps *props;
|
||||
|
||||
if (caps1->id != caps2->id) {
|
||||
GST_DEBUG (GST_CAT_CAPS,"mime types differ (%s to %s)\n",
|
||||
gst_type_find_by_id (caps1->id)->mime,
|
||||
gst_type_find_by_id (caps2->id)->mime);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (caps1->properties == NULL) {
|
||||
return gst_caps_ref (caps2);
|
||||
}
|
||||
if (caps2->properties == NULL) {
|
||||
return gst_caps_ref (caps1);
|
||||
}
|
||||
|
||||
props = gst_props_intersect (caps1->properties, caps2->properties);
|
||||
if (props) {
|
||||
result = gst_caps_new_id ("intersect", caps1->id, props);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_caps_intersect:
|
||||
* @caps1: a capabilty
|
||||
* @caps2: a capabilty
|
||||
*
|
||||
* Make the intersection between two caps.
|
||||
*
|
||||
* Returns: The intersection of the two caps or NULL if the intersection
|
||||
* is empty.
|
||||
*/
|
||||
GstCaps*
|
||||
gst_caps_intersect (GstCaps *caps1, GstCaps *caps2)
|
||||
{
|
||||
GstCaps *result = NULL, *walk = NULL;
|
||||
|
||||
if (caps1 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "first caps is NULL, return other caps\n");
|
||||
return gst_caps_copy (caps2);
|
||||
}
|
||||
if (caps2 == NULL) {
|
||||
GST_DEBUG (GST_CAT_CAPS, "second caps is NULL, return other caps\n");
|
||||
return gst_caps_copy (caps1);
|
||||
}
|
||||
|
||||
while (caps1) {
|
||||
GstCaps *othercaps = caps2;
|
||||
|
||||
while (othercaps) {
|
||||
GstCaps *intersection = gst_caps_intersect_func (caps1, othercaps);
|
||||
|
||||
if (intersection) {
|
||||
if (!result) {
|
||||
walk = result = intersection;
|
||||
}
|
||||
else {
|
||||
walk = walk->next = intersection;
|
||||
}
|
||||
}
|
||||
othercaps = othercaps->next;
|
||||
}
|
||||
caps1 = caps1->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GstCaps*
|
||||
gst_caps_normalize (GstCaps *caps)
|
||||
{
|
||||
GstCaps *result = NULL, *walk = caps;
|
||||
|
||||
if (caps == NULL)
|
||||
return 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);
|
||||
|
||||
if (result == NULL)
|
||||
walk = result = newcaps;
|
||||
else {
|
||||
walk = walk->next = newcaps;
|
||||
}
|
||||
proplist = g_list_next (proplist);
|
||||
}
|
||||
next:
|
||||
caps = caps->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
/**
|
||||
* gst_caps_save_thyself:
|
||||
|
@ -605,6 +772,7 @@ gst_caps_load_thyself (xmlNodePtr parent)
|
|||
caps->refcount = 1;
|
||||
caps->lock = g_mutex_new ();
|
||||
caps->next = NULL;
|
||||
caps->fixed = TRUE;
|
||||
|
||||
while (subfield) {
|
||||
if (!strcmp (subfield->name, "name")) {
|
||||
|
|
|
@ -37,16 +37,20 @@ typedef struct _GstCaps GstCaps;
|
|||
#define GST_CAPS_TRYLOCK(caps) (g_mutex_trylock(GST_CAPS(caps)->lock))
|
||||
#define GST_CAPS_UNLOCK(caps) (g_mutex_unlock(GST_CAPS(caps)->lock))
|
||||
|
||||
#define GST_CAPS_IS_FIXED(caps) ((caps)->fixed)
|
||||
#define GST_CAPS_IS_CHAINED(caps) ((caps)->next)
|
||||
|
||||
struct _GstCaps {
|
||||
gchar *name; /* the name of this caps */
|
||||
guint16 id; /* type id (major type) */
|
||||
gchar *name; /* the name of this caps */
|
||||
guint16 id; /* type id (major type) */
|
||||
|
||||
guint refcount;
|
||||
GMutex *lock; /* global lock for this capability */
|
||||
guint refcount;
|
||||
GMutex *lock; /* global lock for this capability */
|
||||
gboolean fixed; /* this caps doesn't contain variable properties */
|
||||
|
||||
GstProps *properties; /* properties for this capability */
|
||||
GstProps *properties; /* properties for this capability */
|
||||
|
||||
GstCaps *next;
|
||||
GstCaps *next;
|
||||
};
|
||||
|
||||
#define GST_CAPS_NEW(name, type, a...) \
|
||||
|
@ -75,11 +79,14 @@ factoryname (void) \
|
|||
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);
|
||||
|
||||
GstCaps* gst_caps_unref (GstCaps *caps);
|
||||
GstCaps* gst_caps_ref (GstCaps *caps);
|
||||
void gst_caps_destroy (GstCaps *caps);
|
||||
|
||||
void gst_caps_debug (GstCaps *caps);
|
||||
|
||||
GstCaps* gst_caps_copy (GstCaps *caps);
|
||||
GstCaps* gst_caps_copy_on_write (GstCaps *caps);
|
||||
|
||||
|
@ -102,6 +109,7 @@ GstProps* gst_caps_get_props (GstCaps *caps);
|
|||
#define gst_caps_get_fourcc_int(caps, name) gst_props_get_fourcc_int ((caps)->properties, name)
|
||||
#define gst_caps_get_boolean(caps, name) gst_props_get_boolean ((caps)->properties, name)
|
||||
#define gst_caps_get_string(caps, name) gst_props_get_string ((caps)->properties, name)
|
||||
#define gst_caps_has_property(caps, name) gst_props_has_property ((caps)->properties, name)
|
||||
|
||||
GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name);
|
||||
|
||||
|
@ -110,6 +118,8 @@ GstCaps* gst_caps_append (GstCaps *caps, GstCaps *capstoadd);
|
|||
GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd);
|
||||
|
||||
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
|
||||
GstCaps* gst_caps_intersect (GstCaps *caps1, GstCaps *caps2);
|
||||
GstCaps* gst_caps_normalize (GstCaps *caps);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
|
||||
|
|
|
@ -690,6 +690,51 @@ gst_element_request_pad_by_name (GstElement *element, const gchar *name)
|
|||
return pad;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_connect_filtered:
|
||||
* @src: element containing source pad
|
||||
* @srcpadname: name of pad in source element
|
||||
* @dest: element containing destination pad
|
||||
* @destpadname: name of pad in destination element
|
||||
* @filtercaps: the caps to use as a filter
|
||||
*
|
||||
* Connect the two named pads of the source and destination elements.
|
||||
* Side effect is that if one of the pads has no parent, it becomes a
|
||||
* child of the parent of the other element. If they have different
|
||||
* parents, the connection fails.
|
||||
*
|
||||
* Return: TRUE if the pads could be connected.
|
||||
*/
|
||||
gboolean
|
||||
gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname,
|
||||
GstCaps *filtercaps)
|
||||
{
|
||||
GstPad *srcpad,*destpad;
|
||||
|
||||
g_return_val_if_fail (src != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT(src), FALSE);
|
||||
g_return_val_if_fail (srcpadname != NULL, FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT(dest), FALSE);
|
||||
g_return_val_if_fail (destpadname != NULL, FALSE);
|
||||
|
||||
/* obtain the pads requested */
|
||||
srcpad = gst_element_get_pad (src, srcpadname);
|
||||
if (srcpad == NULL) {
|
||||
GST_ERROR (src, "source element has no pad \"%s\"", srcpadname);
|
||||
return FALSE;
|
||||
}
|
||||
destpad = gst_element_get_pad (dest, destpadname);
|
||||
if (srcpad == NULL) {
|
||||
GST_ERROR (dest, "destination element has no pad \"%s\"", destpadname);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* we're satisified they can be connected, let's do it */
|
||||
return gst_pad_connect_filtered (srcpad, destpad, filtercaps);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_connect:
|
||||
* @src: element containing source pad
|
||||
|
@ -701,34 +746,14 @@ gst_element_request_pad_by_name (GstElement *element, const gchar *name)
|
|||
* Side effect is that if one of the pads has no parent, it becomes a
|
||||
* child of the parent of the other element. If they have different
|
||||
* parents, the connection fails.
|
||||
*
|
||||
* Return: TRUE if the pads could be connected.
|
||||
*/
|
||||
void
|
||||
gboolean
|
||||
gst_element_connect (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname)
|
||||
{
|
||||
GstPad *srcpad,*destpad;
|
||||
|
||||
g_return_if_fail (src != NULL);
|
||||
g_return_if_fail (GST_IS_ELEMENT(src));
|
||||
g_return_if_fail (srcpadname != NULL);
|
||||
g_return_if_fail (dest != NULL);
|
||||
g_return_if_fail (GST_IS_ELEMENT(dest));
|
||||
g_return_if_fail (destpadname != NULL);
|
||||
|
||||
/* obtain the pads requested */
|
||||
srcpad = gst_element_get_pad (src, srcpadname);
|
||||
if (srcpad == NULL) {
|
||||
GST_ERROR(src,"source element has no pad \"%s\"",srcpadname);
|
||||
return;
|
||||
}
|
||||
destpad = gst_element_get_pad (dest, destpadname);
|
||||
if (srcpad == NULL) {
|
||||
GST_ERROR(dest,"destination element has no pad \"%s\"",destpadname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we're satisified they can be connected, let's do it */
|
||||
gst_pad_connect(srcpad,destpad);
|
||||
return gst_element_connect_filtered (src, srcpadname, dest, destpadname, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -200,8 +200,11 @@ void gst_element_remove_ghost_pad (GstElement *element, GstPad *pad);
|
|||
GstPad* gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ);
|
||||
GstPad* gst_element_request_pad_by_name (GstElement *element, const gchar *name);
|
||||
|
||||
void gst_element_connect (GstElement *src, const gchar *srcpadname,
|
||||
gboolean gst_element_connect (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname);
|
||||
gboolean gst_element_connect_filtered (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname,
|
||||
GstCaps *filtercaps);
|
||||
void gst_element_disconnect (GstElement *src, const gchar *srcpadname,
|
||||
GstElement *dest, const gchar *destpadname);
|
||||
|
||||
|
|
965
gst/gstpad.c
965
gst/gstpad.c
File diff suppressed because it is too large
Load diff
171
gst/gstpad.h
171
gst/gstpad.h
|
@ -117,25 +117,27 @@ typedef enum {
|
|||
GST_REGION_TIME_LEN,
|
||||
} GstRegionType;
|
||||
|
||||
typedef enum {
|
||||
GST_PAD_NEGOTIATE_FAIL,
|
||||
GST_PAD_NEGOTIATE_AGREE,
|
||||
GST_PAD_NEGOTIATE_TRY,
|
||||
} GstPadNegotiateReturn;
|
||||
|
||||
typedef enum {
|
||||
GST_PAD_CONNECT_REFUSED = 0,
|
||||
GST_PAD_CONNECT_OK = 1,
|
||||
GST_PAD_CONNECT_DONE = 2,
|
||||
GST_PAD_CONNECT_DELAYED = 3,
|
||||
} GstPadConnectReturn;
|
||||
|
||||
/* this defines the functions used to chain buffers
|
||||
* pad is the sink pad (so the same chain function can be used for N pads)
|
||||
* buf is the buffer being passed */
|
||||
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
|
||||
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
|
||||
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
|
||||
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
|
||||
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
|
||||
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
|
||||
|
||||
typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
|
||||
typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
|
||||
typedef GstPadNegotiateReturn (*GstPadNegotiateFunction) (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
typedef void (*GstPadNewCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||
typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
|
||||
typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type,
|
||||
guint64 offset, guint64 len);
|
||||
typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type,
|
||||
guint64 offset, guint64 len);
|
||||
typedef GstPadConnectReturn (*GstPadConnectFunction) (GstPad *pad, GstCaps *caps);
|
||||
typedef GstCaps* (*GstPadGetCapsFunction) (GstPad *pad, GstCaps *caps);
|
||||
typedef GstBufferPool* (*GstPadBufferPoolFunction) (GstPad *pad);
|
||||
|
||||
typedef enum {
|
||||
GST_PAD_UNKNOWN,
|
||||
|
@ -166,6 +168,8 @@ struct _GstRealPad {
|
|||
GstPad pad;
|
||||
|
||||
GstCaps *caps;
|
||||
GstCaps *filter;
|
||||
GstCaps *appfilter;
|
||||
GstPadDirection direction;
|
||||
|
||||
GstScheduler *sched;
|
||||
|
@ -189,8 +193,8 @@ struct _GstRealPad {
|
|||
GstPadGetRegionFunction getregionfunc;
|
||||
GstPadPullRegionFunction pullregionfunc;
|
||||
|
||||
GstPadNegotiateFunction negotiatefunc;
|
||||
GstPadNewCapsFunction newcapsfunc;
|
||||
GstPadGetCapsFunction getcapsfunc;
|
||||
GstPadConnectFunction connectfunc;
|
||||
GstPadBufferPoolFunction bufferpoolfunc;
|
||||
|
||||
GList *ghostpads;
|
||||
|
@ -231,6 +235,8 @@ struct _GstGhostPadClass {
|
|||
/* GstRealPad */
|
||||
#define GST_RPAD_DIRECTION(pad) (((GstRealPad *)(pad))->direction)
|
||||
#define GST_RPAD_CAPS(pad) (((GstRealPad *)(pad))->caps)
|
||||
#define GST_RPAD_FILTER(pad) (((GstRealPad *)(pad))->filter)
|
||||
#define GST_RPAD_APPFILTER(pad) (((GstRealPad *)(pad))->appfilter)
|
||||
#define GST_RPAD_PEER(pad) (((GstRealPad *)(pad))->peer)
|
||||
#define GST_RPAD_BUFPEN(pad) (((GstRealPad *)(pad))->bufpen)
|
||||
#define GST_RPAD_SCHED(pad) (((GstRealPad *)(pad))->sched)
|
||||
|
@ -244,8 +250,8 @@ struct _GstGhostPadClass {
|
|||
#define GST_RPAD_GETREGIONFUNC(pad) (((GstRealPad *)(pad))->getregionfunc)
|
||||
#define GST_RPAD_PULLREGIONFUNC(pad) (((GstRealPad *)(pad))->pullregionfunc)
|
||||
|
||||
#define GST_RPAD_NEGOTIATEFUNC(pad) (((GstRealPad *)(pad))->negotiatefunc)
|
||||
#define GST_RPAD_NEWCAPSFUNC(pad) (((GstRealPad *)(pad))->newcapsfunc)
|
||||
#define GST_RPAD_CONNECTFUNC(pad) (((GstRealPad *)(pad))->connectfunc)
|
||||
#define GST_RPAD_GETCAPSFUNC(pad) (((GstRealPad *)(pad))->getcapsfunc)
|
||||
#define GST_RPAD_BUFFERPOOLFUNC(pad) (((GstRealPad *)(pad))->bufferpoolfunc)
|
||||
|
||||
#define GST_RPAD_REGIONTYPE(pad) (((GstRealPad *)(pad))->regiontype)
|
||||
|
@ -262,9 +268,10 @@ struct _GstGhostPadClass {
|
|||
#define GST_PAD_PEER(pad) GST_RPAD_PEER(GST_PAD_REALIZE(pad))
|
||||
|
||||
/* Some check functions (unused?) */
|
||||
#define GST_PAD_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL)
|
||||
#define GST_PAD_IS_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL)
|
||||
#define GST_PAD_CAN_PULL(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->gethandler != NULL)
|
||||
|
||||
#define GST_PAD_IS_SRC(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SRC)
|
||||
#define GST_PAD_IS_SINK(pad) (GST_PAD_DIRECTION(pad) == GST_PAD_SINK)
|
||||
|
||||
/***** PadTemplate *****/
|
||||
#define GST_TYPE_PADTEMPLATE (gst_padtemplate_get_type ())
|
||||
|
@ -283,6 +290,9 @@ typedef enum {
|
|||
#define GST_PADTEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction)
|
||||
#define GST_PADTEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence)
|
||||
#define GST_PADTEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps)
|
||||
#define GST_PADTEMPLATE_FIXED(templ) (((GstPadTemplate *)(templ))->fixed)
|
||||
|
||||
#define GST_PADTEMPLATE_IS_FIXED(templ) (GST_PADTEMPLATE_FIXED(templ) == TRUE)
|
||||
|
||||
struct _GstPadTemplate {
|
||||
GstObject object;
|
||||
|
@ -291,6 +301,7 @@ struct _GstPadTemplate {
|
|||
GstPadDirection direction;
|
||||
GstPadPresence presence;
|
||||
GstCaps *caps;
|
||||
gboolean fixed;
|
||||
};
|
||||
|
||||
struct _GstPadTemplateClass {
|
||||
|
@ -325,63 +336,66 @@ name (void) \
|
|||
|
||||
#define GST_PADTEMPLATE_GET(fact) (fact)()
|
||||
|
||||
GType gst_pad_get_type (void);
|
||||
GType gst_real_pad_get_type (void);
|
||||
GType gst_ghost_pad_get_type (void);
|
||||
GType gst_pad_get_type (void);
|
||||
GType gst_real_pad_get_type (void);
|
||||
GType gst_ghost_pad_get_type (void);
|
||||
|
||||
GstPad* gst_pad_new (gchar *name, GstPadDirection direction);
|
||||
#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
|
||||
GstPad* gst_pad_new_from_template (GstPadTemplate *templ, gchar *name);
|
||||
GstPad* gst_pad_new (gchar *name, GstPadDirection direction);
|
||||
#define gst_pad_destroy(pad) gst_object_destroy (GST_OBJECT (pad))
|
||||
GstPad* gst_pad_new_from_template (GstPadTemplate *templ, gchar *name);
|
||||
|
||||
GstPadDirection gst_pad_get_direction (GstPad *pad);
|
||||
GstPadDirection gst_pad_get_direction (GstPad *pad);
|
||||
|
||||
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
|
||||
void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
|
||||
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
|
||||
void gst_pad_set_chain_function (GstPad *pad, GstPadChainFunction chain);
|
||||
void gst_pad_set_get_function (GstPad *pad, GstPadGetFunction get);
|
||||
void gst_pad_set_event_function (GstPad *pad, GstPadEventFunction event);
|
||||
|
||||
void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
|
||||
void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
|
||||
|
||||
void gst_pad_set_negotiate_function (GstPad *pad, GstPadNegotiateFunction nego);
|
||||
void gst_pad_set_newcaps_function (GstPad *pad, GstPadNewCapsFunction newcaps);
|
||||
void gst_pad_set_bufferpool_function (GstPad *pad, GstPadBufferPoolFunction bufpool);
|
||||
void gst_pad_set_connect_function (GstPad *pad, GstPadConnectFunction connect);
|
||||
void gst_pad_set_getcaps_function (GstPad *pad, GstPadGetCapsFunction getcaps);
|
||||
void gst_pad_set_bufferpool_function (GstPad *pad, GstPadBufferPoolFunction bufpool);
|
||||
|
||||
gboolean gst_pad_set_caps (GstPad *pad, GstCaps *caps);
|
||||
GstCaps* gst_pad_get_caps (GstPad *pad);
|
||||
GstCaps* gst_pad_get_padtemplate_caps (GstPad *pad);
|
||||
gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
|
||||
GstCaps* gst_pad_get_caps (GstPad *pad);
|
||||
GstCaps* gst_pad_get_padtemplate_caps (GstPad *pad);
|
||||
gboolean gst_pad_try_set_caps (GstPad *pad, GstCaps *caps);
|
||||
gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
|
||||
|
||||
void gst_pad_set_element_private (GstPad *pad, gpointer priv);
|
||||
gpointer gst_pad_get_element_private (GstPad *pad);
|
||||
void gst_pad_set_element_private (GstPad *pad, gpointer priv);
|
||||
gpointer gst_pad_get_element_private (GstPad *pad);
|
||||
|
||||
void gst_pad_set_name (GstPad *pad, const gchar *name);
|
||||
const gchar* gst_pad_get_name (GstPad *pad);
|
||||
void gst_pad_set_name (GstPad *pad, const gchar *name);
|
||||
const gchar* gst_pad_get_name (GstPad *pad);
|
||||
|
||||
void gst_pad_set_parent (GstPad *pad, GstObject *parent);
|
||||
GstElement* gst_pad_get_parent (GstPad *pad);
|
||||
GstElement* gst_pad_get_real_parent (GstPad *pad);
|
||||
void gst_pad_set_parent (GstPad *pad, GstObject *parent);
|
||||
GstElement* gst_pad_get_parent (GstPad *pad);
|
||||
GstElement* gst_pad_get_real_parent (GstPad *pad);
|
||||
|
||||
void gst_pad_set_sched (GstPad *pad, GstScheduler *sched);
|
||||
GstScheduler* gst_pad_get_sched (GstPad *pad);
|
||||
void gst_pad_set_sched (GstPad *pad, GstScheduler *sched);
|
||||
GstScheduler* gst_pad_get_sched (GstPad *pad);
|
||||
|
||||
void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad);
|
||||
void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad);
|
||||
GList* gst_pad_get_ghost_pad_list (GstPad *pad);
|
||||
void gst_pad_add_ghost_pad (GstPad *pad, GstPad *ghostpad);
|
||||
void gst_pad_remove_ghost_pad (GstPad *pad, GstPad *ghostpad);
|
||||
GList* gst_pad_get_ghost_pad_list (GstPad *pad);
|
||||
|
||||
GstPadTemplate* gst_pad_get_padtemplate (GstPad *pad);
|
||||
GstPadTemplate* gst_pad_get_padtemplate (GstPad *pad);
|
||||
|
||||
GstPad* gst_pad_get_peer (GstPad *pad);
|
||||
GstPad* gst_pad_get_peer (GstPad *pad);
|
||||
|
||||
GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
|
||||
GstBufferPool* gst_pad_get_bufferpool (GstPad *pad);
|
||||
|
||||
gboolean gst_pad_try_connect (GstPad *srcpad, GstPad *sinkpad);
|
||||
void gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
|
||||
void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
|
||||
gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
|
||||
gboolean gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps);
|
||||
void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
|
||||
|
||||
gboolean gst_pad_renegotiate (GstPad *pad);
|
||||
GstPadNegotiateReturn gst_pad_negotiate_proxy (GstPad *srcpad, GstPad *destpad, GstCaps **caps);
|
||||
GstPadConnectReturn gst_pad_proxy_connect (GstPad *pad, GstCaps *caps);
|
||||
gboolean gst_pad_reconnect_filtered (GstPad *pad, GstCaps *filtercaps);
|
||||
gboolean gst_pad_try_reconnect_filtered (GstPad *pad, GstCaps *filtercaps);
|
||||
GstCaps* gst_pad_get_allowed_caps (GstPad *pad);
|
||||
gboolean gst_pad_recalc_allowed_caps (GstPad *pad);
|
||||
|
||||
#if 1
|
||||
void gst_pad_push (GstPad *pad, GstBuffer *buf);
|
||||
void gst_pad_push (GstPad *pad, GstBuffer *buf);
|
||||
#else
|
||||
#define gst_pad_push(pad,buf) G_STMT_START{ \
|
||||
if (((GstRealPad *)(pad))->peer->chainhandler) \
|
||||
|
@ -389,8 +403,9 @@ void gst_pad_push (GstPad *pad, GstBuffer *buf);
|
|||
}G_STMT_END
|
||||
#endif
|
||||
#if 1
|
||||
GstBuffer* gst_pad_pull (GstPad *pad);
|
||||
GstBuffer* gst_pad_pullregion (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
|
||||
GstBuffer* gst_pad_pull (GstPad *pad);
|
||||
GstBuffer* gst_pad_pullregion (GstPad *pad, GstRegionType type,
|
||||
guint64 offset, guint64 len);
|
||||
#else
|
||||
#define gst_pad_pull(pad) \
|
||||
( (((GstRealPad *)(pad))->peer->gethandler) ? \
|
||||
|
@ -402,42 +417,42 @@ NULL )
|
|||
NULL )
|
||||
#endif
|
||||
|
||||
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
|
||||
void gst_pad_event_default (GstPad *pad, GstEvent *event);
|
||||
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
|
||||
void gst_pad_event_default (GstPad *pad, GstEvent *event);
|
||||
|
||||
|
||||
|
||||
GstBuffer* gst_pad_peek (GstPad *pad);
|
||||
GstPad* gst_pad_select (GList *padlist);
|
||||
GstPad* gst_pad_selectv (GstPad *pad, ...);
|
||||
GstBuffer* gst_pad_peek (GstPad *pad);
|
||||
GstPad* gst_pad_select (GList *padlist);
|
||||
GstPad* gst_pad_selectv (GstPad *pad, ...);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
|
||||
void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
|
||||
#endif
|
||||
|
||||
|
||||
/* ghostpads */
|
||||
GstPad* gst_ghost_pad_new (gchar *name,GstPad *pad);
|
||||
GstPad* gst_ghost_pad_new (gchar *name,GstPad *pad);
|
||||
|
||||
|
||||
/* templates and factories */
|
||||
GType gst_padtemplate_get_type (void);
|
||||
GType gst_padtemplate_get_type (void);
|
||||
|
||||
GstPadTemplate* gst_padtemplate_new (gchar *name_template,
|
||||
GstPadDirection direction, GstPadPresence presence,
|
||||
GstCaps *caps, ...);
|
||||
GstPadTemplate* gst_padtemplate_new (gchar *name_template,
|
||||
GstPadDirection direction, GstPadPresence presence,
|
||||
GstCaps *caps, ...);
|
||||
|
||||
GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
|
||||
GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
|
||||
GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
|
||||
GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
|
||||
xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
|
||||
GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
|
||||
GstElement *bin,
|
||||
xmlNodePtr parent);
|
||||
xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
|
||||
GstElement *bin,
|
||||
xmlNodePtr parent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
666
gst/gstprops.c
666
gst/gstprops.c
|
@ -1,6 +1,6 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
||||
* 2000 Wim Taymans <wtay@chello.be>
|
||||
* 2000 Wim Taymans <wim.taymans@chello.be>
|
||||
*
|
||||
* gstprops.c: Properties subsystem for generic usage
|
||||
*
|
||||
|
@ -34,6 +34,8 @@ static GMemChunk *_gst_props_chunk;
|
|||
static GMutex *_gst_props_chunk_lock;
|
||||
|
||||
static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2);
|
||||
static GList* gst_props_list_copy (GList *propslist);
|
||||
|
||||
|
||||
void
|
||||
_gst_props_initialize (void)
|
||||
|
@ -52,33 +54,45 @@ _gst_props_initialize (void)
|
|||
static void
|
||||
gst_props_debug_entry (GstPropsEntry *entry)
|
||||
{
|
||||
gchar *name = g_quark_to_string (entry->propid);
|
||||
|
||||
switch (entry->propstype) {
|
||||
case GST_PROPS_INT_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.int_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: int %d\n", name, entry->data.int_data);
|
||||
break;
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%f\n", entry->data.float_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: float %f\n", name, entry->data.float_data);
|
||||
break;
|
||||
case GST_PROPS_FOURCC_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%4.4s\n", (gchar*)&entry->data.fourcc_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: fourcc %4.4s\n", name, (gchar*)&entry->data.fourcc_data);
|
||||
break;
|
||||
case GST_PROPS_BOOL_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%d\n", entry->data.bool_data);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: bool %d\n", name, entry->data.bool_data);
|
||||
break;
|
||||
case GST_PROPS_STRING_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s\n", entry->data.string_data.string);
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: string %s\n", name, entry->data.string_data.string);
|
||||
break;
|
||||
case GST_PROPS_INT_RANGE_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%d-%d\n", entry->data.int_range_data.min,
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: int range %d-%d\n", name, entry->data.int_range_data.min,
|
||||
entry->data.int_range_data.max);
|
||||
break;
|
||||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%f-%f\n", entry->data.float_range_data.min,
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s: float range %f-%f\n", name, entry->data.float_range_data.min,
|
||||
entry->data.float_range_data.max);
|
||||
break;
|
||||
case GST_PROPS_LIST_ID:
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "[list]\n");
|
||||
{
|
||||
GList *entries = entry->data.list_data.entries;
|
||||
|
||||
while (entries) {
|
||||
gst_props_debug_entry ((GstPropsEntry *)entries->data);
|
||||
entries = g_list_next (entries);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_warning ("unknown property type %d", entry->propstype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -98,9 +112,9 @@ props_find_func (gconstpointer a,
|
|||
gconstpointer b)
|
||||
{
|
||||
GstPropsEntry *entry2 = (GstPropsEntry *)a;
|
||||
GQuark entry1 = (GQuark) GPOINTER_TO_INT (b);
|
||||
GQuark quark = (GQuark) GPOINTER_TO_INT (b);
|
||||
|
||||
return (entry1 - entry2->propid);
|
||||
return (quark - entry2->propid);
|
||||
}
|
||||
|
||||
/* This is implemented as a huge macro because we cannot pass
|
||||
|
@ -139,6 +153,72 @@ G_STMT_START { \
|
|||
} \
|
||||
} G_STMT_END
|
||||
|
||||
static GstPropsEntry*
|
||||
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);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_props_entry_destroy (GstPropsEntry *entry)
|
||||
{
|
||||
switch (entry->propstype) {
|
||||
case GST_PROPS_STRING_ID:
|
||||
g_free (entry->data.string_data.string);
|
||||
break;
|
||||
case GST_PROPS_LIST_ID:
|
||||
{
|
||||
GList *entries = entry->data.list_data.entries;
|
||||
|
||||
while (entries) {
|
||||
gst_props_entry_destroy ((GstPropsEntry *)entries->data);
|
||||
entries = g_list_next (entries);
|
||||
}
|
||||
g_list_free (entry->data.list_data.entries);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
static GstProps*
|
||||
gst_props_alloc (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->properties = NULL;
|
||||
props->refcount = 1;
|
||||
props->fixed = TRUE;
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
}
|
||||
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_new:
|
||||
* @firstname: the first property name
|
||||
|
@ -163,19 +243,19 @@ gst_props_new (const gchar *firstname, ...)
|
|||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_add_to_list:
|
||||
* @entries: the existing list of entries
|
||||
* @entry: the new entry to add to the list
|
||||
*
|
||||
* Add a property to a list of properties.
|
||||
*
|
||||
* Returns: a pointer to a list with the new entry added.
|
||||
*/
|
||||
static GList *
|
||||
gst_props_add_to_list (GList * entries, GstPropsEntry *entry)
|
||||
|
||||
void
|
||||
gst_props_debug (GstProps *props)
|
||||
{
|
||||
return g_list_prepend (entries, entry);
|
||||
GList *propslist = props->properties;
|
||||
|
||||
while (propslist) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
|
||||
|
||||
gst_props_debug_entry (entry);
|
||||
|
||||
propslist = g_list_next (propslist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,7 +363,7 @@ gst_props_add_to_int_list (GList * entries, GstPropsEntry * newentry)
|
|||
i = g_list_next (i);
|
||||
}
|
||||
|
||||
return gst_props_add_to_list (entries, newentry);
|
||||
return g_list_prepend (entries, newentry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,23 +398,15 @@ gst_props_newv (const gchar *firstname, va_list var_args)
|
|||
if (firstname == NULL)
|
||||
return NULL;
|
||||
|
||||
g_mutex_lock (_gst_props_chunk_lock);
|
||||
props = g_mem_chunk_alloc (_gst_props_chunk);
|
||||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
|
||||
props->properties = NULL;
|
||||
props->refcount = 1;
|
||||
props = gst_props_alloc ();
|
||||
|
||||
prop_name = firstname;
|
||||
|
||||
/* properties */
|
||||
while (prop_name) {
|
||||
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_props_alloc_entry ();
|
||||
entry->propid = g_quark_from_string (prop_name);
|
||||
GST_PROPS_ENTRY_FILL (entry, var_args);
|
||||
|
||||
|
@ -371,6 +443,10 @@ gst_props_newv (const gchar *firstname, va_list var_args)
|
|||
g_mem_chunk_free (_gst_props_entries_chunk, subentry);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
}
|
||||
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);
|
||||
|
@ -399,13 +475,13 @@ gst_props_newv (const gchar *firstname, va_list var_args)
|
|||
break;
|
||||
default:
|
||||
list_entry->data.list_data.entries =
|
||||
gst_props_add_to_list (list_entry->data.list_data.entries, entry);
|
||||
g_list_prepend (list_entry->data.list_data.entries, entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
|
||||
gst_props_add_entry (props, entry);
|
||||
}
|
||||
if (!inlist)
|
||||
prop_name = va_arg (var_args, gchar*);
|
||||
|
@ -463,7 +539,8 @@ gst_props_set (GstProps *props, const gchar *name, ...)
|
|||
void
|
||||
gst_props_unref (GstProps *props)
|
||||
{
|
||||
g_return_if_fail (props != NULL);
|
||||
if (props == NULL)
|
||||
return;
|
||||
|
||||
props->refcount--;
|
||||
|
||||
|
@ -485,6 +562,7 @@ gst_props_ref (GstProps *props)
|
|||
props->refcount++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_props_destroy:
|
||||
* @props: the props to destroy
|
||||
|
@ -497,25 +575,13 @@ gst_props_destroy (GstProps *props)
|
|||
{
|
||||
GList *entries;
|
||||
|
||||
g_return_if_fail (props != NULL);
|
||||
if (props == NULL)
|
||||
return;
|
||||
|
||||
entries = props->properties;
|
||||
|
||||
while (entries) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)entries->data;
|
||||
|
||||
switch (entry->propstype) {
|
||||
case GST_PROPS_STRING_ID:
|
||||
g_free (entry->data.string_data.string);
|
||||
break;
|
||||
/* FIXME also free the lists */
|
||||
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);
|
||||
|
||||
gst_props_entry_destroy ((GstPropsEntry *)entries->data);
|
||||
entries = g_list_next (entries);
|
||||
}
|
||||
g_list_free (props->properties);
|
||||
|
@ -525,6 +591,43 @@ gst_props_destroy (GstProps *props)
|
|||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* copy entries
|
||||
*/
|
||||
static GstPropsEntry*
|
||||
gst_props_entry_copy (GstPropsEntry *entry)
|
||||
{
|
||||
GstPropsEntry *newentry;
|
||||
|
||||
newentry = gst_props_alloc_entry ();
|
||||
memcpy (newentry, entry, sizeof (GstPropsEntry));
|
||||
if (entry->propstype == GST_PROPS_LIST_ID) {
|
||||
newentry->data.list_data.entries = gst_props_list_copy (entry->data.list_data.entries);
|
||||
}
|
||||
else if (entry->propstype == GST_PROPS_STRING_ID) {
|
||||
newentry->data.string_data.string = g_strdup (entry->data.string_data.string);
|
||||
}
|
||||
|
||||
return newentry;
|
||||
}
|
||||
|
||||
static GList*
|
||||
gst_props_list_copy (GList *propslist)
|
||||
{
|
||||
GList *new = NULL;
|
||||
|
||||
while (propslist) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)propslist->data;
|
||||
|
||||
new = g_list_prepend (new, gst_props_entry_copy (entry));
|
||||
|
||||
propslist = g_list_next (propslist);
|
||||
}
|
||||
new = g_list_reverse (new);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_copy:
|
||||
* @props: the props to copy
|
||||
|
@ -540,32 +643,12 @@ gst_props_copy (GstProps *props)
|
|||
GstProps *new;
|
||||
GList *properties;
|
||||
|
||||
g_return_val_if_fail (props != NULL, NULL);
|
||||
if (props == NULL)
|
||||
return NULL;
|
||||
|
||||
g_mutex_lock (_gst_props_chunk_lock);
|
||||
new = g_mem_chunk_alloc (_gst_props_chunk);
|
||||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
|
||||
new->properties = NULL;
|
||||
|
||||
properties = props->properties;
|
||||
|
||||
while (properties) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)properties->data;
|
||||
GstPropsEntry *newentry;
|
||||
|
||||
g_mutex_lock (_gst_props_entries_chunk_lock);
|
||||
newentry = g_mem_chunk_alloc (_gst_props_entries_chunk);
|
||||
g_mutex_unlock (_gst_props_entries_chunk_lock);
|
||||
|
||||
/* FIXME copy lists too */
|
||||
memcpy (newentry, entry, sizeof (GstPropsEntry));
|
||||
|
||||
new->properties = g_list_prepend (new->properties, newentry);
|
||||
|
||||
properties = g_list_next (properties);
|
||||
}
|
||||
new->properties = g_list_reverse (new->properties);
|
||||
new = gst_props_alloc ();
|
||||
new->properties = gst_props_list_copy (props->properties);
|
||||
new->fixed = props->fixed;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -614,6 +697,12 @@ gst_props_get_entry_func (GstProps *props, const gchar *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_props_has_property (GstProps *props, const gchar *name)
|
||||
{
|
||||
return (gst_props_get_entry_func (props, name) != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_get_int:
|
||||
* @props: the props to get the int value from
|
||||
|
@ -633,6 +722,9 @@ gst_props_get_int (GstProps *props, const gchar *name)
|
|||
if (thisentry) {
|
||||
return thisentry->data.int_data;
|
||||
}
|
||||
else {
|
||||
g_warning ("props: property %s not found", name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -655,6 +747,9 @@ gst_props_get_float (GstProps *props, const gchar *name)
|
|||
if (thisentry) {
|
||||
return thisentry->data.float_data;
|
||||
}
|
||||
else {
|
||||
g_warning ("props: property %s not found", name);
|
||||
}
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
|
@ -677,6 +772,9 @@ gst_props_get_fourcc_int (GstProps *props, const gchar *name)
|
|||
if (thisentry) {
|
||||
return thisentry->data.fourcc_data;
|
||||
}
|
||||
else {
|
||||
g_warning ("props: property %s not found", name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -699,6 +797,9 @@ gst_props_get_boolean (GstProps *props, const gchar *name)
|
|||
if (thisentry) {
|
||||
return thisentry->data.bool_data;
|
||||
}
|
||||
else {
|
||||
g_warning ("props: property %s not found", name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -721,6 +822,9 @@ gst_props_get_string (GstProps *props, const gchar *name)
|
|||
if (thisentry) {
|
||||
return thisentry->data.string_data.string;
|
||||
}
|
||||
else {
|
||||
g_warning ("props: property %s not found", name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -747,7 +851,7 @@ gst_props_merge (GstProps *props, GstProps *tomerge)
|
|||
while (merge_props) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *)merge_props->data;
|
||||
|
||||
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
|
||||
gst_props_add_entry (props, entry);
|
||||
|
||||
merge_props = g_list_next (merge_props);
|
||||
}
|
||||
|
@ -779,8 +883,11 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
{
|
||||
GST_DEBUG (GST_CAT_PROPERTIES,"compare: %s %s\n", g_quark_to_string (entry1->propid),
|
||||
g_quark_to_string (entry2->propid));
|
||||
gst_props_debug_entry (entry1);
|
||||
gst_props_debug_entry (entry2);
|
||||
|
||||
if (entry2->propstype == GST_PROPS_LIST_ID && entry1->propstype != GST_PROPS_LIST_ID) {
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
}
|
||||
|
||||
switch (entry1->propstype) {
|
||||
case GST_PROPS_LIST_ID:
|
||||
{
|
||||
|
@ -803,10 +910,6 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
case GST_PROPS_INT_RANGE_ID:
|
||||
return (entry2->data.int_range_data.min <= entry1->data.int_range_data.min &&
|
||||
entry2->data.int_range_data.max >= entry1->data.int_range_data.max);
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
|
@ -815,22 +918,15 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
return (entry2->data.float_range_data.min <= entry1->data.float_range_data.min &&
|
||||
entry2->data.float_range_data.max >= entry1->data.float_range_data.max);
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FOURCC_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* b <---> a */
|
||||
case GST_PROPS_FOURCC_ID:
|
||||
GST_DEBUG(GST_CAT_PROPERTIES,"\"%4.4s\" <--> \"%4.4s\" ?\n",
|
||||
&entry2->data.fourcc_data, &entry1->data.fourcc_data);
|
||||
return (entry2->data.fourcc_data == entry1->data.fourcc_data);
|
||||
/* b <---> a,b,c */
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_INT_ID:
|
||||
|
@ -845,11 +941,6 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
case GST_PROPS_INT_ID:
|
||||
GST_DEBUG(GST_CAT_PROPERTIES,"%d == %d ?\n",entry1->data.int_data,entry2->data.int_data);
|
||||
return (entry2->data.int_data == entry1->data.int_data);
|
||||
/* b <---> a,b,c */
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
|
@ -861,11 +952,6 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
/* b <---> a */
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
return (entry2->data.float_data == entry1->data.float_data);
|
||||
/* b <---> a,b,c */
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_BOOL_ID:
|
||||
|
@ -873,23 +959,13 @@ gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry
|
|||
/* t <---> t */
|
||||
case GST_PROPS_BOOL_ID:
|
||||
return (entry2->data.bool_data == entry1->data.bool_data);
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
case GST_PROPS_STRING_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* t <---> t */
|
||||
case GST_PROPS_STRING_ID:
|
||||
return (!strcmp (entry2->data.string_data.string, entry1->data.string_data.string));
|
||||
case GST_PROPS_LIST_ID:
|
||||
return gst_props_entry_check_list_compatibility (entry1, entry2);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -927,14 +1003,12 @@ gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
|
|||
entry2 = (GstPropsEntry *)sinklist->data;
|
||||
|
||||
while (entry1->propid < entry2->propid) {
|
||||
GST_DEBUG (GST_CAT_PROPERTIES,"source is more specific in \"%s\"\n", g_quark_to_string (entry1->propid));
|
||||
more++;
|
||||
sourcelist = g_list_next (sourcelist);
|
||||
if (sourcelist) entry1 = (GstPropsEntry *)sourcelist->data;
|
||||
else goto end;
|
||||
}
|
||||
while (entry1->propid > entry2->propid) {
|
||||
GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
|
||||
missing++;
|
||||
sinklist = g_list_next (sinklist);
|
||||
if (sinklist) entry2 = (GstPropsEntry *)sinklist->data;
|
||||
|
@ -945,8 +1019,6 @@ gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
|
|||
compatible = FALSE;
|
||||
GST_DEBUG (GST_CAT_PROPERTIES, "%s are not compatible: \n",
|
||||
g_quark_to_string (entry1->propid));
|
||||
gst_props_debug_entry (entry1);
|
||||
gst_props_debug_entry (entry2);
|
||||
}
|
||||
|
||||
sourcelist = g_list_next (sourcelist);
|
||||
|
@ -956,7 +1028,6 @@ gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops)
|
|||
GstPropsEntry *entry2;
|
||||
entry2 = (GstPropsEntry *)sinklist->data;
|
||||
missing++;
|
||||
GST_DEBUG (GST_CAT_PROPERTIES,"source has missing property \"%s\"\n", g_quark_to_string (entry2->propid));
|
||||
}
|
||||
end:
|
||||
|
||||
|
@ -966,6 +1037,339 @@ end:
|
|||
return compatible;
|
||||
}
|
||||
|
||||
static GstPropsEntry*
|
||||
gst_props_entry_intersect (GstPropsEntry *entry1, GstPropsEntry *entry2)
|
||||
{
|
||||
GstPropsEntry *result = NULL;
|
||||
|
||||
/* try to move the ranges and lists first */
|
||||
switch (entry2->propstype) {
|
||||
case GST_PROPS_INT_RANGE_ID:
|
||||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
case GST_PROPS_LIST_ID:
|
||||
{
|
||||
GstPropsEntry *temp;
|
||||
|
||||
temp = entry1;
|
||||
entry1 = entry2;
|
||||
entry2 = temp;
|
||||
}
|
||||
}
|
||||
|
||||
switch (entry1->propstype) {
|
||||
case GST_PROPS_LIST_ID:
|
||||
{
|
||||
GList *entrylist = entry1->data.list_data.entries;
|
||||
GList *intersection = NULL;
|
||||
|
||||
while (entrylist) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *) entrylist->data;
|
||||
GstPropsEntry *intersectentry;
|
||||
|
||||
intersectentry = gst_props_entry_intersect (entry2, entry);
|
||||
|
||||
if (intersectentry) {
|
||||
if (intersectentry->propstype == GST_PROPS_LIST_ID) {
|
||||
intersection = g_list_concat (intersection, 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;
|
||||
gst_props_entry_destroy (intersectentry);
|
||||
}
|
||||
else {
|
||||
intersection = g_list_prepend (intersection, intersectentry);
|
||||
}
|
||||
}
|
||||
entrylist = g_list_next (entrylist);
|
||||
}
|
||||
if (intersection) {
|
||||
/* check if the list only contains 1 element, if so, we can just copy it */
|
||||
if (g_list_next (intersection) == NULL) {
|
||||
result = (GstPropsEntry *) (intersection->data);
|
||||
g_list_free (intersection);
|
||||
}
|
||||
/* else we need to create a new entry to hold the list */
|
||||
else {
|
||||
result = gst_props_alloc_entry ();
|
||||
result->propid = entry1->propid;
|
||||
result->propstype = GST_PROPS_LIST_ID;
|
||||
result->data.list_data.entries = g_list_reverse (intersection);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case GST_PROPS_INT_RANGE_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* a - b <---> a - c */
|
||||
case GST_PROPS_INT_RANGE_ID:
|
||||
{
|
||||
gint lower = MAX (entry1->data.int_range_data.min, entry2->data.int_range_data.min);
|
||||
gint upper = MIN (entry1->data.int_range_data.max, entry2->data.int_range_data.max);
|
||||
|
||||
if (lower <= upper) {
|
||||
result = gst_props_alloc_entry ();
|
||||
result->propid = entry1->propid;
|
||||
|
||||
if (lower == upper) {
|
||||
result->propstype = GST_PROPS_INT_ID;
|
||||
result->data.int_data = lower;
|
||||
}
|
||||
else {
|
||||
result->propstype = GST_PROPS_INT_RANGE_ID;
|
||||
result->data.int_range_data.min = lower;
|
||||
result->data.int_range_data.max = upper;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_PROPS_INT_ID:
|
||||
if (entry1->data.int_range_data.min <= entry2->data.int_data &&
|
||||
entry1->data.int_range_data.max >= entry2->data.int_data) {
|
||||
result = gst_props_entry_copy (entry2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* a - b <---> a - c */
|
||||
case GST_PROPS_FLOAT_RANGE_ID:
|
||||
{
|
||||
gfloat lower = MAX (entry1->data.float_range_data.min, entry2->data.float_range_data.min);
|
||||
gfloat upper = MIN (entry1->data.float_range_data.max, entry2->data.float_range_data.max);
|
||||
|
||||
if (lower <= upper) {
|
||||
result = gst_props_alloc_entry ();
|
||||
result->propid = entry1->propid;
|
||||
|
||||
if (lower == upper) {
|
||||
result->propstype = GST_PROPS_FLOAT_ID;
|
||||
result->data.float_data = lower;
|
||||
}
|
||||
else {
|
||||
result->propstype = GST_PROPS_FLOAT_RANGE_ID;
|
||||
result->data.float_range_data.min = lower;
|
||||
result->data.float_range_data.max = upper;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
if (entry1->data.float_range_data.min <= entry2->data.float_data &&
|
||||
entry1->data.float_range_data.max >= entry2->data.float_data) {
|
||||
result = gst_props_entry_copy (entry2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FOURCC_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* b <---> a */
|
||||
case GST_PROPS_FOURCC_ID:
|
||||
if (entry1->data.fourcc_data == entry2->data.fourcc_data)
|
||||
result = gst_props_entry_copy (entry1);
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_INT_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* b <---> a */
|
||||
case GST_PROPS_INT_ID:
|
||||
if (entry1->data.int_data == entry2->data.int_data)
|
||||
result = gst_props_entry_copy (entry1);
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* b <---> a */
|
||||
case GST_PROPS_FLOAT_ID:
|
||||
if (entry1->data.float_data == entry2->data.float_data)
|
||||
result = gst_props_entry_copy (entry1);
|
||||
}
|
||||
break;
|
||||
case GST_PROPS_BOOL_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* t <---> t */
|
||||
case GST_PROPS_BOOL_ID:
|
||||
if (entry1->data.bool_data == entry2->data.bool_data)
|
||||
result = gst_props_entry_copy (entry1);
|
||||
}
|
||||
case GST_PROPS_STRING_ID:
|
||||
switch (entry2->propstype) {
|
||||
/* t <---> t */
|
||||
case GST_PROPS_STRING_ID:
|
||||
if (!strcmp (entry1->data.string_data.string, entry2->data.string_data.string))
|
||||
result = gst_props_entry_copy (entry1);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_props_intersect:
|
||||
* @props1: a property
|
||||
* @props2: another property
|
||||
*
|
||||
* Calculates the intersection bewteen two GstProps.
|
||||
*
|
||||
* Returns: a GstProps with the intersection or NULL if the
|
||||
* intersection is empty.
|
||||
*/
|
||||
GstProps*
|
||||
gst_props_intersect (GstProps *props1, GstProps *props2)
|
||||
{
|
||||
GList *props1list;
|
||||
GList *props2list;
|
||||
GstProps *intersection;
|
||||
GList *leftovers;
|
||||
GstPropsEntry *iprops = NULL;
|
||||
|
||||
intersection = gst_props_alloc ();
|
||||
intersection->fixed = TRUE;
|
||||
|
||||
g_return_val_if_fail (props1 != NULL, NULL);
|
||||
g_return_val_if_fail (props2 != NULL, NULL);
|
||||
|
||||
props1list = props1->properties;
|
||||
props2list = props2->properties;
|
||||
|
||||
while (props1list && props2list) {
|
||||
GstPropsEntry *entry1;
|
||||
GstPropsEntry *entry2;
|
||||
|
||||
entry1 = (GstPropsEntry *)props1list->data;
|
||||
entry2 = (GstPropsEntry *)props2list->data;
|
||||
|
||||
while (entry1->propid < entry2->propid) {
|
||||
GstPropsEntry *toadd;
|
||||
|
||||
GST_DEBUG (GST_CAT_PROPERTIES,"source is more specific in \"%s\"\n", 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);
|
||||
|
||||
props1list = g_list_next (props1list);
|
||||
if (props1list)
|
||||
entry1 = (GstPropsEntry *)props1list->data;
|
||||
else
|
||||
goto end;
|
||||
}
|
||||
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);
|
||||
|
||||
props2list = g_list_next (props2list);
|
||||
if (props2list)
|
||||
entry2 = (GstPropsEntry *)props2list->data;
|
||||
else
|
||||
goto end;
|
||||
}
|
||||
/* 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 {
|
||||
gst_props_unref (intersection);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
leftovers = props2list;
|
||||
else
|
||||
goto finish;
|
||||
|
||||
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));
|
||||
|
||||
leftovers = g_list_next (leftovers);
|
||||
}
|
||||
|
||||
finish:
|
||||
intersection->properties = g_list_reverse (intersection->properties);
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
GList*
|
||||
gst_props_normalize (GstProps *props)
|
||||
{
|
||||
GList *entries;
|
||||
GList *result = NULL;
|
||||
|
||||
if (!props)
|
||||
return NULL;
|
||||
|
||||
entries = props->properties;
|
||||
|
||||
while (entries) {
|
||||
GstPropsEntry *entry = (GstPropsEntry *) entries->data;
|
||||
|
||||
if (entry->propstype == GST_PROPS_LIST_ID) {
|
||||
GList *list_entries = entry->data.list_data.entries;
|
||||
|
||||
while (list_entries) {
|
||||
GstPropsEntry *list_entry = (GstPropsEntry *) list_entries->data;
|
||||
GstPropsEntry *new_entry;
|
||||
GstProps *newprops;
|
||||
GList *lentry;
|
||||
|
||||
newprops = gst_props_alloc ();
|
||||
newprops->properties = gst_props_list_copy (props->properties);
|
||||
lentry = g_list_find_custom (newprops->properties, GINT_TO_POINTER (list_entry->propid), props_find_func);
|
||||
if (lentry) {
|
||||
GList *new_list = NULL;
|
||||
|
||||
new_entry = (GstPropsEntry *) lentry->data;
|
||||
memcpy (new_entry, list_entry, sizeof (GstPropsEntry));
|
||||
|
||||
new_list = gst_props_normalize (newprops);
|
||||
result = g_list_concat (new_list, result);
|
||||
}
|
||||
else {
|
||||
result = g_list_append (result, newprops);
|
||||
}
|
||||
|
||||
list_entries = g_list_next (list_entries);
|
||||
}
|
||||
/* we break out of the loop because the other lists are
|
||||
* unrolled in the recursive call */
|
||||
break;
|
||||
}
|
||||
entries = g_list_next (entries);
|
||||
}
|
||||
if (!result) {
|
||||
result = g_list_prepend (result, props);
|
||||
}
|
||||
else {
|
||||
result = g_list_reverse (result);
|
||||
gst_props_unref (props);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
static xmlNodePtr
|
||||
gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
|
||||
|
@ -1029,6 +1433,7 @@ gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
|
|||
xmlNewProp (subtree, "value", entry->data.string_data.string);
|
||||
break;
|
||||
default:
|
||||
g_warning ("trying to save unknown property type %d", entry->propstype);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1062,6 +1467,7 @@ gst_props_save_thyself (GstProps *props, xmlNodePtr parent)
|
|||
subtree = xmlNewChild (parent, NULL, "list", NULL);
|
||||
xmlNewProp (subtree, "name", g_quark_to_string (entry->propid));
|
||||
g_list_foreach (entry->data.list_data.entries, (GFunc) gst_props_save_thyself_func, subtree);
|
||||
break;
|
||||
default:
|
||||
gst_props_save_thyself_func (entry, parent);
|
||||
}
|
||||
|
@ -1078,9 +1484,7 @@ gst_props_load_thyself_func (xmlNodePtr field)
|
|||
GstPropsEntry *entry;
|
||||
gchar *prop;
|
||||
|
||||
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_props_alloc_entry ();
|
||||
|
||||
if (!strcmp(field->name, "int")) {
|
||||
entry->propstype = GST_PROPS_INT_ID;
|
||||
|
@ -1175,27 +1579,19 @@ gst_props_load_thyself (xmlNodePtr parent)
|
|||
xmlNodePtr field = parent->xmlChildrenNode;
|
||||
gchar *prop;
|
||||
|
||||
g_mutex_lock (_gst_props_chunk_lock);
|
||||
props = g_mem_chunk_alloc (_gst_props_chunk);
|
||||
g_mutex_unlock (_gst_props_chunk_lock);
|
||||
|
||||
props->properties = NULL;
|
||||
props->refcount = 1;
|
||||
props = gst_props_alloc ();
|
||||
|
||||
while (field) {
|
||||
if (!strcmp (field->name, "list")) {
|
||||
GstPropsEntry *entry;
|
||||
xmlNodePtr subfield = field->xmlChildrenNode;
|
||||
|
||||
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->propstype = GST_PROPS_LIST_ID;
|
||||
entry->data.list_data.entries = NULL;
|
||||
entry = gst_props_alloc_entry ();
|
||||
prop = xmlGetProp (field, "name");
|
||||
entry->propid = g_quark_from_string (prop);
|
||||
g_free (prop);
|
||||
entry->propstype = GST_PROPS_LIST_ID;
|
||||
entry->data.list_data.entries = NULL;
|
||||
|
||||
while (subfield) {
|
||||
GstPropsEntry *subentry = gst_props_load_thyself_func (subfield);
|
||||
|
@ -1206,7 +1602,7 @@ gst_props_load_thyself (xmlNodePtr parent)
|
|||
subfield = subfield->next;
|
||||
}
|
||||
entry->data.list_data.entries = g_list_reverse (entry->data.list_data.entries);
|
||||
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
|
||||
gst_props_add_entry (props, entry);
|
||||
}
|
||||
else {
|
||||
GstPropsEntry *entry;
|
||||
|
@ -1214,7 +1610,7 @@ gst_props_load_thyself (xmlNodePtr parent)
|
|||
entry = gst_props_load_thyself_func (field);
|
||||
|
||||
if (entry)
|
||||
props->properties = g_list_insert_sorted (props->properties, entry, props_compare_func);
|
||||
gst_props_add_entry (props, entry);
|
||||
}
|
||||
field = field->next;
|
||||
}
|
||||
|
|
|
@ -32,14 +32,18 @@ typedef struct _GstProps GstProps;
|
|||
|
||||
typedef enum {
|
||||
GST_PROPS_END_ID = 0,
|
||||
GST_PROPS_LIST_ID,
|
||||
GST_PROPS_INT_ID,
|
||||
GST_PROPS_INT_RANGE_ID,
|
||||
GST_PROPS_FLOAT_ID,
|
||||
GST_PROPS_FLOAT_RANGE_ID,
|
||||
GST_PROPS_FOURCC_ID,
|
||||
GST_PROPS_BOOL_ID,
|
||||
GST_PROPS_STRING_ID,
|
||||
|
||||
GST_PROPS_VAR_ID, /* after this marker start the variable properties */
|
||||
|
||||
GST_PROPS_LIST_ID,
|
||||
GST_PROPS_FLOAT_RANGE_ID,
|
||||
GST_PROPS_INT_RANGE_ID,
|
||||
|
||||
GST_PROPS_LAST_ID = GST_PROPS_END_ID + 16,
|
||||
} GstPropsId;
|
||||
|
||||
|
@ -55,10 +59,15 @@ typedef enum {
|
|||
#define GST_PROPS_BOOLEAN(a) GST_PROPS_BOOL_ID,(a)
|
||||
#define GST_PROPS_STRING(a) GST_PROPS_STRING_ID,(a)
|
||||
|
||||
#define GST_PROPS_INT_POSITIVE GST_PROPS_INT_RANGE(0,G_MAXINT)
|
||||
#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)
|
||||
|
||||
|
||||
struct _GstProps {
|
||||
gint refcount;
|
||||
GMutex *lock;
|
||||
gboolean fixed;
|
||||
|
||||
GList *properties; /* real properties for this property */
|
||||
};
|
||||
|
@ -73,15 +82,21 @@ void gst_props_unref (GstProps *props);
|
|||
void gst_props_ref (GstProps *props);
|
||||
void gst_props_destroy (GstProps *props);
|
||||
|
||||
void gst_props_debug (GstProps *props);
|
||||
|
||||
GstProps* gst_props_copy (GstProps *props);
|
||||
GstProps* gst_props_copy_on_write (GstProps *props);
|
||||
|
||||
GstProps* gst_props_merge (GstProps *props, GstProps *tomerge);
|
||||
|
||||
gboolean gst_props_check_compatibility (GstProps *fromprops, GstProps *toprops);
|
||||
GstProps* gst_props_intersect (GstProps *props1, GstProps *props2);
|
||||
GList* gst_props_normalize (GstProps *props);
|
||||
|
||||
GstProps* gst_props_set (GstProps *props, const gchar *name, ...);
|
||||
|
||||
gboolean gst_props_has_property (GstProps *props, const gchar *name);
|
||||
|
||||
gint gst_props_get_int (GstProps *props, const gchar *name);
|
||||
gfloat gst_props_get_float (GstProps *props, const gchar *name);
|
||||
gulong gst_props_get_fourcc_int (GstProps *props, const gchar *name);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <gst/gstprops.h>
|
||||
|
||||
#define GST_PROPS_ENTRY_IS_VARIABLE(a) (((GstPropsEntry*)(a))->propstype > GST_PROPS_VAR_ID)
|
||||
|
||||
typedef struct _GstPropsEntry GstPropsEntry;
|
||||
|
||||
struct _GstPropsEntry {
|
||||
|
|
|
@ -78,8 +78,6 @@ static void gst_queue_set_property (GObject *object, guint prop_id,
|
|||
static void gst_queue_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstPadNegotiateReturn gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
static GstPadNegotiateReturn gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
|
||||
static GstBuffer * gst_queue_get (GstPad *pad);
|
||||
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
||||
|
@ -163,6 +161,34 @@ gst_queue_class_init (GstQueueClass *klass)
|
|||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
||||
}
|
||||
|
||||
static GstPadConnectReturn
|
||||
gst_queue_connect (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == queue->srcpad)
|
||||
otherpad = queue->sinkpad;
|
||||
else
|
||||
otherpad = queue->srcpad;
|
||||
|
||||
return gst_pad_proxy_connect (otherpad, caps);
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_queue_getcaps (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == queue->srcpad)
|
||||
otherpad = queue->sinkpad;
|
||||
else
|
||||
otherpad = queue->srcpad;
|
||||
|
||||
return gst_pad_get_allowed_caps (otherpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_queue_init (GstQueue *queue)
|
||||
{
|
||||
|
@ -171,15 +197,17 @@ gst_queue_init (GstQueue *queue)
|
|||
GST_FLAG_SET (queue, GST_ELEMENT_EVENT_AWARE);
|
||||
|
||||
queue->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
|
||||
gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_chain));
|
||||
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
|
||||
gst_pad_set_negotiate_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_sink));
|
||||
gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_get_bufferpool));
|
||||
gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_get_bufferpool));
|
||||
gst_pad_set_connect_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||
gst_pad_set_getcaps_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||
|
||||
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
|
||||
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
|
||||
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
||||
gst_pad_set_negotiate_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_src));
|
||||
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||
|
||||
queue->leaky = GST_QUEUE_NO_LEAK;
|
||||
queue->queue = NULL;
|
||||
|
@ -221,26 +249,6 @@ gst_queue_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (queue->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, queue->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_queue_cleanup_buffers (gpointer data, const gpointer user_data)
|
||||
{
|
||||
|
@ -535,7 +543,7 @@ gst_queue_change_state (GstElement *element)
|
|||
gst_queue_locked_flush (queue);
|
||||
}
|
||||
else if (new_state == GST_STATE_PLAYING) {
|
||||
if (!GST_PAD_CONNECTED (queue->sinkpad)) {
|
||||
if (!GST_PAD_IS_CONNECTED (queue->sinkpad)) {
|
||||
/* FIXME can this be? */
|
||||
if (queue->reader)
|
||||
g_cond_signal (queue->not_empty);
|
||||
|
|
|
@ -187,7 +187,9 @@ gst_typefind_chain (GstPad *pad, GstBuffer *buf)
|
|||
gst_caps_get_name (caps));
|
||||
typefind->caps = caps;
|
||||
|
||||
gst_pad_set_caps (pad, caps);
|
||||
if (!gst_pad_try_reconnect_filtered (pad, caps)) {
|
||||
g_warning ("typefind: found type but peer didn't accept it");
|
||||
}
|
||||
|
||||
{
|
||||
int oldstate = GST_STATE(typefind);
|
||||
|
|
|
@ -133,26 +133,6 @@ gst_identity_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (identity->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_identity_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
identity = GST_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, identity->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_identity_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstIdentity *identity;
|
||||
|
||||
identity = GST_IDENTITY (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, identity->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_identity_init (GstIdentity *identity)
|
||||
{
|
||||
|
@ -160,11 +140,9 @@ gst_identity_init (GstIdentity *identity)
|
|||
gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
|
||||
gst_pad_set_chain_function (identity->sinkpad, GST_DEBUG_FUNCPTR (gst_identity_chain));
|
||||
gst_pad_set_bufferpool_function (identity->sinkpad, gst_identity_get_bufferpool);
|
||||
gst_pad_set_negotiate_function (identity->sinkpad, gst_identity_negotiate_sink);
|
||||
|
||||
identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
|
||||
gst_pad_set_negotiate_function (identity->srcpad, gst_identity_negotiate_src);
|
||||
|
||||
identity->loop_based = FALSE;
|
||||
identity->sleep_time = 0;
|
||||
|
|
|
@ -78,8 +78,6 @@ static void gst_queue_set_property (GObject *object, guint prop_id,
|
|||
static void gst_queue_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstPadNegotiateReturn gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
static GstPadNegotiateReturn gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
|
||||
static GstBuffer * gst_queue_get (GstPad *pad);
|
||||
static GstBufferPool* gst_queue_get_bufferpool (GstPad *pad);
|
||||
|
@ -163,6 +161,34 @@ gst_queue_class_init (GstQueueClass *klass)
|
|||
gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_queue_change_state);
|
||||
}
|
||||
|
||||
static GstPadConnectReturn
|
||||
gst_queue_connect (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == queue->srcpad)
|
||||
otherpad = queue->sinkpad;
|
||||
else
|
||||
otherpad = queue->srcpad;
|
||||
|
||||
return gst_pad_proxy_connect (otherpad, caps);
|
||||
}
|
||||
|
||||
static GstCaps*
|
||||
gst_queue_getcaps (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstQueue *queue = GST_QUEUE (gst_pad_get_parent (pad));
|
||||
GstPad *otherpad;
|
||||
|
||||
if (pad == queue->srcpad)
|
||||
otherpad = queue->sinkpad;
|
||||
else
|
||||
otherpad = queue->srcpad;
|
||||
|
||||
return gst_pad_get_allowed_caps (otherpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_queue_init (GstQueue *queue)
|
||||
{
|
||||
|
@ -171,15 +197,17 @@ gst_queue_init (GstQueue *queue)
|
|||
GST_FLAG_SET (queue, GST_ELEMENT_EVENT_AWARE);
|
||||
|
||||
queue->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_chain));
|
||||
gst_pad_set_chain_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_chain));
|
||||
gst_element_add_pad (GST_ELEMENT (queue), queue->sinkpad);
|
||||
gst_pad_set_negotiate_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_sink));
|
||||
gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR(gst_queue_get_bufferpool));
|
||||
gst_pad_set_bufferpool_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_get_bufferpool));
|
||||
gst_pad_set_connect_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||
gst_pad_set_getcaps_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||
|
||||
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_get));
|
||||
gst_pad_set_get_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_get));
|
||||
gst_element_add_pad (GST_ELEMENT (queue), queue->srcpad);
|
||||
gst_pad_set_negotiate_function (queue->srcpad, GST_DEBUG_FUNCPTR(gst_queue_handle_negotiate_src));
|
||||
gst_pad_set_connect_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_connect));
|
||||
gst_pad_set_getcaps_function (queue->srcpad, GST_DEBUG_FUNCPTR (gst_queue_getcaps));
|
||||
|
||||
queue->leaky = GST_QUEUE_NO_LEAK;
|
||||
queue->queue = NULL;
|
||||
|
@ -221,26 +249,6 @@ gst_queue_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (queue->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstQueue *queue;
|
||||
|
||||
queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, queue->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_queue_cleanup_buffers (gpointer data, const gpointer user_data)
|
||||
{
|
||||
|
@ -535,7 +543,7 @@ gst_queue_change_state (GstElement *element)
|
|||
gst_queue_locked_flush (queue);
|
||||
}
|
||||
else if (new_state == GST_STATE_PLAYING) {
|
||||
if (!GST_PAD_CONNECTED (queue->sinkpad)) {
|
||||
if (!GST_PAD_IS_CONNECTED (queue->sinkpad)) {
|
||||
/* FIXME can this be? */
|
||||
if (queue->reader)
|
||||
g_cond_signal (queue->not_empty);
|
||||
|
|
|
@ -146,26 +146,6 @@ gst_statistics_get_bufferpool (GstPad *pad)
|
|||
return gst_pad_get_bufferpool (statistics->srcpad);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_statistics_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
statistics = GST_STATISTICS (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, statistics->sinkpad, caps);
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_statistics_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
|
||||
{
|
||||
GstStatistics *statistics;
|
||||
|
||||
statistics = GST_STATISTICS (gst_pad_get_parent (pad));
|
||||
|
||||
return gst_pad_negotiate_proxy (pad, statistics->srcpad, caps);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_statistics_init (GstStatistics *statistics)
|
||||
{
|
||||
|
@ -173,11 +153,9 @@ gst_statistics_init (GstStatistics *statistics)
|
|||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->sinkpad);
|
||||
gst_pad_set_chain_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_chain));
|
||||
gst_pad_set_bufferpool_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_get_bufferpool));
|
||||
gst_pad_set_negotiate_function (statistics->sinkpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_sink));
|
||||
|
||||
statistics->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_element_add_pad (GST_ELEMENT (statistics), statistics->srcpad);
|
||||
gst_pad_set_negotiate_function (statistics->srcpad, GST_DEBUG_FUNCPTR (gst_statistics_negotiate_src));
|
||||
|
||||
statistics->timer = NULL;
|
||||
statistics->last_timer = NULL;
|
||||
|
|
|
@ -66,7 +66,6 @@ static void gst_tee_get_property (GObject *object, guint prop_id,
|
|||
|
||||
static void gst_tee_chain (GstPad *pad, GstBuffer *buf);
|
||||
|
||||
static GstPadNegotiateReturn gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
/*static guint gst_tee_signals[LAST_SIGNAL] = { 0 };*/
|
||||
|
@ -110,20 +109,44 @@ gst_tee_class_init (GstTeeClass *klass)
|
|||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
|
||||
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR(gst_tee_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR(gst_tee_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR(gst_tee_request_new_pad);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_tee_sinkconnect (GstPad *pad, GstCaps *caps)
|
||||
{
|
||||
GstTee *tee;
|
||||
GList *pads;
|
||||
|
||||
tee = GST_TEE (gst_pad_get_parent (pad));
|
||||
|
||||
/* go through all the src pads */
|
||||
pads = gst_element_get_pad_list (GST_ELEMENT (tee));
|
||||
|
||||
while (pads) {
|
||||
GstPad *outpad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_IS_CONNECTED (outpad))
|
||||
continue;
|
||||
|
||||
if (!(gst_pad_try_set_caps (outpad, caps))) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_tee_init (GstTee *tee)
|
||||
{
|
||||
tee->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (tee), tee->sinkpad);
|
||||
gst_pad_set_chain_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_chain));
|
||||
gst_pad_set_negotiate_function (tee->sinkpad, GST_DEBUG_FUNCPTR(gst_tee_handle_negotiate_sink));
|
||||
gst_pad_set_connect_function (tee->sinkpad, GST_DEBUG_FUNCPTR (gst_tee_sinkconnect));
|
||||
|
||||
tee->silent = FALSE;
|
||||
}
|
||||
|
@ -152,7 +175,7 @@ gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar
|
|||
GST_PAD_ELEMENT_PRIVATE (srcpad) = NULL;
|
||||
|
||||
if (GST_PAD_CAPS (tee->sinkpad)) {
|
||||
gst_pad_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
|
||||
gst_pad_try_set_caps (srcpad, GST_PAD_CAPS (tee->sinkpad));
|
||||
}
|
||||
|
||||
return srcpad;
|
||||
|
@ -253,18 +276,18 @@ gst_tee_chain (GstPad *pad, GstBuffer *buf)
|
|||
GstEvent *event = GST_EVENT (GST_PAD_ELEMENT_PRIVATE (outpad));
|
||||
|
||||
GST_PAD_ELEMENT_PRIVATE (outpad) = NULL;
|
||||
if (GST_PAD_CONNECTED (outpad))
|
||||
if (GST_PAD_IS_CONNECTED (outpad))
|
||||
gst_pad_push (outpad, GST_BUFFER (event));
|
||||
else
|
||||
gst_event_free (event);
|
||||
}
|
||||
|
||||
if (!tee->silent) {
|
||||
gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu) \n",
|
||||
gst_element_info (GST_ELEMENT (tee), "chain ******* (%s:%s)t (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (outpad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
if (GST_PAD_CONNECTED (outpad))
|
||||
if (GST_PAD_IS_CONNECTED (outpad))
|
||||
gst_pad_push (outpad, buf);
|
||||
else
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -279,30 +302,3 @@ gst_tee_factory_init (GstElementFactory *factory)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GstPadNegotiateReturn
|
||||
gst_tee_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer* data)
|
||||
{
|
||||
GstCaps* tempcaps;
|
||||
gint i;
|
||||
GstTee* tee = GST_TEE (GST_OBJECT_PARENT (pad));
|
||||
GList *pads;
|
||||
|
||||
if (*caps==NULL)
|
||||
return GST_PAD_NEGOTIATE_FAIL;
|
||||
|
||||
/* go through all the src pads */
|
||||
pads = gst_element_get_pad_list (GST_ELEMENT (tee));
|
||||
|
||||
while (pads) {
|
||||
GstPad *outpad = GST_PAD (pads->data);
|
||||
pads = g_list_next (pads);
|
||||
|
||||
if (GST_PAD_DIRECTION (outpad) != GST_PAD_SRC || !GST_PAD_CONNECTED (outpad))
|
||||
continue;
|
||||
|
||||
if (!(gst_pad_set_caps (outpad, *caps))) {
|
||||
return GST_PAD_NEGOTIATE_FAIL;
|
||||
}
|
||||
}
|
||||
return GST_PAD_NEGOTIATE_AGREE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue