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