[02/11] mgcp: Add audio info fields to struct mgcp_rtp_end
diff mbox

Message ID 1399891147-31419-2-git-send-email-jerlbeck@sysmocom.de
State Superseded
Headers show

Commit Message

Jacob Erlbeck May 12, 2014, 10:38 a.m. UTC
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).

Sponsored-by: On-Waves ehf
---
 openbsc/include/openbsc/mgcp_internal.h |    3 ++
 openbsc/src/libmgcp/mgcp_protocol.c     |   82 +++++++++++++++++++++++--------
 2 files changed, 64 insertions(+), 21 deletions(-)

Comments

Holger Freyther May 14, 2014, 5:31 a.m. UTC | #1
On Mon, May 12, 2014 at 12:38:58PM +0200, Jacob Erlbeck wrote:

> +	rtp->subtype_name = talloc_strdup(NULL, audio_codec);
> +	rtp->audio_name = talloc_strdup(NULL, audio_name);

Attach this to a context that at least belongs to a MGCP context.
Make sure to release these strings in mgcp_free_endp or in the
reset one. Or did I miss a call to set_audio_info?

Patch
diff mbox

diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index 56c280d..72ac8e9 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -81,11 +81,14 @@  struct mgcp_rtp_end {
 	/* per endpoint data */
 	int payload_type;
 	uint32_t rate;
+	int channels;
 	uint32_t frame_duration_num;
 	uint32_t frame_duration_den;
 	int  frames_per_packet;
 	uint32_t packet_duration_ms;
 	char *fmtp_extra;
+	char *audio_name;
+	char *subtype_name;
 	int output_enabled;
 
 	/* RTP patching */
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 0f8614c..761a35c 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);
 
@@ -231,6 +233,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;
 
@@ -244,11 +248,12 @@  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->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))
@@ -514,6 +519,47 @@  static int parse_conn_mode(const char *msg, struct mgcp_endpoint *endp)
 	return ret;
 }
 
+static int set_audio_info(struct mgcp_rtp_end *rtp,
+			  int payload_type, const char *audio_name)
+{
+	int rate = 8000;
+	int channels = 1;
+	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:
+			 rtp->rate = 8000;
+			 rtp->channels = 1;
+			 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(NULL, audio_codec);
+	rtp->audio_name = talloc_strdup(NULL, 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))
@@ -600,29 +646,18 @@  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;
 
-			if (sscanf(line, "a=rtpmap:%d %64s",
+			if (sscanf(line, "a=rtpmap:%d %63s",
 				   &payload, audio_name) == 2) {
 				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(rtp, payload, audio_name);
 			} else if (sscanf(line, "a=ptime:%d-%d",
 					  &ptime, &ptime2) >= 1) {
 				if (ptime2 > 0 && ptime2 != ptime)
@@ -645,8 +680,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(rtp, audio_payload, NULL);
 			}
 			break;
 		}
@@ -826,7 +861,7 @@  mgcp_header_done:
 	endp->allocated = 1;
 
 	/* set up RTP media parameters */
-	endp->bts_end.payload_type = tcfg->audio_payload;
+	set_audio_info(&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) {
@@ -1252,6 +1287,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;
 }
 
@@ -1329,6 +1365,9 @@  static void send_msg(struct mgcp_endpoint *endp, int endpoint, int port,
 {
 	char buf[2096];
 	int len;
+	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;
 
 	/* hardcoded to AMR right now, we do not know the real type at this point */
 	len = snprintf(buf, sizeof(buf),
@@ -1338,10 +1377,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;