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