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.
This commit is contained in:
Wim Taymans 2001-03-20 18:29:00 +00:00
parent 29cb713b21
commit 0267b92c93
17 changed files with 792 additions and 79 deletions

View file

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

View file

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

View file

@ -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,9 +578,15 @@ 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")) {
caps->name = xmlNodeGetContent (subfield);

View file

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

View file

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

View file

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

View file

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

View file

@ -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,6 +46,15 @@ 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*
@ -50,7 +64,9 @@ gst_props_create_entry (GstPropsFactory factory, gint *skipped)
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);

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
SUBDIRS =
testprogs = capsnego converter converter2
testprogs = capsnego converter converter2 enum
TESTS = $(testprogs)

View file

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

View file

@ -0,0 +1,227 @@
#include <gst/gst.h>
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);
}

View file

@ -1,6 +1,6 @@
SUBDIRS =
testprogs = capsnego converter converter2
testprogs = capsnego converter converter2 enum
TESTS = $(testprogs)

View file

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

227
testsuite/capsnego/enum.c Normal file
View file

@ -0,0 +1,227 @@
#include <gst/gst.h>
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);
}