Add stats of incoming frame delays for debugging bandwidth estimation.
BUG=crbug/338380
R=stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5519 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
index 170ec76..9f436e2 100644
--- a/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
+++ b/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
@@ -37,6 +37,27 @@
   virtual ~RemoteBitrateObserver() {}
 };
 
+struct ReceiveBandwidthEstimatorStats {
+  ReceiveBandwidthEstimatorStats() : total_propagation_time_delta_ms(0) {}
+
+  // The "propagation_time_delta" of a frame is defined as (d_arrival - d_sent),
+  // where d_arrival is the delta of the arrival times of the frame and the
+  // previous frame, d_sent is the delta of the sent times of the frame and
+  // the previous frame. The sent time is calculated from the RTP timestamp.
+
+  // |total_propagation_time_delta_ms| is the sum of the propagation_time_deltas
+  // of all received frames, except that it's is adjusted to 0 when it becomes
+  // negative.
+  int64_t total_propagation_time_delta_ms;
+  // The propagation_time_deltas for the frames arrived in the last
+  // kProcessIntervalMs using the clock passed to
+  // RemoteBitrateEstimatorFactory::Create.
+  std::vector<int64_t> recent_propagation_time_delta_ms;
+  // The arrival times for the frames arrived in the last kProcessIntervalMs
+  // using the clock passed to RemoteBitrateEstimatorFactory::Create.
+  std::vector<int64_t> recent_arrival_time_ms;
+};
+
 class RemoteBitrateEstimator : public CallStatsObserver, public Module {
  public:
   virtual ~RemoteBitrateEstimator() {}
@@ -58,6 +79,9 @@
   virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
                               unsigned int* bitrate_bps) const = 0;
 
+  // Returns true if the statistics are available.
+  virtual bool GetStats(ReceiveBandwidthEstimatorStats* output) const = 0;
+
  protected:
   static const int kProcessIntervalMs = 1000;
   static const int kStreamTimeOutMs = 2000;
diff --git a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
index a544ee5..b0f9064 100644
--- a/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
+++ b/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc
@@ -55,6 +55,9 @@
   virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
                               unsigned int* bitrate_bps) const OVERRIDE;
 
+  virtual bool GetStats(
+      ReceiveBandwidthEstimatorStats* output) const OVERRIDE;
+
  private:
   typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap;
 
@@ -210,6 +213,12 @@
   return true;
 }
 
+bool RemoteBitrateEstimatorSingleStream::GetStats(
+    ReceiveBandwidthEstimatorStats* output) const {
+  // Not implemented.
+  return false;
+}
+
 void RemoteBitrateEstimatorSingleStream::GetSsrcs(
     std::vector<unsigned int>* ssrcs) const {
   assert(ssrcs);
diff --git a/video_engine/include/vie_rtp_rtcp.h b/video_engine/include/vie_rtp_rtcp.h
index 9d899ad..5ef1892 100644
--- a/video_engine/include/vie_rtp_rtcp.h
+++ b/video_engine/include/vie_rtp_rtcp.h
@@ -27,6 +27,7 @@
 namespace webrtc {
 
 class VideoEngine;
+struct ReceiveBandwidthEstimatorStats;
 
 // This enumerator sets the RTCP mode.
 enum ViERTCPMode {
@@ -389,6 +390,13 @@
       const int video_channel,
       unsigned int* estimated_bandwidth) const = 0;
 
+  // This function gets the receive-side bandwidth esitmator statistics.
+  // TODO(jiayl): remove the default impl when libjingle's FakeWebRtcVideoEngine
+  // is updated.
+  virtual int GetReceiveBandwidthEstimatorStats(
+      const int video_channel,
+      ReceiveBandwidthEstimatorStats* output) const { return -1; }
+
   // This function enables capturing of RTP packets to a binary file on a
   // specific channel and for a given direction. The file can later be
   // replayed using e.g. RTP Tools rtpplay since the binary file format is
diff --git a/video_engine/vie_channel.cc b/video_engine/vie_channel.cc
index 13c0a5c..57e633f 100644
--- a/video_engine/vie_channel.cc
+++ b/video_engine/vie_channel.cc
@@ -1457,6 +1457,11 @@
   vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth);
 }
 
+void ViEChannel::GetReceiveBandwidthEstimatorStats(
+    ReceiveBandwidthEstimatorStats* output) const {
+  vie_receiver_.GetReceiveBandwidthEstimatorStats(output);
+}
+
 int32_t ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
                                        RTPDirections direction) {
   WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
diff --git a/video_engine/vie_channel.h b/video_engine/vie_channel.h
index be961d5..eddaefb 100644
--- a/video_engine/vie_channel.h
+++ b/video_engine/vie_channel.h
@@ -209,6 +209,8 @@
                          uint32_t* nackBitrateSent) const;
   bool GetSendSideDelay(int* avg_send_delay, int* max_send_delay) const;
   void GetEstimatedReceiveBandwidth(uint32_t* estimated_bandwidth) const;
+  void GetReceiveBandwidthEstimatorStats(
+      ReceiveBandwidthEstimatorStats* output) const;
 
   // Called on any new send bitrate estimate.
   void RegisterSendBitrateObserver(BitrateStatisticsObserver* observer);
diff --git a/video_engine/vie_channel_group.cc b/video_engine/vie_channel_group.cc
index f79d65a..cc89bec 100644
--- a/video_engine/vie_channel_group.cc
+++ b/video_engine/vie_channel_group.cc
@@ -85,6 +85,11 @@
     return rbe_->LatestEstimate(ssrcs, bitrate_bps);
   }
 
+  virtual bool GetStats(ReceiveBandwidthEstimatorStats* output) const {
+    CriticalSectionScoped cs(crit_sect_.get());
+    return rbe_->GetStats(output);
+  }
+
  private:
   // Instantiate RBE for Time Offset or Absolute Send Time extensions.
   void PickEstimator(const RTPHeader& header) {
diff --git a/video_engine/vie_receiver.cc b/video_engine/vie_receiver.cc
index 0d88014..3b9c019 100644
--- a/video_engine/vie_receiver.cc
+++ b/video_engine/vie_receiver.cc
@@ -458,6 +458,11 @@
   }
 }
 
+void ViEReceiver::GetReceiveBandwidthEstimatorStats(
+    ReceiveBandwidthEstimatorStats* output) const {
+  remote_bitrate_estimator_->GetStats(output);
+}
+
 ReceiveStatistics* ViEReceiver::GetReceiveStatistics() const {
   return rtp_receive_statistics_.get();
 }
diff --git a/video_engine/vie_receiver.h b/video_engine/vie_receiver.h
index 5cccb51..3e0966d 100644
--- a/video_engine/vie_receiver.h
+++ b/video_engine/vie_receiver.h
@@ -34,6 +34,7 @@
 class RtpReceiver;
 class RtpRtcp;
 class VideoCodingModule;
+struct ReceiveBandwidthEstimatorStats;
 
 class ViEReceiver : public RtpData {
  public:
@@ -85,6 +86,9 @@
 
   void EstimatedReceiveBandwidth(unsigned int* available_bandwidth) const;
 
+  void GetReceiveBandwidthEstimatorStats(
+      ReceiveBandwidthEstimatorStats* output) const;
+
   ReceiveStatistics* GetReceiveStatistics() const;
 
  private:
diff --git a/video_engine/vie_rtp_rtcp_impl.cc b/video_engine/vie_rtp_rtcp_impl.cc
index b655349..bd13df7 100644
--- a/video_engine/vie_rtp_rtcp_impl.cc
+++ b/video_engine/vie_rtp_rtcp_impl.cc
@@ -1003,6 +1003,26 @@
   return 0;
 }
 
+int ViERTP_RTCPImpl::GetReceiveBandwidthEstimatorStats(
+    const int video_channel,
+    ReceiveBandwidthEstimatorStats* output) const {
+  WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
+               ViEId(shared_data_->instance_id(), video_channel),
+               "%s(channel: %d)", __FUNCTION__, video_channel);
+  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
+  ViEChannel* vie_channel = cs.Channel(video_channel);
+  if (!vie_channel) {
+    WEBRTC_TRACE(kTraceError, kTraceVideo,
+                 ViEId(shared_data_->instance_id(), video_channel),
+                 "%s: Could not get channel %d", __FUNCTION__,
+                 video_channel);
+    shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
+    return -1;
+  }
+  vie_channel->GetReceiveBandwidthEstimatorStats(output);
+  return 0;
+}
+
 int ViERTP_RTCPImpl::StartRTPDump(const int video_channel,
                                   const char file_nameUTF8[1024],
                                   RTPDirections direction) {
diff --git a/video_engine/vie_rtp_rtcp_impl.h b/video_engine/vie_rtp_rtcp_impl.h
index caabd2c..74e69ce 100644
--- a/video_engine/vie_rtp_rtcp_impl.h
+++ b/video_engine/vie_rtp_rtcp_impl.h
@@ -110,6 +110,8 @@
   virtual int GetEstimatedReceiveBandwidth(
       const int video_channel,
       unsigned int* estimated_bandwidth) const;
+  virtual int GetReceiveBandwidthEstimatorStats(
+      const int video_channel, ReceiveBandwidthEstimatorStats* output) const;
   virtual int StartRTPDump(const int video_channel,
                            const char file_nameUTF8[1024],
                            RTPDirections direction);