Move sent key frame stats to send_statistics_proxy class.

BUG=

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

Cr-Original-Commit-Position: refs/heads/master@{#10166}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: dec5ebf10614115d6f2561c65f0cce3fd80ecfd2
diff --git a/modules/video_coding/main/interface/video_coding.h b/modules/video_coding/main/interface/video_coding.h
index aeb2f79..7fd2627 100644
--- a/modules/video_coding/main/interface/video_coding.h
+++ b/modules/video_coding/main/interface/video_coding.h
@@ -313,8 +313,6 @@
     //                     < 0,         on error.
     virtual int32_t EnableFrameDropper(bool enable) = 0;
 
-    // Sent frame counters
-    virtual int32_t SentFrameCount(VCMFrameCount& frameCount) const = 0;
 
     /*
     *   Receiver
diff --git a/modules/video_coding/main/source/media_optimization.cc b/modules/video_coding/main/source/media_optimization.cc
index 7f60c6c..b4c1be2 100644
--- a/modules/video_coding/main/source/media_optimization.cc
+++ b/modules/video_coding/main/source/media_optimization.cc
@@ -351,14 +351,6 @@
   return avg_sent_bit_rate_bps_;
 }
 
-VCMFrameCount MediaOptimization::SentFrameCount() {
-  CriticalSectionScoped lock(crit_sect_.get());
-  VCMFrameCount count;
-  count.numDeltaFrames = delta_frame_cnt_;
-  count.numKeyFrames = key_frame_cnt_;
-  return count;
-}
-
 int32_t MediaOptimization::UpdateWithEncodedData(
     const EncodedImage& encoded_image) {
   size_t encoded_length = encoded_image._length;
diff --git a/modules/video_coding/main/source/media_optimization.h b/modules/video_coding/main/source/media_optimization.h
index c3bb3a8..d2c07c9 100644
--- a/modules/video_coding/main/source/media_optimization.h
+++ b/modules/video_coding/main/source/media_optimization.h
@@ -83,7 +83,6 @@
   uint32_t InputFrameRate();
   uint32_t SentFrameRate();
   uint32_t SentBitRate();
-  VCMFrameCount SentFrameCount();
 
  private:
   enum {
diff --git a/modules/video_coding/main/source/video_coding_impl.cc b/modules/video_coding/main/source/video_coding_impl.cc
index e0cf479..e06484e 100644
--- a/modules/video_coding/main/source/video_coding_impl.cc
+++ b/modules/video_coding/main/source/video_coding_impl.cc
@@ -189,10 +189,6 @@
     return sender_->EnableFrameDropper(enable);
   }
 
-  int32_t SentFrameCount(VCMFrameCount& frameCount) const override {
-    return sender_->SentFrameCount(&frameCount);
-  }
-
   void SuspendBelowMinBitrate() override {
     return sender_->SuspendBelowMinBitrate();
   }
diff --git a/modules/video_coding/main/source/video_coding_impl.h b/modules/video_coding/main/source/video_coding_impl.h
index 86a8ca0..6813666 100644
--- a/modules/video_coding/main/source/video_coding_impl.h
+++ b/modules/video_coding/main/source/video_coding_impl.h
@@ -86,7 +86,6 @@
                                   bool internalSource);
 
   int32_t CodecConfigParameters(uint8_t* buffer, int32_t size) const;
-  int32_t SentFrameCount(VCMFrameCount* frameCount);
   int Bitrate(unsigned int* bitrate) const;
   int FrameRate(unsigned int* framerate) const;
 
diff --git a/modules/video_coding/main/source/video_sender.cc b/modules/video_coding/main/source/video_sender.cc
index c59d05a..c5317ec 100644
--- a/modules/video_coding/main/source/video_sender.cc
+++ b/modules/video_coding/main/source/video_sender.cc
@@ -184,13 +184,6 @@
   return VCM_UNINITIALIZED;
 }
 
-// TODO(andresp): Make const once media_opt is thread-safe and this has a
-// pointer to it.
-int32_t VideoSender::SentFrameCount(VCMFrameCount* frameCount) {
-  *frameCount = _mediaOpt.SentFrameCount();
-  return VCM_OK;
-}
-
 // Get encode bitrate
 int VideoSender::Bitrate(unsigned int* bitrate) const {
   RTC_DCHECK(main_thread_.CalledOnValidThread());
diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc
index a95ade5..7316ee8 100644
--- a/video/send_statistics_proxy.cc
+++ b/video/send_statistics_proxy.cc
@@ -64,6 +64,12 @@
   int encode_ms = encode_time_counter_.Avg(kMinRequiredSamples);
   if (encode_ms != -1)
     RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.EncodeTimeInMs", encode_ms);
+
+  int key_frames_permille = key_frame_counter_.Permille(kMinRequiredSamples);
+  if (key_frames_permille != -1) {
+    RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesSentInPermille",
+        key_frames_permille);
+  }
 }
 
 void SendStatisticsProxy::OnOutgoingRate(uint32_t framerate, uint32_t bitrate) {
@@ -162,6 +168,9 @@
   stats->height = encoded_image._encodedHeight;
   update_times_[ssrc].resolution_update_ms = clock_->TimeInMilliseconds();
 
+  if (encoded_image._frameType != kSkipFrame)
+    key_frame_counter_.Add(encoded_image._frameType == kKeyFrame);
+
   // TODO(asapersson): This is incorrect if simulcast layers are encoded on
   // different threads and there is no guarantee that one frame of all layers
   // are encoded before the next start.
@@ -273,4 +282,27 @@
   return sum / num_samples;
 }
 
+void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
+  if (sample)
+    ++sum;
+  ++num_samples;
+}
+
+int SendStatisticsProxy::BoolSampleCounter::Percent(
+    int min_required_samples) const {
+  return Fraction(min_required_samples, 100.0f);
+}
+
+int SendStatisticsProxy::BoolSampleCounter::Permille(
+    int min_required_samples) const {
+  return Fraction(min_required_samples, 1000.0f);
+}
+
+int SendStatisticsProxy::BoolSampleCounter::Fraction(
+    int min_required_samples, float multiplier) const {
+  if (num_samples < min_required_samples || num_samples == 0)
+    return -1;
+  return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
+}
+
 }  // namespace webrtc
diff --git a/video/send_statistics_proxy.h b/video/send_statistics_proxy.h
index 3510ded..6366e5d 100644
--- a/video/send_statistics_proxy.h
+++ b/video/send_statistics_proxy.h
@@ -96,6 +96,17 @@
     int sum;
     int num_samples;
   };
+  struct BoolSampleCounter {
+    BoolSampleCounter() : sum(0), num_samples(0) {}
+    void Add(bool sample);
+    int Percent(int min_required_samples) const;
+    int Permille(int min_required_samples) const;
+
+   private:
+    int Fraction(int min_required_samples, float multiplier) const;
+    int sum;
+    int num_samples;
+  };
   struct StatsUpdateTimes {
     StatsUpdateTimes() : resolution_update_ms(0) {}
     int64_t resolution_update_ms;
@@ -122,6 +133,7 @@
   SampleCounter sent_width_counter_ GUARDED_BY(crit_);
   SampleCounter sent_height_counter_ GUARDED_BY(crit_);
   SampleCounter encode_time_counter_ GUARDED_BY(crit_);
+  BoolSampleCounter key_frame_counter_ GUARDED_BY(crit_);
 };
 
 }  // namespace webrtc
diff --git a/video_engine/vie_encoder.cc b/video_engine/vie_encoder.cc
index cc4783f..fcdc5bb 100644
--- a/video_engine/vie_encoder.cc
+++ b/video_engine/vie_encoder.cc
@@ -137,8 +137,7 @@
       picture_id_sli_(0),
       has_received_rpsi_(false),
       picture_id_rpsi_(0),
-      video_suspended_(false),
-      start_ms_(Clock::GetRealTimeClock()->TimeInMilliseconds()) {
+      video_suspended_(false) {
   bitrate_observer_.reset(new ViEBitrateObserver(this));
 }
 
@@ -175,25 +174,6 @@
 }
 
 ViEEncoder::~ViEEncoder() {
-  UpdateHistograms();
-}
-
-void ViEEncoder::UpdateHistograms() {
-  int64_t elapsed_sec =
-      (Clock::GetRealTimeClock()->TimeInMilliseconds() - start_ms_) / 1000;
-  if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
-    return;
-  }
-  webrtc::VCMFrameCount frames;
-  if (vcm_->SentFrameCount(frames) != VCM_OK) {
-    return;
-  }
-  uint32_t total_frames = frames.numKeyFrames + frames.numDeltaFrames;
-  if (total_frames > 0) {
-    RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesSentInPermille",
-        static_cast<int>(
-            (frames.numKeyFrames * 1000.0f / total_frames) + 0.5f));
-  }
 }
 
 int ViEEncoder::Owner() const {
@@ -493,17 +473,6 @@
   return vcm_->IntraFrameRequest(0);
 }
 
-int32_t ViEEncoder::SendCodecStatistics(
-    uint32_t* num_key_frames, uint32_t* num_delta_frames) {
-  webrtc::VCMFrameCount sent_frames;
-  if (vcm_->SentFrameCount(sent_frames) != VCM_OK) {
-    return -1;
-  }
-  *num_key_frames = sent_frames.numKeyFrames;
-  *num_delta_frames = sent_frames.numDeltaFrames;
-  return 0;
-}
-
 uint32_t ViEEncoder::LastObservedBitrateBps() const {
   CriticalSectionScoped cs(data_cs_.get());
   return last_observed_bitrate_bps_;
diff --git a/video_engine/vie_encoder.h b/video_engine/vie_encoder.h
index 2221f07..ec4a82a 100644
--- a/video_engine/vie_encoder.h
+++ b/video_engine/vie_encoder.h
@@ -102,8 +102,6 @@
   void DeliverFrame(VideoFrame video_frame) override;
 
   int32_t SendKeyFrame();
-  int32_t SendCodecStatistics(uint32_t* num_key_frames,
-                              uint32_t* num_delta_frames);
 
   uint32_t LastObservedBitrateBps() const;
   int CodecTargetBitrate(uint32_t* bitrate) const;
@@ -162,8 +160,6 @@
   void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
   void TraceFrameDropEnd() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
 
-  void UpdateHistograms();
-
   const int channel_id_;
   const uint32_t number_of_cores_;
 
@@ -206,7 +202,6 @@
   std::map<uint32_t, int> ssrc_streams_ GUARDED_BY(data_cs_);
 
   bool video_suspended_ GUARDED_BY(data_cs_);
-  const int64_t start_ms_;
 };
 
 }  // namespace webrtc