aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNeels Hofmeyr <nhofmeyr@sysmocom.de>2022-10-31 18:51:07 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2023-03-18 03:05:34 +0100
commit62bfa37eae97fb8eee65a4c3d6a1138999811e75 (patch)
tree40ff9dc8e61e16e0ea8e7ad5aee940d91713fcbf /src
parent1dc3961a0a1bdc7493002f973fd95197e09a9a91 (diff)
rtp_stream: allow multiple codecs / use codec filter from Assignment
Allow configuring MGW conns with multiple codecs. The new codecs filter can have multiple results, and MGCP can configure multiple codecs. Get rid of this bottleneck, that so far limits to a single codec to MGW. On Assignment Complete, set codec_filter.assignment to the assigned codec, and use that to set the resulting codec (possibly multiple codecs in the future) to create the CN side MGW endpoint. Related: SYS#5066 Change-Id: If9c67b298b30f893ec661f84c9fc622ad01b5ee5
Diffstat (limited to 'src')
-rw-r--r--src/libmsc/call_leg.c19
-rw-r--r--src/libmsc/gsm_04_08_cc.c10
-rw-r--r--src/libmsc/mncc_call.c13
-rw-r--r--src/libmsc/msc_a.c50
-rw-r--r--src/libmsc/msc_ho.c20
-rw-r--r--src/libmsc/msc_t.c4
-rw-r--r--src/libmsc/rtp_stream.c94
7 files changed, 141 insertions, 69 deletions
diff --git a/src/libmsc/call_leg.c b/src/libmsc/call_leg.c
index 03c988205..a8c5c4118 100644
--- a/src/libmsc/call_leg.c
+++ b/src/libmsc/call_leg.c
@@ -324,14 +324,15 @@ struct osmo_sockaddr_str *call_leg_local_ip(struct call_leg *cl, enum rtp_direct
/* Make sure an MGW endpoint CI is set up for an RTP connection.
* This is the one-stop for all to either completely set up a new endpoint connection, or to modify an existing one.
* If not yet present, allocate the rtp_stream for the given direction.
- * Then, call rtp_stream_set_codec() if codec_if_known is non-NULL, and/or rtp_stream_set_remote_addr() if
+ * Then, call rtp_stream_set_codecs() if codecs_if_known is non-NULL, and/or rtp_stream_set_remote_addr() if
* remote_addr_if_known is non-NULL.
* Finally make sure that a CRCX is sent out for this direction, if this has not already happened.
* If the CRCX has already happened but new codec / remote_addr data was passed, call rtp_stream_commit() to trigger an
* MDCX.
*/
int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans,
- const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known)
+ const struct sdp_audio_codecs *codecs_if_known,
+ const struct osmo_sockaddr_str *remote_addr_if_known)
{
if (call_leg_ensure_rtp_alloc(cl, dir, call_id, for_trans))
return -EIO;
@@ -340,8 +341,8 @@ int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t cal
cl->rtp[dir]->use_osmux = true;
cl->rtp[dir]->remote_osmux_cid = -1; /* wildcard */
}
- if (codec_if_known)
- rtp_stream_set_codec(cl->rtp[dir], *codec_if_known);
+ if (codecs_if_known)
+ rtp_stream_set_codecs(cl->rtp[dir], codecs_if_known);
if (remote_addr_if_known && osmo_sockaddr_str_is_nonzero(remote_addr_if_known))
rtp_stream_set_remote_addr(cl->rtp[dir], remote_addr_if_known);
return rtp_stream_ensure_ci(cl->rtp[dir], cl->mgw_endpoint);
@@ -350,25 +351,25 @@ int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t cal
int call_leg_local_bridge(struct call_leg *cl1, uint32_t call_id1, struct gsm_trans *trans1,
struct call_leg *cl2, uint32_t call_id2, struct gsm_trans *trans2)
{
- enum mgcp_codecs codec;
+ struct sdp_audio_codecs *codecs;
cl1->local_bridge = cl2;
cl2->local_bridge = cl1;
/* We may just copy the codec info we have for the RAN side of the first leg to the CN side of both legs. This
* also means that if both legs use different codecs the MGW must perform transcoding on the second leg. */
- if (!cl1->rtp[RTP_TO_RAN] || !cl1->rtp[RTP_TO_RAN]->codec_known) {
+ if (!cl1->rtp[RTP_TO_RAN] || !cl1->rtp[RTP_TO_RAN]->codecs_known) {
LOG_CALL_LEG(cl1, LOGL_ERROR, "RAN-side RTP stream codec is not known, not ready for bridging\n");
return -EINVAL;
}
- codec = cl1->rtp[RTP_TO_RAN]->codec;
+ codecs = &cl1->rtp[RTP_TO_RAN]->codecs;
if (!cl1->rtp[RTP_TO_CN] || !cl2->rtp[RTP_TO_CN])
return -ENOTCONN;
call_leg_ensure_ci(cl1, RTP_TO_CN, call_id1, trans1,
- &codec, &cl2->rtp[RTP_TO_CN]->local);
+ codecs, &cl2->rtp[RTP_TO_CN]->local);
call_leg_ensure_ci(cl2, RTP_TO_CN, call_id2, trans2,
- &codec, &cl1->rtp[RTP_TO_CN]->local);
+ codecs, &cl1->rtp[RTP_TO_CN]->local);
return 0;
}
diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c
index 4a484bb14..269fd5709 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -1822,18 +1822,18 @@ int gsm48_tch_rtp_create(struct gsm_trans *trans)
return -EINVAL;
}
- if (!rtp_cn->codec_known) {
+ if (!rtp_cn->codecs_known) {
LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR,
"Cannot RTP CREATE to MNCC, no codec set up for the RTP CN side\n");
return -EINVAL;
}
/* Codec */
- m = codec_mapping_by_mgcp_codec(rtp_cn->codec);
+ m = codec_mapping_by_subtype_name(rtp_cn->codecs.codec[0].subtype_name);
if (!m) {
LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR,
"Cannot RTP CREATE to MNCC, cannot resolve codec '%s'\n",
- osmo_mgcpc_codec_name(rtp_cn->codec));
+ sdp_audio_codec_to_str(&rtp_cn->codecs.codec[0]));
return -EINVAL;
}
payload_msg_type = m->mncc_payload_msg_type;
@@ -1841,9 +1841,9 @@ int gsm48_tch_rtp_create(struct gsm_trans *trans)
/* Payload Type number */
mgcp_info = osmo_mgcpc_ep_ci_get_rtp_info(rtp_cn->ci);
if (mgcp_info && mgcp_info->ptmap_len)
- payload_type = map_codec_to_pt(mgcp_info->ptmap, mgcp_info->ptmap_len, rtp_cn->codec);
+ payload_type = map_codec_to_pt(mgcp_info->ptmap, mgcp_info->ptmap_len, m->mgcp);
else
- payload_type = rtp_cn->codec;
+ payload_type = m->mgcp;
rtp_cn_local = call_leg_local_ip(cl, RTP_TO_CN);
if (!rtp_cn_local) {
diff --git a/src/libmsc/mncc_call.c b/src/libmsc/mncc_call.c
index fbf96f387..1cf0c3d2d 100644
--- a/src/libmsc/mncc_call.c
+++ b/src/libmsc/mncc_call.c
@@ -263,14 +263,14 @@ static bool mncc_call_rx_rtp_create(struct mncc_call *mncc_call)
return true;
}
- if (!mncc_call->rtps->codec_known) {
+ if (!mncc_call->rtps->codecs_known) {
LOG_MNCC_CALL(mncc_call, LOGL_DEBUG, "Got RTP_CREATE, but RTP stream has no codec set\n");
return true;
}
LOG_MNCC_CALL(mncc_call, LOGL_DEBUG, "Got RTP_CREATE, responding with " OSMO_SOCKADDR_STR_FMT " %s\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&mncc_call->rtps->local),
- osmo_mgcpc_codec_name(mncc_call->rtps->codec));
+ sdp_audio_codecs_to_str(&mncc_call->rtps->codecs));
/* Already know what RTP IP:port to tell the MNCC. Send it. */
return mncc_call_tx_rtp_create(mncc_call);
}
@@ -295,15 +295,16 @@ static bool mncc_call_tx_rtp_create(struct mncc_call *mncc_call)
return false;
}
- if (mncc_call->rtps->codec_known) {
- const struct codec_mapping *m = codec_mapping_by_mgcp_codec(mncc_call->rtps->codec);
+ if (mncc_call->rtps->codecs_known) {
+ struct sdp_audio_codec *codec = &mncc_call->rtps->codecs.codec[0];
+ const struct codec_mapping *m = codec_mapping_by_subtype_name(codec->subtype_name);
if (!m) {
mncc_call_error(mncc_call, "Failed to resolve audio codec '%s'\n",
- osmo_mgcpc_codec_name(mncc_call->rtps->codec));
+ sdp_audio_codec_to_str(codec));
return false;
}
- mncc_msg.rtp.payload_type = m->sdp.payload_type;
+ mncc_msg.rtp.payload_type = codec->payload_type;
mncc_msg.rtp.payload_msg_type = m->mncc_payload_msg_type;
}
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index 7db1d0a40..e9f18407d 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -1327,6 +1327,7 @@ static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct
struct rtp_stream *rtps_to_ran = msc_a->cc.call_leg ? msc_a->cc.call_leg->rtp[RTP_TO_RAN] : NULL;
const enum mgcp_codecs *codec_if_known = ac->assignment_complete.codec_present ?
&ac->assignment_complete.codec : NULL;
+ const struct codec_mapping *codec_cn = NULL;
if (!rtps_to_ran) {
LOG_MSC_A(msc_a, LOGL_ERROR, "Rx Assignment Complete, but no RTP stream is set up\n");
@@ -1344,9 +1345,26 @@ static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct
return;
}
- /* Update RAN-side endpoint CI: */
- if (codec_if_known)
- rtp_stream_set_codec(rtps_to_ran, *codec_if_known);
+ if (codec_if_known) {
+ codec_cn = codec_mapping_by_mgcp_codec(*codec_if_known);
+ if (!codec_cn) {
+ LOG_TRANS(cc_trans, LOGL_ERROR, "Unknown codec in Assignment Complete: %s\n",
+ osmo_mgcpc_codec_name(*codec_if_known));
+ call_leg_release(msc_a->cc.call_leg);
+ return;
+ }
+
+ /* Update RAN-side endpoint CI from Assignment result */
+ rtp_stream_set_one_codec(rtps_to_ran, &codec_cn->sdp);
+
+ /* Update codec filter with Assignment result, for the CN side */
+ cc_trans->cc.codecs.assignment = codec_cn->sdp;
+ } else {
+ /* No codec passed in Assignment Complete, set 'codecs.assignment' to none. */
+ cc_trans->cc.codecs.assignment = (struct sdp_audio_codec){};
+ LOG_TRANS(cc_trans, LOGL_INFO, "Assignment Complete without voice codec\n");
+ }
+
rtp_stream_set_remote_addr(rtps_to_ran, &ac->assignment_complete.remote_rtp);
if (rtps_to_ran->use_osmux)
rtp_stream_set_remote_osmux_cid(rtps_to_ran,
@@ -1364,8 +1382,9 @@ static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct
* endpoint,
* - the Assignment has chosen a speech codec
* go on to create the CN side RTP stream's CI. */
+ codec_filter_run(&cc_trans->cc.codecs);
if (call_leg_ensure_ci(msc_a->cc.call_leg, RTP_TO_CN, cc_trans->callref, cc_trans,
- codec_if_known, NULL)) {
+ &cc_trans->cc.codecs.result.audio_codecs, NULL)) {
LOG_MSC_A_CAT(msc_a, DCC, LOGL_ERROR, "Error creating MGW CI towards CN\n");
call_leg_release(msc_a->cc.call_leg);
return;
@@ -1760,11 +1779,13 @@ static int msc_a_start_assignment(struct msc_a *msc_a, struct gsm_trans *cc_tran
struct call_leg *cl = msc_a->cc.call_leg;
struct msc_i *msc_i = msc_a_msc_i(msc_a);
struct gsm_network *net = msc_a_net(msc_a);
- enum mgcp_codecs codec, *codec_ptr;
+ struct sdp_audio_codecs *codecs;
OSMO_ASSERT(!msc_a->cc.active_trans);
msc_a->cc.active_trans = cc_trans;
+ cc_trans->cc.codecs.assignment = (struct sdp_audio_codec){};
+
OSMO_ASSERT(cc_trans && cc_trans->type == TRANS_CC);
if (!cl) {
@@ -1785,20 +1806,17 @@ static int msc_a_start_assignment(struct msc_a *msc_a, struct gsm_trans *cc_tran
}
}
- /* This will lead to either MSC_EV_CALL_LEG_LOCAL_ADDR_AVAILABLE or MSC_EV_CALL_LEG_TERM.
- * If the local address is already known, then immediately trigger. */
+ /* Make sure an MGW endpoint towards RAN is present. If it is already set up, "skip" to
+ * MSC_EV_CALL_LEG_LOCAL_ADDR_AVAILABLE immediately. If not, set it up. */
if (call_leg_local_ip(cl, RTP_TO_RAN))
return osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, cl->rtp[RTP_TO_RAN]);
- if (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU) {
- /* FUTURE: ran_infra->force_mgw_codecs_to_ran is intended to be used here instead of the special
- * condition on OSMO_RAT_UTRAN_IU and the mgcp_codecs value CODEC_IUFP */
- codec = CODEC_IUFP;
- codec_ptr = &codec;
- } else {
- codec_ptr = NULL;
- }
- return call_leg_ensure_ci(msc_a->cc.call_leg, RTP_TO_RAN, cc_trans->callref, cc_trans, codec_ptr, NULL);
+ codec_filter_run(&cc_trans->cc.codecs);
+ if (msc_a->c.ran->force_mgw_codecs_to_ran.count)
+ codecs = &msc_a->c.ran->force_mgw_codecs_to_ran;
+ else
+ codecs = &cc_trans->cc.codecs.result.audio_codecs;
+ return call_leg_ensure_ci(msc_a->cc.call_leg, RTP_TO_RAN, cc_trans->callref, cc_trans, codecs, NULL);
}
int msc_a_try_call_assignment(struct gsm_trans *cc_trans)
diff --git a/src/libmsc/msc_ho.c b/src/libmsc/msc_ho.c
index 7e7905bb7..d53bb9e4d 100644
--- a/src/libmsc/msc_ho.c
+++ b/src/libmsc/msc_ho.c
@@ -39,6 +39,7 @@
#include <osmocom/msc/call_leg.h>
#include <osmocom/msc/rtp_stream.h>
#include <osmocom/msc/mncc_call.h>
+#include <osmocom/msc/codec_mapping.h>
struct osmo_fsm msc_ho_fsm;
@@ -570,7 +571,7 @@ static int msc_ho_start_inter_msc_call_forwarding(struct msc_a *msc_a, struct ms
/* Backup old cell's RTP IP:port and codec data */
msc_a->ho.old_cell.ran_remote_rtp = rtp_to_ran->remote;
- msc_a->ho.old_cell.codec = rtp_to_ran->codec;
+ msc_a->ho.old_cell.codecs = rtp_to_ran->codecs;
/* Blindly taken over from an MNCC trace of existing code: send an all-zero CCCAP: */
outgoing_call_req.fields |= MNCC_F_CCCAP;
@@ -707,7 +708,7 @@ static void msc_ho_rtp_switch_to_new_cell(struct msc_a *msc_a)
/* Backup old cell's RTP IP:port and codec data */
msc_a->ho.old_cell.ran_remote_rtp = rtp_to_ran->remote;
- msc_a->ho.old_cell.codec = rtp_to_ran->codec;
+ msc_a->ho.old_cell.codecs = rtp_to_ran->codecs;
LOG_HO(msc_a, LOGL_DEBUG, "Switching RTP stream to new cell: from " OSMO_SOCKADDR_STR_FMT " to " OSMO_SOCKADDR_STR_FMT "\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&msc_a->ho.old_cell.ran_remote_rtp),
@@ -726,10 +727,17 @@ static void msc_ho_rtp_switch_to_new_cell(struct msc_a *msc_a)
/* Switch over to the new peer */
rtp_stream_set_remote_addr(rtp_to_ran, &msc_a->ho.new_cell.ran_remote_rtp);
- if (msc_a->ho.new_cell.codec_present)
- rtp_stream_set_codec(rtp_to_ran, msc_a->ho.new_cell.codec);
- else
+ if (msc_a->ho.new_cell.codec_present) {
+ struct sdp_audio_codecs codecs = {};
+ if (!sdp_audio_codecs_add_mgcp_codec(&codecs, msc_a->ho.new_cell.codec)) {
+ LOG_HO(msc_a, LOGL_ERROR,
+ "Cannot resolve codec: %s\n", osmo_mgcpc_codec_name(msc_a->ho.new_cell.codec));
+ } else {
+ rtp_stream_set_codecs(rtp_to_ran, &codecs);
+ }
+ } else {
LOG_HO(msc_a, LOGL_ERROR, "No codec is set\n");
+ }
rtp_stream_commit(rtp_to_ran);
}
@@ -768,7 +776,7 @@ static void msc_ho_rtp_rollback_to_old_cell(struct msc_a *msc_a)
/* Switch back to the old cell */
rtp_stream_set_remote_addr(rtp_to_ran, &msc_a->ho.old_cell.ran_remote_rtp);
- rtp_stream_set_codec(rtp_to_ran, msc_a->ho.old_cell.codec);
+ rtp_stream_set_codecs(rtp_to_ran, &msc_a->ho.old_cell.codecs);
rtp_stream_commit(rtp_to_ran);
}
diff --git a/src/libmsc/msc_t.c b/src/libmsc/msc_t.c
index 43bc74e0c..787d7362f 100644
--- a/src/libmsc/msc_t.c
+++ b/src/libmsc/msc_t.c
@@ -450,9 +450,9 @@ static int msc_t_patch_and_send_ho_request_ack(struct msc_t *msc_t, const struct
if (r->codec_present) {
LOG_MSC_T(msc_t, LOGL_DEBUG, "From Handover Request Ack, got %s\n",
osmo_mgcpc_codec_name(r->codec));
- rtp_stream_set_codec(rtp_ran, r->codec);
+ rtp_stream_set_codecs_from_mgcp_codec(rtp_ran, r->codec);
if (rtp_cn)
- rtp_stream_set_codec(rtp_cn, r->codec);
+ rtp_stream_set_codecs_from_mgcp_codec(rtp_cn, r->codec);
} else {
LOG_MSC_T(msc_t, LOGL_DEBUG, "No codec in Handover Request Ack\n");
}
diff --git a/src/libmsc/rtp_stream.c b/src/libmsc/rtp_stream.c
index b7e7381f3..ac444148e 100644
--- a/src/libmsc/rtp_stream.c
+++ b/src/libmsc/rtp_stream.c
@@ -28,6 +28,7 @@
#include <osmocom/msc/transaction.h>
#include <osmocom/msc/call_leg.h>
#include <osmocom/msc/rtp_stream.h>
+#include <osmocom/msc/codec_mapping.h>
#define LOG_RTPS(rtps, level, fmt, args...) \
LOGPFSML(rtps->fi, level, fmt, ##args)
@@ -78,10 +79,10 @@ void rtp_stream_update_id(struct rtp_stream *rtps)
OSMO_STRBUF_PRINTF(sb, ":no-remote-port");
else if (!rtps->remote_sent_to_mgw)
OSMO_STRBUF_PRINTF(sb, ":remote-port-not-sent");
- if (!rtps->codec_known)
- OSMO_STRBUF_PRINTF(sb, ":no-codec");
- else if (!rtps->codec_sent_to_mgw)
- OSMO_STRBUF_PRINTF(sb, ":codec-not-sent");
+ if (!rtps->codecs_known)
+ OSMO_STRBUF_PRINTF(sb, ":no-codecs");
+ else if (!rtps->codecs_sent_to_mgw)
+ OSMO_STRBUF_PRINTF(sb, ":codecs-not-sent");
if (rtps->use_osmux) {
if (rtps->remote_osmux_cid < 0)
OSMO_STRBUF_PRINTF(sb, ":no-remote-osmux-cid");
@@ -141,7 +142,7 @@ static void check_established(struct rtp_stream *rtps)
&& osmo_sockaddr_str_is_nonzero(&rtps->remote)
&& rtps->remote_sent_to_mgw
&& (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw)
- && rtps->codec_known)
+ && rtps->codecs_known)
rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHED);
}
@@ -171,14 +172,14 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui
osmo_fsm_inst_dispatch(fi->proc.parent, CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE, rtps);
check_established(rtps);
- if ((!rtps->remote_sent_to_mgw || !rtps->codec_sent_to_mgw)
+ if ((!rtps->remote_sent_to_mgw || !rtps->codecs_sent_to_mgw)
&& osmo_sockaddr_str_is_nonzero(&rtps->remote)
&& (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw)
- && rtps->codec_known) {
+ && rtps->codecs_known) {
LOG_RTPS(rtps, LOGL_DEBUG,
"local ip:port set;%s%s%s triggering MDCX to send the new settings\n",
- (!rtps->remote_sent_to_mgw)? " remote ip:port not yet sent," : "",
- (!rtps->codec_sent_to_mgw)? " codec not yet sent," : "",
+ (!rtps->remote_sent_to_mgw) ? " remote ip:port not yet sent," : "",
+ (!rtps->codecs_sent_to_mgw) ? " codecs not yet sent," : "",
(rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw) ? "Osmux CID not yet sent,": "");
rtp_stream_do_mdcx(rtps);
}
@@ -192,7 +193,7 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui
case RTP_STREAM_EV_CRCX_FAIL:
case RTP_STREAM_EV_MDCX_FAIL:
rtps->remote_sent_to_mgw = false;
- rtps->codec_sent_to_mgw = false;
+ rtps->codecs_sent_to_mgw = false;
rtps->remote_osmux_cid_sent_to_mgw = false;
rtp_stream_update_id(rtps);
rtp_stream_state_chg(rtps, RTP_STREAM_ST_DISCARDING);
@@ -310,10 +311,28 @@ static int rtp_stream_do_mgcp_verb(struct rtp_stream *rtps, enum mgcp_verb verb,
if (verb == MGCP_VERB_CRCX)
verb_info.conn_mode = rtps->crcx_conn_mode;
- if (rtps->codec_known) {
- verb_info.codecs[0] = rtps->codec;
- verb_info.codecs_len = 1;
- rtps->codec_sent_to_mgw = true;
+ if (rtps->codecs_known) {
+ /* Send the list of codecs to the MGW. Ideally we would just feed the SDP directly, but for legacy
+ * reasons we still need to translate to a struct mgcp_conn_peer representation to send it. */
+ struct sdp_audio_codec *codec;
+ int i = 0;
+ foreach_sdp_audio_codec(codec, &rtps->codecs) {
+ const struct codec_mapping *m = codec_mapping_by_subtype_name(codec->subtype_name);
+ if (!m) {
+ LOG_RTPS(rtps, LOGL_ERROR, "Cannot map codec '%s' to MGCP: codec is unknown\n",
+ codec->subtype_name);
+ continue;
+ }
+ verb_info.codecs[i] = m->mgcp;
+ verb_info.ptmap[i] = (struct ptmap){
+ .codec = m->mgcp,
+ .pt = codec->payload_type,
+ };
+ i++;
+ verb_info.codecs_len = i;
+ verb_info.ptmap_len = i;
+ }
+ rtps->codecs_sent_to_mgw = true;
}
if (osmo_sockaddr_str_is_nonzero(&rtps->remote)) {
int rc = osmo_strlcpy(verb_info.addr, rtps->remote.ip, sizeof(verb_info.addr));
@@ -368,12 +387,12 @@ int rtp_stream_commit(struct rtp_stream *rtps)
LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no remote RTP address known\n");
return -1;
}
- if (!rtps->codec_known) {
- LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no codec known\n");
+ if (!rtps->codecs_known) {
+ LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no codecs known\n");
return -1;
}
- if (rtps->remote_sent_to_mgw && rtps->codec_sent_to_mgw) {
- LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: both remote RTP address and codec already set up at MGW\n");
+ if (rtps->remote_sent_to_mgw && rtps->codecs_sent_to_mgw) {
+ LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: both remote RTP address and codecs already set up at MGW\n");
return 0;
}
if (!rtps->ci) {
@@ -383,22 +402,47 @@ int rtp_stream_commit(struct rtp_stream *rtps)
LOG_RTPS(rtps, LOGL_DEBUG, "Committing: Tx MDCX to update the MGW: updating%s%s%s\n",
rtps->remote_sent_to_mgw ? "" : " remote-RTP-IP-port",
- rtps->codec_sent_to_mgw ? "" : " codec",
+ rtps->codecs_sent_to_mgw ? "" : " codecs",
(!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) ? "" : " remote-Osmux-CID");
return rtp_stream_do_mdcx(rtps);
}
-void rtp_stream_set_codec(struct rtp_stream *rtps, enum mgcp_codecs codec)
+void rtp_stream_set_codecs(struct rtp_stream *rtps, const struct sdp_audio_codecs *codecs)
{
+ if (!codecs || !codecs->count)
+ return;
+ if (sdp_audio_codecs_cmp(&rtps->codecs, codecs, false, true) == 0) {
+ LOG_RTPS(rtps, LOGL_DEBUG, "no change: codecs already set to %s\n",
+ sdp_audio_codecs_to_str(&rtps->codecs));
+ return;
+ }
if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED)
rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHING);
- LOG_RTPS(rtps, LOGL_DEBUG, "setting codec to %s\n", osmo_mgcpc_codec_name(codec));
- rtps->codec = codec;
- rtps->codec_known = true;
- rtps->codec_sent_to_mgw = false;
+ LOG_RTPS(rtps, LOGL_DEBUG, "setting codecs to %s\n", sdp_audio_codecs_to_str(codecs));
+ rtps->codecs = *codecs;
+ rtps->codecs_known = true;
+ rtps->codecs_sent_to_mgw = false;
rtp_stream_update_id(rtps);
}
+/* Convenience shortcut to call rtp_stream_set_codecs() with a list of only one sdp_audio_codec record. */
+void rtp_stream_set_one_codec(struct rtp_stream *rtps, const struct sdp_audio_codec *codec)
+{
+ struct sdp_audio_codecs codecs = {};
+ sdp_audio_codecs_add_copy(&codecs, codec);
+ rtp_stream_set_codecs(rtps, &codecs);
+}
+
+/* For legacy, rather use rtp_stream_set_codecs() with a full codecs list. */
+bool rtp_stream_set_codecs_from_mgcp_codec(struct rtp_stream *rtps, enum mgcp_codecs codec)
+{
+ struct sdp_audio_codecs codecs = {};
+ if (!sdp_audio_codecs_add_mgcp_codec(&codecs, codec))
+ return false;
+ rtp_stream_set_codecs(rtps, &codecs);
+ return true;
+}
+
void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_sockaddr_str *r)
{
if (osmo_sockaddr_str_cmp(&rtps->remote, r) == 0) {
@@ -433,7 +477,7 @@ bool rtp_stream_is_established(struct rtp_stream *rtps)
if (rtps->fi->state != RTP_STREAM_ST_ESTABLISHED)
return false;
if (!rtps->remote_sent_to_mgw
- || !rtps->codec_sent_to_mgw
+ || !rtps->codecs_sent_to_mgw
|| (rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw))
return false;
return true;