Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Side by Side Diff: webrtc/modules/video_coding/media_opt_util.cc

Issue 1528503003: Lint enabled for webrtc/modules/video_coding folder. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/media_opt_util.h" 11 #include "webrtc/modules/video_coding/media_opt_util.h"
12 12
13 #include <algorithm>
14 #include <float.h> 13 #include <float.h>
15 #include <limits.h> 14 #include <limits.h>
16 #include <math.h> 15 #include <math.h>
17 16
17 #include <algorithm>
18
18 #include "webrtc/modules/include/module_common_types.h" 19 #include "webrtc/modules/include/module_common_types.h"
19 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 20 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
20 #include "webrtc/modules/video_coding/include/video_coding_defines.h" 21 #include "webrtc/modules/video_coding/include/video_coding_defines.h"
21 #include "webrtc/modules/video_coding/fec_tables_xor.h" 22 #include "webrtc/modules/video_coding/fec_tables_xor.h"
22 #include "webrtc/modules/video_coding/nack_fec_tables.h" 23 #include "webrtc/modules/video_coding/nack_fec_tables.h"
23 24
24 namespace webrtc { 25 namespace webrtc {
25 // Max value of loss rates in off-line model 26 // Max value of loss rates in off-line model
26 static const int kPacketLossMax = 129; 27 static const int kPacketLossMax = 129;
27 28
28 namespace media_optimization { 29 namespace media_optimization {
29 30
30 VCMProtectionMethod::VCMProtectionMethod() 31 VCMProtectionMethod::VCMProtectionMethod()
31 : _effectivePacketLoss(0), 32 : _effectivePacketLoss(0),
32 _protectionFactorK(0), 33 _protectionFactorK(0),
33 _protectionFactorD(0), 34 _protectionFactorD(0),
34 _scaleProtKey(2.0f), 35 _scaleProtKey(2.0f),
35 _maxPayloadSize(1460), 36 _maxPayloadSize(1460),
36 _qmRobustness(new VCMQmRobustness()), 37 _qmRobustness(new VCMQmRobustness()),
37 _useUepProtectionK(false), 38 _useUepProtectionK(false),
38 _useUepProtectionD(true), 39 _useUepProtectionD(true),
39 _corrFecCost(1.0), 40 _corrFecCost(1.0),
40 _type(kNone) { 41 _type(kNone) {}
42
43 VCMProtectionMethod::~VCMProtectionMethod() {
44 delete _qmRobustness;
41 } 45 }
42 46 void VCMProtectionMethod::UpdateContentMetrics(
43 VCMProtectionMethod::~VCMProtectionMethod() 47 const VideoContentMetrics* contentMetrics) {
44 { 48 _qmRobustness->UpdateContent(contentMetrics);
45 delete _qmRobustness;
46 }
47 void
48 VCMProtectionMethod::UpdateContentMetrics(const
49 VideoContentMetrics* contentMetrics)
50 {
51 _qmRobustness->UpdateContent(contentMetrics);
52 } 49 }
53 50
54 VCMNackFecMethod::VCMNackFecMethod(int64_t lowRttNackThresholdMs, 51 VCMNackFecMethod::VCMNackFecMethod(int64_t lowRttNackThresholdMs,
55 int64_t highRttNackThresholdMs) 52 int64_t highRttNackThresholdMs)
56 : VCMFecMethod(), 53 : VCMFecMethod(),
57 _lowRttNackMs(lowRttNackThresholdMs), 54 _lowRttNackMs(lowRttNackThresholdMs),
58 _highRttNackMs(highRttNackThresholdMs), 55 _highRttNackMs(highRttNackThresholdMs),
59 _maxFramesFec(1) { 56 _maxFramesFec(1) {
60 assert(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1); 57 assert(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1);
61 assert(highRttNackThresholdMs == -1 || 58 assert(highRttNackThresholdMs == -1 ||
62 lowRttNackThresholdMs <= highRttNackThresholdMs); 59 lowRttNackThresholdMs <= highRttNackThresholdMs);
63 assert(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1); 60 assert(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1);
64 _type = kNackFec; 61 _type = kNackFec;
65 } 62 }
66 63
67 VCMNackFecMethod::~VCMNackFecMethod() 64 VCMNackFecMethod::~VCMNackFecMethod() {
68 { 65 //
69 //
70 } 66 }
71 bool 67 bool VCMNackFecMethod::ProtectionFactor(
72 VCMNackFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) 68 const VCMProtectionParameters* parameters) {
73 { 69 // Hybrid Nack FEC has three operational modes:
74 // Hybrid Nack FEC has three operational modes: 70 // 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate
75 // 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate 71 // (_protectionFactorD) to zero. -1 means no FEC.
76 // (_protectionFactorD) to zero. -1 means no FEC. 72 // 2. High RTT (above _highRttNackMs) - FEC Only: Keep FEC factors.
77 // 2. High RTT (above _highRttNackMs) - FEC Only: Keep FEC factors. 73 // -1 means always allow NACK.
78 // -1 means always allow NACK. 74 // 3. Medium RTT values - Hybrid mode: We will only nack the
79 // 3. Medium RTT values - Hybrid mode: We will only nack the 75 // residual following the decoding of the FEC (refer to JB logic). FEC
80 // residual following the decoding of the FEC (refer to JB logic). FEC 76 // delta protection factor will be adjusted based on the RTT.
81 // delta protection factor will be adjusted based on the RTT.
82 77
83 // Otherwise: we count on FEC; if the RTT is below a threshold, then we 78 // Otherwise: we count on FEC; if the RTT is below a threshold, then we
84 // nack the residual, based on a decision made in the JB. 79 // nack the residual, based on a decision made in the JB.
85 80
86 // Compute the protection factors 81 // Compute the protection factors
87 VCMFecMethod::ProtectionFactor(parameters); 82 VCMFecMethod::ProtectionFactor(parameters);
88 if (_lowRttNackMs == -1 || parameters->rtt < _lowRttNackMs) 83 if (_lowRttNackMs == -1 || parameters->rtt < _lowRttNackMs) {
89 { 84 _protectionFactorD = 0;
90 _protectionFactorD = 0; 85 VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
91 VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
92 }
93 86
94 // When in Hybrid mode (RTT range), adjust FEC rates based on the 87 // When in Hybrid mode (RTT range), adjust FEC rates based on the
95 // RTT (NACK effectiveness) - adjustment factor is in the range [0,1]. 88 // RTT (NACK effectiveness) - adjustment factor is in the range [0,1].
96 else if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs) 89 } else if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs) {
97 { 90 // TODO(mikhal): Disabling adjustment temporarily.
98 // TODO(mikhal): Disabling adjustment temporarily. 91 // uint16_t rttIndex = (uint16_t) parameters->rtt;
99 // uint16_t rttIndex = (uint16_t) parameters->rtt; 92 float adjustRtt = 1.0f; // (float)VCMNackFecTable[rttIndex] / 100.0f;
100 float adjustRtt = 1.0f;// (float)VCMNackFecTable[rttIndex] / 100.0f;
101 93
102 // Adjust FEC with NACK on (for delta frame only) 94 // Adjust FEC with NACK on (for delta frame only)
103 // table depends on RTT relative to rttMax (NACK Threshold) 95 // table depends on RTT relative to rttMax (NACK Threshold)
104 _protectionFactorD = static_cast<uint8_t> 96 _protectionFactorD = static_cast<uint8_t>(
105 (adjustRtt * 97 adjustRtt * static_cast<float>(_protectionFactorD));
106 static_cast<float>(_protectionFactorD)); 98 // update FEC rates after applying adjustment
107 // update FEC rates after applying adjustment 99 VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
108 VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD); 100 }
109 }
110 101
111 return true; 102 return true;
112 } 103 }
113 104
114 int VCMNackFecMethod::ComputeMaxFramesFec( 105 int VCMNackFecMethod::ComputeMaxFramesFec(
115 const VCMProtectionParameters* parameters) { 106 const VCMProtectionParameters* parameters) {
116 if (parameters->numLayers > 2) { 107 if (parameters->numLayers > 2) {
117 // For more than 2 temporal layers we will only have FEC on the base layer, 108 // For more than 2 temporal layers we will only have FEC on the base layer,
118 // and the base layers will be pretty far apart. Therefore we force one 109 // and the base layers will be pretty far apart. Therefore we force one
119 // frame FEC. 110 // frame FEC.
120 return 1; 111 return 1;
121 } 112 }
122 // We set the max number of frames to base the FEC on so that on average 113 // We set the max number of frames to base the FEC on so that on average
123 // we will have complete frames in one RTT. Note that this is an upper 114 // we will have complete frames in one RTT. Note that this is an upper
124 // bound, and that the actual number of frames used for FEC is decided by the 115 // bound, and that the actual number of frames used for FEC is decided by the
125 // RTP module based on the actual number of packets and the protection factor. 116 // RTP module based on the actual number of packets and the protection factor.
126 float base_layer_framerate = parameters->frameRate / 117 float base_layer_framerate =
118 parameters->frameRate /
127 static_cast<float>(1 << (parameters->numLayers - 1)); 119 static_cast<float>(1 << (parameters->numLayers - 1));
128 int max_frames_fec = std::max(static_cast<int>( 120 int max_frames_fec = std::max(
129 2.0f * base_layer_framerate * parameters->rtt / 121 static_cast<int>(2.0f * base_layer_framerate * parameters->rtt / 1000.0f +
130 1000.0f + 0.5f), 1); 122 0.5f),
123 1);
131 // |kUpperLimitFramesFec| is the upper limit on how many frames we 124 // |kUpperLimitFramesFec| is the upper limit on how many frames we
132 // allow any FEC to be based on. 125 // allow any FEC to be based on.
133 if (max_frames_fec > kUpperLimitFramesFec) { 126 if (max_frames_fec > kUpperLimitFramesFec) {
134 max_frames_fec = kUpperLimitFramesFec; 127 max_frames_fec = kUpperLimitFramesFec;
135 } 128 }
136 return max_frames_fec; 129 return max_frames_fec;
137 } 130 }
138 131
139 int VCMNackFecMethod::MaxFramesFec() const { 132 int VCMNackFecMethod::MaxFramesFec() const {
140 return _maxFramesFec; 133 return _maxFramesFec;
141 } 134 }
142 135
143 bool VCMNackFecMethod::BitRateTooLowForFec( 136 bool VCMNackFecMethod::BitRateTooLowForFec(
144 const VCMProtectionParameters* parameters) { 137 const VCMProtectionParameters* parameters) {
145 // Bitrate below which we turn off FEC, regardless of reported packet loss. 138 // Bitrate below which we turn off FEC, regardless of reported packet loss.
146 // The condition should depend on resolution and content. For now, use 139 // The condition should depend on resolution and content. For now, use
147 // threshold on bytes per frame, with some effect for the frame size. 140 // threshold on bytes per frame, with some effect for the frame size.
148 // The condition for turning off FEC is also based on other factors, 141 // The condition for turning off FEC is also based on other factors,
149 // such as |_numLayers|, |_maxFramesFec|, and |_rtt|. 142 // such as |_numLayers|, |_maxFramesFec|, and |_rtt|.
150 int estimate_bytes_per_frame = 1000 * BitsPerFrame(parameters) / 8; 143 int estimate_bytes_per_frame = 1000 * BitsPerFrame(parameters) / 8;
151 int max_bytes_per_frame = kMaxBytesPerFrameForFec; 144 int max_bytes_per_frame = kMaxBytesPerFrameForFec;
152 int num_pixels = parameters->codecWidth * parameters->codecHeight; 145 int num_pixels = parameters->codecWidth * parameters->codecHeight;
153 if (num_pixels <= 352 * 288) { 146 if (num_pixels <= 352 * 288) {
154 max_bytes_per_frame = kMaxBytesPerFrameForFecLow; 147 max_bytes_per_frame = kMaxBytesPerFrameForFecLow;
155 } else if (num_pixels > 640 * 480) { 148 } else if (num_pixels > 640 * 480) {
156 max_bytes_per_frame = kMaxBytesPerFrameForFecHigh; 149 max_bytes_per_frame = kMaxBytesPerFrameForFecHigh;
157 } 150 }
158 // TODO (marpan): add condition based on maximum frames used for FEC, 151 // TODO(marpan): add condition based on maximum frames used for FEC,
159 // and expand condition based on frame size. 152 // and expand condition based on frame size.
160 // Max round trip time threshold in ms. 153 // Max round trip time threshold in ms.
161 const int64_t kMaxRttTurnOffFec = 200; 154 const int64_t kMaxRttTurnOffFec = 200;
162 if (estimate_bytes_per_frame < max_bytes_per_frame && 155 if (estimate_bytes_per_frame < max_bytes_per_frame &&
163 parameters->numLayers < 3 && 156 parameters->numLayers < 3 && parameters->rtt < kMaxRttTurnOffFec) {
164 parameters->rtt < kMaxRttTurnOffFec) {
165 return true; 157 return true;
166 } 158 }
167 return false; 159 return false;
168 } 160 }
169 161
170 bool 162 bool VCMNackFecMethod::EffectivePacketLoss(
171 VCMNackFecMethod::EffectivePacketLoss(const VCMProtectionParameters* parameters) 163 const VCMProtectionParameters* parameters) {
172 { 164 // Set the effective packet loss for encoder (based on FEC code).
173 // Set the effective packet loss for encoder (based on FEC code). 165 // Compute the effective packet loss and residual packet loss due to FEC.
174 // Compute the effective packet loss and residual packet loss due to FEC. 166 VCMFecMethod::EffectivePacketLoss(parameters);
175 VCMFecMethod::EffectivePacketLoss(parameters); 167 return true;
168 }
169
170 bool VCMNackFecMethod::UpdateParameters(
171 const VCMProtectionParameters* parameters) {
172 ProtectionFactor(parameters);
173 EffectivePacketLoss(parameters);
174 _maxFramesFec = ComputeMaxFramesFec(parameters);
175 if (BitRateTooLowForFec(parameters)) {
176 _protectionFactorK = 0;
177 _protectionFactorD = 0;
178 }
179
180 // Protection/fec rates obtained above are defined relative to total number
181 // of packets (total rate: source + fec) FEC in RTP module assumes
182 // protection factor is defined relative to source number of packets so we
183 // should convert the factor to reduce mismatch between mediaOpt's rate and
184 // the actual one
185 _protectionFactorK = VCMFecMethod::ConvertFECRate(_protectionFactorK);
186 _protectionFactorD = VCMFecMethod::ConvertFECRate(_protectionFactorD);
187
188 return true;
189 }
190
191 VCMNackMethod::VCMNackMethod() : VCMProtectionMethod() {
192 _type = kNack;
193 }
194
195 VCMNackMethod::~VCMNackMethod() {
196 //
197 }
198
199 bool VCMNackMethod::EffectivePacketLoss(
200 const VCMProtectionParameters* parameter) {
201 // Effective Packet Loss, NA in current version.
202 _effectivePacketLoss = 0;
203 return true;
204 }
205
206 bool VCMNackMethod::UpdateParameters(
207 const VCMProtectionParameters* parameters) {
208 // Compute the effective packet loss
209 EffectivePacketLoss(parameters);
210
211 // nackCost = (bitRate - nackCost) * (lossPr)
212 return true;
213 }
214
215 VCMFecMethod::VCMFecMethod() : VCMProtectionMethod() {
216 _type = kFec;
217 }
218 VCMFecMethod::~VCMFecMethod() {
219 //
220 }
221
222 uint8_t VCMFecMethod::BoostCodeRateKey(uint8_t packetFrameDelta,
223 uint8_t packetFrameKey) const {
224 uint8_t boostRateKey = 2;
225 // Default: ratio scales the FEC protection up for I frames
226 uint8_t ratio = 1;
227
228 if (packetFrameDelta > 0) {
229 ratio = (int8_t)(packetFrameKey / packetFrameDelta);
230 }
231 ratio = VCM_MAX(boostRateKey, ratio);
232
233 return ratio;
234 }
235
236 uint8_t VCMFecMethod::ConvertFECRate(uint8_t codeRateRTP) const {
237 return static_cast<uint8_t>(VCM_MIN(
238 255,
239 (0.5 + 255.0 * codeRateRTP / static_cast<float>(255 - codeRateRTP))));
240 }
241
242 // Update FEC with protectionFactorD
243 void VCMFecMethod::UpdateProtectionFactorD(uint8_t protectionFactorD) {
244 _protectionFactorD = protectionFactorD;
245 }
246
247 // Update FEC with protectionFactorK
248 void VCMFecMethod::UpdateProtectionFactorK(uint8_t protectionFactorK) {
249 _protectionFactorK = protectionFactorK;
250 }
251
252 bool VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) {
253 // FEC PROTECTION SETTINGS: varies with packet loss and bitrate
254
255 // No protection if (filtered) packetLoss is 0
256 uint8_t packetLoss = (uint8_t)(255 * parameters->lossPr);
257 if (packetLoss == 0) {
258 _protectionFactorK = 0;
259 _protectionFactorD = 0;
176 return true; 260 return true;
177 } 261 }
178 262
179 bool 263 // Parameters for FEC setting:
180 VCMNackFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) 264 // first partition size, thresholds, table pars, spatial resoln fac.
181 { 265
182 ProtectionFactor(parameters); 266 // First partition protection: ~ 20%
183 EffectivePacketLoss(parameters); 267 uint8_t firstPartitionProt = (uint8_t)(255 * 0.20);
184 _maxFramesFec = ComputeMaxFramesFec(parameters); 268
185 if (BitRateTooLowForFec(parameters)) { 269 // Minimum protection level needed to generate one FEC packet for one
186 _protectionFactorK = 0; 270 // source packet/frame (in RTP sender)
187 _protectionFactorD = 0; 271 uint8_t minProtLevelFec = 85;
272
273 // Threshold on packetLoss and bitRrate/frameRate (=average #packets),
274 // above which we allocate protection to cover at least first partition.
275 uint8_t lossThr = 0;
276 uint8_t packetNumThr = 1;
277
278 // Parameters for range of rate index of table.
279 const uint8_t ratePar1 = 5;
280 const uint8_t ratePar2 = 49;
281
282 // Spatial resolution size, relative to a reference size.
283 float spatialSizeToRef =
284 static_cast<float>(parameters->codecWidth * parameters->codecHeight) /
285 (static_cast<float>(704 * 576));
286 // resolnFac: This parameter will generally increase/decrease the FEC rate
287 // (for fixed bitRate and packetLoss) based on system size.
288 // Use a smaller exponent (< 1) to control/soften system size effect.
289 const float resolnFac = 1.0 / powf(spatialSizeToRef, 0.3f);
290
291 const int bitRatePerFrame = BitsPerFrame(parameters);
292
293 // Average number of packets per frame (source and fec):
294 const uint8_t avgTotPackets =
295 1 + (uint8_t)(static_cast<float>(bitRatePerFrame) * 1000.0 /
296 static_cast<float>(8.0 * _maxPayloadSize) +
297 0.5);
298
299 // FEC rate parameters: for P and I frame
300 uint8_t codeRateDelta = 0;
301 uint8_t codeRateKey = 0;
302
303 // Get index for table: the FEC protection depends on an effective rate.
304 // The range on the rate index corresponds to rates (bps)
305 // from ~200k to ~8000k, for 30fps
306 const uint16_t effRateFecTable =
307 static_cast<uint16_t>(resolnFac * bitRatePerFrame);
308 uint8_t rateIndexTable = (uint8_t)VCM_MAX(
309 VCM_MIN((effRateFecTable - ratePar1) / ratePar1, ratePar2), 0);
310
311 // Restrict packet loss range to 50:
312 // current tables defined only up to 50%
313 if (packetLoss >= kPacketLossMax) {
314 packetLoss = kPacketLossMax - 1;
315 }
316 uint16_t indexTable = rateIndexTable * kPacketLossMax + packetLoss;
317
318 // Check on table index
319 assert(indexTable < kSizeCodeRateXORTable);
320
321 // Protection factor for P frame
322 codeRateDelta = kCodeRateXORTable[indexTable];
323
324 if (packetLoss > lossThr && avgTotPackets > packetNumThr) {
325 // Set a minimum based on first partition size.
326 if (codeRateDelta < firstPartitionProt) {
327 codeRateDelta = firstPartitionProt;
188 } 328 }
189 329 }
190 // Protection/fec rates obtained above are defined relative to total number 330
191 // of packets (total rate: source + fec) FEC in RTP module assumes 331 // Check limit on amount of protection for P frame; 50% is max.
192 // protection factor is defined relative to source number of packets so we 332 if (codeRateDelta >= kPacketLossMax) {
193 // should convert the factor to reduce mismatch between mediaOpt's rate and 333 codeRateDelta = kPacketLossMax - 1;
194 // the actual one 334 }
195 _protectionFactorK = VCMFecMethod::ConvertFECRate(_protectionFactorK); 335
196 _protectionFactorD = VCMFecMethod::ConvertFECRate(_protectionFactorD); 336 float adjustFec = 1.0f;
197 337 // Avoid additional adjustments when layers are active.
198 return true; 338 // TODO(mikhal/marco): Update adjusmtent based on layer info.
199 } 339 if (parameters->numLayers == 1) {
200 340 adjustFec = _qmRobustness->AdjustFecFactor(
201 VCMNackMethod::VCMNackMethod(): 341 codeRateDelta, parameters->bitRate, parameters->frameRate,
202 VCMProtectionMethod() 342 parameters->rtt, packetLoss);
203 { 343 }
204 _type = kNack; 344
205 } 345 codeRateDelta = static_cast<uint8_t>(codeRateDelta * adjustFec);
206 346
207 VCMNackMethod::~VCMNackMethod() 347 // For Key frame:
208 { 348 // Effectively at a higher rate, so we scale/boost the rate
209 // 349 // The boost factor may depend on several factors: ratio of packet
210 } 350 // number of I to P frames, how much protection placed on P frames, etc.
211 351 const uint8_t packetFrameDelta = (uint8_t)(0.5 + parameters->packetsPerFrame);
212 bool 352 const uint8_t packetFrameKey =
213 VCMNackMethod::EffectivePacketLoss(const VCMProtectionParameters* parameter) 353 (uint8_t)(0.5 + parameters->packetsPerFrameKey);
214 { 354 const uint8_t boostKey = BoostCodeRateKey(packetFrameDelta, packetFrameKey);
215 // Effective Packet Loss, NA in current version. 355
216 _effectivePacketLoss = 0; 356 rateIndexTable = (uint8_t)VCM_MAX(
217 return true; 357 VCM_MIN(1 + (boostKey * effRateFecTable - ratePar1) / ratePar1, ratePar2),
218 } 358 0);
219 359 uint16_t indexTableKey = rateIndexTable * kPacketLossMax + packetLoss;
220 bool 360
221 VCMNackMethod::UpdateParameters(const VCMProtectionParameters* parameters) 361 indexTableKey = VCM_MIN(indexTableKey, kSizeCodeRateXORTable);
222 { 362
223 // Compute the effective packet loss 363 // Check on table index
224 EffectivePacketLoss(parameters); 364 assert(indexTableKey < kSizeCodeRateXORTable);
225 365
226 // nackCost = (bitRate - nackCost) * (lossPr) 366 // Protection factor for I frame
227 return true; 367 codeRateKey = kCodeRateXORTable[indexTableKey];
228 } 368
229 369 // Boosting for Key frame.
230 VCMFecMethod::VCMFecMethod(): 370 int boostKeyProt = _scaleProtKey * codeRateDelta;
231 VCMProtectionMethod() 371 if (boostKeyProt >= kPacketLossMax) {
232 { 372 boostKeyProt = kPacketLossMax - 1;
233 _type = kFec; 373 }
234 } 374
235 VCMFecMethod::~VCMFecMethod() 375 // Make sure I frame protection is at least larger than P frame protection,
236 { 376 // and at least as high as filtered packet loss.
237 // 377 codeRateKey = static_cast<uint8_t>(
238 } 378 VCM_MAX(packetLoss, VCM_MAX(boostKeyProt, codeRateKey)));
239 379
240 uint8_t 380 // Check limit on amount of protection for I frame: 50% is max.
241 VCMFecMethod::BoostCodeRateKey(uint8_t packetFrameDelta, 381 if (codeRateKey >= kPacketLossMax) {
242 uint8_t packetFrameKey) const 382 codeRateKey = kPacketLossMax - 1;
243 { 383 }
244 uint8_t boostRateKey = 2; 384
245 // Default: ratio scales the FEC protection up for I frames 385 _protectionFactorK = codeRateKey;
246 uint8_t ratio = 1; 386 _protectionFactorD = codeRateDelta;
247 387
248 if (packetFrameDelta > 0) 388 // Generally there is a rate mis-match between the FEC cost estimated
249 { 389 // in mediaOpt and the actual FEC cost sent out in RTP module.
250 ratio = (int8_t) (packetFrameKey / packetFrameDelta); 390 // This is more significant at low rates (small # of source packets), where
251 } 391 // the granularity of the FEC decreases. In this case, non-zero protection
252 ratio = VCM_MAX(boostRateKey, ratio); 392 // in mediaOpt may generate 0 FEC packets in RTP sender (since actual #FEC
253 393 // is based on rounding off protectionFactor on actual source packet number).
254 return ratio; 394 // The correction factor (_corrFecCost) attempts to corrects this, at least
255 } 395 // for cases of low rates (small #packets) and low protection levels.
256 396
257 uint8_t 397 float numPacketsFl = 1.0f + (static_cast<float>(bitRatePerFrame) * 1000.0 /
258 VCMFecMethod::ConvertFECRate(uint8_t codeRateRTP) const 398 static_cast<float>(8.0 * _maxPayloadSize) +
259 { 399 0.5);
260 return static_cast<uint8_t> (VCM_MIN(255,(0.5 + 255.0 * codeRateRTP / 400
261 (float)(255 - codeRateRTP)))); 401 const float estNumFecGen =
262 } 402 0.5f + static_cast<float>(_protectionFactorD * numPacketsFl / 255.0f);
263 403
264 // Update FEC with protectionFactorD 404 // We reduce cost factor (which will reduce overhead for FEC and
265 void 405 // hybrid method) and not the protectionFactor.
266 VCMFecMethod::UpdateProtectionFactorD(uint8_t protectionFactorD) 406 _corrFecCost = 1.0f;
267 { 407 if (estNumFecGen < 1.1f && _protectionFactorD < minProtLevelFec) {
268 _protectionFactorD = protectionFactorD; 408 _corrFecCost = 0.5f;
269 } 409 }
270 410 if (estNumFecGen < 0.9f && _protectionFactorD < minProtLevelFec) {
271 // Update FEC with protectionFactorK 411 _corrFecCost = 0.0f;
272 void 412 }
273 VCMFecMethod::UpdateProtectionFactorK(uint8_t protectionFactorK) 413
274 { 414 // TODO(marpan): Set the UEP protection on/off for Key and Delta frames
275 _protectionFactorK = protectionFactorK; 415 _useUepProtectionK = _qmRobustness->SetUepProtection(
276 } 416 codeRateKey, parameters->bitRate, packetLoss, 0);
277 417
278 bool 418 _useUepProtectionD = _qmRobustness->SetUepProtection(
279 VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) 419 codeRateDelta, parameters->bitRate, packetLoss, 1);
280 { 420
281 // FEC PROTECTION SETTINGS: varies with packet loss and bitrate 421 // DONE WITH FEC PROTECTION SETTINGS
282 422 return true;
283 // No protection if (filtered) packetLoss is 0
284 uint8_t packetLoss = (uint8_t) (255 * parameters->lossPr);
285 if (packetLoss == 0)
286 {
287 _protectionFactorK = 0;
288 _protectionFactorD = 0;
289 return true;
290 }
291
292 // Parameters for FEC setting:
293 // first partition size, thresholds, table pars, spatial resoln fac.
294
295 // First partition protection: ~ 20%
296 uint8_t firstPartitionProt = (uint8_t) (255 * 0.20);
297
298 // Minimum protection level needed to generate one FEC packet for one
299 // source packet/frame (in RTP sender)
300 uint8_t minProtLevelFec = 85;
301
302 // Threshold on packetLoss and bitRrate/frameRate (=average #packets),
303 // above which we allocate protection to cover at least first partition.
304 uint8_t lossThr = 0;
305 uint8_t packetNumThr = 1;
306
307 // Parameters for range of rate index of table.
308 const uint8_t ratePar1 = 5;
309 const uint8_t ratePar2 = 49;
310
311 // Spatial resolution size, relative to a reference size.
312 float spatialSizeToRef = static_cast<float>
313 (parameters->codecWidth * parameters->codecHeight) /
314 (static_cast<float>(704 * 576));
315 // resolnFac: This parameter will generally increase/decrease the FEC rate
316 // (for fixed bitRate and packetLoss) based on system size.
317 // Use a smaller exponent (< 1) to control/soften system size effect.
318 const float resolnFac = 1.0 / powf(spatialSizeToRef, 0.3f);
319
320 const int bitRatePerFrame = BitsPerFrame(parameters);
321
322
323 // Average number of packets per frame (source and fec):
324 const uint8_t avgTotPackets = 1 + (uint8_t)
325 ((float) bitRatePerFrame * 1000.0
326 / (float) (8.0 * _maxPayloadSize) + 0.5);
327
328 // FEC rate parameters: for P and I frame
329 uint8_t codeRateDelta = 0;
330 uint8_t codeRateKey = 0;
331
332 // Get index for table: the FEC protection depends on an effective rate.
333 // The range on the rate index corresponds to rates (bps)
334 // from ~200k to ~8000k, for 30fps
335 const uint16_t effRateFecTable = static_cast<uint16_t>
336 (resolnFac * bitRatePerFrame);
337 uint8_t rateIndexTable =
338 (uint8_t) VCM_MAX(VCM_MIN((effRateFecTable - ratePar1) /
339 ratePar1, ratePar2), 0);
340
341 // Restrict packet loss range to 50:
342 // current tables defined only up to 50%
343 if (packetLoss >= kPacketLossMax)
344 {
345 packetLoss = kPacketLossMax - 1;
346 }
347 uint16_t indexTable = rateIndexTable * kPacketLossMax + packetLoss;
348
349 // Check on table index
350 assert(indexTable < kSizeCodeRateXORTable);
351
352 // Protection factor for P frame
353 codeRateDelta = kCodeRateXORTable[indexTable];
354
355 if (packetLoss > lossThr && avgTotPackets > packetNumThr)
356 {
357 // Set a minimum based on first partition size.
358 if (codeRateDelta < firstPartitionProt)
359 {
360 codeRateDelta = firstPartitionProt;
361 }
362 }
363
364 // Check limit on amount of protection for P frame; 50% is max.
365 if (codeRateDelta >= kPacketLossMax)
366 {
367 codeRateDelta = kPacketLossMax - 1;
368 }
369
370 float adjustFec = 1.0f;
371 // Avoid additional adjustments when layers are active.
372 // TODO(mikhal/marco): Update adjusmtent based on layer info.
373 if (parameters->numLayers == 1)
374 {
375 adjustFec = _qmRobustness->AdjustFecFactor(codeRateDelta,
376 parameters->bitRate,
377 parameters->frameRate,
378 parameters->rtt,
379 packetLoss);
380 }
381
382 codeRateDelta = static_cast<uint8_t>(codeRateDelta * adjustFec);
383
384 // For Key frame:
385 // Effectively at a higher rate, so we scale/boost the rate
386 // The boost factor may depend on several factors: ratio of packet
387 // number of I to P frames, how much protection placed on P frames, etc.
388 const uint8_t packetFrameDelta = (uint8_t)
389 (0.5 + parameters->packetsPerFrame);
390 const uint8_t packetFrameKey = (uint8_t)
391 (0.5 + parameters->packetsPerFrameKey);
392 const uint8_t boostKey = BoostCodeRateKey(packetFrameDelta,
393 packetFrameKey);
394
395 rateIndexTable = (uint8_t) VCM_MAX(VCM_MIN(
396 1 + (boostKey * effRateFecTable - ratePar1) /
397 ratePar1,ratePar2),0);
398 uint16_t indexTableKey = rateIndexTable * kPacketLossMax + packetLoss;
399
400 indexTableKey = VCM_MIN(indexTableKey, kSizeCodeRateXORTable);
401
402 // Check on table index
403 assert(indexTableKey < kSizeCodeRateXORTable);
404
405 // Protection factor for I frame
406 codeRateKey = kCodeRateXORTable[indexTableKey];
407
408 // Boosting for Key frame.
409 int boostKeyProt = _scaleProtKey * codeRateDelta;
410 if (boostKeyProt >= kPacketLossMax)
411 {
412 boostKeyProt = kPacketLossMax - 1;
413 }
414
415 // Make sure I frame protection is at least larger than P frame protection,
416 // and at least as high as filtered packet loss.
417 codeRateKey = static_cast<uint8_t> (VCM_MAX(packetLoss,
418 VCM_MAX(boostKeyProt, codeRateKey)));
419
420 // Check limit on amount of protection for I frame: 50% is max.
421 if (codeRateKey >= kPacketLossMax)
422 {
423 codeRateKey = kPacketLossMax - 1;
424 }
425
426 _protectionFactorK = codeRateKey;
427 _protectionFactorD = codeRateDelta;
428
429 // Generally there is a rate mis-match between the FEC cost estimated
430 // in mediaOpt and the actual FEC cost sent out in RTP module.
431 // This is more significant at low rates (small # of source packets), where
432 // the granularity of the FEC decreases. In this case, non-zero protection
433 // in mediaOpt may generate 0 FEC packets in RTP sender (since actual #FEC
434 // is based on rounding off protectionFactor on actual source packet number) .
435 // The correction factor (_corrFecCost) attempts to corrects this, at least
436 // for cases of low rates (small #packets) and low protection levels.
437
438 float numPacketsFl = 1.0f + ((float) bitRatePerFrame * 1000.0
439 / (float) (8.0 * _maxPayloadSize) + 0.5);
440
441 const float estNumFecGen = 0.5f + static_cast<float> (_protectionFactorD *
442 numPacketsFl / 255.0f);
443
444
445 // We reduce cost factor (which will reduce overhead for FEC and
446 // hybrid method) and not the protectionFactor.
447 _corrFecCost = 1.0f;
448 if (estNumFecGen < 1.1f && _protectionFactorD < minProtLevelFec)
449 {
450 _corrFecCost = 0.5f;
451 }
452 if (estNumFecGen < 0.9f && _protectionFactorD < minProtLevelFec)
453 {
454 _corrFecCost = 0.0f;
455 }
456
457 // TODO (marpan): Set the UEP protection on/off for Key and Delta frames
458 _useUepProtectionK = _qmRobustness->SetUepProtection(codeRateKey,
459 parameters->bitRate,
460 packetLoss,
461 0);
462
463 _useUepProtectionD = _qmRobustness->SetUepProtection(codeRateDelta,
464 parameters->bitRate,
465 packetLoss,
466 1);
467
468 // DONE WITH FEC PROTECTION SETTINGS
469 return true;
470 } 423 }
471 424
472 int VCMFecMethod::BitsPerFrame(const VCMProtectionParameters* parameters) { 425 int VCMFecMethod::BitsPerFrame(const VCMProtectionParameters* parameters) {
473 // When temporal layers are available FEC will only be applied on the base 426 // When temporal layers are available FEC will only be applied on the base
474 // layer. 427 // layer.
475 const float bitRateRatio = 428 const float bitRateRatio =
476 kVp8LayerRateAlloction[parameters->numLayers - 1][0]; 429 kVp8LayerRateAlloction[parameters->numLayers - 1][0];
477 float frameRateRatio = powf(1 / 2.0, parameters->numLayers - 1); 430 float frameRateRatio = powf(1 / 2.0, parameters->numLayers - 1);
478 float bitRate = parameters->bitRate * bitRateRatio; 431 float bitRate = parameters->bitRate * bitRateRatio;
479 float frameRate = parameters->frameRate * frameRateRatio; 432 float frameRate = parameters->frameRate * frameRateRatio;
480 433
481 // TODO(mikhal): Update factor following testing. 434 // TODO(mikhal): Update factor following testing.
482 float adjustmentFactor = 1; 435 float adjustmentFactor = 1;
483 436
484 // Average bits per frame (units of kbits) 437 // Average bits per frame (units of kbits)
485 return static_cast<int>(adjustmentFactor * bitRate / frameRate); 438 return static_cast<int>(adjustmentFactor * bitRate / frameRate);
486 } 439 }
487 440
488 bool 441 bool VCMFecMethod::EffectivePacketLoss(
489 VCMFecMethod::EffectivePacketLoss(const VCMProtectionParameters* parameters) 442 const VCMProtectionParameters* parameters) {
490 { 443 // Effective packet loss to encoder is based on RPL (residual packet loss)
491 // Effective packet loss to encoder is based on RPL (residual packet loss) 444 // this is a soft setting based on degree of FEC protection
492 // this is a soft setting based on degree of FEC protection 445 // RPL = received/input packet loss - average_FEC_recovery
493 // RPL = received/input packet loss - average_FEC_recovery 446 // note: received/input packet loss may be filtered based on FilteredLoss
494 // note: received/input packet loss may be filtered based on FilteredLoss
495 447
496 // Effective Packet Loss, NA in current version. 448 // Effective Packet Loss, NA in current version.
497 _effectivePacketLoss = 0; 449 _effectivePacketLoss = 0;
498 450
499 return true; 451 return true;
500 } 452 }
501 453
502 bool 454 bool VCMFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) {
503 VCMFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) 455 // Compute the protection factor
504 { 456 ProtectionFactor(parameters);
505 // Compute the protection factor
506 ProtectionFactor(parameters);
507 457
508 // Compute the effective packet loss 458 // Compute the effective packet loss
509 EffectivePacketLoss(parameters); 459 EffectivePacketLoss(parameters);
510 460
511 // Protection/fec rates obtained above is defined relative to total number 461 // Protection/fec rates obtained above is defined relative to total number
512 // of packets (total rate: source+fec) FEC in RTP module assumes protection 462 // of packets (total rate: source+fec) FEC in RTP module assumes protection
513 // factor is defined relative to source number of packets so we should 463 // factor is defined relative to source number of packets so we should
514 // convert the factor to reduce mismatch between mediaOpt suggested rate and 464 // convert the factor to reduce mismatch between mediaOpt suggested rate and
515 // the actual rate 465 // the actual rate
516 _protectionFactorK = ConvertFECRate(_protectionFactorK); 466 _protectionFactorK = ConvertFECRate(_protectionFactorK);
517 _protectionFactorD = ConvertFECRate(_protectionFactorD); 467 _protectionFactorD = ConvertFECRate(_protectionFactorD);
518 468
519 return true; 469 return true;
520 } 470 }
521 VCMLossProtectionLogic::VCMLossProtectionLogic(int64_t nowMs): 471 VCMLossProtectionLogic::VCMLossProtectionLogic(int64_t nowMs)
522 _currentParameters(), 472 : _currentParameters(),
523 _rtt(0), 473 _rtt(0),
524 _lossPr(0.0f), 474 _lossPr(0.0f),
525 _bitRate(0.0f), 475 _bitRate(0.0f),
526 _frameRate(0.0f), 476 _frameRate(0.0f),
527 _keyFrameSize(0.0f), 477 _keyFrameSize(0.0f),
528 _fecRateKey(0), 478 _fecRateKey(0),
529 _fecRateDelta(0), 479 _fecRateDelta(0),
530 _lastPrUpdateT(0), 480 _lastPrUpdateT(0),
531 _lossPr255(0.9999f), 481 _lossPr255(0.9999f),
532 _lossPrHistory(), 482 _lossPrHistory(),
533 _shortMaxLossPr255(0), 483 _shortMaxLossPr255(0),
534 _packetsPerFrame(0.9999f), 484 _packetsPerFrame(0.9999f),
535 _packetsPerFrameKey(0.9999f), 485 _packetsPerFrameKey(0.9999f),
536 _codecWidth(0), 486 _codecWidth(0),
537 _codecHeight(0), 487 _codecHeight(0),
538 _numLayers(1) 488 _numLayers(1) {
539 { 489 Reset(nowMs);
540 Reset(nowMs);
541 } 490 }
542 491
543 VCMLossProtectionLogic::~VCMLossProtectionLogic() 492 VCMLossProtectionLogic::~VCMLossProtectionLogic() {
544 { 493 Release();
545 Release();
546 } 494 }
547 495
548 void VCMLossProtectionLogic::SetMethod( 496 void VCMLossProtectionLogic::SetMethod(
549 enum VCMProtectionMethodEnum newMethodType) { 497 enum VCMProtectionMethodEnum newMethodType) {
550 if (_selectedMethod && _selectedMethod->Type() == newMethodType) 498 if (_selectedMethod && _selectedMethod->Type() == newMethodType)
551 return; 499 return;
552 500
553 switch(newMethodType) { 501 switch (newMethodType) {
554 case kNack: 502 case kNack:
555 _selectedMethod.reset(new VCMNackMethod()); 503 _selectedMethod.reset(new VCMNackMethod());
556 break; 504 break;
557 case kFec: 505 case kFec:
558 _selectedMethod.reset(new VCMFecMethod()); 506 _selectedMethod.reset(new VCMFecMethod());
559 break; 507 break;
560 case kNackFec: 508 case kNackFec:
561 _selectedMethod.reset(new VCMNackFecMethod(kLowRttNackMs, -1)); 509 _selectedMethod.reset(new VCMNackFecMethod(kLowRttNackMs, -1));
562 break; 510 break;
563 case kNone: 511 case kNone:
564 _selectedMethod.reset(); 512 _selectedMethod.reset();
565 break; 513 break;
566 } 514 }
567 UpdateMethod(); 515 UpdateMethod();
568 } 516 }
569 517
570 void 518 void VCMLossProtectionLogic::UpdateRtt(int64_t rtt) {
571 VCMLossProtectionLogic::UpdateRtt(int64_t rtt) 519 _rtt = rtt;
572 {
573 _rtt = rtt;
574 } 520 }
575 521
576 void 522 void VCMLossProtectionLogic::UpdateMaxLossHistory(uint8_t lossPr255,
577 VCMLossProtectionLogic::UpdateMaxLossHistory(uint8_t lossPr255, 523 int64_t now) {
578 int64_t now) 524 if (_lossPrHistory[0].timeMs >= 0 &&
579 { 525 now - _lossPrHistory[0].timeMs < kLossPrShortFilterWinMs) {
580 if (_lossPrHistory[0].timeMs >= 0 && 526 if (lossPr255 > _shortMaxLossPr255) {
581 now - _lossPrHistory[0].timeMs < kLossPrShortFilterWinMs) 527 _shortMaxLossPr255 = lossPr255;
582 {
583 if (lossPr255 > _shortMaxLossPr255)
584 {
585 _shortMaxLossPr255 = lossPr255;
586 }
587 } 528 }
588 else 529 } else {
589 { 530 // Only add a new value to the history once a second
590 // Only add a new value to the history once a second 531 if (_lossPrHistory[0].timeMs == -1) {
591 if (_lossPrHistory[0].timeMs == -1) 532 // First, no shift
592 { 533 _shortMaxLossPr255 = lossPr255;
593 // First, no shift 534 } else {
594 _shortMaxLossPr255 = lossPr255; 535 // Shift
595 } 536 for (int32_t i = (kLossPrHistorySize - 2); i >= 0; i--) {
596 else 537 _lossPrHistory[i + 1].lossPr255 = _lossPrHistory[i].lossPr255;
597 { 538 _lossPrHistory[i + 1].timeMs = _lossPrHistory[i].timeMs;
598 // Shift 539 }
599 for (int32_t i = (kLossPrHistorySize - 2); i >= 0; i--) 540 }
600 { 541 if (_shortMaxLossPr255 == 0) {
601 _lossPrHistory[i + 1].lossPr255 = _lossPrHistory[i].lossPr255; 542 _shortMaxLossPr255 = lossPr255;
602 _lossPrHistory[i + 1].timeMs = _lossPrHistory[i].timeMs; 543 }
603 }
604 }
605 if (_shortMaxLossPr255 == 0)
606 {
607 _shortMaxLossPr255 = lossPr255;
608 }
609 544
610 _lossPrHistory[0].lossPr255 = _shortMaxLossPr255; 545 _lossPrHistory[0].lossPr255 = _shortMaxLossPr255;
611 _lossPrHistory[0].timeMs = now; 546 _lossPrHistory[0].timeMs = now;
612 _shortMaxLossPr255 = 0; 547 _shortMaxLossPr255 = 0;
613 } 548 }
614 } 549 }
615 550
616 uint8_t 551 uint8_t VCMLossProtectionLogic::MaxFilteredLossPr(int64_t nowMs) const {
617 VCMLossProtectionLogic::MaxFilteredLossPr(int64_t nowMs) const 552 uint8_t maxFound = _shortMaxLossPr255;
618 { 553 if (_lossPrHistory[0].timeMs == -1) {
619 uint8_t maxFound = _shortMaxLossPr255; 554 return maxFound;
620 if (_lossPrHistory[0].timeMs == -1) 555 }
621 { 556 for (int32_t i = 0; i < kLossPrHistorySize; i++) {
622 return maxFound; 557 if (_lossPrHistory[i].timeMs == -1) {
558 break;
623 } 559 }
624 for (int32_t i = 0; i < kLossPrHistorySize; i++) 560 if (nowMs - _lossPrHistory[i].timeMs >
625 { 561 kLossPrHistorySize * kLossPrShortFilterWinMs) {
626 if (_lossPrHistory[i].timeMs == -1) 562 // This sample (and all samples after this) is too old
627 { 563 break;
628 break;
629 }
630 if (nowMs - _lossPrHistory[i].timeMs >
631 kLossPrHistorySize * kLossPrShortFilterWinMs)
632 {
633 // This sample (and all samples after this) is too old
634 break;
635 }
636 if (_lossPrHistory[i].lossPr255 > maxFound)
637 {
638 // This sample is the largest one this far into the history
639 maxFound = _lossPrHistory[i].lossPr255;
640 }
641 } 564 }
642 return maxFound; 565 if (_lossPrHistory[i].lossPr255 > maxFound) {
566 // This sample is the largest one this far into the history
567 maxFound = _lossPrHistory[i].lossPr255;
568 }
569 }
570 return maxFound;
643 } 571 }
644 572
645 uint8_t VCMLossProtectionLogic::FilteredLoss( 573 uint8_t VCMLossProtectionLogic::FilteredLoss(int64_t nowMs,
646 int64_t nowMs, 574 FilterPacketLossMode filter_mode,
647 FilterPacketLossMode filter_mode, 575 uint8_t lossPr255) {
648 uint8_t lossPr255) {
649
650 // Update the max window filter. 576 // Update the max window filter.
651 UpdateMaxLossHistory(lossPr255, nowMs); 577 UpdateMaxLossHistory(lossPr255, nowMs);
652 578
653 // Update the recursive average filter. 579 // Update the recursive average filter.
654 _lossPr255.Apply(static_cast<float> (nowMs - _lastPrUpdateT), 580 _lossPr255.Apply(static_cast<float>(nowMs - _lastPrUpdateT),
655 static_cast<float> (lossPr255)); 581 static_cast<float>(lossPr255));
656 _lastPrUpdateT = nowMs; 582 _lastPrUpdateT = nowMs;
657 583
658 // Filtered loss: default is received loss (no filtering). 584 // Filtered loss: default is received loss (no filtering).
659 uint8_t filtered_loss = lossPr255; 585 uint8_t filtered_loss = lossPr255;
660 586
661 switch (filter_mode) { 587 switch (filter_mode) {
662 case kNoFilter: 588 case kNoFilter:
663 break; 589 break;
664 case kAvgFilter: 590 case kAvgFilter:
665 filtered_loss = static_cast<uint8_t>(_lossPr255.filtered() + 0.5); 591 filtered_loss = static_cast<uint8_t>(_lossPr255.filtered() + 0.5);
666 break; 592 break;
667 case kMaxFilter: 593 case kMaxFilter:
668 filtered_loss = MaxFilteredLossPr(nowMs); 594 filtered_loss = MaxFilteredLossPr(nowMs);
669 break; 595 break;
670 } 596 }
671 597
672 return filtered_loss; 598 return filtered_loss;
673 } 599 }
674 600
675 void 601 void VCMLossProtectionLogic::UpdateFilteredLossPr(uint8_t packetLossEnc) {
676 VCMLossProtectionLogic::UpdateFilteredLossPr(uint8_t packetLossEnc) 602 _lossPr = static_cast<float>(packetLossEnc) / 255.0;
677 {
678 _lossPr = (float) packetLossEnc / (float) 255.0;
679 } 603 }
680 604
681 void 605 void VCMLossProtectionLogic::UpdateBitRate(float bitRate) {
682 VCMLossProtectionLogic::UpdateBitRate(float bitRate) 606 _bitRate = bitRate;
683 {
684 _bitRate = bitRate;
685 } 607 }
686 608
687 void 609 void VCMLossProtectionLogic::UpdatePacketsPerFrame(float nPackets,
688 VCMLossProtectionLogic::UpdatePacketsPerFrame(float nPackets, int64_t nowMs) 610 int64_t nowMs) {
689 { 611 _packetsPerFrame.Apply(static_cast<float>(nowMs - _lastPacketPerFrameUpdateT),
690 _packetsPerFrame.Apply(static_cast<float>(nowMs - _lastPacketPerFrameUpdateT ), 612 nPackets);
691 nPackets); 613 _lastPacketPerFrameUpdateT = nowMs;
692 _lastPacketPerFrameUpdateT = nowMs;
693 } 614 }
694 615
695 void 616 void VCMLossProtectionLogic::UpdatePacketsPerFrameKey(float nPackets,
696 VCMLossProtectionLogic::UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs) 617 int64_t nowMs) {
697 { 618 _packetsPerFrameKey.Apply(
698 _packetsPerFrameKey.Apply(static_cast<float>(nowMs - 619 static_cast<float>(nowMs - _lastPacketPerFrameUpdateTKey), nPackets);
699 _lastPacketPerFrameUpdateTKey), nPackets); 620 _lastPacketPerFrameUpdateTKey = nowMs;
700 _lastPacketPerFrameUpdateTKey = nowMs;
701 } 621 }
702 622
703 void 623 void VCMLossProtectionLogic::UpdateKeyFrameSize(float keyFrameSize) {
704 VCMLossProtectionLogic::UpdateKeyFrameSize(float keyFrameSize) 624 _keyFrameSize = keyFrameSize;
705 {
706 _keyFrameSize = keyFrameSize;
707 } 625 }
708 626
709 void 627 void VCMLossProtectionLogic::UpdateFrameSize(uint16_t width, uint16_t height) {
710 VCMLossProtectionLogic::UpdateFrameSize(uint16_t width, 628 _codecWidth = width;
711 uint16_t height) 629 _codecHeight = height;
712 {
713 _codecWidth = width;
714 _codecHeight = height;
715 } 630 }
716 631
717 void VCMLossProtectionLogic::UpdateNumLayers(int numLayers) { 632 void VCMLossProtectionLogic::UpdateNumLayers(int numLayers) {
718 _numLayers = (numLayers == 0) ? 1 : numLayers; 633 _numLayers = (numLayers == 0) ? 1 : numLayers;
719 } 634 }
720 635
721 bool 636 bool VCMLossProtectionLogic::UpdateMethod() {
722 VCMLossProtectionLogic::UpdateMethod() 637 if (!_selectedMethod)
723 { 638 return false;
724 if (!_selectedMethod) 639 _currentParameters.rtt = _rtt;
725 return false; 640 _currentParameters.lossPr = _lossPr;
726 _currentParameters.rtt = _rtt; 641 _currentParameters.bitRate = _bitRate;
727 _currentParameters.lossPr = _lossPr; 642 _currentParameters.frameRate = _frameRate; // rename actual frame rate?
728 _currentParameters.bitRate = _bitRate; 643 _currentParameters.keyFrameSize = _keyFrameSize;
729 _currentParameters.frameRate = _frameRate; // rename actual frame rate? 644 _currentParameters.fecRateDelta = _fecRateDelta;
730 _currentParameters.keyFrameSize = _keyFrameSize; 645 _currentParameters.fecRateKey = _fecRateKey;
731 _currentParameters.fecRateDelta = _fecRateDelta; 646 _currentParameters.packetsPerFrame = _packetsPerFrame.filtered();
732 _currentParameters.fecRateKey = _fecRateKey; 647 _currentParameters.packetsPerFrameKey = _packetsPerFrameKey.filtered();
733 _currentParameters.packetsPerFrame = _packetsPerFrame.filtered(); 648 _currentParameters.codecWidth = _codecWidth;
734 _currentParameters.packetsPerFrameKey = _packetsPerFrameKey.filtered(); 649 _currentParameters.codecHeight = _codecHeight;
735 _currentParameters.codecWidth = _codecWidth; 650 _currentParameters.numLayers = _numLayers;
736 _currentParameters.codecHeight = _codecHeight; 651 return _selectedMethod->UpdateParameters(&_currentParameters);
737 _currentParameters.numLayers = _numLayers;
738 return _selectedMethod->UpdateParameters(&_currentParameters);
739 } 652 }
740 653
741 VCMProtectionMethod* 654 VCMProtectionMethod* VCMLossProtectionLogic::SelectedMethod() const {
742 VCMLossProtectionLogic::SelectedMethod() const 655 return _selectedMethod.get();
743 {
744 return _selectedMethod.get();
745 } 656 }
746 657
747 VCMProtectionMethodEnum VCMLossProtectionLogic::SelectedType() const { 658 VCMProtectionMethodEnum VCMLossProtectionLogic::SelectedType() const {
748 return _selectedMethod ? _selectedMethod->Type() : kNone; 659 return _selectedMethod ? _selectedMethod->Type() : kNone;
749 } 660 }
750 661
751 void 662 void VCMLossProtectionLogic::Reset(int64_t nowMs) {
752 VCMLossProtectionLogic::Reset(int64_t nowMs) 663 _lastPrUpdateT = nowMs;
753 { 664 _lastPacketPerFrameUpdateT = nowMs;
754 _lastPrUpdateT = nowMs; 665 _lastPacketPerFrameUpdateTKey = nowMs;
755 _lastPacketPerFrameUpdateT = nowMs; 666 _lossPr255.Reset(0.9999f);
756 _lastPacketPerFrameUpdateTKey = nowMs; 667 _packetsPerFrame.Reset(0.9999f);
757 _lossPr255.Reset(0.9999f); 668 _fecRateDelta = _fecRateKey = 0;
758 _packetsPerFrame.Reset(0.9999f); 669 for (int32_t i = 0; i < kLossPrHistorySize; i++) {
759 _fecRateDelta = _fecRateKey = 0; 670 _lossPrHistory[i].lossPr255 = 0;
760 for (int32_t i = 0; i < kLossPrHistorySize; i++) 671 _lossPrHistory[i].timeMs = -1;
761 { 672 }
762 _lossPrHistory[i].lossPr255 = 0; 673 _shortMaxLossPr255 = 0;
763 _lossPrHistory[i].timeMs = -1; 674 Release();
764 }
765 _shortMaxLossPr255 = 0;
766 Release();
767 } 675 }
768 676
769 void VCMLossProtectionLogic::Release() { 677 void VCMLossProtectionLogic::Release() {
770 _selectedMethod.reset(); 678 _selectedMethod.reset();
771 } 679 }
772 680
773 } // namespace media_optimization 681 } // namespace media_optimization
774 } // namespace webrtc 682 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/media_opt_util.h ('k') | webrtc/modules/video_coding/media_optimization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698