OLD | NEW |
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 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 send_codec_type_(kVideoCodecUnknown), | 81 send_codec_type_(kVideoCodecUnknown), |
82 codec_width_(0), | 82 codec_width_(0), |
83 codec_height_(0), | 83 codec_height_(0), |
84 user_frame_rate_(0), | 84 user_frame_rate_(0), |
85 frame_dropper_(new FrameDropper), | 85 frame_dropper_(new FrameDropper), |
86 loss_prot_logic_( | 86 loss_prot_logic_( |
87 new VCMLossProtectionLogic(clock_->TimeInMilliseconds())), | 87 new VCMLossProtectionLogic(clock_->TimeInMilliseconds())), |
88 fraction_lost_(0), | 88 fraction_lost_(0), |
89 send_statistics_zero_encode_(0), | 89 send_statistics_zero_encode_(0), |
90 max_payload_size_(1460), | 90 max_payload_size_(1460), |
91 target_bit_rate_(0), | 91 video_target_bitrate_(0), |
92 incoming_frame_rate_(0), | 92 incoming_frame_rate_(0), |
93 enable_qm_(false), | 93 enable_qm_(false), |
94 encoded_frame_samples_(), | 94 encoded_frame_samples_(), |
95 avg_sent_bit_rate_bps_(0), | 95 avg_sent_bit_rate_bps_(0), |
96 avg_sent_framerate_(0), | 96 avg_sent_framerate_(0), |
97 key_frame_cnt_(0), | 97 key_frame_cnt_(0), |
98 delta_frame_cnt_(0), | 98 delta_frame_cnt_(0), |
99 content_(new VCMContentMetricsProcessing()), | 99 content_(new VCMContentMetricsProcessing()), |
100 qm_resolution_(new VCMQmResolution()), | 100 qm_resolution_(new VCMQmResolution()), |
101 last_qm_update_time_(0), | 101 last_qm_update_time_(0), |
(...skipping 18 matching lines...) Expand all Loading... |
120 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | 120 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
121 incoming_frame_rate_ = 0.0; | 121 incoming_frame_rate_ = 0.0; |
122 frame_dropper_->Reset(); | 122 frame_dropper_->Reset(); |
123 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); | 123 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
124 frame_dropper_->SetRates(0, 0); | 124 frame_dropper_->SetRates(0, 0); |
125 content_->Reset(); | 125 content_->Reset(); |
126 qm_resolution_->Reset(); | 126 qm_resolution_->Reset(); |
127 loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_); | 127 loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_); |
128 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); | 128 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
129 send_statistics_zero_encode_ = 0; | 129 send_statistics_zero_encode_ = 0; |
130 target_bit_rate_ = 0; | 130 video_target_bitrate_ = 0; |
131 codec_width_ = 0; | 131 codec_width_ = 0; |
132 codec_height_ = 0; | 132 codec_height_ = 0; |
133 user_frame_rate_ = 0; | 133 user_frame_rate_ = 0; |
134 key_frame_cnt_ = 0; | 134 key_frame_cnt_ = 0; |
135 delta_frame_cnt_ = 0; | 135 delta_frame_cnt_ = 0; |
136 last_qm_update_time_ = 0; | 136 last_qm_update_time_ = 0; |
137 last_change_time_ = 0; | 137 last_change_time_ = 0; |
138 encoded_frame_samples_.clear(); | 138 encoded_frame_samples_.clear(); |
139 avg_sent_bit_rate_bps_ = 0; | 139 avg_sent_bit_rate_bps_ = 0; |
140 num_layers_ = 1; | 140 num_layers_ = 1; |
(...skipping 29 matching lines...) Expand all Loading... |
170 // Everything codec specific should be reset here since this means the codec | 170 // Everything codec specific should be reset here since this means the codec |
171 // has changed. If native dimension values have changed, then either user | 171 // has changed. If native dimension values have changed, then either user |
172 // initiated change, or QM initiated change. Will be able to determine only | 172 // initiated change, or QM initiated change. Will be able to determine only |
173 // after the processing of the first frame. | 173 // after the processing of the first frame. |
174 last_change_time_ = clock_->TimeInMilliseconds(); | 174 last_change_time_ = clock_->TimeInMilliseconds(); |
175 content_->Reset(); | 175 content_->Reset(); |
176 content_->UpdateFrameRate(frame_rate); | 176 content_->UpdateFrameRate(frame_rate); |
177 | 177 |
178 max_bit_rate_ = max_bit_rate; | 178 max_bit_rate_ = max_bit_rate; |
179 send_codec_type_ = send_codec_type; | 179 send_codec_type_ = send_codec_type; |
180 target_bit_rate_ = target_bitrate; | 180 video_target_bitrate_ = target_bitrate; |
181 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; | 181 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
182 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); | 182 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
183 loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate)); | 183 loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate)); |
184 loss_prot_logic_->UpdateFrameSize(width, height); | 184 loss_prot_logic_->UpdateFrameSize(width, height); |
185 loss_prot_logic_->UpdateNumLayers(num_layers); | 185 loss_prot_logic_->UpdateNumLayers(num_layers); |
186 frame_dropper_->Reset(); | 186 frame_dropper_->Reset(); |
187 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); | 187 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); |
188 user_frame_rate_ = static_cast<float>(frame_rate); | 188 user_frame_rate_ = static_cast<float>(frame_rate); |
189 codec_width_ = width; | 189 codec_width_ = width; |
190 codec_height_ = height; | 190 codec_height_ = height; |
191 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. | 191 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. |
192 max_payload_size_ = mtu; | 192 max_payload_size_ = mtu; |
193 qm_resolution_->Initialize(target_bitrate_kbps, | 193 qm_resolution_->Initialize(target_bitrate_kbps, |
194 user_frame_rate_, | 194 user_frame_rate_, |
195 codec_width_, | 195 codec_width_, |
196 codec_height_, | 196 codec_height_, |
197 num_layers_); | 197 num_layers_); |
198 } | 198 } |
199 | 199 |
200 uint32_t MediaOptimization::SetTargetRates( | 200 uint32_t MediaOptimization::SetTargetRates( |
201 uint32_t target_bitrate, | 201 uint32_t target_bitrate, |
202 uint8_t fraction_lost, | 202 uint8_t fraction_lost, |
203 int64_t round_trip_time_ms, | 203 int64_t round_trip_time_ms, |
204 VCMProtectionCallback* protection_callback, | 204 VCMProtectionCallback* protection_callback, |
205 VCMQMSettingsCallback* qmsettings_callback) { | 205 VCMQMSettingsCallback* qmsettings_callback) { |
206 CriticalSectionScoped lock(crit_sect_.get()); | 206 CriticalSectionScoped lock(crit_sect_.get()); |
207 // TODO(holmer): Consider putting this threshold only on the video bitrate, | |
208 // and not on protection. | |
209 if (max_bit_rate_ > 0 && | |
210 target_bitrate > static_cast<uint32_t>(max_bit_rate_)) { | |
211 target_bitrate = max_bit_rate_; | |
212 } | |
213 VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod(); | 207 VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod(); |
214 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; | 208 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
215 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); | 209 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
216 loss_prot_logic_->UpdateRtt(round_trip_time_ms); | 210 loss_prot_logic_->UpdateRtt(round_trip_time_ms); |
217 | 211 |
218 // Get frame rate for encoder: this is the actual/sent frame rate. | 212 // Get frame rate for encoder: this is the actual/sent frame rate. |
219 float actual_frame_rate = SentFrameRateInternal(); | 213 float actual_frame_rate = SentFrameRateInternal(); |
220 | 214 |
221 // Sanity check. | 215 // Sanity check. |
222 if (actual_frame_rate < 1.0) { | 216 if (actual_frame_rate < 1.0) { |
(...skipping 11 matching lines...) Expand all Loading... |
234 // filtered value (average or max window filter). | 228 // filtered value (average or max window filter). |
235 // Use max window filter for now. | 229 // Use max window filter for now. |
236 FilterPacketLossMode filter_mode = kMaxFilter; | 230 FilterPacketLossMode filter_mode = kMaxFilter; |
237 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( | 231 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( |
238 clock_->TimeInMilliseconds(), filter_mode, fraction_lost); | 232 clock_->TimeInMilliseconds(), filter_mode, fraction_lost); |
239 | 233 |
240 // For now use the filtered loss for computing the robustness settings. | 234 // For now use the filtered loss for computing the robustness settings. |
241 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); | 235 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); |
242 | 236 |
243 // Rate cost of the protection methods. | 237 // Rate cost of the protection methods. |
244 uint32_t protection_overhead_bps = 0; | 238 float protection_overhead_rate = 0.0f; |
245 | 239 |
246 // Update protection settings, when applicable. | 240 // Update protection settings, when applicable. |
247 float sent_video_rate_kbps = 0.0f; | 241 float sent_video_rate_kbps = 0.0f; |
248 if (loss_prot_logic_->SelectedType() != kNone) { | 242 if (loss_prot_logic_->SelectedType() != kNone) { |
249 // Update protection method with content metrics. | 243 // Update protection method with content metrics. |
250 selected_method->UpdateContentMetrics(content_->ShortTermAvgData()); | 244 selected_method->UpdateContentMetrics(content_->ShortTermAvgData()); |
251 | 245 |
252 // Update method will compute the robustness settings for the given | 246 // Update method will compute the robustness settings for the given |
253 // protection method and the overhead cost | 247 // protection method and the overhead cost |
254 // the protection method is set by the user via SetVideoProtection. | 248 // the protection method is set by the user via SetVideoProtection. |
(...skipping 11 matching lines...) Expand all Loading... |
266 &sent_video_rate_bps, | 260 &sent_video_rate_bps, |
267 &sent_nack_rate_bps, | 261 &sent_nack_rate_bps, |
268 &sent_fec_rate_bps, | 262 &sent_fec_rate_bps, |
269 protection_callback); | 263 protection_callback); |
270 } | 264 } |
271 uint32_t sent_total_rate_bps = | 265 uint32_t sent_total_rate_bps = |
272 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps; | 266 sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps; |
273 // Estimate the overhead costs of the next second as staying the same | 267 // Estimate the overhead costs of the next second as staying the same |
274 // wrt the source bitrate. | 268 // wrt the source bitrate. |
275 if (sent_total_rate_bps > 0) { | 269 if (sent_total_rate_bps > 0) { |
276 protection_overhead_bps = static_cast<uint32_t>( | 270 protection_overhead_rate = |
277 target_bitrate * | 271 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) / |
278 static_cast<double>(sent_nack_rate_bps + sent_fec_rate_bps) / | 272 sent_total_rate_bps; |
279 sent_total_rate_bps + | |
280 0.5); | |
281 } | 273 } |
282 // Cap the overhead estimate to 50%. | 274 // Cap the overhead estimate to 50%. |
283 if (protection_overhead_bps > target_bitrate / 2) | 275 if (protection_overhead_rate > 0.5) |
284 protection_overhead_bps = target_bitrate / 2; | 276 protection_overhead_rate = 0.5; |
285 | 277 |
286 // Get the effective packet loss for encoder ER when applicable. Should be | 278 // Get the effective packet loss for encoder ER when applicable. Should be |
287 // passed to encoder via fraction_lost. | 279 // passed to encoder via fraction_lost. |
288 packet_loss_enc = selected_method->RequiredPacketLossER(); | 280 packet_loss_enc = selected_method->RequiredPacketLossER(); |
289 sent_video_rate_kbps = static_cast<float>(sent_video_rate_bps) / 1000.0f; | 281 sent_video_rate_kbps = static_cast<float>(sent_video_rate_bps) / 1000.0f; |
290 } | 282 } |
291 | 283 |
292 // Source coding rate: total rate - protection overhead. | 284 // Source coding rate: total rate - protection overhead. |
293 target_bit_rate_ = target_bitrate - protection_overhead_bps; | 285 video_target_bitrate_ = target_bitrate * (1.0 - protection_overhead_rate); |
| 286 |
| 287 // Cap target video bitrate to codec maximum. |
| 288 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { |
| 289 video_target_bitrate_ = max_bit_rate_; |
| 290 } |
294 | 291 |
295 // Update encoding rates following protection settings. | 292 // Update encoding rates following protection settings. |
296 float target_video_bitrate_kbps = | 293 float target_video_bitrate_kbps = |
297 static_cast<float>(target_bit_rate_) / 1000.0f; | 294 static_cast<float>(video_target_bitrate_) / 1000.0f; |
298 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); | 295 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); |
299 | 296 |
300 if (enable_qm_ && qmsettings_callback) { | 297 if (enable_qm_ && qmsettings_callback) { |
301 // Update QM with rates. | 298 // Update QM with rates. |
302 qm_resolution_->UpdateRates(target_video_bitrate_kbps, | 299 qm_resolution_->UpdateRates(target_video_bitrate_kbps, |
303 sent_video_rate_kbps, | 300 sent_video_rate_kbps, |
304 incoming_frame_rate_, | 301 incoming_frame_rate_, |
305 fraction_lost_); | 302 fraction_lost_); |
306 // Check for QM selection. | 303 // Check for QM selection. |
307 bool select_qm = CheckStatusForQMchange(); | 304 bool select_qm = CheckStatusForQMchange(); |
308 if (select_qm) { | 305 if (select_qm) { |
309 SelectQuality(qmsettings_callback); | 306 SelectQuality(qmsettings_callback); |
310 } | 307 } |
311 // Reset the short-term averaged content data. | 308 // Reset the short-term averaged content data. |
312 content_->ResetShortTermAvgData(); | 309 content_->ResetShortTermAvgData(); |
313 } | 310 } |
314 | 311 |
315 CheckSuspendConditions(); | 312 CheckSuspendConditions(); |
316 | 313 |
317 return target_bit_rate_; | 314 return video_target_bitrate_; |
318 } | 315 } |
319 | 316 |
320 void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { | 317 void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { |
321 CriticalSectionScoped lock(crit_sect_.get()); | 318 CriticalSectionScoped lock(crit_sect_.get()); |
322 loss_prot_logic_->SetMethod(method); | 319 loss_prot_logic_->SetMethod(method); |
323 } | 320 } |
324 | 321 |
325 uint32_t MediaOptimization::InputFrameRate() { | 322 uint32_t MediaOptimization::InputFrameRate() { |
326 CriticalSectionScoped lock(crit_sect_.get()); | 323 CriticalSectionScoped lock(crit_sect_.get()); |
327 return InputFrameRateInternal(); | 324 return InputFrameRateInternal(); |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 const int64_t diff = | 618 const int64_t diff = |
622 incoming_frame_times_[0] - incoming_frame_times_[num - 1]; | 619 incoming_frame_times_[0] - incoming_frame_times_[num - 1]; |
623 incoming_frame_rate_ = 0.0; // No frame rate estimate available. | 620 incoming_frame_rate_ = 0.0; // No frame rate estimate available. |
624 if (diff > 0) { | 621 if (diff > 0) { |
625 incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff); | 622 incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff); |
626 } | 623 } |
627 } | 624 } |
628 } | 625 } |
629 | 626 |
630 void MediaOptimization::CheckSuspendConditions() { | 627 void MediaOptimization::CheckSuspendConditions() { |
631 // Check conditions for SuspendBelowMinBitrate. |target_bit_rate_| is in bps. | 628 // Check conditions for SuspendBelowMinBitrate. |video_target_bitrate_| is in |
| 629 // bps. |
632 if (suspension_enabled_) { | 630 if (suspension_enabled_) { |
633 if (!video_suspended_) { | 631 if (!video_suspended_) { |
634 // Check if we just went below the threshold. | 632 // Check if we just went below the threshold. |
635 if (target_bit_rate_ < suspension_threshold_bps_) { | 633 if (video_target_bitrate_ < suspension_threshold_bps_) { |
636 video_suspended_ = true; | 634 video_suspended_ = true; |
637 } | 635 } |
638 } else { | 636 } else { |
639 // Video is already suspended. Check if we just went over the threshold | 637 // Video is already suspended. Check if we just went over the threshold |
640 // with a margin. | 638 // with a margin. |
641 if (target_bit_rate_ > | 639 if (video_target_bitrate_ > |
642 suspension_threshold_bps_ + suspension_window_bps_) { | 640 suspension_threshold_bps_ + suspension_window_bps_) { |
643 video_suspended_ = false; | 641 video_suspended_ = false; |
644 } | 642 } |
645 } | 643 } |
646 } | 644 } |
647 } | 645 } |
648 | 646 |
649 } // namespace media_optimization | 647 } // namespace media_optimization |
650 } // namespace webrtc | 648 } // namespace webrtc |
OLD | NEW |