[farsight2/master] Link extra pads if they exist

Olivier Crête olivier.crete at collabora.co.uk
Tue Dec 23 15:25:43 PST 2008


---
 gst/fsrtpconference/fs-rtp-session.c |  233 +++++++++++++++++++++++++++++++++-
 1 files changed, 227 insertions(+), 6 deletions(-)

diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index fbb39ea..f1475ac 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -2844,6 +2844,185 @@ out:
   return ca;
 }
 
+struct link_data {
+  FsRtpSession *session;
+  GstCaps *caps;
+  GstElement *codecbin;
+  FsCodec *codec;
+
+  GList *all_codecs;
+
+  GError **error;
+};
+
+/*
+ * This is a  GstIteratorFoldFunction
+ * It returns FALSE when it wants to stop the iteration
+ */
+
+static gboolean
+link_main_pad (gpointer item, GValue *ret, gpointer user_data)
+{
+  GstPad *pad = item;
+  struct link_data *data = user_data;
+  GstCaps *caps, *intersect;
+  GstPad *other_pad;
+
+  caps = gst_pad_get_caps (pad);
+  intersect = gst_caps_intersect (caps, data->caps);
+  gst_caps_unref (caps);
+
+  if (gst_caps_is_empty (intersect))
+  {
+    gst_caps_unref (intersect);
+    gst_object_unref (pad);
+    return TRUE;
+  }
+  gst_caps_unref (intersect);
+
+  other_pad = gst_element_get_static_pad (data->session->priv->send_capsfilter,
+      "sink");
+
+  if (!other_pad)
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not get the sink pad of the send capsfilter");
+    goto error;
+  }
+
+  if (GST_PAD_LINK_SUCCESSFUL(gst_pad_link (pad, other_pad)))
+    g_value_set_boolean (ret, TRUE);
+  else
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not link the send codec bin for pt %d to the send capsfilter",
+        data->codec->id);
+
+ error:
+
+  gst_object_unref (other_pad);
+  gst_object_unref (pad);
+
+  return FALSE;
+}
+
+
+/*
+ * This is a  GstIteratorFoldFunction
+ * It returns FALSE when it wants to stop the iteration
+ */
+
+static gboolean
+link_other_pads (gpointer item, GValue *ret, gpointer user_data)
+{
+  GstPad *pad = item;
+  struct link_data *data = user_data;
+  GstCaps *caps;
+  GstCaps *filter_caps;
+  GList *listitem;
+  GstElement *capsfilter;
+  GstPad *otherpad;
+
+  if (gst_pad_is_linked (pad))
+  {
+    gst_object_unref (pad);
+    return TRUE;
+  }
+
+  caps = gst_pad_get_caps (pad);
+
+  if (gst_caps_is_empty (caps))
+  {
+    GST_WARNING_OBJECT (pad, "Caps on pad are empty");
+    return TRUE;
+  }
+
+  for (listitem = data->all_codecs; listitem; listitem = g_list_next (listitem))
+  {
+    FsCodec *codec = listitem->data;
+    GstCaps *intersect;
+
+    filter_caps = fs_codec_to_gst_caps (codec);
+    intersect = gst_caps_intersect (filter_caps, caps);
+
+    if (!gst_caps_is_empty (intersect))
+    {
+      GST_LOG_OBJECT (pad, "Pad matches " FS_CODEC_FORMAT,
+          FS_CODEC_ARGS (codec));
+      gst_caps_unref (intersect);
+      break;
+    }
+    gst_caps_unref (filter_caps);
+    gst_caps_unref (intersect);
+  }
+
+  gst_caps_unref (caps);
+
+  if (!listitem)
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_INTERNAL,
+        "Could not find codec that matches the src pad");
+    g_value_set_boolean (ret, FALSE);
+    gst_object_unref (pad);
+    return FALSE;
+  }
+
+  capsfilter = gst_element_factory_make ("capsfilter", NULL);
+  g_object_set (capsfilter, "caps", filter_caps, NULL);
+  gst_caps_unref (filter_caps);
+
+  if (!gst_bin_add (GST_BIN (data->session->priv->conference), capsfilter))
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not add send capsfilter to the conference");
+    gst_object_unref (capsfilter);
+    goto error;
+  }
+
+  data->session->priv->extra_send_capsfilters =
+    g_list_append (data->session->priv->extra_send_capsfilters,
+        capsfilter);
+
+  otherpad = gst_element_get_static_pad (capsfilter, "sink");
+
+  if (!otherpad)
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not get sink pad on capsfilter");
+    goto error;
+  }
+
+  if (GST_PAD_LINK_FAILED (gst_pad_link (pad, otherpad)))
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not get sink pad on capsfilter");
+    gst_object_unref (otherpad);
+    goto error;
+  }
+  gst_object_unref (otherpad);
+  gst_object_unref (pad);
+  pad = NULL;
+
+  if (!gst_element_link (capsfilter, data->session->priv->rtpmuxer))
+  {
+    g_set_error (data->error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not an extra capsfilter to the muxer");
+    g_value_set_boolean (ret, FALSE);
+    return FALSE;
+  }
+
+  return TRUE;
+
+ error:
+
+  g_value_set_boolean (ret, FALSE);
+  gst_bin_remove (GST_BIN (data->session->priv->conference), capsfilter);
+  data->session->priv->extra_send_capsfilters =
+    g_list_remove (data->session->priv->extra_send_capsfilters,
+        capsfilter);
+  gst_object_unref (pad);
+
+  return FALSE;
+}
 
 /**
  * fs_rtp_session_add_send_codec_bin:
@@ -2869,6 +3048,9 @@ fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
   gchar *name;
   GstCaps *sendcaps;
   GList *codecs;
+  GstIterator *iter;
+  GValue link_rv = {0};
+  struct link_data data;
 
   GST_DEBUG ("Trying to add send codecbin for " FS_CODEC_FORMAT,
       FS_CODEC_ARGS (codec));
@@ -2877,11 +3059,11 @@ fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
   codecs = codec_associations_to_codecs (session->priv->codec_associations,
       FALSE);
   codecbin = _create_codec_bin (ca, codec, name, TRUE, codecs, error);
-  fs_codec_list_destroy (codecs);
   g_free (name);
 
   if (!codecbin)
   {
+    fs_codec_list_destroy (codecs);
     return NULL;
   }
 
@@ -2891,16 +3073,17 @@ fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
         "Could not add the send codec bin for pt %d to the pipeline",
         codec->id);
     gst_object_unref (codecbin);
+    fs_codec_list_destroy (codecs);
     return NULL;
   }
 
-
   if (!gst_element_link_pads (session->priv->media_sink_valve, "src",
           codecbin, "sink"))
   {
     g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
         "Could not get the valve sink for the send codec bin");
     gst_bin_remove (GST_BIN (session->priv->conference), (codecbin));
+    fs_codec_list_destroy (codecs);
     return NULL;
   }
 
@@ -2909,17 +3092,52 @@ fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
   g_object_set (G_OBJECT (session->priv->send_capsfilter),
       "caps", sendcaps, NULL);
 
+  iter = gst_element_iterate_src_pads (codecbin);
+
+  g_value_init (&link_rv, G_TYPE_BOOLEAN);
+  g_value_set_boolean (&link_rv, FALSE);
+
+  data.session = session;
+  data.codecbin = codecbin;
+  data.caps = sendcaps;
+  data.error = NULL;
+  data.all_codecs = codecs;
+
+  if (gst_iterator_fold (iter, link_main_pad, &link_rv, &data) ==
+      GST_ITERATOR_ERROR)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not iterate over the src pads of the send codec bin to link"
+        " the main pad for pt %d", codec->id);
+    goto error;
+  }
+
   gst_caps_unref (sendcaps);
 
-  if (!gst_element_link_pads (codecbin, "src",
-          session->priv->send_capsfilter, "sink"))
+  if (!g_value_get_boolean (&link_rv))
+  {
+    gst_iterator_free (iter);
+    goto error;
+  }
+
+  gst_iterator_resync (iter);
+
+  if (gst_iterator_fold (iter, link_other_pads, &link_rv, &data) ==
+      GST_ITERATOR_ERROR)
   {
     g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
-        "Could not link the send codec bin for pt %d to the send capsfilter",
-        codec->id);
+        "Could not iterate over the src pads of the send codec bin to link"
+        " the main pad for pt %d", codec->id);
+    gst_iterator_free (iter);
     goto error;
   }
 
+  gst_iterator_free (iter);
+
+  if (!g_value_get_boolean (&link_rv))
+    goto error;
+
+
   if (!gst_element_sync_state_with_parent (codecbin))
   {
     g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
@@ -2935,11 +3153,14 @@ fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
 
   fs_rtp_session_send_codec_changed (session);
 
+  fs_codec_list_destroy (codecs);
+
   return codecbin;
 
  error:
   gst_element_set_state (codecbin, GST_STATE_NULL);
   gst_bin_remove (GST_BIN (session->priv->conference), codecbin);
+  fs_codec_list_destroy (codecs);
   return NULL;
 }
 
-- 
1.5.6.5




More information about the farsight-commits mailing list