fec_controller_default.cc (8566B)
1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/video_coding/fec_controller_default.h" // NOLINT 12 13 #include <algorithm> 14 #include <cstdint> 15 #include <cstdlib> 16 #include <string> 17 #include <vector> 18 19 #include "api/environment/environment.h" 20 #include "api/fec_controller.h" 21 #include "api/field_trials_view.h" 22 #include "api/video/video_frame_type.h" 23 #include "modules/include/module_fec_types.h" 24 #include "modules/video_coding/media_opt_util.h" 25 #include "rtc_base/logging.h" 26 #include "rtc_base/synchronization/mutex.h" 27 #include "system_wrappers/include/clock.h" 28 29 namespace webrtc { 30 31 const float kProtectionOverheadRateThreshold = 0.5; 32 33 FecControllerDefault::FecControllerDefault( 34 const Environment& env, 35 VCMProtectionCallback* protection_callback) 36 : env_(env), 37 protection_callback_(protection_callback), 38 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(env_)), 39 max_payload_size_(1460), 40 overhead_threshold_(GetProtectionOverheadRateThreshold()) {} 41 42 FecControllerDefault::FecControllerDefault(const Environment& env) 43 : FecControllerDefault(env, nullptr) {} 44 45 FecControllerDefault::~FecControllerDefault(void) { 46 loss_prot_logic_->Release(); 47 } 48 49 void FecControllerDefault::SetProtectionCallback( 50 VCMProtectionCallback* protection_callback) { 51 protection_callback_ = protection_callback; 52 } 53 54 void FecControllerDefault::SetEncodingData(size_t width, 55 size_t height, 56 size_t num_temporal_layers, 57 size_t max_payload_size) { 58 MutexLock lock(&mutex_); 59 loss_prot_logic_->UpdateFrameSize(width, height); 60 loss_prot_logic_->UpdateNumLayers(num_temporal_layers); 61 max_payload_size_ = max_payload_size; 62 } 63 64 float FecControllerDefault::GetProtectionOverheadRateThreshold() { 65 float overhead_threshold = 66 strtof(env_.field_trials() 67 .Lookup("WebRTC-ProtectionOverheadRateThreshold") 68 .c_str(), 69 nullptr); 70 if (overhead_threshold > 0 && overhead_threshold <= 1) { 71 RTC_LOG(LS_INFO) << "ProtectionOverheadRateThreshold is set to " 72 << overhead_threshold; 73 return overhead_threshold; 74 } else if (overhead_threshold < 0 || overhead_threshold > 1) { 75 RTC_LOG(LS_WARNING) 76 << "ProtectionOverheadRateThreshold field trial is set to " 77 "an invalid value, expecting a value between (0, 1]."; 78 } 79 // WebRTC-ProtectionOverheadRateThreshold field trial string is not found, use 80 // the default value. 81 return kProtectionOverheadRateThreshold; 82 } 83 84 uint32_t FecControllerDefault::UpdateFecRates( 85 uint32_t estimated_bitrate_bps, 86 int actual_framerate_fps, 87 uint8_t fraction_lost, 88 std::vector<bool> /* loss_mask_vector */, 89 int64_t round_trip_time_ms) { 90 float target_bitrate_kbps = 91 static_cast<float>(estimated_bitrate_bps) / 1000.0f; 92 // Sanity check. 93 if (actual_framerate_fps < 1.0) { 94 actual_framerate_fps = 1.0; 95 } 96 FecProtectionParams delta_fec_params; 97 FecProtectionParams key_fec_params; 98 { 99 MutexLock lock(&mutex_); 100 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); 101 loss_prot_logic_->UpdateRtt(round_trip_time_ms); 102 // Update frame rate for the loss protection logic class: frame rate should 103 // be the actual/sent rate. 104 loss_prot_logic_->UpdateFrameRate(actual_framerate_fps); 105 // Returns the filtered packet loss, used for the protection setting. 106 // The filtered loss may be the received loss (no filter), or some 107 // filtered value (average or max window filter). 108 // Use max window filter for now. 109 media_optimization::FilterPacketLossMode filter_mode = 110 media_optimization::kMaxFilter; 111 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( 112 env_.clock().TimeInMilliseconds(), filter_mode, fraction_lost); 113 // For now use the filtered loss for computing the robustness settings. 114 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); 115 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) { 116 return estimated_bitrate_bps; 117 } 118 // Update method will compute the robustness settings for the given 119 // protection method and the overhead cost 120 // the protection method is set by the user via SetVideoProtection. 121 loss_prot_logic_->UpdateMethod(); 122 // Get the bit cost of protection method, based on the amount of 123 // overhead data actually transmitted (including headers) the last 124 // second. 125 // Get the FEC code rate for Key frames (set to 0 when NA). 126 key_fec_params.fec_rate = 127 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK(); 128 // Get the FEC code rate for Delta frames (set to 0 when NA). 129 delta_fec_params.fec_rate = 130 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD(); 131 // The RTP module currently requires the same `max_fec_frames` for both 132 // key and delta frames. 133 delta_fec_params.max_fec_frames = 134 loss_prot_logic_->SelectedMethod()->MaxFramesFec(); 135 key_fec_params.max_fec_frames = 136 loss_prot_logic_->SelectedMethod()->MaxFramesFec(); 137 } 138 // Set the FEC packet mask type. `kFecMaskBursty` is more effective for 139 // consecutive losses and little/no packet re-ordering. As we currently 140 // do not have feedback data on the degree of correlated losses and packet 141 // re-ordering, we keep default setting to `kFecMaskRandom` for now. 142 delta_fec_params.fec_mask_type = kFecMaskRandom; 143 key_fec_params.fec_mask_type = kFecMaskRandom; 144 // Update protection callback with protection settings. 145 uint32_t sent_video_rate_bps = 0; 146 uint32_t sent_nack_rate_bps = 0; 147 uint32_t sent_fec_rate_bps = 0; 148 // Rate cost of the protection methods. 149 float protection_overhead_rate = 0.0f; 150 // TODO(Marco): Pass FEC protection values per layer. 151 protection_callback_->ProtectionRequest( 152 &delta_fec_params, &key_fec_params, &sent_video_rate_bps, 153 &sent_nack_rate_bps, &sent_fec_rate_bps); 154 uint32_t sent_total_rate_bps = 155 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps; 156 // Estimate the overhead costs of the next second as staying the same 157 // wrt the source bitrate. 158 if (sent_total_rate_bps > 0) { 159 protection_overhead_rate = 160 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) / 161 sent_total_rate_bps; 162 } 163 // Cap the overhead estimate to a threshold, default is 50%. 164 protection_overhead_rate = 165 std::min(protection_overhead_rate, overhead_threshold_); 166 // Source coding rate: total rate - protection overhead. 167 return estimated_bitrate_bps * (1.0 - protection_overhead_rate); 168 } 169 170 void FecControllerDefault::SetProtectionMethod(bool enable_fec, 171 bool enable_nack) { 172 media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone); 173 if (enable_fec && enable_nack) { 174 method = media_optimization::kNackFec; 175 } else if (enable_nack) { 176 method = media_optimization::kNack; 177 } else if (enable_fec) { 178 method = media_optimization::kFec; 179 } 180 MutexLock lock(&mutex_); 181 loss_prot_logic_->SetMethod(method); 182 } 183 184 void FecControllerDefault::UpdateWithEncodedData( 185 const size_t encoded_image_length, 186 const VideoFrameType encoded_image_frametype) { 187 const size_t encoded_length = encoded_image_length; 188 MutexLock lock(&mutex_); 189 if (encoded_length > 0) { 190 const bool delta_frame = 191 encoded_image_frametype != VideoFrameType::kVideoFrameKey; 192 if (max_payload_size_ > 0 && encoded_length > 0) { 193 const float min_packets_per_frame = 194 encoded_length / static_cast<float>(max_payload_size_); 195 if (delta_frame) { 196 loss_prot_logic_->UpdatePacketsPerFrame( 197 min_packets_per_frame, env_.clock().TimeInMilliseconds()); 198 } else { 199 loss_prot_logic_->UpdatePacketsPerFrameKey( 200 min_packets_per_frame, env_.clock().TimeInMilliseconds()); 201 } 202 } 203 if (!delta_frame && encoded_length > 0) { 204 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length)); 205 } 206 } 207 } 208 209 bool FecControllerDefault::UseLossVectorMask() { 210 return false; 211 } 212 213 } // namespace webrtc