[farsight2/master] Add the FsRtpSubStream struct, use it to implement session_new_recv_pad

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


---
 gst/fsrtpconference/fs-rtp-session.c |  170 +++++++++++++++++++++++++++++++++-
 gst/fsrtpconference/fs-rtp-session.h |    4 +
 gst/fsrtpconference/fs-rtp-stream.h  |    3 +
 3 files changed, 176 insertions(+), 1 deletions(-)

diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index c97aaa6..529c7cd 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -98,8 +98,9 @@ struct _FsRtpSessionPrivate
 
   GError *construction_error;
 
-  /* This list is protected by the session mutex */
+  /* These lists are protected by the session mutex */
   GList *streams;
+  GList *free_substreams;
 
   GMutex *mutex;
 
@@ -150,6 +151,10 @@ static FsStreamTransmitter *fs_rtp_session_get_new_stream_transmitter (
     FsRtpSession *self, gchar *transmitter_name, FsParticipant *participant,
     guint n_parameters, GParameter *parameters, GError **error);
 
+static FsRtpSubStream *fs_rtp_session_new_substream (FsRtpSession *self,
+  GstPad *pad, guint32 ssrc, guint pt);
+
+
 static GObjectClass *parent_class = NULL;
 
 //static guint signals[LAST_SIGNAL] = { 0 };
@@ -1007,3 +1012,166 @@ fs_rtp_session_get_new_stream_transmitter (FsRtpSession *self,
 
   return NULL;
 }
+
+
+/**
+ * fs_rtp_session_get_stream_by_ssrc_locked
+ * @self: The #FsRtpSession
+ * @stream_ssrc: The stream ssrc
+ *
+ * Gets the #FsRtpStream from a list of streams or NULL if it doesnt exist
+ * You have to hold the GST_OBJECT_LOCK to call this function.
+ *
+ * Return value: A #FsRtpStream (unref after use) or NULL if it doesn't exist
+ */
+static FsRtpStream *
+fs_rtp_session_get_stream_by_ssrc_locked (FsRtpSession *self,
+                                            guint stream_ssrc)
+{
+  GList *item = NULL;
+
+  for (item = g_list_first (self->priv->streams);
+       item;
+       item = g_list_next (item)) {
+    FsRtpStream *stream = item->data;
+    guint ssrc = 0;
+
+    g_object_get (stream, "id", &ssrc, NULL);
+
+    if (ssrc == stream_ssrc) {
+      g_object_ref(stream);
+      break;
+    }
+  }
+
+  if (item)
+    return FS_RTP_STREAM (item->data);
+  else
+    return NULL;
+}
+
+
+/**
+ * fs_rtp_session_new_recv_pad:
+ * @session: a #FsSession
+ * @new_pad: the newly created pad
+ * @ssrc: the ssrc for this new pad
+ * @pt: the pt for this new pad
+ *
+ * This function is called by the #FsRtpConference when a new src pad appears.
+ * It can will be called on the streaming thread.
+ */
+
+void
+fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
+  guint32 ssrc, guint pt)
+{
+  FsRtpSubStream *substream = NULL;
+  FsRtpStream *stream = NULL;
+
+  substream = fs_rtp_session_new_substream (session, new_pad,
+    ssrc, pt);
+
+  if (substream == NULL)
+    return;
+
+
+  /* Lets find the FsRtpStream for this substream, if no Stream claims it
+   * then we just store it
+   */
+
+  FS_SESSION_LOCK (session);
+  stream = fs_rtp_session_get_stream_by_ssrc_locked (session, ssrc);
+
+  if (!stream)
+    session->priv->free_substreams =
+      g_list_prepend (session->priv->free_substreams, substream);
+  FS_SESSION_UNLOCK (session);
+  if (stream) {
+    fs_rtp_stream_add_substream (stream, substream);
+    g_object_unref (stream);
+  }
+}
+
+
+struct _FsRtpSubStream {
+  guint32 ssrc;
+  guint pt;
+
+  GstPad *rtpbin_pad;
+
+  GstElement *valve;
+
+  /* This only exists if the codec is valid,
+   * otherwise the rtpbin_pad is blocked */
+  GstElement *codecbin;
+
+  /* This is only created when the substream is associated with a FsRtpStream */
+  GstPad *output_pad;
+};
+
+
+/**
+ * fs_rtp_session_add_codecbin:
+ *
+ * Creates, add, links the rtpbin for a given substream.
+ * It will block the substream if there is no known info on the PT.
+ */
+
+static void
+fs_rtp_session_add_codecbin (FsRtpSession *self, FsRtpSubStream *substream)
+{
+}
+
+static FsRtpSubStream *
+fs_rtp_session_new_substream (FsRtpSession *self, GstPad *pad,
+  guint32 ssrc, guint pt)
+{
+  FsRtpSubStream *substream = g_new0 (FsRtpSubStream, 1);
+
+  substream->ssrc = ssrc;
+  substream->pt = pt;
+  substream->rtpbin_pad = pad;
+
+  substream->valve = gst_element_factory_make ("fsvalve", NULL);
+
+  if (!substream->valve) {
+    gchar *str = g_strdup_printf ("Could not create a fsvalve element for"
+      " session substream with ssrc: %x and pt:%d", ssrc, pt);
+    fs_session_emit_error (FS_SESSION (self), FS_ERROR_CONSTRUCTION,
+      "Could not create required fsvalve element for reception", str);
+    g_free (str);
+    goto error;
+  }
+
+  if (!gst_bin_add (GST_BIN (self->priv->conference), substream->valve)) {
+    gchar *str = g_strdup_printf ("Could not add the fsvalve element for"
+      " session substream with ssrc: %x and pt:%d to the conference bin",
+      ssrc, pt);
+    fs_session_emit_error (FS_SESSION (self), FS_ERROR_CONSTRUCTION,
+      "Could not add the required fsvalve element for reception", str);
+    g_free (str);
+    goto error;
+  }
+
+  /* We set the valve to dropping, the stream will unblock it when its linked */
+  g_object_set (substream->valve, "drop", TRUE, NULL);
+
+  if (gst_element_set_state (substream->valve, GST_STATE_PLAYING) ==
+    GST_STATE_CHANGE_FAILURE) {
+    gchar *str = g_strdup_printf ("Could not set the fsvalve element for"
+      " session substream with ssrc: %x and pt:%d to the playing state",
+      ssrc, pt);
+    fs_session_emit_error (FS_SESSION (self), FS_ERROR_CONSTRUCTION,
+      "Could not set the required fsvalve element to playing", str);
+    g_free (str);
+    goto error;
+  }
+
+  fs_rtp_session_add_codecbin (self, substream);
+
+  return substream;
+ error:
+  g_free (substream);
+  return NULL;
+}
diff --git a/gst/fsrtpconference/fs-rtp-session.h b/gst/fsrtpconference/fs-rtp-session.h
index 539cfa1..01f5e68 100644
--- a/gst/fsrtpconference/fs-rtp-session.h
+++ b/gst/fsrtpconference/fs-rtp-session.h
@@ -72,6 +72,10 @@ struct _FsRtpSession
   FsRtpSessionPrivate *priv;
 };
 
+/* All members are private */
+typedef struct _FsRtpSubStream FsRtpSubStream;
+
+
 GType fs_rtp_session_get_type (void);
 
 FsRtpSession *fs_rtp_session_new (FsMediaType media_type,
diff --git a/gst/fsrtpconference/fs-rtp-stream.h b/gst/fsrtpconference/fs-rtp-stream.h
index d40f39a..e9cffe6 100644
--- a/gst/fsrtpconference/fs-rtp-stream.h
+++ b/gst/fsrtpconference/fs-rtp-stream.h
@@ -76,6 +76,9 @@ FsRtpStream *fs_rtp_stream_new (FsRtpSession *session,
                                 FsStreamTransmitter *stream_transmitter,
                                 GError **error);
 
+void fs_rtp_stream_add_substream (FsRtpStream *stream,
+  FsRtpSubStream *substream);
+
 G_END_DECLS
 
 #endif /* __FS_RTP_STREAM_H__ */
-- 
1.5.6.5




More information about the farsight-commits mailing list