[farsight2/master] Add the substream to the stream, save the current codec inside the substream,

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


---
 gst/fsrtpconference/fs-rtp-session.c   |   59 ++++++++++++++----
 gst/fsrtpconference/fs-rtp-stream.c    |   42 ++++++++++++
 gst/fsrtpconference/fs-rtp-stream.h    |    5 +-
 gst/fsrtpconference/fs-rtp-substream.c |  110 +++++++++++++++++++++++++++++--
 gst/fsrtpconference/fs-rtp-substream.h |   12 +++-
 5 files changed, 204 insertions(+), 24 deletions(-)

diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index e6aa08a..0b77838 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -164,13 +164,20 @@ static gboolean fs_rtp_session_set_send_codec (FsSession *session,
 
 
 static FsStreamTransmitter *fs_rtp_session_get_new_stream_transmitter (
-    FsRtpSession *self, gchar *transmitter_name, FsParticipant *participant,
-    guint n_parameters, GParameter *parameters, GError **error);
+  FsRtpSession *self,
+  gchar *transmitter_name,
+  FsParticipant *participant,
+  guint n_parameters,
+  GParameter *parameters,
+  GError **error);
+
+static GstElement *
+fs_rtp_session_new_recv_codec_bin (FsRtpSession *session,
+  const gchar *name,
+  guint pt,
+  FsCodec **out_codec,
+  GError **error);
 
-static GstElement *fs_rtp_session_new_recv_codec_bin (FsRtpSession *session,
-    const gchar *name,
-    guint pt,
-    GError **error);
 
 static gboolean fs_rtp_session_add_send_codec_bin (FsRtpSession *session,
     GError **error);
@@ -1391,6 +1398,7 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
   GstElement *codecbin = NULL;
   gchar *codec_bin_name = NULL;
   GError *error = NULL;
+  FsCodec *codec = NULL;
 
   substream = fs_rtp_substream_new (session->priv->conference, session, new_pad,
     ssrc, pt, &error);
@@ -1410,11 +1418,11 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
 
   codec_bin_name = g_strdup_printf ("recv%d_%d", ssrc, pt);
   codecbin = fs_rtp_session_new_recv_codec_bin (session, codec_bin_name, pt,
-    &error);
+    &codec, &error);
   g_free (codec_bin_name);
 
   if (codecbin) {
-    if (!fs_rtp_sub_stream_add_codecbin (substream, codecbin, &error)) {
+    if (!fs_rtp_sub_stream_add_codecbin (substream, codecbin, codec, &error)) {
       if (error)
         fs_session_emit_error (FS_SESSION (session), error->code,
           "Could not add the codec bin to the new substream", error->message);
@@ -1443,6 +1451,10 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
 
   g_clear_error (&error);
 
+  fs_codec_destroy (codec);
+  codec = NULL;
+
+
   /* Lets find the FsRtpStream for this substream, if no Stream claims it
    * then we just store it
    */
@@ -1455,7 +1467,12 @@ fs_rtp_session_new_recv_pad (FsRtpSession *session, GstPad *new_pad,
       g_list_prepend (session->priv->free_substreams, substream);
   FS_RTP_SESSION_UNLOCK (session);
   if (stream) {
-    fs_rtp_stream_add_substream (stream, substream);
+    if (!fs_rtp_stream_add_substream (stream, substream, &error)) {
+      fs_session_emit_error (FS_SESSION (session), error->code,
+          "Could not add the output ghostpad to the new substream",
+          error->message);
+    }
+    g_clear_error (&error);
     g_object_unref (stream);
   }
 }
@@ -1648,9 +1665,26 @@ _create_codec_bin (CodecBlueprint *blueprint, FsCodec *codec, const gchar *name,
   return NULL;
 }
 
+/**
+ * fs_rtp_session_new_recv_codec_bin:
+ * @session: a #FsRtpSession
+ * @name: The name of the codec bin to create
+ * @pt: The payload type to create a codec bin for
+ * @out_codec: The address where a newly-allocated copy of the #FsCodec
+ *   this codec bin is for
+ * @error: the location where a #GError can be stored (or NULL)
+ *
+ * This function will create a new reception codec bin for the specified codec
+ *
+ * Returns: a newly-allocated codec bin
+ */
+
 static GstElement *
-fs_rtp_session_new_recv_codec_bin (FsRtpSession *session, const gchar *name,
-  guint pt, GError **error)
+fs_rtp_session_new_recv_codec_bin (FsRtpSession *session,
+  const gchar *name,
+  guint pt,
+  FsCodec **out_codec,
+  GError **error)
 {
   GstElement *codec_bin = NULL;
   CodecAssociation *ca = NULL;
@@ -1686,7 +1720,8 @@ fs_rtp_session_new_recv_codec_bin (FsRtpSession *session, const gchar *name,
 
   codec_bin = _create_codec_bin (blueprint, codec, name, FALSE, error);
 
-  fs_codec_destroy (codec);
+  if (out_codec)
+    *out_codec = codec;
 
   return codec_bin;
 }
diff --git a/gst/fsrtpconference/fs-rtp-stream.c b/gst/fsrtpconference/fs-rtp-stream.c
index 13ffb21..718c111 100644
--- a/gst/fsrtpconference/fs-rtp-stream.c
+++ b/gst/fsrtpconference/fs-rtp-stream.c
@@ -71,6 +71,8 @@ struct _FsRtpStreamPrivate
 
   GList *remote_codecs;
 
+  GList *substreams;
+
   GError *construction_error;
 
   gboolean disposed;
@@ -231,6 +233,12 @@ fs_rtp_stream_dispose (GObject *object)
     return;
   }
 
+  if (self->priv->substreams) {
+    g_list_foreach (self->priv->substreams, (GFunc) gst_object_unref, NULL);
+    g_list_free (self->priv->substreams);
+    self->priv->substreams = NULL;
+  }
+
   if (self->priv->participant) {
     g_object_unref (self->priv->participant);
     self->priv->participant = NULL;
@@ -528,3 +536,37 @@ fs_rtp_stream_transmitter_error (
 
   g_signal_emit_by_name (self, "error", 0, errorno, error_msg, debug_msg);
 }
+
+
+/**
+ * fs_rtp_stream_add_substream:
+ * @stream: a #FsRtpStream
+ * @substream: the #FsRtpSubStream to associate with this stream
+ *
+ * This functions associates a substream with this stream
+ */
+gboolean
+fs_rtp_stream_add_substream (FsRtpStream *stream,
+    FsRtpSubStream *substream,
+    GError **error)
+{
+  GstPad *ghostpad;
+  FsCodec *codec;
+
+  ghostpad = fs_rtp_sub_stream_get_output_ghostpad (substream, error);
+
+  if (!ghostpad)
+    return FALSE;
+
+  g_object_get (substream, "codec", &codec, NULL);
+
+  stream->priv->substreams = g_list_prepend (stream->priv->substreams,
+      substream);
+
+  g_signal_emit_by_name (stream, "src-pad-added", ghostpad, codec);
+
+  fs_codec_destroy (codec);
+  gst_object_unref (ghostpad);
+
+  return TRUE;
+}
diff --git a/gst/fsrtpconference/fs-rtp-stream.h b/gst/fsrtpconference/fs-rtp-stream.h
index 3ca8759..959594c 100644
--- a/gst/fsrtpconference/fs-rtp-stream.h
+++ b/gst/fsrtpconference/fs-rtp-stream.h
@@ -77,8 +77,9 @@ FsRtpStream *fs_rtp_stream_new (FsRtpSession *session,
                                 FsStreamTransmitter *stream_transmitter,
                                 GError **error);
 
-void fs_rtp_stream_add_substream (FsRtpStream *stream,
-  FsRtpSubStream *substream);
+gboolean fs_rtp_stream_add_substream (FsRtpStream *stream,
+    FsRtpSubStream *substream,
+    GError **error);
 
 G_END_DECLS
 
diff --git a/gst/fsrtpconference/fs-rtp-substream.c b/gst/fsrtpconference/fs-rtp-substream.c
index 6f4e4ff..80a5556 100644
--- a/gst/fsrtpconference/fs-rtp-substream.c
+++ b/gst/fsrtpconference/fs-rtp-substream.c
@@ -39,6 +39,7 @@ enum
   PROP_RTPBIN_PAD,
   PROP_SSRC,
   PROP_PT,
+  PROP_CODEC
 };
 
 struct _FsRtpSubStreamPrivate {
@@ -61,7 +62,9 @@ struct _FsRtpSubStreamPrivate {
   GstElement *codecbin;
 
   /* This is only created when the substream is associated with a FsRtpStream */
-  GstPad *output_pad;
+  GstPad *output_ghostpad;
+
+  FsCodec *codec;
 
   GMutex *mutex;
 
@@ -143,6 +146,14 @@ fs_rtp_sub_stream_class_init (FsRtpSubStreamClass *klass)
       0, 128, 0,
       G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class,
+    PROP_CODEC,
+    g_param_spec_boxed ("codec",
+      "The FsCodec this substream is received",
+      "The FsCodec currently received from this substream",
+      FS_TYPE_CODEC,
+      G_PARAM_READABLE));
+
   g_type_class_add_private (klass, sizeof (FsRtpSubStreamPrivate));
 }
 
@@ -209,10 +220,10 @@ fs_rtp_sub_stream_dispose (GObject *object)
   if (self->priv->disposed)
     return;
 
-  if (self->priv->output_pad) {
+  if (self->priv->output_ghostpad) {
     gst_element_remove_pad (GST_ELEMENT (self->priv->conference),
-      self->priv->output_pad);
-    self->priv->output_pad = NULL;
+      self->priv->output_ghostpad);
+    self->priv->output_ghostpad = NULL;
   }
 
   if (self->priv->valve) {
@@ -248,6 +259,9 @@ fs_rtp_sub_stream_finalize (GObject *object)
 {
   FsRtpSubStream *self = FS_RTP_SUB_STREAM (object);
 
+  if (self->priv->codec)
+    fs_codec_destroy (self->priv->codec);
+
   g_mutex_free (self->priv->mutex);
 
   G_OBJECT_CLASS (fs_rtp_sub_stream_parent_class)->finalize (object);
@@ -279,6 +293,9 @@ fs_rtp_sub_stream_set_property (GObject *object,
     case PROP_PT:
       self->priv->pt = g_value_get_uint (value);
       break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
 }
 
@@ -307,6 +324,14 @@ fs_rtp_sub_stream_get_property (GObject *object,
     case PROP_PT:
       g_value_set_uint (value, self->priv->pt);
       break;
+    case PROP_CODEC:
+      FS_RTP_SUB_STREAM_LOCK (self);
+      g_value_set_boxed (value, self->priv->codec);
+      FS_RTP_SUB_STREAM_UNLOCK (self);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
   }
 }
 
@@ -334,17 +359,23 @@ fs_rtp_sub_stream_block (FsRtpSubStream *substream,
 
 /**
  * fs_rtp_session_add_codecbin:
+ * @substream: a #FsRtpSubStream
  * @codecbin: The codec bin
+ * @codec: The #FsCodec currently received by this substream
  *
  * Add and links the rtpbin for a given substream.
- * Eats a reference to the codec bin on success
+ * Eats a reference to the codec bin on success.
+ *
+ * MT safe.
  *
  * Returns: TRUE on success
  */
 
 gboolean
 fs_rtp_sub_stream_add_codecbin (FsRtpSubStream *substream,
-  GstElement *codecbin, GError **error)
+    GstElement *codecbin,
+    FsCodec *codec,
+    GError **error)
 {
   GstPad *codec_bin_sink_pad;
   GstPadLinkReturn linkret;
@@ -353,6 +384,7 @@ fs_rtp_sub_stream_add_codecbin (FsRtpSubStream *substream,
   FS_RTP_SUB_STREAM_LOCK (substream);
   if (substream->priv->codecbin == NULL) {
     substream->priv->codecbin = codecbin;
+    substream->priv->codec = fs_codec_copy (codec);
     has_codecbin = TRUE;
   }
   FS_RTP_SUB_STREAM_UNLOCK (substream);
@@ -413,6 +445,8 @@ fs_rtp_sub_stream_add_codecbin (FsRtpSubStream *substream,
  error_no_remove:
     FS_RTP_SUB_STREAM_LOCK (substream);
     substream->priv->codecbin = NULL;
+    fs_codec_destroy (substream->priv->codec);
+    substream->priv->codec = NULL;
     FS_RTP_SUB_STREAM_UNLOCK (substream);
 
     return FALSE;
@@ -448,8 +482,8 @@ fs_rtp_sub_stream_new (FsRtpConference *conference,
 void
 fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
 {
-  if (substream->priv->output_pad)
-    gst_pad_set_active (substream->priv->output_pad, FALSE);
+  if (substream->priv->output_ghostpad)
+    gst_pad_set_active (substream->priv->output_ghostpad, FALSE);
 
   if (substream->priv->valve)
     gst_element_set_state (substream->priv->valve, GST_STATE_NULL);
@@ -457,3 +491,63 @@ fs_rtp_sub_stream_stop (FsRtpSubStream *substream)
   if (substream->priv->codecbin)
     gst_element_set_state (substream->priv->codecbin, GST_STATE_NULL);
 }
+
+
+/**
+ * fs_rtp_sub_stream_get_output_ghostpad:
+ *
+ * Creates, adds, and returns the output ghostpad for this substreams
+ *
+ * Returns: a #GstPad, must be unrefed when done
+ */
+
+GstPad *
+fs_rtp_sub_stream_get_output_ghostpad (FsRtpSubStream *substream,
+    GError **error)
+{
+  GstPad *codecbin_srcpad;
+  gchar *padname = NULL;
+  guint session_id;
+  GstPad *ghostpad = NULL;
+
+  if (substream->priv->output_ghostpad)
+    return gst_object_ref (substream->priv->output_ghostpad);
+
+  g_object_get (substream->priv->session, "id", &session_id, NULL);
+
+  padname = g_strdup_printf ("src_%d_%d_%d", session_id, substream->priv->ssrc,
+      substream->priv->pt);
+  codecbin_srcpad = gst_element_get_static_pad (substream->priv->codecbin,
+      "src");
+  g_assert (codecbin_srcpad);
+
+  ghostpad = gst_ghost_pad_new_from_template (padname, codecbin_srcpad,
+      gst_element_class_get_pad_template (
+          GST_ELEMENT_GET_CLASS (substream->priv->conference), "src_%d_%d_%d"));
+
+
+  gst_object_unref (codecbin_srcpad);
+  g_free (padname);
+
+  if (!ghostpad)
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could not build ghostpad src_%d_%d_%d", session_id,
+        substream->priv->ssrc, substream->priv->pt);
+    return NULL;
+  }
+
+  if (!gst_element_add_pad (GST_ELEMENT (substream->priv->conference),
+          ghostpad))
+  {
+    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+        "Could add build ghostpad src_%d_%d_%d to the conference",
+        session_id, substream->priv->ssrc, substream->priv->pt);
+    gst_object_unref (ghostpad);
+    return NULL;
+  }
+
+  substream->priv->output_ghostpad = ghostpad;
+
+  return gst_object_ref (ghostpad);
+}
diff --git a/gst/fsrtpconference/fs-rtp-substream.h b/gst/fsrtpconference/fs-rtp-substream.h
index 037c1e3..24f694e 100644
--- a/gst/fsrtpconference/fs-rtp-substream.h
+++ b/gst/fsrtpconference/fs-rtp-substream.h
@@ -80,12 +80,20 @@ FsRtpSubStream *fs_rtp_substream_new (FsRtpConference *conference,
 
 
 gboolean fs_rtp_sub_stream_add_codecbin (FsRtpSubStream *substream,
-  GstElement *codecbin, GError **error);
+    GstElement *codecbin,
+    FsCodec *codec,
+    GError **error);
 
 void fs_rtp_sub_stream_stop (FsRtpSubStream *substream);
 
 void fs_rtp_sub_stream_block (FsRtpSubStream *substream,
-  GstPadBlockCallback callback, gpointer user_data);
+    GstPadBlockCallback callback,
+    gpointer user_data);
+
+
+GstPad *fs_rtp_sub_stream_get_output_ghostpad (FsRtpSubStream *substream,
+    GError **error);
+
 
 G_END_DECLS
 
-- 
1.5.6.5




More information about the farsight-commits mailing list