gstfunnel: avoid access of freed pad
[platform/upstream/gstreamer.git] / gst / gstdebugutils.c
index de74850..e67a77c 100644 (file)
@@ -54,7 +54,7 @@
 
 /*** PIPELINE GRAPHS **********************************************************/
 
-const gchar *priv_gst_dump_dot_dir;     /* NULL *//* set from gst.c */
+extern const gchar *priv_gst_dump_dot_dir;      /* NULL *//* set from gst.c */
 
 const gchar spaces[] = {
   "                                "    /* 32 */
@@ -66,10 +66,10 @@ const gchar spaces[] = {
 extern GstClockTime _priv_gst_info_start_time;
 
 static gchar *
-debug_dump_make_object_name (GstObject * element)
+debug_dump_make_object_name (GstObject * obj)
 {
-  return g_strcanon (g_strdup_printf ("%s_%p", GST_OBJECT_NAME (element),
-          element), G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_", '_');
+  return g_strcanon (g_strdup_printf ("%s_%p", GST_OBJECT_NAME (obj), obj),
+      G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "_", '_');
 }
 
 static gchar *
@@ -81,7 +81,9 @@ debug_dump_get_element_state (GstElement * element)
 
   gst_element_get_state (element, &state, &pending, 0);
   if (pending == GST_STATE_VOID_PENDING) {
-    state_name = g_strdup_printf ("\\n[%c]", state_icons[state]);
+    gboolean is_locked = gst_element_is_locked_state (element);
+    state_name = g_strdup_printf ("\\n[%c]%s", state_icons[state],
+        (is_locked ? "(locked)" : ""));
   } else {
     state_name = g_strdup_printf ("\\n[%c] -> [%c]", state_icons[state],
         state_icons[pending]);
@@ -159,15 +161,17 @@ debug_dump_pad (GstPad * pad, const gchar * color_name,
     }
   }
   if (details & GST_DEBUG_GRAPH_SHOW_STATES) {
-    gchar pad_flags[5];
+    gchar pad_flags[4];
     const gchar *activation_mode = "-><";
 
     /* check if pad flags */
-    pad_flags[0] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKED) ? 'B' : 'b';
-    pad_flags[1] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLUSHING) ? 'F' : 'f';
-    pad_flags[2] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_IN_GETCAPS) ? 'G' : 'g';
-    pad_flags[3] = GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_BLOCKING) ? 'B' : 'b';
-    pad_flags[4] = '\0';
+    pad_flags[0] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKED) ? 'B' : 'b';
+    pad_flags[1] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_FLUSHING) ? 'F' : 'f';
+    pad_flags[2] =
+        GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_BLOCKING) ? 'B' : 'b';
+    pad_flags[3] = '\0';
 
     fprintf (out,
         "%s  %s_%s [color=black, fillcolor=\"%s\", label=\"%s\\n[%c][%s]\", height=\"0.2\", style=\"%s\"];\n",
@@ -203,6 +207,9 @@ debug_dump_element_pad (GstPad * pad, GstElement * element,
     /* output target-pad so that it belongs to this element */
     if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
       if ((target_pad = gst_pad_get_peer (tmp_pad))) {
+        gchar *pad_name, *target_pad_name;
+        const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
+
         if ((target_element = gst_pad_get_parent_element (target_pad))) {
           target_element_name =
               debug_dump_make_object_name (GST_OBJECT (target_element));
@@ -211,10 +218,22 @@ debug_dump_element_pad (GstPad * pad, GstElement * element,
         }
         debug_dump_pad (target_pad, color_name, target_element_name, details,
             out, indent);
+        /* src ghostpad relationship */
+        pad_name = debug_dump_make_object_name (GST_OBJECT (pad));
+        target_pad_name = debug_dump_make_object_name (GST_OBJECT (target_pad));
+        if (dir == GST_PAD_SRC) {
+          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+              target_element_name, target_pad_name, element_name, pad_name);
+        } else {
+          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
+              element_name, pad_name, target_element_name, target_pad_name);
+        }
+        g_free (target_pad_name);
         g_free (target_element_name);
         if (target_element)
           gst_object_unref (target_element);
         gst_object_unref (target_pad);
+        g_free (pad_name);
       }
       gst_object_unref (tmp_pad);
     }
@@ -317,14 +336,13 @@ static void
 debug_dump_element_pad_link (GstPad * pad, GstElement * element,
     GstDebugGraphDetails details, FILE * out, const gint indent)
 {
-  GstElement *peer_element, *target_element;
-  GstPad *peer_pad, *target_pad, *tmp_pad;
+  GstElement *peer_element;
+  GstPad *peer_pad;
   GstCaps *caps, *peer_caps;
   gchar *media = NULL;
   gchar *media_src = NULL, *media_sink = NULL;
   gchar *pad_name, *element_name;
   gchar *peer_pad_name, *peer_element_name;
-  gchar *target_pad_name, *target_element_name;
   const gchar *spc = &spaces[MAX (sizeof (spaces) - (1 + indent * 2), 0)];
 
   if ((peer_pad = gst_pad_get_peer (pad))) {
@@ -333,10 +351,10 @@ debug_dump_element_pad_link (GstPad * pad, GstElement * element,
         ) {
       caps = gst_pad_get_current_caps (pad);
       if (!caps)
-        caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+        caps = gst_pad_get_pad_template_caps (pad);
       peer_caps = gst_pad_get_current_caps (peer_pad);
       if (!peer_caps)
-        peer_caps = gst_caps_copy (gst_pad_get_pad_template_caps (peer_pad));
+        peer_caps = gst_pad_get_pad_template_caps (peer_pad);
 
       media = debug_dump_describe_caps (caps, details);
       /* check if peer caps are different */
@@ -371,63 +389,6 @@ debug_dump_element_pad_link (GstPad * pad, GstElement * element,
       peer_element_name = g_strdup ("");
     }
 
-    if (GST_IS_GHOST_PAD (pad)) {
-      if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (pad)))) {
-        if ((target_pad = gst_pad_get_peer (tmp_pad))) {
-          target_pad_name =
-              debug_dump_make_object_name (GST_OBJECT (target_pad));
-          if ((target_element = gst_pad_get_parent_element (target_pad))) {
-            target_element_name =
-                debug_dump_make_object_name (GST_OBJECT (target_element));
-          } else {
-            target_element_name = g_strdup ("");
-          }
-          /* src ghostpad relationship */
-          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
-              target_element_name, target_pad_name, element_name, pad_name);
-
-          g_free (target_pad_name);
-          g_free (target_element_name);
-          if (target_element)
-            gst_object_unref (target_element);
-          gst_object_unref (target_pad);
-        }
-        gst_object_unref (tmp_pad);
-      }
-    }
-    if (GST_IS_GHOST_PAD (peer_pad)) {
-      if ((tmp_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (peer_pad)))) {
-        if ((target_pad = gst_pad_get_peer (tmp_pad))) {
-          target_pad_name =
-              debug_dump_make_object_name (GST_OBJECT (target_pad));
-          if ((target_element = gst_pad_get_parent_element (target_pad))) {
-            target_element_name =
-                debug_dump_make_object_name (GST_OBJECT (target_element));
-          } else {
-            target_element_name = g_strdup ("");
-          }
-          /* sink ghostpad relationship */
-          fprintf (out, "%s%s_%s -> %s_%s [style=dashed, minlen=0]\n", spc,
-              peer_element_name, peer_pad_name,
-              target_element_name, target_pad_name);
-          /* FIXME: we are missing links from the proxy pad
-           * theoretically we need to:
-           * pad=gst_object_ref(target_pad);
-           * goto line 280: if ((peer_pad = gst_pad_get_peer (pad)))
-           * as this would be ugly we need to refactor ...
-           */
-          debug_dump_element_pad_link (target_pad, target_element, details, out,
-              indent);
-          g_free (target_pad_name);
-          g_free (target_element_name);
-          if (target_element)
-            gst_object_unref (target_element);
-          gst_object_unref (target_pad);
-        }
-        gst_object_unref (tmp_pad);
-      }
-    }
-
     /* pad link */
     if (media) {
       fprintf (out, "%s%s_%s -> %s_%s [label=\"%s\"]\n", spc,
@@ -497,7 +458,7 @@ debug_dump_element_pads (GstIterator * pad_iter, GstPad * pad,
  * @out: file to write to
  * @indent: level of graph indentation
  *
- * Helper for _gst_debug_bin_to_dot_file() to recursively dump a pipeline.
+ * Helper for gst_debug_bin_to_dot_file() to recursively dump a pipeline.
  */
 static void
 debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
@@ -581,10 +542,22 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
             switch (gst_iterator_next (pad_iter, &item2)) {
               case GST_ITERATOR_OK:
                 pad = g_value_get_object (&item2);
-                if (gst_pad_is_linked (pad)
-                    && gst_pad_get_direction (pad) == GST_PAD_SRC) {
-                  debug_dump_element_pad_link (pad, element, details, out,
-                      indent);
+                if (gst_pad_is_linked (pad)) {
+                  if (gst_pad_get_direction (pad) == GST_PAD_SRC) {
+                    debug_dump_element_pad_link (pad, element, details, out,
+                        indent);
+                  } else {
+                    GstPad *peer_pad = gst_pad_get_peer (pad);
+
+                    if (peer_pad) {
+                      if (!GST_IS_GHOST_PAD (peer_pad)
+                          && GST_IS_PROXY_PAD (peer_pad)) {
+                        debug_dump_element_pad_link (peer_pad, NULL, details,
+                            out, indent);
+                      }
+                      gst_object_unref (peer_pad);
+                    }
+                  }
                 }
                 g_value_reset (&item2);
                 break;
@@ -611,12 +584,13 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
         break;
     }
   }
+
   g_value_unset (&item);
   gst_iterator_free (element_iter);
 }
 
 /*
- * _gst_debug_bin_to_dot_file:
+ * gst_debug_bin_to_dot_file:
  * @bin: the top-level pipeline that should be analyzed
  * @file_name: output base filename (e.g. "myplayer")
  *
@@ -628,7 +602,7 @@ debug_dump_element (GstBin * bin, GstDebugGraphDetails details, FILE * out,
  * </programlisting></informalexample>
  */
 void
-_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
   gchar *full_file_name = NULL;
@@ -693,16 +667,16 @@ _gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
 }
 
 /*
- * _gst_debug_bin_to_dot_file_with_ts:
+ * gst_debug_bin_to_dot_file_with_ts:
  * @bin: the top-level pipeline that should be analyzed
  * @file_name: output base filename (e.g. "myplayer")
  *
- * This works like _gst_debug_bin_to_dot_file(), but adds the current timestamp
+ * This works like gst_debug_bin_to_dot_file(), but adds the current timestamp
  * to the filename, so that it can be used to take multiple snapshots.
  */
 void
-_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
-    const gchar * file_name)
+gst_debug_bin_to_dot_file_with_ts (GstBin * bin,
+    GstDebugGraphDetails details, const gchar * file_name)
 {
   gchar *ts_file_name = NULL;
   GstClockTime elapsed;
@@ -725,19 +699,19 @@ _gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
       g_strdup_printf ("%u.%02u.%02u.%09u-%s", GST_TIME_ARGS (elapsed),
       file_name);
 
-  _gst_debug_bin_to_dot_file (bin, details, ts_file_name);
+  gst_debug_bin_to_dot_file (bin, details, ts_file_name);
   g_free (ts_file_name);
 }
 #else /* !GST_DISABLE_GST_DEBUG */
 #ifndef GST_REMOVE_DISABLED
 void
-_gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
 }
 
 void
-_gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
+gst_debug_bin_to_dot_file_with_ts (GstBin * bin, GstDebugGraphDetails details,
     const gchar * file_name)
 {
 }