Browse Source

TT#91003 support AMR mode-set option

Change-Id: I9926e940d7e77d869b2ebdd975417745d42ec1fd
pull/1077/head
Richard Fuchs 5 years ago
parent
commit
23b1aaea10
3 changed files with 101 additions and 2 deletions
  1. +26
    -0
      README.md
  2. +73
    -2
      lib/codeclib.c
  3. +2
    -0
      lib/codeclib.h

+ 26
- 0
README.md View File

@ -476,6 +476,32 @@ this case if no other codecs are specified.
For further information, see the section on the `T.38` dictionary key below. For further information, see the section on the `T.38` dictionary key below.
AMR and AMR-WB
--------------
As AMR supports dynamically adapting the encoder bitrate, as well as restricting the available bitrates,
there are some slight peculiarities about its usage when transcoding.
When setting the bitrate, for example as `AMR-WB/16000/1/23850` in either the `codec-transcode` or the
`codec-set` options, that bitrate will be used as the highest permitted bitrate for the encoder. If
no `mode-set` parameter is communicated in the SDP, then that is the bitrate that will be used.
If a `mode-set` is present, then the highest bitrate from that mode set which is lower or equal to the
given bitrate will be used. If only higher bitrates are allowed by the mode set, then the next higher
bitrate will be used.
To produce an SDP that includes the `mode-set` option (when adding AMR to the codec list via
`codec-transcode`), the full format parameter string can be appended to the codec specification, e.g.
`codec-transcode-AMR-WB/16000/1/23850//mode-set=0,1,2,3,4,5;octet-align=1`. In this example, the bitrate
23850 won't actually be used, as the highest permitted mode is 5 (18250 bps) and so that bitrate will
be used.
If a literal `=` cannot be used due to parsing constraints (i.e. being wrongly interpreted as a
key-value pair), it can be escaped by using two dashes instead, e.g.
`codec-transcode-AMR-WB/16000/1/23850//mode-set--0,1,2,3,4,5;octet-align--1`
The default (highest) bitrates for AMR and AMR-WB are 6700 and 14250, respectively.
Call recording Call recording
============== ==============


+ 73
- 2
lib/codeclib.c View File

@ -1477,6 +1477,22 @@ static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
#define AMR_FT_TYPES 14 #define AMR_FT_TYPES 14
const static unsigned int amr_bitrates[AMR_FT_TYPES] = {
4750, // 0
5150, // 1
5900, // 2
6700, // 3
7400, // 4
7950, // 5
10200, // 6
12200, // 7
0, // comfort noise // 8
0, // comfort noise // 9
0, // comfort noise // 10
0, // comfort noise // 11
0, // invalid // 12
0, // invalid // 13
};
const static unsigned int amr_bits_per_frame[AMR_FT_TYPES] = { const static unsigned int amr_bits_per_frame[AMR_FT_TYPES] = {
95, // 4.75 kbit/s // 0 95, // 4.75 kbit/s // 0
103, // 5.15 kbit/s // 1 103, // 5.15 kbit/s // 1
@ -1493,6 +1509,22 @@ const static unsigned int amr_bits_per_frame[AMR_FT_TYPES] = {
0, // invalid // 12 0, // invalid // 12
0, // invalid // 13 0, // invalid // 13
}; };
const static unsigned int amr_wb_bitrates[AMR_FT_TYPES] = {
6600, // 0
8850, // 1
12650, // 2
14250, // 3
15850, // 4
18250, // 5
19850, // 6
23050, // 7
23850, // 8
0, // comfort noise // 9
0, // invalid // 10
0, // invalid // 11
0, // invalid // 12
0, // invalid // 13
};
const static unsigned int amr_wb_bits_per_frame[AMR_FT_TYPES] = { const static unsigned int amr_wb_bits_per_frame[AMR_FT_TYPES] = {
132, // 6.60 kbit/s // 0 132, // 6.60 kbit/s // 0
177, // 8.85 kbit/s // 1 177, // 8.85 kbit/s // 1
@ -1510,10 +1542,14 @@ const static unsigned int amr_wb_bits_per_frame[AMR_FT_TYPES] = {
0, // invalid // 13 0, // invalid // 13
}; };
static void amr_set_encdec_options(codec_options_t *opts, const str *fmtp, const codec_def_t *def) { static void amr_set_encdec_options(codec_options_t *opts, const str *fmtp, const codec_def_t *def) {
if (!strcmp(def->rtpname, "AMR"))
if (!strcmp(def->rtpname, "AMR")) {
opts->amr.bits_per_frame = amr_bits_per_frame; opts->amr.bits_per_frame = amr_bits_per_frame;
else
opts->amr.bitrates = amr_bitrates;
}
else {
opts->amr.bits_per_frame = amr_wb_bits_per_frame; opts->amr.bits_per_frame = amr_wb_bits_per_frame;
opts->amr.bitrates = amr_wb_bitrates;
}
if (!fmtp || !fmtp->s) if (!fmtp || !fmtp->s)
return; return;
@ -1547,11 +1583,46 @@ static void amr_set_encdec_options(codec_options_t *opts, const str *fmtp, const
opts->amr.octet_aligned = 1; opts->amr.octet_aligned = 1;
opts->amr.interleaving = str_to_i(&token, 0); opts->amr.interleaving = str_to_i(&token, 0);
} }
else if (!str_cmp(&key, "mode-set")) {
str mode;
while (str_token_sep(&mode, &token, ',') == 0) {
int m = str_to_i(&mode, -1);
if (m < 0 || m >= AMR_FT_TYPES)
continue;
opts->amr.mode_set |= (1 << m);
}
}
// XXX other options // XXX other options
} }
} }
static void amr_set_enc_options(encoder_t *enc, const str *fmtp) { static void amr_set_enc_options(encoder_t *enc, const str *fmtp) {
amr_set_encdec_options(&enc->codec_options, fmtp, enc->def); amr_set_encdec_options(&enc->codec_options, fmtp, enc->def);
// if a mode-set was given, pick the highest supported bitrate
if (enc->codec_options.amr.mode_set) {
int max_bitrate = enc->u.avc.avcctx->bit_rate;
int use_bitrate = 0;
for (int i = 0; i < AMR_FT_TYPES; i++) {
if (!(enc->codec_options.amr.mode_set & (1 << i)))
continue;
unsigned int br = enc->codec_options.amr.bitrates[i];
// we depend on the list being in ascending order, with
// invalid modes at the end
if (!br) // end of list
break;
if (br > max_bitrate && use_bitrate) // done
break;
use_bitrate = br;
}
if (!use_bitrate)
ilog(LOG_WARN, "Unable to determine a valid bitrate from %s mode-set, using default",
enc->def->rtpname);
else {
ilog(LOG_DEBUG, "Using %i as initial %s bitrate based on mode-set",
use_bitrate, enc->def->rtpname);
enc->u.avc.avcctx->bit_rate = use_bitrate;
}
}
} }
static void amr_set_dec_options(decoder_t *dec, const str *fmtp) { static void amr_set_dec_options(decoder_t *dec, const str *fmtp) {
amr_set_encdec_options(&dec->codec_options, fmtp, dec->def); amr_set_encdec_options(&dec->codec_options, fmtp, dec->def);


+ 2
- 0
lib/codeclib.h View File

@ -87,11 +87,13 @@ struct codec_type_s {
union codec_options_u { union codec_options_u {
struct { struct {
int interleaving; int interleaving;
unsigned int mode_set; // bitfield
int octet_aligned:1; int octet_aligned:1;
int crc:1; int crc:1;
int robust_sorting:1; int robust_sorting:1;
const unsigned int *bits_per_frame; const unsigned int *bits_per_frame;
const unsigned int *bitrates;
} amr; } amr;
}; };


Loading…
Cancel
Save