@@ -42,36 +42,64 @@ func NewCoverage(mediaPackets []rtp.Packet, numFecPackets uint32) *ProtectionCov
4242 // We allocate the biggest array of bitmasks that respects the max constraints.
4343 var packetMasks [MaxFecPackets ]util.BitArray
4444 for i := 0 ; i < int (MaxFecPackets ); i ++ {
45- packetMasks [i ] = util .NewBitArray ( MaxMediaPackets )
45+ packetMasks [i ] = util.BitArray {}
4646 }
4747
48+ coverage := & ProtectionCoverage {
49+ packetMasks : packetMasks ,
50+ numFecPackets : 0 ,
51+ numMediaPackets : 0 ,
52+ mediaPackets : nil ,
53+ }
54+
55+ coverage .UpdateCoverage (mediaPackets , numFecPackets )
56+ return coverage
57+ }
58+
59+ // UpdateCoverage updates the ProtectionCoverage object with new bitmasks accounting for the numFecPackets
60+ // we want to use to protect the batch media packets.
61+ func (p * ProtectionCoverage ) UpdateCoverage (mediaPackets []rtp.Packet , numFecPackets uint32 ) {
62+ numMediaPackets := uint32 (len (mediaPackets ))
63+
64+ // Basic sanity checks
65+ if numMediaPackets <= 0 || numMediaPackets > MaxMediaPackets {
66+ return
67+ }
68+
69+ p .mediaPackets = mediaPackets
70+
71+ if numFecPackets == p .numFecPackets && numMediaPackets == p .numMediaPackets {
72+ // We have the same number of FEC packets covering the same number of media packets, we can simply
73+ // reuse the previous coverage map with the updated media packets.
74+ return
75+ }
76+
77+ p .numFecPackets = numFecPackets
78+ p .numMediaPackets = numMediaPackets
79+
80+ // The number of FEC packets and/or the number of packets has changed, we need to update the coverage map
81+ // to reflect these new values.
82+ p .resetCoverage ()
83+
4884 // Generate FEC bit mask where numFecPackets FEC packets are covering numMediaPackets Media packets.
4985 // In the packetMasks array, each FEC packet is represented by a single BitArray, each bit in a given BitArray
5086 // corresponds to a specific Media packet.
5187 // Ex: Row I, Col J is set to 1 -> FEC packet I will protect media packet J.
5288 for fecPacketIndex := uint32 (0 ); fecPacketIndex < numFecPackets ; fecPacketIndex ++ {
5389 // We use an interleaved method to determine coverage. Given N FEC packets, Media packet X will be
5490 // covered by FEC packet X % N.
55- for mediaPacketIndex := uint32 (0 ); mediaPacketIndex < numMediaPackets ; mediaPacketIndex ++ {
56- coveringFecPktIndex := mediaPacketIndex % numFecPackets
57- packetMasks [coveringFecPktIndex ].SetBit (mediaPacketIndex , 1 )
91+ coveredMediaPacketIndex := fecPacketIndex
92+ for coveredMediaPacketIndex < numMediaPackets {
93+ p .packetMasks [fecPacketIndex ].SetBit (coveredMediaPacketIndex )
94+ coveredMediaPacketIndex += numFecPackets
5895 }
5996 }
60-
61- return & ProtectionCoverage {
62- packetMasks : packetMasks ,
63- numFecPackets : numFecPackets ,
64- numMediaPackets : numMediaPackets ,
65- mediaPackets : mediaPackets ,
66- }
6797}
6898
6999// ResetCoverage clears the underlying map so that we can reuse it for new batches of RTP packets.
70- func (p * ProtectionCoverage ) ResetCoverage () {
100+ func (p * ProtectionCoverage ) resetCoverage () {
71101 for i := uint32 (0 ); i < MaxFecPackets ; i ++ {
72- for j := uint32 (0 ); j < MaxMediaPackets ; j ++ {
73- p .packetMasks [i ].SetBit (j , 0 )
74- }
102+ p .packetMasks [i ].Reset ()
75103 }
76104}
77105
@@ -86,26 +114,46 @@ func (p *ProtectionCoverage) GetCoveredBy(fecPacketIndex uint32) *util.MediaPack
86114 return util .NewMediaPacketIterator (p .mediaPackets , coverage )
87115}
88116
89- // MarshalBitmasks returns the underlying bitmask that defines which media packets are protected by the
90- // specified fecPacketIndex.
91- func (p * ProtectionCoverage ) MarshalBitmasks (fecPacketIndex uint32 ) []byte {
92- return p .packetMasks [fecPacketIndex ].Marshal ()
93- }
94-
95117// ExtractMask1 returns the first section of the bitmask as defined by the FEC header.
96118// https://datatracker.ietf.org/doc/html/rfc8627#section-4.2.2.1
97119func (p * ProtectionCoverage ) ExtractMask1 (fecPacketIndex uint32 ) uint16 {
98- return uint16 (p .packetMasks [fecPacketIndex ].GetBitValue (0 , 14 ))
120+ mask := p .packetMasks [fecPacketIndex ]
121+ // We get the first 16 bits (64 - 16 -> shift by 48) and we shift once more for K field
122+ mask1 := mask .Lo >> 49
123+ return uint16 (mask1 )
99124}
100125
101126// ExtractMask2 returns the second section of the bitmask as defined by the FEC header.
102127// https://datatracker.ietf.org/doc/html/rfc8627#section-4.2.2.1
103128func (p * ProtectionCoverage ) ExtractMask2 (fecPacketIndex uint32 ) uint32 {
104- return uint32 (p .packetMasks [fecPacketIndex ].GetBitValue (15 , 45 ))
129+ mask := p .packetMasks [fecPacketIndex ]
130+ // We remove the first 15 bits
131+ mask2 := mask .Lo << 15
132+ // We get the first 31 bits (64 - 31 -> shift by 33) and we shift once more for K field
133+ mask2 >>= 34
134+ return uint32 (mask2 )
105135}
106136
107137// ExtractMask3 returns the third section of the bitmask as defined by the FEC header.
108138// https://datatracker.ietf.org/doc/html/rfc8627#section-4.2.2.1
109139func (p * ProtectionCoverage ) ExtractMask3 (fecPacketIndex uint32 ) uint64 {
110- return p .packetMasks [fecPacketIndex ].GetBitValue (46 , 109 )
140+ mask := p .packetMasks [fecPacketIndex ]
141+ // We remove the first 46 bits
142+ maskLo := mask .Lo << 46
143+ maskHi := mask .Hi >> 18
144+ mask3 := maskLo | maskHi
145+ return mask3
146+ }
147+
148+ // ExtractMask3_03 returns the third section of the bitmask as defined by the FEC header.
149+ // https://datatracker.ietf.org/doc/html/draft-ietf-payload-flexible-fec-scheme-03#section-4.2
150+ func (p * ProtectionCoverage ) ExtractMask3_03 (fecPacketIndex uint32 ) uint64 {
151+ mask := p .packetMasks [fecPacketIndex ]
152+ // We remove the first 46 bits
153+ maskLo := mask .Lo << 46
154+ maskHi := mask .Hi >> 18
155+ mask3 := maskLo | maskHi
156+ // We shift once for the K bit.
157+ mask3 >>= 1
158+ return mask3
111159}
0 commit comments