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

Matteo locatster at gmail.com
Fri Nov 19 14:25:10 UTC 2021


Good morning,
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.

*This is my code:*

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

#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"

struct context
{
  GstElement *main_pipeline;
  GstElement *main_pipeline_tee;
  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;

  if (!(pipeline_string = g_strdup_printf(PIPELINE_MAIN_STRING,
                                          1920, 1080)))
  {
    fprintf(stderr, "Error allocating pipeline string\n");
    return -1;
  }

  fprintf(stdout, "Current pipeline string: %s\n", pipeline_string);

  if (!(ctx.main_pipeline = gst_parse_launch(pipeline_string, NULL)))
  {
    fprintf(stderr, "Error parsing pipeline string\n");
    return -1;
  }

  if (!(ctx.main_pipeline_tee =
gst_bin_get_by_name(GST_BIN(ctx.main_pipeline), "split")))
  {
    fprintf(stderr, "Error during get of tee element\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("fakesink",
"seconday_bin_fakesink")))
  {
    fprintf(stderr, "Error creating fakesink in secondary bin\n");
    return -1;
  }

  gst_element_link(ctx.link_element_in_secondary_bin, fakesink);

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

  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.main_pipeline_tee),
"src_%u")))
  {
    fprintf(stderr, "Error getting source pad template\n");
    return -1;
  }

  if (!(ctx.tee_pad = gst_element_request_pad(ctx.main_pipeline_tee,
                                              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.main_pipeline, 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.link_element_in_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;
  }

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

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

  return 0;
}

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

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

  g_main_loop_run(ctx.app_loop);
}

*And the error on the log is this:*

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
0:00:00.491104623   600 0xaaaaef471800 DEBUG               GST_CAPS
gstpad.c:2364:gst_pad_link_check_hierarchy: pads have different
grandparents (NULL) and <testbin>

What I did wrong?

Thank you very much
Matteo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20211119/90eb6dd1/attachment-0001.htm>


More information about the gstreamer-devel mailing list