Pads have different grandparents dynamically connecting main pipeline to a secondary bin

Matteo locatster at gmail.com
Sun Nov 21 17:16:09 UTC 2021


Hello,
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.
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.

I will attach the code that does this:
-It creates the bin videotestsrc -> tee (with allow-not-linked) and adds it
to the main pipeline
- Sets main pipeline to play
- It creates a secondary bin queue -> autovideosink
- After 5 seconds:
  - It requests the pad on the tee and creates a ghost pad adding it to the
primary bin
  - It requests the sink pad on the queue and creates a ghost pad adding it
to the secondary bin
  - It adds secondary bin to pipeline
  - It sets secondary bin to play
  - It links the ghost pads of the primary and secondary bins

#include <stdio.h>
#include <stdlib.h>
#include <gst/gst.h>

#define PIPELINE_MAIN_STRING "videotestsrc ! tee name=split
allow-not-linked=true"

struct context
{
  GstElement *main_pipeline;

  GstElement *primary_bin;
  GstElement *tee_element;
  GstPad *tee_pad;
  GstPad *tee_pad_ghost;
  GMainLoop *app_loop;

  GstElement *secondary_bin;
  GstElement *link_element_in_secondary_bin;
  GstPad *link_element_pad;
  GstPad *link_element_pad_ghost;

} ctx = {0};

static int
create_main_pipeline()
{
  int ret = 0;
  gchar *pipeline_string = NULL;
  GstElement *testsrc;

  if (!(ctx.main_pipeline = gst_pipeline_new("main_pipeline")))
  {
    fprintf(stderr, "Error creating main pipeline\n");
    return -1;
  }

  if (!(ctx.primary_bin = gst_bin_new("primary_bin")))
  {
    fprintf(stderr, "Erorr creating primary bin\n");
    return -1;
  }

  if (!(testsrc = gst_element_factory_make("videotestsrc", "test_src")))
  {
    fprintf(stderr, "Erorr creating test source\n");
    return -1;
  }

  if (!(ctx.tee_element = gst_element_factory_make("tee", "tee")))
  {
    fprintf(stderr, "Error creating tee\n");
    return -1;
  }

  g_object_set(ctx.tee_element, "allow-not-linked", 1, NULL);

  gst_bin_add_many(GST_BIN(ctx.primary_bin), testsrc, ctx.tee_element,
NULL);

  if (!(gst_element_link_many(testsrc, ctx.tee_element, NULL)))
  {
    fprintf(stderr, "Error linking elements\n");
    return -1;
  }

  if (!(gst_bin_add(GST_BIN(ctx.main_pipeline), ctx.primary_bin)))
  {
    fprintf(stderr, "Error adding primary bin to main pipeline\n");
    return -1;
  }

  return 0;
}

static int
create_secondary_bin()
{
  GstElement *fakesink;

  if (!(ctx.secondary_bin = gst_bin_new("testbin")))
  {
    fprintf(stderr, "Error creating secondary bin\n");
    return -1;
  }

  if (!(ctx.link_element_in_secondary_bin =
gst_element_factory_make("queue", "secondary_bin_queue")))
  {
    fprintf(stderr, "Error creating queue in secondary bin\n");
    return -1;
  }

  if (!(fakesink = gst_element_factory_make("autovideosink",
"seconday_bin_fakesink")))
  {
    fprintf(stderr, "Error creating fakesink in secondary bin\n");
    return -1;
  }

  gst_bin_add_many(GST_BIN(ctx.secondary_bin),
ctx.link_element_in_secondary_bin, fakesink, NULL);

  gst_element_link(ctx.link_element_in_secondary_bin, fakesink);

  return 0;
}

static int
request_pads()
{
  GstPadTemplate *source_pad_template;

  //MAIN
  if (!(source_pad_template =
gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(ctx.tee_element),
"src_%u")))
  {
    fprintf(stderr, "Error getting source pad template\n");
    return -1;
  }

  if (!(ctx.tee_pad = gst_element_request_pad(ctx.tee_element,
                                              source_pad_template, NULL,
NULL)))
  {
    fprintf(stderr, "Error requesting main pipeline tee pad\n");
    return -1;
  }

  if (!(ctx.tee_pad_ghost = gst_ghost_pad_new(NULL, ctx.tee_pad)))
  {
    fprintf(stderr, "Error creating ghost pad\n");
    return -1;
  }

  gst_pad_set_active(ctx.tee_pad_ghost, TRUE);

  if (!gst_element_add_pad(ctx.primary_bin, ctx.tee_pad_ghost))
  {
    fprintf(stderr, "Error adding ghost pad to Main pipeline\n");
    return -1;
  }

  //SECONDARY

  if (!(ctx.link_element_pad =
gst_element_get_static_pad(ctx.link_element_in_secondary_bin, "sink")))
  {
    fprintf(stderr, "Error requesting sink pad\n");
    return -1;
  }

  if (!(ctx.link_element_pad_ghost = gst_ghost_pad_new(NULL,
ctx.link_element_pad)))
  {
    fprintf(stderr, "Error creating ghost pad\n");
    return -1;
  }

  gst_pad_set_active(ctx.link_element_pad_ghost, TRUE);

  if (!gst_element_add_pad(ctx.secondary_bin, ctx.link_element_pad_ghost))
  {
    fprintf(stderr, "Error adding ghost pad to BIN\n");
    return -1;
  }

  return 0;
}

static int
connect_secondary_bin()
{
  if (request_pads() < 0)
    return -1;

  if (!(gst_bin_add(GST_BIN(ctx.main_pipeline), ctx.secondary_bin)))
  {
    fprintf(stderr, "Error adding bin to main pipeline\n");
    return -1;
  }

  fprintf(stdout, "SETTING NEW TO PLAY\n");

  if (gst_element_set_state(ctx.secondary_bin, GST_STATE_PLAYING) ==
GST_STATE_CHANGE_FAILURE)
  {
    fprintf(stderr, "Error setting secondary bin in play mode\n");
    return -1;
  }

  fprintf(stdout, "LINKING PADS\n");

  if (gst_pad_link(ctx.tee_pad_ghost, ctx.link_element_pad_ghost) !=
GST_PAD_LINK_OK)
  {
    fprintf(stderr, "Error connecting source pad to sink pad\n");
    return -1;
  }

  // if (!(gst_pad_link(ctx.tee_pad_ghost, ctx.link_element_pad_ghost)))
  // {
  //   fprintf(stderr, "Error connecting source pad to sink pad\n");
  //   return -1;
  // }

  return 0;
}

// static GstPadProbeReturn
// event_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
// {
//   fprintf(stderr, "TE\n");

//   if (GST_EVENT_TYPE(GST_PAD_PROBE_INFO_DATA(info)) != GST_EVENT_EOS)
//     return GST_PAD_PROBE_PASS;

//   gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));

//   fprintf(stderr, "Starting DISCONNECTION\n");

//   gst_element_set_state(ctx.secondary_bin, GST_STATE_NULL);

//   gst_bin_remove(GST_BIN(ctx.main_pipeline), ctx.secondary_bin);

//   gst_element_release_request_pad(ctx.tee_element, ctx.tee_pad_ghost);
//   gst_element_release_request_pad(ctx.tee_element, ctx.tee_pad);
//   gst_object_unref(ctx.tee_pad);
//   gst_object_unref(ctx.tee_pad_ghost);

//   fprintf(stderr, "DISCONNECTION DONE\n");
//   return GST_PAD_PROBE_DROP;
// }

// static GstPadProbeReturn
// pad_probe_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data)
// {
//   fprintf(stderr, "PAD PROBE 1\n");
//   gst_pad_remove_probe(pad, GST_PAD_PROBE_INFO_ID(info));
//   fprintf(stderr, "Add another probe\n");
//   gst_pad_add_probe(ctx.tee_pad_ghost,
//                     GST_PAD_PROBE_TYPE_BLOCK |
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback)event_probe_cb,
NULL, NULL);

//   fprintf(stderr, "Sending EOS\n");
//   if (!(gst_pad_send_event(ctx.link_element_pad_ghost,
gst_event_new_eos())))
//   {
//     fprintf(stderr, "Error sending EOS to sink PAD\n");
//     return GST_PAD_PROBE_OK;
//   }

//   fprintf(stderr, "EOS sent\n");

//   return GST_PAD_PROBE_OK;
// }

// static gboolean
// timeout_cb(gpointer user_data)
// {
//   gst_pad_add_probe(ctx.tee_pad_ghost,
GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
//                     (GstPadProbeCallback)pad_probe_cb, (gpointer)NULL,
NULL);

//   return FALSE;
// }

static gboolean
timeout2_cb(gpointer user_data)
{
  if (connect_secondary_bin() < 0)
    exit(1);

  return FALSE;
}

int main()
{
  gst_init(NULL, NULL);

  if (!(ctx.app_loop = g_main_loop_new(NULL, FALSE)))
  {
    fprintf(stderr, "Error allocating main application loop\n");
    exit(1);
  }

  if (create_main_pipeline() < 0)
    exit(1);

  if (create_secondary_bin() < 0)
    exit(1);

  if (gst_element_set_state(ctx.main_pipeline, GST_STATE_PLAYING) ==
GST_STATE_CHANGE_FAILURE)
  {
    fprintf(stderr, "Error during set to play of pipeline\n");
    exit(1);
  }

  g_timeout_add(5000, (GSourceFunc)timeout2_cb, NULL);

  //g_timeout_add(10000, (GSourceFunc)timeout_cb, NULL);
  g_main_loop_run(ctx.app_loop);
}

What could be the problem?
Thank you very much

Matteo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20211121/256475a9/attachment.htm>


More information about the gstreamer-devel mailing list