[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