Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2011 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/video_coding/main/source/internal_defines.h"
     12 #include "webrtc/modules/video_coding/main/source/jitter_estimator.h"
     13 #include "webrtc/modules/video_coding/main/source/rtt_filter.h"
     14 #include "webrtc/system_wrappers/interface/clock.h"
     15 #include "webrtc/system_wrappers/interface/field_trial.h"
     16 
     17 #include <assert.h>
     18 #include <math.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 namespace webrtc {
     23 
     24 enum { kStartupDelaySamples = 30 };
     25 enum { kFsAccuStartupSamples = 5 };
     26 enum { kMaxFramerateEstimate = 200 };
     27 
     28 VCMJitterEstimator::VCMJitterEstimator(const Clock* clock,
     29                                        int32_t vcmId,
     30                                        int32_t receiverId)
     31     : _vcmId(vcmId),
     32       _receiverId(receiverId),
     33       _phi(0.97),
     34       _psi(0.9999),
     35       _alphaCountMax(400),
     36       _thetaLow(0.000001),
     37       _nackLimit(3),
     38       _numStdDevDelayOutlier(15),
     39       _numStdDevFrameSizeOutlier(3),
     40       _noiseStdDevs(2.33),       // ~Less than 1% chance
     41                                  // (look up in normal distribution table)...
     42       _noiseStdDevOffset(30.0),  // ...of getting 30 ms freezes
     43       _rttFilter(),
     44       fps_counter_(30),  // TODO(sprang): Use an estimator with limit based on
     45                          // time, rather than number of samples.
     46       low_rate_experiment_(kInit),
     47       clock_(clock) {
     48   Reset();
     49 }
     50 
     51 VCMJitterEstimator::~VCMJitterEstimator() {
     52 }
     53 
     54 VCMJitterEstimator&
     55 VCMJitterEstimator::operator=(const VCMJitterEstimator& rhs)
     56 {
     57     if (this != &rhs)
     58     {
     59         memcpy(_thetaCov, rhs._thetaCov, sizeof(_thetaCov));
     60         memcpy(_Qcov, rhs._Qcov, sizeof(_Qcov));
     61 
     62         _vcmId = rhs._vcmId;
     63         _receiverId = rhs._receiverId;
     64         _avgFrameSize = rhs._avgFrameSize;
     65         _varFrameSize = rhs._varFrameSize;
     66         _maxFrameSize = rhs._maxFrameSize;
     67         _fsSum = rhs._fsSum;
     68         _fsCount = rhs._fsCount;
     69         _lastUpdateT = rhs._lastUpdateT;
     70         _prevEstimate = rhs._prevEstimate;
     71         _prevFrameSize = rhs._prevFrameSize;
     72         _avgNoise = rhs._avgNoise;
     73         _alphaCount = rhs._alphaCount;
     74         _filterJitterEstimate = rhs._filterJitterEstimate;
     75         _startupCount = rhs._startupCount;
     76         _latestNackTimestamp = rhs._latestNackTimestamp;
     77         _nackCount = rhs._nackCount;
     78         _rttFilter = rhs._rttFilter;
     79     }
     80     return *this;
     81 }
     82 
     83 // Resets the JitterEstimate
     84 void
     85 VCMJitterEstimator::Reset()
     86 {
     87     _theta[0] = 1/(512e3/8);
     88     _theta[1] = 0;
     89     _varNoise = 4.0;
     90 
     91     _thetaCov[0][0] = 1e-4;
     92     _thetaCov[1][1] = 1e2;
     93     _thetaCov[0][1] = _thetaCov[1][0] = 0;
     94     _Qcov[0][0] = 2.5e-10;
     95     _Qcov[1][1] = 1e-10;
     96     _Qcov[0][1] = _Qcov[1][0] = 0;
     97     _avgFrameSize = 500;
     98     _maxFrameSize = 500;
     99     _varFrameSize = 100;
    100     _lastUpdateT = -1;
    101     _prevEstimate = -1.0;
    102     _prevFrameSize = 0;
    103     _avgNoise = 0.0;
    104     _alphaCount = 1;
    105     _filterJitterEstimate = 0.0;
    106     _latestNackTimestamp = 0;
    107     _nackCount = 0;
    108     _fsSum = 0;
    109     _fsCount = 0;
    110     _startupCount = 0;
    111     _rttFilter.Reset();
    112     fps_counter_.Reset();
    113 }
    114 
    115 void
    116 VCMJitterEstimator::ResetNackCount()
    117 {
    118     _nackCount = 0;
    119 }
    120 
    121 // Updates the estimates with the new measurements
    122 void
    123 VCMJitterEstimator::UpdateEstimate(int64_t frameDelayMS, uint32_t frameSizeBytes,
    124                                             bool incompleteFrame /* = false */)
    125 {
    126     if (frameSizeBytes == 0)
    127     {
    128         return;
    129     }
    130     int deltaFS = frameSizeBytes - _prevFrameSize;
    131     if (_fsCount < kFsAccuStartupSamples)
    132     {
    133         _fsSum += frameSizeBytes;
    134         _fsCount++;
    135     }
    136     else if (_fsCount == kFsAccuStartupSamples)
    137     {
    138         // Give the frame size filter
    139         _avgFrameSize = static_cast<double>(_fsSum) /
    140                         static_cast<double>(_fsCount);
    141         _fsCount++;
    142     }
    143     if (!incompleteFrame || frameSizeBytes > _avgFrameSize)
    144     {
    145         double avgFrameSize = _phi * _avgFrameSize +
    146                               (1 - _phi) * frameSizeBytes;
    147         if (frameSizeBytes < _avgFrameSize + 2 * sqrt(_varFrameSize))
    148         {
    149             // Only update the average frame size if this sample wasn't a
    150             // key frame
    151             _avgFrameSize = avgFrameSize;
    152         }
    153         // Update the variance anyway since we want to capture cases where we only get
    154         // key frames.
    155         _varFrameSize = VCM_MAX(_phi * _varFrameSize + (1 - _phi) *
    156                                 (frameSizeBytes - avgFrameSize) *
    157                                 (frameSizeBytes - avgFrameSize), 1.0);
    158     }
    159 
    160     // Update max frameSize estimate
    161     _maxFrameSize = VCM_MAX(_psi * _maxFrameSize, static_cast<double>(frameSizeBytes));
    162 
    163     if (_prevFrameSize == 0)
    164     {
    165         _prevFrameSize = frameSizeBytes;
    166         return;
    167     }
    168     _prevFrameSize = frameSizeBytes;
    169 
    170     // Only update the Kalman filter if the sample is not considered
    171     // an extreme outlier. Even if it is an extreme outlier from a
    172     // delay point of view, if the frame size also is large the
    173     // deviation is probably due to an incorrect line slope.
    174     double deviation = DeviationFromExpectedDelay(frameDelayMS, deltaFS);
    175 
    176     if (fabs(deviation) < _numStdDevDelayOutlier * sqrt(_varNoise) ||
    177         frameSizeBytes > _avgFrameSize + _numStdDevFrameSizeOutlier * sqrt(_varFrameSize))
    178     {
    179         // Update the variance of the deviation from the
    180         // line given by the Kalman filter
    181         EstimateRandomJitter(deviation, incompleteFrame);
    182         // Prevent updating with frames which have been congested by a large
    183         // frame, and therefore arrives almost at the same time as that frame.
    184         // This can occur when we receive a large frame (key frame) which
    185         // has been delayed. The next frame is of normal size (delta frame),
    186         // and thus deltaFS will be << 0. This removes all frame samples
    187         // which arrives after a key frame.
    188         if ((!incompleteFrame || deviation >= 0.0) &&
    189             static_cast<double>(deltaFS) > - 0.25 * _maxFrameSize)
    190         {
    191             // Update the Kalman filter with the new data
    192             KalmanEstimateChannel(frameDelayMS, deltaFS);
    193         }
    194     }
    195     else
    196     {
    197         int nStdDev = (deviation >= 0) ? _numStdDevDelayOutlier : -_numStdDevDelayOutlier;
    198         EstimateRandomJitter(nStdDev * sqrt(_varNoise), incompleteFrame);
    199     }
    200     // Post process the total estimated jitter
    201     if (_startupCount >= kStartupDelaySamples)
    202     {
    203         PostProcessEstimate();
    204     }
    205     else
    206     {
    207         _startupCount++;
    208     }
    209 }
    210 
    211 // Updates the nack/packet ratio
    212 void
    213 VCMJitterEstimator::FrameNacked()
    214 {
    215     // Wait until _nackLimit retransmissions has been received,
    216     // then always add ~1 RTT delay.
    217     // TODO(holmer): Should we ever remove the additional delay if the
    218     // the packet losses seem to have stopped? We could for instance scale
    219     // the number of RTTs to add with the amount of retransmissions in a given
    220     // time interval, or similar.
    221     if (_nackCount < _nackLimit)
    222     {
    223         _nackCount++;
    224     }
    225 }
    226 
    227 // Updates Kalman estimate of the channel
    228 // The caller is expected to sanity check the inputs.
    229 void
    230 VCMJitterEstimator::KalmanEstimateChannel(int64_t frameDelayMS,
    231                                           int32_t deltaFSBytes)
    232 {
    233     double Mh[2];
    234     double hMh_sigma;
    235     double kalmanGain[2];
    236     double measureRes;
    237     double t00, t01;
    238 
    239     // Kalman filtering
    240 
    241     // Prediction
    242     // M = M + Q
    243     _thetaCov[0][0] += _Qcov[0][0];
    244     _thetaCov[0][1] += _Qcov[0][1];
    245     _thetaCov[1][0] += _Qcov[1][0];
    246     _thetaCov[1][1] += _Qcov[1][1];
    247 
    248     // Kalman gain
    249     // K = M*h'/(sigma2n + h*M*h') = M*h'/(1 + h*M*h')
    250     // h = [dFS 1]
    251     // Mh = M*h'
    252     // hMh_sigma = h*M*h' + R
    253     Mh[0] = _thetaCov[0][0] * deltaFSBytes + _thetaCov[0][1];
    254     Mh[1] = _thetaCov[1][0] * deltaFSBytes + _thetaCov[1][1];
    255     // sigma weights measurements with a small deltaFS as noisy and
    256     // measurements with large deltaFS as good
    257     if (_maxFrameSize < 1.0)
    258     {
    259         return;
    260     }
    261     double sigma = (300.0 * exp(-fabs(static_cast<double>(deltaFSBytes)) /
    262                    (1e0 * _maxFrameSize)) + 1) * sqrt(_varNoise);
    263     if (sigma < 1.0)
    264     {
    265         sigma = 1.0;
    266     }
    267     hMh_sigma = deltaFSBytes * Mh[0] + Mh[1] + sigma;
    268     if ((hMh_sigma < 1e-9 && hMh_sigma >= 0) || (hMh_sigma > -1e-9 && hMh_sigma <= 0))
    269     {
    270         assert(false);
    271         return;
    272     }
    273     kalmanGain[0] = Mh[0] / hMh_sigma;
    274     kalmanGain[1] = Mh[1] / hMh_sigma;
    275 
    276     // Correction
    277     // theta = theta + K*(dT - h*theta)
    278     measureRes = frameDelayMS - (deltaFSBytes * _theta[0] + _theta[1]);
    279     _theta[0] += kalmanGain[0] * measureRes;
    280     _theta[1] += kalmanGain[1] * measureRes;
    281 
    282     if (_theta[0] < _thetaLow)
    283     {
    284         _theta[0] = _thetaLow;
    285     }
    286 
    287     // M = (I - K*h)*M
    288     t00 = _thetaCov[0][0];
    289     t01 = _thetaCov[0][1];
    290     _thetaCov[0][0] = (1 - kalmanGain[0] * deltaFSBytes) * t00 -
    291                       kalmanGain[0] * _thetaCov[1][0];
    292     _thetaCov[0][1] = (1 - kalmanGain[0] * deltaFSBytes) * t01 -
    293                       kalmanGain[0] * _thetaCov[1][1];
    294     _thetaCov[1][0] = _thetaCov[1][0] * (1 - kalmanGain[1]) -
    295                       kalmanGain[1] * deltaFSBytes * t00;
    296     _thetaCov[1][1] = _thetaCov[1][1] * (1 - kalmanGain[1]) -
    297                       kalmanGain[1] * deltaFSBytes * t01;
    298 
    299     // Covariance matrix, must be positive semi-definite
    300     assert(_thetaCov[0][0] + _thetaCov[1][1] >= 0 &&
    301            _thetaCov[0][0] * _thetaCov[1][1] - _thetaCov[0][1] * _thetaCov[1][0] >= 0 &&
    302            _thetaCov[0][0] >= 0);
    303 }
    304 
    305 // Calculate difference in delay between a sample and the
    306 // expected delay estimated by the Kalman filter
    307 double
    308 VCMJitterEstimator::DeviationFromExpectedDelay(int64_t frameDelayMS,
    309                                                int32_t deltaFSBytes) const
    310 {
    311     return frameDelayMS - (_theta[0] * deltaFSBytes + _theta[1]);
    312 }
    313 
    314 // Estimates the random jitter by calculating the variance of the
    315 // sample distance from the line given by theta.
    316 void VCMJitterEstimator::EstimateRandomJitter(double d_dT,
    317                                               bool incompleteFrame) {
    318   uint64_t now = clock_->TimeInMicroseconds();
    319   if (_lastUpdateT != -1) {
    320     fps_counter_.AddSample(now - _lastUpdateT);
    321   }
    322   _lastUpdateT = now;
    323 
    324   if (_alphaCount == 0) {
    325     assert(false);
    326     return;
    327   }
    328   double alpha =
    329       static_cast<double>(_alphaCount - 1) / static_cast<double>(_alphaCount);
    330   _alphaCount++;
    331   if (_alphaCount > _alphaCountMax)
    332     _alphaCount = _alphaCountMax;
    333 
    334   if (LowRateExperimentEnabled()) {
    335     // In order to avoid a low frame rate stream to react slower to changes,
    336     // scale the alpha weight relative a 30 fps stream.
    337     double fps = GetFrameRate();
    338     if (fps > 0.0) {
    339       double rate_scale = 30.0 / fps;
    340       // At startup, there can be a lot of noise in the fps estimate.
    341       // Interpolate rate_scale linearly, from 1.0 at sample #1, to 30.0 / fps
    342       // at sample #kStartupDelaySamples.
    343       if (_alphaCount < kStartupDelaySamples) {
    344         rate_scale =
    345             (_alphaCount * rate_scale + (kStartupDelaySamples - _alphaCount)) /
    346             kStartupDelaySamples;
    347       }
    348       alpha = pow(alpha, rate_scale);
    349     }
    350   }
    351 
    352   double avgNoise = alpha * _avgNoise + (1 - alpha) * d_dT;
    353   double varNoise =
    354       alpha * _varNoise + (1 - alpha) * (d_dT - _avgNoise) * (d_dT - _avgNoise);
    355   if (!incompleteFrame || varNoise > _varNoise) {
    356     _avgNoise = avgNoise;
    357     _varNoise = varNoise;
    358   }
    359   if (_varNoise < 1.0) {
    360     // The variance should never be zero, since we might get
    361     // stuck and consider all samples as outliers.
    362     _varNoise = 1.0;
    363   }
    364 }
    365 
    366 double
    367 VCMJitterEstimator::NoiseThreshold() const
    368 {
    369     double noiseThreshold = _noiseStdDevs * sqrt(_varNoise) - _noiseStdDevOffset;
    370     if (noiseThreshold < 1.0)
    371     {
    372         noiseThreshold = 1.0;
    373     }
    374     return noiseThreshold;
    375 }
    376 
    377 // Calculates the current jitter estimate from the filtered estimates
    378 double
    379 VCMJitterEstimator::CalculateEstimate()
    380 {
    381     double ret = _theta[0] * (_maxFrameSize - _avgFrameSize) + NoiseThreshold();
    382 
    383     // A very low estimate (or negative) is neglected
    384     if (ret < 1.0) {
    385         if (_prevEstimate <= 0.01)
    386         {
    387             ret = 1.0;
    388         }
    389         else
    390         {
    391             ret = _prevEstimate;
    392         }
    393     }
    394     if (ret > 10000.0) // Sanity
    395     {
    396         ret = 10000.0;
    397     }
    398     _prevEstimate = ret;
    399     return ret;
    400 }
    401 
    402 void
    403 VCMJitterEstimator::PostProcessEstimate()
    404 {
    405     _filterJitterEstimate = CalculateEstimate();
    406 }
    407 
    408 void
    409 VCMJitterEstimator::UpdateRtt(uint32_t rttMs)
    410 {
    411     _rttFilter.Update(rttMs);
    412 }
    413 
    414 void
    415 VCMJitterEstimator::UpdateMaxFrameSize(uint32_t frameSizeBytes)
    416 {
    417     if (_maxFrameSize < frameSizeBytes)
    418     {
    419         _maxFrameSize = frameSizeBytes;
    420     }
    421 }
    422 
    423 // Returns the current filtered estimate if available,
    424 // otherwise tries to calculate an estimate.
    425 int VCMJitterEstimator::GetJitterEstimate(double rttMultiplier) {
    426   double jitterMS = CalculateEstimate() + OPERATING_SYSTEM_JITTER;
    427   if (_filterJitterEstimate > jitterMS)
    428     jitterMS = _filterJitterEstimate;
    429   if (_nackCount >= _nackLimit)
    430     jitterMS += _rttFilter.RttMs() * rttMultiplier;
    431 
    432   if (LowRateExperimentEnabled()) {
    433     static const double kJitterScaleLowThreshold = 5.0;
    434     static const double kJitterScaleHighThreshold = 10.0;
    435     double fps = GetFrameRate();
    436     // Ignore jitter for very low fps streams.
    437     if (fps < kJitterScaleLowThreshold) {
    438       if (fps == 0.0) {
    439         return jitterMS;
    440       }
    441       return 0;
    442     }
    443 
    444     // Semi-low frame rate; scale by factor linearly interpolated from 0.0 at
    445     // kJitterScaleLowThreshold to 1.0 at kJitterScaleHighThreshold.
    446     if (fps < kJitterScaleHighThreshold) {
    447       jitterMS =
    448           (1.0 / (kJitterScaleHighThreshold - kJitterScaleLowThreshold)) *
    449           (fps - kJitterScaleLowThreshold) * jitterMS;
    450     }
    451   }
    452 
    453   return static_cast<uint32_t>(jitterMS + 0.5);
    454 }
    455 
    456 bool VCMJitterEstimator::LowRateExperimentEnabled() {
    457   if (low_rate_experiment_ == kInit) {
    458     std::string group =
    459         webrtc::field_trial::FindFullName("WebRTC-ReducedJitterDelay");
    460     if (group == "Disabled") {
    461       low_rate_experiment_ = kDisabled;
    462     } else {
    463       low_rate_experiment_ = kEnabled;
    464     }
    465   }
    466   return low_rate_experiment_ == kEnabled ? true : false;
    467 }
    468 
    469 double VCMJitterEstimator::GetFrameRate() const {
    470   if (fps_counter_.count() == 0)
    471     return 0;
    472 
    473   double fps = 1000000.0 / fps_counter_.ComputeMean();
    474   // Sanity check.
    475   assert(fps >= 0.0);
    476   if (fps > kMaxFramerateEstimate) {
    477     fps = kMaxFramerateEstimate;
    478   }
    479   return fps;
    480 }
    481 
    482 }
    483