[MERGED] osmo-ttcn3-hacks[master]: Add RTP_Emulation (stream source/sink) on top of RTP_CodecPort

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/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Wed Dec 13 18:53:50 UTC 2017


Harald Welte has submitted this change and it was merged.

Change subject: Add RTP_Emulation (stream source/sink) on top of RTP_CodecPort
......................................................................


Add RTP_Emulation (stream source/sink) on top of RTP_CodecPort

Change-Id: Ic0750bdc025cd6f16094843550429d976fb44f4f
---
A library/RTP_Emulation.ttcn
1 file changed, 209 insertions(+), 0 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/library/RTP_Emulation.ttcn b/library/RTP_Emulation.ttcn
new file mode 100644
index 0000000..b8b1dbe
--- /dev/null
+++ b/library/RTP_Emulation.ttcn
@@ -0,0 +1,209 @@
+module RTP_Emulation {
+
+/* Functionalities that we want this module to imeplement:
+ *  * act as a RTP source that generates a RTP Stream
+ *  * act asaa RTP sink that consumes a RTP Stream
+ *
+ * for all of the above, we want to be able to 
+ *  * specify the payload type
+ *  * specify the interval / sample rate
+ *  * create drop-outs in the stream
+ *  * detect reordered or lost frames
+ *  * validate if the size of the frames matches epectations
+ *  * play back real audio (at least some tones?)
+ *  * enable/disable generation/verification of RTCP
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from RTP_Types all;
+import from RTP_CodecPort all;
+import from RTP_CodecPort_CtrlFunct all;
+
+type component RTP_Emulation_CT {
+	/* down-facing ports for RTP and RTCP codec ports on top of IPL4asp */
+	port RTP_CODEC_PT RTP;
+	var integer g_rtp_conn_id := -1;
+	port RTP_CODEC_PT RTCP;
+	var integer g_rtcp_conn_id := -1;
+
+	/* user-facing port for controlling the binding */
+	port RTPEM_CTRL_PT CTRL;
+
+	/* configurable by user, should be fixed */
+	var INT7b g_tx_payload_type := 0;
+	var integer g_tx_samplerate_hz := 8000;
+	var integer g_tx_duration_ms := 20;
+	var BIT32_BO_LAST g_tx_ssrc := hex2bit('DEADBEEF'H);
+
+	var HostName g_remote_host;
+	var PortNumber g_remote_port;
+	var HostName g_local_host;
+	var PortNumber g_local_port;
+
+	/* state variables, change over time */
+	var boolean g_rx_enabled := false;
+	var LIN2_BO_LAST g_tx_next_seq := 0;
+	var uint32_t g_tx_next_ts := 0;
+
+	var INT7b g_rx_payload_type := 0;
+	var LIN2_BO_LAST g_rx_last_seq;
+	var uint32_t g_rx_last_ts;
+}
+
+type enumerated RtpemMode {
+	RTPEM_MODE_NONE,
+	RTPEM_MODE_TXONLY,
+	RTPEM_MODE_RXONLY,
+	RTPEM_MODE_BIDIR
+};
+
+signature RTPEM_bind(in HostName local_host, inout PortNumber local_port);
+signature RTPEM_connect(in HostName remote_host, in PortNumber remote_port);
+signature RTPEM_mode(in RtpemMode mode);
+
+type port RTPEM_CTRL_PT procedure {
+	inout RTPEM_bind, RTPEM_connect, RTPEM_mode;
+} with { extension "internal" };
+
+template PDU_RTP ts_RTP(BIT32_BO_LAST ssrc, INT7b pt, LIN2_BO_LAST seq, uint32_t ts,
+			octetstring payload, BIT1 marker := '0'B) := {
+	version := 2,
+	padding_ind := '0'B,
+	extension_ind := '0'B,
+	CSRC_count := 0,
+	marker_bit := marker,
+	payload_type := pt,
+	sequence_number := seq,
+	time_stamp := int2bit(ts, 4),
+	SSRC_id := ssrc,
+	CSRCs := omit,
+	ext_header := omit,
+	data := payload
+}
+
+private function f_tx_rtp(octetstring payload, BIT1 marker := '0'B) runs on RTP_Emulation_CT {
+	var PDU_RTP rtp := valueof(ts_RTP(g_tx_ssrc, g_tx_payload_type, g_tx_next_seq,
+					  g_tx_next_ts, payload, marker));
+	RTP.send(t_RTP_Send(g_rtp_conn_id, RTP_messages_union:{rtp:=rtp}));
+	/* increment sequence + timestamp for next transmit */
+	g_tx_next_seq := g_tx_next_seq + 1;
+	g_tx_next_ts := g_tx_next_ts + (g_tx_samplerate_hz mod (1000 mod g_tx_duration_ms));
+}
+
+function f_main() runs on RTP_Emulation_CT
+{
+	var Result res;
+
+	timer T_transmit := 1000.0/int2float(g_tx_duration_ms);
+	var RTP_RecvFrom rx_rtp;
+	var template RTP_RecvFrom tr := {
+		connId := ?,
+		remName := ?,
+		remPort := ?,
+		locName := ?,
+		locPort := ?,
+		msg := ?
+	};
+	var template RTP_RecvFrom tr_rtp := tr;
+	var template RTP_RecvFrom tr_rtcp := tr;
+	tr_rtp.connId := g_rtp_conn_id;
+	tr_rtp.msg := { rtp := ? };
+	tr_rtp.connId := g_rtcp_conn_id;
+	tr_rtcp.msg := { rtcp := ? };
+
+	while (true) {
+	alt {
+		/* control procedures (calls) from the user */
+		[] CTRL.getcall(RTPEM_bind:{?,?}) -> param(g_local_host, g_local_port) {
+			if (g_local_port rem 2 == 1) {
+				//CTRL.raise(RTPEM_bind, "Local Port is not an even port number!");
+				log("Local Port is not an even port number!");
+				continue;
+			}
+			res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTP, g_local_host,
+								g_local_port, {udp:={}});
+			g_rtp_conn_id := res.connId;
+			res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTP, g_local_host,
+								g_local_port+1, {udp:={}});
+			g_rtcp_conn_id := res.connId;
+			CTRL.reply(RTPEM_bind:{g_local_host, g_local_port});
+		}
+		[] CTRL.getcall(RTPEM_connect:{?,?}) -> param (g_remote_host, g_remote_port) {
+			if (g_remote_port rem 2 == 1) {
+				//CTRL.raise(RTPEM_connect, "Remote Port is not an even number!");
+				log("Remote Port is not an even number!");
+				continue;
+			}
+			res := RTP_CodecPort_CtrlFunct.f_IPL4_connect(RTP, g_remote_host,
+								g_remote_port,
+								g_local_host, g_local_port,
+								g_rtp_conn_id, {udp:={}});
+			res := RTP_CodecPort_CtrlFunct.f_IPL4_connect(RTCP, g_remote_host,
+								g_remote_port+1,
+								g_local_host, g_local_port+1,
+								g_rtcp_conn_id, {udp:={}});
+			CTRL.reply(RTPEM_connect:{g_remote_host, g_remote_port});
+		}
+		[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_NONE}) {
+			T_transmit.stop;
+			g_rx_enabled := false;
+		}
+		[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_TXONLY}) {
+			/* start transmit timer */
+			T_transmit.start;
+			g_rx_enabled := false;
+		}
+		[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_RXONLY}) {
+
+			T_transmit.stop;
+			if (g_rx_enabled == false) {
+				/* flush queues */
+				RTP.clear;
+				RTCP.clear;
+				g_rx_enabled := true;
+			}
+		}
+		[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_BIDIR}) {
+			T_transmit.start;
+			if (g_rx_enabled == false) {
+				/* flush queues */
+				RTP.clear;
+				RTCP.clear;
+				g_rx_enabled := true;
+			}
+		}
+
+		/* simply ignore any RTTP/RTCP if receiver not enabled */
+		[g_rx_enabled==false] RTP.receive(tr_rtp) { }
+		[g_rx_enabled==false] RTCP.receive(tr_rtp) { }
+
+		/* process received RTCP/RTP if receiver enabled */
+		[g_rx_enabled] RTP.receive(tr_rtp) -> value rx_rtp {
+			log("RX RTP: ", rx_rtp);
+		}
+		[g_rx_enabled] RTCP.receive(tr_rtcp) -> value rx_rtp {
+			log("RX RTCP: ", rx_rtp);
+		}
+
+		/* transmit if timer has expired */
+		[] T_transmit.timeout {
+			/* send one RTP frame, re-start timer */
+			f_tx_rtp('01020304'O);
+			T_transmit.start;
+		}
+
+		/* fail on any unexpected messages */
+		[] RTP.receive {
+			setverdict(fail, "Received unexpected type from RTP");
+		}
+		[] RTCP.receive {
+			setverdict(fail, "Received unexpected type from RTCP");
+		}
+	}
+	}
+}
+
+
+}

-- 
To view, visit https://gerrit.osmocom.org/5326
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic0750bdc025cd6f16094843550429d976fb44f4f
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list