| 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 |