|  | /* | 
|  | *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ | 
|  | #define WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ | 
|  |  | 
|  | #include <math.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "webrtc/base/numerics/exp_filter.h" | 
|  | #include "webrtc/modules/video_coding/internal_defines.h" | 
|  | #include "webrtc/typedefs.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace media_optimization { | 
|  |  | 
|  | // Number of time periods used for (max) window filter for packet loss | 
|  | // TODO(marpan): set reasonable window size for filtered packet loss, | 
|  | // adjustment should be based on logged/real data of loss stats/correlation. | 
|  | enum { kLossPrHistorySize = 10 }; | 
|  |  | 
|  | // 1000 ms, total filter length is (kLossPrHistorySize * 1000) ms | 
|  | enum { kLossPrShortFilterWinMs = 1000 }; | 
|  |  | 
|  | // The type of filter used on the received packet loss reports. | 
|  | enum FilterPacketLossMode { | 
|  | kNoFilter,   // No filtering on received loss. | 
|  | kAvgFilter,  // Recursive average filter. | 
|  | kMaxFilter   // Max-window filter, over the time interval of: | 
|  | // (kLossPrHistorySize * kLossPrShortFilterWinMs) ms. | 
|  | }; | 
|  |  | 
|  | // Thresholds for hybrid NACK/FEC | 
|  | // common to media optimization and the jitter buffer. | 
|  | const int64_t kLowRttNackMs = 20; | 
|  |  | 
|  | // If the RTT is higher than this an extra RTT wont be added to to the jitter | 
|  | // buffer delay. | 
|  | const int kMaxRttDelayThreshold = 500; | 
|  |  | 
|  | struct VCMProtectionParameters { | 
|  | VCMProtectionParameters() | 
|  | : rtt(0), | 
|  | lossPr(0.0f), | 
|  | bitRate(0.0f), | 
|  | packetsPerFrame(0.0f), | 
|  | packetsPerFrameKey(0.0f), | 
|  | frameRate(0.0f), | 
|  | keyFrameSize(0.0f), | 
|  | fecRateDelta(0), | 
|  | fecRateKey(0), | 
|  | codecWidth(0), | 
|  | codecHeight(0), | 
|  | numLayers(1) {} | 
|  |  | 
|  | int64_t rtt; | 
|  | float lossPr; | 
|  | float bitRate; | 
|  | float packetsPerFrame; | 
|  | float packetsPerFrameKey; | 
|  | float frameRate; | 
|  | float keyFrameSize; | 
|  | uint8_t fecRateDelta; | 
|  | uint8_t fecRateKey; | 
|  | uint16_t codecWidth; | 
|  | uint16_t codecHeight; | 
|  | int numLayers; | 
|  | }; | 
|  |  | 
|  | /******************************/ | 
|  | /* VCMProtectionMethod class  */ | 
|  | /******************************/ | 
|  |  | 
|  | enum VCMProtectionMethodEnum { kNack, kFec, kNackFec, kNone }; | 
|  |  | 
|  | class VCMLossProbabilitySample { | 
|  | public: | 
|  | VCMLossProbabilitySample() : lossPr255(0), timeMs(-1) {} | 
|  |  | 
|  | uint8_t lossPr255; | 
|  | int64_t timeMs; | 
|  | }; | 
|  |  | 
|  | class VCMProtectionMethod { | 
|  | public: | 
|  | VCMProtectionMethod(); | 
|  | virtual ~VCMProtectionMethod(); | 
|  |  | 
|  | // Updates the efficiency of the method using the parameters provided | 
|  | // | 
|  | // Input: | 
|  | //         - parameters         : Parameters used to calculate efficiency | 
|  | // | 
|  | // Return value                 : True if this method is recommended in | 
|  | //                                the given conditions. | 
|  | virtual bool UpdateParameters(const VCMProtectionParameters* parameters) = 0; | 
|  |  | 
|  | // Returns the protection type | 
|  | // | 
|  | // Return value                 : The protection type | 
|  | enum VCMProtectionMethodEnum Type() const { return _type; } | 
|  |  | 
|  | // Returns the effective packet loss for ER, required by this protection | 
|  | // method | 
|  | // | 
|  | // Return value                 : Required effective packet loss | 
|  | virtual uint8_t RequiredPacketLossER() { return _effectivePacketLoss; } | 
|  |  | 
|  | // Extracts the FEC protection factor for Key frame, required by this | 
|  | // protection method | 
|  | // | 
|  | // Return value                 : Required protectionFactor for Key frame | 
|  | virtual uint8_t RequiredProtectionFactorK() { return _protectionFactorK; } | 
|  |  | 
|  | // Extracts the FEC protection factor for Delta frame, required by this | 
|  | // protection method | 
|  | // | 
|  | // Return value                 : Required protectionFactor for delta frame | 
|  | virtual uint8_t RequiredProtectionFactorD() { return _protectionFactorD; } | 
|  |  | 
|  | // Extracts whether the FEC Unequal protection (UEP) is used for Key frame. | 
|  | // | 
|  | // Return value                 : Required Unequal protection on/off state. | 
|  | virtual bool RequiredUepProtectionK() { return _useUepProtectionK; } | 
|  |  | 
|  | // Extracts whether the the FEC Unequal protection (UEP) is used for Delta | 
|  | // frame. | 
|  | // | 
|  | // Return value                 : Required Unequal protection on/off state. | 
|  | virtual bool RequiredUepProtectionD() { return _useUepProtectionD; } | 
|  |  | 
|  | virtual int MaxFramesFec() const { return 1; } | 
|  |  | 
|  | protected: | 
|  | uint8_t _effectivePacketLoss; | 
|  | uint8_t _protectionFactorK; | 
|  | uint8_t _protectionFactorD; | 
|  | // Estimation of residual loss after the FEC | 
|  | float _scaleProtKey; | 
|  | int32_t _maxPayloadSize; | 
|  |  | 
|  | bool _useUepProtectionK; | 
|  | bool _useUepProtectionD; | 
|  | float _corrFecCost; | 
|  | enum VCMProtectionMethodEnum _type; | 
|  | }; | 
|  |  | 
|  | class VCMNackMethod : public VCMProtectionMethod { | 
|  | public: | 
|  | VCMNackMethod(); | 
|  | virtual ~VCMNackMethod(); | 
|  | virtual bool UpdateParameters(const VCMProtectionParameters* parameters); | 
|  | // Get the effective packet loss | 
|  | bool EffectivePacketLoss(const VCMProtectionParameters* parameter); | 
|  | }; | 
|  |  | 
|  | class VCMFecMethod : public VCMProtectionMethod { | 
|  | public: | 
|  | VCMFecMethod(); | 
|  | virtual ~VCMFecMethod(); | 
|  | virtual bool UpdateParameters(const VCMProtectionParameters* parameters); | 
|  | // Get the effective packet loss for ER | 
|  | bool EffectivePacketLoss(const VCMProtectionParameters* parameters); | 
|  | // Get the FEC protection factors | 
|  | bool ProtectionFactor(const VCMProtectionParameters* parameters); | 
|  | // Get the boost for key frame protection | 
|  | uint8_t BoostCodeRateKey(uint8_t packetFrameDelta, | 
|  | uint8_t packetFrameKey) const; | 
|  | // Convert the rates: defined relative to total# packets or source# packets | 
|  | uint8_t ConvertFECRate(uint8_t codeRate) const; | 
|  | // Get the average effective recovery from FEC: for random loss model | 
|  | float AvgRecoveryFEC(const VCMProtectionParameters* parameters) const; | 
|  | // Update FEC with protectionFactorD | 
|  | void UpdateProtectionFactorD(uint8_t protectionFactorD); | 
|  | // Update FEC with protectionFactorK | 
|  | void UpdateProtectionFactorK(uint8_t protectionFactorK); | 
|  | // Compute the bits per frame. Account for temporal layers when applicable. | 
|  | int BitsPerFrame(const VCMProtectionParameters* parameters); | 
|  |  | 
|  | protected: | 
|  | enum { kUpperLimitFramesFec = 6 }; | 
|  | // Thresholds values for the bytes/frame and round trip time, below which we | 
|  | // may turn off FEC, depending on |_numLayers| and |_maxFramesFec|. | 
|  | // Max bytes/frame for VGA, corresponds to ~140k at 25fps. | 
|  | enum { kMaxBytesPerFrameForFec = 700 }; | 
|  | // Max bytes/frame for CIF and lower: corresponds to ~80k at 25fps. | 
|  | enum { kMaxBytesPerFrameForFecLow = 400 }; | 
|  | // Max bytes/frame for frame size larger than VGA, ~200k at 25fps. | 
|  | enum { kMaxBytesPerFrameForFecHigh = 1000 }; | 
|  | }; | 
|  |  | 
|  | class VCMNackFecMethod : public VCMFecMethod { | 
|  | public: | 
|  | VCMNackFecMethod(int64_t lowRttNackThresholdMs, | 
|  | int64_t highRttNackThresholdMs); | 
|  | virtual ~VCMNackFecMethod(); | 
|  | virtual bool UpdateParameters(const VCMProtectionParameters* parameters); | 
|  | // Get the effective packet loss for ER | 
|  | bool EffectivePacketLoss(const VCMProtectionParameters* parameters); | 
|  | // Get the protection factors | 
|  | bool ProtectionFactor(const VCMProtectionParameters* parameters); | 
|  | // Get the max number of frames the FEC is allowed to be based on. | 
|  | int MaxFramesFec() const; | 
|  | // Turn off the FEC based on low bitrate and other factors. | 
|  | bool BitRateTooLowForFec(const VCMProtectionParameters* parameters); | 
|  |  | 
|  | private: | 
|  | int ComputeMaxFramesFec(const VCMProtectionParameters* parameters); | 
|  |  | 
|  | int64_t _lowRttNackMs; | 
|  | int64_t _highRttNackMs; | 
|  | int _maxFramesFec; | 
|  | }; | 
|  |  | 
|  | class VCMLossProtectionLogic { | 
|  | public: | 
|  | explicit VCMLossProtectionLogic(int64_t nowMs); | 
|  | ~VCMLossProtectionLogic(); | 
|  |  | 
|  | // Set the protection method to be used | 
|  | // | 
|  | // Input: | 
|  | //        - newMethodType    : New requested protection method type. If one | 
|  | //                           is already set, it will be deleted and replaced | 
|  | void SetMethod(VCMProtectionMethodEnum newMethodType); | 
|  |  | 
|  | // Update the round-trip time | 
|  | // | 
|  | // Input: | 
|  | //          - rtt           : Round-trip time in seconds. | 
|  | void UpdateRtt(int64_t rtt); | 
|  |  | 
|  | // Update the filtered packet loss. | 
|  | // | 
|  | // Input: | 
|  | //          - packetLossEnc :  The reported packet loss filtered | 
|  | //                             (max window or average) | 
|  | void UpdateFilteredLossPr(uint8_t packetLossEnc); | 
|  |  | 
|  | // Update the current target bit rate. | 
|  | // | 
|  | // Input: | 
|  | //          - bitRate          : The current target bit rate in kbits/s | 
|  | void UpdateBitRate(float bitRate); | 
|  |  | 
|  | // Update the number of packets per frame estimate, for delta frames | 
|  | // | 
|  | // Input: | 
|  | //          - nPackets         : Number of packets in the latest sent frame. | 
|  | void UpdatePacketsPerFrame(float nPackets, int64_t nowMs); | 
|  |  | 
|  | // Update the number of packets per frame estimate, for key frames | 
|  | // | 
|  | // Input: | 
|  | //          - nPackets         : umber of packets in the latest sent frame. | 
|  | void UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs); | 
|  |  | 
|  | // Update the keyFrameSize estimate | 
|  | // | 
|  | // Input: | 
|  | //          - keyFrameSize     : The size of the latest sent key frame. | 
|  | void UpdateKeyFrameSize(float keyFrameSize); | 
|  |  | 
|  | // Update the frame rate | 
|  | // | 
|  | // Input: | 
|  | //          - frameRate        : The current target frame rate. | 
|  | void UpdateFrameRate(float frameRate) { _frameRate = frameRate; } | 
|  |  | 
|  | // Update the frame size | 
|  | // | 
|  | // Input: | 
|  | //          - width        : The codec frame width. | 
|  | //          - height       : The codec frame height. | 
|  | void UpdateFrameSize(size_t width, size_t height); | 
|  |  | 
|  | // Update the number of active layers | 
|  | // | 
|  | // Input: | 
|  | //          - numLayers    : Number of layers used. | 
|  | void UpdateNumLayers(int numLayers); | 
|  |  | 
|  | // The amount of packet loss to cover for with FEC. | 
|  | // | 
|  | // Input: | 
|  | //          - fecRateKey      : Packet loss to cover for with FEC when | 
|  | //                              sending key frames. | 
|  | //          - fecRateDelta    : Packet loss to cover for with FEC when | 
|  | //                              sending delta frames. | 
|  | void UpdateFECRates(uint8_t fecRateKey, uint8_t fecRateDelta) { | 
|  | _fecRateKey = fecRateKey; | 
|  | _fecRateDelta = fecRateDelta; | 
|  | } | 
|  |  | 
|  | // Update the protection methods with the current VCMProtectionParameters | 
|  | // and set the requested protection settings. | 
|  | // Return value     : Returns true on update | 
|  | bool UpdateMethod(); | 
|  |  | 
|  | // Returns the method currently selected. | 
|  | // | 
|  | // Return value                 : The protection method currently selected. | 
|  | VCMProtectionMethod* SelectedMethod() const; | 
|  |  | 
|  | // Return the protection type of the currently selected method | 
|  | VCMProtectionMethodEnum SelectedType() const; | 
|  |  | 
|  | // Updates the filtered loss for the average and max window packet loss, | 
|  | // and returns the filtered loss probability in the interval [0, 255]. | 
|  | // The returned filtered loss value depends on the parameter |filter_mode|. | 
|  | // The input parameter |lossPr255| is the received packet loss. | 
|  |  | 
|  | // Return value                 : The filtered loss probability | 
|  | uint8_t FilteredLoss(int64_t nowMs, | 
|  | FilterPacketLossMode filter_mode, | 
|  | uint8_t lossPr255); | 
|  |  | 
|  | void Reset(int64_t nowMs); | 
|  |  | 
|  | void Release(); | 
|  |  | 
|  | private: | 
|  | // Sets the available loss protection methods. | 
|  | void UpdateMaxLossHistory(uint8_t lossPr255, int64_t now); | 
|  | uint8_t MaxFilteredLossPr(int64_t nowMs) const; | 
|  | std::unique_ptr<VCMProtectionMethod> _selectedMethod; | 
|  | VCMProtectionParameters _currentParameters; | 
|  | int64_t _rtt; | 
|  | float _lossPr; | 
|  | float _bitRate; | 
|  | float _frameRate; | 
|  | float _keyFrameSize; | 
|  | uint8_t _fecRateKey; | 
|  | uint8_t _fecRateDelta; | 
|  | int64_t _lastPrUpdateT; | 
|  | int64_t _lastPacketPerFrameUpdateT; | 
|  | int64_t _lastPacketPerFrameUpdateTKey; | 
|  | rtc::ExpFilter _lossPr255; | 
|  | VCMLossProbabilitySample _lossPrHistory[kLossPrHistorySize]; | 
|  | uint8_t _shortMaxLossPr255; | 
|  | rtc::ExpFilter _packetsPerFrame; | 
|  | rtc::ExpFilter _packetsPerFrameKey; | 
|  | size_t _codecWidth; | 
|  | size_t _codecHeight; | 
|  | int _numLayers; | 
|  | }; | 
|  |  | 
|  | }  // namespace media_optimization | 
|  | }  // namespace webrtc | 
|  |  | 
|  | #endif  // WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_ |