Refactored *_new() functions.
authorEdward Hervey <bilboed@bilboed.com>
Thu, 31 Aug 2006 10:59:11 +0000 (10:59 +0000)
committerEdward Hervey <bilboed@bilboed.com>
Thu, 31 Aug 2006 10:59:11 +0000 (10:59 +0000)
Original commit message from CVS:
* docs/gst/gstreamer-sections.txt:
* gst/gstghostpad.c: (gst_proxy_pad_do_getcaps),
(gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked),
(gst_proxy_pad_dispose), (gst_ghost_pad_new_full),
(gst_ghost_pad_new_no_target), (gst_ghost_pad_new),
(gst_ghost_pad_new_from_template),
(gst_ghost_pad_new_no_target_from_template):
* gst/gstghostpad.h:
Refactored *_new() functions.
Templates are now used as a g_object_new() parameter.
Use template in _do_getcaps() if we don't have a target.
Small documentation cleanups.
Added two new constructors:
gst_ghost_pad_new_from_template()
gst_ghost_pad_new_no_target_from_template()
* tests/check/gst/gstghostpad.c: (GST_START_TEST),
(gst_ghost_pad_suite):
Added tests for new ghostpad instanciation functions.
API additions: gst_ghost_pad_new_from_template,
gst_ghost_pad_new_no_target_from_template

ChangeLog
docs/gst/gstreamer-sections.txt
gst/gstghostpad.c
gst/gstghostpad.h
tests/check/gst/gstghostpad.c

index f3f145b..ab90f2a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2006-08-31  Edward Hervey  <edward@fluendo.com>
+
+       * docs/gst/gstreamer-sections.txt:
+       * gst/gstghostpad.c: (gst_proxy_pad_do_getcaps),
+       (gst_proxy_pad_do_setcaps), (gst_proxy_pad_set_target_unlocked),
+       (gst_proxy_pad_dispose), (gst_ghost_pad_new_full),
+       (gst_ghost_pad_new_no_target), (gst_ghost_pad_new),
+       (gst_ghost_pad_new_from_template),
+       (gst_ghost_pad_new_no_target_from_template):
+       * gst/gstghostpad.h:
+       Refactored *_new() functions.
+       Templates are now used as a g_object_new() parameter.
+       Use template in _do_getcaps() if we don't have a target.
+       Small documentation cleanups.
+       Added two new constructors:
+       gst_ghost_pad_new_from_template()
+       gst_ghost_pad_new_no_target_from_template()
+       * tests/check/gst/gstghostpad.c: (GST_START_TEST),
+       (gst_ghost_pad_suite):
+       Added tests for new ghostpad instanciation functions.
+
+       API additions: gst_ghost_pad_new_from_template,
+       gst_ghost_pad_new_no_target_from_template
+
 2006-08-30  Stefan Kost,,,  <ensonic@users.sf.net>
 
        * docs/random/ensonic/profiling.txt:
index faf54b9..113df16 100644 (file)
@@ -714,6 +714,8 @@ gst_format_get_type
 GstGhostPad
 gst_ghost_pad_new
 gst_ghost_pad_new_no_target
+gst_ghost_pad_new_from_template
+gst_ghost_pad_new_no_target_from_template
 gst_ghost_pad_set_target
 gst_ghost_pad_get_target
 <SUBSECTION Standard>
@@ -723,6 +725,7 @@ GST_IS_GHOST_PAD
 GST_GHOST_PAD_CLASS
 GST_IS_GHOST_PAD_CLASS
 GST_TYPE_GHOST_PAD
+GST_GHOST_PAD_CAST
 <SUBSECTION Private>
 gst_ghost_pad_get_type
 </SECTION>
index 99876f7..f418128 100644 (file)
@@ -39,6 +39,8 @@
  * to create the ghost-pad and use gst_ghost_pad_set_target() to establish the
  * association later on.
  *
+ * Note that GhostPads add overhead to the data processing of a pipeline.
+ *
  * Last reviewed on 2005-11-18 (0.9.5)
  */
 
@@ -51,6 +53,8 @@
 #define GST_IS_PROXY_PAD_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PROXY_PAD))
 #define GST_PROXY_PAD(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROXY_PAD, GstProxyPad))
 #define GST_PROXY_PAD_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PROXY_PAD, GstProxyPadClass))
+#define GST_PROXY_PAD_CAST(obj)         ((GstProxyPad *)obj)
+
 #define GST_PROXY_PAD_TARGET(pad)       (GST_PROXY_PAD (pad)->target)
 #define GST_PROXY_PAD_INTERNAL(pad)     (GST_PROXY_PAD (pad)->internal)
 
@@ -233,11 +237,29 @@ gst_proxy_pad_do_getcaps (GstPad * pad)
   GstCaps *res;
 
   if (target) {
+    /* if we have a real target, proxy the call */
+    GST_DEBUG_OBJECT (pad, "get caps of target");
     res = gst_pad_get_caps (target);
     gst_object_unref (target);
   } else {
+    GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
+
+    /* else, if we have a template, use that */
+    if (templ) {
+      res = GST_PAD_TEMPLATE_CAPS (templ);
+      GST_DEBUG_OBJECT (pad,
+          "using pad template %p with caps %p %" GST_PTR_FORMAT, templ, res,
+          res);
+      res = gst_caps_ref (res);
+      goto done;
+    }
+
+    /* last resort, any caps */
+    GST_DEBUG_OBJECT (pad, "pad has no template, returning ANY");
     res = gst_caps_new_any ();
   }
+
+done:
   return res;
 }
 
@@ -276,10 +298,9 @@ gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
     res = gst_pad_set_caps (target, caps);
     gst_object_unref (target);
   } else {
-    /*
-       We don't have any target, but we shouldn't return FALSE since this
-       would stop the actual push of a buffer (which might trigger a pad block
-       or probe, or properly return GST_FLOW_NOT_LINKED.
+    /* We don't have any target, but we shouldn't return FALSE since this
+     * would stop the actual push of a buffer (which might trigger a pad block
+     * or probe, or properly return GST_FLOW_NOT_LINKED.
      */
     res = TRUE;
   }
@@ -293,11 +314,9 @@ gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
 
   if (target) {
     GST_LOG_OBJECT (pad, "setting target %s:%s", GST_DEBUG_PAD_NAME (target));
-    if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target))) {
-      GST_ERROR_OBJECT (pad,
-          "target pad doesn't have the same direction as ourself");
-      return FALSE;
-    }
+
+    if (G_UNLIKELY (GST_PAD_DIRECTION (pad) != GST_PAD_DIRECTION (target)))
+      goto wrong_direction;
   } else
     GST_LOG_OBJECT (pad, "clearing target");
 
@@ -312,6 +331,13 @@ gst_proxy_pad_set_target_unlocked (GstPad * pad, GstPad * target)
     GST_PROXY_PAD_TARGET (pad) = gst_object_ref (target);
 
   return TRUE;
+
+wrong_direction:
+  {
+    GST_ERROR_OBJECT (pad,
+        "target pad doesn't have the same direction as ourself");
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -364,9 +390,8 @@ gst_proxy_pad_dispose (GObject * object)
   /* remove and unref the target */
   target_p = &GST_PROXY_PAD_TARGET (pad);
   gst_object_replace ((GstObject **) target_p, NULL);
-  /*
-     The internal is only cleared by GstGhostPad::dispose, since it is the 
-     parent of non-ghost GstProxyPad and owns the refcount on the internal.
+  /* The internal is only cleared by GstGhostPad::dispose, since it is the 
+   * parent of non-ghost GstProxyPad and owns the refcount on the internal.
    */
   GST_PROXY_UNLOCK (pad);
 
@@ -757,30 +782,23 @@ gst_ghost_pad_dispose (GObject * object)
   G_OBJECT_CLASS (gst_ghost_pad_parent_class)->dispose (object);
 }
 
-/**
- * gst_ghost_pad_new_no_target:
- * @name: the name of the new pad, or NULL to assign a default name.
- * @dir: the direction of the ghostpad
- *
- * Create a new ghostpad without a target with the given direction.
- * A target can be set on the ghostpad later with the
- * gst_ghost_pad_set_target() function.
- *
- * The created ghostpad will not have a padtemplate.
- *
- * Returns: a new #GstPad, or NULL in case of an error.
- */
-GstPad *
-gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
+static GstPad *
+gst_ghost_pad_new_full (const gchar * name, GstPadDirection dir,
+    GstPadTemplate * templ)
 {
   GstPad *ret;
   GstPad *internal;
 
-  GST_LOG ("name:%s, direction:%d", name, dir);
+  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
 
   /* OBJECT CREATION */
-
-  ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name, "direction", dir, NULL);
+  if (templ) {
+    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
+        "direction", dir, "template", templ, NULL);
+  } else {
+    ret = g_object_new (GST_TYPE_GHOST_PAD, "name", name,
+        "direction", dir, NULL);
+  }
 
   /* Set directional padfunctions for ghostpad */
   if (dir == GST_PAD_SINK) {
@@ -837,7 +855,7 @@ gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
      This is why we don't take extra refcounts in the assignments below
    */
   GST_PROXY_PAD_INTERNAL (ret) = internal;
-  GST_PROXY_PAD_INTERNAL (GST_PROXY_PAD_INTERNAL (ret)) = GST_PAD (ret);
+  GST_PROXY_PAD_INTERNAL (internal) = GST_PAD (ret);
 
   /* could be more general here, iterating over all writable properties...
    * taking the short road for now tho */
@@ -856,6 +874,29 @@ beach:
 }
 
 /**
+ * gst_ghost_pad_new_no_target:
+ * @name: the name of the new pad, or NULL to assign a default name.
+ * @dir: the direction of the ghostpad
+ *
+ * Create a new ghostpad without a target with the given direction.
+ * A target can be set on the ghostpad later with the
+ * gst_ghost_pad_set_target() function.
+ *
+ * The created ghostpad will not have a padtemplate.
+ *
+ * Returns: a new #GstPad, or NULL in case of an error.
+ */
+GstPad *
+gst_ghost_pad_new_no_target (const gchar * name, GstPadDirection dir)
+{
+  g_return_val_if_fail (dir != GST_PAD_UNKNOWN, NULL);
+
+  GST_LOG ("name:%s, direction:%d", name, dir);
+
+  return gst_ghost_pad_new_full (name, dir, NULL);
+}
+
+/**
  * gst_ghost_pad_new:
  * @name: the name of the new pad, or NULL to assign a default name.
  * @target: the pad to ghost.
@@ -877,9 +918,85 @@ gst_ghost_pad_new (const gchar * name, GstPad * target)
   g_return_val_if_fail (GST_IS_PAD (target), NULL);
   g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
 
-  if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target)))) {
-    gst_ghost_pad_set_target (GST_GHOST_PAD (ret), target);
+  if ((ret = gst_ghost_pad_new_no_target (name, GST_PAD_DIRECTION (target))))
+    if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
+      goto set_target_failed;
+
+  return ret;
+
+  /* ERRORS */
+set_target_failed:
+  {
+    gst_object_unref (ret);
+    return NULL;
   }
+}
+
+/**
+ * gst_ghost_pad_new_from_template:
+ * @name: the name of the new pad, or NULL to assign a default name.
+ * @target: the pad to ghost.
+ * @templ: the #GstPadTemplate to use on the ghostpad.
+ *
+ * Create a new ghostpad with @target as the target. The direction will be taken
+ * from the target pad. The template used on the ghostpad will be @template.
+ *
+ * Will ref the target.
+ *
+ * Returns: a new #GstPad, or NULL in case of an error.
+ *
+ * Since: 0.10.10
+ */
+
+GstPad *
+gst_ghost_pad_new_from_template (const gchar * name, GstPad * target,
+    GstPadTemplate * templ)
+{
+  GstPad *ret;
+
+  g_return_val_if_fail (GST_IS_PAD (target), NULL);
+  g_return_val_if_fail (!gst_pad_is_linked (target), NULL);
+  g_return_val_if_fail (templ != NULL, NULL);
+  g_return_val_if_fail (templ->direction == GST_PAD_DIRECTION (target), NULL);
+
+  if ((ret = gst_ghost_pad_new_full (name, GST_PAD_DIRECTION (target), templ)))
+    if (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ret), target))
+      goto set_target_failed;
+
+  return ret;
+
+  /* ERRORS */
+set_target_failed:
+  {
+    gst_object_unref (ret);
+    return NULL;
+  }
+}
+
+/**
+ * gst_ghost_pad_new_no_target_from_template:
+ * @name: the name of the new pad, or NULL to assign a default name.
+ * @templ: the #GstPadTemplate to create the ghostpad from.
+ *
+ * Create a new ghostpad based on @templ, without setting a target. The
+ * direction will be taken from @templ.
+ *
+ * Returns: a new #GstPad, or NULL in case of an error.
+ *
+ * Since: 0.10.10
+ */
+
+GstPad *
+gst_ghost_pad_new_no_target_from_template (const gchar * name,
+    GstPadTemplate * templ)
+{
+  GstPad *ret;
+
+  g_return_val_if_fail (templ != NULL, NULL);
+
+  ret =
+      gst_ghost_pad_new_full (name, GST_PAD_TEMPLATE_DIRECTION (templ), templ);
+
   return ret;
 }
 
index 3e19f3a..dd9dd83 100644 (file)
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 #define GST_IS_GHOST_PAD_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
 #define GST_GHOST_PAD(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
 #define GST_GHOST_PAD_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
+#define GST_GHOST_PAD_CAST(obj)                ((GstGhostPad*)(obj))
 
 /**
  * GstGhostPad:
@@ -50,6 +51,9 @@ GType          gst_ghost_pad_get_type         (void);
 GstPad*                 gst_ghost_pad_new              (const gchar *name, GstPad *target);
 GstPad*                 gst_ghost_pad_new_no_target    (const gchar *name, GstPadDirection dir);
 
+GstPad*                 gst_ghost_pad_new_from_template (const gchar *name, GstPad * target, GstPadTemplate * templ);
+GstPad*                 gst_ghost_pad_new_no_target_from_template (const gchar *name, GstPadTemplate * templ);
+
 GstPad*                 gst_ghost_pad_get_target       (GstGhostPad *gpad);
 gboolean        gst_ghost_pad_set_target       (GstGhostPad *gpad, GstPad *newtarget);
 
index 793dd35..f9cc49f 100644 (file)
@@ -479,6 +479,84 @@ GST_START_TEST (test_ghost_pads_probes)
 
 GST_END_TEST;
 
+GST_START_TEST (test_ghost_pads_new_from_template)
+{
+  GstPad *sinkpad, *ghostpad;
+  GstPadTemplate *padtempl, *ghosttempl;
+  GstCaps *padcaps, *ghostcaps, *newcaps;
+
+  padcaps = gst_caps_from_string ("some/caps");
+  fail_unless (padcaps != NULL);
+  ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
+  fail_unless (ghostcaps != NULL);
+
+  padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
+      GST_PAD_ALWAYS, padcaps);
+  fail_unless (padtempl != NULL);
+  ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
+      GST_PAD_ALWAYS, ghostcaps);
+
+  sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
+  fail_unless (sinkpad != NULL);
+
+  ghostpad = gst_ghost_pad_new_from_template ("ghostpad", sinkpad, ghosttempl);
+  fail_unless (ghostpad != NULL);
+
+  /* check template is properly set */
+  fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
+
+  /* check ghostpad caps are from the sinkpad */
+  newcaps = gst_pad_get_caps (ghostpad);
+  fail_unless (newcaps != NULL);
+  fail_unless (gst_caps_is_equal (newcaps, padcaps));
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_ghost_pads_new_no_target_from_template)
+{
+  GstPad *sinkpad, *ghostpad;
+  GstPadTemplate *padtempl, *ghosttempl;
+  GstCaps *padcaps, *ghostcaps, *newcaps;
+
+  padcaps = gst_caps_from_string ("some/caps");
+  fail_unless (padcaps != NULL);
+  ghostcaps = gst_caps_from_string ("some/caps;some/other-caps");
+  fail_unless (ghostcaps != NULL);
+
+  padtempl = gst_pad_template_new ("padtempl", GST_PAD_SINK,
+      GST_PAD_ALWAYS, padcaps);
+  fail_unless (padtempl != NULL);
+  ghosttempl = gst_pad_template_new ("ghosttempl", GST_PAD_SINK,
+      GST_PAD_ALWAYS, ghostcaps);
+
+  sinkpad = gst_pad_new_from_template (padtempl, "sinkpad");
+  fail_unless (sinkpad != NULL);
+
+  ghostpad = gst_ghost_pad_new_no_target_from_template ("ghostpad", ghosttempl);
+  fail_unless (ghostpad != NULL);
+
+  /* check template is properly set */
+  fail_unless (GST_PAD_PAD_TEMPLATE (ghostpad) == ghosttempl);
+
+  /* check ghostpad caps are from the ghostpad template */
+  newcaps = gst_pad_get_caps (ghostpad);
+  fail_unless (newcaps != NULL);
+  fail_unless (gst_caps_is_equal (newcaps, ghostcaps));
+  gst_caps_unref (newcaps);
+
+  fail_unless (gst_ghost_pad_set_target ((GstGhostPad *) ghostpad, sinkpad));
+
+  /* check ghostpad caps are now from the target pad */
+  newcaps = gst_pad_get_caps (ghostpad);
+  fail_unless (newcaps != NULL);
+  fail_unless (gst_caps_is_equal (newcaps, padcaps));
+  gst_caps_unref (newcaps);
+
+}
+
+GST_END_TEST;
+
 Suite *
 gst_ghost_pad_suite (void)
 {
@@ -494,6 +572,8 @@ gst_ghost_pad_suite (void)
 /*  tcase_add_test (tc_chain, test_ghost_pad_notarget); */
   tcase_add_test (tc_chain, test_ghost_pads_block);
   tcase_add_test (tc_chain, test_ghost_pads_probes);
+  tcase_add_test (tc_chain, test_ghost_pads_new_from_template);
+  tcase_add_test (tc_chain, test_ghost_pads_new_no_target_from_template);
 
   return s;
 }