]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pjsip: Extend 'asymmetric_rtp_codec' option to include us changing.
authorJoshua Colp <jcolp@digium.com>
Tue, 6 Jun 2017 12:04:21 +0000 (12:04 +0000)
committerJoshua Colp <jcolp@digium.com>
Wed, 7 Jun 2017 13:12:55 +0000 (13:12 +0000)
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

CHANGES
channels/chan_pjsip.c
res/res_pjsip_sdp_rtp.c

diff --git a/CHANGES b/CHANGES
index 2dd47245dcc01c41eba5da4f2d0109ddfac59a9e..6007928df71f9fe7c2e6ef66512d534a3f9f2d03 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -25,6 +25,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 13.15.0 to Asterisk 13.16.0 ----------
 ------------------------------------------------------------------------------
index 97c3d101bd253969796d733b7e62190e9274a2bf..fdbeef8aa60a3b9832b396a1d91bbb00fa1e5adb 100644 (file)
@@ -737,11 +737,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);
index cafbd52ec83e2e4fa381bf290343c9e9a5ba18a9..d39842f3a8fb726b79beb7aeb13873ff327baa7d 100644 (file)
@@ -401,7 +401,24 @@ static int set_caps(struct ast_sip_session *session, struct ast_sip_session_medi
                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);
-               ast_format_cap_append_from_cap(caps, joint, media_type);
+
+               /*
+                * 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.
+                */
+               if (!session->endpoint->asymmetric_rtp_codec) {
+                       struct ast_format *best;
+
+                       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