diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 3293dd77b996263c5a6acb04d60cc65872e1cda3..df752c90207c38a5c9c8e3451f1ecb0ce4ed3470 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2016,6 +2016,16 @@ int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_ca */ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format); +/*! + * \brief Sets write format for a channel. + * All internal data will than be handled in an interleaved format. (needed by binaural opus) + * + * \param chan channel to change + * \param format format to set for writing + * \return Returns 0 on success, -1 on failure + */ +int ast_set_write_format_interleaved_stereo(struct ast_channel *chan, struct ast_format *format); + /*! * \brief Sends text to a channel * diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h index b8cd219713b5aebe61a825de96cf2887e697d30a..8188eb8ebfec52a31d14c5749b0ee63f8b9689ef 100644 --- a/include/asterisk/translate.h +++ b/include/asterisk/translate.h @@ -231,6 +231,7 @@ struct ast_trans_pvt { * explicit_dst contains an attribute which describes whether both parties * want to do forward-error correction (FEC). */ struct ast_format *explicit_dst; + int interleaved_stereo; /*!< indicates if samples are in interleaved order, for stereo lin */ }; /*! \brief generic frameout function */ diff --git a/main/channel.c b/main/channel.c index e2390ad6536aed5aa7279065d1ba00e7ee3f1564..6804496f4128a4ce7fb933b3bf86e702146d18c2 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5442,7 +5442,7 @@ static const struct set_format_access set_format_access_write = { .setoption = AST_OPTION_FORMAT_WRITE, }; -static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, const int direction) +static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, const int direction, int interleaved_stereo) { struct ast_trans_pvt *trans_pvt; struct ast_format_cap *cap_native; @@ -5544,16 +5544,20 @@ static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, } /* Now we have a good choice for both. */ + trans_pvt = access->get_trans(chan); if ((ast_format_cmp(rawformat, best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && (ast_format_cmp(format, best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) && ((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || access->get_trans(chan))) { - /* the channel is already in these formats, so nothing to do */ - ast_channel_unlock(chan); - return 0; + /* the channel is already in these formats, so nothing to do, unless the interleaved format is not set correctly */ + if (trans_pvt != NULL) { + if (trans_pvt->interleaved_stereo == interleaved_stereo) { + ast_channel_unlock(chan); + return 0; + } + } } /* Free any translation we have right now */ - trans_pvt = access->get_trans(chan); if (trans_pvt) { ast_translator_free_path(trans_pvt); access->set_trans(chan, NULL); @@ -5571,9 +5575,11 @@ static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, if (!direction) { /* reading */ trans_pvt = ast_translator_build_path(best_set_fmt, best_native_fmt); + trans_pvt->interleaved_stereo = 0; } else { /* writing */ trans_pvt = ast_translator_build_path(best_native_fmt, best_set_fmt); + trans_pvt->interleaved_stereo = interleaved_stereo; } access->set_trans(chan, trans_pvt); res = trans_pvt ? 0 : -1; @@ -5613,7 +5619,7 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format) } ast_format_cap_append(cap, format, 0); - res = set_format(chan, cap, 0); + res = set_format(chan, cap, 0, 0); ao2_cleanup(cap); return res; @@ -5621,7 +5627,25 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format) int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) { - return set_format(chan, cap, 0); + return set_format(chan, cap, 0, 0); +} + +int ast_set_write_format_interleaved_stereo(struct ast_channel *chan, struct ast_format *format) +{ + struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + int res; + + ast_assert(format != NULL); + + if (!cap) { + return -1; + } + ast_format_cap_append(cap, format, 0); + + res = set_format(chan, cap, 1, 1); + + ao2_cleanup(cap); + return res; } int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) @@ -5636,7 +5660,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) } ast_format_cap_append(cap, format, 0); - res = set_format(chan, cap, 1); + res = set_format(chan, cap, 1, 0); ao2_cleanup(cap); return res; @@ -5644,7 +5668,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format) int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap) { - return set_format(chan, cap, 1); + return set_format(chan, cap, 1, 0); } const char *ast_channel_reason2str(int reason)