/* * 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 #include #include "webrtc/base/exp_filter.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/video_coding/internal_defines.h" #include "webrtc/modules/video_coding/qm_select.h" #include "webrtc/system_wrappers/include/trace.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; 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; } // Updates content metrics void UpdateContentMetrics(const VideoContentMetrics* contentMetrics); protected: uint8_t _effectivePacketLoss; uint8_t _protectionFactorK; uint8_t _protectionFactorD; // Estimation of residual loss after the FEC float _scaleProtKey; int32_t _maxPayloadSize; VCMQmRobustness* _qmRobustness; 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(uint16_t width, uint16_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; rtc::scoped_ptr _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; uint16_t _codecWidth; uint16_t _codecHeight; int _numLayers; }; } // namespace media_optimization } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_