#include GstPad *srcpad, *sinkpad; GstPad *srcconvpad, *sinkconvpad; GstPadTemplate *srcpadtempl, *sinkpadtempl; GstPadTemplate *srcconvtempl, *sinkconvtempl; gint converter_in = -1, converter_out = -1; gint target_rate = 2000; static GstPadTemplate* src_factory (void) { return gst_padtemplate_new ( "src", GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_new ( "test_src", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT_RANGE (16, 20000), NULL)), NULL); } static GstPadTemplate* src_conv_factory (void) { return gst_padtemplate_new ( "src", GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_new ( "test_src", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT_RANGE (16, 20000), NULL)), NULL); } static GstPadTemplate* sink_conv_factory (void) { return gst_padtemplate_new ( "src", GST_PAD_SINK, GST_PAD_ALWAYS, gst_caps_new ( "test_src", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT_RANGE (16, 20000), NULL)), NULL); } static GstPadTemplate* sink_factory (void) { return gst_padtemplate_new ( "sink", GST_PAD_SINK, GST_PAD_ALWAYS, gst_caps_new ( "test_sink", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT_RANGE (16, 20000), NULL)), NULL); } static GstCaps* sink_caps (void) { return gst_caps_new ( "sink_caps", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT (6000), NULL)); } static GstCaps* src_caps (void) { return gst_caps_new ( "src_caps", "audio/raw", gst_props_new ( "rate", GST_PROPS_INT (3000), NULL)); } static GstPadTemplate *srctempl, *sinktempl; static GstCaps *srccaps, *sinkcaps; static GstPadNegotiateReturn converter_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data) { g_print (">"); if (*data == NULL) { *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, gpointer *data) { g_print ("<"); if (*data == NULL) { *caps = GST_PAD_CAPS (srcconvpad); return GST_PAD_NEGOTIATE_TRY; } if (*caps) { converter_in = gst_caps_get_int (*caps, "rate"); if (*data == 1) { converter_out = gst_caps_get_int (*caps, "rate"); return gst_pad_negotiate_proxy (pad, srcconvpad, caps); } return GST_PAD_NEGOTIATE_AGREE; } return GST_PAD_NEGOTIATE_FAIL; } static GstPadNegotiateReturn target_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data) { g_print ("{"); if (*data == NULL) { *caps = gst_caps_new ( "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 = src_factory (); sinktempl = sink_factory (); srcpad = gst_pad_new_from_template (srctempl, "src"); sinkpad = gst_pad_new_from_template (sinktempl, "sink"); srcconvtempl = src_conv_factory (); sinkconvtempl = 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 = sink_caps (); srccaps = 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); }