• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/cast/rtcp/test_rtcp_packet_builder.h"
6 
7 #include "base/logging.h"
8 #include "media/cast/rtcp/rtcp_utility.h"
9 
10 namespace media {
11 namespace cast {
12 
TestRtcpPacketBuilder()13 TestRtcpPacketBuilder::TestRtcpPacketBuilder()
14     : ptr_of_length_(NULL),
15       big_endian_writer_(reinterpret_cast<char*>(buffer_), kMaxIpPacketSize) {}
16 
AddSr(uint32 sender_ssrc,int number_of_report_blocks)17 void TestRtcpPacketBuilder::AddSr(uint32 sender_ssrc,
18                                   int number_of_report_blocks) {
19   AddRtcpHeader(200, number_of_report_blocks);
20   big_endian_writer_.WriteU32(sender_ssrc);
21   big_endian_writer_.WriteU32(kNtpHigh);  // NTP timestamp.
22   big_endian_writer_.WriteU32(kNtpLow);
23   big_endian_writer_.WriteU32(kRtpTimestamp);
24   big_endian_writer_.WriteU32(kSendPacketCount);
25   big_endian_writer_.WriteU32(kSendOctetCount);
26 }
27 
AddSrWithNtp(uint32 sender_ssrc,uint32 ntp_high,uint32 ntp_low,uint32 rtp_timestamp)28 void TestRtcpPacketBuilder::AddSrWithNtp(uint32 sender_ssrc,
29                                          uint32 ntp_high,
30                                          uint32 ntp_low,
31                                          uint32 rtp_timestamp) {
32   AddRtcpHeader(200, 0);
33   big_endian_writer_.WriteU32(sender_ssrc);
34   big_endian_writer_.WriteU32(ntp_high);
35   big_endian_writer_.WriteU32(ntp_low);
36   big_endian_writer_.WriteU32(rtp_timestamp);
37   big_endian_writer_.WriteU32(kSendPacketCount);
38   big_endian_writer_.WriteU32(kSendOctetCount);
39 }
40 
AddRr(uint32 sender_ssrc,int number_of_report_blocks)41 void TestRtcpPacketBuilder::AddRr(uint32 sender_ssrc,
42                                   int number_of_report_blocks) {
43   AddRtcpHeader(201, number_of_report_blocks);
44   big_endian_writer_.WriteU32(sender_ssrc);
45 }
46 
AddRb(uint32 rtp_ssrc)47 void TestRtcpPacketBuilder::AddRb(uint32 rtp_ssrc) {
48   big_endian_writer_.WriteU32(rtp_ssrc);
49   big_endian_writer_.WriteU32(kLoss);
50   big_endian_writer_.WriteU32(kExtendedMax);
51   big_endian_writer_.WriteU32(kTestJitter);
52   big_endian_writer_.WriteU32(kLastSr);
53   big_endian_writer_.WriteU32(kDelayLastSr);
54 }
55 
AddSdesCname(uint32 sender_ssrc,const std::string & c_name)56 void TestRtcpPacketBuilder::AddSdesCname(uint32 sender_ssrc,
57                                          const std::string& c_name) {
58   AddRtcpHeader(202, 1);
59   big_endian_writer_.WriteU32(sender_ssrc);
60   big_endian_writer_.WriteU8(1);  // c_name.
61 
62   DCHECK_LE(c_name.size(), 255u);
63   big_endian_writer_.WriteU8(
64       static_cast<uint8>(c_name.size()));  // c_name length in bytes.
65   for (size_t i = 0; i < c_name.size(); ++i) {
66     big_endian_writer_.WriteU8(c_name.c_str()[i]);
67   }
68   int padding;
69   switch (c_name.size() % 4) {
70     case 0:
71       padding = 2;
72       break;
73     case 1:
74       padding = 1;
75       break;
76     case 2:
77       padding = 4;
78       break;
79     case 3:
80       padding = 3;
81       break;
82   }
83   for (int j = 0; j < padding; ++j) {
84     big_endian_writer_.WriteU8(0);
85   }
86 }
87 
AddXrHeader(uint32 sender_ssrc)88 void TestRtcpPacketBuilder::AddXrHeader(uint32 sender_ssrc) {
89   AddRtcpHeader(207, 0);
90   big_endian_writer_.WriteU32(sender_ssrc);
91 }
92 
AddXrUnknownBlock()93 void TestRtcpPacketBuilder::AddXrUnknownBlock() {
94   big_endian_writer_.WriteU8(9);   // Block type.
95   big_endian_writer_.WriteU8(0);   // Reserved.
96   big_endian_writer_.WriteU16(4);  // Block length.
97   // First receiver same as sender of this report.
98   big_endian_writer_.WriteU32(0);
99   big_endian_writer_.WriteU32(0);
100   big_endian_writer_.WriteU32(0);
101   big_endian_writer_.WriteU32(0);
102 }
103 
AddXrDlrrBlock(uint32 sender_ssrc)104 void TestRtcpPacketBuilder::AddXrDlrrBlock(uint32 sender_ssrc) {
105   big_endian_writer_.WriteU8(5);   // Block type.
106   big_endian_writer_.WriteU8(0);   // Reserved.
107   big_endian_writer_.WriteU16(3);  // Block length.
108 
109   // First receiver same as sender of this report.
110   big_endian_writer_.WriteU32(sender_ssrc);
111   big_endian_writer_.WriteU32(kLastRr);
112   big_endian_writer_.WriteU32(kDelayLastRr);
113 }
114 
AddXrExtendedDlrrBlock(uint32 sender_ssrc)115 void TestRtcpPacketBuilder::AddXrExtendedDlrrBlock(uint32 sender_ssrc) {
116   big_endian_writer_.WriteU8(5);   // Block type.
117   big_endian_writer_.WriteU8(0);   // Reserved.
118   big_endian_writer_.WriteU16(9);  // Block length.
119   big_endian_writer_.WriteU32(0xaaaaaaaa);
120   big_endian_writer_.WriteU32(0xaaaaaaaa);
121   big_endian_writer_.WriteU32(0xaaaaaaaa);
122 
123   // First receiver same as sender of this report.
124   big_endian_writer_.WriteU32(sender_ssrc);
125   big_endian_writer_.WriteU32(kLastRr);
126   big_endian_writer_.WriteU32(kDelayLastRr);
127   big_endian_writer_.WriteU32(0xbbbbbbbb);
128   big_endian_writer_.WriteU32(0xbbbbbbbb);
129   big_endian_writer_.WriteU32(0xbbbbbbbb);
130 }
131 
AddXrRrtrBlock()132 void TestRtcpPacketBuilder::AddXrRrtrBlock() {
133   big_endian_writer_.WriteU8(4);   // Block type.
134   big_endian_writer_.WriteU8(0);   // Reserved.
135   big_endian_writer_.WriteU16(2);  // Block length.
136   big_endian_writer_.WriteU32(kNtpHigh);
137   big_endian_writer_.WriteU32(kNtpLow);
138 }
139 
AddNack(uint32 sender_ssrc,uint32 media_ssrc)140 void TestRtcpPacketBuilder::AddNack(uint32 sender_ssrc, uint32 media_ssrc) {
141   AddRtcpHeader(205, 1);
142   big_endian_writer_.WriteU32(sender_ssrc);
143   big_endian_writer_.WriteU32(media_ssrc);
144   big_endian_writer_.WriteU16(kMissingPacket);
145   big_endian_writer_.WriteU16(0);
146 }
147 
AddSendReportRequest(uint32 sender_ssrc,uint32 media_ssrc)148 void TestRtcpPacketBuilder::AddSendReportRequest(uint32 sender_ssrc,
149                                                  uint32 media_ssrc) {
150   AddRtcpHeader(205, 5);
151   big_endian_writer_.WriteU32(sender_ssrc);
152   big_endian_writer_.WriteU32(media_ssrc);
153 }
154 
AddPli(uint32 sender_ssrc,uint32 media_ssrc)155 void TestRtcpPacketBuilder::AddPli(uint32 sender_ssrc, uint32 media_ssrc) {
156   AddRtcpHeader(206, 1);
157   big_endian_writer_.WriteU32(sender_ssrc);
158   big_endian_writer_.WriteU32(media_ssrc);
159 }
160 
AddRpsi(uint32 sender_ssrc,uint32 media_ssrc)161 void TestRtcpPacketBuilder::AddRpsi(uint32 sender_ssrc, uint32 media_ssrc) {
162   AddRtcpHeader(206, 3);
163   big_endian_writer_.WriteU32(sender_ssrc);
164   big_endian_writer_.WriteU32(media_ssrc);
165   big_endian_writer_.WriteU8(0);  // Padding bits.
166   big_endian_writer_.WriteU8(kPayloadtype);
167   uint64 picture_id = kPictureId;
168 
169   for (int i = 9; i > 0; i--) {
170     big_endian_writer_.WriteU8(0x80 |
171                                static_cast<uint8>(picture_id >> (i * 7)));
172   }
173   // Add last byte of picture ID.
174   big_endian_writer_.WriteU8(static_cast<uint8>(picture_id & 0x7f));
175 }
176 
AddRemb(uint32 sender_ssrc,uint32 media_ssrc)177 void TestRtcpPacketBuilder::AddRemb(uint32 sender_ssrc, uint32 media_ssrc) {
178   AddRtcpHeader(206, 15);
179   big_endian_writer_.WriteU32(sender_ssrc);
180   big_endian_writer_.WriteU32(0);
181   big_endian_writer_.WriteU8('R');
182   big_endian_writer_.WriteU8('E');
183   big_endian_writer_.WriteU8('M');
184   big_endian_writer_.WriteU8('B');
185   big_endian_writer_.WriteU8(1);  // Number of SSRCs.
186   big_endian_writer_.WriteU8(1);  // BR Exp.
187   //  BR Mantissa.
188   big_endian_writer_.WriteU16(static_cast<uint16>(kTestRembBitrate / 2));
189   big_endian_writer_.WriteU32(media_ssrc);
190 }
191 
AddCast(uint32 sender_ssrc,uint32 media_ssrc,uint16 target_delay_ms)192 void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc,
193                                     uint32 media_ssrc,
194                                     uint16 target_delay_ms) {
195   AddRtcpHeader(206, 15);
196   big_endian_writer_.WriteU32(sender_ssrc);
197   big_endian_writer_.WriteU32(media_ssrc);
198   big_endian_writer_.WriteU8('C');
199   big_endian_writer_.WriteU8('A');
200   big_endian_writer_.WriteU8('S');
201   big_endian_writer_.WriteU8('T');
202   big_endian_writer_.WriteU8(kAckFrameId);
203   big_endian_writer_.WriteU8(3);     // Loss fields.
204   big_endian_writer_.WriteU16(target_delay_ms);
205   big_endian_writer_.WriteU8(kLostFrameId);
206   big_endian_writer_.WriteU16(kRtcpCastAllPacketsLost);
207   big_endian_writer_.WriteU8(0);  // Lost packet id mask.
208   big_endian_writer_.WriteU8(kFrameIdWithLostPackets);
209   big_endian_writer_.WriteU16(kLostPacketId1);
210   big_endian_writer_.WriteU8(0x2);  // Lost packet id mask.
211   big_endian_writer_.WriteU8(kFrameIdWithLostPackets);
212   big_endian_writer_.WriteU16(kLostPacketId3);
213   big_endian_writer_.WriteU8(0);  // Lost packet id mask.
214 }
215 
AddReceiverLog(uint32 sender_ssrc)216 void TestRtcpPacketBuilder::AddReceiverLog(uint32 sender_ssrc) {
217   AddRtcpHeader(204, 2);
218   big_endian_writer_.WriteU32(sender_ssrc);
219   big_endian_writer_.WriteU8('C');
220   big_endian_writer_.WriteU8('A');
221   big_endian_writer_.WriteU8('S');
222   big_endian_writer_.WriteU8('T');
223 }
224 
AddReceiverFrameLog(uint32 rtp_timestamp,int num_events,uint32 event_timesamp_base)225 void TestRtcpPacketBuilder::AddReceiverFrameLog(uint32 rtp_timestamp,
226                                                 int num_events,
227                                                 uint32 event_timesamp_base) {
228   big_endian_writer_.WriteU32(rtp_timestamp);
229   big_endian_writer_.WriteU8(static_cast<uint8>(num_events - 1));
230   big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base >> 16));
231   big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base >> 8));
232   big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base));
233 }
234 
AddReceiverEventLog(uint16 event_data,CastLoggingEvent event,uint16 event_timesamp_delta)235 void TestRtcpPacketBuilder::AddReceiverEventLog(uint16 event_data,
236                                                 CastLoggingEvent event,
237                                                 uint16 event_timesamp_delta) {
238   big_endian_writer_.WriteU16(event_data);
239   uint8 event_id = ConvertEventTypeToWireFormat(event);
240   uint16 type_and_delta = static_cast<uint16>(event_id) << 12;
241   type_and_delta += event_timesamp_delta & 0x0fff;
242   big_endian_writer_.WriteU16(type_and_delta);
243 }
244 
GetPacket()245 scoped_ptr<media::cast::Packet> TestRtcpPacketBuilder::GetPacket() {
246   PatchLengthField();
247   return scoped_ptr<media::cast::Packet>(
248       new media::cast::Packet(buffer_, buffer_ + Length()));
249 }
250 
Data()251 const uint8* TestRtcpPacketBuilder::Data() {
252   PatchLengthField();
253   return buffer_;
254 }
255 
PatchLengthField()256 void TestRtcpPacketBuilder::PatchLengthField() {
257   if (ptr_of_length_) {
258     // Back-patch the packet length. The client must have taken
259     // care of proper padding to 32-bit words.
260     int this_packet_length = (big_endian_writer_.ptr() - ptr_of_length_ - 2);
261     DCHECK_EQ(0, this_packet_length % 4)
262         << "Packets must be a multiple of 32 bits long";
263     *ptr_of_length_ = this_packet_length >> 10;
264     *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF;
265     ptr_of_length_ = NULL;
266   }
267 }
268 
269 // Set the 5-bit value in the 1st byte of the header
270 // and the payload type. Set aside room for the length field,
271 // and make provision for back-patching it.
AddRtcpHeader(int payload,int format_or_count)272 void TestRtcpPacketBuilder::AddRtcpHeader(int payload, int format_or_count) {
273   PatchLengthField();
274   big_endian_writer_.WriteU8(0x80 | (format_or_count & 0x1F));
275   big_endian_writer_.WriteU8(payload);
276   ptr_of_length_ = big_endian_writer_.ptr();
277 
278   // Initialize length to "clearly illegal".
279   big_endian_writer_.WriteU16(0xDEAD);
280 }
281 
282 }  // namespace cast
283 }  // namespace media
284