[PATCH 4/5] mgcp: Parse SDP to get rate and packet duration

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Jacob Erlbeck jerlbeck at sysmocom.de
Tue Dec 10 14:02:18 UTC 2013


This patch parses the 'ptime' and 'maxptime' SDP attributes, and the
SDP rate information and sets up packet_duration_ms accordingly. If
the packet duration is unknown or allows for different values (e.g.
because 'ptime' uses a range or 'maxptime' allows for more than one
frame) the duration is set to 0.

Sponsored-by: On-Waves ehf
---
 openbsc/src/libmgcp/mgcp_network.c  |    9 ++++++
 openbsc/src/libmgcp/mgcp_protocol.c |   53 +++++++++++++++++++++++++++++++----
 openbsc/tests/mgcp/mgcp_test.c      |    4 +++
 openbsc/tests/mgcp/mgcp_test.ok     |   10 +++----
 4 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/openbsc/src/libmgcp/mgcp_network.c b/openbsc/src/libmgcp/mgcp_network.c
index 8bd8afb..40227af 100644
--- a/openbsc/src/libmgcp/mgcp_network.c
+++ b/openbsc/src/libmgcp/mgcp_network.c
@@ -300,6 +300,15 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *sta
 			state->seq_offset, state->packet_duration,
 			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
 			endp->conn_mode);
+		if (state->packet_duration == 0 && rtp_end->force_constant_timing)
+			LOGP(DMGCP, LOGL_ERROR,
+			"Cannot patch timestamps on 0x%x: "
+			"RTP packet duration is unknown, SSRC: %u, "
+			"from %s:%d in %d\n",
+			ENDPOINT_NUMBER(endp), state->in_stream.ssrc,
+			inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
+			endp->conn_mode);
+
 	} else if (state->in_stream.ssrc != ssrc) {
 		LOGP(DMGCP, LOGL_NOTICE,
 			"The SSRC changed on 0x%x: %u -> %u  "
diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c
index 5403861..b9e1382 100644
--- a/openbsc/src/libmgcp/mgcp_protocol.c
+++ b/openbsc/src/libmgcp/mgcp_protocol.c
@@ -562,25 +562,64 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
 {
 	char *line;
 	int found_media = 0;
+	int audio_payload = -1;
 
 	for_each_line(line, p->save) {
 		switch (line[0]) {
-		case 'a':
 		case 'o':
 		case 's':
 		case 't':
 		case 'v':
 			/* skip these SDP attributes */
 			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",
+				   &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));
+			} else if (sscanf(line, "a=ptime:%d-%d",
+					  &ptime, &ptime2) >= 1) {
+				if (ptime2 > 0 && ptime2 != ptime)
+					rtp->packet_duration_ms = 0;
+				else
+					rtp->packet_duration_ms = ptime;
+			} else if (sscanf(line, "a=maxptime:%d", &ptime2) == 1) {
+				if (ptime2 * rtp->frame_duration_den >
+				    rtp->frame_duration_num * 1500)
+					/* more than 1 frame */
+					rtp->packet_duration_ms = 0;
+			}
+			break;
+		}
 		case 'm': {
 			int port;
-			int payload;
+			audio_payload = -1;
 
 			if (sscanf(line, "m=audio %d RTP/AVP %d",
-				   &port, &payload) == 2) {
+				   &port, &audio_payload) == 2) {
 				rtp->rtp_port = htons(port);
 				rtp->rtcp_port = htons(port + 1);
-				rtp->payload_type = payload;
+				rtp->payload_type = audio_payload;
 				found_media = 1;
 			}
 			break;
@@ -608,8 +647,10 @@ static int parse_sdp_data(struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p)
 
 	if (found_media)
 		LOGP(DMGCP, LOGL_NOTICE,
-		     "Got media info via SDP: port %d, payload %d, addr %s\n",
-		     ntohs(rtp->rtp_port), rtp->payload_type, inet_ntoa(rtp->addr));
+		     "Got media info via SDP: port %d, payload %d, "
+		     "duration %d, addr %s\n",
+		     ntohs(rtp->rtp_port), rtp->payload_type,
+		     rtp->packet_duration_ms, inet_ntoa(rtp->addr));
 
 	return found_media;
 }
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index 3591124..8768426 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -636,6 +636,10 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
 	 * trunk.endpoints are set up properly. */
 	mgcp_free_endp(&endp);
 
+	/* There is no MGCP/SDP around, so set this by hand to make timestamp
+	 * patching possible */
+	rtp->packet_duration_ms = 20;
+
 	rtp->payload_type = 98;
 
 	for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) {
diff --git a/openbsc/tests/mgcp/mgcp_test.ok b/openbsc/tests/mgcp/mgcp_test.ok
index 24f9b33..f9dd7cb 100644
--- a/openbsc/tests/mgcp/mgcp_test.ok
+++ b/openbsc/tests/mgcp/mgcp_test.ok
@@ -16,22 +16,22 @@ Testing AUEP2
 Testing MDCX1
 Testing MDCX2
 Testing CRCX
-Packet duration not set
+Detected packet duration: 40
 Requested packetetization period: 20-20
 Testing MDCX3
 Packet duration not set
 Requested packetization period not set
 Testing MDCX4
-Packet duration not set
+Detected packet duration: 40
 Requested packetetization period: 20-20
 Testing MDCX4_PT1
-Packet duration not set
+Detected packet duration: 40
 Requested packetetization period: 20-40
 Testing MDCX4_PT2
-Packet duration not set
+Detected packet duration: 40
 Requested packetetization period: 20-20
 Testing MDCX4_PT3
-Packet duration not set
+Detected packet duration: 40
 Requested packetization period not set
 Testing DLCX
 Detected packet duration: 20
-- 
1.7.9.5





More information about the OpenBSC mailing list