From 0267b92c930176934e8f4a85eebeb6ab4ba6f799 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 20 Mar 2001 18:29:00 +0000 Subject: [PATCH] More work on capsnego proxying. It should be OK now. Original commit message from CVS: More work on capsnego proxying. It should be OK now. Added another testcase enum that shows various capsnego algorithms. Warn about pads that try to set a capability incompatible with their padtemplate. Implemented refcounting and copy_on_write for caps/props. --- gst/gst.c | 2 + gst/gstbuffer.c | 18 +- gst/gstcaps.c | 127 ++++++++++-- gst/gstcaps.h | 10 +- gst/gstpad.c | 42 ++-- gst/gstpad.h | 2 +- gst/gstplugin.c | 2 +- gst/gstprops.c | 155 +++++++++++++-- gst/gstprops.h | 9 + gst/gstqueue.c | 21 +- plugins/elements/gstqueue.c | 21 +- tests/old/testsuite/capsnego/Makefile.am | 2 +- tests/old/testsuite/capsnego/converter2.c | 2 +- tests/old/testsuite/capsnego/enum.c | 227 ++++++++++++++++++++++ testsuite/capsnego/Makefile.am | 2 +- testsuite/capsnego/converter2.c | 2 +- testsuite/capsnego/enum.c | 227 ++++++++++++++++++++++ 17 files changed, 792 insertions(+), 79 deletions(-) create mode 100644 tests/old/testsuite/capsnego/enum.c create mode 100644 testsuite/capsnego/enum.c diff --git a/gst/gst.c b/gst/gst.c index 15ab7fb08b..0b0189b7f5 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -71,6 +71,8 @@ gst_init (int *argc, char **argv[]) _gst_cpu_initialize (); _gst_type_initialize (); + _gst_props_initialize (); + _gst_caps_initialize (); _gst_plugin_initialize (); _gst_buffer_initialize (); diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c index 465986a7ff..5f29ab84d1 100644 --- a/gst/gstbuffer.c +++ b/gst/gstbuffer.c @@ -27,8 +27,8 @@ #include "gstbuffer.h" -GMemChunk *_gst_buffer_chunk; -GMutex *chunck_lock; +static GMemChunk *_gst_buffer_chunk; +static GMutex *_gst_buffer_chunk_lock; void _gst_buffer_initialize (void) @@ -36,7 +36,7 @@ _gst_buffer_initialize (void) _gst_buffer_chunk = g_mem_chunk_new ("GstBuffer", sizeof(GstBuffer), sizeof(GstBuffer) * 16, G_ALLOC_AND_FREE); - chunck_lock = g_mutex_new (); + _gst_buffer_chunk_lock = g_mutex_new (); } /** @@ -51,9 +51,9 @@ gst_buffer_new(void) { GstBuffer *buffer; - g_mutex_lock (chunck_lock); + g_mutex_lock (_gst_buffer_chunk_lock); buffer = g_mem_chunk_alloc (_gst_buffer_chunk); - g_mutex_unlock (chunck_lock); + g_mutex_unlock (_gst_buffer_chunk_lock); GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer); // g_print("allocating new mutex\n"); @@ -112,9 +112,9 @@ gst_buffer_create_sub (GstBuffer *parent, g_return_val_if_fail (size > 0, NULL); g_return_val_if_fail ((offset+size) <= parent->size, NULL); - g_mutex_lock (chunck_lock); + g_mutex_lock (_gst_buffer_chunk_lock); buffer = g_mem_chunk_alloc (_gst_buffer_chunk); - g_mutex_unlock (chunck_lock); + g_mutex_unlock (_gst_buffer_chunk_lock); GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p", buffer, parent); buffer->lock = g_mutex_new (); @@ -235,9 +235,9 @@ void gst_buffer_destroy (GstBuffer *buffer) //g_print("freed mutex\n"); // remove it entirely from memory - g_mutex_lock (chunck_lock); + g_mutex_lock (_gst_buffer_chunk_lock); g_mem_chunk_free (_gst_buffer_chunk,buffer); - g_mutex_unlock (chunck_lock); + g_mutex_unlock (_gst_buffer_chunk_lock); } /** diff --git a/gst/gstcaps.c b/gst/gstcaps.c index 4e6b8f3de7..c878915ad8 100644 --- a/gst/gstcaps.c +++ b/gst/gstcaps.c @@ -28,10 +28,16 @@ #include "gstpropsprivate.h" +static GMemChunk *_gst_caps_chunk; +static GMutex *_gst_caps_chunk_lock; void _gst_caps_initialize (void) { + _gst_caps_chunk = g_mem_chunk_new ("GstCaps", + sizeof (GstCaps), sizeof (GstCaps) * 256, + G_ALLOC_AND_FREE); + _gst_caps_chunk_lock = g_mutex_new (); } static guint16 @@ -68,11 +74,15 @@ gst_caps_new (const gchar *name, const gchar *mime) g_return_val_if_fail (mime != NULL, NULL); - caps = g_new0 (GstCaps, 1); + 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->properties = NULL; caps->next = NULL; + caps->refcount = 1; return caps; } @@ -128,7 +138,6 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter) { GstCapsFactoryEntry tag; gint i = 0; - guint16 typeid; gchar *name; GstCaps *caps; @@ -142,20 +151,110 @@ gst_caps_register_count (GstCapsFactory *factory, guint *counter) tag = (*factory)[i++]; g_return_val_if_fail (tag != NULL, NULL); - typeid = get_type_for_mime ((gchar *)tag); - - caps = g_new0 (GstCaps, 1); - g_return_val_if_fail (caps != NULL, NULL); - - caps->name = g_strdup (name); - caps->id = typeid; - caps->properties = gst_props_register_count (&(*factory)[i], counter); + caps = gst_caps_new_with_props (name, (gchar *)tag, + gst_props_register_count (&(*factory)[i], counter)); *counter += 2; return caps; } +/** + * gst_caps_destroy: + * @caps: the caps to destroy + * + * Frees the memory used by this caps structure and all + * the chained caps and properties. + */ +void +gst_caps_destroy (GstCaps *caps) +{ + g_return_if_fail (caps != NULL); + + if (caps->next) + gst_caps_unref (caps->next); + + g_free (caps->name); + g_free (caps); +} + +/** + * gst_caps_unref: + * @caps: the caps to unref + * + * Decrease the refcount of this caps structure, + * destroying it when the refcount is 0 + */ +void +gst_caps_unref (GstCaps *caps) +{ + g_return_if_fail (caps != NULL); + + caps->refcount--; + + if (caps->next) + gst_caps_unref (caps->next); + + if (caps->refcount == 0) + gst_caps_destroy (caps); +} + +/** + * gst_caps_ref: + * @caps: the caps to ref + * + * Increase the refcount of this caps structure + */ +void +gst_caps_ref (GstCaps *caps) +{ + g_return_if_fail (caps != NULL); + + caps->refcount++; +} + +/** + * gst_caps_copy_on_write: + * @caps: the caps to copy + * + * Copies the caps if the refcount is greater than 1 + */ +GstCaps* +gst_caps_copy (GstCaps *caps) +{ + GstCaps *new = caps;; + + g_return_val_if_fail (caps != NULL, NULL); + + new = gst_caps_new_with_props ( + caps->name, + (gst_type_find_by_id (caps->id))->mime, + gst_props_copy (caps->properties)); + + return new; +} + +/** + * gst_caps_copy_on_write: + * @caps: the caps to copy + * + * Copies the caps if the refcount is greater than 1 + */ +GstCaps* +gst_caps_copy_on_write (GstCaps *caps) +{ + GstCaps *new = caps;; + + g_return_val_if_fail (caps != NULL, NULL); + + if (caps->refcount > 1) { + new = gst_caps_copy (caps); + gst_caps_unref (caps); + } + + return new; +} + /** * gst_caps_get_name: * @caps: the caps to get the name from @@ -479,8 +578,14 @@ gst_caps_load_thyself (xmlNodePtr parent) while (field) { if (!strcmp (field->name, "capscomp")) { xmlNodePtr subfield = field->xmlChildrenNode; - GstCaps *caps = g_new0 (GstCaps, 1); + GstCaps *caps; gchar *content; + + g_mutex_lock (_gst_caps_chunk_lock); + caps = g_mem_chunk_alloc0 (_gst_caps_chunk); + g_mutex_unlock (_gst_caps_chunk_lock); + + caps->refcount = 1; while (subfield) { if (!strcmp (subfield->name, "name")) { diff --git a/gst/gstcaps.h b/gst/gstcaps.h index 626a51a31d..2521e7a70e 100644 --- a/gst/gstcaps.h +++ b/gst/gstcaps.h @@ -45,9 +45,10 @@ typedef GstCapsFactoryEntry GstCapsFactory[]; struct _GstCaps { gchar *name; /* the name of this caps */ - guint16 id; /* type id (major type) */ + guint refcount; + GstProps *properties; /* properties for this capability */ GstCaps *next; @@ -61,6 +62,13 @@ GstCaps* gst_caps_new_with_props (const gchar *name, const gchar *mime, GstPro GstCaps* gst_caps_register (GstCapsFactory *factory); GstCaps* gst_caps_register_count (GstCapsFactory *factory, guint *counter); +void gst_caps_unref (GstCaps *caps); +void gst_caps_ref (GstCaps *caps); +void gst_caps_destroy (GstCaps *caps); + +GstCaps* gst_caps_copy (GstCaps *caps); +GstCaps* gst_caps_copy_on_write (GstCaps *caps); + const gchar* gst_caps_get_name (GstCaps *caps); void gst_caps_set_name (GstCaps *caps, const gchar *name); diff --git a/gst/gstpad.c b/gst/gstpad.c index 14c46a10b5..3aa883816b 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -740,9 +740,13 @@ gst_pad_set_caps (GstPad *pad, if (!gst_caps_check_compatibility (caps, gst_pad_get_padtemplate_caps (pad))) { g_warning ("pad %s:%s tried to set caps incompatible with its padtemplate\n", GST_DEBUG_PAD_NAME (pad)); - return FALSE; + //return FALSE; } + if (GST_PAD_CAPS (pad)) + gst_caps_unref (GST_PAD_CAPS (pad)); + + gst_caps_ref (caps); GST_PAD_CAPS(pad) = caps; return gst_pad_renegotiate (pad); @@ -945,7 +949,7 @@ gst_pad_renegotiate_func (GstPad *pad, GstPad *peerpad, GstCaps **newcaps, gint matchtempl = gst_caps_check_compatibility (*newcaps, gst_pad_get_padtemplate_caps (GST_PAD (otherpad))); - GST_DEBUG (GST_CAT_ELEMENT_PADS, "caps compatibility check %d\n", matchtempl); + GST_DEBUG (GST_CAT_ELEMENT_PADS, "caps compatibility check %s\n", (matchtempl?"ok":"fail")); if (matchtempl) { if (otherpad->negotiatefunc) { @@ -963,17 +967,19 @@ gst_pad_renegotiate_func (GstPad *pad, GstPad *peerpad, GstCaps **newcaps, gint } else { *newcaps = GST_PAD_CAPS (otherpad); + gst_caps_ref(*newcaps); } } else { *newcaps = GST_PAD_CAPS (otherpad); + gst_caps_ref(*newcaps); } (*counter)++; if (currentpad->negotiatefunc) { - GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s\n", - GST_DEBUG_PAD_NAME (currentpad)); + GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s counter: %d\n", + GST_DEBUG_PAD_NAME (currentpad), *counter); result = currentpad->negotiatefunc (GST_PAD (currentpad), newcaps, *counter); switch (result) { @@ -995,6 +1001,9 @@ gst_pad_renegotiate_func (GstPad *pad, GstPad *peerpad, GstCaps **newcaps, gint } while (*counter < 100); + g_warning ("negotiation between (%s:%s) and (%s:%s) failed: too many attempts (%d)\n", + GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad), *counter); + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation failed, too many attempts\n"); return FALSE; @@ -1051,28 +1060,31 @@ gst_pad_renegotiate (GstPad *pad) GstPadNegotiateReturn -gst_pad_negotiate_proxy (GstPad *pad, GstCaps **caps, gint counter) +gst_pad_negotiate_proxy (GstPad *srcpad, GstPad *destpad, GstCaps **caps, gint counter) { - GstRealPad *peer; + GstRealPad *srcpeer; + GstRealPad *destpeer; gboolean result; - g_return_val_if_fail (pad != NULL, GST_PAD_NEGOTIATE_FAIL); + g_return_val_if_fail (srcpad != NULL, GST_PAD_NEGOTIATE_FAIL); + g_return_val_if_fail (destpad != NULL, GST_PAD_NEGOTIATE_FAIL); - GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation proxied to pad (%s:%s)\n", GST_DEBUG_PAD_NAME (pad)); + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation proxied from pad (%s:%s) to pad (%s:%s)\n", + GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (destpad)); - peer = GST_RPAD_PEER (pad); + srcpeer = GST_RPAD_PEER (srcpad); + destpeer = GST_RPAD_PEER (destpad); - //GST_PAD_CAPS (pad) = caps; - - if (peer) { - result = gst_pad_renegotiate_func (pad, GST_PAD (peer), caps, &counter); + if (srcpeer && destpeer) { + counter--; + result = gst_pad_renegotiate_func (GST_PAD (srcpeer), GST_PAD (destpeer), caps, &counter); if (result) { GST_DEBUG (GST_CAT_ELEMENT_PADS, "pads aggreed on caps :)\n"); /* here we have some sort of aggreement of the caps */ - GST_PAD_CAPS (pad) = *caps; - GST_PAD_CAPS (peer) = *caps; + GST_PAD_CAPS (srcpad) = *caps; + GST_PAD_CAPS (destpad) = *caps; } else { return GST_PAD_NEGOTIATE_FAIL; diff --git a/gst/gstpad.h b/gst/gstpad.h index f11cc89c3a..55e24a0463 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -309,7 +309,7 @@ gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad); void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad); gboolean gst_pad_renegotiate (GstPad *pad); -GstPadNegotiateReturn gst_pad_negotiate_proxy (GstPad *pad, GstCaps **caps, gint count); +GstPadNegotiateReturn gst_pad_negotiate_proxy (GstPad *srcpad, GstPad *destpad, GstCaps **caps, gint count); #if 1 void gst_pad_push (GstPad *pad, GstBuffer *buf); diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 557232a27c..edeba3dbc7 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -227,7 +227,7 @@ gst_plugin_load_all(void) path = _gst_plugin_paths; while (path != NULL) { - GST_INFO (GST_CAT_PLUGIN_LOADING,"loading plugins from %s\n",(gchar *)path->data); + GST_INFO (GST_CAT_PLUGIN_LOADING,"loading plugins from %s",(gchar *)path->data); gst_plugin_load_recurse(path->data,NULL); path = g_list_next(path); } diff --git a/gst/gstprops.c b/gst/gstprops.c index e0e6429203..211a147236 100644 --- a/gst/gstprops.c +++ b/gst/gstprops.c @@ -26,6 +26,11 @@ #include "gstprops.h" #include "gstpropsprivate.h" +static GMemChunk *_gst_props_entries_chunk; +static GMutex *_gst_props_entries_chunk_lock; + +static GMemChunk *_gst_props_chunk; +static GMutex *_gst_props_chunk_lock; static gboolean gst_props_entry_check_compatibility (GstPropsEntry *entry1, GstPropsEntry *entry2); @@ -41,16 +46,27 @@ static guint _arg_len[] = { void _gst_props_initialize (void) { + _gst_props_entries_chunk = g_mem_chunk_new ("GstPropsEntries", + sizeof (GstPropsEntry), sizeof (GstPropsEntry) * 256, + G_ALLOC_AND_FREE); + _gst_props_entries_chunk_lock = g_mutex_new (); + + _gst_props_chunk = g_mem_chunk_new ("GstProps", + sizeof (GstProps), sizeof (GstProps) * 256, + G_ALLOC_AND_FREE); + _gst_props_chunk_lock = g_mutex_new (); } -static GstPropsEntry * +static GstPropsEntry* gst_props_create_entry (GstPropsFactory factory, gint *skipped) { GstPropsFactoryEntry tag; GstPropsEntry *entry; guint i=0; - entry = g_new0 (GstPropsEntry, 1); + 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); tag = factory[i++]; switch (GPOINTER_TO_INT (tag)) { @@ -68,15 +84,17 @@ gst_props_create_entry (GstPropsFactory factory, gint *skipped) entry->data.fourcc_data = GPOINTER_TO_INT (factory[i++]); break; case GST_PROPS_LIST_ID_NUM: - g_print("gstprops: list not allowed in list\n"); + g_warning ("gstprops: list not allowed in list\n"); break; case GST_PROPS_BOOL_ID_NUM: entry->propstype = GST_PROPS_BOOL_ID_NUM; entry->data.bool_data = GPOINTER_TO_INT (factory[i++]); break; default: - g_print("gstprops: unknown props id found\n"); - g_free (entry); + g_warning ("gstprops: unknown props id found\n"); + 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); entry = NULL; break; } @@ -146,10 +164,14 @@ gst_props_register_count (GstPropsFactory factory, guint *counter) if (!tag) goto end; - props = g_new0 (GstProps, 1); + g_mutex_lock (_gst_props_chunk_lock); + props = g_mem_chunk_alloc (_gst_props_chunk); + g_mutex_unlock (_gst_props_chunk_lock); + g_return_val_if_fail (props != NULL, NULL); props->properties = NULL; + props->refcount = 1; while (tag) { GQuark quark; @@ -168,7 +190,10 @@ gst_props_register_count (GstPropsFactory factory, guint *counter) { GstPropsEntry *list_entry; - entry = g_new0 (GstPropsEntry, 1); + 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->propid = quark; entry->propstype = GST_PROPS_LIST_ID_NUM; entry->data.list_data.entries = NULL; @@ -331,6 +356,99 @@ gst_props_set (GstProps *props, const gchar *name, GstPropsFactoryEntry entry, . return props; } +void +gst_props_unref (GstProps *props) +{ + g_return_if_fail (props != NULL); + + props->refcount--; + + if (props->refcount == 0) + gst_props_destroy (props); +} + +void +gst_props_ref (GstProps *props) +{ + g_return_if_fail (props != NULL); + + props->refcount++; +} + +void +gst_props_destroy (GstProps *props) +{ + GList *entries; + + g_return_if_fail (props != NULL); + + entries = props->properties; + + while (entries) { + GstPropsEntry *entry = (GstPropsEntry *)entries->data; + + // FIXME also free the lists + 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); + + entries = g_list_next (entries); + } + + g_list_free (props->properties); +} + +GstProps* +gst_props_copy (GstProps *props) +{ + GstProps *new; + GList *properties; + + g_return_val_if_fail (props != NULL, 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); + + return new; +} + +GstProps* +gst_props_copy_on_write (GstProps *props) +{ + GstProps *new = props;; + + g_return_val_if_fail (props != NULL, NULL); + + if (props->refcount > 1) { + new = gst_props_copy (props); + gst_props_unref (props); + } + + return props; +} + gint gst_props_get_int (GstProps *props, const gchar *name) { @@ -681,7 +799,9 @@ gst_props_load_thyself_func (xmlNodePtr field) GstPropsEntry *entry; gchar *prop; - entry = g_new0 (GstPropsEntry, 1); + 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); if (!strcmp(field->name, "int")) { entry->propstype = GST_PROPS_INT_ID_NUM; @@ -724,7 +844,9 @@ gst_props_load_thyself_func (xmlNodePtr field) g_free (prop); } else { - g_free (entry); + 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); entry = NULL; } @@ -742,17 +864,28 @@ gst_props_load_thyself_func (xmlNodePtr field) GstProps* gst_props_load_thyself (xmlNodePtr parent) { - GstProps *props = g_new0 (GstProps, 1); + GstProps *props; 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; + while (field) { if (!strcmp (field->name, "list")) { GstPropsEntry *entry; xmlNodePtr subfield = field->xmlChildrenNode; - entry = g_new0 (GstPropsEntry, 1); + 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_NUM; + entry->data.list_data.entries = NULL; prop = xmlGetProp (field, "name"); entry->propid = g_quark_from_string (prop); g_free (prop); diff --git a/gst/gstprops.h b/gst/gstprops.h index aae07a3fc4..cc9fe398bd 100644 --- a/gst/gstprops.h +++ b/gst/gstprops.h @@ -67,6 +67,8 @@ typedef enum { struct _GstProps { + gint refcount; + GList *properties; /* real properties for this property */ }; @@ -78,6 +80,13 @@ GstProps* gst_props_register_count (GstPropsFactory factory, guint *counter); GstProps* gst_props_new (GstPropsFactoryEntry entry, ...); +void gst_props_unref (GstProps *props); +void gst_props_ref (GstProps *props); +void gst_props_destroy (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); diff --git a/gst/gstqueue.c b/gst/gstqueue.c index 43f3211fc7..9b7a4c18fb 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -159,17 +159,10 @@ gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - if (counter == 0) { - *caps = NULL; - return GST_PAD_NEGOTIATE_TRY; - } - if (*caps) { - if (counter == 1) { - return gst_pad_negotiate_proxy (queue->sinkpad, caps, counter); - } - } + return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps, counter); + - return GST_PAD_NEGOTIATE_FAIL; + //return GST_PAD_NEGOTIATE_FAIL; } static GstPadNegotiateReturn @@ -179,17 +172,19 @@ gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + /* if (counter == 0) { *caps = NULL; return GST_PAD_NEGOTIATE_TRY; } if (*caps) { - if (counter == 1) { - return gst_pad_negotiate_proxy (queue->srcpad, caps, counter); - } + */ + return gst_pad_negotiate_proxy (pad, queue->srcpad, caps, counter); + /* } return GST_PAD_NEGOTIATE_FAIL; + */ } static gboolean diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 43f3211fc7..9b7a4c18fb 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -159,17 +159,10 @@ gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - if (counter == 0) { - *caps = NULL; - return GST_PAD_NEGOTIATE_TRY; - } - if (*caps) { - if (counter == 1) { - return gst_pad_negotiate_proxy (queue->sinkpad, caps, counter); - } - } + return gst_pad_negotiate_proxy (pad, queue->sinkpad, caps, counter); + - return GST_PAD_NEGOTIATE_FAIL; + //return GST_PAD_NEGOTIATE_FAIL; } static GstPadNegotiateReturn @@ -179,17 +172,19 @@ gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); + /* if (counter == 0) { *caps = NULL; return GST_PAD_NEGOTIATE_TRY; } if (*caps) { - if (counter == 1) { - return gst_pad_negotiate_proxy (queue->srcpad, caps, counter); - } + */ + return gst_pad_negotiate_proxy (pad, queue->srcpad, caps, counter); + /* } return GST_PAD_NEGOTIATE_FAIL; + */ } static gboolean diff --git a/tests/old/testsuite/capsnego/Makefile.am b/tests/old/testsuite/capsnego/Makefile.am index 99c79043e9..c2ac4395e7 100644 --- a/tests/old/testsuite/capsnego/Makefile.am +++ b/tests/old/testsuite/capsnego/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = -testprogs = capsnego converter converter2 +testprogs = capsnego converter converter2 enum TESTS = $(testprogs) diff --git a/tests/old/testsuite/capsnego/converter2.c b/tests/old/testsuite/capsnego/converter2.c index 1091dc25a0..0532c76956 100644 --- a/tests/old/testsuite/capsnego/converter2.c +++ b/tests/old/testsuite/capsnego/converter2.c @@ -104,7 +104,7 @@ converter_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) if (counter == 1) { converter_out = gst_caps_get_int (*caps, "rate"); - return gst_pad_negotiate_proxy (srcconvpad, caps, counter); + return gst_pad_negotiate_proxy (pad, srcconvpad, caps, counter); } return GST_PAD_NEGOTIATE_AGREE; } diff --git a/tests/old/testsuite/capsnego/enum.c b/tests/old/testsuite/capsnego/enum.c new file mode 100644 index 0000000000..e3959309e9 --- /dev/null +++ b/tests/old/testsuite/capsnego/enum.c @@ -0,0 +1,227 @@ + +#include + +GstPad *srcconvpad, *sinkconvpad; +GstPadTemplate *srcconvtempl, *sinkconvtempl; + +static GstPadFactory src_conv_factory = { + "src", + GST_PAD_FACTORY_SRC, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_src", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstPadFactory sink_conv_factory = { + "src", + GST_PAD_FACTORY_SINK, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_src", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstCapsFactory src_caps = { + "src_caps", + "audio/raw", + "rate", GST_PROPS_INT (3000), + NULL +}; + +static GstCaps *srccaps, *sinkcaps; + +static gint src_rate = 140; +static gint sink_rate = 100; + +static GstPadNegotiateReturn +negotiate_src (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print (">(%d:%d)", src_rate, (*caps)->refcount); + src_rate++; + + if (counter == 0 || caps == NULL) { + g_print ("*"); + *caps = gst_caps_new_with_props ( + "src_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (src_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + gint in_rate = gst_caps_get_int (*caps, "rate"); + g_print ("(%d)", in_rate); + + if (in_rate > 140 && in_rate < 300) { + g_print ("A"); + return GST_PAD_NEGOTIATE_AGREE; + } + + *caps = gst_caps_copy_on_write (*caps); + gst_caps_set (*caps, "rate", GST_PROPS_INT (src_rate)); + g_print ("T"); + return GST_PAD_NEGOTIATE_TRY; + } + + g_print ("F"); + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + + g_print ("<(%d:%d:%p)", sink_rate, (*caps)->refcount, *caps); + sink_rate++; + + if (counter == 0 || *caps == NULL) { + g_print ("*"); + *caps = gst_caps_new_with_props ( + "sink_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (sink_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + gint in_rate = gst_caps_get_int (*caps, "rate"); + g_print ("(%d)", in_rate); + + if (in_rate >= 100 && in_rate < 140) { + g_print ("A"); + return GST_PAD_NEGOTIATE_AGREE; + } + + *caps = gst_caps_copy_on_write (*caps); + g_print ("%p", *caps); + gst_caps_set (*caps, "rate", GST_PROPS_INT (sink_rate)); + + g_print ("T"); + return GST_PAD_NEGOTIATE_TRY; + } + + g_print ("F"); + return GST_PAD_NEGOTIATE_FAIL; +} + +int +main (int argc, char *argv[]) +{ + gboolean overall = TRUE; + gboolean result; + GstElement *queue; + + gst_init (&argc, &argv); + + g_mem_chunk_info(); + + srcconvtempl = gst_padtemplate_new (&src_conv_factory); + sinkconvtempl = gst_padtemplate_new (&sink_conv_factory); + srcconvpad = gst_pad_new_from_template (srcconvtempl, "src"); + sinkconvpad = gst_pad_new_from_template (sinkconvtempl, "sink"); + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, negotiate_sink); + + srccaps = gst_caps_register (&src_caps); + sinkcaps = gst_caps_copy (srccaps); + + g_print ("The wild goose chase...\n"); + + result = gst_pad_connect (srcconvpad, sinkconvpad); + g_print ("pad connect 1: %d\n", result); + overall &= (result == TRUE); + + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("with the src negotiate function disabled...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, NULL); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (120)); + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + g_print ("with the sink negotiate function disabled...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, NULL); + + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (170)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("without negotiate functions...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, NULL); + gst_pad_set_negotiate_function (sinkconvpad, NULL); + + sinkcaps = gst_caps_copy (sinkcaps); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (150)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + sinkcaps = gst_caps_copy (sinkcaps); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (160)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("with a proxy element in between...\n"); + + gst_pad_disconnect (srcconvpad, sinkconvpad); + + queue = gst_elementfactory_make ("queue", "queue"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, negotiate_sink); + + gst_pad_connect (srcconvpad, gst_element_get_pad (queue, "sink")); + gst_pad_connect (gst_element_get_pad (queue, "src"), sinkconvpad); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (50)); + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + exit (!overall); +} diff --git a/testsuite/capsnego/Makefile.am b/testsuite/capsnego/Makefile.am index 99c79043e9..c2ac4395e7 100644 --- a/testsuite/capsnego/Makefile.am +++ b/testsuite/capsnego/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = -testprogs = capsnego converter converter2 +testprogs = capsnego converter converter2 enum TESTS = $(testprogs) diff --git a/testsuite/capsnego/converter2.c b/testsuite/capsnego/converter2.c index 1091dc25a0..0532c76956 100644 --- a/testsuite/capsnego/converter2.c +++ b/testsuite/capsnego/converter2.c @@ -104,7 +104,7 @@ converter_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) if (counter == 1) { converter_out = gst_caps_get_int (*caps, "rate"); - return gst_pad_negotiate_proxy (srcconvpad, caps, counter); + return gst_pad_negotiate_proxy (pad, srcconvpad, caps, counter); } return GST_PAD_NEGOTIATE_AGREE; } diff --git a/testsuite/capsnego/enum.c b/testsuite/capsnego/enum.c new file mode 100644 index 0000000000..e3959309e9 --- /dev/null +++ b/testsuite/capsnego/enum.c @@ -0,0 +1,227 @@ + +#include + +GstPad *srcconvpad, *sinkconvpad; +GstPadTemplate *srcconvtempl, *sinkconvtempl; + +static GstPadFactory src_conv_factory = { + "src", + GST_PAD_FACTORY_SRC, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_src", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstPadFactory sink_conv_factory = { + "src", + GST_PAD_FACTORY_SINK, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_src", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstCapsFactory src_caps = { + "src_caps", + "audio/raw", + "rate", GST_PROPS_INT (3000), + NULL +}; + +static GstCaps *srccaps, *sinkcaps; + +static gint src_rate = 140; +static gint sink_rate = 100; + +static GstPadNegotiateReturn +negotiate_src (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print (">(%d:%d)", src_rate, (*caps)->refcount); + src_rate++; + + if (counter == 0 || caps == NULL) { + g_print ("*"); + *caps = gst_caps_new_with_props ( + "src_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (src_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + gint in_rate = gst_caps_get_int (*caps, "rate"); + g_print ("(%d)", in_rate); + + if (in_rate > 140 && in_rate < 300) { + g_print ("A"); + return GST_PAD_NEGOTIATE_AGREE; + } + + *caps = gst_caps_copy_on_write (*caps); + gst_caps_set (*caps, "rate", GST_PROPS_INT (src_rate)); + g_print ("T"); + return GST_PAD_NEGOTIATE_TRY; + } + + g_print ("F"); + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + + g_print ("<(%d:%d:%p)", sink_rate, (*caps)->refcount, *caps); + sink_rate++; + + if (counter == 0 || *caps == NULL) { + g_print ("*"); + *caps = gst_caps_new_with_props ( + "sink_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (sink_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + gint in_rate = gst_caps_get_int (*caps, "rate"); + g_print ("(%d)", in_rate); + + if (in_rate >= 100 && in_rate < 140) { + g_print ("A"); + return GST_PAD_NEGOTIATE_AGREE; + } + + *caps = gst_caps_copy_on_write (*caps); + g_print ("%p", *caps); + gst_caps_set (*caps, "rate", GST_PROPS_INT (sink_rate)); + + g_print ("T"); + return GST_PAD_NEGOTIATE_TRY; + } + + g_print ("F"); + return GST_PAD_NEGOTIATE_FAIL; +} + +int +main (int argc, char *argv[]) +{ + gboolean overall = TRUE; + gboolean result; + GstElement *queue; + + gst_init (&argc, &argv); + + g_mem_chunk_info(); + + srcconvtempl = gst_padtemplate_new (&src_conv_factory); + sinkconvtempl = gst_padtemplate_new (&sink_conv_factory); + srcconvpad = gst_pad_new_from_template (srcconvtempl, "src"); + sinkconvpad = gst_pad_new_from_template (sinkconvtempl, "sink"); + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, negotiate_sink); + + srccaps = gst_caps_register (&src_caps); + sinkcaps = gst_caps_copy (srccaps); + + g_print ("The wild goose chase...\n"); + + result = gst_pad_connect (srcconvpad, sinkconvpad); + g_print ("pad connect 1: %d\n", result); + overall &= (result == TRUE); + + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("with the src negotiate function disabled...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, NULL); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (120)); + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + g_print ("with the sink negotiate function disabled...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, NULL); + + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (170)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("without negotiate functions...\n"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, NULL); + gst_pad_set_negotiate_function (sinkconvpad, NULL); + + sinkcaps = gst_caps_copy (sinkcaps); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (150)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + sinkcaps = gst_caps_copy (sinkcaps); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (160)); + result = gst_pad_set_caps (sinkconvpad, sinkcaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + g_print ("with a proxy element in between...\n"); + + gst_pad_disconnect (srcconvpad, sinkconvpad); + + queue = gst_elementfactory_make ("queue", "queue"); + + GST_PAD_CAPS (srcconvpad) = NULL; + GST_PAD_CAPS (sinkconvpad) = NULL; + src_rate = 140; + sink_rate = 100; + + gst_pad_set_negotiate_function (srcconvpad, negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, negotiate_sink); + + gst_pad_connect (srcconvpad, gst_element_get_pad (queue, "sink")); + gst_pad_connect (gst_element_get_pad (queue, "src"), sinkconvpad); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (50)); + result = gst_pad_set_caps (srcconvpad, srccaps); + g_print ("\nset caps on src: %d, final rate: %d\n", result, + gst_caps_get_int (gst_pad_get_caps (srcconvpad), "rate")); + + + exit (!overall); +}