blob: 1e2c197673e7bb033b7a850dbefeedda958e8310 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
stefan@webrtc.org8fe03af2012-01-23 14:56:14 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_
12#define MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_
niklase@google.com470e71d2011-07-07 08:21:25 +000013
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000014#include <math.h>
15#include <stdlib.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000016
kwiberg3f55dea2016-02-29 05:51:59 -080017#include <memory>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/video_coding/internal_defines.h"
20#include "rtc_base/numerics/exp_filter.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000021
stefan@webrtc.orga64300a2013-03-04 15:24:40 +000022namespace webrtc {
23namespace media_optimization {
24
marpan@google.com30ecda12011-09-09 17:15:12 +000025// Number of time periods used for (max) window filter for packet loss
philipel9d3ab612015-12-21 04:12:39 -080026// TODO(marpan): set reasonable window size for filtered packet loss,
marpan@google.com30ecda12011-09-09 17:15:12 +000027// adjustment should be based on logged/real data of loss stats/correlation.
28enum { kLossPrHistorySize = 10 };
29
30// 1000 ms, total filter length is (kLossPrHistorySize * 1000) ms
mikhal@google.comb29d9402011-08-01 16:39:20 +000031enum { kLossPrShortFilterWinMs = 1000 };
niklase@google.com470e71d2011-07-07 08:21:25 +000032
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +000033// The type of filter used on the received packet loss reports.
34enum FilterPacketLossMode {
philipel9d3ab612015-12-21 04:12:39 -080035 kNoFilter, // No filtering on received loss.
36 kAvgFilter, // Recursive average filter.
37 kMaxFilter // Max-window filter, over the time interval of:
38 // (kLossPrHistorySize * kLossPrShortFilterWinMs) ms.
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +000039};
40
niklase@google.com470e71d2011-07-07 08:21:25 +000041// Thresholds for hybrid NACK/FEC
42// common to media optimization and the jitter buffer.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000043const int64_t kLowRttNackMs = 20;
niklase@google.com470e71d2011-07-07 08:21:25 +000044
philipelae284082016-05-09 12:14:29 +020045// If the RTT is higher than this an extra RTT wont be added to to the jitter
46// buffer delay.
47const int kMaxRttDelayThreshold = 500;
48
philipel9d3ab612015-12-21 04:12:39 -080049struct VCMProtectionParameters {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020050 VCMProtectionParameters();
niklase@google.com470e71d2011-07-07 08:21:25 +000051
philipel9d3ab612015-12-21 04:12:39 -080052 int64_t rtt;
53 float lossPr;
54 float bitRate;
55 float packetsPerFrame;
56 float packetsPerFrameKey;
57 float frameRate;
58 float keyFrameSize;
59 uint8_t fecRateDelta;
60 uint8_t fecRateKey;
61 uint16_t codecWidth;
62 uint16_t codecHeight;
63 int numLayers;
niklase@google.com470e71d2011-07-07 08:21:25 +000064};
65
niklase@google.com470e71d2011-07-07 08:21:25 +000066/******************************/
stefan@webrtc.orga64300a2013-03-04 15:24:40 +000067/* VCMProtectionMethod class */
68/******************************/
niklase@google.com470e71d2011-07-07 08:21:25 +000069
philipel9d3ab612015-12-21 04:12:39 -080070enum VCMProtectionMethodEnum { kNack, kFec, kNackFec, kNone };
71
72class VCMLossProbabilitySample {
73 public:
74 VCMLossProbabilitySample() : lossPr255(0), timeMs(-1) {}
75
76 uint8_t lossPr255;
77 int64_t timeMs;
niklase@google.com470e71d2011-07-07 08:21:25 +000078};
79
philipel9d3ab612015-12-21 04:12:39 -080080class VCMProtectionMethod {
81 public:
82 VCMProtectionMethod();
83 virtual ~VCMProtectionMethod();
niklase@google.com470e71d2011-07-07 08:21:25 +000084
philipel9d3ab612015-12-21 04:12:39 -080085 // Updates the efficiency of the method using the parameters provided
86 //
87 // Input:
88 // - parameters : Parameters used to calculate efficiency
89 //
90 // Return value : True if this method is recommended in
91 // the given conditions.
92 virtual bool UpdateParameters(const VCMProtectionParameters* parameters) = 0;
93
94 // Returns the protection type
95 //
96 // Return value : The protection type
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020097 VCMProtectionMethodEnum Type() const;
philipel9d3ab612015-12-21 04:12:39 -080098
99 // Returns the effective packet loss for ER, required by this protection
100 // method
101 //
102 // Return value : Required effective packet loss
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200103 virtual uint8_t RequiredPacketLossER();
philipel9d3ab612015-12-21 04:12:39 -0800104
105 // Extracts the FEC protection factor for Key frame, required by this
106 // protection method
107 //
108 // Return value : Required protectionFactor for Key frame
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200109 virtual uint8_t RequiredProtectionFactorK();
philipel9d3ab612015-12-21 04:12:39 -0800110
111 // Extracts the FEC protection factor for Delta frame, required by this
112 // protection method
113 //
114 // Return value : Required protectionFactor for delta frame
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200115 virtual uint8_t RequiredProtectionFactorD();
philipel9d3ab612015-12-21 04:12:39 -0800116
117 // Extracts whether the FEC Unequal protection (UEP) is used for Key frame.
118 //
119 // Return value : Required Unequal protection on/off state.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200120 virtual bool RequiredUepProtectionK();
philipel9d3ab612015-12-21 04:12:39 -0800121
122 // Extracts whether the the FEC Unequal protection (UEP) is used for Delta
123 // frame.
124 //
125 // Return value : Required Unequal protection on/off state.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200126 virtual bool RequiredUepProtectionD();
philipel9d3ab612015-12-21 04:12:39 -0800127
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200128 virtual int MaxFramesFec() const;
philipel9d3ab612015-12-21 04:12:39 -0800129
philipel9d3ab612015-12-21 04:12:39 -0800130 protected:
131 uint8_t _effectivePacketLoss;
132 uint8_t _protectionFactorK;
133 uint8_t _protectionFactorD;
134 // Estimation of residual loss after the FEC
135 float _scaleProtKey;
136 int32_t _maxPayloadSize;
137
philipel9d3ab612015-12-21 04:12:39 -0800138 bool _useUepProtectionK;
139 bool _useUepProtectionD;
140 float _corrFecCost;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200141 VCMProtectionMethodEnum _type;
niklase@google.com470e71d2011-07-07 08:21:25 +0000142};
143
philipel9d3ab612015-12-21 04:12:39 -0800144class VCMNackMethod : public VCMProtectionMethod {
145 public:
146 VCMNackMethod();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200147 ~VCMNackMethod() override;
148 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800149 // Get the effective packet loss
150 bool EffectivePacketLoss(const VCMProtectionParameters* parameter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000151};
152
philipel9d3ab612015-12-21 04:12:39 -0800153class VCMFecMethod : public VCMProtectionMethod {
154 public:
155 VCMFecMethod();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200156 ~VCMFecMethod() override;
157 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800158 // Get the effective packet loss for ER
159 bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
160 // Get the FEC protection factors
161 bool ProtectionFactor(const VCMProtectionParameters* parameters);
162 // Get the boost for key frame protection
163 uint8_t BoostCodeRateKey(uint8_t packetFrameDelta,
164 uint8_t packetFrameKey) const;
165 // Convert the rates: defined relative to total# packets or source# packets
166 uint8_t ConvertFECRate(uint8_t codeRate) const;
167 // Get the average effective recovery from FEC: for random loss model
168 float AvgRecoveryFEC(const VCMProtectionParameters* parameters) const;
169 // Update FEC with protectionFactorD
170 void UpdateProtectionFactorD(uint8_t protectionFactorD);
171 // Update FEC with protectionFactorK
172 void UpdateProtectionFactorK(uint8_t protectionFactorK);
173 // Compute the bits per frame. Account for temporal layers when applicable.
174 int BitsPerFrame(const VCMProtectionParameters* parameters);
175
176 protected:
177 enum { kUpperLimitFramesFec = 6 };
178 // Thresholds values for the bytes/frame and round trip time, below which we
179 // may turn off FEC, depending on |_numLayers| and |_maxFramesFec|.
180 // Max bytes/frame for VGA, corresponds to ~140k at 25fps.
181 enum { kMaxBytesPerFrameForFec = 700 };
182 // Max bytes/frame for CIF and lower: corresponds to ~80k at 25fps.
183 enum { kMaxBytesPerFrameForFecLow = 400 };
184 // Max bytes/frame for frame size larger than VGA, ~200k at 25fps.
185 enum { kMaxBytesPerFrameForFecHigh = 1000 };
niklase@google.com470e71d2011-07-07 08:21:25 +0000186};
187
philipel9d3ab612015-12-21 04:12:39 -0800188class VCMNackFecMethod : public VCMFecMethod {
189 public:
190 VCMNackFecMethod(int64_t lowRttNackThresholdMs,
191 int64_t highRttNackThresholdMs);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200192 ~VCMNackFecMethod() override;
193 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800194 // Get the effective packet loss for ER
195 bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
196 // Get the protection factors
197 bool ProtectionFactor(const VCMProtectionParameters* parameters);
198 // Get the max number of frames the FEC is allowed to be based on.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200199 int MaxFramesFec() const override;
philipel9d3ab612015-12-21 04:12:39 -0800200 // Turn off the FEC based on low bitrate and other factors.
201 bool BitRateTooLowForFec(const VCMProtectionParameters* parameters);
stefan@webrtc.orgc35f5ce2012-04-11 07:42:25 +0000202
philipel9d3ab612015-12-21 04:12:39 -0800203 private:
204 int ComputeMaxFramesFec(const VCMProtectionParameters* parameters);
205
206 int64_t _lowRttNackMs;
207 int64_t _highRttNackMs;
208 int _maxFramesFec;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209};
210
philipel9d3ab612015-12-21 04:12:39 -0800211class VCMLossProtectionLogic {
212 public:
213 explicit VCMLossProtectionLogic(int64_t nowMs);
214 ~VCMLossProtectionLogic();
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
philipel9d3ab612015-12-21 04:12:39 -0800216 // Set the protection method to be used
217 //
218 // Input:
219 // - newMethodType : New requested protection method type. If one
220 // is already set, it will be deleted and replaced
221 void SetMethod(VCMProtectionMethodEnum newMethodType);
stefan@webrtc.orgc35f5ce2012-04-11 07:42:25 +0000222
philipel9d3ab612015-12-21 04:12:39 -0800223 // Update the round-trip time
224 //
225 // Input:
226 // - rtt : Round-trip time in seconds.
227 void UpdateRtt(int64_t rtt);
niklase@google.com470e71d2011-07-07 08:21:25 +0000228
philipel9d3ab612015-12-21 04:12:39 -0800229 // Update the filtered packet loss.
230 //
231 // Input:
232 // - packetLossEnc : The reported packet loss filtered
233 // (max window or average)
234 void UpdateFilteredLossPr(uint8_t packetLossEnc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
philipel9d3ab612015-12-21 04:12:39 -0800236 // Update the current target bit rate.
237 //
238 // Input:
239 // - bitRate : The current target bit rate in kbits/s
240 void UpdateBitRate(float bitRate);
mikhal@webrtc.orga057a952011-08-26 21:17:34 +0000241
philipel9d3ab612015-12-21 04:12:39 -0800242 // Update the number of packets per frame estimate, for delta frames
243 //
244 // Input:
245 // - nPackets : Number of packets in the latest sent frame.
246 void UpdatePacketsPerFrame(float nPackets, int64_t nowMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000247
philipel9d3ab612015-12-21 04:12:39 -0800248 // Update the number of packets per frame estimate, for key frames
249 //
250 // Input:
251 // - nPackets : umber of packets in the latest sent frame.
252 void UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000253
philipel9d3ab612015-12-21 04:12:39 -0800254 // Update the keyFrameSize estimate
255 //
256 // Input:
257 // - keyFrameSize : The size of the latest sent key frame.
258 void UpdateKeyFrameSize(float keyFrameSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000259
philipel9d3ab612015-12-21 04:12:39 -0800260 // Update the frame rate
261 //
262 // Input:
263 // - frameRate : The current target frame rate.
264 void UpdateFrameRate(float frameRate) { _frameRate = frameRate; }
niklase@google.com470e71d2011-07-07 08:21:25 +0000265
philipel9d3ab612015-12-21 04:12:39 -0800266 // Update the frame size
267 //
268 // Input:
269 // - width : The codec frame width.
270 // - height : The codec frame height.
perkjc2c24f72016-07-11 01:47:32 -0700271 void UpdateFrameSize(size_t width, size_t height);
niklase@google.com470e71d2011-07-07 08:21:25 +0000272
philipel9d3ab612015-12-21 04:12:39 -0800273 // Update the number of active layers
274 //
275 // Input:
276 // - numLayers : Number of layers used.
277 void UpdateNumLayers(int numLayers);
niklase@google.com470e71d2011-07-07 08:21:25 +0000278
philipel9d3ab612015-12-21 04:12:39 -0800279 // The amount of packet loss to cover for with FEC.
280 //
281 // Input:
282 // - fecRateKey : Packet loss to cover for with FEC when
283 // sending key frames.
284 // - fecRateDelta : Packet loss to cover for with FEC when
285 // sending delta frames.
286 void UpdateFECRates(uint8_t fecRateKey, uint8_t fecRateDelta) {
287 _fecRateKey = fecRateKey;
288 _fecRateDelta = fecRateDelta;
289 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000290
philipel9d3ab612015-12-21 04:12:39 -0800291 // Update the protection methods with the current VCMProtectionParameters
292 // and set the requested protection settings.
293 // Return value : Returns true on update
294 bool UpdateMethod();
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
philipel9d3ab612015-12-21 04:12:39 -0800296 // Returns the method currently selected.
297 //
298 // Return value : The protection method currently selected.
299 VCMProtectionMethod* SelectedMethod() const;
mikhal@webrtc.org0e7d9d82011-12-19 19:04:49 +0000300
philipel9d3ab612015-12-21 04:12:39 -0800301 // Return the protection type of the currently selected method
302 VCMProtectionMethodEnum SelectedType() const;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303
philipel9d3ab612015-12-21 04:12:39 -0800304 // Updates the filtered loss for the average and max window packet loss,
305 // and returns the filtered loss probability in the interval [0, 255].
306 // The returned filtered loss value depends on the parameter |filter_mode|.
307 // The input parameter |lossPr255| is the received packet loss.
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
philipel9d3ab612015-12-21 04:12:39 -0800309 // Return value : The filtered loss probability
310 uint8_t FilteredLoss(int64_t nowMs,
311 FilterPacketLossMode filter_mode,
312 uint8_t lossPr255);
niklase@google.com470e71d2011-07-07 08:21:25 +0000313
philipel9d3ab612015-12-21 04:12:39 -0800314 void Reset(int64_t nowMs);
mikhal@webrtc.orga057a952011-08-26 21:17:34 +0000315
philipel9d3ab612015-12-21 04:12:39 -0800316 void Release();
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +0000317
philipel9d3ab612015-12-21 04:12:39 -0800318 private:
319 // Sets the available loss protection methods.
320 void UpdateMaxLossHistory(uint8_t lossPr255, int64_t now);
321 uint8_t MaxFilteredLossPr(int64_t nowMs) const;
kwiberg3f55dea2016-02-29 05:51:59 -0800322 std::unique_ptr<VCMProtectionMethod> _selectedMethod;
philipel9d3ab612015-12-21 04:12:39 -0800323 VCMProtectionParameters _currentParameters;
324 int64_t _rtt;
325 float _lossPr;
326 float _bitRate;
327 float _frameRate;
328 float _keyFrameSize;
329 uint8_t _fecRateKey;
330 uint8_t _fecRateDelta;
331 int64_t _lastPrUpdateT;
332 int64_t _lastPacketPerFrameUpdateT;
333 int64_t _lastPacketPerFrameUpdateTKey;
334 rtc::ExpFilter _lossPr255;
335 VCMLossProbabilitySample _lossPrHistory[kLossPrHistorySize];
336 uint8_t _shortMaxLossPr255;
337 rtc::ExpFilter _packetsPerFrame;
338 rtc::ExpFilter _packetsPerFrameKey;
perkjc2c24f72016-07-11 01:47:32 -0700339 size_t _codecWidth;
340 size_t _codecHeight;
philipel9d3ab612015-12-21 04:12:39 -0800341 int _numLayers;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342};
343
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000344} // namespace media_optimization
345} // namespace webrtc
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200347#endif // MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_