Store timestamp for each sample to be able to plot them in future

Bug: webrtc:10138
Change-Id: Ifde909ac4f92e5d0f089e5d2f6fc544c9ae97db1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/151652
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29154}
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 7b0108d..bd0b57f 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -563,6 +563,7 @@
     ":rtc_base_approved",
     ":safe_compare",
     "../api:array_view",
+    "../api/units:timestamp",
     "//third_party/abseil-cpp/absl/algorithm:container",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
diff --git a/rtc_base/numerics/samples_stats_counter.cc b/rtc_base/numerics/samples_stats_counter.cc
index 0d18c9f..c262d48 100644
--- a/rtc_base/numerics/samples_stats_counter.cc
+++ b/rtc_base/numerics/samples_stats_counter.cc
@@ -13,6 +13,7 @@
 #include <cmath>
 
 #include "absl/algorithm/container.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
@@ -26,8 +27,12 @@
     default;
 
 void SamplesStatsCounter::AddSample(double value) {
-  stats_.AddSample(value);
-  samples_.push_back(value);
+  AddSample(StatsSample{value, Timestamp::us(rtc::TimeMicros())});
+}
+
+void SamplesStatsCounter::AddSample(StatsSample sample) {
+  stats_.AddSample(sample.value);
+  samples_.push_back(sample);
   sorted_ = false;
 }
 
@@ -42,7 +47,9 @@
   RTC_CHECK_GE(percentile, 0);
   RTC_CHECK_LE(percentile, 1);
   if (!sorted_) {
-    absl::c_sort(samples_);
+    absl::c_sort(samples_, [](const StatsSample& a, const StatsSample& b) {
+      return a.value < b.value;
+    });
     sorted_ = true;
   }
   const double raw_rank = percentile * (samples_.size() - 1);
@@ -61,16 +68,17 @@
   RTC_DCHECK_LT(fract_part, 1);
   RTC_DCHECK(rank + fract_part == raw_rank);
 
-  const double low = samples_[rank];
-  const double high = samples_[std::min(rank + 1, samples_.size() - 1)];
+  const double low = samples_[rank].value;
+  const double high = samples_[std::min(rank + 1, samples_.size() - 1)].value;
   return low + fract_part * (high - low);
 }
 
 SamplesStatsCounter operator*(const SamplesStatsCounter& counter,
                               double value) {
   SamplesStatsCounter out;
-  for (auto& sample : counter.GetSamples()) {
-    out.AddSample(sample * value);
+  for (const auto& sample : counter.GetTimedSamples()) {
+    out.AddSample(
+        SamplesStatsCounter::StatsSample{sample.value * value, sample.time});
   }
   return out;
 }
@@ -78,8 +86,9 @@
 SamplesStatsCounter operator/(const SamplesStatsCounter& counter,
                               double value) {
   SamplesStatsCounter out;
-  for (auto& sample : counter.GetSamples()) {
-    out.AddSample(sample / value);
+  for (const auto& sample : counter.GetTimedSamples()) {
+    out.AddSample(
+        SamplesStatsCounter::StatsSample{sample.value / value, sample.time});
   }
   return out;
 }
diff --git a/rtc_base/numerics/samples_stats_counter.h b/rtc_base/numerics/samples_stats_counter.h
index 6f79cee..a4ec443 100644
--- a/rtc_base/numerics/samples_stats_counter.h
+++ b/rtc_base/numerics/samples_stats_counter.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "api/array_view.h"
+#include "api/units/timestamp.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/running_statistics.h"
 
@@ -23,6 +24,11 @@
 // while slightly adapting the interface.
 class SamplesStatsCounter {
  public:
+  struct StatsSample {
+    double value;
+    Timestamp time;
+  };
+
   SamplesStatsCounter();
   ~SamplesStatsCounter();
   SamplesStatsCounter(const SamplesStatsCounter&);
@@ -32,6 +38,7 @@
 
   // Adds sample to the stats in amortized O(1) time.
   void AddSample(double value);
+  void AddSample(StatsSample sample);
 
   // Adds samples from another counter.
   void AddSamples(const SamplesStatsCounter& other);
@@ -80,11 +87,19 @@
   // guarantees of order, so samples can be in different order comparing to in
   // which they were added into counter. Also return value will be invalidate
   // after call to any non const method.
-  rtc::ArrayView<const double> GetSamples() const { return samples_; }
+  rtc::ArrayView<const StatsSample> GetTimedSamples() const { return samples_; }
+  std::vector<double> GetSamples() const {
+    std::vector<double> out;
+    out.reserve(samples_.size());
+    for (const auto& sample : samples_) {
+      out.push_back(sample.value);
+    }
+    return out;
+  }
 
  private:
   RunningStatistics<double> stats_;
-  std::vector<double> samples_;
+  std::vector<StatsSample> samples_;
   bool sorted_ = false;
 };