aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2019-02-28 16:00:23 +0100
committerPhilipp Maier <pmaier@sysmocom.de>2019-02-28 17:18:10 +0100
commit63ce8ce2e973c893675bd8fbed2b8fabaa0d6018 (patch)
tree8fc6eafae0366030bfd7de94f46e85fd6d35282e
parent9fc8a02196d484daeff6ecf6be97d6b550b274ab (diff)
AMR: Add option to convert between bw-effient and octet aligned modepmaier/amrmangle
RFC3267 specifies two framing modes for AMR packets. An octet aligned mode is specified where all fields of the AMR packets are aligned to octet boundaries. The second framing mode is the bandwith efficient mode where the fields are directly packed one after another. Which format is used is usually communicated by out of band means, however it is still possible to distinguish the framing mode by looking at the frame. Once the framing mode is distinguished, the packet can be converted into the opposite framing mode. - Add new VTY rtp-patch options - Add conversion function Change-Id: Id46a3622a6b1995d5fce4bc611d409bcb4aef13b Depends: libosmo-netif I5b5a0fa644d8dbb1f04f9d7e35312683c7b3d196 Related: OS#3807
-rw-r--r--include/osmocom/mgcp/mgcp.h1
-rw-r--r--include/osmocom/mgcp/mgcp_internal.h1
-rw-r--r--src/libosmo-mgcp/mgcp_network.c41
-rw-r--r--src/libosmo-mgcp/mgcp_protocol.c1
-rw-r--r--src/libosmo-mgcp/mgcp_vty.c39
5 files changed, 83 insertions, 0 deletions
diff --git a/include/osmocom/mgcp/mgcp.h b/include/osmocom/mgcp/mgcp.h
index 5886a6534..4c5ec7df8 100644
--- a/include/osmocom/mgcp/mgcp.h
+++ b/include/osmocom/mgcp/mgcp.h
@@ -191,6 +191,7 @@ struct mgcp_trunk_config {
int force_constant_ssrc; /* 0: don't, 1: once */
int force_aligned_timing;
bool rfc5993_hr_convert;
+ bool amr_oa_bwe_convert;
/* spec handling */
int force_realloc;
diff --git a/include/osmocom/mgcp/mgcp_internal.h b/include/osmocom/mgcp/mgcp_internal.h
index a6239c2e3..c82c5e10e 100644
--- a/include/osmocom/mgcp/mgcp_internal.h
+++ b/include/osmocom/mgcp/mgcp_internal.h
@@ -129,6 +129,7 @@ struct mgcp_rtp_end {
/* should we perform align_rtp_timestamp_offset() (1) or not (0) */
int force_aligned_timing;
bool rfc5993_hr_convert;
+ bool amr_oa_bwe_convert;
/* Each end has a separate socket for RTP and RTCP */
struct osmo_fd rtp;
diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c
index 33738bc6e..5f96ace02 100644
--- a/src/libosmo-mgcp/mgcp_network.c
+++ b/src/libosmo-mgcp/mgcp_network.c
@@ -34,6 +34,7 @@
#include <osmocom/core/socket.h>
#include <osmocom/core/byteswap.h>
#include <osmocom/netif/rtp.h>
+#include <osmocom/netif/amr.h>
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/mgcp_common.h>
#include <osmocom/mgcp/mgcp_internal.h>
@@ -686,6 +687,41 @@ static void rfc5993_hr_convert(struct mgcp_endpoint *endp, char *data, int *len)
}
}
+/* For AMR RTP two framing modes are defined RFC3267. There is a bandwith
+ * efficient encoding scheme where all fields are packed together one after
+ * another and an octet aligned mode where all fields are aligned to octet
+ * boundaries. This function is used to convert between the two modes */
+static void amr_oa_bwe_convert(struct mgcp_endpoint *endp, char *data, int *len)
+{
+ /* NOTE: *data has an overall length of RTP_BUF_SIZE, so there is
+ * plenty of space available to store the slightly larger, converted
+ * data */
+
+ struct rtp_hdr *rtp_hdr;
+ unsigned int payload_len;
+ int rc;
+
+ OSMO_ASSERT(*len >= sizeof(struct rtp_hdr));
+ rtp_hdr = (struct rtp_hdr *)data;
+
+ payload_len = *len - sizeof(struct rtp_hdr);
+
+ if (osmo_amr_is_oa(rtp_hdr->data, payload_len))
+ rc = osmo_amr_oa_to_bwe(rtp_hdr->data, payload_len);
+ else
+ rc = osmo_amr_bwe_to_oa(rtp_hdr->data, payload_len,
+ RTP_BUF_SIZE);
+
+ if (rc < 0) {
+ LOGP(DRTP, LOGL_ERROR,
+ "endpoint:0x%x AMR RTP packet conversion failed\n",
+ ENDPOINT_NUMBER(endp));
+ return;
+ }
+
+ *len = rc + sizeof(struct rtp_hdr);
+}
+
/* Forward data to a debug tap. This is debug function that is intended for
* debugging the voice traffic with tools like gstreamer */
static void forward_data(int fd, struct mgcp_rtp_tap *tap, const char *buf,
@@ -799,6 +835,11 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
"GSM-HR-08") == 0)
rfc5993_hr_convert(endp, buf, &buflen);
+ else if (rtp_end->amr_oa_bwe_convert
+ && strcmp(conn_src->end.codec->subtype_name,
+ "AMR") == 0)
+ amr_oa_bwe_convert(endp, buf, &buflen);
+
LOGP(DRTP, LOGL_DEBUG,
"endpoint:0x%x process/send to %s %s "
"rtp_port:%u rtcp_port:%u\n",
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index 82db02f97..77f75de59 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -653,6 +653,7 @@ void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
rtp->force_aligned_timing = tcfg->force_aligned_timing;
rtp->force_constant_ssrc = patch_ssrc ? 1 : 0;
rtp->rfc5993_hr_convert = tcfg->rfc5993_hr_convert;
+ rtp->amr_oa_bwe_convert = tcfg->amr_oa_bwe_convert;
LOGP(DLMGCP, LOGL_DEBUG,
"Configuring RTP endpoint: local port %d%s%s\n",
diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c
index a47376b25..803853ee7 100644
--- a/src/libosmo-mgcp/mgcp_vty.c
+++ b/src/libosmo-mgcp/mgcp_vty.c
@@ -38,6 +38,7 @@
#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
#define RTP_TS101318_RFC5993_CONV_STR "Convert GSM-HR from TS101318 to RFC5993 and vice versa\n"
+#define RTP_AMR_OA_BWE_CONV_STR "Convert AMR from octet-aligned to bandwith-efficient mode and vice versa\n"
static struct mgcp_config *g_cfg = NULL;
@@ -744,6 +745,22 @@ DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
return CMD_SUCCESS;
}
+DEFUN(cfg_mgcp_patch_rtp_amr_oa_bwe,
+ cfg_mgcp_patch_rtp_amr_oa_bwe_cmd,
+ "rtp-patch amr-oa-bwe", RTP_PATCH_STR RTP_AMR_OA_BWE_CONV_STR)
+{
+ g_cfg->trunk.amr_oa_bwe_convert = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mgcp_no_patch_rtp_amr_oa_bwe,
+ cfg_mgcp_no_patch_rtp_amr_oa_bwe_cmd,
+ "no rtp-patch amr-oa-bwe", NO_STR RTP_PATCH_STR RTP_AMR_OA_BWE_CONV_STR)
+{
+ g_cfg->trunk.amr_oa_bwe_convert = false;
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_mgcp_no_patch_rtp,
cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
{
@@ -1040,6 +1057,24 @@ DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
return CMD_SUCCESS;
}
+DEFUN(cfg_trunk_patch_rtp_amr_oa_bwe,
+ cfg_trunk_patch_rtp_amr_oa_bwe_cmd,
+ "rtp-patch amr-oa-bwe", RTP_PATCH_STR RTP_AMR_OA_BWE_CONV_STR)
+{
+ struct mgcp_trunk_config *trunk = vty->index;
+ trunk->amr_oa_bwe_convert = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_trunk_no_patch_rtp_amr_oa_bwe,
+ cfg_trunk_no_patch_rtp_amr_oa_bwe_cmd,
+ "no rtp-patch amr-oa-bwe", NO_STR RTP_PATCH_STR RTP_AMR_OA_BWE_CONV_STR)
+{
+ struct mgcp_trunk_config *trunk = vty->index;
+ trunk->amr_oa_bwe_convert = false;
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_trunk_no_patch_rtp,
cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
{
@@ -1448,6 +1483,8 @@ int mgcp_vty_init(void)
install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_rfc5993hr_cmd);
install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_rfc5993hr_cmd);
+ install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_amr_oa_bwe_cmd);
+ install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_amr_oa_bwe_cmd);
install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
@@ -1481,6 +1518,8 @@ int mgcp_vty_init(void)
install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_rfc5993hr_cmd);
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_rfc5993hr_cmd);
+ install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_amr_oa_bwe_cmd);
+ install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_amr_oa_bwe_cmd);
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);