diff --git a/pkg/sfu/downtrack.go b/pkg/sfu/downtrack.go index 590a2ac79..dc8ea8979 100644 --- a/pkg/sfu/downtrack.go +++ b/pkg/sfu/downtrack.go @@ -88,6 +88,7 @@ const ( waitBeforeSendPaddingOnMute = 100 * time.Millisecond maxPaddingOnMuteDuration = 5 * time.Second + paddingOnMuteInterval = 100 * time.Millisecond ) // ------------------------------------------------------------------- @@ -1158,7 +1159,14 @@ func (d *DownTrack) WritePaddingRTP(bytesToSend int, paddingOnMute bool, forceMa return 0 } - snts, err := d.forwarder.GetSnTsForPadding(num, forceMarker) + frameRate := uint32(0) + if paddingOnMute { + // advance timestamps when sending dummy padding packets to start a stream + // to ensure receiver sees proper timestamp and starts the stream + frameRate = uint32(time.Second / paddingOnMuteInterval) + } + + snts, err := d.forwarder.GetSnTsForPadding(num, frameRate, forceMarker) if err != nil { return 0 } @@ -2391,7 +2399,6 @@ func (d *DownTrack) sendPaddingOnMute() { // let uptrack have chance to send packet before we send padding time.Sleep(waitBeforeSendPaddingOnMute) - paddingOnMuteInterval := 100 * time.Millisecond numPackets := maxPaddingOnMuteDuration / paddingOnMuteInterval for i := 0; i < int(numPackets); i++ { if d.rtpStats.IsActive() || d.IsClosed() { diff --git a/pkg/sfu/forwarder.go b/pkg/sfu/forwarder.go index b27338946..66b636703 100644 --- a/pkg/sfu/forwarder.go +++ b/pkg/sfu/forwarder.go @@ -2153,7 +2153,7 @@ func (f *Forwarder) maybeStart() { ) } -func (f *Forwarder) GetSnTsForPadding(num int, forceMarker bool) ([]SnTs, error) { +func (f *Forwarder) GetSnTsForPadding(num int, frameRate uint32, forceMarker bool) ([]SnTs, error) { f.lock.Lock() defer f.lock.Unlock() @@ -2167,7 +2167,13 @@ func (f *Forwarder) GetSnTsForPadding(num int, forceMarker bool) ([]SnTs, error) if !f.vls.GetTarget().IsValid() { forceMarker = true } - return f.rtpMunger.UpdateAndGetPaddingSnTs(num, 0, 0, forceMarker, 0) + return f.rtpMunger.UpdateAndGetPaddingSnTs( + num, + f.clockRate, + frameRate, + forceMarker, + f.rtpMunger.GetState().ExtLastTimestamp, + ) } func (f *Forwarder) GetSnTsForBlankFrames(frameRate uint32, numPackets int) ([]SnTs, bool, error) { @@ -2192,7 +2198,13 @@ func (f *Forwarder) GetSnTsForBlankFrames(frameRate uint32, numPackets int) ([]S if int64(extExpectedTS-extLastTS) <= 0 { extExpectedTS = extLastTS + 1 } - snts, err := f.rtpMunger.UpdateAndGetPaddingSnTs(numPackets, f.clockRate, frameRate, frameEndNeeded, extExpectedTS) + snts, err := f.rtpMunger.UpdateAndGetPaddingSnTs( + numPackets, + f.clockRate, + frameRate, + frameEndNeeded, + extExpectedTS, + ) return snts, frameEndNeeded, err } diff --git a/pkg/sfu/forwarder_test.go b/pkg/sfu/forwarder_test.go index 649ebbcc1..ee2743b97 100644 --- a/pkg/sfu/forwarder_test.go +++ b/pkg/sfu/forwarder_test.go @@ -1943,7 +1943,7 @@ func TestForwarderGetSnTsForPadding(t *testing.T) { disable(f) // should get back frame end needed as the last packet did not have RTP marker set - snts, err := f.GetSnTsForPadding(5, false) + snts, err := f.GetSnTsForPadding(5, 0, false) require.NoError(t, err) numPadding := 5 @@ -1959,7 +1959,7 @@ func TestForwarderGetSnTsForPadding(t *testing.T) { require.Equal(t, sntsExpected, snts) // now that there is a marker, timestamp should jump on first padding when asked again - snts, err = f.GetSnTsForPadding(numPadding, false) + snts, err = f.GetSnTsForPadding(numPadding, 0, false) require.NoError(t, err) for i := 0; i < numPadding; i++ { diff --git a/pkg/sfu/rtpmunger.go b/pkg/sfu/rtpmunger.go index 7eb41d776..bd9aa0ef6 100644 --- a/pkg/sfu/rtpmunger.go +++ b/pkg/sfu/rtpmunger.go @@ -269,7 +269,13 @@ func (r *RTPMunger) FilterRTX(nacks []uint16) []uint16 { return filtered } -func (r *RTPMunger) UpdateAndGetPaddingSnTs(num int, clockRate uint32, frameRate uint32, forceMarker bool, extRtpTimestamp uint64) ([]SnTs, error) { +func (r *RTPMunger) UpdateAndGetPaddingSnTs( + num int, + clockRate uint32, + frameRate uint32, + forceMarker bool, + extRtpTimestamp uint64, +) ([]SnTs, error) { if num == 0 { return nil, nil }