[farsight2/master] Integrate transmitters into the FsRtpSession
Olivier Crête
olivier.crete at collabora.co.uk
Tue Dec 23 15:19:40 PST 2008
---
gst/fsrtpconference/fs-rtp-session.c | 172 +++++++++++++++++++++++++++++++++-
1 files changed, 170 insertions(+), 2 deletions(-)
diff --git a/gst/fsrtpconference/fs-rtp-session.c b/gst/fsrtpconference/fs-rtp-session.c
index fc8cd8d..fdb6d7d 100644
--- a/gst/fsrtpconference/fs-rtp-session.c
+++ b/gst/fsrtpconference/fs-rtp-session.c
@@ -35,10 +35,13 @@
#include <gst/gst.h>
+#include <gst/farsight/fs-transmitter.h>
+
#include "fs-rtp-session.h"
#include "fs-rtp-stream.h"
#include "fs-rtp-participant.h"
+
/* Signals */
enum
{
@@ -69,6 +72,8 @@ struct _FsRtpSessionPrivate
*/
FsRtpConference *conference;
+ GHashTable *transmitters;
+
/* We keep references to these elements
*/
@@ -133,6 +138,10 @@ static gboolean fs_rtp_session_set_send_codec (FsSession *session,
GError **error);
+static FsStreamTransmitter *fs_rtp_session_get_new_stream_transmitter (
+ FsRtpSession *self, gchar *transmitter_name, FsParticipant *participant,
+ guint n_parameters, GParameter *parameters, GError **error);
+
static GObjectClass *parent_class = NULL;
//static guint signals[LAST_SIGNAL] = { 0 };
@@ -217,6 +226,30 @@ fs_rtp_session_init (FsRtpSession *self)
self->priv = FS_RTP_SESSION_GET_PRIVATE (self);
self->priv->disposed = FALSE;
self->priv->construction_error = NULL;
+
+ self->priv->transmitters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+}
+
+static gboolean
+_remove_transmitter (gpointer key, gpointer value, gpointer user_data)
+{
+ FsRtpSession *self = FS_RTP_SESSION (user_data);
+ FsTransmitter *transmitter = FS_TRANSMITTER (value);
+ GstElement *src, *sink;
+
+ g_object_get (transmitter, "gst-sink", &sink, "gst-src", &src, NULL);
+
+ gst_bin_remove (GST_BIN (self->priv->conference), src);
+ gst_element_set_state (src, GST_STATE_NULL);
+
+ gst_bin_remove (GST_BIN (self->priv->conference), sink);
+ gst_element_set_state (sink, GST_STATE_NULL);
+
+ gst_object_unref (src);
+ gst_object_unref (sink);
+
+ return TRUE;
}
static void
@@ -283,6 +316,14 @@ fs_rtp_session_dispose (GObject *object)
self->priv->transmitter_rtcp_funnel = NULL;
}
+ if (self->priv->transmitters) {
+ g_hash_table_foreach_remove (self->priv->transmitters, _remove_transmitter,
+ self);
+
+ g_hash_table_destroy (self->priv->transmitters);
+ self->priv->transmitters = NULL;
+ }
+
/* MAKE sure dispose does not run twice. */
self->priv->disposed = TRUE;
@@ -573,12 +614,13 @@ fs_rtp_session_constructed (GObject *object)
static FsStream *
fs_rtp_session_new_stream (FsSession *session, FsParticipant *participant,
FsStreamDirection direction, gchar *transmitter,
- guint g_parameters, GParameter *parameters,
+ guint n_parameters, GParameter *parameters,
GError **error)
{
FsRtpSession *self = FS_RTP_SESSION (session);
FsRtpParticipant *rtpparticipant = NULL;
FsStream *new_stream = NULL;
+ FsStreamTransmitter *st;
if (!FS_IS_RTP_PARTICIPANT (participant)) {
g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
@@ -587,8 +629,14 @@ fs_rtp_session_new_stream (FsSession *session, FsParticipant *participant,
}
rtpparticipant = FS_RTP_PARTICIPANT (participant);
+ st = fs_rtp_session_get_new_stream_transmitter (self, transmitter,
+ participant, n_parameters, parameters, error);
+
+ if (!st)
+ return NULL;
+
new_stream = FS_STREAM_CAST (fs_rtp_stream_new (self, rtpparticipant,
- direction, NULL));
+ direction, st));
return new_stream;
}
@@ -749,3 +797,123 @@ fs_rtp_session_link_network_sink (FsRtpSession *session, GstPad *src_pad)
gst_object_unref (transmitter_rtcp_tee_sink_pad);
}
+
+static gboolean
+_get_request_pad_and_link (GstElement *tee_funnel, const gchar *tee_funnel_name,
+ GstElement *sinksrc, const gchar *sinksrc_padname, GstPadDirection direction,
+ GError **error)
+{
+ GstPad *requestpad = NULL;
+ GstPad *transpad = NULL;
+ GstPadLinkReturn ret;
+ gchar *requestpad_name = (direction == GST_PAD_SINK) ? "src%d" : "sink%d";
+
+ /* The transmitter will only be removed when the whole session is disposed,
+ * then the
+ */
+ requestpad = gst_element_get_request_pad (tee_funnel, requestpad_name);
+
+
+ if (!requestpad) {
+ g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+ "Can not get the %s pad from the transmitter %s element",
+ requestpad_name, tee_funnel_name);
+ goto error;
+ }
+
+ transpad = gst_element_get_static_pad (sinksrc, sinksrc_padname);
+
+ if (direction == GST_PAD_SINK)
+ ret = gst_pad_link (requestpad, transpad);
+ else
+ ret = gst_pad_link (transpad, requestpad);
+
+ gst_object_unref (transpad);
+
+ if (GST_PAD_LINK_FAILED(ret)) {
+ g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+ "Can not link the %s to the transmitter %s", tee_funnel_name,
+ (direction == GST_PAD_SINK) ? "sink" : "src");
+ goto error;
+ }
+
+ return TRUE;
+
+ error:
+ if (requestpad)
+ gst_element_release_request_pad (tee_funnel, requestpad);
+
+ return FALSE;
+}
+
+static FsStreamTransmitter *
+fs_rtp_session_get_new_stream_transmitter (FsRtpSession *self,
+ gchar *transmitter_name, FsParticipant *participant, guint n_parameters,
+ GParameter *parameters, GError **error)
+{
+ FsTransmitter *transmitter;
+ GstElement *src, *sink;
+
+ transmitter = g_hash_table_lookup (self->priv->transmitters,
+ transmitter_name);
+
+ if (transmitter) {
+ return fs_transmitter_new_stream_transmitter (transmitter, participant,
+ n_parameters, parameters, error);
+ }
+
+ transmitter = fs_transmitter_new (transmitter_name, 2, error);
+ if (!transmitter)
+ return NULL;
+
+ g_object_get (transmitter, "gst-sink", &sink, "gst-src", &src, NULL);
+
+ if(!gst_bin_add (GST_BIN (self->priv->conference), sink)) {
+ g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+ "Could not add the transmitter sink for %s to the conference",
+ transmitter_name);
+ goto error;
+ }
+
+ if(!gst_bin_add (GST_BIN (self->priv->conference), src)) {
+ g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
+ "Could not add the transmitter src for %s to the conference",
+ transmitter_name);
+ goto error;
+ }
+
+ if(!_get_request_pad_and_link (self->priv->transmitter_rtp_tee,
+ "rtp tee", sink, "sink1", GST_PAD_SINK, error))
+ goto error;
+
+ if(!_get_request_pad_and_link (self->priv->transmitter_rtcp_tee,
+ "rtcp tee", sink, "sink2", GST_PAD_SINK, error))
+ goto error;
+
+ if(!_get_request_pad_and_link (self->priv->transmitter_rtp_funnel,
+ "rtp funnel", src, "src1", GST_PAD_SRC, error))
+ goto error;
+
+ if(!_get_request_pad_and_link (self->priv->transmitter_rtcp_funnel,
+ "rtcp funnel", src, "src2", GST_PAD_SRC, error))
+ goto error;
+
+ g_hash_table_insert (self->priv->transmitters, g_strdup (transmitter_name),
+ transmitter);
+
+ gst_object_unref (src);
+ gst_object_unref (sink);
+
+ return fs_transmitter_new_stream_transmitter (transmitter, participant,
+ n_parameters, parameters, error);
+
+ error:
+ if (src)
+ gst_object_unref (src);
+ if (sink)
+ gst_object_unref (sink);
+ if (transmitter)
+ g_object_unref (transmitter);
+
+ return NULL;
+}
--
1.5.6.5
More information about the farsight-commits
mailing list