blob: 38fd0760fcffe986d7f39f62e8b454450aa4976e [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
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <stdlib.h>
Ying Wang68b2df72018-10-22 16:50:43 +020012#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string>
Ying Wang68b2df72018-10-22 16:50:43 +020014
Yves Gerey3e707812018-11-28 16:47:49 +010015#include "modules/include/module_fec_types.h"
Ying Wang68b2df72018-10-22 16:50:43 +020016#include "modules/video_coding/fec_controller_default.h" // NOLINT
17#include "rtc_base/logging.h"
18#include "system_wrappers/include/field_trial.h"
Per69b332d2016-06-02 15:45:42 +020019
20namespace webrtc {
Per69b332d2016-06-02 15:45:42 +020021using rtc::CritScope;
Ying Wang68b2df72018-10-22 16:50:43 +020022
23const float kProtectionOverheadRateThreshold = 0.5;
24
Ying Wang3b790f32018-01-19 17:58:57 +010025FecControllerDefault::FecControllerDefault(
Per69b332d2016-06-02 15:45:42 +020026 Clock* clock,
27 VCMProtectionCallback* protection_callback)
28 : clock_(clock),
29 protection_callback_(protection_callback),
30 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
31 clock_->TimeInMilliseconds())),
Ying Wang68b2df72018-10-22 16:50:43 +020032 max_payload_size_(1460),
33 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Per69b332d2016-06-02 15:45:42 +020034
Ying Wang3b790f32018-01-19 17:58:57 +010035FecControllerDefault::FecControllerDefault(Clock* clock)
36 : clock_(clock),
37 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
38 clock_->TimeInMilliseconds())),
Ying Wang68b2df72018-10-22 16:50:43 +020039 max_payload_size_(1460),
40 overhead_threshold_(GetProtectionOverheadRateThreshold()) {}
Ying Wang3b790f32018-01-19 17:58:57 +010041
42FecControllerDefault::~FecControllerDefault(void) {
Per69b332d2016-06-02 15:45:42 +020043 loss_prot_logic_->Release();
44}
45
Ying Wang3b790f32018-01-19 17:58:57 +010046void FecControllerDefault::SetProtectionCallback(
47 VCMProtectionCallback* protection_callback) {
48 protection_callback_ = protection_callback;
49}
50
51void FecControllerDefault::SetEncodingData(size_t width,
52 size_t height,
53 size_t num_temporal_layers,
54 size_t max_payload_size) {
Per69b332d2016-06-02 15:45:42 +020055 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020056 loss_prot_logic_->UpdateFrameSize(width, height);
57 loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
58 max_payload_size_ = max_payload_size;
59}
60
Ying Wang68b2df72018-10-22 16:50:43 +020061float FecControllerDefault::GetProtectionOverheadRateThreshold() {
62 float overhead_threshold =
63 strtof(webrtc::field_trial::FindFullName(
64 "WebRTC-ProtectionOverheadRateThreshold")
65 .c_str(),
66 nullptr);
67 if (overhead_threshold > 0 && overhead_threshold <= 1) {
68 RTC_LOG(LS_INFO) << "ProtectionOverheadRateThreshold is set to "
69 << overhead_threshold;
70 return overhead_threshold;
71 } else if (overhead_threshold < 0 || overhead_threshold > 1) {
72 RTC_LOG(WARNING) << "ProtectionOverheadRateThreshold field trial is set to "
73 "an invalid value, expecting a value between (0, 1].";
74 }
75 // WebRTC-ProtectionOverheadRateThreshold field trial string is not found, use
76 // the default value.
77 return kProtectionOverheadRateThreshold;
78}
79
Ying Wang3b790f32018-01-19 17:58:57 +010080uint32_t FecControllerDefault::UpdateFecRates(
Per69b332d2016-06-02 15:45:42 +020081 uint32_t estimated_bitrate_bps,
82 int actual_framerate_fps,
83 uint8_t fraction_lost,
Ying Wang3b790f32018-01-19 17:58:57 +010084 std::vector<bool> loss_mask_vector,
Per69b332d2016-06-02 15:45:42 +020085 int64_t round_trip_time_ms) {
86 float target_bitrate_kbps =
87 static_cast<float>(estimated_bitrate_bps) / 1000.0f;
88 // Sanity check.
89 if (actual_framerate_fps < 1.0) {
90 actual_framerate_fps = 1.0;
91 }
Per69b332d2016-06-02 15:45:42 +020092 FecProtectionParams delta_fec_params;
93 FecProtectionParams key_fec_params;
94 {
95 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020096 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
97 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
Per69b332d2016-06-02 15:45:42 +020098 // Update frame rate for the loss protection logic class: frame rate should
99 // be the actual/sent rate.
100 loss_prot_logic_->UpdateFrameRate(actual_framerate_fps);
Per69b332d2016-06-02 15:45:42 +0200101 // Returns the filtered packet loss, used for the protection setting.
102 // The filtered loss may be the received loss (no filter), or some
103 // filtered value (average or max window filter).
104 // Use max window filter for now.
105 media_optimization::FilterPacketLossMode filter_mode =
106 media_optimization::kMaxFilter;
107 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
108 clock_->TimeInMilliseconds(), filter_mode, fraction_lost);
Per69b332d2016-06-02 15:45:42 +0200109 // For now use the filtered loss for computing the robustness settings.
110 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
Per69b332d2016-06-02 15:45:42 +0200111 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
112 return estimated_bitrate_bps;
113 }
Per69b332d2016-06-02 15:45:42 +0200114 // Update method will compute the robustness settings for the given
115 // protection method and the overhead cost
116 // the protection method is set by the user via SetVideoProtection.
117 loss_prot_logic_->UpdateMethod();
Per69b332d2016-06-02 15:45:42 +0200118 // Get the bit cost of protection method, based on the amount of
119 // overhead data actually transmitted (including headers) the last
120 // second.
Per69b332d2016-06-02 15:45:42 +0200121 // Get the FEC code rate for Key frames (set to 0 when NA).
122 key_fec_params.fec_rate =
123 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK();
Per69b332d2016-06-02 15:45:42 +0200124 // Get the FEC code rate for Delta frames (set to 0 when NA).
125 delta_fec_params.fec_rate =
126 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD();
Per69b332d2016-06-02 15:45:42 +0200127 // The RTP module currently requires the same |max_fec_frames| for both
128 // key and delta frames.
129 delta_fec_params.max_fec_frames =
130 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
131 key_fec_params.max_fec_frames =
132 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
133 }
Per69b332d2016-06-02 15:45:42 +0200134 // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
135 // consecutive losses and little/no packet re-ordering. As we currently
136 // do not have feedback data on the degree of correlated losses and packet
137 // re-ordering, we keep default setting to |kFecMaskRandom| for now.
138 delta_fec_params.fec_mask_type = kFecMaskRandom;
139 key_fec_params.fec_mask_type = kFecMaskRandom;
Per69b332d2016-06-02 15:45:42 +0200140 // Update protection callback with protection settings.
141 uint32_t sent_video_rate_bps = 0;
142 uint32_t sent_nack_rate_bps = 0;
143 uint32_t sent_fec_rate_bps = 0;
144 // Rate cost of the protection methods.
145 float protection_overhead_rate = 0.0f;
Per69b332d2016-06-02 15:45:42 +0200146 // TODO(Marco): Pass FEC protection values per layer.
147 protection_callback_->ProtectionRequest(
148 &delta_fec_params, &key_fec_params, &sent_video_rate_bps,
149 &sent_nack_rate_bps, &sent_fec_rate_bps);
Per69b332d2016-06-02 15:45:42 +0200150 uint32_t sent_total_rate_bps =
151 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
152 // Estimate the overhead costs of the next second as staying the same
153 // wrt the source bitrate.
154 if (sent_total_rate_bps > 0) {
155 protection_overhead_rate =
156 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
157 sent_total_rate_bps;
158 }
Ying Wang68b2df72018-10-22 16:50:43 +0200159 // Cap the overhead estimate to a threshold, default is 50%.
160 protection_overhead_rate =
161 std::min(protection_overhead_rate, overhead_threshold_);
Per69b332d2016-06-02 15:45:42 +0200162 // Source coding rate: total rate - protection overhead.
163 return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
164}
Ying Wang3b790f32018-01-19 17:58:57 +0100165void FecControllerDefault::SetProtectionMethod(bool enable_fec,
166 bool enable_nack) {
Per69b332d2016-06-02 15:45:42 +0200167 media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone);
168 if (enable_fec && enable_nack) {
169 method = media_optimization::kNackFec;
170 } else if (enable_nack) {
171 method = media_optimization::kNack;
172 } else if (enable_fec) {
173 method = media_optimization::kFec;
174 }
175 CritScope lock(&crit_sect_);
176 loss_prot_logic_->SetMethod(method);
177}
Ying Wang3b790f32018-01-19 17:58:57 +0100178void FecControllerDefault::UpdateWithEncodedData(
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100179 const size_t encoded_image_length,
Niels Möller87e2d782019-03-07 10:18:23 +0100180 const VideoFrameType encoded_image_frametype) {
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100181 const size_t encoded_length = encoded_image_length;
Per69b332d2016-06-02 15:45:42 +0200182 CritScope lock(&crit_sect_);
183 if (encoded_length > 0) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100184 const bool delta_frame =
185 encoded_image_frametype != VideoFrameType::kVideoFrameKey;
Per69b332d2016-06-02 15:45:42 +0200186 if (max_payload_size_ > 0 && encoded_length > 0) {
187 const float min_packets_per_frame =
188 encoded_length / static_cast<float>(max_payload_size_);
189 if (delta_frame) {
190 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
191 clock_->TimeInMilliseconds());
192 } else {
193 loss_prot_logic_->UpdatePacketsPerFrameKey(
194 min_packets_per_frame, clock_->TimeInMilliseconds());
195 }
196 }
197 if (!delta_frame && encoded_length > 0) {
198 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
199 }
200 }
201}
Mirko Bonadei8fdcac32018-08-28 16:30:18 +0200202
203bool FecControllerDefault::UseLossVectorMask() {
204 return false;
205}
206
Per69b332d2016-06-02 15:45:42 +0200207} // namespace webrtc