From 29cb713b216678367d9450a6f506a4d662f421c2 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Sun, 18 Mar 2001 16:17:39 +0000 Subject: [PATCH] More work on capsnego, mostly proxying Original commit message from CVS: More work on capsnego, mostly proxying Added another testsuite for capsnego Added caps to vorbisdec, mp3parse, mp1videoparse Redid the queue proxy handling a bit. --- gst/autoplug/gststaticautoplugrender.c | 4 +- gst/gstpad.c | 163 ++++++++++------ gst/gstqueue.c | 28 ++- plugins/elements/gstqueue.c | 28 ++- tests/old/testsuite/capsnego/.gitignore | 1 + tests/old/testsuite/capsnego/Makefile.am | 2 +- tests/old/testsuite/capsnego/converter2.c | 224 ++++++++++++++++++++++ testsuite/capsnego/.gitignore | 1 + testsuite/capsnego/Makefile.am | 2 +- testsuite/capsnego/converter2.c | 224 ++++++++++++++++++++++ 10 files changed, 606 insertions(+), 71 deletions(-) create mode 100644 tests/old/testsuite/capsnego/converter2.c create mode 100644 testsuite/capsnego/converter2.c diff --git a/gst/autoplug/gststaticautoplugrender.c b/gst/autoplug/gststaticautoplugrender.c index 180c29f805..a9989ff03d 100644 --- a/gst/autoplug/gststaticautoplugrender.c +++ b/gst/autoplug/gststaticautoplugrender.c @@ -140,8 +140,8 @@ gst_autoplug_pads_autoplug_func (GstElement *src, GstPad *pad, GstElement *sink) GList *sinkpads; gboolean connected = FALSE; - GST_DEBUG (0,"gstpipeline: autoplug pad connect function for \"%s\" to \"%s\"\n", - GST_ELEMENT_NAME(src), GST_ELEMENT_NAME(sink)); + GST_DEBUG (0,"gstpipeline: autoplug pad connect function for %s %s:%s to \"%s\"\n", + GST_ELEMENT_NAME (src), GST_DEBUG_PAD_NAME(pad), GST_ELEMENT_NAME(sink)); sinkpads = gst_element_get_pad_list(sink); while (sinkpads) { diff --git a/gst/gstpad.c b/gst/gstpad.c index 5021e51e17..14c46a10b5 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -737,6 +737,12 @@ gst_pad_set_caps (GstPad *pad, g_return_val_if_fail (pad != NULL, FALSE); g_return_val_if_fail (GST_IS_REAL_PAD (pad), FALSE); // NOTE this restriction + 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; + } + GST_PAD_CAPS(pad) = caps; return gst_pad_renegotiate (pad); @@ -920,6 +926,80 @@ cleanup: g_strfreev (split); } +static gboolean +gst_pad_renegotiate_func (GstPad *pad, GstPad *peerpad, GstCaps **newcaps, gint *counter) +{ + GstRealPad *currentpad, *otherpad; + GstPadNegotiateReturn result; + + g_return_val_if_fail (pad != NULL, FALSE); + + currentpad = GST_PAD_REALIZE (pad); + otherpad = GST_REAL_PAD (peerpad); + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiating pad %s:%s and %s:%s counter:%d\n", + GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(peerpad), *counter); + + do { + gboolean matchtempl; + + 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); + + if (matchtempl) { + if (otherpad->negotiatefunc) { + GstRealPad *temp; + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "switching pad for next phase\n"); + + temp = currentpad; + currentpad = otherpad; + otherpad = temp; + } + else if (gst_caps_check_compatibility (*newcaps, GST_PAD_CAPS (otherpad))) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation succeeded\n"); + return TRUE; + } + else { + *newcaps = GST_PAD_CAPS (otherpad); + } + } + else { + *newcaps = GST_PAD_CAPS (otherpad); + } + + (*counter)++; + + if (currentpad->negotiatefunc) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "calling negotiate function on pad %s:%s\n", + GST_DEBUG_PAD_NAME (currentpad)); + result = currentpad->negotiatefunc (GST_PAD (currentpad), newcaps, *counter); + + switch (result) { + case GST_PAD_NEGOTIATE_FAIL: + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation failed\n"); + return FALSE; + case GST_PAD_NEGOTIATE_AGREE: + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation succeeded\n"); + return TRUE; + case GST_PAD_NEGOTIATE_TRY: + GST_DEBUG (GST_CAT_ELEMENT_PADS, "try another option\n"); + break; + } + } + else { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation failed, no more options\n"); + return FALSE; + } + + } while (*counter < 100); + + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation failed, too many attempts\n"); + + return FALSE; +} + /** * gst_pad_renegotiate: * @pad: the pad to perform the negotiation on @@ -931,11 +1011,10 @@ cleanup: gboolean gst_pad_renegotiate (GstPad *pad) { - gint counter = 0; GstCaps *newcaps = NULL; GstRealPad *peerpad, *currentpad, *otherpad; - GstPadDirection currentdirection; - GstPadNegotiateReturn result; + gboolean result; + gint counter = 0; g_return_val_if_fail (pad != NULL, FALSE); @@ -957,80 +1036,46 @@ gst_pad_renegotiate (GstPad *pad) newcaps = GST_PAD_CAPS (pad); g_assert (newcaps != NULL); - currentdirection = GST_PAD_DIRECTION (currentpad); + result = gst_pad_renegotiate_func (pad, GST_PAD (peerpad), &newcaps, &counter); - do { - gboolean matchtempl; + if (result) { + GST_DEBUG (GST_CAT_ELEMENT_PADS, "pads aggreed on caps :)\n"); - matchtempl = gst_caps_check_compatibility (newcaps, gst_pad_get_padtemplate_caps (GST_PAD (otherpad))); + /* here we have some sort of aggreement of the caps */ + GST_PAD_CAPS (currentpad) = newcaps; + GST_PAD_CAPS (otherpad) = newcaps; + } - if (matchtempl) { - if (otherpad->negotiatefunc) { - GstRealPad *temp; - - temp = currentpad; - currentpad = otherpad; - otherpad = temp; - } - else if (gst_caps_check_compatibility (newcaps, GST_PAD_CAPS (otherpad))) { - break; - } - else { - newcaps = GST_PAD_CAPS (otherpad); - } - } - else { - newcaps = GST_PAD_CAPS (otherpad); - } - - counter++; - - if (currentpad->negotiatefunc) { - result = currentpad->negotiatefunc (GST_PAD (currentpad), &newcaps, counter); - - switch (result) { - case GST_PAD_NEGOTIATE_FAIL: - return FALSE; - case GST_PAD_NEGOTIATE_AGREE: - goto succeed; - case GST_PAD_NEGOTIATE_TRY: - break; - } - } - else { - return FALSE; - } - - } while (counter < 100); - -succeed: - - 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; + return result; } + GstPadNegotiateReturn gst_pad_negotiate_proxy (GstPad *pad, GstCaps **caps, gint counter) { GstRealPad *peer; + gboolean result; g_return_val_if_fail (pad != NULL, GST_PAD_NEGOTIATE_FAIL); - GST_DEBUG (GST_CAT_ELEMENT_PADS, "pad (%s:%s) proxied\n", GST_DEBUG_PAD_NAME (pad)); + GST_DEBUG (GST_CAT_ELEMENT_PADS, "negotiation proxied to pad (%s:%s)\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)); - return peer->negotiatefunc (peer, caps, counter); + result = gst_pad_renegotiate_func (pad, GST_PAD (peer), 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; + } + else { + return GST_PAD_NEGOTIATE_FAIL; } } diff --git a/gst/gstqueue.c b/gst/gstqueue.c index b9521b0a7a..43f3211fc7 100644 --- a/gst/gstqueue.c +++ b/gst/gstqueue.c @@ -153,23 +153,43 @@ gst_queue_init (GstQueue *queue) } static GstPadNegotiateReturn -gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint count) +gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) { GstQueue *queue; queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - return gst_pad_negotiate_proxy (queue->sinkpad, caps, count); + 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_FAIL; } static GstPadNegotiateReturn -gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint count) +gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) { GstQueue *queue; queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - return gst_pad_negotiate_proxy (queue->srcpad, caps, count); + 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_FAIL; } static gboolean diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index b9521b0a7a..43f3211fc7 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -153,23 +153,43 @@ gst_queue_init (GstQueue *queue) } static GstPadNegotiateReturn -gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint count) +gst_queue_handle_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) { GstQueue *queue; queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - return gst_pad_negotiate_proxy (queue->sinkpad, caps, count); + 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_FAIL; } static GstPadNegotiateReturn -gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint count) +gst_queue_handle_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) { GstQueue *queue; queue = GST_QUEUE (GST_OBJECT_PARENT (pad)); - return gst_pad_negotiate_proxy (queue->srcpad, caps, count); + 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_FAIL; } static gboolean diff --git a/tests/old/testsuite/capsnego/.gitignore b/tests/old/testsuite/capsnego/.gitignore index 848066a15b..e04eb91e53 100644 --- a/tests/old/testsuite/capsnego/.gitignore +++ b/tests/old/testsuite/capsnego/.gitignore @@ -7,3 +7,4 @@ Makefile.in .libs capsnego converter +converter2 diff --git a/tests/old/testsuite/capsnego/Makefile.am b/tests/old/testsuite/capsnego/Makefile.am index 624ec5093c..99c79043e9 100644 --- a/tests/old/testsuite/capsnego/Makefile.am +++ b/tests/old/testsuite/capsnego/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = -testprogs = capsnego converter +testprogs = capsnego converter converter2 TESTS = $(testprogs) diff --git a/tests/old/testsuite/capsnego/converter2.c b/tests/old/testsuite/capsnego/converter2.c new file mode 100644 index 0000000000..1091dc25a0 --- /dev/null +++ b/tests/old/testsuite/capsnego/converter2.c @@ -0,0 +1,224 @@ + +#include + +GstPad *srcpad, *sinkpad; +GstPad *srcconvpad, *sinkconvpad; +GstPad *srcpadtempl, *sinkpadtempl; +GstPad *srcconvtempl, *sinkconvtempl; + +gint converter_in = -1, converter_out = -1; +gint target_rate = 2000; + +static GstPadFactory src_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 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 GstPadFactory sink_factory = { + "sink", + GST_PAD_FACTORY_SINK, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_sink", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstCapsFactory sink_caps = { + "sink_caps", + "audio/raw", + "rate", GST_PROPS_INT (6000), + NULL +}; + +static GstCapsFactory src_caps = { + "src_caps", + "audio/raw", + "rate", GST_PROPS_INT (3000), + NULL +}; + +static GstPadTemplate *srctempl, *sinktempl; +static GstCaps *srccaps, *sinkcaps; + +static GstPadNegotiateReturn +converter_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print (">"); + + if (counter == 0) { + *caps = NULL; + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + converter_out = gst_caps_get_int (*caps, "rate"); + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +converter_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print ("<"); + if (counter == 0) { + *caps = GST_PAD_CAPS (srcconvpad); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + converter_in = gst_caps_get_int (*caps, "rate"); + + if (counter == 1) { + converter_out = gst_caps_get_int (*caps, "rate"); + return gst_pad_negotiate_proxy (srcconvpad, caps, counter); + } + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +target_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print ("{"); + if (counter == 0) { + *caps = gst_caps_new_with_props ( + "target_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (target_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + target_rate = gst_caps_get_int (*caps, "rate"); + g_print ("target set %d\n", target_rate); + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +int +main (int argc, char *argv[]) +{ + gboolean overall = TRUE; + gboolean result; + + gst_init (&argc, &argv); + + srctempl = gst_padtemplate_new (&src_factory); + sinktempl = gst_padtemplate_new (&sink_factory); + srcpad = gst_pad_new_from_template (srctempl, "src"); + sinkpad = gst_pad_new_from_template (sinktempl, "sink"); + + srcconvtempl = gst_padtemplate_new (&src_conv_factory); + sinkconvtempl = gst_padtemplate_new (&sink_conv_factory); + srcconvpad = gst_pad_new_from_template (srcconvtempl, "csrc"); + sinkconvpad = gst_pad_new_from_template (sinkconvtempl, "csink"); + + gst_pad_set_negotiate_function (srcconvpad, converter_negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, converter_negotiate_sink); + gst_pad_set_negotiate_function (sinkpad, target_negotiate_sink); + + sinkcaps = gst_caps_register (&sink_caps); + srccaps = gst_caps_register (&src_caps); + + g_print ("-------) (-----------) (----- \n"); + g_print (" ! ! converter ! ! \n"); + g_print (" src -- csink csrc -- sink \n"); + g_print ("-------) (-----------) (----- \n\n"); + g_print ("The convertor first tries to proxy the caps received\n"); + g_print ("on its csink pad to its csrc pad, when that fails, it\n"); + g_print ("sets up the conversion.\n\n"); + + + g_print ("sink pad set caps (rate=%d), converter status: %d %d\n", target_rate, + converter_in, converter_out); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("result: %d, converter status: %d %d, target: %d\n\n", result, + converter_in, converter_out, target_rate); + + result = gst_pad_connect (srcpad, sinkconvpad); + g_print ("pad connect 1: %d\n", result); + overall &= (result == TRUE); + result = gst_pad_connect (srcconvpad, sinkpad); + g_print ("pad connect 2: %d\n", result); + overall &= (result == TRUE); + + g_print ("after connect, converter status: %d %d, target %d\n\n", converter_in, converter_out, target_rate); + + g_print ("src pad set caps (rate=%d), converter status: %d %d, target %d \n", gst_caps_get_int (srccaps, "rate"), + converter_in, converter_out, target_rate); + result = gst_pad_set_caps (srcpad, srccaps); + g_print ("result %d, converter status: %d %d, target %d\n\n", result, + converter_in, converter_out, target_rate); + + g_print ("sink pad set caps (rate=2000), converter status: %d %d, target %d \n", + converter_in, converter_out, target_rate); + target_rate = 2000; + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("result %d, converter status: %d %d, target: %d\n\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (4000)); + result = gst_pad_renegotiate (srcpad); + g_print ("sink pad renegotiate caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (40000)); + result = gst_pad_set_caps (srcpad, srccaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (40000)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + target_rate = 9000; + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + exit (!overall); +} diff --git a/testsuite/capsnego/.gitignore b/testsuite/capsnego/.gitignore index 848066a15b..e04eb91e53 100644 --- a/testsuite/capsnego/.gitignore +++ b/testsuite/capsnego/.gitignore @@ -7,3 +7,4 @@ Makefile.in .libs capsnego converter +converter2 diff --git a/testsuite/capsnego/Makefile.am b/testsuite/capsnego/Makefile.am index 624ec5093c..99c79043e9 100644 --- a/testsuite/capsnego/Makefile.am +++ b/testsuite/capsnego/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = -testprogs = capsnego converter +testprogs = capsnego converter converter2 TESTS = $(testprogs) diff --git a/testsuite/capsnego/converter2.c b/testsuite/capsnego/converter2.c new file mode 100644 index 0000000000..1091dc25a0 --- /dev/null +++ b/testsuite/capsnego/converter2.c @@ -0,0 +1,224 @@ + +#include + +GstPad *srcpad, *sinkpad; +GstPad *srcconvpad, *sinkconvpad; +GstPad *srcpadtempl, *sinkpadtempl; +GstPad *srcconvtempl, *sinkconvtempl; + +gint converter_in = -1, converter_out = -1; +gint target_rate = 2000; + +static GstPadFactory src_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 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 GstPadFactory sink_factory = { + "sink", + GST_PAD_FACTORY_SINK, + GST_PAD_FACTORY_ALWAYS, + GST_PAD_FACTORY_CAPS( + "test_sink", + "audio/raw", + "rate", GST_PROPS_INT_RANGE (16, 20000) + ), + NULL, +}; + +static GstCapsFactory sink_caps = { + "sink_caps", + "audio/raw", + "rate", GST_PROPS_INT (6000), + NULL +}; + +static GstCapsFactory src_caps = { + "src_caps", + "audio/raw", + "rate", GST_PROPS_INT (3000), + NULL +}; + +static GstPadTemplate *srctempl, *sinktempl; +static GstCaps *srccaps, *sinkcaps; + +static GstPadNegotiateReturn +converter_negotiate_src (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print (">"); + + if (counter == 0) { + *caps = NULL; + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + converter_out = gst_caps_get_int (*caps, "rate"); + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +converter_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print ("<"); + if (counter == 0) { + *caps = GST_PAD_CAPS (srcconvpad); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + converter_in = gst_caps_get_int (*caps, "rate"); + + if (counter == 1) { + converter_out = gst_caps_get_int (*caps, "rate"); + return gst_pad_negotiate_proxy (srcconvpad, caps, counter); + } + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +static GstPadNegotiateReturn +target_negotiate_sink (GstPad *pad, GstCaps **caps, gint counter) +{ + g_print ("{"); + if (counter == 0) { + *caps = gst_caps_new_with_props ( + "target_caps", + "audio/raw", + gst_props_new ( + "rate", GST_PROPS_INT (target_rate), + NULL) + ); + return GST_PAD_NEGOTIATE_TRY; + } + if (*caps) { + target_rate = gst_caps_get_int (*caps, "rate"); + g_print ("target set %d\n", target_rate); + return GST_PAD_NEGOTIATE_AGREE; + } + + return GST_PAD_NEGOTIATE_FAIL; +} + +int +main (int argc, char *argv[]) +{ + gboolean overall = TRUE; + gboolean result; + + gst_init (&argc, &argv); + + srctempl = gst_padtemplate_new (&src_factory); + sinktempl = gst_padtemplate_new (&sink_factory); + srcpad = gst_pad_new_from_template (srctempl, "src"); + sinkpad = gst_pad_new_from_template (sinktempl, "sink"); + + srcconvtempl = gst_padtemplate_new (&src_conv_factory); + sinkconvtempl = gst_padtemplate_new (&sink_conv_factory); + srcconvpad = gst_pad_new_from_template (srcconvtempl, "csrc"); + sinkconvpad = gst_pad_new_from_template (sinkconvtempl, "csink"); + + gst_pad_set_negotiate_function (srcconvpad, converter_negotiate_src); + gst_pad_set_negotiate_function (sinkconvpad, converter_negotiate_sink); + gst_pad_set_negotiate_function (sinkpad, target_negotiate_sink); + + sinkcaps = gst_caps_register (&sink_caps); + srccaps = gst_caps_register (&src_caps); + + g_print ("-------) (-----------) (----- \n"); + g_print (" ! ! converter ! ! \n"); + g_print (" src -- csink csrc -- sink \n"); + g_print ("-------) (-----------) (----- \n\n"); + g_print ("The convertor first tries to proxy the caps received\n"); + g_print ("on its csink pad to its csrc pad, when that fails, it\n"); + g_print ("sets up the conversion.\n\n"); + + + g_print ("sink pad set caps (rate=%d), converter status: %d %d\n", target_rate, + converter_in, converter_out); + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("result: %d, converter status: %d %d, target: %d\n\n", result, + converter_in, converter_out, target_rate); + + result = gst_pad_connect (srcpad, sinkconvpad); + g_print ("pad connect 1: %d\n", result); + overall &= (result == TRUE); + result = gst_pad_connect (srcconvpad, sinkpad); + g_print ("pad connect 2: %d\n", result); + overall &= (result == TRUE); + + g_print ("after connect, converter status: %d %d, target %d\n\n", converter_in, converter_out, target_rate); + + g_print ("src pad set caps (rate=%d), converter status: %d %d, target %d \n", gst_caps_get_int (srccaps, "rate"), + converter_in, converter_out, target_rate); + result = gst_pad_set_caps (srcpad, srccaps); + g_print ("result %d, converter status: %d %d, target %d\n\n", result, + converter_in, converter_out, target_rate); + + g_print ("sink pad set caps (rate=2000), converter status: %d %d, target %d \n", + converter_in, converter_out, target_rate); + target_rate = 2000; + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("result %d, converter status: %d %d, target: %d\n\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (4000)); + result = gst_pad_renegotiate (srcpad); + g_print ("sink pad renegotiate caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (srccaps, "rate", GST_PROPS_INT (40000)); + result = gst_pad_set_caps (srcpad, srccaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (40000)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + target_rate = 9000; + gst_caps_set (sinkcaps, "rate", GST_PROPS_INT (target_rate)); + result = gst_pad_set_caps (sinkpad, sinkcaps); + g_print ("sink pad set caps %d, converter status: %d %d, target: %d\n", result, + converter_in, converter_out, target_rate); + + exit (!overall); +}