falconia has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/32711 )
Change subject: codec cosmetic: move old FR ECU code to ecu_fr_old.c ......................................................................
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 --- M src/codec/Makefile.am M src/codec/ecu_fr.c A src/codec/ecu_fr_old.c 3 files changed, 189 insertions(+), 138 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/11/32711/1
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; +}