@@ -14,7 +14,10 @@ type ReceptionReport struct {
1414 FractionLost uint8
1515 // The total number of RTP data packets from source SSRC that have
1616 // been lost since the beginning of reception.
17- TotalLost uint32
17+ // https://www.ietf.org/rfc/rfc3550.txt Section 6.4 and appendix A.3
18+ // The total number of packets lost is a signed number and can be
19+ // negative
20+ TotalLost int32
1821 // The low 16 bits contain the highest sequence number received in an
1922 // RTP data packet from source SSRC, and the most significant 16
2023 // bits extend that sequence number with the corresponding count of
@@ -71,13 +74,17 @@ func (r ReceptionReport) Marshal() ([]byte, error) {
7174 rawPacket [fractionLostOffset ] = r .FractionLost
7275
7376 // pack TotalLost into 24 bits
74- if r .TotalLost >= (1 << 25 ) {
77+ // we first convert signed integer to unsigned before using bit operators
78+ uTotalLost := uint32 (r .TotalLost )
79+ if uTotalLost & 0xff800000 != 0xff800000 && uTotalLost & 0xff800000 != 0 {
7580 return nil , errInvalidTotalLost
7681 }
82+ // Convert int32 to int24
83+ uTotalLost = uTotalLost & 0x80000000 >> 8 | uTotalLost & 0x007fffff
7784 tlBytes := rawPacket [totalLostOffset :]
78- tlBytes [0 ] = byte (r . TotalLost >> 16 )
79- tlBytes [1 ] = byte (r . TotalLost >> 8 )
80- tlBytes [2 ] = byte (r . TotalLost )
85+ tlBytes [0 ] = byte (uTotalLost >> 16 )
86+ tlBytes [1 ] = byte (uTotalLost >> 8 )
87+ tlBytes [2 ] = byte (uTotalLost )
8188
8289 binary .BigEndian .PutUint32 (rawPacket [lastSeqOffset :], r .LastSequenceNumber )
8390 binary .BigEndian .PutUint32 (rawPacket [jitterOffset :], r .Jitter )
@@ -115,7 +122,13 @@ func (r *ReceptionReport) Unmarshal(rawPacket []byte) error {
115122 r .FractionLost = rawPacket [fractionLostOffset ]
116123
117124 tlBytes := rawPacket [totalLostOffset :]
118- r .TotalLost = uint32 (tlBytes [2 ]) | uint32 (tlBytes [1 ])<< 8 | uint32 (tlBytes [0 ])<< 16
125+ uTotalLost := uint32 (tlBytes [2 ]) | uint32 (tlBytes [1 ])<< 8 | uint32 (tlBytes [0 ])<< 16
126+ // test sign
127+ ua := uTotalLost & 0x007fffff
128+ if uTotalLost & 0x00800000 == 0x00800000 {
129+ ua |= 0xff800000
130+ }
131+ r .TotalLost = int32 (ua )
119132
120133 r .LastSequenceNumber = binary .BigEndian .Uint32 (rawPacket [lastSeqOffset :])
121134 r .Jitter = binary .BigEndian .Uint32 (rawPacket [jitterOffset :])
0 commit comments