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
23namespace webrtc {
24namespace 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.
29enum { kLossPrHistorySize = 10 };
30
31// 1000 ms, total filter length is (kLossPrHistorySize * 1000) ms
32enum { kLossPrShortFilterWinMs = 1000 };
33
34// The type of filter used on the received packet loss reports.
35enum 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.
44enum HybridNackTH {
45    kHighRttNackMs = 100,
46    kLowRttNackMs = 20
47};
48
49struct VCMProtectionParameters
50{
51    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
78enum VCMProtectionMethodEnum
79{
80    kNack,
81    kFec,
82    kNackFec,
83    kNone
84};
85
86class VCMLossProbabilitySample
87{
88public:
89    VCMLossProbabilitySample() : lossPr255(0), timeMs(-1) {};
90
91    uint8_t     lossPr255;
92    int64_t     timeMs;
93};
94
95
96class VCMProtectionMethod
97{
98public:
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
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
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
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
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
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.
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.
145    virtual bool RequiredUepProtectionD() { return _useUepProtectionD; }
146
147    virtual int MaxFramesFec() const { return 1; }
148
149    // Updates content metrics
150    void UpdateContentMetrics(const VideoContentMetrics* contentMetrics);
151
152protected:
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
170class VCMNackMethod : public VCMProtectionMethod
171{
172public:
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
180class VCMFecMethod : public VCMProtectionMethod
181{
182public:
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
204protected:
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
219class VCMNackFecMethod : public VCMFecMethod
220{
221public:
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);
234private:
235    int ComputeMaxFramesFec(const VCMProtectionParameters* parameters);
236
237    int _lowRttNackMs;
238    int _highRttNackMs;
239    int _maxFramesFec;
240};
241
242class VCMLossProtectionLogic
243{
244public:
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.
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.
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
366private:
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