1663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org/*
2663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *
4663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  Use of this source code is governed by a BSD-style license
5663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  that can be found in the LICENSE file in the root of the source
6663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  tree. An additional intellectual property rights grant can be found
7663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  in the file PATENTS.  All contributing project authors may
8663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org */
10663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
11663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
12663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
13663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
1499681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
15663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
167eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgusing webrtc::RTCPUtility::kBtDlrr;
177eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgusing webrtc::RTCPUtility::kBtReceiverReferenceTime;
187eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgusing webrtc::RTCPUtility::kBtVoipMetric;
197eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
20847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::PT_APP;
21b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::PT_BYE;
22847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::PT_IJ;
23b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::PT_PSFB;
24b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::PT_RR;
25b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::PT_RTPFB;
26847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::PT_SDES;
27b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::PT_SR;
28847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::PT_XR;
29b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
30847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketAPP;
31b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketBYE;
32847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBAPP;
33b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBFIR;
34b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
35847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBPLI;
36847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
37b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
38847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBSLI;
39847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
40b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketReportBlockItem;
41b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRR;
42b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
43b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
44847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
45847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem;
46847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR;
47847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem;
48b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketSR;
49847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
50847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem;
51847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketXR;
52847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgusing webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem;
53b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
54663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgnamespace webrtc {
55663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgnamespace rtcp {
56663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgnamespace {
57b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// Unused SSRC of media source, set to 0.
58b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgconst uint32_t kUnusedMediaSourceSsrc0 = 0;
59b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
60847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
61663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  buffer[(*offset)++] = value;
62663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
63847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
646aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord16ToBuffer(buffer + *offset, value);
65663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  *offset += 2;
66663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
67847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
686aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord24ToBuffer(buffer + *offset, value);
69663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  *offset += 3;
70663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
71847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
726aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org  RtpUtility::AssignUWord32ToBuffer(buffer + *offset, value);
73663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  *offset += 4;
74663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
75663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,
777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                                         uint8_t bits_mantissa,
787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                                         uint32_t* mantissa,
797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                                         uint8_t* exp) {
807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  // input_base10 = mantissa * 2^exp
817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  assert(bits_mantissa <= 32);
827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint32_t mantissa_max = (1 << bits_mantissa) - 1;
837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint8_t exponent = 0;
847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (uint32_t i = 0; i < 64; ++i) {
857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    if (input_base10 <= (mantissa_max << i)) {
867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      exponent = i;
877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      break;
887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    }
897eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
907eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  *exp = exponent;
917eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  *mantissa = (input_base10 >> exponent);
927eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
937eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
94847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgsize_t BlockToHeaderLength(size_t length_in_bytes) {
95b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  // Length in 32-bit words minus 1.
96b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(length_in_bytes > 0);
97b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(length_in_bytes % 4 == 0);
98b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  return (length_in_bytes / 4) - 1;
99b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
100b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
101663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
102663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
103b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// RTP header format.
104b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   0                   1                   2                   3
105b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   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
106b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//  |V=2|P| RC/FMT  |      PT       |             length            |
108b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
110b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateHeader(uint8_t count_or_format,  // Depends on packet type.
111b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                  uint8_t packet_type,
112847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                  size_t length,
113b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                  uint8_t* buffer,
114847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                  size_t* pos) {
115847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  assert(length <= 0xffff);
116b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  const uint8_t kVersion = 2;
117b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
118b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord8(buffer, pos, packet_type);
119b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord16(buffer, pos, length);
120b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
121b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
122b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//  Sender report (SR) (RFC 3550).
123663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   0                   1                   2                   3
124663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   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
125663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |V=2|P|    RC   |   PT=SR=200   |             length            |
127663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                         SSRC of sender                        |
129663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
130663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |              NTP timestamp, most significant word             |
131663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |             NTP timestamp, least significant word             |
133663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                         RTP timestamp                         |
135663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                     sender's packet count                     |
137663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                      sender's octet count                     |
139663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
140663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
141b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateSenderReport(const RTCPPacketSR& sr,
142847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                        size_t length,
143663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org                        uint8_t* buffer,
144847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                        size_t* pos) {
145b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
146663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.SenderSSRC);
147663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.NTPMostSignificant);
148663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
149663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.RTPTimestamp);
150663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.SenderPacketCount);
151663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, sr.SenderOctetCount);
152663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
153663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
154b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//  Receiver report (RR), header (RFC 3550).
155663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
156663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   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
157663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |V=2|P|    RC   |   PT=RR=201   |             length            |
159663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                     SSRC of packet sender                     |
161663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
162663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
163b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateReceiverReport(const RTCPPacketRR& rr,
164847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                          size_t length,
165663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org                          uint8_t* buffer,
166847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                          size_t* pos) {
167b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
168663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, rr.SenderSSRC);
169663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
170663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
171663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  Report block (RFC 3550).
172663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
173663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   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
174663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
175663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                 SSRC_1 (SSRC of first source)                 |
176663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  | fraction lost |       cumulative number of packets lost       |
178663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |           extended highest sequence number received           |
180663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                      interarrival jitter                      |
182663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                         last SR (LSR)                         |
184663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
185663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  |                   delay since last SR (DLSR)                  |
186663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
187663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
188847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
189847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                        uint8_t* buffer,
190847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                        size_t* pos) {
191847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  for (std::vector<RTCPPacketReportBlockItem>::const_iterator
192847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org       it = blocks.begin(); it != blocks.end(); ++it) {
193847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).SSRC);
194847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).FractionLost);
195847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
196847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
197847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).Jitter);
198847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).LastSR);
199847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).DelayLastSR);
200847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
201847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
202847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
203847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Transmission Time Offsets in RTP Streams (RFC 5450).
204847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
205847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//      0                   1                   2                   3
206847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//      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
207847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// hdr |V=2|P|    RC   |   PT=IJ=195   |             length            |
209847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     |                      inter-arrival jitter                     |
211847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     .                                                               .
213847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     .                                                               .
214847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     .                                                               .
215847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     |                      inter-arrival jitter                     |
216847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
218847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreateIj(const std::vector<uint32_t>& ij_items,
219847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org              uint8_t* buffer,
220847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org              size_t* pos) {
221847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  size_t length = ij_items.size();
222847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateHeader(length, PT_IJ, length, buffer, pos);
223847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  for (std::vector<uint32_t>::const_iterator it = ij_items.begin();
224847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org       it != ij_items.end(); ++it) {
225847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, *it);
226847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
227847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
228847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
229847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Source Description (SDES) (RFC 3550).
230847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
231847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//         0                   1                   2                   3
232847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//         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
233847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// header |V=2|P|    SC   |  PT=SDES=202  |             length            |
235847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
236847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// chunk  |                          SSRC/CSRC_1                          |
237847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        |                           SDES items                          |
239847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        |                              ...                              |
240847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
241847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// chunk  |                          SSRC/CSRC_2                          |
242847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
243847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        |                           SDES items                          |
244847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        |                              ...                              |
245847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
246847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
247847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Canonical End-Point Identifier SDES Item (CNAME)
248847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
249847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//    0                   1                   2                   3
250847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//    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
251847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   |    CNAME=1    |     length    | user and domain name        ...
253847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
255847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreateSdes(const std::vector<Sdes::Chunk>& chunks,
256847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t length,
257847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                uint8_t* buffer,
258847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t* pos) {
259847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateHeader(chunks.size(), PT_SDES, length, buffer, pos);
260847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  const uint8_t kSdesItemType = 1;
261847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
262847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org       it != chunks.end(); ++it) {
263847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).ssrc);
264847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord8(buffer, pos, kSdesItemType);
265847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).name.length());
266847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
267847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    *pos += (*it).name.length();
268847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    memset(buffer + *pos, 0, (*it).null_octets);
269847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    *pos += (*it).null_octets;
270847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
271663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
272663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
273663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// Bye packet (BYE) (RFC 3550).
274663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
275663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//        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
276663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       |V=2|P|    SC   |   PT=BYE=203  |             length            |
278663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       |                           SSRC/CSRC                           |
280663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       :                              ...                              :
282663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
283663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// (opt) |     length    |               reason for leaving            ...
284663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
286b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateBye(const RTCPPacketBYE& bye,
287663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org               const std::vector<uint32_t>& csrcs,
288847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t length,
289663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org               uint8_t* buffer,
290847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t* pos) {
291b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(length, PT_BYE, length, buffer, pos);
292663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, bye.SenderSSRC);
293663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
294663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org       it != csrcs.end(); ++it) {
295663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    AssignUWord32(buffer, pos, *it);
296663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
297663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
298663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
299847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Application-Defined packet (APP) (RFC 3550).
300847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
301847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   0                   1                   2                   3
302847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   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
303847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
304847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  |V=2|P| subtype |   PT=APP=204  |             length            |
305847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  |                           SSRC/CSRC                           |
307847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
308847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  |                          name (ASCII)                         |
309847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
310847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  |                   application-dependent data                ...
311847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
312847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
313847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreateApp(const RTCPPacketAPP& app,
314847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               uint32_t ssrc,
315847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t length,
316847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               uint8_t* buffer,
317847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t* pos) {
318847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateHeader(app.SubType, PT_APP, length, buffer, pos);
319847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, ssrc);
320847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, app.Name);
321847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  memcpy(buffer + *pos, app.Data, app.Size);
322847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  *pos += app.Size;
323847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
324847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
325663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// RFC 4585: Feedback format.
326663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
327663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// Common packet format:
328663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
329663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//    0                   1                   2                   3
330663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//    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
331663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
332663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   |V=2|P|   FMT   |       PT      |          length               |
333663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   |                  SSRC of packet sender                        |
335663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   |                  SSRC of media source                         |
337663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
338663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   :            Feedback Control Information (FCI)                 :
339663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   :
340663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
341b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
342847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Picture loss indication (PLI) (RFC 4585).
343847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
344847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// FCI: no feedback control information.
345847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
346847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreatePli(const RTCPPacketPSFBPLI& pli,
347847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t length,
348847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               uint8_t* buffer,
349847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t* pos) {
350847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  const uint8_t kFmt = 1;
351847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
352847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, pli.SenderSSRC);
353847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, pli.MediaSSRC);
354847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
355847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
356847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// Slice loss indication (SLI) (RFC 4585).
357847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
358847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org// FCI:
359847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//
360847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//    0                   1                   2                   3
361847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//    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
362847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   |            First        |        Number           | PictureID |
364847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
366847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid CreateSli(const RTCPPacketPSFBSLI& sli,
367847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               const RTCPPacketPSFBSLIItem& sli_item,
368847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t length,
369847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               uint8_t* buffer,
370847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t* pos) {
371847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  const uint8_t kFmt = 2;
372847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
373847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, sli.SenderSSRC);
374847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord32(buffer, pos, sli.MediaSSRC);
375847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
376847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
377847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
378847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                            ((sli_item.NumberOfMB >> 10) & 0x07));
379847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
380847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
381847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
382847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
383b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// Generic NACK (RFC 4585).
384b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//
385b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// FCI:
386b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//
387b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//    0                   1                   2                   3
388b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//    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
389b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   |            PID                |             BLP               |
391b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
393b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateNack(const RTCPPacketRTPFBNACK& nack,
394b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
395847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t length,
396b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                uint8_t* buffer,
397847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t* pos) {
398b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  const uint8_t kFmt = 1;
399b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
400b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord32(buffer, pos, nack.SenderSSRC);
401b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord32(buffer, pos, nack.MediaSSRC);
402b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  for (std::vector<RTCPPacketRTPFBNACKItem>::const_iterator
403b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org      it = nack_fields.begin(); it != nack_fields.end(); ++it) {
404b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).PacketID);
405b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).BitMask);
406b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
407b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
408b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
409b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// Reference picture selection indication (RPSI) (RFC 4585).
410b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//
411b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org// FCI:
412b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//
413b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//    0                   1                   2                   3
414b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//    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
415b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   |      PB       |0| Payload Type|    Native RPSI bit string     |
417b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
418b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   |   defined per codec          ...                | Padding (0) |
419b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
421b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
422b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                uint8_t padding_bytes,
423847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t length,
424b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org                uint8_t* buffer,
425847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                size_t* pos) {
426b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  // Native bit string should be a multiple of 8 bits.
427b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(rpsi.NumberOfValidBits % 8 == 0);
428b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  const uint8_t kFmt = 3;
429b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
430b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord32(buffer, pos, rpsi.SenderSSRC);
431b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord32(buffer, pos, rpsi.MediaSSRC);
432b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord8(buffer, pos, padding_bytes * 8);
433b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord8(buffer, pos, rpsi.PayloadType);
434b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
435b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  *pos += rpsi.NumberOfValidBits / 8;
436b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  memset(buffer + *pos, 0, padding_bytes);
437b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  *pos += padding_bytes;
438b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
439b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
440663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// Full intra request (FIR) (RFC 5104).
441663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
442663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org// FCI:
443663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//
444663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//    0                   1                   2                   3
445663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//    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
446663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   |                              SSRC                             |
448663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
449663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   | Seq nr.       |    Reserved                                   |
450663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
451663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
452b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid CreateFir(const RTCPPacketPSFBFIR& fir,
453b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org               const RTCPPacketPSFBFIRItem& fir_item,
454847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t length,
455b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org               uint8_t* buffer,
456847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org               size_t* pos) {
457663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  const uint8_t kFmt = 4;
458b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
459663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, fir.SenderSSRC);
460b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
461663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord32(buffer, pos, fir_item.SSRC);
462663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
463663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  AssignUWord24(buffer, pos, 0);
464663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
4657eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
4667eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
4677eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                     uint8_t* buffer,
4687eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                     size_t* pos) {
4697eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000;
4707eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint32_t mantissa = 0;
4717eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint8_t exp = 0;
4727eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp);
4737eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
4747eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, tmmbr_item.SSRC);
4757eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03));
4767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, mantissa >> 7);
4777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, (mantissa << 1) +
4787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                            ((tmmbr_item.MeasuredOverhead >> 8) & 0x01));
4797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead);
4807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
4817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
4827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
4837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
4847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// FCI:
4857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
4867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    0                   1                   2                   3
4877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    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
4887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4897eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |                              SSRC                             |
4907eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4917eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
4927eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4937eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
4947eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
4957eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
4967eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 size_t length,
4977eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 uint8_t* buffer,
4987eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 size_t* pos) {
4997eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const uint8_t kFmt = 3;
5007eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
5017eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, tmmbr.SenderSSRC);
5027eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
5037eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateTmmbrItem(tmmbr_item, buffer, pos);
5047eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
5057eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5067eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
5077eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
5087eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// FCI:
5097eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
5107eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    0                   1                   2                   3
5117eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    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
5127eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5137eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |                              SSRC                             |
5147eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5157eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
5167eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5177eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5187eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
5197eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items,
5207eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 size_t length,
5217eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 uint8_t* buffer,
5227eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 size_t* pos) {
5237eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const uint8_t kFmt = 4;
5247eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
5257eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, tmmbn.SenderSSRC);
5267eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
5277eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (uint8_t i = 0; i < tmmbn_items.size(); ++i) {
5287eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    CreateTmmbrItem(tmmbn_items[i], buffer, pos);
5297eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
5307eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
5317eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5327eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
5337eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
5347eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    0                   1                   2                   3
5357eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//    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
5367eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5377eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |V=2|P| FMT=15  |   PT=206      |             length            |
5387eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5397eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |                  SSRC of packet sender                        |
5407eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5417eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |                  SSRC of media source                         |
5427eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5437eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |  Unique identifier 'R' 'E' 'M' 'B'                            |
5447eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5457eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
5467eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5477eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |   SSRC feedback                                               |
5487eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5497eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   |  ...                                                          |
5507eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5517eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateRemb(const RTCPPacketPSFBAPP& remb,
5527eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                const RTCPPacketPSFBREMBItem& remb_item,
5537eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                size_t length,
5547eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                uint8_t* buffer,
5557eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                size_t* pos) {
5567eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint32_t mantissa = 0;
5577eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  uint8_t exp = 0;
5587eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
5597eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5607eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const uint8_t kFmt = 15;
5617eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
5627eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, remb.SenderSSRC);
5637eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
5647eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, 'R');
5657eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, 'E');
5667eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, 'M');
5677eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, 'B');
5687eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs);
5697eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03));
5707eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, mantissa >> 8);
5717eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, mantissa);
5727eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) {
5737eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord32(buffer, pos, remb_item.SSRCs[i]);
5747eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
5757eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
5767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
5787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
5797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// Format for XR packets:
5807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
5817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   0                   1                   2                   3
5827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   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
5837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |V=2|P|reserved |   PT=XR=207   |             length            |
5857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                              SSRC                             |
5877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  :                         report blocks                         :
5897eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5907eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5917eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateXrHeader(const RTCPPacketXR& header,
5927eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                    size_t length,
5937eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                    uint8_t* buffer,
5947eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                    size_t* pos) {
5957eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateHeader(0U, PT_XR, length, buffer, pos);
5967eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord32(buffer, pos, header.OriginatorSSRC);
5977eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
5987eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
5997eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateXrBlockHeader(uint8_t block_type,
6007eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                         uint16_t block_length,
6017eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                         uint8_t* buffer,
6027eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                         size_t* pos) {
6037eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, block_type);
6047eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord8(buffer, pos, 0);
6057eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  AssignUWord16(buffer, pos, block_length);
6067eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
6077eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6087eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// Receiver Reference Time Report Block (RFC 3611).
6097eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
6107eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   0                   1                   2                   3
6117eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   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
6127eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6137eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |     BT=4      |   reserved    |       block length = 2        |
6147eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6157eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |              NTP timestamp, most significant word             |
6167eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6177eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |             NTP timestamp, least significant word             |
6187eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6197eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6207eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs,
6217eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                uint8_t* buffer,
6227eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                size_t* pos) {
6237eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const uint16_t kBlockLength = 2;
6247eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it =
6257eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org       rrtrs.begin(); it != rrtrs.end(); ++it) {
6267eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos);
6277eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).NTPMostSignificant);
6287eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).NTPLeastSignificant);
6297eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
6307eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
6317eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6327eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// DLRR Report Block (RFC 3611).
6337eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
6347eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   0                   1                   2                   3
6357eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   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
6367eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6377eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |     BT=5      |   reserved    |         block length          |
6387eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
6397eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                 SSRC_1 (SSRC of first receiver)               | sub-
6407eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
6417eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                         last RR (LRR)                         |   1
6427eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6437eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                   delay since last RR (DLRR)                  |
6447eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
6457eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                 SSRC_2 (SSRC of second receiver)              | sub-
6467eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
6477eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  :                               ...                             :   2
6487eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6497eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs,
6507eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                uint8_t* buffer,
6517eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                size_t* pos) {
6527eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin();
6537eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org       it != dlrrs.end(); ++it) {
6547eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    if ((*it).empty()) {
6557eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      continue;
6567eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    }
6577eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    uint16_t block_length = 3 * (*it).size();
6587eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos);
6597eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    for (Xr::DlrrBlock::const_iterator it_block = (*it).begin();
6607eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org         it_block != (*it).end(); ++it_block) {
6617eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      AssignUWord32(buffer, pos, (*it_block).SSRC);
6627eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      AssignUWord32(buffer, pos, (*it_block).LastRR);
6637eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      AssignUWord32(buffer, pos, (*it_block).DelayLastRR);
6647eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    }
6657eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
6667eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
6677eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6687eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org// VoIP Metrics Report Block (RFC 3611).
6697eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//
6707eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   0                   1                   2                   3
6717eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//   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
6727eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6737eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |     BT=7      |   reserved    |       block length = 8        |
6747eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6757eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |                        SSRC of source                         |
6767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |   loss rate   | discard rate  | burst density |  gap density  |
6787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |       burst duration          |         gap duration          |
6807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |     round trip delay          |       end system delay        |
6827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  | signal level  |  noise level  |     RERL      |     Gmin      |
6847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |   R factor    | ext. R factor |    MOS-LQ     |    MOS-CQ     |
6867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |   RX config   |   reserved    |          JB nominal           |
6887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6897eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  |          JB maximum           |          JB abs max           |
6907eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
6917eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
6927eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics,
6937eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                      uint8_t* buffer,
6947eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                      size_t* pos) {
6957eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const uint16_t kBlockLength = 8;
6967eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it =
6977eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org       metrics.begin(); it != metrics.end(); ++it) {
6987eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos);
6997eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord32(buffer, pos, (*it).SSRC);
7007eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).lossRate);
7017eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).discardRate);
7027eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).burstDensity);
7037eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).gapDensity);
7047eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).burstDuration);
7057eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).gapDuration);
7067eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).roundTripDelay);
7077eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).endSystemDelay);
7087eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).signalLevel);
7097eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).noiseLevel);
7107eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).RERL);
7117eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).Gmin);
7127eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).Rfactor);
7137eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).extRfactor);
7147eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).MOSLQ);
7157eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).MOSCQ);
7167eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, (*it).RXconfig);
7177eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord8(buffer, pos, 0);
7187eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).JBnominal);
7197eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).JBmax);
7207eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    AssignUWord16(buffer, pos, (*it).JBabsMax);
7217eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
7227eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
723663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}  // namespace
724663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
725663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid RtcpPacket::Append(RtcpPacket* packet) {
726663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  assert(packet);
727663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  appended_packets_.push_back(packet);
728663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
729663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
730663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgRawPacket RtcpPacket::Build() const {
731847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  size_t length = 0;
732663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  uint8_t packet[IP_PACKET_SIZE];
733847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateAndAddAppended(packet, &length, IP_PACKET_SIZE);
734847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  return RawPacket(packet, length);
735663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
736663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
737847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid RtcpPacket::Build(uint8_t* packet,
738847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                       size_t* length,
739847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                       size_t max_length) const {
740847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  *length = 0;
741847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateAndAddAppended(packet, length, max_length);
742663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
743663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
744663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid RtcpPacket::CreateAndAddAppended(uint8_t* packet,
745847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                                      size_t* length,
746847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                                      size_t max_length) const {
747847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  Create(packet, length, max_length);
748663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
749663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org      it != appended_packets_.end(); ++it) {
750847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    (*it)->CreateAndAddAppended(packet, length, max_length);
751663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
752663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
753663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
754847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Empty::Create(uint8_t* packet, size_t* length, size_t max_length) const {
755663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
756663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
757663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid SenderReport::Create(uint8_t* packet,
758847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                          size_t* length,
759847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                          size_t max_length) const {
760847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
76199681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
762663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
763663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
764847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, length);
765847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateReportBlocks(report_blocks_, packet, length);
766663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
767663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
768663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid SenderReport::WithReportBlock(ReportBlock* block) {
769663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  assert(block);
770663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
77199681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max report blocks reached.";
772663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
773663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
774847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  report_blocks_.push_back(block->report_block_);
775663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  sr_.NumberOfReportBlocks = report_blocks_.size();
776663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
777663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
778663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid ReceiverReport::Create(uint8_t* packet,
779847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                            size_t* length,
780847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org                            size_t max_length) const {
781847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
78299681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
783663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
784663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
785847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, length);
786847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateReportBlocks(report_blocks_, packet, length);
787663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
788663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
789663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid ReceiverReport::WithReportBlock(ReportBlock* block) {
790663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  assert(block);
791663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
79299681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max report blocks reached.";
793663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
794663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
795847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  report_blocks_.push_back(block->report_block_);
796663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  rr_.NumberOfReportBlocks = report_blocks_.size();
797663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
798663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
799847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Ij::Create(uint8_t* packet, size_t* length, size_t max_length) const {
800847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
801847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
802847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
803847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
804847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateIj(ij_items_, packet, length);
805847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
806847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
807847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Ij::WithJitterItem(uint32_t jitter) {
808847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (ij_items_.size() >= kMaxNumberOfIjItems) {
809847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
810847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
811847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
812847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  ij_items_.push_back(jitter);
813847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
814847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
815847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Sdes::Create(uint8_t* packet, size_t* length, size_t max_length) const {
816847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  assert(!chunks_.empty());
817847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
818847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
819847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
820847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
821847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, length);
822847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
823847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
824847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Sdes::WithCName(uint32_t ssrc, std::string cname) {
825847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  assert(cname.length() <= 0xff);
826847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (chunks_.size() >= kMaxNumberOfChunks) {
827847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max SDES chunks reached.";
828847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
829847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
830847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // In each chunk, the list of items must be terminated by one or more null
831847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // octets. The next chunk must start on a 32-bit boundary.
832847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // CNAME (1 byte) | length (1 byte) | name | padding.
833847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  int null_octets = 4 - ((2 + cname.length()) % 4);
834847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  Chunk chunk;
835847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  chunk.ssrc = ssrc;
836847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  chunk.name = cname;
837847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  chunk.null_octets = null_octets;
838847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  chunks_.push_back(chunk);
839b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
840b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
841847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgsize_t Sdes::BlockLength() const {
842847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // Header (4 bytes).
843847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // Chunk:
844847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
845847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  size_t length = kHeaderLength;
846847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  for (std::vector<Chunk>::const_iterator it = chunks_.begin();
847847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org       it != chunks_.end(); ++it) {
848847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    length += 6 + (*it).name.length() + (*it).null_octets;
849847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
850847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  assert(length % 4 == 0);
851847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  return length;
852847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
853847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
854847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Bye::Create(uint8_t* packet, size_t* length, size_t max_length) const {
855847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
85699681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
857663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
858663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
859847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, length);
860663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
861663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
862663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.orgvoid Bye::WithCsrc(uint32_t csrc) {
863663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  if (csrcs_.size() >= kMaxNumberOfCsrcs) {
86499681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max CSRC size reached.";
865663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
866663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
867663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  csrcs_.push_back(csrc);
868663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
869663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
870847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid App::Create(uint8_t* packet, size_t* length, size_t max_length) const {
871847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
872847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
873847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
874847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
875847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, length);
876847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
877847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
878847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Pli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
879847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
880847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
881847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
882847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
883847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, length);
884847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
885847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
886847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Sli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
887847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
888847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
889847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org    return;
890847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  }
891847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet,
892847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org            length);
893847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org}
894847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org
895847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Nack::Create(uint8_t* packet, size_t* length, size_t max_length) const {
896b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(!nack_fields_.empty());
897847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
89899681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
899663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org    return;
900663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org  }
901847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateNack(nack_, nack_fields_, BlockToHeaderLength(BlockLength()), packet,
902847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org             length);
903663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
904663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org
905b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid Nack::WithList(const uint16_t* nack_list, int length) {
906b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(nack_list);
907b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(nack_fields_.empty());
908b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  int i = 0;
909b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  while (i < length) {
910b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    uint16_t pid = nack_list[i++];
911b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    // Bitmask specifies losses in any of the 16 packets following the pid.
912b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    uint16_t bitmask = 0;
913b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    while (i < length) {
914b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org      int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
915b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org      if (shift >= 0 && shift <= 15) {
916b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org        bitmask |= (1 << shift);
917b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org        ++i;
918b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org      } else {
919b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org        break;
920b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org      }
921b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    }
922b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    RTCPUtility::RTCPPacketRTPFBNACKItem item;
923b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    item.PacketID = pid;
924b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    item.BitMask = bitmask;
925b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    nack_fields_.push_back(item);
926b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
927b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
928b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
929847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Rpsi::Create(uint8_t* packet, size_t* length, size_t max_length) const {
930b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  assert(rpsi_.NumberOfValidBits > 0);
931847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
932b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
933b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    return;
934b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
935847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
936847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org             length);
937b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
938b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
939b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.orgvoid Rpsi::WithPictureId(uint64_t picture_id) {
940b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  const uint32_t kPidBits = 7;
941bad8a13a7532047cb53c4969a07506252e3a2aa5fbarchard@google.com  const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL;
942b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  uint8_t required_bytes = 0;
943b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  uint64_t shifted_pid = picture_id;
944b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  do {
945b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    ++required_bytes;
946b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
947b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  } while (shifted_pid > 0);
948b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
949b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  // Convert picture id to native bit string (natively defined by the video
950b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  // codec).
951b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  int pos = 0;
952b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  for (int i = required_bytes - 1; i > 0; i--) {
953b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    rpsi_.NativeBitString[pos++] =
954b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org        0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
955b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
956b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
957b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  rpsi_.NumberOfValidBits = pos * 8;
958b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
959b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
960b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  padding_bytes_ = 4 - ((2 + required_bytes) % 4);
961b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  if (padding_bytes_ == 4) {
962b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    padding_bytes_ = 0;
963b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
964b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org}
965b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org
966847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.orgvoid Fir::Create(uint8_t* packet, size_t* length, size_t max_length) const {
967847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  if (*length + BlockLength() > max_length) {
968b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
969b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org    return;
970b5b864863573bcf0a341e6462fe697450c64a873asapersson@webrtc.org  }
971847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org  CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet,
972847dfa535730a30d57cf26d788d31070b70a02afasapersson@webrtc.org            length);
973663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}
9747eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
9757eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Remb::Create(uint8_t* packet, size_t* length, size_t max_length) const {
9767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (*length + BlockLength() > max_length) {
9777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
9787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
9797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
9807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateRemb(remb_, remb_item_, BlockToHeaderLength(BlockLength()), packet,
9817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org             length);
9827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
9837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
9847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Remb::AppliesTo(uint32_t ssrc) {
9857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) {
9867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached.";
9877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
9887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
9897eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc;
9907eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
9917eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
9927eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Tmmbr::Create(uint8_t* packet, size_t* length, size_t max_length) const {
9937eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (*length + BlockLength() > max_length) {
9947eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
9957eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
9967eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
9977eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateTmmbr(tmmbr_, tmmbr_item_, BlockToHeaderLength(BlockLength()), packet,
9987eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org              length);
9997eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10007eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10017eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) {
10027eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  assert(overhead <= 0x1ff);
10037eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) {
10047eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max TMMBN size reached.";
10057eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10067eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10077eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  RTCPPacketRTPFBTMMBRItem tmmbn_item;
10087eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  tmmbn_item.SSRC = ssrc;
10097eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps;
10107eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  tmmbn_item.MeasuredOverhead = overhead;
10117eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  tmmbn_items_.push_back(tmmbn_item);
10127eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10137eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10147eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Tmmbn::Create(uint8_t* packet, size_t* length, size_t max_length) const {
10157eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (*length + BlockLength() > max_length) {
10167eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
10177eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10187eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10197eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateTmmbn(tmmbn_, tmmbn_items_, BlockToHeaderLength(BlockLength()), packet,
10207eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org              length);
10217eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10227eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10237eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Xr::Create(uint8_t* packet, size_t* length, size_t max_length) const {
10247eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (*length + BlockLength() > max_length) {
10257eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max packet size reached.";
10267eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10277eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10287eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateXrHeader(xr_header_, BlockToHeaderLength(BlockLength()), packet,
10297eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                 length);
10307eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateRrtr(rrtr_blocks_, packet, length);
10317eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateDlrr(dlrr_blocks_, packet, length);
10327eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  CreateVoipMetric(voip_metric_blocks_, packet, length);
10337eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10347eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10357eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Xr::WithRrtr(Rrtr* rrtr) {
10367eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  assert(rrtr);
10377eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) {
10387eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max RRTR blocks reached.";
10397eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10407eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10417eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  rrtr_blocks_.push_back(rrtr->rrtr_block_);
10427eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10437eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10447eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Xr::WithDlrr(Dlrr* dlrr) {
10457eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  assert(dlrr);
10467eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
10477eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max DLRR blocks reached.";
10487eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10497eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10507eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  dlrr_blocks_.push_back(dlrr->dlrr_block_);
10517eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10527eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10537eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Xr::WithVoipMetric(VoipMetric* voip_metric) {
10547eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  assert(voip_metric);
10557eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) {
10567eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max Voip Metric blocks reached.";
10577eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10587eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10597eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  voip_metric_blocks_.push_back(voip_metric->metric_);
10607eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10617eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10627eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgsize_t Xr::DlrrLength() const {
10637eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const size_t kBlockHeaderLen = 4;
10647eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  const size_t kSubBlockLen = 12;
10657eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  size_t length = 0;
10667eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin();
10677eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org       it != dlrr_blocks_.end(); ++it) {
10687eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    if (!(*it).empty()) {
10697eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org      length += kBlockHeaderLen + kSubBlockLen * (*it).size();
10707eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    }
10717eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10727eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  return length;
10737eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10747eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
10757eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.orgvoid Dlrr::WithDlrrItem(uint32_t ssrc,
10767eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                        uint32_t last_rr,
10777eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org                        uint32_t delay_last_rr) {
10787eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) {
10797eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    LOG(LS_WARNING) << "Max DLRR items reached.";
10807eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org    return;
10817eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  }
10827eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  RTCPPacketXRDLRRReportBlockItem dlrr;
10837eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  dlrr.SSRC = ssrc;
10847eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  dlrr.LastRR = last_rr;
10857eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  dlrr.DelayLastRR = delay_last_rr;
10867eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org  dlrr_block_.push_back(dlrr);
10877eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org}
10887eec1dd08bce4d7a30d090c67a240c274b95755casapersson@webrtc.org
1089663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}  // namespace rtcp
1090663ba07859170b985f47fb4ce8fd9af947e440efasapersson@webrtc.org}  // namespace webrtc
1091