aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/src/libmgcp/mgcp_transcode.c54
-rw-r--r--openbsc/tests/mgcp/mgcp_transcoding_test.c61
-rw-r--r--openbsc/tests/mgcp/mgcp_transcoding_test.ok1
3 files changed, 115 insertions, 1 deletions
diff --git a/openbsc/src/libmgcp/mgcp_transcode.c b/openbsc/src/libmgcp/mgcp_transcode.c
index e961ba6cc..38daeb8ae 100644
--- a/openbsc/src/libmgcp/mgcp_transcode.c
+++ b/openbsc/src/libmgcp/mgcp_transcode.c
@@ -397,11 +397,62 @@ static int encode_audio(struct mgcp_process_rtp_state *state,
return nbytes;
}
+static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end)
+{
+ if (&endp->bts_end == dst_end)
+ return &endp->net_end;
+ else if (&endp->net_end == dst_end)
+ return &endp->bts_end;
+ OSMO_ASSERT(0);
+}
+
+/*
+ * With some modems we get offered multiple codecs
+ * and we have selected one of them. It might not
+ * be the right one and we need to detect this with
+ * the first audio packets. One difficulty is that
+ * we patch the rtp payload type in place, so we
+ * need to discuss this.
+ */
+struct mgcp_process_rtp_state *check_transcode_state(
+ struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ struct rtp_hdr *rtp_hdr)
+{
+ struct mgcp_rtp_end *src_end;
+
+ /* Only deal with messages from net to bts */
+ if (&endp->bts_end != dst_end)
+ goto done;
+
+ src_end = source_for_dest(endp, dst_end);
+
+ /* Already patched */
+ if (rtp_hdr->payload_type == dst_end->codec.payload_type)
+ goto done;
+ /* The payload we expect */
+ if (rtp_hdr->payload_type == src_end->codec.payload_type)
+ goto done;
+ /* The matching alternate payload type? Then switch */
+ if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
+ struct mgcp_config *cfg = endp->cfg;
+ struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
+ src_end->alt_codec = src_end->codec;
+ src_end->codec = tmp_codec;
+ cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
+ cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
+ }
+
+done:
+ return dst_end->rtp_process_data;
+}
+
int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
struct mgcp_rtp_end *dst_end,
char *data, int *len, int buf_size)
{
- struct mgcp_process_rtp_state *state = dst_end->rtp_process_data;
+ struct mgcp_process_rtp_state *state;
const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
char *payload_data = (char *) &rtp_hdr->data[0];
@@ -414,6 +465,7 @@ int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
uint32_t ts_no;
int rc;
+ state = check_transcode_state(endp, dst_end, rtp_hdr);
if (!state)
return 0;
diff --git a/openbsc/tests/mgcp/mgcp_transcoding_test.c b/openbsc/tests/mgcp/mgcp_transcoding_test.c
index 079f62eba..cf679b356 100644
--- a/openbsc/tests/mgcp/mgcp_transcoding_test.c
+++ b/openbsc/tests/mgcp/mgcp_transcoding_test.c
@@ -174,6 +174,9 @@ static int given_configured_endpoint(int in_samples, int out_samples,
tcfg = talloc_zero(cfg, struct mgcp_trunk_config);
endp = talloc_zero(tcfg, struct mgcp_endpoint);
+ cfg->setup_rtp_processing_cb = mgcp_transcoding_setup;
+ cfg->rtp_processing_cb = mgcp_transcoding_process_rtp;
+ cfg->get_net_downlink_format_cb = mgcp_transcoding_net_downlink_format;
tcfg->endpoints = endp;
tcfg->number_endpoints = 1;
@@ -433,6 +436,63 @@ static void test_transcode_result(void)
}
}
+static void test_transcode_change(void)
+{
+ char buf[4096] = {0x80, 0};
+ void *ctx;
+
+ struct mgcp_endpoint *endp;
+ struct mgcp_process_rtp_state *state;
+ struct rtp_hdr *hdr;
+
+ int len, res;
+
+ {
+ /* from GSM to PCMA and same ptime */
+ printf("Testing Initial G729->GSM, PCMA->GSM\n");
+ given_configured_endpoint(160, 0, "g729", "gsm", &ctx, &endp);
+ endp->net_end.alt_codec = endp->net_end.codec;
+ endp->net_end.alt_codec.payload_type = audio_name_to_type("pcma");
+ state = endp->bts_end.rtp_process_data;
+
+ /* initial transcoding work */
+ OSMO_ASSERT(state->src_fmt == AF_G729);
+ OSMO_ASSERT(state->dst_fmt == AF_GSM);
+ OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8);
+ OSMO_ASSERT(endp->net_end.codec.payload_type == 18);
+
+ /* result */
+ len = audio_packets_pcma[0].len;
+ memcpy(buf, audio_packets_pcma[0].data, len);
+ res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+ OSMO_ASSERT(res == sizeof(struct rtp_hdr));
+ OSMO_ASSERT(state->sample_cnt == 0);
+ OSMO_ASSERT(state->src_fmt == AF_PCMA);
+ OSMO_ASSERT(state->dst_fmt == AF_GSM);
+ OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 18);
+ OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
+
+ len = res;
+ res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+ OSMO_ASSERT(res == -ENOMSG);
+
+
+ /* now check that comfort noise doesn't change anything */
+ len = audio_packets_pcma[1].len;
+ memcpy(buf, audio_packets_pcma[1].data, len);
+ hdr = (struct rtp_hdr *) buf;
+ hdr->payload_type = 11;
+ res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
+ OSMO_ASSERT(state->sample_cnt == 80);
+ OSMO_ASSERT(state->src_fmt == AF_PCMA);
+ OSMO_ASSERT(state->dst_fmt == AF_GSM);
+ OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 18);
+ OSMO_ASSERT(endp->net_end.codec.payload_type == 8);
+
+ talloc_free(ctx);
+ }
+}
+
static int test_repacking(int in_samples, int out_samples, int no_transcode)
{
char buf[4096] = {0x80, 0};
@@ -582,6 +642,7 @@ int main(int argc, char **argv)
test_repacking(160, 100, 1);
test_rtp_seq_state();
test_transcode_result();
+ test_transcode_change();
return 0;
}
diff --git a/openbsc/tests/mgcp/mgcp_transcoding_test.ok b/openbsc/tests/mgcp/mgcp_transcoding_test.ok
index 7c1c8cebd..5cfc2897e 100644
--- a/openbsc/tests/mgcp/mgcp_transcoding_test.ok
+++ b/openbsc/tests/mgcp/mgcp_transcoding_test.ok
@@ -536,3 +536,4 @@ got 1 pcma output frames (80 octets) count=12
generating 160 pcma input samples
got 1 pcma output frames (80 octets) count=12
got 1 pcma output frames (80 octets) count=12
+Testing Initial G729->GSM, PCMA->GSM