Add receive bitrates to histogram stats:
- total bitrate ("WebRTC.Video.BitrateReceivedInKbps")
- media bitrate ("WebRTC.Video.MediaBitrateReceivedInKbps")
- rtx bitrate ("WebRTC.Video.RtxBitrateReceivedInKbps")
- padding bitrate ("WebRTC.Video.PaddingBitrateReceivedInKbps")

BUG=crbug/419657
R=mflodman@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/27189005

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@7756 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/common_types.h b/common_types.h
index aa6f319..9cb56af 100644
--- a/common_types.h
+++ b/common_types.h
@@ -239,6 +239,15 @@
      retransmitted_packets(0),
      fec_packets(0) {}
 
+  void Add(const StreamDataCounters& other) {
+    bytes += other.bytes;
+    header_bytes += other.header_bytes;
+    padding_bytes += other.padding_bytes;
+    packets += other.packets;
+    retransmitted_packets += other.retransmitted_packets;
+    fec_packets += other.fec_packets;
+  }
+
   // TODO(pbos): Rename bytes -> media_bytes.
   size_t bytes;  // Payload bytes, excluding RTP headers and padding.
   size_t header_bytes;  // Number of bytes used by RTP headers.
diff --git a/modules/rtp_rtcp/interface/receive_statistics.h b/modules/rtp_rtcp/interface/receive_statistics.h
index ae1fbb6..8cbed80 100644
--- a/modules/rtp_rtcp/interface/receive_statistics.h
+++ b/modules/rtp_rtcp/interface/receive_statistics.h
@@ -28,6 +28,11 @@
   virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) = 0;
   virtual void GetDataCounters(size_t* bytes_received,
                                uint32_t* packets_received) const = 0;
+
+  // Gets received stream data counters (includes reset counter values).
+  virtual void GetReceiveStreamDataCounters(
+      StreamDataCounters* data_counters) const = 0;
+
   virtual uint32_t BitrateReceived() const = 0;
 
   // Resets all statistics.
diff --git a/modules/rtp_rtcp/interface/rtp_payload_registry.h b/modules/rtp_rtcp/interface/rtp_payload_registry.h
index bbdac67..f58eaea 100644
--- a/modules/rtp_rtcp/interface/rtp_payload_registry.h
+++ b/modules/rtp_rtcp/interface/rtp_payload_registry.h
@@ -77,6 +77,8 @@
 
   void SetRtxSsrc(uint32_t ssrc);
 
+  bool GetRtxSsrc(uint32_t* ssrc) const;
+
   void SetRtxPayloadType(int payload_type);
 
   bool IsRtx(const RTPHeader& header) const;
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index eeb6e31..8585e16 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -63,6 +63,7 @@
   received_seq_wraps_ = 0;
   received_seq_max_ = 0;
   received_seq_first_ = 0;
+  stored_sum_receive_counters_.Add(receive_counters_);
   receive_counters_ = StreamDataCounters();
 }
 
@@ -314,6 +315,13 @@
   }
 }
 
+void StreamStatisticianImpl::GetReceiveStreamDataCounters(
+    StreamDataCounters* data_counters) const {
+  CriticalSectionScoped cs(stream_lock_.get());
+  *data_counters = receive_counters_;
+  data_counters->Add(stored_sum_receive_counters_);
+}
+
 uint32_t StreamStatisticianImpl::BitrateReceived() const {
   CriticalSectionScoped cs(stream_lock_.get());
   return incoming_bitrate_.BitrateNow();
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index bef856f..f3eaa58 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -33,6 +33,8 @@
   virtual bool GetStatistics(RtcpStatistics* statistics, bool reset) OVERRIDE;
   virtual void GetDataCounters(size_t* bytes_received,
                                uint32_t* packets_received) const OVERRIDE;
+  virtual void GetReceiveStreamDataCounters(
+      StreamDataCounters* data_counters) const OVERRIDE;
   virtual uint32_t BitrateReceived() const OVERRIDE;
   virtual void ResetStatistics() OVERRIDE;
   virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
@@ -83,6 +85,9 @@
   size_t received_packet_overhead_;
   StreamDataCounters receive_counters_;
 
+  // Stored counter values. Includes sum of reset counter values for the stream.
+  StreamDataCounters stored_sum_receive_counters_;
+
   // Counter values when we sent the last report.
   uint32_t last_report_inorder_packets_;
   uint32_t last_report_old_packets_;
diff --git a/modules/rtp_rtcp/source/rtp_payload_registry.cc b/modules/rtp_rtcp/source/rtp_payload_registry.cc
index 6073016..727a4d3 100644
--- a/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -286,6 +286,12 @@
   rtx_ = true;
 }
 
+bool RTPPayloadRegistry::GetRtxSsrc(uint32_t* ssrc) const {
+  CriticalSectionScoped cs(crit_sect_.get());
+  *ssrc = ssrc_rtx_;
+  return rtx_;
+}
+
 void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
   CriticalSectionScoped cs(crit_sect_.get());
   assert(payload_type >= 0);
diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc
index 6fedaf7..cec65f5 100644
--- a/video/video_send_stream_tests.cc
+++ b/video/video_send_stream_tests.cc
@@ -252,6 +252,8 @@
       *bytes_received = 0;
       *packets_received = 0;
     }
+    virtual void GetReceiveStreamDataCounters(
+        StreamDataCounters* data_counters) const OVERRIDE {}
     virtual uint32_t BitrateReceived() const OVERRIDE { return 0; }
     virtual void ResetStatistics() OVERRIDE {}
     virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
diff --git a/video_engine/vie_channel.cc b/video_engine/vie_channel.cc
index 2918313..8679c17 100644
--- a/video_engine/vie_channel.cc
+++ b/video_engine/vie_channel.cc
@@ -258,7 +258,7 @@
         rtcp_received.fir_packets / elapsed_minutes);
     RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsReceivedPerMinute",
         rtcp_received.pli_packets / elapsed_minutes);
-  } else if (vie_receiver_.GetRemoteSsrc() > 0)  {
+  } else if (vie_receiver_.GetRemoteSsrc() > 0) {
     // Get receive stats if we are receiving packets, i.e. there is a remote
     // ssrc.
     if (rtcp_sent.nack_requests > 0) {
@@ -281,6 +281,26 @@
                 0.5f));
       }
     }
+    StreamDataCounters data;
+    StreamDataCounters rtx_data;
+    GetReceiveStreamDataCounters(&data, &rtx_data);
+    uint32_t media_bytes = data.bytes;
+    uint32_t rtx_bytes =
+        rtx_data.bytes + rtx_data.header_bytes + rtx_data.padding_bytes;
+    uint32_t total_bytes = data.bytes + data.header_bytes + data.padding_bytes;
+    total_bytes += rtx_bytes;
+    uint32_t padding_bytes = data.padding_bytes + rtx_data.padding_bytes;
+    RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.BitrateReceivedInKbps",
+        total_bytes * 8 / (elapsed_minutes * 60) / 1000);
+    RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.MediaBitrateReceivedInKbps",
+        media_bytes * 8 / (elapsed_minutes * 60) / 1000);
+    RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PaddingBitrateReceivedInKbps",
+        padding_bytes * 8 / (elapsed_minutes * 60) / 1000);
+    uint32_t ssrc = 0;
+    if (vie_receiver_.GetRtxSsrc(&ssrc)) {
+      RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.RtxBitrateReceivedInKbps",
+          rtx_bytes * 8 / (elapsed_minutes * 60) / 1000);
+    }
   }
 }
 
@@ -1164,6 +1184,24 @@
   return 0;
 }
 
+void ViEChannel::GetReceiveStreamDataCounters(
+    StreamDataCounters* data,
+    StreamDataCounters* rtx_data) const {
+  StreamStatistician* statistician = vie_receiver_.GetReceiveStatistics()->
+      GetStatistician(vie_receiver_.GetRemoteSsrc());
+  if (statistician) {
+    statistician->GetReceiveStreamDataCounters(data);
+  }
+  uint32_t rtx_ssrc = 0;
+  if (vie_receiver_.GetRtxSsrc(&rtx_ssrc)) {
+    StreamStatistician* statistician =
+        vie_receiver_.GetReceiveStatistics()->GetStatistician(rtx_ssrc);
+    if (statistician) {
+      statistician->GetReceiveStreamDataCounters(rtx_data);
+    }
+  }
+}
+
 void ViEChannel::RegisterSendChannelRtpStatisticsCallback(
       StreamDataCountersCallback* callback) {
   rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(callback);
diff --git a/video_engine/vie_channel.h b/video_engine/vie_channel.h
index 3f2621a..ffb754c 100644
--- a/video_engine/vie_channel.h
+++ b/video_engine/vie_channel.h
@@ -194,6 +194,10 @@
                            size_t* bytes_received,
                            uint32_t* packets_received) const;
 
+  // Gets received stream data counters.
+  void GetReceiveStreamDataCounters(StreamDataCounters* data,
+                                    StreamDataCounters* rtx_data) const;
+
   // Called on update of RTP statistics.
   void RegisterSendChannelRtpStatisticsCallback(
       StreamDataCountersCallback* callback);
diff --git a/video_engine/vie_receiver.cc b/video_engine/vie_receiver.cc
index 8f359bf..6dec985 100644
--- a/video_engine/vie_receiver.cc
+++ b/video_engine/vie_receiver.cc
@@ -110,6 +110,10 @@
   rtp_payload_registry_->SetRtxSsrc(ssrc);
 }
 
+bool ViEReceiver::GetRtxSsrc(uint32_t* ssrc) const {
+  return rtp_payload_registry_->GetRtxSsrc(ssrc);
+}
+
 uint32_t ViEReceiver::GetRemoteSsrc() const {
   return rtp_receiver_->SSRC();
 }
diff --git a/video_engine/vie_receiver.h b/video_engine/vie_receiver.h
index a7b238b..39a85e4 100644
--- a/video_engine/vie_receiver.h
+++ b/video_engine/vie_receiver.h
@@ -49,6 +49,7 @@
   void SetNackStatus(bool enable, int max_nack_reordering_threshold);
   void SetRtxPayloadType(int payload_type);
   void SetRtxSsrc(uint32_t ssrc);
+  bool GetRtxSsrc(uint32_t* ssrc) const;
 
   uint32_t GetRemoteSsrc() const;
   int GetCsrcs(uint32_t* csrcs) const;