receiver_report.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package rtcp
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. // A ReceiverReport (RR) packet provides reception quality feedback for an RTP stream
  7. type ReceiverReport struct {
  8. // The synchronization source identifier for the originator of this RR packet.
  9. SSRC uint32
  10. // Zero or more reception report blocks depending on the number of other
  11. // sources heard by this sender since the last report. Each reception report
  12. // block conveys statistics on the reception of RTP packets from a
  13. // single synchronization source.
  14. Reports []ReceptionReport
  15. // Extension contains additional, payload-specific information that needs to
  16. // be reported regularly about the receiver.
  17. ProfileExtensions []byte
  18. }
  19. const (
  20. ssrcLength = 4
  21. rrSSRCOffset = headerLength
  22. rrReportOffset = rrSSRCOffset + ssrcLength
  23. )
  24. // Marshal encodes the ReceiverReport in binary
  25. func (r ReceiverReport) Marshal() ([]byte, error) {
  26. /*
  27. * 0 1 2 3
  28. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  29. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  30. * header |V=2|P| RC | PT=RR=201 | length |
  31. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  32. * | SSRC of packet sender |
  33. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  34. * report | SSRC_1 (SSRC of first source) |
  35. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  36. * 1 | fraction lost | cumulative number of packets lost |
  37. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  38. * | extended highest sequence number received |
  39. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  40. * | interarrival jitter |
  41. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  42. * | last SR (LSR) |
  43. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  44. * | delay since last SR (DLSR) |
  45. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  46. * report | SSRC_2 (SSRC of second source) |
  47. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  48. * 2 : ... :
  49. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  50. * | profile-specific extensions |
  51. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52. */
  53. rawPacket := make([]byte, r.len())
  54. packetBody := rawPacket[headerLength:]
  55. binary.BigEndian.PutUint32(packetBody, r.SSRC)
  56. for i, rp := range r.Reports {
  57. data, err := rp.Marshal()
  58. if err != nil {
  59. return nil, err
  60. }
  61. offset := ssrcLength + receptionReportLength*i
  62. copy(packetBody[offset:], data)
  63. }
  64. if len(r.Reports) > countMax {
  65. return nil, errTooManyReports
  66. }
  67. pe := make([]byte, len(r.ProfileExtensions))
  68. copy(pe, r.ProfileExtensions)
  69. // if the length of the profile extensions isn't devisible
  70. // by 4, we need to pad the end.
  71. for (len(pe) & 0x3) != 0 {
  72. pe = append(pe, 0)
  73. }
  74. rawPacket = append(rawPacket, pe...)
  75. hData, err := r.Header().Marshal()
  76. if err != nil {
  77. return nil, err
  78. }
  79. copy(rawPacket, hData)
  80. return rawPacket, nil
  81. }
  82. // Unmarshal decodes the ReceiverReport from binary
  83. func (r *ReceiverReport) Unmarshal(rawPacket []byte) error {
  84. /*
  85. * 0 1 2 3
  86. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  87. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  88. * header |V=2|P| RC | PT=RR=201 | length |
  89. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  90. * | SSRC of packet sender |
  91. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  92. * report | SSRC_1 (SSRC of first source) |
  93. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  94. * 1 | fraction lost | cumulative number of packets lost |
  95. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  96. * | extended highest sequence number received |
  97. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  98. * | interarrival jitter |
  99. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  100. * | last SR (LSR) |
  101. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  102. * | delay since last SR (DLSR) |
  103. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  104. * report | SSRC_2 (SSRC of second source) |
  105. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  106. * 2 : ... :
  107. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  108. * | profile-specific extensions |
  109. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  110. */
  111. if len(rawPacket) < (headerLength + ssrcLength) {
  112. return errPacketTooShort
  113. }
  114. var h Header
  115. if err := h.Unmarshal(rawPacket); err != nil {
  116. return err
  117. }
  118. if h.Type != TypeReceiverReport {
  119. return errWrongType
  120. }
  121. r.SSRC = binary.BigEndian.Uint32(rawPacket[rrSSRCOffset:])
  122. for i := rrReportOffset; i < len(rawPacket) && len(r.Reports) < int(h.Count); i += receptionReportLength {
  123. var rr ReceptionReport
  124. if err := rr.Unmarshal(rawPacket[i:]); err != nil {
  125. return err
  126. }
  127. r.Reports = append(r.Reports, rr)
  128. }
  129. r.ProfileExtensions = rawPacket[rrReportOffset+(len(r.Reports)*receptionReportLength):]
  130. if uint8(len(r.Reports)) != h.Count {
  131. return errInvalidHeader
  132. }
  133. return nil
  134. }
  135. func (r *ReceiverReport) len() int {
  136. repsLength := 0
  137. for _, rep := range r.Reports {
  138. repsLength += rep.len()
  139. }
  140. return headerLength + ssrcLength + repsLength
  141. }
  142. // Header returns the Header associated with this packet.
  143. func (r *ReceiverReport) Header() Header {
  144. return Header{
  145. Count: uint8(len(r.Reports)),
  146. Type: TypeReceiverReport,
  147. Length: uint16((r.len()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))),
  148. }
  149. }
  150. // DestinationSSRC returns an array of SSRC values that this packet refers to.
  151. func (r *ReceiverReport) DestinationSSRC() []uint32 {
  152. out := make([]uint32, len(r.Reports))
  153. for i, v := range r.Reports {
  154. out[i] = v.SSRC
  155. }
  156. return out
  157. }
  158. func (r ReceiverReport) String() string {
  159. out := fmt.Sprintf("ReceiverReport from %x\n", r.SSRC)
  160. out += "\tSSRC \tLost\tLastSequence\n"
  161. for _, i := range r.Reports {
  162. out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
  163. }
  164. out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions)
  165. return out
  166. }