diff --git a/daemon/codec.c b/daemon/codec.c index f080dae0f..ddd8f2f92 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -167,7 +167,8 @@ struct codec_ssrc_handler { format_t dtmf_format; uint64_t dtmf_ts, last_dtmf_event_ts; GQueue dtmf_events; - struct dtmf_event dtmf_event; + struct dtmf_event dtmf_event; // for replacing PCM with DTMF event + struct dtmf_event dtmf_state; // state tracker for DTMF actions // silence detection GQueue silence_events; @@ -2097,11 +2098,17 @@ static void __dtmf_dsp_callback(void *ptr, int code, int level, int delay) { } void codec_add_dtmf_event(struct codec_ssrc_handler *ch, int code, int level, uint64_t ts) { - struct dtmf_event *ev = g_slice_alloc(sizeof(*ev)); - *ev = (struct dtmf_event) { .code = code, .volume = level, .ts = ts }; + struct dtmf_event new_ev = { .code = code, .volume = level, .ts = ts }; ilogs(transcoding, LOG_DEBUG, "DTMF event state change: code %i, volume %i, TS %lu", - ev->code, ev->volume, (unsigned long) ts); - g_queue_push_tail(&ch->dtmf_events, ev); + new_ev.code, new_ev.volume, (unsigned long) ts); + dtmf_dsp_event(&new_ev, &ch->dtmf_state, ch->handler->media, ch->handler->source_pt.clock_rate); + + // add to queue if we're doing PCM -> DTMF event conversion + if (ch->handler && ch->handler->dtmf_payload_type != -1) { + struct dtmf_event *ev = g_slice_alloc(sizeof(*ev)); + *ev = new_ev; + g_queue_push_tail(&ch->dtmf_events, ev); + } } uint64_t codec_last_dtmf_event(struct codec_ssrc_handler *ch) { diff --git a/daemon/dtmf.c b/daemon/dtmf.c index f79412e5c..450c21f3b 100644 --- a/daemon/dtmf.c +++ b/daemon/dtmf.c @@ -21,6 +21,15 @@ void dtmf_init(void) { } } +static unsigned int dtmf_volume_from_dsp(int vol) { + if (vol > 0) + return 0; + else if (vol >= -63) + return -1 * vol; + else + return 63; +} + static void dtmf_bencode_and_notify(struct call_media *media, unsigned int event, unsigned int volume, unsigned int duration, const endpoint_t *fsin, int clockrate) { @@ -152,6 +161,36 @@ int dtmf_event_packet(struct media_packet *mp, str *payload, int clockrate) { return 1; } +void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_event_p, + struct call_media *media, int clockrate) +{ + // update state tracker regardless of outcome + struct dtmf_event cur_event = *cur_event_p; + *cur_event_p = *new_event; + + if (!media) + return; + // we only care for "end" events + if (cur_event.code == 0 || new_event->code != 0) + return; + if (!media->streams.length) + return; + + // we don't have a real fsin so just use the stream address + struct packet_stream *ps = media->streams.head->data; + + unsigned int duration = cur_event.ts - new_event->ts; + + ilog(LOG_DEBUG, "DTMF DSP end event: event %u, volume %u, duration %u", + cur_event.code, cur_event.volume, duration); + + if (!dtmf_do_logging()) + return; + + dtmf_end_event(media, dtmf_code_from_char(cur_event.code), dtmf_volume_from_dsp(cur_event.volume), + duration, &ps->endpoint, clockrate, false); +} + void dtmf_event_free(void *e) { g_slice_free1(sizeof(struct dtmf_event), e); } @@ -198,12 +237,7 @@ int dtmf_event_payload(str *buf, uint64_t *pts, uint64_t duration, struct dtmf_e ZERO(*ev_pt); ev_pt->event = dtmf_code; - if (cur_event->volume > 0) - ev_pt->volume = 0; - else if (cur_event->volume >= -63) - ev_pt->volume = -1 * cur_event->volume; - else - ev_pt->volume = 63; + ev_pt->volume = dtmf_volume_from_dsp(cur_event->volume); ev_pt->end = (ret == 3) ? 1 : 0; ev_pt->duration = htons(*pts - cur_event->ts + duration); diff --git a/include/dtmf.h b/include/dtmf.h index 8140ea561..23bcf9164 100644 --- a/include/dtmf.h +++ b/include/dtmf.h @@ -27,5 +27,7 @@ int dtmf_code_from_char(char); const char *dtmf_inject(struct call_media *media, int code, int volume, int duration, int pause, struct call_media *sink); bool dtmf_do_logging(void); +void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_event, + struct call_media *media, int clockrate); #endif