diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-08-29 07:43:35 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-08-30 15:04:15 +0200 |
commit | 4f4bffdf207b9526dddb5cb38d47d50e5b6a9709 (patch) | |
tree | e9a33f6f305d3d4bf7669baf204e4211c017ebb2 | |
parent | 91eb1fa1829119f14ebb50928fed562ee11161a1 (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.h | 28 | ||||
-rw-r--r-- | openbsc/include/openbsc/rtp_rfc.h | 1 | ||||
-rw-r--r-- | openbsc/src/libmgcp/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/libmgcp/rtp_helper.c | 130 | ||||
-rw-r--r-- | openbsc/tests/mgcp/mgcp_test.c | 87 |
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; } |