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