TT#91003 handle AMR CMR

Change-Id: I9fdb58359c25b3fcedf25872c98ac8ff582fa488
pull/1077/head
Richard Fuchs 5 years ago
parent e8aac8272c
commit 6fc9459016

@ -502,6 +502,9 @@ key-value pair), it can be escaped by using two dashes instead, e.g.
The default (highest) bitrates for AMR and AMR-WB are 6700 and 14250, respectively.
If a Codec Mode Request (CMR) is received from the AMR peer, then *rtpengine* will adhere to the request
and switch encoder bitrate unconditionally, even if it's a higher bitrate than originally desired.
Call recording
==============

@ -1723,6 +1723,19 @@ uint64_t codec_decoder_unskip_pts(struct codec_ssrc_handler *ch) {
}
static int codec_decoder_event(enum codec_event event, void *ptr, void *data) {
struct call_media *media = data;
if (!media)
return 0;
switch (event) {
case CE_AMR_CMR_RECV:
// ignore locking and races for this
media->u.amr.cmr.cmr_in = GPOINTER_TO_UINT(ptr);
media->u.amr.cmr.cmr_in_ts = rtpe_now;
break;
default:
break;
}
return 0;
}
@ -1985,6 +1998,10 @@ static int packet_decoded_common(decoder_t *decoder, AVFrame *frame, void *u1, v
__dtmf_detect(ch, frame);
// locking deliberately ignored
if (mp->media_out)
ch->encoder->codec_options.amr.cmr = mp->media_out->u.amr.cmr;
input_func(ch->encoder, frame, h->packet_encoded, ch, mp);
discard:

@ -336,6 +336,13 @@ struct call_media {
struct codec_handler *dtmf_injector;
struct t38_gateway *t38_gateway;
struct codec_handler *t38_handler;
#ifdef WITH_TRANSCODING
union {
struct {
struct amr_cmr cmr;
} amr;
} u;
#endif
int ptime; // either from SDP or overridden

@ -57,6 +57,7 @@ static int avc_encoder_input(encoder_t *enc, AVFrame **frame);
static void avc_encoder_close(encoder_t *enc);
static int amr_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static void amr_encoder_got_packet(encoder_t *enc);
static int ilbc_decoder_input(decoder_t *dec, const str *data, GQueue *out);
static const char *dtmf_decoder_init(decoder_t *, const str *);
@ -90,6 +91,7 @@ static const codec_type_t codec_type_amr = {
.decoder_close = avc_decoder_close,
.encoder_init = avc_encoder_init,
.encoder_input = avc_encoder_input,
.encoder_got_packet = amr_encoder_got_packet,
.encoder_close = avc_encoder_close,
};
static const codec_type_t codec_type_dtmf = {
@ -1234,10 +1236,11 @@ int encoder_input_data(encoder_t *enc, AVFrame *frame,
return -1;
if (enc->avpkt.size) {
//av_write_frame(output->fmtctx, &output->avpkt);
if (enc->def->codec_type->encoder_got_packet)
enc->def->codec_type->encoder_got_packet(enc);
callback(enc, u1, u2);
//output->fifo_pts += output->frame->nb_samples;
enc->mux_dts = enc->avpkt.dts + 1; // min next expected dts
av_packet_unref(&enc->avpkt);
@ -1645,7 +1648,10 @@ static int amr_decoder_input(decoder_t *dec, const str *data, GQueue *out) {
err = "no CMR";
if (bitstr_shift_ret(&d, 4, &cmr))
goto err;
// XXX handle CMR?
unsigned int cmr_int = cmr_chr[0] >> 4;
if (cmr_int != 15)
decoder_event(dec, CE_AMR_CMR_RECV, GUINT_TO_POINTER(cmr_int));
if (dec->codec_options.amr.octet_aligned) {
if (bitstr_shift(&d, 4))
@ -1746,6 +1752,24 @@ err:
return -1;
}
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;
unsigned int cmr = enc->codec_options.amr.cmr.cmr_in;
if (cmr >= AMR_FT_TYPES)
return;
// ignore CMR for invalid modes
if (enc->codec_options.amr.mode_set && !(enc->codec_options.amr.mode_set & (1 << cmr)))
return;
int req_br = enc->codec_options.amr.bitrates[cmr];
if (!req_br)
return;
enc->u.avc.avcctx->bit_rate = req_br;
}
static void amr_encoder_got_packet(encoder_t *enc) {
amr_encoder_mode_change(enc);
}
static int packetizer_amr(AVPacket *pkt, GString *buf, str *output, encoder_t *enc) {
assert(pkt->size >= 1);

@ -81,9 +81,15 @@ struct codec_type_s {
const char *(*encoder_init)(encoder_t *, const str *);
int (*encoder_input)(encoder_t *, AVFrame **);
void (*encoder_got_packet)(encoder_t *);
void (*encoder_close)(encoder_t *);
};
struct amr_cmr {
struct timeval cmr_in_ts;
unsigned int cmr_in;
};
union codec_options_u {
struct {
int interleaving;
@ -94,6 +100,8 @@ union codec_options_u {
const unsigned int *bits_per_frame;
const unsigned int *bitrates;
struct amr_cmr cmr; // input from external calling code
} amr;
};
@ -145,7 +153,7 @@ struct resample_s {
};
enum codec_event {
CE_DUMMY = -1,
CE_AMR_CMR_RECV,
};
struct decoder_s {
@ -191,6 +199,12 @@ struct encoder_s {
struct {
AVCodec *codec;
AVCodecContext *avcctx;
union {
struct {
struct timeval cmr_in_ts; // used internally
} amr;
} u;
} avc;
#ifdef HAVE_BCG729
bcg729EncoderChannelContextStruct *bcg729;

Loading…
Cancel
Save