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/rtcp_sender.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "media/cast/cast_environment.h"
12 #include "media/cast/net/pacing/paced_sender.h"
13 #include "media/cast/rtcp/rtcp_utility.h"
14 #include "net/base/big_endian.h"
15
16 static const size_t kRtcpCastLogHeaderSize = 12;
17 static const size_t kRtcpSenderFrameLogSize = 4;
18 static const size_t kRtcpReceiverFrameLogSize = 8;
19 static const size_t kRtcpReceiverEventLogSize = 4;
20
21 namespace {
MergeEventTypeAndTimestampForWireFormat(const media::cast::CastLoggingEvent & event,const base::TimeDelta & time_delta)22 uint16 MergeEventTypeAndTimestampForWireFormat(
23 const media::cast::CastLoggingEvent& event,
24 const base::TimeDelta& time_delta) {
25 int64 time_delta_ms = time_delta.InMilliseconds();
26 // Max delta is 4096 milliseconds.
27 DCHECK_GE(GG_INT64_C(0xfff), time_delta_ms);
28
29 uint16 event_type_and_timestamp_delta =
30 static_cast<uint16>(time_delta_ms & 0xfff);
31
32 uint16 event_type = 0;
33 switch (event) {
34 case media::cast::kAckSent:
35 event_type = 1;
36 break;
37 case media::cast::kAudioPlayoutDelay:
38 event_type = 2;
39 break;
40 case media::cast::kAudioFrameDecoded:
41 event_type = 3;
42 break;
43 case media::cast::kVideoFrameDecoded:
44 event_type = 4;
45 break;
46 case media::cast::kVideoRenderDelay:
47 event_type = 5;
48 break;
49 case media::cast::kPacketReceived:
50 event_type = 6;
51 break;
52 default:
53 NOTREACHED();
54 }
55 DCHECK(!(event_type & 0xfff0));
56 return (event_type << 12) + event_type_and_timestamp_delta;
57 }
58
ScanRtcpReceiverLogMessage(const media::cast::RtcpReceiverLogMessage & receiver_log_message,size_t start_size,size_t * number_of_frames,size_t * total_number_of_messages_to_send,size_t * rtcp_log_size)59 bool ScanRtcpReceiverLogMessage(
60 const media::cast::RtcpReceiverLogMessage& receiver_log_message,
61 size_t start_size,
62 size_t* number_of_frames,
63 size_t* total_number_of_messages_to_send,
64 size_t* rtcp_log_size) {
65 if (receiver_log_message.empty()) return false;
66
67 size_t remaining_space = media::cast::kIpPacketSize - start_size;
68
69 // We must have space for at least one message
70 DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize +
71 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize)
72 << "Not enough buffer space";
73
74 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize +
75 kRtcpReceiverEventLogSize) {
76 return false;
77 }
78 // Account for the RTCP header for an application-defined packet.
79 remaining_space -= kRtcpCastLogHeaderSize;
80
81 media::cast::RtcpReceiverLogMessage::const_iterator frame_it =
82 receiver_log_message.begin();
83 for (; frame_it != receiver_log_message.end(); ++frame_it) {
84 (*number_of_frames)++;
85
86 remaining_space -= kRtcpReceiverFrameLogSize;
87
88 size_t messages_in_frame = frame_it->event_log_messages_.size();
89 size_t remaining_space_in_messages =
90 remaining_space / kRtcpReceiverEventLogSize;
91 size_t messages_to_send = std::min(messages_in_frame,
92 remaining_space_in_messages);
93 if (messages_to_send > media::cast::kRtcpMaxReceiverLogMessages) {
94 // We can't send more than 256 messages.
95 remaining_space -= media::cast::kRtcpMaxReceiverLogMessages *
96 kRtcpReceiverEventLogSize;
97 *total_number_of_messages_to_send +=
98 media::cast::kRtcpMaxReceiverLogMessages;
99 break;
100 }
101 remaining_space -= messages_to_send * kRtcpReceiverEventLogSize;
102 *total_number_of_messages_to_send += messages_to_send;
103
104 if (remaining_space <
105 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) {
106 // Make sure that we have room for at least one more message.
107 break;
108 }
109 }
110 *rtcp_log_size = kRtcpCastLogHeaderSize +
111 *number_of_frames * kRtcpReceiverFrameLogSize +
112 *total_number_of_messages_to_send * kRtcpReceiverEventLogSize;
113 DCHECK_GE(media::cast::kIpPacketSize,
114 start_size + *rtcp_log_size) << "Not enough buffer space";
115
116 VLOG(1) << "number of frames " << *number_of_frames;
117 VLOG(1) << "total messages to send " << *total_number_of_messages_to_send;
118 VLOG(1) << "rtcp log size " << *rtcp_log_size;
119 return true;
120 }
121 } // namespace
122
123 namespace media {
124 namespace cast {
125
RtcpSender(scoped_refptr<CastEnvironment> cast_environment,PacedPacketSender * outgoing_transport,uint32 sending_ssrc,const std::string & c_name)126 RtcpSender::RtcpSender(scoped_refptr<CastEnvironment> cast_environment,
127 PacedPacketSender* outgoing_transport,
128 uint32 sending_ssrc,
129 const std::string& c_name)
130 : ssrc_(sending_ssrc),
131 c_name_(c_name),
132 transport_(outgoing_transport),
133 cast_environment_(cast_environment) {
134 DCHECK_LT(c_name_.length(), kRtcpCnameSize) << "Invalid config";
135 }
136
~RtcpSender()137 RtcpSender::~RtcpSender() {}
138
SendRtcpFromRtpSender(uint32 packet_type_flags,const RtcpSenderInfo * sender_info,const RtcpDlrrReportBlock * dlrr,RtcpSenderLogMessage * sender_log)139 void RtcpSender::SendRtcpFromRtpSender(uint32 packet_type_flags,
140 const RtcpSenderInfo* sender_info,
141 const RtcpDlrrReportBlock* dlrr,
142 RtcpSenderLogMessage* sender_log) {
143 if (packet_type_flags & kRtcpRr ||
144 packet_type_flags & kRtcpPli ||
145 packet_type_flags & kRtcpRrtr ||
146 packet_type_flags & kRtcpCast ||
147 packet_type_flags & kRtcpReceiverLog ||
148 packet_type_flags & kRtcpRpsi ||
149 packet_type_flags & kRtcpRemb ||
150 packet_type_flags & kRtcpNack) {
151 NOTREACHED() << "Invalid argument";
152 }
153
154 std::vector<uint8> packet;
155 packet.reserve(kIpPacketSize);
156 if (packet_type_flags & kRtcpSr) {
157 DCHECK(sender_info) << "Invalid argument";
158 BuildSR(*sender_info, NULL, &packet);
159 BuildSdec(&packet);
160 }
161 if (packet_type_flags & kRtcpBye) {
162 BuildBye(&packet);
163 }
164 if (packet_type_flags & kRtcpDlrr) {
165 DCHECK(dlrr) << "Invalid argument";
166 BuildDlrrRb(dlrr, &packet);
167 }
168 if (packet_type_flags & kRtcpSenderLog) {
169 DCHECK(sender_log) << "Invalid argument";
170 BuildSenderLog(sender_log, &packet);
171 }
172 if (packet.empty())
173 return; // Sanity don't send empty packets.
174
175 transport_->SendRtcpPacket(packet);
176 }
177
SendRtcpFromRtpReceiver(uint32 packet_type_flags,const RtcpReportBlock * report_block,const RtcpReceiverReferenceTimeReport * rrtr,const RtcpCastMessage * cast_message,RtcpReceiverLogMessage * receiver_log)178 void RtcpSender::SendRtcpFromRtpReceiver(
179 uint32 packet_type_flags,
180 const RtcpReportBlock* report_block,
181 const RtcpReceiverReferenceTimeReport* rrtr,
182 const RtcpCastMessage* cast_message,
183 RtcpReceiverLogMessage* receiver_log) {
184 if (packet_type_flags & kRtcpSr ||
185 packet_type_flags & kRtcpDlrr ||
186 packet_type_flags & kRtcpSenderLog) {
187 NOTREACHED() << "Invalid argument";
188 }
189 if (packet_type_flags & kRtcpPli ||
190 packet_type_flags & kRtcpRpsi ||
191 packet_type_flags & kRtcpRemb ||
192 packet_type_flags & kRtcpNack) {
193 // Implement these for webrtc interop.
194 NOTIMPLEMENTED();
195 }
196 std::vector<uint8> packet;
197 packet.reserve(kIpPacketSize);
198
199 if (packet_type_flags & kRtcpRr) {
200 BuildRR(report_block, &packet);
201 if (!c_name_.empty()) {
202 BuildSdec(&packet);
203 }
204 }
205 if (packet_type_flags & kRtcpBye) {
206 BuildBye(&packet);
207 }
208 if (packet_type_flags & kRtcpRrtr) {
209 DCHECK(rrtr) << "Invalid argument";
210 BuildRrtr(rrtr, &packet);
211 }
212 if (packet_type_flags & kRtcpCast) {
213 DCHECK(cast_message) << "Invalid argument";
214 BuildCast(cast_message, &packet);
215 }
216 if (packet_type_flags & kRtcpReceiverLog) {
217 DCHECK(receiver_log) << "Invalid argument";
218 BuildReceiverLog(receiver_log, &packet);
219 }
220 if (packet.empty()) return; // Sanity don't send empty packets.
221
222 transport_->SendRtcpPacket(packet);
223 }
224
BuildSR(const RtcpSenderInfo & sender_info,const RtcpReportBlock * report_block,std::vector<uint8> * packet) const225 void RtcpSender::BuildSR(const RtcpSenderInfo& sender_info,
226 const RtcpReportBlock* report_block,
227 std::vector<uint8>* packet) const {
228 // Sender report.
229 size_t start_size = packet->size();
230 DCHECK_LT(start_size + 52, kIpPacketSize) << "Not enough buffer space";
231 if (start_size + 52 > kIpPacketSize) return;
232
233 uint16 number_of_rows = (report_block) ? 12 : 6;
234 packet->resize(start_size + 28);
235
236 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 28);
237 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
238 big_endian_writer.WriteU8(kPacketTypeSenderReport);
239 big_endian_writer.WriteU16(number_of_rows);
240 big_endian_writer.WriteU32(ssrc_);
241 big_endian_writer.WriteU32(sender_info.ntp_seconds);
242 big_endian_writer.WriteU32(sender_info.ntp_fraction);
243 big_endian_writer.WriteU32(sender_info.rtp_timestamp);
244 big_endian_writer.WriteU32(sender_info.send_packet_count);
245 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count));
246
247 if (report_block) {
248 AddReportBlocks(*report_block, packet); // Adds 24 bytes.
249 }
250 }
251
BuildRR(const RtcpReportBlock * report_block,std::vector<uint8> * packet) const252 void RtcpSender::BuildRR(const RtcpReportBlock* report_block,
253 std::vector<uint8>* packet) const {
254 size_t start_size = packet->size();
255 DCHECK_LT(start_size + 32, kIpPacketSize) << "Not enough buffer space";
256 if (start_size + 32 > kIpPacketSize) return;
257
258 uint16 number_of_rows = (report_block) ? 7 : 1;
259 packet->resize(start_size + 8);
260
261 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
262 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0));
263 big_endian_writer.WriteU8(kPacketTypeReceiverReport);
264 big_endian_writer.WriteU16(number_of_rows);
265 big_endian_writer.WriteU32(ssrc_);
266
267 if (report_block) {
268 AddReportBlocks(*report_block, packet); // Adds 24 bytes.
269 }
270 }
271
AddReportBlocks(const RtcpReportBlock & report_block,std::vector<uint8> * packet) const272 void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block,
273 std::vector<uint8>* packet) const {
274 size_t start_size = packet->size();
275 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
276 if (start_size + 24 > kIpPacketSize) return;
277
278 packet->resize(start_size + 24);
279
280 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
281 big_endian_writer.WriteU32(report_block.media_ssrc);
282 big_endian_writer.WriteU8(report_block.fraction_lost);
283 big_endian_writer.WriteU8(report_block.cumulative_lost >> 16);
284 big_endian_writer.WriteU8(report_block.cumulative_lost >> 8);
285 big_endian_writer.WriteU8(report_block.cumulative_lost);
286
287 // Extended highest seq_no, contain the highest sequence number received.
288 big_endian_writer.WriteU32(report_block.extended_high_sequence_number);
289 big_endian_writer.WriteU32(report_block.jitter);
290
291 // Last SR timestamp; our NTP time when we received the last report.
292 // This is the value that we read from the send report packet not when we
293 // received it.
294 big_endian_writer.WriteU32(report_block.last_sr);
295
296 // Delay since last received report, time since we received the report.
297 big_endian_writer.WriteU32(report_block.delay_since_last_sr);
298 }
299
BuildSdec(std::vector<uint8> * packet) const300 void RtcpSender::BuildSdec(std::vector<uint8>* packet) const {
301 size_t start_size = packet->size();
302 DCHECK_LT(start_size + 12 + c_name_.length(), kIpPacketSize)
303 << "Not enough buffer space";
304 if (start_size + 12 > kIpPacketSize) return;
305
306 // SDES Source Description.
307 packet->resize(start_size + 10);
308
309 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
310 // We always need to add one SDES CNAME.
311 big_endian_writer.WriteU8(0x80 + 1);
312 big_endian_writer.WriteU8(kPacketTypeSdes);
313
314 // Handle SDES length later on.
315 uint32 sdes_length_position = static_cast<uint32>(start_size) + 3;
316 big_endian_writer.WriteU16(0);
317 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
318 big_endian_writer.WriteU8(1); // CNAME = 1
319 big_endian_writer.WriteU8(static_cast<uint8>(c_name_.length()));
320
321 size_t sdes_length = 10 + c_name_.length();
322 packet->insert(packet->end(), c_name_.c_str(),
323 c_name_.c_str() + c_name_.length());
324
325 size_t padding = 0;
326
327 // We must have a zero field even if we have an even multiple of 4 bytes.
328 if ((packet->size() % 4) == 0) {
329 padding++;
330 packet->push_back(0);
331 }
332 while ((packet->size() % 4) != 0) {
333 padding++;
334 packet->push_back(0);
335 }
336 sdes_length += padding;
337
338 // In 32-bit words minus one and we don't count the header.
339 uint8 buffer_length = static_cast<uint8>((sdes_length / 4) - 1);
340 (*packet)[sdes_length_position] = buffer_length;
341 }
342
BuildPli(uint32 remote_ssrc,std::vector<uint8> * packet) const343 void RtcpSender::BuildPli(uint32 remote_ssrc,
344 std::vector<uint8>* packet) const {
345 size_t start_size = packet->size();
346 DCHECK_LT(start_size + 12, kIpPacketSize) << "Not enough buffer space";
347 if (start_size + 12 > kIpPacketSize) return;
348
349 packet->resize(start_size + 12);
350
351 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 12);
352 uint8 FMT = 1; // Picture loss indicator.
353 big_endian_writer.WriteU8(0x80 + FMT);
354 big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
355 big_endian_writer.WriteU16(2); // Used fixed length of 2.
356 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
357 big_endian_writer.WriteU32(remote_ssrc); // Add the remote SSRC.
358 }
359
360 /*
361 0 1 2 3
362 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
363 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
364 | PB |0| Payload Type| Native Rpsi bit string |
365 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
366 | defined per codec ... | Padding (0) |
367 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
368 */
BuildRpsi(const RtcpRpsiMessage * rpsi,std::vector<uint8> * packet) const369 void RtcpSender::BuildRpsi(const RtcpRpsiMessage* rpsi,
370 std::vector<uint8>* packet) const {
371 size_t start_size = packet->size();
372 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
373 if (start_size + 24 > kIpPacketSize) return;
374
375 packet->resize(start_size + 24);
376
377 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
378 uint8 FMT = 3; // Reference Picture Selection Indication.
379 big_endian_writer.WriteU8(0x80 + FMT);
380 big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
381
382 // Calculate length.
383 uint32 bits_required = 7;
384 uint8 bytes_required = 1;
385 while ((rpsi->picture_id >> bits_required) > 0) {
386 bits_required += 7;
387 bytes_required++;
388 }
389 uint8 size = 3;
390 if (bytes_required > 6) {
391 size = 5;
392 } else if (bytes_required > 2) {
393 size = 4;
394 }
395 big_endian_writer.WriteU8(0);
396 big_endian_writer.WriteU8(size);
397 big_endian_writer.WriteU32(ssrc_);
398 big_endian_writer.WriteU32(rpsi->remote_ssrc);
399
400 uint8 padding_bytes = 4 - ((2 + bytes_required) % 4);
401 if (padding_bytes == 4) {
402 padding_bytes = 0;
403 }
404 // Add padding length in bits, padding can be 0, 8, 16 or 24.
405 big_endian_writer.WriteU8(padding_bytes * 8);
406 big_endian_writer.WriteU8(rpsi->payload_type);
407
408 // Add picture ID.
409 for (int i = bytes_required - 1; i > 0; i--) {
410 big_endian_writer.WriteU8(
411 0x80 | static_cast<uint8>(rpsi->picture_id >> (i * 7)));
412 }
413 // Add last byte of picture ID.
414 big_endian_writer.WriteU8(static_cast<uint8>(rpsi->picture_id & 0x7f));
415
416 // Add padding.
417 for (int j = 0; j < padding_bytes; ++j) {
418 big_endian_writer.WriteU8(0);
419 }
420 }
421
BuildRemb(const RtcpRembMessage * remb,std::vector<uint8> * packet) const422 void RtcpSender::BuildRemb(const RtcpRembMessage* remb,
423 std::vector<uint8>* packet) const {
424 size_t start_size = packet->size();
425 size_t remb_size = 20 + 4 * remb->remb_ssrcs.size();
426 DCHECK_LT(start_size + remb_size, kIpPacketSize)
427 << "Not enough buffer space";
428 if (start_size + remb_size > kIpPacketSize) return;
429
430 packet->resize(start_size + remb_size);
431
432 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), remb_size);
433
434 // Add application layer feedback.
435 uint8 FMT = 15;
436 big_endian_writer.WriteU8(0x80 + FMT);
437 big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
438 big_endian_writer.WriteU8(0);
439 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size() + 4));
440 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
441 big_endian_writer.WriteU32(0); // Remote SSRC must be 0.
442 big_endian_writer.WriteU32(kRemb);
443 big_endian_writer.WriteU8(static_cast<uint8>(remb->remb_ssrcs.size()));
444
445 // 6 bit exponent and a 18 bit mantissa.
446 uint8 bitrate_exponent;
447 uint32 bitrate_mantissa;
448 BitrateToRembExponentBitrate(remb->remb_bitrate,
449 &bitrate_exponent,
450 &bitrate_mantissa);
451
452 big_endian_writer.WriteU8(static_cast<uint8>((bitrate_exponent << 2) +
453 ((bitrate_mantissa >> 16) & 0x03)));
454 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa >> 8));
455 big_endian_writer.WriteU8(static_cast<uint8>(bitrate_mantissa));
456
457 std::list<uint32>::const_iterator it = remb->remb_ssrcs.begin();
458 for (; it != remb->remb_ssrcs.end(); ++it) {
459 big_endian_writer.WriteU32(*it);
460 }
461 cast_environment_->Logging()->InsertGenericEvent(kRembBitrate,
462 remb->remb_bitrate);
463 }
464
BuildNack(const RtcpNackMessage * nack,std::vector<uint8> * packet) const465 void RtcpSender::BuildNack(const RtcpNackMessage* nack,
466 std::vector<uint8>* packet) const {
467 size_t start_size = packet->size();
468 DCHECK_LT(start_size + 16, kIpPacketSize) << "Not enough buffer space";
469 if (start_size + 16 > kIpPacketSize) return;
470
471 packet->resize(start_size + 16);
472
473 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 16);
474
475 uint8 FMT = 1;
476 big_endian_writer.WriteU8(0x80 + FMT);
477 big_endian_writer.WriteU8(kPacketTypeGenericRtpFeedback);
478 big_endian_writer.WriteU8(0);
479 size_t nack_size_pos = start_size + 3;
480 big_endian_writer.WriteU8(3);
481 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
482 big_endian_writer.WriteU32(nack->remote_ssrc); // Add the remote SSRC.
483
484 // Build NACK bitmasks and write them to the Rtcp message.
485 // The nack list should be sorted and not contain duplicates.
486 size_t number_of_nack_fields = 0;
487 size_t max_number_of_nack_fields = std::min<size_t>(kRtcpMaxNackFields,
488 (kIpPacketSize - packet->size()) / 4);
489
490 std::list<uint16>::const_iterator it = nack->nack_list.begin();
491 while (it != nack->nack_list.end() &&
492 number_of_nack_fields < max_number_of_nack_fields) {
493 uint16 nack_sequence_number = *it;
494 uint16 bitmask = 0;
495 ++it;
496 while (it != nack->nack_list.end()) {
497 int shift = static_cast<uint16>(*it - nack_sequence_number) - 1;
498 if (shift >= 0 && shift <= 15) {
499 bitmask |= (1 << shift);
500 ++it;
501 } else {
502 break;
503 }
504 }
505 // Write the sequence number and the bitmask to the packet.
506 start_size = packet->size();
507 DCHECK_LT(start_size + 4, kIpPacketSize) << "Not enough buffer space";
508 if (start_size + 4 > kIpPacketSize) return;
509
510 packet->resize(start_size + 4);
511 net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
512 big_endian_nack_writer.WriteU16(nack_sequence_number);
513 big_endian_nack_writer.WriteU16(bitmask);
514 number_of_nack_fields++;
515 }
516 DCHECK_GE(kRtcpMaxNackFields, number_of_nack_fields);
517 (*packet)[nack_size_pos] = static_cast<uint8>(2 + number_of_nack_fields);
518 }
519
BuildBye(std::vector<uint8> * packet) const520 void RtcpSender::BuildBye(std::vector<uint8>* packet) const {
521 size_t start_size = packet->size();
522 DCHECK_LT(start_size + 8, kIpPacketSize) << "Not enough buffer space";
523 if (start_size + 8 > kIpPacketSize) return;
524
525 packet->resize(start_size + 8);
526
527 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 8);
528 big_endian_writer.WriteU8(0x80 + 1);
529 big_endian_writer.WriteU8(kPacketTypeBye);
530 big_endian_writer.WriteU16(1); // Length.
531 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
532 }
533
534 /*
535 0 1 2 3
536 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
537 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 |V=2|P|reserved | PT=XR=207 | length |
539 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540 | SSRC |
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 | BT=5 | reserved | block length |
543 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
544 | SSRC_1 (SSRC of first receiver) | sub-
545 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
546 | last RR (LRR) | 1
547 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548 | delay since last RR (DLRR) |
549 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
550 */
BuildDlrrRb(const RtcpDlrrReportBlock * dlrr,std::vector<uint8> * packet) const551 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock* dlrr,
552 std::vector<uint8>* packet) const {
553 size_t start_size = packet->size();
554 DCHECK_LT(start_size + 24, kIpPacketSize) << "Not enough buffer space";
555 if (start_size + 24 > kIpPacketSize) return;
556
557 packet->resize(start_size + 24);
558
559 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 24);
560 big_endian_writer.WriteU8(0x80);
561 big_endian_writer.WriteU8(kPacketTypeXr);
562 big_endian_writer.WriteU16(5); // Length.
563 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
564 big_endian_writer.WriteU8(5); // Add block type.
565 big_endian_writer.WriteU8(0); // Add reserved.
566 big_endian_writer.WriteU16(3); // Block length.
567 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC.
568 big_endian_writer.WriteU32(dlrr->last_rr);
569 big_endian_writer.WriteU32(dlrr->delay_since_last_rr);
570 }
571
BuildRrtr(const RtcpReceiverReferenceTimeReport * rrtr,std::vector<uint8> * packet) const572 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr,
573 std::vector<uint8>* packet) const {
574 size_t start_size = packet->size();
575 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space";
576 if (start_size + 20 > kIpPacketSize) return;
577
578 packet->resize(start_size + 20);
579
580 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
581
582 big_endian_writer.WriteU8(0x80);
583 big_endian_writer.WriteU8(kPacketTypeXr);
584 big_endian_writer.WriteU16(4); // Length.
585 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
586 big_endian_writer.WriteU8(4); // Add block type.
587 big_endian_writer.WriteU8(0); // Add reserved.
588 big_endian_writer.WriteU16(2); // Block length.
589
590 // Add the media (received RTP) SSRC.
591 big_endian_writer.WriteU32(rrtr->ntp_seconds);
592 big_endian_writer.WriteU32(rrtr->ntp_fraction);
593 }
594
BuildCast(const RtcpCastMessage * cast,std::vector<uint8> * packet) const595 void RtcpSender::BuildCast(const RtcpCastMessage* cast,
596 std::vector<uint8>* packet) const {
597 size_t start_size = packet->size();
598 DCHECK_LT(start_size + 20, kIpPacketSize) << "Not enough buffer space";
599 if (start_size + 20 > kIpPacketSize) return;
600
601 packet->resize(start_size + 20);
602
603 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 20);
604 uint8 FMT = 15; // Application layer feedback.
605 big_endian_writer.WriteU8(0x80 + FMT);
606 big_endian_writer.WriteU8(kPacketTypePayloadSpecific);
607 big_endian_writer.WriteU8(0);
608 size_t cast_size_pos = start_size + 3; // Save length position.
609 big_endian_writer.WriteU8(4);
610 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
611 big_endian_writer.WriteU32(cast->media_ssrc_); // Remote SSRC.
612 big_endian_writer.WriteU32(kCast);
613 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id_));
614 size_t cast_loss_field_pos = start_size + 17; // Save loss field position.
615 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields.
616 big_endian_writer.WriteU8(0); // Reserved.
617 big_endian_writer.WriteU8(0); // Reserved.
618
619 size_t number_of_loss_fields = 0;
620 size_t max_number_of_loss_fields = std::min<size_t>(kRtcpMaxCastLossFields,
621 (kIpPacketSize - packet->size()) / 4);
622
623 MissingFramesAndPacketsMap::const_iterator frame_it =
624 cast->missing_frames_and_packets_.begin();
625
626 for (; frame_it != cast->missing_frames_and_packets_.end() &&
627 number_of_loss_fields < max_number_of_loss_fields; ++frame_it) {
628 // Iterate through all frames with missing packets.
629 if (frame_it->second.empty()) {
630 // Special case all packets in a frame is missing.
631 start_size = packet->size();
632 packet->resize(start_size + 4);
633 net::BigEndianWriter big_endian_nack_writer(&((*packet)[start_size]), 4);
634 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
635 big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost);
636 big_endian_nack_writer.WriteU8(0);
637 ++number_of_loss_fields;
638 } else {
639 PacketIdSet::const_iterator packet_it = frame_it->second.begin();
640 while (packet_it != frame_it->second.end()) {
641 uint16 packet_id = *packet_it;
642
643 start_size = packet->size();
644 packet->resize(start_size + 4);
645 net::BigEndianWriter big_endian_nack_writer(
646 &((*packet)[start_size]), 4);
647
648 // Write frame and packet id to buffer before calculating bitmask.
649 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first));
650 big_endian_nack_writer.WriteU16(packet_id);
651
652 uint8 bitmask = 0;
653 ++packet_it;
654 while (packet_it != frame_it->second.end()) {
655 int shift = static_cast<uint8>(*packet_it - packet_id) - 1;
656 if (shift >= 0 && shift <= 7) {
657 bitmask |= (1 << shift);
658 ++packet_it;
659 } else {
660 break;
661 }
662 }
663 big_endian_nack_writer.WriteU8(bitmask);
664 ++number_of_loss_fields;
665 }
666 }
667 }
668 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields);
669 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields);
670 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields);
671 }
672
BuildSenderLog(RtcpSenderLogMessage * sender_log_message,std::vector<uint8> * packet) const673 void RtcpSender::BuildSenderLog(RtcpSenderLogMessage* sender_log_message,
674 std::vector<uint8>* packet) const {
675 DCHECK(sender_log_message);
676 DCHECK(packet);
677 size_t start_size = packet->size();
678 size_t remaining_space = kIpPacketSize - start_size;
679 DCHECK_GE(remaining_space, kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize)
680 << "Not enough buffer space";
681 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpSenderFrameLogSize)
682 return;
683
684 size_t space_for_x_messages =
685 (remaining_space - kRtcpCastLogHeaderSize) / kRtcpSenderFrameLogSize;
686 size_t number_of_messages = std::min(space_for_x_messages,
687 sender_log_message->size());
688
689 size_t log_size = kRtcpCastLogHeaderSize +
690 number_of_messages * kRtcpSenderFrameLogSize;
691 packet->resize(start_size + log_size);
692
693 net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), log_size);
694 big_endian_writer.WriteU8(0x80 + kSenderLogSubtype);
695 big_endian_writer.WriteU8(kPacketTypeApplicationDefined);
696 big_endian_writer.WriteU16(static_cast<uint16>(2 + number_of_messages));
697 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
698 big_endian_writer.WriteU32(kCast);
699
700 for (; number_of_messages > 0; --number_of_messages) {
701 DCHECK(!sender_log_message->empty());
702 const RtcpSenderFrameLogMessage& message = sender_log_message->front();
703 big_endian_writer.WriteU8(static_cast<uint8>(message.frame_status));
704 // We send the 24 east significant bits of the RTP timestamp.
705 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 16));
706 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp >> 8));
707 big_endian_writer.WriteU8(static_cast<uint8>(message.rtp_timestamp));
708 sender_log_message->pop_front();
709 }
710 }
711
BuildReceiverLog(RtcpReceiverLogMessage * receiver_log_message,std::vector<uint8> * packet) const712 void RtcpSender::BuildReceiverLog(RtcpReceiverLogMessage* receiver_log_message,
713 std::vector<uint8>* packet) const {
714 DCHECK(receiver_log_message);
715 const size_t packet_start_size = packet->size();
716 size_t number_of_frames = 0;
717 size_t total_number_of_messages_to_send = 0;
718 size_t rtcp_log_size = 0;
719
720 if (!ScanRtcpReceiverLogMessage(*receiver_log_message,
721 packet_start_size,
722 &number_of_frames,
723 &total_number_of_messages_to_send,
724 &rtcp_log_size)) {
725 return;
726 }
727 packet->resize(packet_start_size + rtcp_log_size);
728
729 net::BigEndianWriter big_endian_writer(&((*packet)[packet_start_size]),
730 rtcp_log_size);
731 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype);
732 big_endian_writer.WriteU8(kPacketTypeApplicationDefined);
733 big_endian_writer.WriteU16(static_cast<uint16>(2 + 2 * number_of_frames +
734 total_number_of_messages_to_send));
735 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC.
736 big_endian_writer.WriteU32(kCast);
737
738 while (!receiver_log_message->empty() &&
739 total_number_of_messages_to_send > 0) {
740 RtcpReceiverFrameLogMessage& frame_log_messages =
741 receiver_log_message->front();
742 // Add our frame header.
743 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_);
744 size_t messages_in_frame = frame_log_messages.event_log_messages_.size();
745 if (messages_in_frame > total_number_of_messages_to_send) {
746 // We are running out of space.
747 messages_in_frame = total_number_of_messages_to_send;
748 }
749 // Keep track of how many messages we have left to send.
750 total_number_of_messages_to_send -= messages_in_frame;
751
752 // On the wire format is number of messages - 1.
753 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1));
754
755 base::TimeTicks event_timestamp_base =
756 frame_log_messages.event_log_messages_.front().event_timestamp;
757 uint32 base_timestamp_ms =
758 (event_timestamp_base - base::TimeTicks()).InMilliseconds();
759 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16));
760 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8));
761 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms));
762
763 while (!frame_log_messages.event_log_messages_.empty() &&
764 messages_in_frame > 0) {
765 const RtcpReceiverEventLogMessage& event_message =
766 frame_log_messages.event_log_messages_.front();
767 uint16 event_type_and_timestamp_delta =
768 MergeEventTypeAndTimestampForWireFormat(event_message.type,
769 event_message.event_timestamp - event_timestamp_base);
770 switch (event_message.type) {
771 case kAckSent:
772 case kAudioPlayoutDelay:
773 case kAudioFrameDecoded:
774 case kVideoFrameDecoded:
775 case kVideoRenderDelay:
776 big_endian_writer.WriteU16(static_cast<uint16>(
777 event_message.delay_delta.InMilliseconds()));
778 big_endian_writer.WriteU16(event_type_and_timestamp_delta);
779 break;
780 case kPacketReceived:
781 big_endian_writer.WriteU16(event_message.packet_id);
782 big_endian_writer.WriteU16(event_type_and_timestamp_delta);
783 break;
784 default:
785 NOTREACHED();
786 }
787 messages_in_frame--;
788 frame_log_messages.event_log_messages_.pop_front();
789 }
790 if (frame_log_messages.event_log_messages_.empty()) {
791 // We sent all messages on this frame; pop the frame header.
792 receiver_log_message->pop_front();
793 }
794 }
795 DCHECK_EQ(total_number_of_messages_to_send, 0);
796 }
797
798 } // namespace cast
799 } // namespace media
800