TT#91003 honour AMR mode change restrictions

Change-Id: I632f27c7068f3b7f6f3648992fcc6e5b5d65a29a
pull/1077/head
Richard Fuchs 5 years ago
parent ed9de316c7
commit 1020bcb80d

@ -361,7 +361,7 @@ static codec_def_t __codec_defs[] = {
.default_channels = 1,
.default_bitrate = 6700,
.default_ptime = 20,
.default_fmtp = "octet-align=1",
.default_fmtp = "octet-align=1;mode-change-capability=2",
.packetizer = packetizer_amr,
.bits_per_sample = 2, // max is 12200 / 8000 = 1.525 bits per sample, rounded up
.media_type = MT_AUDIO,
@ -378,7 +378,7 @@ static codec_def_t __codec_defs[] = {
.default_channels = 1,
.default_bitrate = 14250,
.default_ptime = 20,
.default_fmtp = "octet-align=1",
.default_fmtp = "octet-align=1;mode-change-capability=2",
.packetizer = packetizer_amr,
.bits_per_sample = 2, // max is 23850 / 16000 = 1.490625 bits per sample, rounded up
.media_type = MT_AUDIO,
@ -1626,7 +1626,12 @@ static void amr_set_encdec_options_cb(str *key, str *token, void *data) {
opts->amr.mode_set |= (1 << m);
}
}
// XXX other options
else if (!str_cmp(key, "mode-change-period"))
opts->amr.mode_change_period = str_to_i(token, 0);
else if (!str_cmp(key, "mode-change-neighbor")) {
if (token->len == 1 && token->s[0] == '1')
opts->amr.mode_change_neighbor = 1;
}
}
static void amr_set_encdec_options(codec_options_t *opts, const str *fmtp, const codec_def_t *def) {
if (!strcmp(def->rtpname, "AMR")) {
@ -1873,6 +1878,9 @@ 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)))
return;
// mode change requested: check if this is allowed right now
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 >= AMR_FT_TYPES)
return;
@ -1882,10 +1890,43 @@ static void amr_encoder_mode_change(encoder_t *enc) {
int req_br = enc->codec_options.amr.bitrates[cmr];
if (!req_br)
return;
int cmr_done = 1;
if (enc->codec_options.amr.mode_change_neighbor) {
// handle non-neighbour mode changes
int cur_br = enc->u.avc.avcctx->bit_rate;
// step up or down from the requested bitrate towards the current one
int cmr_diff = (req_br > cur_br) ? -1 : 1;
int neigh_br = req_br;
int cmr_br = req_br;
while (1) {
// step up or down towards the current bitrate
cmr += cmr_diff;
// still in bounds?
if (cmr < 0 || cmr >= AMR_FT_TYPES)
break;
cmr_br = enc->codec_options.amr.bitrates[cmr];
if (cmr_br == cur_br)
break;
// allowed by mode set?
if (enc->codec_options.amr.mode_set) {
if (!(enc->codec_options.amr.mode_set & (1 << cmr)))
continue; // go to next mode
}
// valid bitrate - continue stepping
neigh_br = cmr_br;
}
// did we finish stepping or is there more to go?
if (neigh_br != req_br)
cmr_done = 0;
req_br = neigh_br; // set to this
}
enc->u.avc.avcctx->bit_rate = req_br;
if (cmr_done)
enc->u.avc.u.amr.cmr_in_ts = enc->codec_options.amr.cmr.cmr_in_ts;
}
static void amr_encoder_got_packet(encoder_t *enc) {
amr_encoder_mode_change(enc);
enc->u.avc.u.amr.pkt_seq++;
}
static int packetizer_amr(AVPacket *pkt, GString *buf, str *output, encoder_t *enc) {
assert(pkt->size >= 1);

@ -99,9 +99,11 @@ union codec_options_u {
struct {
int interleaving;
unsigned int mode_set; // bitfield
int mode_change_period;
int octet_aligned:1;
int crc:1;
int robust_sorting:1;
int mode_change_neighbor:1;
const unsigned int *bits_per_frame;
const unsigned int *bitrates;
@ -220,6 +222,7 @@ struct encoder_s {
struct timeval cmr_in_ts;
struct timeval cmr_out_ts;
unsigned int cmr_out_seq;
uint64_t pkt_seq;
} amr;
} u;
} avc;

@ -60,7 +60,7 @@ m=audio PORT RTP/AVP 8 96
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1
a=fmtp:96 octet-align=1;mode-change-capability=2
a=sendrecv
a=rtcp:PORT
SDP
@ -74,7 +74,7 @@ t=0 0
m=audio 3002 RTP/AVP 96
c=IN IP4 198.51.100.10
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1
a=fmtp:96 octet-align=1;mode-change-capability=2
a=sendrecv
--------------------------------------
v=0
@ -115,7 +115,7 @@ m=audio PORT RTP/AVP 8 96
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1
a=fmtp:96 octet-align=1;mode-change-capability=2
a=sendrecv
a=rtcp:PORT
SDP
@ -129,7 +129,7 @@ t=0 0
m=audio 3006 RTP/AVP 96
c=IN IP4 198.51.100.10
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1
a=fmtp:96 octet-align=1;mode-change-capability=2
a=sendrecv
--------------------------------------
v=0
@ -170,7 +170,7 @@ m=audio PORT RTP/AVP 8 96
c=IN IP4 203.0.113.1
a=rtpmap:8 PCMA/8000
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1
a=fmtp:96 octet-align=1;mode-change-capability=2
a=sendrecv
a=rtcp:PORT
SDP
@ -184,7 +184,7 @@ t=0 0
m=audio 3010 RTP/AVP 96
c=IN IP4 198.51.100.10
a=rtpmap:96 AMR-WB/16000
a=fmtp:96 octet-align=1; mode-set=0,1,2,3,4
a=fmtp:96 octet-align=1; mode-set=0,1,2,3,4; mode-change-capability=2
a=sendrecv
--------------------------------------
v=0

Loading…
Cancel
Save