// Copyright 2014 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 MEDIA_BLINK_VIDEO_FRAME_COMPOSITOR_H_ #define MEDIA_BLINK_VIDEO_FRAME_COMPOSITOR_H_ #include "base/callback.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/time/tick_clock.h" #include "base/timer/timer.h" #include "cc/layers/video_frame_provider.h" #include "media/base/media_export.h" #include "media/base/video_renderer_sink.h" #include "ui/gfx/geometry/size.h" namespace media { class VideoFrame; // VideoFrameCompositor acts as a bridge between the media and cc layers for // rendering video frames. I.e. a media::VideoRenderer will talk to this class // from the media side, while a cc::VideoFrameProvider::Client will talk to it // from the cc side. // // This class is responsible for requesting new frames from a video renderer in // response to requests from the VFP::Client. Since the VFP::Client may stop // issuing requests in response to visibility changes it is also responsible for // ensuring the "freshness" of the current frame for programmatic frame // requests; e.g., Canvas.drawImage() requests // // This class is also responsible for detecting frames dropped by the compositor // after rendering and signaling that information to a RenderCallback. It // detects frames not dropped by verifying each GetCurrentFrame() is followed // by a PutCurrentFrame() before the next UpdateCurrentFrame() call. // // VideoRenderSink::RenderCallback implementations must call Start() and Stop() // once new frames are expected or are no longer expected to be ready; this data // is relayed to the compositor to avoid extraneous callbacks. // // VideoFrameCompositor is also responsible for pumping UpdateCurrentFrame() // callbacks in the background when |client_| has decided to suspend them. // // VideoFrameCompositor must live on the same thread as the compositor, though // it may be constructed on any thread. class MEDIA_EXPORT VideoFrameCompositor : public VideoRendererSink, NON_EXPORTED_BASE(public cc::VideoFrameProvider) { public: // |compositor_task_runner| is the task runner on which this class will live, // though it may be constructed on any thread. // // |natural_size_changed_cb| is run with the new natural size of the video // frame whenever a change in natural size is detected. It is not called the // first time UpdateCurrentFrame() is called. Run on the same thread as the // caller of UpdateCurrentFrame(). // // |opacity_changed_cb| is run when a change in opacity is detected. It *is* // called the first time UpdateCurrentFrame() is called. Run on the same // thread as the caller of UpdateCurrentFrame(). // // TODO(dalecurtis): Investigate the inconsistency between the callbacks with // respect to why we don't call |natural_size_changed_cb| on the first frame. // I suspect it was for historical reasons that no longer make sense. VideoFrameCompositor( const scoped_refptr& compositor_task_runner, const base::Callback& natural_size_changed_cb, const base::Callback& opacity_changed_cb); // Destruction must happen on the compositor thread; Stop() must have been // called before destruction starts. ~VideoFrameCompositor() override; // cc::VideoFrameProvider implementation. These methods must be called on the // |compositor_task_runner_|. void SetVideoFrameProviderClient( cc::VideoFrameProvider::Client* client) override; bool UpdateCurrentFrame(base::TimeTicks deadline_min, base::TimeTicks deadline_max) override; bool HasCurrentFrame() override; scoped_refptr GetCurrentFrame() override; void PutCurrentFrame() override; // VideoRendererSink implementation. These methods must be called from the // same thread (typically the media thread). void Start(RenderCallback* callback) override; void Stop() override; 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