OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 void Reset() { frame_times_.clear(); } | 246 void Reset() { frame_times_.clear(); } |
247 int NumFrames() const { return static_cast<int>(frame_times_.size()); } | 247 int NumFrames() const { return static_cast<int>(frame_times_.size()); } |
248 int last_processing_time_ms() const { return last_processing_time_ms_; } | 248 int last_processing_time_ms() const { return last_processing_time_ms_; } |
249 | 249 |
250 private: | 250 private: |
251 // Captured frames mapped by the capture time. | 251 // Captured frames mapped by the capture time. |
252 std::map<int64_t, int64_t> frame_times_; | 252 std::map<int64_t, int64_t> frame_times_; |
253 int last_processing_time_ms_; | 253 int last_processing_time_ms_; |
254 }; | 254 }; |
255 | 255 |
256 // TODO(asapersson): Remove this class. Not used. | |
257 // Class for calculating the capture queue delay change. | |
258 class OveruseFrameDetector::CaptureQueueDelay { | |
259 public: | |
260 CaptureQueueDelay() | |
261 : kWeightFactor(0.5f), | |
262 delay_ms_(0), | |
263 filtered_delay_ms_per_s_(new rtc::ExpFilter(kWeightFactor)) { | |
264 filtered_delay_ms_per_s_->Apply(1.0f, 0.0f); | |
265 } | |
266 ~CaptureQueueDelay() {} | |
267 | |
268 void FrameCaptured(int64_t now) { | |
269 const size_t kMaxSize = 200; | |
270 if (frames_.size() > kMaxSize) { | |
271 frames_.pop_front(); | |
272 } | |
273 frames_.push_back(now); | |
274 } | |
275 | |
276 void FrameProcessingStarted(int64_t now) { | |
277 if (frames_.empty()) { | |
278 return; | |
279 } | |
280 delay_ms_ = now - frames_.front(); | |
281 frames_.pop_front(); | |
282 } | |
283 | |
284 void CalculateDelayChange(int64_t diff_last_sample_ms) { | |
285 if (diff_last_sample_ms <= 0) { | |
286 return; | |
287 } | |
288 float exp = static_cast<float>(diff_last_sample_ms) / kProcessIntervalMs; | |
289 exp = std::min(exp, kMaxExp); | |
290 filtered_delay_ms_per_s_->Apply(exp, | |
291 delay_ms_ * 1000.0f / diff_last_sample_ms); | |
292 ClearFrames(); | |
293 } | |
294 | |
295 void ClearFrames() { | |
296 frames_.clear(); | |
297 } | |
298 | |
299 int delay_ms() const { | |
300 return delay_ms_; | |
301 } | |
302 | |
303 int Value() const { | |
304 return static_cast<int>(filtered_delay_ms_per_s_->filtered() + 0.5); | |
305 } | |
306 | |
307 private: | |
308 const float kWeightFactor; | |
309 std::list<int64_t> frames_; | |
310 int delay_ms_; | |
311 rtc::scoped_ptr<rtc::ExpFilter> filtered_delay_ms_per_s_; | |
312 }; | |
313 | 256 |
314 OveruseFrameDetector::OveruseFrameDetector( | 257 OveruseFrameDetector::OveruseFrameDetector( |
315 Clock* clock, | 258 Clock* clock, |
316 const CpuOveruseOptions& options, | 259 const CpuOveruseOptions& options, |
317 CpuOveruseObserver* observer, | 260 CpuOveruseObserver* observer, |
318 CpuOveruseMetricsObserver* metrics_observer) | 261 CpuOveruseMetricsObserver* metrics_observer) |
319 : options_(options), | 262 : options_(options), |
320 observer_(observer), | 263 observer_(observer), |
321 metrics_observer_(metrics_observer), | 264 metrics_observer_(metrics_observer), |
322 clock_(clock), | 265 clock_(clock), |
323 next_process_time_(clock_->TimeInMilliseconds()), | 266 next_process_time_(clock_->TimeInMilliseconds()), |
324 num_process_times_(0), | 267 num_process_times_(0), |
325 capture_deltas_(options), | 268 capture_deltas_(options), |
326 last_capture_time_(0), | 269 last_capture_time_(0), |
327 last_overuse_time_(0), | 270 last_overuse_time_(0), |
328 checks_above_threshold_(0), | 271 checks_above_threshold_(0), |
329 num_overuse_detections_(0), | 272 num_overuse_detections_(0), |
330 last_rampup_time_(0), | 273 last_rampup_time_(0), |
331 in_quick_rampup_(false), | 274 in_quick_rampup_(false), |
332 current_rampup_delay_ms_(kStandardRampUpDelayMs), | 275 current_rampup_delay_ms_(kStandardRampUpDelayMs), |
333 num_pixels_(0), | 276 num_pixels_(0), |
334 last_encode_sample_ms_(0), | 277 last_encode_sample_ms_(0), |
335 encode_time_(new EncodeTimeAvg()), | 278 encode_time_(new EncodeTimeAvg()), |
336 usage_(new SendProcessingUsage(options)), | 279 usage_(new SendProcessingUsage(options)), |
337 frame_queue_(new FrameQueue()), | 280 frame_queue_(new FrameQueue()), |
338 last_sample_time_ms_(0), | 281 last_sample_time_ms_(0) { |
339 capture_queue_delay_(new CaptureQueueDelay()) { | |
340 DCHECK(metrics_observer != nullptr); | 282 DCHECK(metrics_observer != nullptr); |
341 // Make sure stats are initially up-to-date. This simplifies unit testing | 283 // Make sure stats are initially up-to-date. This simplifies unit testing |
342 // since we don't have to trigger an update using one of the methods which | 284 // since we don't have to trigger an update using one of the methods which |
343 // would also alter the overuse state. | 285 // would also alter the overuse state. |
344 UpdateCpuOveruseMetrics(); | 286 UpdateCpuOveruseMetrics(); |
345 processing_thread_.DetachFromThread(); | 287 processing_thread_.DetachFromThread(); |
346 } | 288 } |
347 | 289 |
348 OveruseFrameDetector::~OveruseFrameDetector() { | 290 OveruseFrameDetector::~OveruseFrameDetector() { |
349 } | 291 } |
350 | 292 |
351 int OveruseFrameDetector::CaptureQueueDelayMsPerS() const { | |
352 rtc::CritScope cs(&crit_); | |
353 return capture_queue_delay_->delay_ms(); | |
354 } | |
355 | |
356 int OveruseFrameDetector::LastProcessingTimeMs() const { | 293 int OveruseFrameDetector::LastProcessingTimeMs() const { |
357 rtc::CritScope cs(&crit_); | 294 rtc::CritScope cs(&crit_); |
358 return frame_queue_->last_processing_time_ms(); | 295 return frame_queue_->last_processing_time_ms(); |
359 } | 296 } |
360 | 297 |
361 int OveruseFrameDetector::FramesInQueue() const { | 298 int OveruseFrameDetector::FramesInQueue() const { |
362 rtc::CritScope cs(&crit_); | 299 rtc::CritScope cs(&crit_); |
363 return frame_queue_->NumFrames(); | 300 return frame_queue_->NumFrames(); |
364 } | 301 } |
365 | 302 |
366 void OveruseFrameDetector::UpdateCpuOveruseMetrics() { | 303 void OveruseFrameDetector::UpdateCpuOveruseMetrics() { |
367 metrics_.capture_jitter_ms = static_cast<int>(capture_deltas_.StdDev() + 0.5); | 304 metrics_.capture_jitter_ms = static_cast<int>(capture_deltas_.StdDev() + 0.5); |
368 metrics_.avg_encode_time_ms = encode_time_->Value(); | 305 metrics_.avg_encode_time_ms = encode_time_->Value(); |
369 metrics_.encode_usage_percent = usage_->Value(); | 306 metrics_.encode_usage_percent = usage_->Value(); |
370 metrics_.capture_queue_delay_ms_per_s = capture_queue_delay_->Value(); | |
371 | 307 |
372 metrics_observer_->CpuOveruseMetricsUpdated(metrics_); | 308 metrics_observer_->CpuOveruseMetricsUpdated(metrics_); |
373 } | 309 } |
374 | 310 |
375 int64_t OveruseFrameDetector::TimeUntilNextProcess() { | 311 int64_t OveruseFrameDetector::TimeUntilNextProcess() { |
376 DCHECK(processing_thread_.CalledOnValidThread()); | 312 DCHECK(processing_thread_.CalledOnValidThread()); |
377 return next_process_time_ - clock_->TimeInMilliseconds(); | 313 return next_process_time_ - clock_->TimeInMilliseconds(); |
378 } | 314 } |
379 | 315 |
380 bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const { | 316 bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const { |
381 if (num_pixels != num_pixels_) { | 317 if (num_pixels != num_pixels_) { |
382 return true; | 318 return true; |
383 } | 319 } |
384 return false; | 320 return false; |
385 } | 321 } |
386 | 322 |
387 bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const { | 323 bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const { |
388 if (last_capture_time_ == 0) { | 324 if (last_capture_time_ == 0) { |
389 return false; | 325 return false; |
390 } | 326 } |
391 return (now - last_capture_time_) > options_.frame_timeout_interval_ms; | 327 return (now - last_capture_time_) > options_.frame_timeout_interval_ms; |
392 } | 328 } |
393 | 329 |
394 void OveruseFrameDetector::ResetAll(int num_pixels) { | 330 void OveruseFrameDetector::ResetAll(int num_pixels) { |
395 num_pixels_ = num_pixels; | 331 num_pixels_ = num_pixels; |
396 capture_deltas_.Reset(); | 332 capture_deltas_.Reset(); |
397 usage_->Reset(); | 333 usage_->Reset(); |
398 frame_queue_->Reset(); | 334 frame_queue_->Reset(); |
399 capture_queue_delay_->ClearFrames(); | |
400 last_capture_time_ = 0; | 335 last_capture_time_ = 0; |
401 num_process_times_ = 0; | 336 num_process_times_ = 0; |
402 UpdateCpuOveruseMetrics(); | 337 UpdateCpuOveruseMetrics(); |
403 } | 338 } |
404 | 339 |
405 void OveruseFrameDetector::FrameCaptured(int width, | 340 void OveruseFrameDetector::FrameCaptured(int width, |
406 int height, | 341 int height, |
407 int64_t capture_time_ms) { | 342 int64_t capture_time_ms) { |
408 rtc::CritScope cs(&crit_); | 343 rtc::CritScope cs(&crit_); |
409 | 344 |
410 int64_t now = clock_->TimeInMilliseconds(); | 345 int64_t now = clock_->TimeInMilliseconds(); |
411 if (FrameSizeChanged(width * height) || FrameTimeoutDetected(now)) { | 346 if (FrameSizeChanged(width * height) || FrameTimeoutDetected(now)) { |
412 ResetAll(width * height); | 347 ResetAll(width * height); |
413 } | 348 } |
414 | 349 |
415 if (last_capture_time_ != 0) { | 350 if (last_capture_time_ != 0) { |
416 capture_deltas_.AddSample(now - last_capture_time_); | 351 capture_deltas_.AddSample(now - last_capture_time_); |
417 usage_->AddCaptureSample(now - last_capture_time_); | 352 usage_->AddCaptureSample(now - last_capture_time_); |
418 } | 353 } |
419 last_capture_time_ = now; | 354 last_capture_time_ = now; |
420 | 355 |
421 capture_queue_delay_->FrameCaptured(now); | |
422 | |
423 if (options_.enable_extended_processing_usage) { | 356 if (options_.enable_extended_processing_usage) { |
424 frame_queue_->Start(capture_time_ms, now); | 357 frame_queue_->Start(capture_time_ms, now); |
425 } | 358 } |
426 UpdateCpuOveruseMetrics(); | 359 UpdateCpuOveruseMetrics(); |
427 } | 360 } |
428 | 361 |
429 void OveruseFrameDetector::FrameProcessingStarted() { | |
430 rtc::CritScope cs(&crit_); | |
431 capture_queue_delay_->FrameProcessingStarted(clock_->TimeInMilliseconds()); | |
432 } | |
433 | |
434 void OveruseFrameDetector::FrameEncoded(int encode_time_ms) { | 362 void OveruseFrameDetector::FrameEncoded(int encode_time_ms) { |
435 rtc::CritScope cs(&crit_); | 363 rtc::CritScope cs(&crit_); |
436 int64_t now = clock_->TimeInMilliseconds(); | 364 int64_t now = clock_->TimeInMilliseconds(); |
437 if (last_encode_sample_ms_ != 0) { | 365 if (last_encode_sample_ms_ != 0) { |
438 int64_t diff_ms = now - last_encode_sample_ms_; | 366 int64_t diff_ms = now - last_encode_sample_ms_; |
439 encode_time_->AddSample(encode_time_ms, diff_ms); | 367 encode_time_->AddSample(encode_time_ms, diff_ms); |
440 } | 368 } |
441 last_encode_sample_ms_ = now; | 369 last_encode_sample_ms_ = now; |
442 | 370 |
443 if (!options_.enable_extended_processing_usage) { | 371 if (!options_.enable_extended_processing_usage) { |
(...skipping 26 matching lines...) Expand all Loading... |
470 | 398 |
471 int32_t OveruseFrameDetector::Process() { | 399 int32_t OveruseFrameDetector::Process() { |
472 DCHECK(processing_thread_.CalledOnValidThread()); | 400 DCHECK(processing_thread_.CalledOnValidThread()); |
473 | 401 |
474 int64_t now = clock_->TimeInMilliseconds(); | 402 int64_t now = clock_->TimeInMilliseconds(); |
475 | 403 |
476 // Used to protect against Process() being called too often. | 404 // Used to protect against Process() being called too often. |
477 if (now < next_process_time_) | 405 if (now < next_process_time_) |
478 return 0; | 406 return 0; |
479 | 407 |
480 int64_t diff_ms = now - next_process_time_ + kProcessIntervalMs; | |
481 next_process_time_ = now + kProcessIntervalMs; | 408 next_process_time_ = now + kProcessIntervalMs; |
482 | 409 |
483 rtc::CritScope cs(&crit_); | 410 rtc::CritScope cs(&crit_); |
484 ++num_process_times_; | 411 ++num_process_times_; |
485 | 412 |
486 capture_queue_delay_->CalculateDelayChange(diff_ms); | |
487 UpdateCpuOveruseMetrics(); | |
488 | |
489 if (num_process_times_ <= options_.min_process_count) { | 413 if (num_process_times_ <= options_.min_process_count) { |
490 return 0; | 414 return 0; |
491 } | 415 } |
492 | 416 |
493 if (IsOverusing()) { | 417 if (IsOverusing()) { |
494 // If the last thing we did was going up, and now have to back down, we need | 418 // If the last thing we did was going up, and now have to back down, we need |
495 // to check if this peak was short. If so we should back off to avoid going | 419 // to check if this peak was short. If so we should back off to avoid going |
496 // back and forth between this load, the system doesn't seem to handle it. | 420 // back and forth between this load, the system doesn't seem to handle it. |
497 bool check_for_backoff = last_rampup_time_ > last_overuse_time_; | 421 bool check_for_backoff = last_rampup_time_ > last_overuse_time_; |
498 if (check_for_backoff) { | 422 if (check_for_backoff) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 bool underusing = false; | 483 bool underusing = false; |
560 if (options_.enable_capture_jitter_method) { | 484 if (options_.enable_capture_jitter_method) { |
561 underusing = capture_deltas_.StdDev() < | 485 underusing = capture_deltas_.StdDev() < |
562 options_.low_capture_jitter_threshold_ms; | 486 options_.low_capture_jitter_threshold_ms; |
563 } else if (options_.enable_encode_usage_method) { | 487 } else if (options_.enable_encode_usage_method) { |
564 underusing = usage_->Value() < options_.low_encode_usage_threshold_percent; | 488 underusing = usage_->Value() < options_.low_encode_usage_threshold_percent; |
565 } | 489 } |
566 return underusing; | 490 return underusing; |
567 } | 491 } |
568 } // namespace webrtc | 492 } // namespace webrtc |
OLD | NEW |