| Index: webrtc/video/overuse_frame_detector.cc
|
| diff --git a/webrtc/video/overuse_frame_detector.cc b/webrtc/video/overuse_frame_detector.cc
|
| index cc4c000a7355e4faa151de3e99ed33469efd45c0..bb89864bb0409f9bbee1a95168697266b9654238 100644
|
| --- a/webrtc/video/overuse_frame_detector.cc
|
| +++ b/webrtc/video/overuse_frame_detector.cc
|
| @@ -31,7 +31,8 @@
|
| namespace webrtc {
|
|
|
| namespace {
|
| -const int64_t kProcessIntervalMs = 5000;
|
| +const int64_t kCheckForOveruseIntervalMs = 5000;
|
| +const int64_t kTimeToFirstCheckForOveruseMs = 100;
|
|
|
| // Delay between consecutive rampups. (Used for quick recovery.)
|
| const int kQuickRampUpDelayMs = 10 * 1000;
|
| @@ -170,13 +171,44 @@ class OveruseFrameDetector::SendProcessingUsage {
|
| std::unique_ptr<rtc::ExpFilter> filtered_frame_diff_ms_;
|
| };
|
|
|
| +class OveruseFrameDetector::CheckOveruseTask : public rtc::QueuedTask {
|
| + public:
|
| + explicit CheckOveruseTask(OveruseFrameDetector* overuse_detector)
|
| + : overuse_detector_(overuse_detector) {
|
| + rtc::TaskQueue::Current()->PostDelayedTask(
|
| + std::unique_ptr<rtc::QueuedTask>(this), kTimeToFirstCheckForOveruseMs);
|
| + }
|
| +
|
| + void Stop() {
|
| + RTC_CHECK(task_checker_.CalledSequentially());
|
| + overuse_detector_ = nullptr;
|
| + }
|
| +
|
| + private:
|
| + bool Run() override {
|
| + RTC_CHECK(task_checker_.CalledSequentially());
|
| + if (!overuse_detector_)
|
| + return true; // This will make the task queue delete this task.
|
| + overuse_detector_->CheckForOveruse();
|
| +
|
| + rtc::TaskQueue::Current()->PostDelayedTask(
|
| + std::unique_ptr<rtc::QueuedTask>(this), kCheckForOveruseIntervalMs);
|
| + // Return false to prevent this task from being deleted. Ownership has been
|
| + // transferred to the task queue when PostDelayedTask was called.
|
| + return false;
|
| + }
|
| + rtc::SequencedTaskChecker task_checker_;
|
| + OveruseFrameDetector* overuse_detector_;
|
| +};
|
| +
|
| OveruseFrameDetector::OveruseFrameDetector(
|
| Clock* clock,
|
| const CpuOveruseOptions& options,
|
| CpuOveruseObserver* observer,
|
| EncodedFrameObserver* encoder_timing,
|
| CpuOveruseMetricsObserver* metrics_observer)
|
| - : options_(options),
|
| + : check_overuse_task_(nullptr),
|
| + options_(options),
|
| observer_(observer),
|
| encoder_timing_(encoder_timing),
|
| metrics_observer_(metrics_observer),
|
| @@ -185,7 +217,6 @@ OveruseFrameDetector::OveruseFrameDetector(
|
| last_capture_time_ms_(-1),
|
| last_processed_capture_time_ms_(-1),
|
| num_pixels_(0),
|
| - next_process_time_ms_(clock_->TimeInMilliseconds()),
|
| last_overuse_time_ms_(-1),
|
| checks_above_threshold_(0),
|
| num_overuse_detections_(0),
|
| @@ -193,13 +224,26 @@ OveruseFrameDetector::OveruseFrameDetector(
|
| in_quick_rampup_(false),
|
| current_rampup_delay_ms_(kStandardRampUpDelayMs),
|
| usage_(new SendProcessingUsage(options)) {
|
| - processing_thread_.DetachFromThread();
|
| + task_checker_.Detach();
|
| }
|
|
|
| OveruseFrameDetector::~OveruseFrameDetector() {
|
| + RTC_DCHECK(!check_overuse_task_) << "StopCheckForOverUse must be called.";
|
| +}
|
| +
|
| +void OveruseFrameDetector::StartCheckForOveruse() {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| + RTC_DCHECK(!check_overuse_task_);
|
| + check_overuse_task_ = new CheckOveruseTask(this);
|
| +}
|
| +void OveruseFrameDetector::StopCheckForOveruse() {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| + check_overuse_task_->Stop();
|
| + check_overuse_task_ = nullptr;
|
| }
|
|
|
| void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| if (!metrics_)
|
| metrics_ = rtc::Optional<CpuOveruseMetrics>(CpuOveruseMetrics());
|
| metrics_->encode_usage_percent = usage_->Value();
|
| @@ -207,12 +251,8 @@ void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) {
|
| metrics_observer_->OnEncodedFrameTimeMeasured(encode_duration_ms, *metrics_);
|
| }
|
|
|
| -int64_t OveruseFrameDetector::TimeUntilNextProcess() {
|
| - RTC_DCHECK(processing_thread_.CalledOnValidThread());
|
| - return next_process_time_ms_ - clock_->TimeInMilliseconds();
|
| -}
|
| -
|
| bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| if (num_pixels != num_pixels_) {
|
| return true;
|
| }
|
| @@ -220,12 +260,14 @@ bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const {
|
| }
|
|
|
| bool OveruseFrameDetector::FrameTimeoutDetected(int64_t now) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| if (last_capture_time_ms_ == -1)
|
| return false;
|
| return (now - last_capture_time_ms_) > options_.frame_timeout_interval_ms;
|
| }
|
|
|
| void OveruseFrameDetector::ResetAll(int num_pixels) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| num_pixels_ = num_pixels;
|
| usage_->Reset();
|
| frame_timing_.clear();
|
| @@ -235,36 +277,36 @@ void OveruseFrameDetector::ResetAll(int num_pixels) {
|
| metrics_ = rtc::Optional<CpuOveruseMetrics>();
|
| }
|
|
|
| -void OveruseFrameDetector::FrameCaptured(const VideoFrame& frame) {
|
| - rtc::CritScope cs(&crit_);
|
| +void OveruseFrameDetector::FrameCaptured(const VideoFrame& frame,
|
| + int64_t time_when_first_seen_ms) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
|
|
| - int64_t now = clock_->TimeInMilliseconds();
|
| if (FrameSizeChanged(frame.width() * frame.height()) ||
|
| - FrameTimeoutDetected(now)) {
|
| + FrameTimeoutDetected(time_when_first_seen_ms)) {
|
| ResetAll(frame.width() * frame.height());
|
| }
|
|
|
| if (last_capture_time_ms_ != -1)
|
| - usage_->AddCaptureSample(now - last_capture_time_ms_);
|
| + usage_->AddCaptureSample(time_when_first_seen_ms - last_capture_time_ms_);
|
|
|
| - last_capture_time_ms_ = now;
|
| + last_capture_time_ms_ = time_when_first_seen_ms;
|
|
|
| - frame_timing_.push_back(
|
| - FrameTiming(frame.ntp_time_ms(), frame.timestamp(), now));
|
| + frame_timing_.push_back(FrameTiming(frame.ntp_time_ms(), frame.timestamp(),
|
| + time_when_first_seen_ms));
|
| }
|
|
|
| -void OveruseFrameDetector::FrameSent(uint32_t timestamp) {
|
| - rtc::CritScope cs(&crit_);
|
| +void OveruseFrameDetector::FrameSent(uint32_t timestamp,
|
| + int64_t time_sent_in_ms) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| // Delay before reporting actual encoding time, used to have the ability to
|
| // detect total encoding time when encoding more than one layer. Encoding is
|
| // here assumed to finish within a second (or that we get enough long-time
|
| // samples before one second to trigger an overuse even when this is not the
|
| // case).
|
| static const int64_t kEncodingTimeMeasureWindowMs = 1000;
|
| - int64_t now = clock_->TimeInMilliseconds();
|
| for (auto& it : frame_timing_) {
|
| if (it.timestamp == timestamp) {
|
| - it.last_send_ms = now;
|
| + it.last_send_ms = time_sent_in_ms;
|
| break;
|
| }
|
| }
|
| @@ -276,7 +318,7 @@ void OveruseFrameDetector::FrameSent(uint32_t timestamp) {
|
| // https://crbug.com/350106
|
| while (!frame_timing_.empty()) {
|
| FrameTiming timing = frame_timing_.front();
|
| - if (now - timing.capture_ms < kEncodingTimeMeasureWindowMs)
|
| + if (time_sent_in_ms - timing.capture_ms < kEncodingTimeMeasureWindowMs)
|
| break;
|
| if (timing.last_send_ms != -1) {
|
| int encode_duration_ms =
|
| @@ -296,28 +338,15 @@ void OveruseFrameDetector::FrameSent(uint32_t timestamp) {
|
| }
|
| }
|
|
|
| -void OveruseFrameDetector::Process() {
|
| - RTC_DCHECK(processing_thread_.CalledOnValidThread());
|
| -
|
| - int64_t now = clock_->TimeInMilliseconds();
|
| -
|
| - // Used to protect against Process() being called too often.
|
| - if (now < next_process_time_ms_)
|
| +void OveruseFrameDetector::CheckForOveruse() {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| + ++num_process_times_;
|
| + if (num_process_times_ <= options_.min_process_count || !metrics_)
|
| return;
|
|
|
| - next_process_time_ms_ = now + kProcessIntervalMs;
|
| -
|
| - CpuOveruseMetrics current_metrics;
|
| - {
|
| - rtc::CritScope cs(&crit_);
|
| - ++num_process_times_;
|
| - if (num_process_times_ <= options_.min_process_count || !metrics_)
|
| - return;
|
| -
|
| - current_metrics = *metrics_;
|
| - }
|
| + int64_t now = clock_->TimeInMilliseconds();
|
|
|
| - if (IsOverusing(current_metrics)) {
|
| + if (IsOverusing(*metrics_)) {
|
| // If the last thing we did was going up, and now have to back down, we need
|
| // to check if this peak was short. If so we should back off to avoid going
|
| // back and forth between this load, the system doesn't seem to handle it.
|
| @@ -342,7 +371,7 @@ void OveruseFrameDetector::Process() {
|
|
|
| if (observer_)
|
| observer_->OveruseDetected();
|
| - } else if (IsUnderusing(current_metrics, now)) {
|
| + } else if (IsUnderusing(*metrics_, now)) {
|
| last_rampup_time_ms_ = now;
|
| in_quick_rampup_ = true;
|
|
|
| @@ -354,12 +383,13 @@ void OveruseFrameDetector::Process() {
|
| in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
|
|
|
| LOG(LS_VERBOSE) << " Frame stats: "
|
| - << " encode usage " << current_metrics.encode_usage_percent
|
| + << " encode usage " << metrics_->encode_usage_percent
|
| << " overuse detections " << num_overuse_detections_
|
| << " rampup delay " << rampup_delay;
|
| }
|
|
|
| bool OveruseFrameDetector::IsOverusing(const CpuOveruseMetrics& metrics) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| if (metrics.encode_usage_percent >=
|
| options_.high_encode_usage_threshold_percent) {
|
| ++checks_above_threshold_;
|
| @@ -371,6 +401,7 @@ bool OveruseFrameDetector::IsOverusing(const CpuOveruseMetrics& metrics) {
|
|
|
| bool OveruseFrameDetector::IsUnderusing(const CpuOveruseMetrics& metrics,
|
| int64_t time_now) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
| int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_;
|
| if (time_now < last_rampup_time_ms_ + delay)
|
| return false;
|
|
|