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:
Wim Taymans 2002-01-13 22:22:42 +00:00
parent 0a0598f97a
commit b2ee38575d
19 changed files with 1536 additions and 941 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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")) {

View file

@ -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);

View file

@ -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);
}
/**

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;
}