Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: webrtc/modules/video_coding/jitter_estimator.cc

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

Powered by Google App Engine
This is Rietveld 408576698