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
This commit is contained in:
Harald Welte 2019-08-01 20:05:05 +02:00 committed by laforge
parent 766f77c3d9
commit 750d8311f5
6 changed files with 447 additions and 1 deletions

View File

@ -13,3 +13,57 @@ struct osmo_ecu_fr_state {
void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, const uint8_t *frame);
int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame);
enum osmo_ecu_codec {
OSMO_ECU_CODEC_HR,
OSMO_ECU_CODEC_FR,
OSMO_ECU_CODEC_EFR,
OSMO_ECU_CODEC_AMR,
_NUM_OSMO_ECU_CODECS
};
/***********************************************************************
* Generic ECU abstraction layer below
***********************************************************************/
/* 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 <laforge@gnumonks.org> on August 1, 2019.
*/
struct osmo_ecu_state {
enum osmo_ecu_codec codec;
uint8_t data[0];
};
/* initialize an ECU instance */
struct osmo_ecu_state *osmo_ecu_init(void *ctx, enum osmo_ecu_codec codec);
/* destroy an ECU instance */
void osmo_ecu_destroy(struct osmo_ecu_state *st);
/* process a received frame a substitute/erroneous frame */
int osmo_ecu_frame_in(struct osmo_ecu_state *st, bool bfi,
const uint8_t *frame, unsigned int frame_bytes);
/* generate output data for a substitute/erroneous frame */
int osmo_ecu_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out);
struct osmo_ecu_ops {
struct osmo_ecu_state * (*init)(void *ctx, enum osmo_ecu_codec codec);
void (*destroy)(struct osmo_ecu_state *);
int (*frame_in)(struct osmo_ecu_state *st, bool bfi,
const uint8_t *frame, unsigned int frame_bytes);
int (*frame_out)(struct osmo_ecu_state *st, uint8_t *frame_out);
};
int osmo_ecu_register(const struct osmo_ecu_ops *ops, enum osmo_ecu_codec codec);

View File

@ -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

118
src/codec/ecu.c Normal file
View File

@ -0,0 +1,118 @@
/* Core infrastructure for ECU implementations */
/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
*
* 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 <laforge@gnumonks.org> on August 1, 2019.
*/
#include <string.h>
#include <errno.h>
#include <osmocom/codec/ecu.h>
#include <osmocom/core/talloc.h>
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;
}

View File

@ -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);
}

View File

@ -113,6 +113,8 @@ void test_fr_concealment(void)
int i, rc;
int j = 0;
printf("=> Testing FR concealment (simple, consecutive bad frames)\n");
while (sample_frame_hex[j] != NULL) {
/* Parse frame from string to hex */
osmo_hexparse(sample_frame_hex[j], frame, GSM_FR_BYTES);
@ -148,6 +150,8 @@ void test_fr_concealment_realistic()
unsigned int frame_len;
int rc, i = 0;
printf("\n=> Testing FR concealment (realistic, various bad frames)\n");
while (fr_frames_hex[i] != NULL) {
/* Debug print */
printf("Frame No. %03i:\n", i);
@ -174,11 +178,54 @@ void test_fr_concealment_realistic()
}
}
/* Simulate a real life situation: voice frames with a few dropouts, using generic core */
void test_fr_concealment_realistic_core()
{
struct osmo_ecu_state *state = osmo_ecu_init(NULL, OSMO_ECU_CODEC_FR);
uint8_t frame[GSM_FR_BYTES];
unsigned int frame_len;
int rc, i = 0;
printf("\n=> Testing FR concealment (realistic, using ECU abstraction)\n");
OSMO_ASSERT(state);
while (fr_frames_hex[i] != NULL) {
/* Debug print */
printf("Frame No. %03i:\n", i);
/* Good or bad frame? */
frame_len = strlen(fr_frames_hex[i]) / 2;
if (frame_len == GSM_FR_BYTES) {
printf(" * input: %s\n", fr_frames_hex[i]);
osmo_hexparse(fr_frames_hex[i], frame, GSM_FR_BYTES);
osmo_ecu_frame_in(state, false, frame, GSM_FR_BYTES);
} else {
printf(" * input: (bad)\n");
memset(frame, 0x00, GSM_FR_BYTES);
osmo_ecu_frame_in(state, true, frame, 0);
rc = osmo_ecu_frame_out(state, frame);
OSMO_ASSERT(rc == GSM_FR_BYTES);
}
/* Print result */
printf(" * output: %s\n",
osmo_hexdump_nospc(frame, GSM_FR_BYTES));
/* Go to the next frame */
i++;
}
osmo_ecu_destroy(state);
}
int main(int argc, char **argv)
{
/* Perform actual tests */
test_fr_concealment();
test_fr_concealment_realistic();
test_fr_concealment_realistic_core();
return 0;
}

View File

@ -1,3 +1,4 @@
=> Testing FR concealment (simple, consecutive bad frames)
Start with: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da, XMAXC: [3f, 3f, 3f, 3f]
conceal: 00, result: d9ec9be212901f802335598c501f805bad3d4ba01f809b69df5a501f809cd1b4da XMAXC: [3f, 3f, 3f, 3f]
conceal: 01, result: d9ec9be212901d802335598c501d805bad3d4ba01d809b69df5a501d809cd1b4da XMAXC: [3b, 3b, 3b, 3b]
@ -40,6 +41,181 @@ conceal: 16, result: d0000000000000000000000000000000000000000000000000000000000
conceal: 17, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]
conceal: 18, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]
conceal: 19, result: d00000000000000000000000000000000000000000000000000000000000000000 XMAXC: [0, 0, 0, 0]
=> Testing FR concealment (realistic, various bad frames)
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
=> Testing FR concealment (realistic, using ECU abstraction)
Frame No. 000:
* input: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723
* output: d9aa93ae63de00471a91b95b8660471392b4a2daa037628f391c624039258dc723