codec cosmetic: move old FR ECU code to ecu_fr_old.c

The current FR codec ECU implementation consists of two parts:
there is a pair of functions that implement the actual functionality,
and these functions are also made public as a now-deprecated legacy
API - and there is the new ECU abstraction.  If the FR ECU
implementation behind the generic ECU abstraction is to be changed
to a different one, the old implementation still has to be retained
for those public legacy osmo_ecu_fr_reset() and osmo_ecu_fr_conceal()
API functions to remain available and unbroken.  Move this legacy
ECU implementation to its own C module in preparation for changing
the preferred ECU implementation.

Related: OS#6027
Change-Id: Ia169b8bcc6331227a11b78eb7ffca0c7ab838c69
diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am
index f05ac1f..f7877fe 100644
--- a/src/codec/Makefile.am
+++ b/src/codec/Makefile.am
@@ -13,6 +13,7 @@
 
 lib_LTLIBRARIES = libosmocodec.la
 
-libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu.c ecu_fr.c
+libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu.c ecu_fr.c \
+	ecu_fr_old.c
 libosmocodec_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined
 libosmocodec_la_LIBADD = $(top_builddir)/src/core/libosmocore.la
diff --git a/src/codec/ecu_fr.c b/src/codec/ecu_fr.c
index 218d837..124a58c 100644
--- a/src/codec/ecu_fr.c
+++ b/src/codec/ecu_fr.c
@@ -21,146 +21,9 @@
 #include <stdint.h>
 #include <errno.h>
 
-#include <osmocom/core/bitvec.h>
-
-#include <osmocom/codec/gsm610_bits.h>
 #include <osmocom/codec/codec.h>
 #include <osmocom/codec/ecu.h>
 
-/* See also GSM 06.11, chapter 6 Example solution */
-#define GSM610_XMAXC_REDUCE	4
-#define GSM610_XMAXC_LEN	6
-
-/**
- * Reduce the XMAXC field. When the XMAXC field reaches
- * zero the function will return true.
- */
-static bool reduce_xmaxcr(struct bitvec *frame_bitvec,
-	const unsigned int index)
-{
-	unsigned int field_index;
-	uint64_t field;
-
-	field_index = index;
-	field = bitvec_read_field(frame_bitvec, &field_index, GSM610_XMAXC_LEN);
-	if (field > GSM610_XMAXC_REDUCE)
-		field -= GSM610_XMAXC_REDUCE;
-	else
-		field = 0;
-
-	field_index = index;
-	bitvec_write_field(frame_bitvec, &field_index, field, GSM610_XMAXC_LEN);
-
-	return field == 0;
-}
-
-/**
- * Reduce all XMAXC fields in the frame. When all XMAXC fields
- * reach zero, then the function will return true.
- */
-static bool reduce_xmaxcr_all(struct bitvec *frame_bitvec)
-{
-	bool silent = true;
-
-	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC00);
-	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC10);
-	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC20);
-	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC30);
-
-	return silent;
-}
-
-/* Use certain modifications to conceal the errors in a full rate frame */
-static int conceal_frame(uint8_t *frame)
-{
-	struct bitvec *frame_bitvec;
-	unsigned int len;
-	bool silent;
-	int rc = 0;
-
-	/* In case we already deal with a silent frame,
-	 * there is nothing to, we just abort immediately */
-	if (osmo_fr_check_sid(frame, GSM_FR_BYTES))
-		return 0;
-
-	/* Attempt to allocate memory for bitvec */
-	frame_bitvec = bitvec_alloc(GSM_FR_BYTES, NULL);
-	if (!frame_bitvec)
-		return -ENOMEM;
-
-	/* Convert a frame to bitvec */
-	len = bitvec_unpack(frame_bitvec, frame);
-	if (len != GSM_FR_BYTES) {
-		rc = -EIO;
-		goto leave;
-	}
-
-	/* Fudge frame parameters */
-	silent = reduce_xmaxcr_all(frame_bitvec);
-
-	/* If we reached silence level, mute the frame
-	 * completely, this also means that we can
-	 * save the bitvec_pack operation */
-	if (silent) {
-		memset(frame, 0x00, GSM_FR_BYTES);
-		frame[0] = 0xd0;
-		goto leave;
-	}
-
-	/* Convert back to packed byte form */
-	len = bitvec_pack(frame_bitvec, frame);
-	if (len != GSM_FR_BYTES) {
-		rc = -EIO;
-		goto leave;
-	}
-
-leave:
-	bitvec_free(frame_bitvec);
-	return rc;
-}
-
-/*!
- * To be called when a good frame is received.
- * This function will then create a backup of the frame
- * and reset the internal state.
- * \param[in] state The state object for the ECU
- * \param[out] frame The valid frame (GSM_FR_BYTES bytes in RTP payload format)
- */
-void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, const uint8_t *frame)
-{
-	state->subsequent_lost_frame = false;
-	memcpy(state->frame_backup, frame, GSM_FR_BYTES);
-}
-
-/*!
- * To be called when a bad frame is received.
- * This function will then generate a replacement frame
- * that can be used to conceal the dropout.
- * \param[in] state The state object for the ECU
- * \param[out] frame The buffer to fill with GSM_FR_BYTES of replacement frame
- * \returns 0 if the frame was sucessfully filled
- */
-int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame)
-{
-	int rc;
-
-	/* For subsequent frames we run the error concealment
-	 * functions on the backed up frame before we restore
-	 * the backup */
-	if (state->subsequent_lost_frame) {
-		rc = conceal_frame(state->frame_backup);
-		if (rc)
-			return rc;
-	}
-
-	/* Restore the backed up frame and set flag in case
-	 * we receive even more bad frames */
-	memcpy(frame, state->frame_backup, GSM_FR_BYTES);
-	state->subsequent_lost_frame = true;
-
-	return 0;
-}
-
 /***********************************************************************
  * Integration with ECU core
  ***********************************************************************/
diff --git a/src/codec/ecu_fr_old.c b/src/codec/ecu_fr_old.c
new file mode 100644
index 0000000..cfefce1
--- /dev/null
+++ b/src/codec/ecu_fr_old.c
@@ -0,0 +1,166 @@
+/*
+ * (C) 2017 by sysmocom - s.f.m.c. GmbH
+ * (C) 2017 by Philipp Maier <pmaier@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ *
+ * This module implements legacy, deprecated osmo_ecu_fr_reset() and
+ * osmo_ecu_fr_conceal() functions only - see ecu_fr.c for the new
+ * GSM-FR ECU implementation.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <osmocom/core/bitvec.h>
+
+#include <osmocom/codec/gsm610_bits.h>
+#include <osmocom/codec/codec.h>
+#include <osmocom/codec/ecu.h>
+
+/* See also GSM 06.11, chapter 6 Example solution */
+#define GSM610_XMAXC_REDUCE	4
+#define GSM610_XMAXC_LEN	6
+
+/**
+ * Reduce the XMAXC field. When the XMAXC field reaches
+ * zero the function will return true.
+ */
+static bool reduce_xmaxcr(struct bitvec *frame_bitvec,
+	const unsigned int index)
+{
+	unsigned int field_index;
+	uint64_t field;
+
+	field_index = index;
+	field = bitvec_read_field(frame_bitvec, &field_index, GSM610_XMAXC_LEN);
+	if (field > GSM610_XMAXC_REDUCE)
+		field -= GSM610_XMAXC_REDUCE;
+	else
+		field = 0;
+
+	field_index = index;
+	bitvec_write_field(frame_bitvec, &field_index, field, GSM610_XMAXC_LEN);
+
+	return field == 0;
+}
+
+/**
+ * Reduce all XMAXC fields in the frame. When all XMAXC fields
+ * reach zero, then the function will return true.
+ */
+static bool reduce_xmaxcr_all(struct bitvec *frame_bitvec)
+{
+	bool silent = true;
+
+	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC00);
+	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC10);
+	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC20);
+	silent &= reduce_xmaxcr(frame_bitvec, GSM610_RTP_XMAXC30);
+
+	return silent;
+}
+
+/* Use certain modifications to conceal the errors in a full rate frame */
+static int conceal_frame(uint8_t *frame)
+{
+	struct bitvec *frame_bitvec;
+	unsigned int len;
+	bool silent;
+	int rc = 0;
+
+	/* In case we already deal with a silent frame,
+	 * there is nothing to, we just abort immediately */
+	if (osmo_fr_check_sid(frame, GSM_FR_BYTES))
+		return 0;
+
+	/* Attempt to allocate memory for bitvec */
+	frame_bitvec = bitvec_alloc(GSM_FR_BYTES, NULL);
+	if (!frame_bitvec)
+		return -ENOMEM;
+
+	/* Convert a frame to bitvec */
+	len = bitvec_unpack(frame_bitvec, frame);
+	if (len != GSM_FR_BYTES) {
+		rc = -EIO;
+		goto leave;
+	}
+
+	/* Fudge frame parameters */
+	silent = reduce_xmaxcr_all(frame_bitvec);
+
+	/* If we reached silence level, mute the frame
+	 * completely, this also means that we can
+	 * save the bitvec_pack operation */
+	if (silent) {
+		memset(frame, 0x00, GSM_FR_BYTES);
+		frame[0] = 0xd0;
+		goto leave;
+	}
+
+	/* Convert back to packed byte form */
+	len = bitvec_pack(frame_bitvec, frame);
+	if (len != GSM_FR_BYTES) {
+		rc = -EIO;
+		goto leave;
+	}
+
+leave:
+	bitvec_free(frame_bitvec);
+	return rc;
+}
+
+/*!
+ * To be called when a good frame is received.
+ * This function will then create a backup of the frame
+ * and reset the internal state.
+ * \param[in] state The state object for the ECU
+ * \param[out] frame The valid frame (GSM_FR_BYTES bytes in RTP payload format)
+ */
+void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, const uint8_t *frame)
+{
+	state->subsequent_lost_frame = false;
+	memcpy(state->frame_backup, frame, GSM_FR_BYTES);
+}
+
+/*!
+ * To be called when a bad frame is received.
+ * This function will then generate a replacement frame
+ * that can be used to conceal the dropout.
+ * \param[in] state The state object for the ECU
+ * \param[out] frame The buffer to fill with GSM_FR_BYTES of replacement frame
+ * \returns 0 if the frame was successfully filled
+ */
+int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame)
+{
+	int rc;
+
+	/* For subsequent frames we run the error concealment
+	 * functions on the backed up frame before we restore
+	 * the backup */
+	if (state->subsequent_lost_frame) {
+		rc = conceal_frame(state->frame_backup);
+		if (rc)
+			return rc;
+	}
+
+	/* Restore the backed up frame and set flag in case
+	 * we receive even more bad frames */
+	memcpy(frame, state->frame_backup, GSM_FR_BYTES);
+	state->subsequent_lost_frame = true;
+
+	return 0;
+}