Add framerate for complete received frames to histogram stats:
"WebRTC.Video.CompleteFramesReceivedPerSecond".

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

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7762 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
index 7a866d8..7a95b71 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer.cc
@@ -133,6 +133,7 @@
       num_packets_(0),
       num_duplicated_packets_(0),
       num_discarded_packets_(0),
+      time_first_packet_ms_(0),
       jitter_estimate_(clock),
       inter_frame_delay_(clock_->TimeInMilliseconds()),
       rtt_ms_(kDefaultRtt),
@@ -169,11 +170,28 @@
 }
 
 void VCMJitterBuffer::UpdateHistograms() {
-  if (num_packets_ > 0) {
-    RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DiscardedPacketsInPercent",
-        num_discarded_packets_ * 100 / num_packets_);
-    RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DuplicatedPacketsInPercent",
-        num_duplicated_packets_ * 100 / num_packets_);
+  if (num_packets_ <= 0) {
+    return;
+  }
+  int64_t elapsed_sec =
+      (clock_->TimeInMilliseconds() - time_first_packet_ms_) / 1000;
+  if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
+    return;
+  }
+
+  RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DiscardedPacketsInPercent",
+      num_discarded_packets_ * 100 / num_packets_);
+  RTC_HISTOGRAM_PERCENTAGE("WebRTC.Video.DuplicatedPacketsInPercent",
+      num_duplicated_packets_ * 100 / num_packets_);
+
+  uint32_t total_frames = receive_statistics_[kVideoFrameKey] +
+                          receive_statistics_[kVideoFrameDelta];
+  if (total_frames > 0) {
+    RTC_HISTOGRAM_COUNTS_100("WebRTC.Video.CompleteFramesReceivedPerSecond",
+        static_cast<int>((total_frames / elapsed_sec) + 0.5f));
+    RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille",
+        static_cast<int>((receive_statistics_[kVideoFrameKey] * 1000.0f /
+            total_frames) + 0.5f));
   }
 }
 
@@ -191,6 +209,7 @@
   num_packets_ = 0;
   num_duplicated_packets_ = 0;
   num_discarded_packets_ = 0;
+  time_first_packet_ms_ = 0;
 
   // Start in a non-signaled state.
   frame_event_->Reset();
@@ -540,6 +559,9 @@
   CriticalSectionScoped cs(crit_sect_);
 
   ++num_packets_;
+  if (num_packets_ == 1) {
+    time_first_packet_ms_ = clock_->TimeInMilliseconds();
+  }
   // Does this packet belong to an old frame?
   if (last_decoded_state_.IsOldPacket(&packet)) {
     // Account only for media packets.
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.h b/webrtc/modules/video_coding/main/source/jitter_buffer.h
index 4918aa5..3722912 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer.h
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer.h
@@ -17,6 +17,7 @@
 #include <vector>
 
 #include "webrtc/base/constructormagic.h"
+#include "webrtc/base/thread_annotations.h"
 #include "webrtc/modules/interface/module_common_types.h"
 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
 #include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
@@ -201,6 +202,7 @@
                               VCMFrameBuffer** frame,
                               FrameList** frame_list)
       EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+
   // Returns true if |frame| is continuous in |decoding_state|, not taking
   // decodable frames into account.
   bool IsContinuousInState(const VCMFrameBuffer& frame,
@@ -281,7 +283,7 @@
 
   uint16_t EstimatedLowSequenceNumber(const VCMFrameBuffer& frame) const;
 
-  void UpdateHistograms();
+  void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
 
   Clock* clock_;
   // If we are running (have started) or not.
@@ -311,11 +313,13 @@
   // Number of packets in a row that have been too old.
   int num_consecutive_old_packets_;
   // Number of packets received.
-  int num_packets_;
+  int num_packets_ GUARDED_BY(crit_sect_);
   // Number of duplicated packets received.
-  int num_duplicated_packets_;
+  int num_duplicated_packets_ GUARDED_BY(crit_sect_);
   // Number of packets discarded by the jitter buffer.
-  int num_discarded_packets_;
+  int num_discarded_packets_ GUARDED_BY(crit_sect_);
+  // Time when first packet is received.
+  int64_t time_first_packet_ms_ GUARDED_BY(crit_sect_);
 
   // Jitter estimation.
   // Filter for estimating jitter.
diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
index 5d5e29a..e5561d5 100644
--- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
+++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc
@@ -111,10 +111,10 @@
   uint32_t timestamp_;
   int size_;
   uint8_t data_[1500];
-  scoped_ptr<VCMJitterBuffer> jitter_buffer_;
   scoped_ptr<VCMPacket> packet_;
   scoped_ptr<SimulatedClock> clock_;
   NullEventFactory event_factory_;
+  scoped_ptr<VCMJitterBuffer> jitter_buffer_;
 };
 
 
diff --git a/webrtc/system_wrappers/interface/metrics.h b/webrtc/system_wrappers/interface/metrics.h
index 0390140..36da4cd 100644
--- a/webrtc/system_wrappers/interface/metrics.h
+++ b/webrtc/system_wrappers/interface/metrics.h
@@ -104,6 +104,9 @@
 namespace webrtc {
 namespace metrics {
 
+// Time that should have elapsed for stats that are gathered once per call.
+enum { kMinRunTimeInSeconds = 10 };
+
 class Histogram;
 
 // Functions for getting pointer to histogram (constructs or finds the named
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 8679c17..e6fbf3c 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -236,10 +236,9 @@
 }
 
 void ViEChannel::UpdateHistograms() {
-  const float kMinCallLengthInMinutes = 0.5f;
   float elapsed_minutes =
       (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 60000.0f;
-  if (elapsed_minutes < kMinCallLengthInMinutes) {
+  if (elapsed_minutes < metrics::kMinRunTimeInSeconds / 60.0f) {
     return;
   }
   RtcpPacketTypeCounter rtcp_sent;
@@ -272,15 +271,6 @@
     RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.PliPacketsSentPerMinute",
         rtcp_sent.pli_packets / elapsed_minutes);
 
-    webrtc::VCMFrameCount frames;
-    if (vcm_->ReceivedFrameCount(frames) == VCM_OK) {
-      uint32_t total_frames = frames.numKeyFrames + frames.numDeltaFrames;
-      if (total_frames > 0) {
-        RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille",
-            static_cast<int>((frames.numKeyFrames * 1000.0f / total_frames) +
-                0.5f));
-      }
-    }
     StreamDataCounters data;
     StreamDataCounters rtx_data;
     GetReceiveStreamDataCounters(&data, &rtx_data);
diff --git a/webrtc/video_engine/vie_encoder.cc b/webrtc/video_engine/vie_encoder.cc
index 8bd40df..1d6b816 100644
--- a/webrtc/video_engine/vie_encoder.cc
+++ b/webrtc/video_engine/vie_encoder.cc
@@ -241,10 +241,9 @@
 }
 
 void ViEEncoder::UpdateHistograms() {
-  const float kMinCallLengthInMinutes = 0.5f;
-  float elapsed_minutes =
-      (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 60000.0f;
-  if (elapsed_minutes < kMinCallLengthInMinutes) {
+  int64_t elapsed_sec =
+      (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 1000;
+  if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
     return;
   }
   webrtc::VCMFrameCount frames;