parse-launch: warn when still waiting to plug sub-pipelines after no-more-pads
authorStefan Sauer <ensonic@users.sf.net>
Sat, 2 Jan 2016 18:42:17 +0000 (19:42 +0100)
committerStefan Sauer <ensonic@users.sf.net>
Sun, 3 Jan 2016 21:58:06 +0000 (22:58 +0100)
The parse-launch API automagically handles dynamic pads and performs delayed
linking as needed, without any feedback about whether the linking succeeded or
not however. If a delayed dynamic link can't be completed for whatever reason,
parse-launch will simply wait in case a suitable pad appears later. This may
never happen though, in which case the pipeline may just hang forever.

Try to improve this by connecting to the "no-more-pads" signal of any element
with dynamic pads and posting a warning message for the related outstanding
dynamic links when "no-more-pads" is emitted.

Fixes #760003

gst/gstparse.h
gst/parse/grammar.y

index c2456c9..44912f0 100644 (file)
@@ -35,6 +35,8 @@ GQuark gst_parse_error_quark (void);
  */
 #define GST_PARSE_ERROR gst_parse_error_quark ()
 
+/* FIXME 2.0: rename to GstParseLaunchError, this is not only related to
+ *parsing */
 /**
  * GstParseError:
  * @GST_PARSE_ERROR_SYNTAX: A syntax error occurred.
@@ -44,6 +46,7 @@ GQuark gst_parse_error_quark (void);
  * @GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY: There was an error setting a property
  * @GST_PARSE_ERROR_EMPTY_BIN: An empty bin was specified.
  * @GST_PARSE_ERROR_EMPTY: An empty description was specified
+ * @GST_PARSE_ERROR_DELAYED_LINK: A delayed link did not get resolved.
  *
  * The different parsing errors that can occur.
  */
@@ -55,7 +58,8 @@ typedef enum
   GST_PARSE_ERROR_LINK,
   GST_PARSE_ERROR_COULD_NOT_SET_PROPERTY,
   GST_PARSE_ERROR_EMPTY_BIN,
-  GST_PARSE_ERROR_EMPTY
+  GST_PARSE_ERROR_EMPTY,
+  GST_PARSE_ERROR_DELAYED_LINK
 } GstParseError;
 
 /**
index 03f8c55..c129db4 100644 (file)
@@ -232,7 +232,7 @@ typedef struct {
   gchar *sink_pad;
   GstElement *sink;
   GstCaps *caps;
-  gulong signal_id;
+  gulong pad_added_signal_id, no_more_pads_signal_id;
 } DelayedLink;
 
 typedef struct {
@@ -490,6 +490,19 @@ static void gst_parse_free_delayed_link (DelayedLink *link)
   g_slice_free (DelayedLink, link);
 }
 
+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 %s:%s to %s:%s",
+                   GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
+                   GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (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 */
+}
+
 static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
 {
   DelayedLink *link = data;
@@ -505,7 +518,9 @@ static void gst_parse_found_pad (GstElement *src, GstPad *pad, gpointer data)
     GST_CAT_DEBUG (GST_CAT_PIPELINE, "delayed linking %s:%s to %s:%s worked",
                           GST_STR_NULL (GST_ELEMENT_NAME (src)), GST_STR_NULL (link->src_pad),
                           GST_STR_NULL (GST_ELEMENT_NAME (link->sink)), GST_STR_NULL (link->sink_pad));
-    g_signal_handler_disconnect (src, link->signal_id);
+    g_signal_handler_disconnect (src, link->no_more_pads_signal_id);
+    /* releases 'link' */
+    g_signal_handler_disconnect (src, link->pad_added_signal_id);
   }
 }
 
@@ -539,9 +554,11 @@ gst_parse_perform_delayed_link (GstElement *src, const gchar *src_pad,
       } else {
        data->caps = NULL;
       }
-      data->signal_id = g_signal_connect_data (src, "pad-added",
+      data->pad_added_signal_id = g_signal_connect_data (src, "pad-added",
           G_CALLBACK (gst_parse_found_pad), data,
           (GClosureNotify) gst_parse_free_delayed_link, (GConnectFlags) 0);
+      data->no_more_pads_signal_id = g_signal_connect (src, "no-more-pads",
+          G_CALLBACK (gst_parse_no_more_pads), data);
       return TRUE;
     }
   }