From 2d1933633a4780dbf1572f6e7653ee57979131c9 Mon Sep 17 00:00:00 2001 From: Richard Fuchs <rfuchs@sipwise.com> Date: Tue, 15 Apr 2025 14:14:23 -0400 Subject: [PATCH] MT#55283 remember DTMF start TS In case stray audio is receveived before the DTMF event is fully finished, retain the internal state from the beginning of the event to make sure that the output is consistent. This fixes both DTMF timestamps jumping during the end event, and audio timestamps being off after the end event. Closes #1929 Change-Id: I4e675b15153e35a8d1546b947e4b82879c1577b4 --- daemon/codec.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index f94cf8c42..c03e34e6f 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -220,7 +220,7 @@ struct codec_ssrc_handler { dtmf_rx_state_t *dtmf_dsp; resample_t dtmf_resampler; format_t dtmf_format; - uint64_t dtmf_ts, last_dtmf_event_ts; + uint64_t dtmf_ts, last_dtmf_event_ts, dtmf_out_ts; dtmf_event_q dtmf_events; struct dtmf_event dtmf_event; // for replacing PCM with DTMF event struct dtmf_event dtmf_state; // state tracker for DTMF actions @@ -2515,19 +2515,21 @@ static int codec_add_dtmf_packet(struct codec_ssrc_handler *ch, struct codec_ssr // this is a new event ch->dtmf_ts = packet->ts; // start TS ch->last_dtmf_event_ts = 0; // last DTMF event duration - } - unsigned long ts = fraction_divl(output_ch->encoder->next_pts, &output_ch->encoder->clockrate_fact); - // roll back TS to start of event - ts -= ch->last_dtmf_event_ts; - // adjust to output RTP TS - unsigned long packet_ts = ts + output_ch->csch.first_ts; + unsigned long ts = fraction_divl(output_ch->encoder->next_pts, &output_ch->encoder->clockrate_fact); + // roll back TS to start of event + ts -= ch->last_dtmf_event_ts; + // adjust to output RTP TS + unsigned long packet_ts = ts + output_ch->csch.first_ts; + ch->dtmf_out_ts = packet_ts; - ilogs(transcoding, LOG_DEBUG, "Scaling DTMF packet timestamp and duration: TS %lu -> %lu " - "(%u -> %u)", - packet->ts, packet_ts, - h->source_pt.clock_rate, h->dest_pt.clock_rate); - packet->ts = packet_ts; + ilogs(transcoding, LOG_DEBUG, "Scaling DTMF packet timestamp and duration: TS %lu -> %lu " + "(%u -> %u)", + packet->ts, packet_ts, + h->source_pt.clock_rate, h->dest_pt.clock_rate); + } + + packet->ts = ch->dtmf_out_ts; if (packet->payload->len >= sizeof(struct telephone_event_payload)) { struct telephone_event_payload *dtmf = (void *) packet->payload->s; @@ -2541,10 +2543,16 @@ static int codec_add_dtmf_packet(struct codec_ssrc_handler *ch, struct codec_ssr ch->dtmf_first_duration = duration; ts_delay = duration - ch->dtmf_first_duration; - // shift forward our output RTP TS - output_ch->encoder->next_pts = fraction_multl(ts + duration, &output_ch->encoder->clockrate_fact); - output_ch->encoder->packet_pts += fraction_multl(duration - ch->last_dtmf_event_ts, &output_ch->encoder->clockrate_fact); - ch->last_dtmf_event_ts = duration; + if (ch->last_dtmf_event_ts != duration) { + // shift forward our output RTP TS + output_ch->encoder->next_pts + = fraction_multl(packet->ts - output_ch->csch.first_ts + duration, + &output_ch->encoder->clockrate_fact); + output_ch->encoder->packet_pts + += fraction_multl(duration - ch->last_dtmf_event_ts, + &output_ch->encoder->clockrate_fact); + ch->last_dtmf_event_ts = duration; + } } payload_type = h->dtmf_payload_type; if (payload_type == -1)