OLD | NEW |
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/utility/frame_dropper.h" | 11 #include "webrtc/modules/video_coding/utility/frame_dropper.h" |
12 | 12 |
13 #include "webrtc/system_wrappers/include/trace.h" | 13 #include "webrtc/system_wrappers/include/trace.h" |
14 | 14 |
15 namespace webrtc | 15 namespace webrtc { |
16 { | |
17 | 16 |
18 const float kDefaultKeyFrameSizeAvgKBits = 0.9f; | 17 const float kDefaultKeyFrameSizeAvgKBits = 0.9f; |
19 const float kDefaultKeyFrameRatio = 0.99f; | 18 const float kDefaultKeyFrameRatio = 0.99f; |
20 const float kDefaultDropRatioAlpha = 0.9f; | 19 const float kDefaultDropRatioAlpha = 0.9f; |
21 const float kDefaultDropRatioMax = 0.96f; | 20 const float kDefaultDropRatioMax = 0.96f; |
22 const float kDefaultMaxTimeToDropFrames = 4.0f; // In seconds. | 21 const float kDefaultMaxTimeToDropFrames = 4.0f; // In seconds. |
23 | 22 |
24 FrameDropper::FrameDropper() | 23 FrameDropper::FrameDropper() |
25 : | 24 : _keyFrameSizeAvgKbits(kDefaultKeyFrameSizeAvgKBits), |
26 _keyFrameSizeAvgKbits(kDefaultKeyFrameSizeAvgKBits), | 25 _keyFrameRatio(kDefaultKeyFrameRatio), |
27 _keyFrameRatio(kDefaultKeyFrameRatio), | 26 _dropRatio(kDefaultDropRatioAlpha, kDefaultDropRatioMax), |
28 _dropRatio(kDefaultDropRatioAlpha, kDefaultDropRatioMax), | 27 _enabled(true), |
29 _enabled(true), | 28 _max_time_drops(kDefaultMaxTimeToDropFrames) { |
30 _max_time_drops(kDefaultMaxTimeToDropFrames) | 29 Reset(); |
31 { | |
32 Reset(); | |
33 } | 30 } |
34 | 31 |
35 FrameDropper::FrameDropper(float max_time_drops) | 32 FrameDropper::FrameDropper(float max_time_drops) |
36 : | 33 : _keyFrameSizeAvgKbits(kDefaultKeyFrameSizeAvgKBits), |
37 _keyFrameSizeAvgKbits(kDefaultKeyFrameSizeAvgKBits), | 34 _keyFrameRatio(kDefaultKeyFrameRatio), |
38 _keyFrameRatio(kDefaultKeyFrameRatio), | 35 _dropRatio(kDefaultDropRatioAlpha, kDefaultDropRatioMax), |
39 _dropRatio(kDefaultDropRatioAlpha, kDefaultDropRatioMax), | 36 _enabled(true), |
40 _enabled(true), | 37 _max_time_drops(max_time_drops) { |
41 _max_time_drops(max_time_drops) | 38 Reset(); |
42 { | 39 } |
43 Reset(); | 40 |
44 } | 41 void FrameDropper::Reset() { |
45 | 42 _keyFrameRatio.Reset(0.99f); |
46 void | 43 _keyFrameRatio.Apply( |
47 FrameDropper::Reset() | 44 1.0f, 1.0f / 300.0f); // 1 key frame every 10th second in 30 fps |
48 { | 45 _keyFrameSizeAvgKbits.Reset(0.9f); |
49 _keyFrameRatio.Reset(0.99f); | 46 _keyFrameCount = 0; |
50 _keyFrameRatio.Apply(1.0f, 1.0f/300.0f); // 1 key frame every 10th second in
30 fps | 47 _accumulator = 0.0f; |
51 _keyFrameSizeAvgKbits.Reset(0.9f); | 48 _accumulatorMax = 150.0f; // assume 300 kb/s and 0.5 s window |
52 _keyFrameCount = 0; | 49 _targetBitRate = 300.0f; |
| 50 _incoming_frame_rate = 30; |
| 51 _keyFrameSpreadFrames = 0.5f * _incoming_frame_rate; |
| 52 _dropNext = false; |
| 53 _dropRatio.Reset(0.9f); |
| 54 _dropRatio.Apply(0.0f, 0.0f); // Initialize to 0 |
| 55 _dropCount = 0; |
| 56 _windowSize = 0.5f; |
| 57 _wasBelowMax = true; |
| 58 _fastMode = false; // start with normal (non-aggressive) mode |
| 59 // Cap for the encoder buffer level/accumulator, in secs. |
| 60 _cap_buffer_size = 3.0f; |
| 61 // Cap on maximum amount of dropped frames between kept frames, in secs. |
| 62 _max_time_drops = 4.0f; |
| 63 } |
| 64 |
| 65 void FrameDropper::Enable(bool enable) { |
| 66 _enabled = enable; |
| 67 } |
| 68 |
| 69 void FrameDropper::Fill(size_t frameSizeBytes, bool deltaFrame) { |
| 70 if (!_enabled) { |
| 71 return; |
| 72 } |
| 73 float frameSizeKbits = 8.0f * static_cast<float>(frameSizeBytes) / 1000.0f; |
| 74 if (!deltaFrame && |
| 75 !_fastMode) { // fast mode does not treat key-frames any different |
| 76 _keyFrameSizeAvgKbits.Apply(1, frameSizeKbits); |
| 77 _keyFrameRatio.Apply(1.0, 1.0); |
| 78 if (frameSizeKbits > _keyFrameSizeAvgKbits.filtered()) { |
| 79 // Remove the average key frame size since we |
| 80 // compensate for key frames when adding delta |
| 81 // frames. |
| 82 frameSizeKbits -= _keyFrameSizeAvgKbits.filtered(); |
| 83 } else { |
| 84 // Shouldn't be negative, so zero is the lower bound. |
| 85 frameSizeKbits = 0; |
| 86 } |
| 87 if (_keyFrameRatio.filtered() > 1e-5 && |
| 88 1 / _keyFrameRatio.filtered() < _keyFrameSpreadFrames) { |
| 89 // We are sending key frames more often than our upper bound for |
| 90 // how much we allow the key frame compensation to be spread |
| 91 // out in time. Therefor we must use the key frame ratio rather |
| 92 // than keyFrameSpreadFrames. |
| 93 _keyFrameCount = |
| 94 static_cast<int32_t>(1 / _keyFrameRatio.filtered() + 0.5); |
| 95 } else { |
| 96 // Compensate for the key frame the following frames |
| 97 _keyFrameCount = static_cast<int32_t>(_keyFrameSpreadFrames + 0.5); |
| 98 } |
| 99 } else { |
| 100 // Decrease the keyFrameRatio |
| 101 _keyFrameRatio.Apply(1.0, 0.0); |
| 102 } |
| 103 // Change the level of the accumulator (bucket) |
| 104 _accumulator += frameSizeKbits; |
| 105 CapAccumulator(); |
| 106 } |
| 107 |
| 108 void FrameDropper::Leak(uint32_t inputFrameRate) { |
| 109 if (!_enabled) { |
| 110 return; |
| 111 } |
| 112 if (inputFrameRate < 1) { |
| 113 return; |
| 114 } |
| 115 if (_targetBitRate < 0.0f) { |
| 116 return; |
| 117 } |
| 118 _keyFrameSpreadFrames = 0.5f * inputFrameRate; |
| 119 // T is the expected bits per frame (target). If all frames were the same |
| 120 // size, |
| 121 // we would get T bits per frame. Notice that T is also weighted to be able to |
| 122 // force a lower frame rate if wanted. |
| 123 float T = _targetBitRate / inputFrameRate; |
| 124 if (_keyFrameCount > 0) { |
| 125 // Perform the key frame compensation |
| 126 if (_keyFrameRatio.filtered() > 0 && |
| 127 1 / _keyFrameRatio.filtered() < _keyFrameSpreadFrames) { |
| 128 T -= _keyFrameSizeAvgKbits.filtered() * _keyFrameRatio.filtered(); |
| 129 } else { |
| 130 T -= _keyFrameSizeAvgKbits.filtered() / _keyFrameSpreadFrames; |
| 131 } |
| 132 _keyFrameCount--; |
| 133 } |
| 134 _accumulator -= T; |
| 135 if (_accumulator < 0.0f) { |
53 _accumulator = 0.0f; | 136 _accumulator = 0.0f; |
54 _accumulatorMax = 150.0f; // assume 300 kb/s and 0.5 s window | 137 } |
55 _targetBitRate = 300.0f; | 138 UpdateRatio(); |
56 _incoming_frame_rate = 30; | 139 } |
57 _keyFrameSpreadFrames = 0.5f * _incoming_frame_rate; | 140 |
| 141 void FrameDropper::UpdateNack(uint32_t nackBytes) { |
| 142 if (!_enabled) { |
| 143 return; |
| 144 } |
| 145 _accumulator += static_cast<float>(nackBytes) * 8.0f / 1000.0f; |
| 146 } |
| 147 |
| 148 void FrameDropper::FillBucket(float inKbits, float outKbits) { |
| 149 _accumulator += (inKbits - outKbits); |
| 150 } |
| 151 |
| 152 void FrameDropper::UpdateRatio() { |
| 153 if (_accumulator > 1.3f * _accumulatorMax) { |
| 154 // Too far above accumulator max, react faster |
| 155 _dropRatio.UpdateBase(0.8f); |
| 156 } else { |
| 157 // Go back to normal reaction |
| 158 _dropRatio.UpdateBase(0.9f); |
| 159 } |
| 160 if (_accumulator > _accumulatorMax) { |
| 161 // We are above accumulator max, and should ideally |
| 162 // drop a frame. Increase the dropRatio and drop |
| 163 // the frame later. |
| 164 if (_wasBelowMax) { |
| 165 _dropNext = true; |
| 166 } |
| 167 if (_fastMode) { |
| 168 // always drop in aggressive mode |
| 169 _dropNext = true; |
| 170 } |
| 171 |
| 172 _dropRatio.Apply(1.0f, 1.0f); |
| 173 _dropRatio.UpdateBase(0.9f); |
| 174 } else { |
| 175 _dropRatio.Apply(1.0f, 0.0f); |
| 176 } |
| 177 _wasBelowMax = _accumulator < _accumulatorMax; |
| 178 } |
| 179 |
| 180 // This function signals when to drop frames to the caller. It makes use of the |
| 181 // dropRatio |
| 182 // to smooth out the drops over time. |
| 183 bool FrameDropper::DropFrame() { |
| 184 if (!_enabled) { |
| 185 return false; |
| 186 } |
| 187 if (_dropNext) { |
58 _dropNext = false; | 188 _dropNext = false; |
59 _dropRatio.Reset(0.9f); | |
60 _dropRatio.Apply(0.0f, 0.0f); // Initialize to 0 | |
61 _dropCount = 0; | 189 _dropCount = 0; |
62 _windowSize = 0.5f; | 190 } |
63 _wasBelowMax = true; | 191 |
64 _fastMode = false; // start with normal (non-aggressive) mode | 192 if (_dropRatio.filtered() >= 0.5f) { // Drops per keep |
65 // Cap for the encoder buffer level/accumulator, in secs. | 193 // limit is the number of frames we should drop between each kept frame |
66 _cap_buffer_size = 3.0f; | 194 // to keep our drop ratio. limit is positive in this case. |
67 // Cap on maximum amount of dropped frames between kept frames, in secs. | 195 float denom = 1.0f - _dropRatio.filtered(); |
68 _max_time_drops = 4.0f; | 196 if (denom < 1e-5) { |
69 } | 197 denom = 1e-5; |
70 | 198 } |
71 void | 199 int32_t limit = static_cast<int32_t>(1.0f / denom - 1.0f + 0.5f); |
72 FrameDropper::Enable(bool enable) | 200 // Put a bound on the max amount of dropped frames between each kept |
73 { | 201 // frame, in terms of frame rate and window size (secs). |
74 _enabled = enable; | 202 int max_limit = static_cast<int>(_incoming_frame_rate * _max_time_drops); |
75 } | 203 if (limit > max_limit) { |
76 | 204 limit = max_limit; |
77 void | 205 } |
78 FrameDropper::Fill(size_t frameSizeBytes, bool deltaFrame) | 206 if (_dropCount < 0) { |
79 { | 207 // Reset the _dropCount since it was negative and should be positive. |
80 if (!_enabled) | 208 if (_dropRatio.filtered() > 0.4f) { |
81 { | 209 _dropCount = -_dropCount; |
82 return; | 210 } else { |
83 } | 211 _dropCount = 0; |
84 float frameSizeKbits = 8.0f * static_cast<float>(frameSizeBytes) / 1000.0f; | 212 } |
85 if (!deltaFrame && !_fastMode) // fast mode does not treat key-frames any di
fferent | 213 } |
86 { | 214 if (_dropCount < limit) { |
87 _keyFrameSizeAvgKbits.Apply(1, frameSizeKbits); | 215 // As long we are below the limit we should drop frames. |
88 _keyFrameRatio.Apply(1.0, 1.0); | 216 _dropCount++; |
89 if (frameSizeKbits > _keyFrameSizeAvgKbits.filtered()) | 217 return true; |
90 { | 218 } else { |
91 // Remove the average key frame size since we | 219 // Only when we reset _dropCount a frame should be kept. |
92 // compensate for key frames when adding delta | 220 _dropCount = 0; |
93 // frames. | 221 return false; |
94 frameSizeKbits -= _keyFrameSizeAvgKbits.filtered(); | 222 } |
95 } | 223 } else if (_dropRatio.filtered() > 0.0f && |
96 else | 224 _dropRatio.filtered() < 0.5f) { // Keeps per drop |
97 { | 225 // limit is the number of frames we should keep between each drop |
98 // Shouldn't be negative, so zero is the lower bound. | 226 // in order to keep the drop ratio. limit is negative in this case, |
99 frameSizeKbits = 0; | 227 // and the _dropCount is also negative. |
100 } | 228 float denom = _dropRatio.filtered(); |
101 if (_keyFrameRatio.filtered() > 1e-5 && | 229 if (denom < 1e-5) { |
102 1 / _keyFrameRatio.filtered() < _keyFrameSpreadFrames) | 230 denom = 1e-5; |
103 { | 231 } |
104 // We are sending key frames more often than our upper bound for | 232 int32_t limit = -static_cast<int32_t>(1.0f / denom - 1.0f + 0.5f); |
105 // how much we allow the key frame compensation to be spread | 233 if (_dropCount > 0) { |
106 // out in time. Therefor we must use the key frame ratio rather | 234 // Reset the _dropCount since we have a positive |
107 // than keyFrameSpreadFrames. | 235 // _dropCount, and it should be negative. |
108 _keyFrameCount = | 236 if (_dropRatio.filtered() < 0.6f) { |
109 static_cast<int32_t>(1 / _keyFrameRatio.filtered() + 0.5); | 237 _dropCount = -_dropCount; |
110 } | 238 } else { |
111 else | 239 _dropCount = 0; |
112 { | 240 } |
113 // Compensate for the key frame the following frames | 241 } |
114 _keyFrameCount = static_cast<int32_t>(_keyFrameSpreadFrames + 0.5); | 242 if (_dropCount > limit) { |
115 } | 243 if (_dropCount == 0) { |
116 } | 244 // Drop frames when we reset _dropCount. |
117 else | 245 _dropCount--; |
118 { | 246 return true; |
119 // Decrease the keyFrameRatio | 247 } else { |
120 _keyFrameRatio.Apply(1.0, 0.0); | 248 // Keep frames as long as we haven't reached limit. |
121 } | 249 _dropCount--; |
122 // Change the level of the accumulator (bucket) | |
123 _accumulator += frameSizeKbits; | |
124 CapAccumulator(); | |
125 } | |
126 | |
127 void | |
128 FrameDropper::Leak(uint32_t inputFrameRate) | |
129 { | |
130 if (!_enabled) | |
131 { | |
132 return; | |
133 } | |
134 if (inputFrameRate < 1) | |
135 { | |
136 return; | |
137 } | |
138 if (_targetBitRate < 0.0f) | |
139 { | |
140 return; | |
141 } | |
142 _keyFrameSpreadFrames = 0.5f * inputFrameRate; | |
143 // T is the expected bits per frame (target). If all frames were the same si
ze, | |
144 // we would get T bits per frame. Notice that T is also weighted to be able
to | |
145 // force a lower frame rate if wanted. | |
146 float T = _targetBitRate / inputFrameRate; | |
147 if (_keyFrameCount > 0) | |
148 { | |
149 // Perform the key frame compensation | |
150 if (_keyFrameRatio.filtered() > 0 && | |
151 1 / _keyFrameRatio.filtered() < _keyFrameSpreadFrames) | |
152 { | |
153 T -= _keyFrameSizeAvgKbits.filtered() * _keyFrameRatio.filtered(); | |
154 } | |
155 else | |
156 { | |
157 T -= _keyFrameSizeAvgKbits.filtered() / _keyFrameSpreadFrames; | |
158 } | |
159 _keyFrameCount--; | |
160 } | |
161 _accumulator -= T; | |
162 if (_accumulator < 0.0f) | |
163 { | |
164 _accumulator = 0.0f; | |
165 } | |
166 UpdateRatio(); | |
167 } | |
168 | |
169 void | |
170 FrameDropper::UpdateNack(uint32_t nackBytes) | |
171 { | |
172 if (!_enabled) | |
173 { | |
174 return; | |
175 } | |
176 _accumulator += static_cast<float>(nackBytes) * 8.0f / 1000.0f; | |
177 } | |
178 | |
179 void | |
180 FrameDropper::FillBucket(float inKbits, float outKbits) | |
181 { | |
182 _accumulator += (inKbits - outKbits); | |
183 } | |
184 | |
185 void | |
186 FrameDropper::UpdateRatio() | |
187 { | |
188 if (_accumulator > 1.3f * _accumulatorMax) | |
189 { | |
190 // Too far above accumulator max, react faster | |
191 _dropRatio.UpdateBase(0.8f); | |
192 } | |
193 else | |
194 { | |
195 // Go back to normal reaction | |
196 _dropRatio.UpdateBase(0.9f); | |
197 } | |
198 if (_accumulator > _accumulatorMax) | |
199 { | |
200 // We are above accumulator max, and should ideally | |
201 // drop a frame. Increase the dropRatio and drop | |
202 // the frame later. | |
203 if (_wasBelowMax) | |
204 { | |
205 _dropNext = true; | |
206 } | |
207 if (_fastMode) | |
208 { | |
209 // always drop in aggressive mode | |
210 _dropNext = true; | |
211 } | |
212 | |
213 _dropRatio.Apply(1.0f, 1.0f); | |
214 _dropRatio.UpdateBase(0.9f); | |
215 } | |
216 else | |
217 { | |
218 _dropRatio.Apply(1.0f, 0.0f); | |
219 } | |
220 _wasBelowMax = _accumulator < _accumulatorMax; | |
221 } | |
222 | |
223 // This function signals when to drop frames to the caller. It makes use of the
dropRatio | |
224 // to smooth out the drops over time. | |
225 bool | |
226 FrameDropper::DropFrame() | |
227 { | |
228 if (!_enabled) | |
229 { | |
230 return false; | 250 return false; |
231 } | 251 } |
232 if (_dropNext) | 252 } else { |
233 { | 253 _dropCount = 0; |
234 _dropNext = false; | 254 return false; |
235 _dropCount = 0; | 255 } |
236 } | 256 } |
237 | 257 _dropCount = 0; |
238 if (_dropRatio.filtered() >= 0.5f) // Drops per keep | 258 return false; |
239 { | 259 |
240 // limit is the number of frames we should drop between each kept frame | 260 // A simpler version, unfiltered and quicker |
241 // to keep our drop ratio. limit is positive in this case. | 261 // bool dropNext = _dropNext; |
242 float denom = 1.0f - _dropRatio.filtered(); | 262 // _dropNext = false; |
243 if (denom < 1e-5) | 263 // return dropNext; |
244 { | 264 } |
245 denom = (float)1e-5; | 265 |
246 } | 266 void FrameDropper::SetRates(float bitRate, float incoming_frame_rate) { |
247 int32_t limit = static_cast<int32_t>(1.0f / denom - 1.0f + 0.5f); | 267 // Bit rate of -1 means infinite bandwidth. |
248 // Put a bound on the max amount of dropped frames between each kept | 268 _accumulatorMax = bitRate * _windowSize; // bitRate * windowSize (in seconds) |
249 // frame, in terms of frame rate and window size (secs). | 269 if (_targetBitRate > 0.0f && bitRate < _targetBitRate && |
250 int max_limit = static_cast<int>(_incoming_frame_rate * | 270 _accumulator > _accumulatorMax) { |
251 _max_time_drops); | 271 // Rescale the accumulator level if the accumulator max decreases |
252 if (limit > max_limit) { | 272 _accumulator = bitRate / _targetBitRate * _accumulator; |
253 limit = max_limit; | 273 } |
254 } | 274 _targetBitRate = bitRate; |
255 if (_dropCount < 0) | 275 CapAccumulator(); |
256 { | 276 _incoming_frame_rate = incoming_frame_rate; |
257 // Reset the _dropCount since it was negative and should be positive
. | 277 } |
258 if (_dropRatio.filtered() > 0.4f) | 278 |
259 { | 279 float FrameDropper::ActualFrameRate(uint32_t inputFrameRate) const { |
260 _dropCount = -_dropCount; | 280 if (!_enabled) { |
261 } | 281 return static_cast<float>(inputFrameRate); |
262 else | 282 } |
263 { | 283 return inputFrameRate * (1.0f - _dropRatio.filtered()); |
264 _dropCount = 0; | |
265 } | |
266 } | |
267 if (_dropCount < limit) | |
268 { | |
269 // As long we are below the limit we should drop frames. | |
270 _dropCount++; | |
271 return true; | |
272 } | |
273 else | |
274 { | |
275 // Only when we reset _dropCount a frame should be kept. | |
276 _dropCount = 0; | |
277 return false; | |
278 } | |
279 } | |
280 else if (_dropRatio.filtered() > 0.0f && | |
281 _dropRatio.filtered() < 0.5f) // Keeps per drop | |
282 { | |
283 // limit is the number of frames we should keep between each drop | |
284 // in order to keep the drop ratio. limit is negative in this case, | |
285 // and the _dropCount is also negative. | |
286 float denom = _dropRatio.filtered(); | |
287 if (denom < 1e-5) | |
288 { | |
289 denom = (float)1e-5; | |
290 } | |
291 int32_t limit = -static_cast<int32_t>(1.0f / denom - 1.0f + 0.5f); | |
292 if (_dropCount > 0) | |
293 { | |
294 // Reset the _dropCount since we have a positive | |
295 // _dropCount, and it should be negative. | |
296 if (_dropRatio.filtered() < 0.6f) | |
297 { | |
298 _dropCount = -_dropCount; | |
299 } | |
300 else | |
301 { | |
302 _dropCount = 0; | |
303 } | |
304 } | |
305 if (_dropCount > limit) | |
306 { | |
307 if (_dropCount == 0) | |
308 { | |
309 // Drop frames when we reset _dropCount. | |
310 _dropCount--; | |
311 return true; | |
312 } | |
313 else | |
314 { | |
315 // Keep frames as long as we haven't reached limit. | |
316 _dropCount--; | |
317 return false; | |
318 } | |
319 } | |
320 else | |
321 { | |
322 _dropCount = 0; | |
323 return false; | |
324 } | |
325 } | |
326 _dropCount = 0; | |
327 return false; | |
328 | |
329 // A simpler version, unfiltered and quicker | |
330 //bool dropNext = _dropNext; | |
331 //_dropNext = false; | |
332 //return dropNext; | |
333 } | |
334 | |
335 void | |
336 FrameDropper::SetRates(float bitRate, float incoming_frame_rate) | |
337 { | |
338 // Bit rate of -1 means infinite bandwidth. | |
339 _accumulatorMax = bitRate * _windowSize; // bitRate * windowSize (in seconds
) | |
340 if (_targetBitRate > 0.0f && bitRate < _targetBitRate && _accumulator > _acc
umulatorMax) | |
341 { | |
342 // Rescale the accumulator level if the accumulator max decreases | |
343 _accumulator = bitRate / _targetBitRate * _accumulator; | |
344 } | |
345 _targetBitRate = bitRate; | |
346 CapAccumulator(); | |
347 _incoming_frame_rate = incoming_frame_rate; | |
348 } | |
349 | |
350 float | |
351 FrameDropper::ActualFrameRate(uint32_t inputFrameRate) const | |
352 { | |
353 if (!_enabled) | |
354 { | |
355 return static_cast<float>(inputFrameRate); | |
356 } | |
357 return inputFrameRate * (1.0f - _dropRatio.filtered()); | |
358 } | 284 } |
359 | 285 |
360 // Put a cap on the accumulator, i.e., don't let it grow beyond some level. | 286 // Put a cap on the accumulator, i.e., don't let it grow beyond some level. |
361 // This is a temporary fix for screencasting where very large frames from | 287 // This is a temporary fix for screencasting where very large frames from |
362 // encoder will cause very slow response (too many frame drops). | 288 // encoder will cause very slow response (too many frame drops). |
363 void FrameDropper::CapAccumulator() { | 289 void FrameDropper::CapAccumulator() { |
364 float max_accumulator = _targetBitRate * _cap_buffer_size; | 290 float max_accumulator = _targetBitRate * _cap_buffer_size; |
365 if (_accumulator > max_accumulator) { | 291 if (_accumulator > max_accumulator) { |
366 _accumulator = max_accumulator; | 292 _accumulator = max_accumulator; |
367 } | 293 } |
368 } | 294 } |
369 | 295 } // namespace webrtc |
370 } | |
OLD | NEW |