|
|
|
@ -175,6 +175,7 @@ struct silence_event {
|
|
|
|
uint64_t start;
|
|
|
|
uint64_t start;
|
|
|
|
uint64_t end;
|
|
|
|
uint64_t end;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
TYPED_GQUEUE(silence_event, struct silence_event)
|
|
|
|
|
|
|
|
|
|
|
|
struct codec_ssrc_handler {
|
|
|
|
struct codec_ssrc_handler {
|
|
|
|
struct ssrc_entry h; // must be first
|
|
|
|
struct ssrc_entry h; // must be first
|
|
|
|
@ -200,7 +201,7 @@ struct codec_ssrc_handler {
|
|
|
|
struct dtmf_event dtmf_state; // state tracker for DTMF actions
|
|
|
|
struct dtmf_event dtmf_state; // state tracker for DTMF actions
|
|
|
|
|
|
|
|
|
|
|
|
// silence detection
|
|
|
|
// silence detection
|
|
|
|
GQueue silence_events;
|
|
|
|
silence_event_q silence_events;
|
|
|
|
|
|
|
|
|
|
|
|
// DTMF audio suppression
|
|
|
|
// DTMF audio suppression
|
|
|
|
unsigned long dtmf_start_ts;
|
|
|
|
unsigned long dtmf_start_ts;
|
|
|
|
@ -3665,14 +3666,14 @@ void codec_handlers_stop(codec_handlers_q *q, struct call_media *sink) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void silence_event_free(void *p) {
|
|
|
|
static void silence_event_free(struct silence_event *p) {
|
|
|
|
g_slice_free1(sizeof(struct silence_event), p);
|
|
|
|
g_slice_free1(sizeof(*p), p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define __silence_detect_type(type) \
|
|
|
|
#define __silence_detect_type(type) \
|
|
|
|
static void __silence_detect_ ## type(struct codec_ssrc_handler *ch, AVFrame *frame, type thres) { \
|
|
|
|
static void __silence_detect_ ## type(struct codec_ssrc_handler *ch, AVFrame *frame, type thres) { \
|
|
|
|
type *s = (void *) frame->data[0]; \
|
|
|
|
type *s = (void *) frame->data[0]; \
|
|
|
|
struct silence_event *last = g_queue_peek_tail(&ch->silence_events); \
|
|
|
|
struct silence_event *last = t_queue_peek_tail(&ch->silence_events); \
|
|
|
|
\
|
|
|
|
\
|
|
|
|
if (last && last->end) /* last event finished? */ \
|
|
|
|
if (last && last->end) /* last event finished? */ \
|
|
|
|
last = NULL; \
|
|
|
|
last = NULL; \
|
|
|
|
@ -3684,7 +3685,7 @@ static void __silence_detect_ ## type(struct codec_ssrc_handler *ch, AVFrame *fr
|
|
|
|
/* new event */ \
|
|
|
|
/* new event */ \
|
|
|
|
last = g_slice_alloc0(sizeof(*last)); \
|
|
|
|
last = g_slice_alloc0(sizeof(*last)); \
|
|
|
|
last->start = frame->pts + i; \
|
|
|
|
last->start = frame->pts + i; \
|
|
|
|
g_queue_push_tail(&ch->silence_events, last); \
|
|
|
|
t_queue_push_tail(&ch->silence_events, last); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
else { \
|
|
|
|
else { \
|
|
|
|
@ -3726,11 +3727,11 @@ static void __silence_detect(struct codec_ssrc_handler *ch, AVFrame *frame) {
|
|
|
|
frame->format);
|
|
|
|
frame->format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static int is_silence_event(str *inout, GQueue *events, uint64_t pts, uint64_t duration) {
|
|
|
|
static int is_silence_event(str *inout, silence_event_q *events, uint64_t pts, uint64_t duration) {
|
|
|
|
uint64_t end = pts + duration;
|
|
|
|
uint64_t end = pts + duration;
|
|
|
|
|
|
|
|
|
|
|
|
while (events->length) {
|
|
|
|
while (events->length) {
|
|
|
|
struct silence_event *first = g_queue_peek_head(events);
|
|
|
|
struct silence_event *first = t_queue_peek_head(events);
|
|
|
|
if (first->start > pts) // future event
|
|
|
|
if (first->start > pts) // future event
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
if (!first->end) // ongoing event
|
|
|
|
if (!first->end) // ongoing event
|
|
|
|
@ -3738,7 +3739,7 @@ static int is_silence_event(str *inout, GQueue *events, uint64_t pts, uint64_t d
|
|
|
|
if (first->end > end) // event finished with end in the future
|
|
|
|
if (first->end > end) // event finished with end in the future
|
|
|
|
goto silence;
|
|
|
|
goto silence;
|
|
|
|
// event has ended: remove it
|
|
|
|
// event has ended: remove it
|
|
|
|
g_queue_pop_head(events);
|
|
|
|
t_queue_pop_head(events);
|
|
|
|
// does the event fill the entire span?
|
|
|
|
// does the event fill the entire span?
|
|
|
|
if (first->end == end) {
|
|
|
|
if (first->end == end) {
|
|
|
|
silence_event_free(first);
|
|
|
|
silence_event_free(first);
|
|
|
|
@ -3917,7 +3918,7 @@ static void __free_ssrc_handler(void *chp) {
|
|
|
|
dtmf_rx_free(ch->dtmf_dsp);
|
|
|
|
dtmf_rx_free(ch->dtmf_dsp);
|
|
|
|
resample_shutdown(&ch->dtmf_resampler);
|
|
|
|
resample_shutdown(&ch->dtmf_resampler);
|
|
|
|
t_queue_clear_full(&ch->dtmf_events, dtmf_event_free);
|
|
|
|
t_queue_clear_full(&ch->dtmf_events, dtmf_event_free);
|
|
|
|
g_queue_clear_full(&ch->silence_events, silence_event_free);
|
|
|
|
t_queue_clear_full(&ch->silence_events, silence_event_free);
|
|
|
|
dtx_buffer_stop(&ch->dtx_buffer);
|
|
|
|
dtx_buffer_stop(&ch->dtx_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|