]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
chan_pjsip: fix switching sending codec when asymmetric_rtp_codec=no 71/5071/1
authorAlexei Gradinari <alex2grad@gmail.com>
Tue, 15 Nov 2016 21:01:27 +0000 (16:01 -0500)
committerKevin Harwell <kharwell@digium.com>
Wed, 22 Feb 2017 23:11:51 +0000 (17:11 -0600)
The sending codec is switched to the receiving codec and then
is switched back to the best native codec on EVERY receiving RTP packets.
This is because after call of ast_channel_set_rawwriteformat there is call
of ast_set_write_format which calls set_format which sets rawwriteformat
to the best native format.

This patch adds a new function ast_set_write_format_path which set
specific write path on channel and uses this function to switch
the sending codec.

ASTERISK-26603 #close

Change-Id: I5b7d098f8b254ce8f45546e6c36e5d324737f71d
(cherry picked from commit cf6d13180effc92a2483dccc68f2f188689a40fa)

channels/chan_pjsip.c
include/asterisk/channel.h
main/channel.c

index cc4b2efa943862dfb8079564811b74b2b217e05d..6e3d087a46cf52d3fec227ec0df46856b7597fa7 100644 (file)
@@ -679,7 +679,11 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
        return f;
 }
 
-/*! \brief Function called by core to read any waiting frames */
+/*!
+ * \brief Function called by core to read any waiting frames 
+ *
+ * \note The channel is already locked.
+ */
 static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
 {
        struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
@@ -737,8 +741,7 @@ static struct ast_frame *chan_pjsip_read(struct ast_channel *ast)
                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)));
-               ast_channel_set_rawwriteformat(ast, f->subclass.format);
-               ast_set_write_format(ast, ast_channel_writeformat(ast));
+               ast_set_write_format_path(ast, ast_channel_writeformat(ast), f->subclass.format);
 
                if (ast_channel_is_bridged(ast)) {
                        ast_channel_set_unbridged_nolock(ast, 1);
index 5f138ba326d34bb09660c83a6ec2f3a54aca83a3..c237a009f0a15d210975e9e6a7f916253a44e160 100644 (file)
@@ -2002,6 +2002,21 @@ int ast_prod(struct ast_channel *chan);
  */
 int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_format, struct ast_format *core_format);
 
+/*!
+ * \brief Set specific write path on channel.
+ * \since 13.13.0
+ *
+ * \param chan Channel to setup write path.
+ * \param core_format What the core wants to write.
+ * \param raw_format Raw write format.
+ *
+ * \pre chan is locked
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int ast_set_write_format_path(struct ast_channel *chan, struct ast_format *core_format, struct ast_format *raw_format);
+
 /*!
  * \brief Sets read format on channel chan from capabilities
  * Set read format for channel to whichever component of "format" is best.
index fd0260e5a199b498045b4233debb053aec9713c1..07f3182b71550619bfaac28616d24bed4c6c82b9 100644 (file)
@@ -5454,6 +5454,42 @@ int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_fo
        return 0;
 }
 
+int ast_set_write_format_path(struct ast_channel *chan, struct ast_format *core_format, struct ast_format *raw_format)
+{
+       struct ast_trans_pvt *trans_old;
+       struct ast_trans_pvt *trans_new;
+
+       if (ast_format_cmp(ast_channel_rawwriteformat(chan), raw_format) == AST_FORMAT_CMP_EQUAL
+               && ast_format_cmp(ast_channel_writeformat(chan), core_format) == AST_FORMAT_CMP_EQUAL) {
+               /* Nothing to setup */
+               return 0;
+       }
+
+       ast_debug(1, "Channel %s setting write format path: %s -> %s\n",
+               ast_channel_name(chan),
+               ast_format_get_name(core_format),
+               ast_format_get_name(raw_format));
+
+       /* Setup new translation path. */
+       if (ast_format_cmp(raw_format, core_format) != AST_FORMAT_CMP_EQUAL) {
+               trans_new = ast_translator_build_path(raw_format, core_format);
+               if (!trans_new) {
+                       return -1;
+               }
+       } else {
+               /* No translation needed. */
+               trans_new = NULL;
+       }
+       trans_old = ast_channel_writetrans(chan);
+       if (trans_old) {
+               ast_translator_free_path(trans_old);
+       }
+       ast_channel_writetrans_set(chan, trans_new);
+       ast_channel_set_rawwriteformat(chan, raw_format);
+       ast_channel_set_writeformat(chan, core_format);
+       return 0;
+}
+
 struct set_format_access {
        const char *direction;
        struct ast_trans_pvt *(*get_trans)(const struct ast_channel *chan);