summaryrefslogtreecommitdiffstats
path: root/src/codec
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-05-25 18:13:51 +0200
committerHolger Freyther <holger@freyther.de>2016-05-31 10:11:51 +0000
commit92db150488bdadf6577a4968feabd5a3ab694c5e (patch)
treebbe91ee76c6dd6e41077ba22d29dc9c574b13516 /src/codec
parentadef12a3497d14aafe677b77b468b952f4c6b5d5 (diff)
Add helper functions for AMR codec
* add functions to encode/decode various codec paramters from RTP payload with AMR frame according to RFC 4867 * those functions are extended version based on code from osmo-bts' amr.c by Andreas Eversberg * add corresponding enum types and strings for logging * add regression tests It's useful both to replace manual parsing in osmo-bts with fuctions covered by test suite and as a debugging helpers for issues related to AMR. Change-Id: Ia217679a07d3fbc970f435e20f6eac33d34bd597 Related: OS#1562 Reviewed-on: https://gerrit.osmocom.org/118 Tested-by: Jenkins Builder Reviewed-by: Holger Freyther <holger@freyther.de>
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/Makefile.am2
-rw-r--r--src/codec/gsm690.c106
2 files changed, 107 insertions, 1 deletions
diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am
index b4834e52..619897f5 100644
--- a/src/codec/Makefile.am
+++ b/src/codec/Makefile.am
@@ -2,7 +2,7 @@
# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
LIBVERSION=0:0:0
-AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS)
AM_CFLAGS = -Wall
lib_LTLIBRARIES = libosmocodec.la
diff --git a/src/codec/gsm690.c b/src/codec/gsm690.c
index fdf3302f..0f4bf8fe 100644
--- a/src/codec/gsm690.c
+++ b/src/codec/gsm690.c
@@ -22,7 +22,12 @@
*/
#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/codec/codec.h>
/*
* These table map between the raw encoder parameter output and
* the format used before channel coding. Both in GSM and in various
@@ -208,3 +213,104 @@ const uint16_t gsm690_4_75_bitorder[95] = {
88, 90, 91, 34, 55, 68, 89, 37, 58, 71,
92, 31, 52, 65, 86,
};
+
+static const uint8_t amr_len_by_ft[16] = {
+ 12, 13, 15, 17, 19, 20, 26, 31, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const struct value_string osmo_amr_type_names[] = {
+ { AMR_4_75, "AMR 4,75 kbits/s" },
+ { AMR_5_15, "AMR 5,15 kbit/s" },
+ { AMR_5_90, "AMR 5,90 kbit/s" },
+ { AMR_6_70, "AMR 6,70 kbit/s (PDC-EFR)" },
+ { AMR_7_40, "AMR 7,40 kbit/s (TDMA-EFR)" },
+ { AMR_7_95, "AMR 7,95 kbit/s" },
+ { AMR_10_2, "AMR 10,2 kbit/s" },
+ { AMR_12_2, "AMR 12,2 kbit/s (GSM-EFR)" },
+ { AMR_SID, "AMR SID" },
+ { AMR_GSM_EFR_SID, "GSM-EFR SID" },
+ { AMR_TDMA_EFR_SID, "TDMA-EFR SID" },
+ { AMR_PDC_EFR_SID, "PDC-EFR SID" },
+ { AMR_NO_DATA, "No Data/NA" },
+ { 0, NULL },
+};
+
+/*! \brief Decode various AMR parameters from RTP payload (RFC 4867) acording to
+ * 3GPP TS 26.101
+ * \param[in] rtppayload Payload from RTP packet
+ * \param[in] payload_len length of rtppayload
+ * \param[out] cmr AMR Codec Mode Request, not filled if NULL
+ * \param[out] cmi AMR Codec Mode Indicator, -1 if not applicable for this type,
+ * not filled if NULL
+ * \param[out] ft AMR Frame Type, not filled if NULL
+ * \param[out] bfi AMR Bad Frame Indicator, not filled if NULL
+ * \param[out] sti AMR SID Type Indicator, -1 if not applicable for this type,
+ * not filled if NULL
+ * \returns length of AMR data or negative value on error
+ */
+int osmo_amr_rtp_dec(const uint8_t *rtppayload, int payload_len, uint8_t *cmr,
+ int8_t *cmi, enum osmo_amr_type *ft,
+ enum osmo_amr_quality *bfi, int8_t *sti)
+{
+ /* RFC 4867 § 4.4.2 ToC - compound payloads are not supported: F = 0 */
+ uint8_t type = (rtppayload[1] >> 3) & 0xf;
+
+ /* compound payloads are not supported */
+ if (rtppayload[1] >> 7)
+ return -ENOTSUP;
+
+ if (payload_len - 2 < amr_len_by_ft[type])
+ return -ENOTSUP;
+
+ if (payload_len < 2)
+ return -EINVAL;
+
+ if (ft)
+ *ft = type;
+
+ if (cmr)
+ *cmr = rtppayload[0] >> 4;
+
+ if (bfi)
+ *bfi = (rtppayload[1] >> 2) & 1;
+
+ /* Table 6 in 3GPP TS 26.101 */
+ if (cmi)
+ *cmi = (type == AMR_SID) ? ((rtppayload[6] >> 1) & 7) : -1;
+
+ if (sti)
+ *sti = (type == AMR_SID) ? (rtppayload[6] & 0x10) : -1;
+
+ return 2 + amr_len_by_ft[type];
+}
+
+/*! \brief Encode various AMR parameters from RTP payload (RFC 4867)
+ * \param[out] payload Payload for RTP packet, contains speech data (if any)
+ * except for have 2 first bytes where header will be built
+ * \param[in] cmr AMR codec Mode Request
+ * \param[in] ft AMR Frame Type
+ * \param[in] bfi AMR Bad Frame Indicator
+ * \returns length of AMR data (header + ToC + speech data) or negative value
+ * on error
+ *
+ * Note: only octet-aligned mode is supported so the header occupies 2 full
+ * bytes. Optional interleaving header is not supported.
+ */
+int osmo_amr_rtp_enc(uint8_t *payload, uint8_t cmr, enum osmo_amr_type ft,
+ enum osmo_amr_quality bfi)
+{
+ if (cmr > 15)
+ return -EINVAL;
+
+ if (ft > 15)
+ return -ENOTSUP;
+
+ /* RFC 4867 § 4.3.1 payload header */
+ payload[0] = cmr << 4;
+
+ /* RFC 4867 § 4.4.2 ToC - compound payloads are not supported: F = 0 */
+ payload[1] = (((uint8_t)ft) << 3) | (((uint8_t)bfi) << 2);
+
+ /* speech data */
+ return 2 + amr_len_by_ft[ft];
+}