Use RtcpPacket classes for SenderReport/ReceiveReport in RTCPSender

BUG=2450
R=asapersson@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#9483}
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
index 07ce336..7038532 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.cc
@@ -810,13 +810,12 @@
   return true;
 }
 
-bool SenderReport::WithReportBlock(ReportBlock* block) {
-  assert(block);
+bool SenderReport::WithReportBlock(const ReportBlock& block) {
   if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
     LOG(LS_WARNING) << "Max report blocks reached.";
     return false;
   }
-  report_blocks_.push_back(block->report_block_);
+  report_blocks_.push_back(block.report_block_);
   sr_.NumberOfReportBlocks = report_blocks_.size();
   return true;
 }
@@ -834,13 +833,12 @@
   return true;
 }
 
-bool ReceiverReport::WithReportBlock(ReportBlock* block) {
-  assert(block);
+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->report_block_);
+  report_blocks_.push_back(block.report_block_);
   rr_.NumberOfReportBlocks = report_blocks_.size();
   return true;
 }
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
index ffa3e0d..d212497 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet.h
@@ -234,7 +234,7 @@
   void WithOctetCount(uint32_t octet_count) {
     sr_.SenderOctetCount = octet_count;
   }
-  bool WithReportBlock(ReportBlock* block);
+  bool WithReportBlock(const ReportBlock& block);
 
  protected:
   bool Create(uint8_t* packet,
@@ -282,7 +282,7 @@
   void From(uint32_t ssrc) {
     rr_.SenderSSRC = ssrc;
   }
-  bool WithReportBlock(ReportBlock* block);
+  bool WithReportBlock(const ReportBlock& block);
 
  protected:
   bool Create(uint8_t* packet,
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
index f2ff1cc..0097159 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet_unittest.cc
@@ -71,7 +71,7 @@
 
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
 
   rtc::scoped_ptr<RawPacket> packet(rr.Build());
   RtcpPacketParser parser;
@@ -96,8 +96,8 @@
 
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb1));
-  EXPECT_TRUE(rr.WithReportBlock(&rb2));
+  EXPECT_TRUE(rr.WithReportBlock(rb1));
+  EXPECT_TRUE(rr.WithReportBlock(rb2));
 
   rtc::scoped_ptr<RawPacket> packet(rr.Build());
   RtcpPacketParser parser;
@@ -116,10 +116,10 @@
   ReportBlock rb;
   for (int i = 0; i < kMaxReportBlocks; ++i) {
     rb.To(kRemoteSsrc + i);
-    EXPECT_TRUE(rr.WithReportBlock(&rb));
+    EXPECT_TRUE(rr.WithReportBlock(rb));
   }
   rb.To(kRemoteSsrc + kMaxReportBlocks);
-  EXPECT_FALSE(rr.WithReportBlock(&rb));
+  EXPECT_FALSE(rr.WithReportBlock(rb));
 }
 
 TEST(RtcpPacketTest, Sr) {
@@ -151,7 +151,7 @@
 
   SenderReport sr;
   sr.From(kSenderSsrc);
-  EXPECT_TRUE(sr.WithReportBlock(&rb));
+  EXPECT_TRUE(sr.WithReportBlock(rb));
 
   rtc::scoped_ptr<RawPacket> packet(sr.Build());
   RtcpPacketParser parser;
@@ -170,8 +170,8 @@
 
   SenderReport sr;
   sr.From(kSenderSsrc);
-  EXPECT_TRUE(sr.WithReportBlock(&rb1));
-  EXPECT_TRUE(sr.WithReportBlock(&rb2));
+  EXPECT_TRUE(sr.WithReportBlock(rb1));
+  EXPECT_TRUE(sr.WithReportBlock(rb2));
 
   rtc::scoped_ptr<RawPacket> packet(sr.Build());
   RtcpPacketParser parser;
@@ -190,10 +190,10 @@
   ReportBlock rb;
   for (int i = 0; i < kMaxReportBlocks; ++i) {
     rb.To(kRemoteSsrc + i);
-    EXPECT_TRUE(sr.WithReportBlock(&rb));
+    EXPECT_TRUE(sr.WithReportBlock(rb));
   }
   rb.To(kRemoteSsrc + kMaxReportBlocks);
-  EXPECT_FALSE(sr.WithReportBlock(&rb));
+  EXPECT_FALSE(sr.WithReportBlock(rb));
 }
 
 TEST(RtcpPacketTest, IjNoItem) {
@@ -567,7 +567,7 @@
   ReportBlock rb;
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
   rr.Append(&fir);
 
   rtc::scoped_ptr<RawPacket> packet(rr.Build());
@@ -598,7 +598,7 @@
   ReportBlock rb;
 
   ReceiverReport rr;
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
   rr.Append(&fir);
 
   SenderReport sr;
@@ -657,7 +657,7 @@
   ReportBlock rb;
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
   rr.Append(&fir);
 
   const size_t kRrLength = 8;
@@ -687,7 +687,7 @@
   ReportBlock rb;
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
 
   const size_t kRrLength = 8;
   const size_t kReportBlockLength = 24;
@@ -708,7 +708,7 @@
   ReportBlock rb;
   ReceiverReport rr;
   rr.From(kSenderSsrc);
-  EXPECT_TRUE(rr.WithReportBlock(&rb));
+  EXPECT_TRUE(rr.WithReportBlock(rb));
   rr.Append(&fir);
 
   const size_t kRrLength = 8;
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index ad1970c..40db251 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -197,7 +197,7 @@
   rb.To(kSourceSsrc + 1);
   rtcp::ReceiverReport rr;
   rr.From(kSenderSsrc);
-  rr.WithReportBlock(&rb);
+  rr.WithReportBlock(rb);
   rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
   EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
   EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
@@ -220,7 +220,7 @@
   rb.To(kSourceSsrc);
   rtcp::ReceiverReport rr;
   rr.From(kSenderSsrc);
-  rr.WithReportBlock(&rb);
+  rr.WithReportBlock(rb);
   rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
   EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
   EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
@@ -255,8 +255,8 @@
 
   rtcp::ReceiverReport rr1;
   rr1.From(kSenderSsrc);
-  rr1.WithReportBlock(&rb1);
-  rr1.WithReportBlock(&rb2);
+  rr1.WithReportBlock(rb1);
+  rr1.WithReportBlock(rb2);
 
   rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
@@ -278,8 +278,8 @@
 
   rtcp::ReceiverReport rr2;
   rr2.From(kSenderSsrc);
-  rr2.WithReportBlock(&rb3);
-  rr2.WithReportBlock(&rb4);
+  rr2.WithReportBlock(rb3);
+  rr2.WithReportBlock(rb4);
 
   rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
@@ -318,7 +318,7 @@
   rb1.WithCumulativeLost(kCumLost[0]);
   rtcp::ReceiverReport rr1;
   rr1.From(kSenderSsrc1);
-  rr1.WithReportBlock(&rb1);
+  rr1.WithReportBlock(rb1);
 
   rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
@@ -341,7 +341,7 @@
   rb2.WithCumulativeLost(kCumLost[1]);
   rtcp::ReceiverReport rr2;
   rr2.From(kSenderSsrc2);
-  rr2.WithReportBlock(&rb2);
+  rr2.WithReportBlock(rb2);
   rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
   ASSERT_EQ(1u, rtcp_packet_info_.report_blocks.size());
@@ -374,7 +374,7 @@
   rb.To(kSourceSsrc);
   rtcp::ReceiverReport rr;
   rr.From(kSenderSsrc);
-  rr.WithReportBlock(&rb);
+  rr.WithReportBlock(rb);
   rtc::scoped_ptr<rtcp::RawPacket> packet(rr.Build());
   EXPECT_EQ(0, InjectRtcpPacket(packet->Buffer(), packet->Length()));
   EXPECT_EQ(kSenderSsrc, rtcp_packet_info_.remoteSSRC);
@@ -484,8 +484,8 @@
   rb2.To(kSourceSsrcs[1]);
   rtcp::ReceiverReport rr;
   rr.From(kSenderSsrc);
-  rr.WithReportBlock(&rb1);
-  rr.WithReportBlock(&rb2);
+  rr.WithReportBlock(rb1);
+  rr.WithReportBlock(rb2);
 
   rtc::scoped_ptr<rtcp::RawPacket> p1(rr.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
@@ -802,7 +802,7 @@
   rb1.WithExtHighestSeqNum(kSequenceNumber);
   rtcp::ReceiverReport rr1;
   rr1.From(kSenderSsrc);
-  rr1.WithReportBlock(&rb1);
+  rr1.WithReportBlock(rb1);
   rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
   system_clock_.AdvanceTimeMilliseconds(3 * kRtcpIntervalMs - 1);
@@ -831,7 +831,7 @@
   rb2.WithExtHighestSeqNum(kSequenceNumber + 1);
   rtcp::ReceiverReport rr2;
   rr2.From(kSenderSsrc);
-  rr2.WithReportBlock(&rb2);
+  rr2.WithReportBlock(rb2);
   rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
   EXPECT_FALSE(rtcp_receiver_->RtcpRrTimeout(kRtcpIntervalMs));
@@ -1008,7 +1008,7 @@
 
   rtcp::ReceiverReport rr1;
   rr1.From(kSenderSsrc);
-  rr1.WithReportBlock(&rb1);
+  rr1.WithReportBlock(rb1);
   rtc::scoped_ptr<rtcp::RawPacket> p1(rr1.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p1->Buffer(), p1->Length()));
   EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss,
@@ -1026,7 +1026,7 @@
 
   rtcp::ReceiverReport rr2;
   rr2.From(kSenderSsrc);
-  rr2.WithReportBlock(&rb2);
+  rr2.WithReportBlock(rb2);
   rtc::scoped_ptr<rtcp::RawPacket> p2(rr2.Build());
   EXPECT_EQ(0, InjectRtcpPacket(p2->Buffer(), p2->Length()));
   EXPECT_TRUE(callback.Matches(kSourceSsrc, kSequenceNumber, kFractionLoss,
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
index a104fec..11ff4b3 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -113,6 +113,20 @@
   uint32_t position;
 };
 
+// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
+class RTCPSender::PacketBuiltCallback
+    : public rtcp::RtcpPacket::PacketReadyCallback {
+ public:
+  PacketBuiltCallback(RtcpContext* context) : context_(context) {}
+  virtual ~PacketBuiltCallback() {}
+  void OnPacketReady(uint8_t* data, size_t length) override {
+    context_->position += length;
+  }
+
+ private:
+  RtcpContext* const context_;
+};
+
 RTCPSender::RTCPSender(
     int32_t id,
     bool audio,
@@ -150,6 +164,7 @@
       packet_oh_send_(0),
 
       app_sub_type_(0),
+      app_name_(0),
       app_data_(nullptr),
       app_length_(0),
 
@@ -181,9 +196,6 @@
 }
 
 RTCPSender::~RTCPSender() {
-  for (auto it : internal_report_blocks_)
-    delete it.second;
-
   for (auto it : csrc_cnames_)
     delete it.second;
 }
@@ -465,42 +477,24 @@
   return true;
 }
 
-int32_t RTCPSender::AddReportBlock(
-    uint32_t SSRC,
-    std::map<uint32_t, RTCPReportBlock*>* report_blocks,
-    const RTCPReportBlock* reportBlock) {
-  assert(reportBlock);
-
-  if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
+int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
+  if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
     LOG(LS_WARNING) << "Too many report blocks.";
     return -1;
   }
-  std::map<uint32_t, RTCPReportBlock*>::iterator it =
-      report_blocks->find(SSRC);
-  if (it != report_blocks->end()) {
-    delete it->second;
-    report_blocks->erase(it);
-  }
-  RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
-  memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
-  (*report_blocks)[SSRC] = copyReportBlock;
+  rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
+  block->To(report_block.remoteSSRC);
+  block->WithFractionLost(report_block.fractionLost);
+  block->WithCumulativeLost(report_block.cumulativeLost);
+  block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
+  block->WithJitter(report_block.jitter);
+  block->WithLastSr(report_block.lastSR);
+  block->WithDelayLastSr(report_block.delaySinceLastSR);
+
   return 0;
 }
 
 RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
-  // sanity
-  if (ctx->position + 52 >= IP_PACKET_SIZE) {
-    LOG(LS_WARNING) << "Failed to build Sender Report.";
-    return BuildResult::kTruncated;
-  }
-  uint32_t RTPtime;
-
-  uint32_t posNumberOfReportBlocks = ctx->position;
-  *ctx->AllocateData(1) = 0x80;
-
-  // Sender report
-  *ctx->AllocateData(1) = 200;
-
   for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
     // shift old
     last_send_report_[i + 1] = last_send_report_[i];
@@ -514,47 +508,30 @@
   // the frame being captured at this moment. We are calculating that
   // timestamp as the last frame's timestamp + the time since the last frame
   // was captured.
-  RTPtime = start_timestamp_ + last_rtp_timestamp_ +
-            (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
-                (ctx->feedback_state.frequency_hz / 1000);
+  uint32_t rtp_timestamp =
+      start_timestamp_ + last_rtp_timestamp_ +
+      (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
+          (ctx->feedback_state.frequency_hz / 1000);
 
-  // Add sender data
-  // Save  for our length field
-  ctx->AllocateData(2);
+  rtcp::SenderReport report;
+  report.From(ssrc_);
+  report.WithNtpSec(ctx->ntp_sec);
+  report.WithNtpFrac(ctx->ntp_frac);
+  report.WithRtpTimestamp(rtp_timestamp);
+  report.WithPacketCount(ctx->feedback_state.packets_sent);
+  report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
 
-  // Add our own SSRC
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
-  // NTP
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), RTPtime);
+  for (auto it : report_blocks_)
+    report.WithReportBlock(it.second);
 
-  // sender's packet count
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                       ctx->feedback_state.packets_sent);
-
-  // sender's octet count
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                       ctx->feedback_state.media_bytes_sent);
-
-  uint8_t numberOfReportBlocks = 0;
-  BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
-  switch (result) {
-    case BuildResult::kError:
-    case BuildResult::kTruncated:
-    case BuildResult::kAborted:
-      return result;
-    case BuildResult::kSuccess:
-      break;
-    default:
-      abort();
+  PacketBuiltCallback callback(ctx);
+  if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
+                                  ctx->buffer_size - ctx->position,
+                                  &callback)) {
+    return BuildResult::kTruncated;
   }
 
-  ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
-
-  uint16_t len = static_cast<uint16_t>((ctx->position / 4) - 1);
-  ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[2], len);
-
+  report_blocks_.clear();
   return BuildResult::kSuccess;
 }
 
@@ -636,39 +613,19 @@
 }
 
 RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
-  // sanity one block
-  if (ctx->position + 32 >= IP_PACKET_SIZE)
+  rtcp::ReceiverReport report;
+  report.From(ssrc_);
+  for (auto it : report_blocks_)
+    report.WithReportBlock(it.second);
+
+  PacketBuiltCallback callback(ctx);
+  if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
+                                  ctx->buffer_size - ctx->position,
+                                  &callback)) {
     return BuildResult::kTruncated;
-
-  uint32_t posNumberOfReportBlocks = ctx->position;
-
-  *ctx->AllocateData(1) = 0x80;
-  *ctx->AllocateData(1) = 201;
-
-  // Save  for our length field
-  uint32_t len_pos = ctx->position;
-  ctx->AllocateData(2);
-
-  // Add our own SSRC
-  ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
-
-  uint8_t numberOfReportBlocks = 0;
-  BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
-  switch (result) {
-    case BuildResult::kError:
-    case BuildResult::kTruncated:
-    case BuildResult::kAborted:
-      return result;
-    case BuildResult::kSuccess:
-      break;
-    default:
-      abort();
   }
 
-  ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
-
-  uint16_t len = uint16_t((ctx->position) / 4 - 1);
-  ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[len_pos], len);
+  report_blocks_.clear();
 
   return BuildResult::kSuccess;
 }
@@ -1491,9 +1448,9 @@
     if (!statisticians.empty()) {
       for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
         RTCPReportBlock report_block;
-        if (PrepareReport(feedback_state, it->second, &report_block,
-                          &context.ntp_sec, &context.ntp_frac)) {
-          AddReportBlock(it->first, &internal_report_blocks_, &report_block);
+        if (PrepareReport(feedback_state, it->first, it->second,
+                          &report_block)) {
+          AddReportBlock(report_block);
         }
       }
       if (extended_jitter_report_enabled_)
@@ -1539,9 +1496,9 @@
 }
 
 bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
+                               uint32_t ssrc,
                                StreamStatistician* statistician,
-                               RTCPReportBlock* report_block,
-                               uint32_t* ntp_secs, uint32_t* ntp_frac) {
+                               RTCPReportBlock* report_block) {
   // Do we have receive statistics to send?
   RtcpStatistics stats;
   if (!statistician->GetStatistics(&stats, true))
@@ -1551,18 +1508,22 @@
   report_block->extendedHighSeqNum =
       stats.extended_max_sequence_number;
   report_block->jitter = stats.jitter;
+  report_block->remoteSSRC = ssrc;
 
-  // get our NTP as late as possible to avoid a race
-  clock_->CurrentNtp(*ntp_secs, *ntp_frac);
+  // TODO(sprang): Do we really need separate time stamps for each report?
+  // Get our NTP as late as possible to avoid a race.
+  uint32_t ntp_secs;
+  uint32_t ntp_frac;
+  clock_->CurrentNtp(ntp_secs, ntp_frac);
 
-  // Delay since last received report
+  // Delay since last received report.
   uint32_t delaySinceLastReceivedSR = 0;
   if ((feedback_state.last_rr_ntp_secs != 0) ||
       (feedback_state.last_rr_ntp_frac != 0)) {
-    // get the 16 lowest bits of seconds and the 16 higest bits of fractions
-    uint32_t now = *ntp_secs & 0x0000FFFF;
+    // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
+    uint32_t now = ntp_secs & 0x0000FFFF;
     now <<= 16;
-    now += (*ntp_frac & 0xffff0000) >> 16;
+    now += (ntp_frac & 0xffff0000) >> 16;
 
     uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
     receiveTime <<= 16;
@@ -1627,59 +1588,6 @@
   return xr_send_receiver_reference_time_enabled_;
 }
 
-// called under critsect critical_section_rtcp_sender_
-RTCPSender::BuildResult RTCPSender::WriteAllReportBlocksToBuffer(
-    RtcpContext* ctx,
-    uint8_t* numberOfReportBlocks) {
-  *numberOfReportBlocks = internal_report_blocks_.size();
-  if ((ctx->position + *numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
-    LOG(LS_WARNING) << "Can't fit all report blocks.";
-    return BuildResult::kError;
-  }
-  WriteReportBlocksToBuffer(ctx, internal_report_blocks_);
-  while (!internal_report_blocks_.empty()) {
-    delete internal_report_blocks_.begin()->second;
-    internal_report_blocks_.erase(internal_report_blocks_.begin());
-  }
-  return BuildResult::kSuccess;
-}
-
-void RTCPSender::WriteReportBlocksToBuffer(
-    RtcpContext* ctx,
-    const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
-  std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
-      report_blocks.begin();
-  for (; it != report_blocks.end(); it++) {
-    uint32_t remoteSSRC = it->first;
-    RTCPReportBlock* reportBlock = it->second;
-    if (reportBlock) {
-      // Remote SSRC
-      ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remoteSSRC);
-
-      // fraction lost
-      *ctx->AllocateData(1) = reportBlock->fractionLost;
-
-      // cumulative loss
-      ByteWriter<uint32_t, 3>::WriteBigEndian(ctx->AllocateData(3),
-                                              reportBlock->cumulativeLost);
-
-      // extended highest seq_no, contain the highest sequence number received
-      ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                           reportBlock->extendedHighSeqNum);
-
-      // Jitter
-      ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                           reportBlock->jitter);
-
-      ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                           reportBlock->lastSR);
-
-      ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
-                                           reportBlock->delaySinceLastSR);
-    }
-  }
-}
-
 // no callbacks allowed inside this function
 int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
                              uint32_t maxBitrateKbit) {
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
index 143fef7..50500ff 100644
--- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.h
@@ -22,6 +22,7 @@
 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "webrtc/modules/rtp_rtcp/interface/receive_statistics.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
@@ -176,24 +177,13 @@
 
  int32_t SendToNetwork(const uint8_t* dataBuffer, size_t length);
 
- RTCPSender::BuildResult WriteAllReportBlocksToBuffer(
-     RtcpContext* context,
-     uint8_t* numberOfReportBlocks)
+ int32_t AddReportBlock(const RTCPReportBlock& report_block)
      EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_);
 
- void WriteReportBlocksToBuffer(
-     RtcpContext* context,
-     const std::map<uint32_t, RTCPReportBlock*>& report_blocks);
-
- int32_t AddReportBlock(uint32_t SSRC,
-                        std::map<uint32_t, RTCPReportBlock*>* report_blocks,
-                        const RTCPReportBlock* receiveBlock);
-
  bool PrepareReport(const FeedbackState& feedback_state,
+                    uint32_t ssrc,
                     StreamStatistician* statistician,
-                    RTCPReportBlock* report_block,
-                    uint32_t* ntp_secs,
-                    uint32_t* ntp_frac);
+                    RTCPReportBlock* report_block);
 
  int PrepareRTCP(const FeedbackState& feedback_state,
                  const std::set<RTCPPacketType>& packetTypes,
@@ -266,8 +256,9 @@
 
  ReceiveStatistics* receive_statistics_
      GUARDED_BY(critical_section_rtcp_sender_);
- std::map<uint32_t, RTCPReportBlock*> internal_report_blocks_
+ std::map<uint32_t, rtcp::ReportBlock> report_blocks_
      GUARDED_BY(critical_section_rtcp_sender_);
+ // TODO(sprang): Can we avoid pointers here?
  std::map<uint32_t, RTCPUtility::RTCPCnameInformation*> csrc_cnames_
      GUARDED_BY(critical_section_rtcp_sender_);
 
@@ -338,6 +329,8 @@
 
  typedef BuildResult (RTCPSender::*Builder)(RtcpContext*);
  std::map<RTCPPacketType, Builder> builders_;
+
+ class PacketBuiltCallback;
 };
 }  // namespace webrtc