mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-18 04:05:34 +00:00
parse-launch: Support linking all pads with new operator
Introduce a new operator ':' - e.g. element1 ':' element2 For example, 'uridecodebin : encodebin' - if the encodebin has multiple profiles compatible with the decodebin, multiple links will be created. With '!' , after one delayed link is successfully done, the pad-added callback is disconnected. https://bugzilla.gnome.org/show_bug.cgi?id=751450
This commit is contained in:
parent
bf3a7c54f7
commit
5a5ae1be1f
5 changed files with 79 additions and 32 deletions
|
@ -233,6 +233,7 @@ typedef struct {
|
|||
GstElement *sink;
|
||||
GstCaps *caps;
|
||||
gulong pad_added_signal_id, no_more_pads_signal_id;
|
||||
gboolean all_pads;
|
||||
} DelayedLink;
|
||||
|
||||
typedef struct {
|
||||
|
@ -499,11 +500,15 @@ static void gst_parse_no_more_pads (GstElement *src, gpointer data)
|
|||
{
|
||||
DelayedLink *link = data;
|
||||
|
||||
GST_ELEMENT_WARNING(src, PARSE, DELAYED_LINK,
|
||||
(_("Delayed linking failed.")),
|
||||
("failed delayed linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT,
|
||||
PRETTY_PAD_NAME_ARGS (src, link->src_pad),
|
||||
PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad)));
|
||||
/* Don't warn for all-pads links, as we expect those to
|
||||
* still be active at no-more-pads */
|
||||
if (!link->all_pads) {
|
||||
GST_ELEMENT_WARNING(src, PARSE, DELAYED_LINK,
|
||||
(_("Delayed linking failed.")),
|
||||
("failed delayed linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT,
|
||||
PRETTY_PAD_NAME_ARGS (src, link->src_pad),
|
||||
PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad)));
|
||||
}
|
||||
/* we keep the handlers connected, so that in case an element still adds a pad
|
||||
* despite no-more-pads, we will consider it for pending delayed links */
|
||||
}
|
||||
|
@ -513,7 +518,8 @@ static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
|
|||
DelayedLink *link = data;
|
||||
|
||||
GST_CAT_INFO (GST_CAT_PIPELINE,
|
||||
"trying delayed linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT,
|
||||
"trying delayed linking %s " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT,
|
||||
link->all_pads ? "all pads" : "one pad",
|
||||
PRETTY_PAD_NAME_ARGS (src, link->src_pad),
|
||||
PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad));
|
||||
|
||||
|
@ -522,12 +528,14 @@ static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
|
|||
/* do this here, we don't want to get any problems later on when
|
||||
* unlocking states */
|
||||
GST_CAT_DEBUG (GST_CAT_PIPELINE,
|
||||
"delayed linking " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT " worked",
|
||||
"delayed linking %s " PRETTY_PAD_NAME_FMT " to " PRETTY_PAD_NAME_FMT " worked",
|
||||
link->all_pads ? "all pads" : "one pad",
|
||||
PRETTY_PAD_NAME_ARGS (src, link->src_pad),
|
||||
PRETTY_PAD_NAME_ARGS (link->sink, link->sink_pad));
|
||||
g_signal_handler_disconnect (src, link->no_more_pads_signal_id);
|
||||
/* releases 'link' */
|
||||
g_signal_handler_disconnect (src, link->pad_added_signal_id);
|
||||
if (!link->all_pads)
|
||||
g_signal_handler_disconnect (src, link->pad_added_signal_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,7 +543,7 @@ static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
|
|||
static gboolean
|
||||
gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
|
||||
GstElement *sink, const gchar *sink_pad,
|
||||
GstCaps *caps)
|
||||
GstCaps *caps, gboolean all_pads)
|
||||
{
|
||||
GList *templs = gst_element_class_get_pad_template_list (
|
||||
GST_ELEMENT_GET_CLASS (src));
|
||||
|
@ -547,6 +555,8 @@ gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
|
|||
{
|
||||
DelayedLink *data = g_slice_new (DelayedLink);
|
||||
|
||||
data->all_pads = all_pads;
|
||||
|
||||
/* TODO: maybe we should check if src_pad matches this template's names */
|
||||
|
||||
GST_CAT_DEBUG (GST_CAT_PIPELINE,
|
||||
|
@ -596,18 +606,30 @@ gst_parse_perform_link (link_t *link, graph_t *graph)
|
|||
g_slist_length (srcs), g_slist_length (sinks), link->caps);
|
||||
|
||||
if (!srcs || !sinks) {
|
||||
if (gst_element_link_pads_filtered (src,
|
||||
gboolean found_one = gst_element_link_pads_filtered (src,
|
||||
srcs ? (const gchar *) srcs->data : NULL, sink,
|
||||
sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
|
||||
sinks ? (const gchar *) sinks->data : NULL, link->caps);
|
||||
|
||||
if (found_one) {
|
||||
if (!link->all_pads)
|
||||
goto success; /* Linked one, and not an all-pads link = we're done */
|
||||
|
||||
/* Try and link more available pads */
|
||||
while (gst_element_link_pads_filtered (src,
|
||||
srcs ? (const gchar *) srcs->data : NULL, sink,
|
||||
sinks ? (const gchar *) sinks->data : NULL, link->caps));
|
||||
}
|
||||
|
||||
/* We either didn't find any static pads, or this is a all-pads link,
|
||||
* in which case watch for future pads and link those. Not a failure
|
||||
* in the all-pads case if there's no sometimes pads to watch */
|
||||
if (gst_parse_perform_delayed_link (src,
|
||||
srcs ? (const gchar *) srcs->data : NULL,
|
||||
sink, sinks ? (const gchar *) sinks->data : NULL, link->caps,
|
||||
link->all_pads) || link->all_pads) {
|
||||
goto success;
|
||||
} else {
|
||||
if (gst_parse_perform_delayed_link (src,
|
||||
srcs ? (const gchar *) srcs->data : NULL,
|
||||
sink, sinks ? (const gchar *) sinks->data : NULL, link->caps)) {
|
||||
goto success;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (g_slist_length (link->src.pads) != g_slist_length (link->sink.pads)) {
|
||||
|
@ -624,7 +646,7 @@ gst_parse_perform_link (link_t *link, graph_t *graph)
|
|||
} else {
|
||||
if (gst_parse_perform_delayed_link (src, src_pad,
|
||||
sink, sink_pad,
|
||||
link->caps)) {
|
||||
link->caps, link->all_pads)) {
|
||||
continue;
|
||||
} else {
|
||||
goto error;
|
||||
|
@ -666,6 +688,7 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
|
|||
%left <ss> REF PADREF BINREF
|
||||
%token <ss> ASSIGNMENT
|
||||
%token <ss> LINK
|
||||
%token <ss> LINK_ALL
|
||||
|
||||
%type <ss> binopener
|
||||
%type <gg> graph
|
||||
|
@ -691,7 +714,7 @@ static int yyerror (void *scanner, graph_t *graph, const char *s);
|
|||
%left '(' ')'
|
||||
%left ','
|
||||
%right '.'
|
||||
%left '!' '='
|
||||
%left '!' '=' ':'
|
||||
|
||||
%lex-param { void *scanner }
|
||||
%parse-param { void *scanner }
|
||||
|
@ -805,17 +828,19 @@ openchain:
|
|||
$$ = $4;
|
||||
$$->last.pads = g_slist_concat ($$->last.pads, $5);
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
link: LINK { $$ = gst_parse_link_new ();
|
||||
$$->src.element = NULL;
|
||||
$$->sink.element = NULL;
|
||||
$$->src.name = NULL;
|
||||
$$->sink.name = NULL;
|
||||
$$->src.pads = NULL;
|
||||
$$->sink.pads = NULL;
|
||||
$$->caps = NULL;
|
||||
$$->all_pads = FALSE;
|
||||
if ($1) {
|
||||
$$->caps = gst_caps_from_string ($1);
|
||||
if ($$->caps == NULL)
|
||||
SET_ERROR (graph->error, GST_PARSE_ERROR_LINK, _("could not parse caps \"%s\""), $1);
|
||||
gst_parse_strfree ($1);
|
||||
}
|
||||
}
|
||||
| LINK_ALL { $$ = gst_parse_link_new ();
|
||||
$$->all_pads = TRUE;
|
||||
if ($1) {
|
||||
$$->caps = gst_caps_from_string ($1);
|
||||
if ($$->caps == NULL)
|
||||
|
|
|
@ -50,7 +50,7 @@ PRINT (const char *format, ...)
|
|||
|
||||
%}
|
||||
|
||||
_operator [(){}.!,;=]
|
||||
_operator [(){}.!:,;=]
|
||||
_identifier [[:alnum:]_][[:alnum:]\-_%:]*
|
||||
|
||||
_char ("\\".)|([^[:space:]])
|
||||
|
@ -75,7 +75,7 @@ _mimetype {_mimechar}+"/"{_mimechar}+
|
|||
_capschar ("\\".)|([^\;!])
|
||||
_capsstring {_capschar}+
|
||||
_caps {_mimetype}(","[^!]|{_capsstring})*
|
||||
_link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)*"!")|("!")
|
||||
_link ([!:][[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)*[!:])|([!:])
|
||||
|
||||
%x value
|
||||
%option noyywrap
|
||||
|
@ -128,21 +128,33 @@ _link ("!"[[:space:]]*{_caps}([[:space:]]*(";"[[:space:]]*{_caps})*[[:space:]]*)
|
|||
|
||||
{_link} {
|
||||
gchar *c = yytext;
|
||||
gchar op;
|
||||
gboolean link_all;
|
||||
|
||||
PRINT ("LINK: %s", yytext);
|
||||
/* First char is a link operator */
|
||||
link_all = (*c == ':');
|
||||
c++;
|
||||
if (*c) {
|
||||
while (g_ascii_isspace (*c)) c++;
|
||||
c = yylval->ss = gst_parse_strdup (c);
|
||||
while (*c) c++;
|
||||
if (*--c != '!')
|
||||
/* Last non-space char is a link operator */
|
||||
op = *--c;
|
||||
if (op != '!' && op != ':')
|
||||
g_assert_not_reached ();
|
||||
if (op == ':')
|
||||
link_all = TRUE;
|
||||
|
||||
/* Walk backward past whitespaces - what remains
|
||||
* is a filter caps string, or empty */
|
||||
while (g_ascii_isspace (*--c));
|
||||
*++c = '\0';
|
||||
} else {
|
||||
yylval->ss = NULL;
|
||||
}
|
||||
BEGIN (INITIAL);
|
||||
return LINK;
|
||||
return link_all ? LINK_ALL : LINK;
|
||||
}
|
||||
{_url} {
|
||||
PRINT ("URL: %s", yytext);
|
||||
|
|
|
@ -15,6 +15,7 @@ typedef struct {
|
|||
reference_t src;
|
||||
reference_t sink;
|
||||
GstCaps *caps;
|
||||
gboolean all_pads;
|
||||
} link_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -108,6 +108,10 @@ static const gchar *test_lines[] = {
|
|||
/* "(name=mabin fakesrc) mabin. ! fakesink", FIXME: linking to named bin does not work yet */
|
||||
/* "(name=mabin name=yoyo fakesrc) yoyo. ! fakesink", FIXME: linking to named bin does not work yet */
|
||||
"deepsrc. ! fakesink fakesrc ! ( identity ! ( identity ! ( identity name=deepsrc ) ) )", /* deep name resolution, multilevel ghostpad creation */
|
||||
"fakesrc : fakesink", /* linking all matching pads */
|
||||
"fakesrc : video/x-all : fakesink", /* linking all matching pads with filter */
|
||||
"fakesrc ! video/x-all : fakesink", /* linking all matching pads with filter */
|
||||
"fakesrc : video/x-all ! fakesink", /* linking all matching pads with filter */
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@ partial pipelines instead of a full-fledged top-level pipeline.
|
|||
|
||||
\fI[[SRCELEMENT].[PAD1,...]]\fR ! \fI[[SINKELEMENT].[PAD1,...]]\fR
|
||||
\fI[[SRCELEMENT].[PAD1,...]]\fR ! CAPS ! \fI[[SINKELEMENT].[PAD1,...]]\fR
|
||||
\fI[[SRCELEMENT].[PAD1,...]]\fR : \fI[[SINKELEMENT].[PAD1,...]]\fR
|
||||
\fI[[SRCELEMENT].[PAD1,...]]\fR : CAPS : \fI[[SINKELEMENT].[PAD1,...]]\fR
|
||||
|
||||
Links the element with name SRCELEMENT to the element with name SINKELEMENT,
|
||||
using the caps specified in CAPS as a filter.
|
||||
|
@ -178,6 +180,9 @@ specified and multiple links are done in the given order.
|
|||
So the simplest link is a simple exclamation mark, that links the element to
|
||||
the left of it to the element right of it.
|
||||
.br
|
||||
Linking using the : operator attempts to link all possible pads between
|
||||
the elements
|
||||
.br
|
||||
|
||||
.B Caps
|
||||
|
||||
|
|
Loading…
Reference in a new issue