blob: f204b01c7ca215f29f4ae80df6c6e1cebbef6963 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/video_coding/fec_controller_default.h" // NOLINT
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stdlib.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Ying Wang68b2df72018-10-22 16:50:43 +020015#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <string>
Ying Wang68b2df72018-10-22 16:50:43 +020017
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "modules/include/module_fec_types.h"
Ying Wang68b2df72018-10-22 16:50:43 +020019#include "rtc_base/logging.h"
20#include "system_wrappers/include/field_trial.h"
Per69b332d2016-06-02 15:45:42 +020021
22namespace webrtc {
Ying Wang68b2df72018-10-22 16:50:43 +020023
24const float kProtectionOverheadRateThreshold = 0.5;
25
Ying Wang3b790f32018-01-19 17:58:57 +010026FecControllerDefault::FecControllerDefault(
Per69b332d2016-06-02 15:45:42 +020027 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())),
Ying Wang68b2df72018-10-22 16:50:43 +020033 max_payload_size_(1460),
34 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Per69b332d2016-06-02 15:45:42 +020035
Ying Wang3b790f32018-01-19 17:58:57 +010036FecControllerDefault::FecControllerDefault(Clock* clock)
37 : clock_(clock),
38 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
39 clock_->TimeInMilliseconds())),
Ying Wang68b2df72018-10-22 16:50:43 +020040 max_payload_size_(1460),
41 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Ying Wang3b790f32018-01-19 17:58:57 +010042
43FecControllerDefault::~FecControllerDefault(void) {
Per69b332d2016-06-02 15:45:42 +020044 loss_prot_logic_->Release();
45}
46
Ying Wang3b790f32018-01-19 17:58:57 +010047void FecControllerDefault::SetProtectionCallback(
48 VCMProtectionCallback* protection_callback) {
49 protection_callback_ = protection_callback;
50}
51
52void FecControllerDefault::SetEncodingData(size_t width,
53 size_t height,
54 size_t num_temporal_layers,
55 size_t max_payload_size) {
Markus Handell6deec382020-07-07 12:17:12 +020056 MutexLock lock(&mutex_);
Per69b332d2016-06-02 15:45:42 +020057 loss_prot_logic_->UpdateFrameSize(width, height);
58 loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
59 max_payload_size_ = max_payload_size;
60}
61
Ying Wang68b2df72018-10-22 16:50:43 +020062float 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) {
Harald Alvestrandef5b21e2021-11-27 21:31:08 +000073 RTC_LOG(LS_WARNING)
74 << "ProtectionOverheadRateThreshold field trial is set to "
75 "an invalid value, expecting a value between (0, 1].";
Ying Wang68b2df72018-10-22 16:50:43 +020076 }
77 // WebRTC-ProtectionOverheadRateThreshold field trial string is not found, use
78 // the default value.
79 return kProtectionOverheadRateThreshold;
80}
81
Ying Wang3b790f32018-01-19 17:58:57 +010082uint32_t FecControllerDefault::UpdateFecRates(
Per69b332d2016-06-02 15:45:42 +020083 uint32_t estimated_bitrate_bps,
84 int actual_framerate_fps,
85 uint8_t fraction_lost,
Ying Wang3b790f32018-01-19 17:58:57 +010086 std::vector<bool> loss_mask_vector,
Per69b332d2016-06-02 15:45:42 +020087 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 }
Per69b332d2016-06-02 15:45:42 +020094 FecProtectionParams delta_fec_params;
95 FecProtectionParams key_fec_params;
96 {
Markus Handell6deec382020-07-07 12:17:12 +020097 MutexLock lock(&mutex_);
Per69b332d2016-06-02 15:45:42 +020098 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
99 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
Per69b332d2016-06-02 15:45:42 +0200100 // 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);
Per69b332d2016-06-02 15:45:42 +0200103 // 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);
Per69b332d2016-06-02 15:45:42 +0200111 // For now use the filtered loss for computing the robustness settings.
112 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
Per69b332d2016-06-02 15:45:42 +0200113 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
114 return estimated_bitrate_bps;
115 }
Per69b332d2016-06-02 15:45:42 +0200116 // 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();
Per69b332d2016-06-02 15:45:42 +0200120 // Get the bit cost of protection method, based on the amount of
121 // overhead data actually transmitted (including headers) the last
122 // second.
Per69b332d2016-06-02 15:45:42 +0200123 // 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();
Per69b332d2016-06-02 15:45:42 +0200126 // 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();
Artem Titovdcd7fc72021-08-09 13:02:57 +0200129 // The RTP module currently requires the same `max_fec_frames` for both
Per69b332d2016-06-02 15:45:42 +0200130 // 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 }
Artem Titovdcd7fc72021-08-09 13:02:57 +0200136 // Set the FEC packet mask type. `kFecMaskBursty` is more effective for
Per69b332d2016-06-02 15:45:42 +0200137 // 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
Artem Titovdcd7fc72021-08-09 13:02:57 +0200139 // re-ordering, we keep default setting to `kFecMaskRandom` for now.
Per69b332d2016-06-02 15:45:42 +0200140 delta_fec_params.fec_mask_type = kFecMaskRandom;
141 key_fec_params.fec_mask_type = kFecMaskRandom;
Per69b332d2016-06-02 15:45:42 +0200142 // 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;
Per69b332d2016-06-02 15:45:42 +0200148 // 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);
Per69b332d2016-06-02 15:45:42 +0200152 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 }
Ying Wang68b2df72018-10-22 16:50:43 +0200161 // Cap the overhead estimate to a threshold, default is 50%.
162 protection_overhead_rate =
163 std::min(protection_overhead_rate, overhead_threshold_);
Per69b332d2016-06-02 15:45:42 +0200164 // Source coding rate: total rate - protection overhead.
165 return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
166}
Elad Alonf91353e2019-06-05 11:20:36 +0200167
Ying Wang3b790f32018-01-19 17:58:57 +0100168void FecControllerDefault::SetProtectionMethod(bool enable_fec,
169 bool enable_nack) {
Per69b332d2016-06-02 15:45:42 +0200170 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 }
Markus Handell6deec382020-07-07 12:17:12 +0200178 MutexLock lock(&mutex_);
Per69b332d2016-06-02 15:45:42 +0200179 loss_prot_logic_->SetMethod(method);
180}
Elad Alonf91353e2019-06-05 11:20:36 +0200181
Ying Wang3b790f32018-01-19 17:58:57 +0100182void FecControllerDefault::UpdateWithEncodedData(
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100183 const size_t encoded_image_length,
Niels Möller87e2d782019-03-07 10:18:23 +0100184 const VideoFrameType encoded_image_frametype) {
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100185 const size_t encoded_length = encoded_image_length;
Markus Handell6deec382020-07-07 12:17:12 +0200186 MutexLock lock(&mutex_);
Per69b332d2016-06-02 15:45:42 +0200187 if (encoded_length > 0) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100188 const bool delta_frame =
189 encoded_image_frametype != VideoFrameType::kVideoFrameKey;
Per69b332d2016-06-02 15:45:42 +0200190 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}
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200206
207bool FecControllerDefault::UseLossVectorMask() {
208 return false;
209}
210
Per69b332d2016-06-02 15:45:42 +0200211} // namespace webrtc