blob: 84e8a7bfcc5ec36963ccd1eef92a9ef34be4dba7 [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 Wang3b790f32018-01-19 17:58:57 +010011#include "modules/video_coding/fec_controller_default.h"
Per69b332d2016-06-02 15:45:42 +020012
13namespace webrtc {
Per69b332d2016-06-02 15:45:42 +020014using rtc::CritScope;
Ying Wang3b790f32018-01-19 17:58:57 +010015FecControllerDefault::FecControllerDefault(
Per69b332d2016-06-02 15:45:42 +020016 Clock* clock,
17 VCMProtectionCallback* protection_callback)
18 : clock_(clock),
19 protection_callback_(protection_callback),
20 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
21 clock_->TimeInMilliseconds())),
22 max_payload_size_(1460) {}
23
Ying Wang3b790f32018-01-19 17:58:57 +010024FecControllerDefault::FecControllerDefault(Clock* clock)
25 : clock_(clock),
26 loss_prot_logic_(new media_optimization::VCMLossProtectionLogic(
27 clock_->TimeInMilliseconds())),
28 max_payload_size_(1460) {}
29
30FecControllerDefault::~FecControllerDefault(void) {
Per69b332d2016-06-02 15:45:42 +020031 loss_prot_logic_->Release();
32}
33
Ying Wang3b790f32018-01-19 17:58:57 +010034void FecControllerDefault::SetProtectionCallback(
35 VCMProtectionCallback* protection_callback) {
36 protection_callback_ = protection_callback;
37}
38
39void FecControllerDefault::SetEncodingData(size_t width,
40 size_t height,
41 size_t num_temporal_layers,
42 size_t max_payload_size) {
Per69b332d2016-06-02 15:45:42 +020043 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020044 loss_prot_logic_->UpdateFrameSize(width, height);
45 loss_prot_logic_->UpdateNumLayers(num_temporal_layers);
46 max_payload_size_ = max_payload_size;
47}
48
Ying Wang3b790f32018-01-19 17:58:57 +010049uint32_t FecControllerDefault::UpdateFecRates(
Per69b332d2016-06-02 15:45:42 +020050 uint32_t estimated_bitrate_bps,
51 int actual_framerate_fps,
52 uint8_t fraction_lost,
Ying Wang3b790f32018-01-19 17:58:57 +010053 std::vector<bool> loss_mask_vector,
Per69b332d2016-06-02 15:45:42 +020054 int64_t round_trip_time_ms) {
55 float target_bitrate_kbps =
56 static_cast<float>(estimated_bitrate_bps) / 1000.0f;
57 // Sanity check.
58 if (actual_framerate_fps < 1.0) {
59 actual_framerate_fps = 1.0;
60 }
Per69b332d2016-06-02 15:45:42 +020061 FecProtectionParams delta_fec_params;
62 FecProtectionParams key_fec_params;
63 {
64 CritScope lock(&crit_sect_);
Per69b332d2016-06-02 15:45:42 +020065 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
66 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
Per69b332d2016-06-02 15:45:42 +020067 // Update frame rate for the loss protection logic class: frame rate should
68 // be the actual/sent rate.
69 loss_prot_logic_->UpdateFrameRate(actual_framerate_fps);
Per69b332d2016-06-02 15:45:42 +020070 // Returns the filtered packet loss, used for the protection setting.
71 // The filtered loss may be the received loss (no filter), or some
72 // filtered value (average or max window filter).
73 // Use max window filter for now.
74 media_optimization::FilterPacketLossMode filter_mode =
75 media_optimization::kMaxFilter;
76 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
77 clock_->TimeInMilliseconds(), filter_mode, fraction_lost);
Per69b332d2016-06-02 15:45:42 +020078 // For now use the filtered loss for computing the robustness settings.
79 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
Per69b332d2016-06-02 15:45:42 +020080 if (loss_prot_logic_->SelectedType() == media_optimization::kNone) {
81 return estimated_bitrate_bps;
82 }
Per69b332d2016-06-02 15:45:42 +020083 // Update method will compute the robustness settings for the given
84 // protection method and the overhead cost
85 // the protection method is set by the user via SetVideoProtection.
86 loss_prot_logic_->UpdateMethod();
Per69b332d2016-06-02 15:45:42 +020087 // Get the bit cost of protection method, based on the amount of
88 // overhead data actually transmitted (including headers) the last
89 // second.
Per69b332d2016-06-02 15:45:42 +020090 // Get the FEC code rate for Key frames (set to 0 when NA).
91 key_fec_params.fec_rate =
92 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK();
Per69b332d2016-06-02 15:45:42 +020093 // Get the FEC code rate for Delta frames (set to 0 when NA).
94 delta_fec_params.fec_rate =
95 loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD();
Per69b332d2016-06-02 15:45:42 +020096 // The RTP module currently requires the same |max_fec_frames| for both
97 // key and delta frames.
98 delta_fec_params.max_fec_frames =
99 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
100 key_fec_params.max_fec_frames =
101 loss_prot_logic_->SelectedMethod()->MaxFramesFec();
102 }
Per69b332d2016-06-02 15:45:42 +0200103 // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
104 // consecutive losses and little/no packet re-ordering. As we currently
105 // do not have feedback data on the degree of correlated losses and packet
106 // re-ordering, we keep default setting to |kFecMaskRandom| for now.
107 delta_fec_params.fec_mask_type = kFecMaskRandom;
108 key_fec_params.fec_mask_type = kFecMaskRandom;
Per69b332d2016-06-02 15:45:42 +0200109 // Update protection callback with protection settings.
110 uint32_t sent_video_rate_bps = 0;
111 uint32_t sent_nack_rate_bps = 0;
112 uint32_t sent_fec_rate_bps = 0;
113 // Rate cost of the protection methods.
114 float protection_overhead_rate = 0.0f;
Per69b332d2016-06-02 15:45:42 +0200115 // TODO(Marco): Pass FEC protection values per layer.
116 protection_callback_->ProtectionRequest(
117 &delta_fec_params, &key_fec_params, &sent_video_rate_bps,
118 &sent_nack_rate_bps, &sent_fec_rate_bps);
Per69b332d2016-06-02 15:45:42 +0200119 uint32_t sent_total_rate_bps =
120 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
121 // Estimate the overhead costs of the next second as staying the same
122 // wrt the source bitrate.
123 if (sent_total_rate_bps > 0) {
124 protection_overhead_rate =
125 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
126 sent_total_rate_bps;
127 }
128 // Cap the overhead estimate to 50%.
129 if (protection_overhead_rate > 0.5)
130 protection_overhead_rate = 0.5;
Per69b332d2016-06-02 15:45:42 +0200131 // Source coding rate: total rate - protection overhead.
132 return estimated_bitrate_bps * (1.0 - protection_overhead_rate);
133}
Ying Wang3b790f32018-01-19 17:58:57 +0100134void FecControllerDefault::SetProtectionMethod(bool enable_fec,
135 bool enable_nack) {
Per69b332d2016-06-02 15:45:42 +0200136 media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone);
137 if (enable_fec && enable_nack) {
138 method = media_optimization::kNackFec;
139 } else if (enable_nack) {
140 method = media_optimization::kNack;
141 } else if (enable_fec) {
142 method = media_optimization::kFec;
143 }
144 CritScope lock(&crit_sect_);
145 loss_prot_logic_->SetMethod(method);
146}
Ying Wang3b790f32018-01-19 17:58:57 +0100147void FecControllerDefault::UpdateWithEncodedData(
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100148 const size_t encoded_image_length,
149 const FrameType encoded_image_frametype) {
150 const size_t encoded_length = encoded_image_length;
Per69b332d2016-06-02 15:45:42 +0200151 CritScope lock(&crit_sect_);
152 if (encoded_length > 0) {
Ying Wang0dd1b0a2018-02-20 12:50:27 +0100153 const bool delta_frame = encoded_image_frametype != kVideoFrameKey;
Per69b332d2016-06-02 15:45:42 +0200154 if (max_payload_size_ > 0 && encoded_length > 0) {
155 const float min_packets_per_frame =
156 encoded_length / static_cast<float>(max_payload_size_);
157 if (delta_frame) {
158 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
159 clock_->TimeInMilliseconds());
160 } else {
161 loss_prot_logic_->UpdatePacketsPerFrameKey(
162 min_packets_per_frame, clock_->TimeInMilliseconds());
163 }
164 }
165 if (!delta_frame && encoded_length > 0) {
166 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
167 }
168 }
169}
Per69b332d2016-06-02 15:45:42 +0200170} // namespace webrtc