blob: 9cc8d6db3ec8674238dbd01c281600abe3c33993 [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"
Mirko Bonadei71207422017-09-15 13:58:09 +020021#include "typedefs.h" // NOLINT(build/include)
niklase@google.com470e71d2011-07-07 08:21:25 +000022
stefan@webrtc.orga64300a2013-03-04 15:24:40 +000023namespace webrtc {
24namespace media_optimization {
25
marpan@google.com30ecda12011-09-09 17:15:12 +000026// Number of time periods used for (max) window filter for packet loss
philipel9d3ab612015-12-21 04:12:39 -080027// TODO(marpan): set reasonable window size for filtered packet loss,
marpan@google.com30ecda12011-09-09 17:15:12 +000028// 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
mikhal@google.comb29d9402011-08-01 16:39:20 +000032enum { kLossPrShortFilterWinMs = 1000 };
niklase@google.com470e71d2011-07-07 08:21:25 +000033
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +000034// The type of filter used on the received packet loss reports.
35enum FilterPacketLossMode {
philipel9d3ab612015-12-21 04:12:39 -080036 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.
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +000040};
41
niklase@google.com470e71d2011-07-07 08:21:25 +000042// Thresholds for hybrid NACK/FEC
43// common to media optimization and the jitter buffer.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000044const int64_t kLowRttNackMs = 20;
niklase@google.com470e71d2011-07-07 08:21:25 +000045
philipelae284082016-05-09 12:14:29 +020046// If the RTT is higher than this an extra RTT wont be added to to the jitter
47// buffer delay.
48const int kMaxRttDelayThreshold = 500;
49
philipel9d3ab612015-12-21 04:12:39 -080050struct VCMProtectionParameters {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020051 VCMProtectionParameters();
niklase@google.com470e71d2011-07-07 08:21:25 +000052
philipel9d3ab612015-12-21 04:12:39 -080053 int64_t rtt;
54 float lossPr;
55 float bitRate;
56 float packetsPerFrame;
57 float packetsPerFrameKey;
58 float frameRate;
59 float keyFrameSize;
60 uint8_t fecRateDelta;
61 uint8_t fecRateKey;
62 uint16_t codecWidth;
63 uint16_t codecHeight;
64 int numLayers;
niklase@google.com470e71d2011-07-07 08:21:25 +000065};
66
niklase@google.com470e71d2011-07-07 08:21:25 +000067/******************************/
stefan@webrtc.orga64300a2013-03-04 15:24:40 +000068/* VCMProtectionMethod class */
69/******************************/
niklase@google.com470e71d2011-07-07 08:21:25 +000070
philipel9d3ab612015-12-21 04:12:39 -080071enum VCMProtectionMethodEnum { kNack, kFec, kNackFec, kNone };
72
73class VCMLossProbabilitySample {
74 public:
75 VCMLossProbabilitySample() : lossPr255(0), timeMs(-1) {}
76
77 uint8_t lossPr255;
78 int64_t timeMs;
niklase@google.com470e71d2011-07-07 08:21:25 +000079};
80
philipel9d3ab612015-12-21 04:12:39 -080081class VCMProtectionMethod {
82 public:
83 VCMProtectionMethod();
84 virtual ~VCMProtectionMethod();
niklase@google.com470e71d2011-07-07 08:21:25 +000085
philipel9d3ab612015-12-21 04:12:39 -080086 // Updates the efficiency of the method using the parameters provided
87 //
88 // Input:
89 // - parameters : Parameters used to calculate efficiency
90 //
91 // Return value : True if this method is recommended in
92 // the given conditions.
93 virtual bool UpdateParameters(const VCMProtectionParameters* parameters) = 0;
94
95 // Returns the protection type
96 //
97 // Return value : The protection type
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020098 VCMProtectionMethodEnum Type() const;
philipel9d3ab612015-12-21 04:12:39 -080099
100 // Returns the effective packet loss for ER, required by this protection
101 // method
102 //
103 // Return value : Required effective packet loss
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200104 virtual uint8_t RequiredPacketLossER();
philipel9d3ab612015-12-21 04:12:39 -0800105
106 // Extracts the FEC protection factor for Key frame, required by this
107 // protection method
108 //
109 // Return value : Required protectionFactor for Key frame
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200110 virtual uint8_t RequiredProtectionFactorK();
philipel9d3ab612015-12-21 04:12:39 -0800111
112 // Extracts the FEC protection factor for Delta frame, required by this
113 // protection method
114 //
115 // Return value : Required protectionFactor for delta frame
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200116 virtual uint8_t RequiredProtectionFactorD();
philipel9d3ab612015-12-21 04:12:39 -0800117
118 // Extracts whether the FEC Unequal protection (UEP) is used for Key frame.
119 //
120 // Return value : Required Unequal protection on/off state.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200121 virtual bool RequiredUepProtectionK();
philipel9d3ab612015-12-21 04:12:39 -0800122
123 // Extracts whether the the FEC Unequal protection (UEP) is used for Delta
124 // frame.
125 //
126 // Return value : Required Unequal protection on/off state.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200127 virtual bool RequiredUepProtectionD();
philipel9d3ab612015-12-21 04:12:39 -0800128
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200129 virtual int MaxFramesFec() const;
philipel9d3ab612015-12-21 04:12:39 -0800130
philipel9d3ab612015-12-21 04:12:39 -0800131 protected:
132 uint8_t _effectivePacketLoss;
133 uint8_t _protectionFactorK;
134 uint8_t _protectionFactorD;
135 // Estimation of residual loss after the FEC
136 float _scaleProtKey;
137 int32_t _maxPayloadSize;
138
philipel9d3ab612015-12-21 04:12:39 -0800139 bool _useUepProtectionK;
140 bool _useUepProtectionD;
141 float _corrFecCost;
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200142 VCMProtectionMethodEnum _type;
niklase@google.com470e71d2011-07-07 08:21:25 +0000143};
144
philipel9d3ab612015-12-21 04:12:39 -0800145class VCMNackMethod : public VCMProtectionMethod {
146 public:
147 VCMNackMethod();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200148 ~VCMNackMethod() override;
149 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800150 // Get the effective packet loss
151 bool EffectivePacketLoss(const VCMProtectionParameters* parameter);
niklase@google.com470e71d2011-07-07 08:21:25 +0000152};
153
philipel9d3ab612015-12-21 04:12:39 -0800154class VCMFecMethod : public VCMProtectionMethod {
155 public:
156 VCMFecMethod();
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200157 ~VCMFecMethod() override;
158 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800159 // Get the effective packet loss for ER
160 bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
161 // Get the FEC protection factors
162 bool ProtectionFactor(const VCMProtectionParameters* parameters);
163 // Get the boost for key frame protection
164 uint8_t BoostCodeRateKey(uint8_t packetFrameDelta,
165 uint8_t packetFrameKey) const;
166 // Convert the rates: defined relative to total# packets or source# packets
167 uint8_t ConvertFECRate(uint8_t codeRate) const;
168 // Get the average effective recovery from FEC: for random loss model
169 float AvgRecoveryFEC(const VCMProtectionParameters* parameters) const;
170 // Update FEC with protectionFactorD
171 void UpdateProtectionFactorD(uint8_t protectionFactorD);
172 // Update FEC with protectionFactorK
173 void UpdateProtectionFactorK(uint8_t protectionFactorK);
174 // Compute the bits per frame. Account for temporal layers when applicable.
175 int BitsPerFrame(const VCMProtectionParameters* parameters);
176
177 protected:
178 enum { kUpperLimitFramesFec = 6 };
179 // Thresholds values for the bytes/frame and round trip time, below which we
180 // may turn off FEC, depending on |_numLayers| and |_maxFramesFec|.
181 // Max bytes/frame for VGA, corresponds to ~140k at 25fps.
182 enum { kMaxBytesPerFrameForFec = 700 };
183 // Max bytes/frame for CIF and lower: corresponds to ~80k at 25fps.
184 enum { kMaxBytesPerFrameForFecLow = 400 };
185 // Max bytes/frame for frame size larger than VGA, ~200k at 25fps.
186 enum { kMaxBytesPerFrameForFecHigh = 1000 };
niklase@google.com470e71d2011-07-07 08:21:25 +0000187};
188
philipel9d3ab612015-12-21 04:12:39 -0800189class VCMNackFecMethod : public VCMFecMethod {
190 public:
191 VCMNackFecMethod(int64_t lowRttNackThresholdMs,
192 int64_t highRttNackThresholdMs);
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200193 ~VCMNackFecMethod() override;
194 bool UpdateParameters(const VCMProtectionParameters* parameters) override;
philipel9d3ab612015-12-21 04:12:39 -0800195 // Get the effective packet loss for ER
196 bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
197 // Get the protection factors
198 bool ProtectionFactor(const VCMProtectionParameters* parameters);
199 // Get the max number of frames the FEC is allowed to be based on.
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200200 int MaxFramesFec() const override;
philipel9d3ab612015-12-21 04:12:39 -0800201 // Turn off the FEC based on low bitrate and other factors.
202 bool BitRateTooLowForFec(const VCMProtectionParameters* parameters);
stefan@webrtc.orgc35f5ce2012-04-11 07:42:25 +0000203
philipel9d3ab612015-12-21 04:12:39 -0800204 private:
205 int ComputeMaxFramesFec(const VCMProtectionParameters* parameters);
206
207 int64_t _lowRttNackMs;
208 int64_t _highRttNackMs;
209 int _maxFramesFec;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210};
211
philipel9d3ab612015-12-21 04:12:39 -0800212class VCMLossProtectionLogic {
213 public:
214 explicit VCMLossProtectionLogic(int64_t nowMs);
215 ~VCMLossProtectionLogic();
niklase@google.com470e71d2011-07-07 08:21:25 +0000216
philipel9d3ab612015-12-21 04:12:39 -0800217 // Set the protection method to be used
218 //
219 // Input:
220 // - newMethodType : New requested protection method type. If one
221 // is already set, it will be deleted and replaced
222 void SetMethod(VCMProtectionMethodEnum newMethodType);
stefan@webrtc.orgc35f5ce2012-04-11 07:42:25 +0000223
philipel9d3ab612015-12-21 04:12:39 -0800224 // Update the round-trip time
225 //
226 // Input:
227 // - rtt : Round-trip time in seconds.
228 void UpdateRtt(int64_t rtt);
niklase@google.com470e71d2011-07-07 08:21:25 +0000229
philipel9d3ab612015-12-21 04:12:39 -0800230 // Update the filtered packet loss.
231 //
232 // Input:
233 // - packetLossEnc : The reported packet loss filtered
234 // (max window or average)
235 void UpdateFilteredLossPr(uint8_t packetLossEnc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000236
philipel9d3ab612015-12-21 04:12:39 -0800237 // Update the current target bit rate.
238 //
239 // Input:
240 // - bitRate : The current target bit rate in kbits/s
241 void UpdateBitRate(float bitRate);
mikhal@webrtc.orga057a952011-08-26 21:17:34 +0000242
philipel9d3ab612015-12-21 04:12:39 -0800243 // Update the number of packets per frame estimate, for delta frames
244 //
245 // Input:
246 // - nPackets : Number of packets in the latest sent frame.
247 void UpdatePacketsPerFrame(float nPackets, int64_t nowMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000248
philipel9d3ab612015-12-21 04:12:39 -0800249 // Update the number of packets per frame estimate, for key frames
250 //
251 // Input:
252 // - nPackets : umber of packets in the latest sent frame.
253 void UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000254
philipel9d3ab612015-12-21 04:12:39 -0800255 // Update the keyFrameSize estimate
256 //
257 // Input:
258 // - keyFrameSize : The size of the latest sent key frame.
259 void UpdateKeyFrameSize(float keyFrameSize);
niklase@google.com470e71d2011-07-07 08:21:25 +0000260
philipel9d3ab612015-12-21 04:12:39 -0800261 // Update the frame rate
262 //
263 // Input:
264 // - frameRate : The current target frame rate.
265 void UpdateFrameRate(float frameRate) { _frameRate = frameRate; }
niklase@google.com470e71d2011-07-07 08:21:25 +0000266
philipel9d3ab612015-12-21 04:12:39 -0800267 // Update the frame size
268 //
269 // Input:
270 // - width : The codec frame width.
271 // - height : The codec frame height.
perkjc2c24f72016-07-11 01:47:32 -0700272 void UpdateFrameSize(size_t width, size_t height);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273
philipel9d3ab612015-12-21 04:12:39 -0800274 // Update the number of active layers
275 //
276 // Input:
277 // - numLayers : Number of layers used.
278 void UpdateNumLayers(int numLayers);
niklase@google.com470e71d2011-07-07 08:21:25 +0000279
philipel9d3ab612015-12-21 04:12:39 -0800280 // The amount of packet loss to cover for with FEC.
281 //
282 // Input:
283 // - fecRateKey : Packet loss to cover for with FEC when
284 // sending key frames.
285 // - fecRateDelta : Packet loss to cover for with FEC when
286 // sending delta frames.
287 void UpdateFECRates(uint8_t fecRateKey, uint8_t fecRateDelta) {
288 _fecRateKey = fecRateKey;
289 _fecRateDelta = fecRateDelta;
290 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000291
philipel9d3ab612015-12-21 04:12:39 -0800292 // Update the protection methods with the current VCMProtectionParameters
293 // and set the requested protection settings.
294 // Return value : Returns true on update
295 bool UpdateMethod();
niklase@google.com470e71d2011-07-07 08:21:25 +0000296
philipel9d3ab612015-12-21 04:12:39 -0800297 // Returns the method currently selected.
298 //
299 // Return value : The protection method currently selected.
300 VCMProtectionMethod* SelectedMethod() const;
mikhal@webrtc.org0e7d9d82011-12-19 19:04:49 +0000301
philipel9d3ab612015-12-21 04:12:39 -0800302 // Return the protection type of the currently selected method
303 VCMProtectionMethodEnum SelectedType() const;
niklase@google.com470e71d2011-07-07 08:21:25 +0000304
philipel9d3ab612015-12-21 04:12:39 -0800305 // Updates the filtered loss for the average and max window packet loss,
306 // and returns the filtered loss probability in the interval [0, 255].
307 // The returned filtered loss value depends on the parameter |filter_mode|.
308 // The input parameter |lossPr255| is the received packet loss.
niklase@google.com470e71d2011-07-07 08:21:25 +0000309
philipel9d3ab612015-12-21 04:12:39 -0800310 // Return value : The filtered loss probability
311 uint8_t FilteredLoss(int64_t nowMs,
312 FilterPacketLossMode filter_mode,
313 uint8_t lossPr255);
niklase@google.com470e71d2011-07-07 08:21:25 +0000314
philipel9d3ab612015-12-21 04:12:39 -0800315 void Reset(int64_t nowMs);
mikhal@webrtc.orga057a952011-08-26 21:17:34 +0000316
philipel9d3ab612015-12-21 04:12:39 -0800317 void Release();
marpan@webrtc.org2dad3fb2012-01-09 18:18:36 +0000318
philipel9d3ab612015-12-21 04:12:39 -0800319 private:
320 // Sets the available loss protection methods.
321 void UpdateMaxLossHistory(uint8_t lossPr255, int64_t now);
322 uint8_t MaxFilteredLossPr(int64_t nowMs) const;
kwiberg3f55dea2016-02-29 05:51:59 -0800323 std::unique_ptr<VCMProtectionMethod> _selectedMethod;
philipel9d3ab612015-12-21 04:12:39 -0800324 VCMProtectionParameters _currentParameters;
325 int64_t _rtt;
326 float _lossPr;
327 float _bitRate;
328 float _frameRate;
329 float _keyFrameSize;
330 uint8_t _fecRateKey;
331 uint8_t _fecRateDelta;
332 int64_t _lastPrUpdateT;
333 int64_t _lastPacketPerFrameUpdateT;
334 int64_t _lastPacketPerFrameUpdateTKey;
335 rtc::ExpFilter _lossPr255;
336 VCMLossProbabilitySample _lossPrHistory[kLossPrHistorySize];
337 uint8_t _shortMaxLossPr255;
338 rtc::ExpFilter _packetsPerFrame;
339 rtc::ExpFilter _packetsPerFrameKey;
perkjc2c24f72016-07-11 01:47:32 -0700340 size_t _codecWidth;
341 size_t _codecHeight;
philipel9d3ab612015-12-21 04:12:39 -0800342 int _numLayers;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343};
344
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000345} // namespace media_optimization
346} // namespace webrtc
niklase@google.com470e71d2011-07-07 08:21:25 +0000347
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200348#endif // MODULES_VIDEO_CODING_MEDIA_OPT_UTIL_H_