summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexei Gradinari <alex2grad@gmail.com>2016-11-15 16:01:27 -0500
committerGeorge Joseph <gjoseph@digium.com>2016-11-30 07:55:08 -0500
commitd49fbc5f4e045a625cb6b6fb91eef5b00a490bf2 (patch)
tree2470133f7f9d8a7a19b20c64ff91cf86c73a3e2a
parenta15258146476fb26e3fc7ca8340ccb3aa3692e4c (diff)
chan_pjsip: fix switching sending codec when asymmetric_rtp_codec=no
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
-rw-r--r--channels/chan_pjsip.c9
-rw-r--r--include/asterisk/channel.h15
-rw-r--r--main/channel.c36
3 files changed, 57 insertions, 3 deletions
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index b0dba1b47..f397accda 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -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);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 9745bc220..1637371c3 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1993,6 +1993,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.
* \param chan channel to change
diff --git a/main/channel.c b/main/channel.c
index b4d451a70..be31f39f6 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5476,6 +5476,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);