blob: 841ed742dac509e5772a02674044c3fbef474a8f [file] [log] [blame]
Per69b332d2016-06-02 15:45:42 +02001/*
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
Ying Wang68b2df72018-10-22 16:50:43 +020011#include <algorithm>
12
13#include "modules/video_coding/fec_controller_default.h" // NOLINT
14#include "rtc_base/logging.h"
15#include "system_wrappers/include/field_trial.h"
Per69b332d2016-06-02 15:45:42 +020016
17namespace webrtc {
Per69b332d2016-06-02 15:45:42 +020018using rtc::CritScope;
Ying Wang68b2df72018-10-22 16:50:43 +020019
20const float kProtectionOverheadRateThreshold = 0.5;
21
Ying Wang3b790f32018-01-19 17:58:57 +010022FecControllerDefault::FecControllerDefault(
Per69b332d2016-06-02 15:45:42 +020023 Clock* clock,
24 VCMProtectionCallback* protection_callback)
25 : clock_(clock),
26 protection_callback_(protection_callback),
27 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
28 clock_->TimeInMilliseconds())),
Ying Wang68b2df72018-10-22 16:50:43 +020029 max_payload_size_(1460),
30 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Per69b332d2016-06-02 15:45:42 +020031
Ying Wang3b790f32018-01-19 17:58:57 +010032FecControllerDefault::FecControllerDefault(Clock* clock)
33 : clock_(clock),
34 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
35 clock_->TimeInMilliseconds())),
Ying Wang68b2df72018-10-22 16:50:43 +020036 max_payload_size_(1460),
37 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Ying Wang3b790f32018-01-19 17:58:57 +010038
39FecControllerDefault::~FecControllerDefault(void) {
Per69b332d2016-06-02 15:45:42 +020040 loss_prot_logic_->Release();
41}
42
Ying Wang3b790f32018-01-19 17:58:57 +010043void FecControllerDefault::SetProtectionCallback(
44 VCMProtectionCallback* protection_callback) {
45 protection_callback_ = protection_callback;
46}
47
48void FecControllerDefault::SetEncodingData(size_t width,
49 size_t height,
50 size_t num_temporal_layers,
51 size_t max_payload_size) {
Per69b332d2016-06-02 15:45:42 +020052 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020053 loss_prot_logic_->UpdateFrameSize(width, height);
54 loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
55 max_payload_size_ = max_payload_size;
56}
57
Ying Wang68b2df72018-10-22 16:50:43 +020058float FecControllerDefault::GetProtectionOverheadRateThreshold() {
59 float overhead_threshold =
60 strtof(webrtc::field_trial::FindFullName(
61 "WebRTC-ProtectionOverheadRateThreshold")
62 .c_str(),
63 nullptr);
64 if (overhead_threshold > 0 && overhead_threshold <= 1) {
65 RTC_LOG(LS_INFO) << "ProtectionOverheadRateThreshold is set to "
66 << overhead_threshold;
67 return overhead_threshold;
68 } else if (overhead_threshold < 0 || overhead_threshold > 1) {
69 RTC_LOG(WARNING) << "ProtectionOverheadRateThreshold field trial is set to "
70 "an invalid value, expecting a value between (0, 1].";
71 }
72 // WebRTC-ProtectionOverheadRateThreshold field trial string is not found, use
73 // the default value.
74 return kProtectionOverheadRateThreshold;
75}
76
Ying Wang3b790f32018-01-19 17:58:57 +010077uint32_t FecControllerDefault::UpdateFecRates(
Per69b332d2016-06-02 15:45:42 +020078 uint32_t estimated_bitrate_bps,
79 int actual_framerate_fps,
80 uint8_t fraction_lost,
Ying Wang3b790f32018-01-19 17:58:57 +010081 std::vector<bool> loss_mask_vector,
Per69b332d2016-06-02 15:45:42 +020082 int64_t round_trip_time_ms) {
83 float target_bitrate_kbps =
84 static_cast<float>(estimated_bitrate_bps) / 1000.0f;
85 // Sanity check.
86 if (actual_framerate_fps < 1.0) {
87 actual_framerate_fps = 1.0;
88 }
Per69b332d2016-06-02 15:45:42 +020089 FecProtectionParams delta_fec_params;
90 FecProtectionParams key_fec_params;
91 {
92 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020093 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
94 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
Per69b332d2016-06-02 15:45:42 +020095 // Update frame rate for the loss protection logic class: frame rate should
96 // be the actual/sent rate.
97 loss_prot_logic_->UpdateFrameRate(actual_framerate_fps);
Per69b332d2016-06-02 15:45:42 +020098 // Returns the filtered packet loss, used for the protection setting.
99 // The filtered loss may be the received loss (no filter), or some
100 // filtered value (average or max window filter).
101 // Use max window filter for now.
102 media_optimization::FilterPacketLossMode filter_mode =
103 media_optimization::kMaxFilter;
104 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
105 clock_->TimeInMilliseconds(), filter_mode, fraction_lost);
Per69b332d2016-06-02 15:45:42 +0200106 // For now use the filtered loss for computing the robustness settings.
107 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
Per69b332d2016-06-02 15:45:42 +0200108 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
109 return estimated_bitrate_bps;
110 }
Per69b332d2016-06-02 15:45:42 +0200111 // Update method will compute the robustness settings for the given
112 // protection method and the overhead cost
113 // the protection method is set by the user via SetVideoProtection.
114 loss_prot_logic_->UpdateMethod();
Per69b332d2016-06-02 15:45:42 +0200115 // Get the bit cost of protection method, based on the amount of
116 // overhead data actually transmitted (including headers) the last
117 // second.
Per69b332d2016-06-02 15:45:42 +0200118 // Get the FEC code rate for Key frames (set to 0 when NA).
119 key_fec_params.fec_rate =
120 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK();
Per69b332d2016-06-02 15:45:42 +0200121 // Get the FEC code rate for Delta frames (set to 0 when NA).
122 delta_fec_params.fec_rate =
123 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD();
Per69b332d2016-06-02 15:45:42 +0200124 // The RTP module currently requires the same |max_fec_frames| for both
125 // key and delta frames.
126 delta_fec_params.max_fec_frames =
127 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
128 key_fec_params.max_fec_frames =
129 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
130 }
Per69b332d2016-06-02 15:45:42 +0200131 // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
132 // consecutive losses and little/no packet re-ordering. As we currently
133 // do not have feedback data on the degree of correlated losses and packet
134 // re-ordering, we keep default setting to |kFecMaskRandom| for now.
135 delta_fec_params.fec_mask_type = kFecMaskRandom;
136 key_fec_params.fec_mask_type = kFecMaskRandom;
Per69b332d2016-06-02 15:45:42 +0200137 // Update protection callback with protection settings.
138 uint32_t sent_video_rate_bps = 0;
139 uint32_t sent_nack_rate_bps = 0;
140 uint32_t sent_fec_rate_bps = 0;
141 // Rate cost of the protection methods.
142 float protection_overhead_rate = 0.0f;
Per69b332d2016-06-02 15:45:42 +0200143 // TODO(Marco): Pass FEC protection values per layer.
144 protection_callback_->ProtectionRequest(
145 &delta_fec_params, &key_fec_params, &sent_video_rate_bps,
146 &sent_nack_rate_bps, &sent_fec_rate_bps);
Per69b332d2016-06-02 15:45:42 +0200147 uint32_t sent_total_rate_bps =
148 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
149 // Estimate the overhead costs of the next second as staying the same
150 // wrt the source bitrate.
151 if (sent_total_rate_bps > 0) {
152 protection_overhead_rate =
153 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
154 sent_total_rate_bps;
155 }
Ying Wang68b2df72018-10-22 16:50:43 +0200156 // Cap the overhead estimate to a threshold, default is 50%.
157 protection_overhead_rate =
158 std::min(protection_overhead_rate, overhead_threshold_);
Per69b332d2016-06-02 15:45:42 +0200159 // Source coding rate: total rate - protection overhead.
160 return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
161}
Ying Wang3b790f32018-01-19 17:58:57 +0100162void FecControllerDefault::SetProtectionMethod(bool enable_fec,
163 bool enable_nack) {
Per69b332d2016-06-02 15:45:42 +0200164 media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone);
165 if (enable_fec && enable_nack) {
166 method = media_optimization::kNackFec;
167 } else if (enable_nack) {
168 method = media_optimization::kNack;
169 } else if (enable_fec) {
170 method = media_optimization::kFec;
171 }
172 CritScope lock(&crit_sect_);
173 loss_prot_logic_->SetMethod(method);
174}
Ying Wang3b790f32018-01-19 17:58:57 +0100175void FecControllerDefault::UpdateWithEncodedData(
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100176 const size_t encoded_image_length,
177 const FrameType encoded_image_frametype) {
178 const size_t encoded_length = encoded_image_length;
Per69b332d2016-06-02 15:45:42 +0200179 CritScope lock(&crit_sect_);
180 if (encoded_length > 0) {
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100181 const bool delta_frame = encoded_image_frametype != kVideoFrameKey;
Per69b332d2016-06-02 15:45:42 +0200182 if (max_payload_size_ > 0 && encoded_length > 0) {
183 const float min_packets_per_frame =
184 encoded_length / static_cast<float>(max_payload_size_);
185 if (delta_frame) {
186 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
187 clock_->TimeInMilliseconds());
188 } else {
189 loss_prot_logic_->UpdatePacketsPerFrameKey(
190 min_packets_per_frame, clock_->TimeInMilliseconds());
191 }
192 }
193 if (!delta_frame && encoded_length > 0) {
194 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
195 }
196 }
197}
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200198
199bool FecControllerDefault::UseLossVectorMask() {
200 return false;
201}
202
Per69b332d2016-06-02 15:45:42 +0200203} // namespace webrtc