diff options
author | Joshua Colp <jcolp@digium.com> | 2017-04-24 15:59:44 +0000 |
---|---|---|
committer | Joshua Colp <jcolp@digium.com> | 2017-04-27 10:39:46 +0000 |
commit | 2b22c3c84b8894c5663fec8655b0670b6bca4078 (patch) | |
tree | 119cd5ee07ec1d1ca60ff7c5765f6fd21cce1a28 /main/channel.c | |
parent | dc6654d969224129bdd7b4080eda6e027c6454b9 (diff) |
channel: Add ability to request an outgoing channel with stream topology.
This change extends the ast_request functionality by adding another
function and callback to create an outgoing channel with a requested
stream topology. Fallback is provided by either converting the
requested stream topology into a format capabilities structure if
the channel driver does not support streams or by converting the
requested format capabilities into a stream topology if the channel
driver does support streams.
The Dial application has also been updated to request an outgoing
channel with the stream topology of the calling channel.
ASTERISK-26959
Change-Id: Ifa9037a672ac21d42dd7125aa09816dc879a70e6
Diffstat (limited to 'main/channel.c')
-rw-r--r-- | main/channel.c | 106 |
1 files changed, 73 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); } /*! |