summaryrefslogtreecommitdiff
path: root/rakia/media-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'rakia/media-stream.c')
-rw-r--r--rakia/media-stream.c286
1 files changed, 134 insertions, 152 deletions
diff --git a/rakia/media-stream.c b/rakia/media-stream.c
index 002c265..a8cbf2c 100644
--- a/rakia/media-stream.c
+++ b/rakia/media-stream.c
@@ -135,8 +135,6 @@ struct _RakiaMediaStreamPrivate
gboolean hold_state; /* see gobj. prop. 'hold-state' */
gboolean created_locally; /* see gobj. prop. 'created-locally' */
- gchar *stream_sdp; /* SDP description of the stream */
-
GValue native_codecs; /* intersected codec list */
GValue native_candidates;
@@ -168,8 +166,10 @@ static void push_remote_candidates (RakiaMediaStream *stream);
static void push_active_candidate_pair (RakiaMediaStream *stream);
static void priv_update_sending (RakiaMediaStream *stream,
TpMediaStreamDirection direction);
-static void priv_update_local_sdp(RakiaMediaStream *stream);
-static void priv_generate_sdp (RakiaMediaStream *stream);
+static void priv_emit_local_ready (RakiaMediaStream *stream);
+static const char *priv_get_preferred_native_candidate (
+ RakiaMediaStreamPrivate *priv,
+ const GPtrArray **transports);
/***********************************************************************
* Set: Gobject interface
@@ -178,15 +178,11 @@ static void priv_generate_sdp (RakiaMediaStream *stream);
static void
rakia_media_stream_init (RakiaMediaStream *self)
{
- RakiaMediaStreamPrivate *priv =
- G_TYPE_INSTANCE_GET_PRIVATE ((self),
- RAKIA_TYPE_MEDIA_STREAM, RakiaMediaStreamPrivate);
+ RakiaMediaStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE ((self),
+ RAKIA_TYPE_MEDIA_STREAM, RakiaMediaStreamPrivate);
self->priv = priv;
- priv->playing = FALSE;
- priv->sending = FALSE;
-
g_value_init (&priv->native_codecs, TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST);
g_value_take_boxed (&priv->native_codecs,
dbus_g_type_specialized_construct (TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST));
@@ -194,12 +190,6 @@ rakia_media_stream_init (RakiaMediaStream *self)
g_value_init (&priv->native_candidates, TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST);
g_value_take_boxed (&priv->native_candidates,
dbus_g_type_specialized_construct (TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST));
-
- priv->native_cands_prepared = FALSE;
- priv->native_codecs_prepared = FALSE;
-
- priv->push_remote_cands_pending = FALSE;
- priv->push_remote_codecs_pending = FALSE;
}
static void
@@ -552,7 +542,6 @@ rakia_media_stream_finalize (GObject *object)
/* free any data held directly by the object here */
g_free (priv->object_path);
- g_free (priv->stream_sdp);
g_value_unset (&priv->native_codecs);
g_value_unset (&priv->native_candidates);
@@ -607,7 +596,6 @@ rakia_media_stream_error (TpSvcMediaStreamHandler *iface,
STREAM_DEBUG (self, "StreamHandler.Error called: %u %s", errno, message);
-
rakia_media_stream_close (self);
tp_svc_media_stream_handler_return_from_error (context);
@@ -637,7 +625,7 @@ rakia_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface,
priv->native_cands_prepared = TRUE;
if (priv->native_codecs_prepared)
- priv_generate_sdp (obj);
+ priv_emit_local_ready (obj);
push_active_candidate_pair (obj);
@@ -653,9 +641,9 @@ rakia_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface,
*/
static void
rakia_media_stream_new_active_candidate_pair (TpSvcMediaStreamHandler *iface,
- const gchar *native_candidate_id,
- const gchar *remote_candidate_id,
- DBusGMethodInvocation *context)
+ const gchar *native_candidate_id,
+ const gchar *remote_candidate_id,
+ DBusGMethodInvocation *context)
{
RakiaMediaStream *self = RAKIA_MEDIA_STREAM (iface);
RakiaMediaStreamPrivate *priv = self->priv;
@@ -701,13 +689,6 @@ rakia_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface,
priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (obj);
- if (priv->stream_sdp != NULL)
- {
- MESSAGE ("Stream %u: SDP already generated, ignoring native candidate '%s'", priv->id, candidate_id);
- tp_svc_media_stream_handler_return_from_new_native_candidate (context);
- return;
- }
-
g_return_if_fail (transports->len >= 1);
/* Rate the preferability of the address */
@@ -752,17 +733,14 @@ priv_set_local_codecs (RakiaMediaStream *self,
const GPtrArray *codecs)
{
RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- GValue val = { 0, };
STREAM_DEBUG(self, "putting list of %d locally supported codecs into cache",
codecs->len);
- g_value_init (&val, TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST);
- g_value_set_static_boxed (&val, codecs);
- g_value_copy (&val, &priv->native_codecs);
+ g_value_set_boxed (&priv->native_codecs, codecs);
priv->native_codecs_prepared = TRUE;
if (priv->native_cands_prepared)
- priv_generate_sdp (self);
+ priv_emit_local_ready (self);
}
static void
@@ -786,19 +764,12 @@ rakia_media_stream_codecs_updated (TpSvcMediaStreamHandler *iface,
}
else
{
- GValue val = { 0, };
-
STREAM_DEBUG (self, "putting list of %d locally supported "
"codecs from CodecsUpdated into cache", codecs->len);
- g_value_init (&val, TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST);
- g_value_set_static_boxed (&val, codecs);
- g_value_copy (&val, &priv->native_codecs);
+ g_value_set_boxed (&priv->native_codecs, codecs);
- /* This doesn't use priv_generate_sdp because it short-circuits if
- * priv->stream_sdp is already set. We want to update it.
- */
if (priv->native_cands_prepared)
- priv_update_local_sdp (self);
+ g_signal_emit (self, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
tp_svc_media_stream_handler_return_from_codecs_updated (context);
}
@@ -848,10 +819,6 @@ rakia_media_stream_ready (TpSvcMediaStreamHandler *iface,
tp_svc_media_stream_handler_emit_set_stream_sending (
iface, priv->sending);
- priv->native_codecs_prepared = TRUE;
- if (priv->native_cands_prepared)
- priv_generate_sdp (obj);
-
if (priv->push_remote_cands_pending)
{
priv->push_remote_cands_pending = FALSE;
@@ -938,10 +905,10 @@ rakia_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface,
"got codec intersection containing %u codecs from stream-engine",
codecs->len);
- /* Uncomment the line below if there's need to limit the local codec list
- * with the intersection for later SDP negotiations.
- * TODO: Make sure to update the SDP for the stream as well. */
- /* g_value_set_boxed (&priv->native_codecs, codecs); */
+ /* Save the local codecs, but avoid triggering a new
+ * session update at this point. If the stream engine have changed any codec
+ * parameters, it is supposed to follow up with CodecsUpdated. */
+ g_value_set_boxed (&priv->native_codecs, codecs);
if (priv->codec_intersect_pending)
{
@@ -1009,17 +976,6 @@ rakia_media_stream_close (RakiaMediaStream *self)
tp_svc_media_stream_handler_emit_close (self);
}
-/**
- * Described the local stream configuration in SDP (RFC2327),
- * or NULL if stream not configured yet.
- */
-const char *rakia_media_stream_local_sdp (RakiaMediaStream *obj)
-{
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (obj);
- return priv->stream_sdp;
-}
-
TpMediaStreamDirection
rakia_media_stream_direction_from_remote_media (const sdp_media_t *media)
{
@@ -1342,7 +1298,7 @@ rakia_media_stream_set_direction (RakiaMediaStream *stream,
&& priv->native_codecs_prepared
&& priv_get_requested_direction (priv)
!= old_sdp_direction)
- priv_update_local_sdp (stream);
+ g_signal_emit (stream, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
}
/*
@@ -1401,10 +1357,9 @@ rakia_media_stream_get_requested_direction (RakiaMediaStream *self)
*/
gboolean rakia_media_stream_is_local_ready (RakiaMediaStream *self)
{
- RakiaMediaStreamPrivate *priv;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
- g_assert (priv->stream_sdp == NULL || priv->ready_received);
- return (priv->stream_sdp != NULL);
+ RakiaMediaStreamPrivate *priv = self->priv;
+ return (priv->ready_received && priv->native_cands_prepared
+ && priv->native_codecs_prepared);
}
gboolean
@@ -1443,17 +1398,10 @@ rakia_media_stream_request_hold_state (RakiaMediaStream *self, gboolean hold)
}
static void
-priv_generate_sdp (RakiaMediaStream *self)
+priv_emit_local_ready (RakiaMediaStream *self)
{
- RakiaMediaStreamPrivate *priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (self);
-
- if (priv->stream_sdp != NULL)
- return;
-
- priv_update_local_sdp (self);
-
- g_assert (priv->stream_sdp != NULL);
-
+ /* Trigger any session updates that are due in the current session state */
+ g_signal_emit (self, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
g_signal_emit (self, signals[SIG_READY], 0);
}
@@ -1720,20 +1668,18 @@ static void push_remote_candidates (RakiaMediaStream *stream)
static void
push_active_candidate_pair (RakiaMediaStream *stream)
{
- RakiaMediaStreamPrivate *priv;
-
- DEBUG("enter");
-
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
+ RakiaMediaStreamPrivate *priv = stream->priv;
- if (priv->ready_received
- && priv->native_candidate_id != NULL
+ if (priv->ready_received && priv->native_cands_prepared
&& priv->remote_candidate_id != NULL)
{
+ const char *native_candidate_id;
+
+ native_candidate_id = priv_get_preferred_native_candidate (priv, NULL);
STREAM_DEBUG (stream, "emitting SetActiveCandidatePair for %s-%s",
- priv->native_candidate_id, priv->remote_candidate_id);
- tp_svc_media_stream_handler_emit_set_active_candidate_pair (
- stream, priv->native_candidate_id, priv->remote_candidate_id);
+ native_candidate_id, priv->remote_candidate_id);
+ tp_svc_media_stream_handler_emit_set_active_candidate_pair (stream,
+ native_candidate_id, priv->remote_candidate_id);
}
}
@@ -1815,31 +1761,16 @@ priv_append_rtpmaps (const GPtrArray *codecs, GString *mline, GString *alines)
* Refreshes the local SDP based on Farsight stream, and current
* object, state.
*/
-static void
-priv_update_local_sdp(RakiaMediaStream *stream)
+static const char *
+priv_get_preferred_native_candidate (RakiaMediaStreamPrivate *priv,
+ const GPtrArray **transports)
{
- RakiaMediaStreamPrivate *priv;
- GString *mline;
- GString *alines;
- gchar *cline;
- GValue transport = { 0 };
const GPtrArray *candidates;
- gchar *tr_addr = NULL;
- /* gchar *tr_user = NULL; */
- /* gchar *tr_pass = NULL; */
- gchar *tr_subtype = NULL;
- gchar *tr_profile = NULL;
- guint tr_port;
- guint tr_component;
- /* guint tr_type; */
- /* gdouble tr_pref; */
- guint rtcp_port = 0;
- gchar *rtcp_address = NULL;
- const gchar *dirline;
+ const gchar *candidate_id = NULL;
+ const GPtrArray *ca_tports = NULL;
+ GValue transport = { 0 };
int i;
- priv = RAKIA_MEDIA_STREAM_GET_PRIVATE (stream);
-
candidates = g_value_get_boxed (&priv->native_candidates);
g_value_init (&transport, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT);
@@ -1850,9 +1781,7 @@ priv_update_local_sdp(RakiaMediaStream *stream)
for (i = candidates->len - 1; i >= 0; --i)
{
GValueArray *candidate;
- const gchar *candidate_id;
- const GPtrArray *ca_tports;
- guint tr_proto = TP_MEDIA_STREAM_BASE_PROTO_UDP;
+ guint tr_proto = (guint) -1;
guint j;
candidate = g_ptr_array_index (candidates, i);
@@ -1868,33 +1797,18 @@ priv_update_local_sdp(RakiaMediaStream *stream)
for (j = 0; j < ca_tports->len; j++)
{
+ guint tr_component = 0;
+
g_value_set_static_boxed (&transport,
g_ptr_array_index (ca_tports, j));
+
+ /* Find the RTP component */
dbus_g_type_struct_get (&transport,
0, &tr_component,
+ 3, &tr_proto,
G_MAXUINT);
- switch (tr_component)
- {
- case 1: /* RTP */
- dbus_g_type_struct_get (&transport,
- 1, &tr_addr,
- 2, &tr_port,
- 3, &tr_proto,
- 4, &tr_subtype,
- 5, &tr_profile,
- /* 6, &tr_pref, */
- /* 7, &tr_type, */
- /* 8, &tr_user, */
- /* 9, &tr_pass, */
- G_MAXUINT);
- break;
- case 2: /* RTCP */
- dbus_g_type_struct_get (&transport,
- 1, &rtcp_address,
- 2, &rtcp_port,
- G_MAXUINT);
- break;
- }
+ if (tr_component == 1)
+ break;
}
if (priv->native_candidate_id != NULL)
@@ -1904,28 +1818,100 @@ priv_update_local_sdp(RakiaMediaStream *stream)
}
else if (tr_proto == TP_MEDIA_STREAM_BASE_PROTO_UDP)
{
- g_free (priv->native_candidate_id);
- priv->native_candidate_id = g_strdup (candidate_id);
break;
}
}
- g_return_if_fail (i >= 0);
+
+ if (i < 0)
+ {
+ WARNING ("preferred candidate not found");
+ return NULL;
+ }
+
+ if (transports != NULL)
+ *transports = ca_tports;
+
+ return candidate_id;
+}
+
+/**
+ * Produces the SDP description of the stream based on Farsight state and
+ * current object state.
+ *
+ * @param stream The stream object
+ * @param signal_update If true, emit the signal "local-media-updated".
+ */
+void
+rakia_media_stream_generate_sdp (RakiaMediaStream *stream, GString *out)
+{
+ RakiaMediaStreamPrivate *priv = stream->priv;
+ GString *alines;
+ GValue transport = { 0 };
+ const GPtrArray *transports = NULL;
+ gchar *tr_addr = NULL;
+ /* gchar *tr_user = NULL; */
+ /* gchar *tr_pass = NULL; */
+ gchar *tr_subtype = NULL;
+ gchar *tr_profile = NULL;
+ guint tr_port;
+ /* guint tr_type; */
+ /* gdouble tr_pref; */
+ guint rtcp_port = 0;
+ gchar *rtcp_address = NULL;
+ const gchar *dirline;
+ guint j;
+
+ priv_get_preferred_native_candidate (priv, &transports);
+
+ g_return_if_fail (transports != NULL);
+
+ g_value_init (&transport, TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT);
+
+ for (j = 0; j != transports->len; j++)
+ {
+ guint tr_component;
+
+ g_value_set_static_boxed (&transport,
+ g_ptr_array_index (transports, j));
+
+ dbus_g_type_struct_get (&transport,
+ 0, &tr_component,
+ G_MAXUINT);
+ switch (tr_component)
+ {
+ case 1: /* RTP */
+ dbus_g_type_struct_get (&transport,
+ 1, &tr_addr,
+ 2, &tr_port,
+ 4, &tr_subtype,
+ 5, &tr_profile,
+ /* 6, &tr_pref, */
+ /* 7, &tr_type, */
+ /* 8, &tr_user, */
+ /* 9, &tr_pass, */
+ G_MAXUINT);
+ break;
+ case 2: /* RTCP */
+ dbus_g_type_struct_get (&transport,
+ 1, &rtcp_address,
+ 2, &rtcp_port,
+ G_MAXUINT);
+ break;
+ }
+ }
+
g_return_if_fail (tr_addr != NULL);
g_return_if_fail (tr_subtype != NULL);
g_return_if_fail (tr_profile != NULL);
- mline = g_string_new ("m=");
- g_string_append_printf (mline,
+ g_string_append (out, "m=");
+ g_string_append_printf (out,
"%s %u %s/%s",
priv_media_type_to_str (priv->media_type),
tr_port,
tr_subtype,
tr_profile);
- cline = g_strdup_printf ("c=IN %s %s\r\n",
- (strchr (tr_addr, ':') == NULL)? "IP4" : "IP6",
- tr_addr);
-
switch (priv_get_requested_direction (priv))
{
case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL:
@@ -1967,13 +1953,13 @@ priv_update_local_sdp(RakiaMediaStream *stream)
}
priv_append_rtpmaps (g_value_get_boxed (&priv->native_codecs),
- mline, alines);
+ out, alines);
+
+ g_string_append_printf (out, "\r\nc=IN %s %s\r\n",
+ (strchr (tr_addr, ':') == NULL)? "IP4" : "IP6",
+ tr_addr);
- g_free(priv->stream_sdp);
- priv->stream_sdp = g_strconcat(mline->str, "\r\n",
- cline,
- alines->str,
- NULL);
+ g_string_append (out, alines->str);
g_free (tr_addr);
g_free (tr_profile);
@@ -1982,11 +1968,7 @@ priv_update_local_sdp(RakiaMediaStream *stream)
/* g_free (tr_pass); */
g_free (rtcp_address);
- g_string_free (mline, TRUE);
- g_free (cline);
g_string_free (alines, TRUE);
-
- g_signal_emit (stream, signals[SIG_LOCAL_MEDIA_UPDATED], 0);
}
static void