Add histogram stats for average QP per frame for VP8 (for sent video streams):
- "WebRTC.Video.Encoded.Qp.Vp8"
- "WebRTC.Video.Encoded.Qp.Vp8.S0"
- "WebRTC.Video.Encoded.Qp.Vp8.S1"
- "WebRTC.Video.Encoded.Qp.Vp8.S2"

BUG=

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

Cr-Commit-Position: refs/heads/master@{#12174}
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
index 31e1d80..e4df929 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc
@@ -1040,6 +1040,10 @@
         // Report once per frame (lowest stream always sent).
         encoded_images_[encoder_idx].adapt_reason_.bw_resolutions_disabled =
             (stream_idx == 0) ? bw_resolutions_disabled : -1;
+        int qp_128 = -1;
+        vpx_codec_control(&encoders_[encoder_idx], VP8E_GET_LAST_QUANTIZER,
+                          &qp_128);
+        encoded_images_[encoder_idx].qp_ = qp_128;
         encoded_complete_callback_->Encoded(encoded_images_[encoder_idx],
                                             &codec_specific, &frag_info);
       } else if (codec_.mode == kScreensharing) {
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index 6c689bf..3d82a3b 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -193,6 +193,29 @@
         kIndex, uma_prefix_ + "SendSideDelayMaxInMs", max_delay_ms);
   }
 
+  for (const auto& it : qp_counters_) {
+    int qp = it.second.vp8.Avg(kMinRequiredSamples);
+    if (qp != -1) {
+      int spatial_idx = it.first;
+      if (spatial_idx == -1) {
+        RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex, uma_prefix_ + "Encoded.Qp.Vp8",
+                                         qp);
+      } else if (spatial_idx == 0) {
+        RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
+                                         uma_prefix_ + "Encoded.Qp.Vp8.S0", qp);
+      } else if (spatial_idx == 1) {
+        RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
+                                         uma_prefix_ + "Encoded.Qp.Vp8.S1", qp);
+      } else if (spatial_idx == 2) {
+        RTC_LOGGED_HISTOGRAMS_COUNTS_200(kIndex,
+                                         uma_prefix_ + "Encoded.Qp.Vp8.S2", qp);
+      } else {
+        LOG(LS_WARNING) << "QP stats not recorded for VP8 spatial idx "
+                        << spatial_idx;
+      }
+    }
+  }
+
   if (first_rtcp_stats_time_ms_ != -1) {
     int64_t elapsed_sec =
         (clock_->TimeInMilliseconds() - first_rtcp_stats_time_ms_) / 1000;
@@ -427,6 +450,13 @@
     }
   }
 
+  if (encoded_image.qp_ != -1 && rtp_video_header != nullptr &&
+      rtp_video_header->codec == kRtpVideoVp8) {
+    int spatial_idx =
+        (config_.rtp.ssrcs.size() == 1) ? -1 : static_cast<int>(simulcast_idx);
+    uma_container_->qp_counters_[spatial_idx].vp8.Add(encoded_image.qp_);
+  }
+
   // 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.
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index 66f0336..5a479a1 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -125,6 +125,9 @@
     int64_t resolution_update_ms;
     int64_t bitrate_update_ms;
   };
+  struct QpCounters {
+    SampleCounter vp8;
+  };
   void PurgeOldStats() EXCLUSIVE_LOCKS_REQUIRED(crit_);
   VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
       EXCLUSIVE_LOCKS_REQUIRED(crit_);
@@ -172,6 +175,8 @@
     int64_t first_rtp_stats_time_ms_;
     ReportBlockStats report_block_stats_;
     const VideoSendStream::Stats start_stats_;
+    std::map<int, QpCounters>
+        qp_counters_;  // QP counters mapped by spatial idx.
   };
 
   std::unique_ptr<UmaSamplesContainer> uma_container_ GUARDED_BY(crit_);
diff --git a/webrtc/video/send_statistics_proxy_unittest.cc b/webrtc/video/send_statistics_proxy_unittest.cc
index a98505f..bb404fb 100644
--- a/webrtc/video/send_statistics_proxy_unittest.cc
+++ b/webrtc/video/send_statistics_proxy_unittest.cc
@@ -327,6 +327,57 @@
   EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.InputWidthInPixels"));
 }
 
+TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
+  test::ClearHistograms();
+  const int kMinRequiredSamples = 200;
+  const int kQpIdx0 = 21;
+  const int kQpIdx1 = 39;
+  EncodedImage encoded_image;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.codec = kRtpVideoVp8;
+
+  for (int i = 0; i < kMinRequiredSamples; ++i) {
+    rtp_video_header.simulcastIdx = 0;
+    encoded_image.qp_ = kQpIdx0;
+    statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
+    rtp_video_header.simulcastIdx = 1;
+    encoded_image.qp_ = kQpIdx1;
+    statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
+  }
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
+  EXPECT_EQ(kQpIdx0,
+            test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8.S0"));
+  EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
+  EXPECT_EQ(kQpIdx1,
+            test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8.S1"));
+}
+
+TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
+  VideoSendStream::Config config(nullptr);
+  config.rtp.ssrcs.push_back(kFirstSsrc);
+  statistics_proxy_.reset(new SendStatisticsProxy(
+      &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo));
+
+  test::ClearHistograms();
+  const int kMinRequiredSamples = 200;
+  const int kQpIdx0 = 21;
+  EncodedImage encoded_image;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.codec = kRtpVideoVp8;
+
+  for (int i = 0; i < kMinRequiredSamples; ++i) {
+    rtp_video_header.simulcastIdx = 0;
+    encoded_image.qp_ = kQpIdx0;
+    statistics_proxy_->OnSendEncodedImage(encoded_image, &rtp_video_header);
+  }
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, test::NumHistogramSamples("WebRTC.Video.Encoded.Qp.Vp8"));
+  EXPECT_EQ(kQpIdx0, test::LastHistogramSample("WebRTC.Video.Encoded.Qp.Vp8"));
+}
+
 TEST_F(SendStatisticsProxyTest, NoSubstreams) {
   uint32_t excluded_ssrc =
       std::max(