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