diff --git a/daemon/codec.c b/daemon/codec.c index a18535934..6a2ef6066 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -184,6 +184,7 @@ static int __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *ch, struct transcode_packet *packet, struct media_packet *mp, int (*func)(struct codec_ssrc_handler *ch, struct transcode_packet *packet, struct media_packet *mp)); +static struct codec_handler *__decoder_handler(struct codec_handler *h, struct media_packet *mp); static struct codec_handler codec_handler_stub_ssrc = { @@ -1935,11 +1936,16 @@ static int packet_dtmf_fwd(struct codec_ssrc_handler *ch, struct transcode_packe struct media_packet *mp) { int payload_type = -1; // take from handler's output config + struct codec_ssrc_handler *output_ch = NULL; + struct codec_ssrc_handler *decoder_ch = NULL; if (ch->handler->dtmf_scaler) { // this is actually a DTMF -> PCM handler // grab our underlying PCM transcoder - struct codec_ssrc_handler *output_ch = __output_ssrc_handler(ch, mp); + struct codec_handler *decoder_handler = __decoder_handler(ch->handler, mp); + decoder_ch = get_ssrc(mp->ssrc_in->parent->h.ssrc, + decoder_handler->ssrc_hash); + output_ch = __output_ssrc_handler(decoder_ch, mp); if (G_UNLIKELY(!ch->encoder || !output_ch->encoder)) goto skip; @@ -1983,10 +1989,14 @@ static int packet_dtmf_fwd(struct codec_ssrc_handler *ch, struct transcode_packe ch->last_dtmf_event_ts = duration; } payload_type = ch->handler->dtmf_payload_type; - obj_put(&output_ch->h); } -skip:; +skip: + if (output_ch) + obj_put(&output_ch->h); + if (decoder_ch) + obj_put(&decoder_ch->h); + char *buf = malloc(packet->payload->len + sizeof(struct rtp_header) + RTP_BUFFER_TAIL_ROOM); memcpy(buf + sizeof(struct rtp_header), packet->payload->s, packet->payload->len); if (packet->ignore_seq) // inject original seq diff --git a/t/auto-daemon-tests-dtx.pl b/t/auto-daemon-tests-dtx.pl index 419d6b013..2d8c992e5 100755 --- a/t/auto-daemon-tests-dtx.pl +++ b/t/auto-daemon-tests-dtx.pl @@ -306,4 +306,131 @@ rcv($sock_b, $port_a, rtpm(9, 9, 1600, $ssrc, "\xfb\xb8\xde\xde\x71\xb6\xfb\xdf\ rtpe_req('delete', 'AMR w DTMF', { 'from-tag' => ft() }); + + +($sock_a, $sock_b) = new_call([qw(198.51.100.10 4042)], [qw(198.51.100.10 4044)]); + +($port_a) = offer('AMR w reverse DTMF', + { + codec => { + mask => ['all'], + transcode => [ + 'AMR-WB/16000/1///mode-set--0,1,2;mode-change-period--2;mode-change-capability--2/dtx--1', + 'PCMA', + 'telephone-event' + ], + } }, < [] }, < ft() }); + done_testing();