This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.orgHello Neels Hofmeyr, Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/5214 to look at the new patch set (#2). osmo-bts-trx: add error concealment unit for GSM-FR When a bad GSM-FR voice frame is received, the frame replaced ith a silence frame. This may cause unpleasant audio effects. Add a functionality (see ecu_fr.c, ecu_fr_conceal() and ecu_fr_reset() to craft a replacement frame from the last known good frame. Add unit test (ecu_fr_test.c) Integrate into osmo-bts-trx Change-Id: Iae9e69a9578ae305bca42f834694af96a29084e6 --- M configure.ac M include/osmo-bts/Makefile.am A include/osmo-bts/ecu_fr.h M include/osmo-bts/gsm_data_shared.h M src/common/Makefile.am A src/common/ecu_fr.c M src/osmo-bts-trx/scheduler_trx.c M tests/Makefile.am A tests/ecu_fr/Makefile.am A tests/ecu_fr/ecu_fr_test.c A tests/ecu_fr/ecu_fr_test.ok M tests/testsuite.at 12 files changed, 818 insertions(+), 5 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/14/5214/2 diff --git a/configure.ac b/configure.ac index e3ea9ca..0d1a882 100644 --- a/configure.ac +++ b/configure.ac @@ -180,4 +180,5 @@ tests/tx_power/Makefile tests/power/Makefile tests/meas/Makefile + tests/ecu_fr/Makefile Makefile) diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am index a15ce3d..86bcdf1 100644 --- a/include/osmo-bts/Makefile.am +++ b/include/osmo-bts/Makefile.am @@ -2,4 +2,4 @@ oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \ handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \ power_control.h scheduler.h scheduler_backend.h phy_link.h \ - dtx_dl_amr_fsm.h + dtx_dl_amr_fsm.h ecu_fr.h diff --git a/include/osmo-bts/ecu_fr.h b/include/osmo-bts/ecu_fr.h new file mode 100644 index 0000000..f33f508 --- /dev/null +++ b/include/osmo-bts/ecu_fr.h @@ -0,0 +1,10 @@ +#pragma once + +/* Context information for the full rate ECU states */ +struct ecu_fr_ctx { + bool subsequent_lost_frame; + uint8_t frame_backup[GSM_FR_BYTES]; +}; + +void ecu_fr_reset(struct ecu_fr_ctx *ctx, uint8_t *frame); +void ecu_fr_conceal(struct ecu_fr_ctx *ctx, uint8_t *frame); diff --git a/include/osmo-bts/gsm_data_shared.h b/include/osmo-bts/gsm_data_shared.h index a05e4ca..37d6e0b 100644 --- a/include/osmo-bts/gsm_data_shared.h +++ b/include/osmo-bts/gsm_data_shared.h @@ -19,6 +19,7 @@ #include <osmocom/gsm/protocol/gsm_12_21.h> #include <osmocom/abis/e1_input.h> +#include <osmo-bts/ecu_fr.h> #ifndef ROLE_BSC #include <osmocom/gsm/lapdm.h> @@ -381,6 +382,8 @@ } ms_power_ctrl; struct msgb *pending_rel_ind_msg; + + struct ecu_fr_ctx ecu_fr_ctx; #endif }; diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 67f3e80..d2d6ec6 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -12,6 +12,6 @@ load_indication.c pcu_sock.c handover.c msg_utils.c \ tx_power.c bts_ctrl_commands.c bts_ctrl_lookup.c \ l1sap.c cbch.c power_control.c main.c phy_link.c \ - dtx_dl_amr_fsm.c + dtx_dl_amr_fsm.c ecu_fr.c libl1sched_a_SOURCES = scheduler.c diff --git a/src/common/ecu_fr.c b/src/common/ecu_fr.c new file mode 100644 index 0000000..92228cd --- /dev/null +++ b/src/common/ecu_fr.c @@ -0,0 +1,415 @@ +/* (C) 2017 by sysmocom - s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Philipp Maier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <stdint.h> + +#include <osmo-bts/gsm_data.h> +#include <osmo-bts/logging.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/codec/codec.h> +#include <osmocom/core/bitvec.h> +#include <osmo-bts/ecu_fr.h> + +/* See also GSM 6.11, chapter 6 Example solution */ +#define GSM610_XMAXC_REDUCE 4 +#define GSM610_XMAXC_LEN 6 + +/* See also RFC 3551 Table 3: GSM payload format: */ +enum gsm610_bit_offsets { + GSM610_SIGNATURE_0, + GSM610_SIGNATURE_1, + GSM610_SIGNATURE_2, + GSM610_SIGNATURE_3, + GSM610_LARC0_0, + GSM610_LARC0_1, + GSM610_LARC0_2, + GSM610_LARC0_3, + GSM610_LARC0_4, + GSM610_LARC0_5, + GSM610_LARC1_0, + GSM610_LARC1_1, + GSM610_LARC1_2, + GSM610_LARC1_3, + GSM610_LARC1_4, + GSM610_LARC1_5, + GSM610_LARC2_0, + GSM610_LARC2_1, + GSM610_LARC2_2, + GSM610_LARC2_3, + GSM610_LARC2_4, + GSM610_LARC3_0, + GSM610_LARC3_1, + GSM610_LARC3_2, + GSM610_LARC3_3, + GSM610_LARC3_4, + GSM610_LARC4_0, + GSM610_LARC4_1, + GSM610_LARC4_2, + GSM610_LARC4_3, + GSM610_LARC5_0, + GSM610_LARC5_1, + GSM610_LARC5_2, + GSM610_LARC5_3, + GSM610_LARC6_0, + GSM610_LARC6_1, + GSM610_LARC6_2, + GSM610_LARC7_0, + GSM610_LARC7_1, + GSM610_LARC7_2, + GSM610_NC0_0, + GSM610_NC0_1, + GSM610_NC0_2, + GSM610_NC0_3, + GSM610_NC0_4, + GSM610_NC0_5, + GSM610_NC0_6, + GSM610_BC0_0, + GSM610_BC0_1, + GSM610_MC0_0, + GSM610_MC0_1, + GSM610_XMAXC00, + GSM610_XMAXC01, + GSM610_XMAXC02, + GSM610_XMAXC03, + GSM610_XMAXC04, + GSM610_XMAXC05, + GSM610_XMC0_0, + GSM610_XMC0_1, + GSM610_XMC0_2, + GSM610_XMC1_0, + GSM610_XMC1_1, + GSM610_XMC1_2, + GSM610_XMC2_0, + GSM610_XMC2_1, + GSM610_XMC2_2, + GSM610_XMC3_0, + GSM610_XMC3_1, + GSM610_XMC3_2, + GSM610_XMC4_0, + GSM610_XMC4_1, + GSM610_XMC4_2, + GSM610_XMC5_0, + GSM610_XMC5_1, + GSM610_XMC5_2, + GSM610_XMC6_0, + GSM610_XMC6_1, + GSM610_XMC6_2, + GSM610_XMC7_0, + GSM610_XMC7_1, + GSM610_XMC7_2, + GSM610_XMC8_0, + GSM610_XMC8_1, + GSM610_XMC8_2, + GSM610_XMC9_0, + GSM610_XMC9_1, + GSM610_XMC9_2, + GSM610_XMC10_0, + GSM610_XMC10_1, + GSM610_XMC10_2, + GSM610_XMC11_0, + GSM610_XMC11_1, + GSM610_XMC11_2, + GSM610_XMC12_0, + GSM610_XMC12_1, + GSM610_XCM12_2, + GSM610_NC1_0, + GSM610_NC1_1, + GSM610_NC1_2, + GSM610_NC1_3, + GSM610_NC1_4, + GSM610_NC1_5, + GSM610_NC1_6, + GSM610_BC1_0, + GSM610_BC1_1, + GSM610_MC1_0, + GSM610_MC1_1, + GSM610_XMAXC10, + GSM610_XMAXC11, + GSM610_XMAXC12, + GSM610_XMAXC13, + GSM610_XMAXC14, + GSM610_XMAX15, + GSM610_XMC13_0, + GSM610_XMC13_1, + GSM610_XMC13_2, + GSM610_XMC14_0, + GSM610_XMC14_1, + GSM610_XMC14_2, + GSM610_XMC15_0, + GSM610_XMC15_1, + GSM610_XMC15_2, + GSM610_XMC16_0, + GSM610_XMC16_1, + GSM610_XMC16_2, + GSM610_XMC17_0, + GSM610_XMC17_1, + GSM610_XMC17_2, + GSM610_XMC18_0, + GSM610_XMC18_1, + GSM610_XMC18_2, + GSM610_XMC19_0, + GSM610_XMC19_1, + GSM610_XMC19_2, + GSM610_XMC20_0, + GSM610_XMC20_1, + GSM610_XMC20_2, + GSM610_XMC21_0, + GSM610_XMC21_1, + GSM610_XMC21_2, + GSM610_XMC22_0, + GSM610_XMC22_1, + GSM610_XMC22_2, + GSM610_XMC23_0, + GSM610_XMC23_1, + GSM610_XMC23_2, + GSM610_XMC24_0, + GSM610_XMC24_1, + GSM610_XMC24_2, + GSM610_XMC25_0, + GSM610_XMC25_1, + GSM610_XMC25_2, + GSM610_NC2_0, + GSM610_NC2_1, + GSM610_NC2_2, + GSM610_NC2_3, + GSM610_NC2_4, + GSM610_NC2_5, + GSM610_NC2_6, + GSM610_BC2_0, + GSM610_BC2_1, + GSM610_MC2_0, + GSM610_MC2_1, + GSM610_XMAXC20, + GSM610_XMAXC21, + GSM610_XMAXC22, + GSM610_XMAXC23, + GSM610_XMAXC24, + GSM610_XMAXC25, + GSM610_XMC26_0, + GSM610_XMC26_1, + GSM610_XMC26_2, + GSM610_XMC27_0, + GSM610_XMC27_1, + GSM610_XMC27_2, + GSM610_XMC28_0, + GSM610_XMC28_1, + GSM610_XMC28_2, + GSM610_XMC29_0, + GSM610_XMC29_1, + GSM610_XMC29_2, + GSM610_XMC30_0, + GSM610_XMC30_1, + GSM610_XMC30_2, + GSM610_XMC31_0, + GSM610_XMC31_1, + GSM610_XMC31_2, + GSM610_XMC32_0, + GSM610_XMC32_1, + GSM610_XMC32_2, + GSM610_XMC33_0, + GSM610_XMC33_1, + GSM610_XMC33_2, + GSM610_XMC34_0, + GSM610_XMC34_1, + GSM610_XMC34_2, + GSM610_XMC35_0, + GSM610_XMC35_1, + GSM610_XMC35_2, + GSM610_XMC36_0, + GSM610_XMC36_1, + GSM610_XMC36_2, + GSM610_XMC37_0, + GSM610_XMC37_1, + GSM610_XMC37_2, + GSM610_XMC38_0, + GSM610_XMC38_1, + GSM610_XMC38_2, + GSM610_NC3_0, + GSM610_NC3_1, + GSM610_NC3_2, + GSM610_NC3_3, + GSM610_NC3_4, + GSM610_NC3_5, + GSM610_NC3_6, + GSM610_BC3_0, + GSM610_BC3_1, + GSM610_MC3_0, + GSM610_MC3_1, + GSM610_XMAXC30, + GSM610_XMAXC31, + GSM610_XMAXC32, + GSM610_XMAXC33, + GSM610_XMAXC34, + GSM610_XMAXC35, + GSM610_XMC39_0, + GSM610_XMC39_1, + GSM610_XMC39_2, + GSM610_XMC40_0, + GSM610_XMC40_1, + GSM610_XMC40_2, + GSM610_XMC41_0, + GSM610_XMC41_1, + GSM610_XMC41_2, + GSM610_XMC42_0, + GSM610_XMC42_1, + GSM610_XMC42_2, + GSM610_XMC43_0, + GSM610_XMC43_1, + GSM610_XMC43_2, + GSM610_XMC44_0, + GSM610_XMC44_1, + GSM610_XMC44_2, + GSM610_XMC45_0, + GSM610_XMC45_1, + GSM610_XMC45_2, + GSM610_XMC46_0, + GSM610_XMC46_1, + GSM610_XMC46_2, + GSM610_XMC47_0, + GSM610_XMC47_1, + GSM610_XMC47_2, + GSM610_XMC48_0, + GSM610_XMC48_1, + GSM610_XMC48_2, + GSM610_XMC49_0, + GSM610_XMC49_1, + GSM610_XMC49_2, + GSM610_XMC50_0, + GSM610_XMC50_1, + GSM610_XMC50_2, + GSM610_XMC51_0, + GSM610_XMC51_1, + GSM610_XMC51_2 +}; + +/* Reduce the XMAXC field. When the XMAXC field reaches + * zero, then the function will return true */ +static bool reduce_xmaxcr(struct bitvec *frame_bitvec, unsigned int index) +{ + unsigned int field_index; + uint64_t field; + bool silent = true; + + 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; + if (field != 0) + silent = false; + field_index = index; + bitvec_write_field(frame_bitvec, &field_index, field, GSM610_XMAXC_LEN); + + return silent; +} + +/* 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 = false; + + if (reduce_xmaxcr(frame_bitvec, GSM610_XMAXC00)) + silent = true; + if (reduce_xmaxcr(frame_bitvec, GSM610_XMAXC10)) + silent = true; + if (reduce_xmaxcr(frame_bitvec, GSM610_XMAXC20)) + silent = true; + if (reduce_xmaxcr(frame_bitvec, GSM610_XMAXC30)) + silent = true; + return silent; +} + +/* Use certain modifications to conceal the errors in a full rate frame */ +static void conceal_frame(uint8_t *frame) +{ + struct bitvec *frame_bitvec; + bool silent; + int rc; + + /* 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)) { + goto leave_nofree; + } + + /* Convert to bitvec */ + frame_bitvec = bitvec_alloc(GSM_FR_BYTES, NULL); + if (!frame_bitvec) { + LOGP(DL1P, LOGL_ERROR, "Unpacking GSM-FR frame failed, no memory to store the resulting bitvec!\n"); + goto leave_nofree; + } + rc = bitvec_unpack(frame_bitvec, frame); + if (rc != GSM_FR_BYTES) { + LOGP(DL1P, LOGL_ERROR, "Unpacking GSM-FR frame failed, wrong number of bits unpacked!\n"); + 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, 0, GSM_FR_BYTES); + frame[0] = 0xd0; + goto leave; + } + + /* Convert back to packed byte form */ + rc = bitvec_pack(frame_bitvec, frame); + if (rc != GSM_FR_BYTES) { + LOGP(DL1P, LOGL_ERROR, "Packing GSM-FR frame failed, wrong number of bits packed!\n"); + goto leave; + } + +leave: + bitvec_free(frame_bitvec); +leave_nofree: + return; +} + +/* To be called whan a good frame is received. This function will then create + * a backup of the frame and reset its internal state */ +void ecu_fr_reset(struct ecu_fr_ctx *ctx, uint8_t *frame) +{ + ctx->subsequent_lost_frame = false; + memcpy(ctx->frame_backup, frame, sizeof(ctx->frame_backup)); +} + +/* 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 */ +void ecu_fr_conceal(struct ecu_fr_ctx *ctx, uint8_t *frame) +{ + /* For subsequent frames we run the error concealment + * functions on the backed up frame before we restore + * the backup. */ + if (ctx->subsequent_lost_frame) { + conceal_frame(ctx->frame_backup); + } + + /* Restore the backed up frame and set flag in case + * we receive even more bad frames */ + memcpy(frame, ctx->frame_backup, sizeof(ctx->frame_backup)); + ctx->subsequent_lost_frame = true; +} diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index d3928f1..dfcd031 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -968,6 +968,7 @@ uint8_t tch_data[128]; /* just to be safe */ int rc, amr = 0; int n_errors, n_bits_total; + bool bfi_flag = false; struct gsm_lchan *lchan = get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | tn); @@ -1058,11 +1059,13 @@ if (rc < 0) { LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u)\n", fn % l1ts->mf_period, l1ts->mf_period); + bfi_flag = true; goto bfi; } if (rc < 4) { LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u) " "with invalid codec mode %d\n", fn % l1ts->mf_period, l1ts->mf_period, rc); + bfi_flag = true; goto bfi; } @@ -1079,8 +1082,7 @@ case GSM48_CMODE_SPEECH_V1: /* FR */ if (lchan->tch.dtx.ul_sid) return 0; /* DTXu: pause in progress */ - memset(tch_data, 0, GSM_FR_BYTES); - tch_data[0] = 0xd0; + ecu_fr_conceal(&lchan->ecu_fr_ctx, tch_data); rc = GSM_FR_BYTES; break; case GSM48_CMODE_SPEECH_EFR: /* EFR */ @@ -1108,6 +1110,9 @@ if (rsl_cmode != RSL_CMOD_SPD_SPEECH) return 0; + if (!bfi_flag && tch_mode == GSM48_CMODE_SPEECH_V1) + ecu_fr_reset(&lchan->ecu_fr_ctx, tch_data); + /* TCH or BFI */ return _sched_compose_tch_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan, tch_data, rc); diff --git a/tests/Makefile.am b/tests/Makefile.am index 1eb28d6..e77a355 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = paging cipher agch misc handover tx_power power meas +SUBDIRS = paging cipher agch misc handover tx_power power meas ecu_fr if ENABLE_SYSMOBTS SUBDIRS += sysmobts diff --git a/tests/ecu_fr/Makefile.am b/tests/ecu_fr/Makefile.am new file mode 100644 index 0000000..6dc7549 --- /dev/null +++ b/tests/ecu_fr/Makefile.am @@ -0,0 +1,8 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOCODEC_CFLAGS)$(LIBOSMOTRAU_CFLAGS) +LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOTRAU_LIBS) $(LIBOSMOABIS_LIBS) +noinst_PROGRAMS = ecu_fr_test +EXTRA_DIST = ecu_fr_test.ok + +ecu_fr_test_SOURCES = ecu_fr_test.c +ecu_fr_test_LDADD = $(top_builddir)/src/common/libbts.a $(LDADD) diff --git a/tests/ecu_fr/ecu_fr_test.c b/tests/ecu_fr/ecu_fr_test.c new file mode 100644 index 0000000..bc1cc56 --- /dev/null +++ b/tests/ecu_fr/ecu_fr_test.c @@ -0,0 +1,171 @@ +#include <stdint.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <getopt.h> +#include <limits.h> +#include <sched.h> +#include <sys/signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <net/if.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/application.h> +#include <osmocom/vty/telnet_interface.h> +#include <osmocom/vty/logging.h> + +#include <osmo-bts/gsm_data.h> +#include <osmo-bts/logging.h> +#include <osmo-bts/ecu_fr.h> + +/* Set with sample fullrate voice frames and some intentional dropouts. */ +char *fr_voice[] = { + "d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723", + "d8eb83699a66c036ec89b7246e6034dc8d48948620589b7256e3a6603b2371b8da", + "d967abaa1cbe4035238da6ace4c036d46ec69ba600391c4eb8a2b040591c6a3924", + "d8e8a42662c240472469b91bd2e0452291b6dba600495b8e38dcb020491a71c91b", + "da2aac1ddbb00036e46e26dcec6039138db923822047137248e3560048e38dc8e3", + "d929ab2a9b5240395b6dc72ba020469c8d551c5440349c9148e36a4036a372471b", + "d9eb93215bb8a0271c69c724682036db71c71a94a0372491b72bee4044eb71b923", + "d9ab9aa19abc40391b6e5ae2ee40471b91c6dbe820492291b8e4b84036e47238db", + "d96b9be9db782044e371b55cb200389491c69b8ea034e271c8d3808038ec6db8e3", + "d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd", + "BAD", + "d9ea9c219ce60046e38d3724e0c034e56e36eb7e0038d471b8dcb260491b8dbb23", + "d9e89be9d9e0a0391b6dd6a4624029247138e3a2a04713922524de0036db69d91c", + "d9699422a2b6a048dd90c91c6a802b6259395c8880575b4a58e4ac20269d7248d4", + "d967ac5b1baae0371c71b8ab9c804a9e8e58a55a8038626ec8dcb640395c7244dc", + "d9e8a3e262e68027638db52b88a038634e471a7ec049136e3b1bc8402923adcad2", + "d8eab36e1bbe0046e34d491b608035137658d3524044e48e375cdac0472b9238d4", + "d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b", + "BAD", + "BAD", + "d8e6a2e1d3d2605b1376c8d35280392451391cbc80392a71b6db8aa049238dc8ab", + "d9a87ba1a3982048eb8a471cac00472b4e391bbc40292489b71cc200495b8d3ae3", + "d9278b2a1ba4c0475b8dc722d6e0491b5228da70204ae36dc71d94a056a29236e3", + "d9ec9be2129520392335598c50c04b5bad3d4ba680789b69df5a5aa0469cd1b4da", + "d8ea932623e660669b8e4a9dd8a03aa32a76e466e028d396cc9bbe4047256dc8e5", + "d96a94215aa0403aab713f22e8e024e68db91ab6a027abd1a55b6e804aec9146e4", + "d867ac21e270a0350d6ac91a724037247246d2a6c0396c89d6dc562049244e48d5", + "d8a9b460d3b48026a4ad471b7c20452491b69bbc803ae48db722ee00292491a8db", + "d928a3e1d3b24036e37244abf02047634d371b74c047637148a29ac03b234e38e3", + "d9ab9b21d2e0c0471c693aec54e044dbae46dc7c20391badb724ee8038e469bb15", + "d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963", + "BAD", + "BAD", + "BAD", + "BAD", + "BAD", + "BAD", + "d92c8b6d5aee4034ebb22724862047145634a5c0a038e371b8e4a880485c89dd25", + "d8e78b29e3c6c038dba9d91beca04723ad491cda80471471b6ec7ae03b1396b91b", + "d8a78b25e37a0022dd8a46dc68a0351bad391bde2046e56dd8dc96c038e396d89b", + "d8a88c255ab6e038e38e48dbde8038ad8dc8db8ec0376372b564b44038e49234dc", + "d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3", + "d8ee9bea5ae4003ae371b713eae05adc91995a5ea064dcc9571e786026ed51c52c", + "d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763", + "d92aab696190c046e26e392cae0026a376a8dc662048d291b75b54c04ad3ae3b1b", + "d8e7a469627a6038e289cb1baca0569b8db6dddec026dc8e38e5dc803722722d23", + "d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713", + "BAD", + "d7299c19a3be8024e58ea7a49f20a522963ad976e0a76ecd92b38500cb62aa4c94", + "d7eb6c6262eee02b2c42e79a60a0aa55aed68a7f00ad358e10fad960e55a39396d", + "d970858dd2ab61d91355ebc15ca1a6a7ca48a05cc0dae66f2523c2a1bad3825daa", + "d8f0844a23ad20da50d6de025e81c37392b9039cc0c764c1bd1e94c1b699736a98", + "d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3", + "d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763", + "d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763", + "d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763", + "d2577a1cda50004924924924500049249249245000492492492450004923924924", + NULL +}; + +/* Start with a good voice frame and then simulate 20 consecutive bad frames, + * watch how the error concealment decreases the XMAXC parameters */ +void test_fr_concealment(void *ctx) +{ + char frame_hex[] = + "d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da"; + uint8_t *frame; + unsigned int len; + int i; + struct ecu_fr_ctx ecu_fr_ctx; + + len = strlen(frame_hex); + frame = talloc_zero_size(ctx, GSM_FR_BYTES); + len = osmo_hexparse(frame_hex, frame, GSM_FR_BYTES); + OSMO_ASSERT(len == GSM_FR_BYTES); + + printf(" Start with: %s\n", + osmo_hexdump_nospc(frame, GSM_FR_BYTES)); + + /* Reset the ECU with the proposed known good frame */ + ecu_fr_reset(&ecu_fr_ctx, frame); + + /* Now pretend that we do not receive any good frames anymore */ + for (i = 0; i < 20; i++) { + ecu_fr_conceal(&ecu_fr_ctx, frame); + printf("conceal: %02i, result: %s\n", i, + osmo_hexdump_nospc(frame, GSM_FR_BYTES)); + } + + talloc_free(frame); +} + +/* Simulate a real life situation, voce frames with a few dropouts */ +void test_fr_concealment_realistic() +{ + uint8_t frame[GSM_FR_BYTES]; + unsigned int len; + unsigned int id = 0; + struct ecu_fr_ctx ecu_fr_ctx; + + while (1) { + /* Detect end of test samples */ + if (fr_voice[id] == NULL) + return; + + printf("Frame No. %03i:\n", id); + len = strlen(fr_voice[id]) / 2; + + if (len != GSM_FR_BYTES) { + memset(frame, 0, GSM_FR_BYTES); + ecu_fr_conceal(&ecu_fr_ctx, frame); + printf(" * input: (bad)\n"); + } else { + osmo_hexparse(fr_voice[id], frame, GSM_FR_BYTES); + printf(" * input: %s\n", + osmo_hexdump_nospc(frame, GSM_FR_BYTES)); + ecu_fr_reset(&ecu_fr_ctx, frame); + } + printf(" * output: %s\n", + osmo_hexdump_nospc(frame, GSM_FR_BYTES)); + id++; + } +} + +int main(int argc, char **argv) +{ + void *tall_bts_ctx; + + tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); + msgb_talloc_ctx_init(tall_bts_ctx, 0); + + bts_log_init(NULL); + osmo_stderr_target->categories[DL1C].loglevel = LOGL_DEBUG; + + test_fr_concealment(tall_bts_ctx); + test_fr_concealment_realistic(); + + printf("Success\n"); + talloc_report_full(tall_bts_ctx, stderr); + printf("Talloc total blocks: %lu\n", talloc_total_blocks(tall_bts_ctx)); + OSMO_ASSERT(talloc_total_blocks(tall_bts_ctx) == 2); + + return 0; +} diff --git a/tests/ecu_fr/ecu_fr_test.ok b/tests/ecu_fr/ecu_fr_test.ok new file mode 100644 index 0000000..fab883e --- /dev/null +++ b/tests/ecu_fr/ecu_fr_test.ok @@ -0,0 +1,194 @@ + Start with: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da +conceal: 00, result: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da +conceal: 01, result: d9ec9be212901d802335598c501d805bad3d4ba01d809b69df5a501d809cd1b4da +conceal: 02, result: d9ec9be212901b802335598c501b805bad3d4ba01b809b69df5a501b809cd1b4da +conceal: 03, result: d9ec9be2129019802335598c5019805bad3d4ba019809b69df5a5019809cd1b4da +conceal: 04, result: d9ec9be2129017802335598c5017805bad3d4ba017809b69df5a5017809cd1b4da +conceal: 05, result: d9ec9be2129015802335598c5015805bad3d4ba015809b69df5a5015809cd1b4da +conceal: 06, result: d9ec9be2129013802335598c5013805bad3d4ba013809b69df5a5013809cd1b4da +conceal: 07, result: d9ec9be2129011802335598c5011805bad3d4ba011809b69df5a5011809cd1b4da +conceal: 08, result: d9ec9be212900f802335598c500f805bad3d4ba00f809b69df5a500f809cd1b4da +conceal: 09, result: d9ec9be212900d802335598c500d805bad3d4ba00d809b69df5a500d809cd1b4da +conceal: 10, result: d9ec9be212900b802335598c500b805bad3d4ba00b809b69df5a500b809cd1b4da +conceal: 11, result: d9ec9be2129009802335598c5009805bad3d4ba009809b69df5a5009809cd1b4da +conceal: 12, result: d9ec9be2129007802335598c5007805bad3d4ba007809b69df5a5007809cd1b4da +conceal: 13, result: d9ec9be2129005802335598c5005805bad3d4ba005809b69df5a5005809cd1b4da +conceal: 14, result: d9ec9be2129003802335598c5003805bad3d4ba003809b69df5a5003809cd1b4da +conceal: 15, result: d9ec9be2129001802335598c5001805bad3d4ba001809b69df5a5001809cd1b4da +conceal: 16, result: d00000000000000000000000000000000000000000000000000000000000000000 +conceal: 17, result: d00000000000000000000000000000000000000000000000000000000000000000 +conceal: 18, result: d00000000000000000000000000000000000000000000000000000000000000000 +conceal: 19, result: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 000: + * input: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723 + * output: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723 +Frame No. 001: + * input: d8eb83699a66c036ec89b7246e6034dc8d48948620589b7256e3a6603b2371b8da + * output: d8eb83699a66c036ec89b7246e6034dc8d48948620589b7256e3a6603b2371b8da +Frame No. 002: + * input: d967abaa1cbe4035238da6ace4c036d46ec69ba600391c4eb8a2b040591c6a3924 + * output: d967abaa1cbe4035238da6ace4c036d46ec69ba600391c4eb8a2b040591c6a3924 +Frame No. 003: + * input: d8e8a42662c240472469b91bd2e0452291b6dba600495b8e38dcb020491a71c91b + * output: d8e8a42662c240472469b91bd2e0452291b6dba600495b8e38dcb020491a71c91b +Frame No. 004: + * input: da2aac1ddbb00036e46e26dcec6039138db923822047137248e3560048e38dc8e3 + * output: da2aac1ddbb00036e46e26dcec6039138db923822047137248e3560048e38dc8e3 +Frame No. 005: + * input: d929ab2a9b5240395b6dc72ba020469c8d551c5440349c9148e36a4036a372471b + * output: d929ab2a9b5240395b6dc72ba020469c8d551c5440349c9148e36a4036a372471b +Frame No. 006: + * input: d9eb93215bb8a0271c69c724682036db71c71a94a0372491b72bee4044eb71b923 + * output: d9eb93215bb8a0271c69c724682036db71c71a94a0372491b72bee4044eb71b923 +Frame No. 007: + * input: d9ab9aa19abc40391b6e5ae2ee40471b91c6dbe820492291b8e4b84036e47238db + * output: d9ab9aa19abc40391b6e5ae2ee40471b91c6dbe820492291b8e4b84036e47238db +Frame No. 008: + * input: d96b9be9db782044e371b55cb200389491c69b8ea034e271c8d3808038ec6db8e3 + * output: d96b9be9db782044e371b55cb200389491c69b8ea034e271c8d3808038ec6db8e3 +Frame No. 009: + * input: d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd + * output: d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd +Frame No. 010: + * input: (bad) + * output: d9aa9365e3f060375c6db6ebc4c02764b1c51b78a0571c91a723de6049248dc8dd +Frame No. 011: + * input: d9ea9c219ce60046e38d3724e0c034e56e36eb7e0038d471b8dcb260491b8dbb23 + * output: d9ea9c219ce60046e38d3724e0c034e56e36eb7e0038d471b8dcb260491b8dbb23 +Frame No. 012: + * input: d9e89be9d9e0a0391b6dd6a4624029247138e3a2a04713922524de0036db69d91c + * output: d9e89be9d9e0a0391b6dd6a4624029247138e3a2a04713922524de0036db69d91c +Frame No. 013: + * input: d9699422a2b6a048dd90c91c6a802b6259395c8880575b4a58e4ac20269d7248d4 + * output: d9699422a2b6a048dd90c91c6a802b6259395c8880575b4a58e4ac20269d7248d4 +Frame No. 014: + * input: d967ac5b1baae0371c71b8ab9c804a9e8e58a55a8038626ec8dcb640395c7244dc + * output: d967ac5b1baae0371c71b8ab9c804a9e8e58a55a8038626ec8dcb640395c7244dc +Frame No. 015: + * input: d9e8a3e262e68027638db52b88a038634e471a7ec049136e3b1bc8402923adcad2 + * output: d9e8a3e262e68027638db52b88a038634e471a7ec049136e3b1bc8402923adcad2 +Frame No. 016: + * input: d8eab36e1bbe0046e34d491b608035137658d3524044e48e375cdac0472b9238d4 + * output: d8eab36e1bbe0046e34d491b608035137658d3524044e48e375cdac0472b9238d4 +Frame No. 017: + * input: d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b + * output: d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b +Frame No. 018: + * input: (bad) + * output: d9689ba5e3d260491b516adb5e4027256e27227ee0351c8e549a5c60492471971b +Frame No. 019: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 020: + * input: d8e6a2e1d3d2605b1376c8d35280392451391cbc80392a71b6db8aa049238dc8ab + * output: d8e6a2e1d3d2605b1376c8d35280392451391cbc80392a71b6db8aa049238dc8ab +Frame No. 021: + * input: d9a87ba1a3982048eb8a471cac00472b4e391bbc40292489b71cc200495b8d3ae3 + * output: d9a87ba1a3982048eb8a471cac00472b4e391bbc40292489b71cc200495b8d3ae3 +Frame No. 022: + * input: d9278b2a1ba4c0475b8dc722d6e0491b5228da70204ae36dc71d94a056a29236e3 + * output: d9278b2a1ba4c0475b8dc722d6e0491b5228da70204ae36dc71d94a056a29236e3 +Frame No. 023: + * input: d9ec9be2129520392335598c50c04b5bad3d4ba680789b69df5a5aa0469cd1b4da + * output: d9ec9be2129520392335598c50c04b5bad3d4ba680789b69df5a5aa0469cd1b4da +Frame No. 024: + * input: d8ea932623e660669b8e4a9dd8a03aa32a76e466e028d396cc9bbe4047256dc8e5 + * output: d8ea932623e660669b8e4a9dd8a03aa32a76e466e028d396cc9bbe4047256dc8e5 +Frame No. 025: + * input: d96a94215aa0403aab713f22e8e024e68db91ab6a027abd1a55b6e804aec9146e4 + * output: d96a94215aa0403aab713f22e8e024e68db91ab6a027abd1a55b6e804aec9146e4 +Frame No. 026: + * input: d867ac21e270a0350d6ac91a724037247246d2a6c0396c89d6dc562049244e48d5 + * output: d867ac21e270a0350d6ac91a724037247246d2a6c0396c89d6dc562049244e48d5 +Frame No. 027: + * input: d8a9b460d3b48026a4ad471b7c20452491b69bbc803ae48db722ee00292491a8db + * output: d8a9b460d3b48026a4ad471b7c20452491b69bbc803ae48db722ee00292491a8db +Frame No. 028: + * input: d928a3e1d3b24036e37244abf02047634d371b74c047637148a29ac03b234e38e3 + * output: d928a3e1d3b24036e37244abf02047634d371b74c047637148a29ac03b234e38e3 +Frame No. 029: + * input: d9ab9b21d2e0c0471c693aec54e044dbae46dc7c20391badb724ee8038e469bb15 + * output: d9ab9b21d2e0c0471c693aec54e044dbae46dc7c20391badb724ee8038e469bb15 +Frame No. 030: + * input: d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963 + * output: d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963 +Frame No. 031: + * input: (bad) + * output: d9a99361a276403b1a6ad6dcd40026e489c8e3bc40371c4dc564e2c036e28eb963 +Frame No. 032: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 033: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 034: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 035: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 036: + * input: (bad) + * output: d00000000000000000000000000000000000000000000000000000000000000000 +Frame No. 037: + * input: d92c8b6d5aee4034ebb22724862047145634a5c0a038e371b8e4a880485c89dd25 + * output: d92c8b6d5aee4034ebb22724862047145634a5c0a038e371b8e4a880485c89dd25 +Frame No. 038: + * input: d8e78b29e3c6c038dba9d91beca04723ad491cda80471471b6ec7ae03b1396b91b + * output: d8e78b29e3c6c038dba9d91beca04723ad491cda80471471b6ec7ae03b1396b91b +Frame No. 039: + * input: d8a78b25e37a0022dd8a46dc68a0351bad391bde2046e56dd8dc96c038e396d89b + * output: d8a78b25e37a0022dd8a46dc68a0351bad391bde2046e56dd8dc96c038e396d89b +Frame No. 040: + * input: d8a88c255ab6e038e38e48dbde8038ad8dc8db8ec0376372b564b44038e49234dc + * output: d8a88c255ab6e038e38e48dbde8038ad8dc8db8ec0376372b564b44038e49234dc +Frame No. 041: + * input: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3 + * output: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3 +Frame No. 042: + * input: d8ee9bea5ae4003ae371b713eae05adc91995a5ea064dcc9571e786026ed51c52c + * output: d8ee9bea5ae4003ae371b713eae05adc91995a5ea064dcc9571e786026ed51c52c +Frame No. 043: + * input: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 + * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 +Frame No. 044: + * input: d92aab696190c046e26e392cae0026a376a8dc662048d291b75b54c04ad3ae3b1b + * output: d92aab696190c046e26e392cae0026a376a8dc662048d291b75b54c04ad3ae3b1b +Frame No. 045: + * input: d8e7a469627a6038e289cb1baca0569b8db6dddec026dc8e38e5dc803722722d23 + * output: d8e7a469627a6038e289cb1baca0569b8db6dddec026dc8e38e5dc803722722d23 +Frame No. 046: + * input: d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713 + * output: d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713 +Frame No. 047: + * input: (bad) + * output: d8a88c299b64c03a548a58e37420272c6dd76b92c0471c9236dbc0e0551c71c713 +Frame No. 048: + * input: d7299c19a3be8024e58ea7a49f20a522963ad976e0a76ecd92b38500cb62aa4c94 + * output: d7299c19a3be8024e58ea7a49f20a522963ad976e0a76ecd92b38500cb62aa4c94 +Frame No. 049: + * input: d7eb6c6262eee02b2c42e79a60a0aa55aed68a7f00ad358e10fad960e55a39396d + * output: d7eb6c6262eee02b2c42e79a60a0aa55aed68a7f00ad358e10fad960e55a39396d +Frame No. 050: + * input: d970858dd2ab61d91355ebc15ca1a6a7ca48a05cc0dae66f2523c2a1bad3825daa + * output: d970858dd2ab61d91355ebc15ca1a6a7ca48a05cc0dae66f2523c2a1bad3825daa +Frame No. 051: + * input: d8f0844a23ad20da50d6de025e81c37392b9039cc0c764c1bd1e94c1b699736a98 + * output: d8f0844a23ad20da50d6de025e81c37392b9039cc0c764c1bd1e94c1b699736a98 +Frame No. 052: + * input: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3 + * output: d9708ce6a39ce049646646a2c1a0272496b29a66c037db562863ace0795b55b2e3 +Frame No. 053: + * input: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 + * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 +Frame No. 054: + * input: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 + * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 +Frame No. 055: + * input: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 + * output: d9299421d2944036ed69b8e572a048e36d551cd480571d4ec95be680356c69c763 +Frame No. 056: + * input: d2577a1cda50004924924924500049249249245000492492492450004923924924 + * output: d2577a1cda50004924924924500049249249245000492492492450004923924924 +Success +Talloc total blocks: 2 diff --git a/tests/testsuite.at b/tests/testsuite.at index 2d1cefd..c6196a5 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -49,3 +49,9 @@ cat $abs_srcdir/meas/meas_test.ok > expout AT_CHECK([$abs_top_builddir/tests/meas/meas_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([ecu_fr]) +AT_KEYWORDS([ecu_fr]) +cat $abs_srcdir/ecu_fr/ecu_fr_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/ecu_fr/ecu_fr_test], [], [expout], [ignore]) +AT_CLEANUP -- To view, visit https://gerrit.osmocom.org/5214 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: Iae9e69a9578ae305bca42f834694af96a29084e6 Gerrit-PatchSet: 2 Gerrit-Project: osmo-bts Gerrit-Branch: master Gerrit-Owner: dexter <pmaier at sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>