summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJenkins2 <jenkins2@gerrit.asterisk.org>2017-04-27 17:53:53 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2017-04-27 17:53:53 -0500
commit528e2384474a20321aaa9a61959c89cdfe3ccf56 (patch)
treec57186e08a15fad41d98202fe7c00488641ab8bf /main
parent16089ae1c98e92156b1cc784a87d0d9d15535d0f (diff)
parent2b22c3c84b8894c5663fec8655b0670b6bca4078 (diff)
Merge "channel: Add ability to request an outgoing channel with stream topology."
Diffstat (limited to 'main')
-rw-r--r--main/channel.c106
-rw-r--r--main/stream.c26
2 files changed, 99 insertions, 33 deletions
diff --git a/main/channel.c b/main/channel.c
index 31f363938..e37d66525 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5976,7 +5976,8 @@ static int set_security_requirements(const struct ast_channel *requestor, struct
return 0;
}
-struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
+static struct ast_channel *request_channel(const char *type, struct ast_format_cap *request_cap, struct ast_stream_topology *topology,
+ const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
{
struct chanlist *chan;
struct ast_channel *c;
@@ -5993,13 +5994,47 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
}
AST_RWLIST_TRAVERSE(&backends, chan, list) {
+ if (strcasecmp(type, chan->tech->type)) {
+ continue;
+ }
+
+ break;
+ }
+
+ AST_RWLIST_UNLOCK(&backends);
+
+ if (!chan) {
+ ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
+ *cause = AST_CAUSE_NOSUCHDRIVER;
+ return NULL;
+ }
+
+ /* Allow either format capabilities or stream topology to be provided and adapt */
+ if (chan->tech->requester_with_stream_topology) {
+ struct ast_stream_topology *tmp_converted_topology = NULL;
+
+ if (!topology && request_cap) {
+ /* Turn the requested capabilities into a stream topology */
+ topology = tmp_converted_topology = ast_stream_topology_create_from_format_cap(request_cap);
+ }
+
+ c = chan->tech->requester_with_stream_topology(type, topology, assignedids, requestor, addr, cause);
+
+ ast_stream_topology_free(tmp_converted_topology);
+ if (!c) {
+ return NULL;
+ }
+ } else if (chan->tech->requester) {
+ struct ast_format_cap *tmp_converted_cap = NULL;
struct ast_format_cap *tmp_cap;
RAII_VAR(struct ast_format *, tmp_fmt, NULL, ao2_cleanup);
RAII_VAR(struct ast_format *, best_audio_fmt, NULL, ao2_cleanup);
struct ast_format_cap *joint_cap;
- if (strcasecmp(type, chan->tech->type))
- continue;
+ if (!request_cap && topology) {
+ /* Turn the request stream topology into capabilities */
+ request_cap = tmp_converted_cap = ast_format_cap_from_stream_topology(topology);
+ }
/* find the best audio format to use */
tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
@@ -6018,13 +6053,10 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
ast_format_cap_get_names(chan->tech->capabilities, &tech_codecs),
ast_format_cap_get_names(request_cap, &request_codecs));
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
- AST_RWLIST_UNLOCK(&backends);
+ ao2_cleanup(tmp_converted_cap);
return NULL;
}
}
- AST_RWLIST_UNLOCK(&backends);
- if (!chan->tech->requester)
- return NULL;
/* XXX Only the audio format calculated as being the best for translation
* purposes is used for the request. This is because we don't have the ability
@@ -6033,50 +6065,58 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
*/
joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!joint_cap) {
+ ao2_cleanup(tmp_converted_cap);
return NULL;
}
ast_format_cap_append_from_cap(joint_cap, request_cap, AST_MEDIA_TYPE_UNKNOWN);
ast_format_cap_remove_by_type(joint_cap, AST_MEDIA_TYPE_AUDIO);
ast_format_cap_append(joint_cap, best_audio_fmt, 0);
+ ao2_cleanup(tmp_converted_cap);
+
+ c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause);
- if (!(c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause))) {
+ if (!c) {
ao2_ref(joint_cap, -1);
return NULL;
}
+ } else {
+ return NULL;
+ }
- if (requestor) {
- ast_callid callid;
-
- ast_channel_lock_both(c, (struct ast_channel *) requestor);
+ if (requestor) {
+ ast_callid callid;
- /* Set the newly created channel's callid to the same as the requestor. */
- callid = ast_channel_callid(requestor);
- if (callid) {
- ast_channel_callid_set(c, callid);
- }
+ ast_channel_lock_both(c, (struct ast_channel *) requestor);
- ast_channel_unlock(c);
- ast_channel_unlock((struct ast_channel *) requestor);
+ /* Set the newly created channel's callid to the same as the requestor. */
+ callid = ast_channel_callid(requestor);
+ if (callid) {
+ ast_channel_callid_set(c, callid);
}
- ao2_ref(joint_cap, -1);
-
- if (set_security_requirements(requestor, c)) {
- ast_log(LOG_WARNING, "Setting security requirements failed\n");
- ast_hangup(c);
- *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
- return NULL;
- }
+ ast_channel_unlock(c);
+ ast_channel_unlock((struct ast_channel *) requestor);
+ }
- /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
- return c;
+ if (set_security_requirements(requestor, c)) {
+ ast_log(LOG_WARNING, "Setting security requirements failed\n");
+ ast_hangup(c);
+ *cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
+ return NULL;
}
- ast_log(LOG_WARNING, "No channel type registered for '%s'\n", type);
- *cause = AST_CAUSE_NOSUCHDRIVER;
- AST_RWLIST_UNLOCK(&backends);
+ /* no need to generate a Newchannel event here; it is done in the channel_alloc call */
+ return c;
+}
- return NULL;
+struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
+{
+ return request_channel(type, request_cap, NULL, assignedids, requestor, addr, cause);
+}
+
+struct ast_channel *ast_request_with_stream_topology(const char *type, struct ast_stream_topology *topology, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
+{
+ return request_channel(type, NULL, topology, assignedids, requestor, addr, cause);
}
/*!
diff --git a/main/stream.c b/main/stream.c
index 9d36dbf25..cf2633e1b 100644
--- a/main/stream.c
+++ b/main/stream.c
@@ -392,6 +392,32 @@ struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
return topology;
}
+struct ast_format_cap *ast_format_cap_from_stream_topology(
+ struct ast_stream_topology *topology)
+{
+ struct ast_format_cap *caps;
+ int i;
+
+ ast_assert(topology != NULL);
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!caps) {
+ return NULL;
+ }
+
+ for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
+ struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
+
+ if (!stream->formats) {
+ continue;
+ }
+
+ ast_format_cap_append_from_cap(caps, stream->formats, AST_MEDIA_TYPE_UNKNOWN);
+ }
+
+ return caps;
+}
+
struct ast_stream *ast_stream_topology_get_first_stream_by_type(
const struct ast_stream_topology *topology,
enum ast_media_type type)