From: Jan Schmidt Date: Thu, 25 Jun 2015 17:29:27 +0000 (+1000) Subject: parse-launch: Support linking all pads with new operator X-Git-Tag: 1.12.0~283 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5a5ae1be1fc22ab538fb74984a99ce9d8f708f80;p=platform%2Fupstream%2Fgstreamer.git 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 --- diff --git a/gst/parse/grammar.y b/gst/parse/grammar.y index 85d37dd..d7b431e 100644 --- a/gst/parse/grammar.y +++ b/gst/parse/grammar.y @@ -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); + + 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)) { + 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 REF PADREF BINREF %token ASSIGNMENT %token LINK +%token LINK_ALL %type binopener %type 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) diff --git a/gst/parse/parse.l b/gst/parse/parse.l index 53afba8..50acf5c 100644 --- a/gst/parse/parse.l +++ b/gst/parse/parse.l @@ -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); diff --git a/gst/parse/types.h b/gst/parse/types.h index fbeaf20..66d13dd 100644 --- a/gst/parse/types.h +++ b/gst/parse/types.h @@ -15,6 +15,7 @@ typedef struct { reference_t src; reference_t sink; GstCaps *caps; + gboolean all_pads; } link_t; typedef struct { diff --git a/tests/check/pipelines/parse-launch.c b/tests/check/pipelines/parse-launch.c index 6472070..6e91165 100644 --- a/tests/check/pipelines/parse-launch.c +++ b/tests/check/pipelines/parse-launch.c @@ -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 }; diff --git a/tools/gst-launch.1.in b/tools/gst-launch.1.in index 5034f29..9406611 100644 --- a/tools/gst-launch.1.in +++ b/tools/gst-launch.1.in @@ -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