transport_layer_nack.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package rtcp
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "math"
  6. )
  7. // PacketBitmap shouldn't be used like a normal integral,
  8. // so it's type is masked here. Access it with PacketList().
  9. type PacketBitmap uint16
  10. // NackPair is a wire-representation of a collection of
  11. // Lost RTP packets
  12. type NackPair struct {
  13. // ID of lost packets
  14. PacketID uint16
  15. // Bitmask of following lost packets
  16. LostPackets PacketBitmap
  17. }
  18. // The TransportLayerNack packet informs the encoder about the loss of a transport packet
  19. // IETF RFC 4585, Section 6.2.1
  20. // https://tools.ietf.org/html/rfc4585#section-6.2.1
  21. type TransportLayerNack struct {
  22. // SSRC of sender
  23. SenderSSRC uint32
  24. // SSRC of the media source
  25. MediaSSRC uint32
  26. Nacks []NackPair
  27. }
  28. // NackPairsFromSequenceNumbers generates a slice of NackPair from a list of SequenceNumbers
  29. // This handles generating the proper values for PacketID/LostPackets
  30. func NackPairsFromSequenceNumbers(sequenceNumbers []uint16) (pairs []NackPair) {
  31. if len(sequenceNumbers) == 0 {
  32. return []NackPair{}
  33. }
  34. nackPair := &NackPair{PacketID: sequenceNumbers[0]}
  35. for i := 1; i < len(sequenceNumbers); i++ {
  36. m := sequenceNumbers[i]
  37. if m-nackPair.PacketID > 16 {
  38. pairs = append(pairs, *nackPair)
  39. nackPair = &NackPair{PacketID: m}
  40. continue
  41. }
  42. nackPair.LostPackets |= 1 << (m - nackPair.PacketID - 1)
  43. }
  44. pairs = append(pairs, *nackPair)
  45. return
  46. }
  47. // Range calls f sequentially for each sequence number covered by n.
  48. // If f returns false, Range stops the iteration.
  49. func (n *NackPair) Range(f func(seqno uint16) bool) {
  50. more := f(n.PacketID)
  51. if !more {
  52. return
  53. }
  54. b := n.LostPackets
  55. for i := uint16(0); b != 0; i++ {
  56. if (b & (1 << i)) != 0 {
  57. b &^= (1 << i)
  58. more = f(n.PacketID + i + 1)
  59. if !more {
  60. return
  61. }
  62. }
  63. }
  64. }
  65. // PacketList returns a list of Nack'd packets that's referenced by a NackPair
  66. func (n *NackPair) PacketList() []uint16 {
  67. out := make([]uint16, 0, 17)
  68. n.Range(func(seqno uint16) bool {
  69. out = append(out, seqno)
  70. return true
  71. })
  72. return out
  73. }
  74. const (
  75. tlnLength = 2
  76. nackOffset = 8
  77. )
  78. // Marshal encodes the TransportLayerNack in binary
  79. func (p TransportLayerNack) Marshal() ([]byte, error) {
  80. if len(p.Nacks)+tlnLength > math.MaxUint8 {
  81. return nil, errTooManyReports
  82. }
  83. rawPacket := make([]byte, nackOffset+(len(p.Nacks)*4))
  84. binary.BigEndian.PutUint32(rawPacket, p.SenderSSRC)
  85. binary.BigEndian.PutUint32(rawPacket[4:], p.MediaSSRC)
  86. for i := 0; i < len(p.Nacks); i++ {
  87. binary.BigEndian.PutUint16(rawPacket[nackOffset+(4*i):], p.Nacks[i].PacketID)
  88. binary.BigEndian.PutUint16(rawPacket[nackOffset+(4*i)+2:], uint16(p.Nacks[i].LostPackets))
  89. }
  90. h := p.Header()
  91. hData, err := h.Marshal()
  92. if err != nil {
  93. return nil, err
  94. }
  95. return append(hData, rawPacket...), nil
  96. }
  97. // Unmarshal decodes the TransportLayerNack from binary
  98. func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error {
  99. if len(rawPacket) < (headerLength + ssrcLength) {
  100. return errPacketTooShort
  101. }
  102. var h Header
  103. if err := h.Unmarshal(rawPacket); err != nil {
  104. return err
  105. }
  106. if len(rawPacket) < (headerLength + int(4*h.Length)) {
  107. return errPacketTooShort
  108. }
  109. if h.Type != TypeTransportSpecificFeedback || h.Count != FormatTLN {
  110. return errWrongType
  111. }
  112. p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:])
  113. p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:])
  114. for i := headerLength + nackOffset; i < (headerLength + int(h.Length*4)); i += 4 {
  115. p.Nacks = append(p.Nacks, NackPair{
  116. binary.BigEndian.Uint16(rawPacket[i:]),
  117. PacketBitmap(binary.BigEndian.Uint16(rawPacket[i+2:])),
  118. })
  119. }
  120. return nil
  121. }
  122. func (p *TransportLayerNack) len() int {
  123. return headerLength + nackOffset + (len(p.Nacks) * 4)
  124. }
  125. // Header returns the Header associated with this packet.
  126. func (p *TransportLayerNack) Header() Header {
  127. return Header{
  128. Count: FormatTLN,
  129. Type: TypeTransportSpecificFeedback,
  130. Length: uint16((p.len() / 4) - 1),
  131. }
  132. }
  133. func (p TransportLayerNack) String() string {
  134. out := fmt.Sprintf("TransportLayerNack from %x\n", p.SenderSSRC)
  135. out += fmt.Sprintf("\tMedia Ssrc %x\n", p.MediaSSRC)
  136. out += "\tID\tLostPackets\n"
  137. for _, i := range p.Nacks {
  138. out += fmt.Sprintf("\t%d\t%b\n", i.PacketID, i.LostPackets)
  139. }
  140. return out
  141. }
  142. // DestinationSSRC returns an array of SSRC values that this packet refers to.
  143. func (p *TransportLayerNack) DestinationSSRC() []uint32 {
  144. return []uint32{p.MediaSSRC}
  145. }