diff --git a/daemon/codec.c b/daemon/codec.c index 4bd817674..580fd473e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -3393,7 +3393,8 @@ static bool __buffer_dtx(struct dtx_buffer *dtxb, struct codec_ssrc_handler *dec unsigned long ts = packet ? packet->ts : 0; - if (!mp->ssrc_out->seq_set) { + // Discard entries have no packet; initialize sequencing with the first real packet. + if (packet && !mp->ssrc_out->seq_set) { mp->ssrc_out->seq_set = true; mp->ssrc_out->seq_out = packet->p.seq; } diff --git a/t/Makefile b/t/Makefile index d70fb778c..e7b76ad99 100644 --- a/t/Makefile +++ b/t/Makefile @@ -109,7 +109,8 @@ include ../lib/common.Makefile daemon-tests-templ-def daemon-tests-templ-def-offer daemon-tests-t38 daemon-tests-evs-dtx \ daemon-tests-transform daemon-tests-http daemon-tests-heuristic daemon-tests-asymmetric \ daemon-tests-dtx-no-shift daemon-tests-rtcp daemon-tests-redis-subscribe \ - daemon-tests-recording + daemon-tests-recording \ + daemon-tests-dtx-dtmf TESTS= test-bitstr aes-crypt aead-aes-crypt test-const_str_hash.strhash ifeq ($(with_transcoding),yes) @@ -157,7 +158,8 @@ daemon-tests: daemon-tests-main daemon-tests-jb daemon-tests-pubsub daemon-tests daemon-tests-sdp-orig-replacements daemon-tests-moh daemon-tests-evs-dtx daemon-tests-transform \ daemon-tests-transcode-config daemon-tests-codec-prefs daemon-tests-http daemon-tests-heuristic \ daemon-tests-asymmetric daemon-tests-rtcp daemon-tests-redis-subscribe \ - daemon-tests-recording + daemon-tests-recording \ + daemon-tests-dtx-dtmf daemon-test-deps: tests-preload.so $(MAKE) -C ../daemon @@ -177,6 +179,9 @@ daemon-tests-asymmetric: daemon-test-deps daemon-tests-dtx: daemon-test-deps ./auto-test-helper "$@" perl -I../perl auto-daemon-tests-dtx.pl +daemon-tests-dtx-dtmf: daemon-test-deps + ./auto-test-helper "$@" perl -I../perl auto-daemon-tests-dtx-dtmf.pl + daemon-tests-dtx-no-shift: daemon-test-deps ./auto-test-helper "$@" perl -I../perl auto-daemon-tests-dtx-no-shift.pl diff --git a/t/auto-daemon-tests-dtx-dtmf.pl b/t/auto-daemon-tests-dtx-dtmf.pl new file mode 100755 index 000000000..bba2094cb --- /dev/null +++ b/t/auto-daemon-tests-dtx-dtmf.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use NGCP::Rtpengine::Test; +use NGCP::Rtpclient::SRTP; +use NGCP::Rtpengine::AutoTest; +use Test::More; + +# Run without extended codec dependencies: G.711 also supports DTX buffering. +autotest_start(qw(--config-file=none -t -1 -i 203.0.113.1 + -n 2223 -f -L 7 -E --silence-detect=1 --dtx-delay=50)) or die; + +my ($sock_a, $sock_b) = new_call([qw(198.51.100.10 5000)], [qw(198.51.100.10 5002)]); +my $name = 'DTMF suppression before first DTX audio packet'; + +my ($port_a) = offer($name, { codec => { transcode => ['PCMA'] } }, < ft(), flags => ['directional'] }); +snd($sock_a, $port_b, rtp(0, 1999, 3840, 0x5678, "\x40" x 160)); +rcv_no($sock_b); +rtpe_req('unblock media', $name, { 'from-tag' => ft(), flags => ['directional'] }); + +# Block the event itself so it cannot initialize the output RTP sequence. +rtpe_req('block DTMF', $name, { 'from-tag' => ft() }); +snd($sock_a, $port_b, rtp(101 | 0x80, 2000, 4000, 0x5678, "\x0a\x07\x00\xa0")); +# The first audio packets overlap the active event and become null discard entries. +snd($sock_a, $port_b, rtp(0, 2001, 4000, 0x5678, "\x40" x 160)); +snd($sock_a, $port_b, rtp(0, 2002, 4160, 0x5678, "\x40" x 160)); +rcv_no($sock_b); +rtpe_req('query', $name, { 'from-tag' => ft() }); + +# End the event, then verify that the first real audio packet supplies the sequence +# and subsequent packets continue normally rather than starting from zero. +snd($sock_a, $port_b, rtp(101, 2003, 4000, 0x5678, "\x0a\x87\x01\x40")); +snd($sock_a, $port_b, rtp(0, 2004, 4320, 0x5678, "\x40" x 160)); +snd($sock_a, $port_b, rtp(0, 2005, 4480, 0x5678, "\x40" x 160)); +# The output timestamp origin includes the suppressed interval. +my ($ssrc) = rcv($sock_b, $port_a, rtpm(8, 2004, 4000, -1, "\x68" x 160)); +rcv($sock_b, $port_a, rtpm(8, 2005, 4160, $ssrc, "\x68" x 160)); +rtpe_req('delete', $name, { 'from-tag' => ft() }); + +done_testing();