Commit 910087dc authored by Yuri Wiitala's avatar Yuri Wiitala Committed by Commit Bot

Re-Re-land "FrameSinkVideoCapturer: Fix refresh logic for damaged sources."

This reverts commit 13c588bc, to re-land
the original patch (https://chromium-review.googlesource.com/884996)
again. This patch contains fixes needed to restore tab capture
functionality and clear up failing perf waterfall bots.

This time, I'm landing with the "sensitive to random bots not in the CQ"
content_browsertests disabled. I will re-enable them in a separate
change so that people stop reverting this very important fix, the act of
which keeps making things worse elsewhere.

TBR=xjz@chromium.org,kylechar@chromium.org

Bug: 806635, 785072, 754872
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: I15ac4faaa168eb57f1775b70148382c3933de82f
Reviewed-on: https://chromium-review.googlesource.com/891541
Commit-Queue: Yuri Wiitala <miu@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532598}
parent 3044c7ef
......@@ -414,13 +414,16 @@ void CompositorFrameSinkSupport::DetachCaptureClient(
capture_clients_.erase(it);
}
gfx::Size CompositorFrameSinkSupport::GetSurfaceSize() {
gfx::Size CompositorFrameSinkSupport::GetActiveFrameSize() {
if (current_surface_id_.is_valid()) {
Surface* current_surface =
surface_manager_->GetSurfaceForId(current_surface_id_);
if (current_surface)
if (current_surface->HasActiveFrame()) {
DCHECK(current_surface->GetActiveFrame().size_in_pixels() ==
current_surface->size_in_pixels());
return current_surface->size_in_pixels();
}
}
return gfx::Size();
}
......
......@@ -104,7 +104,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
// CapturableFrameSink implementation.
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
void DetachCaptureClient(CapturableFrameSink::Client* client) override;
gfx::Size GetSurfaceSize() override;
gfx::Size GetActiveFrameSize() override;
void RequestCopyOfSurface(
std::unique_ptr<CopyOutputRequest> request) override;
......
......@@ -49,8 +49,9 @@ class CapturableFrameSink {
virtual void AttachCaptureClient(Client* client) = 0;
virtual void DetachCaptureClient(Client* client) = 0;
// Returns the current surface size.
virtual gfx::Size GetSurfaceSize() = 0;
// Returns the currently-active frame size, or an empty size if there is no
// active frame.
virtual gfx::Size GetActiveFrameSize() = 0;
// Issues a request for a copy of the next composited frame.
virtual void RequestCopyOfSurface(
......
......@@ -125,10 +125,6 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// exceeding 60% of the design limit is considered "red line" operation.
static constexpr float kTargetPipelineUtilization = 0.6f;
// The amount of time to wait before retrying a refresh frame request.
static constexpr base::TimeDelta kRefreshFrameRetryInterval =
base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / 4);
private:
friend class FrameSinkVideoCapturerTest;
......@@ -140,12 +136,24 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// up-to-date content will be sent to the consumer in the near future. This
// refresh operation will be canceled if a compositing event triggers a frame
// capture in the meantime.
void ScheduleRefreshFrame(media::VideoCaptureOracle::Event event);
void ScheduleRefreshFrame();
// Returns the delay that should be used when setting the refresh timer. This
// is based on the current oracle prediction for frame duration.
base::TimeDelta GetDelayBeforeNextRefreshAttempt() const;
// Executes the refresh capture, if conditions permit. Otherwise, schedules a
// Called whenever a major damage event, such as a capture parameter change, a
// resolved target change, etc., occurs. This marks the entire source as dirty
// and ensures the consumer will receive a refresh frame with up-to-date
// content.
void RefreshEntireSourceSoon();
// Executes a refresh capture, if conditions permit. Otherwise, schedules a
// later retry. Note that the retry "polling" should be a short-term state,
// since it only occurs when the capture target hasn't yet been resolved.
void RefreshOrReschedule(media::VideoCaptureOracle::Event event);
// since it only occurs until the oracle allows the next frame capture to take
// place. If a refresh was already pending, it is canceled in favor of this
// new refresh.
void RefreshSoon();
// CapturableFrameSink::Client implementation:
void OnBeginFrame(const BeginFrameArgs& args) final;
......@@ -227,15 +235,20 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
using TimeRingBuffer = std::array<base::TimeTicks, kDesignLimitMaxFrames>;
base::flat_map<BeginFrameSourceId, TimeRingBuffer> frame_display_times_;
// The portion of the source content that has changed, but has not yet been
// captured.
gfx::Rect dirty_rect_;
// These are sequence counters used to ensure that the frames are being
// delivered in the same order they are captured.
int64_t next_capture_frame_number_ = 0;
int64_t next_delivery_frame_number_ = 0;
// When the oracle rejects a "refresh frame" request, or a target is not yet
// resolved, this timer is set to auto-retry the refresh at a later point.
// This ensures refresh frame requests eventually result in a frame being
// delivered to the consumer.
// This timer is started whenever the consumer needs another frame delivered.
// This might be because: 1) the consumer was just started and needs an
// initial frame; 2) the capture target changed; 3) the oracle rejected
// an event for timing reasons; 4) to satisfy explicit requests for a refresh
// frame, when RequestRefreshFrame() has been called.
//
// Note: This is always set, but the instance is overridden for unit testing.
base::Optional<base::OneShotTimer> refresh_frame_retry_timer_;
......
......@@ -228,7 +228,7 @@ void AuraWindowCaptureMachine::Capture(base::TimeTicks event_time) {
const base::TimeTicks start_time = base::TimeTicks::Now();
media::VideoCaptureOracle::Event event;
if (event_time.is_null()) {
event = media::VideoCaptureOracle::kActiveRefreshRequest;
event = media::VideoCaptureOracle::kRefreshRequest;
event_time = start_time;
} else {
event = media::VideoCaptureOracle::kCompositorUpdate;
......
......@@ -216,31 +216,26 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
// Creates and starts the device for frame capture, and checks that the
// initial refresh frame is delivered.
void AllocateAndStartAndWaitForFirstFrame() {
frames_.clear();
last_frame_timestamp_ = base::TimeDelta::Min();
capture_stack()->SetFrameCallback(
base::BindRepeating(&WebContentsVideoCaptureDeviceBrowserTest::OnFrame,
base::Unretained(this)));
auto* const main_frame = shell()->web_contents()->GetMainFrame();
device_ = std::make_unique<WebContentsVideoCaptureDevice>(
main_frame->GetProcess()->GetID(), main_frame->GetRoutingID());
base::RunLoop run_loop;
capture_stack()->SetFrameCallback(base::BindRepeating(
[](base::RunLoop* loop, base::TimeDelta* first_frame_timestamp,
scoped_refptr<media::VideoFrame> frame) {
*first_frame_timestamp = frame->timestamp();
loop->Quit();
},
&run_loop, &last_frame_timestamp_));
device_->AllocateAndStartWithReceiver(
SnapshotCaptureParams(), capture_stack()->CreateFrameReceiver());
run_loop.Run();
RunAllPendingInMessageLoop(BrowserThread::UI);
EXPECT_TRUE(capture_stack()->started());
EXPECT_FALSE(capture_stack()->error_occurred());
capture_stack()->ExpectNoLogMessages();
frames_.clear();
capture_stack()->SetFrameCallback(
base::BindRepeating(&WebContentsVideoCaptureDeviceBrowserTest::OnFrame,
base::Unretained(this)));
min_capture_period_ = base::TimeDelta::FromMicroseconds(
base::Time::kMicrosecondsPerSecond /
device_->capture_params().requested_format.frame_rate);
WaitForFrameWithColor(SK_ColorBLACK);
}
// Stops and destroys the device.
......@@ -312,6 +307,7 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
}
if (IsApproximatelySameColor(color, average_content_rgb)) {
VLOG(1) << "Observed desired frame.";
return;
} else {
VLOG(3) << "PNG dump of undesired frame: "
......@@ -472,7 +468,7 @@ class WebContentsVideoCaptureDeviceBrowserTest : public ContentBrowserTest {
// Tests that the device refuses to start if the WebContents target was
// destroyed before the device could start.
// TODO(crbug/754872): Temporarily disabling due to flakiness.
// TODO(crbug/754872): To be re-enabled in separate change.
IN_PROC_BROWSER_TEST_F(
WebContentsVideoCaptureDeviceBrowserTest,
DISABLED_ErrorsOutIfWebContentsHasGoneBeforeDeviceStart) {
......@@ -507,7 +503,7 @@ IN_PROC_BROWSER_TEST_F(
// Tests that the device starts, captures a frame, and then gracefully
// errors-out because the WebContents is destroyed before the device is stopped.
// TODO(crbug/754872): Temporarily disabling due to flakiness.
// TODO(crbug/754872): To be re-enabled in separate change.
IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
DISABLED_ErrorsOutWhenWebContentsIsDestroyed) {
AllocateAndStartAndWaitForFirstFrame();
......@@ -529,7 +525,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
// Tests that the device stops delivering frames while suspended. When resumed,
// any content changes that occurred during the suspend should cause a new frame
// to be delivered, to ensure the client is up-to-date.
// TODO(crbug/754872): Temporarily disabling due to flakiness.
// TODO(crbug/754872): To be re-enabled in separate change.
IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
DISABLED_SuspendsAndResumes) {
AllocateAndStartAndWaitForFirstFrame();
......@@ -563,7 +559,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
// Tests that the device delivers refresh frames when asked, while the source
// content is not changing.
// TODO(crbug/754872): Temporarily disabling due to flakiness.
// TODO(crbug/754872): To be re-enabled in separate change.
IN_PROC_BROWSER_TEST_F(WebContentsVideoCaptureDeviceBrowserTest,
DISABLED_DeliversRefreshFramesUponRequest) {
AllocateAndStartAndWaitForFirstFrame();
......@@ -595,8 +591,16 @@ class WebContentsVideoCaptureDeviceBrowserTestP
}
};
// TODO(crbug/754872): Determine why these tests time out on CrOS only.
#if !defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS)
INSTANTIATE_TEST_CASE_P(
,
WebContentsVideoCaptureDeviceBrowserTestP,
testing::Combine(
// On ChromeOS, software compositing is not an option.
testing::Values(false),
// Force video frame resolutions to have a fixed aspect ratio?
testing::Values(false, true)));
#else
INSTANTIATE_TEST_CASE_P(
,
WebContentsVideoCaptureDeviceBrowserTestP,
......@@ -605,13 +609,13 @@ INSTANTIATE_TEST_CASE_P(
testing::Values(false, true),
// Force video frame resolutions to have a fixed aspect ratio?
testing::Values(false, true)));
#endif // !defined(OS_CHROMEOS)
#endif // defined(OS_CHROMEOS)
// Tests that the device successfully captures a series of content changes,
// whether the browser is running with software compositing or GPU-accelerated
// compositing, and whether the WebContents is visible/hidden or
// occluded/unoccluded.
// TODO(crbug/754872): Temporarily disabling due to flakiness.
// TODO(crbug/754872): To be re-enabled in separate change.
IN_PROC_BROWSER_TEST_P(WebContentsVideoCaptureDeviceBrowserTestP,
DISABLED_CapturesContentChanges) {
SCOPED_TRACE(testing::Message()
......
......@@ -278,8 +278,7 @@ void ScreenCaptureMachineAndroid::MaybeCaptureForRefresh() {
if (lastFrame_.get() == nullptr)
return;
const VideoCaptureOracle::Event event =
VideoCaptureOracle::kActiveRefreshRequest;
const VideoCaptureOracle::Event event = VideoCaptureOracle::kRefreshRequest;
const base::TimeTicks start_time = base::TimeTicks::Now();
scoped_refptr<VideoFrame> frame;
ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
......
......@@ -70,18 +70,6 @@ void ScreenCaptureDeviceCore::RequestRefreshFrame() {
if (state_ != kCapturing)
return;
// Try to use the less resource-intensive "passive" refresh mechanism, unless
// this is the first refresh following a Resume().
if (force_active_refresh_once_) {
capture_machine_->MaybeCaptureForRefresh();
force_active_refresh_once_ = false;
return;
}
// Make a best-effort attempt at a passive refresh, but fall-back to an active
// refresh if that fails.
if (oracle_proxy_->AttemptPassiveRefresh())
return;
capture_machine_->MaybeCaptureForRefresh();
}
......@@ -102,7 +90,6 @@ void ScreenCaptureDeviceCore::Resume() {
if (state_ != kSuspended)
return;
force_active_refresh_once_ = true;
TransitionStateTo(kCapturing);
capture_machine_->Resume();
......@@ -140,9 +127,7 @@ void ScreenCaptureDeviceCore::CaptureStarted(bool success) {
ScreenCaptureDeviceCore::ScreenCaptureDeviceCore(
std::unique_ptr<VideoCaptureMachine> capture_machine)
: state_(kIdle),
capture_machine_(std::move(capture_machine)),
force_active_refresh_once_(false) {
: state_(kIdle), capture_machine_(std::move(capture_machine)) {
DCHECK(capture_machine_.get());
}
......
......@@ -50,15 +50,8 @@ class CAPTURE_EXPORT VideoCaptureMachine {
// overloading or under-utilization.
virtual bool IsAutoThrottlingEnabled() const;
// Called by ScreenCaptureDeviceCore when it failed to satisfy a "refresh
// frame" request by attempting to resurrect the last video frame from the
// buffer pool (this is referred to as the "passive" refresh approach). The
// failure can happen for a number of reasons (e.g., the oracle decided to
// change resolution, or consumers of the last video frame are not yet
// finished with it).
//
// The implementation of this method should consult the oracle, using the
// kActiveRefreshRequest event type, to decide whether to initiate a new frame
// kRefreshRequest event type, to decide whether to initiate a new frame
// capture, and then do so if the oracle agrees.
virtual void MaybeCaptureForRefresh() = 0;
......@@ -121,12 +114,6 @@ class CAPTURE_EXPORT ScreenCaptureDeviceCore
// component of the system with direct access to |client_|.
scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
// After Resume(), some unknown amount of time has passed, and the content of
// the capture source may have changed. This flag is used to ensure that the
// passive refresh mechanism is not used for the first refresh frame following
// a Resume().
bool force_active_refresh_once_;
DISALLOW_COPY_AND_ASSIGN(ScreenCaptureDeviceCore);
};
......
......@@ -100,20 +100,9 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
coded_size.SetSize(base::bits::Align(visible_size.width(), 16),
base::bits::Align(visible_size.height(), 16));
if (event == VideoCaptureOracle::kPassiveRefreshRequest) {
output_buffer = client_->ResurrectLastOutputBuffer(
coded_size, params_.requested_format.pixel_format,
params_.requested_format.pixel_storage, frame_number);
if (!output_buffer.is_valid()) {
TRACE_EVENT_INSTANT0("gpu.capture", "ResurrectionFailed",
TRACE_EVENT_SCOPE_THREAD);
return false;
}
} else {
output_buffer = client_->ReserveOutputBuffer(
coded_size, params_.requested_format.pixel_format,
params_.requested_format.pixel_storage, frame_number);
}
// Get the current buffer pool utilization and attenuate it: The utilization
// reported to the oracle is in terms of a maximum sustainable amount (not
......@@ -188,21 +177,6 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
return true;
}
bool ThreadSafeCaptureOracle::AttemptPassiveRefresh() {
const base::TimeTicks refresh_time = base::TimeTicks::Now();
scoped_refptr<VideoFrame> frame;
CaptureFrameCallback capture_callback;
if (!ObserveEventAndDecideCapture(VideoCaptureOracle::kPassiveRefreshRequest,
gfx::Rect(), refresh_time, &frame,
&capture_callback)) {
return false;
}
capture_callback.Run(std::move(frame), refresh_time, true);
return true;
}
gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const {
base::AutoLock guard(lock_);
return oracle_.capture_size();
......
......@@ -60,12 +60,6 @@ class CAPTURE_EXPORT ThreadSafeCaptureOracle
scoped_refptr<VideoFrame>* storage,
CaptureFrameCallback* callback);
// Attempt to re-send the last frame to the VideoCaptureDevice::Client.
// Returns true if successful. This can fail if the last frame is no longer
// available in the buffer pool, or if the VideoCaptureOracle decides to
// reject the "passive" refresh.
bool AttemptPassiveRefresh();
base::TimeDelta min_capture_period() const {
return oracle_.min_capture_period();
}
......
......@@ -101,7 +101,6 @@ constexpr base::TimeDelta VideoCaptureOracle::kDefaultMinCapturePeriod;
VideoCaptureOracle::VideoCaptureOracle(bool enable_auto_throttling)
: auto_throttling_enabled_(enable_auto_throttling),
next_frame_number_(0),
source_is_dirty_(true),
last_successfully_delivered_frame_number_(-1),
num_frames_pending_(0),
smoothing_sampler_(kDefaultMinCapturePeriod),
......@@ -151,11 +150,6 @@ bool VideoCaptureOracle::ObserveEventAndDecideCapture(
}
last_event_time_[event] = event_time;
// If the event indicates a change to the source content, set a flag that will
// prevent passive refresh requests until a capture is made.
if (event != kActiveRefreshRequest && event != kPassiveRefreshRequest)
source_is_dirty_ = true;
bool should_sample = false;
duration_of_next_frame_ = base::TimeDelta();
switch (event) {
......@@ -178,12 +172,7 @@ bool VideoCaptureOracle::ObserveEventAndDecideCapture(
break;
}
case kPassiveRefreshRequest:
if (source_is_dirty_)
break;
// Intentional flow-through to next case here!
case kActiveRefreshRequest:
case kMouseCursorUpdate:
case kRefreshRequest:
// Only allow non-compositor samplings when content has not recently been
// animating, and only if there are no samplings currently in progress.
if (num_frames_pending_ == 0) {
......@@ -237,8 +226,6 @@ bool VideoCaptureOracle::ObserveEventAndDecideCapture(
void VideoCaptureOracle::RecordCapture(double pool_utilization) {
DCHECK(std::isfinite(pool_utilization) && pool_utilization >= 0.0);
source_is_dirty_ = false;
smoothing_sampler_.RecordSample();
const base::TimeTicks timestamp = GetFrameTimestamp(next_frame_number_);
content_sampler_.RecordSample(timestamp);
......@@ -289,9 +276,6 @@ bool VideoCaptureOracle::CompleteCapture(int frame_number,
if (!capture_was_successful) {
VLOG(2) << "Capture of frame #" << frame_number << " was not successful.";
// Since capture of this frame might have been required for capturing an
// update to the source content, set the dirty flag.
source_is_dirty_ = true;
return false;
}
......@@ -343,7 +327,6 @@ void VideoCaptureOracle::CancelAllCaptures() {
//
// ...which simplifies to:
num_frames_pending_ = 0;
source_is_dirty_ = true;
}
void VideoCaptureOracle::RecordConsumerFeedback(int frame_number,
......@@ -380,12 +363,8 @@ const char* VideoCaptureOracle::EventAsString(Event event) {
switch (event) {
case kCompositorUpdate:
return "compositor";
case kActiveRefreshRequest:
return "active_refresh";
case kPassiveRefreshRequest:
return "passive_refresh";
case kMouseCursorUpdate:
return "mouse";
case kRefreshRequest:
return "refresh";
case kNumEvents:
break;
}
......
......@@ -24,9 +24,7 @@ class CAPTURE_EXPORT VideoCaptureOracle {
public:
enum Event {
kCompositorUpdate,
kActiveRefreshRequest,
kPassiveRefreshRequest,
kMouseCursorUpdate,
kRefreshRequest,
kNumEvents,
};
......@@ -169,11 +167,6 @@ class CAPTURE_EXPORT VideoCaptureOracle {
// sanity-check that event times are monotonically non-decreasing.
base::TimeTicks last_event_time_[kNumEvents];
// Set to true if there have been updates to the source content that were not
// sampled. This will prevent passive refresh requests from being satisfied
// when an active refresh should be used instead.
bool source_is_dirty_;
// Updated by the last call to ObserveEventAndDecideCapture() with the
// estimated duration of the next frame to sample. This is zero if the method
// returned false.
......
......@@ -257,7 +257,7 @@ TEST(VideoCaptureOracleTest, SamplesAtCorrectTimesAroundRefreshRequests) {
for (int i = 0; i < 10; ++i) {
t += refresh_interval;
ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, gfx::Rect(), t));
VideoCaptureOracle::kRefreshRequest, gfx::Rect(), t));
}
// Now, complete the oustanding compositor-based capture and continue
......@@ -267,8 +267,8 @@ TEST(VideoCaptureOracleTest, SamplesAtCorrectTimesAroundRefreshRequests) {
did_complete_a_capture = false;
for (int i = 0; i < 10; ++i) {
t += refresh_interval;
if (oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, gfx::Rect(), t)) {
if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
gfx::Rect(), t)) {
const int frame_number = oracle.next_frame_number();
oracle.RecordCapture(0.0);
ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
......@@ -281,8 +281,8 @@ TEST(VideoCaptureOracleTest, SamplesAtCorrectTimesAroundRefreshRequests) {
for (int i = 0; i <= 10; ++i) {
ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
t += refresh_interval;
if (oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, gfx::Rect(), t)) {
if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
gfx::Rect(), t)) {
break;
}
}
......@@ -294,14 +294,14 @@ TEST(VideoCaptureOracleTest, SamplesAtCorrectTimesAroundRefreshRequests) {
for (int i = 0; i < 10; ++i) {
t += refresh_interval;
ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, gfx::Rect(), t));
VideoCaptureOracle::kRefreshRequest, gfx::Rect(), t));
}
ASSERT_TRUE(oracle.CompleteCapture(frame_number, true, &ignored));
for (int i = 0; i <= 10; ++i) {
ASSERT_GT(10, i) << "BUG: Seems like it'll never happen!";
t += refresh_interval;
if (oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, gfx::Rect(), t)) {
if (oracle.ObserveEventAndDecideCapture(VideoCaptureOracle::kRefreshRequest,
gfx::Rect(), t)) {
break;
}
}
......@@ -361,43 +361,6 @@ TEST(VideoCaptureOracleTest, DoesNotRapidlyChangeCaptureSize) {
}
}
// Tests that un-sampled compositor update event will fail the next passive
// refresh request, forcing an active refresh.
TEST(VideoCaptureOracleTest, EnforceActiveRefreshForUnsampledCompositorUpdate) {
const gfx::Rect damage_rect(Get720pSize());
const base::TimeDelta event_increment = Get30HzPeriod() * 2;
const base::TimeDelta short_event_increment = Get30HzPeriod() / 4;
VideoCaptureOracle oracle(false);
oracle.SetMinCapturePeriod(Get30HzPeriod());
oracle.SetCaptureSizeConstraints(Get720pSize(), Get720pSize(), false);
base::TimeTicks t = InitialTestTimeTicks();
int last_frame_number;
base::TimeTicks ignored;
// CompositorUpdate is sampled normally.
t += event_increment;
ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
last_frame_number = oracle.next_frame_number();
oracle.RecordCapture(0.0);
ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, true, &ignored));
// Next CompositorUpdate comes too soon and won't be sampled.
t += short_event_increment;
ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kCompositorUpdate, damage_rect, t));
// Then the next valid PassiveRefreshRequest will fail to enforce an
// ActiveRefreshRequest to capture the updated content.
t += event_increment;
ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kPassiveRefreshRequest, damage_rect, t));
ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
VideoCaptureOracle::kActiveRefreshRequest, damage_rect, t));
}
namespace {
// Tests that VideoCaptureOracle can auto-throttle by stepping the capture size
......
......@@ -104,3 +104,8 @@
# Flaky Result on Windows-7 http://crbug.com/883463
-MainThreadEventQueueBrowserTest.MouseMove
# Shared memory pooling bug when viz::FrameSinkCapturerImpl runs in the VIZ
# process. http://crbug.com/806635
-WebContentsVideoCaptureDeviceBrowserTest.*
-WebContentsVideoCaptureDeviceBrowserTestP.*
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment