sender_report.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package rtcp
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. // A SenderReport (SR) packet provides reception quality feedback for an RTP stream
  7. type SenderReport struct {
  8. // The synchronization source identifier for the originator of this SR packet.
  9. SSRC uint32
  10. // The wallclock time when this report was sent so that it may be used in
  11. // combination with timestamps returned in reception reports from other
  12. // receivers to measure round-trip propagation to those receivers.
  13. NTPTime uint64
  14. // Corresponds to the same time as the NTP timestamp (above), but in
  15. // the same units and with the same random offset as the RTP
  16. // timestamps in data packets. This correspondence may be used for
  17. // intra- and inter-media synchronization for sources whose NTP
  18. // timestamps are synchronized, and may be used by media-independent
  19. // receivers to estimate the nominal RTP clock frequency.
  20. RTPTime uint32
  21. // The total number of RTP data packets transmitted by the sender
  22. // since starting transmission up until the time this SR packet was
  23. // generated.
  24. PacketCount uint32
  25. // The total number of payload octets (i.e., not including header or
  26. // padding) transmitted in RTP data packets by the sender since
  27. // starting transmission up until the time this SR packet was
  28. // generated.
  29. OctetCount uint32
  30. // Zero or more reception report blocks depending on the number of other
  31. // sources heard by this sender since the last report. Each reception report
  32. // block conveys statistics on the reception of RTP packets from a
  33. // single synchronization source.
  34. Reports []ReceptionReport
  35. // ProfileExtensions contains additional, payload-specific information that needs to
  36. // be reported regularly about the sender.
  37. ProfileExtensions []byte
  38. }
  39. const (
  40. srHeaderLength = 24
  41. srSSRCOffset = 0
  42. srNTPOffset = srSSRCOffset + ssrcLength
  43. ntpTimeLength = 8
  44. srRTPOffset = srNTPOffset + ntpTimeLength
  45. rtpTimeLength = 4
  46. srPacketCountOffset = srRTPOffset + rtpTimeLength
  47. srPacketCountLength = 4
  48. srOctetCountOffset = srPacketCountOffset + srPacketCountLength
  49. srOctetCountLength = 4
  50. srReportOffset = srOctetCountOffset + srOctetCountLength
  51. )
  52. // Marshal encodes the SenderReport in binary
  53. func (r SenderReport) Marshal() ([]byte, error) {
  54. /*
  55. * 0 1 2 3
  56. * 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
  57. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  58. * header |V=2|P| RC | PT=SR=200 | length |
  59. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  60. * | SSRC of sender |
  61. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  62. * sender | NTP timestamp, most significant word |
  63. * info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64. * | NTP timestamp, least significant word |
  65. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  66. * | RTP timestamp |
  67. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  68. * | sender's packet count |
  69. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  70. * | sender's octet count |
  71. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  72. * report | SSRC_1 (SSRC of first source) |
  73. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  74. * 1 | fraction lost | cumulative number of packets lost |
  75. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  76. * | extended highest sequence number received |
  77. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  78. * | interarrival jitter |
  79. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  80. * | last SR (LSR) |
  81. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  82. * | delay since last SR (DLSR) |
  83. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  84. * report | SSRC_2 (SSRC of second source) |
  85. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  86. * 2 : ... :
  87. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  88. * | profile-specific extensions |
  89. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  90. */
  91. rawPacket := make([]byte, r.len())
  92. packetBody := rawPacket[headerLength:]
  93. binary.BigEndian.PutUint32(packetBody[srSSRCOffset:], r.SSRC)
  94. binary.BigEndian.PutUint64(packetBody[srNTPOffset:], r.NTPTime)
  95. binary.BigEndian.PutUint32(packetBody[srRTPOffset:], r.RTPTime)
  96. binary.BigEndian.PutUint32(packetBody[srPacketCountOffset:], r.PacketCount)
  97. binary.BigEndian.PutUint32(packetBody[srOctetCountOffset:], r.OctetCount)
  98. offset := srHeaderLength
  99. for _, rp := range r.Reports {
  100. data, err := rp.Marshal()
  101. if err != nil {
  102. return nil, err
  103. }
  104. copy(packetBody[offset:], data)
  105. offset += receptionReportLength
  106. }
  107. if len(r.Reports) > countMax {
  108. return nil, errTooManyReports
  109. }
  110. copy(packetBody[offset:], r.ProfileExtensions)
  111. hData, err := r.Header().Marshal()
  112. if err != nil {
  113. return nil, err
  114. }
  115. copy(rawPacket, hData)
  116. return rawPacket, nil
  117. }
  118. // Unmarshal decodes the SenderReport from binary
  119. func (r *SenderReport) Unmarshal(rawPacket []byte) error {
  120. /*
  121. * 0 1 2 3
  122. * 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
  123. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  124. * header |V=2|P| RC | PT=SR=200 | length |
  125. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  126. * | SSRC of sender |
  127. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  128. * sender | NTP timestamp, most significant word |
  129. * info +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  130. * | NTP timestamp, least significant word |
  131. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  132. * | RTP timestamp |
  133. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  134. * | sender's packet count |
  135. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  136. * | sender's octet count |
  137. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  138. * report | SSRC_1 (SSRC of first source) |
  139. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  140. * 1 | fraction lost | cumulative number of packets lost |
  141. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  142. * | extended highest sequence number received |
  143. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  144. * | interarrival jitter |
  145. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  146. * | last SR (LSR) |
  147. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  148. * | delay since last SR (DLSR) |
  149. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  150. * report | SSRC_2 (SSRC of second source) |
  151. * block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  152. * 2 : ... :
  153. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  154. * | profile-specific extensions |
  155. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  156. */
  157. if len(rawPacket) < (headerLength + srHeaderLength) {
  158. return errPacketTooShort
  159. }
  160. var h Header
  161. if err := h.Unmarshal(rawPacket); err != nil {
  162. return err
  163. }
  164. if h.Type != TypeSenderReport {
  165. return errWrongType
  166. }
  167. packetBody := rawPacket[headerLength:]
  168. r.SSRC = binary.BigEndian.Uint32(packetBody[srSSRCOffset:])
  169. r.NTPTime = binary.BigEndian.Uint64(packetBody[srNTPOffset:])
  170. r.RTPTime = binary.BigEndian.Uint32(packetBody[srRTPOffset:])
  171. r.PacketCount = binary.BigEndian.Uint32(packetBody[srPacketCountOffset:])
  172. r.OctetCount = binary.BigEndian.Uint32(packetBody[srOctetCountOffset:])
  173. offset := srReportOffset
  174. for i := 0; i < int(h.Count); i++ {
  175. rrEnd := offset + receptionReportLength
  176. if rrEnd > len(packetBody) {
  177. return errPacketTooShort
  178. }
  179. rrBody := packetBody[offset : offset+receptionReportLength]
  180. offset = rrEnd
  181. var rr ReceptionReport
  182. if err := rr.Unmarshal(rrBody); err != nil {
  183. return err
  184. }
  185. r.Reports = append(r.Reports, rr)
  186. }
  187. if offset < len(packetBody) {
  188. r.ProfileExtensions = packetBody[offset:]
  189. }
  190. if uint8(len(r.Reports)) != h.Count {
  191. return errInvalidHeader
  192. }
  193. return nil
  194. }
  195. // DestinationSSRC returns an array of SSRC values that this packet refers to.
  196. func (r *SenderReport) DestinationSSRC() []uint32 {
  197. out := make([]uint32, len(r.Reports)+1)
  198. for i, v := range r.Reports {
  199. out[i] = v.SSRC
  200. }
  201. out[len(r.Reports)] = r.SSRC
  202. return out
  203. }
  204. func (r *SenderReport) len() int {
  205. repsLength := 0
  206. for _, rep := range r.Reports {
  207. repsLength += rep.len()
  208. }
  209. return headerLength + srHeaderLength + repsLength + len(r.ProfileExtensions)
  210. }
  211. // Header returns the Header associated with this packet.
  212. func (r *SenderReport) Header() Header {
  213. return Header{
  214. Count: uint8(len(r.Reports)),
  215. Type: TypeSenderReport,
  216. Length: uint16((r.len() / 4) - 1),
  217. }
  218. }
  219. func (r SenderReport) String() string {
  220. out := fmt.Sprintf("SenderReport from %x\n", r.SSRC)
  221. out += fmt.Sprintf("\tNTPTime:\t%d\n", r.NTPTime)
  222. out += fmt.Sprintf("\tRTPTIme:\t%d\n", r.RTPTime)
  223. out += fmt.Sprintf("\tPacketCount:\t%d\n", r.PacketCount)
  224. out += fmt.Sprintf("\tOctetCount:\t%d\n", r.OctetCount)
  225. out += "\tSSRC \tLost\tLastSequence\n"
  226. for _, i := range r.Reports {
  227. out += fmt.Sprintf("\t%x\t%d/%d\t%d\n", i.SSRC, i.FractionLost, i.TotalLost, i.LastSequenceNumber)
  228. }
  229. out += fmt.Sprintf("\tProfile Extension Data: %v\n", r.ProfileExtensions)
  230. return out
  231. }