1515package sip
1616
1717import (
18+ "context"
1819 "fmt"
1920 "io"
2021 "math"
@@ -32,6 +33,7 @@ import (
3233 "github.com/stretchr/testify/require"
3334
3435 msdk "github.com/livekit/media-sdk"
36+ "github.com/livekit/media-sdk/dtmf"
3537 "github.com/livekit/media-sdk/rtp"
3638 "github.com/livekit/media-sdk/sdp"
3739 "github.com/livekit/mediatransportutil/pkg/rtcconfig"
@@ -802,3 +804,75 @@ func TestSymmetricRTP(t *testing.T) {
802804 require .Equal (t , newAddr .String (), curDstPtr .String ())
803805 })
804806}
807+
808+ func generateDTMFPackets (t * testing.T , digits string ) [][]* rtp.Packet {
809+ t .Helper ()
810+ var buf rtp.Buffer
811+ packets := make ([][]* rtp.Packet , len (digits ))
812+ last := len (buf )
813+ w := rtp .NewSeqWriter (& buf ).NewStream (101 , dtmf .SampleRate )
814+ timestamp := uint32 (1000 )
815+ for i := range digits {
816+ err := dtmf .Write (context .Background (), nil , w , timestamp , digits [i :i + 1 ])
817+ require .NoError (t , err )
818+ require .NotEmpty (t , buf )
819+ timestamp += uint32 (dtmf .SampleRate / 2 )
820+ packets [i ] = slices .Clone (buf [last :])
821+ last = len (buf )
822+ }
823+ return packets
824+ }
825+
826+ func dropPackets (t * testing.T , dropType string , packets []* rtp.Packet ) []* rtp.Packet {
827+ t .Helper ()
828+ switch dropType {
829+ case "none" :
830+ return packets
831+ case "first" :
832+ require .Greater (t , len (packets ), 3 )
833+ return packets [3 :]
834+ case "last" :
835+ require .Greater (t , len (packets ), 3 )
836+ return packets [:len (packets )- 3 ]
837+ case "middle" :
838+ require .Greater (t , len (packets ), 6 )
839+ ret := slices .Clone (packets [:3 ])
840+ ret = append (ret , packets [len (packets )- 3 :]... )
841+ return ret
842+ default :
843+ t .Fatal ("unknown drop type: " + dropType )
844+ return nil
845+ }
846+ }
847+
848+ func TestMediaPortDTMF (t * testing.T ) {
849+ digitCases := []string {"1" , "12" , "123" }
850+ lossCases := []string {"none" , "first" , "last" , "middle" }
851+
852+ for _ , digits := range digitCases {
853+ packets := generateDTMFPackets (t , digits )
854+ for _ , lossPackets := range lossCases {
855+ t .Run (fmt .Sprintf ("digits=%s/loss=%s" , digits , lossPackets ), func (t * testing.T ) {
856+ p := & MediaPort {}
857+ p .lastDTMFTimestamp .Store (math .MaxUint32 )
858+ got := ""
859+ p .HandleDTMF (func (ev dtmf.Event ) {
860+ t .Logf ("received DTMF event: %+v" , ev )
861+ got = fmt .Sprintf ("%s%s" , got , strconv .Itoa (int (ev .Code )))
862+ })
863+ for _ , digitPackets := range packets {
864+ sendPackets := dropPackets (t , lossPackets , digitPackets )
865+ t .Logf ("sending %d/%d packets" , len (sendPackets ), len (digitPackets ))
866+ for _ , pkt := range sendPackets {
867+ h := pkt .Header
868+ t .Logf ("sending packet: seq=%d, ts=%d, marker=%t" , h .SequenceNumber , h .Timestamp , h .Marker )
869+ require .NoError (t , p .dtmfHandler (& h , pkt .Payload ))
870+ }
871+ }
872+ t .Logf ("sent: %s" , digits )
873+ t .Logf ("got: %s" , got )
874+ require .Equal (t , digits , got )
875+ })
876+ }
877+ }
878+ }
0 commit comments