root/media/cast/rtcp/test_rtcp_packet_builder.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. big_endian_writer_
  2. AddSr
  3. AddSrWithNtp
  4. AddRr
  5. AddRb
  6. AddSdesCname
  7. AddXrHeader
  8. AddXrUnknownBlock
  9. AddXrDlrrBlock
  10. AddXrExtendedDlrrBlock
  11. AddXrRrtrBlock
  12. AddNack
  13. AddSendReportRequest
  14. AddPli
  15. AddRpsi
  16. AddRemb
  17. AddCast
  18. AddSenderLog
  19. AddSenderFrameLog
  20. AddReceiverLog
  21. AddReceiverFrameLog
  22. AddReceiverEventLog
  23. GetPacket
  24. Data
  25. PatchLengthField
  26. AddRtcpHeader

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/cast/rtcp/test_rtcp_packet_builder.h"
#include "base/logging.h"

namespace media {
namespace cast {

TestRtcpPacketBuilder::TestRtcpPacketBuilder()
    : ptr_of_length_(NULL),
      big_endian_writer_(reinterpret_cast<char*>(buffer_), kMaxIpPacketSize) {}

void TestRtcpPacketBuilder::AddSr(uint32 sender_ssrc,
                                  int number_of_report_blocks) {
  AddRtcpHeader(200, number_of_report_blocks);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(kNtpHigh);  // NTP timestamp.
  big_endian_writer_.WriteU32(kNtpLow);
  big_endian_writer_.WriteU32(kRtpTimestamp);
  big_endian_writer_.WriteU32(kSendPacketCount);
  big_endian_writer_.WriteU32(kSendOctetCount);
}

void TestRtcpPacketBuilder::AddSrWithNtp(uint32 sender_ssrc,
                                         uint32 ntp_high,
                                         uint32 ntp_low,
                                         uint32 rtp_timestamp) {
  AddRtcpHeader(200, 0);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(ntp_high);
  big_endian_writer_.WriteU32(ntp_low);
  big_endian_writer_.WriteU32(rtp_timestamp);
  big_endian_writer_.WriteU32(kSendPacketCount);
  big_endian_writer_.WriteU32(kSendOctetCount);
}

void TestRtcpPacketBuilder::AddRr(uint32 sender_ssrc,
                                  int number_of_report_blocks) {
  AddRtcpHeader(201, number_of_report_blocks);
  big_endian_writer_.WriteU32(sender_ssrc);
}

void TestRtcpPacketBuilder::AddRb(uint32 rtp_ssrc) {
  big_endian_writer_.WriteU32(rtp_ssrc);
  big_endian_writer_.WriteU32(kLoss);
  big_endian_writer_.WriteU32(kExtendedMax);
  big_endian_writer_.WriteU32(kTestJitter);
  big_endian_writer_.WriteU32(kLastSr);
  big_endian_writer_.WriteU32(kDelayLastSr);
}

void TestRtcpPacketBuilder::AddSdesCname(uint32 sender_ssrc,
                                         const std::string& c_name) {
  AddRtcpHeader(202, 1);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU8(1);  // c_name.

  DCHECK_LE(c_name.size(), 255u);
  big_endian_writer_.WriteU8(
      static_cast<uint8>(c_name.size()));  // c_name length in bytes.
  for (size_t i = 0; i < c_name.size(); ++i) {
    big_endian_writer_.WriteU8(c_name.c_str()[i]);
  }
  int padding;
  switch (c_name.size() % 4) {
    case 0:
      padding = 2;
      break;
    case 1:
      padding = 1;
      break;
    case 2:
      padding = 4;
      break;
    case 3:
      padding = 3;
      break;
  }
  for (int j = 0; j < padding; ++j) {
    big_endian_writer_.WriteU8(0);
  }
}

void TestRtcpPacketBuilder::AddXrHeader(uint32 sender_ssrc) {
  AddRtcpHeader(207, 0);
  big_endian_writer_.WriteU32(sender_ssrc);
}

void TestRtcpPacketBuilder::AddXrUnknownBlock() {
  big_endian_writer_.WriteU8(9);   // Block type.
  big_endian_writer_.WriteU8(0);   // Reserved.
  big_endian_writer_.WriteU16(4);  // Block length.
  // First receiver same as sender of this report.
  big_endian_writer_.WriteU32(0);
  big_endian_writer_.WriteU32(0);
  big_endian_writer_.WriteU32(0);
  big_endian_writer_.WriteU32(0);
}

void TestRtcpPacketBuilder::AddXrDlrrBlock(uint32 sender_ssrc) {
  big_endian_writer_.WriteU8(5);   // Block type.
  big_endian_writer_.WriteU8(0);   // Reserved.
  big_endian_writer_.WriteU16(3);  // Block length.

  // First receiver same as sender of this report.
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(kLastRr);
  big_endian_writer_.WriteU32(kDelayLastRr);
}

void TestRtcpPacketBuilder::AddXrExtendedDlrrBlock(uint32 sender_ssrc) {
  big_endian_writer_.WriteU8(5);   // Block type.
  big_endian_writer_.WriteU8(0);   // Reserved.
  big_endian_writer_.WriteU16(9);  // Block length.
  big_endian_writer_.WriteU32(0xaaaaaaaa);
  big_endian_writer_.WriteU32(0xaaaaaaaa);
  big_endian_writer_.WriteU32(0xaaaaaaaa);

  // First receiver same as sender of this report.
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(kLastRr);
  big_endian_writer_.WriteU32(kDelayLastRr);
  big_endian_writer_.WriteU32(0xbbbbbbbb);
  big_endian_writer_.WriteU32(0xbbbbbbbb);
  big_endian_writer_.WriteU32(0xbbbbbbbb);
}

void TestRtcpPacketBuilder::AddXrRrtrBlock() {
  big_endian_writer_.WriteU8(4);   // Block type.
  big_endian_writer_.WriteU8(0);   // Reserved.
  big_endian_writer_.WriteU16(2);  // Block length.
  big_endian_writer_.WriteU32(kNtpHigh);
  big_endian_writer_.WriteU32(kNtpLow);
}

void TestRtcpPacketBuilder::AddNack(uint32 sender_ssrc, uint32 media_ssrc) {
  AddRtcpHeader(205, 1);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(media_ssrc);
  big_endian_writer_.WriteU16(kMissingPacket);
  big_endian_writer_.WriteU16(0);
}

void TestRtcpPacketBuilder::AddSendReportRequest(uint32 sender_ssrc,
                                                 uint32 media_ssrc) {
  AddRtcpHeader(205, 5);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(media_ssrc);
}

void TestRtcpPacketBuilder::AddPli(uint32 sender_ssrc, uint32 media_ssrc) {
  AddRtcpHeader(206, 1);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(media_ssrc);
}

void TestRtcpPacketBuilder::AddRpsi(uint32 sender_ssrc, uint32 media_ssrc) {
  AddRtcpHeader(206, 3);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(media_ssrc);
  big_endian_writer_.WriteU8(0);  // Padding bits.
  big_endian_writer_.WriteU8(kPayloadtype);
  uint64 picture_id = kPictureId;

  for (int i = 9; i > 0; i--) {
    big_endian_writer_.WriteU8(0x80 |
                               static_cast<uint8>(picture_id >> (i * 7)));
  }
  // Add last byte of picture ID.
  big_endian_writer_.WriteU8(static_cast<uint8>(picture_id & 0x7f));
}

void TestRtcpPacketBuilder::AddRemb(uint32 sender_ssrc, uint32 media_ssrc) {
  AddRtcpHeader(206, 15);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(0);
  big_endian_writer_.WriteU8('R');
  big_endian_writer_.WriteU8('E');
  big_endian_writer_.WriteU8('M');
  big_endian_writer_.WriteU8('B');
  big_endian_writer_.WriteU8(1);  // Number of SSRCs.
  big_endian_writer_.WriteU8(1);  // BR Exp.
  //  BR Mantissa.
  big_endian_writer_.WriteU16(static_cast<uint16>(kTestRembBitrate / 2));
  big_endian_writer_.WriteU32(media_ssrc);
}

void TestRtcpPacketBuilder::AddCast(uint32 sender_ssrc,
                                    uint32 media_ssrc,
                                    uint16 target_delay_ms) {
  AddRtcpHeader(206, 15);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU32(media_ssrc);
  big_endian_writer_.WriteU8('C');
  big_endian_writer_.WriteU8('A');
  big_endian_writer_.WriteU8('S');
  big_endian_writer_.WriteU8('T');
  big_endian_writer_.WriteU8(kAckFrameId);
  big_endian_writer_.WriteU8(3);     // Loss fields.
  big_endian_writer_.WriteU16(target_delay_ms);
  big_endian_writer_.WriteU8(kLostFrameId);
  big_endian_writer_.WriteU16(kRtcpCastAllPacketsLost);
  big_endian_writer_.WriteU8(0);  // Lost packet id mask.
  big_endian_writer_.WriteU8(kFrameIdWithLostPackets);
  big_endian_writer_.WriteU16(kLostPacketId1);
  big_endian_writer_.WriteU8(0x2);  // Lost packet id mask.
  big_endian_writer_.WriteU8(kFrameIdWithLostPackets);
  big_endian_writer_.WriteU16(kLostPacketId3);
  big_endian_writer_.WriteU8(0);  // Lost packet id mask.
}

void TestRtcpPacketBuilder::AddSenderLog(uint32 sender_ssrc) {
  AddRtcpHeader(204, 1);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU8('C');
  big_endian_writer_.WriteU8('A');
  big_endian_writer_.WriteU8('S');
  big_endian_writer_.WriteU8('T');
}

void TestRtcpPacketBuilder::AddSenderFrameLog(uint8 event_id,
                                              uint32 rtp_timestamp) {
  big_endian_writer_.WriteU32((static_cast<uint32>(event_id) << 24) +
                              (rtp_timestamp & 0xffffff));
}

void TestRtcpPacketBuilder::AddReceiverLog(uint32 sender_ssrc) {
  AddRtcpHeader(204, 2);
  big_endian_writer_.WriteU32(sender_ssrc);
  big_endian_writer_.WriteU8('C');
  big_endian_writer_.WriteU8('A');
  big_endian_writer_.WriteU8('S');
  big_endian_writer_.WriteU8('T');
}

void TestRtcpPacketBuilder::AddReceiverFrameLog(uint32 rtp_timestamp,
                                                int num_events,
                                                uint32 event_timesamp_base) {
  big_endian_writer_.WriteU32(rtp_timestamp);
  big_endian_writer_.WriteU8(static_cast<uint8>(num_events - 1));
  big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base >> 16));
  big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base >> 8));
  big_endian_writer_.WriteU8(static_cast<uint8>(event_timesamp_base));
}

void TestRtcpPacketBuilder::AddReceiverEventLog(uint16 event_data,
                                                uint8 event_id,
                                                uint16 event_timesamp_delta) {
  big_endian_writer_.WriteU16(event_data);
  uint16 type_and_delta = static_cast<uint16>(event_id) << 12;
  type_and_delta += event_timesamp_delta & 0x0fff;
  big_endian_writer_.WriteU16(type_and_delta);
}

scoped_ptr<media::cast::Packet> TestRtcpPacketBuilder::GetPacket() {
  PatchLengthField();
  return scoped_ptr<media::cast::Packet>(
      new media::cast::Packet(buffer_, buffer_ + Length()));
}

const uint8* TestRtcpPacketBuilder::Data() {
  PatchLengthField();
  return buffer_;
}

void TestRtcpPacketBuilder::PatchLengthField() {
  if (ptr_of_length_) {
    // Back-patch the packet length. The client must have taken
    // care of proper padding to 32-bit words.
    int this_packet_length = (big_endian_writer_.ptr() - ptr_of_length_ - 2);
    DCHECK_EQ(0, this_packet_length % 4)
        << "Packets must be a multiple of 32 bits long";
    *ptr_of_length_ = this_packet_length >> 10;
    *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF;
    ptr_of_length_ = NULL;
  }
}

// Set the 5-bit value in the 1st byte of the header
// and the payload type. Set aside room for the length field,
// and make provision for back-patching it.
void TestRtcpPacketBuilder::AddRtcpHeader(int payload, int format_or_count) {
  PatchLengthField();
  big_endian_writer_.WriteU8(0x80 | (format_or_count & 0x1F));
  big_endian_writer_.WriteU8(payload);
  ptr_of_length_ = big_endian_writer_.ptr();

  // Initialize length to "clearly illegal".
  big_endian_writer_.WriteU16(0xDEAD);
}

}  // namespace cast
}  // namespace media

/* [<][>][^][v][top][bottom][index][help] */