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>
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 @@
 
 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 @@
 
 	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 @@
 	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 @@
 	if (enc_reset_flg)
 		resetEnc();
 
+	memcpy(state->bss_save, state->bss_base, state->bss_len);
+
 	return 0;
 }
 
@@ -84,6 +113,8 @@
 	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 @@
 
 	state->dec_reset_flg = dec_reset_flg;
 
+	memcpy(state->bss_save, state->bss_base, state->bss_len);
+
 	return 0;
 }