diff options
-rw-r--r-- | channels/chan_pjsip.c | 9 | ||||
-rw-r--r-- | include/asterisk/channel.h | 15 | ||||
-rw-r--r-- | main/channel.c | 36 |
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); |