diff --git a/include/osmocom/mgcp/mgcp_codec.h b/include/osmocom/mgcp/mgcp_codec.h index 1f29b0888..cfc8ecf06 100644 --- a/include/osmocom/mgcp/mgcp_codec.h +++ b/include/osmocom/mgcp/mgcp_codec.h @@ -13,8 +13,7 @@ struct mgcp_conn_rtp; void mgcp_codec_summary(struct mgcp_conn_rtp *conn); void mgcp_codec_reset_all(struct mgcp_conn_rtp *conn); int mgcp_codec_add(struct mgcp_conn_rtp *conn, int payload_type, const char *audio_name, const struct mgcp_codec_param *param); -int mgcp_codec_decide(struct mgcp_conn_rtp *conn); -struct mgcp_rtp_codec *mgcp_codec_find_convertible(struct mgcp_conn_rtp *conn, struct mgcp_rtp_codec *codec); +int mgcp_codec_decide(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst); const struct mgcp_rtp_codec *mgcp_codec_pt_find_by_subtype_name(struct mgcp_conn_rtp *conn, const char *subtype_name, unsigned int match_nr); bool mgcp_codec_amr_align_mode_is_indicated(const struct mgcp_rtp_codec *codec); diff --git a/include/osmocom/mgcp/mgcp_trunk.h b/include/osmocom/mgcp/mgcp_trunk.h index 33c3d5b03..e608161ed 100644 --- a/include/osmocom/mgcp/mgcp_trunk.h +++ b/include/osmocom/mgcp/mgcp_trunk.h @@ -31,8 +31,6 @@ struct mgcp_trunk { int audio_send_ptime; int audio_send_name; - int no_audio_transcoding; - int omit_rtcp; int keepalive_interval; diff --git a/src/libosmo-mgcp/mgcp_codec.c b/src/libosmo-mgcp/mgcp_codec.c index 7fada78ee..905795c71 100644 --- a/src/libosmo-mgcp/mgcp_codec.c +++ b/src/libosmo-mgcp/mgcp_codec.c @@ -344,11 +344,30 @@ static bool codecs_convertible(struct mgcp_rtp_codec *codec_a, struct mgcp_rtp_c return true; } -/*! For a given codec, find a convertible codec in the given connection. - * \param[in] conn connection to search for a convertible codec - * \param[in] codec for which a convertible codec shall be found. - * \returns codec on success, -NULL on failure. */ -struct mgcp_rtp_codec *mgcp_codec_find_convertible(struct mgcp_conn_rtp *conn, struct mgcp_rtp_codec *codec) +struct mgcp_rtp_codec *mgcp_codec_find_same(struct mgcp_conn_rtp *conn, struct mgcp_rtp_codec *codec) +{ + struct mgcp_rtp_end *rtp_end; + unsigned int i; + unsigned int codecs_assigned; + + rtp_end = &conn->end; + + /* Use the codec information from the source and try to find the equivalent of it on the destination side. In + * the first run we will look for an exact match. */ + codecs_assigned = rtp_end->codecs_assigned; + OSMO_ASSERT(codecs_assigned <= MGCP_MAX_CODECS); + for (i = 0; i < codecs_assigned; i++) { + if (codecs_same(codec, &rtp_end->codecs[i])) { + return &rtp_end->codecs[i]; + break; + } + } + + return NULL; +} + +/* For a given codec, find a convertible codec in the given connection. */ +static struct mgcp_rtp_codec *codec_find_convertible(struct mgcp_conn_rtp *conn, struct mgcp_rtp_codec *codec) { struct mgcp_rtp_end *rtp_end; unsigned int i; @@ -359,93 +378,72 @@ struct mgcp_rtp_codec *mgcp_codec_find_convertible(struct mgcp_conn_rtp *conn, s /* Use the codec information from the source and try to find the equivalent of it on the destination side. In * the first run we will look for an exact match. */ - codecs_assigned = rtp_end->codecs_assigned; - OSMO_ASSERT(codecs_assigned <= MGCP_MAX_CODECS); - for (i = 0; i < codecs_assigned; i++) { - if (codecs_same(codec, &rtp_end->codecs[i])) { - codec_convertible = &rtp_end->codecs[i]; - break; - } - } + codec_convertible = mgcp_codec_find_same(conn, codec); + if (codec_convertible) + return codec_convertible; /* In case we weren't able to find an exact match, we will try to find a match that is the same codec, but the * payload format may be different. This alternative will require a frame format conversion (i.e. AMR bwe->oe) */ - if (!codec_convertible) { - for (i = 0; i < codecs_assigned; i++) { - if (codecs_convertible(codec, &rtp_end->codecs[i])) { - codec_convertible = &rtp_end->codecs[i]; - break; - } + codecs_assigned = rtp_end->codecs_assigned; + OSMO_ASSERT(codecs_assigned <= MGCP_MAX_CODECS); + for (i = 0; i < codecs_assigned; i++) { + if (codecs_convertible(codec, &rtp_end->codecs[i])) { + codec_convertible = &rtp_end->codecs[i]; + break; } } return codec_convertible; } -/* Check if the given codec is applicable on the specified endpoint - * Helper function for mgcp_codec_decide() */ -static bool is_codec_compatible(const struct mgcp_endpoint *endp, const struct mgcp_rtp_codec *codec) -{ - /* A codec name must be set, if not, this might mean that the codec - * (payload type) that was assigned is unknown to us so we must stop - * here. */ - if (!strlen(codec->subtype_name)) - return false; - - /* FIXME: implement meaningful checks to make sure that the given codec - * is compatible with the given endpoint */ - - return true; -} - -/*! Decide for one suitable codec - * \param[in] conn related rtp-connection. +/*! Decide for one suitable codec on both of the given connections. In case a destination connection is not available, + * a tentative decision is made. + * \param[inout] conn_src related rtp-connection. + * \param[inout] conn_dst related destination rtp-connection (NULL if not present). * \returns 0 on success, -EINVAL on failure. */ -int mgcp_codec_decide(struct mgcp_conn_rtp *conn) +int mgcp_codec_decide(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst) { - struct mgcp_rtp_end *rtp; unsigned int i; - struct mgcp_endpoint *endp; - bool codec_assigned = false; - endp = conn->conn->endp; - rtp = &conn->end; - - /* This function works on the results the SDP/LCO parser has extracted - * from the MGCP message. The goal is to select a suitable codec for - * the given connection. When transcoding is available, the first codec - * from the codec list is taken without further checking. When - * transcoding is not available, then the choice must be made more - * carefully. Each codec in the list is checked until one is found that - * is rated compatible. The rating is done by the helper function - * is_codec_compatible(), which does the actual checking. */ - for (i = 0; i < rtp->codecs_assigned; i++) { - /* When no transcoding is available, avoid codecs that would - * require transcoding. */ - if (endp->trunk->no_audio_transcoding && !is_codec_compatible(endp, &rtp->codecs[i])) { - LOGP(DLMGCP, LOGL_NOTICE, "transcoding not available, skipping codec: %d/%s\n", - rtp->codecs[i].payload_type, rtp->codecs[i].subtype_name); - continue; - } - - rtp->codec = &rtp->codecs[i]; - codec_assigned = true; - break; + /* In case no destination connection is available (yet), or in case the destination connection exists but has + * no codecs assigned, we are forced to make a simple tentative decision: + * We just use the first codec of the source connection (conn_src) */ + OSMO_ASSERT(conn_src->end.codecs_assigned <= MGCP_MAX_CODECS); + if (!conn_dst || conn_dst->end.codecs_assigned == 0) { + if (conn_src->end.codecs_assigned >= 1) { + conn_src->end.codec = &conn_src->end.codecs[0]; + return 0; + } else + return -EINVAL; } - /* FIXME: To the reviewes: This is problematic. I do not get why we - * need to reset the packet_duration_ms depending on the codec - * selection. I thought it were all 20ms? Is this to address some - * cornercase. (This piece of code was in the code path before, - * together with the note: "TODO/XXX: Store this per codec and derive - * it on use" */ - if (codec_assigned) { - if (rtp->maximum_packet_time >= 0 - && rtp->maximum_packet_time * rtp->codec->frame_duration_den > - rtp->codec->frame_duration_num * 1500) - rtp->packet_duration_ms = 0; + /* Compare all codecs of the source connection (conn_src) to the codecs of the destination connection (conn_dst). In case + * of a match set this codec on both connections. This would be an ideal selection since no codec conversion would be + * required. */ + for (i = 0; i < conn_src->end.codecs_assigned; i++) { + struct mgcp_rtp_codec *codec_conn_dst = mgcp_codec_find_same(conn_dst, &conn_src->end.codecs[i]); + if (codec_conn_dst) { + /* We found the a codec that is exactly the same (same codec, same payload format etc.) on both + * sides. We now set this codec on both connections. */ + conn_dst->end.codec = codec_conn_dst; + conn_src->end.codec = mgcp_codec_find_same(conn_src, codec_conn_dst); + OSMO_ASSERT(conn_src->end.codec); + return 0; + } + } - return 0; + /* In case we could not find a codec that is exactly the same, let's at least try to find a codec that we are able + * to convert. */ + for (i = 0; i < conn_src->end.codecs_assigned; i++) { + struct mgcp_rtp_codec *codec_conn_dst = codec_find_convertible(conn_dst, &conn_src->end.codecs[i]); + if (codec_conn_dst) { + /* We found the a codec that we are able to convert on both sides. We now set this codec on both + * connections. */ + conn_dst->end.codec = codec_conn_dst; + conn_src->end.codec = codec_find_convertible(conn_src, codec_conn_dst); + OSMO_ASSERT(conn_src->end.codec); + return 0; + } } return -EINVAL; diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c index ea1a699d8..6b1690717 100644 --- a/src/libosmo-mgcp/mgcp_network.c +++ b/src/libosmo-mgcp/mgcp_network.c @@ -492,32 +492,24 @@ void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp, /* There may be different payload type numbers negotiated for two connections. * Patch the payload type of an RTP packet so that it uses the payload type - * that is valid for the destination connection (conn_dst) */ -static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src, struct mgcp_conn_rtp *conn_dst, struct msgb *msg) + * of the codec that is set for the destination connection (conn_dst) */ +static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_dst, struct msgb *msg) { struct rtp_hdr *rtp_hdr; - struct mgcp_rtp_codec *codec_src; - struct mgcp_rtp_codec *codec_dst; if (msgb_length(msg) < sizeof(struct rtp_hdr)) { - LOG_CONN_RTP(conn_src, LOGL_ERROR, "RTP packet too short (%u < %zu)\n", + LOG_CONN_RTP(conn_dst, LOGL_NOTICE, "RTP packet too short (%u < %zu)\n", msgb_length(msg), sizeof(struct rtp_hdr)); return -EINVAL; } rtp_hdr = (struct rtp_hdr *)msgb_data(msg); - /* Find the codec information that is used on the source side */ - codec_src = mgcp_codec_from_pt(conn_src, rtp_hdr->payload_type); - if (!codec_src) + if (!conn_dst->end.codec) { + LOG_CONN_RTP(conn_dst, LOGL_NOTICE, "no codec set on destination connection!\n"); return -EINVAL; + } + rtp_hdr->payload_type = (uint8_t) conn_dst->end.codec->payload_type; - /* Lookup a suitable codec in the destination connection. (The codec must be of the same type or at least - * convertible) */ - codec_dst = mgcp_codec_find_convertible(conn_dst, codec_src); - if (!codec_dst) - return -EINVAL; - - rtp_hdr->payload_type = (uint8_t) codec_dst->payload_type; return 0; } @@ -1172,7 +1164,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr * IuUP -> AMR: calls this function, skip patching if conn_src is IuUP. * {AMR or IuUP} -> IuUP: calls mgcp_udp_send() directly, skipping this function: No need to examine dst. */ if (is_rtp && !mgcp_conn_rtp_is_iuup(conn_src)) { - rc = mgcp_patch_pt(conn_src, conn_dst, msg); + rc = mgcp_patch_pt(conn_dst, msg); if (rc < 0) { /* FIXME: It is legal that the payload type on the egress connection is * different from the payload type that has been negotiated on the diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c index b697a9430..1fa345b86 100644 --- a/src/libosmo-mgcp/mgcp_protocol.c +++ b/src/libosmo-mgcp/mgcp_protocol.c @@ -761,6 +761,9 @@ static int handle_codec_info(struct mgcp_conn_rtp *conn, struct mgcp_request_data *rq, int have_sdp, bool crcx) { struct mgcp_endpoint *endp = rq->endp; + struct mgcp_conn *conn_dst; + struct mgcp_conn_rtp *conn_dst_rtp; + int rc; char *cmd; @@ -802,8 +805,15 @@ static int handle_codec_info(struct mgcp_conn_rtp *conn, goto error; } + /* Try to find an destination RTP connection that we can include in the codec decision. */ + conn_dst = mgcp_find_dst_conn(conn->conn); + if (conn_dst && conn_dst->type == MGCP_CONN_TYPE_RTP) + conn_dst_rtp = &conn_dst->u.rtp; + else + conn_dst_rtp = NULL; + /* Make codec decision */ - if (mgcp_codec_decide(conn) != 0) + if (mgcp_codec_decide(conn, conn_dst_rtp) != 0) goto error; return 0; diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c index 5c19c14ee..784894c18 100644 --- a/src/libosmo-mgcp/mgcp_vty.c +++ b/src/libosmo-mgcp/mgcp_vty.c @@ -120,8 +120,6 @@ static int config_write_mgcp(struct vty *vty) trunk->audio_send_name ? "" : "no ", VTY_NEWLINE); vty_out(vty, " number endpoints %u%s", trunk->v.vty_number_endpoints, VTY_NEWLINE); - vty_out(vty, " %sallow-transcoding%s", - trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE); if (strlen(g_cfg->call_agent_addr)) vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE); @@ -701,25 +699,19 @@ DEFUN_USRATTR(cfg_mgcp_sdp_fmtp_extra, return CMD_SUCCESS; } -DEFUN_USRATTR(cfg_mgcp_allow_transcoding, - cfg_mgcp_allow_transcoding_cmd, - X(MGW_CMD_ATTR_NEWCONN), - "allow-transcoding", "Allow transcoding\n") +DEFUN_DEPRECATED(cfg_mgcp_allow_transcoding, + cfg_mgcp_allow_transcoding_cmd, + "allow-transcoding", "Allow transcoding\n") { - struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID); - OSMO_ASSERT(trunk); - trunk->no_audio_transcoding = 0; + vty_out(vty, "%% Deprecated 'allow-transcoding' config no longer has any effect%s", VTY_NEWLINE); return CMD_SUCCESS; } -DEFUN_USRATTR(cfg_mgcp_no_allow_transcoding, - cfg_mgcp_no_allow_transcoding_cmd, - X(MGW_CMD_ATTR_NEWCONN), - "no allow-transcoding", NO_STR "Allow transcoding\n") +DEFUN_DEPRECATED(cfg_mgcp_no_allow_transcoding, + cfg_mgcp_no_allow_transcoding_cmd, + "no allow-transcoding", NO_STR "Allow transcoding\n") { - struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID); - OSMO_ASSERT(trunk); - trunk->no_audio_transcoding = 1; + vty_out(vty, "%% Deprecated 'no allow-transcoding' config no longer has any effect%s", VTY_NEWLINE); return CMD_SUCCESS; } @@ -1073,8 +1065,6 @@ static int config_write_trunk(struct vty *vty) if (trunk->audio_fmtp_extra) vty_out(vty, " sdp audio fmtp-extra %s%s", trunk->audio_fmtp_extra, VTY_NEWLINE); - vty_out(vty, " %sallow-transcoding%s", - trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE); } return CMD_SUCCESS; @@ -1326,23 +1316,19 @@ DEFUN_ATTR(cfg_trunk_no_rtp_keepalive, return CMD_SUCCESS; } -DEFUN_USRATTR(cfg_trunk_allow_transcoding, - cfg_trunk_allow_transcoding_cmd, - X(MGW_CMD_ATTR_NEWCONN), - "allow-transcoding", "Allow transcoding\n") +DEFUN_DEPRECATED(cfg_trunk_allow_transcoding, + cfg_trunk_allow_transcoding_cmd, + "allow-transcoding", "Allow transcoding\n") { - struct mgcp_trunk *trunk = vty->index; - trunk->no_audio_transcoding = 0; + vty_out(vty, "%% Deprecated 'allow-transcoding' config no longer has any effect%s", VTY_NEWLINE); return CMD_SUCCESS; } -DEFUN_USRATTR(cfg_trunk_no_allow_transcoding, - cfg_trunk_no_allow_transcoding_cmd, - X(MGW_CMD_ATTR_NEWCONN), - "no allow-transcoding", NO_STR "Allow transcoding\n") +DEFUN_DEPRECATED(cfg_trunk_no_allow_transcoding, + cfg_trunk_no_allow_transcoding_cmd, + "no allow-transcoding", NO_STR "Allow transcoding\n") { - struct mgcp_trunk *trunk = vty->index; - trunk->no_audio_transcoding = 1; + vty_out(vty, "%% Deprecated 'no allow-transcoding' config no longer has any effect%s", VTY_NEWLINE); return CMD_SUCCESS; } diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c index bc2dae0e5..2374e9195 100644 --- a/tests/mgcp/mgcp_test.c +++ b/tests/mgcp/mgcp_test.c @@ -1467,7 +1467,6 @@ static void test_multilple_codec(void) /* Allocate 5@mgw and let osmo-mgw pick a codec from the list */ last_endpoint[0] = '\0'; inp = create_msg(CRCX_MULT_GSM_EXACT, NULL); - trunk->no_audio_transcoding = 1; resp = mgcp_handle_message(cfg, inp); OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id, sizeof(conn_id)) == 0); @@ -1511,7 +1510,6 @@ static void test_multilple_codec(void) last_endpoint[0] = '\0'; inp = create_msg(CRCX_MULT_GSM_EXACT, NULL); - trunk->no_audio_transcoding = 0; resp = mgcp_handle_message(cfg, inp); OSMO_ASSERT(get_conn_id_from_response(resp->data, conn_id, sizeof(conn_id)) == 0); @@ -1769,26 +1767,25 @@ static const struct mgcp_codec_param amr_param_octet_aligned_unset = { .amr_octet_aligned_present = false, }; -struct testcase_mgcp_codec_find_convertible_codec { +struct testcase_mgcp_codec_decide_codec { int payload_type; const char *audio_name; const struct mgcp_codec_param *param; int expect_rc; }; -struct testcase_mgcp_codec_find_convertible_expect { - bool end; +struct testcase_mgcp_codec_decide_expect { int payload_type_map[2]; }; -struct testcase_mgcp_codec_find_convertible { +struct testcase_mgcp_codec_decide { const char *descr; /* two conns on an endpoint, each with N configured codecs */ - struct testcase_mgcp_codec_find_convertible_codec codecs[2][10]; - struct testcase_mgcp_codec_find_convertible_expect expect[32]; + struct testcase_mgcp_codec_decide_codec codecs[2][10]; + struct testcase_mgcp_codec_decide_expect expect[2]; }; -static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_convertible_cases[] = { +static const struct testcase_mgcp_codec_decide test_mgcp_codec_find_convertible_cases[] = { { .descr = "same order, but differing payload type numbers", .codecs = { @@ -1805,10 +1802,7 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, .expect = { { .payload_type_map = {112, 96}, }, - { .payload_type_map = {0, 0}, }, - { .payload_type_map = {111, 97} }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + { .payload_type_map = {112, 96}, }, }, }, { @@ -1826,11 +1820,8 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, }, .expect = { - { .payload_type_map = {112, 96}, }, { .payload_type_map = {0, 0}, }, - { .payload_type_map = {111, 97} }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + { .payload_type_map = {111, 97}, }, }, }, { @@ -1848,11 +1839,8 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, }, .expect = { - { .payload_type_map = {96, 97}, }, - { .payload_type_map = {97, 96}, }, { .payload_type_map = {0, 0}, }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + { .payload_type_map = {96, 97}, }, }, }, { @@ -1868,10 +1856,8 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, }, .expect = { - { .payload_type_map = {112, -EINVAL}, }, - { .payload_type_map = {0, -EINVAL}, }, - { .payload_type_map = {111, -EINVAL} }, - { .end = true }, + { .payload_type_map = {-EINVAL, -EINVAL}, }, + { .payload_type_map = {-EINVAL, 96}, }, }, }, { @@ -1888,13 +1874,11 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, .expect = { { .payload_type_map = {112, -EINVAL}, }, - { .payload_type_map = {0, -EINVAL}, }, - { .payload_type_map = {111, -EINVAL} }, - { .end = true }, + { .payload_type_map = {-EINVAL, -EINVAL}, }, }, }, { - .descr = "test AMR with differing octet-aligned settings", + .descr = "test AMR with differing octet-aligned settings (both <-> both)", .codecs = { { { 111, "AMR/8000", &amr_param_octet_aligned_true, }, @@ -1908,8 +1892,38 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co .expect = { { .payload_type_map = {111, 121}, }, { .payload_type_map = {112, 122} }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + }, + }, + { + .descr = "test AMR with differing octet-aligned settings (oa <-> both)", + .codecs = { + { + { 111, "AMR/8000", &amr_param_octet_aligned_true, }, + }, + { + { 122, "AMR/8000", &amr_param_octet_aligned_false, }, + { 121, "AMR/8000", &amr_param_octet_aligned_true, }, + }, + }, + .expect = { + { .payload_type_map = {111, 121}, }, + { .payload_type_map = {111, 121}, }, + }, + }, + { + .descr = "test AMR with differing octet-aligned settings (bwe <-> both)", + .codecs = { + { + { 112, "AMR/8000", &amr_param_octet_aligned_false, }, + }, + { + { 122, "AMR/8000", &amr_param_octet_aligned_false, }, + { 121, "AMR/8000", &amr_param_octet_aligned_true, }, + }, + }, + .expect = { + { .payload_type_map = {112, 122}, }, + { .payload_type_map = {112, 122}, }, }, }, { @@ -1924,8 +1938,7 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, .expect = { { .payload_type_map = {111, 122}, }, - { .payload_type_map = {55, -EINVAL}, }, - { .end = true }, + { .payload_type_map = {111, 122}, }, }, }, { @@ -1940,8 +1953,7 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, .expect = { { .payload_type_map = {111, 122}, }, - { .payload_type_map = {55, -EINVAL}, }, - { .end = true }, + { .payload_type_map = {111, 122}, }, }, }, { @@ -1957,8 +1969,7 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co .expect = { /* Note: Both 111, anbd 112 will translate to 122. The translation from 112 */ { .payload_type_map = {112, 122} }, - { .payload_type_map = {55, -EINVAL}, }, - { .end = true }, + { .payload_type_map = {112, 122}, }, }, }, { @@ -1974,8 +1985,7 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co .expect = { /* Note: Both 111, anbd 112 will translate to 122. The translation from 112 */ { .payload_type_map = {112, 122} }, - { .payload_type_map = {55, -EINVAL}, }, - { .end = true }, + { .payload_type_map = {112, 122}, }, }, }, { @@ -1993,11 +2003,8 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, }, .expect = { - { .payload_type_map = {112, 96}, }, { .payload_type_map = {0, 0}, }, - { .payload_type_map = {111, 97} }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + { .payload_type_map = {111, 97}, }, }, }, { @@ -2015,11 +2022,8 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, }, .expect = { - { .payload_type_map = {112, 96}, }, { .payload_type_map = {0, 0}, }, - { .payload_type_map = {111, 97} }, - { .payload_type_map = {123, -EINVAL} }, - { .end = true }, + { .payload_type_map = {111, 97}, }, }, }, { @@ -2037,70 +2041,97 @@ static const struct testcase_mgcp_codec_find_convertible test_mgcp_codec_find_co }, .expect = { { .payload_type_map = {111, 121}, }, - { .payload_type_map = {112, -EINVAL} }, - { .payload_type_map = {113, -EINVAL} }, - { .end = true }, + { .payload_type_map = {111, 121} }, }, }, }; -static int pt_translate(struct mgcp_conn_rtp *conn, unsigned int index_src, unsigned int index_dst, int payload_type) +static bool codec_decision(struct mgcp_conn_rtp *conn, unsigned int index_conn_src, unsigned int index_conn_dst, + const struct testcase_mgcp_codec_decide_expect *expect) { - struct mgcp_rtp_codec *codec_src = NULL; - struct mgcp_rtp_codec *codec_dst = NULL; - struct mgcp_conn_rtp *conn_src = &conn[index_src]; - struct mgcp_conn_rtp *conn_dst = &conn[index_dst]; + bool ok = true; + int payload_type_conn_src; + int payload_type_conn_dst; - /* Find the codec information that is used on the source side */ - codec_src = mgcp_codec_from_pt(conn_src, payload_type); - if (!codec_src) { - printf(" - mgcp_codec_from_pt(conn%u, %d) -> NO RESULT\n", index_src, payload_type); - return -EINVAL; - } - printf(" - mgcp_codec_from_pt(conn%u, %d) -> %s\n", index_src, payload_type, codec_src->subtype_name); + printf(" - mgcp_codec_decide(&conn[%u], &conn[%u]):\n", index_conn_src, index_conn_dst); + if (mgcp_codec_decide(&conn[index_conn_src], &conn[index_conn_dst]) != 0) { + if (expect->payload_type_map[index_conn_src] == -EINVAL + && expect->payload_type_map[index_conn_dst] == -EINVAL) + printf(" codec decision failed (expected)!\n"); + else { + printf(" ERROR: codec decision failed!\n"); + ok = false; + } + } else { + printf(" Codec decision result:\n"); + if (conn[index_conn_src].end.codec) { + payload_type_conn_src = conn[index_conn_src].end.codec->payload_type; + printf(" conn[%u]: codec:%s, pt:%d\n", + index_conn_src, conn[index_conn_src].end.codec->subtype_name, payload_type_conn_src); + } else { + payload_type_conn_src = -EINVAL; + printf(" conn[%u]: codec:none, pt:none\n", index_conn_src); + } - codec_dst = mgcp_codec_find_convertible(conn_dst, codec_src); - if (!codec_dst) { - printf(" - mgcp_codec_find_convertible(conn%u, %s) -> NO RESULT\n", index_dst, codec_src->subtype_name); - return -EINVAL; + if (conn[index_conn_dst].end.codec) { + payload_type_conn_dst = conn[index_conn_dst].end.codec->payload_type; + printf(" conn[%u]: codec:%s, pt:%d\n", + index_conn_dst, conn[index_conn_dst].end.codec->subtype_name, + payload_type_conn_dst); + } else { + payload_type_conn_dst = -EINVAL; + printf(" conn[%u]: codec:none, pt:none\n", index_conn_dst); + } + + if (payload_type_conn_src != expect->payload_type_map[index_conn_src]) { + printf(" ERROR: conn[%u] unexpected codec decision, expected pt=%d, got pt=%d\n", + index_conn_src, expect->payload_type_map[index_conn_src], payload_type_conn_src); + ok = false; + } + + if (payload_type_conn_dst != expect->payload_type_map[index_conn_dst]) { + printf(" ERROR: conn[%u] unexpected codec decision, expected pt=%d, got pt=%d\n", + index_conn_dst, expect->payload_type_map[index_conn_dst], + payload_type_conn_dst); + ok = false; + } } - printf(" - mgcp_codec_find_convertible(conn%u, %s) -> %s -> %u\n", - index_dst, codec_src->subtype_name, codec_dst->subtype_name, codec_dst->payload_type); - return codec_dst->payload_type; + + return ok; } -static void test_mgcp_codec_find_convertible(void) +static void test_mgcp_codec_decide(void) { int i; bool ok = true; printf("\nTesting mgcp_codec_find_convertible()\n"); for (i = 0; i < ARRAY_SIZE(test_mgcp_codec_find_convertible_cases); i++) { - const struct testcase_mgcp_codec_find_convertible *t = &test_mgcp_codec_find_convertible_cases[i]; - struct mgcp_conn_rtp conn[2] = {}; + const struct testcase_mgcp_codec_decide *t = &test_mgcp_codec_find_convertible_cases[i]; + struct mgcp_conn_rtp conn[2] = { }; int rc; int conn_i; int c; printf("#%d: %s\n", i, t->descr); + /* Build testvector (add codecs to conn, set properties etc... */ for (conn_i = 0; conn_i < 2; conn_i++) { printf(" - add codecs on conn%d:\n", conn_i); for (c = 0; c < ARRAY_SIZE(t->codecs[conn_i]); c++) { - const struct testcase_mgcp_codec_find_convertible_codec *codec = &t->codecs[conn_i][c]; + const struct testcase_mgcp_codec_decide_codec *codec = &t->codecs[conn_i][c]; if (!codec->audio_name) break; - rc = mgcp_codec_add(&conn[conn_i], codec->payload_type, codec->audio_name, codec->param); + rc = mgcp_codec_add(&conn[conn_i], codec->payload_type, codec->audio_name, + codec->param); printf(" %2d: %3d %s%s -> rc=%d\n", c, codec->payload_type, codec->audio_name, codec->param ? - (codec->param->amr_octet_aligned_present? - (codec->param->amr_octet_aligned ? - " octet-aligned=1" : " octet-aligned=0") - : " octet-aligned=unset") - : "", - rc); + (codec->param->amr_octet_aligned_present ? + (codec->param->amr_octet_aligned ? " octet-aligned=1" : " octet-aligned=0") + : " octet-aligned=unset") + : "", rc); if (rc != codec->expect_rc) { printf(" ERROR: expected rc=%d\n", codec->expect_rc); ok = false; @@ -2110,32 +2141,17 @@ static void test_mgcp_codec_find_convertible(void) printf(" (none)\n"); } - for (c = 0; c < ARRAY_SIZE(t->expect); c++) { - const struct testcase_mgcp_codec_find_convertible_expect *expect = &t->expect[c]; - int result; + /* Run codec decision and check expectation */ + if (!codec_decision(conn, 0, 1, &t->expect[0])) + ok = false; - if (expect->end) - break; + if (!codec_decision(conn, 1, 0, &t->expect[1])) + ok = false; - result = pt_translate(conn, 0, 1, expect->payload_type_map[0]); - if (result != expect->payload_type_map[1]) { - printf(" ERROR: expected -> %d\n", expect->payload_type_map[1]); - ok = false; - } - - /* If the expected result is an error, don't do reverse map test */ - if (expect->payload_type_map[1] < 0) - continue; - - result = pt_translate(conn, 1, 0, expect->payload_type_map[1]); - if (result != expect->payload_type_map[0]) { - printf(" ERROR: expected -> %d\n", expect->payload_type_map[0]); - ok = false; - } - } - - for (conn_i = 0; conn_i < 2; conn_i++) - mgcp_codec_reset_all(&conn[conn_i]); + if (ok) + printf(" ===> SUCCESS: codec decision as expected!\n"); + else + printf(" ===> FAIL: unexpected codec decision!\n"); } OSMO_ASSERT(ok); @@ -2295,7 +2311,7 @@ int main(int argc, char **argv) test_osmux_cid(); test_get_lco_identifier(); test_check_local_cx_options(ctx); - test_mgcp_codec_find_convertible(); + test_mgcp_codec_decide(); test_conn_id_matching(); test_e1_trunk_nr_from_epname(); test_mgcp_is_rtp_dummy_payload(); diff --git a/tests/mgcp/mgcp_test.ok b/tests/mgcp/mgcp_test.ok index 4ea9a34ef..08df5d499 100644 --- a/tests/mgcp/mgcp_test.ok +++ b/tests/mgcp/mgcp_test.ok @@ -1286,19 +1286,15 @@ Testing mgcp_codec_find_convertible() 0: 96 AMR/8000/1 octet-aligned=1 -> rc=0 1: 0 PCMU/8000/1 -> rc=0 2: 97 GSM-HR-08/8000/1 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 96 - - mgcp_codec_from_pt(conn1, 96) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn1, 0) -> PCMU - - mgcp_codec_find_convertible(conn0, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 97 - - mgcp_codec_from_pt(conn1, 97) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 111 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:112 + conn[1]: codec:AMR, pt:96 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:96 + conn[0]: codec:AMR, pt:112 + ===> SUCCESS: codec decision as expected! #1: different order and different payload type numbers - add codecs on conn0: 0: 0 PCMU/8000/1 -> rc=0 @@ -1308,19 +1304,15 @@ Testing mgcp_codec_find_convertible() 0: 97 GSM-HR-08/8000/1 -> rc=0 1: 0 PCMU/8000/1 -> rc=0 2: 96 AMR/8000/1 octet-aligned=1 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 96 - - mgcp_codec_from_pt(conn1, 96) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn1, 0) -> PCMU - - mgcp_codec_find_convertible(conn0, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 97 - - mgcp_codec_from_pt(conn1, 97) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 111 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:PCMU, pt:0 + conn[1]: codec:PCMU, pt:0 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:GSM-HR-08, pt:97 + conn[0]: codec:GSM-HR-08, pt:111 + ===> SUCCESS: codec decision as expected! #2: both sides have the same payload_type numbers assigned to differing codecs - add codecs on conn0: 0: 0 PCMU/8000/1 -> rc=0 @@ -1330,19 +1322,15 @@ Testing mgcp_codec_find_convertible() 0: 97 GSM-HR-08/8000/1 -> rc=0 1: 0 PCMU/8000/1 -> rc=0 2: 96 AMR/8000/1 octet-aligned=1 -> rc=0 - - mgcp_codec_from_pt(conn0, 96) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 97 - - mgcp_codec_from_pt(conn1, 97) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 96 - - mgcp_codec_from_pt(conn0, 97) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 96 - - mgcp_codec_from_pt(conn1, 96) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 97 - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn1, 0) -> PCMU - - mgcp_codec_find_convertible(conn0, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:PCMU, pt:0 + conn[1]: codec:PCMU, pt:0 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:GSM-HR-08, pt:97 + conn[0]: codec:GSM-HR-08, pt:96 + ===> SUCCESS: codec decision as expected! #3: conn0 has no codecs - add codecs on conn0: (none) @@ -1350,9 +1338,13 @@ Testing mgcp_codec_find_convertible() 0: 96 AMR/8000/1 octet-aligned=1 -> rc=0 1: 0 PCMU/8000/1 -> rc=0 2: 97 GSM-HR-08/8000/1 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> NO RESULT - - mgcp_codec_from_pt(conn0, 0) -> NO RESULT - - mgcp_codec_from_pt(conn0, 111) -> NO RESULT + - mgcp_codec_decide(&conn[0], &conn[1]): + codec decision failed (expected)! + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:96 + conn[0]: codec:none, pt:none + ===> SUCCESS: codec decision as expected! #4: conn1 has no codecs - add codecs on conn0: 0: 112 AMR/8000/1 octet-aligned=1 -> rc=0 @@ -1360,69 +1352,116 @@ Testing mgcp_codec_find_convertible() 2: 111 GSM-HR-08/8000/1 -> rc=0 - add codecs on conn1: (none) - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> NO RESULT - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> NO RESULT - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> NO RESULT -#5: test AMR with differing octet-aligned settings + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:112 + conn[1]: codec:none, pt:none + - mgcp_codec_decide(&conn[1], &conn[0]): + codec decision failed (expected)! + ===> SUCCESS: codec decision as expected! +#5: test AMR with differing octet-aligned settings (both <-> both) - add codecs on conn0: 0: 111 AMR/8000 octet-aligned=1 -> rc=0 1: 112 AMR/8000 octet-aligned=0 -> rc=0 - add codecs on conn1: 0: 122 AMR/8000 octet-aligned=0 -> rc=0 1: 121 AMR/8000 octet-aligned=1 -> rc=0 - - mgcp_codec_from_pt(conn0, 111) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 121 - - mgcp_codec_from_pt(conn1, 121) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 111 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 122 - - mgcp_codec_from_pt(conn1, 122) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT -#6: test AMR with missing octet-aligned settings (oa <-> unset) + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:111 + conn[1]: codec:AMR, pt:121 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:112 + ===> SUCCESS: codec decision as expected! +#6: test AMR with differing octet-aligned settings (oa <-> both) + - add codecs on conn0: + 0: 111 AMR/8000 octet-aligned=1 -> rc=0 + - add codecs on conn1: + 0: 122 AMR/8000 octet-aligned=0 -> rc=0 + 1: 121 AMR/8000 octet-aligned=1 -> rc=0 + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:111 + conn[1]: codec:AMR, pt:121 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:121 + conn[0]: codec:AMR, pt:111 + ===> SUCCESS: codec decision as expected! +#7: test AMR with differing octet-aligned settings (bwe <-> both) + - add codecs on conn0: + 0: 112 AMR/8000 octet-aligned=0 -> rc=0 + - add codecs on conn1: + 0: 122 AMR/8000 octet-aligned=0 -> rc=0 + 1: 121 AMR/8000 octet-aligned=1 -> rc=0 + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:112 + conn[1]: codec:AMR, pt:122 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:112 + ===> SUCCESS: codec decision as expected! +#8: test AMR with missing octet-aligned settings (oa <-> unset) - add codecs on conn0: 0: 111 AMR/8000 octet-aligned=1 -> rc=0 - add codecs on conn1: 0: 122 AMR/8000 octet-aligned=unset -> rc=0 - - mgcp_codec_from_pt(conn0, 111) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 122 - - mgcp_codec_from_pt(conn1, 122) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 111 - - mgcp_codec_from_pt(conn0, 55) -> NO RESULT -#7: test AMR with missing octet-aligned settings (bwe <-> unset) + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:111 + conn[1]: codec:AMR, pt:122 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:111 + ===> SUCCESS: codec decision as expected! +#9: test AMR with missing octet-aligned settings (bwe <-> unset) - add codecs on conn0: 0: 111 AMR/8000 octet-aligned=0 -> rc=0 - add codecs on conn1: 0: 122 AMR/8000 octet-aligned=unset -> rc=0 - - mgcp_codec_from_pt(conn0, 111) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 122 - - mgcp_codec_from_pt(conn1, 122) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 111 - - mgcp_codec_from_pt(conn0, 55) -> NO RESULT -#8: test AMR with NULL param (oa <-> null) + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:111 + conn[1]: codec:AMR, pt:122 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:111 + ===> SUCCESS: codec decision as expected! +#10: test AMR with NULL param (oa <-> null) - add codecs on conn0: 0: 112 AMR/8000 octet-aligned=1 -> rc=0 - add codecs on conn1: 0: 122 AMR/8000 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 122 - - mgcp_codec_from_pt(conn1, 122) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 55) -> NO RESULT -#9: test AMR with NULL param (bwe <-> null) + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:112 + conn[1]: codec:AMR, pt:122 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:112 + ===> SUCCESS: codec decision as expected! +#11: test AMR with NULL param (bwe <-> null) - add codecs on conn0: 0: 112 AMR/8000 octet-aligned=0 -> rc=0 - add codecs on conn1: 0: 122 AMR/8000 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 122 - - mgcp_codec_from_pt(conn1, 122) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 55) -> NO RESULT -#10: match FOO/8000/1 and FOO/8000 as identical, single channel is implicit + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:AMR, pt:112 + conn[1]: codec:AMR, pt:122 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:AMR, pt:122 + conn[0]: codec:AMR, pt:112 + ===> SUCCESS: codec decision as expected! +#12: match FOO/8000/1 and FOO/8000 as identical, single channel is implicit - add codecs on conn0: 0: 0 PCMU/8000/1 -> rc=0 1: 111 GSM-HR-08/8000/1 -> rc=0 @@ -1431,20 +1470,16 @@ Testing mgcp_codec_find_convertible() 0: 97 GSM-HR-08/8000 -> rc=0 1: 0 PCMU/8000 -> rc=0 2: 96 AMR/8000 octet-aligned=1 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 96 - - mgcp_codec_from_pt(conn1, 96) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn1, 0) -> PCMU - - mgcp_codec_find_convertible(conn0, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 97 - - mgcp_codec_from_pt(conn1, 97) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 111 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT -#11: match FOO/8000/1 and FOO as identical, 8k and single channel are implicit + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:PCMU, pt:0 + conn[1]: codec:PCMU, pt:0 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:GSM-HR-08, pt:97 + conn[0]: codec:GSM-HR-08, pt:111 + ===> SUCCESS: codec decision as expected! +#13: match FOO/8000/1 and FOO as identical, 8k and single channel are implicit - add codecs on conn0: 0: 0 PCMU/8000/1 -> rc=0 1: 111 GSM-HR-08/8000/1 -> rc=0 @@ -1453,20 +1488,16 @@ Testing mgcp_codec_find_convertible() 0: 97 GSM-HR-08 -> rc=0 1: 0 PCMU -> rc=0 2: 96 AMR octet-aligned=1 -> rc=0 - - mgcp_codec_from_pt(conn0, 112) -> AMR - - mgcp_codec_find_convertible(conn1, AMR) -> AMR -> 96 - - mgcp_codec_from_pt(conn1, 96) -> AMR - - mgcp_codec_find_convertible(conn0, AMR) -> AMR -> 112 - - mgcp_codec_from_pt(conn0, 0) -> PCMU - - mgcp_codec_find_convertible(conn1, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn1, 0) -> PCMU - - mgcp_codec_find_convertible(conn0, PCMU) -> PCMU -> 0 - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 97 - - mgcp_codec_from_pt(conn1, 97) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 111 - - mgcp_codec_from_pt(conn0, 123) -> NO RESULT -#12: test whether channel number matching is waterproof + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:PCMU, pt:0 + conn[1]: codec:PCMU, pt:0 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:GSM-HR-08, pt:97 + conn[0]: codec:GSM-HR-08, pt:111 + ===> SUCCESS: codec decision as expected! +#14: test whether channel number matching is waterproof - add codecs on conn0: 0: 111 GSM-HR-08/8000 -> rc=0 1: 112 GSM-HR-08/8000/2 -> rc=-22 @@ -1474,12 +1505,15 @@ Testing mgcp_codec_find_convertible() - add codecs on conn1: 0: 122 GSM-HR-08/8000/2 -> rc=-22 1: 121 GSM-HR-08/8000/1 -> rc=0 - - mgcp_codec_from_pt(conn0, 111) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn1, GSM-HR-08) -> GSM-HR-08 -> 121 - - mgcp_codec_from_pt(conn1, 121) -> GSM-HR-08 - - mgcp_codec_find_convertible(conn0, GSM-HR-08) -> GSM-HR-08 -> 111 - - mgcp_codec_from_pt(conn0, 112) -> NO RESULT - - mgcp_codec_from_pt(conn0, 113) -> NO RESULT + - mgcp_codec_decide(&conn[0], &conn[1]): + Codec decision result: + conn[0]: codec:GSM-HR-08, pt:111 + conn[1]: codec:GSM-HR-08, pt:121 + - mgcp_codec_decide(&conn[1], &conn[0]): + Codec decision result: + conn[1]: codec:GSM-HR-08, pt:121 + conn[0]: codec:GSM-HR-08, pt:111 + ===> SUCCESS: codec decision as expected! Testing test_conn_id_matching needle='23AB' found '000023AB'