Gstreamer中pad的链接

Gstreamer中的pad根据输入输出方向,有src和sink两种。根据pad创建的时机,有always pad、sometimes pad、request pad,这样不同的pad,链接方式就不同。

pad相当与element的接口,element间的连接,实质上就是pad间的连接,所以这里总结下pad的链接。

pad link的分类

always pad

  • gst_element_link_many,按顺序链接element,元素列表以NULL结尾,链接前要确保已使用gst_bin_add()将element添加到bin或者pipeline里面。

sometimes pad

  • sometimes pad不能用gst_element_link_many,得在element创建pad后,通过pad-addedsignal触发,调用回调函数才行。

request pad

  • request pad的链接需要先gst_element_request_pad,获取reqest pad,链接到的目标pad如果是always pad的话可以通过gst_element_get_static_pad获得。然后通过gst_pad_link进行链接。

filter link

  • gst_element_link_filtered使用给定的caps作为filter caps,将@src链接到@dest, 链接必须从源到目标;该函数查找尚未链接的现有pad。如有必要,它将要求提供新的pad。

sometimes pad的链接

初始时没有pad的element(如uridecodebin),pad会在数据流到element时才会创建,这种pad被成为Sometimes Pad,不同于Always Pad,sometimes pad不能通过gst_element_link_many直接将两个element link起来,需要根据pad-added信号,在pad创建后,在对应的回调函数里面链接pad到对应的pad之上才可以。

参考1


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

参考2

  // subprojects/gst-plugins-good/tests/examples/equalizer/demo.c
  gst_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");
  }

实例request pad的链接

这段代码可以在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);

实例filter的链接

搜索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);

你可能感兴趣的:(gstreamer,linux)