summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2017-06-06 12:04:21 +0000
committerJoshua Colp <jcolp@digium.com>2017-06-07 13:34:58 +0000
commitd3e951edf5517b9f508a7e1b474176ec2be9e18f (patch)
treea63f7b9110bad02f8cefca66ff8849a7d51c9ae9
parent9f054955f2f7830d4a7d20326d9fea7dff277456 (diff)
pjsip: Extend 'asymmetric_rtp_codec' option to include us changing.
PJSIP support in Asterisk differs from chan_sip in that it allows media to be sent as-is without transcoding provided the codecs were negotiated in the SDP. This is allowed according to the RFC. Support for this differs quite a lot though and some endpoints do not handle it well. This change extends the 'asymmetric_rtp_codec' option to also cover this case. When set to no (the default) the code behaves as chan_sip does - the best codec is selected and we will only ever send that, unless we change what we are sending if the remote side changes. When set to yes we will send media as-is without transcoding if the codec has been negotiated in the SDP. ASTERISK-26996 Change-Id: Ib1647f6902a0843e8c435946f831c2159e8d1d51
-rw-r--r--CHANGES6
-rw-r--r--channels/chan_pjsip.c15
-rw-r--r--res/res_pjsip_sdp_rtp.c16
3 files changed, 36 insertions, 1 deletions
diff --git a/CHANGES b/CHANGES
index 442f59d62..741916aa2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -34,6 +34,12 @@ chan_pjsip
function any contact which is considered unreachable due to qualify being
enabled will no longer be called.
+ * The asymmetric_rtp_codec option now also controls whether chan_pjsip will
+ send media as-is without transcoding if the codec has been negotiated in the
+ SDP. If set to "no" then Asterisk will only ever send the preferred codec
+ from the SDP, unless the remote side sends a different codec and we will
+ switch to match.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 14.4.0 to Asterisk 14.5.0 ------------
------------------------------------------------------------------------------
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 5bf339ee9..19fb20bec 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -735,11 +735,24 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
if (!session->endpoint->asymmetric_rtp_codec &&
ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
- /* For maximum compatibility we ensure that the write format matches that of the received media */
+ struct ast_format_cap *caps;
+
+ /* For maximum compatibility we ensure that the formats match that of the received media */
ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
ast_format_get_name(f->subclass.format), ast_channel_name(ast),
ast_format_get_name(ast_channel_rawwriteformat(ast)));
+
+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (caps) {
+ ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(ast), AST_MEDIA_TYPE_UNKNOWN);
+ ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
+ ast_format_cap_append(caps, f->subclass.format, 0);
+ ast_channel_nativeformats_set(ast, caps);
+ ao2_ref(caps, -1);
+ }
+
ast_set_write_format_path(ast, ast_channel_writeformat(ast), f->subclass.format);
+ ast_set_read_format_path(ast, ast_channel_readformat(ast), f->subclass.format);
if (ast_channel_is_bridged(ast)) {
ast_channel_set_unbridged_nolock(ast, 1);
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 97e365c10..c5a673aa4 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -410,13 +410,29 @@ static int set_caps(struct ast_sip_session *session,
ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(session->channel),
AST_MEDIA_TYPE_UNKNOWN);
ast_format_cap_remove_by_type(caps, media_type);
+
if (session->endpoint->preferred_codec_only){
struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
ast_format_cap_append(caps, preferred_fmt, 0);
ao2_ref(preferred_fmt, -1);
+ } else if (!session->endpoint->asymmetric_rtp_codec) {
+ struct ast_format *best;
+ /*
+ * If we don't allow the sending codec to be changed on our side
+ * then get the best codec from the joint capabilities of the media
+ * type and use only that. This ensures the core won't start sending
+ * out a format that we aren't currently sending.
+ */
+
+ best = ast_format_cap_get_best_by_type(joint, media_type);
+ if (best) {
+ ast_format_cap_append(caps, best, ast_format_cap_get_framing(joint));
+ ao2_ref(best, -1);
+ }
} else {
ast_format_cap_append_from_cap(caps, joint, media_type);
}
+
/*
* Apply the new formats to the channel, potentially changing
* raw read/write formats and translation path while doing so.