aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libmgcp/mgcp_protocol.c
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-03-17 12:30:56 +0100
committerJacob Erlbeck <jerlbeck@sysmocom.de>2014-06-05 14:00:41 +0200
commit845d0054b45dff5f5606b38dcacd9bf06a605f07 (patch)
tree35d558d1337817aeae48a379f6f75c5c94d0f7aa /openbsc/src/libmgcp/mgcp_protocol.c
parenta0d64ce063fbf60733c6f2949015091aa33a2c9d (diff)
mgcp: Add audio info fields to struct mgcp_rtp_end
This patch adds the fields channels, subtype_name, and audio_name to the struct. The field audio_name contains the full string that has been used for the last part of a SDP a=rtpmap line. The others contain decoded parts of that string. If no a=rtpmap line has been given (e.g. because dynamic payload types are not used), values are assigned when the payload type matches one of the predefined ones (GSM, G729, PCMA). The patch also moves the audio_name parsing code to a dedicated set_audio_info() function. Sponsored-by: On-Waves ehf
Diffstat (limited to 'openbsc/src/libmgcp/mgcp_protocol.c')
-rw-r--r--openbsc/src/libmgcp/mgcp_protocol.c84
1 files changed, 64 insertions, 20 deletions
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 964971b00..862bf175d 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -28,6 +28,7 @@
#include <time.h>
#include <limits.h>
#include <unistd.h>
+#include <errno.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
@@ -77,6 +78,7 @@ char *strline_r(char *str, char **saveptr)
#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end);
@@ -244,6 +246,8 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
{
const char *addr = endp->cfg->local_ip;
const char *fmtp_extra = endp->bts_end.fmtp_extra;
+ const char *audio_name = endp->bts_end.audio_name;
+ int payload_type = endp->bts_end.payload_type;
char sdp_record[4096];
int len;
@@ -257,12 +261,13 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
"c=IN IP4 %s\r\n"
"t=0 0\r\n"
"m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s\r\n"
+ "a=rtpmap:%d%s%s\r\n"
"%s%s",
endp->ci, endp->cfg->osmux && endp->osmux ? "\nX-Osmux: On" : "",
endp->ci, addr, addr,
- endp->net_end.local_port, endp->bts_end.payload_type,
- endp->bts_end.payload_type, endp->tcfg->audio_name,
+ endp->net_end.local_port, payload_type,
+ payload_type,
+ audio_name ? " " : "", audio_name ? audio_name : "",
fmtp_extra ? fmtp_extra : "", fmtp_extra ? "\r\n" : "");
if (len < 0 || len >= sizeof(sdp_record))
@@ -528,6 +533,48 @@ static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp)
return ret;
}
+static int set_audio_info(void *ctx, struct mgcp_rtp_end *rtp,
+ int payload_type, const char *audio_name)
+{
+ int rate = rtp->rate;
+ int channels = rtp->channels;
+ char audio_codec[64];
+
+ talloc_free(rtp->subtype_name);
+ rtp->subtype_name = NULL;
+ talloc_free(rtp->audio_name);
+ rtp->audio_name = NULL;
+
+ rtp->payload_type = payload_type;
+
+ if (!audio_name) {
+ switch (payload_type) {
+ case 3: audio_name = "GSM/8000/1"; break;
+ case 8: audio_name = "PCMA/8000/1"; break;
+ case 18: audio_name = "G729/8000/1"; break;
+ default:
+ /* Payload type is unknown, don't change rate and
+ * channels. */
+ /* TODO: return value? */
+ return 0;
+ }
+ }
+
+ if (sscanf(audio_name, "%63[^/]/%d/%d",
+ audio_codec, &rate, &channels) < 2)
+ return -EINVAL;
+
+ rtp->rate = rate;
+ rtp->channels = channels;
+ rtp->subtype_name = talloc_strdup(ctx, audio_codec);
+ rtp->audio_name = talloc_strdup(ctx, audio_name);
+ if (channels != 1)
+ LOGP(DMGCP, LOGL_NOTICE,
+ "Channels != 1 in SDP: '%s'\n", audio_name);
+
+ return 0;
+}
+
static int allocate_port(struct mgcp_endpoint *endp, struct mgcp_rtp_end *end,
struct mgcp_port_range *range,
int (*alloc)(struct mgcp_endpoint *endp, int port))
@@ -614,11 +661,8 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
break;
case 'a': {
int payload;
- int rate;
- int channels = 1;
int ptime, ptime2 = 0;
char audio_name[64];
- char audio_codec[64];
if (audio_payload == -1)
break;
@@ -628,15 +672,7 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
if (payload != audio_payload)
break;
- if (sscanf(audio_name, "%[^/]/%d/%d",
- audio_codec, &rate, &channels) < 2)
- break;
-
- rtp->rate = rate;
- if (channels != 1)
- LOGP(DMGCP, LOGL_NOTICE,
- "Channels != 1 in SDP: '%s' on 0x%x\n",
- line, ENDPOINT_NUMBER(p->endp));
+ set_audio_info(p->cfg, rtp, payload, audio_name);
} else if (sscanf(line, "a=ptime:%d-%d",
&ptime, &ptime2) >= 1) {
if (ptime2 > 0 && ptime2 != ptime)
@@ -659,8 +695,8 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
&port, &audio_payload) == 2) {
rtp->rtp_port = htons(port);
rtp->rtcp_port = htons(port + 1);
- rtp->payload_type = audio_payload;
found_media = 1;
+ set_audio_info(p->cfg, rtp, audio_payload, NULL);
}
break;
}
@@ -851,7 +887,7 @@ mgcp_header_done:
endp->allocated = 1;
/* set up RTP media parameters */
- endp->bts_end.payload_type = tcfg->audio_payload;
+ set_audio_info(p->cfg, &endp->bts_end, tcfg->audio_payload, tcfg->audio_name);
endp->bts_end.fmtp_extra = talloc_strdup(tcfg->endpoints,
tcfg->audio_fmtp_extra);
if (have_sdp) {
@@ -1297,6 +1333,10 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
end->local_alloc = -1;
talloc_free(end->fmtp_extra);
end->fmtp_extra = NULL;
+ talloc_free(end->subtype_name);
+ end->subtype_name = NULL;
+ talloc_free(end->audio_name);
+ end->audio_name = NULL;
talloc_free(end->rtp_process_data);
end->rtp_process_data = NULL;
@@ -1306,6 +1346,7 @@ static void mgcp_rtp_end_reset(struct mgcp_rtp_end *end)
end->frames_per_packet = 0; /* unknown */
end->packet_duration_ms = DEFAULT_RTP_AUDIO_PACKET_DURATION_MS;
end->rate = DEFAULT_RTP_AUDIO_DEFAULT_RATE;
+ end->channels = DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS;
end->output_enabled = 0;
}
@@ -1383,6 +1424,8 @@ static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
{
char buf[2096];
int len;
+ const char *audio_name = endp->bts_end.audio_name;
+ int payload_type = endp->bts_end.payload_type;
/* hardcoded to AMR right now, we do not know the real type at this point */
len = snprintf(buf, sizeof(buf),
@@ -1392,10 +1435,11 @@ static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
"\r\n"
"c=IN IP4 %s\r\n"
"m=audio %d RTP/AVP %d\r\n"
- "a=rtpmap:%d %s\r\n",
+ "a=rtpmap:%d%s%s\r\n",
msg, endpoint, mode, endp->cfg->source_addr,
- port, endp->tcfg->audio_payload,
- endp->tcfg->audio_payload, endp->tcfg->audio_name);
+ port, payload_type,
+ payload_type,
+ audio_name ? " " : "", audio_name ? audio_name : "");
if (len < 0)
return;