1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/media_opt_util.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <algorithm> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <float.h> 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <limits.h> 16a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include <math.h> 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 18a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/interface/module_common_types.h" 19a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 20a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h" 21a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/er_tables_xor.h" 22a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/fec_tables_xor.h" 23a557f436b9d694d5a0a045e0295e1794f2df48eapbos@webrtc.org#include "webrtc/modules/video_coding/main/source/nack_fec_tables.h" 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 26bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.orgnamespace media_optimization { 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod::VCMProtectionMethod(): 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_effectivePacketLoss(0), 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_protectionFactorK(0), 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_protectionFactorD(0), 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_residualPacketLossFec(0.0f), 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_scaleProtKey(2.0f), 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_maxPayloadSize(1460), 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_qmRobustness(new VCMQmRobustness()), 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_useUepProtectionK(false), 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_useUepProtectionD(true), 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_corrFecCost(1.0), 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_type(kNone), 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_efficiency(0) 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod::~VCMProtectionMethod() 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _qmRobustness; 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod::UpdateContentMetrics(const 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoContentMetrics* contentMetrics) 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _qmRobustness->UpdateContent(contentMetrics); 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackFecMethod::VCMNackFecMethod(int lowRttNackThresholdMs, 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int highRttNackThresholdMs) 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : VCMFecMethod(), 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lowRttNackMs(lowRttNackThresholdMs), 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _highRttNackMs(highRttNackThresholdMs), 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _maxFramesFec(1) { 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1); 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(highRttNackThresholdMs == -1 || 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lowRttNackThresholdMs <= highRttNackThresholdMs); 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1); 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _type = kNackFec; 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackFecMethod::~VCMNackFecMethod() 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Hybrid Nack FEC has three operational modes: 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (_protectionFactorD) to zero. -1 means no FEC. 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 2. High RTT (above _highRttNackMs) - FEC Only: Keep FEC factors. 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // -1 means always allow NACK. 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 3. Medium RTT values - Hybrid mode: We will only nack the 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // residual following the decoding of the FEC (refer to JB logic). FEC 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // delta protection factor will be adjusted based on the RTT. 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Otherwise: we count on FEC; if the RTT is below a threshold, then we 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // nack the residual, based on a decision made in the JB. 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the protection factors 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMFecMethod::ProtectionFactor(parameters); 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lowRttNackMs == -1 || parameters->rtt < _lowRttNackMs) 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = 0; 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD); 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When in Hybrid mode (RTT range), adjust FEC rates based on the 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // RTT (NACK effectiveness) - adjustment factor is in the range [0,1]. 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs) 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(mikhal): Disabling adjustment temporarily. 101dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org // uint16_t rttIndex = (uint16_t) parameters->rtt; 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float adjustRtt = 1.0f;// (float)VCMNackFecTable[rttIndex] / 100.0f; 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Adjust FEC with NACK on (for delta frame only) 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // table depends on RTT relative to rttMax (NACK Threshold) 106dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org _protectionFactorD = static_cast<uint8_t> 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (adjustRtt * 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<float>(_protectionFactorD)); 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // update FEC rates after applying adjustment 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD); 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint VCMNackFecMethod::ComputeMaxFramesFec( 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VCMProtectionParameters* parameters) { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (parameters->numLayers > 2) { 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For more than 2 temporal layers we will only have FEC on the base layer, 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and the base layers will be pretty far apart. Therefore we force one 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // frame FEC. 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 1; 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We set the max number of frames to base the FEC on so that on average 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // we will have complete frames in one RTT. Note that this is an upper 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // bound, and that the actual number of frames used for FEC is decided by the 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // RTP module based on the actual number of packets and the protection factor. 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float base_layer_framerate = parameters->frameRate / 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<float>(1 << (parameters->numLayers - 1)); 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int max_frames_fec = std::max(static_cast<int>( 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2.0f * base_layer_framerate * parameters->rtt / 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1000.0f + 0.5f), 1); 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // |kUpperLimitFramesFec| is the upper limit on how many frames we 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // allow any FEC to be based on. 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (max_frames_fec > kUpperLimitFramesFec) { 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org max_frames_fec = kUpperLimitFramesFec; 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return max_frames_fec; 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint VCMNackFecMethod::MaxFramesFec() const { 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _maxFramesFec; 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VCMNackFecMethod::BitRateTooLowForFec( 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VCMProtectionParameters* parameters) { 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Bitrate below which we turn off FEC, regardless of reported packet loss. 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The condition should depend on resolution and content. For now, use 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // threshold on bytes per frame, with some effect for the frame size. 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The condition for turning off FEC is also based on other factors, 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // such as |_numLayers|, |_maxFramesFec|, and |_rtt|. 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int estimate_bytes_per_frame = 1000 * BitsPerFrame(parameters) / 8; 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int max_bytes_per_frame = kMaxBytesPerFrameForFec; 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int num_pixels = parameters->codecWidth * parameters->codecHeight; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (num_pixels <= 352 * 288) { 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org max_bytes_per_frame = kMaxBytesPerFrameForFecLow; 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (num_pixels > 640 * 480) { 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org max_bytes_per_frame = kMaxBytesPerFrameForFecHigh; 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO (marpan): add condition based on maximum frames used for FEC, 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and expand condition based on frame size. 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (estimate_bytes_per_frame < max_bytes_per_frame && 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->numLayers < 3 && 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->rtt < kMaxRttTurnOffFec) { 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackFecMethod::EffectivePacketLoss(const VCMProtectionParameters* parameters) 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the effective packet loss for encoder (based on FEC code). 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the effective packet loss and residual packet loss due to FEC. 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMFecMethod::EffectivePacketLoss(parameters); 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ProtectionFactor(parameters); 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EffectivePacketLoss(parameters); 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _maxFramesFec = ComputeMaxFramesFec(parameters); 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (BitRateTooLowForFec(parameters)) { 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = 0; 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = 0; 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Efficiency computation is based on FEC and NACK 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Add FEC cost: ignore I frames for now 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fecRate = static_cast<float> (_protectionFactorD) / 255.0f; 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _efficiency = parameters->bitRate * fecRate * _corrFecCost; 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Add NACK cost, when applicable 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs) 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // nackCost = (bitRate - nackCost) * (lossPr) 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _efficiency += parameters->bitRate * _residualPacketLossFec / 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (1.0f + _residualPacketLossFec); 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Protection/fec rates obtained above are defined relative to total number 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // of packets (total rate: source + fec) FEC in RTP module assumes 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // protection factor is defined relative to source number of packets so we 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // should convert the factor to reduce mismatch between mediaOpt's rate and 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the actual one 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = VCMFecMethod::ConvertFECRate(_protectionFactorK); 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = VCMFecMethod::ConvertFECRate(_protectionFactorD); 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackMethod::VCMNackMethod(): 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod() 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _type = kNack; 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackMethod::~VCMNackMethod() 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackMethod::EffectivePacketLoss(const VCMProtectionParameters* parameter) 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Effective Packet Loss, NA in current version. 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _effectivePacketLoss = 0; 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMNackMethod::UpdateParameters(const VCMProtectionParameters* parameters) 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the effective packet loss 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EffectivePacketLoss(parameters); 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // nackCost = (bitRate - nackCost) * (lossPr) 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _efficiency = parameters->bitRate * parameters->lossPr / 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (1.0f + parameters->lossPr); 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::VCMFecMethod(): 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod() 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _type = kFec; 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::~VCMFecMethod() 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 256dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orguint8_t 257dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMFecMethod::BoostCodeRateKey(uint8_t packetFrameDelta, 258dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t packetFrameKey) const 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 260dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t boostRateKey = 2; 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Default: ratio scales the FEC protection up for I frames 262dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t ratio = 1; 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packetFrameDelta > 0) 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 266dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org ratio = (int8_t) (packetFrameKey / packetFrameDelta); 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ratio = VCM_MAX(boostRateKey, ratio); 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ratio; 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 273dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orguint8_t 274dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMFecMethod::ConvertFECRate(uint8_t codeRateRTP) const 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 276dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org return static_cast<uint8_t> (VCM_MIN(255,(0.5 + 255.0 * codeRateRTP / 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (float)(255 - codeRateRTP)))); 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Update FEC with protectionFactorD 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 282dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMFecMethod::UpdateProtectionFactorD(uint8_t protectionFactorD) 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = protectionFactorD; 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Update FEC with protectionFactorK 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 289dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMFecMethod::UpdateProtectionFactorK(uint8_t protectionFactorK) 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = protectionFactorK; 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// AvgRecoveryFEC: computes the residual packet loss (RPL) function. 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This is the average recovery from the FEC, assuming random packet loss model. 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Computed off-line for a range of FEC code parameters and loss rates. 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfloat 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::AvgRecoveryFEC(const VCMProtectionParameters* parameters) const 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Total (avg) bits available per frame: total rate over actual/sent frame 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // rate units are kbits/frame 302dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint16_t bitRatePerFrame = static_cast<uint16_t> 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (parameters->bitRate / (parameters->frameRate)); 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Total (average) number of packets per frame (source and fec): 306dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t avgTotPackets = 1 + static_cast<uint8_t> 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (static_cast<float> (bitRatePerFrame * 1000.0) / 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<float> (8.0 * _maxPayloadSize) + 0.5); 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float protectionFactor = static_cast<float>(_protectionFactorD) / 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 255.0; 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 31311b3eb19f84236e8416d1bd7a53a00fca9fa22e1marpan@webrtc.org // Round down for estimated #FEC packets/frame, to keep 31411b3eb19f84236e8416d1bd7a53a00fca9fa22e1marpan@webrtc.org // |fecPacketsPerFrame| <= |sourcePacketsPerFrame|. 315dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t fecPacketsPerFrame = static_cast<uint8_t> 31611b3eb19f84236e8416d1bd7a53a00fca9fa22e1marpan@webrtc.org (protectionFactor * avgTotPackets); 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 318dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t sourcePacketsPerFrame = avgTotPackets - fecPacketsPerFrame; 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ( (fecPacketsPerFrame == 0) || (sourcePacketsPerFrame == 0) ) 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // No protection, or rate too low: so average recovery from FEC == 0. 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0.0; 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Table defined up to kMaxNumPackets 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (sourcePacketsPerFrame > kMaxNumPackets) 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sourcePacketsPerFrame = kMaxNumPackets; 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Table defined up to kMaxNumPackets 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (fecPacketsPerFrame > kMaxNumPackets) 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fecPacketsPerFrame = kMaxNumPackets; 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Code index for tables: up to (kMaxNumPackets * kMaxNumPackets) 339dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint16_t codeIndexTable[kMaxNumPackets * kMaxNumPackets]; 340dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint16_t k = 0; 341dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org for (uint8_t i = 1; i <= kMaxNumPackets; i++) 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 343dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org for (uint8_t j = 1; j <= i; j++) 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeIndexTable[(j - 1) * kMaxNumPackets + i - 1] = k; 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org k += 1; 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 350dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t lossRate = static_cast<uint8_t> (255.0 * 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->lossPr + 0.5f); 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Constrain lossRate to 50%: tables defined up to 50% 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (lossRate >= kPacketLossMax) 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lossRate = kPacketLossMax - 1; 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 359dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint16_t codeIndex = (fecPacketsPerFrame - 1) * kMaxNumPackets + 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (sourcePacketsPerFrame - 1); 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 362dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint16_t indexTable = codeIndexTable[codeIndex] * kPacketLossMax + 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org lossRate; 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check on table index 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(indexTable < kSizeAvgFECRecoveryXOR); 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float avgFecRecov = static_cast<float>(kAvgFECRecoveryXOR[indexTable]); 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return avgFecRecov; 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters) 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // FEC PROTECTION SETTINGS: varies with packet loss and bitrate 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // No protection if (filtered) packetLoss is 0 378dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t packetLoss = (uint8_t) (255 * parameters->lossPr); 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packetLoss == 0) 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = 0; 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = 0; 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Parameters for FEC setting: 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // first partition size, thresholds, table pars, spatial resoln fac. 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // First partition protection: ~ 20% 390dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t firstPartitionProt = (uint8_t) (255 * 0.20); 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Minimum protection level needed to generate one FEC packet for one 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // source packet/frame (in RTP sender) 394dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t minProtLevelFec = 85; 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Threshold on packetLoss and bitRrate/frameRate (=average #packets), 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // above which we allocate protection to cover at least first partition. 398dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t lossThr = 0; 399dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t packetNumThr = 1; 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Parameters for range of rate index of table. 402dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t ratePar1 = 5; 403dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t ratePar2 = 49; 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Spatial resolution size, relative to a reference size. 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float spatialSizeToRef = static_cast<float> 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (parameters->codecWidth * parameters->codecHeight) / 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (static_cast<float>(704 * 576)); 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // resolnFac: This parameter will generally increase/decrease the FEC rate 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (for fixed bitRate and packetLoss) based on system size. 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use a smaller exponent (< 1) to control/soften system size effect. 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float resolnFac = 1.0 / powf(spatialSizeToRef, 0.3f); 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int bitRatePerFrame = BitsPerFrame(parameters); 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Average number of packets per frame (source and fec): 418dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t avgTotPackets = 1 + (uint8_t) 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ((float) bitRatePerFrame * 1000.0 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / (float) (8.0 * _maxPayloadSize) + 0.5); 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // FEC rate parameters: for P and I frame 423dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t codeRateDelta = 0; 424dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t codeRateKey = 0; 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get index for table: the FEC protection depends on an effective rate. 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The range on the rate index corresponds to rates (bps) 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // from ~200k to ~8000k, for 30fps 429dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint16_t effRateFecTable = static_cast<uint16_t> 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (resolnFac * bitRatePerFrame); 431dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t rateIndexTable = 432dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org (uint8_t) VCM_MAX(VCM_MIN((effRateFecTable - ratePar1) / 433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ratePar1, ratePar2), 0); 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Restrict packet loss range to 50: 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // current tables defined only up to 50% 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packetLoss >= kPacketLossMax) 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packetLoss = kPacketLossMax - 1; 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 441dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint16_t indexTable = rateIndexTable * kPacketLossMax + packetLoss; 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check on table index 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(indexTable < kSizeCodeRateXORTable); 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Protection factor for P frame 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeRateDelta = kCodeRateXORTable[indexTable]; 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packetLoss > lossThr && avgTotPackets > packetNumThr) 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set a minimum based on first partition size. 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (codeRateDelta < firstPartitionProt) 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeRateDelta = firstPartitionProt; 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check limit on amount of protection for P frame; 50% is max. 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (codeRateDelta >= kPacketLossMax) 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeRateDelta = kPacketLossMax - 1; 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float adjustFec = 1.0f; 465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Avoid additional adjustments when layers are active. 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(mikhal/marco): Update adjusmtent based on layer info. 467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (parameters->numLayers == 1) 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org adjustFec = _qmRobustness->AdjustFecFactor(codeRateDelta, 470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->bitRate, 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->frameRate, 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->rtt, 473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packetLoss); 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 476dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org codeRateDelta = static_cast<uint8_t>(codeRateDelta * adjustFec); 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // For Key frame: 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Effectively at a higher rate, so we scale/boost the rate 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The boost factor may depend on several factors: ratio of packet 481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // number of I to P frames, how much protection placed on P frames, etc. 482dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t packetFrameDelta = (uint8_t) 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (0.5 + parameters->packetsPerFrame); 484dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t packetFrameKey = (uint8_t) 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (0.5 + parameters->packetsPerFrameKey); 486dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org const uint8_t boostKey = BoostCodeRateKey(packetFrameDelta, 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packetFrameKey); 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 489dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org rateIndexTable = (uint8_t) VCM_MAX(VCM_MIN( 490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1 + (boostKey * effRateFecTable - ratePar1) / 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ratePar1,ratePar2),0); 492dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint16_t indexTableKey = rateIndexTable * kPacketLossMax + packetLoss; 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org indexTableKey = VCM_MIN(indexTableKey, kSizeCodeRateXORTable); 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check on table index 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(indexTableKey < kSizeCodeRateXORTable); 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Protection factor for I frame 500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeRateKey = kCodeRateXORTable[indexTableKey]; 501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Boosting for Key frame. 503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int boostKeyProt = _scaleProtKey * codeRateDelta; 504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (boostKeyProt >= kPacketLossMax) 505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 506b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org boostKeyProt = kPacketLossMax - 1; 507b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 508b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 509b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure I frame protection is at least larger than P frame protection, 510b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // and at least as high as filtered packet loss. 511dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org codeRateKey = static_cast<uint8_t> (VCM_MAX(packetLoss, 512b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCM_MAX(boostKeyProt, codeRateKey))); 513b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 514b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Check limit on amount of protection for I frame: 50% is max. 515b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (codeRateKey >= kPacketLossMax) 516b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org codeRateKey = kPacketLossMax - 1; 518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = codeRateKey; 521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = codeRateDelta; 522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Generally there is a rate mis-match between the FEC cost estimated 524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in mediaOpt and the actual FEC cost sent out in RTP module. 525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This is more significant at low rates (small # of source packets), where 526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the granularity of the FEC decreases. In this case, non-zero protection 527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in mediaOpt may generate 0 FEC packets in RTP sender (since actual #FEC 528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // is based on rounding off protectionFactor on actual source packet number). 529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The correction factor (_corrFecCost) attempts to corrects this, at least 530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // for cases of low rates (small #packets) and low protection levels. 531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 532b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float numPacketsFl = 1.0f + ((float) bitRatePerFrame * 1000.0 533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / (float) (8.0 * _maxPayloadSize) + 0.5); 534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float estNumFecGen = 0.5f + static_cast<float> (_protectionFactorD * 536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org numPacketsFl / 255.0f); 537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We reduce cost factor (which will reduce overhead for FEC and 540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // hybrid method) and not the protectionFactor. 541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _corrFecCost = 1.0f; 542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (estNumFecGen < 1.1f && _protectionFactorD < minProtLevelFec) 543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _corrFecCost = 0.5f; 545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (estNumFecGen < 0.9f && _protectionFactorD < minProtLevelFec) 547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _corrFecCost = 0.0f; 549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO (marpan): Set the UEP protection on/off for Key and Delta frames 552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _useUepProtectionK = _qmRobustness->SetUepProtection(codeRateKey, 553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->bitRate, 554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packetLoss, 555b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 0); 556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _useUepProtectionD = _qmRobustness->SetUepProtection(codeRateDelta, 558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org parameters->bitRate, 559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org packetLoss, 560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1); 561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // DONE WITH FEC PROTECTION SETTINGS 563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint VCMFecMethod::BitsPerFrame(const VCMProtectionParameters* parameters) { 567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // When temporal layers are available FEC will only be applied on the base 568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // layer. 569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const float bitRateRatio = 570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kVp8LayerRateAlloction[parameters->numLayers - 1][0]; 571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float frameRateRatio = powf(1 / 2.0, parameters->numLayers - 1); 572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float bitRate = parameters->bitRate * bitRateRatio; 573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float frameRate = parameters->frameRate * frameRateRatio; 574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(mikhal): Update factor following testing. 576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float adjustmentFactor = 1; 577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Average bits per frame (units of kbits) 579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return static_cast<int>(adjustmentFactor * bitRate / frameRate); 580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::EffectivePacketLoss(const VCMProtectionParameters* parameters) 584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Effective packet loss to encoder is based on RPL (residual packet loss) 586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this is a soft setting based on degree of FEC protection 587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // RPL = received/input packet loss - average_FEC_recovery 588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // note: received/input packet loss may be filtered based on FilteredLoss 589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The packet loss: 591dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t packetLoss = (uint8_t) (255 * parameters->lossPr); 592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float avgFecRecov = AvgRecoveryFEC(parameters); 594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Residual Packet Loss: 596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _residualPacketLossFec = (float) (packetLoss - avgFecRecov) / 255.0f; 597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Effective Packet Loss, NA in current version. 599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _effectivePacketLoss = 0; 600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 604b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 605b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMFecMethod::UpdateParameters(const VCMProtectionParameters* parameters) 606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 607b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the protection factor 608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ProtectionFactor(parameters); 609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the effective packet loss 611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org EffectivePacketLoss(parameters); 612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Compute the bit cost 614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ignore key frames for now. 615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float fecRate = static_cast<float> (_protectionFactorD) / 255.0f; 616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (fecRate >= 0.0f) 617b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // use this formula if the fecRate (protection factor) is defined 619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // relative to number of source packets 620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // this is the case for the previous tables: 621b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // _efficiency = parameters->bitRate * ( 1.0 - 1.0 / (1.0 + fecRate)); 622b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 623b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // in the new tables, the fecRate is defined relative to total number of 624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // packets (total rate), so overhead cost is: 625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _efficiency = parameters->bitRate * fecRate * _corrFecCost; 626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 627b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _efficiency = 0.0f; 630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 632b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Protection/fec rates obtained above is defined relative to total number 633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // of packets (total rate: source+fec) FEC in RTP module assumes protection 634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // factor is defined relative to source number of packets so we should 635b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // convert the factor to reduce mismatch between mediaOpt suggested rate and 636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the actual rate 637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorK = ConvertFECRate(_protectionFactorK); 638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _protectionFactorD = ConvertFECRate(_protectionFactorD); 639b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::VCMLossProtectionLogic(int64_t nowMs): 643b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_selectedMethod(NULL), 644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_currentParameters(), 645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_rtt(0), 646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_lossPr(0.0f), 647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_bitRate(0.0f), 648b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_frameRate(0.0f), 649b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_keyFrameSize(0.0f), 650b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_fecRateKey(0), 651b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_fecRateDelta(0), 652b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_lastPrUpdateT(0), 653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_lossPr255(0.9999f), 654b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_lossPrHistory(), 655b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_shortMaxLossPr255(0), 656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_packetsPerFrame(0.9999f), 657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_packetsPerFrameKey(0.9999f), 658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_residualPacketLossFec(0), 659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_codecWidth(0), 660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_codecHeight(0), 661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org_numLayers(1) 662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Reset(nowMs); 664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::~VCMLossProtectionLogic() 667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 668b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Release(); 669b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 670b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 671b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 672b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::SetMethod(enum VCMProtectionMethodEnum newMethodType) 673b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 674b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_selectedMethod != NULL) 675b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 676b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_selectedMethod->Type() == newMethodType) 677b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 678b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Nothing to update 679b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 680b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 681b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // New method - delete existing one 682b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _selectedMethod; 683b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 684b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VCMProtectionMethod *newMethod = NULL; 685b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (newMethodType) 686b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 687b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kNack: 688b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 689b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newMethod = new VCMNackMethod(); 690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 691b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 692b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kFec: 693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 694b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newMethod = new VCMFecMethod(); 695b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kNackFec: 698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Default to always having NACK enabled for the hybrid mode. 700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org newMethod = new VCMNackFecMethod(kLowRttNackMs, -1); 701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 709b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _selectedMethod = newMethod; 711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 712b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 713b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 714b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::RemoveMethod(enum VCMProtectionMethodEnum method) 715b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 716b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_selectedMethod == NULL) 717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (_selectedMethod->Type() == method) 721b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 722b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _selectedMethod; 723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _selectedMethod = NULL; 724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfloat 729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::RequiredBitRate() const 730b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org float RequiredBitRate = 0.0f; 732b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_selectedMethod != NULL) 733b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 734b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RequiredBitRate = _selectedMethod->RequiredBitRate(); 735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 736b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return RequiredBitRate; 737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 740dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMLossProtectionLogic::UpdateRtt(uint32_t rtt) 741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 742b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _rtt = rtt; 743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdateResidualPacketLoss(float residualPacketLoss) 747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _residualPacketLossFec = residualPacketLoss; 749b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 752dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMLossProtectionLogic::UpdateMaxLossHistory(uint8_t lossPr255, 753dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org int64_t now) 754b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lossPrHistory[0].timeMs >= 0 && 756b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org now - _lossPrHistory[0].timeMs < kLossPrShortFilterWinMs) 757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 758b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (lossPr255 > _shortMaxLossPr255) 759b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 760b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _shortMaxLossPr255 = lossPr255; 761b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 762b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 763b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 764b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 765b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Only add a new value to the history once a second 766b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lossPrHistory[0].timeMs == -1) 767b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 768b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // First, no shift 769b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _shortMaxLossPr255 = lossPr255; 770b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 771b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 772b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 773b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Shift 774dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org for (int32_t i = (kLossPrHistorySize - 2); i >= 0; i--) 775b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 776b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[i + 1].lossPr255 = _lossPrHistory[i].lossPr255; 777b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[i + 1].timeMs = _lossPrHistory[i].timeMs; 778b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 780b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_shortMaxLossPr255 == 0) 781b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _shortMaxLossPr255 = lossPr255; 783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 784b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 785b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[0].lossPr255 = _shortMaxLossPr255; 786b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[0].timeMs = now; 787b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _shortMaxLossPr255 = 0; 788b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 789b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 790b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 791dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orguint8_t 792dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMLossProtectionLogic::MaxFilteredLossPr(int64_t nowMs) const 793b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 794dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t maxFound = _shortMaxLossPr255; 795b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lossPrHistory[0].timeMs == -1) 796b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 797b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return maxFound; 798b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 799dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org for (int32_t i = 0; i < kLossPrHistorySize; i++) 800b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 801b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lossPrHistory[i].timeMs == -1) 802b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 803b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 804b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 805b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (nowMs - _lossPrHistory[i].timeMs > 806b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org kLossPrHistorySize * kLossPrShortFilterWinMs) 807b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 808b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This sample (and all samples after this) is too old 809b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 810b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 811b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_lossPrHistory[i].lossPr255 > maxFound) 812b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 813b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This sample is the largest one this far into the history 814b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maxFound = _lossPrHistory[i].lossPr255; 815b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 816b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 817b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return maxFound; 818b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 819b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 820dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orguint8_t VCMLossProtectionLogic::FilteredLoss( 821b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int64_t nowMs, 822b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FilterPacketLossMode filter_mode, 823dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t lossPr255) { 824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update the max window filter. 826b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org UpdateMaxLossHistory(lossPr255, nowMs); 827b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 828b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update the recursive average filter. 829b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPr255.Apply(static_cast<float> (nowMs - _lastPrUpdateT), 830b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<float> (lossPr255)); 831b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPrUpdateT = nowMs; 832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Filtered loss: default is received loss (no filtering). 834dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint8_t filtered_loss = lossPr255; 835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 836b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (filter_mode) { 837b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kNoFilter: 838b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 839b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kAvgFilter: 84031b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org filtered_loss = static_cast<uint8_t>(_lossPr255.filtered() + 0.5); 841b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 842b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case kMaxFilter: 843b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org filtered_loss = MaxFilteredLossPr(nowMs); 844b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; 845b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 846b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 847b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return filtered_loss; 848b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 849b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 850b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 851dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMLossProtectionLogic::UpdateFilteredLossPr(uint8_t packetLossEnc) 852b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 853b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPr = (float) packetLossEnc / (float) 255.0; 854b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 855b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 856b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 857b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdateBitRate(float bitRate) 858b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 859b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _bitRate = bitRate; 860b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 861b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 862b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 863b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdatePacketsPerFrame(float nPackets, int64_t nowMs) 864b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 865b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _packetsPerFrame.Apply(static_cast<float>(nowMs - _lastPacketPerFrameUpdateT), 866b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org nPackets); 867b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPacketPerFrameUpdateT = nowMs; 868b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 869b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 870b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 871b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdatePacketsPerFrameKey(float nPackets, int64_t nowMs) 872b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 873b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _packetsPerFrameKey.Apply(static_cast<float>(nowMs - 874b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPacketPerFrameUpdateTKey), nPackets); 875b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPacketPerFrameUpdateTKey = nowMs; 876b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 877b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 878b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 879b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdateKeyFrameSize(float keyFrameSize) 880b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 881b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _keyFrameSize = keyFrameSize; 882b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 883b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 884b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 885dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.orgVCMLossProtectionLogic::UpdateFrameSize(uint16_t width, 886dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org uint16_t height) 887b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 888b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _codecWidth = width; 889b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _codecHeight = height; 890b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 891b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 892b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid VCMLossProtectionLogic::UpdateNumLayers(int numLayers) { 893b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _numLayers = (numLayers == 0) ? 1 : numLayers; 894b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 895b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 896b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool 897b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::UpdateMethod() 898b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 899b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_selectedMethod == NULL) 900b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 901b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 902b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.rtt = _rtt; 904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.lossPr = _lossPr; 905b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.bitRate = _bitRate; 906b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.frameRate = _frameRate; // rename actual frame rate? 907b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.keyFrameSize = _keyFrameSize; 908b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.fecRateDelta = _fecRateDelta; 909b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.fecRateKey = _fecRateKey; 91031b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org _currentParameters.packetsPerFrame = _packetsPerFrame.filtered(); 91131b38da0e2ba9778d241267f0cf1ba8dd2f36e83minyue@webrtc.org _currentParameters.packetsPerFrameKey = _packetsPerFrameKey.filtered(); 912b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.residualPacketLossFec = _residualPacketLossFec; 913b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.codecWidth = _codecWidth; 914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.codecHeight = _codecHeight; 915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentParameters.numLayers = _numLayers; 916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _selectedMethod->UpdateParameters(&_currentParameters); 917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethod* 920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::SelectedMethod() const 921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _selectedMethod; 923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMProtectionMethodEnum 926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::SelectedType() const 927b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 928b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _selectedMethod->Type(); 929b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 930b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 931b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 932b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::Reset(int64_t nowMs) 933b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 934b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPrUpdateT = nowMs; 935b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPacketPerFrameUpdateT = nowMs; 936b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lastPacketPerFrameUpdateTKey = nowMs; 937b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPr255.Reset(0.9999f); 938b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _packetsPerFrame.Reset(0.9999f); 939b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _fecRateDelta = _fecRateKey = 0; 940dba5f4541529da6ce75cc634834a9197e610731bpbos@webrtc.org for (int32_t i = 0; i < kLossPrHistorySize; i++) 941b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 942b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[i].lossPr255 = 0; 943b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _lossPrHistory[i].timeMs = -1; 944b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 945b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _shortMaxLossPr255 = 0; 946b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Release(); 947b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 948b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 949b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid 950b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVCMLossProtectionLogic::Release() 951b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _selectedMethod; 953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _selectedMethod = NULL; 954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 956bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org} // namespace media_optimization 957bb78b2c7ce8cc4445811d0e881890a29b14a4f2bstefan@webrtc.org} // namespace webrtc 958