summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 d4a7d618d..4aae15ce9 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -677,7 +677,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);
@@ -735,8 +739,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 5c73c777e..6f220271a 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 bd5f35172..bcfb8afa9 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5474,6 +5474,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);