aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2015-12-30 11:47:44 +0100
committerSylvain Munaut <tnt@246tNt.com>2015-12-30 11:55:03 +0100
commitc0f0342596ea6e6faecb0d3cf4be692fa999eb4e (patch)
treefb16770a58e2f9cdd20a2a68c5a9271f9ae9dc05
parent5e2e0442e0fd0f4d6cfaed7049d4dad2139d7d4c (diff)
libgsmhr: Make it safe to decode/encode different streams at once
Basically the reference code has a bunch of global state. With some minimal patchihg (previous commit) we can ensure that all that state is within .bss So what we do it to save/restore the bss section between calls of the reference code so we can process several in // and we don't have to completely fix all reference to global state in the reference codec. Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--libgsmhr/Makefile.am1
-rw-r--r--libgsmhr/libgsmhr.c33
2 files changed, 34 insertions, 0 deletions
diff --git a/libgsmhr/Makefile.am b/libgsmhr/Makefile.am
index 15166b4..e6d246d 100644
--- a/libgsmhr/Makefile.am
+++ b/libgsmhr/Makefile.am
@@ -19,6 +19,7 @@ $(REFSRC_SRC) libgsmhr.c: ${REFSRC_PATH}/.downloaded
lib_LTLIBRARIES = libgsmhr.la
libgsmhr_la_SOURCES = $(REFSRC_SRC) libgsmhr.c
+libgsmhr_la_LIBADD = -ldl
clean-local:
-rm -rf ${REFSRC_PATH}/*.{c,h} ${REFSRC_PATH}/.downloaded
diff --git a/libgsmhr/libgsmhr.c b/libgsmhr/libgsmhr.c
index d018c90..eca0ce0 100644
--- a/libgsmhr/libgsmhr.c
+++ b/libgsmhr/libgsmhr.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <dlfcn.h>
#include <gsmhr/gsmhr.h>
@@ -35,12 +36,21 @@
struct gsmhr {
int dec_reset_flg;
+
+ void *bss_base;
+ void *bss_save;
+ unsigned bss_len;
};
EXPORT struct gsmhr *
gsmhr_init(void)
{
struct gsmhr *state;
+ void *lib;
+
+ lib = dlopen("libgsmhr.so.0", RTLD_NOW | RTLD_NOLOAD);
+ if (!lib)
+ return NULL;
state = calloc(1, sizeof(struct gsmhr));
if (!state)
@@ -48,6 +58,21 @@ gsmhr_init(void)
state->dec_reset_flg = 1;
+ state->bss_base = dlsym(lib, "__bss_start");
+ state->bss_len = dlsym(lib, "_end") - state->bss_base;
+ state->bss_save = malloc(state->bss_len);
+
+ if (!state->bss_save)
+ {
+ free(state);
+ return NULL;
+ }
+
+ resetDec();
+ resetEnc();
+
+ memcpy(state->bss_save, state->bss_base, state->bss_len);
+
return state;
}
@@ -63,6 +88,8 @@ gsmhr_encode(struct gsmhr *state, int16_t *hr_params, const int16_t *pcm)
int enc_reset_flg;
Shortword pcm_b[F_LEN];
+ memcpy(state->bss_base, state->bss_save, state->bss_len);
+
memcpy(pcm_b, pcm, F_LEN*sizeof(int16_t));
enc_reset_flg = encoderHomingFrameTest(pcm_b);
@@ -72,6 +99,8 @@ gsmhr_encode(struct gsmhr *state, int16_t *hr_params, const int16_t *pcm)
if (enc_reset_flg)
resetEnc();
+ memcpy(state->bss_save, state->bss_base, state->bss_len);
+
return 0;
}
@@ -84,6 +113,8 @@ gsmhr_decode(struct gsmhr *state, int16_t *pcm, const int16_t *hr_params)
int dec_reset_flg;
Shortword hr_params_b[22];
+ memcpy(state->bss_base, state->bss_save, state->bss_len);
+
memcpy(hr_params_b, hr_params, 22*sizeof(int16_t));
if (state->dec_reset_flg)
@@ -107,5 +138,7 @@ gsmhr_decode(struct gsmhr *state, int16_t *pcm, const int16_t *hr_params)
state->dec_reset_flg = dec_reset_flg;
+ memcpy(state->bss_save, state->bss_base, state->bss_len);
+
return 0;
}