changeset 510:5bf71b091323

libgsmhr1: add direct conversion from RTP input to decoder params
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 25 Aug 2024 02:19:37 +0000
parents b7ddcb178ef6
children a5d61331b675
files libgsmhr1/Makefile libgsmhr1/rtp_in_direct.c libgsmhr1/tw_gsmhr.h
diffstat 3 files changed, 88 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libgsmhr1/Makefile	Sat Aug 17 23:11:51 2024 +0000
+++ b/libgsmhr1/Makefile	Sun Aug 25 02:19:37 2024 +0000
@@ -1,6 +1,6 @@
 OBJS=	dhf_params.o enc_out_order.o mathdp31.o mathhalf.o pack_frame.o \
-	rtp_in.o sid_detect.o sid_reset.o sp_rom.o twts002_in.o twts002_out.o \
-	unpack_frame.o
+	rtp_in.o rtp_in_direct.o sid_detect.o sid_reset.o sp_rom.o twts002_in.o\
+	twts002_out.o unpack_frame.o
 HDRS=	enc_out_order.h mathdp31.h mathhalf.h namespace.h sp_rom.h tw_gsmhr.h \
 	typedefs.h
 LIB=	libgsmhr1.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgsmhr1/rtp_in_direct.c	Sun Aug 25 02:19:37 2024 +0000
@@ -0,0 +1,84 @@
+/*
+ * The function implemented in this module takes whatever HRv1 payload format
+ * came in from RTP (can be RFC 5993 with or without TW-TS-002 extensions,
+ * can be bare TS 101 318, can be zero-length or missing payload) and turns it
+ * into the internal input form for the HRv1 decoder.  It is logically
+ * equivalent to calling gsmhr_rtp_in_preen() followed by
+ * gsmhr_decoder_twts002_in(), but is more efficient by avoiding the extra
+ * intermediate buffer and copying.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include "tw_gsmhr.h"
+
+static void emit_bfi_nodata(int16_t *params)
+{
+	memset(params, 0, sizeof(int16_t) * GSMHR_NUM_PARAMS);
+	params[18] = 2;		/* BFI with no data */
+	params[19] = 0;		/* UFI */
+	params[20] = 0;		/* SID */
+	params[21] = 0;		/* TAF */
+}
+
+int gsmhr_rtp_in_direct(const uint8_t *rtp_in, unsigned rtp_in_len,
+			int16_t *params)
+{
+	int ft;
+
+	switch (rtp_in_len) {
+	case 0:
+		/* BFI-no-data, but not an invalid RTP input per se */
+		emit_bfi_nodata(params);
+		return 0;
+	case 1:
+		/*
+		 * This length is valid only if the payload is in
+		 * RFC 5993 or TW-TS-002 format with FT=1 or FT=7.
+		 */
+		if (rtp_in[0] & 0x80)
+			goto bad_rtp_input;
+		ft = rtp_in[0] >> 4;
+		if (ft == 1 || ft == 7) {
+			gsmhr_decoder_twts002_in(rtp_in, params);
+			return 0;
+		} else
+			goto bad_rtp_input;
+	case GSMHR_FRAME_LEN_RPF:
+		/*
+		 * The length is that of a TS 101 318 payload.
+		 * No further checks can be done: every possible
+		 * bit pattern is a valid payload in this format.
+		 * But we do need to check for a perfect SID
+		 * (the only kind of SID this format allows)
+		 * and mark it accordingly in the output.
+		 */
+		gsmhr_unpack_ts101318(rtp_in, params);
+		params[18] = 0;		/* BFI */
+		params[19] = 0;		/* UFI */
+		params[20] = gsmhr_ts101318_is_perfect_sid(rtp_in);
+		params[21] = 0;		/* TAF */
+		return 0;
+	case GSMHR_FRAME_LEN_5993:
+		/*
+		 * This length is valid only if the payload is in
+		 * RFC 5993 or TW-TS-002 format with FT=0, FT=2 or FT=6.
+		 */
+		if (rtp_in[0] & 0x80)
+			goto bad_rtp_input;
+		ft = rtp_in[0] >> 4;
+		if (ft == 0 || ft == 2 || ft == 6) {
+			gsmhr_decoder_twts002_in(rtp_in, params);
+			return 0;
+		} else
+			goto bad_rtp_input;
+	default:
+	bad_rtp_input:
+		/*
+		 * Treat it like BFI-no-data, and tell the caller
+		 * that we received an invalid RTP payload.
+		 */
+		emit_bfi_nodata(params);
+		return -1;
+	}
+}
--- a/libgsmhr1/tw_gsmhr.h	Sat Aug 17 23:11:51 2024 +0000
+++ b/libgsmhr1/tw_gsmhr.h	Sun Aug 25 02:19:37 2024 +0000
@@ -48,6 +48,8 @@
 
 int gsmhr_rtp_in_preen(const uint8_t *rtp_in, unsigned rtp_in_len,
 			uint8_t *canon_pl);
+int gsmhr_rtp_in_direct(const uint8_t *rtp_in, unsigned rtp_in_len,
+			int16_t *param);
 
 /* perfect SID detection and regeneration */