From 34b934693fbcd164dec0f2297ec358a2095b9c58 Mon Sep 17 00:00:00 2001 From: Anunay Maheshwari Date: Sat, 31 May 2025 22:08:34 +0530 Subject: [PATCH 1/4] fix(sampleWriter): handle dropped packets --- pcm.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pcm.go b/pcm.go index 1e22246..da78518 100644 --- a/pcm.go +++ b/pcm.go @@ -182,6 +182,7 @@ type sampleWriter[T ~[]byte] struct { w MediaSampleWriter sampleRate int sampleDur time.Duration + lastWrite time.Time } func (w *sampleWriter[T]) String() string { @@ -199,7 +200,17 @@ func (w *sampleWriter[T]) Close() error { func (w *sampleWriter[T]) WriteSample(in T) error { data := make([]byte, len(in)) copy(data, in) - return w.w.WriteSample(media.Sample{Data: data, Duration: w.sampleDur}) + + var droppedPackets uint16 + if !w.lastWrite.IsZero() { + timeSinceLastWrite := time.Since(w.lastWrite) + if timeSinceLastWrite > w.sampleDur { + droppedPackets = uint16((timeSinceLastWrite - w.sampleDur) / w.sampleDur) + } + } + + w.lastWrite = time.Now() + return w.w.WriteSample(media.Sample{Data: data, Duration: w.sampleDur, PrevDroppedPackets: droppedPackets}) } // MonoToStereo converts mono PCM from src to stereo PCM in dst. From 12b1dee09819cabff75b66e00c1929f22abab666 Mon Sep 17 00:00:00 2001 From: Anunay Maheshwari Date: Sun, 1 Jun 2025 00:36:58 +0530 Subject: [PATCH 2/4] feat(opus): support dtx encoding --- opus/opus.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/opus/opus.go b/opus/opus.go index 4b2af7c..d1e1109 100644 --- a/opus/opus.go +++ b/opus/opus.go @@ -64,7 +64,7 @@ func Decode(w media.PCM16Writer, targetChannels int, logger logger.Logger) (Writ }, nil } -func Encode(w Writer, channels int, logger logger.Logger) (media.PCM16Writer, error) { +func Encode(w Writer, channels int, useDtx bool, logger logger.Logger) (media.PCM16Writer, error) { enc, err := opus.NewEncoder(w.SampleRate(), channels, opus.AppVoIP) if err != nil { return nil, err @@ -73,6 +73,7 @@ func Encode(w Writer, channels int, logger logger.Logger) (media.PCM16Writer, er w: w, enc: enc, buf: make([]byte, w.SampleRate()/rtp.DefFramesPerSec*channels), + useDtx: useDtx, logger: logger, }, nil } @@ -162,6 +163,7 @@ type encoder struct { w Writer enc *opus.Encoder buf Sample + useDtx bool logger logger.Logger } @@ -178,6 +180,13 @@ func (e *encoder) WriteSample(in media.PCM16Sample) error { if err != nil { return err } + + // opus_encode() returns the number of bytes actually written to the packet. + // The return value can be negative, which indicates that an error has occurred. + // If the return value is 1 byte, then the packet does not need to be transmitted (DTX). + if n == 1 && e.useDtx { + return nil + } return e.w.WriteSample(e.buf[:n]) } From 607419611b200ca3a24c3d76b4edaea676f1a2ae Mon Sep 17 00:00:00 2001 From: Anunay Maheshwari Date: Sun, 1 Jun 2025 11:10:21 +0530 Subject: [PATCH 3/4] fix: add tolerance to PrevPacketsDropped calculation --- pcm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pcm.go b/pcm.go index da78518..9254d80 100644 --- a/pcm.go +++ b/pcm.go @@ -204,7 +204,8 @@ func (w *sampleWriter[T]) WriteSample(in T) error { var droppedPackets uint16 if !w.lastWrite.IsZero() { timeSinceLastWrite := time.Since(w.lastWrite) - if timeSinceLastWrite > w.sampleDur { + tolerance := w.sampleDur / 10 + if timeSinceLastWrite > w.sampleDur+tolerance { droppedPackets = uint16((timeSinceLastWrite - w.sampleDur) / w.sampleDur) } } From 1a044d5f6d13784f25f9feb4cd7ed466c08f63d3 Mon Sep 17 00:00:00 2001 From: Anunay Maheshwari Date: Sun, 1 Jun 2025 20:31:17 +0530 Subject: [PATCH 4/4] fix(PrevDroppedPackets): use tolerance in calculation --- pcm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcm.go b/pcm.go index 9254d80..52b2ea9 100644 --- a/pcm.go +++ b/pcm.go @@ -205,8 +205,8 @@ func (w *sampleWriter[T]) WriteSample(in T) error { if !w.lastWrite.IsZero() { timeSinceLastWrite := time.Since(w.lastWrite) tolerance := w.sampleDur / 10 - if timeSinceLastWrite > w.sampleDur+tolerance { - droppedPackets = uint16((timeSinceLastWrite - w.sampleDur) / w.sampleDur) + if timeSinceLastWrite > (w.sampleDur + tolerance) { + droppedPackets = uint16((timeSinceLastWrite - (w.sampleDur - tolerance)) / w.sampleDur) } }