Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/modules/rtp_rtcp/source/bitrate.h"
     12 
     13 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
     14 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
     15 
     16 namespace webrtc {
     17 
     18 Bitrate::Bitrate(Clock* clock, Observer* observer)
     19     : clock_(clock),
     20       crit_(CriticalSectionWrapper::CreateCriticalSection()),
     21       packet_rate_(0),
     22       bitrate_(0),
     23       bitrate_next_idx_(0),
     24       time_last_rate_update_(0),
     25       bytes_count_(0),
     26       packet_count_(0),
     27       observer_(observer) {
     28   memset(packet_rate_array_, 0, sizeof(packet_rate_array_));
     29   memset(bitrate_diff_ms_, 0, sizeof(bitrate_diff_ms_));
     30   memset(bitrate_array_, 0, sizeof(bitrate_array_));
     31 }
     32 
     33 Bitrate::~Bitrate() {}
     34 
     35 void Bitrate::Update(const size_t bytes) {
     36   CriticalSectionScoped cs(crit_.get());
     37   bytes_count_ += bytes;
     38   packet_count_++;
     39 }
     40 
     41 uint32_t Bitrate::PacketRate() const {
     42   CriticalSectionScoped cs(crit_.get());
     43   return packet_rate_;
     44 }
     45 
     46 uint32_t Bitrate::BitrateLast() const {
     47   CriticalSectionScoped cs(crit_.get());
     48   return bitrate_;
     49 }
     50 
     51 uint32_t Bitrate::BitrateNow() const {
     52   CriticalSectionScoped cs(crit_.get());
     53   int64_t now = clock_->TimeInMilliseconds();
     54   int64_t diff_ms = now - time_last_rate_update_;
     55 
     56   if (diff_ms > 10000) {  // 10 seconds.
     57     // Too high difference, ignore.
     58     return bitrate_;
     59   }
     60   int64_t bits_since_last_rate_update = 8 * bytes_count_ * 1000;
     61 
     62   // We have to consider the time when the measurement was done:
     63   // ((bits/sec * sec) + (bits)) / sec.
     64   int64_t bitrate = (static_cast<uint64_t>(bitrate_) * 1000 +
     65                            bits_since_last_rate_update) / (1000 + diff_ms);
     66   return static_cast<uint32_t>(bitrate);
     67 }
     68 
     69 int64_t Bitrate::time_last_rate_update() const {
     70   CriticalSectionScoped cs(crit_.get());
     71   return time_last_rate_update_;
     72 }
     73 
     74 // Triggered by timer.
     75 void Bitrate::Process() {
     76   BitrateStatistics stats;
     77   {
     78     CriticalSectionScoped cs(crit_.get());
     79     int64_t now = clock_->CurrentNtpInMilliseconds();
     80     int64_t diff_ms = now - time_last_rate_update_;
     81 
     82     if (diff_ms < 100) {
     83       // Not enough data, wait...
     84       return;
     85     }
     86     if (diff_ms > 10000) {  // 10 seconds.
     87       // Too high difference, ignore.
     88       time_last_rate_update_ = now;
     89       bytes_count_ = 0;
     90       packet_count_ = 0;
     91       return;
     92     }
     93     packet_rate_array_[bitrate_next_idx_] = (packet_count_ * 1000) / diff_ms;
     94     bitrate_array_[bitrate_next_idx_] = 8 * ((bytes_count_ * 1000) / diff_ms);
     95     bitrate_diff_ms_[bitrate_next_idx_] = diff_ms;
     96     bitrate_next_idx_++;
     97     if (bitrate_next_idx_ >= 10) {
     98       bitrate_next_idx_ = 0;
     99     }
    100     int64_t sum_diffMS = 0;
    101     int64_t sum_bitrateMS = 0;
    102     int64_t sum_packetrateMS = 0;
    103     for (int i = 0; i < 10; i++) {
    104       sum_diffMS += bitrate_diff_ms_[i];
    105       sum_bitrateMS += bitrate_array_[i] * bitrate_diff_ms_[i];
    106       sum_packetrateMS += packet_rate_array_[i] * bitrate_diff_ms_[i];
    107     }
    108     time_last_rate_update_ = now;
    109     bytes_count_ = 0;
    110     packet_count_ = 0;
    111     packet_rate_ = static_cast<uint32_t>(sum_packetrateMS / sum_diffMS);
    112     bitrate_ = static_cast<uint32_t>(sum_bitrateMS / sum_diffMS);
    113 
    114     stats.bitrate_bps = bitrate_;
    115     stats.packet_rate = packet_rate_;
    116     stats.timestamp_ms = now;
    117   }
    118 
    119   if (observer_)
    120     observer_->BitrateUpdated(stats);
    121 }
    122 
    123 }  // namespace webrtc
    124