TT#122401 support multiple DTX method per codec

Change-Id: I775d56e675255b3dca4227779d1146d8c8806f06
rfuchs/1283
Richard Fuchs 5 years ago
parent 11988524ab
commit dc38a0e88e

@ -2642,7 +2642,7 @@ static void __dtx_free(void *p) {
mutex_destroy(&dtxb->lock);
}
static void __dtx_setup(struct codec_ssrc_handler *ch) {
if (!ch->handler->source_pt.codec_def->dtx || ch->dtx_buffer)
if (!decoder_has_dtx(ch->decoder) || ch->dtx_buffer)
return;
if (!rtpe_config.dtx_delay)

@ -106,6 +106,13 @@ static const codec_type_t codec_type_cn = {
.decoder_close = avc_decoder_close,
};
static const dtx_method_t dtx_method_silence = {
.do_dtx = generic_silence_dtx,
};
static const dtx_method_t dtx_method_amr = {
.do_dtx = amr_dtx,
};
#ifdef HAVE_BCG729
static packetizer_f packetizer_g729; // aggregate some frames into packets
@ -142,7 +149,9 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "PCMU",
@ -155,7 +164,9 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "G723",
@ -168,7 +179,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "G722",
@ -181,7 +194,9 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 8,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "QCELP",
@ -191,7 +206,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
#ifndef HAVE_BCG729
{
@ -204,7 +221,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "G729a",
@ -216,7 +235,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
#else
{
@ -231,7 +252,9 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 1, // 10 ms frame has 80 samples and encodes as (max) 10 bytes = 80 bits
.media_type = MT_AUDIO,
.codec_type = &codec_type_bcg729,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "G729a",
@ -244,7 +267,9 @@ static codec_def_t __codec_defs[] = {
.bits_per_sample = 1, // 10 ms frame has 80 samples and encodes as (max) 10 bytes = 80 bits
.media_type = MT_AUDIO,
.codec_type = &codec_type_bcg729,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
#endif
{
@ -257,7 +282,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "GSM",
@ -269,7 +296,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "iLBC",
@ -299,7 +328,9 @@ static codec_def_t __codec_defs[] = {
.codec_type = &codec_type_avcodec,
.init = opus_init,
.set_enc_options = opus_set_enc_options,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "vorbis",
@ -310,7 +341,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "ac3",
@ -319,7 +352,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "eac3",
@ -328,7 +363,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "ATRAC3",
@ -337,7 +374,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "ATRAC-X",
@ -346,7 +385,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0)
{
@ -356,7 +397,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "EVRC0",
@ -366,7 +409,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "EVRC1",
@ -376,7 +421,9 @@ static codec_def_t __codec_defs[] = {
.packetizer = packetizer_passthrough,
.media_type = MT_AUDIO,
.codec_type = &codec_type_avcodec,
.dtx = generic_silence_dtx,
.dtx_methods = {
[DTX_SILENCE] = &dtx_method_silence,
},
},
#endif
{
@ -395,7 +442,10 @@ static codec_def_t __codec_defs[] = {
.codec_type = &codec_type_amr,
.set_enc_options = amr_set_enc_options,
.set_dec_options = amr_set_dec_options,
.dtx = amr_dtx,
.dtx_methods = {
[DTX_NATIVE] = &dtx_method_amr,
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "AMR-WB",
@ -413,7 +463,10 @@ static codec_def_t __codec_defs[] = {
.codec_type = &codec_type_amr,
.set_enc_options = amr_set_enc_options,
.set_dec_options = amr_set_dec_options,
.dtx = amr_dtx,
.dtx_methods = {
[DTX_NATIVE] = &dtx_method_amr,
[DTX_SILENCE] = &dtx_method_silence,
},
},
{
.rtpname = "telephone-event",
@ -559,6 +612,15 @@ decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels,
else
ret->ptime = def->default_ptime;
// init with first supported DTX method
enum dtx_method dm = -1;
for (int i = 0; i < NUM_DTX_METHODS; i++) {
if (def->dtx_methods[i]) {
dm = i;
break;
}
}
err = def->codec_type->decoder_init(ret, fmtp, extra_opts);
if (err)
goto err;
@ -568,6 +630,8 @@ decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels,
ret->pts = (uint64_t) -1LL;
ret->rtp_ts = (unsigned long) -1L;
decoder_switch_dtx(ret, dm);
return ret;
err:
@ -579,6 +643,33 @@ err:
}
int decoder_switch_dtx(decoder_t *dec, enum dtx_method dm) {
if (dec->dtx.cleanup)
dec->dtx.cleanup(dec);
ZERO(dec->dtx);
unsigned int i = dm;
if (i >= NUM_DTX_METHODS)
return -1;
const dtx_method_t *dmp = dec->def->dtx_methods[i];
if (!dmp)
return -1;
dec->dtx = *dmp;
if (dmp->init) {
if (dmp->init(dec)) {
ilog(LOG_ERR, "Failed to initialise DTX (%u)", i);
decoder_switch_dtx(dec, -1);
return -1;
}
}
return 0;
}
gboolean decoder_has_dtx(decoder_t *dec) {
return dec->dtx.do_dtx == NULL ? FALSE : TRUE;
}
static void avc_decoder_close(decoder_t *dec) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
avcodec_free_context(&dec->u.avc.avcctx);
@ -597,6 +688,8 @@ void decoder_close(decoder_t *dec) {
if (dec->def && dec->def->codec_type && dec->def->codec_type->decoder_close)
dec->def->codec_type->decoder_close(dec);
decoder_switch_dtx(dec, -1);
resample_shutdown(&dec->resampler);
g_slice_free1(sizeof(*dec), dec);
}
@ -712,7 +805,7 @@ static int __decoder_input_data(decoder_t *dec, const str *data, unsigned long t
if (G_UNLIKELY(!dec))
return -1;
if (!data && !dec->def->dtx)
if (!data && !dec->dtx.do_dtx)
return 0;
ts *= dec->def->clockrate_mult;
@ -741,7 +834,7 @@ static int __decoder_input_data(decoder_t *dec, const str *data, unsigned long t
if (data)
dec->def->codec_type->decoder_input(dec, data, &frames);
else
dec->def->dtx(dec, &frames, ptime);
dec->dtx.do_dtx(dec, &frames, ptime);
AVFrame *frame;
int ret = 0;

@ -58,6 +58,7 @@ struct resample_s;
struct seq_packet_s;
struct rtp_payload_type;
union codec_options_u;
struct dtx_method_s;
typedef struct codec_type_s codec_type_t;
typedef struct decoder_s decoder_t;
@ -66,13 +67,13 @@ typedef struct format_s format_t;
typedef struct resample_s resample_t;
typedef struct seq_packet_s seq_packet_t;
typedef union codec_options_u codec_options_t;
typedef struct dtx_method_s dtx_method_t;
typedef int packetizer_f(AVPacket *, GString *, str *, encoder_t *);
typedef void format_init_f(struct rtp_payload_type *);
typedef void set_enc_options_f(encoder_t *, const str *, const str *);
typedef void set_dec_options_f(decoder_t *, const str *, const str *);
typedef int format_cmp_f(const struct rtp_payload_type *, const struct rtp_payload_type *);
typedef int decoder_dtx_f(decoder_t *, GQueue *, int);
@ -117,6 +118,13 @@ union codec_options_u {
} amr;
};
enum dtx_method {
DTX_NATIVE = 0,
DTX_SILENCE,
NUM_DTX_METHODS
};
struct codec_def_s {
const char * const rtpname;
int clockrate_mult;
@ -137,7 +145,7 @@ struct codec_def_s {
format_init_f *init;
set_enc_options_f *set_enc_options;
set_dec_options_f *set_dec_options;
decoder_dtx_f *dtx;
const dtx_method_t * const dtx_methods[NUM_DTX_METHODS];
// filled in by codeclib_init()
str rtpname_str;
@ -171,9 +179,16 @@ enum codec_event {
CE_AMR_SEND_CMR,
};
struct dtx_method_s {
int (*init)(decoder_t *);
void (*cleanup)(decoder_t *);
int (*do_dtx)(decoder_t *, GQueue *, int);
};
struct decoder_s {
const codec_def_t *def;
codec_options_t codec_options;
dtx_method_t dtx;
format_t in_format,
dec_out_format,
@ -281,6 +296,8 @@ decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels,
void decoder_close(decoder_t *dec);
int decoder_input_data(decoder_t *dec, const str *data, unsigned long ts,
int (*callback)(decoder_t *, AVFrame *, void *u1, void *u2), void *u1, void *u2);
gboolean decoder_has_dtx(decoder_t *);
int decoder_switch_dtx(decoder_t *dec, enum dtx_method);
int decoder_dtx(decoder_t *dec, unsigned long ts, int ptime,
int (*callback)(decoder_t *, AVFrame *, void *u1, void *u2), void *u1, void *u2);

Loading…
Cancel
Save