| Index: content/browser/renderer_host/media/video_capture_oracle.cc
|
| diff --git a/content/browser/renderer_host/media/video_capture_oracle.cc b/content/browser/renderer_host/media/video_capture_oracle.cc
|
| deleted file mode 100644
|
| index 499bde468aab112e5ffae4875505a6abc48ac34b..0000000000000000000000000000000000000000
|
| --- a/content/browser/renderer_host/media/video_capture_oracle.cc
|
| +++ /dev/null
|
| @@ -1,170 +0,0 @@
|
| -// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/browser/renderer_host/media/video_capture_oracle.h"
|
| -
|
| -#include "base/debug/trace_event.h"
|
| -
|
| -namespace content {
|
| -
|
| -namespace {
|
| -
|
| -// This value controls how many redundant, timer-base captures occur when the
|
| -// content is static. Redundantly capturing the same frame allows iterative
|
| -// quality enhancement, and also allows the buffer to fill in "buffered mode".
|
| -//
|
| -// TODO(nick): Controlling this here is a hack and a layering violation, since
|
| -// it's a strategy specific to the WebRTC consumer, and probably just papers
|
| -// over some frame dropping and quality bugs. It should either be controlled at
|
| -// a higher level, or else redundant frame generation should be pushed down
|
| -// further into the WebRTC encoding stack.
|
| -const int kNumRedundantCapturesOfStaticContent = 200;
|
| -
|
| -} // anonymous namespace
|
| -
|
| -VideoCaptureOracle::VideoCaptureOracle(base::TimeDelta capture_period,
|
| - bool events_are_reliable)
|
| - : capture_period_(capture_period),
|
| - frame_number_(0),
|
| - last_delivered_frame_number_(0),
|
| - sampler_(capture_period_,
|
| - events_are_reliable,
|
| - kNumRedundantCapturesOfStaticContent) {}
|
| -
|
| -bool VideoCaptureOracle::ObserveEventAndDecideCapture(
|
| - Event event,
|
| - base::TimeTicks event_time) {
|
| - // Record |event| and decide whether it's a good time to capture.
|
| - const bool content_is_dirty = (event == kCompositorUpdate ||
|
| - event == kSoftwarePaint);
|
| - bool should_sample;
|
| - if (content_is_dirty) {
|
| - frame_number_++;
|
| - should_sample = sampler_.AddEventAndConsiderSampling(event_time);
|
| - } else {
|
| - should_sample = sampler_.IsOverdueForSamplingAt(event_time);
|
| - }
|
| - return should_sample;
|
| -}
|
| -
|
| -int VideoCaptureOracle::RecordCapture() {
|
| - sampler_.RecordSample();
|
| - return frame_number_;
|
| -}
|
| -
|
| -bool VideoCaptureOracle::CompleteCapture(int frame_number,
|
| - base::TimeTicks timestamp) {
|
| - // Drop frame if previous frame number is higher or we're trying to deliver
|
| - // a frame with the same timestamp.
|
| - if (last_delivered_frame_number_ > frame_number ||
|
| - last_delivered_frame_timestamp_ == timestamp) {
|
| - LOG(ERROR) << "Frame with same timestamp or out of order delivery. "
|
| - << "Dropping frame.";
|
| - return false;
|
| - }
|
| -
|
| - if (last_delivered_frame_timestamp_ > timestamp) {
|
| - // We should not get here unless time was adjusted backwards.
|
| - LOG(ERROR) << "Frame with past timestamp (" << timestamp.ToInternalValue()
|
| - << ") was delivered";
|
| - }
|
| -
|
| - last_delivered_frame_number_ = frame_number;
|
| - last_delivered_frame_timestamp_ = timestamp;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -SmoothEventSampler::SmoothEventSampler(base::TimeDelta capture_period,
|
| - bool events_are_reliable,
|
| - int redundant_capture_goal)
|
| - : events_are_reliable_(events_are_reliable),
|
| - capture_period_(capture_period),
|
| - redundant_capture_goal_(redundant_capture_goal),
|
| - token_bucket_capacity_(capture_period + capture_period / 2),
|
| - overdue_sample_count_(0),
|
| - token_bucket_(token_bucket_capacity_) {
|
| - DCHECK_GT(capture_period_.InMicroseconds(), 0);
|
| -}
|
| -
|
| -bool SmoothEventSampler::AddEventAndConsiderSampling(
|
| - base::TimeTicks event_time) {
|
| - DCHECK(!event_time.is_null());
|
| -
|
| - // Add tokens to the bucket based on advancement in time. Then, re-bound the
|
| - // number of tokens in the bucket. Overflow occurs when there is too much
|
| - // time between events (a common case), or when RecordSample() is not being
|
| - // called often enough (a bug). On the other hand, if RecordSample() is being
|
| - // called too often (e.g., as a reaction to IsOverdueForSamplingAt()), the
|
| - // bucket will underflow.
|
| - if (!current_event_.is_null()) {
|
| - if (current_event_ < event_time) {
|
| - token_bucket_ += event_time - current_event_;
|
| - if (token_bucket_ > token_bucket_capacity_)
|
| - token_bucket_ = token_bucket_capacity_;
|
| - }
|
| - // Side note: If the system clock is reset, causing |current_event_| to be
|
| - // greater than |event_time|, everything here will simply gracefully adjust.
|
| - if (token_bucket_ < base::TimeDelta())
|
| - token_bucket_ = base::TimeDelta();
|
| - TRACE_COUNTER1("mirroring",
|
| - "MirroringTokenBucketUsec", token_bucket_.InMicroseconds());
|
| - }
|
| - current_event_ = event_time;
|
| -
|
| - // Return true if one capture period's worth of tokens are in the bucket.
|
| - return token_bucket_ >= capture_period_;
|
| -}
|
| -
|
| -void SmoothEventSampler::RecordSample() {
|
| - token_bucket_ -= capture_period_;
|
| - TRACE_COUNTER1("mirroring",
|
| - "MirroringTokenBucketUsec", token_bucket_.InMicroseconds());
|
| -
|
| - bool was_paused = overdue_sample_count_ == redundant_capture_goal_;
|
| - if (HasUnrecordedEvent()) {
|
| - last_sample_ = current_event_;
|
| - overdue_sample_count_ = 0;
|
| - } else {
|
| - ++overdue_sample_count_;
|
| - }
|
| - bool is_paused = overdue_sample_count_ == redundant_capture_goal_;
|
| -
|
| - VLOG_IF(0, !was_paused && is_paused)
|
| - << "Tab content unchanged for " << redundant_capture_goal_
|
| - << " frames; capture will halt until content changes.";
|
| - VLOG_IF(0, was_paused && !is_paused)
|
| - << "Content changed; capture will resume.";
|
| -}
|
| -
|
| -bool SmoothEventSampler::IsOverdueForSamplingAt(base::TimeTicks event_time)
|
| - const {
|
| - DCHECK(!event_time.is_null());
|
| -
|
| - // If we don't get events on compositor updates on this platform, then we
|
| - // don't reliably know whether we're dirty.
|
| - if (events_are_reliable_) {
|
| - if (!HasUnrecordedEvent() &&
|
| - overdue_sample_count_ >= redundant_capture_goal_) {
|
| - return false; // Not dirty.
|
| - }
|
| - }
|
| -
|
| - if (last_sample_.is_null())
|
| - return true;
|
| -
|
| - // If we're dirty but not yet old, then we've recently gotten updates, so we
|
| - // won't request a sample just yet.
|
| - base::TimeDelta dirty_interval = event_time - last_sample_;
|
| - if (dirty_interval < capture_period_ * 4)
|
| - return false;
|
| - else
|
| - return true;
|
| -}
|
| -
|
| -bool SmoothEventSampler::HasUnrecordedEvent() const {
|
| - return !current_event_.is_null() && current_event_ != last_sample_;
|
| -}
|
| -
|
| -} // namespace content
|
|
|