aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-08-19 14:43:35 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-08-19 15:44:44 +0200
commitceef936ea894781a14584efc9256856cca6d1c0f (patch)
tree0be10a903b15d6723e98a4488c2dde1ee55ae8a6
parent57e95a22f02b5b2ec781d9bc977c785a6e6f1166 (diff)
mgcp: Add transcoding from PCMU as well
Use the existing ulaw encode/decode to support PCMU as well. The MERA VoIP switch has some severe issues with the GSM codec and it appears easier to enable transcoding for it. The mera switch doesn't appear to cope with codec change between a SIP 180 trying and the 200 ok connection result. Inserting the codec is touching too many places. Ideally we should have the transcoding function as pointer in the struct as well but the arguments differ.. so it is not a direct way forward.
-rw-r--r--openbsc/include/openbsc/mgcp_transcode.h3
-rw-r--r--openbsc/src/libmgcp/mgcp_sdp.c8
-rw-r--r--openbsc/src/libmgcp/mgcp_transcode.c26
3 files changed, 36 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/mgcp_transcode.h b/openbsc/include/openbsc/mgcp_transcode.h
index cb11cb21..147e48bb 100644
--- a/openbsc/include/openbsc/mgcp_transcode.h
+++ b/openbsc/include/openbsc/mgcp_transcode.h
@@ -33,7 +33,8 @@ enum audio_format {
AF_L16,
AF_GSM,
AF_G729,
- AF_PCMA
+ AF_PCMA,
+ AF_PCMU
};
diff --git a/openbsc/src/libmgcp/mgcp_sdp.c b/openbsc/src/libmgcp/mgcp_sdp.c
index aa4ef305..b6489449 100644
--- a/openbsc/src/libmgcp/mgcp_sdp.c
+++ b/openbsc/src/libmgcp/mgcp_sdp.c
@@ -54,6 +54,7 @@ int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
if (!audio_name) {
switch (payload_type) {
+ case 0: audio_name = "PCMU/8000/1"; break;
case 3: audio_name = "GSM/8000/1"; break;
case 8: audio_name = "PCMA/8000/1"; break;
case 18: audio_name = "G729/8000/1"; break;
@@ -89,6 +90,8 @@ int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
payload_type = 3;
else if (!strcmp(audio_codec, "PCMA"))
payload_type = 8;
+ else if (!strcmp(audio_codec, "PCMU"))
+ payload_type = 0;
else if (!strcmp(audio_codec, "G729"))
payload_type = 18;
}
@@ -109,6 +112,11 @@ void codecs_initialize(void *ctx, struct sdp_rtp_map *codecs, int used)
for (i = 0; i < used; ++i) {
switch (codecs[i].payload_type) {
+ case 0:
+ codecs[i].codec_name = "PCMU";
+ codecs[i].rate = 8000;
+ codecs[i].channels = 1;
+ break;
case 3:
codecs[i].codec_name = "GSM";
codecs[i].rate = 8000;
diff --git a/openbsc/src/libmgcp/mgcp_transcode.c b/openbsc/src/libmgcp/mgcp_transcode.c
index 12cce261..c994d329 100644
--- a/openbsc/src/libmgcp/mgcp_transcode.c
+++ b/openbsc/src/libmgcp/mgcp_transcode.c
@@ -52,6 +52,8 @@ static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
return AF_GSM;
if (!strcasecmp("PCMA", codec->subtype_name))
return AF_PCMA;
+ if (!strcasecmp("PCMU", codec->subtype_name))
+ return AF_PCMU;
#ifdef HAVE_BCG729
if (!strcasecmp("G729", codec->subtype_name))
return AF_G729;
@@ -61,6 +63,8 @@ static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
}
switch (codec->payload_type) {
+ case 0 /* PCMU */:
+ return AF_PCMU;
case 3 /* GSM */:
return AF_GSM;
case 8 /* PCMA */:
@@ -102,6 +106,18 @@ static void alaw_decode(unsigned char *buf, short *sample, size_t n)
*(sample++) = alaw_to_s16(*(buf++));
}
+static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
+{
+ for (; n > 0; --n)
+ *(buf++) = s16_to_ulaw(*(sample++));
+}
+
+static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
+{
+ for (; n > 0; --n)
+ *(sample++) = ulaw_to_s16(*(buf++));
+}
+
static int processing_state_destructor(struct mgcp_process_rtp_state *state)
{
switch (state->src_fmt) {
@@ -226,6 +242,7 @@ int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
}
break;
#endif
+ case AF_PCMU:
case AF_PCMA:
state->src_frame_size = 80;
state->src_samples_per_frame = 80;
@@ -264,6 +281,7 @@ int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
}
break;
#endif
+ case AF_PCMU:
case AF_PCMA:
state->dst_frame_size = 80;
state->dst_samples_per_frame = 80;
@@ -331,6 +349,10 @@ static int decode_audio(struct mgcp_process_rtp_state *state,
bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
break;
#endif
+ case AF_PCMU:
+ ulaw_decode(*src, state->samples + state->sample_cnt,
+ state->src_samples_per_frame);
+ break;
case AF_PCMA:
alaw_decode(*src, state->samples + state->sample_cnt,
state->src_samples_per_frame);
@@ -381,6 +403,10 @@ static int encode_audio(struct mgcp_process_rtp_state *state,
state->samples + state->sample_offs, dst);
break;
#endif
+ case AF_PCMU:
+ ulaw_encode(state->samples + state->sample_offs, dst,
+ state->src_samples_per_frame);
+ break;
case AF_PCMA:
alaw_encode(state->samples + state->sample_offs, dst,
state->src_samples_per_frame);