From 750d8311f5c0455f2caaa2ae9dba2cc99300c9dd Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 1 Aug 2019 20:05:05 +0200 Subject: codec/ecu: Introduce new generic Error Concealment Unit abstraction We don't want to expose the details of a given ECU implementation to the user (e.g. osmo-bts), but have a generic abstraction layer where an ECU implementation can simply register a few call-back functions with the generic core. As the developer and copyright holder of the related code, I hereby state that any ECU implementation using 'struct osmo_ecu_ops' and registering with the 'osmo_ecu_register()' function shall not be considered as a derivative work under any applicable copyright law; the copyleft terms of GPLv2 shall hence not apply to any such ECU implementation. The intent of the above exception is to allow anyone to combine third party Error Concealment Unit implementations with libosmocore, including but not limited to such published by ETSI. Change-Id: I4d33c9c7c2d4c7462ff38a49c178b65accae1915 --- src/codec/Makefile.am | 2 +- src/codec/ecu.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/codec/ecu_fr.c | 51 ++++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 src/codec/ecu.c (limited to 'src') diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am index b522d43a..c9d7a228 100644 --- a/src/codec/Makefile.am +++ b/src/codec/Makefile.am @@ -13,6 +13,6 @@ endif lib_LTLIBRARIES = libosmocodec.la -libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu_fr.c +libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c ecu.c ecu_fr.c libosmocodec_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined libosmocodec_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/codec/ecu.c b/src/codec/ecu.c new file mode 100644 index 00000000..db7148ce --- /dev/null +++ b/src/codec/ecu.c @@ -0,0 +1,118 @@ +/* Core infrastructure for ECU implementations */ + +/* (C) 2019 by Harald Welte + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* As the developer and copyright holder of the related code, I hereby + * state that any ECU implementation using 'struct osmo_ecu_ops' and + * registering with the 'osmo_ecu_register()' function shall not be + * considered as a derivative work under any applicable copyright law; + * the copyleft terms of GPLv2 shall hence not apply to any such ECU + * implementation. + * + * The intent of the above exception is to allow anyone to combine third + * party Error Concealment Unit implementations with libosmocodec. + * including but not limited to such published by ETSI. + * + * -- Harald Welte on August 1, 2019. + */ + +#include +#include + +#include +#include + +static const struct osmo_ecu_ops *g_ecu_ops[_NUM_OSMO_ECU_CODECS]; + +/*********************************************************************** + * high-level API for users + ***********************************************************************/ + +/*! initialize an ECU instance for given codec. + * \param[in] ctx talloc context from which to allocate + * \parma[in] codec codec for which to initialize/create ECU */ +struct osmo_ecu_state *osmo_ecu_init(void *ctx, enum osmo_ecu_codec codec) +{ + if (codec >= ARRAY_SIZE(g_ecu_ops)) + return NULL; + if (!g_ecu_ops[codec] || !g_ecu_ops[codec]->init) + return NULL; + return g_ecu_ops[codec]->init(ctx, codec); +} + +/*! destroy an ECU instance */ +void osmo_ecu_destroy(struct osmo_ecu_state *st) +{ + if (st->codec >= ARRAY_SIZE(g_ecu_ops)) + return; + if (!g_ecu_ops[st->codec]) + return; + + if (!g_ecu_ops[st->codec]->destroy) + talloc_free(st); + else + g_ecu_ops[st->codec]->destroy(st); +} + +/*! process a received frame a substitute/erroneous frame. + * \param[in] st ECU state/instance on which to operate + * \param[in] bfi Bad Frame Indication + * \param[in] frame received codec frame to be processed + * \param[in] frame_bytes number of bytes available in frame */ +int osmo_ecu_frame_in(struct osmo_ecu_state *st, bool bfi, + const uint8_t *frame, unsigned int frame_bytes) +{ + if (st->codec >= ARRAY_SIZE(g_ecu_ops)) + return -EINVAL; + if (!g_ecu_ops[st->codec]) + return -EBUSY; + return g_ecu_ops[st->codec]->frame_in(st, bfi, frame, frame_bytes); +} + +/*! generate output data for a substitute/erroneous frame. + * \param[in] st ECU state/instance on which to operate + * \param[out] frame_out buffer for generated output frame + * \return number of bytes written to frame_out; negative on error */ +int osmo_ecu_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out) +{ + if (st->codec >= ARRAY_SIZE(g_ecu_ops)) + return -EINVAL; + if (!g_ecu_ops[st->codec]) + return -EBUSY; + return g_ecu_ops[st->codec]->frame_out(st, frame_out); +} + +/*********************************************************************** + * low-level API for ECU implementations + ***********************************************************************/ + +/*! register an ECU implementation for a given codec */ +int osmo_ecu_register(const struct osmo_ecu_ops *ops, enum osmo_ecu_codec codec) +{ + if (codec >= ARRAY_SIZE(g_ecu_ops)) + return -EINVAL; + if (g_ecu_ops[codec]) + return -EBUSY; + + g_ecu_ops[codec] = ops; + + return 0; +} diff --git a/src/codec/ecu_fr.c b/src/codec/ecu_fr.c index ef42ea9f..4545172a 100644 --- a/src/codec/ecu_fr.c +++ b/src/codec/ecu_fr.c @@ -164,3 +164,54 @@ int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame) return 0; } + +/*********************************************************************** + * Integration with ECU core + ***********************************************************************/ + +static struct osmo_ecu_state *ecu_fr_init(void *ctx, enum osmo_ecu_codec codec) +{ + struct osmo_ecu_state *st; + size_t size = sizeof(*st) + sizeof(struct osmo_ecu_fr_state); + + st = talloc_named_const(ctx, size, "ecu_state_FR"); + if (!st) + return NULL; + + memset(st, 0, size); + st->codec = codec; + + return st; +} + +static int ecu_fr_frame_in(struct osmo_ecu_state *st, bool bfi, const uint8_t *frame, + unsigned int frame_bytes) +{ + struct osmo_ecu_fr_state *fr = (struct osmo_ecu_fr_state *) &st->data; + if (bfi) + return 0; + + osmo_ecu_fr_reset(fr, frame); + return 0; +} + +static int ecu_fr_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out) +{ + struct osmo_ecu_fr_state *fr = (struct osmo_ecu_fr_state *) &st->data; + + if (osmo_ecu_fr_conceal(fr, frame_out) == 0) + return GSM_FR_BYTES; + else + return -1; +} + +static const struct osmo_ecu_ops osmo_ecu_ops_fr = { + .init = ecu_fr_init, + .frame_in = ecu_fr_frame_in, + .frame_out = ecu_fr_frame_out, +}; + +static __attribute__((constructor)) void on_dso_load_ecu_fr(void) +{ + osmo_ecu_register(&osmo_ecu_ops_fr, OSMO_ECU_CODEC_FR); +} -- cgit v1.2.3