mirror of https://gerrit.osmocom.org/libosmocore
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
This commit is contained in:
parent
8f026bf3b7
commit
8fa13c66ac
|
@ -13,6 +13,7 @@ endif
|
|||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
***********************************************************************/
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue