Repository: pion/interceptor (go)

Issue:
Incorrect PacketsReceived value from RemoteInboundRTPStreamStats
<!--
  Come join our community on Slack https://pion.ly/slack for quicker support and more resources

  We also provide a Knowledge Base https://pion.ly/knowledge-base that covers Pion and general WebRTC
  
  We maintain a FAQ of common issues and questions https://pion.ly/knowledge-base/pion-basics/faq/

 Please answer these questions before submitting your issue. Thanks!
-->

### Your environment.
  - Version: v0.1.17

### What did you do?
<!--
If possible, provide an example for reproducing the error.
A complete runnable program is good.
-->
Captured `OutboundRTPStreamStats` and `RemoteInboundRTPStreamStats` using the stats interceptor, from a previously defined track.

```go
go func() {
	var stats *stats.Stats

	ssrc := uint32(rtpSender.GetParameters().Encodings[0].SSRC)
	for !element.stop {
		stats = statsGetter.Get(ssrc)
		if stats != nil {
			log.Println(stats.OutboundRTPStreamStats, stats.RemoteInboundRTPStreamStats)
		}
		time.Sleep(time.Second * 5)
	}
}()
```

### What did you expect?
Values of `PacketsSent` from `OutboundRTPStreamStats` should be aligned or slightly higher than `PacketsReceived` from `RemoteInboundRTPStreamStats`.

### What happened?
Once in a while, `PacketsReceived`'s value explode and is not correctly aligned anymore:

```
2023/06/26 14:31:19 OutboundRTPStreamStats
        PacketsSent: 2991
        BytesSent: 3501804
        HeaderBytesSent: 35892
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 2991
        PacketsLost: 0
        Jitter: 0.0192
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0

2023/06/26 14:31:24 OutboundRTPStreamStats
        PacketsSent: 3588
        BytesSent: 4196307
        HeaderBytesSent: 43056
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 3583
        PacketsLost: 0
        Jitter: 0.017822222222222222
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0

2023/06/26 14:31:29 OutboundRTPStreamStats
        PacketsSent: 4185
        BytesSent: 4893407
        HeaderBytesSent: 50220
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 4185
        PacketsLost: 0
        Jitter: 0.021566666666666668
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0

2023/06/26 14:31:34 OutboundRTPStreamStats
        PacketsSent: 4785
        BytesSent: 5595347
        HeaderBytesSent: 57420
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 4294841009
        PacketsLost: 0
        Jitter: 0.022344444444444445
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0

2023/06/26 14:31:39 OutboundRTPStreamStats
        PacketsSent: 5384
        BytesSent: 6300016
        HeaderBytesSent: 64608
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 4294841608
        PacketsLost: 0
        Jitter: 0.0145
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0

2023/06/26 14:31:44 OutboundRTPStreamStats
        PacketsSent: 6115
        BytesSent: 7160160
        HeaderBytesSent: 73380
        NACKCount: 0
        FIRCount: 0
        PLICount: 0
 RemoteInboundRTPStreamStats:
        PacketsReceived: 4294842339
        PacketsLost: 0
        Jitter: 0.011177777777777778
        RoundTripTime: 0s
        TotalRoundTripTime: 0s
        FractionLost: 0
        RoundTripTimeMeasurements: 0
```

Pull request:
Fix/issue#193
#### Description

Sequence number cycles and highest sequence number calculations were incorrect and broke at higher cycles.

#### Reference issue
Fixes #193 


Patch:
diff --git a/pkg/stats/stats_recorder.go b/pkg/stats/stats_recorder.go
index ee4d31d..a9338ee 100644
--- a/pkg/stats/stats_recorder.go
+++ b/pkg/stats/stats_recorder.go
@@ -218,9 +218,9 @@ func (r *recorder) recordOutgoingRTP(latestStats internalStats, v *outgoingRTP)
 func (r *recorder) recordIncomingRR(latestStats internalStats, pkt *rtcp.ReceiverReport, ts time.Time) internalStats {
 	for _, report := range pkt.Reports {
 		if latestStats.remoteInboundFirstSequenceNumberInitialized {
-			cycles := uint64(report.LastSequenceNumber & 0xFFFF0000)
+			cycles := uint64(report.LastSequenceNumber&0xFFFF0000) >> 16
 			nr := uint64(report.LastSequenceNumber & 0x0000FFFF)
-			highest := cycles*0xFFFF + nr
+			highest := cycles*(0xFFFF+1) + nr
 			latestStats.RemoteInboundRTPStreamStats.PacketsReceived = highest - uint64(report.TotalLost) - uint64(latestStats.remoteInboundFirstSequenceNumber) + 1
 		}
 		latestStats.RemoteInboundRTPStreamStats.PacketsLost = int64(report.TotalLost)


Test patch:
diff --git a/pkg/stats/stats_recorder_test.go b/pkg/stats/stats_recorder_test.go
index a74ac54..3aa5b4c 100644
--- a/pkg/stats/stats_recorder_test.go
+++ b/pkg/stats/stats_recorder_test.go
@@ -153,6 +153,62 @@ func TestStatsRecorder(t *testing.T) {
 				FractionLost: 0.33203125,
 			},
 		},
+		{
+			name: "issue#193",
+			records: []record{
+				{
+					ts: now,
+					content: outgoingRTP{
+						header: rtp.Header{
+							SequenceNumber: 65535,
+						},
+					},
+				},
+				{
+					ts: now,
+					content: outgoingRTP{
+						header: rtp.Header{
+							SequenceNumber: 0,
+						},
+					},
+				},
+				{
+					ts: now,
+					content: incomingRTCP{
+						pkts: []rtcp.Packet{
+							&rtcp.ReceiverReport{
+								SSRC: 0,
+								Reports: []rtcp.ReceptionReport{
+									{
+										SSRC:               0,
+										FractionLost:       0,
+										TotalLost:          0,
+										LastSequenceNumber: 1 << 16,
+										Jitter:             45000,
+									},
+								},
+							},
+							cname,
+						},
+					},
+				},
+			},
+			expectedOutboundRTPStreamStats: OutboundRTPStreamStats{
+				SentRTPStreamStats: SentRTPStreamStats{
+					PacketsSent: 2,
+					BytesSent:   24,
+				},
+				HeaderBytesSent: 24,
+			},
+			expectedRemoteInboundRTPStreamStats: RemoteInboundRTPStreamStats{
+				ReceivedRTPStreamStats: ReceivedRTPStreamStats{
+					PacketsReceived: 2,
+					PacketsLost:     0,
+					Jitter:          0.5,
+				},
+				FractionLost: 0.0,
+			},
+		},
 		{
 			name: "basicOutgoingRTCP",
 			records: []record{