|
|
|
|
@ -1092,7 +1092,7 @@ bool codec_handlers_update(struct call_media *receiver, struct call_media *sink,
|
|
|
|
|
if (flags && flags->inject_dtmf)
|
|
|
|
|
sink->monologue->inject_dtmf = 1;
|
|
|
|
|
|
|
|
|
|
bool use_ssrc_passthrough = !!MEDIA_ISSET(receiver, ECHO);
|
|
|
|
|
bool use_ssrc_passthrough = MEDIA_ISSET(receiver, ECHO) || sink->monologue->inject_dtmf;
|
|
|
|
|
|
|
|
|
|
// do we have to force everything through the transcoding engine even if codecs match?
|
|
|
|
|
bool force_transcoding = do_pcm_dtmf_blocking || do_dtmf_blocking || use_audio_player;
|
|
|
|
|
@ -1307,8 +1307,8 @@ sink_pt_fixed:;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// force transcoding if we want DTMF injection
|
|
|
|
|
if (sink->monologue->inject_dtmf)
|
|
|
|
|
// force transcoding if we want DTMF injection and there's no DTMF PT
|
|
|
|
|
if (!sink_dtmf_pt && sink->monologue->inject_dtmf)
|
|
|
|
|
goto transcode;
|
|
|
|
|
|
|
|
|
|
// everything matches - we can do passthrough
|
|
|
|
|
@ -2399,13 +2399,66 @@ static int handler_func_passthrough_ssrc(struct codec_handler *h, struct media_p
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
// save original payload in case DTMF mangles it
|
|
|
|
|
str orig_raw = mp->raw;
|
|
|
|
|
|
|
|
|
|
// provide an uninitialised buffer as potential output storage for DTMF
|
|
|
|
|
char buf[sizeof(*mp->rtp) + sizeof(struct telephone_event_payload) + RTP_BUFFER_TAIL_ROOM];
|
|
|
|
|
|
|
|
|
|
// default function to return packets
|
|
|
|
|
void (*add_packet_fn)(struct media_packet *mp, unsigned int clockrate) = codec_add_raw_packet;
|
|
|
|
|
|
|
|
|
|
unsigned int duplicates = 0;
|
|
|
|
|
|
|
|
|
|
// check for DTMF injection
|
|
|
|
|
if (h->dtmf_payload_type != -1) {
|
|
|
|
|
struct codec_ssrc_handler *ch = get_ssrc(mp->ssrc_in->parent->h.ssrc, h->ssrc_hash);
|
|
|
|
|
uint64_t ts = ntohl(mp->rtp->timestamp);
|
|
|
|
|
|
|
|
|
|
str ev_pl = { .s = buf + sizeof(*mp->rtp) };
|
|
|
|
|
|
|
|
|
|
int is_dtmf = dtmf_event_payload(&ev_pl, &ts, h->source_pt.clock_rate * h->source_pt.ptime / 1000,
|
|
|
|
|
&ch->dtmf_event, &ch->dtmf_events);
|
|
|
|
|
if (is_dtmf) {
|
|
|
|
|
// fix up RTP header
|
|
|
|
|
struct rtp_header *r = (void *) buf;
|
|
|
|
|
*r = *mp->rtp;
|
|
|
|
|
r->m_pt = h->dtmf_payload_type;
|
|
|
|
|
r->timestamp = htonl(ts);
|
|
|
|
|
if (is_dtmf == 1)
|
|
|
|
|
r->m_pt |= 0x80;
|
|
|
|
|
else if (is_dtmf == 3) // end event
|
|
|
|
|
duplicates = 2;
|
|
|
|
|
mp->rtp = r;
|
|
|
|
|
mp->raw.s = buf;
|
|
|
|
|
mp->raw.len = ev_pl.len + sizeof(*mp->rtp);
|
|
|
|
|
|
|
|
|
|
add_packet_fn = codec_add_raw_packet_dup;
|
|
|
|
|
}
|
|
|
|
|
obj_put(&ch->h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// substitute out SSRC etc
|
|
|
|
|
mp->rtp->ssrc = htonl(mp->ssrc_out->parent->h.ssrc);
|
|
|
|
|
mp->rtp->seq_num = htons(ntohs(mp->rtp->seq_num) + mp->ssrc_out->parent->seq_diff);
|
|
|
|
|
|
|
|
|
|
// keep track of other stats here?
|
|
|
|
|
// to track our seq
|
|
|
|
|
unsigned short seq = ntohs(mp->rtp->seq_num);
|
|
|
|
|
|
|
|
|
|
__buffer_delay_raw(h->delay_buffer, h, codec_add_raw_packet, mp, h->source_pt.clock_rate);
|
|
|
|
|
while (true) {
|
|
|
|
|
mp->rtp->seq_num = htons(seq + mp->ssrc_out->parent->seq_diff);
|
|
|
|
|
|
|
|
|
|
// keep track of other stats here?
|
|
|
|
|
|
|
|
|
|
__buffer_delay_raw(h->delay_buffer, h, add_packet_fn, mp, h->source_pt.clock_rate);
|
|
|
|
|
|
|
|
|
|
if (duplicates == 0)
|
|
|
|
|
break;
|
|
|
|
|
duplicates--;
|
|
|
|
|
mp->ssrc_out->parent->seq_diff++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// restore original in case it was mangled
|
|
|
|
|
mp->raw = orig_raw;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|