• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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