aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-08-29 07:43:35 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-08-30 15:04:15 +0200
commit4f4bffdf207b9526dddb5cb38d47d50e5b6a9709 (patch)
treee9a33f6f305d3d4bf7669baf204e4211c017ebb2
parent91eb1fa1829119f14ebb50928fed562ee11161a1 (diff)
rtp: Add routine to compress the audio samples
No way to undo the compression yet, no integration with the MGCP network code.
-rw-r--r--openbsc/include/openbsc/mgcp_internal.h28
-rw-r--r--openbsc/include/openbsc/rtp_rfc.h1
-rw-r--r--openbsc/src/libmgcp/Makefile.am2
-rw-r--r--openbsc/src/libmgcp/rtp_helper.c130
-rw-r--r--openbsc/tests/mgcp/mgcp_test.c87
5 files changed, 247 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index a9d51494b..dc00112d3 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -23,8 +23,14 @@
#ifndef OPENBSC_MGCP_DATA_H
#define OPENBSC_MGCP_DATA_H
+#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <stdint.h>
+
#define CI_UNUSED 0
enum mgcp_connection_mode {
@@ -53,6 +59,18 @@ struct mgcp_rtp_state {
int32_t timestamp_offset;
};
+/**
+ * I hold the state of the RTP compression.
+ */
+struct mgcp_rtp_compr_state {
+ uint32_t generated_ssrc;
+ uint32_t timestamp;
+ uint16_t sequence;
+
+ /* on wire it is 8bit, so we can see overruns here */
+ int16_t last_ts;
+};
+
struct mgcp_rtp_end {
/* statistics */
unsigned int packets;
@@ -122,6 +140,11 @@ struct mgcp_endpoint {
/* tap for the endpoint */
struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+
+ /* compression for this endpoint */
+ int compr_enabled;
+ struct mgcp_rtp_compr_state compr_loc_state;
+ struct mgcp_rtp_compr_state compr_rem_state;
};
#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
@@ -150,5 +173,10 @@ static inline int endp_back_channel(int endpoint)
struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+int rtp_compress(struct mgcp_rtp_compr_state *state, struct msgb *msg,
+ int endpoint, struct llist_head *rtp_packets);
+struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, void *ctx,
+ struct msgb *msg);
+
#endif
diff --git a/openbsc/include/openbsc/rtp_rfc.h b/openbsc/include/openbsc/rtp_rfc.h
index 68a8e7c97..55b194e5e 100644
--- a/openbsc/include/openbsc/rtp_rfc.h
+++ b/openbsc/include/openbsc/rtp_rfc.h
@@ -44,6 +44,7 @@ struct rtp_hdr {
uint16_t sequence;
uint32_t timestamp;
uint32_t ssrc;
+ uint8_t data[0];
} __attribute__((packed));
diff --git a/openbsc/src/libmgcp/Makefile.am b/openbsc/src/libmgcp/Makefile.am
index 6347eac69..cf5c30e08 100644
--- a/openbsc/src/libmgcp/Makefile.am
+++ b/openbsc/src/libmgcp/Makefile.am
@@ -4,4 +4,4 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS)
noinst_LIBRARIES = libmgcp.a
-libmgcp_a_SOURCES = mgcp_protocol.c mgcp_network.c mgcp_vty.c
+libmgcp_a_SOURCES = mgcp_protocol.c mgcp_network.c mgcp_vty.c rtp_helper.c
diff --git a/openbsc/src/libmgcp/rtp_helper.c b/openbsc/src/libmgcp/rtp_helper.c
new file mode 100644
index 000000000..77fc4c819
--- /dev/null
+++ b/openbsc/src/libmgcp/rtp_helper.c
@@ -0,0 +1,130 @@
+/*
+ * (C) 2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2011 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <openbsc/debug.h>
+#include <openbsc/rtp_rfc.h>
+#include <openbsc/mgcp_internal.h>
+
+#include <osmocom/core/talloc.h>
+
+#include <string.h>
+
+
+struct reduced_rtp_hdr {
+ /** I will need to be inflated to the SSRC */
+ uint8_t endp;
+ /** I will need to be inflated to both the TS and the Sequence Number */
+ uint8_t sequence_no;
+ /**
+ * I represent the type, you should know the size of each payload now.
+ * I represent the number of payloads that follow
+ */
+ uint8_t type : 4,
+ payloads : 4;
+ uint8_t data[0];
+} __attribute__((packed));
+
+#define msgb_put_struct(msg, str) \
+ (str *) msgb_put(msg, sizeof(str))
+
+/**
+ * I try to compress these packets into one single stream. I have various
+ * limitations. I do not support packets that jump backwards, the rtp_packets
+ * list must be properly sorted, everything else will be discarded.
+ *
+ * Also somethings like:
+ * seq_no:1, seq_no:3, seq_no: 5
+ * will be folded into
+ * 3 payloads, Payload:1, Payload:2, Payload:3
+ *
+ * And the decoder will decode it to:
+ * seq_no:1, seq_no:2, seq_no: 3
+ *
+ */
+int rtp_compress(struct mgcp_rtp_compr_state *state, struct msgb *msg,
+ int endp, struct llist_head *rtp_packets)
+{
+ struct msgb *rtp, *tmp;
+ struct reduced_rtp_hdr *reduced_hdr;
+ uint16_t last_sequence = 0;
+ int count = 0;
+ uint8_t *data;
+
+ /*
+ * sanity check if everything is a RTP packet
+ */
+ llist_for_each_entry_safe(rtp, tmp, rtp_packets, list) {
+ struct rtp_hdr *hdr;
+ uint16_t sequence;
+
+ if (msgb_l2len(rtp) < sizeof(struct rtp_hdr)) {
+ LOGP(DMGCP, LOGL_ERROR,
+ "Packet is too small on %d/0x%x\n", endp, endp);
+ llist_del(&rtp->list);
+ talloc_free(rtp);
+ continue;
+ }
+
+ hdr = (struct rtp_hdr *) rtp->l2h;
+ sequence = ntohs(hdr->sequence);
+ if (sequence < last_sequence && sequence != 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Packet is not in sequence.\n");
+ llist_del(&rtp->list);
+ talloc_free(rtp);
+ last_sequence = sequence;
+ continue;
+ }
+
+ last_sequence = sequence;
+ count += 1;
+ }
+
+
+ if (llist_empty(rtp_packets))
+ return 0;
+
+ reduced_hdr = msgb_put_struct(msg, struct reduced_rtp_hdr);
+ reduced_hdr->endp = endp;
+ reduced_hdr->sequence_no = ++state->last_ts % UCHAR_MAX;
+ reduced_hdr->type = 0;
+ reduced_hdr->payloads = count;
+
+
+ llist_for_each_entry_safe(rtp, tmp, rtp_packets, list) {
+ struct rtp_hdr *hdr = (struct rtp_hdr *) rtp->l2h;
+ uint32_t len = msgb_l2len(rtp) - sizeof(*hdr);
+ data = msgb_put(msg, len);
+ memcpy(data, hdr->data, len);
+
+ llist_del(&rtp->list);
+ talloc_free(rtp);
+ }
+
+ return count;
+}
+
+struct llist_head rtp_decompress(struct mgcp_rtp_compr_state *state, void *ctx,
+ struct msgb *msg)
+{
+ struct llist_head list;
+ INIT_LLIST_HEAD(&list);
+
+ return list;
+}
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index b7273de43..8c4ee84d0 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -22,6 +22,8 @@
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
+
+#include <limits.h>
#include <string.h>
static struct msgb *create_auep1()
@@ -73,10 +75,95 @@ static void test_auep(void)
talloc_free(cfg);
}
+/**
+ * Sample RTP data
+ */
+
+static const uint8_t packet_1[] = {
+ 0x80, 0xe2, 0xcb, 0x87, 0xf7, 0xcb, 0xba, 0x48,
+ 0x6f, 0x0f, 0xb1, 0xda, 0x00, 0x14, 0xb2, 0xb6,
+ 0xf8, 0x7b, 0x04, 0x81, 0x69, 0xf1, 0xdd, 0x33,
+ 0xd4, 0xd9, 0x45, 0x5c, 0x54,
+};
+
+
+static const uint8_t packet_2[] = {
+ 0x80, 0x62, 0xcb, 0x88, 0xf7, 0xcb, 0xba, 0xe8,
+ 0x6f, 0x0f, 0xb1, 0xda, 0x00, 0x14, 0x3d, 0xb6,
+ 0xf8, 0x08, 0x77, 0xfd, 0xeb, 0x51, 0xc7, 0x3f,
+ 0xb3, 0x82, 0x56, 0x56, 0x64,
+};
+
+static const uint8_t packet_3[] = {
+ 0x80, 0x62, 0xcb, 0x89, 0xf7, 0xcb, 0xbb, 0x88,
+ 0x6f, 0x0f, 0xb1, 0xda, 0x00, 0x14, 0xb2, 0xb6,
+ 0xf8, 0x7e, 0x01, 0x01, 0x7e, 0x06, 0x63, 0xb5,
+ 0xc7, 0x41, 0x65, 0xa0, 0x10
+};
+
+static const uint8_t packet_4[] = {
+ 0x80, 0x62, 0xcb, 0x8a, 0xf7, 0xcb, 0xbc, 0x28,
+ 0x6f, 0x0f, 0xb1, 0xda, 0x00, 0x14, 0x3d, 0xb6,
+ 0xf8, 0x1c, 0x63, 0xf9, 0xe9, 0x71, 0xc3, 0x3f,
+ 0x13, 0x0e, 0x5e, 0x56, 0x6c
+};
+
+static struct msgb *from(const uint8_t *data, uint16_t len)
+{
+ struct msgb *msg = msgb_alloc_headroom(4096, 128, "from");
+ msg->l2h = msgb_put(msg, len);
+ memcpy(msg->l2h, data, len);
+ return msg;
+}
+
+#define FROM(array) \
+ from(array, sizeof(array))
+
+void test_compress()
+{
+ struct msgb *msg1 = FROM(packet_1);
+ struct msgb *msg2 = FROM(packet_2);
+ struct msgb *msg3 = FROM(packet_3);
+ struct msgb *msg4 = FROM(packet_4);
+
+ struct llist_head list;
+ INIT_LLIST_HEAD(&list);
+ msgb_enqueue(&list, msg1);
+ msgb_enqueue(&list, msg2);
+ msgb_enqueue(&list, msg3);
+ msgb_enqueue(&list, msg4);
+
+ struct mgcp_rtp_compr_state state;
+ memset(&state, 0, sizeof(state));
+ state.last_ts = UCHAR_MAX;
+
+ struct msgb *out = msgb_alloc_headroom(4096, 128, "out");
+ out->l2h = msgb_put(out, 0);
+
+ int rc = rtp_compress(&state, out, 23, &list);
+ if (rc != 4) {
+ fprintf(stderr, "Result is not 4: %d\n", rc);
+ abort();
+ }
+
+ if (msgb_l2len(out) != (17*4 + 3)) {
+ fprintf(stderr, "Result is wrong size: %d\n", msgb_l2len(out));
+ abort();
+ }
+
+ printf("output is: %s\n", osmo_hexdump(out->l2h, msgb_l2len(out)));
+
+
+ list = rtp_decompress(&state, NULL, out);
+
+ msgb_free(out);
+}
+
int main(int argc, char **argv)
{
osmo_init_logging(&log_info);
test_auep();
+ test_compress();
return 0;
}