Browse Source

MT#56861 support DTMF injection with passthrough

Change-Id: I26fa6cf033a12d6b2fe66a7c688c87739091cbd1
pull/1657/head
Richard Fuchs 3 years ago
parent
commit
86e336c3ff
1 changed files with 59 additions and 6 deletions
  1. +59
    -6
      daemon/codec.c

+ 59
- 6
daemon/codec.c View File

@ -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;
}


Loading…
Cancel
Save