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 |
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/content_metrics_processing.h" | |
15 #include "webrtc/modules/video_coding/qm_select.h" | |
16 #include "webrtc/modules/video_coding/utility/frame_dropper.h" | 14 #include "webrtc/modules/video_coding/utility/frame_dropper.h" |
17 #include "webrtc/system_wrappers/include/clock.h" | 15 #include "webrtc/system_wrappers/include/clock.h" |
18 | 16 |
19 namespace webrtc { | 17 namespace webrtc { |
20 namespace media_optimization { | 18 namespace media_optimization { |
21 namespace { | 19 namespace { |
22 void UpdateProtectionCallback( | 20 void UpdateProtectionCallback( |
23 VCMProtectionMethod* selected_method, | 21 VCMProtectionMethod* selected_method, |
24 uint32_t* video_rate_bps, | 22 uint32_t* video_rate_bps, |
25 uint32_t* nack_overhead_rate_bps, | 23 uint32_t* nack_overhead_rate_bps, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 codec_height_(0), | 72 codec_height_(0), |
75 user_frame_rate_(0), | 73 user_frame_rate_(0), |
76 frame_dropper_(new FrameDropper), | 74 frame_dropper_(new FrameDropper), |
77 loss_prot_logic_( | 75 loss_prot_logic_( |
78 new VCMLossProtectionLogic(clock_->TimeInMilliseconds())), | 76 new VCMLossProtectionLogic(clock_->TimeInMilliseconds())), |
79 fraction_lost_(0), | 77 fraction_lost_(0), |
80 send_statistics_zero_encode_(0), | 78 send_statistics_zero_encode_(0), |
81 max_payload_size_(1460), | 79 max_payload_size_(1460), |
82 video_target_bitrate_(0), | 80 video_target_bitrate_(0), |
83 incoming_frame_rate_(0), | 81 incoming_frame_rate_(0), |
84 enable_qm_(false), | |
85 encoded_frame_samples_(), | 82 encoded_frame_samples_(), |
86 avg_sent_bit_rate_bps_(0), | 83 avg_sent_bit_rate_bps_(0), |
87 avg_sent_framerate_(0), | 84 avg_sent_framerate_(0), |
88 key_frame_cnt_(0), | 85 key_frame_cnt_(0), |
89 delta_frame_cnt_(0), | 86 delta_frame_cnt_(0), |
90 content_(new VCMContentMetricsProcessing()), | |
91 qm_resolution_(new VCMQmResolution()), | |
92 last_qm_update_time_(0), | |
93 last_change_time_(0), | |
94 num_layers_(0), | 87 num_layers_(0), |
95 suspension_enabled_(false), | 88 suspension_enabled_(false), |
96 video_suspended_(false), | 89 video_suspended_(false), |
97 suspension_threshold_bps_(0), | 90 suspension_threshold_bps_(0), |
98 suspension_window_bps_(0) { | 91 suspension_window_bps_(0) { |
99 memset(send_statistics_, 0, sizeof(send_statistics_)); | 92 memset(send_statistics_, 0, sizeof(send_statistics_)); |
100 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | 93 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
101 } | 94 } |
102 | 95 |
103 MediaOptimization::~MediaOptimization(void) { | 96 MediaOptimization::~MediaOptimization(void) { |
104 loss_prot_logic_->Release(); | 97 loss_prot_logic_->Release(); |
105 } | 98 } |
106 | 99 |
107 void MediaOptimization::Reset() { | 100 void MediaOptimization::Reset() { |
108 CriticalSectionScoped lock(crit_sect_.get()); | 101 CriticalSectionScoped lock(crit_sect_.get()); |
109 SetEncodingDataInternal(kVideoCodecUnknown, 0, 0, 0, 0, 0, 0, | 102 SetEncodingDataInternal(kVideoCodecUnknown, 0, 0, 0, 0, 0, 0, |
110 max_payload_size_); | 103 max_payload_size_); |
111 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | 104 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
112 incoming_frame_rate_ = 0.0; | 105 incoming_frame_rate_ = 0.0; |
113 frame_dropper_->Reset(); | 106 frame_dropper_->Reset(); |
114 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); | 107 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
115 frame_dropper_->SetRates(0, 0); | 108 frame_dropper_->SetRates(0, 0); |
116 content_->Reset(); | |
117 qm_resolution_->Reset(); | |
118 loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_); | 109 loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_); |
119 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); | 110 loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
120 send_statistics_zero_encode_ = 0; | 111 send_statistics_zero_encode_ = 0; |
121 video_target_bitrate_ = 0; | 112 video_target_bitrate_ = 0; |
122 codec_width_ = 0; | 113 codec_width_ = 0; |
123 codec_height_ = 0; | 114 codec_height_ = 0; |
124 user_frame_rate_ = 0; | 115 user_frame_rate_ = 0; |
125 key_frame_cnt_ = 0; | 116 key_frame_cnt_ = 0; |
126 delta_frame_cnt_ = 0; | 117 delta_frame_cnt_ = 0; |
127 last_qm_update_time_ = 0; | |
128 last_change_time_ = 0; | |
129 encoded_frame_samples_.clear(); | 118 encoded_frame_samples_.clear(); |
130 avg_sent_bit_rate_bps_ = 0; | 119 avg_sent_bit_rate_bps_ = 0; |
131 num_layers_ = 1; | 120 num_layers_ = 1; |
132 } | 121 } |
133 | 122 |
134 void MediaOptimization::SetEncodingData(VideoCodecType send_codec_type, | 123 void MediaOptimization::SetEncodingData(VideoCodecType send_codec_type, |
135 int32_t max_bit_rate, | 124 int32_t max_bit_rate, |
136 uint32_t target_bitrate, | 125 uint32_t target_bitrate, |
137 uint16_t width, | 126 uint16_t width, |
138 uint16_t height, | 127 uint16_t height, |
139 uint32_t frame_rate, | 128 uint32_t frame_rate, |
140 int num_layers, | 129 int num_layers, |
141 int32_t mtu) { | 130 int32_t mtu) { |
142 CriticalSectionScoped lock(crit_sect_.get()); | 131 CriticalSectionScoped lock(crit_sect_.get()); |
143 SetEncodingDataInternal(send_codec_type, max_bit_rate, frame_rate, | 132 SetEncodingDataInternal(send_codec_type, max_bit_rate, frame_rate, |
144 target_bitrate, width, height, num_layers, mtu); | 133 target_bitrate, width, height, num_layers, mtu); |
145 } | 134 } |
146 | 135 |
147 void MediaOptimization::SetEncodingDataInternal(VideoCodecType send_codec_type, | 136 void MediaOptimization::SetEncodingDataInternal(VideoCodecType send_codec_type, |
148 int32_t max_bit_rate, | 137 int32_t max_bit_rate, |
149 uint32_t frame_rate, | 138 uint32_t frame_rate, |
150 uint32_t target_bitrate, | 139 uint32_t target_bitrate, |
151 uint16_t width, | 140 uint16_t width, |
152 uint16_t height, | 141 uint16_t height, |
153 int num_layers, | 142 int num_layers, |
154 int32_t mtu) { | 143 int32_t mtu) { |
155 // Everything codec specific should be reset here since this means the codec | 144 // Everything codec specific should be reset here since this means the codec |
156 // has changed. If native dimension values have changed, then either user | 145 // has changed. |
157 // initiated change, or QM initiated change. Will be able to determine only | |
158 // after the processing of the first frame. | |
159 last_change_time_ = clock_->TimeInMilliseconds(); | |
160 content_->Reset(); | |
161 content_->UpdateFrameRate(frame_rate); | |
162 | 146 |
163 max_bit_rate_ = max_bit_rate; | 147 max_bit_rate_ = max_bit_rate; |
164 send_codec_type_ = send_codec_type; | 148 send_codec_type_ = send_codec_type; |
165 video_target_bitrate_ = target_bitrate; | 149 video_target_bitrate_ = target_bitrate; |
166 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; | 150 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
167 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); | 151 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
168 loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate)); | 152 loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate)); |
169 loss_prot_logic_->UpdateFrameSize(width, height); | 153 loss_prot_logic_->UpdateFrameSize(width, height); |
170 loss_prot_logic_->UpdateNumLayers(num_layers); | 154 loss_prot_logic_->UpdateNumLayers(num_layers); |
171 frame_dropper_->Reset(); | 155 frame_dropper_->Reset(); |
172 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); | 156 frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); |
173 user_frame_rate_ = static_cast<float>(frame_rate); | 157 user_frame_rate_ = static_cast<float>(frame_rate); |
174 codec_width_ = width; | 158 codec_width_ = width; |
175 codec_height_ = height; | 159 codec_height_ = height; |
176 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. | 160 num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. |
177 max_payload_size_ = mtu; | 161 max_payload_size_ = mtu; |
178 qm_resolution_->Initialize(target_bitrate_kbps, user_frame_rate_, | |
179 codec_width_, codec_height_, num_layers_); | |
180 } | 162 } |
181 | 163 |
182 uint32_t MediaOptimization::SetTargetRates( | 164 uint32_t MediaOptimization::SetTargetRates( |
183 uint32_t target_bitrate, | 165 uint32_t target_bitrate, |
184 uint8_t fraction_lost, | 166 uint8_t fraction_lost, |
185 int64_t round_trip_time_ms, | 167 int64_t round_trip_time_ms, |
186 VCMProtectionCallback* protection_callback, | 168 VCMProtectionCallback* protection_callback) { |
187 VCMQMSettingsCallback* qmsettings_callback) { | |
188 CriticalSectionScoped lock(crit_sect_.get()); | 169 CriticalSectionScoped lock(crit_sect_.get()); |
189 VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod(); | 170 VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod(); |
190 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; | 171 float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
191 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); | 172 loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
192 loss_prot_logic_->UpdateRtt(round_trip_time_ms); | 173 loss_prot_logic_->UpdateRtt(round_trip_time_ms); |
193 | 174 |
194 // Get frame rate for encoder: this is the actual/sent frame rate. | 175 // Get frame rate for encoder: this is the actual/sent frame rate. |
195 float actual_frame_rate = SentFrameRateInternal(); | 176 float actual_frame_rate = SentFrameRateInternal(); |
196 | 177 |
197 // Sanity check. | 178 // Sanity check. |
(...skipping 15 matching lines...) Expand all Loading... |
213 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( | 194 uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( |
214 clock_->TimeInMilliseconds(), filter_mode, fraction_lost); | 195 clock_->TimeInMilliseconds(), filter_mode, fraction_lost); |
215 | 196 |
216 // For now use the filtered loss for computing the robustness settings. | 197 // For now use the filtered loss for computing the robustness settings. |
217 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); | 198 loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); |
218 | 199 |
219 // Rate cost of the protection methods. | 200 // Rate cost of the protection methods. |
220 float protection_overhead_rate = 0.0f; | 201 float protection_overhead_rate = 0.0f; |
221 | 202 |
222 // Update protection settings, when applicable. | 203 // Update protection settings, when applicable. |
223 float sent_video_rate_kbps = 0.0f; | |
224 if (loss_prot_logic_->SelectedType() != kNone) { | 204 if (loss_prot_logic_->SelectedType() != kNone) { |
225 // Update method will compute the robustness settings for the given | 205 // Update method will compute the robustness settings for the given |
226 // protection method and the overhead cost | 206 // protection method and the overhead cost |
227 // the protection method is set by the user via SetVideoProtection. | 207 // the protection method is set by the user via SetVideoProtection. |
228 loss_prot_logic_->UpdateMethod(); | 208 loss_prot_logic_->UpdateMethod(); |
229 | 209 |
230 // Update protection callback with protection settings. | 210 // Update protection callback with protection settings. |
231 uint32_t sent_video_rate_bps = 0; | 211 uint32_t sent_video_rate_bps = 0; |
232 uint32_t sent_nack_rate_bps = 0; | 212 uint32_t sent_nack_rate_bps = 0; |
233 uint32_t sent_fec_rate_bps = 0; | 213 uint32_t sent_fec_rate_bps = 0; |
(...skipping 14 matching lines...) Expand all Loading... |
248 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) / | 228 static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) / |
249 sent_total_rate_bps; | 229 sent_total_rate_bps; |
250 } | 230 } |
251 // Cap the overhead estimate to 50%. | 231 // Cap the overhead estimate to 50%. |
252 if (protection_overhead_rate > 0.5) | 232 if (protection_overhead_rate > 0.5) |
253 protection_overhead_rate = 0.5; | 233 protection_overhead_rate = 0.5; |
254 | 234 |
255 // Get the effective packet loss for encoder ER when applicable. Should be | 235 // Get the effective packet loss for encoder ER when applicable. Should be |
256 // passed to encoder via fraction_lost. | 236 // passed to encoder via fraction_lost. |
257 packet_loss_enc = selected_method->RequiredPacketLossER(); | 237 packet_loss_enc = selected_method->RequiredPacketLossER(); |
258 sent_video_rate_kbps = static_cast<float>(sent_video_rate_bps) / 1000.0f; | |
259 } | 238 } |
260 | 239 |
261 // Source coding rate: total rate - protection overhead. | 240 // Source coding rate: total rate - protection overhead. |
262 video_target_bitrate_ = target_bitrate * (1.0 - protection_overhead_rate); | 241 video_target_bitrate_ = target_bitrate * (1.0 - protection_overhead_rate); |
263 | 242 |
264 // Cap target video bitrate to codec maximum. | 243 // Cap target video bitrate to codec maximum. |
265 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { | 244 if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { |
266 video_target_bitrate_ = max_bit_rate_; | 245 video_target_bitrate_ = max_bit_rate_; |
267 } | 246 } |
268 | 247 |
269 // Update encoding rates following protection settings. | 248 // Update encoding rates following protection settings. |
270 float target_video_bitrate_kbps = | 249 float target_video_bitrate_kbps = |
271 static_cast<float>(video_target_bitrate_) / 1000.0f; | 250 static_cast<float>(video_target_bitrate_) / 1000.0f; |
272 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); | 251 frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); |
273 | 252 |
274 if (enable_qm_ && qmsettings_callback) { | |
275 // Update QM with rates. | |
276 qm_resolution_->UpdateRates(target_video_bitrate_kbps, sent_video_rate_kbps, | |
277 incoming_frame_rate_, fraction_lost_); | |
278 // Check for QM selection. | |
279 bool select_qm = CheckStatusForQMchange(); | |
280 if (select_qm) { | |
281 SelectQuality(qmsettings_callback); | |
282 } | |
283 // Reset the short-term averaged content data. | |
284 content_->ResetShortTermAvgData(); | |
285 } | |
286 | |
287 CheckSuspendConditions(); | 253 CheckSuspendConditions(); |
288 | 254 |
289 return video_target_bitrate_; | 255 return video_target_bitrate_; |
290 } | 256 } |
291 | 257 |
292 void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { | 258 void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { |
293 CriticalSectionScoped lock(crit_sect_.get()); | 259 CriticalSectionScoped lock(crit_sect_.get()); |
294 loss_prot_logic_->SetMethod(method); | 260 loss_prot_logic_->SetMethod(method); |
295 } | 261 } |
296 | 262 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 if (max_payload_size_ > 0 && encoded_length > 0) { | 316 if (max_payload_size_ > 0 && encoded_length > 0) { |
351 const float min_packets_per_frame = | 317 const float min_packets_per_frame = |
352 encoded_length / static_cast<float>(max_payload_size_); | 318 encoded_length / static_cast<float>(max_payload_size_); |
353 if (delta_frame) { | 319 if (delta_frame) { |
354 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame, | 320 loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame, |
355 clock_->TimeInMilliseconds()); | 321 clock_->TimeInMilliseconds()); |
356 } else { | 322 } else { |
357 loss_prot_logic_->UpdatePacketsPerFrameKey( | 323 loss_prot_logic_->UpdatePacketsPerFrameKey( |
358 min_packets_per_frame, clock_->TimeInMilliseconds()); | 324 min_packets_per_frame, clock_->TimeInMilliseconds()); |
359 } | 325 } |
360 | |
361 if (enable_qm_) { | |
362 // Update quality select with encoded length. | |
363 qm_resolution_->UpdateEncodedSize(encoded_length); | |
364 } | |
365 } | 326 } |
366 if (!delta_frame && encoded_length > 0) { | 327 if (!delta_frame && encoded_length > 0) { |
367 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length)); | 328 loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length)); |
368 } | 329 } |
369 | 330 |
370 // Updating counters. | 331 // Updating counters. |
371 if (delta_frame) { | 332 if (delta_frame) { |
372 delta_frame_cnt_++; | 333 delta_frame_cnt_++; |
373 } else { | 334 } else { |
374 key_frame_cnt_++; | 335 key_frame_cnt_++; |
375 } | 336 } |
376 } | 337 } |
377 | 338 |
378 return VCM_OK; | 339 return VCM_OK; |
379 } | 340 } |
380 | 341 |
381 void MediaOptimization::EnableQM(bool enable) { | |
382 CriticalSectionScoped lock(crit_sect_.get()); | |
383 enable_qm_ = enable; | |
384 } | |
385 | |
386 void MediaOptimization::EnableFrameDropper(bool enable) { | 342 void MediaOptimization::EnableFrameDropper(bool enable) { |
387 CriticalSectionScoped lock(crit_sect_.get()); | 343 CriticalSectionScoped lock(crit_sect_.get()); |
388 frame_dropper_->Enable(enable); | 344 frame_dropper_->Enable(enable); |
389 } | 345 } |
390 | 346 |
391 void MediaOptimization::SuspendBelowMinBitrate(int threshold_bps, | 347 void MediaOptimization::SuspendBelowMinBitrate(int threshold_bps, |
392 int window_bps) { | 348 int window_bps) { |
393 CriticalSectionScoped lock(crit_sect_.get()); | 349 CriticalSectionScoped lock(crit_sect_.get()); |
394 assert(threshold_bps > 0 && window_bps >= 0); | 350 assert(threshold_bps > 0 && window_bps >= 0); |
395 suspension_threshold_bps_ = threshold_bps; | 351 suspension_threshold_bps_ = threshold_bps; |
(...skipping 11 matching lines...) Expand all Loading... |
407 CriticalSectionScoped lock(crit_sect_.get()); | 363 CriticalSectionScoped lock(crit_sect_.get()); |
408 UpdateIncomingFrameRate(); | 364 UpdateIncomingFrameRate(); |
409 // Leak appropriate number of bytes. | 365 // Leak appropriate number of bytes. |
410 frame_dropper_->Leak((uint32_t)(InputFrameRateInternal() + 0.5f)); | 366 frame_dropper_->Leak((uint32_t)(InputFrameRateInternal() + 0.5f)); |
411 if (video_suspended_) { | 367 if (video_suspended_) { |
412 return true; // Drop all frames when muted. | 368 return true; // Drop all frames when muted. |
413 } | 369 } |
414 return frame_dropper_->DropFrame(); | 370 return frame_dropper_->DropFrame(); |
415 } | 371 } |
416 | 372 |
417 void MediaOptimization::UpdateContentData( | |
418 const VideoContentMetrics* content_metrics) { | |
419 CriticalSectionScoped lock(crit_sect_.get()); | |
420 // Updating content metrics. | |
421 if (content_metrics == NULL) { | |
422 // Disable QM if metrics are NULL. | |
423 enable_qm_ = false; | |
424 qm_resolution_->Reset(); | |
425 } else { | |
426 content_->UpdateContentData(content_metrics); | |
427 } | |
428 } | |
429 | |
430 void MediaOptimization::UpdateIncomingFrameRate() { | 373 void MediaOptimization::UpdateIncomingFrameRate() { |
431 int64_t now = clock_->TimeInMilliseconds(); | 374 int64_t now = clock_->TimeInMilliseconds(); |
432 if (incoming_frame_times_[0] == 0) { | 375 if (incoming_frame_times_[0] == 0) { |
433 // No shifting if this is the first time. | 376 // No shifting if this is the first time. |
434 } else { | 377 } else { |
435 // Shift all times one step. | 378 // Shift all times one step. |
436 for (int32_t i = (kFrameCountHistorySize - 2); i >= 0; i--) { | 379 for (int32_t i = (kFrameCountHistorySize - 2); i >= 0; i--) { |
437 incoming_frame_times_[i + 1] = incoming_frame_times_[i]; | 380 incoming_frame_times_[i + 1] = incoming_frame_times_[i]; |
438 } | 381 } |
439 } | 382 } |
440 incoming_frame_times_[0] = now; | 383 incoming_frame_times_[0] = now; |
441 ProcessIncomingFrameRate(now); | 384 ProcessIncomingFrameRate(now); |
442 } | 385 } |
443 | 386 |
444 int32_t MediaOptimization::SelectQuality( | |
445 VCMQMSettingsCallback* video_qmsettings_callback) { | |
446 // Reset quantities for QM select. | |
447 qm_resolution_->ResetQM(); | |
448 | |
449 // Update QM will long-term averaged content metrics. | |
450 qm_resolution_->UpdateContent(content_->LongTermAvgData()); | |
451 | |
452 // Select quality mode. | |
453 VCMResolutionScale* qm = NULL; | |
454 int32_t ret = qm_resolution_->SelectResolution(&qm); | |
455 if (ret < 0) { | |
456 return ret; | |
457 } | |
458 | |
459 // Check for updates to spatial/temporal modes. | |
460 QMUpdate(qm, video_qmsettings_callback); | |
461 | |
462 // Reset all the rate and related frame counters quantities. | |
463 qm_resolution_->ResetRates(); | |
464 | |
465 // Reset counters. | |
466 last_qm_update_time_ = clock_->TimeInMilliseconds(); | |
467 | |
468 // Reset content metrics. | |
469 content_->Reset(); | |
470 | |
471 return VCM_OK; | |
472 } | |
473 | |
474 void MediaOptimization::PurgeOldFrameSamples(int64_t now_ms) { | 387 void MediaOptimization::PurgeOldFrameSamples(int64_t now_ms) { |
475 while (!encoded_frame_samples_.empty()) { | 388 while (!encoded_frame_samples_.empty()) { |
476 if (now_ms - encoded_frame_samples_.front().time_complete_ms > | 389 if (now_ms - encoded_frame_samples_.front().time_complete_ms > |
477 kBitrateAverageWinMs) { | 390 kBitrateAverageWinMs) { |
478 encoded_frame_samples_.pop_front(); | 391 encoded_frame_samples_.pop_front(); |
479 } else { | 392 } else { |
480 break; | 393 break; |
481 } | 394 } |
482 } | 395 } |
483 } | 396 } |
(...skipping 26 matching lines...) Expand all Loading... |
510 int denom = encoded_frame_samples_.back().timestamp - | 423 int denom = encoded_frame_samples_.back().timestamp - |
511 encoded_frame_samples_.front().timestamp; | 424 encoded_frame_samples_.front().timestamp; |
512 if (denom > 0) { | 425 if (denom > 0) { |
513 avg_sent_framerate_ = | 426 avg_sent_framerate_ = |
514 (90000 * (encoded_frame_samples_.size() - 1) + denom / 2) / denom; | 427 (90000 * (encoded_frame_samples_.size() - 1) + denom / 2) / denom; |
515 } else { | 428 } else { |
516 avg_sent_framerate_ = encoded_frame_samples_.size(); | 429 avg_sent_framerate_ = encoded_frame_samples_.size(); |
517 } | 430 } |
518 } | 431 } |
519 | 432 |
520 bool MediaOptimization::QMUpdate( | |
521 VCMResolutionScale* qm, | |
522 VCMQMSettingsCallback* video_qmsettings_callback) { | |
523 // Check for no change. | |
524 if (!qm->change_resolution_spatial && !qm->change_resolution_temporal) { | |
525 return false; | |
526 } | |
527 | |
528 // Check for change in frame rate. | |
529 if (qm->change_resolution_temporal) { | |
530 incoming_frame_rate_ = qm->frame_rate; | |
531 // Reset frame rate estimate. | |
532 memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); | |
533 } | |
534 | |
535 // Check for change in frame size. | |
536 if (qm->change_resolution_spatial) { | |
537 codec_width_ = qm->codec_width; | |
538 codec_height_ = qm->codec_height; | |
539 } | |
540 | |
541 LOG(LS_INFO) << "Media optimizer requests the video resolution to be changed " | |
542 "to " | |
543 << qm->codec_width << "x" << qm->codec_height << "@" | |
544 << qm->frame_rate; | |
545 | |
546 // Update VPM with new target frame rate and frame size. | |
547 // Note: use |qm->frame_rate| instead of |_incoming_frame_rate| for updating | |
548 // target frame rate in VPM frame dropper. The quantity |_incoming_frame_rate| | |
549 // will vary/fluctuate, and since we don't want to change the state of the | |
550 // VPM frame dropper, unless a temporal action was selected, we use the | |
551 // quantity |qm->frame_rate| for updating. | |
552 video_qmsettings_callback->SetVideoQMSettings(qm->frame_rate, codec_width_, | |
553 codec_height_); | |
554 content_->UpdateFrameRate(qm->frame_rate); | |
555 qm_resolution_->UpdateCodecParameters(qm->frame_rate, codec_width_, | |
556 codec_height_); | |
557 return true; | |
558 } | |
559 | |
560 // Check timing constraints and look for significant change in: | |
561 // (1) scene content, | |
562 // (2) target bit rate. | |
563 bool MediaOptimization::CheckStatusForQMchange() { | |
564 bool status = true; | |
565 | |
566 // Check that we do not call QMSelect too often, and that we waited some time | |
567 // (to sample the metrics) from the event last_change_time | |
568 // last_change_time is the time where user changed the size/rate/frame rate | |
569 // (via SetEncodingData). | |
570 int64_t now = clock_->TimeInMilliseconds(); | |
571 if ((now - last_qm_update_time_) < kQmMinIntervalMs || | |
572 (now - last_change_time_) < kQmMinIntervalMs) { | |
573 status = false; | |
574 } | |
575 | |
576 return status; | |
577 } | |
578 | |
579 // Allowing VCM to keep track of incoming frame rate. | 433 // Allowing VCM to keep track of incoming frame rate. |
580 void MediaOptimization::ProcessIncomingFrameRate(int64_t now) { | 434 void MediaOptimization::ProcessIncomingFrameRate(int64_t now) { |
581 int32_t num = 0; | 435 int32_t num = 0; |
582 int32_t nr_of_frames = 0; | 436 int32_t nr_of_frames = 0; |
583 for (num = 1; num < (kFrameCountHistorySize - 1); ++num) { | 437 for (num = 1; num < (kFrameCountHistorySize - 1); ++num) { |
584 if (incoming_frame_times_[num] <= 0 || | 438 if (incoming_frame_times_[num] <= 0 || |
585 // don't use data older than 2 s | 439 // don't use data older than 2 s |
586 now - incoming_frame_times_[num] > kFrameHistoryWinMs) { | 440 now - incoming_frame_times_[num] > kFrameHistoryWinMs) { |
587 break; | 441 break; |
588 } else { | 442 } else { |
(...skipping 25 matching lines...) Expand all Loading... |
614 if (video_target_bitrate_ > | 468 if (video_target_bitrate_ > |
615 suspension_threshold_bps_ + suspension_window_bps_) { | 469 suspension_threshold_bps_ + suspension_window_bps_) { |
616 video_suspended_ = false; | 470 video_suspended_ = false; |
617 } | 471 } |
618 } | 472 } |
619 } | 473 } |
620 } | 474 } |
621 | 475 |
622 } // namespace media_optimization | 476 } // namespace media_optimization |
623 } // namespace webrtc | 477 } // namespace webrtc |
OLD | NEW |