From 44ce4de962fd1c456383a4ee2f39b9599edd42de Mon Sep 17 00:00:00 2001 From: dalecurtis Date: Mon, 11 May 2015 11:42:07 -0700 Subject: [PATCH] Allow WMPI to drive compositor updates for invisible video tags. Invisible tags don't get compositor updates, so we need to let them drive those updates (within reason). This allows VideoFrameCompositor instances without a VideoFrameProvider::Client to update at up to 250Hz, which should be enough for everyone. This is done by introducing GetCurrentFrameAndMaybeBackgroundRender() which is called by WebMediaPlayerImpl for grabbing frames. If we have no client, have a callback, and are background rendering, this allows WebMediaPlayerImpl::paint() calls to drive frame acquisition. Also fixes bug with media_blink_unittests which isn't caught by the try bots for some reason... BUG=485783 TEST=new unittest, ro.me plays great. Review URL: https://codereview.chromium.org/1132213002 Cr-Commit-Position: refs/heads/master@{#329201} --- media/blink/run_all_unittests.cc | 7 ++ media/blink/video_frame_compositor.cc | 24 ++++++ media/blink/video_frame_compositor.h | 14 ++++ .../blink/video_frame_compositor_unittest.cc | 78 +++++++++++++++---- media/blink/webmediaplayer_impl.cc | 4 +- 5 files changed, 112 insertions(+), 15 deletions(-) diff --git a/media/blink/run_all_unittests.cc b/media/blink/run_all_unittests.cc index f85144b0643381..0261dc2602e732 100644 --- a/media/blink/run_all_unittests.cc +++ b/media/blink/run_all_unittests.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/message_loop/message_loop.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" #include "build/build_config.h" @@ -81,6 +82,12 @@ void BlinkMediaTestSuite::Initialize() { gin::V8Initializer::LoadV8Snapshot(); #endif + // Dummy task runner is initialized here because the blink::initialize creates + // IsolateHolder which needs the current task runner handle. There should be + // no task posted to this task runner. + scoped_ptr message_loop; + if (!base::MessageLoop::current()) + message_loop.reset(new base::MessageLoop()); blink::initialize(blink_platform_support_.get()); } diff --git a/media/blink/video_frame_compositor.cc b/media/blink/video_frame_compositor.cc index 634eb4f35bb131..3e19254f67bc5e 100644 --- a/media/blink/video_frame_compositor.cc +++ b/media/blink/video_frame_compositor.cc @@ -165,6 +165,29 @@ void VideoFrameCompositor::PaintFrameUsingOldRenderingPath( client_->DidReceiveFrame(); } +scoped_refptr +VideoFrameCompositor::GetCurrentFrameAndUpdateIfStale() { + DCHECK(compositor_task_runner_->BelongsToCurrentThread()); + if (client_ || !rendering_ || !is_background_rendering_) + return current_frame_; + + DCHECK(!last_background_render_.is_null()); + + const base::TimeTicks now = tick_clock_->NowTicks(); + const base::TimeDelta interval = now - last_background_render_; + + // Cap updates to 250Hz which should be more than enough for everyone. + if (interval < base::TimeDelta::FromMilliseconds(4)) + return current_frame_; + + // Update the interval based on the time between calls and call background + // render which will give this information to the client. + last_interval_ = interval; + BackgroundRender(); + + return current_frame_; +} + bool VideoFrameCompositor::ProcessNewFrame( const scoped_refptr& frame) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); @@ -191,6 +214,7 @@ bool VideoFrameCompositor::ProcessNewFrame( void VideoFrameCompositor::BackgroundRender() { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); const base::TimeTicks now = tick_clock_->NowTicks(); + last_background_render_ = now; CallRender(now, now + last_interval_, true); } diff --git a/media/blink/video_frame_compositor.h b/media/blink/video_frame_compositor.h index 4eb2e7e179de83..6b34b11f965854 100644 --- a/media/blink/video_frame_compositor.h +++ b/media/blink/video_frame_compositor.h @@ -88,6 +88,19 @@ class MEDIA_EXPORT VideoFrameCompositor void PaintFrameUsingOldRenderingPath( const scoped_refptr& frame) override; + // Returns |current_frame_| if |client_| is set. If no |client_| is set, + // |is_background_rendering_| is true, and |callback_| is set, it requests a + // new frame from |callback_|, using the elapsed time between calls to this + // function as the render interval; defaulting to 16.6ms if no prior calls + // have been made. A cap of 250Hz (4ms) is in place to prevent clients from + // accidentally (or intentionally) spamming the rendering pipeline. + // + // This method is primarily to facilitate canvas and WebGL based applications + // where the