Move histogram for number of pause events to per stream:

"WebRTC.Call.NumberOfPauseEvents" -> "WebRTC.Video.NumberOfPauseEvents"

Recorded if a certain time has passed (10 sec) since the first media packet was sent.

Moved to per stream to know when media has started and to prevent logging stats for calls that was never in use.

Add histogram for percentage of paused video time for sent video streams:
"WebRTC.Video.PausedTimeInPercent"

BUG=b/32659204

Review-Url: https://codereview.webrtc.org/2530393003
Cr-Commit-Position: refs/heads/master@{#15681}
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index de497f6..b7ae199 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -2391,6 +2391,9 @@
   EXPECT_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
   EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
 
+  EXPECT_EQ(1, metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
+  EXPECT_EQ(1, metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
+
   EXPECT_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
   EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
   EXPECT_EQ(1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
diff --git a/webrtc/video/send_statistics_proxy.cc b/webrtc/video/send_statistics_proxy.cc
index 6c249f7..bd1441f 100644
--- a/webrtc/video/send_statistics_proxy.cc
+++ b/webrtc/video/send_statistics_proxy.cc
@@ -322,6 +322,16 @@
     int64_t elapsed_sec =
         (clock_->TimeInMilliseconds() - first_rtp_stats_time_ms_) / 1000;
     if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
+      RTC_HISTOGRAMS_COUNTS_100(kIndex, uma_prefix_ + "NumberOfPauseEvents",
+                                target_rate_updates_.pause_resume_events);
+
+      int paused_time_percent =
+          paused_time_counter_.Percent(metrics::kMinRunTimeInSeconds * 1000);
+      if (paused_time_percent != -1) {
+        RTC_HISTOGRAMS_PERCENTAGE(kIndex, uma_prefix_ + "PausedTimeInPercent",
+                                  paused_time_percent);
+      }
+
       StreamDataCounters rtp;
       StreamDataCounters rtx;
       AccumulateRtxStats(current_stats, rtp_config.rtx.ssrcs, &rtp, &rtx);
@@ -467,6 +477,25 @@
 
 void SendStatisticsProxy::OnSetEncoderTargetRate(uint32_t bitrate_bps) {
   rtc::CritScope lock(&crit_);
+  if (uma_container_->target_rate_updates_.last_ms == -1 && bitrate_bps == 0)
+    return;  // Start on first non-zero bitrate, may initially be zero.
+
+  int64_t now = clock_->TimeInMilliseconds();
+  if (uma_container_->target_rate_updates_.last_ms != -1) {
+    bool was_paused = stats_.target_media_bitrate_bps == 0;
+    int64_t diff_ms = now - uma_container_->target_rate_updates_.last_ms;
+    uma_container_->paused_time_counter_.Add(was_paused, diff_ms);
+
+    // Use last to not include update when stream is stopped and video disabled.
+    if (uma_container_->target_rate_updates_.last_paused_or_resumed)
+      ++uma_container_->target_rate_updates_.pause_resume_events;
+
+    // Check if video is paused/resumed.
+    uma_container_->target_rate_updates_.last_paused_or_resumed =
+        (bitrate_bps == 0) != was_paused;
+  }
+  uma_container_->target_rate_updates_.last_ms = now;
+
   stats_.target_media_bitrate_bps = bitrate_bps;
 }
 
@@ -699,10 +728,11 @@
   ++num_samples;
 }
 
-int SendStatisticsProxy::SampleCounter::Avg(int min_required_samples) const {
+int SendStatisticsProxy::SampleCounter::Avg(
+    int64_t min_required_samples) const {
   if (num_samples < min_required_samples || num_samples == 0)
     return -1;
-  return (sum + (num_samples / 2)) / num_samples;
+  return static_cast<int>((sum + (num_samples / 2)) / num_samples);
 }
 
 void SendStatisticsProxy::BoolSampleCounter::Add(bool sample) {
@@ -711,18 +741,24 @@
   ++num_samples;
 }
 
+void SendStatisticsProxy::BoolSampleCounter::Add(bool sample, int64_t count) {
+  if (sample)
+    sum += count;
+  num_samples += count;
+}
 int SendStatisticsProxy::BoolSampleCounter::Percent(
-    int min_required_samples) const {
+    int64_t min_required_samples) const {
   return Fraction(min_required_samples, 100.0f);
 }
 
 int SendStatisticsProxy::BoolSampleCounter::Permille(
-    int min_required_samples) const {
+    int64_t min_required_samples) const {
   return Fraction(min_required_samples, 1000.0f);
 }
 
 int SendStatisticsProxy::BoolSampleCounter::Fraction(
-    int min_required_samples, float multiplier) const {
+    int64_t 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);
diff --git a/webrtc/video/send_statistics_proxy.h b/webrtc/video/send_statistics_proxy.h
index ec8bb6d..68d17e4 100644
--- a/webrtc/video/send_statistics_proxy.h
+++ b/webrtc/video/send_statistics_proxy.h
@@ -113,30 +113,38 @@
     SampleCounter() : sum(0), num_samples(0) {}
     ~SampleCounter() {}
     void Add(int sample);
-    int Avg(int min_required_samples) const;
+    int Avg(int64_t min_required_samples) const;
 
    private:
-    int sum;
-    int num_samples;
+    int64_t sum;
+    int64_t num_samples;
   };
   class BoolSampleCounter {
    public:
     BoolSampleCounter() : sum(0), num_samples(0) {}
     ~BoolSampleCounter() {}
     void Add(bool sample);
-    int Percent(int min_required_samples) const;
-    int Permille(int min_required_samples) const;
+    void Add(bool sample, int64_t count);
+    int Percent(int64_t min_required_samples) const;
+    int Permille(int64_t min_required_samples) const;
 
    private:
-    int Fraction(int min_required_samples, float multiplier) const;
-    int sum;
-    int num_samples;
+    int Fraction(int64_t min_required_samples, float multiplier) const;
+    int64_t sum;
+    int64_t num_samples;
   };
   struct StatsUpdateTimes {
     StatsUpdateTimes() : resolution_update_ms(0), bitrate_update_ms(0) {}
     int64_t resolution_update_ms;
     int64_t bitrate_update_ms;
   };
+  struct TargetRateUpdates {
+    TargetRateUpdates()
+        : pause_resume_events(0), last_paused_or_resumed(false), last_ms(-1) {}
+    int pause_resume_events;
+    bool last_paused_or_resumed;
+    int64_t last_ms;
+  };
   struct QpCounters {
     SampleCounter vp8;   // QP range: 0-127
     SampleCounter vp9;   // QP range: 0-255
@@ -192,6 +200,8 @@
     RateCounter sent_fps_counter_;
     int64_t first_rtcp_stats_time_ms_;
     int64_t first_rtp_stats_time_ms_;
+    BoolSampleCounter paused_time_counter_;
+    TargetRateUpdates target_rate_updates_;
     ReportBlockStats report_block_stats_;
     const VideoSendStream::Stats start_stats_;
     std::map<int, QpCounters>
diff --git a/webrtc/video/send_statistics_proxy_unittest.cc b/webrtc/video/send_statistics_proxy_unittest.cc
index acb8a30..7fa3ae3 100644
--- a/webrtc/video/send_statistics_proxy_unittest.cc
+++ b/webrtc/video/send_statistics_proxy_unittest.cc
@@ -88,6 +88,13 @@
     return it->second;
   }
 
+  void UpdateDataCounters(uint32_t ssrc) {
+    StreamDataCountersCallback* proxy =
+        static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
+    StreamDataCounters counters;
+    proxy->DataCountersUpdated(counters, ssrc);
+  }
+
   void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
     EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
     EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
@@ -510,6 +517,114 @@
   EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
 }
 
+TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
+  // First RTP packet sent.
+  UpdateDataCounters(kFirstSsrc);
+
+  // Min runtime has passed.
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
+}
+
+TEST_F(SendStatisticsProxyTest,
+       PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
+  // First RTP packet sent.
+  UpdateDataCounters(kFirstSsrc);
+
+  // Min runtime has not passed.
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
+  statistics_proxy_.reset();
+  EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+  EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
+}
+
+TEST_F(SendStatisticsProxyTest,
+       PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
+  // First RTP packet not sent.
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
+  statistics_proxy_.reset();
+  EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+}
+
+TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
+  // First RTP packet sent and min runtime passed.
+  UpdateDataCounters(kFirstSsrc);
+
+  // No change. Video: 10000 ms, paused: 0 ms (0%).
+  statistics_proxy_->OnSetEncoderTargetRate(50000);
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
+  statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
+
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
+}
+
+TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
+  // First RTP packet sent and min runtime passed.
+  UpdateDataCounters(kFirstSsrc);
+
+  // One change. Video: 7000 ms, paused: 3000 ms (30%).
+  statistics_proxy_->OnSetEncoderTargetRate(50000);
+  fake_clock_.AdvanceTimeMilliseconds(7000);
+  statistics_proxy_->OnSetEncoderTargetRate(0);
+  fake_clock_.AdvanceTimeMilliseconds(3000);
+  statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
+
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
+}
+
+TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
+  // First RTP packet sent.
+  UpdateDataCounters(kFirstSsrc);
+
+  // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
+  statistics_proxy_->OnSetEncoderTargetRate(0);
+  fake_clock_.AdvanceTimeMilliseconds(1000);
+  statistics_proxy_->OnSetEncoderTargetRate(50000);  // Starts on bitrate > 0.
+  fake_clock_.AdvanceTimeMilliseconds(7000);
+  statistics_proxy_->OnSetEncoderTargetRate(60000);
+  fake_clock_.AdvanceTimeMilliseconds(3000);
+  statistics_proxy_->OnSetEncoderTargetRate(0);
+  fake_clock_.AdvanceTimeMilliseconds(250);
+  statistics_proxy_->OnSetEncoderTargetRate(0);
+  fake_clock_.AdvanceTimeMilliseconds(750);
+  statistics_proxy_->OnSetEncoderTargetRate(60000);
+  fake_clock_.AdvanceTimeMilliseconds(5000);
+  statistics_proxy_->OnSetEncoderTargetRate(50000);
+  fake_clock_.AdvanceTimeMilliseconds(4000);
+  statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
+
+  statistics_proxy_.reset();
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
+  EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
+  EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
+}
+
+TEST_F(SendStatisticsProxyTest,
+       PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
+  // First RTP packet sent.
+  UpdateDataCounters(kFirstSsrc);
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
+
+  // Min runtime has not passed.
+  statistics_proxy_->OnSetEncoderTargetRate(50000);
+  fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
+  statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
+
+  statistics_proxy_.reset();
+  EXPECT_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
+}
+
 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
   EncodedImage encoded_image;
   CodecSpecificInfo codec_info;
@@ -739,6 +854,18 @@
   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
 }
 
+TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
+  // Initially zero.
+  EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
+
+  const int kBitrate = 100000;
+  statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
+  EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
+
+  statistics_proxy_->OnSetEncoderTargetRate(0);
+  EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
+}
+
 TEST_F(SendStatisticsProxyTest, NoSubstreams) {
   uint32_t excluded_ssrc =
       std::max(