MT#55831 opus: configurable codec settings for OPUS codec

opus.conf may contain an fmtp line with opus codec parameters,
all in one line, e.g.
maxplaybackrate=16000;stereo=0;useinbandfec=1

supported parameters:
 maxplaybackrate
 stereo
 useinbandfec
(real ticket number: TT#13019)

Change-Id: I74b7a2a6902dbe718785da89c189f4c726a05a7a
mr11.2.1
Stefan Sayer 4 years ago committed by Donat Zenichev
parent 5c5695ce80
commit 4dd4d94bd1

@ -47,6 +47,7 @@
*/
#include <opus/opus.h>
#include <stdio.h>
#define _OPUS_APPLICATION_ OPUS_APPLICATION_VOIP
/* Allowed values:
@ -88,6 +89,10 @@ static long opus_create(const char* format_parameters, const char** format_param
amci_codec_fmt_info_t** format_description);
static void opus_destroy(long h_inst);
static int opus_negotiate_fmt(int is_offer, const char* params_in, char* params_out, unsigned int params_out_len);
static int opus_load(const char* ModConfigPath);
#if SYSTEM_SAMPLECLOCK_RATE >= 48000
#define _OPUS_RATE 48000
#elif SYSTEM_SAMPLECLOCK_RATE >= 24000
@ -103,13 +108,14 @@ static void opus_destroy(long h_inst);
static amci_codec_fmt_info_t opus_fmt_description[] = { {AMCI_FMT_FRAME_LENGTH, 20},
{AMCI_FMT_FRAME_SIZE, 20 * _OPUS_RATE / 1000}, {0,0}};
BEGIN_EXPORTS( "opus" , AMCI_NO_MODULEINIT, AMCI_NO_MODULEDESTROY )
BEGIN_EXPORTS( "opus" , opus_load, AMCI_NO_MODULEDESTROY )
BEGIN_CODECS
CODEC( CODEC_OPUS, pcm16_2_opus, opus_2_pcm16, opus_plc,
CODEC_WITH_FMT( CODEC_OPUS, pcm16_2_opus, opus_2_pcm16, opus_plc,
opus_create,
opus_destroy,
NULL, NULL )
NULL, NULL ,
opus_negotiate_fmt)
END_CODECS
BEGIN_PAYLOADS
@ -126,13 +132,154 @@ typedef struct {
OpusDecoder* opus_dec;
} opus_state_t;
/* e.g. "maxplaybackrate=8000; stereo=0; useinbandfec=1" */
char default_format_parameters[80];
int opus_load(const char* ModConfigPath) {
default_format_parameters[0]='\0';
char conf_file[256];
if (NULL != ModConfigPath) {
sprintf(conf_file, "%sopus.conf",ModConfigPath);
FILE* fp = fopen(conf_file, "rt");
if (fp) {
char line[80];
while(fgets(line, 80, fp) != NULL) {
if (!line[0] ||line[0]=='#')
continue;
strcpy(default_format_parameters, line);
break;
}
DBG("initialized default format parameters as '%s'\n", default_format_parameters);
fclose(fp);
}
}
DBG("OPUS: initialized\n");
return 0;
}
int opus_negotiate_fmt(int is_offer, const char* params_in, char* params_out, unsigned int params_out_len) {
// todo: properly negotiating features
strncpy(params_out, default_format_parameters, params_out_len);
return 0;
}
/*
Search for a parameter assignement in input string.
If it's not found *param_value is null, otherwise *param_value points to the
right hand term.
In both cases a pointer suitable for a new search is returned
*/
static char* read_param(char* input, const char *param, char** param_value)
{
int param_size;
/* Eat spaces and semi-colons */
while (*input && (*input==' ' || *input==';' || *input=='"'))
input;
*param_value = NULL;
param_size = strlen(param);
if (strncmp(input, param, param_size))
return input;
if (*(input+param_size) != '=')
return input;
input=param_size+1;
/* Found and discarded a matching parameter */
*param_value = input;
while (*input && *input!=' ' && *input!=';' && *input!='"')
input;
if (*input=='"')
{
*param_value = *param_value+1; /* remove " */
/* string will end after next: " */
while (*input && *input!='"' && *input!='\r' && *input!='\n')
input;
if (*input=='"')
input--; /* remove " */
}
if (*input)
*input = 0;
return input;
}
#define BLEN 63
void decode_format_parameters(const char* format_parameters, unsigned int* maxbandwidth, int* useinbandfec, int* stereo) {
if (format_parameters && strlen(format_parameters)<=BLEN){
char buffer2[BLEN+1];
char *buffer = buffer2;
strcpy(buffer, format_parameters);
while (*buffer) {
char *param_value;
/* maxplaybackrate */
buffer=read_param(buffer, "maxplaybackrate", &param_value);
if (param_value) {
*maxbandwidth = atoi(param_value);
if (!*maxbandwidth) {
*maxbandwidth = _OPUS_RATE;
DBG("wrong maxbandwidth value '%s'\n", param_value);
}
continue;
}
/* stereo */
buffer=read_param(buffer, "stereo", &param_value);
if (param_value) {
if (*param_value == '1')
*stereo = 1;
else
*stereo = 0;
continue;
}
/* useinbandfec */
buffer=read_param(buffer, "useinbandfec", &param_value);
if (param_value) {
if (*param_value == '1')
*useinbandfec = 1;
else
*useinbandfec = 0;
continue;
}
/* Unknown parameter */
if (*buffer) {
param_value = buffer;
while (*buffer && *buffer!=';')
buffer;
if (*buffer)
*buffer = 0;
DBG("OPUS: SDP parameter fmtp: %s ignored in creating encoder.\n", param_value);
}
}
}
}
long opus_create(const char* format_parameters, const char** format_parameters_out,
amci_codec_fmt_info_t** format_description) {
opus_state_t* codec_inst;
int error;
unsigned int maxbandwidth = _OPUS_RATE;
int useinbandfec = _OPUS_INBAND_FEC_;
int stereo = 0;
if (format_parameters) {
DBG("\n\n\n");
DBG("OPUS params: >>%s<<.\n", format_parameters);
DBG("\n\n\n");
decode_format_parameters(format_parameters, &maxbandwidth, &useinbandfec, &stereo);
}
codec_inst = (opus_state_t*)malloc(sizeof(opus_state_t));
@ -140,17 +287,34 @@ long opus_create(const char* format_parameters, const char** format_parameters_o
if (!codec_inst)
return -1;
DBG("OPUS: creating encoder with maxbandwidth=%u, stereo=%s, useinbandfec=%s\n",
maxbandwidth, stereo?"true":"false", useinbandfec?"true":"false");
codec_inst->opus_enc = opus_encoder_create(_OPUS_RATE,1,_OPUS_APPLICATION_,&error);
if (error) {
DBG("OPUS: error %d while creating encoder state.\n", error);
return -1;
}
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_FORCE_CHANNELS(1));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_MAX_BANDWIDTH(_OPUS_MAX_BANDWIDTH_));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_FORCE_CHANNELS(stereo ? 2:1));
unsigned int opus_set_bw = _OPUS_RATE;
if (maxbandwidth <= 8000) {
opus_set_bw = OPUS_BANDWIDTH_NARROWBAND;
} else if (maxbandwidth <= 12000) {
opus_set_bw = OPUS_BANDWIDTH_MEDIUMBAND;
} else if (maxbandwidth <= 16000) {
opus_set_bw = OPUS_BANDWIDTH_WIDEBAND;
} else if (maxbandwidth <= 24000) {
opus_set_bw = OPUS_BANDWIDTH_SUPERWIDEBAND;
} else {
opus_set_bw = OPUS_BANDWIDTH_FULLBAND;
}
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_MAX_BANDWIDTH(opus_set_bw));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_PACKET_LOSS_PERC(_OPUS_PKT_LOSS_PCT_));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_COMPLEXITY(_OPUS_COMPLEXITY_));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_INBAND_FEC(_OPUS_INBAND_FEC_));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_INBAND_FEC(useinbandfec ? 1:0));
opus_encoder_ctl(codec_inst->opus_enc, OPUS_SET_DTX(_OPUS_DTX_));
codec_inst->opus_dec = opus_decoder_create(_OPUS_RATE,1,&error);

Loading…
Cancel
Save