neels has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-msc/+/30125 )

 (

7 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted 
one.
 )Change subject: rtp_stream: allow multiple codecs / use codec filter from 
Assignment
......................................................................

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
---
M include/osmocom/msc/call_leg.h
M include/osmocom/msc/msc_ho.h
M include/osmocom/msc/rtp_stream.h
M src/libmsc/call_leg.c
M src/libmsc/gsm_04_08_cc.c
M src/libmsc/mncc_call.c
M src/libmsc/msc_a.c
M src/libmsc/msc_ho.c
M src/libmsc/msc_t.c
M src/libmsc/rtp_stream.c
M tests/msc_vlr/msc_vlr_test_call.err
M tests/msc_vlr/msc_vlr_tests.c
12 files changed, 205 insertions(+), 106 deletions(-)

Approvals:
  laforge: Looks good to me, but someone else must approve
  pespin: Looks good to me, but someone else must approve
  neels: Looks good to me, approved
  Jenkins Builder: Verified




diff --git a/include/osmocom/msc/call_leg.h b/include/osmocom/msc/call_leg.h
index a225b66..c7d3b97 100644
--- a/include/osmocom/msc/call_leg.h
+++ b/include/osmocom/msc/call_leg.h
@@ -12,6 +12,7 @@
 struct gsm_trans;
 struct rtp_stream;
 enum rtp_direction;
+struct sdp_audio_codecs;

 extern struct osmo_tdef g_mgw_tdefs[];

@@ -74,7 +75,8 @@
 int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, 
uint32_t call_id,
                              struct gsm_trans *for_trans);
 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);
 struct osmo_sockaddr_str *call_leg_local_ip(struct call_leg *cl, enum 
rtp_direction dir);

 void call_leg_rtp_stream_gone(struct call_leg *cl, struct rtp_stream *rtps);
diff --git a/include/osmocom/msc/msc_ho.h b/include/osmocom/msc/msc_ho.h
index 99956f1..a3f60c7 100644
--- a/include/osmocom/msc/msc_ho.h
+++ b/include/osmocom/msc/msc_ho.h
@@ -31,7 +31,7 @@
 #include <osmocom/msc/neighbor_ident.h>
 #include <osmocom/msc/ran_msg.h>
 #include <osmocom/msc/mncc_call.h>
-
+#include <osmocom/msc/sdp_msg.h>

 struct gsm0808_handover_required;

@@ -92,7 +92,7 @@
        struct {
                /* Saved RTP IP:port and codec in case we need to roll back */
                struct osmo_sockaddr_str ran_remote_rtp;
-               enum mgcp_codecs codec;
+               struct sdp_audio_codecs codecs;
        } old_cell;
 };

diff --git a/include/osmocom/msc/rtp_stream.h b/include/osmocom/msc/rtp_stream.h
index c53c4f1..afc5725 100644
--- a/include/osmocom/msc/rtp_stream.h
+++ b/include/osmocom/msc/rtp_stream.h
@@ -5,6 +5,7 @@

 #include <osmocom/core/sockaddr_str.h>
 #include <osmocom/mgcp_client/mgcp_client.h>
+#include <osmocom/msc/sdp_msg.h>

 struct gsm_trans;

@@ -37,9 +38,9 @@
        struct osmo_sockaddr_str remote;
        bool remote_sent_to_mgw;

-       bool codec_known;
-       enum mgcp_codecs codec;
-       bool codec_sent_to_mgw;
+       bool codecs_known;
+       struct sdp_audio_codecs codecs;
+       bool codecs_sent_to_mgw;

        struct osmo_mgcpc_ep_ci *ci;

@@ -64,7 +65,9 @@
 int rtp_stream_ensure_ci(struct rtp_stream *rtps, struct osmo_mgcpc_ep 
*at_endpoint);
 int rtp_stream_do_mdcx(struct rtp_stream *rtps);

-void rtp_stream_set_codec(struct rtp_stream *rtps, enum mgcp_codecs codec);
+bool rtp_stream_set_codecs_from_mgcp_codec(struct rtp_stream *rtps, enum 
mgcp_codecs codec);
+void rtp_stream_set_one_codec(struct rtp_stream *rtps, const struct 
sdp_audio_codec *codec);
+void rtp_stream_set_codecs(struct rtp_stream *rtps, const struct 
sdp_audio_codecs *codecs);
 void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct 
osmo_sockaddr_str *r);
 void rtp_stream_set_remote_osmux_cid(struct rtp_stream *rtps, uint8_t 
osmux_cid);
 int rtp_stream_commit(struct rtp_stream *rtps);
diff --git a/src/libmsc/call_leg.c b/src/libmsc/call_leg.c
index 03c9882..a8c5c41 100644
--- a/src/libmsc/call_leg.c
+++ b/src/libmsc/call_leg.c
@@ -324,14 +324,15 @@
 /* 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 @@
                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_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 4a484bb..269fd57 100644
--- a/src/libmsc/gsm_04_08_cc.c
+++ b/src/libmsc/gsm_04_08_cc.c
@@ -1822,18 +1822,18 @@
                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 @@
        /* 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 fbf96f3..1cf0c3d 100644
--- a/src/libmsc/mncc_call.c
+++ b/src/libmsc/mncc_call.c
@@ -263,14 +263,14 @@
                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 @@
                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 7db1d0a..e9f1840 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -1327,6 +1327,7 @@
        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 @@
                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 @@
         *   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 @@
        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 @@
                }
        }

-       /* 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 7e7905b..d53bb9e 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 @@

        /* 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 @@

        /* 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 @@

        /* 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 @@

        /* 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 43bc74e..787d736 100644
--- a/src/libmsc/msc_t.c
+++ b/src/libmsc/msc_t.c
@@ -450,9 +450,9 @@
                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 b7e7381..ac44414 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 @@
                        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 @@
            && 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 @@
                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 @@
        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 @@
        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 @@
                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 @@

        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 @@
        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;
diff --git a/tests/msc_vlr/msc_vlr_test_call.err 
b/tests/msc_vlr/msc_vlr_test_call.err
index fbe2601..877015a 100644
--- a/tests/msc_vlr/msc_vlr_test_call.err
+++ b/tests/msc_vlr/msc_vlr_test_call.err
@@ -301,10 +301,10 @@
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 Starting call assignment
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Allocated
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 is child of 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000001
+  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000001 
codecs=VND.3GPP.IUFP/16000#96
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to VND.3GPP.IUFP/16000
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to VND.3GPP.IUFP/16000#96
 - MGW acknowledges the CRCX, triggering Assignment
   MGW --CRCX OK to RTP_TO_RAN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -314,13 +314,13 @@
 DMSC 
dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}:
 Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
 - Assignment succeeds, triggering CRCX to CN
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 RAN decode: ASSIGNMENT_COMPLETE
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}:
 setting remote addr to 1.2.3.4:1234
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}:
 Not committing: no MGW endpoint CI set up
-  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000001
+  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000001 
codecs=AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 - CN RTP address is available, trigger MNCC_RTP_CREATE
   MGW --CRCX OK to RTP_TO_CN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -779,10 +779,10 @@
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 Starting call assignment
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 Allocated
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 is child of 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423
+  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423 codecs=VND.3GPP.IUFP/16000#96
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to VND.3GPP.IUFP/16000
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to VND.3GPP.IUFP/16000#96
 DMNCC trans(CC:MO_TERM_CALL_CONF 
IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP 
callref-0x423 tid-0) tx MNCC_CALL_CONF_IND
   MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND
 DREF 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 - rx_from_ms: now used by 1 (cc)
@@ -800,13 +800,13 @@
 DMSC 
dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}:
 Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
 - Assignment completes, triggering CRCX to CN
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 RAN decode: ASSIGNMENT_COMPLETE
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}:
 setting remote addr to 1.2.3.4:1234
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}:
 Not committing: no MGW endpoint CI set up
-  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423
+  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423 codecs=AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 - When the CN side RTP address is known, send MNCC_RTP_CREATE
   MGW --CRCX OK to RTP_TO_CN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -1249,10 +1249,10 @@
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 Starting call assignment
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 Allocated
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 is child of 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423
+  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423 codecs=VND.3GPP.IUFP/16000#96
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to VND.3GPP.IUFP/16000
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to VND.3GPP.IUFP/16000#96
 DMNCC trans(CC:MO_TERM_CALL_CONF 
IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP 
callref-0x423 tid-0) tx MNCC_CALL_CONF_IND
   MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND
 DREF 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 - rx_from_ms: now used by 1 (cc)
@@ -1270,13 +1270,13 @@
 DMSC 
dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}:
 Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
 - Assignment completes, triggering CRCX to CN
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}:
 RAN decode: ASSIGNMENT_COMPLETE
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}:
 setting remote addr to 1.2.3.4:1234
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}:
 Not committing: no MGW endpoint CI set up
-  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423
+  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423 codecs=AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 - When the CN side RTP address is known, send MNCC_RTP_CREATE
   MGW --CRCX OK to RTP_TO_CN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -1667,10 +1667,10 @@
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 Starting call assignment
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Allocated
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 is child of 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000002
+  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000002 
codecs=VND.3GPP.IUFP/16000#96
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to VND.3GPP.IUFP/16000
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to VND.3GPP.IUFP/16000#96
 - MGW acknowledges the CRCX, triggering Assignment
   MGW --CRCX OK to RTP_TO_RAN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -1680,13 +1680,13 @@
 DMSC 
dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}:
 Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
 - Assignment succeeds, triggering CRCX to CN
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 RAN decode: ASSIGNMENT_COMPLETE
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}:
 setting remote addr to 1.2.3.4:1234
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}:
 Not committing: no MGW endpoint CI set up
-  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000002
+  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000002 
codecs=AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 - CN RTP address is available, trigger MNCC_RTP_CREATE
   MGW --CRCX OK to RTP_TO_CN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -2094,10 +2094,10 @@
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 Starting call assignment
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Allocated
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 is child of 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000003
+  MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000003 
codecs=VND.3GPP.IUFP/16000#96
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to VND.3GPP.IUFP/16000
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to VND.3GPP.IUFP/16000#96
 - MGW acknowledges the CRCX, triggering Assignment
   MGW --CRCX OK to RTP_TO_RAN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
@@ -2107,13 +2107,13 @@
 DMSC 
dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}:
 Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST
 - Assignment succeeds, triggering CRCX to CN
 DIUCS 
msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}:
 RAN decode: ASSIGNMENT_COMPLETE
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}:
 setting remote addr to 1.2.3.4:1234
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}:
 Not committing: no MGW endpoint CI set up
-  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000003
+  MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000003 
codecs=AMR:octet-align=1#112
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 Allocated
 DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}:
 is child of 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)
-DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codec to AMR/8000/1
+DCC 
rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}:
 setting codecs to AMR:octet-align=1#112
 - CN RTP address is available, trigger MNCC_RTP_CREATE
   MGW --CRCX OK to RTP_TO_CN--> MSC
 DCC 
call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}:
 Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
index b0c60ed..45b97a2 100644
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ b/tests/msc_vlr/msc_vlr_tests.c
@@ -41,6 +41,7 @@
 #include <osmocom/msc/msc_t.h>
 #include <osmocom/msc/call_leg.h>
 #include <osmocom/msc/rtp_stream.h>
+#include <osmocom/msc/codec_mapping.h>

 #include "msc_vlr_tests.h"

@@ -852,20 +853,23 @@

 /* override, requires '-Wl,--wrap=call_leg_ensure_ci' */
 int __real_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);
 int __wrap_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 (!cl->rtp[dir]) {
-               log("MGW <--CRCX to %s-- MSC: callref=0x%x", 
rtp_direction_name(dir), call_id);
+               log("MGW <--CRCX to %s-- MSC: callref=0x%x codecs=%s", 
rtp_direction_name(dir), call_id,
+                   codecs_if_known ? sdp_audio_codecs_to_str(codecs_if_known) 
: "unset");

                OSMO_ASSERT(expecting_crcx == dir);
                expecting_crcx = -1;
                got_crcx = true;

                call_leg_ensure_rtp_alloc(cl, dir, call_id, for_trans);
-               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);
        }

--
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/30125
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: If9c67b298b30f893ec661f84c9fc622ad01b5ee5
Gerrit-Change-Number: 30125
Gerrit-PatchSet: 9
Gerrit-Owner: neels <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: neels <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to