Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: webrtc/modules/video_coding/media_optimization.cc

Issue 1972083002: Move logic for calculating needed bitrate overhead used by NACK and FEC to VideoSender. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressed Åsas comments. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/media_optimization.h" 11 #include "webrtc/modules/video_coding/media_optimization.h"
12 12
13 #include "webrtc/base/logging.h" 13 #include "webrtc/base/logging.h"
14 #include "webrtc/modules/video_coding/utility/frame_dropper.h" 14 #include "webrtc/modules/video_coding/utility/frame_dropper.h"
15 #include "webrtc/system_wrappers/include/clock.h" 15 #include "webrtc/system_wrappers/include/clock.h"
16 16
17 namespace webrtc { 17 namespace webrtc {
18 namespace media_optimization { 18 namespace media_optimization {
19 namespace {
20 void UpdateProtectionCallback(
21 VCMProtectionMethod* selected_method,
22 uint32_t* video_rate_bps,
23 uint32_t* nack_overhead_rate_bps,
24 uint32_t* fec_overhead_rate_bps,
25 VCMProtectionCallback* video_protection_callback) {
26 FecProtectionParams delta_fec_params;
27 FecProtectionParams key_fec_params;
28 // Get the FEC code rate for Key frames (set to 0 when NA).
29 key_fec_params.fec_rate = selected_method->RequiredProtectionFactorK();
30
31 // Get the FEC code rate for Delta frames (set to 0 when NA).
32 delta_fec_params.fec_rate = selected_method->RequiredProtectionFactorD();
33
34 // The RTP module currently requires the same |max_fec_frames| for both
35 // key and delta frames.
36 delta_fec_params.max_fec_frames = selected_method->MaxFramesFec();
37 key_fec_params.max_fec_frames = selected_method->MaxFramesFec();
38
39 // Set the FEC packet mask type. |kFecMaskBursty| is more effective for
40 // consecutive losses and little/no packet re-ordering. As we currently
41 // do not have feedback data on the degree of correlated losses and packet
42 // re-ordering, we keep default setting to |kFecMaskRandom| for now.
43 delta_fec_params.fec_mask_type = kFecMaskRandom;
44 key_fec_params.fec_mask_type = kFecMaskRandom;
45
46 // TODO(Marco): Pass FEC protection values per layer.
47 video_protection_callback->ProtectionRequest(
48 &delta_fec_params, &key_fec_params, video_rate_bps,
49 nack_overhead_rate_bps, fec_overhead_rate_bps);
50 }
51 } // namespace
52 19
53 struct MediaOptimization::EncodedFrameSample { 20 struct MediaOptimization::EncodedFrameSample {
54 EncodedFrameSample(size_t size_bytes, 21 EncodedFrameSample(size_t size_bytes,
55 uint32_t timestamp, 22 uint32_t timestamp,
56 int64_t time_complete_ms) 23 int64_t time_complete_ms)
57 : size_bytes(size_bytes), 24 : size_bytes(size_bytes),
58 timestamp(timestamp), 25 timestamp(timestamp),
59 time_complete_ms(time_complete_ms) {} 26 time_complete_ms(time_complete_ms) {}
60 27
61 size_t size_bytes; 28 size_t size_bytes;
62 uint32_t timestamp; 29 uint32_t timestamp;
63 int64_t time_complete_ms; 30 int64_t time_complete_ms;
64 }; 31 };
65 32
66 MediaOptimization::MediaOptimization(Clock* clock) 33 MediaOptimization::MediaOptimization(Clock* clock)
67 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), 34 : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
68 clock_(clock), 35 clock_(clock),
69 max_bit_rate_(0), 36 max_bit_rate_(0),
70 send_codec_type_(kVideoCodecUnknown),
71 codec_width_(0), 37 codec_width_(0),
72 codec_height_(0), 38 codec_height_(0),
73 user_frame_rate_(0), 39 user_frame_rate_(0),
74 frame_dropper_(new FrameDropper), 40 frame_dropper_(new FrameDropper),
75 loss_prot_logic_(
76 new VCMLossProtectionLogic(clock_->TimeInMilliseconds())),
77 fraction_lost_(0), 41 fraction_lost_(0),
78 send_statistics_zero_encode_(0), 42 send_statistics_zero_encode_(0),
79 max_payload_size_(1460), 43 max_payload_size_(1460),
80 video_target_bitrate_(0), 44 video_target_bitrate_(0),
81 incoming_frame_rate_(0), 45 incoming_frame_rate_(0),
82 encoded_frame_samples_(), 46 encoded_frame_samples_(),
83 avg_sent_bit_rate_bps_(0), 47 avg_sent_bit_rate_bps_(0),
84 avg_sent_framerate_(0), 48 avg_sent_framerate_(0),
85 key_frame_cnt_(0),
86 delta_frame_cnt_(0),
87 num_layers_(0), 49 num_layers_(0),
88 suspension_enabled_(false), 50 suspension_enabled_(false),
89 video_suspended_(false), 51 video_suspended_(false),
90 suspension_threshold_bps_(0), 52 suspension_threshold_bps_(0),
91 suspension_window_bps_(0) { 53 suspension_window_bps_(0) {
92 memset(send_statistics_, 0, sizeof(send_statistics_)); 54 memset(send_statistics_, 0, sizeof(send_statistics_));
93 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); 55 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_));
94 } 56 }
95 57
96 MediaOptimization::~MediaOptimization(void) { 58 MediaOptimization::~MediaOptimization(void) {
97 loss_prot_logic_->Release();
98 } 59 }
99 60
100 void MediaOptimization::Reset() { 61 void MediaOptimization::Reset() {
101 CriticalSectionScoped lock(crit_sect_.get()); 62 CriticalSectionScoped lock(crit_sect_.get());
102 SetEncodingDataInternal(kVideoCodecUnknown, 0, 0, 0, 0, 0, 0, 63 SetEncodingDataInternal(0, 0, 0, 0, 0, 0, max_payload_size_);
103 max_payload_size_);
104 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); 64 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_));
105 incoming_frame_rate_ = 0.0; 65 incoming_frame_rate_ = 0.0;
106 frame_dropper_->Reset(); 66 frame_dropper_->Reset();
107 loss_prot_logic_->Reset(clock_->TimeInMilliseconds());
108 frame_dropper_->SetRates(0, 0); 67 frame_dropper_->SetRates(0, 0);
109 loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_);
110 loss_prot_logic_->Reset(clock_->TimeInMilliseconds());
111 send_statistics_zero_encode_ = 0; 68 send_statistics_zero_encode_ = 0;
112 video_target_bitrate_ = 0; 69 video_target_bitrate_ = 0;
113 codec_width_ = 0; 70 codec_width_ = 0;
114 codec_height_ = 0; 71 codec_height_ = 0;
115 user_frame_rate_ = 0; 72 user_frame_rate_ = 0;
116 key_frame_cnt_ = 0;
117 delta_frame_cnt_ = 0;
118 encoded_frame_samples_.clear(); 73 encoded_frame_samples_.clear();
119 avg_sent_bit_rate_bps_ = 0; 74 avg_sent_bit_rate_bps_ = 0;
120 num_layers_ = 1; 75 num_layers_ = 1;
121 } 76 }
122 77
123 void MediaOptimization::SetEncodingData(VideoCodecType send_codec_type, 78 void MediaOptimization::SetEncodingData(int32_t max_bit_rate,
124 int32_t max_bit_rate,
125 uint32_t target_bitrate, 79 uint32_t target_bitrate,
126 uint16_t width, 80 uint16_t width,
127 uint16_t height, 81 uint16_t height,
128 uint32_t frame_rate, 82 uint32_t frame_rate,
129 int num_layers, 83 int num_layers,
130 int32_t mtu) { 84 int32_t mtu) {
131 CriticalSectionScoped lock(crit_sect_.get()); 85 CriticalSectionScoped lock(crit_sect_.get());
132 SetEncodingDataInternal(send_codec_type, max_bit_rate, frame_rate, 86 SetEncodingDataInternal(max_bit_rate, frame_rate, target_bitrate, width,
133 target_bitrate, width, height, num_layers, mtu); 87 height, num_layers, mtu);
134 } 88 }
135 89
136 void MediaOptimization::SetEncodingDataInternal(VideoCodecType send_codec_type, 90 void MediaOptimization::SetEncodingDataInternal(int32_t max_bit_rate,
137 int32_t max_bit_rate,
138 uint32_t frame_rate, 91 uint32_t frame_rate,
139 uint32_t target_bitrate, 92 uint32_t target_bitrate,
140 uint16_t width, 93 uint16_t width,
141 uint16_t height, 94 uint16_t height,
142 int num_layers, 95 int num_layers,
143 int32_t mtu) { 96 int32_t mtu) {
144 // Everything codec specific should be reset here since this means the codec 97 // Everything codec specific should be reset here since this means the codec
145 // has changed. 98 // has changed.
146 99
147 max_bit_rate_ = max_bit_rate; 100 max_bit_rate_ = max_bit_rate;
148 send_codec_type_ = send_codec_type;
149 video_target_bitrate_ = target_bitrate; 101 video_target_bitrate_ = target_bitrate;
150 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; 102 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f;
151 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
152 loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate));
153 loss_prot_logic_->UpdateFrameSize(width, height);
154 loss_prot_logic_->UpdateNumLayers(num_layers);
155 frame_dropper_->Reset(); 103 frame_dropper_->Reset();
156 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); 104 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate));
157 user_frame_rate_ = static_cast<float>(frame_rate); 105 user_frame_rate_ = static_cast<float>(frame_rate);
158 codec_width_ = width; 106 codec_width_ = width;
159 codec_height_ = height; 107 codec_height_ = height;
160 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. 108 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero.
161 max_payload_size_ = mtu; 109 max_payload_size_ = mtu;
162 } 110 }
163 111
164 uint32_t MediaOptimization::SetTargetRates( 112 uint32_t MediaOptimization::SetTargetRates(uint32_t target_bitrate,
165 uint32_t target_bitrate, 113 uint8_t fraction_lost,
166 uint8_t fraction_lost, 114 int64_t round_trip_time_ms) {
167 int64_t round_trip_time_ms,
168 VCMProtectionCallback* protection_callback) {
169 CriticalSectionScoped lock(crit_sect_.get()); 115 CriticalSectionScoped lock(crit_sect_.get());
170 VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod();
171 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f;
172 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps);
173 loss_prot_logic_->UpdateRtt(round_trip_time_ms);
174 116
175 // Get frame rate for encoder: this is the actual/sent frame rate. 117 // Get frame rate for encoder: this is the actual/sent frame rate.
176 float actual_frame_rate = SentFrameRateInternal(); 118 float actual_frame_rate = SentFrameRateInternal();
177 119
178 // Sanity check. 120 // Sanity check.
179 if (actual_frame_rate < 1.0) { 121 if (actual_frame_rate < 1.0) {
180 actual_frame_rate = 1.0; 122 actual_frame_rate = 1.0;
181 } 123 }
182 124
183 // Update frame rate for the loss protection logic class: frame rate should
184 // be the actual/sent rate.
185 loss_prot_logic_->UpdateFrameRate(actual_frame_rate);
186
187 fraction_lost_ = fraction_lost; 125 fraction_lost_ = fraction_lost;
188 126
189 // Returns the filtered packet loss, used for the protection setting. 127 video_target_bitrate_ = target_bitrate;
190 // The filtered loss may be the received loss (no filter), or some
191 // filtered value (average or max window filter).
192 // Use max window filter for now.
193 FilterPacketLossMode filter_mode = kMaxFilter;
194 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss(
195 clock_->TimeInMilliseconds(), filter_mode, fraction_lost);
196
197 // For now use the filtered loss for computing the robustness settings.
198 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc);
199
200 // Rate cost of the protection methods.
201 float protection_overhead_rate = 0.0f;
202
203 // Update protection settings, when applicable.
204 if (loss_prot_logic_->SelectedType() != kNone) {
205 // Update method will compute the robustness settings for the given
206 // protection method and the overhead cost
207 // the protection method is set by the user via SetVideoProtection.
208 loss_prot_logic_->UpdateMethod();
209
210 // Update protection callback with protection settings.
211 uint32_t sent_video_rate_bps = 0;
212 uint32_t sent_nack_rate_bps = 0;
213 uint32_t sent_fec_rate_bps = 0;
214 // Get the bit cost of protection method, based on the amount of
215 // overhead data actually transmitted (including headers) the last
216 // second.
217 if (protection_callback) {
218 UpdateProtectionCallback(selected_method, &sent_video_rate_bps,
219 &sent_nack_rate_bps, &sent_fec_rate_bps,
220 protection_callback);
221 }
222 uint32_t sent_total_rate_bps =
223 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps;
224 // Estimate the overhead costs of the next second as staying the same
225 // wrt the source bitrate.
226 if (sent_total_rate_bps > 0) {
227 protection_overhead_rate =
228 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) /
229 sent_total_rate_bps;
230 }
231 // Cap the overhead estimate to 50%.
232 if (protection_overhead_rate > 0.5)
233 protection_overhead_rate = 0.5;
234
235 // Get the effective packet loss for encoder ER when applicable. Should be
236 // passed to encoder via fraction_lost.
237 packet_loss_enc = selected_method->RequiredPacketLossER();
238 }
239
240 // Source coding rate: total rate - protection overhead.
241 video_target_bitrate_ = target_bitrate * (1.0 - protection_overhead_rate);
242 128
243 // Cap target video bitrate to codec maximum. 129 // Cap target video bitrate to codec maximum.
244 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { 130 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) {
245 video_target_bitrate_ = max_bit_rate_; 131 video_target_bitrate_ = max_bit_rate_;
246 } 132 }
247 133
248 // Update encoding rates following protection settings. 134 // Update encoding rates following protection settings.
249 float target_video_bitrate_kbps = 135 float target_video_bitrate_kbps =
250 static_cast<float>(video_target_bitrate_) / 1000.0f; 136 static_cast<float>(video_target_bitrate_) / 1000.0f;
251 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); 137 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_);
252 138
253 CheckSuspendConditions(); 139 CheckSuspendConditions();
254 140
255 return video_target_bitrate_; 141 return video_target_bitrate_;
256 } 142 }
257 143
258 void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) {
259 CriticalSectionScoped lock(crit_sect_.get());
260 loss_prot_logic_->SetMethod(method);
261 }
262
263 uint32_t MediaOptimization::InputFrameRate() { 144 uint32_t MediaOptimization::InputFrameRate() {
264 CriticalSectionScoped lock(crit_sect_.get()); 145 CriticalSectionScoped lock(crit_sect_.get());
265 return InputFrameRateInternal(); 146 return InputFrameRateInternal();
266 } 147 }
267 148
268 uint32_t MediaOptimization::InputFrameRateInternal() { 149 uint32_t MediaOptimization::InputFrameRateInternal() {
269 ProcessIncomingFrameRate(clock_->TimeInMilliseconds()); 150 ProcessIncomingFrameRate(clock_->TimeInMilliseconds());
270 return uint32_t(incoming_frame_rate_ + 0.5f); 151 return uint32_t(incoming_frame_rate_ + 0.5f);
271 } 152 }
272 153
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 encoded_frame_samples_.back().size_bytes += encoded_length; 185 encoded_frame_samples_.back().size_bytes += encoded_length;
305 encoded_frame_samples_.back().time_complete_ms = now_ms; 186 encoded_frame_samples_.back().time_complete_ms = now_ms;
306 } else { 187 } else {
307 encoded_frame_samples_.push_back( 188 encoded_frame_samples_.push_back(
308 EncodedFrameSample(encoded_length, timestamp, now_ms)); 189 EncodedFrameSample(encoded_length, timestamp, now_ms));
309 } 190 }
310 UpdateSentBitrate(now_ms); 191 UpdateSentBitrate(now_ms);
311 UpdateSentFramerate(); 192 UpdateSentFramerate();
312 if (encoded_length > 0) { 193 if (encoded_length > 0) {
313 const bool delta_frame = encoded_image._frameType != kVideoFrameKey; 194 const bool delta_frame = encoded_image._frameType != kVideoFrameKey;
314
315 frame_dropper_->Fill(encoded_length, delta_frame); 195 frame_dropper_->Fill(encoded_length, delta_frame);
316 if (max_payload_size_ > 0 && encoded_length > 0) {
317 const float min_packets_per_frame =
318 encoded_length / static_cast<float>(max_payload_size_);
319 if (delta_frame) {
320 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame,
321 clock_->TimeInMilliseconds());
322 } else {
323 loss_prot_logic_->UpdatePacketsPerFrameKey(
324 min_packets_per_frame, clock_->TimeInMilliseconds());
325 }
326 }
327 if (!delta_frame && encoded_length > 0) {
328 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length));
329 }
330
331 // Updating counters.
332 if (delta_frame) {
333 delta_frame_cnt_++;
334 } else {
335 key_frame_cnt_++;
336 }
337 } 196 }
338 197
339 return VCM_OK; 198 return VCM_OK;
340 } 199 }
341 200
342 void MediaOptimization::EnableFrameDropper(bool enable) { 201 void MediaOptimization::EnableFrameDropper(bool enable) {
343 CriticalSectionScoped lock(crit_sect_.get()); 202 CriticalSectionScoped lock(crit_sect_.get());
344 frame_dropper_->Enable(enable); 203 frame_dropper_->Enable(enable);
345 } 204 }
346 205
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (video_target_bitrate_ > 327 if (video_target_bitrate_ >
469 suspension_threshold_bps_ + suspension_window_bps_) { 328 suspension_threshold_bps_ + suspension_window_bps_) {
470 video_suspended_ = false; 329 video_suspended_ = false;
471 } 330 }
472 } 331 }
473 } 332 }
474 } 333 }
475 334
476 } // namespace media_optimization 335 } // namespace media_optimization
477 } // namespace webrtc 336 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/media_optimization.h ('k') | webrtc/modules/video_coding/media_optimization_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698