Change in mncc-python[master]: rtpsource: Modularize generation of RTP frames

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/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Fri May 1 14:28:34 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/mncc-python/+/17978 )

Change subject: rtpsource: Modularize generation of RTP frames
......................................................................

rtpsource: Modularize generation of RTP frames

Change-Id: Iad98e1753fef1927c0e8a7493372141372a38224
---
M rtpsource/Makefile
M rtpsource/internal.h
A rtpsource/rtp_provider.c
A rtpsource/rtp_provider.h
A rtpsource/rtp_provider_static.c
M rtpsource/rtpsource.c
6 files changed, 230 insertions(+), 7 deletions(-)

Approvals:
  osmith: Verified
  laforge: Looks good to me, approved



diff --git a/rtpsource/Makefile b/rtpsource/Makefile
index 9972325..2ede792 100644
--- a/rtpsource/Makefile
+++ b/rtpsource/Makefile
@@ -4,7 +4,7 @@
 CFLAGS:= -g -Wall $(OSMO_CFLAGS)
 LIBS:= $(OSMO_LIBS)
 
-rtpsource: rtpsource.o ctrl_if.o
+rtpsource: rtpsource.o ctrl_if.o rtp_provider.o rtp_provider_static.o
 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
 
 
diff --git a/rtpsource/internal.h b/rtpsource/internal.h
index 13d07aa..a4501a2 100644
--- a/rtpsource/internal.h
+++ b/rtpsource/internal.h
@@ -8,6 +8,8 @@
 	DMAIN,
 };
 
+struct rtp_provider_instance;
+
 struct rtp_connection {
 	struct llist_head list;
 
@@ -21,6 +23,7 @@
 	uint16_t remote_port;
 
 	uint8_t rtp_pt;
+	struct rtp_provider_instance *rtp_prov_inst;
 };
 
 struct rtpsource_state {
diff --git a/rtpsource/rtp_provider.c b/rtpsource/rtp_provider.c
new file mode 100644
index 0000000..0d2b9c6
--- /dev/null
+++ b/rtpsource/rtp_provider.c
@@ -0,0 +1,54 @@
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/linuxlist.h>
+
+#include "rtp_provider.h"
+#include "internal.h"
+
+
+static LLIST_HEAD(g_providers);
+static LLIST_HEAD(g_prov_instances);
+
+void rtp_provider_register(struct rtp_provider *prov)
+{
+	llist_add_tail(&prov->list, &g_providers);
+}
+
+const struct rtp_provider *rtp_provider_find(const char *name)
+{
+	struct rtp_provider *p;
+	llist_for_each_entry(p, &g_providers, list) {
+		if (!strcmp(name, p->name))
+			return p;
+	}
+	LOGP(DMAIN, LOGL_ERROR, "Couldn't find RTP provider '%s'\n", name);
+	return NULL;
+}
+
+struct rtp_provider_instance *
+rtp_provider_instance_alloc(void *ctx, const struct rtp_provider *provider, enum codec_type codec)
+{
+	struct rtp_provider_instance *pi;
+
+	pi = talloc_zero(ctx, struct rtp_provider_instance);
+	if (!pi)
+		return NULL;
+
+	pi->provider = provider;
+	pi->codec = codec;
+	llist_add_tail(&pi->list, &g_prov_instances);
+
+	return pi;
+}
+
+void rtp_provider_instance_free(struct rtp_provider_instance *pi)
+{
+	llist_del(&pi->list);
+	talloc_free(pi);
+}
+
+int rtp_provider_instance_gen_frame(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size)
+{
+	OSMO_ASSERT(pi->provider);
+	return pi->provider->rtp_gen(pi, out, out_size);
+}
diff --git a/rtpsource/rtp_provider.h b/rtpsource/rtp_provider.h
new file mode 100644
index 0000000..7048a3e
--- /dev/null
+++ b/rtpsource/rtp_provider.h
@@ -0,0 +1,51 @@
+#pragma once
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+enum codec_type {
+	CODEC_ULAW,
+	CODEC_ALAW,
+	CODEC_GSM_FR,
+	CODEC_GSM_EFR,
+	CODEC_GSM_HR,
+	CODEC_AMR_4_75,
+	CODEC_AMR_5_15,
+	CODEC_AMR_5_90,
+	CODEC_AMR_6_70,
+	CODEC_AMR_7_40,
+	CODEC_AMR_7_95,
+	CODEC_AMR_10_2,
+	CODEC_AMR_12_2,
+	CODEC_AMR_SID,
+	_NUM_CODECS
+};
+
+struct rtp_provider_instance;
+
+struct rtp_provider {
+	/* global list of RTP providers */
+	struct llist_head list;
+	const char *name;
+
+	/* generate the next RTP packet; return length in octests or negative on error */
+	int (*rtp_gen)(struct rtp_provider_instance *inst, uint8_t *out, size_t out_size);
+};
+
+struct rtp_provider_instance {
+	/* entry in global list of RTP provider instances */
+	struct llist_head list;
+	/* pointer to provider of which we are an instance */
+	const struct rtp_provider *provider;
+	/* codec payload we are to generate */
+	enum codec_type codec;
+
+	/* private user data */
+	void *priv;
+};
+
+void rtp_provider_register(struct rtp_provider *prov);
+const struct rtp_provider *rtp_provider_find(const char *name);
+
+struct rtp_provider_instance *rtp_provider_instance_alloc(void *ctx, const struct rtp_provider *provider, enum codec_type codec);
+void rtp_provider_instance_free(struct rtp_provider_instance *pi);
+int rtp_provider_instance_gen_frame(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size);
diff --git a/rtpsource/rtp_provider_static.c b/rtpsource/rtp_provider_static.c
new file mode 100644
index 0000000..323e686
--- /dev/null
+++ b/rtpsource/rtp_provider_static.c
@@ -0,0 +1,107 @@
+
+#include <errno.h>
+#include <osmocom/codec/codec.h>
+#include <osmocom/core/utils.h>
+
+#include "rtp_provider.h"
+#include "internal.h"
+
+static struct rtp_provider static_provider;
+
+static const uint8_t len4codec[_NUM_CODECS] = {
+    [CODEC_ULAW] = 160,
+    [CODEC_ALAW] = 160,
+    [CODEC_GSM_FR] = GSM_FR_BYTES,
+    [CODEC_GSM_EFR] = GSM_EFR_BYTES,
+    [CODEC_GSM_HR] = GSM_HR_BYTES,
+    [CODEC_AMR_4_75] = 12,
+    [CODEC_AMR_5_15] = 13,
+    [CODEC_AMR_5_90] = 15,
+    [CODEC_AMR_6_70] = 17,
+    [CODEC_AMR_7_40] = 19,
+    [CODEC_AMR_7_95] = 20,
+    [CODEC_AMR_10_2] = 26,
+    [CODEC_AMR_12_2] = 31,
+    [CODEC_AMR_SID] = 5,
+};
+
+/* generate a static / fixed RTP payload of matching codec/mode */
+static int rtp_gen_static(struct rtp_provider_instance *pi, uint8_t *out, size_t out_size)
+{
+	uint8_t len;
+
+	OSMO_ASSERT(pi->provider == &static_provider);
+
+	len = len4codec[pi->codec];
+	if (out_size < len) {
+		LOGP(DMAIN, LOGL_ERROR, "out_size %zu < %u\n", out_size, len);
+		return -EINVAL;
+	}
+
+	memset(out, 0, len);
+
+	switch (pi->codec) {
+	case CODEC_ULAW:
+	case CODEC_ALAW:
+		break;
+	case CODEC_GSM_FR:
+		out[0] = (out[0] & 0x0f) | 0xD0; /* mask in first four bit for FR */
+		break;
+	case CODEC_GSM_EFR:
+		out[0] = (out[0] & 0x0f) | 0xC0; /* mask in first four bit for EFR */
+		break;
+	case CODEC_GSM_HR:
+		break;
+	case CODEC_AMR_4_75:
+		out[0] = 0 << 4;
+		out[1] = 0 << 3;
+		break;
+	case CODEC_AMR_5_15:
+		out[0] = 1 << 4;
+		out[1] = 1 << 3;
+		break;
+	case CODEC_AMR_5_90:
+		out[0] = 2 << 4;
+		out[1] = 2 << 3;
+		break;
+	case CODEC_AMR_6_70:
+		out[0] = 3 << 4;
+		out[1] = 3 << 3;
+		break;
+	case CODEC_AMR_7_40:
+		out[0] = 4 << 4;
+		out[1] = 4 << 3;
+		break;
+	case CODEC_AMR_7_95:
+		out[0] = 5 << 4;
+		out[1] = 5 << 3;
+		break;
+	case CODEC_AMR_10_2:
+		out[0] = 6 << 4;
+		out[1] = 6 << 3;
+		break;
+	case CODEC_AMR_12_2:
+		out[0] = 7 << 4;
+		out[1] = 7 << 3;
+		break;
+	case CODEC_AMR_SID:
+		out[0] = 2 << 4; /* CMR: 5.90 */
+		out[0] = 8 << 3;
+		break;
+	default:
+		OSMO_ASSERT(0);
+	}
+
+	return len;
+}
+
+
+static struct rtp_provider static_provider = {
+	.name = "static",
+	.rtp_gen = &rtp_gen_static,
+};
+
+static void __attribute__((constructor)) rtp_provider_static_constr(void)
+{
+	rtp_provider_register(&static_provider);
+}
diff --git a/rtpsource/rtpsource.c b/rtpsource/rtpsource.c
index 569d962..3087262 100644
--- a/rtpsource/rtpsource.c
+++ b/rtpsource/rtpsource.c
@@ -48,6 +48,7 @@
 #include <osmocom/trau/osmo_ortp.h>
 
 #include "internal.h"
+#include "rtp_provider.h"
 
 
 /* find a connection based on its CNAME */
@@ -64,13 +65,18 @@
 /* create a new RTP connection for given CNAME; includes binding of local RTP port */
 struct rtp_connection *create_connection(struct rtpsource_state *rss, const char *cname)
 {
+	const struct rtp_provider *rtp_prov;
 	struct rtp_connection *conn;
+	enum codec_type codec = CODEC_GSM_FR; // TODO: configurable
 	const char *host;
 	int port;
 	int rc;
 
 	OSMO_ASSERT(!find_connection_by_cname(rss, cname));
 
+	rtp_prov = rtp_provider_find("static"); // TODO: configurable
+	OSMO_ASSERT(rtp_prov);
+
 	conn = talloc_zero(rss, struct rtp_connection);
 	OSMO_ASSERT(conn);
 	conn->cname = talloc_strdup(conn, cname);
@@ -90,6 +96,9 @@
 	osmo_rtp_set_source_desc(conn->rtp_sock, conn->cname, "rtpsource", NULL, NULL,
 				 NULL, "osmo-rtpsource", NULL);
 
+	conn->rtp_prov_inst = rtp_provider_instance_alloc(conn, rtp_prov, codec);
+	OSMO_ASSERT(conn->rtp_prov_inst);
+
 	llist_add_tail(&conn->list, &rss->connections);
 
 	CLOGP(conn, DMAIN, LOGL_INFO, "Created RTP connection; local=%s:%u\n",
@@ -156,12 +165,11 @@
 
 	/* iterate over all RTP connections and send one frame each */
 	llist_for_each_entry(conn, &rss->connections, list) {
-		int i;
-		/* TODO: have different sources (file+name, ...) */
-		uint8_t payload[33];
-		memset(payload, 0, sizeof(payload));
-		payload[0] = (payload[0] & 0x0f) | 0xD0; /* mask in first four bit for FR */
-		osmo_rtp_send_frame_ext(conn->rtp_sock, payload, sizeof(payload), 160, false);
+		uint8_t payload[256];
+		int i, len;
+
+		len = rtp_provider_instance_gen_frame(conn->rtp_prov_inst, payload, sizeof(payload));
+		osmo_rtp_send_frame_ext(conn->rtp_sock, payload, len, 160, false);
 		/* make sure RTP clock advances correctly, even if we missed transmit of some */
 		for (i = 1; i < expire_count; i++)
 			osmo_rtp_skipped_frame(conn->rtp_sock, 160);

-- 
To view, visit https://gerrit.osmocom.org/c/mncc-python/+/17978
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: mncc-python
Gerrit-Branch: master
Gerrit-Change-Id: Iad98e1753fef1927c0e8a7493372141372a38224
Gerrit-Change-Number: 17978
Gerrit-PatchSet: 2
Gerrit-Owner: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200501/40872b1f/attachment.htm>


More information about the gerrit-log mailing list