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 #ifndef WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ 12 #define WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ 13 14 #include <math.h> 15 #include <stdlib.h> 16 17 #include "webrtc/base/exp_filter.h" 18 #include "webrtc/modules/video_coding/main/source/internal_defines.h" 19 #include "webrtc/modules/video_coding/main/source/qm_select.h" 20 #include "webrtc/system_wrappers/interface/trace.h" 21 #include "webrtc/typedefs.h" 22 23 namespace webrtc { 24 namespace media_optimization { 25 26 // Number of time periods used for (max) window filter for packet loss 27 // TODO (marpan): set reasonable window size for filtered packet loss, 28 // adjustment should be based on logged/real data of loss stats/correlation. 29 enum { kLossPrHistorySize = 10 }; 30 31 // 1000 ms, total filter length is (kLossPrHistorySize * 1000) ms 32 enum { kLossPrShortFilterWinMs = 1000 }; 33 34 // The type of filter used on the received packet loss reports. 35 enum FilterPacketLossMode { 36 kNoFilter, // No filtering on received loss. 37 kAvgFilter, // Recursive average filter. 38 kMaxFilter // Max-window filter, over the time interval of: 39 // (kLossPrHistorySize * kLossPrShortFilterWinMs) ms. 40 }; 41 42 // Thresholds for hybrid NACK/FEC 43 // common to media optimization and the jitter buffer. 44 enum HybridNackTH { 45 kHighRttNackMs = 100, 46 kLowRttNackMs = 20 47 }; 48 49 struct VCMProtectionParameters 50 { VCMProtectionParametersVCMProtectionParameters51 VCMProtectionParameters() : rtt(0), lossPr(0.0f), bitRate(0.0f), 52 packetsPerFrame(0.0f), packetsPerFrameKey(0.0f), frameRate(0.0f), 53 keyFrameSize(0.0f), fecRateDelta(0), fecRateKey(0), 54 residualPacketLossFec(0.0f), codecWidth(0), codecHeight(0), 55 numLayers(1) 56 {} 57 58 int rtt; 59 float lossPr; 60 float bitRate; 61 float packetsPerFrame; 62 float packetsPerFrameKey; 63 float frameRate; 64 float keyFrameSize; 65 uint8_t fecRateDelta; 66 uint8_t fecRateKey; 67 float residualPacketLossFec; 68 uint16_t codecWidth; 69 uint16_t codecHeight; 70 int numLayers; 71 }; 72 73 74 /******************************/ 75 /* VCMProtectionMethod class */ 76 /******************************/ 77 78 enum VCMProtectionMethodEnum 79 { 80 kNack, 81 kFec, 82 kNackFec, 83 kNone 84 }; 85 86 class VCMLossProbabilitySample 87 { 88 public: VCMLossProbabilitySample()89 VCMLossProbabilitySample() : lossPr255(0), timeMs(-1) {}; 90 91 uint8_t lossPr255; 92 int64_t timeMs; 93 }; 94 95 96 class VCMProtectionMethod 97 { 98 public: 99 VCMProtectionMethod(); 100 virtual ~VCMProtectionMethod(); 101 102 // Updates the efficiency of the method using the parameters provided 103 // 104 // Input: 105 // - parameters : Parameters used to calculate efficiency 106 // 107 // Return value : True if this method is recommended in 108 // the given conditions. 109 virtual bool UpdateParameters(const VCMProtectionParameters* parameters) = 0; 110 111 // Returns the protection type 112 // 113 // Return value : The protection type Type()114 enum VCMProtectionMethodEnum Type() const { return _type; } 115 116 // Returns the bit rate required by this protection method 117 // during these conditions. 118 // 119 // Return value : Required bit rate RequiredBitRate()120 virtual float RequiredBitRate() { return _efficiency; } 121 122 // Returns the effective packet loss for ER, required by this protection method 123 // 124 // Return value : Required effective packet loss RequiredPacketLossER()125 virtual uint8_t RequiredPacketLossER() { return _effectivePacketLoss; } 126 127 // Extracts the FEC protection factor for Key frame, required by this protection method 128 // 129 // Return value : Required protectionFactor for Key frame RequiredProtectionFactorK()130 virtual uint8_t RequiredProtectionFactorK() { return _protectionFactorK; } 131 132 // Extracts the FEC protection factor for Delta frame, required by this protection method 133 // 134 // Return value : Required protectionFactor for delta frame RequiredProtectionFactorD()135 virtual uint8_t RequiredProtectionFactorD() { return _protectionFactorD; } 136 137 // Extracts whether the FEC Unequal protection (UEP) is used for Key frame. 138 // 139 // Return value : Required Unequal protection on/off state. RequiredUepProtectionK()140 virtual bool RequiredUepProtectionK() { return _useUepProtectionK; } 141 142 // Extracts whether the the FEC Unequal protection (UEP) is used for Delta frame. 143 // 144 // Return value : Required Unequal protection on/off state. RequiredUepProtectionD()145 virtual bool RequiredUepProtectionD() { return _useUepProtectionD; } 146 MaxFramesFec()147 virtual int MaxFramesFec() const { return 1; } 148 149 // Updates content metrics 150 void UpdateContentMetrics(const VideoContentMetrics* contentMetrics); 151 152 protected: 153 154 uint8_t _effectivePacketLoss; 155 uint8_t _protectionFactorK; 156 uint8_t _protectionFactorD; 157 // Estimation of residual loss after the FEC 158 float _residualPacketLossFec; 159 float _scaleProtKey; 160 int32_t _maxPayloadSize; 161 162 VCMQmRobustness* _qmRobustness; 163 bool _useUepProtectionK; 164 bool _useUepProtectionD; 165 float _corrFecCost; 166 enum VCMProtectionMethodEnum _type; 167 float _efficiency; 168 }; 169 170 class VCMNackMethod : public VCMProtectionMethod 171 { 172 public: 173 VCMNackMethod(); 174 virtual ~VCMNackMethod(); 175 virtual bool UpdateParameters(const VCMProtectionParameters* parameters); 176 // Get the effective packet loss 177 bool EffectivePacketLoss(const VCMProtectionParameters* parameter); 178 }; 179 180 class VCMFecMethod : public VCMProtectionMethod 181 { 182 public: 183 VCMFecMethod(); 184 virtual ~VCMFecMethod(); 185 virtual bool UpdateParameters(const VCMProtectionParameters* parameters); 186 // Get the effective packet loss for ER 187 bool EffectivePacketLoss(const VCMProtectionParameters* parameters); 188 // Get the FEC protection factors 189 bool ProtectionFactor(const VCMProtectionParameters* parameters); 190 // Get the boost for key frame protection 191 uint8_t BoostCodeRateKey(uint8_t packetFrameDelta, 192 uint8_t packetFrameKey) const; 193 // Convert the rates: defined relative to total# packets or source# packets 194 uint8_t ConvertFECRate(uint8_t codeRate) const; 195 // Get the average effective recovery from FEC: for random loss model 196 float AvgRecoveryFEC(const VCMProtectionParameters* parameters) const; 197 // Update FEC with protectionFactorD 198 void UpdateProtectionFactorD(uint8_t protectionFactorD); 199 // Update FEC with protectionFactorK 200 void UpdateProtectionFactorK(uint8_t protectionFactorK); 201 // Compute the bits per frame. Account for temporal layers when applicable. 202 int BitsPerFrame(const VCMProtectionParameters* parameters); 203 204 protected: 205 enum { kUpperLimitFramesFec = 6 }; 206 // Thresholds values for the bytes/frame and round trip time, below which we 207 // may turn off FEC, depending on |_numLayers| and |_maxFramesFec|. 208 // Max bytes/frame for VGA, corresponds to ~140k at 25fps. 209 enum { kMaxBytesPerFrameForFec = 700 }; 210 // Max bytes/frame for CIF and lower: corresponds to ~80k at 25fps. 211 enum { kMaxBytesPerFrameForFecLow = 400 }; 212 // Max bytes/frame for frame size larger than VGA, ~200k at 25fps. 213 enum { kMaxBytesPerFrameForFecHigh = 1000 }; 214 // Max round trip time threshold in ms. 215 enum { kMaxRttTurnOffFec = 200 }; 216 }; 217 218 219 class VCMNackFecMethod : public VCMFecMethod 220 { 221 public: 222 VCMNackFecMethod(int lowRttNackThresholdMs, 223 int highRttNackThresholdMs); 224 virtual ~VCMNackFecMethod(); 225 virtual bool UpdateParameters(const VCMProtectionParameters* parameters); 226 // Get the effective packet loss for ER 227 bool EffectivePacketLoss(const VCMProtectionParameters* parameters); 228 // Get the protection factors 229 bool ProtectionFactor(const VCMProtectionParameters* parameters); 230 // Get the max number of frames the FEC is allowed to be based on. 231 int MaxFramesFec() const; 232 // Turn off the FEC based on low bitrate and other factors. 233 bool BitRateTooLowForFec(const VCMProtectionParameters* parameters); 234 private: 235 int ComputeMaxFramesFec(const VCMProtectionParameters* parameters); 236 237 int _lowRttNackMs; 238 int _highRttNackMs; 239 int _maxFramesFec; 240 }; 241 242 class VCMLossProtectionLogic 243 { 244 public: 245 VCMLossProtectionLogic(int64_t nowMs); 246 ~VCMLossProtectionLogic(); 247 248 // Set the protection method to be used 249 // 250 // Input: 251 // - newMethodType : New requested protection method type. If one 252 // is already set, it will be deleted and replaced 253 // Return value: Returns true on update 254 bool SetMethod(VCMProtectionMethodEnum newMethodType); 255 256 // Remove requested protection method 257 // Input: 258 // - method : method to be removed (if currently selected) 259 // 260 // Return value: Returns true on update 261 bool RemoveMethod(VCMProtectionMethodEnum method); 262 263 // Return required bit rate per selected protectin method 264 float RequiredBitRate() const; 265 266 // Update the round-trip time 267 // 268 // Input: 269 // - rtt : Round-trip time in seconds. 270 void UpdateRtt(uint32_t rtt); 271 272 // Update residual packet loss 273 // 274 // Input: 275 // - residualPacketLoss : residual packet loss: 276 // effective loss after FEC recovery 277 void UpdateResidualPacketLoss(float _residualPacketLoss); 278 279 // Update the filtered packet loss. 280 // 281 // Input: 282 // - packetLossEnc : The reported packet loss filtered 283 // (max window or average) 284 void UpdateFilteredLossPr(uint8_t packetLossEnc); 285 286 // Update the current target bit rate. 287 // 288 // Input: 289 // - bitRate : The current target bit rate in kbits/s 290 void UpdateBitRate(float bitRate); 291 292 // Update the number of packets per frame estimate, for delta frames 293 // 294 // Input: 295 // - nPackets : Number of packets in the latest sent frame. 296 void UpdatePacketsPerFrame(float nPackets, int64_t nowMs); 297 298 // Update the number of packets per frame estimate, for key frames 299 // 300 // Input: 301 // - nPackets : umber of packets in the latest sent frame. 302 void UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs); 303 304 // Update the keyFrameSize estimate 305 // 306 // Input: 307 // - keyFrameSize : The size of the latest sent key frame. 308 void UpdateKeyFrameSize(float keyFrameSize); 309 310 // Update the frame rate 311 // 312 // Input: 313 // - frameRate : The current target frame rate. UpdateFrameRate(float frameRate)314 void UpdateFrameRate(float frameRate) { _frameRate = frameRate; } 315 316 // Update the frame size 317 // 318 // Input: 319 // - width : The codec frame width. 320 // - height : The codec frame height. 321 void UpdateFrameSize(uint16_t width, uint16_t height); 322 323 // Update the number of active layers 324 // 325 // Input: 326 // - numLayers : Number of layers used. 327 void UpdateNumLayers(int numLayers); 328 329 // The amount of packet loss to cover for with FEC. 330 // 331 // Input: 332 // - fecRateKey : Packet loss to cover for with FEC when 333 // sending key frames. 334 // - fecRateDelta : Packet loss to cover for with FEC when 335 // sending delta frames. UpdateFECRates(uint8_t fecRateKey,uint8_t fecRateDelta)336 void UpdateFECRates(uint8_t fecRateKey, uint8_t fecRateDelta) 337 { _fecRateKey = fecRateKey; 338 _fecRateDelta = fecRateDelta; } 339 340 // Update the protection methods with the current VCMProtectionParameters 341 // and set the requested protection settings. 342 // Return value : Returns true on update 343 bool UpdateMethod(); 344 345 // Returns the method currently selected. 346 // 347 // Return value : The protection method currently selected. 348 VCMProtectionMethod* SelectedMethod() const; 349 350 // Return the protection type of the currently selected method 351 VCMProtectionMethodEnum SelectedType() const; 352 353 // Updates the filtered loss for the average and max window packet loss, 354 // and returns the filtered loss probability in the interval [0, 255]. 355 // The returned filtered loss value depends on the parameter |filter_mode|. 356 // The input parameter |lossPr255| is the received packet loss. 357 358 // Return value : The filtered loss probability 359 uint8_t FilteredLoss(int64_t nowMs, FilterPacketLossMode filter_mode, 360 uint8_t lossPr255); 361 362 void Reset(int64_t nowMs); 363 364 void Release(); 365 366 private: 367 // Sets the available loss protection methods. 368 void UpdateMaxLossHistory(uint8_t lossPr255, int64_t now); 369 uint8_t MaxFilteredLossPr(int64_t nowMs) const; 370 VCMProtectionMethod* _selectedMethod; 371 VCMProtectionParameters _currentParameters; 372 uint32_t _rtt; 373 float _lossPr; 374 float _bitRate; 375 float _frameRate; 376 float _keyFrameSize; 377 uint8_t _fecRateKey; 378 uint8_t _fecRateDelta; 379 int64_t _lastPrUpdateT; 380 int64_t _lastPacketPerFrameUpdateT; 381 int64_t _lastPacketPerFrameUpdateTKey; 382 rtc::ExpFilter _lossPr255; 383 VCMLossProbabilitySample _lossPrHistory[kLossPrHistorySize]; 384 uint8_t _shortMaxLossPr255; 385 rtc::ExpFilter _packetsPerFrame; 386 rtc::ExpFilter _packetsPerFrameKey; 387 float _residualPacketLossFec; 388 uint16_t _codecWidth; 389 uint16_t _codecHeight; 390 int _numLayers; 391 }; 392 393 } // namespace media_optimization 394 } // namespace webrtc 395 396 #endif // WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ 397