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

Side by Side Diff: webrtc/video/overuse_frame_detector.cc

Issue 2633673002: Refactor OveruseFrameDetector to use timing in us units (Closed)
Patch Set: Rebased. Created 3 years, 11 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
« no previous file with comments | « webrtc/video/overuse_frame_detector.h ('k') | webrtc/video/overuse_frame_detector_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 #include "webrtc/video/overuse_frame_detector.h" 11 #include "webrtc/video/overuse_frame_detector.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 #include <math.h> 14 #include <math.h>
15 15
16 #include <algorithm> 16 #include <algorithm>
17 #include <list> 17 #include <list>
18 #include <map> 18 #include <map>
19 19
20 #include "webrtc/api/video/video_frame.h" 20 #include "webrtc/api/video/video_frame.h"
21 #include "webrtc/base/checks.h" 21 #include "webrtc/base/checks.h"
22 #include "webrtc/base/logging.h" 22 #include "webrtc/base/logging.h"
23 #include "webrtc/base/numerics/exp_filter.h" 23 #include "webrtc/base/numerics/exp_filter.h"
24 #include "webrtc/common_video/include/frame_callback.h" 24 #include "webrtc/common_video/include/frame_callback.h"
25 #include "webrtc/system_wrappers/include/clock.h"
26 25
27 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) 26 #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
28 #include <mach/mach.h> 27 #include <mach/mach.h>
29 #endif // defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) 28 #endif // defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
30 29
31 namespace webrtc { 30 namespace webrtc {
32 31
33 namespace { 32 namespace {
34 const int64_t kCheckForOveruseIntervalMs = 5000; 33 const int64_t kCheckForOveruseIntervalMs = 5000;
35 const int64_t kTimeToFirstCheckForOveruseMs = 100; 34 const int64_t kTimeToFirstCheckForOveruseMs = 100;
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 std::unique_ptr<rtc::QueuedTask>(this), kCheckForOveruseIntervalMs); 195 std::unique_ptr<rtc::QueuedTask>(this), kCheckForOveruseIntervalMs);
197 // Return false to prevent this task from being deleted. Ownership has been 196 // Return false to prevent this task from being deleted. Ownership has been
198 // transferred to the task queue when PostDelayedTask was called. 197 // transferred to the task queue when PostDelayedTask was called.
199 return false; 198 return false;
200 } 199 }
201 rtc::SequencedTaskChecker task_checker_; 200 rtc::SequencedTaskChecker task_checker_;
202 OveruseFrameDetector* overuse_detector_; 201 OveruseFrameDetector* overuse_detector_;
203 }; 202 };
204 203
205 OveruseFrameDetector::OveruseFrameDetector( 204 OveruseFrameDetector::OveruseFrameDetector(
206 Clock* clock,
207 const CpuOveruseOptions& options, 205 const CpuOveruseOptions& options,
208 ScalingObserverInterface* observer, 206 ScalingObserverInterface* observer,
209 EncodedFrameObserver* encoder_timing, 207 EncodedFrameObserver* encoder_timing,
210 CpuOveruseMetricsObserver* metrics_observer) 208 CpuOveruseMetricsObserver* metrics_observer)
211 : check_overuse_task_(nullptr), 209 : check_overuse_task_(nullptr),
212 options_(options), 210 options_(options),
213 observer_(observer), 211 observer_(observer),
214 encoder_timing_(encoder_timing), 212 encoder_timing_(encoder_timing),
215 metrics_observer_(metrics_observer), 213 metrics_observer_(metrics_observer),
216 clock_(clock),
217 num_process_times_(0), 214 num_process_times_(0),
218 last_capture_time_ms_(-1), 215 // TODO(nisse): Use rtc::Optional
219 last_processed_capture_time_ms_(-1), 216 last_capture_time_us_(-1),
217 last_processed_capture_time_us_(-1),
220 num_pixels_(0), 218 num_pixels_(0),
221 last_overuse_time_ms_(-1), 219 last_overuse_time_ms_(-1),
222 checks_above_threshold_(0), 220 checks_above_threshold_(0),
223 num_overuse_detections_(0), 221 num_overuse_detections_(0),
224 last_rampup_time_ms_(-1), 222 last_rampup_time_ms_(-1),
225 in_quick_rampup_(false), 223 in_quick_rampup_(false),
226 current_rampup_delay_ms_(kStandardRampUpDelayMs), 224 current_rampup_delay_ms_(kStandardRampUpDelayMs),
227 usage_(new SendProcessingUsage(options)) { 225 usage_(new SendProcessingUsage(options)) {
228 task_checker_.Detach(); 226 task_checker_.Detach();
229 } 227 }
(...skipping 23 matching lines...) Expand all
253 } 251 }
254 252
255 bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const { 253 bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const {
256 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 254 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
257 if (num_pixels != num_pixels_) { 255 if (num_pixels != num_pixels_) {
258 return true; 256 return true;
259 } 257 }
260 return false; 258 return false;
261 } 259 }
262 260
263 bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const { 261 bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now_us) const {
264 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 262 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
265 if (last_capture_time_ms_ == -1) 263 if (last_capture_time_us_ == -1)
266 return false; 264 return false;
267 return (now - last_capture_time_ms_) > options_.frame_timeout_interval_ms; 265 return (now_us - last_capture_time_us_) >
266 options_.frame_timeout_interval_ms * rtc::kNumMicrosecsPerMillisec;
268 } 267 }
269 268
270 void OveruseFrameDetector::ResetAll(int num_pixels) { 269 void OveruseFrameDetector::ResetAll(int num_pixels) {
271 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 270 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
272 num_pixels_ = num_pixels; 271 num_pixels_ = num_pixels;
273 usage_->Reset(); 272 usage_->Reset();
274 frame_timing_.clear(); 273 frame_timing_.clear();
275 last_capture_time_ms_ = -1; 274 last_capture_time_us_ = -1;
276 last_processed_capture_time_ms_ = -1; 275 last_processed_capture_time_us_ = -1;
277 num_process_times_ = 0; 276 num_process_times_ = 0;
278 metrics_ = rtc::Optional<CpuOveruseMetrics>(); 277 metrics_ = rtc::Optional<CpuOveruseMetrics>();
279 } 278 }
280 279
281 void OveruseFrameDetector::FrameCaptured(const VideoFrame& frame, 280 void OveruseFrameDetector::FrameCaptured(const VideoFrame& frame,
282 int64_t time_when_first_seen_ms) { 281 int64_t time_when_first_seen_us) {
283 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 282 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
284 283
285 if (FrameSizeChanged(frame.width() * frame.height()) || 284 if (FrameSizeChanged(frame.width() * frame.height()) ||
286 FrameTimeoutDetected(time_when_first_seen_ms)) { 285 FrameTimeoutDetected(time_when_first_seen_us)) {
287 ResetAll(frame.width() * frame.height()); 286 ResetAll(frame.width() * frame.height());
288 } 287 }
289 288
290 if (last_capture_time_ms_ != -1) 289 if (last_capture_time_us_ != -1)
291 usage_->AddCaptureSample(time_when_first_seen_ms - last_capture_time_ms_); 290 usage_->AddCaptureSample(
291 1e-3 * (time_when_first_seen_us - last_capture_time_us_));
292 292
293 last_capture_time_ms_ = time_when_first_seen_ms; 293 last_capture_time_us_ = time_when_first_seen_us;
294 294
295 frame_timing_.push_back(FrameTiming(frame.ntp_time_ms(), frame.timestamp(), 295 frame_timing_.push_back(FrameTiming(frame.timestamp_us(), frame.timestamp(),
296 time_when_first_seen_ms)); 296 time_when_first_seen_us));
297 } 297 }
298 298
299 void OveruseFrameDetector::FrameSent(uint32_t timestamp, 299 void OveruseFrameDetector::FrameSent(uint32_t timestamp,
300 int64_t time_sent_in_ms) { 300 int64_t time_sent_in_us) {
301 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 301 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
302 // Delay before reporting actual encoding time, used to have the ability to 302 // Delay before reporting actual encoding time, used to have the ability to
303 // detect total encoding time when encoding more than one layer. Encoding is 303 // detect total encoding time when encoding more than one layer. Encoding is
304 // here assumed to finish within a second (or that we get enough long-time 304 // here assumed to finish within a second (or that we get enough long-time
305 // samples before one second to trigger an overuse even when this is not the 305 // samples before one second to trigger an overuse even when this is not the
306 // case). 306 // case).
307 static const int64_t kEncodingTimeMeasureWindowMs = 1000; 307 static const int64_t kEncodingTimeMeasureWindowMs = 1000;
308 for (auto& it : frame_timing_) { 308 for (auto& it : frame_timing_) {
309 if (it.timestamp == timestamp) { 309 if (it.timestamp == timestamp) {
310 it.last_send_ms = time_sent_in_ms; 310 it.last_send_us = time_sent_in_us;
311 break; 311 break;
312 } 312 }
313 } 313 }
314 // TODO(pbos): Handle the case/log errors when not finding the corresponding 314 // TODO(pbos): Handle the case/log errors when not finding the corresponding
315 // frame (either very slow encoding or incorrect wrong timestamps returned 315 // frame (either very slow encoding or incorrect wrong timestamps returned
316 // from the encoder). 316 // from the encoder).
317 // This is currently the case for all frames on ChromeOS, so logging them 317 // This is currently the case for all frames on ChromeOS, so logging them
318 // would be spammy, and triggering overuse would be wrong. 318 // would be spammy, and triggering overuse would be wrong.
319 // https://crbug.com/350106 319 // https://crbug.com/350106
320 while (!frame_timing_.empty()) { 320 while (!frame_timing_.empty()) {
321 FrameTiming timing = frame_timing_.front(); 321 FrameTiming timing = frame_timing_.front();
322 if (time_sent_in_ms - timing.capture_ms < kEncodingTimeMeasureWindowMs) 322 if (time_sent_in_us - timing.capture_us <
323 kEncodingTimeMeasureWindowMs * rtc::kNumMicrosecsPerMillisec)
323 break; 324 break;
324 if (timing.last_send_ms != -1) { 325 if (timing.last_send_us != -1) {
325 int encode_duration_ms = 326 int encode_duration_us =
326 static_cast<int>(timing.last_send_ms - timing.capture_ms); 327 static_cast<int>(timing.last_send_us - timing.capture_us);
327 if (encoder_timing_) { 328 if (encoder_timing_) {
328 encoder_timing_->OnEncodeTiming(timing.capture_ntp_ms, 329 // TODO(nisse): Update encoder_timing_ to also use us units.
329 encode_duration_ms); 330 encoder_timing_->OnEncodeTiming(timing.capture_time_us /
331 rtc::kNumMicrosecsPerMillisec,
332 encode_duration_us /
333 rtc::kNumMicrosecsPerMillisec);
330 } 334 }
331 if (last_processed_capture_time_ms_ != -1) { 335 if (last_processed_capture_time_us_ != -1) {
332 int64_t diff_ms = timing.capture_ms - last_processed_capture_time_ms_; 336 int64_t diff_us = timing.capture_us - last_processed_capture_time_us_;
333 usage_->AddSample(encode_duration_ms, diff_ms); 337 usage_->AddSample(1e-3 * encode_duration_us, 1e-3 * diff_us);
334 } 338 }
335 last_processed_capture_time_ms_ = timing.capture_ms; 339 last_processed_capture_time_us_ = timing.capture_us;
336 EncodedFrameTimeMeasured(encode_duration_ms); 340 EncodedFrameTimeMeasured(encode_duration_us /
341 rtc::kNumMicrosecsPerMillisec);
337 } 342 }
338 frame_timing_.pop_front(); 343 frame_timing_.pop_front();
339 } 344 }
340 } 345 }
341 346
342 void OveruseFrameDetector::CheckForOveruse() { 347 void OveruseFrameDetector::CheckForOveruse() {
343 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 348 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
344 ++num_process_times_; 349 ++num_process_times_;
345 if (num_process_times_ <= options_.min_process_count || !metrics_) 350 if (num_process_times_ <= options_.min_process_count || !metrics_)
346 return; 351 return;
347 352
348 int64_t now = clock_->TimeInMilliseconds(); 353 int64_t now_ms = rtc::TimeMillis();
349 354
350 if (IsOverusing(*metrics_)) { 355 if (IsOverusing(*metrics_)) {
351 // If the last thing we did was going up, and now have to back down, we need 356 // If the last thing we did was going up, and now have to back down, we need
352 // to check if this peak was short. If so we should back off to avoid going 357 // to check if this peak was short. If so we should back off to avoid going
353 // back and forth between this load, the system doesn't seem to handle it. 358 // back and forth between this load, the system doesn't seem to handle it.
354 bool check_for_backoff = last_rampup_time_ms_ > last_overuse_time_ms_; 359 bool check_for_backoff = last_rampup_time_ms_ > last_overuse_time_ms_;
355 if (check_for_backoff) { 360 if (check_for_backoff) {
356 if (now - last_rampup_time_ms_ < kStandardRampUpDelayMs || 361 if (now_ms - last_rampup_time_ms_ < kStandardRampUpDelayMs ||
357 num_overuse_detections_ > kMaxOverusesBeforeApplyRampupDelay) { 362 num_overuse_detections_ > kMaxOverusesBeforeApplyRampupDelay) {
358 // Going up was not ok for very long, back off. 363 // Going up was not ok for very long, back off.
359 current_rampup_delay_ms_ *= kRampUpBackoffFactor; 364 current_rampup_delay_ms_ *= kRampUpBackoffFactor;
360 if (current_rampup_delay_ms_ > kMaxRampUpDelayMs) 365 if (current_rampup_delay_ms_ > kMaxRampUpDelayMs)
361 current_rampup_delay_ms_ = kMaxRampUpDelayMs; 366 current_rampup_delay_ms_ = kMaxRampUpDelayMs;
362 } else { 367 } else {
363 // Not currently backing off, reset rampup delay. 368 // Not currently backing off, reset rampup delay.
364 current_rampup_delay_ms_ = kStandardRampUpDelayMs; 369 current_rampup_delay_ms_ = kStandardRampUpDelayMs;
365 } 370 }
366 } 371 }
367 372
368 last_overuse_time_ms_ = now; 373 last_overuse_time_ms_ = now_ms;
369 in_quick_rampup_ = false; 374 in_quick_rampup_ = false;
370 checks_above_threshold_ = 0; 375 checks_above_threshold_ = 0;
371 ++num_overuse_detections_; 376 ++num_overuse_detections_;
372 377
373 if (observer_) 378 if (observer_)
374 observer_->ScaleDown(kScaleReasonCpu); 379 observer_->ScaleDown(kScaleReasonCpu);
375 } else if (IsUnderusing(*metrics_, now)) { 380 } else if (IsUnderusing(*metrics_, now_ms)) {
376 last_rampup_time_ms_ = now; 381 last_rampup_time_ms_ = now_ms;
377 in_quick_rampup_ = true; 382 in_quick_rampup_ = true;
378 383
379 if (observer_) 384 if (observer_)
380 observer_->ScaleUp(kScaleReasonCpu); 385 observer_->ScaleUp(kScaleReasonCpu);
381 } 386 }
382 387
383 int rampup_delay = 388 int rampup_delay =
384 in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; 389 in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
385 390
386 LOG(LS_VERBOSE) << " Frame stats: " 391 LOG(LS_VERBOSE) << " Frame stats: "
(...skipping 17 matching lines...) Expand all
404 int64_t time_now) { 409 int64_t time_now) {
405 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); 410 RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
406 int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; 411 int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
407 if (time_now < last_rampup_time_ms_ + delay) 412 if (time_now < last_rampup_time_ms_ + delay)
408 return false; 413 return false;
409 414
410 return metrics.encode_usage_percent < 415 return metrics.encode_usage_percent <
411 options_.low_encode_usage_threshold_percent; 416 options_.low_encode_usage_threshold_percent;
412 } 417 }
413 } // namespace webrtc 418 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/overuse_frame_detector.h ('k') | webrtc/video/overuse_frame_detector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698