MT#55447 add support for EVS

Change-Id: I54993cefbb3d30a4dc87b13507dd0d61739baaa0
pull/1577/head
Richard Fuchs 3 years ago
parent 69640dbb13
commit dc1a44f3ec

@ -433,6 +433,7 @@ The following codecs are supported by *rtpengine*:
* iLBC
* Opus
* AMR (narrowband and wideband)
* EVS (if supplied -- see below)
Codec support is dependent on support provided by the `ffmpeg` codec libraries, which may vary from
version to version. Use the `--codecs` command line option to have *rtpengine* print a list of codecs
@ -557,6 +558,33 @@ outgoing bitrate without being requested to by the peer via a CMR. To enable thi
longer than this interval ago, *rtpengine* will increase the bitrate by one step if possible. Afterwards,
the interval starts over.
EVS
---
Enhanced Voice Services (EVS) is a patent-encumbered codec for which (at the
time of writing) no implementation exists which can be freely used and
distributed. As such, support for EVS is only available if an implementation is
supplied separately. Currently the only implementation supported is the
ETSI/3GPP reference implementation (either floating-point or fixed-point). Any
licensing issues that might result from such usage are the responsibility of
the user of this software.
The EVS codec implementation can be provided as a shared object library (*.so*)
which is loaded in during runtime (at startup). The supported implementations
can be seen as subdirectories within the `evs/` directory. Currently supported
are version 17.0.0 of the ETSI/3GPP reference implementation, *126.442* for the
fixed-point implementation and *126.443* for the floating-point implementation.
(The floating-point implementation seems to be significantly faster, but is not
bit-precise.)
To supply the codec implementation as a shared object during runtime, extract
the reference implementation's *.zip* file and apply the provided `patch`
([from here](https://github.com/sipwise/rtpengine/tree/master/evs)) that is
appropriate for the chosen implementation. Run the build using `make`
(suggested build flags are `RELEASE=1 make`) and it should produce a file
`lib3gpp-evs.so`. Point *rtpengine* to this file using the `evs-lib-path=`
option to enable support for EVS.
Call recording
==============

@ -41,7 +41,7 @@ endif
#CFLAGS+= -DSRTCP_KEY_DERIVATION_RFC_COMPLIANCE
#CFLAGS+= -DSTRICT_SDES_KEY_LIFETIME
LDLIBS= -lm
LDLIBS= -lm -ldl
LDLIBS+= $(shell pkg-config --libs glib-2.0)
LDLIBS+= $(shell pkg-config --libs gthread-2.0)
LDLIBS+= $(shell pkg-config --libs zlib)

@ -2343,6 +2343,12 @@ static int codec_decoder_event(enum codec_event event, void *ptr, void *data) {
// ignore locking and races for this
media->encoder_callback.amr.cmr_out = GPOINTER_TO_UINT(ptr);
media->encoder_callback.amr.cmr_out_ts = rtpe_now;
break;
case CE_EVS_CMR_RECV:
// ignore locking and races for this
media->encoder_callback.evs.cmr_in = GPOINTER_TO_UINT(ptr);
media->encoder_callback.evs.cmr_in_ts = rtpe_now;
break;
default:
break;
}

@ -356,6 +356,11 @@ launched.
Set the stack size of each thread to the value given in kB. Defaults to 2048
kB. Can be set to -1 to leave the default provided by the OS unchanged.
=item B<--evs-lib-path=>I<FILE>
Points to the shared object file (B<.so>) containing the reference
implementation for the EVS codec. See the F<README> for more details.
=item B<--sip-source>
The original B<rtpproxy> as well as older version of B<rtpengine> by default

@ -0,0 +1,131 @@
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
# Paths
SRC_ENC = lib_enc lib_com basic_op basic_math
SRC_DEC = lib_dec lib_com basic_op basic_math
+SRC_LIB = lib_dec lib_enc lib_com basic_op basic_math
BUILD = build
SRC_DIRS = $(sort -u $(SRC_ENC) $(SRC_DEC))
@@ -10,6 +11,7 @@ SRC_DIRS = $(sort -u $(SRC_ENC) $(SRC_DEC))
# Name of CLI binaries
CLI_ENC = EVS_cod
CLI_DEC = EVS_dec
+LIB_SO = lib3gpp-evs.so
# Default tool settings
CC = gcc
@@ -49,13 +51,17 @@ CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR))
# Source file search paths
VPATH = $(SRC_DIRS)
+CFLAGS += -fPIC
+
###############################################################################
SRCS_ENC = $(foreach DIR,$(SRC_ENC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c)))
SRCS_DEC = $(foreach DIR,$(SRC_DEC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c)))
+SRCS_LIB = $(filter-out encoder.c decoder.c voip_client.c,$(foreach DIR,$(SRC_LIB),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))))
OBJS_ENC = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.o))
OBJS_DEC = $(addprefix $(BUILD)/,$(SRCS_DEC:.c=.o))
+OBJS_LIB = $(addprefix $(BUILD)/,$(SRCS_LIB:.c=.o))
DEPS = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.P) $(SRCS_DEC:.c=.P))
@@ -63,7 +69,7 @@ DEPS = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.P) $(SRCS_DEC:.c=.P))
.PHONY: all clean clean_all
-all: $(CLI_ENC) $(CLI_DEC)
+all: $(CLI_ENC) $(CLI_DEC) $(LIB_SO)
$(BUILD):
$(QUIET)mkdir -p $(BUILD)
@@ -74,6 +80,9 @@ $(CLI_ENC): $(OBJS_ENC)
$(CLI_DEC): $(OBJS_DEC)
$(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_DEC) -lm -o $(CLI_DEC)
+$(LIB_SO): $(OBJS_LIB)
+ $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_LIB) -lm -shared -o $(LIB_SO)
+
clean:
$(QUIET)$(RM) $(OBJS_ENC) $(OBJS_DEC) $(DEPS)
$(QUIET)$(RM) $(DEPS:.P=.d)
diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h
--- a/lib_com/prot_fx.h
+++ b/lib_com/prot_fx.h
@@ -622,6 +622,11 @@ void SetModeIndex(
void init_encoder_fx(
Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */
);
+unsigned long encoder_size(void);
+unsigned long encoder_ind_list_size(void);
+void encoder_set_opts(Encoder_State_fx *st_fx, unsigned long Fs, void *ind_list);
+void encoder_set_brate(Encoder_State_fx *st, unsigned long brate, unsigned int bwidth,
+ unsigned int mode, unsigned int amr);
void destroy_encoder_fx( Encoder_State_fx *st_fx );
@@ -654,6 +659,8 @@ Word16 gp_clip_fx(
void init_decoder_fx(
Decoder_State_fx *st_fx /* o: Decoder static variables structure */
);
+unsigned long decoder_size(void);
+void decoder_set_Fs(Decoder_State_fx *st_fx, unsigned long Fs);
void destroy_decoder(
Decoder_State_fx *st_fx /* o: Decoder static variables structure */
diff --git a/lib_dec/init_dec_fx.c b/lib_dec/init_dec_fx.c
--- a/lib_dec/init_dec_fx.c
+++ b/lib_dec/init_dec_fx.c
@@ -965,3 +965,12 @@ void destroy_decoder(
return;
}
+
+
+
+unsigned long decoder_size(void) {
+ return sizeof(Decoder_State_fx);
+}
+void decoder_set_Fs(Decoder_State_fx *st_fx, unsigned long Fs) {
+ st_fx->output_Fs_fx = Fs;
+}
diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c
--- a/lib_enc/init_enc_fx.c
+++ b/lib_enc/init_enc_fx.c
@@ -1006,3 +1006,31 @@ void destroy_encoder_fx(
return;
}
+
+
+
+unsigned long encoder_size(void) {
+ return sizeof(Encoder_State_fx);
+}
+void encoder_set_opts(Encoder_State_fx *st_fx, unsigned long Fs, void *ind_list) {
+ st_fx->input_Fs_fx = Fs;
+ st_fx->ind_list_fx = ind_list;
+ st_fx->rf_fec_indicator = 1;
+ st_fx->last_codec_mode = st_fx->codec_mode;
+}
+void encoder_set_brate(Encoder_State_fx *st, unsigned long brate, unsigned int bwidth,
+ unsigned int mode, unsigned int amr) {
+ if (brate == 5900) {
+ st->Opt_SC_VBR_fx = 1;
+ brate = 7200;
+ }
+ else
+ st->Opt_SC_VBR_fx = 0;
+ st->total_brate_fx = brate;
+ st->codec_mode = mode;
+ st->Opt_AMR_WB_fx = amr;
+ st->max_bwidth_fx = bwidth;
+}
+unsigned long encoder_ind_list_size(void) {
+ return sizeof(Indice_fx) * MAX_NUM_INDICES;
+}

@ -0,0 +1,131 @@
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
# Paths
SRC_ENC = lib_enc lib_com
SRC_DEC = lib_dec lib_com
+SRC_LIB = lib_dec lib_enc lib_com
BUILD = build
SRC_DIRS = $(sort -u $(SRC_ENC) $(SRC_DEC))
@@ -10,6 +11,7 @@ SRC_DIRS = $(sort -u $(SRC_ENC) $(SRC_DEC))
# Name of CLI binaries
CLI_ENC = EVS_cod
CLI_DEC = EVS_dec
+LIB_SO = lib3gpp-evs.so
# Default tool settings
CC = gcc
@@ -62,13 +64,17 @@ CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR))
# Source file search paths
VPATH = $(SRC_DIRS)
+CFLAGS += -fPIC
+
###############################################################################
SRCS_ENC = $(foreach DIR,$(SRC_ENC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c)))
SRCS_DEC = $(foreach DIR,$(SRC_DEC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c)))
+SRCS_LIB = $(filter-out encoder.c decoder.c voip_client.c,$(foreach DIR,$(SRC_LIB),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))))
OBJS_ENC = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.o))
OBJS_DEC = $(addprefix $(BUILD)/,$(SRCS_DEC:.c=.o))
+OBJS_LIB = $(addprefix $(BUILD)/,$(SRCS_LIB:.c=.o))
DEPS = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.P) $(SRCS_DEC:.c=.P))
@@ -76,7 +82,7 @@ DEPS = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.P) $(SRCS_DEC:.c=.P))
.PHONY: all clean clean_all
-all: $(CLI_ENC) $(CLI_DEC)
+all: $(CLI_ENC) $(CLI_DEC) $(LIB_SO)
$(BUILD):
$(QUIET)mkdir -p $(BUILD)
@@ -87,6 +93,9 @@ $(CLI_ENC): $(OBJS_ENC)
$(CLI_DEC): $(OBJS_DEC)
$(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_DEC) -lm -o $(CLI_DEC)
+$(LIB_SO): $(OBJS_LIB)
+ $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_LIB) -lm -shared -o $(LIB_SO)
+
clean:
$(QUIET)$(RM) $(OBJS_ENC) $(OBJS_DEC) $(DEPS)
$(QUIET)$(RM) $(DEPS:.P=.d)
diff --git a/lib_com/prot.h b/lib_com/prot.h
--- a/lib_com/prot.h
+++ b/lib_com/prot.h
@@ -624,6 +624,11 @@ short lsp_convert_poly(
const short L_frame, /* i : flag for up or down conversion */
const short Opt_AMRWB /* i : flag for the AMR-WB IO mode */
);
+unsigned long encoder_size(void);
+unsigned long encoder_ind_list_size(void);
+void encoder_set_opts(Encoder_State *st, unsigned long Fs, void *ind_list);
+void encoder_set_brate(Encoder_State *st, unsigned long brate, unsigned int bwidth,
+ unsigned int mode, unsigned int amr);
short findpulse( /* o : pulse position */
const short L_frame, /* i : length of the frame */
@@ -651,6 +656,8 @@ void preemph(
const short L, /* i : vector size */
float *mem /* i/o: memory (x[-1]) */
);
+unsigned long decoder_size(void);
+void decoder_set_Fs(Decoder_State *st, unsigned long Fs);
void cb_shape(
const short preemphFlag, /* i : flag for pre-emphasis */
diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c
--- a/lib_dec/init_dec.c
+++ b/lib_dec/init_dec.c
@@ -653,3 +653,12 @@ void destroy_decoder(
return;
}
+
+
+
+unsigned long decoder_size(void) {
+ return sizeof(Decoder_State);
+}
+void decoder_set_Fs(Decoder_State *st, unsigned long Fs) {
+ st->output_Fs = Fs;
+}
diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c
--- a/lib_enc/init_enc.c
+++ b/lib_enc/init_enc.c
@@ -729,3 +729,31 @@ void destroy_encoder(
return;
}
+
+
+
+unsigned long encoder_size(void) {
+ return sizeof(Encoder_State);
+}
+void encoder_set_opts(Encoder_State *st, unsigned long Fs, void *ind_list) {
+ st->input_Fs = Fs;
+ st->ind_list = ind_list;
+ st->rf_fec_indicator = 1;
+ st->last_codec_mode = st->codec_mode;
+}
+void encoder_set_brate(Encoder_State *st, unsigned long brate, unsigned int bwidth,
+ unsigned int mode, unsigned int amr) {
+ if (brate == 5900) {
+ st->Opt_SC_VBR = 1;
+ brate = 7200;
+ }
+ else
+ st->Opt_SC_VBR = 0;
+ st->total_brate = brate;
+ st->codec_mode = mode;
+ st->Opt_AMR_WB = amr;
+ st->max_bwidth = bwidth;
+}
+unsigned long encoder_ind_list_size(void) {
+ return sizeof(Indice) * MAX_NUM_INDICES;
+}

@ -162,6 +162,7 @@ void config_load(int *argc, char ***argv, GOptionEntry *app_entries, const char
{ "pidfile", 'p', 0, G_OPTION_ARG_FILENAME, &rtpe_common_config_ptr->pidfile, "Write PID to file", "FILE" },
{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &rtpe_common_config_ptr->foreground, "Don't fork to background", NULL },
{ "thread-stack", 0,0, G_OPTION_ARG_INT, &rtpe_common_config_ptr->thread_stack, "Thread stack size in kB", "INT" },
{ "evs-lib-path", 0,0, G_OPTION_ARG_FILENAME, &rtpe_common_config_ptr->evs_lib_path, "Location of .so for 3GPP EVS codec", "FILE" },
{ NULL, }
};
#undef ll

@ -30,6 +30,7 @@ struct rtpengine_common_config {
int foreground;
int thread_stack;
int max_log_line_length;
char *evs_lib_path;
};
extern struct rtpengine_common_config *rtpe_common_config_ptr;

File diff suppressed because it is too large Load Diff

@ -112,8 +112,12 @@ struct encoder_callback_s {
struct timeval cmr_out_ts;
unsigned int cmr_out;
} amr;
};
struct {
struct timeval cmr_in_ts;
unsigned int cmr_in;
} evs;
};
union codec_options_u {
struct {
const unsigned int *bits_per_frame;
@ -122,6 +126,10 @@ union codec_options_u {
int mode_change_interval;
int cmr_interval;
} amr;
struct {
enum evs_bw max_bw;
} evs;
};
enum dtx_method {
@ -190,6 +198,7 @@ struct resample_s {
enum codec_event {
CE_AMR_CMR_RECV,
CE_AMR_SEND_CMR,
CE_EVS_CMR_RECV,
};
struct dtx_method_s {
@ -240,6 +249,7 @@ struct decoder_s {
unsigned int event;
unsigned long duration;
} dtmf;
void *evs;
} u;
unsigned long rtp_ts;
@ -276,6 +286,11 @@ struct encoder_s {
#ifdef HAVE_BCG729
bcg729EncoderChannelContextStruct *bcg729;
#endif
struct {
void *ctx;
void *ind_list;
struct timeval cmr_in_ts;
} evs;
} u;
AVPacket *avpkt;
AVAudioFifo *fifo;

@ -21,6 +21,17 @@ struct rtp_header {
} __attribute__ ((packed));
enum evs_bw {
EVS_BW_NB = 0,
EVS_BW_WB = 1,
EVS_BW_SWB = 2,
EVS_BW_FB = 3,
__EVS_BW_MAX,
EVS_BW_UNSPEC = -1,
};
union codec_format_options {
struct {
int interleaving;
@ -35,6 +46,27 @@ union codec_format_options {
struct {
int mode;
} ilbc;
struct {
// EVS options
unsigned int min_br, max_br;
unsigned int min_br_send, max_br_send;
unsigned int min_br_recv, max_br_recv;
enum evs_bw min_bw, max_bw;
enum evs_bw min_bw_send, max_bw_send;
enum evs_bw min_bw_recv, max_bw_recv;
// AMR options
unsigned int mode_set; // bitfield
int mode_change_period;
// bit field options
unsigned int hf_only:1;
unsigned int amr_io:1;
unsigned int no_dtx:1;
unsigned int no_dtx_recv:1;
int cmr:2; // -1, 0, 1
// AMR bit options
unsigned int mode_change_neighbor:1;
} evs;
};
struct rtp_codec_format {

@ -14,7 +14,7 @@ CFLAGS+= $(shell pkg-config --cflags libavfilter)
CFLAGS+= $(shell mysql_config --cflags)
CFLAGS+= $(shell pkg-config --cflags openssl)
LDLIBS= -lm
LDLIBS= -lm -ldl
LDLIBS+= $(shell pkg-config --libs glib-2.0)
LDLIBS+= $(shell pkg-config --libs gthread-2.0)
LDLIBS+= $(shell pkg-config --libs libavcodec)

@ -127,6 +127,11 @@ known.
Set the stack size of each thread to the value given in kB. Defaults to 2048
kB. Can be set to -1 to leave the default provided by the OS unchanged.
=item B<--evs-lib-path=>I<FILE>
Points to the shared object file (B<.so>) containing the reference
implementation for the EVS codec. See the F<README> for more details.
=item B<--output-storage=>B<file>|B<db>|B<both>
Where to store media files. By default, media files are written directly to the

@ -35,7 +35,7 @@ else
CFLAGS+= -DWITHOUT_CODECLIB
endif
LDLIBS= -lm
LDLIBS= -lm -ldl
LDLIBS+= $(shell pkg-config --libs glib-2.0)
LDLIBS+= $(shell pkg-config --libs gthread-2.0)
LDLIBS+= $(shell pkg-config --libs libcrypto)
@ -88,7 +88,8 @@ include ../lib/common.Makefile
.PHONY: all-tests unit-tests daemon-tests daemon-tests \
daemon-tests-main daemon-tests-jb daemon-tests-dtx daemon-tests-dtx-cn daemon-tests-pubsub \
daemon-tests-intfs daemon-tests-stats daemon-tests-delay-buffer daemon-tests-delay-timing
daemon-tests-intfs daemon-tests-stats daemon-tests-delay-buffer daemon-tests-delay-timing \
daemon-tests-evs
TESTS= test-bitstr aes-crypt aead-aes-crypt test-const_str_hash.strhash
ifeq ($(with_transcoding),yes)
@ -123,6 +124,7 @@ unit-tests: $(TESTS)
fi
daemon-tests: daemon-tests-main daemon-tests-jb daemon-tests-pubsub daemon-tests-websocket \
daemon-tests-evs \
daemon-tests-intfs daemon-tests-stats # daemon-tests-delay-buffer daemon-tests-delay-timing
daemon-test-deps: tests-preload.so
@ -208,6 +210,14 @@ daemon-tests-delay-timing: daemon-test-deps
test "$$(ls fake-$@-sockets)" = ""
rmdir fake-$@-sockets
daemon-tests-evs: daemon-test-deps
rm -rf fake-$@-sockets
mkdir fake-$@-sockets
LD_PRELOAD=../t/tests-preload.so RTPE_BIN=../daemon/rtpengine TEST_SOCKET_PATH=./fake-$@-sockets \
perl -I../perl auto-daemon-tests-evs.pl
test "$$(ls fake-$@-sockets)" = ""
rmdir fake-$@-sockets
test-bitstr: test-bitstr.o
spandsp_send_fax_pcm: spandsp_send_fax_pcm.o

File diff suppressed because it is too large Load Diff

@ -4,6 +4,10 @@
#include "resample.h"
#include "codeclib.h"
#include "fix_frame_channel_layout.h"
#include "main.h"
struct rtpengine_config rtpe_config;
struct rtpengine_config initial_rtpe_config;
void test_1(int in_samples, int in_format, int in_rate, int in_channels, bool no_filter,
int out_format, int out_rate, int out_channels,
@ -43,6 +47,7 @@ void test_1(int in_samples, int in_format, int in_rate, int in_channels, bool no
}
int main(void) {
rtpe_common_config_ptr = &rtpe_config.common;
codeclib_init(0);
test_1(320, AV_SAMPLE_FMT_S16, 16000, 1, false, AV_SAMPLE_FMT_S16, 8000, 1, 144);

Loading…
Cancel
Save