summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-10-12 17:03:45 +0000
committerJoshua Colp <jcolp@digium.com>2017-10-13 17:24:08 -0500
commit7d51a79beb903874da97f52a31fabfdd94ac3680 (patch)
tree78c6baa0ed24138f51321a9b1b6ff42c5be58f1c
parent85bdfe2df717ca21d7c620dea7a3c4362da5ea6a (diff)
bridge_simple: Improve renegotiation success rate.
When making channels compatible the bridge_simple module will renegotiate one to better match the other. Some endpoints incorrectly terminate the call if this process fails. To better handle this scenario the audio streams present on the new requested topology will include any existing negotiated formats that happen to exist on the first valid audio stream. This ensures formats are persent that are known to be acceptable to the remote endpoint. ASTERISK-27259 Change-Id: I8fc0cc03e8bcfd0be8302f13b9f32d8268977f43
-rw-r--r--bridges/bridge_simple.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/bridges/bridge_simple.c b/bridges/bridge_simple.c
index a49bc39f3..7ee196674 100644
--- a/bridges/bridge_simple.c
+++ b/bridges/bridge_simple.c
@@ -113,6 +113,58 @@ static struct ast_bridge_technology simple_bridge = {
.stream_topology_changed = simple_bridge_stream_topology_changed,
};
+static void simple_bridge_request_stream_topology_change(struct ast_channel *chan,
+ struct ast_stream_topology *requested_topology)
+{
+ struct ast_stream_topology *existing_topology = ast_channel_get_stream_topology(chan);
+ struct ast_stream *stream;
+ struct ast_format_cap *audio_formats = NULL;
+ struct ast_stream_topology *new_topology;
+ int i;
+
+ /* We find an existing stream with negotiated audio formats that we can place into
+ * any audio streams in the new topology to ensure that negotiation succeeds. Some
+ * endpoints incorrectly terminate the call if SDP negotiation fails.
+ */
+ for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
+ stream = ast_stream_topology_get_stream(existing_topology, i);
+
+ if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
+ ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
+ continue;
+ }
+
+ audio_formats = ast_stream_get_formats(stream);
+ break;
+ }
+
+ if (!audio_formats) {
+ ast_channel_request_stream_topology_change(chan, requested_topology, &simple_bridge);
+ return;
+ }
+
+ new_topology = ast_stream_topology_clone(requested_topology);
+ if (!new_topology) {
+ ast_channel_request_stream_topology_change(chan, requested_topology, &simple_bridge);
+ return;
+ }
+
+ for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
+ stream = ast_stream_topology_get_stream(new_topology, i);
+
+ if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
+ ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
+ continue;
+ }
+
+ ast_format_cap_append_from_cap(ast_stream_get_formats(stream), audio_formats, AST_MEDIA_TYPE_AUDIO);
+ }
+
+ ast_channel_request_stream_topology_change(chan, new_topology, &simple_bridge);
+
+ ast_stream_topology_free(new_topology);
+}
+
static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
struct ast_bridge_channel *bridge_channel)
{
@@ -135,9 +187,9 @@ static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
/* Align topologies according to size or first channel to join */
if (ast_stream_topology_get_count(t0) < ast_stream_topology_get_count(t1)) {
- ast_channel_request_stream_topology_change(c0, t1, &simple_bridge);
+ simple_bridge_request_stream_topology_change(c0, t1);
} else {
- ast_channel_request_stream_topology_change(c1, t0, &simple_bridge);
+ simple_bridge_request_stream_topology_change(c1, t0);
}
}