From 0304e025fa123d1ed5126831d8467fb374cb358a Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 16 Mar 2023 14:18:08 -0400 Subject: [PATCH] MT#56861 support DTMF injection from DTMF This replicates the code to replace audio packets with injected DTMF events. Unfortunately the code paths between forwarding audio and processing/forwarding DTMF events is quite different, so some slight duplication is needed. Additionally the case of blocked DTMF + injected DTMF must be handled. Change-Id: Ieb576b4b6644c9b154ba4c6ebd48fe12ff08e1de --- daemon/codec.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index fc7fb0f30..93a9e696c 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -2164,11 +2164,76 @@ static int packet_dtmf(struct codec_ssrc_handler *ch, struct codec_ssrc_handler if (dtmf_event_processed == -1) return -1; - int ret = 0; enum block_dtmf_mode block_dtmf = dtmf_get_block_mode(mp->call, mp->media->monologue); - if (block_dtmf == BLOCK_DTMF_DROP) + bool do_blocking = block_dtmf == BLOCK_DTMF_DROP; + + if (packet->payload->len >= sizeof(struct telephone_event_payload)) { + struct telephone_event_payload *dtmf = (void *) packet->payload->s; + struct codec_handler *h = input_ch->handler; + // fudge up TS and duration values + uint64_t duration = h->source_pt.clock_rate * h->source_pt.ptime / 1000; + uint64_t ts = packet->ts + ntohs(dtmf->duration) - duration; + + // remember this as last "encoder" TS + atomic64_set(&mp->ssrc_in->last_ts, ts); + + // provide an uninitialised buffer as potential output storage for DTMF + char buf[sizeof(struct telephone_event_payload)]; + str ev_pl; + str_init_len(&ev_pl, buf, sizeof(buf)); + + int is_dtmf = dtmf_event_payload(&ev_pl, &ts, duration, + &input_ch->dtmf_event, &input_ch->dtmf_events); + if (is_dtmf) { + // generate appropriate transcode_packets + unsigned int copies = 1; + if (dtmf_event_processed == 1) // discard duplicate end packets + copies = 0; + else if (is_dtmf == 3) // end event + copies = 3; + + // fix up RTP header + struct rtp_header r; + r = *mp->rtp; + r.m_pt = h->dtmf_payload_type; + r.timestamp = htonl(ts); + + for (; copies > 0; copies--) { + struct transcode_packet *dup = g_slice_alloc(sizeof(*dup)); + *dup = *packet; + dup->payload = str_dup(&ev_pl); + dup->rtp = r; + dup->bypass_seq = 0; + dup->ts = ts; + if (is_dtmf == 1) + dup->marker = 1; + + int ret = 0; + + if (__buffer_dtx(input_ch->dtx_buffer, ch, input_ch, dup, mp, packet_dtmf_fwd)) + ret = 1; // consumed + else + ret = packet_dtmf_fwd(ch, input_ch, dup, mp); + + if (ret == 0) + __transcode_packet_free(dup); + } + + // discard the received event + do_blocking = true; + + + } + else if (!input_ch->dtmf_events.length) + mp->media->monologue->dtmf_injection_active = 0; + + } + + int ret = 0; + + if (do_blocking) { } else { // pass through