summaryrefslogtreecommitdiff
path: root/channels/chan_pjsip.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels/chan_pjsip.c')
-rw-r--r--channels/chan_pjsip.c118
1 files changed, 83 insertions, 35 deletions
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 0a8d1bcb5..16f042622 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -223,17 +223,6 @@ static void chan_pjsip_get_codec(struct ast_channel *chan, struct ast_format_cap
ast_format_cap_append_from_cap(result, channel->session->endpoint->media.codecs, AST_MEDIA_TYPE_UNKNOWN);
}
-static int send_direct_media_request(void *data)
-{
- struct ast_sip_session *session = data;
- int res;
-
- res = ast_sip_session_refresh(session, NULL, NULL, NULL,
- session->endpoint->media.direct_media.method, 1);
- ao2_ref(session, -1);
- return res;
-}
-
/*! \brief Destructor function for \ref transport_info_data */
static void transport_info_destroy(void *obj)
{
@@ -302,6 +291,83 @@ static int check_for_rtp_changes(struct ast_channel *chan, struct ast_rtp_instan
return changed;
}
+struct rtp_direct_media_data {
+ struct ast_channel *chan;
+ struct ast_rtp_instance *rtp;
+ struct ast_rtp_instance *vrtp;
+ struct ast_format_cap *cap;
+ struct ast_sip_session *session;
+};
+
+static void rtp_direct_media_data_destroy(void *data)
+{
+ struct rtp_direct_media_data *cdata = data;
+
+ ao2_cleanup(cdata->session);
+ ao2_cleanup(cdata->cap);
+ ao2_cleanup(cdata->vrtp);
+ ao2_cleanup(cdata->rtp);
+ ao2_cleanup(cdata->chan);
+}
+
+static struct rtp_direct_media_data *rtp_direct_media_data_create(
+ struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp,
+ const struct ast_format_cap *cap, struct ast_sip_session *session)
+{
+ struct rtp_direct_media_data *cdata = ao2_alloc(sizeof(*cdata), rtp_direct_media_data_destroy);
+
+ if (!cdata) {
+ return NULL;
+ }
+
+ cdata->chan = ao2_bump(chan);
+ cdata->rtp = ao2_bump(rtp);
+ cdata->vrtp = ao2_bump(vrtp);
+ cdata->cap = ao2_bump((struct ast_format_cap *)cap);
+ cdata->session = ao2_bump(session);
+
+ return cdata;
+}
+
+static int send_direct_media_request(void *data)
+{
+ struct rtp_direct_media_data *cdata = data;
+ struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(cdata->chan);
+ struct chan_pjsip_pvt *pvt = channel->pvt;
+ int changed = 0;
+ int res = 0;
+
+ if (pvt->media[SIP_MEDIA_AUDIO]) {
+ changed |= check_for_rtp_changes(
+ cdata->chan, cdata->rtp, pvt->media[SIP_MEDIA_AUDIO], 1);
+ }
+ if (pvt->media[SIP_MEDIA_VIDEO]) {
+ changed |= check_for_rtp_changes(
+ cdata->chan, cdata->vrtp, pvt->media[SIP_MEDIA_VIDEO], 3);
+ }
+
+ if (direct_media_mitigate_glare(cdata->session)) {
+ ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(cdata->chan));
+ return 0;
+ }
+
+ if (cdata->cap && ast_format_cap_count(cdata->cap) &&
+ !ast_format_cap_identical(cdata->session->direct_media_cap, cdata->cap)) {
+ ast_format_cap_remove_by_type(cdata->session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_append_from_cap(cdata->session->direct_media_cap, cdata->cap, AST_MEDIA_TYPE_UNKNOWN);
+ changed = 1;
+ }
+
+ if (changed) {
+ ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(cdata->chan));
+ res = ast_sip_session_refresh(cdata->session, NULL, NULL, NULL,
+ cdata->session->endpoint->media.direct_media.method, 1);
+ }
+
+ ao2_ref(cdata, -1);
+ return res;
+}
+
/*! \brief Function called by RTP engine to change where the remote party should send media */
static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
struct ast_rtp_instance *rtp,
@@ -311,9 +377,8 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
int nat_active)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
- struct chan_pjsip_pvt *pvt = channel->pvt;
struct ast_sip_session *session = channel->session;
- int changed = 0;
+ struct rtp_direct_media_data *cdata;
/* Don't try to do any direct media shenanigans on early bridges */
if ((rtp || vrtp || tpeer) && !ast_channel_is_bridged(chan)) {
@@ -326,31 +391,14 @@ static int chan_pjsip_set_rtp_peer(struct ast_channel *chan,
return 0;
}
- if (pvt->media[SIP_MEDIA_AUDIO]) {
- changed |= check_for_rtp_changes(chan, rtp, pvt->media[SIP_MEDIA_AUDIO], 1);
- }
- if (pvt->media[SIP_MEDIA_VIDEO]) {
- changed |= check_for_rtp_changes(chan, vrtp, pvt->media[SIP_MEDIA_VIDEO], 3);
- }
-
- if (direct_media_mitigate_glare(session)) {
- ast_debug(4, "Disregarding setting RTP on %s: mitigating re-INVITE glare\n", ast_channel_name(chan));
+ cdata = rtp_direct_media_data_create(chan, rtp, vrtp, cap, session);
+ if (!cdata) {
return 0;
}
- if (cap && ast_format_cap_count(cap) && !ast_format_cap_identical(session->direct_media_cap, cap)) {
- ast_format_cap_remove_by_type(session->direct_media_cap, AST_MEDIA_TYPE_UNKNOWN);
- ast_format_cap_append_from_cap(session->direct_media_cap, cap, AST_MEDIA_TYPE_UNKNOWN);
- changed = 1;
- }
-
- if (changed) {
- ao2_ref(session, +1);
-
- ast_debug(4, "RTP changed on %s; initiating direct media update\n", ast_channel_name(chan));
- if (ast_sip_push_task(session->serializer, send_direct_media_request, session)) {
- ao2_cleanup(session);
- }
+ if (ast_sip_push_task(session->serializer, send_direct_media_request, cdata)) {
+ ast_log(LOG_ERROR, "Unable to send direct media request for channel %s\n", ast_channel_name(chan));
+ ao2_ref(cdata, -1);
}
return 0;