Skip to content

Commit

Permalink
cc: Add support for sending BeginFrames for video.
Browse files Browse the repository at this point in the history
This CL adds support for plumbing BeginFrames to
VideoFrameProviderClientImpl if it opts into it. This is required for
upcoming video rendering changes to improve video smoothness.

BUG=456991

Review URL: https://codereview.chromium.org/1039533002

Cr-Commit-Position: refs/heads/master@{#325550}
  • Loading branch information
sunnyps authored and Commit bot committed Apr 16, 2015
1 parent b6e3939 commit 7d073dc
Show file tree
Hide file tree
Showing 21 changed files with 172 additions and 8 deletions.
1 change: 1 addition & 0 deletions cc/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ component("cc") {
"scheduler/scheduler_settings.h",
"scheduler/scheduler_state_machine.cc",
"scheduler/scheduler_state_machine.h",
"scheduler/video_frame_controller.h",
"trees/blocking_task_runner.cc",
"trees/blocking_task_runner.h",
"trees/damage_tracker.cc",
Expand Down
1 change: 1 addition & 0 deletions cc/cc.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@
'scheduler/scheduler_settings.h',
'scheduler/scheduler_state_machine.cc',
'scheduler/scheduler_state_machine.h',
'scheduler/video_frame_controller.h',
'trees/blocking_task_runner.cc',
'trees/blocking_task_runner.h',
'trees/damage_tracker.cc',
Expand Down
19 changes: 15 additions & 4 deletions cc/layers/video_frame_provider_client_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ namespace cc {

// static
scoped_refptr<VideoFrameProviderClientImpl>
VideoFrameProviderClientImpl::Create(VideoFrameProvider* provider) {
return make_scoped_refptr(new VideoFrameProviderClientImpl(provider));
VideoFrameProviderClientImpl::Create(VideoFrameProvider* provider,
VideoFrameControllerClient* client) {
return make_scoped_refptr(new VideoFrameProviderClientImpl(provider, client));
}

VideoFrameProviderClientImpl::VideoFrameProviderClientImpl(
VideoFrameProvider* provider)
: provider_(provider), active_video_layer_(nullptr), stopped_(false) {
VideoFrameProvider* provider,
VideoFrameControllerClient* client)
: provider_(provider),
client_(client),
active_video_layer_(nullptr),
stopped_(false) {
// This only happens during a commit on the compositor thread while the main
// thread is blocked. That makes this a thread-safe call to set the video
// frame provider client that does not require a lock. The same is true of
Expand Down Expand Up @@ -59,6 +64,7 @@ void VideoFrameProviderClientImpl::Stop() {
provider_->SetVideoFrameProviderClient(nullptr);
provider_ = nullptr;
}
client_->RemoveVideoFrameController(this);
active_video_layer_ = nullptr;
stopped_ = true;
}
Expand Down Expand Up @@ -134,4 +140,9 @@ void VideoFrameProviderClientImpl::DidUpdateMatrix(const float* matrix) {
active_video_layer_->SetNeedsRedraw();
}

void VideoFrameProviderClientImpl::OnBeginFrame(const BeginFrameArgs& args) {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
}

} // namespace cc
12 changes: 10 additions & 2 deletions cc/layers/video_frame_provider_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "base/threading/thread_checker.h"
#include "cc/base/cc_export.h"
#include "cc/layers/video_frame_provider.h"
#include "cc/scheduler/video_frame_controller.h"
#include "ui/gfx/transform.h"

namespace media { class VideoFrame; }
Expand All @@ -23,11 +24,13 @@ class VideoLayerImpl;
// has.
class CC_EXPORT VideoFrameProviderClientImpl
: public VideoFrameProvider::Client,
public VideoFrameController,
public base::RefCounted<VideoFrameProviderClientImpl> {
public:
// Must be created on the impl thread while the main thread is blocked.
static scoped_refptr<VideoFrameProviderClientImpl> Create(
VideoFrameProvider* provider);
VideoFrameProvider* provider,
VideoFrameControllerClient* client);

VideoLayerImpl* ActiveVideoLayer() const;
void SetActiveVideoLayer(VideoLayerImpl* video_layer);
Expand All @@ -42,6 +45,9 @@ class CC_EXPORT VideoFrameProviderClientImpl

const gfx::Transform& StreamTextureMatrix() const;

// VideoFrameController implementation.
void OnBeginFrame(const BeginFrameArgs& args) override;

// VideoFrameProvider::Client implementation.
// Called on the main thread.
void StopUsingProvider() override;
Expand All @@ -54,10 +60,12 @@ class CC_EXPORT VideoFrameProviderClientImpl
private:
friend class base::RefCounted<VideoFrameProviderClientImpl>;

explicit VideoFrameProviderClientImpl(VideoFrameProvider* provider);
VideoFrameProviderClientImpl(VideoFrameProvider* provider,
VideoFrameControllerClient* client);
~VideoFrameProviderClientImpl() override;

VideoFrameProvider* provider_;
VideoFrameControllerClient* client_;
VideoLayerImpl* active_video_layer_;
bool stopped_;

Expand Down
3 changes: 2 additions & 1 deletion cc/layers/video_layer_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ scoped_ptr<VideoLayerImpl> VideoLayerImpl::Create(
DCHECK(tree_impl->proxy()->IsImplThread());

scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl =
VideoFrameProviderClientImpl::Create(provider);
VideoFrameProviderClientImpl::Create(
provider, tree_impl->GetVideoFrameControllerClient());

return make_scoped_ptr(
new VideoLayerImpl(tree_impl, id, provider_client_impl, video_rotation));
Expand Down
5 changes: 5 additions & 0 deletions cc/scheduler/scheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,11 @@ void Scheduler::SetAuthoritativeVSyncInterval(const base::TimeDelta& interval) {
vsync_observer_->OnUpdateVSyncParameters(last_vsync_timebase_, interval);
}

void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) {
state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames);
ProcessScheduledActions();
}

void Scheduler::OnDrawForOutputSurface() {
DCHECK(settings_.using_synchronous_renderer_compositor);
DCHECK_EQ(state_machine_.begin_impl_frame_state(),
Expand Down
1 change: 1 addition & 0 deletions cc/scheduler/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ class CC_EXPORT Scheduler : public BeginFrameObserverMixIn {
}

void SetChildrenNeedBeginFrames(bool children_need_begin_frames);
void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);

void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval);

Expand Down
12 changes: 11 additions & 1 deletion cc/scheduler/scheduler_state_machine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ SchedulerStateMachine::SchedulerStateMachine(const SchedulerSettings& settings)
continuous_painting_(false),
children_need_begin_frames_(false),
defer_commits_(false),
video_needs_begin_frames_(false),
last_commit_had_no_updates_(false),
wait_for_active_tree_ready_to_draw_(false),
did_request_swap_in_last_frame_(false),
Expand Down Expand Up @@ -243,6 +244,7 @@ void SchedulerStateMachine::AsValueInto(
skip_next_begin_main_frame_to_reduce_latency_);
state->SetBoolean("continuous_painting", continuous_painting_);
state->SetBoolean("children_need_begin_frames", children_need_begin_frames_);
state->SetBoolean("video_needs_begin_frames", video_needs_begin_frames_);
state->SetBoolean("defer_commits", defer_commits_);
state->SetBoolean("last_commit_had_no_updates", last_commit_had_no_updates_);
state->SetBoolean("did_request_swap_in_last_frame",
Expand Down Expand Up @@ -723,6 +725,9 @@ void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
bool SchedulerStateMachine::BeginFrameRequiredForChildren() const {
return children_need_begin_frames_;
}
bool SchedulerStateMachine::BeginFrameNeededForVideo() const {
return video_needs_begin_frames_;
}

bool SchedulerStateMachine::BeginFrameNeeded() const {
// We can't handle BeginFrames when output surface isn't initialized.
Expand All @@ -735,14 +740,19 @@ bool SchedulerStateMachine::BeginFrameNeeded() const {
return false;

return (BeginFrameRequiredForAction() || BeginFrameRequiredForChildren() ||
ProactiveBeginFrameWanted());
BeginFrameNeededForVideo() || ProactiveBeginFrameWanted());
}

void SchedulerStateMachine::SetChildrenNeedBeginFrames(
bool children_need_begin_frames) {
children_need_begin_frames_ = children_need_begin_frames;
}

void SchedulerStateMachine::SetVideoNeedsBeginFrames(
bool video_needs_begin_frames) {
video_needs_begin_frames_ = video_needs_begin_frames;
}

void SchedulerStateMachine::SetDeferCommits(bool defer_commits) {
defer_commits_ = defer_commits;
}
Expand Down
5 changes: 5 additions & 0 deletions cc/scheduler/scheduler_state_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,13 @@ class CC_EXPORT SchedulerStateMachine {
return children_need_begin_frames_;
}

void SetVideoNeedsBeginFrames(bool video_needs_begin_frames);
bool video_needs_begin_frames() const { return video_needs_begin_frames_; }

protected:
bool BeginFrameRequiredForAction() const;
bool BeginFrameRequiredForChildren() const;
bool BeginFrameNeededForVideo() const;
bool ProactiveBeginFrameWanted() const;

bool ShouldTriggerBeginImplFrameDeadlineImmediately() const;
Expand Down Expand Up @@ -330,6 +334,7 @@ class CC_EXPORT SchedulerStateMachine {
bool continuous_painting_;
bool children_need_begin_frames_;
bool defer_commits_;
bool video_needs_begin_frames_;
bool last_commit_had_no_updates_;
bool wait_for_active_tree_ready_to_draw_;
bool did_request_swap_in_last_frame_;
Expand Down
31 changes: 31 additions & 0 deletions cc/scheduler/scheduler_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,37 @@ TEST_F(SchedulerTest, SendBeginFramesToChildrenWithoutCommit) {
EXPECT_TRUE(client_->begin_frame_is_sent_to_children());
}

TEST_F(SchedulerTest, VideoNeedsBeginFrames) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);

scheduler_->SetVideoNeedsBeginFrames(true);
EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_);
EXPECT_TRUE(client_->needs_begin_frames());

client_->Reset();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
// WillBeginImplFrame is responsible for sending BeginFrames to video.
EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);

client_->Reset();
EXPECT_SCOPED(AdvanceFrame());
EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending());
EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_);

client_->Reset();
scheduler_->SetVideoNeedsBeginFrames(false);
EXPECT_NO_ACTION(client_);

client_->Reset();
task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true));
EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending());
EXPECT_ACTION("SetNeedsBeginFrames(false)", client_, 0, 2);
EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2);
EXPECT_FALSE(client_->needs_begin_frames());
}

TEST_F(SchedulerTest, RequestCommit) {
scheduler_settings_.use_external_begin_frame_source = true;
SetUpScheduler(true);
Expand Down
35 changes: 35 additions & 0 deletions cc/scheduler/video_frame_controller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 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.

#ifndef CC_SCHEDULER_VIDEO_FRAME_CONTROLLER_H_
#define CC_SCHEDULER_VIDEO_FRAME_CONTROLLER_H_

#include "cc/base/cc_export.h"
#include "cc/output/begin_frame_args.h"

namespace cc {

class VideoFrameController;

class CC_EXPORT VideoFrameControllerClient {
public:
virtual void AddVideoFrameController(VideoFrameController* controller) = 0;
virtual void RemoveVideoFrameController(VideoFrameController* controller) = 0;

protected:
virtual ~VideoFrameControllerClient() {}
};

// TODO(sunnyps): Consider making this a BeginFrameObserver some day.
class CC_EXPORT VideoFrameController {
public:
virtual void OnBeginFrame(const BeginFrameArgs& args) = 0;

protected:
virtual ~VideoFrameController() {}
};

} // namespace cc

#endif // CC_SCHEDULER_VIDEO_FRAME_CONTROLLER_H_
1 change: 1 addition & 0 deletions cc/test/fake_layer_tree_host_impl_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
void SetNeedsAnimateOnImplThread() override {}
void SetNeedsCommitOnImplThread() override {}
void SetNeedsPrepareTilesOnImplThread() override {}
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
void PostAnimationEventsToMainThreadOnImplThread(
scoped_ptr<AnimationEventsVector> events) override {}
bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
Expand Down
18 changes: 18 additions & 0 deletions cc/trees/layer_tree_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1653,6 +1653,9 @@ void LayerTreeHostImpl::WillBeginImplFrame(const BeginFrameArgs& args) {
// we are beginning now.
SetNeedsRedraw();
}

for (auto& it : video_frame_controllers_)
it->OnBeginFrame(args);
}

void LayerTreeHostImpl::UpdateViewportContainerSizes() {
Expand Down Expand Up @@ -3070,6 +3073,21 @@ void LayerTreeHostImpl::SetNeedsRedrawForScrollbarAnimation() {
SetNeedsRedraw();
}

void LayerTreeHostImpl::AddVideoFrameController(
VideoFrameController* controller) {
bool was_empty = video_frame_controllers_.empty();
video_frame_controllers_.insert(controller);
if (was_empty)
client_->SetVideoNeedsBeginFrames(true);
}

void LayerTreeHostImpl::RemoveVideoFrameController(
VideoFrameController* controller) {
video_frame_controllers_.erase(controller);
if (video_frame_controllers_.empty())
client_->SetVideoNeedsBeginFrames(false);
}

void LayerTreeHostImpl::SetTreePriority(TreePriority priority) {
if (!tile_manager_)
return;
Expand Down
9 changes: 9 additions & 0 deletions cc/trees/layer_tree_host_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "cc/resources/ui_resource_client.h"
#include "cc/scheduler/commit_earlyout_reason.h"
#include "cc/scheduler/draw_result.h"
#include "cc/scheduler/video_frame_controller.h"
#include "cc/trees/layer_tree_settings.h"
#include "cc/trees/proxy.h"
#include "skia/ext/refptr.h"
Expand Down Expand Up @@ -104,6 +105,7 @@ class LayerTreeHostImplClient {
virtual void SetNeedsAnimateOnImplThread() = 0;
virtual void SetNeedsCommitOnImplThread() = 0;
virtual void SetNeedsPrepareTilesOnImplThread() = 0;
virtual void SetVideoNeedsBeginFrames(bool needs_begin_frames) = 0;
virtual void PostAnimationEventsToMainThreadOnImplThread(
scoped_ptr<AnimationEventsVector> events) = 0;
// Returns true if resources were deleted by this call.
Expand Down Expand Up @@ -136,6 +138,7 @@ class CC_EXPORT LayerTreeHostImpl
public OutputSurfaceClient,
public TopControlsManagerClient,
public ScrollbarAnimationControllerClient,
public VideoFrameControllerClient,
public base::SupportsWeakPtr<LayerTreeHostImpl> {
public:
static scoped_ptr<LayerTreeHostImpl> Create(
Expand Down Expand Up @@ -278,6 +281,10 @@ class CC_EXPORT LayerTreeHostImpl
base::TimeDelta delay) override;
void SetNeedsRedrawForScrollbarAnimation() override;

// VideoBeginFrameSource implementation.
void AddVideoFrameController(VideoFrameController* controller) override;
void RemoveVideoFrameController(VideoFrameController* controller) override;

// OutputSurfaceClient implementation.
void CommitVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) override;
Expand Down Expand Up @@ -573,6 +580,7 @@ class CC_EXPORT LayerTreeHostImpl
// Scroll by preferring to move the inner viewport first, only moving the
// outer if the inner is at its scroll extents.
void ScrollViewportInnerFirst(gfx::Vector2dF scroll_delta);

void AnimatePageScale(base::TimeTicks monotonic_time);
void AnimateScrollbars(base::TimeTicks monotonic_time);
void AnimateTopControls(base::TimeTicks monotonic_time);
Expand Down Expand Up @@ -726,6 +734,7 @@ class CC_EXPORT LayerTreeHostImpl

scoped_ptr<AnimationRegistrar> animation_registrar_;
std::set<ScrollbarAnimationController*> scrollbar_animation_controllers_;
std::set<VideoFrameController*> video_frame_controllers_;

RenderingStatsInstrumentation* rendering_stats_instrumentation_;
MicroBenchmarkControllerImpl micro_benchmark_controller_;
Expand Down
1 change: 1 addition & 0 deletions cc/trees/layer_tree_host_impl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class LayerTreeHostImplTest : public testing::Test,
did_request_prepare_tiles_ = true;
}
void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
void PostAnimationEventsToMainThreadOnImplThread(
scoped_ptr<AnimationEventsVector> events) override {}
bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
Expand Down
5 changes: 5 additions & 0 deletions cc/trees/layer_tree_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,11 @@ BlockingTaskRunner* LayerTreeImpl::BlockingMainThreadTaskRunner() const {
return proxy()->blocking_main_thread_task_runner();
}

VideoFrameControllerClient* LayerTreeImpl::GetVideoFrameControllerClient()
const {
return layer_tree_host_impl_;
}

void LayerTreeImpl::SetPendingPageScaleAnimation(
scoped_ptr<PendingPageScaleAnimation> pending_animation) {
pending_page_scale_animation_ = pending_animation.Pass();
Expand Down
Loading

0 comments on commit 7d073dc

Please sign in to comment.