rtcp::ReceiverReport moved into own file and got Parse function

BUG=webrtc:5260
R=asapersson@webrtc.org

Review URL: https://codereview.webrtc.org/1453083002 .

Cr-Commit-Position: refs/heads/master@{#10897}
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 3d99253..5d7899c 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -308,6 +308,7 @@
                 'rtp_rtcp/source/rtcp_packet/bye_unittest.cc',
                 'rtp_rtcp/source/rtcp_packet/extended_jitter_report_unittest.cc',
                 'rtp_rtcp/source/rtcp_packet/pli_unittest.cc',
+                'rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc',
                 'rtp_rtcp/source/rtcp_packet/report_block_unittest.cc',
                 'rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc',
                 'rtp_rtcp/source/rtcp_receiver_unittest.cc',
diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn
index 9624658..21869b4 100644
--- a/webrtc/modules/rtp_rtcp/BUILD.gn
+++ b/webrtc/modules/rtp_rtcp/BUILD.gn
@@ -56,6 +56,8 @@
     "source/rtcp_packet/pli.h",
     "source/rtcp_packet/psfb.cc",
     "source/rtcp_packet/psfb.h",
+    "source/rtcp_packet/receiver_report.cc",
+    "source/rtcp_packet/receiver_report.h",
     "source/rtcp_packet/report_block.cc",
     "source/rtcp_packet/report_block.h",
     "source/rtcp_packet/transport_feedback.cc",
diff --git a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
index 1e69c12..a315b02 100644
--- a/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
+++ b/webrtc/modules/rtp_rtcp/rtp_rtcp.gypi
@@ -51,6 +51,8 @@
         'source/rtcp_packet/pli.h',
         'source/rtcp_packet/psfb.cc',
         'source/rtcp_packet/psfb.h',
+        'source/rtcp_packet/receiver_report.cc',
+        'source/rtcp_packet/receiver_report.h',
         'source/rtcp_packet/report_block.cc',
         'source/rtcp_packet/report_block.h',
         'source/rtcp_packet/transport_feedback.cc',
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
index d23abdc..41ebcad 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
@@ -21,7 +21,6 @@
 using webrtc::RTCPUtility::PT_APP;
 using webrtc::RTCPUtility::PT_IJ;
 using webrtc::RTCPUtility::PT_PSFB;
-using webrtc::RTCPUtility::PT_RR;
 using webrtc::RTCPUtility::PT_RTPFB;
 using webrtc::RTCPUtility::PT_SDES;
 using webrtc::RTCPUtility::PT_SR;
@@ -36,7 +35,6 @@
 using webrtc::RTCPUtility::RTCPPacketPSFBSLI;
 using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
 using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
-using webrtc::RTCPUtility::RTCPPacketRR;
 using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
 using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
@@ -119,21 +117,6 @@
   AssignUWord32(buffer, pos, sr.SenderOctetCount);
 }
 
-//  Receiver report (RR), header (RFC 3550).
-//
-//   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
-//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  |V=2|P|    RC   |   PT=RR=201   |             length            |
-//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  |                     SSRC of packet sender                     |
-//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-
-void CreateReceiverReport(const RTCPPacketRR& rr,
-                          uint8_t* buffer,
-                          size_t* pos) {
-  AssignUWord32(buffer, pos, rr.SenderSSRC);
-}
-
 //  Report block (RFC 3550).
 //
 //   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
@@ -681,30 +664,6 @@
   return true;
 }
 
-bool ReceiverReport::Create(uint8_t* packet,
-                            size_t* index,
-                            size_t max_length,
-                            RtcpPacket::PacketReadyCallback* callback) const {
-  while (*index + BlockLength() > max_length) {
-    if (!OnBufferFull(packet, index, callback))
-      return false;
-  }
-  CreateHeader(rr_.NumberOfReportBlocks, PT_RR, HeaderLength(), packet, index);
-  CreateReceiverReport(rr_, packet, index);
-  CreateReportBlocks(report_blocks_, packet, index);
-  return true;
-}
-
-bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
-  if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
-    LOG(LS_WARNING) << "Max report blocks reached.";
-    return false;
-  }
-  report_blocks_.push_back(block);
-  rr_.NumberOfReportBlocks = report_blocks_.size();
-  return true;
-}
-
 bool Sdes::Create(uint8_t* packet,
                   size_t* index,
                   size_t max_length,
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
index 39c2728..1f5e223 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
@@ -216,52 +216,6 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport);
 };
 
-//
-// RTCP receiver report (RFC 3550).
-//
-//   0                   1                   2                   3
-//   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
-//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  |V=2|P|    RC   |   PT=RR=201   |             length            |
-//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//  |                     SSRC of packet sender                     |
-//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//  |                         report block(s)                       |
-//  |                            ....                               |
-
-class ReceiverReport : public RtcpPacket {
- public:
-  ReceiverReport() : RtcpPacket() {
-    memset(&rr_, 0, sizeof(rr_));
-  }
-
-  virtual ~ReceiverReport() {}
-
-  void From(uint32_t ssrc) {
-    rr_.SenderSSRC = ssrc;
-  }
-  bool WithReportBlock(const ReportBlock& block);
-
- protected:
-  bool Create(uint8_t* packet,
-              size_t* index,
-              size_t max_length,
-              RtcpPacket::PacketReadyCallback* callback) const override;
-
- private:
-  static const int kMaxNumberOfReportBlocks = 0x1F;
-
-  size_t BlockLength() const {
-    const size_t kRrHeaderLength = 8;
-    return kRrHeaderLength + report_blocks_.size() * kReportBlockLength;
-  }
-
-  RTCPUtility::RTCPPacketRR rr_;
-  std::vector<ReportBlock> report_blocks_;
-
-  RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport);
-};
-
 // Source Description (SDES) (RFC 3550).
 //
 //         0                   1                   2                   3
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc
new file mode 100644
index 0000000..ef64b4f
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.cc
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
+
+using webrtc::RTCPUtility::RtcpCommonHeader;
+
+namespace webrtc {
+namespace rtcp {
+
+//
+// RTCP receiver report (RFC 3550).
+//
+//   0                   1                   2                   3
+//   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
+//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  |V=2|P|    RC   |   PT=RR=201   |             length            |
+//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//  |                     SSRC of packet sender                     |
+//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//  |                         report block(s)                       |
+//  |                            ....                               |
+bool ReceiverReport::Parse(const RTCPUtility::RtcpCommonHeader& header,
+                           const uint8_t* payload) {
+  RTC_DCHECK(header.packet_type == kPacketType);
+
+  const uint8_t report_blocks_count = header.count_or_format;
+
+  if (header.payload_size_bytes <
+      kRrBaseLength + report_blocks_count * ReportBlock::kLength) {
+    LOG(LS_WARNING) << "Packet is too small to contain all the data.";
+    return false;
+  }
+
+  sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload);
+
+  const uint8_t* next_report_block = payload + kRrBaseLength;
+
+  report_blocks_.resize(report_blocks_count);
+  for (ReportBlock& block : report_blocks_) {
+    block.Parse(next_report_block, ReportBlock::kLength);
+    next_report_block += ReportBlock::kLength;
+  }
+
+  RTC_DCHECK_LE(next_report_block, payload + header.payload_size_bytes);
+  return true;
+}
+
+bool ReceiverReport::Create(uint8_t* packet,
+                            size_t* index,
+                            size_t max_length,
+                            RtcpPacket::PacketReadyCallback* callback) const {
+  while (*index + BlockLength() > max_length) {
+    if (!OnBufferFull(packet, index, callback))
+      return false;
+  }
+  CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
+               index);
+  ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc_);
+  *index += kRrBaseLength;
+  for (const ReportBlock& block : report_blocks_) {
+    block.Create(packet + *index);
+    *index += ReportBlock::kLength;
+  }
+  return true;
+}
+
+bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
+  if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
+    LOG(LS_WARNING) << "Max report blocks reached.";
+    return false;
+  }
+  report_blocks_.push_back(block);
+  return true;
+}
+
+}  // namespace rtcp
+}  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h
new file mode 100644
index 0000000..172a84e
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_
+#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_
+
+#include <vector>
+
+#include "webrtc/base/basictypes.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+
+namespace webrtc {
+namespace rtcp {
+
+class ReceiverReport : public RtcpPacket {
+ public:
+  static const uint8_t kPacketType = 201;
+  ReceiverReport() : sender_ssrc_(0) {}
+
+  virtual ~ReceiverReport() {}
+
+  // Parse assumes header is already parsed and validated.
+  bool Parse(const RTCPUtility::RtcpCommonHeader& header,
+             const uint8_t* payload);  // Size of the payload is in the header.
+
+  void From(uint32_t ssrc) { sender_ssrc_ = ssrc; }
+  bool WithReportBlock(const ReportBlock& block);
+
+  uint32_t sender_ssrc() const { return sender_ssrc_; }
+  const std::vector<ReportBlock>& report_blocks() const {
+    return report_blocks_;
+  }
+
+ protected:
+  bool Create(uint8_t* packet,
+              size_t* index,
+              size_t max_length,
+              RtcpPacket::PacketReadyCallback* callback) const override;
+
+ private:
+  static const size_t kRrBaseLength = 4;
+  static const size_t kMaxNumberOfReportBlocks = 0x1F;
+
+  size_t BlockLength() const {
+    return kHeaderLength + kRrBaseLength +
+           report_blocks_.size() * ReportBlock::kLength;
+  }
+
+  uint32_t sender_ssrc_;
+  std::vector<ReportBlock> report_blocks_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport);
+};
+
+}  // namespace rtcp
+}  // namespace webrtc
+#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RECEIVER_REPORT_H_
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc
new file mode 100644
index 0000000..4fd329f
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report_unittest.cc
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using webrtc::rtcp::RawPacket;
+using webrtc::rtcp::ReceiverReport;
+using webrtc::rtcp::ReportBlock;
+using webrtc::RTCPUtility::RtcpCommonHeader;
+using webrtc::RTCPUtility::RtcpParseCommonHeader;
+
+namespace webrtc {
+namespace {
+const uint32_t kSenderSsrc = 0x12345678;
+const uint32_t kRemoteSsrc = 0x23456789;
+const uint8_t kFractionLost = 55;
+const uint32_t kCumulativeLost = 0x111213;
+const uint32_t kExtHighestSeqNum = 0x22232425;
+const uint32_t kJitter = 0x33343536;
+const uint32_t kLastSr = 0x44454647;
+const uint32_t kDelayLastSr = 0x55565758;
+// Manually created ReceiverReport with one ReportBlock matching constants
+// above.
+// Having this block allows to test Create and Parse separately.
+const uint8_t kPacket[] = {0x81, 201,  0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
+                           0x23, 0x45, 0x67, 0x89, 55,   0x11, 0x12, 0x13,
+                           0x22, 0x23, 0x24, 0x25, 0x33, 0x34, 0x35, 0x36,
+                           0x44, 0x45, 0x46, 0x47, 0x55, 0x56, 0x57, 0x58};
+const size_t kPacketLength = sizeof(kPacket);
+
+class RtcpPacketReceiverReportTest : public ::testing::Test {
+ protected:
+  void BuildPacket() { packet = rr.Build().Pass(); }
+  void ParsePacket() {
+    RtcpCommonHeader header;
+    EXPECT_TRUE(
+        RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header));
+    EXPECT_EQ(header.BlockSize(), packet->Length());
+    EXPECT_TRUE(parsed_.Parse(
+        header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes));
+  }
+
+  ReceiverReport rr;
+  rtc::scoped_ptr<RawPacket> packet;
+  const ReceiverReport& parsed() { return parsed_; }
+
+ private:
+  ReceiverReport parsed_;
+};
+
+TEST_F(RtcpPacketReceiverReportTest, Parse) {
+  RtcpCommonHeader header;
+  RtcpParseCommonHeader(kPacket, kPacketLength, &header);
+  EXPECT_TRUE(rr.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes));
+  const ReceiverReport& parsed = rr;
+
+  EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc());
+  EXPECT_EQ(1u, parsed.report_blocks().size());
+  const ReportBlock& rb = parsed.report_blocks().front();
+  EXPECT_EQ(kRemoteSsrc, rb.source_ssrc());
+  EXPECT_EQ(kFractionLost, rb.fraction_lost());
+  EXPECT_EQ(kCumulativeLost, rb.cumulative_lost());
+  EXPECT_EQ(kExtHighestSeqNum, rb.extended_high_seq_num());
+  EXPECT_EQ(kJitter, rb.jitter());
+  EXPECT_EQ(kLastSr, rb.last_sr());
+  EXPECT_EQ(kDelayLastSr, rb.delay_since_last_sr());
+}
+
+TEST_F(RtcpPacketReceiverReportTest, ParseFailsOnIncorrectSize) {
+  RtcpCommonHeader header;
+  RtcpParseCommonHeader(kPacket, kPacketLength, &header);
+  header.count_or_format++;  // Damage the packet.
+  EXPECT_FALSE(rr.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes));
+}
+
+TEST_F(RtcpPacketReceiverReportTest, Create) {
+  rr.From(kSenderSsrc);
+  ReportBlock rb;
+  rb.To(kRemoteSsrc);
+  rb.WithFractionLost(kFractionLost);
+  rb.WithCumulativeLost(kCumulativeLost);
+  rb.WithExtHighestSeqNum(kExtHighestSeqNum);
+  rb.WithJitter(kJitter);
+  rb.WithLastSr(kLastSr);
+  rb.WithDelayLastSr(kDelayLastSr);
+  rr.WithReportBlock(rb);
+
+  BuildPacket();
+
+  ASSERT_EQ(kPacketLength, packet->Length());
+  EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength));
+}
+
+TEST_F(RtcpPacketReceiverReportTest, WithoutReportBlocks) {
+  rr.From(kSenderSsrc);
+
+  BuildPacket();
+  ParsePacket();
+
+  EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc());
+  EXPECT_EQ(0u, parsed().report_blocks().size());
+}
+
+TEST_F(RtcpPacketReceiverReportTest, WithTwoReportBlocks) {
+  ReportBlock rb1;
+  rb1.To(kRemoteSsrc);
+  ReportBlock rb2;
+  rb2.To(kRemoteSsrc + 1);
+
+  rr.From(kSenderSsrc);
+  EXPECT_TRUE(rr.WithReportBlock(rb1));
+  EXPECT_TRUE(rr.WithReportBlock(rb2));
+
+  BuildPacket();
+  ParsePacket();
+
+  EXPECT_EQ(kSenderSsrc, parsed().sender_ssrc());
+  EXPECT_EQ(2u, parsed().report_blocks().size());
+  EXPECT_EQ(kRemoteSsrc, parsed().report_blocks()[0].source_ssrc());
+  EXPECT_EQ(kRemoteSsrc + 1, parsed().report_blocks()[1].source_ssrc());
+}
+
+TEST_F(RtcpPacketReceiverReportTest, WithTooManyReportBlocks) {
+  rr.From(kSenderSsrc);
+  const size_t kMaxReportBlocks = (1 << 5) - 1;
+  ReportBlock rb;
+  for (size_t i = 0; i < kMaxReportBlocks; ++i) {
+    rb.To(kRemoteSsrc + i);
+    EXPECT_TRUE(rr.WithReportBlock(rb));
+  }
+  rb.To(kRemoteSsrc + kMaxReportBlocks);
+  EXPECT_FALSE(rr.WithReportBlock(rb));
+}
+
+}  // namespace
+}  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
index 1743d99..dc2b113 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
@@ -16,6 +16,7 @@
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
 #include "webrtc/test/rtcp_packet_parser.h"
 
 using ::testing::ElementsAre;
@@ -26,16 +27,15 @@
 using webrtc::rtcp::Empty;
 using webrtc::rtcp::Fir;
 using webrtc::rtcp::Nack;
-using webrtc::rtcp::Sdes;
-using webrtc::rtcp::SenderReport;
-using webrtc::rtcp::Sli;
 using webrtc::rtcp::RawPacket;
 using webrtc::rtcp::ReceiverReport;
 using webrtc::rtcp::Remb;
 using webrtc::rtcp::ReportBlock;
 using webrtc::rtcp::Rpsi;
 using webrtc::rtcp::Rrtr;
+using webrtc::rtcp::Sdes;
 using webrtc::rtcp::SenderReport;
+using webrtc::rtcp::Sli;
 using webrtc::rtcp::Tmmbn;
 using webrtc::rtcp::Tmmbr;
 using webrtc::rtcp::VoipMetric;
@@ -47,81 +47,6 @@
 const uint32_t kSenderSsrc = 0x12345678;
 const uint32_t kRemoteSsrc = 0x23456789;
 
-TEST(RtcpPacketTest, Rr) {
-  ReceiverReport rr;
-  rr.From(kSenderSsrc);
-
-  rtc::scoped_ptr<RawPacket> packet(rr.Build());
-  RtcpPacketParser parser;
-  parser.Parse(packet->Buffer(), packet->Length());
-  EXPECT_EQ(1, parser.receiver_report()->num_packets());
-  EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc());
-  EXPECT_EQ(0, parser.report_block()->num_packets());
-}
-
-TEST(RtcpPacketTest, RrWithOneReportBlock) {
-  ReportBlock rb;
-  rb.To(kRemoteSsrc);
-  rb.WithFractionLost(55);
-  rb.WithCumulativeLost(0x111111);
-  rb.WithExtHighestSeqNum(0x22222222);
-  rb.WithJitter(0x33333333);
-  rb.WithLastSr(0x44444444);
-  rb.WithDelayLastSr(0x55555555);
-
-  ReceiverReport rr;
-  rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(rb));
-
-  rtc::scoped_ptr<RawPacket> packet(rr.Build());
-  RtcpPacketParser parser;
-  parser.Parse(packet->Buffer(), packet->Length());
-  EXPECT_EQ(1, parser.receiver_report()->num_packets());
-  EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc());
-  EXPECT_EQ(1, parser.report_block()->num_packets());
-  EXPECT_EQ(kRemoteSsrc, parser.report_block()->Ssrc());
-  EXPECT_EQ(55U, parser.report_block()->FractionLost());
-  EXPECT_EQ(0x111111U, parser.report_block()->CumPacketLost());
-  EXPECT_EQ(0x22222222U, parser.report_block()->ExtHighestSeqNum());
-  EXPECT_EQ(0x33333333U, parser.report_block()->Jitter());
-  EXPECT_EQ(0x44444444U, parser.report_block()->LastSr());
-  EXPECT_EQ(0x55555555U, parser.report_block()->DelayLastSr());
-}
-
-TEST(RtcpPacketTest, RrWithTwoReportBlocks) {
-  ReportBlock rb1;
-  rb1.To(kRemoteSsrc);
-  ReportBlock rb2;
-  rb2.To(kRemoteSsrc + 1);
-
-  ReceiverReport rr;
-  rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(rb1));
-  EXPECT_TRUE(rr.WithReportBlock(rb2));
-
-  rtc::scoped_ptr<RawPacket> packet(rr.Build());
-  RtcpPacketParser parser;
-  parser.Parse(packet->Buffer(), packet->Length());
-  EXPECT_EQ(1, parser.receiver_report()->num_packets());
-  EXPECT_EQ(kSenderSsrc, parser.receiver_report()->Ssrc());
-  EXPECT_EQ(2, parser.report_block()->num_packets());
-  EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc));
-  EXPECT_EQ(1, parser.report_blocks_per_ssrc(kRemoteSsrc + 1));
-}
-
-TEST(RtcpPacketTest, RrWithTooManyReportBlocks) {
-  ReceiverReport rr;
-  rr.From(kSenderSsrc);
-  const int kMaxReportBlocks = (1 << 5) - 1;
-  ReportBlock rb;
-  for (int i = 0; i < kMaxReportBlocks; ++i) {
-    rb.To(kRemoteSsrc + i);
-    EXPECT_TRUE(rr.WithReportBlock(rb));
-  }
-  rb.To(kRemoteSsrc + kMaxReportBlocks);
-  EXPECT_FALSE(rr.WithReportBlock(rb));
-}
-
 TEST(RtcpPacketTest, Sr) {
   SenderReport sr;
   sr.From(kSenderSsrc);
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index ac0389a..b75fb73 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -29,6 +29,7 @@
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
 
 namespace webrtc {
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
index 5add7cf..ac3f337 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -25,6 +25,7 @@
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"