tests/sched/Makefile
tests/eos/Makefile
testsuite/Makefile
+tests/nego/Makefile
examples/Makefile
examples/autoplug/Makefile
examples/helloworld/Makefile
-----------------------
when two pads are connected the following steps will take
-placei (not sure, FIXME):
+place (not sure, FIXME):
- if both pads have caps, the caps are checked. If the caps
are incompatible, the padtemplates are checked, if they
while (pads) {
GstPad *pad = (GstPad *)pads->data;
- GList *caps = gst_pad_get_caps_list (pad);
+ GstCaps *caps = gst_pad_get_caps (pad);
gchar *mime;
gchar *data[2];
GtkCTreeNode *padnode;
if (caps) {
GstType *type;
- type = gst_type_find_by_id (((GstCaps *)caps->data)->id);
+ type = gst_type_find_by_id (caps->id);
mime = type->mime;
}
else {
padnode = gtk_ctree_insert_node (GTK_CTREE (tree), NULL, NULL, data, 0,
NULL, NULL, NULL, NULL, FALSE, TRUE);
- while (caps) {
- GstCaps *cap = (GstCaps *)caps->data;
- gst_editor_add_caps_to_tree (cap, tree, padnode);
-
- caps = g_list_next (caps);
- }
+ gst_editor_add_caps_to_tree (caps, tree, padnode);
pads = g_list_next (pads);
}
static GstElement* gst_static_autoplug_to_caps (GstAutoplug *autoplug,
- GList *srccaps, GList *sinkcaps, va_list args);
+ GstCaps *srccaps, GstCaps *sinkcaps, va_list args);
static GstAutoplugClass *parent_class = NULL;
if (srctemp->direction == GST_PAD_SRC &&
desttemp->direction == GST_PAD_SINK) {
- if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
+ if (gst_caps_check_compatibility (gst_padtemplate_get_caps (srctemp),
+ gst_padtemplate_get_caps (desttemp))) {
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
!GST_PAD_CONNECTED(sinkpad))
{
- if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
+ if (gst_caps_check_compatibility (gst_pad_get_caps(pad), gst_pad_get_caps(sinkpad))) {
gst_pad_connect(pad, sinkpad);
GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
GST_ELEMENT_NAME(src));
typedef struct {
GstElement *result;
- GList *endcap;
+ GstCaps *endcap;
gint i;
} dynamic_pad_struct;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
+ GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
pads = g_list_next (pads);
- if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
+ if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), info->endcap)) {
gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
break;
}
typedef struct {
- GList *src;
- GList *sink;
+ GstCaps *src;
+ GstCaps *sink;
} caps_struct;
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
gboolean res;
if (IS_CAPS (src) && IS_CAPS (dest)) {
- res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
- //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
+ res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)dest);
}
else if (IS_CAPS (src)) {
- res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
- //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
+ res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)src);
}
else if (IS_CAPS (dest)) {
- res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
- //GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
+ res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest);
}
else {
res = gst_autoplug_can_match ((GstElementFactory *)src, (GstElementFactory *)dest);
}
static GstElement*
-gst_static_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args)
+gst_static_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args)
{
caps_struct caps;
- GList *capslist;
+ GstCaps *capslist;
GstElement *result = NULL, *srcelement = NULL;
GList **factories;
GList *chains = NULL;
else {
}
- capslist = va_arg (args, GList *);
+ capslist = va_arg (args, GstCaps *);
}
/*
while (pads) {
GstPad *pad = GST_PAD (pads->data);
+ GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
- if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
+ if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) {
gst_element_add_ghost_pad (result, pad, "sink");
break;
}
* find a suitable pad to turn into a ghostpad
*/
{
- GList *endcap = (GList *)(endcaps->data);
+ GstCaps *endcap = (GstCaps *)(endcaps->data);
GList *pads = gst_element_get_pad_list (thesrcelement);
gboolean have_pad = FALSE;
endcaps = g_list_next (endcaps);
while (pads) {
GstPad *pad = GST_PAD (pads->data);
+ GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
pads = g_list_next (pads);
- if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), endcap)) {
+ if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (templ), endcap)) {
gst_element_add_ghost_pad (result, pad, g_strdup_printf("src_%02d", i));
have_pad = TRUE;
break;
static GstElement* gst_static_autoplug_to_render (GstAutoplug *autoplug,
- GList *srccaps, GstElement *target, va_list args);
+ GstCaps *srccaps, GstElement *target, va_list args);
static GstAutoplugClass *parent_class = NULL;
if (srctemp->direction == GST_PAD_SRC &&
desttemp->direction == GST_PAD_SINK) {
- if (gst_caps_list_check_compatibility (srctemp->caps, desttemp->caps)) {
+ if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (srctemp), GST_PADTEMPLATE_CAPS (desttemp))) {
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,
"factory \"%s\" can connect with factory \"%s\"", src->name, dest->name);
return TRUE;
GstPad *sinkpad = (GstPad *)sinkpads->data;
// if we have a match, connect the pads
- if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
- !GST_PAD_CONNECTED(sinkpad))
+ if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
+ !GST_PAD_CONNECTED (pad) && !GST_PAD_CONNECTED(sinkpad))
{
- if (gst_caps_list_check_compatibility (gst_pad_get_caps_list(pad), gst_pad_get_caps_list(sinkpad))) {
- gst_pad_connect(pad, sinkpad);
- GST_DEBUG (0,"gstpipeline: autoconnect pad \"%s\" in element %s <-> ", GST_PAD_NAME (pad),
- GST_ELEMENT_NAME(src));
- GST_DEBUG (0,"pad \"%s\" in element %s\n", GST_PAD_NAME (sinkpad),
- GST_ELEMENT_NAME(sink));
- connected = TRUE;
- break;
+ if ((connected = gst_pad_connect (pad, sinkpad))) {
+ break;
}
else {
- GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
+ GST_DEBUG (0,"pads incompatible %s, %s\n", GST_PAD_NAME (pad), GST_PAD_NAME (sinkpad));
}
}
sinkpads = g_list_next(sinkpads);
return connected;
}
-typedef struct {
- GstElement *result;
- GList *endcap;
- gint i;
-} dynamic_pad_struct;
-
-static void
-autoplug_dynamic_pad (GstElement *element, GstPad *pad, gpointer data)
-{
- dynamic_pad_struct *info = (dynamic_pad_struct *)data;
- GList *pads = gst_element_get_pad_list (element);
-
- GST_DEBUG (0,"attempting to dynamically create a ghostpad for %s=%s\n", GST_ELEMENT_NAME (element),
- GST_PAD_NAME (pad));
-
- while (pads) {
- GstPad *pad = GST_PAD (pads->data);
- pads = g_list_next (pads);
-
- if (gst_caps_list_check_compatibility (gst_pad_get_caps_list (pad), info->endcap)) {
- gst_element_add_ghost_pad (info->result, pad, g_strdup_printf("src_%02d", info->i));
- GST_DEBUG (0,"gstpipeline: new dynamic pad %s\n", GST_PAD_NAME (pad));
- break;
- }
- }
-}
-
static void
gst_autoplug_pads_autoplug (GstElement *src, GstElement *sink)
{
while (srcpads && !connected) {
GstPad *srcpad = (GstPad *)srcpads->data;
- if (gst_pad_get_direction(srcpad) == GST_PAD_SRC)
+ if (gst_pad_get_direction(srcpad) == GST_PAD_SRC) {
connected = gst_autoplug_pads_autoplug_func (src, srcpad, sink);
+ if (connected)
+ break;
+ }
srcpads = g_list_next(srcpads);
}
}
typedef struct {
- GList *src;
- GList *sink;
+ GstCaps *src;
+ GstCaps *sink;
} caps_struct;
#define IS_CAPS(cap) (((cap) == caps->src) || (cap) == caps->sink)
gboolean res;
if (IS_CAPS (src) && IS_CAPS (dest)) {
- res = gst_caps_list_check_compatibility ((GList *)src, (GList *)dest);
+ res = gst_caps_check_compatibility ((GstCaps *)src, (GstCaps *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"caps %d to caps %d %d", ((GstCaps *)src)->id, ((GstCaps *)dest)->id, res);
}
else if (IS_CAPS (src)) {
- res = gst_elementfactory_can_sink_caps_list ((GstElementFactory *)dest, (GList *)src);
+ res = gst_elementfactory_can_sink_caps ((GstElementFactory *)dest, (GstCaps *)src);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to src caps %d %d", ((GstElementFactory *)dest)->name, ((GstCaps *)src)->id, res);
}
else if (IS_CAPS (dest)) {
- res = gst_elementfactory_can_src_caps_list ((GstElementFactory *)src, (GList *)dest);
+ res = gst_elementfactory_can_src_caps ((GstElementFactory *)src, (GstCaps *)dest);
//GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"factory %s to sink caps %d %d", ((GstElementFactory *)src)->name, ((GstCaps *)dest)->id, res);
}
else {
}
static GstElement*
-gst_static_autoplug_to_render (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args)
+gst_static_autoplug_to_render (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args)
{
caps_struct caps;
GstElement *targetelement;
while (targetelement) {
GList *elements;
GstPad *pad;
+ GstPadTemplate *templ;
pad = GST_PAD (gst_element_get_pad_list (targetelement)->data);
+ templ = GST_PAD_PADTEMPLATE (pad);
- caps.sink = gst_pad_get_caps_list (pad);
+ caps.sink = GST_PADTEMPLATE_CAPS (templ);
GST_INFO (GST_CAT_AUTOPLUG_ATTEMPT,"autoplugging two caps structures");
while (pads) {
GstPad *pad = GST_PAD (pads->data);
+ GstPadTemplate *templ = GST_PAD_PADTEMPLATE (pad);
- if (gst_caps_list_check_compatibility (srccaps, gst_pad_get_caps_list (pad))) {
+ if (gst_caps_check_compatibility (srccaps, GST_PADTEMPLATE_CAPS (templ))) {
gst_element_add_ghost_pad (result, pad, "sink");
break;
}
// this element suggests the use of a thread, so we set one up...
if (GST_ELEMENT_IS_THREAD_SUGGESTED(element) || use_thread) {
GstElement *queue;
- GList *sinkpads;
- GstPad *srcpad, *sinkpad;
+ GstPad *srcpad;
use_thread = FALSE;
srcpad = gst_element_get_pad(queue, "src");
- sinkpads = gst_element_get_pad_list(element);
- while (sinkpads) {
- sinkpad = (GstPad *)sinkpads->data;
-
- // FIXME connect matching pads, not just the first one...
- if (gst_pad_get_direction(sinkpad) == GST_PAD_SINK &&
- !GST_PAD_CONNECTED(sinkpad)) {
- GList *caps = gst_pad_get_caps_list (sinkpad);
-
- // the queue has the type of the elements it connects
- gst_pad_set_caps_list (srcpad, caps);
- gst_pad_set_caps_list (gst_element_get_pad(queue, "sink"), caps);
- break;
- }
- sinkpads = g_list_next(sinkpads);
- }
gst_autoplug_pads_autoplug(thesrcelement, queue);
GST_DEBUG (0,"adding element %s\n", GST_ELEMENT_NAME (element));
/* otherwise (READY or higher) we need to open the sound card */
} else {
if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) {
- if (!gst_audiosink_open_audio (GST_AUDIOSINK (element)))
- return GST_STATE_FAILURE;
+ if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) {
+ //return GST_STATE_FAILURE;
+ }
}
}
GstElement*
-gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...)
+gst_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...)
{
GstAutoplugClass *oclass;
GstElement *element = NULL;
}
GstElement*
-gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps, GstElement *target, ...)
+gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, ...)
{
GstAutoplugClass *oclass;
GstElement *element = NULL;
void (*new_object) (GstAutoplug *autoplug, GstObject *object);
/* perform the autoplugging */
- GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, va_list args);
- GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GList *srccaps, GstElement *target, va_list args);
+ GstElement* (*autoplug_to_caps) (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, va_list args);
+ GstElement* (*autoplug_to_renderers) (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *target, va_list args);
};
typedef struct _GstAutoplugFactory GstAutoplugFactory;
void gst_autoplug_signal_new_object (GstAutoplug *autoplug, GstObject *object);
-GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GList *srccaps, GList *sinkcaps, ...);
-GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GList *srccaps,
+GstElement* gst_autoplug_to_caps (GstAutoplug *autoplug, GstCaps *srccaps, GstCaps *sinkcaps, ...);
+GstElement* gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps,
GstElement *target, ...);
caps->name = g_strdup (name);
caps->id = get_type_for_mime (mime);
caps->properties = NULL;
+ caps->next = NULL;
return caps;
}
}
/**
- * gst_caps_check_compatibility:
- * @fromcaps: a capabilty
- * @tocaps: a capabilty
+ * gst_caps_append:
+ * @caps: a capabilty
+ * @capstoadd: the capability to append
*
- * Checks whether two capabilities are compatible.
+ * Appends a capability to the existing capability.
*
- * Returns: TRUE if compatible, FALSE otherwise
+ * Returns: the new capability
*/
-gboolean
-gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
+GstCaps*
+gst_caps_append (GstCaps *caps, GstCaps *capstoadd)
{
- g_return_val_if_fail (fromcaps != NULL, FALSE);
- g_return_val_if_fail (tocaps != NULL, FALSE);
+ GstCaps *orig = caps;
+
+ if (caps == NULL)
+ return capstoadd;
+
+ while (caps->next) {
+ caps = caps->next;
+ }
+ caps->next = capstoadd;
+
+ return orig;
+}
+
+/**
+ * gst_caps_prepend:
+ * @caps: a capabilty
+ * @capstoadd: a capabilty to prepend
+ *
+ * prepend the capability to the list of capabilities
+ *
+ * Returns: the new capability
+ */
+GstCaps*
+gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd)
+{
+ GstCaps *orig = capstoadd;
+
+ if (capstoadd == NULL)
+ return caps;
+
+ while (capstoadd->next) {
+ capstoadd = capstoadd->next;
+ }
+ capstoadd->next = caps;
+ return orig;
+}
+
+GstCaps*
+gst_caps_get_by_name (GstCaps *caps, const gchar *name)
+{
+ g_return_val_if_fail (caps != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ while (caps) {
+ if (!strcmp (caps->name, name))
+ return caps;
+ caps = caps->next;
+ }
+
+ return NULL;
+}
+
+static gboolean
+gst_caps_check_compatibility_func (GstCaps *fromcaps, GstCaps *tocaps)
+{
+ if (fromcaps == NULL ||
+ tocaps == NULL)
+ return TRUE;
+
if (fromcaps->id != tocaps->id) {
GST_DEBUG (0,"gstcaps: mime types differ (%d to %d)\n",
fromcaps->id, tocaps->id);
* Returns: TRUE if compatible, FALSE otherwise
*/
gboolean
-gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps)
+gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
{
while (fromcaps) {
- GstCaps *fromcap = (GstCaps *)fromcaps->data;
- GList *destcaps = tocaps;
+ GstCaps *destcaps = tocaps;
while (destcaps) {
- GstCaps *destcap = (GstCaps *)destcaps->data;
-
- if (gst_caps_check_compatibility (fromcap, destcap))
+ if (gst_caps_check_compatibility_func (fromcaps, destcaps))
return TRUE;
- destcaps = g_list_next (destcaps);
+ destcaps = destcaps->next;
}
- fromcaps = g_list_next (fromcaps);
+ fromcaps = fromcaps->next;
}
return FALSE;
}
gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent)
{
xmlNodePtr subtree;
+ xmlNodePtr subsubtree;
- g_return_val_if_fail (caps != NULL, NULL);
+ while (caps) {
+ subtree = xmlNewChild (parent, NULL, "capscomp", NULL);
- xmlNewChild (parent, NULL, "name", caps->name);
- xmlNewChild (parent, NULL, "type", gst_type_find_by_id (caps->id)->mime);
- if (caps->properties) {
- subtree = xmlNewChild (parent, NULL, "properties", NULL);
+ xmlNewChild (subtree, NULL, "name", caps->name);
+ xmlNewChild (subtree, NULL, "type", gst_type_find_by_id (caps->id)->mime);
+ if (caps->properties) {
+ subsubtree = xmlNewChild (subtree, NULL, "properties", NULL);
- gst_props_save_thyself (caps->properties, subtree);
+ gst_props_save_thyself (caps->properties, subsubtree);
+ }
+
+ caps = caps->next;
}
return parent;
GstCaps*
gst_caps_load_thyself (xmlNodePtr parent)
{
- GstCaps *caps = g_new0 (GstCaps, 1);
+ GstCaps *result = NULL;
xmlNodePtr field = parent->xmlChildrenNode;
- gchar *content;
while (field) {
- if (!strcmp (field->name, "name")) {
- caps->name = xmlNodeGetContent (field);
- }
- if (!strcmp (field->name, "type")) {
- content = xmlNodeGetContent (field);
- caps->id = get_type_for_mime (content);
- g_free (content);
- }
- else if (!strcmp (field->name, "properties")) {
- caps->properties = gst_props_load_thyself (field);
+ if (!strcmp (field->name, "capscomp")) {
+ xmlNodePtr subfield = field->xmlChildrenNode;
+ GstCaps *caps = g_new0 (GstCaps, 1);
+ gchar *content;
+
+ while (subfield) {
+ if (!strcmp (subfield->name, "name")) {
+ caps->name = xmlNodeGetContent (subfield);
+ }
+ if (!strcmp (subfield->name, "type")) {
+ content = xmlNodeGetContent (subfield);
+ caps->id = get_type_for_mime (content);
+ g_free (content);
+ }
+ else if (!strcmp (subfield->name, "properties")) {
+ caps->properties = gst_props_load_thyself (subfield);
+ }
+
+ subfield = subfield->next;
+ }
+ result = gst_caps_append (result, caps);
}
field = field->next;
}
- return caps;
+ return result;
}
guint16 id; /* type id (major type) */
GstProps *properties; /* properties for this capability */
+
+ GstCaps *next;
};
/* initialize the subsystem */
GstCaps* gst_caps_set_props (GstCaps *caps, GstProps *props);
GstProps* gst_caps_get_props (GstCaps *caps);
+GstCaps* gst_caps_get_by_name (GstCaps *caps, const gchar *name);
+
+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);
-gboolean gst_caps_list_check_compatibility (GList *fromcaps, GList *tocaps);
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
GstCaps* gst_caps_load_thyself (xmlNodePtr parent);
if (padtempl->direction == GST_PAD_SRC &&
compattempl->direction == GST_PAD_SINK) {
GST_DEBUG(0,"compatible direction: found src pad template\n");
- compat = gst_caps_list_check_compatibility(padtempl->caps,
- compattempl->caps);
+ compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (padtempl),
+ GST_PADTEMPLATE_CAPS (compattempl));
GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not "));
} else if (padtempl->direction == GST_PAD_SINK &&
compattempl->direction == GST_PAD_SRC) {
GST_DEBUG(0,"compatible direction: found sink pad template\n");
- compat = gst_caps_list_check_compatibility(compattempl->caps,
- padtempl->caps);
+ compat = gst_caps_check_compatibility(GST_PADTEMPLATE_CAPS (compattempl),
+ GST_PADTEMPLATE_CAPS (padtempl));
GST_DEBUG(0,"caps are %scompatible\n", (compat?"":"not "));
}
GstCaps *caps);
gboolean gst_elementfactory_can_sink_caps (GstElementFactory *factory,
GstCaps *caps);
-gboolean gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
- GList *caps);
-gboolean gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
- GList *caps);
+gboolean gst_elementfactory_can_src_caps (GstElementFactory *factory,
+ GstCaps *caps);
+gboolean gst_elementfactory_can_sink_caps (GstElementFactory *factory,
+ GstCaps *caps);
GstElement* gst_elementfactory_create (GstElementFactory *factory,
const gchar *name);
}
/**
- * gst_elementfactory_can_src_caps_list :
+ * gst_elementfactory_can_src_caps :
* @factory: factory to query
- * @caps: the caps list to check
+ * @caps: the caps to check
*
- * Checks if the factory can source the given capability list.
+ * Checks if the factory can source the given capability.
*
* Returns: true if it can src the capabilities
*/
gboolean
-gst_elementfactory_can_src_caps_list (GstElementFactory *factory,
- GList *caps)
+gst_elementfactory_can_src_caps (GstElementFactory *factory,
+ GstCaps *caps)
{
GList *templates;
GstPadTemplate *template = (GstPadTemplate *)templates->data;
if (template->direction == GST_PAD_SRC) {
- if (gst_caps_list_check_compatibility (template->caps, caps))
+ if (gst_caps_check_compatibility (GST_PADTEMPLATE_CAPS (template), caps))
return TRUE;
}
templates = g_list_next (templates);
}
/**
- * gst_elementfactory_can_sink_caps_list :
+ * gst_elementfactory_can_sink_caps :
* @factory: factory to query
- * @caps: the caps list to check
+ * @caps: the caps to check
*
- * Checks if the factory can sink the given capability list.
+ * Checks if the factory can sink the given capability.
*
* Returns: true if it can sink the capabilities
*/
gboolean
-gst_elementfactory_can_sink_caps_list (GstElementFactory *factory,
- GList *caps)
+gst_elementfactory_can_sink_caps (GstElementFactory *factory,
+ GstCaps *caps)
{
GList *templates;
GstPadTemplate *template = (GstPadTemplate *)templates->data;
if (template->direction == GST_PAD_SINK) {
- if (gst_caps_list_check_compatibility (caps, template->caps))
+ if (gst_caps_check_compatibility (caps, GST_PADTEMPLATE_CAPS (template)))
return TRUE;
}
templates = g_list_next (templates);
}
/**
- * gst_elementfactory_can_src_caps :
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can src the given capability.
- *
- * Returns: true if it can sink the capability
- */
-gboolean
-gst_elementfactory_can_src_caps (GstElementFactory *factory,
- GstCaps *caps)
-{
- GList *dummy;
- gboolean ret;
-
- dummy = g_list_prepend (NULL, caps);
-
- ret = gst_elementfactory_can_src_caps_list (factory, dummy);
-
- g_list_free (dummy);
-
- return ret;
-}
-
-/**
- * gst_elementfactory_can_sink_caps :
- * @factory: factory to query
- * @caps: the caps to check
- *
- * Checks if the factory can sink the given capability.
- *
- * Returns: true if it can sink the capability
- */
-gboolean
-gst_elementfactory_can_sink_caps (GstElementFactory *factory,
- GstCaps *caps)
-{
- GList *dummy;
- gboolean ret;
-
- dummy = g_list_prepend (NULL, caps);
-
- ret = gst_elementfactory_can_sink_caps_list (factory, dummy);
-
- g_list_free (dummy);
-
- return ret;
-}
-
-/**
* gst_elementfactory_save_thyself:
* @factory: factory to save
* @parent: the parent xmlNodePtr
g_return_val_if_fail (templ != NULL, NULL);
pad = gst_pad_new (name, templ->direction);
- GST_PAD_CAPS(pad) = templ->caps;
GST_PAD_PADTEMPLATE(pad) = templ;
+ GST_PAD_CAPS (pad) = GST_PADTEMPLATE_CAPS (templ);
return pad;
}
GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_EOSFUNC(pad),eos);
}
+/**
+ * gst_pad_set_eos_function:
+ * @pad: the pad to set the eos function for
+ * @eos: the eos function
+ *
+ * Set the given EOS function for the pad.
+ */
+void
+gst_pad_set_negotiate_function (GstPad *pad,
+ GstPadNegotiateFunction nego)
+{
+ g_return_if_fail (pad != NULL);
+ g_return_if_fail (GST_IS_REAL_PAD (pad));
+
+ GST_RPAD_NEGOTIATEFUNC(pad) = nego;
+ GST_DEBUG (0,"negotiatefunc for %s:%s(@%p) at %p is set to %p\n",
+ GST_DEBUG_PAD_NAME(pad),pad,&GST_RPAD_NEGOTIATEFUNC(pad),nego);
+}
+
static void
* @sinkpad: the sink pad to connect
*
* Connects the source pad to the sink pad.
+ *
+ * Returns: TRUE if the pad could be connected
*/
-void
+gboolean
gst_pad_connect (GstPad *srcpad,
GstPad *sinkpad)
{
GstRealPad *realsrc, *realsink;
GstRealPad *temppad;
+ gboolean negotiated = FALSE;
/* generic checks */
- g_return_if_fail(srcpad != NULL);
- g_return_if_fail(GST_IS_PAD(srcpad));
- g_return_if_fail(sinkpad != NULL);
- g_return_if_fail(GST_IS_PAD(sinkpad));
+ g_return_val_if_fail(srcpad != NULL, FALSE);
+ g_return_val_if_fail(GST_IS_PAD(srcpad), FALSE);
+ g_return_val_if_fail(sinkpad != NULL, FALSE);
+ g_return_val_if_fail(GST_IS_PAD(sinkpad), FALSE);
+
+ GST_INFO (GST_CAT_ELEMENT_PADS, "about to connect %s:%s and %s:%s",
+ GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
// now we need to deal with the real/ghost stuff
realsrc = GST_PAD_REALIZE(srcpad);
realsink = GST_PAD_REALIZE(sinkpad);
- g_return_if_fail(GST_RPAD_PEER(realsrc) == NULL);
- g_return_if_fail(GST_RPAD_PEER(realsink) == NULL);
+ g_return_val_if_fail(GST_RPAD_PEER(realsrc) == NULL, FALSE);
+ g_return_val_if_fail(GST_RPAD_PEER(realsink) == NULL, FALSE);
/* check for reversed directions and swap if necessary */
if ((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SINK) &&
realsrc = realsink;
realsink = temppad;
}
- g_return_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
- (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK));
+ g_return_val_if_fail((GST_RPAD_DIRECTION(realsrc) == GST_PAD_SRC) &&
+ (GST_RPAD_DIRECTION(realsink) == GST_PAD_SINK), FALSE);
- if (!gst_pad_check_compatibility (srcpad, sinkpad)) {
- g_warning ("gstpad: connecting incompatible pads (%s:%s) and (%s:%s)\n",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
- }
- else {
- GST_DEBUG (0,"gstpad: connecting compatible pads (%s:%s) and (%s:%s)\n",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
- }
/* first set peers */
GST_RPAD_PEER(realsrc) = realsink;
GST_RPAD_PEER(realsink) = realsrc;
- /* set the connected flag */
/* FIXME: set connected flag */
GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s",
GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
+
+ if (GST_PAD_CAPS (srcpad)) {
+ negotiated = gst_pad_renegotiate (srcpad);
+ }
+ else {
+ negotiated = gst_pad_renegotiate (sinkpad);
+ }
+
+ if (!negotiated) {
+ gst_pad_disconnect (srcpad, sinkpad);
+ return FALSE;
+ }
+ return TRUE;
}
/**
*
* Returns: the parent object
*/
+GstPadTemplate*
+gst_pad_get_padtemplate (GstPad *pad)
+{
+ g_return_val_if_fail (pad != NULL, NULL);
+ g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+
+ return GST_PAD_PADTEMPLATE (pad);
+}
+
+/**
+ * gst_pad_get_parent:
+ * @pad: the pad to get the parent from
+ *
+ * Get the parent object of this pad.
+ *
+ * Returns: the parent object
+ */
GstObject*
gst_pad_get_parent (GstPad *pad)
{
}
/**
- * gst_pad_set_caps_list:
+ * gst_pad_set_caps:
* @pad: the pad to set the caps to
* @caps: a GList of the capabilities to attach to this pad
*
* Set the capabilities of this pad.
*/
void
-gst_pad_set_caps_list (GstPad *pad,
- GList *caps)
+gst_pad_set_caps (GstPad *pad,
+ GstCaps *caps)
{
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_REAL_PAD (pad)); // NOTE this restriction
GST_PAD_CAPS(pad) = caps;
+
+ gst_pad_renegotiate (pad);
}
/**
*
* Returns: a list of the capabilities of this pad
*/
-GList *
-gst_pad_get_caps_list (GstPad *pad)
+GstCaps*
+gst_pad_get_caps (GstPad *pad)
{
g_return_val_if_fail (pad != NULL, NULL);
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
*
* Returns: a capability or NULL if not found
*/
-GstCaps *
-gst_pad_get_caps_by_name (GstPad *pad, gchar *name)
+GstCaps*
+gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name)
{
- GList *caps;
-
- g_return_val_if_fail (pad != NULL, NULL);
- g_return_val_if_fail (GST_IS_PAD (pad), NULL);
+ GstCaps *caps;
- caps = GST_PAD_CAPS(pad);
-
- while (caps) {
- GstCaps *cap = (GstCaps *)caps->data;
-
- if (!strcmp (cap->name, name))
- return cap;
+ g_return_val_if_fail (templ != NULL, NULL);
- caps = g_list_next (caps);
- }
+ caps = GST_PADTEMPLATE_CAPS (templ);
+ if (!caps)
+ return NULL;
- return NULL;
+ return gst_caps_get_by_name (caps, name);
}
/**
gboolean
gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad)
{
- GstRealPad *realsrc, *realsink;
-
g_return_val_if_fail (srcpad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (srcpad), FALSE);
g_return_val_if_fail (sinkpad != NULL, FALSE);
g_return_val_if_fail (GST_IS_PAD (sinkpad), FALSE);
- realsrc = GST_PAD_REALIZE(srcpad);
- realsink = GST_PAD_REALIZE(sinkpad);
-
- if (GST_RPAD_CAPS(realsrc) && GST_RPAD_CAPS(realsink)) {
- if (!gst_caps_list_check_compatibility (GST_RPAD_CAPS(realsrc), GST_RPAD_CAPS(realsink))) {
+ if (GST_PAD_CAPS(srcpad) && GST_PAD_CAPS(sinkpad)) {
+ if (!gst_caps_check_compatibility (GST_PAD_CAPS(srcpad), GST_PAD_CAPS(sinkpad))) {
return FALSE;
}
else {
}
}
else {
- GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s)\n",
- GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad));
+ GST_DEBUG (0,"gstpad: could not check capabilities of pads (%s:%s) and (%s:%s) %p %p\n",
+ GST_DEBUG_PAD_NAME (srcpad), GST_DEBUG_PAD_NAME (sinkpad),
+ GST_PAD_CAPS (srcpad), GST_PAD_CAPS (sinkpad));
return TRUE;
}
}
g_strfreev (split);
}
+/**
+ * gst_pad_renegotiate:
+ * @pad: the pad to perform the negotiation on
+ *
+ * Perform the negotiation process with the peer pad.
+ *
+ * Returns: TRUE if the negotiation process succeded
+ */
+gboolean
+gst_pad_renegotiate (GstPad *pad)
+{
+ gint counter = 0;
+ GstCaps *newcaps = NULL;
+ GstRealPad *peerpad, *currentpad, *otherpad;
+ GstCaps *currentcaps;
+
+ g_return_val_if_fail (pad != NULL, FALSE);
+
+ peerpad = GST_PAD_PEER (pad);
+
+ currentpad = GST_PAD_REALIZE (pad);
+
+ if (!peerpad) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "no peer pad for pad %s:%s\n",
+ GST_DEBUG_PAD_NAME(currentpad));
+ return TRUE;
+ }
+
+ otherpad = GST_REAL_PAD (peerpad);
+
+ GST_INFO (GST_CAT_ELEMENT_PADS, "negotiating pad %s:%s and %s:%s",
+ GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad));
+
+ newcaps = GST_PAD_CAPS (pad);
+
+ do {
+ currentcaps = newcaps;
+
+ /* this pad wants to negotiate */
+ if (currentpad->negotiatefunc) {
+
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s, count=%d\n",
+ GST_DEBUG_PAD_NAME(currentpad), counter);
+ newcaps = (currentpad->negotiatefunc) (GST_PAD (currentpad), currentcaps, counter);
+
+ if (newcaps == NULL) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has refused, negotiation failed :(, count=%d\n",
+ GST_DEBUG_PAD_NAME(currentpad), counter);
+ return FALSE;
+ }
+ if (newcaps == currentcaps) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s aggreed with caps, count=%d\n",
+ GST_DEBUG_PAD_NAME(currentpad), counter);
+ break;
+ }
+ }
+ /* this pad doesn't want to negotiate, take its caps and that will be it then */
+ else {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "getting caps from pad %s:%s, count=%d\n",
+ GST_DEBUG_PAD_NAME(currentpad), counter);
+ newcaps = GST_PAD_CAPS (currentpad);
+ }
+ /* we have a caps structure now */
+
+ /* check if the other pad wants to negotiate */
+ if (!otherpad->negotiatefunc) {
+ /* the pad doesn't want to negotiate, so we check if the caps
+ * we got from the current pad are compatible */
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s doesn't want to negotiate, count=%d\n",
+ GST_DEBUG_PAD_NAME(otherpad), counter);
+ if (!otherpad->caps ||
+ gst_caps_check_compatibility (newcaps, otherpad->caps)) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps, count=%d\n",
+ GST_DEBUG_PAD_NAME(otherpad), counter);
+ /* we're lucky */
+ break;
+ }
+ /* else, we let the current pad select another caps */
+ }
+ /* if the other pad wants to negotiate, setup the pointers */
+ else {
+ GstRealPad *temp;
+
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "switching pads for next phase\n");
+
+ temp = currentpad;
+ currentpad = otherpad;
+ otherpad = temp;
+ }
+
+ counter++;
+
+ } while (counter < 100); // FIXME
+
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pads aggreed on caps :)\n");
+
+ /* here we have some sort of aggreement of the caps */
+ GST_PAD_CAPS (currentpad) = newcaps;
+ GST_PAD_CAPS (otherpad) = newcaps;
+
+ return TRUE;
+}
+
+GstCaps*
+gst_pad_negotiate_proxy (GstPad *pad, GstCaps *caps, gint count)
+{
+ GstRealPad *peer;
+ GstCaps *newcaps = caps;
+
+ g_return_val_if_fail (pad != NULL, NULL);
+
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad (%s:%s) proxied\n", GST_DEBUG_PAD_NAME (pad));
+
+ peer = GST_RPAD_PEER (pad);
+
+ GST_PAD_CAPS (pad) = caps;
+
+ if (peer) {
+ if (peer->negotiatefunc) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate on peer (%s:%s)\n", GST_DEBUG_PAD_NAME (peer));
+ newcaps = peer->negotiatefunc (pad, caps, count);
+ }
+ else if (!peer->caps ||
+ gst_caps_check_compatibility (newcaps, peer->caps)) {
+ GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad %s:%s has compatible caps\n",
+ GST_DEBUG_PAD_NAME(peer));
+ }
+ else return NULL;
+ }
+
+ if (caps == newcaps) {
+ GST_PAD_CAPS (pad) = newcaps;
+ if (peer) GST_PAD_CAPS (peer) = newcaps;
+ }
+
+ return newcaps;
+}
/**
* gst_pad_save_thyself:
tag = (*factory)[i++];
- while (GPOINTER_TO_INT (tag) == 1) {
- new->caps = g_list_append (new->caps, gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
+ while (GPOINTER_TO_INT (tag) == GST_PAD_FACTORY_CAPS_ID) {
+ GST_PADTEMPLATE_CAPS (new) = gst_caps_append (GST_PADTEMPLATE_CAPS (new),
+ gst_caps_register_count ((GstCapsFactory *)&(*factory)[i], &counter));
i+=counter;
tag = (*factory)[i++];
}
GstPadTemplate*
gst_padtemplate_create (gchar *name_template,
GstPadDirection direction, GstPadPresence presence,
- GList *caps)
+ GstCaps *caps)
{
GstPadTemplate *new;
new = gtk_type_new (gst_padtemplate_get_type ());
- new->name_template = name_template;
- new->direction = direction;
- new->presence = presence;
- new->caps = caps;
+ GST_PADTEMPLATE_NAME_TEMPLATE (new) = name_template;
+ GST_PADTEMPLATE_DIRECTION (new) = direction;
+ GST_PADTEMPLATE_PRESENCE (new) = presence;
+ GST_PADTEMPLATE_CAPS (new) = caps;
return new;
}
+/**
+ * gst_padtemplate_get_caps:
+ * @templ: the padtemplate to use
+ *
+ * Get the capabilities of the padtemplate
+ *
+ * Returns: a GstCaps*
+ */
+GstCaps*
+gst_padtemplate_get_caps (GstPadTemplate *templ)
+{
+ g_return_val_if_fail (templ != NULL, NULL);
+
+ return GST_PADTEMPLATE_CAPS (templ);
+}
/**
* gst_padtemplate_save_thyself:
gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent)
{
xmlNodePtr subtree;
- GList *caps;
guchar *presence;
+ GST_DEBUG (0,"saving padtemplate %s\n", templ->name_template);
+
xmlNewChild(parent,NULL,"nametemplate", templ->name_template);
xmlNewChild(parent,NULL,"direction", (templ->direction == GST_PAD_SINK? "sink":"src"));
}
xmlNewChild(parent,NULL,"presence", presence);
- caps = templ->caps;
- while (caps) {
- GstCaps *cap = (GstCaps *)caps->data;
-
+ if (GST_PADTEMPLATE_CAPS (templ)) {
subtree = xmlNewChild (parent, NULL, "caps", NULL);
- gst_caps_save_thyself (cap, subtree);
-
- caps = g_list_next (caps);
+ gst_caps_save_thyself (GST_PADTEMPLATE_CAPS (templ), subtree);
}
return parent;
gchar *name_template = NULL;
GstPadDirection direction = GST_PAD_UNKNOWN;
GstPadPresence presence = GST_PAD_ALWAYS;
- GList *caps = NULL;
+ GstCaps *caps = NULL;
while (field) {
if (!strcmp(field->name, "nametemplate")) {
g_free (value);
}
else if (!strcmp(field->name, "caps")) {
- caps = g_list_append (caps, gst_caps_load_thyself (field));
+ caps = gst_caps_load_thyself (field);
}
field = field->next;
}
typedef GstBuffer *(*GstPadPullFunction) (GstPad *pad);
typedef GstBuffer *(*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
typedef gboolean (*GstPadEOSFunction) (GstPad *pad);
+typedef GstCaps* (*GstPadNegotiateFunction) (GstPad *pad, GstCaps *caps, gint count);
typedef enum {
GST_PAD_UNKNOWN,
struct _GstRealPad {
GstPad pad;
- GList *caps;
+ GstCaps *caps;
GstPadDirection direction;
cothread_state *threadstate;
GstPadPullFunction pullfunc;
GstPadPullRegionFunction pullregionfunc;
+ GstPadNegotiateFunction negotiatefunc;
+
GList *ghostpads;
};
#define GST_RPAD_PULLREGIONFUNC(pad) (((GstRealPad *)(pad))->pullregionfunc)
#define GST_RPAD_QOSFUNC(pad) (((GstRealPad *)(pad))->qosfunc)
#define GST_RPAD_EOSFUNC(pad) (((GstRealPad *)(pad))->eosfunc)
+#define GST_RPAD_NEGOTIATEFUNC(pad) (((GstRealPad *)(pad))->negotiatefunc)
#define GST_RPAD_REGIONTYPE(pad) (((GstRealPad *)(pad))->regiontype)
#define GST_RPAD_OFFSET(pad) (((GstRealPad *)(pad))->offset)
#define GST_PAD_PEER(pad) GST_RPAD_PEER(GST_PAD_REALIZE(pad))
/* Some check functions (unused?) */
-#define GST_PAD_CONNECTED(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->peer != NULL)
+#define GST_PAD_CONNECTED(pad) (GST_PAD_PEER(pad) != NULL)
#define GST_PAD_CAN_PULL(pad) (GST_IS_REAL_PAD(pad) && GST_REAL_PAD(pad)->pullfunc != NULL)
GST_PAD_REQUEST,
} GstPadPresence;
+#define GST_PADTEMPLATE_NAME_TEMPLATE(templ) (((GstPadTemplate *)(templ))->name_template)
+#define GST_PADTEMPLATE_DIRECTION(templ) (((GstPadTemplate *)(templ))->direction)
+#define GST_PADTEMPLATE_PRESENCE(templ) (((GstPadTemplate *)(templ))->presence)
+#define GST_PADTEMPLATE_CAPS(templ) (((GstPadTemplate *)(templ))->caps)
+
struct _GstPadTemplate {
GstObject object;
gchar *name_template;
GstPadDirection direction;
GstPadPresence presence;
- GList *caps;
+ GstCaps *caps;
};
struct _GstPadTemplateClass {
#define GST_PAD_FACTORY_SRC GINT_TO_POINTER(GST_PAD_SRC)
#define GST_PAD_FACTORY_SINK GINT_TO_POINTER(GST_PAD_SINK)
-#define GST_PAD_FACTORY_CAPS(a...) GINT_TO_POINTER(1),##a,NULL
+#define GST_PAD_FACTORY_CAPS_ID 1
+#define GST_PAD_FACTORY_CAPS(a...) GINT_TO_POINTER(GST_PAD_FACTORY_CAPS_ID),##a,NULL
GtkType gst_pad_get_type (void);
void gst_pad_set_getregion_function (GstPad *pad, GstPadGetRegionFunction getregion);
void gst_pad_set_qos_function (GstPad *pad, GstPadQoSFunction qos);
void gst_pad_set_eos_function (GstPad *pad, GstPadEOSFunction eos);
+void gst_pad_set_negotiate_function (GstPad *pad, GstPadNegotiateFunction nego);
-void gst_pad_set_caps_list (GstPad *pad, GList *caps);
-GList* gst_pad_get_caps_list (GstPad *pad);
-GstCaps* gst_pad_get_caps_by_name (GstPad *pad, gchar *name);
+void gst_pad_set_caps (GstPad *pad, GstCaps *caps);
+GstCaps* gst_pad_get_caps (GstPad *pad);
gboolean gst_pad_check_compatibility (GstPad *srcpad, GstPad *sinkpad);
void gst_pad_set_element_private (GstPad *pad, gpointer priv);
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);
+
GstPad* gst_pad_get_peer (GstPad *pad);
-void gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
+gboolean gst_pad_connect (GstPad *srcpad, GstPad *sinkpad);
void gst_pad_disconnect (GstPad *srcpad, GstPad *sinkpad);
+gboolean gst_pad_renegotiate (GstPad *pad);
+GstCaps* gst_pad_negotiate_proxy (GstPad *pad, GstCaps* caps, gint count);
+
#if 1
void gst_pad_push (GstPad *pad, GstBuffer *buf);
#else
GstPadTemplate* gst_padtemplate_new (GstPadFactory *factory);
GstPadTemplate* gst_padtemplate_create (gchar *name_template,
GstPadDirection direction, GstPadPresence presence,
- GList *caps);
+ GstCaps *caps);
+
+GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
+GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name);
xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
static void gst_queue_get_arg (GtkObject *object, GtkArg *arg, guint id);
static gboolean gst_queue_handle_eos (GstPad *pad);
+static GstCaps* gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count);
+static GstCaps* gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count);
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
static GstBuffer * gst_queue_get (GstPad *pad);
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_eos_function (queue->sinkpad, gst_queue_handle_eos);
+ gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink);
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
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_queue_handle_negotiate_src);
queue->queue = NULL;
queue->level_buffers = 0;
queue->fullcond = g_cond_new ();
}
+static GstCaps*
+gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count)
+{
+ GstQueue *queue;
+
+ queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+ return gst_pad_negotiate_proxy (queue->sinkpad, caps, count);
+}
+
+static GstCaps*
+gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count)
+{
+ GstQueue *queue;
+
+ queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+ return gst_pad_negotiate_proxy (queue->srcpad, caps, count);
+}
+
static gboolean
gst_queue_handle_eos (GstPad *pad)
{
if (found) {
caps = gst_util_get_pointer_arg (GTK_OBJECT (typefind), "caps");
- gst_pad_set_caps_list (gst_element_get_pad (element, "src"), g_list_prepend (NULL, caps));
+ gst_pad_set_caps (gst_element_get_pad (element, "src"), caps);
}
gst_pad_disconnect (gst_element_get_pad (element, "src"),
gtk_signal_connect (GTK_OBJECT (autoplug), "new_object", gst_play_object_added, play);
new_element = gst_autoplug_to_renderers (autoplug,
- gst_pad_get_caps_list (gst_element_get_pad (priv->src, "src")),
+ gst_pad_get_caps (gst_element_get_pad (priv->src, "src")),
priv->video_element,
priv->audio_element,
NULL);
/* otherwise (READY or higher) we need to open the sound card */
} else {
if (!GST_FLAG_IS_SET (element, GST_AUDIOSINK_OPEN)) {
- if (!gst_audiosink_open_audio (GST_AUDIOSINK (element)))
- return GST_STATE_FAILURE;
+ if (!gst_audiosink_open_audio (GST_AUDIOSINK (element))) {
+ //return GST_STATE_FAILURE;
+ }
}
}
static void gst_queue_get_arg (GtkObject *object, GtkArg *arg, guint id);
static gboolean gst_queue_handle_eos (GstPad *pad);
+static GstCaps* gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count);
+static GstCaps* gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count);
static void gst_queue_chain (GstPad *pad, GstBuffer *buf);
static GstBuffer * gst_queue_get (GstPad *pad);
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_eos_function (queue->sinkpad, gst_queue_handle_eos);
+ gst_pad_set_negotiate_function (queue->sinkpad, gst_queue_handle_negotiate_sink);
queue->srcpad = gst_pad_new ("src", GST_PAD_SRC);
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_queue_handle_negotiate_src);
queue->queue = NULL;
queue->level_buffers = 0;
queue->fullcond = g_cond_new ();
}
+static GstCaps*
+gst_queue_handle_negotiate_src (GstPad *pad, GstCaps *caps, gint count)
+{
+ GstQueue *queue;
+
+ queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+ return gst_pad_negotiate_proxy (queue->sinkpad, caps, count);
+}
+
+static GstCaps*
+gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps *caps, gint count)
+{
+ GstQueue *queue;
+
+ queue = GST_QUEUE (GST_OBJECT_PARENT (pad));
+
+ return gst_pad_negotiate_proxy (queue->srcpad, caps, count);
+}
+
static gboolean
gst_queue_handle_eos (GstPad *pad)
{
tee
autoplug2
autoplug3
+capsconnect
SUBDIRS = sched eos
noinst_PROGRAMS = init loadall simplefake states caps queue registry \
-paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3
+paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 \
+capsconnect
# we have nothing but apps here, we can do this safely
LIBS += $(GST_LIBS)
gtk_signal_connect (GTK_OBJECT (autoplugger), "new_object", new_object_added, NULL);
element = gst_autoplug_to_caps (autoplugger, testcaps,
- gst_pad_get_caps_list (gst_element_get_pad (audiosink, "sink")),
- gst_pad_get_caps_list (gst_element_get_pad (videosink, "sink")),
+ gst_pad_get_caps (gst_element_get_pad (audiosink, "sink")),
+ gst_pad_get_caps (gst_element_get_pad (videosink, "sink")),
NULL);
g_assert (element != NULL);
--- /dev/null
+#include <gst/gst.h>
+
+int main(int argc,char *argv[])
+{
+ gboolean testret;
+ xmlDocPtr doc;
+ xmlNodePtr parent;
+ GstElement *mpg123;
+ GstElement *mp3parse;
+ GstElement *queue;
+ GstPad *sinkpad;
+ GstPad *srcpad;
+ GstPad *qsinkpad;
+
+ doc = xmlNewDoc ("1.0");
+ doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Capabilities", NULL);
+
+ gst_init (&argc, &argv);
+
+ mpg123 = gst_elementfactory_make ("mpg123", "mpg123");
+ g_assert (mpg123 != NULL);
+
+ sinkpad = gst_element_get_pad (mpg123, "sink");
+ g_assert (sinkpad != NULL);
+
+ queue = gst_elementfactory_make ("queue", "queue");
+ g_assert (queue != NULL);
+
+ srcpad = gst_element_get_pad (queue, "src");
+ g_assert (srcpad != NULL);
+ qsinkpad = gst_element_get_pad (queue, "sink");
+ g_assert (qsinkpad != NULL);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent);
+
+ gst_pad_connect (srcpad, sinkpad);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect src", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (srcpad), parent);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent);
+
+ mp3parse = gst_elementfactory_make ("mp3parse", "mp3parse");
+ g_assert (mp3parse != NULL);
+
+ gst_pad_connect (gst_element_get_pad (mp3parse, "src"), qsinkpad);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "queue caps after connect sink", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (qsinkpad), parent);
+
+ parent = xmlNewChild (doc->xmlRootNode, NULL, "mpg123 caps after connect sink", NULL);
+ gst_caps_save_thyself (gst_pad_get_caps (sinkpad), parent);
+
+ xmlDocDump(stdout, doc);
+
+ return 0;
+}
--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+nego1
--- /dev/null
+noinst_PROGRAMS = nego1
+
+# jsut apps here, this is safe
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
--- /dev/null
+#include <gst/gst.h>
+
+/* this is an example of the src pad dictating the caps
+ * the sink pad only accepts audio/raw */
+
+static GstCaps*
+negotiate (GstPad *pad, GstCaps *caps, gint count)
+{
+ g_print ("negotiation entered\n");
+
+ if (!strcmp (gst_caps_get_mime (caps), "audio/raw"))
+ return caps;
+
+ return NULL;
+}
+
+int
+main(int argc,char *argv[])
+{
+ GstPad *srcpad, *sinkpad;
+ GstCaps *new;
+
+ gst_init(&argc,&argv);
+
+ srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+
+ gst_pad_connect (srcpad, sinkpad);
+
+ gst_pad_set_negotiate_function (sinkpad, negotiate);
+
+ /* fill in our desired caps */
+ new = gst_caps_new_with_props (
+ "src_caps", /* name */
+ "audio/raw", /* mime */
+ gst_props_new (
+ "format", GST_PROPS_INT (16),
+ "depth", GST_PROPS_INT (16),
+ "rate", GST_PROPS_INT (48000),
+ "channels", GST_PROPS_INT (2),
+ NULL
+ )
+ );
+
+ gst_pad_set_caps (srcpad, new);
+
+ new = gst_caps_new_with_props (
+ "src_caps", /* name */
+ "video/raw", /* mime */
+ gst_props_new (
+ "format", GST_PROPS_FOURCC ('Y','U','Y','V'),
+ NULL
+ )
+ );
+
+ gst_pad_set_caps (srcpad, new);
+
+ exit (0);
+}