Fixed a miscalculation of sent bitrate caused by mixup of time units

Bug: webrtc:7949
Change-Id: Ia57fdd3d1de0952b80e77c30b0a6cfe44515eff2
Reviewed-on: https://chromium-review.googlesource.com/561460
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#18917}
diff --git a/webrtc/modules/video_coding/media_optimization.cc b/webrtc/modules/video_coding/media_optimization.cc
index f0cbd62..9c74f4b 100644
--- a/webrtc/modules/video_coding/media_optimization.cc
+++ b/webrtc/modules/video_coding/media_optimization.cc
@@ -18,6 +18,8 @@
 
 namespace webrtc {
 namespace media_optimization {
+const int kMsPerSec = 1000;
+const int kBitsPerByte = 8;
 
 struct MediaOptimization::EncodedFrameSample {
   EncodedFrameSample(size_t size_bytes,
@@ -44,7 +46,6 @@
       video_target_bitrate_(0),
       incoming_frame_rate_(0),
       encoded_frame_samples_(),
-      avg_sent_bit_rate_bps_(0),
       avg_sent_framerate_(0),
       num_layers_(0) {
   memset(send_statistics_, 0, sizeof(send_statistics_));
@@ -67,7 +68,6 @@
   codec_height_ = 0;
   user_frame_rate_ = 0;
   encoded_frame_samples_.clear();
-  avg_sent_bit_rate_bps_ = 0;
   num_layers_ = 1;
 }
 
@@ -147,17 +147,19 @@
 }
 
 uint32_t MediaOptimization::SentFrameRateInternal() {
-  PurgeOldFrameSamples(clock_->TimeInMilliseconds());
+  PurgeOldFrameSamples(clock_->TimeInMilliseconds() - kBitrateAverageWinMs);
   UpdateSentFramerate();
   return avg_sent_framerate_;
 }
 
 uint32_t MediaOptimization::SentBitRate() {
   rtc::CritScope lock(&crit_sect_);
-  const int64_t now_ms = clock_->TimeInMilliseconds();
-  PurgeOldFrameSamples(now_ms);
-  UpdateSentBitrate(now_ms);
-  return avg_sent_bit_rate_bps_;
+  PurgeOldFrameSamples(clock_->TimeInMilliseconds() - kBitrateAverageWinMs);
+  size_t sent_bytes = 0;
+  for (auto& frame_sample : encoded_frame_samples_) {
+    sent_bytes += frame_sample.size_bytes;
+  }
+  return sent_bytes * kBitsPerByte * kMsPerSec / kBitrateAverageWinMs;
 }
 
 int32_t MediaOptimization::UpdateWithEncodedData(
@@ -166,7 +168,7 @@
   uint32_t timestamp = encoded_image._timeStamp;
   rtc::CritScope lock(&crit_sect_);
   const int64_t now_ms = clock_->TimeInMilliseconds();
-  PurgeOldFrameSamples(now_ms);
+  PurgeOldFrameSamples(now_ms - kBitrateAverageWinMs);
   if (encoded_frame_samples_.size() > 0 &&
       encoded_frame_samples_.back().timestamp == timestamp) {
     // Frames having the same timestamp are generated from the same input
@@ -178,7 +180,6 @@
     encoded_frame_samples_.push_back(
         EncodedFrameSample(encoded_length, timestamp, now_ms));
   }
-  UpdateSentBitrate(now_ms);
   UpdateSentFramerate();
   if (encoded_length > 0) {
     const bool delta_frame = encoded_image._frameType != kVideoFrameKey;
@@ -215,10 +216,9 @@
   ProcessIncomingFrameRate(now);
 }
 
-void MediaOptimization::PurgeOldFrameSamples(int64_t now_ms) {
+void MediaOptimization::PurgeOldFrameSamples(int64_t threshold_ms) {
   while (!encoded_frame_samples_.empty()) {
-    if (now_ms - encoded_frame_samples_.front().time_complete_ms >
-        kBitrateAverageWinMs) {
+    if (encoded_frame_samples_.front().time_complete_ms < threshold_ms) {
       encoded_frame_samples_.pop_front();
     } else {
       break;
@@ -226,26 +226,6 @@
   }
 }
 
-void MediaOptimization::UpdateSentBitrate(int64_t now_ms) {
-  if (encoded_frame_samples_.empty()) {
-    avg_sent_bit_rate_bps_ = 0;
-    return;
-  }
-  size_t framesize_sum = 0;
-  for (FrameSampleList::iterator it = encoded_frame_samples_.begin();
-       it != encoded_frame_samples_.end(); ++it) {
-    framesize_sum += it->size_bytes;
-  }
-  float denom = static_cast<float>(
-      now_ms - encoded_frame_samples_.front().time_complete_ms);
-  if (denom >= 1.0f) {
-    avg_sent_bit_rate_bps_ =
-        static_cast<uint32_t>(framesize_sum * 8.0f * 1000.0f / denom + 0.5f);
-  } else {
-    avg_sent_bit_rate_bps_ = framesize_sum * 8;
-  }
-}
-
 void MediaOptimization::UpdateSentFramerate() {
   if (encoded_frame_samples_.size() <= 1) {
     avg_sent_framerate_ = encoded_frame_samples_.size();
diff --git a/webrtc/modules/video_coding/media_optimization.h b/webrtc/modules/video_coding/media_optimization.h
index dcca61b..ffc3209 100644
--- a/webrtc/modules/video_coding/media_optimization.h
+++ b/webrtc/modules/video_coding/media_optimization.h
@@ -74,9 +74,10 @@
   typedef std::list<EncodedFrameSample> FrameSampleList;
 
   void UpdateIncomingFrameRate() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
-  void PurgeOldFrameSamples(int64_t now_ms)
+  void PurgeOldFrameSamples(int64_t threshold_ms)
       EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
-  void UpdateSentBitrate(int64_t now_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
+  // Updates the sent bitrate field, a call to PurgeOldFrameSamples must preceed
+  int GetSentBitrate(int64_t now_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
   void UpdateSentFramerate() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
 
   void ProcessIncomingFrameRate(int64_t now)
@@ -116,7 +117,6 @@
   float incoming_frame_rate_ GUARDED_BY(crit_sect_);
   int64_t incoming_frame_times_[kFrameCountHistorySize] GUARDED_BY(crit_sect_);
   std::list<EncodedFrameSample> encoded_frame_samples_ GUARDED_BY(crit_sect_);
-  uint32_t avg_sent_bit_rate_bps_ GUARDED_BY(crit_sect_);
   uint32_t avg_sent_framerate_ GUARDED_BY(crit_sect_);
   int num_layers_ GUARDED_BY(crit_sect_);
 };