Home | History | Annotate | Download | only in video_engine
      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/video_engine/call_stats.h"
     12 
     13 #include <assert.h>
     14 
     15 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
     16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     17 #include "webrtc/system_wrappers/interface/tick_util.h"
     18 
     19 namespace webrtc {
     20 
     21 // A rtt report is considered valid for this long.
     22 const int kRttTimeoutMs = 1500;
     23 // Time interval for updating the observers.
     24 const int kUpdateIntervalMs = 1000;
     25 
     26 class RtcpObserver : public RtcpRttStats {
     27  public:
     28   explicit RtcpObserver(CallStats* owner) : owner_(owner) {}
     29   virtual ~RtcpObserver() {}
     30 
     31   virtual void OnRttUpdate(uint32_t rtt) {
     32     owner_->OnRttUpdate(rtt);
     33   }
     34 
     35   virtual uint32_t LastProcessedRtt() const {
     36     return owner_->last_processed_rtt_ms();
     37   }
     38 
     39  private:
     40   CallStats* owner_;
     41 
     42   DISALLOW_COPY_AND_ASSIGN(RtcpObserver);
     43 };
     44 
     45 CallStats::CallStats()
     46     : crit_(CriticalSectionWrapper::CreateCriticalSection()),
     47       rtcp_rtt_stats_(new RtcpObserver(this)),
     48       last_process_time_(TickTime::MillisecondTimestamp()),
     49       last_processed_rtt_ms_(0) {
     50 }
     51 
     52 CallStats::~CallStats() {
     53   assert(observers_.empty());
     54 }
     55 
     56 int32_t CallStats::TimeUntilNextProcess() {
     57   return last_process_time_ + kUpdateIntervalMs -
     58       TickTime::MillisecondTimestamp();
     59 }
     60 
     61 int32_t CallStats::Process() {
     62   CriticalSectionScoped cs(crit_.get());
     63   if (TickTime::MillisecondTimestamp() < last_process_time_ + kUpdateIntervalMs)
     64     return 0;
     65 
     66   // Remove invalid, as in too old, rtt values.
     67   int64_t time_now = TickTime::MillisecondTimestamp();
     68   while (!reports_.empty() && reports_.front().time + kRttTimeoutMs <
     69          time_now) {
     70     reports_.pop_front();
     71   }
     72 
     73   // Find the max stored RTT.
     74   uint32_t max_rtt = 0;
     75   for (std::list<RttTime>::const_iterator it = reports_.begin();
     76        it != reports_.end(); ++it) {
     77     if (it->rtt > max_rtt)
     78       max_rtt = it->rtt;
     79   }
     80 
     81   // If there is a valid rtt, update all observers.
     82   if (max_rtt > 0) {
     83     for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
     84          it != observers_.end(); ++it) {
     85       (*it)->OnRttUpdate(max_rtt);
     86     }
     87   }
     88   last_processed_rtt_ms_ = max_rtt;
     89   last_process_time_ = time_now;
     90   return 0;
     91 }
     92 
     93 uint32_t CallStats::last_processed_rtt_ms() const {
     94   CriticalSectionScoped cs(crit_.get());
     95   return last_processed_rtt_ms_;
     96 }
     97 
     98 RtcpRttStats* CallStats::rtcp_rtt_stats() const {
     99   return rtcp_rtt_stats_.get();
    100 }
    101 
    102 void CallStats::RegisterStatsObserver(CallStatsObserver* observer) {
    103   CriticalSectionScoped cs(crit_.get());
    104   for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
    105        it != observers_.end(); ++it) {
    106     if (*it == observer)
    107       return;
    108   }
    109   observers_.push_back(observer);
    110 }
    111 
    112 void CallStats::DeregisterStatsObserver(CallStatsObserver* observer) {
    113   CriticalSectionScoped cs(crit_.get());
    114   for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
    115        it != observers_.end(); ++it) {
    116     if (*it == observer) {
    117       observers_.erase(it);
    118       return;
    119     }
    120   }
    121 }
    122 
    123 void CallStats::OnRttUpdate(uint32_t rtt) {
    124   CriticalSectionScoped cs(crit_.get());
    125   int64_t time_now = TickTime::MillisecondTimestamp();
    126   reports_.push_back(RttTime(rtt, time_now));
    127 }
    128 
    129 }  // namespace webrtc
    130