<div dir="ltr">Good morning,<br>I'm making some experiments with gstreamer API and I'm trying to connect a pipeline with a dynamically created bin that has a queue and a fakesink. I created ghost pads on both sides (main pipeline and the secondary bin) but I cannot link together the two as "pads have different grandparents" error is coming up in the log.<div><br><u style=""><b>This is my code:</b></u><div><br></div><div>#include <stdio.h><br>#include <stdlib.h><br>#include <gst/gst.h><br><br>#define PIPELINE_MAIN_STRING "v4l2src device=\"/dev/video0\" name=\"v4l2_src_element\" ! video/x-raw,width=%d,height=%d ! tee name=split allow-not-linked=true"<br><br>struct context<br>{<br>  GstElement *main_pipeline;<br>  GstElement *main_pipeline_tee;<br>  GstPad *tee_pad;<br>  GstPad *tee_pad_ghost;<br>  GMainLoop *app_loop;<br><br>  GstElement *secondary_bin;<br>  GstElement *link_element_in_secondary_bin;<br>  GstPad *link_element_pad;<br>  GstPad *link_element_pad_ghost;<br><br>} ctx = {0};<br><br>static int<br>create_main_pipeline()<br>{<br>  int ret = 0;<br>  gchar *pipeline_string = NULL;<br><br>  if (!(pipeline_string = g_strdup_printf(PIPELINE_MAIN_STRING,<br>                                          1920, 1080)))<br>  {<br>    fprintf(stderr, "Error allocating pipeline string\n");<br>    return -1;<br>  }<br><br>  fprintf(stdout, "Current pipeline string: %s\n", pipeline_string);<br><br>  if (!(ctx.main_pipeline = gst_parse_launch(pipeline_string, NULL)))<br>  {<br>    fprintf(stderr, "Error parsing pipeline string\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.main_pipeline_tee = gst_bin_get_by_name(GST_BIN(ctx.main_pipeline), "split")))<br>  {<br>    fprintf(stderr, "Error during get of tee element\n");<br>    return -1;<br>  }<br><br>  return 0;<br>}<br><br>static int<br>create_secondary_bin()<br>{<br>  GstElement *fakesink;<br><br>  if (!(ctx.secondary_bin = gst_bin_new("testbin")))<br>  {<br>    fprintf(stderr, "Error creating secondary bin\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.link_element_in_secondary_bin = gst_element_factory_make("queue", "secondary_bin_queue")))<br>  {<br>    fprintf(stderr, "Error creating queue in secondary bin\n");<br>    return -1;<br>  }<br><br>  if (!(fakesink = gst_element_factory_make("fakesink", "seconday_bin_fakesink")))<br>  {<br>    fprintf(stderr, "Error creating fakesink in secondary bin\n");<br>    return -1;<br>  }<br><br>  gst_element_link(ctx.link_element_in_secondary_bin, fakesink);<br><br>  gst_bin_add_many(GST_BIN(ctx.secondary_bin), ctx.link_element_in_secondary_bin, fakesink, NULL);<br><br>  return 0;<br>}<br><br>static int<br>request_pads()<br>{<br>  GstPadTemplate *source_pad_template;<br><br>  //MAIN<br>  if (!(source_pad_template = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(ctx.main_pipeline_tee), "src_%u")))<br>  {<br>    fprintf(stderr, "Error getting source pad template\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.tee_pad = gst_element_request_pad(ctx.main_pipeline_tee,<br>                                              source_pad_template, NULL, NULL)))<br>  {<br>    fprintf(stderr, "Error requesting main pipeline tee pad\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.tee_pad_ghost = gst_ghost_pad_new(NULL, ctx.tee_pad)))<br>  {<br>    fprintf(stderr, "Error creating ghost pad\n");<br>    return -1;<br>  }<br><br>  gst_pad_set_active(ctx.tee_pad_ghost, TRUE);<br><br>  if (!gst_element_add_pad(ctx.main_pipeline, ctx.tee_pad_ghost))<br>  {<br>    fprintf(stderr, "Error adding ghost pad to Main pipeline\n");<br>    return -1;<br>  }<br><br>  //SECONDARY<br><br>  if (!(ctx.link_element_pad = gst_element_get_static_pad(ctx.link_element_in_secondary_bin, "sink")))<br>  {<br>    fprintf(stderr, "Error requesting sink pad\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.link_element_pad_ghost = gst_ghost_pad_new(NULL, ctx.link_element_pad)))<br>  {<br>    fprintf(stderr, "Error creating ghost pad\n");<br>    return -1;<br>  }<br><br>  gst_pad_set_active(ctx.link_element_pad_ghost, TRUE);<br><br>  if (!gst_element_add_pad(ctx.link_element_in_secondary_bin, ctx.link_element_pad_ghost))<br>  {<br>    fprintf(stderr, "Error adding ghost pad to BIN\n");<br>    return -1;<br>  }<br><br>  return 0;<br>}<br><br>static int<br>connect_secondary_bin()<br>{<br>  if (request_pads() < 0)<br>    return -1;<br><br>  if (!(gst_bin_add(GST_BIN(ctx.main_pipeline), ctx.secondary_bin)))<br>  {<br>    fprintf(stderr, "Error adding bin to main pipeline\n");<br>    return -1;<br>  }<br><br>  if (!(gst_pad_link(ctx.tee_pad_ghost, ctx.link_element_pad_ghost)))<br>  {<br>    fprintf(stderr, "Error connecting source pad to sink pad\n");<br>    return -1;<br>  }<br><br>  if (gst_element_set_state(ctx.secondary_bin, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE)<br>  {<br>    fprintf(stderr, "Error setting secondary bin in play mode\n");<br>    return -1;<br>  }<br><br>  return 0;<br>}<br><br>int main()<br>{<br>  gst_init(NULL, NULL);<br><br>  if (!(ctx.app_loop = g_main_loop_new(NULL, FALSE)))<br>  {<br>    fprintf(stderr, "Error allocating main application loop\n");<br>    exit(1);<br>  }<br><br>  if (create_main_pipeline() < 0)<br>    exit(1);<br><br>  if (create_secondary_bin() < 0)<br>    exit(1);<br><br>  if (gst_element_set_state(ctx.main_pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE)<br>  {<br>    fprintf(stderr, "Error during set to play of pipeline\n");<br>    exit(1);<br>  }<br><br>  if (connect_secondary_bin() < 0)<br>    exit(1);<br><br>  g_main_loop_run(ctx.app_loop);<br>}<br></div><div><br></div><div><b><u>And the error on the log is this:</u></b></div><div><b><u><br></u></b></div><div>0:00:00.491082498   600 0xaaaaef471800 INFO                GST_PADS gstpad.c:2377:gst_pad_link_prepare: trying to link pipeline0:ghostpad0 and secondary_bin_queue:ghostpad1<br>0:00:00.491104623   600 0xaaaaef471800 DEBUG               GST_CAPS gstpad.c:2364:gst_pad_link_check_hierarchy: pads have different grandparents (NULL) and <testbin><br></div></div><div><br></div><div>What I did wrong?</div><div><br></div><div>Thank you very much</div><div>Matteo</div></div>