• 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/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