Browse Source

TT#91003 add `mode-change-interval` AMR option

Change-Id: I08d54cf5c17c1d1d66218cdb9c06aa5ac9bb6837
pull/1077/head
Richard Fuchs 5 years ago
parent
commit
cd5cd8483b
3 changed files with 65 additions and 2 deletions
  1. +6
    -0
      README.md
  2. +57
    -2
      lib/codeclib.c
  3. +2
    -0
      lib/codeclib.h

+ 6
- 0
README.md View File

@ -514,6 +514,12 @@ was not received will ever be requested, and a CMR will be sent only once per in
specify a CMR interval of 500 milliseconds (with `=` escapes):
`codec-transcode-AMR-WB/16000/1/23850//mode-set--0,1,2/CMR-interval--500`
Similar to the `CMR-interval` option, *rtpengine* can optionally attempt to periodically increase the
outgoing bitrate without being requested to by the peer via a CMR. To enable this, set the option
`mode-change-interval` to the desired interval in milliseconds. If the last CMR from the AMR peer was
longer than this interval ago, *rtpengine* will increase the bitrate by one step if possible. Afterwards,
the interval starts over.
Call recording
==============


+ 57
- 2
lib/codeclib.c View File

@ -1650,12 +1650,17 @@ static void amr_set_dec_codec_options(str *key, str *value, void *data) {
if (!str_cmp(key, "CMR-interval"))
dec->codec_options.amr.cmr_interval = str_to_i(value, 0);
else if (!str_cmp(key, "mode-change-interval"))
dec->codec_options.amr.mode_change_interval = str_to_i(value, 0);
}
static void amr_set_enc_codec_options(str *key, str *value, void *data) {
encoder_t *enc = data;
if (!str_cmp(key, "CMR-interval"))
; // not an encoder optoin
; // not an encoder option
else if (!str_cmp(key, "mode-change-interval"))
; // not an encoder option
else {
// our string might not be null terminated
char *s = g_strdup_printf(STR_FORMAT, STR_FMT(key));
@ -1770,8 +1775,21 @@ static int amr_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
goto err;
unsigned int cmr_int = cmr_chr[0] >> 4;
if (cmr_int != 15)
if (cmr_int != 15) {
decoder_event(dec, CE_AMR_CMR_RECV, GUINT_TO_POINTER(cmr_int));
dec->u.avc.u.amr.last_cmr = rtpe_now;
}
else if (dec->codec_options.amr.mode_change_interval) {
// no CMR, check if we're due to do our own mode change
if (!dec->u.avc.u.amr.last_cmr.tv_sec) // start tracking now
dec->u.avc.u.amr.last_cmr = rtpe_now;
else if (timeval_diff(&rtpe_now, &dec->u.avc.u.amr.last_cmr)
>= dec->codec_options.amr.mode_change_interval * 1000) {
// switch up if we can
decoder_event(dec, CE_AMR_CMR_RECV, GUINT_TO_POINTER(0xffff));
dec->u.avc.u.amr.last_cmr = rtpe_now;
}
}
if (dec->codec_options.amr.octet_aligned) {
if (bitstr_shift(&d, 4))
@ -1874,6 +1892,41 @@ err:
return -1;
}
static unsigned int amr_encoder_find_next_mode(encoder_t *enc) {
int mode = -1;
for (int i = 0; i < AMR_FT_TYPES; i++) {
int br = enc->codec_options.amr.bitrates[i];
if (!br) // end of list
break;
if (br == enc->u.avc.avcctx->bit_rate) {
mode = i;
break;
}
}
if (mode == -1)
return -1;
int next_mode = mode + 1;
// if modes are restricted, find the next one up
if (enc->codec_options.amr.mode_set) {
// is there anything?
if ((1 << next_mode) > enc->codec_options.amr.mode_set)
return -1;
int next_up = -1;
for (; next_mode < AMR_FT_TYPES; next_mode++) {
if (!(enc->codec_options.amr.mode_set & (1 << next_mode)))
continue;
next_up = next_mode;
break;
}
if (next_up == -1)
return -1;
next_mode = next_up;
}
// valid mode?
if (next_mode >= AMR_FT_TYPES || enc->codec_options.amr.bitrates[next_mode] == 0)
return -1;
return next_mode;
}
static void amr_encoder_mode_change(encoder_t *enc) {
if (!memcmp(&enc->codec_options.amr.cmr.cmr_in_ts,
&enc->u.avc.u.amr.cmr_in_ts, sizeof(struct timeval)))
@ -1882,6 +1935,8 @@ static void amr_encoder_mode_change(encoder_t *enc) {
if (enc->codec_options.amr.mode_change_period == 2 && (enc->u.avc.u.amr.pkt_seq & 1) != 0)
return;
unsigned int cmr = enc->codec_options.amr.cmr.cmr_in;
if (cmr == 0xffff)
cmr = amr_encoder_find_next_mode(enc);
if (cmr >= AMR_FT_TYPES)
return;
// ignore CMR for invalid modes


+ 2
- 0
lib/codeclib.h View File

@ -100,6 +100,7 @@ union codec_options_u {
int interleaving;
unsigned int mode_set; // bitfield
int mode_change_period;
int mode_change_interval;
int octet_aligned:1;
int crc:1;
int robust_sorting:1;
@ -184,6 +185,7 @@ struct decoder_s {
struct {
uint16_t bitrate_tracker[AMR_FT_TYPES];
struct timeval tracker_end;
struct timeval last_cmr;
} amr;
} u;
} avc;


Loading…
Cancel
Save