Gstreamer中的pad根据输入输出方向,有src和sink两种。根据pad创建的时机,有always pad、sometimes pad、request pad,这样不同的pad,链接方式就不同。
pad相当与element的接口,element间的连接,实质上就是pad间的连接,所以这里总结下pad的链接。
always pad
gst_bin_add()
将element添加到bin或者pipeline里面。sometimes pad
pad-added
signal触发,调用回调函数才行。request pad
filter link
初始时没有pad的element(如uridecodebin),pad会在数据流到element时才会创建,这种pad被成为Sometimes Pad
,不同于Always Pad
,sometimes pad不能通过gst_element_link_many直接将两个element link起来,需要根据pad-added
信号,在pad创建后,在对应的回调函数里面链接pad到对应的pad之上才可以。
// gst-plugins-good/tests/examples/equalizer/demo.c/* Uri decoding */decodebin = gst_element_factory_make ("uridecodebin", "decoder");g_object_set (G_OBJECT (decodebin), "uri", argv[1], NULL);/* Force float32 samples */decconvert = gst_element_factory_make ("audioconvert", "decconvert");/* Handle dynamic pads */g_signal_connect (G_OBJECT (decodebin), "pad-added",G_CALLBACK (dynamic_link), gst_element_get_static_pad (decconvert, "sink"));// pad-added的回调函数
static void
dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer user_data)
{GstPad *target = GST_PAD (user_data);gst_pad_link (newpad, target);gst_object_unref (target);
}
// subprojects/gst-plugins-good/tests/examples/equalizer/demo.cgst_bin_add_many (GST_BIN (bin), decodebin, decconvert, capsfilter, equalizer, spectrum, sinkconvert, sink, NULL);if (!gst_element_link_many (decconvert, capsfilter, equalizer, spectrum, sinkconvert, sink, NULL)) {fprintf (stderr, "can't link elements\n");exit (1);}/* Handle dynamic pads */g_signal_connect (G_OBJECT (decodebin), "pad-added",G_CALLBACK (dynamic_link), gst_element_get_static_pad (decconvert,"sink"));
pipeline原型:
uridecodebin! parsebin ! decodebin
代码:
uridecodebin_ = gst_element_factory_make("uridecodebin", "uridec");parsebin_ = gst_element_factory_make("parsebin", "parser");decodebin_ = gst_element_factory_make("decodebin", "decodebin");gst_bin_add_many (GST_BIN(pipeline_), uridecodebin_, parsebin_, decodebin_, NULL);g_signal_connect (G_OBJECT (uridecodebin_), "pad-added",G_CALLBACK (link_uridec_parsebin_cb), gst_element_get_static_pad (parsebin_, "sink"));g_signal_connect (G_OBJECT (parsebin_), "pad-added",G_CALLBACK (link_parsebin_decbin_cb), gst_element_get_static_pad (decodebin_, "sink"));g_signal_connect (G_OBJECT (parsebin_), "pad-added",G_CALLBACK (link_decbin_aconv_cb),gst_element_get_static_pad (audioconv_, "sink"));
下面这样是不行的,因为uridecodebin/parsebin/decodebin都不是awlays pad
:
if (!gst_element_link_many(uridecodebin_, parsebin_, NULL) ||!gst_element_link_many(parsebin_, decodebin_, NULL) ||!gst_element_link_many(decodebin_, audioconv_, NULL)) {GST_ERROR("link many got error");}
这段代码可以在gstreamer教程中找到,路径:
gst-docs/examples/tutorials/basic-tutorial-7.c
代码:
/* Manually link the Tee, which has "Request" pads */tee_audio_pad = gst_element_request_pad_simple (tee, "src_%u");g_print ("Obtained request pad %s for audio branch.\n",gst_pad_get_name (tee_audio_pad));queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink");tee_video_pad = gst_element_request_pad_simple (tee, "src_%u");g_print ("Obtained request pad %s for video branch.\n",gst_pad_get_name (tee_video_pad));queue_video_pad = gst_element_get_static_pad (video_queue, "sink");if (gst_pad_link (tee_audio_pad, queue_audio_pad) != GST_PAD_LINK_OK ||gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK) {g_printerr ("Tee could not be linked.\n");gst_object_unref (pipeline);return -1;}gst_object_unref (queue_audio_pad);gst_object_unref (queue_video_pad);
搜索gst_element_link_filtered,可以看到源码中很多地方都有用到,比较简单:
aresample_ = gst_element_factory_make("audioresample", "aresample");aconv_ = gst_element_factory_make("audioconvert", "aconv");GstCaps* filter;filter = gst_caps_from_string("audio/x-raw, format=(string)S16LE, rate=(int)16000");if(!gst_element_link_filtered(aresample_, aconv_, filter)) {GST_ERROR("failed to link audioresample and audioconvert !");}gst_caps_unref (filter);