|
|
|
@ -36,7 +36,7 @@ struct mqtt_timer { |
|
|
|
typedef void (*raw_input_func_t)(struct media_packet *mp, unsigned int); |
|
|
|
|
|
|
|
static void __buffer_delay_raw(struct delay_buffer *dbuf, |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate); |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate, uint32_t); |
|
|
|
|
|
|
|
|
|
|
|
static codec_handler_func handler_func_passthrough; |
|
|
|
@ -133,6 +133,7 @@ struct delay_frame { |
|
|
|
AVFrame *frame; |
|
|
|
struct media_packet mp; |
|
|
|
unsigned int clockrate; |
|
|
|
uint32_t ts; |
|
|
|
encoder_input_func_t encoder_func; |
|
|
|
raw_input_func_t raw_func; |
|
|
|
struct codec_handler *handler; |
|
|
|
@ -984,6 +985,9 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
AUTO_CLEANUP(GHashTable *output_transcoders, __g_hash_table_destroy) |
|
|
|
= g_hash_table_new(g_direct_hash, g_direct_equal); |
|
|
|
|
|
|
|
enum block_dtmf_mode dtmf_block_mode = dtmf_get_block_mode(NULL, receiver->monologue); |
|
|
|
bool do_pcm_dtmf_blocking = is_pcm_dtmf_block_mode(dtmf_block_mode); |
|
|
|
|
|
|
|
|
|
|
|
for (GList *l = receiver->codecs.codec_prefs.head; l; ) { |
|
|
|
struct rtp_payload_type *pt = l->data; |
|
|
|
@ -1052,6 +1056,10 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
sink_pt = pref_dest_codec; |
|
|
|
} |
|
|
|
|
|
|
|
// ignore DTMF sink if we're blocking DTMF in PCM replacement mode |
|
|
|
if (do_pcm_dtmf_blocking && sink_pt && sink_pt->codec_def && sink_pt->codec_def->dtmf) |
|
|
|
sink_pt = NULL; |
|
|
|
|
|
|
|
// still no output? pick the preferred sink codec |
|
|
|
if (!sink_pt) |
|
|
|
sink_pt = pref_dest_codec; |
|
|
|
@ -1098,6 +1106,15 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
if (receiver->monologue->detect_dtmf) |
|
|
|
pcm_dtmf_detect = true; |
|
|
|
|
|
|
|
// special mode for DTMF blocking |
|
|
|
if (do_pcm_dtmf_blocking) { |
|
|
|
sink_dtmf_pt = NULL; // always transcode DTMF to PCM |
|
|
|
|
|
|
|
// enable DSP if we expect DTMF to be carried as PCM |
|
|
|
if (!recv_dtmf_pt) |
|
|
|
pcm_dtmf_detect = true; |
|
|
|
} |
|
|
|
|
|
|
|
if (pcm_dtmf_detect) { |
|
|
|
if (sink_dtmf_pt) |
|
|
|
ilogs(codec, LOG_DEBUG, "Enabling PCM DTMF detection from " STR_FORMAT |
|
|
|
@ -1144,7 +1161,7 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink, |
|
|
|
// DTMF |
|
|
|
if (pcm_dtmf_detect) |
|
|
|
goto transcode; |
|
|
|
if (recv_dtmf_pt && recv_dtmf_pt->for_transcoding && !sink_dtmf_pt) { |
|
|
|
if (recv_dtmf_pt && (recv_dtmf_pt->for_transcoding || do_pcm_dtmf_blocking) && !sink_dtmf_pt) { |
|
|
|
ilogs(codec, LOG_DEBUG, "Transcoding DTMF events to PCM from " STR_FORMAT |
|
|
|
" to " STR_FORMAT, |
|
|
|
STR_FMT(&pt->encoding_with_params), |
|
|
|
@ -1410,12 +1427,14 @@ static int handler_func_passthrough(struct codec_handler *h, struct media_packet |
|
|
|
if (!handler_silence_block(h, mp)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
uint32_t ts = 0; |
|
|
|
if (mp->rtp) { |
|
|
|
codec_calc_jitter(mp->ssrc_in, ntohl(mp->rtp->timestamp), h->source_pt.clock_rate, &mp->tv); |
|
|
|
ts = ntohl(mp->rtp->timestamp); |
|
|
|
codec_calc_jitter(mp->ssrc_in, ts, h->source_pt.clock_rate, &mp->tv); |
|
|
|
codec_calc_lost(mp->ssrc_in, ntohs(mp->rtp->seq_num)); |
|
|
|
} |
|
|
|
|
|
|
|
__buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate); |
|
|
|
__buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate, ts); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -1842,7 +1861,7 @@ static int packet_dtmf_event(struct codec_ssrc_handler *ch, struct codec_ssrc_ha |
|
|
|
LOCK(&mp->media->dtmf_lock); |
|
|
|
|
|
|
|
if (mp->media->dtmf_ts != packet->ts) { // ignore already processed events |
|
|
|
int ret = dtmf_event_packet(mp, packet->payload, ch->encoder_format.clockrate); |
|
|
|
int ret = dtmf_event_packet(mp, packet->payload, ch->encoder_format.clockrate, packet->ts); |
|
|
|
if (G_UNLIKELY(ret == -1)) // error |
|
|
|
return -1; |
|
|
|
if (ret == 1) { |
|
|
|
@ -2074,8 +2093,10 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p |
|
|
|
if (!handler_silence_block(h, mp)) |
|
|
|
return 0; |
|
|
|
|
|
|
|
uint32_t ts = 0; |
|
|
|
if (mp->rtp) { |
|
|
|
codec_calc_jitter(mp->ssrc_in, ntohl(mp->rtp->timestamp), h->source_pt.clock_rate, &mp->tv); |
|
|
|
ts = ntohl(mp->rtp->timestamp); |
|
|
|
codec_calc_jitter(mp->ssrc_in, ts, h->source_pt.clock_rate, &mp->tv); |
|
|
|
codec_calc_lost(mp->ssrc_in, ntohs(mp->rtp->seq_num)); |
|
|
|
} |
|
|
|
|
|
|
|
@ -2085,7 +2106,7 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p |
|
|
|
|
|
|
|
// keep track of other stats here? |
|
|
|
|
|
|
|
__buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate); |
|
|
|
__buffer_delay_raw(h->delay_buffer, codec_add_raw_packet, mp, h->source_pt.clock_rate, ts); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
@ -2116,7 +2137,8 @@ void codec_add_dtmf_event(struct codec_ssrc_handler *ch, int code, int level, ui |
|
|
|
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", |
|
|
|
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); |
|
|
|
dtmf_dsp_event(&new_ev, &ch->dtmf_state, ch->handler->media, ch->handler->source_pt.clock_rate, |
|
|
|
ts + ch->first_ts); |
|
|
|
|
|
|
|
// add to queue if we're doing PCM -> DTMF event conversion |
|
|
|
if (ch->handler && ch->handler->dtmf_payload_type != -1) { |
|
|
|
@ -2203,7 +2225,7 @@ static int delay_frame_cmp(const void *A, const void *B, void *ptr) { |
|
|
|
|
|
|
|
// consumes frame |
|
|
|
static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_handler *ch, |
|
|
|
encoder_input_func_t input_func, AVFrame *frame, struct media_packet *mp) |
|
|
|
encoder_input_func_t input_func, AVFrame *frame, struct media_packet *mp, uint32_t ts) |
|
|
|
{ |
|
|
|
if (__buffer_delay_do_direct(dbuf)) { |
|
|
|
// input now |
|
|
|
@ -2215,6 +2237,7 @@ static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_ha |
|
|
|
struct delay_frame *dframe = g_slice_alloc0(sizeof(*dframe)); |
|
|
|
dframe->frame = frame; |
|
|
|
dframe->encoder_func = input_func; |
|
|
|
dframe->ts = ts; |
|
|
|
dframe->ch = obj_get(&ch->h); |
|
|
|
media_packet_copy(&dframe->mp, mp); |
|
|
|
|
|
|
|
@ -2226,7 +2249,7 @@ static void __buffer_delay_frame(struct delay_buffer *dbuf, struct codec_ssrc_ha |
|
|
|
} |
|
|
|
|
|
|
|
static void __buffer_delay_raw(struct delay_buffer *dbuf, |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate) |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate, uint32_t ts) |
|
|
|
{ |
|
|
|
if (__buffer_delay_do_direct(dbuf)) { |
|
|
|
// direct passthrough |
|
|
|
@ -2349,6 +2372,25 @@ static void dtx_buffer_stop(struct dtx_buffer **dtxbp) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void delay_frame_manipulate(struct delay_frame *dframe) { |
|
|
|
struct call_media *media = dframe->mp.media; |
|
|
|
if (!media) |
|
|
|
return; |
|
|
|
|
|
|
|
AVFrame *frame = dframe->frame; |
|
|
|
|
|
|
|
if (is_in_dtmf_event(media, dframe->ts, frame->sample_rate, media->buffer_delay, media->buffer_delay)) { |
|
|
|
enum block_dtmf_mode mode = dtmf_get_block_mode(dframe->mp.call, media->monologue); |
|
|
|
|
|
|
|
switch (mode) { |
|
|
|
case BLOCK_DTMF_SILENCE: |
|
|
|
memset(frame->extended_data[0], 0, frame->linesize[0]); |
|
|
|
break; |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
static void __delay_frame_process(struct delay_buffer *dbuf, struct delay_frame *dframe) { |
|
|
|
if (dframe->mp.rtp) { |
|
|
|
// adjust output seq num. pushing packets into the delay buffer looks as if they |
|
|
|
@ -2361,7 +2403,8 @@ static void __delay_frame_process(struct delay_buffer *dbuf, struct delay_frame |
|
|
|
|
|
|
|
struct codec_ssrc_handler *csh = dframe->ch; |
|
|
|
|
|
|
|
if (csh && csh->handler && csh->encoder) { |
|
|
|
if (csh && csh->handler && csh->encoder && dframe->encoder_func) { |
|
|
|
delay_frame_manipulate(dframe); |
|
|
|
dframe->encoder_func(csh->encoder, dframe->frame, csh->handler->packet_encoded, |
|
|
|
csh, &dframe->mp); |
|
|
|
} |
|
|
|
@ -3224,7 +3267,8 @@ static int packet_decoded_common(decoder_t *decoder, AVFrame *frame, void *u1, v |
|
|
|
if (mp->media_out) |
|
|
|
ch->encoder->codec_options.amr.cmr = mp->media_out->u.amr.cmr; |
|
|
|
|
|
|
|
__buffer_delay_frame(h->delay_buffer, ch, input_func, frame, mp); |
|
|
|
uint32_t ts = mp->rtp ? ntohl(mp->rtp->timestamp) : frame->pts; |
|
|
|
__buffer_delay_frame(h->delay_buffer, ch, input_func, frame, mp, ts); |
|
|
|
frame = NULL; // consumed |
|
|
|
|
|
|
|
discard: |
|
|
|
@ -3294,7 +3338,7 @@ out: |
|
|
|
|
|
|
|
// dummy/stub |
|
|
|
static void __buffer_delay_raw(struct delay_buffer *dbuf, |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate) |
|
|
|
raw_input_func_t input_func, struct media_packet *mp, unsigned int clockrate, uint32_t ts) |
|
|
|
{ |
|
|
|
input_func(mp, clockrate); |
|
|
|
} |
|
|
|
|