Allow parsing empty RTCP TargetBitrate messages, but stop sending them.

Also, add ToString() convenience method to the target bitrate struct. Super useful when doing printf debugging :)

BUG=webrtc:7858

Review-Url: https://codereview.webrtc.org/2947633003
Cr-Original-Commit-Position: refs/heads/master@{#18717}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: d0fc37a8841ed70b5338ce80ac9c3e8ac139a310
diff --git a/common_types.cc b/common_types.cc
index 0511f0d..70e5d2e 100644
--- a/common_types.cc
+++ b/common_types.cc
@@ -209,4 +209,53 @@
   return sum;
 }
 
+std::string BitrateAllocation::ToString() const {
+  if (sum_ == 0)
+    return "BitrateAllocation [ [] ]";
+
+  // TODO(sprang): Replace this stringstream with something cheaper.
+  std::ostringstream oss;
+  oss << "BitrateAllocation [";
+  uint32_t spatial_cumulator = 0;
+  for (int si = 0; si < kMaxSpatialLayers; ++si) {
+    RTC_DCHECK_LE(spatial_cumulator, sum_);
+    if (spatial_cumulator == sum_)
+      break;
+
+    const uint32_t layer_sum = GetSpatialLayerSum(si);
+    if (layer_sum == sum_) {
+      oss << " [";
+    } else {
+      if (si > 0)
+        oss << ",";
+      oss << std::endl << "  [";
+    }
+    spatial_cumulator += layer_sum;
+
+    uint32_t temporal_cumulator = 0;
+    for (int ti = 0; ti < kMaxTemporalStreams; ++ti) {
+      RTC_DCHECK_LE(temporal_cumulator, layer_sum);
+      if (temporal_cumulator == layer_sum)
+        break;
+
+      if (ti > 0)
+        oss << ", ";
+
+      uint32_t bitrate = bitrates_[si][ti];
+      oss << bitrate;
+      temporal_cumulator += bitrate;
+    }
+    oss << "]";
+  }
+
+  RTC_DCHECK_EQ(spatial_cumulator, sum_);
+  oss << " ]";
+  return oss.str();
+}
+
+std::ostream& BitrateAllocation::operator<<(std::ostream& os) const {
+  os << ToString();
+  return os;
+}
+
 }  // namespace webrtc
diff --git a/common_types.h b/common_types.h
index b0a21d6..7b62dbc 100644
--- a/common_types.h
+++ b/common_types.h
@@ -646,6 +646,10 @@
     return !(*this == other);
   }
 
+  // Expensive, please use only in tests.
+  std::string ToString() const;
+  std::ostream& operator<<(std::ostream& os) const;
+
  private:
   uint32_t sum_;
   uint32_t bitrates_[kMaxSpatialLayers][kMaxTemporalStreams];
diff --git a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
index 583083b..d559eef 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/extended_reports.cc
@@ -204,9 +204,8 @@
 
 void ExtendedReports::ParseTargetBitrateBlock(const uint8_t* block,
                                               uint16_t block_length) {
-  target_bitrate_ = rtc::Optional<TargetBitrate>(TargetBitrate());
-  if (!target_bitrate_->Parse(block, block_length))
-    target_bitrate_ = rtc::Optional<TargetBitrate>();
+  target_bitrate_.emplace();
+  target_bitrate_->Parse(block, block_length);
 }
 }  // namespace rtcp
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.cc b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.cc
index 9132642..1a00006 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.cc
@@ -11,7 +11,6 @@
 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h"
 
 #include "webrtc/base/checks.h"
-#include "webrtc/base/logging.h"
 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
 
 namespace webrtc {
@@ -65,15 +64,7 @@
 TargetBitrate::TargetBitrate() {}
 TargetBitrate::~TargetBitrate() {}
 
-bool TargetBitrate::Parse(const uint8_t* block, uint16_t block_length) {
-  if (block_length < 1) {
-    LOG(LS_WARNING)
-        << "Cannot parse TargetBitrate RTCP packet: Too little payload data ("
-        << kTargetBitrateHeaderSizeBytes << " bytes needed, got "
-        << block_length * 4 << ").";
-    return false;
-  }
-
+void TargetBitrate::Parse(const uint8_t* block, uint16_t block_length) {
   // Validate block header (should already have been parsed and checked).
   RTC_DCHECK_EQ(block[0], kBlockType);
   RTC_DCHECK_EQ(block_length, ByteReader<uint16_t>::ReadBigEndian(&block[2]));
@@ -91,8 +82,6 @@
     index += kBitrateItemSizeBytes;
     AddTargetBitrate((layers >> 4) & 0x0F, layers & 0x0F, bitrate_kbps);
   }
-
-  return true;
 }
 
 void TargetBitrate::AddTargetBitrate(uint8_t spatial_layer,
diff --git a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h
index d3f672a..d7c49a9 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h
+++ b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h
@@ -45,7 +45,7 @@
 
   const std::vector<BitrateItem>& GetTargetBitrates() const;
 
-  bool Parse(const uint8_t* block, uint16_t block_length);
+  void Parse(const uint8_t* block, uint16_t block_length);
 
   size_t BlockLength() const;
 
diff --git a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate_unittest.cc b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate_unittest.cc
index 1c8f39d..2c5098d 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/target_bitrate_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/target_bitrate_unittest.cc
@@ -54,7 +54,7 @@
 
 TEST(TargetBitrateTest, Parse) {
   TargetBitrate target_bitrate;
-  EXPECT_TRUE(target_bitrate.Parse(kPacket, kPacketLengthBlocks));
+  target_bitrate.Parse(kPacket, kPacketLengthBlocks);
   CheckBitrateItems(target_bitrate.GetTargetBitrates());
 }
 
@@ -86,4 +86,11 @@
   EXPECT_EQ(0, memcmp(kPacket, buffer, sizeof(kPacket)));
 }
 
+TEST(TargetBitrateTest, ParseNullBitratePacket) {
+  const uint8_t kNullPacket[] = {TargetBitrate::kBlockType, 0x00, 0x00, 0x00};
+  TargetBitrate target_bitrate;
+  target_bitrate.Parse(kNullPacket, 0);
+  EXPECT_TRUE(target_bitrate.GetTargetBitrates().empty());
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index b5e0d9a..4a3235f 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -121,6 +121,7 @@
       remote_ssrc_(0),
       xr_rrtr_status_(false),
       xr_rr_rtt_ms_(0),
+      oldest_tmmbr_info_ms_(0),
       last_received_rr_ms_(0),
       last_increased_sequence_number_ms_(0),
       stats_callback_(nullptr),
diff --git a/video/payload_router.cc b/video/payload_router.cc
index 12ced89..e0e95ae 100644
--- a/video/payload_router.cc
+++ b/video/payload_router.cc
@@ -171,6 +171,10 @@
       // Simulcast is in use, split the BitrateAllocation into one struct per
       // rtp stream, moving over the temporal layer allocation.
       for (size_t si = 0; si < rtp_modules_.size(); ++si) {
+        // Don't send empty TargetBitrate messages on streams not being relayed.
+        if (bitrate.GetSpatialLayerSum(si) == 0)
+          break;
+
         BitrateAllocation layer_bitrate;
         for (int tl = 0; tl < kMaxTemporalStreams; ++tl)
           layer_bitrate.SetBitrate(0, tl, bitrate.GetBitrate(si, tl));
diff --git a/video/payload_router_unittest.cc b/video/payload_router_unittest.cc
index e316695..9f58ceb 100644
--- a/video/payload_router_unittest.cc
+++ b/video/payload_router_unittest.cc
@@ -178,6 +178,29 @@
   payload_router.OnBitrateAllocationUpdated(bitrate);
 }
 
+TEST(PayloadRouterTest, SimulcastTargetBitrateWithInactiveStream) {
+  // Set up two active rtp modules.
+  NiceMock<MockRtpRtcp> rtp_1;
+  NiceMock<MockRtpRtcp> rtp_2;
+  std::vector<RtpRtcp*> modules;
+  modules.push_back(&rtp_1);
+  modules.push_back(&rtp_2);
+  PayloadRouter payload_router(modules, 42);
+  payload_router.SetActive(true);
+
+  // Create bitrate allocation with bitrate only for the first stream.
+  BitrateAllocation bitrate;
+  bitrate.SetBitrate(0, 0, 10000);
+  bitrate.SetBitrate(0, 1, 20000);
+
+  // Expect only the first rtp module to be asked to send a TargetBitrate
+  // message. (No target bitrate with 0bps sent from the second one.)
+  EXPECT_CALL(rtp_1, SetVideoBitrateAllocation(bitrate)).Times(1);
+  EXPECT_CALL(rtp_2, SetVideoBitrateAllocation(_)).Times(0);
+
+  payload_router.OnBitrateAllocationUpdated(bitrate);
+}
+
 TEST(PayloadRouterTest, SvcTargetBitrate) {
   NiceMock<MockRtpRtcp> rtp_1;
   std::vector<RtpRtcp*> modules;