diff options
-rw-r--r-- | include/asterisk/res_pjsip_session.h | 2 | ||||
-rw-r--r-- | include/asterisk/stream.h | 21 | ||||
-rw-r--r-- | main/cli.c | 2 | ||||
-rw-r--r-- | main/stream.c | 27 | ||||
-rw-r--r-- | res/res_pjsip_sdp_rtp.c | 17 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 67 |
6 files changed, 121 insertions, 15 deletions
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index b7a22b937..a0fc9650e 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -111,6 +111,8 @@ struct ast_sip_session_media { char label[AST_UUID_STR_LEN]; /*! \brief The underlying session has been changed in some fashion */ unsigned int changed; + /*! \brief Remote media stream label */ + char *remote_mslabel; }; /*! diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h index 2c1053a7b..c2d5a8877 100644 --- a/include/asterisk/stream.h +++ b/include/asterisk/stream.h @@ -476,4 +476,25 @@ struct ast_stream *ast_stream_topology_get_first_stream_by_type( void ast_stream_topology_map(const struct ast_stream_topology *topology, struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1); +/*! + * \brief Get the stream group that a stream is part of + * + * \param stream The stream + * + * \return the numerical stream group (-1 if not in a group) + * + * \since 15.2.0 + */ +int ast_stream_get_group(const struct ast_stream *stream); + +/*! + * \brief Set the stream group for a stream + * + * \param stream The stream + * \param group The group the stream is part of + * + * \since 15.2.0 + */ +void ast_stream_set_group(struct ast_stream *stream, int group); + #endif /* _AST_STREAM_H */ diff --git a/main/cli.c b/main/cli.c index ef86e256a..d9aab85cb 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1690,10 +1690,12 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar "Name: %s\n" " Type: %s\n" " State: %s\n" + " Group: %d\n" " Formats: %s\n", ast_stream_get_name(stream), ast_codec_media_type2str(ast_stream_get_type(stream)), ast_stream_state2str(ast_stream_get_state(stream)), + ast_stream_get_group(stream), ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf) ); } diff --git a/main/stream.c b/main/stream.c index 89ed0dc53..c233b2f34 100644 --- a/main/stream.c +++ b/main/stream.c @@ -67,6 +67,11 @@ struct ast_stream { ast_stream_data_free_fn data_free_fn[AST_STREAM_DATA_SLOT_MAX]; /*! + * \brief The group that the stream is part of + */ + int group; + + /*! * \brief Name for the stream within the context of the channel it is on */ char name[0]; @@ -90,6 +95,7 @@ struct ast_stream *ast_stream_alloc(const char *name, enum ast_media_type type) stream->type = type; stream->state = AST_STREAM_STATE_INACTIVE; + stream->group = -1; strcpy(stream->name, S_OR(name, "")); /* Safe */ return stream; @@ -115,6 +121,7 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char memcpy(new_stream, stream, sizeof(*new_stream)); strcpy(new_stream->name, stream_name); /* Safe */ + new_stream->group = -1; if (new_stream->formats) { ao2_ref(new_stream->formats, +1); } @@ -288,14 +295,16 @@ struct ast_stream_topology *ast_stream_topology_clone( } for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) { - struct ast_stream *stream = - ast_stream_clone(AST_VECTOR_GET(&topology->streams, i), NULL); + struct ast_stream *existing = AST_VECTOR_GET(&topology->streams, i); + struct ast_stream *stream = ast_stream_clone(existing, NULL); if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) { ast_stream_free(stream); ast_stream_topology_free(new_topology); return NULL; } + + ast_stream_set_group(stream, ast_stream_get_group(existing)); } return new_topology; @@ -580,3 +589,17 @@ void ast_stream_topology_map(const struct ast_stream_topology *topology, AST_VECTOR_REPLACE(v1, index, i); } } + +int ast_stream_get_group(const struct ast_stream *stream) +{ + ast_assert(stream != NULL); + + return stream->group; +} + +void ast_stream_set_group(struct ast_stream *stream, int group) +{ + ast_assert(stream != NULL); + + stream->group = group; +} diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 604fd421e..a87758267 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -1052,20 +1052,11 @@ static void add_msid_to_stream(struct ast_sip_session *session, } if (ast_strlen_zero(session_media->mslabel)) { - if (ast_sip_session_is_pending_stream_default(session, stream)) { - int index; - - /* If this is a default stream we group them together under the same stream, but as different tracks */ - for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) { - struct ast_sip_session_media *other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index); - - if (session_media == other_session_media) { - continue; - } + /* If this stream is grouped with another then use its media stream label if possible */ + if (ast_stream_get_group(stream) != -1) { + struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream)); - ast_copy_string(session_media->mslabel, other_session_media->mslabel, sizeof(session_media->mslabel)); - break; - } + ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel)); } if (ast_strlen_zero(session_media->mslabel)) { diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 37ff53105..4724d46ce 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -399,6 +399,7 @@ static void session_media_dtor(void *obj) } ast_free(session_media->mid); + ast_free(session_media->remote_mslabel); } struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session, @@ -553,6 +554,70 @@ static int set_mid_and_bundle_group(struct ast_sip_session *session, return 0; } +static void set_remote_mslabel_and_stream_group(struct ast_sip_session *session, + struct ast_sip_session_media *session_media, + const pjmedia_sdp_session *sdp, + const struct pjmedia_sdp_media *stream, + struct ast_stream *asterisk_stream) +{ + int index; + + ast_free(session_media->remote_mslabel); + session_media->remote_mslabel = NULL; + + for (index = 0; index < stream->attr_count; ++index) { + pjmedia_sdp_attr *attr = stream->attr[index]; + char attr_value[pj_strlen(&attr->value) + 1]; + char *ssrc_attribute_name, *ssrc_attribute_value = NULL; + char *msid, *tmp = attr_value; + static const pj_str_t STR_msid = { "msid", 4 }; + static const pj_str_t STR_ssrc = { "ssrc", 4 }; + + if (!pj_strcmp(&attr->name, &STR_msid)) { + ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value)); + msid = strsep(&tmp, " "); + session_media->remote_mslabel = ast_strdup(msid); + break; + } else if (!pj_strcmp(&attr->name, &STR_ssrc)) { + ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value)); + + if ((ssrc_attribute_name = strchr(attr_value, ' '))) { + /* This has an actual attribute */ + *ssrc_attribute_name++ = '\0'; + ssrc_attribute_value = strchr(ssrc_attribute_name, ':'); + if (ssrc_attribute_value) { + /* Values are actually optional according to the spec */ + *ssrc_attribute_value++ = '\0'; + } + + if (!strcasecmp(ssrc_attribute_name, "mslabel") && !ast_strlen_zero(ssrc_attribute_value)) { + session_media->remote_mslabel = ast_strdup(ssrc_attribute_value); + break; + } + } + } + } + + if (ast_strlen_zero(session_media->remote_mslabel)) { + return; + } + + /* Iterate through the existing streams looking for a match and if so then group this with it */ + for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) { + struct ast_sip_session_media *group_session_media; + + group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index); + + if (ast_strlen_zero(group_session_media->remote_mslabel) || + strcmp(group_session_media->remote_mslabel, session_media->remote_mslabel)) { + continue; + } + + ast_stream_set_group(asterisk_stream, index); + break; + } +} + static void remove_stream_from_bundle(struct ast_sip_session_media *session_media, struct ast_stream *stream) { @@ -630,6 +695,7 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd } set_mid_and_bundle_group(session, session_media, sdp, remote_stream); + set_remote_mslabel_and_stream_group(session, session_media, sdp, remote_stream, stream); if (session_media->handler) { handler = session_media->handler; @@ -730,6 +796,7 @@ static int handle_negotiated_sdp_session_media(struct ast_sip_session_media *ses ast_copy_pj_str(media, &local->media[index]->desc.media, sizeof(media)); set_mid_and_bundle_group(session, session_media, remote, remote->media[index]); + set_remote_mslabel_and_stream_group(session, session_media, remote, remote->media[index], asterisk_stream); handler = session_media->handler; if (handler) { |