TT#136957 refactor DTMF event tracking into a list

Change-Id: I09aec46cad4cbb92aab67b7e9158d4d1598df186
pull/1430/head
Richard Fuchs 4 years ago
parent 3a90f44383
commit c794c00efa

@ -49,6 +49,7 @@
#include "t38.h"
#include "mqtt.h"
#include "janus.h"
#include "dtmf.h"
struct iterator_helper {
@ -3442,6 +3443,8 @@ void call_media_free(struct call_media **mdp) {
g_queue_clear_full(&md->sdp_attributes, free);
mutex_destroy(&md->dtmf_lock);
g_slice_free1(sizeof(*md), md);
g_queue_clear_full(&md->dtmf_recv, dtmf_event_free);
mutex_destroy(&md->dtmf_lock);
*mdp = NULL;
}

@ -2511,7 +2511,9 @@ static void delay_frame_manipulate(struct delay_frame *dframe) {
AVFrame *frame = dframe->frame;
if (is_in_dtmf_event(media, dframe->ts, frame->sample_rate, media->buffer_delay, media->buffer_delay)) {
if (is_in_dtmf_event(&media->dtmf_recv, dframe->ts, frame->sample_rate, media->buffer_delay,
media->buffer_delay))
{
struct call_monologue *ml = media->monologue;
enum block_dtmf_mode mode = dtmf_get_block_mode(dframe->mp.call, ml);
@ -2558,7 +2560,9 @@ static void delay_packet_manipulate(struct delay_frame *dframe) {
struct media_packet *mp = &dframe->mp;
if (is_in_dtmf_event(media, dframe->ts, dframe->clockrate, media->buffer_delay, media->buffer_delay)) {
if (is_in_dtmf_event(&media->dtmf_recv, dframe->ts, dframe->clockrate, media->buffer_delay,
media->buffer_delay))
{
// is this a DTMF event packet?
if (!dframe->handler->source_pt.codec_def || !dframe->handler->source_pt.codec_def->dtmf)
return;

@ -125,14 +125,16 @@ bool dtmf_do_logging(void) {
return false;
}
// media->dtmf_lock must be held
static void dtmf_end_event(struct call_media *media, unsigned int event, unsigned int volume,
unsigned int duration, const endpoint_t *fsin, int clockrate, bool rfc_event, uint64_t ts)
{
if (!clockrate)
clockrate = 8000;
media->dtmf_code = 0;
media->dtmf_end = ts;
struct dtmf_event *ev = g_slice_alloc0(sizeof(*ev));
*ev = (struct dtmf_event) { .code = 0, .ts = ts, .volume = 0 };
g_queue_push_tail(&media->dtmf_recv, ev);
if (!dtmf_do_logging())
return;
@ -186,6 +188,7 @@ static void dtmf_trigger_unset(struct call *c, void *mlp) {
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_check_trigger(struct call_media *media, char event, uint64_t ts, int clockrate) {
struct call_monologue *ml = media->monologue;
@ -198,8 +201,10 @@ static void dtmf_check_trigger(struct call_media *media, char event, uint64_t ts
return;
// check delay from previous event
if (media->dtmf_start) {
uint32_t ts_diff = ts - media->dtmf_start;
// dtmf_lock already held
struct dtmf_event *last_ev = g_queue_peek_tail(&media->dtmf_recv);
if (last_ev) {
uint32_t ts_diff = ts - last_ev->ts;
uint64_t ts_diff_ms = ts_diff * 1000 / clockrate;
if (ts_diff_ms > rtpe_config.dtmf_digit_delay) {
// delay too long: restart event trigger
@ -259,8 +264,10 @@ static void dtmf_check_trigger(struct call_media *media, char event, uint64_t ts
ml->dtmf_trigger_match = 0;
}
static void dtmf_code_event(struct call_media *media, char event, uint64_t ts, int clockrate) {
if (media->dtmf_code == event) // old/ongoing event
// media->dtmf_lock must be held
static void dtmf_code_event(struct call_media *media, char event, uint64_t ts, int clockrate, int volume) {
struct dtmf_event *ev = g_queue_peek_tail(&media->dtmf_recv);
if (ev && ev->code == event)
return;
// start of new event
@ -268,41 +275,61 @@ static void dtmf_code_event(struct call_media *media, char event, uint64_t ts, i
// check trigger before setting new dtmf_start
dtmf_check_trigger(media, event, ts, clockrate);
media->dtmf_code = event;
media->dtmf_start = ts;
media->dtmf_end = 0;
media->dtmf_event_state = 0;
ev = g_slice_alloc0(sizeof(*ev));
*ev = (struct dtmf_event) { .code = event, .ts = ts, .volume = volume };
g_queue_push_tail(&media->dtmf_recv, ev);
mutex_unlock(&media->dtmf_lock);
}
bool is_in_dtmf_event(struct call_media *media, uint32_t ts, int clockrate, unsigned int head,
bool is_in_dtmf_event(GQueue *events, uint32_t ts, int clockrate, unsigned int head,
unsigned int trail)
{
if (!clockrate)
clockrate = 8000;
uint32_t cutoff = clockrate * 10;
uint32_t neg = ~(clockrate * 100);
uint32_t start_ts = ts + head * clockrate / 1000;
uint32_t end_ts = ts - trail * clockrate / 1000;
if (!media->dtmf_start)
return false;
if (media->dtmf_code) {
// active event. is it current?
uint32_t start_diff = start_ts - media->dtmf_start;
if (start_diff > clockrate * 10)
return false; // outdated start TS
}
else {
// event has already ended. did it just end now?
uint32_t end_diff = media->dtmf_end - end_ts;
if (end_diff > clockrate * 10)
return false; // bad or old end TS
// go backwards through our list of DTMF events
for (GList *l = events->tail; l; l = l->prev) {
struct dtmf_event *ev = l->data;
uint32_t ts = ev->ts; // truncate to 32 bits
if (ev->code) {
// start event: check TS against our shifted start TS.
// start_ts must be larger than ts, but not much larger.
uint32_t start_diff = start_ts - ts;
// much too large? that means start_ts < ts. keep looking, we're close.
if (start_diff >= neg)
continue;
// diff >= 0 and less than 10 seconds? that's a match.
if (start_diff <= cutoff)
return true;
// anything else is a bad/outdated TS. stop.
break;
}
else {
// stop event: check TS against our shifted end TS.
uint32_t end_diff = end_ts - ts;
if (end_diff >= neg)
continue;
if (end_diff == 0) // for end events, we wait until after the end
continue;
if (end_diff <= cutoff)
return false;
break;
}
}
return true;
return false;
}
// media->dtmf_lock must be held
int dtmf_event_packet(struct media_packet *mp, str *payload, int clockrate, uint64_t ts) {
struct telephone_event_payload *dtmf;
if (payload->len < sizeof(*dtmf)) {
@ -315,7 +342,7 @@ int dtmf_event_packet(struct media_packet *mp, str *payload, int clockrate, uint
dtmf->event, dtmf->volume, dtmf->end, ntohs(dtmf->duration));
if (!dtmf->end) {
dtmf_code_event(mp->media, dtmf_code_to_char(dtmf->event), ts, clockrate);
dtmf_code_event(mp->media, dtmf_code_to_char(dtmf->event), ts, clockrate, dtmf->volume);
return 0;
}
@ -350,6 +377,8 @@ void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_e
unsigned int duration = cur_event.ts - new_event->ts;
LOCK(&media->dtmf_lock);
if (end_event) {
ilog(LOG_DEBUG, "DTMF DSP end event: event %u, volume %u, duration %u",
cur_event.code, cur_event.volume, duration);
@ -362,7 +391,7 @@ void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_e
new_event->code, new_event->volume, duration);
int code = dtmf_code_from_char(new_event->code); // for validation
if (code != -1)
dtmf_code_event(media, (char) new_event->code, ts, clockrate);
dtmf_code_event(media, (char) new_event->code, ts, clockrate, new_event->volume);
}
}

@ -405,10 +405,10 @@ struct call_media {
mutex_t dtmf_lock;
unsigned long dtmf_ts; // TS of last processed end event
uint32_t dtmf_start;
char dtmf_code;
uint32_t dtmf_end;
// lists are append-only
GQueue dtmf_recv;
unsigned int dtmf_event_state;
#ifdef WITH_TRANSCODING
union {
struct {

@ -16,7 +16,7 @@ struct call_monologue;
struct dtmf_event {
int code;
int code; // char for start, zero for end
int volume;
uint64_t ts;
};
@ -35,6 +35,6 @@ void dtmf_dsp_event(const struct dtmf_event *new_event, struct dtmf_event *cur_e
enum block_dtmf_mode dtmf_get_block_mode(struct call *call, struct call_monologue *ml);
bool is_pcm_dtmf_block_mode(enum block_dtmf_mode mode);
bool is_dtmf_replace_mode(enum block_dtmf_mode mode);
bool is_in_dtmf_event(struct call_media *, uint32_t ts, int clockrate, unsigned int head, unsigned int trail);
bool is_in_dtmf_event(GQueue *, uint32_t ts, int clockrate, unsigned int head, unsigned int trail);
#endif

Loading…
Cancel
Save