<div dir="ltr">Hello,<div>At the end I found that creating two separate bins and adding them to the pipeline does not raise the "pads have different grandparents" problem.</div><div>But now I have another problem, after I add the second bin to the pipeline it takes seconds to start playing, in particular I see in the log that it starts playing after a "unlocked after timeout" clock event.</div><div><br></div><div>I will attach the code that does this:</div><div>-It creates the bin videotestsrc -> tee (with allow-not-linked) and adds it to the main pipeline</div><div>- Sets main pipeline to play</div><div>- It creates a secondary bin queue -> autovideosink</div><div>- After 5 seconds:</div><div>  - It requests the pad on the tee and creates a ghost pad adding it to the primary bin</div><div>  - It requests the sink pad on the queue and creates a ghost pad adding it to the secondary bin</div><div>  - It adds secondary bin to pipeline</div><div>  - It sets secondary bin to play  </div><div>  - It links the ghost pads of the primary and secondary bins</div><div><br></div><div>#include <stdio.h><br>#include <stdlib.h><br>#include <gst/gst.h><br><br>#define PIPELINE_MAIN_STRING "videotestsrc ! tee name=split allow-not-linked=true"<br><br>struct context<br>{<br>  GstElement *main_pipeline;<br><br>  GstElement *primary_bin;<br>  GstElement *tee_element;<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>  GstElement *testsrc;<br><br>  if (!(ctx.main_pipeline = gst_pipeline_new("main_pipeline")))<br>  {<br>    fprintf(stderr, "Error creating main pipeline\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.primary_bin = gst_bin_new("primary_bin")))<br>  {<br>    fprintf(stderr, "Erorr creating primary bin\n");<br>    return -1;<br>  }<br><br>  if (!(testsrc = gst_element_factory_make("videotestsrc", "test_src")))<br>  {<br>    fprintf(stderr, "Erorr creating test source\n");<br>    return -1;<br>  }<br><br>  if (!(ctx.tee_element = gst_element_factory_make("tee", "tee")))<br>  {<br>    fprintf(stderr, "Error creating tee\n");<br>    return -1;<br>  }<br><br>  g_object_set(ctx.tee_element, "allow-not-linked", 1, NULL);<br><br>  gst_bin_add_many(GST_BIN(ctx.primary_bin), testsrc, ctx.tee_element, NULL);<br><br>  if (!(gst_element_link_many(testsrc, ctx.tee_element, NULL)))<br>  {<br>    fprintf(stderr, "Error linking elements\n");<br>    return -1;<br>  }<br><br>  if (!(gst_bin_add(GST_BIN(ctx.main_pipeline), ctx.primary_bin)))<br>  {<br>    fprintf(stderr, "Error adding primary bin to main pipeline\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("autovideosink", "seconday_bin_fakesink")))<br>  {<br>    fprintf(stderr, "Error creating fakesink in secondary bin\n");<br>    return -1;<br>  }<br><br>  gst_bin_add_many(GST_BIN(ctx.secondary_bin), ctx.link_element_in_secondary_bin, fakesink, NULL);<br><br>  gst_element_link(ctx.link_element_in_secondary_bin, fakesink);<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.tee_element), "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.tee_element,<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.primary_bin, 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.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>  fprintf(stdout, "SETTING NEW TO PLAY\n");<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>  fprintf(stdout, "LINKING PADS\n");<br><br>  if (gst_pad_link(ctx.tee_pad_ghost, ctx.link_element_pad_ghost) != GST_PAD_LINK_OK)<br>  {<br>    fprintf(stderr, "Error connecting source pad to sink pad\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>  return 0;<br>}<br><br>// static GstPadProbeReturn<br>// event_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)<br>// {<br>//   fprintf(stderr, "TE\n");<br><br>//   if (GST_EVENT_TYPE(GST_PAD_PROBE_INFO_DATA(info)) != GST_EVENT_EOS)<br>//     return GST_PAD_PROBE_PASS;<br><br>//   gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));<br><br>//   fprintf(stderr, "Starting DISCONNECTION\n");<br><br>//   gst_element_set_state(ctx.secondary_bin, GST_STATE_NULL);<br><br>//   gst_bin_remove(GST_BIN(ctx.main_pipeline), ctx.secondary_bin);<br><br>//   gst_element_release_request_pad(ctx.tee_element, ctx.tee_pad_ghost);<br>//   gst_element_release_request_pad(ctx.tee_element, ctx.tee_pad);<br>//   gst_object_unref(ctx.tee_pad);<br>//   gst_object_unref(ctx.tee_pad_ghost);<br><br>//   fprintf(stderr, "DISCONNECTION DONE\n");<br>//   return GST_PAD_PROBE_DROP;<br>// }<br><br>// static GstPadProbeReturn<br>// pad_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)<br>// {<br>//   fprintf(stderr, "PAD PROBE 1\n");<br>//   gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));<br>//   fprintf(stderr, "Add another probe\n");<br>//   gst_pad_add_probe(ctx.tee_pad_ghost,<br>//                     GST_PAD_PROBE_TYPE_BLOCK | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback)event_probe_cb, NULL, NULL);<br><br>//   fprintf(stderr, "Sending EOS\n");<br>//   if (!(gst_pad_send_event(ctx.link_element_pad_ghost, gst_event_new_eos())))<br>//   {<br>//     fprintf(stderr, "Error sending EOS to sink PAD\n");<br>//     return GST_PAD_PROBE_OK;<br>//   }<br><br>//   fprintf(stderr, "EOS sent\n");<br><br>//   return GST_PAD_PROBE_OK;<br>// }<br><br>// static gboolean<br>// timeout_cb(gpointer user_data)<br>// {<br>//   gst_pad_add_probe(ctx.tee_pad_ghost, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,<br>//                     (GstPadProbeCallback)pad_probe_cb, (gpointer)NULL, NULL);<br><br>//   return FALSE;<br>// }<br><br>static gboolean<br>timeout2_cb(gpointer user_data)<br>{<br>  if (connect_secondary_bin() < 0)<br>    exit(1);<br><br>  return FALSE;<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>  g_timeout_add(5000, (GSourceFunc)timeout2_cb, NULL);<br><br>  //g_timeout_add(10000, (GSourceFunc)timeout_cb, NULL);<br>  g_main_loop_run(ctx.app_loop);<br>}<br></div><div><br></div><div>What could be the problem?</div><div>Thank you very much</div><div><br></div><div>Matteo</div><div><br></div></div>