From b88521bab34a870a3a765706fc048456a81e7aa9 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 8 Dec 2021 12:48:17 -0500 Subject: [PATCH] TT#14008 eliminate duplicate DTMF reports when forking media With multiple media subscriptions, codec handlers are called consecutively, once for each forwarding chain, leading to DTMF events reported multiple times. The DTMF trigger must therefore keep track of the state in the upper media object, not in the codec handlers. Change-Id: I9ceaf406e093f25b7c037a325a0f2a7a91954922 (cherry picked from commit 2ff1a6afb2fcd56dcfc0b4206561e9d78ca16db4) --- daemon/call.c | 2 ++ daemon/codec.c | 25 ++++++++++++++----------- include/call.h | 4 ++++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/daemon/call.c b/daemon/call.c index fdcae5fc9..24b110a8d 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -809,6 +809,7 @@ struct call_media *call_media_new(struct call *call) { med = uid_slice_alloc0(med, &call->medias); med->call = call; codec_store_init(&med->codecs, med); + mutex_init(&med->dtmf_lock); return med; } @@ -3316,6 +3317,7 @@ void call_media_free(struct call_media **mdp) { codec_handler_free(&md->t38_handler); t38_gateway_put(&md->t38_gateway); g_queue_clear_full(&md->sdp_attributes, free); + mutex_destroy(&md->dtmf_lock); g_slice_free1(sizeof(*md), md); *mdp = NULL; } diff --git a/daemon/codec.c b/daemon/codec.c index a716deed8..a04b5bff2 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -128,7 +128,6 @@ struct codec_ssrc_handler { int bytes_per_packet; unsigned long first_ts; // for output TS scaling unsigned long last_ts; // to detect input lag and handle lost packets - unsigned long ts_in; // for DTMF dupe detection struct timeval first_send; unsigned long first_send_ts; long output_skew; @@ -1735,17 +1734,21 @@ static struct codec_handler *__input_handler(struct codec_handler *h, struct med static int packet_dtmf(struct codec_ssrc_handler *ch, struct codec_ssrc_handler *input_ch, struct transcode_packet *packet, struct media_packet *mp) { - if (ch->ts_in != packet->ts) { // ignore already processed events - int ret = dtmf_event(mp, packet->payload, ch->encoder_format.clockrate); - if (G_UNLIKELY(ret == -1)) // error - return -1; - if (ret == 1) { - // END event - ch->ts_in = packet->ts; - input_ch->dtmf_start_ts = 0; + { + LOCK(&mp->media->dtmf_lock); + + if (mp->media->dtmf_ts != packet->ts) { // ignore already processed events + int ret = dtmf_event(mp, packet->payload, ch->encoder_format.clockrate); + if (G_UNLIKELY(ret == -1)) // error + return -1; + if (ret == 1) { + // END event + mp->media->dtmf_ts = packet->ts; + input_ch->dtmf_start_ts = 0; + } + else + input_ch->dtmf_start_ts = packet->ts ? packet->ts : 1; } - else - input_ch->dtmf_start_ts = packet->ts ? packet->ts : 1; } int ret = 0; diff --git a/include/call.h b/include/call.h index 7fa6c1ff9..191f87a91 100644 --- a/include/call.h +++ b/include/call.h @@ -378,6 +378,10 @@ struct call_media { //struct codec_handler *dtmf_injector; struct t38_gateway *t38_gateway; struct codec_handler *t38_handler; + + mutex_t dtmf_lock; + unsigned long dtmf_ts; // TS of last processed end event + #ifdef WITH_TRANSCODING union { struct {