mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Merge "core / pjsip: Add support for grouping streams together."
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@@ -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 */
|
||||
|
@@ -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)
|
||||
);
|
||||
}
|
||||
|
@@ -66,6 +66,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
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
@@ -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 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));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user